diff --git a/.clang-format.changes b/.clang-format.changes index cb16dd6d14..89f6960445 100644 --- a/.clang-format.changes +++ b/.clang-format.changes @@ -1,3 +1,3 @@ SortIncludes: false -Standard: c++11 -StatementMacros: [MKDLL, MKDLLdec, MKDLLif, MKDLLvp, MKDLLvpf] +Standard: c++14 +StatementMacros: [MKDLL, MKDLLdec, MKDLLif, MKDLLvp, MKDLLvpf] \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2862ebb5a6..c8c043b646 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ .clang-format .cmake-format.yaml +external/tests/ nmodlconf.h.in nrnconf.h.in +test/ringtest/*.dat build .DS_Store .eggs/ @@ -21,25 +23,25 @@ virtualenv # These files are generated at build time # It would be a good idea to create them in the # build directory in the future. -src/nrnoc/apcount.c -src/nrnoc/exp2syn.c -src/nrnoc/expsyn.c -src/nrnoc/feature.c -src/nrnoc/hh.c +src/nrnoc/apcount.cpp +src/nrnoc/exp2syn.cpp +src/nrnoc/expsyn.cpp +src/nrnoc/feature.cpp +src/nrnoc/hh.cpp src/nrnoc/hh.mod.orig src/nrnoc/hocusr.h -src/nrnoc/intfire1.c -src/nrnoc/intfire2.c -src/nrnoc/intfire4.c -src/nrnoc/netstim.c +src/nrnoc/intfire1.cpp +src/nrnoc/intfire2.cpp +src/nrnoc/intfire4.cpp +src/nrnoc/netstim.cpp src/nrnoc/nrnversion. src/nrnoc/nrnversion.h -src/nrnoc/oclmp.c -src/nrnoc/passive.c -src/nrnoc/pattern.c -src/nrnoc/ppmark.c -src/nrnoc/stim.c -src/nrnoc/svclmp.c -src/nrnoc/syn.c -src/nrnoc/vclmp.c +src/nrnoc/oclmp.cpp +src/nrnoc/passive.cpp +src/nrnoc/pattern.cpp +src/nrnoc/ppmark.cpp +src/nrnoc/stim.cpp +src/nrnoc/svclmp.cpp +src/nrnoc/syn.cpp +src/nrnoc/vclmp.cpp share/lib/python/neuron/help_data.dat diff --git a/CMakeLists.txt b/CMakeLists.txt index 924391b397..b3325dca8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,14 +17,14 @@ if(DEFINED ENV{CRAYPE_VERSION}) endif() project( NEURON - VERSION 8.2.0 + VERSION 9.0.0 LANGUAGES C CXX HOMEPAGE_URL "https://www.neuron.yale.edu/neuron/") # ============================================================================= # CMake common project settings # ============================================================================= -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/bin/nrnivmodl.in b/bin/nrnivmodl.in index 7ba08590eb..6856cb3de6 100755 --- a/bin/nrnivmodl.in +++ b/bin/nrnivmodl.in @@ -151,13 +151,13 @@ for i in "${files[@]}" ; do dir_name="$(dirname "$f")" # Note: indentation for shell lines in make rules must be a tab echo "\ -./${base_name// /\\ }.c: ${f// /\\ }.mod +./${base_name// /\\ }.cpp: ${f// /\\ }.mod @printf \" -> \$(C_GREEN)NMODL\$(C_RESET) \$<\\\n\" (cd \"$dir_name\"; @NRN_NOCMODL_SANITIZER_ENVIRONMENT_STRING@ MODLUNIT=\$(NRNUNITS) \$(NOCMODL) \"$base_name.mod\" -o \"$mdir\") -./${base_name// /\\ }.o: ./${base_name// /\\ }.c +./${base_name// /\\ }.o: ./${base_name// /\\ }.cpp @printf \" -> \$(C_GREEN)Compiling\$(C_RESET) \$<\\\n\" - \$(COMPILE) -I\"$dir_name\" \$(INCLUDES) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c \$< -o \$@ + \$(CXXCOMPILE) -I\"$dir_name\" \$(INCLUDES) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c \$< -o \$@ " >> "$MODMAKE" done diff --git a/bin/nrnivmodl_makefile_cmake.in b/bin/nrnivmodl_makefile_cmake.in index 9d37fbaf49..1a32c4a337 100644 --- a/bin/nrnivmodl_makefile_cmake.in +++ b/bin/nrnivmodl_makefile_cmake.in @@ -61,15 +61,11 @@ ifeq (@NRN_INCLUDE_MPI_HEADERS@, ON) INCLUDES += $(if @MPI_C_INCLUDE_PATH@, -I$(subst ;, -I,@MPI_C_INCLUDE_PATH@),) endif -# CC/CXX are always defined. If the definition comes from default change it -ifeq ($(origin CC), default) - CC = @CMAKE_C_COMPILER@ +# CXX is always defined. If the definition comes from default change it +ifeq ($(origin CXX), default) CXX = @CMAKE_CXX_COMPILER@ endif -CFLAGS = @BUILD_TYPE_C_FLAGS@ @CMAKE_C_FLAGS@ -CXXFLAGS = @BUILD_TYPE_CXX_FLAGS@ @CMAKE_CXX_FLAGS@ @CXX11_STANDARD_COMPILE_OPTION@ - -COMPILE = $(CC) $(CFLAGS) @NRN_COMPILE_DEFS_STRING@ @NRN_COMPILE_FLAGS_STRING@ +CXXFLAGS = @BUILD_TYPE_CXX_FLAGS@ @CMAKE_CXX_FLAGS@ @CMAKE_CXX14_STANDARD_COMPILE_OPTION@ CXXCOMPILE = $(CXX) $(CXXFLAGS) @NRN_COMPILE_DEFS_STRING@ @NRN_COMPILE_FLAGS_STRING@ CXX_LINK_EXE = $(CXX) $(CXXFLAGS) @CMAKE_EXE_LINKER_FLAGS@ @NRN_LINK_FLAGS_STRING@ CXX_LINK_SHARED = $(CXX) $(CXXFLAGS) @CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS@ @CMAKE_SHARED_LIBRARY_CXX_FLAGS@ @CMAKE_SHARED_LINKER_FLAGS@ @@ -139,12 +135,12 @@ mech_lib_static: mod_func.o $(mod_objs) $(nrn_lib) build_always mod_func.o: mod_func.cpp @printf " -> $(C_GREEN)Compiling$(C_RESET) $<\n" - $(COMPILE) $(INCLUDES) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c $< -o $@ + $(CXXCOMPILE) $(INCLUDES) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c $< -o $@ # Generic build c->o. Need PIC for shared lib $(OBJS_DIR)/%.o: $(MODC_DIR)/%.c | $(OBJS_DIR) @printf " -> $(C_GREEN)Compiling$(C_RESET) $<\n" - $(COMPILE) $(INCLUDES) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c $< -o $@ + $(CXXCOMPILE) $(INCLUDES) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c $< -o $@ include makemod2c_inc diff --git a/cmake/CMakeListsNrnMech.cmake b/cmake/CMakeListsNrnMech.cmake index 7738ca3ed6..09630185ea 100644 --- a/cmake/CMakeListsNrnMech.cmake +++ b/cmake/CMakeListsNrnMech.cmake @@ -66,9 +66,6 @@ foreach(link_lib ${NRN_LINK_LIBS}) string(APPEND NRN_LINK_DEFS " ${link_flag}") endforeach() -# PGI add --c++11;-A option for c++11 flag -string(REPLACE ";" " " CXX11_STANDARD_COMPILE_OPTION "${CMAKE_CXX11_STANDARD_COMPILE_OPTION}") - # Compiler flags depending on cmake build type from BUILD_TYPE__FLAGS string(TOUPPER "${CMAKE_BUILD_TYPE}" _BUILD_TYPE) set(BUILD_TYPE_C_FLAGS "${CMAKE_C_FLAGS_${_BUILD_TYPE}}") diff --git a/cmake/CompilerHelper.cmake b/cmake/CompilerHelper.cmake index 422a15960e..c7b27e21d6 100644 --- a/cmake/CompilerHelper.cmake +++ b/cmake/CompilerHelper.cmake @@ -58,7 +58,5 @@ endif() if(CMAKE_CXX_COMPILER_ID MATCHES "PGI") # CMake adds strict standard complaint PGI flag "-A" which breaks compilation of old codes (e.g. # spdlog, fmt) - set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "") - set(CMAKE_CXX11_STANDARD_COMPILE_OPTION --c++11) set(CMAKE_CXX14_STANDARD_COMPILE_OPTION --c++14) endif() diff --git a/cmake/ConfigFileSetting.cmake b/cmake/ConfigFileSetting.cmake index 2c6b0cde7b..314d6cbec0 100644 --- a/cmake/ConfigFileSetting.cmake +++ b/cmake/ConfigFileSetting.cmake @@ -293,7 +293,7 @@ if(MINGW) nrn_configure_file(nrnsetupmingw.nsi src/mswin) nrn_configure_file(pre_setup_exe.sh src/mswin) # Just name and not path since setup.exe user chooses location of install. - set(CC x86_64-w64-mingw32-gcc.exe) + set(CXX x86_64-w64-mingw32-g++.exe) set(BUILD_MINGW_TRUE "") set(BUILD_MINGW_FALSE "#") set(nrnskip_rebase "#") diff --git a/cmake/MacroHelper.cmake b/cmake/MacroHelper.cmake index 1096494130..c3018bdf77 100644 --- a/cmake/MacroHelper.cmake +++ b/cmake/MacroHelper.cmake @@ -234,14 +234,14 @@ endmacro() # ============================================================================= # Run nocmodl to convert NMODL to C # ============================================================================= -macro(nocmodl_mod_to_c modfile_basename) +macro(nocmodl_mod_to_cpp modfile_basename) add_custom_command( - OUTPUT ${modfile_basename}.c + OUTPUT ${modfile_basename}.cpp COMMAND ${CMAKE_COMMAND} -E env "MODLUNIT=${PROJECT_BINARY_DIR}/share/nrn/lib/nrnunits.lib" ${NRN_NOCMODL_SANITIZER_ENVIRONMENT} ${PROJECT_BINARY_DIR}/bin/nocmodl ${modfile_basename}.mod - COMMAND sed "'s/_reg()/_reg_()/'" ${modfile_basename}.c > ${modfile_basename}.c.tmp - COMMAND mv ${modfile_basename}.c.tmp ${modfile_basename}.c + COMMAND sed "'s/_reg()/_reg_()/'" ${modfile_basename}.cpp > ${modfile_basename}.cpp.tmp + COMMAND mv ${modfile_basename}.cpp.tmp ${modfile_basename}.cpp DEPENDS nocmodl ${modfile_basename}.mod WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/src/nrniv) endmacro() diff --git a/cmake/NeuronFileLists.cmake b/cmake/NeuronFileLists.cmake index 72b4fd1c62..7388a4470a 100644 --- a/cmake/NeuronFileLists.cmake +++ b/cmake/NeuronFileLists.cmake @@ -2,6 +2,7 @@ # Lists of header files to install # ============================================================================= set(HEADER_FILES_TO_INSTALL + bbsavestate.h cabvars.h cspmatrix.h cspredef.h @@ -46,7 +47,8 @@ set(HEADER_FILES_TO_INSTALL scoplib.h section.h spconfig.h - spmatrix.h) + spmatrix.h + treeset.h) # ============================================================================= # Lists of headers populated using check_include_files diff --git a/docs/guide/how_to_get_started.rst b/docs/guide/how_to_get_started.rst index efa8ff7b55..5073d4c251 100644 --- a/docs/guide/how_to_get_started.rst +++ b/docs/guide/how_to_get_started.rst @@ -31,3 +31,12 @@ Using NMODL to add new mechanisms to NEURON * NEURON comes with a bunch of mod files that can serve as starting points for "programming by example." Under MSWin the default mechanisms (hh, pas, expsyn etc.) are in `github.com/neuronsimulator/nrn/tree/master/src/nrnoc `_. A large collection of mod files is at `github.com/neuronsimulator/nrn/tree/master/share/examples/nrniv/nmodl `_. * You may also find useful examples in `ModelDB `_. +.. include:: ../rst_substitutions.txt + +.. note:: + Starting in |neuron_with_cpp_mechanisms|, NMODL is translated into C++ code + instead of C. + This change is not fully backwards compatible, and you may find that older + NMODL code needs to be updated to work with |neuron_with_cpp_mechanisms|. + This is principally an issue for MOD files that include ``VERBATIM`` blocks. + For more information, see :ref:`porting-mechanisms-to-cpp`. diff --git a/docs/guide/index.rst b/docs/guide/index.rst index 7916cbfafc..86ca40cd97 100644 --- a/docs/guide/index.rst +++ b/docs/guide/index.rst @@ -13,4 +13,5 @@ Guides import3d optimization randomness + porting_mechanisms_to_cpp faq \ No newline at end of file diff --git a/docs/guide/porting_mechanisms_to_cpp.rst b/docs/guide/porting_mechanisms_to_cpp.rst new file mode 100644 index 0000000000..5b2df166ec --- /dev/null +++ b/docs/guide/porting_mechanisms_to_cpp.rst @@ -0,0 +1,326 @@ +.. include:: ../rst_substitutions.txt + +.. _porting-mechanisms-to-cpp: + +Adapting MOD files for C++ with |neuron_with_cpp_mechanisms| +============================================================ + +In older versions of NEURON, MOD files containing NMODL code were translated +into C code before being compiled and executed by NEURON. +Starting with |neuron_with_cpp_mechanisms|, NMODL code is translated into C++ +code instead. + +In most cases, this does not present any issues, as simple C code is typically +valid C++, and no changes are required. +However, C and C++ are not the same language, and there are cases in which MOD +files containing ``VERBATIM`` blocks need to be modified in order to build with +|neuron_with_cpp_mechanisms|. + +Before you start, you should decide if you need your MOD files to be +compatible simultaneously with |neuron_with_cpp_mechanisms| **and** older +versions, or if you can safely stop supporting older versions. +Supporting both is generally possible, but it may be more cumbersome than +committing to using C++ features. +Considering NEURON has maintained strong backward compatibility and its +internal numerical methods haven't changed with migration to C++, it is likely +to be sufficient to adapt MOD files to C++ only and use +|neuron_with_cpp_mechanisms|. +If you do decide to preserve compatibility across versions, the preprocessor +macros described in :ref:`python_verbatim` may prove useful. + +.. note:: + If you have a model that stopped compiling when you upgraded to or beyond + |neuron_with_cpp_mechanisms|, the first thing that you should check is + whether the relevant MOD files have already been updated in ModelDB or in the + GitHub repository of that model. You can check the repository name with the + model accession number under ``_. + An updated version may already be available! + + The following models were updated in ModelDB in preparation for + |neuron_with_cpp_mechanisms| and may serve as useful references: + `2487 `_, + `2730 `_, + `2733 `_, + `3658 `_, + `7399 `_, + `7400 `_, + `8284 `_, + `9889 `_, + `12631 `_, + `26997 `_, + `35358 `_, + `37819 `_, + `51781 `_, + `52034 `_, + `64229 `_, + `64296 `_, + `87585 `_, + `93321 `_, + `97868 `_, + `97874 `_, + `97917 `_, + `105507 `_, + `106891 `_, + `113732 `_, + `116094 `_, + `116830 `_, + `116838 `_, + `116862 `_, + `123815 `_, + `136095 `_, + `136310 `_, + `137845 `_, + `138379 `_, + `139421 `_, + `140881 `_, + `141505 `_, + `144538 `_, + `144549 `_, + `144586 `_, + `146949 `_, + `149000 `_, + `149739 `_, + `150240 `_, + `150245 `_, + `150551 `_, + `150556 `_, + `150691 `_, + `151126 `_, + `151282 `_, + `153280 `_, + `154732 `_, + `155568 `_, + `155601 `_, + `155602 `_, + `156780 `_, + `157157 `_, + `168874 `_, + `181967 `_, + `182129 `_, + `183300 `_, + `185355 `_, + `185858 `_, + `186768 `_, + `187604 `_, + `189154 `_, + `194897 `_, + `195615 `_, + `223031 `_, + `225080 `_, + `231427 `_, + `232097 `_, + `239177 `_, + `241165 `_, + `241240 `_, + `244262 `_, + `244848 `_, + `247968 `_, + `249463 `_, + `256388 `_ and + `259366 `_. + +.. + Does this need some more qualification? Are there non-VERBATIM + incompatibilities? + +Legacy patterns that are invalid C++ +------------------------------------ + +This section aims to list some patterns that the NEURON developers have found +in pre-|neuron_with_cpp_mechanisms| models that need to be modified to be valid +C++. + +Implicit pointer type conversions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +C++ has stricter rules governing pointer type conversions than C. For example + +.. code-block:: cpp + + double* x = (void*)0; // valid C, invalid C++ + double* x = nullptr; // valid C++, invalid C + double* x = (double*)0; // valid C and C++ (C-style casts discouraged in C++) + +Similarly, in C one can pass a ``void*`` argument to a function that expects a +``double*``. In C++ this is forbidden. + +The same issue may manifest itself in code such as + +.. code-block:: cpp + + double* x = malloc(7 * sizeof(double)); // valid C, invalid C++ + double* x = new double[7]; // valid C++, invalid C + double* x = (double*)malloc(7 * sizeof(double)); // valid C and C++ (C-style casts discouraged in C++) + +If you choose to move from using C ``malloc`` and ``free`` to using C++ ``new`` +and ``delete`` then remember that you cannot mix and match ``new`` with ``free`` +and so on. + +.. note:: + Explicit memory management with ``new`` and ``delete`` is discouraged in C++ + (`R.11: Avoid calling new and delete explicitly `_). + If you do not need to support older versions of NEURON, you may be able to + use standard library containers such as ``std::vector``. + +.. _local-non-prototype-function-declaration: + +Local non-prototype function declarations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In C, the function declaration + +.. code-block:: c + + void some_function(); + +is a `non-prototype function declaration +`_: it declares +that ``some_function`` exists, but it does not specify the number of arguments +that it takes, or their types. +In C++, the same code declares that ``some_function`` takes zero arguments (the +C equivalent of this is ``void some_function(void)``). + +If such a declaration occurs in a top-level ``VERBATIM`` block then it is +likely to be harmless: it will add a zero-parameter overload of the function, +which will never be called. +It **will**, however, cause a problem if the declaration is included **inside** +an NMODL construct + +.. code-block:: c + + PROCEDURE procedure() { + VERBATIM + void some_method_taking_an_int(); // problematic in C++ + some_method_taking_an_int(42); + ENDVERBATIM + } + +because in this case the local declaration hides the real declaration, which is +something like + +.. code-block:: c + + void some_method_taking_an_int(int); + +in a NEURON header that is included when the translated MOD file is compiled. +In this case, the problematic local declaration can simply be removed. + +.. _function-decls-with-incorrect-types: + +Function declarations with incorrect types +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In older MOD files and versions of NEURON, API methods were often accessed by +declaring them in the MOD file and not by including a correct declaration from +NEURON itself. +In NEURON 8.2+, more declarations are implicitly included when MOD files are +compiled. +This can lead to problems if the declaration in the MOD file did not specify +the correct argument and return types. + +.. code-block:: cpp + + Rand* nrn_random_arg(int); // correct declaration from NEURON header, only in new NEURON + /* ... */ + void* nrn_random_arg(int); // incorrect declaration in MOD file, clashes with previous line + +The fix here is simply to remove the incorrect declaration from the MOD file. + +If the argument types are incorrect, the situation is slightly more nuanced. +This is because C++ supports overloading functions by argument type, but not by +return type. + +.. code-block:: cpp + + void sink(Thing*); // correct declaration from NEURON header, only in new NEURON + /* ... */ + void sink(void*); // incorrect declaration in MOD file, adds an overload, not a compilation error + /* ... */ + void* void_ptr; + sink(void_ptr); // probably used to work, now causes a linker error + Thing* thing_ptr; + sink(thing_ptr); // works with both old and new NEURON + +Here the incorrect declaration ``sink(void*)`` declares a second overload of +the ``sink`` function, which is not defined anywhere. +With |neuron_with_cpp_mechanisms| the ``sink(void_ptr)`` line will select the +``void*`` second overload, based on the argument type, and this will fail during +linking because this overload is not defined (only ``sink(Thing*)`` has a +definition). + +In contrast, ``sink(thing_ptr)`` will select the correct overload in +|neuron_with_cpp_mechanisms|, and it also works in older NEURON versions +because ``Thing*`` can be implicitly converted to ``void*``. + +The fix here is, again, to remove the incorrect declaration from the MOD file. + +See also the section below, :ref:`deprecated-overloads-taking-void`, for cases +where NEURON **does** provide a (deprecated) definition of the ``void*`` +overload. + +K&R function definitions +^^^^^^^^^^^^^^^^^^^^^^^^ +C supports (`until C23 +`_) a legacy +("K&R") syntax for function declarations. +This is not valid C++. + +There is no advantage to the legacy syntax. If you have legacy definitions such +as + +.. code-block:: c + + void foo(a, b) int a, b; { /* ... */ } + +then simply replace them with + +.. code-block:: cpp + + void foo(int a, int b) { /* ... */ } + +which is valid in both C and C++. + +Legacy patterns that are considered deprecated +---------------------------------------------- +As noted above (:ref:`local-non-prototype-function-declaration`), declarations +such as + +.. code-block:: c + + VERBATIM + extern void vector_resize(); + ENDVERBATIM + +at the global scope in MOD files declare C++ function overloads that take no +parameters. +If such declarations appear at the global scope then they do not hide the +correct declarations, so this can be harmless, but it is not necessary. +In |neuron_with_cpp_mechanisms| the full declarations of the NEURON API methods +that can be used in MOD files are implicitly included via the ``mech_api.h`` +header, so this explicit declaration of a zero-parameter overload is not needed +and can safely be removed. + +.. _deprecated-overloads-taking-void: + +Deprecated overloads taking ``void*`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +As noted above (:ref:`function-decls-with-incorrect-types`), +|neuron_with_cpp_mechanisms| provides extra overloads for some API methods that +aim to smooth the transition from C to C++. +These overloads are provided for widely used methods, and where overloading on +return type would not be required. + +An example is the ``vector_capacity`` function, which in +|neuron_with_cpp_mechanisms| has two overloads + +.. code-block:: cpp + + int vector_capacity(IvocVect*); + [[deprecated("non-void* overloads are preferred")]] int vector_capacity(void*); + +The second one simply casts its argument to ``IvocVect*`` and calls the first +one. +The ``[[deprecated]]`` attribute means that MOD files that use the second +overload emit compilation warnings when they are compiled using ``nrnivmodl``. + +If your MOD files produce these deprecation warnings, make sure that the +relevant method (``vector_capacity`` in this example) is being called with an +argument of the correct type (``IvocVect*``), and not a type that is implicitly +converted to ``void*``. diff --git a/docs/python/modelspec/programmatic/mechanisms/nmodl2.rst b/docs/python/modelspec/programmatic/mechanisms/nmodl2.rst index bec76442fe..de08935792 100755 --- a/docs/python/modelspec/programmatic/mechanisms/nmodl2.rst +++ b/docs/python/modelspec/programmatic/mechanisms/nmodl2.rst @@ -463,5 +463,6 @@ Description: merging models into one larger model may eliminate the instability. +.. _python_verbatim: .. include:: ../../../../nmodl/verbatim.rst diff --git a/docs/rst_substitutions.txt b/docs/rst_substitutions.txt new file mode 100644 index 0000000000..714f38ff6f --- /dev/null +++ b/docs/rst_substitutions.txt @@ -0,0 +1 @@ +.. |neuron_with_cpp_mechanisms| replace:: NEURON 9.0[.dev] \ No newline at end of file diff --git a/external/coreneuron b/external/coreneuron index 6215225fe2..53796632df 160000 --- a/external/coreneuron +++ b/external/coreneuron @@ -1 +1 @@ -Subproject commit 6215225fe2814648f55d9457a79d373f72df62c2 +Subproject commit 53796632df93e81e59bd9e746d0293bbee544df5 diff --git a/mingw_files/nrnmingwenv.sh b/mingw_files/nrnmingwenv.sh index 386fe9856d..58b19d2037 100644 --- a/mingw_files/nrnmingwenv.sh +++ b/mingw_files/nrnmingwenv.sh @@ -2,7 +2,7 @@ set -ex -# Copies minimal compiler toolchain +# Copies minimal g++ compiler toolchain # to allow nrnivmodl (mknrndll) to build nrnmech.dll . # if arg then assume it is destination, eg, c:/marshalnrn64/nrn @@ -28,7 +28,7 @@ cp $HOME/.inputrc $NM/etc/inputrc #cp /msys2.ini $NM #cp /msys2_shell.cmd $NM -binprog="basename bash cat cp dirname echo find grep ls make mintty +binprog="basename bash cat cp dirname echo env find git grep ls make mintty mkdir mv rebase rm sed sh sort unzip which cygpath cygcheck uname" for i in $binprog ; do echo $i @@ -63,9 +63,9 @@ cp_dlls $NM/usr/bin $NM/usr/bin M=$NM/mingw64 X=x86_64-w64-mingw32 -gccver=`gcc --version | sed -n '1s/.* //p'` +gccver=`g++ --version | sed -n '1s/.* //p'` if test ! -d "$gccver" ; then - gccver=`gcc --version | sed -n '1s/.*) *\([^ ]*\).*/\1/p'` + gccver=`g++ --version | sed -n '1s/.*) *\([^ ]*\).*/\1/p'` fi # all the folders involved that have files @@ -85,26 +85,29 @@ copy() { copy mingw64/bin ' as.exe ld.exe +x86_64-w64-mingw32-g++.exe x86_64-w64-mingw32-gcc.exe +libstdc++-6.dll ' cp_dlls $NM/mingw64/bin $NM/mingw64/bin copy mingw64/lib/gcc/x86_64-w64-mingw32/$gccver ' cc1.exe +cc1plus.exe libgcc.a liblto_plugin.dll ' cp_dlls $NM/mingw64/lib/gcc/x86_64-w64-mingw32/$gccver $NM/mingw64/bin rm -f $NM/mingw64/bin/libwinpthread-1.dll # already in $N/bin -# copy all needed include files by processing output of gcc -E +# copy all needed include files by processing output of g++ -E copyinc() { - echo "" > temp.c + echo "" > temp.cxx for i in $* ; do echo "#include <$i>" - done >> temp.c - echo "int main(int argc, char** argv){return 0;}" >> temp.c - gcc -E temp.c | grep '^#.*include' > temp1 + done >> temp.cxx + echo "int main(int argc, char** argv){return 0;}" >> temp.cxx + g++ -E temp.cxx | grep '^#.*include' > temp1 sed -n 's,^.*msys64/,,p' temp1 | sed -n 's,".*,,p' > temp2 sort temp2 | uniq > temp3 sed -n 's,/[^/]*$,,p' temp3 | sort | uniq > temp4 @@ -116,6 +119,12 @@ copyinc() { done } + +copyinc ' +cstdint +' + +# from gcc days and all (most) ModelDB include copyinc ' _mingw.h _mingw_mac.h @@ -126,7 +135,9 @@ corecrt.h corecrt_startup.h corecrt_wstdlib.h crtdefs.h +ctype.h errno.h +float.h inttypes.h limits.h malloc.h @@ -137,13 +148,14 @@ pthread_compat.h pthread_signal.h pthread_unistd.h signal.h -stdio.h stddef.h stdint.h +stdio.h stdlib.h string.h swprintf.inl time.h +sys/time.h unistd.h vadefs.h ' @@ -174,4 +186,5 @@ if test -f /mingw64/lib/libgcc_s.a ; then # gcc 11.2.0 Rev 10 fi copy $gcclib ' libgcc_s.a +libstdc++.dll.a ' diff --git a/src/ivoc/graph.cpp b/src/ivoc/graph.cpp index eb43d28a82..2cadc7a8b9 100644 --- a/src/ivoc/graph.cpp +++ b/src/ivoc/graph.cpp @@ -48,6 +48,7 @@ extern Image* gif_image(const char*); #include "classreg.h" #include "gui-redirect.h" +#include "treeset.h" extern Object** (*nrnpy_gui_helper_)(const char* name, Object* obj); extern double (*nrnpy_object_to_double_)(Object*); @@ -1497,7 +1498,6 @@ Graph::Graph(bool b) extern "C" { extern void hoc_free_list(Symlist**); -extern double* nrn_recalc_ptr(double*); } // extern "C"; Graph::~Graph() { diff --git a/src/ivoc/ivocmain.cpp b/src/ivoc/ivocmain.cpp index d021c7e1ed..e273b65864 100644 --- a/src/ivoc/ivocmain.cpp +++ b/src/ivoc/ivocmain.cpp @@ -873,7 +873,6 @@ void ivoc_final_exit() { } extern "C" { -extern double* getarg(int i); extern int ifarg(int); } // extern "C" diff --git a/src/ivoc/ivocrand.cpp b/src/ivoc/ivocrand.cpp index bc5cdc3743..27ac546820 100644 --- a/src/ivoc/ivocrand.cpp +++ b/src/ivoc/ivocrand.cpp @@ -58,17 +58,6 @@ class RandomPlay: public Observer, public Resource { using RandomPlayList = std::vector; static RandomPlayList* random_play_list_; -extern "C" { -double nrn_random_pick(Rand* r); -void nrn_random_reset(Rand* r); -Rand* nrn_random_arg(int); -long nrn_get_random_sequence(Rand* r); -void nrn_set_random_sequence(Rand* r, long seq); -int nrn_random_isran123(Rand* r, uint32_t* id1, uint32_t* id2, uint32_t* id3); -int nrn_random123_setseq(Rand* r, uint32_t seq, char which); -int nrn_random123_getseq(Rand* r, uint32_t* seq, char* which); -} // extern "C" - #include class NrnRandom123: public RNG { @@ -321,19 +310,19 @@ static double r_MCellRan4(void* r) { return (double) mcr->orig_; } -extern "C" long nrn_get_random_sequence(Rand* r) { +long nrn_get_random_sequence(Rand* r) { assert(r->type_ == 2); MCellRan4* mcr = (MCellRan4*) r->gen; return mcr->ihigh_; } -extern "C" void nrn_set_random_sequence(Rand* r, long seq) { +void nrn_set_random_sequence(Rand* r, long seq) { assert(r->type_ == 2); MCellRan4* mcr = (MCellRan4*) r->gen; mcr->ihigh_ = seq; } -extern "C" int nrn_random_isran123(Rand* r, uint32_t* id1, uint32_t* id2, uint32_t* id3) { +int nrn_random_isran123(Rand* r, uint32_t* id1, uint32_t* id2, uint32_t* id3) { if (r->type_ == 4) { NrnRandom123* nr = (NrnRandom123*) r->gen; nrnran123_getids3(nr->s_, id1, id2, id3); @@ -436,7 +425,7 @@ static double r_repick(void* r) { return (*(x->rand))(); } -extern "C" double nrn_random_pick(Rand* r) { +double nrn_random_pick(Rand* r) { if (r) { return (*(r->rand))(); } else { @@ -444,13 +433,13 @@ extern "C" double nrn_random_pick(Rand* r) { } } -extern "C" void nrn_random_reset(Rand* r) { +void nrn_random_reset(Rand* r) { if (r) { r->gen->reset(); } } -extern "C" Rand* nrn_random_arg(int i) { +Rand* nrn_random_arg(int i) { Object* ob = *hoc_objgetarg(i); check_obj_type(ob, "Random"); Rand* r = (Rand*) (ob->u.this_pointer); @@ -649,3 +638,26 @@ void Random_reg() { class2oc("Random", r_cons, r_destruct, r_members, NULL, NULL, NULL); random_play_list_ = new RandomPlayList; } + +// Deprecated backwards-compatibility definitions +long nrn_get_random_sequence(void* r) { + return nrn_get_random_sequence(static_cast(r)); +} +int nrn_random_isran123(void* r, uint32_t* id1, uint32_t* id2, uint32_t* id3) { + return nrn_random_isran123(static_cast(r), id1, id2, id3); +} +double nrn_random_pick(void* r) { + return nrn_random_pick(static_cast(r)); +} +void nrn_random_reset(void* r) { + nrn_random_reset(static_cast(r)); +} +int nrn_random123_getseq(void* r, uint32_t* seq, char* which) { + return nrn_random123_getseq(static_cast(r), seq, which); +} +int nrn_random123_setseq(void* r, uint32_t seq, char which) { + return nrn_random123_setseq(static_cast(r), seq, which); +} +void nrn_set_random_sequence(void* r, int seq) { + nrn_set_random_sequence(static_cast(r), static_cast(seq)); +} \ No newline at end of file diff --git a/src/ivoc/ivocvect.cpp b/src/ivoc/ivocvect.cpp index bcd3f20f35..a3385366f7 100644 --- a/src/ivoc/ivocvect.cpp +++ b/src/ivoc/ivocvect.cpp @@ -129,8 +129,10 @@ static double dmaxint_ = 9007199254740992; #include "utility.h" #endif #include "oc2iv.h" -#include "parse.hpp" +#include "oc_ansi.h" #include "ocfile.h" +#include "ocfunc.h" +#include "parse.hpp" extern Object* hoc_thisobject; extern Symlist* hoc_top_level_symlist; @@ -139,14 +141,6 @@ IvocVect* (*nrnpy_vec_from_python_p_)(void*); Object** (*nrnpy_vec_to_python_p_)(void*); Object** (*nrnpy_vec_as_numpy_helper_)(int, double*); -// math functions with error checking defined in oc/SRC/math.cpp -extern double hoc_Log(double x), hoc_Log10(double x), /*hoc_Exp(double x), */ hoc_Sqrt(double x); -extern double hoc_scan(FILE*); - -extern "C" { -extern double hoc_Exp(double); -} // extern "C" - static int narg() { int i = 0; while (ifarg(i++)) @@ -166,12 +160,10 @@ static int narg() { int cmpfcn(double a, double b) { return ((a) <= (b)) ? (((a) == (b)) ? 0 : -1) : 1; } -typedef int (*doubleComparator)(double, double); extern "C" { extern void install_vector_method(const char* name, Pfrd_vp); extern int vector_instance_px(void*, double**); -extern int nrn_mlh_gsort(double* vec, int* base_ptr, int total_elems, doubleComparator cmp); } // extern "C" extern int vector_arg_px(int, double**); @@ -298,38 +290,60 @@ static Symbol* svec_; // extern "C" vector functions used by ocmatrix.dll // can also be used in mod files -Vect* vector_new(int n, Object* o) { - return new Vect(n, o); -} -Vect* vector_new0() { - return new Vect(); -} -Vect* vector_new1(int n) { - return new Vect(n); -} -Vect* vector_new2(Vect* v) { - return new Vect(*v); -} void vector_delete(Vect* v) { delete v; } -int vector_buffer_size(Vect* v) { +IvocVect* vector_arg(int i) { + Object* ob = *hoc_objgetarg(i); + if (!ob || ob->ctemplate != svec_->u.ctemplate) { + check_obj_type(ob, "Vector"); + } + return static_cast(ob->u.this_pointer); +} +int vector_buffer_size(IvocVect* v) { return v->buffer_size(); } -int vector_capacity(Vect* v) { +int vector_buffer_size(void* v) { + return vector_buffer_size(static_cast(v)); +} +int vector_capacity(IvocVect* v) { return v->size(); } -void vector_resize(Vect* v, int n) { +int vector_capacity(void* v) { + return vector_capacity(static_cast(v)); +} +IvocVect* vector_new(int n, Object* o) { + return new IvocVect(n, o); +} +IvocVect* vector_new0() { + return new IvocVect(); +} +IvocVect* vector_new1(int n) { + return new IvocVect(n); +} +IvocVect* vector_new2(IvocVect* v) { + return new IvocVect(*v); +} +Object** vector_pobj(IvocVect* v) { + return &v->obj_; +} +Object** vector_pobj(void* v) { + return vector_pobj(static_cast(v)); +} +void vector_resize(IvocVect* v, int n) { v->resize(n); } -Object** vector_temp_objvar(Vect* v) { - return v->temp_objvar(); +void vector_resize(void* v, int n) { + vector_resize(static_cast(v), n); } -double* vector_vec(Vect* v) { +double* vector_vec(IvocVect* v) { return v->data(); } -Object** vector_pobj(Vect* v) { - return &v->obj_; +double* vector_vec(void* v) { + return vector_vec(static_cast(v)); +} +Object** vector_temp_objvar(Vect* v) { + return v->temp_objvar(); } char* vector_get_label(Vect* v) { return v->label_; @@ -394,14 +408,6 @@ extern "C" int vector_instance_px(void* v, double** px) { return x->size(); } -extern "C" Vect* vector_arg(int i) { - Object* ob = *hoc_objgetarg(i); - if (!ob || ob->ctemplate != svec_->u.ctemplate) { - check_obj_type(ob, "Vector"); - } - return (Vect*) (ob->u.this_pointer); -} - int is_vector_arg(int i) { Object* ob = *hoc_objgetarg(i); if (!ob || ob->ctemplate != svec_->u.ctemplate) { @@ -4033,7 +4039,7 @@ static inline void SWAP(int* A, int* B) { smaller partition. This *guarantees* no more than log (n) stack size is needed! */ -extern "C" int nrn_mlh_gsort(double* vec, int* base_ptr, int total_elems, doubleComparator cmp) { +int nrn_mlh_gsort(double* vec, int* base_ptr, int total_elems, int (*cmp)(double, double)) { /* Stack node declarations used to store unfulfilled partition obligations. */ struct stack_node { int* lo; diff --git a/src/ivoc/ivocvect.h b/src/ivoc/ivocvect.h index 131bd62568..d114d05886 100644 --- a/src/ivoc/ivocvect.h +++ b/src/ivoc/ivocvect.h @@ -11,7 +11,6 @@ extern "C" { extern void notify_freed_val_array(double*, size_t); } -#define Vect IvocVect using ParentVect = std::vector; struct Object; @@ -115,31 +114,15 @@ double stdDev(InputIterator begin, InputIterator end) { } extern "C" { -extern Vect* vector_new(int, Object*); // use this if possible -extern Vect* vector_new0(); -extern Vect* vector_new1(int); -extern Vect* vector_new2(Vect*); -extern void vector_delete(Vect*); -extern int vector_buffer_size(Vect*); -extern Object** vector_temp_objvar(Vect*); -extern Object** vector_pobj(Vect*); +extern void vector_delete(IvocVect*); +extern Object** vector_temp_objvar(IvocVect*); extern int is_vector_arg(int); -extern char* vector_get_label(Vect*); -extern void vector_set_label(Vect*, char*); +extern char* vector_get_label(IvocVect*); +extern void vector_set_label(IvocVect*, char*); } // extern "C" -#if defined(__cplusplus) -extern "C" { -#endif - -extern Vect* vector_arg(int); -extern double* vector_vec(Vect*); -extern int vector_capacity(Vect*); -extern void vector_resize(Vect*, int); - -#if defined(__cplusplus) -} -#endif +// olupton 2022-01-21: backwards compatibility +using Vect = IvocVect; #endif diff --git a/src/ivoc/matrix.cpp b/src/ivoc/matrix.cpp index 0f893bc616..4dbadde2b7 100644 --- a/src/ivoc/matrix.cpp +++ b/src/ivoc/matrix.cpp @@ -14,7 +14,6 @@ static Symbol* smat_; extern int hoc_return_type_code; extern double hoc_scan(FILE*); -extern "C" FILE* hoc_obj_file_arg(int i); extern Object** hoc_temp_objptr(Object*); #if 0 @@ -203,7 +202,7 @@ static Object** m_mulv(void* v) { vout = vector_arg(2); } else { #ifdef WIN32 - vout = vector_new1(m->nrow()); + vout = vector_new(m->nrow()); #else vout = new Vect(m->nrow()); #endif @@ -332,7 +331,7 @@ static Object** m_symmeig(void* v) { out->resize(m->nrow(), m->ncol()); Vect* vout; #ifdef WIN32 - vout = vector_new1(m->nrow()); + vout = vector_new(m->nrow()); p = vector_temp_objvar(vout); #else vout = new Vect(m->nrow()); @@ -355,7 +354,7 @@ static Object** m_svd(void* vv) { Vect* d; int dsize = m->nrow() < m->ncol() ? m->nrow() : m->ncol(); #ifdef WIN32 - d = vector_new1(dsize); + d = vector_new(dsize); p = vector_temp_objvar(d); #else d = new Vect(dsize); @@ -393,7 +392,7 @@ static Object** m_getrow(void* v) { #endif } else { #ifdef WIN32 - vout = vector_new1(m->ncol()); + vout = vector_new(m->ncol()); #else vout = new Vect(m->ncol()); #endif @@ -419,7 +418,7 @@ static Object** m_getcol(void* v) { #endif } else { #ifdef WIN32 - vout = vector_new1(m->nrow()); + vout = vector_new(m->nrow()); #else vout = new Vect(m->nrow()); #endif @@ -496,7 +495,7 @@ static Object** m_getdiag(void* v) { #endif } else { #ifdef WIN32 - vout = vector_new1(m->nrow()); + vout = vector_new(m->nrow()); #else vout = new Vect(m->nrow()); #endif @@ -579,7 +578,7 @@ static Object** m_solv(void* v) { } if (!vout) { #ifdef WIN32 - vout = vector_new1(m->nrow()); + vout = vector_new(m->nrow()); #else vout = new Vect(m->nrow()); #endif @@ -634,7 +633,7 @@ static Object** m_to_vector(void* v) { vout = vector_arg(1); vector_resize(vout, nrow * ncol); } else { - vout = vector_new1(nrow * ncol); + vout = vector_new(nrow * ncol); } k = 0; double* ve = vector_vec(vout); diff --git a/src/ivoc/ocfile.cpp b/src/ivoc/ocfile.cpp index 5154e99d82..fe6df0ac89 100644 --- a/src/ivoc/ocfile.cpp +++ b/src/ivoc/ocfile.cpp @@ -51,9 +51,7 @@ int ivoc_unlink(const char* s) { } #include "hocstr.h" -extern "C" FILE* hoc_obj_file_arg(int i); - -extern "C" FILE* hoc_obj_file_arg(int i) { +FILE* hoc_obj_file_arg(int i) { Object* ob = *hoc_objgetarg(i); check_obj_type(ob, "File"); OcFile* f = (OcFile*) (ob->u.this_pointer); diff --git a/src/ivoc/xmenu.cpp b/src/ivoc/xmenu.cpp index ffb0925369..494989388b 100644 --- a/src/ivoc/xmenu.cpp +++ b/src/ivoc/xmenu.cpp @@ -50,6 +50,7 @@ char** (*nrnpy_gui_helper3_str_)(const char* name, Object* obj, int handle_strpt #include "parse.hpp" #include "utility.h" #include "scenepic.h" +#include "treeset.h" // The problem this overcomes is that the pick of an input handler normally @@ -168,7 +169,6 @@ static String* xvalue_format; extern int units_on_flag_; extern Symbol* hoc_get_last_pointer_symbol(); -extern "C" double* nrn_recalc_ptr(double*); void hoc_notify_value() { Oc oc; oc.notify(); diff --git a/src/modlunit/units.cpp b/src/modlunit/units.cpp index 8ad5b2829e..d1736afc77 100644 --- a/src/modlunit/units.cpp +++ b/src/modlunit/units.cpp @@ -1173,11 +1173,12 @@ void nrnunit_dynamic_str(char* buf, const char* name, char* u1, char* u2) { double legacy = dynam_unit_mag(1, u1, u2); double modern = dynam_unit_mag(0, u1, u2); + // TODO: use %a instead of %.18g when translated mechanisms are compiled with + // C++17 instead of C++14 to get an exact hex representation of a double sprintf(buf, "\n" "#define %s _nrnunit_%s[_nrnunit_use_legacy_]\n" - /*since c++17/c99, %a instead of %.18g for exact hex representation of double*/ - "static double _nrnunit_%s[2] = {%a, %g}; /* %.18g */\n", + "static double _nrnunit_%s[2] = {%.18g, %g};\n", name, name, name, diff --git a/src/mswin/lib/mknrndl2.sh b/src/mswin/lib/mknrndl2.sh index 9f3bd0ad87..2ef81903bf 100755 --- a/src/mswin/lib/mknrndl2.sh +++ b/src/mswin/lib/mknrndl2.sh @@ -41,34 +41,34 @@ echo '#include #include "hocdec.h" #define IMPORT extern __declspec(dllimport) IMPORT int nrnmpi_myid, nrn_nobanner_; -' > mod_func.c +' > mod_func.cpp for i in $prefixes do - echo extern void _"$i"_reg"();" >> mod_func.c + echo "extern \"C\" void _${i}_reg();" >> mod_func.cpp done echo ' -void modl_reg(){ +extern "C" void modl_reg(){ //nrn_mswindll_stdio(stdin, stdout, stderr); if (!nrn_nobanner_) if (nrnmpi_myid < 1) { fprintf(stderr, "Additional mechanisms from files'$newline'"); -' >> mod_func.c +' >> mod_func.cpp for i in $files do - echo 'fprintf(stderr," '$i'");' >>mod_func.c + echo 'fprintf(stderr," '$i'");' >>mod_func.cpp done echo 'fprintf(stderr, "'$newline'"); - }' >>mod_func.c + }' >>mod_func.cpp echo -n 'MODOBJFILES=' >$$.tmp for i in $prefixes do - echo _"$i"_reg"();" >> mod_func.c + echo _"$i"_reg"();" >> mod_func.cpp echo -n " $i.o" >> $$.tmp done -echo "}" >> mod_func.c +echo "}" >> mod_func.cpp #echo ' "' >> $$.tmp # cat $$.tmp diff --git a/src/mswin/lib/mknrndl2a.sh b/src/mswin/lib/mknrndl2a.sh new file mode 100644 index 0000000000..994bd5990f --- /dev/null +++ b/src/mswin/lib/mknrndl2a.sh @@ -0,0 +1,6 @@ +#!env bash +export N="$1" +export PATH="$2" +export MODLUNIT="$3" +export TMP="$N/mingw/tmp" +$N/lib/mknrndl2.sh diff --git a/src/mswin/lib/mknrndll.mak.in b/src/mswin/lib/mknrndll.mak.in index f28ebb361d..2bb7e11c95 100755 --- a/src/mswin/lib/mknrndll.mak.in +++ b/src/mswin/lib/mknrndll.mak.in @@ -1,10 +1,10 @@ # for x86_64-w64-mingw64 need the full name of the compiler. -@BUILD_MINGW_TRUE@CC = @CC@ -@BUILD_MINGW_FALSE@CC = gcc +@BUILD_MINGW_TRUE@CXX = @CXX@ +@BUILD_MINGW_FALSE@CXX = g++ EXTRA_FLAGS = @MINGW_CFLAG@ -CFLAGS = \ +CXXFLAGS = \ -DDLL_EXPORT -DPIC \ -I$N/include -I$N/src/scopmath -I$N/src/nrnoc -I$N/src/oc \ $(EXTRA_FLAGS) @@ -15,36 +15,36 @@ bin = bin@binsuffix@ # to handle variations of filename extensions .SUFFIXES: .o .mod .moD .mOd .mOD .Mod .MoD .MOd .MOD -.PRECIOUS: %.c +.PRECIOUS: %.cpp %.o : %.mod -%.c : %.mod +%.cpp : %.mod nocmodl $* -%.o : %.c - $(CC) $(CFLAGS) -c $*.c +%.o : %.cpp + $(CXX) $(CXXFLAGS) -c $*.cpp # additional rules to handle variations of filename extensions -%.c : %.moD +%.cpp : %.moD nocmodl $* -%.c : %.mOd +%.cpp : %.mOd nocmodl $* -%.c : %.mOD +%.cpp : %.mOD nocmodl $* -%.c : %.Mod +%.cpp : %.Mod nocmodl $* -%.c : %.MoD +%.cpp : %.MoD nocmodl $* -%.c : %.MOd +%.cpp : %.MOd nocmodl $* -%.c : %.MOD +%.cpp : %.MOD nocmodl $* %.o : %.moD @@ -61,11 +61,11 @@ bin = bin@binsuffix@ %.o : %.MOD -mod_func.o: mod_func.c - $(CC) $(CFLAGS) -c $*.c +mod_func.o: mod_func.cpp + $(CXX) $(CXXFLAGS) -c $*.cpp nrnmech.dll: mod_func.o $(MODOBJFILES) - $(CC) $(EXTRA_FLAGS) -shared mod_func.o $(MODOBJFILES) \ + $(CXX) $(EXTRA_FLAGS) -shared mod_func.o $(MODOBJFILES) \ -L$N/$(bin) -lnrniv -lpthread -o $(TARGET) @nrnskip_rebase@rebase -b 0x64000000 -v nrnmech.dll diff --git a/src/mswin/pre_setup_exe.sh.in b/src/mswin/pre_setup_exe.sh.in index dc392c2c31..957cd3f98d 100644 --- a/src/mswin/pre_setup_exe.sh.in +++ b/src/mswin/pre_setup_exe.sh.in @@ -70,8 +70,10 @@ cp_dlls $N/bin export N export MODLUNIT=$N/lib/nrnunits.lib export PATH=$nx/bin:$nx/mingw/usr/bin:$nx/mingw/mingw64/bin:$PATH - cd $N/demo/release ; $N/lib/mknrndl2.sh - rm *.o *.c + cd $N/demo/release + # wrapper for mknrndl2.sh is needed because child bash has almost empty environment + $srcdir/src/mswin/lib/mknrndl2a.sh "$N" "$PATH" "$MODLUNIT" + rm *.o *.cpp if test ! -f nrnmech.dll ; then echo 'could not build nrnmech.dll' exit 1; diff --git a/src/nmodl/deriv.cpp b/src/nmodl/deriv.cpp index d5ce0e1c9b..0709ad0d06 100644 --- a/src/nmodl/deriv.cpp +++ b/src/nmodl/deriv.cpp @@ -122,7 +122,9 @@ void solv_diffeq(Item* qsol, lappendstr(thread_mem_init_list, buf); Sprintf(buf, " free((void*)(_thread[_dith%d]._pval));\n", listnum); lappendstr(thread_cleanup_list, buf); - Sprintf(buf, " nrn_destroy_newtonspace(_newtonspace%d);\n", listnum); + Sprintf(buf, + " nrn_destroy_newtonspace(static_cast(_newtonspace%d));\n", + listnum); lappendstr(thread_cleanup_list, buf); thread_data_index += 4; } else { diff --git a/src/nmodl/kinetic.cpp b/src/nmodl/kinetic.cpp index 6ef67cd99a..38999604b3 100644 --- a/src/nmodl/kinetic.cpp +++ b/src/nmodl/kinetic.cpp @@ -917,11 +917,17 @@ for(_i=%d;_i<%d;_i++){\n", } else { /*for sparse matrix solver*/ /* boilerplate for using sparse matrix solver */ - Sprintf(buf, "static double *_coef%d;\n", fun->u.i); - qv = linsertstr(procfunc, buf); + { + static int first = 1; + if (first) { + first = 0; + Sprintf(buf, "static double *_coef%d;\n", fun->u.i); + qv = linsertstr(procfunc, buf); #if VECTORIZE - vectorize_substitute(qv, ""); + vectorize_substitute(qv, ""); #endif + } + } Sprintf(buf, "\n#define _RHS%d(_arg) _coef%d[_arg + 1]\n", fun->u.i, fun->u.i); qv = linsertstr(procfunc, buf); #if VECTORIZE @@ -935,8 +941,8 @@ for(_i=%d;_i<%d;_i++){\n", qv = linsertstr(procfunc, buf); #if VECTORIZE Sprintf(buf, - "\n#define _MATELM%d(_row,_col) *(_nrn_thread_getelm(_so, _row + 1, _col + " - "1))\n", + "\n#define _MATELM%d(_row,_col) " + "*(_nrn_thread_getelm(static_cast(_so), _row + 1, _col + 1))\n", fun->u.i); vectorize_substitute(qv, buf); #endif @@ -944,7 +950,7 @@ for(_i=%d;_i<%d;_i++){\n", static int first = 1; if (first) { first = 0; - Sprintf(buf, "extern double *_getelm();\n"); + Sprintf(buf, "extern double *_getelm(int, int);\n"); qv = linsertstr(procfunc, buf); #if VECTORIZE Sprintf(buf, "extern double *_nrn_thread_getelm(SparseObj*, int, int);\n"); diff --git a/src/nmodl/modl.cpp b/src/nmodl/modl.cpp index e20d58125b..9c6e6a3612 100644 --- a/src/nmodl/modl.cpp +++ b/src/nmodl/modl.cpp @@ -87,7 +87,7 @@ static struct option long_options[] = {{"version", no_argument, 0, 'v'}, {0, 0, 0, 0}}; static void show_options(char** argv) { - fprintf(stderr, "Source to source compiler from NMODL to C\n"); + fprintf(stderr, "Source to source compiler from NMODL to C++\n"); fprintf(stderr, "Usage: %s [options] Inputfile\n", argv[0]); fprintf(stderr, "Options:\n"); fprintf(stderr, @@ -157,7 +157,7 @@ int main(int argc, char** argv) { #if NMODL || HMODL #else #if !SIMSYS - Fprintf(stderr, "Translating %s into %s.c and %s.var\n", finname, modprefix, modprefix); + Fprintf(stderr, "Translating %s into %s.cpp and %s.var\n", finname, modprefix, modprefix); #endif #endif IGNORE(yyparse()); @@ -224,17 +224,18 @@ no longer adequate for saying we can not */ #endif if (nmodl_text) { Item* q; - char* pf = NULL; + char* pf{nullptr}; #if HAVE_REALPATH && !defined(NRN_AVOID_ABSOLUTE_PATHS) - pf = realpath(finname, NULL); + pf = realpath(finname, nullptr); #endif - fprintf(fcout, - "\n#if NMODL_TEXT\nstatic const char* nmodl_filename = \"%s\";\nstatic const char* " - "nmodl_file_text = \n", - pf ? pf : finname); + fprintf( + fcout, + "\n#if NMODL_TEXT\nstatic void register_nmodl_text_and_filename(int mech_type) {\n"); + fprintf(fcout, " const char* nmodl_filename = \"%s\";\n", pf ? pf : finname); if (pf) { free(pf); } + fprintf(fcout, " const char* nmodl_file_text = \n"); ITERATE(q, filetxtlist) { char* s = STR(q); char* cp; @@ -250,7 +251,11 @@ no longer adequate for saying we can not */ fputc(*cp, fcout); } } - fprintf(fcout, " ;\n#endif\n"); + fprintf(fcout, " ;\n"); + fprintf(fcout, " hoc_reg_nmodl_filename(mech_type, nmodl_filename);\n"); + fprintf(fcout, " hoc_reg_nmodl_text(mech_type, nmodl_file_text);\n"); + fprintf(fcout, "}\n"); + fprintf(fcout, "#endif\n"); } #endif @@ -264,7 +269,7 @@ no longer adequate for saying we can not */ fprintf(stderr, "Derivatives of STATE array variables are not translated correctly and compile " "time errors will be generated.\n"); - fprintf(stderr, "The %s.c file may be manually edited to fix these errors.\n", modprefix); + fprintf(stderr, "The %s.cpp file may be manually edited to fix these errors.\n", modprefix); } #endif @@ -323,12 +328,12 @@ static void openfiles(char* given_filename, char* output_dir) { } char* basename = strrchr(modprefix, '/'); if (basename) { - Sprintf(output_filename, "%s%s.c", output_dir, basename); + Sprintf(output_filename, "%s%s.cpp", output_dir, basename); } else { - Sprintf(output_filename, "%s/%s.c", output_dir, modprefix); + Sprintf(output_filename, "%s/%s.cpp", output_dir, modprefix); } } else { - Sprintf(output_filename, "%s.c", modprefix); + Sprintf(output_filename, "%s.cpp", modprefix); } if ((fcout = fopen(output_filename, "w")) == (FILE*) 0) { @@ -355,24 +360,7 @@ static void openfiles(char* given_filename, char* output_dir) { #endif } -static std::string str_replace(std::string str, - const std::string& search_str, - const std::string& replace_str) { - if (search_str.empty()) { - return str; - } - - size_t pos; - while ((pos = str.find(search_str)) != std::string::npos) { - str.replace(pos, search_str.size(), replace_str); - } - - return str; -} - // Post-adjustments for VERBATIM blocks (i.e make them compatible with CPP). void verbatim_adjust(char* q) { - // template is a reserved CPP keyword - const std::string repl = str_replace(q, "u.template", "u.ctemplate"); - Fprintf(fcout, "%s", repl.c_str()); + Fprintf(fcout, "%s", q); } diff --git a/src/nmodl/noccout.cpp b/src/nmodl/noccout.cpp index 5d73693f30..6be257ff43 100644 --- a/src/nmodl/noccout.cpp +++ b/src/nmodl/noccout.cpp @@ -211,7 +211,7 @@ void c_out() { #if NMODL /* generation of initmodel interface */ #if VECTORIZE - P("\nstatic void nrn_init(NrnThread* _nt, _Memb_list* _ml, int _type){\n"); + P("\nstatic void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){\n"); P("Node *_nd; double _v; int* _ni; int _iml, _cntml;\n"); P("#if CACHEVEC\n"); P(" _ni = _ml->_nodeindices;\n"); @@ -262,7 +262,7 @@ void c_out() { well as make sure all currents accumulated properly (currents list) */ if (brkpnt_exists) { - P("\nstatic void nrn_cur(NrnThread* _nt, _Memb_list* _ml, int _type){\n"); + P("\nstatic void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type){\n"); P("Node *_nd; int* _ni; double _rhs, _v; int _iml, _cntml;\n"); P("#if CACHEVEC\n"); P(" _ni = _ml->_nodeindices;\n"); @@ -336,7 +336,7 @@ void c_out() { /* for the classic breakpoint block, nrn_cur computed the conductance, _g, and now the jacobian calculation merely returns that */ - P("\nstatic void nrn_jacob(NrnThread* _nt, _Memb_list* _ml, int _type){\n"); + P("\nstatic void nrn_jacob(NrnThread* _nt, Memb_list* _ml, int _type){\n"); P("Node *_nd; int* _ni; int _iml, _cntml;\n"); P("#if CACHEVEC\n"); P(" _ni = _ml->_nodeindices;\n"); @@ -385,7 +385,7 @@ void c_out() { /* nrnstate list contains the EQUATION solve statement so this advances states by dt */ #if VECTORIZE - P("\nstatic void nrn_state(NrnThread* _nt, _Memb_list* _ml, int _type){\n"); + P("\nstatic void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type){\n"); #else P("\nstatic nrn_state(_prop, _v) Prop *_prop; double _v; {\n"); #endif @@ -697,7 +697,7 @@ void c_out_vectorize() { Fflush(fcout); /* generation of initmodel interface */ - P("\nstatic void nrn_init(NrnThread* _nt, _Memb_list* _ml, int _type){\n"); + P("\nstatic void nrn_init(NrnThread* _nt, Memb_list* _ml, int _type){\n"); P("double* _p; Datum* _ppvar; Datum* _thread;\n"); P("Node *_nd; double _v; int* _ni; int _iml, _cntml;\n"); P("#if CACHEVEC\n"); @@ -756,7 +756,7 @@ void c_out_vectorize() { well as make sure all currents accumulated properly (currents list) */ if (brkpnt_exists) { - P("\nstatic void nrn_cur(NrnThread* _nt, _Memb_list* _ml, int _type) {\n"); + P("\nstatic void nrn_cur(NrnThread* _nt, Memb_list* _ml, int _type) {\n"); P("double* _p; Datum* _ppvar; Datum* _thread;\n"); P("Node *_nd; int* _ni; double _rhs, _v; int _iml, _cntml;\n"); P("#if CACHEVEC\n"); @@ -842,7 +842,7 @@ void c_out_vectorize() { P(" \n}\n"); /* for the classic breakpoint block, nrn_cur computed the conductance, _g, and now the jacobian calculation merely returns that */ - P("\nstatic void nrn_jacob(NrnThread* _nt, _Memb_list* _ml, int _type) {\n"); + P("\nstatic void nrn_jacob(NrnThread* _nt, Memb_list* _ml, int _type) {\n"); P("double* _p; Datum* _ppvar; Datum* _thread;\n"); P("Node *_nd; int* _ni; int _iml, _cntml;\n"); P("#if CACHEVEC\n"); @@ -893,7 +893,7 @@ void c_out_vectorize() { /* nrnstate list contains the EQUATION solve statement so this advances states by dt */ - P("\nstatic void nrn_state(NrnThread* _nt, _Memb_list* _ml, int _type) {\n"); + P("\nstatic void nrn_state(NrnThread* _nt, Memb_list* _ml, int _type) {\n"); if (nrnstate || currents->next == currents) { P("double* _p; Datum* _ppvar; Datum* _thread;\n"); P("Node *_nd; double _v = 0.0; int* _ni; int _iml, _cntml;\n"); @@ -940,7 +940,6 @@ void c_out_vectorize() { P(" if (!_first) return;\n"); printlist(initlist); P("_first = 0;\n}\n"); - P("\n#if defined(__cplusplus)\n} /* extern \"C\" */\n#endif\n"); } void vectorize_substitute(Item* q, char* str) { diff --git a/src/nmodl/nocpout.cpp b/src/nmodl/nocpout.cpp index b738dde825..9d87e31d3d 100644 --- a/src/nmodl/nocpout.cpp +++ b/src/nmodl/nocpout.cpp @@ -237,12 +237,7 @@ void parout() { if (brkpnt_exists) { brkpnt_str_ = "nrn_cur, nrn_jacob, nrn_state"; } else { - brkpnt_str_ = "0, 0, 0"; -#if 1 || defined(__MINGW32__) - /* x86_64-w64-mingw32-gcc passed 0 without zeroing the high 32 bits */ - /* also cygwin64 gcc 4.8.1, so cast to void* universally */ - brkpnt_str_ = "(void*)0, (void*)0, (void*)0"; -#endif + brkpnt_str_ = "nullptr, nullptr, nullptr"; } for (modbase = modprefix + strlen(modprefix); modbase != modprefix; modbase--) { @@ -279,7 +274,7 @@ void parout() { \n#if METHOD3\nextern int _method3;\n#endif\n\ \n#if !NRNGPU\ \n#undef exp\ -\n#define exp hoc_Exp\nextern double hoc_Exp(double);\ +\n#define exp hoc_Exp\ \n#endif\n\ "); if (protect_include_) { @@ -341,7 +336,7 @@ void parout() { /*SUPPRESS 763*/\n\ /*SUPPRESS 765*/\n\ "); - Lappendstr(defs_list, "extern double *getarg();\n"); + Lappendstr(defs_list, "extern double *hoc_getarg(int);\n"); #if VECTORIZE if (vectorize) { Sprintf(buf, "/* Thread safe. No static _p or _ppvar. */\n"); @@ -359,7 +354,6 @@ void parout() { Lappendstr(defs_list, "\n#if MAC\n#if !defined(v)\n#define v _mlhv\n#endif\n#if !defined(h)\n#define h " "_mlhh\n#endif\n#endif\n"); - Lappendstr(defs_list, "\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n"); Lappendstr(defs_list, "static int hoc_nrnpointerindex = "); if (pointercount) { q = nrnpointers->next; @@ -429,11 +423,8 @@ extern Memb_func* memb_func;\n\ "\n" "#define NMODL_TEXT 1\n" "#if NMODL_TEXT\n" - "static const char* nmodl_file_text;\n" - "static const char* nmodl_filename;\n" - "extern void hoc_reg_nmodl_text(int, const char*);\n" - "extern void hoc_reg_nmodl_filename(int, const char*);\n" - "#endif\n\n"); + "static void register_nmodl_text_and_filename(int mechtype);\n" + "#endif\n"); } /**** create special point process functions */ @@ -762,12 +753,12 @@ extern Memb_func* memb_func;\n\ /*declaration of the range variables names to HOC */ Lappendstr( defs_list, - "static void nrn_alloc(Prop*);\nstatic void nrn_init(NrnThread*, _Memb_list*, int);\nstatic void nrn_state(NrnThread*, _Memb_list*, int);\n\ + "static void nrn_alloc(Prop*);\nstatic void nrn_init(NrnThread*, Memb_list*, int);\nstatic void nrn_state(NrnThread*, Memb_list*, int);\n\ "); if (brkpnt_exists) { Lappendstr(defs_list, - "static void nrn_cur(NrnThread*, _Memb_list*, int);\nstatic void " - "nrn_jacob(NrnThread*, _Memb_list*, int);\n"); + "static void nrn_cur(NrnThread*, Memb_list*, int);\nstatic void " + "nrn_jacob(NrnThread*, Memb_list*, int);\n"); } /* count the number of pointers needed */ ppvar_cnt = ioncount + diamdec + pointercount + areadec; @@ -1138,7 +1129,7 @@ extern void hoc_register_tolerance(int, HocStateTolerance*, Symbol***);\n\ extern void _cvode_abstol( Symbol**, double*, int);\n\n\ "); Sprintf(buf, - "void _%s_reg() {\n\ + "extern \"C\" void _%s_reg() {\n\ int _vectorized = %d;\n", modbase, vectorize); @@ -1146,7 +1137,7 @@ extern void _cvode_abstol( Symbol**, double*, int);\n\n\ q = lappendstr(defs_list, ""); Lappendstr(defs_list, "_initlists();\n"); #else - Sprintf(buf, "void _%s_reg() {\n _initlists();\n", modbase); + Sprintf(buf, "extern \"C\" void _%s_reg() {\n _initlists();\n", modbase); Lappendstr(defs_list, buf); #endif @@ -1220,8 +1211,7 @@ extern void _cvode_abstol( Symbol**, double*, int);\n\n\ } if (nmodl_text) { lappendstr(defs_list, - "#if NMODL_TEXT\n hoc_reg_nmodl_text(_mechtype, nmodl_file_text);\n " - "hoc_reg_nmodl_filename(_mechtype, nmodl_filename);\n#endif\n"); + "#if NMODL_TEXT\n register_nmodl_text_and_filename(_mechtype);\n#endif\n"); } sprintf(buf, " hoc_register_prop_size(_mechtype, %d, %d);\n", parraycount, ppvar_cnt); Lappendstr(defs_list, buf); @@ -1447,7 +1437,7 @@ void ldifusreg() { dfdcur = STR(q); ++n; sprintf(buf, - "static void* _difspace%d;\nextern double nrn_nernst_coef();\n\ + "static void* _difspace%d;\nextern double nrn_nernst_coef(int);\n\ static double _difcoef%d(int _i, double* _p, Datum* _ppvar, double* _pdvol, double* _pdfcdc, Datum* _thread, NrnThread* _nt) {\n \ *_pdvol = ", n, @@ -2573,8 +2563,8 @@ static int _ode_count(int _type){ hoc_execerror(\"%s\", \"cannot be used with CV "\n\ static int _ode_count(int);\n\ static void _ode_map(int, double**, double**, double*, Datum*, double*, int);\n\ -static void _ode_spec(NrnThread*, _Memb_list*, int);\n\ -static void _ode_matsol(NrnThread*, _Memb_list*, int);\n\ +static void _ode_spec(NrnThread*, Memb_list*, int);\n\ +static void _ode_matsol(NrnThread*, Memb_list*, int);\n\ "); sprintf(buf, "\n\ @@ -2588,7 +2578,7 @@ static int _ode_count(int _type){ return %d;}\n", cvode_proced_emit(); } else { Lappendstr(procfunc, - "\nstatic void _ode_spec(NrnThread* _nt, _Memb_list* _ml, int _type) {\n"); + "\nstatic void _ode_spec(NrnThread* _nt, Memb_list* _ml, int _type) {\n"); out_nt_ml_frag(procfunc); lst = get_ion_variables(1); if (lst->next->itemtype) @@ -2670,7 +2660,7 @@ static void _ode_synonym(int _cnt, double** _pp, Datum** _ppd) {"); } Lappendstr(procfunc, "}\n"); Lappendstr(procfunc, - "\nstatic void _ode_matsol(NrnThread* _nt, _Memb_list* _ml, int _type) {\n"); + "\nstatic void _ode_matsol(NrnThread* _nt, Memb_list* _ml, int _type) {\n"); out_nt_ml_frag(procfunc); lst = get_ion_variables(1); if (lst->next->itemtype) @@ -2814,9 +2804,8 @@ void net_receive(Item* qarg, Item* qp1, Item* qp2, Item* qstmt, Item* qend) { insertstr(qstmt, " assert(_tsav <= t); _tsav = t;"); } else { insertstr(qstmt, - " if (_tsav > t){ extern char* hoc_object_name(); " - "hoc_execerror(hoc_object_name(_pnt->ob), \":Event arrived out of order. " - "Must call ParallelContext.set_maxstep AFTER assigning minimum " + " if (_tsav > t){ hoc_execerror(hoc_object_name(_pnt->ob), \":Event arrived " + "out of order. Must call ParallelContext.set_maxstep AFTER assigning minimum " "NetCon.delay\");}\n _tsav = t;"); } } diff --git a/src/nmodl/parsact.cpp b/src/nmodl/parsact.cpp index 10ddfa0829..d68340649d 100644 --- a/src/nmodl/parsact.cpp +++ b/src/nmodl/parsact.cpp @@ -1080,7 +1080,8 @@ void vectorize_use_func(Item* qname, Item* qpar1, Item* qexpr, Item* qpar2, int if (blocktype == NETRECEIVE) { Insertstr(qpar1->next, "_tqitem, _args, _pnt,"); } else if (blocktype == INITIAL1) { - Insertstr(qpar1->next, "_tqitem, (double*)0, _ppvar[1]._pvoid,"); + Insertstr(qpar1->next, + "_tqitem, nullptr, static_cast(_ppvar[1]._pvoid),"); } else { diag("net_send allowed only in INITIAL and NET_RECEIVE blocks", (char*) 0); } diff --git a/src/nmodl/simultan.cpp b/src/nmodl/simultan.cpp index ba3625e2c1..37445f33ab 100644 --- a/src/nmodl/simultan.cpp +++ b/src/nmodl/simultan.cpp @@ -11,7 +11,7 @@ int nonlin_common(Item*, int); void solv_nonlin(Item* qsol, Symbol* fun, Symbol* method, int numeqn, int listnum) { Sprintf(buf, - "%s(%d,_slist%d, _p, %s, _dlist%d);\n", + "%s(%d,_slist%d, _p, %s_wrapper_returning_int, _dlist%d);\n", method->name, numeqn, listnum, @@ -59,7 +59,11 @@ void massagenonlin(Item* q1, Item* q2, Item* q3, Item* q4, int sensused) { Symbol* nonfun; /* all this junk is still in the intoken list */ - Sprintf(buf, "static void %s();\n", SYM(q2)->name); + Sprintf(buf, + "static void %s();\nstatic int %s_wrapper_returning_int() { %s(); return 42; }", + SYM(q2)->name, + SYM(q2)->name, + SYM(q2)->name); Linsertstr(procfunc, buf); replacstr(q1, "\nstatic void"); Insertstr(q3, "()\n"); @@ -195,8 +199,8 @@ Item* mixed_eqns(Item* q2, Item* q3, Item* q4) /* name, '{', '}' */ numlist); qret = insertstr(q3, buf); Sprintf(buf, - "error = nrn_newton_thread(_newtonspace%d, %d,_slist%d, _p, %s, _dlist%d, _ppvar, " - "_thread, _nt);\n", + "error = nrn_newton_thread(static_cast(_newtonspace%d), %d,_slist%d, _p, " + "%s, _dlist%d, _ppvar, _thread, _nt);\n", numlist - 1, counts, numlist, diff --git a/src/nrncvode/cvodeobj.cpp b/src/nrncvode/cvodeobj.cpp index 4865d39b89..86a86264b9 100644 --- a/src/nrncvode/cvodeobj.cpp +++ b/src/nrncvode/cvodeobj.cpp @@ -4,7 +4,6 @@ #include "nrnmpi.h" -extern "C" void cvode_fadvance(); void cvode_finitialize(); extern void (*nrn_multisplit_setup_)(); @@ -70,7 +69,6 @@ extern "C" Point_process* ob2pntproc(Object*); extern void (*nrnthread_v_transfer_)(NrnThread*); extern void (*nrnmpi_v_transfer_)(); -extern int cvode_active_; extern NetCvode* net_cvode_instance; extern short* nrn_is_artificial_; extern "C" int structure_change_cnt; diff --git a/src/nrncvode/cvodestb.cpp b/src/nrncvode/cvodestb.cpp index c1f730a01f..9b35961f04 100644 --- a/src/nrncvode/cvodestb.cpp +++ b/src/nrncvode/cvodestb.cpp @@ -3,6 +3,7 @@ #include #include "classreg.h" +#include "nrncvode.h" #include "nrnoc2iv.h" #include "datapath.h" #if USECVODE @@ -12,7 +13,6 @@ class Cvode; #endif -extern "C" void cvode_fadvance(double); void cvode_finitialize(double t0); void nrncvode_set_t(double); extern "C" bool at_time(NrnThread*, double); @@ -21,7 +21,6 @@ extern double dt, t; #define nt_t nrn_threads->_t #define nt_dt nrn_threads->_dt extern "C" void nrn_random_play(); -extern int cvode_active_; extern int nrn_use_daspk_; NetCvode* net_cvode_instance; @@ -98,7 +97,7 @@ void nrn_solver_prepare() { extern "C" int v_structure_change; -extern "C" void cvode_fadvance(double tstop) { // tstop = -1 means single step +void cvode_fadvance(double tstop) { // tstop = -1 means single step #if USECVODE int err; extern int tree_changed; diff --git a/src/nrncvode/hocevent.cpp b/src/nrncvode/hocevent.cpp index ca7064a511..76ab444c5e 100644 --- a/src/nrncvode/hocevent.cpp +++ b/src/nrncvode/hocevent.cpp @@ -4,8 +4,6 @@ #include #include -extern int cvode_active_; - declarePool(HocEventPool, HocEvent) implementPool(HocEventPool, HocEvent) HocEventPool* HocEvent::hepool_; diff --git a/src/nrncvode/netcvode.cpp b/src/nrncvode/netcvode.cpp index ef70a2d038..694ed4f550 100644 --- a/src/nrncvode/netcvode.cpp +++ b/src/nrncvode/netcvode.cpp @@ -37,8 +37,10 @@ #include "netcon.h" #include "netcvode.h" #include "nrncore_write/utils/nrncore_utils.h" +#include "nrniv_mf.h" #include "nrnste.h" #include "profile.h" +#include "treeset.h" #include "utils/profile/profiler_interface.h" #include #include @@ -70,7 +72,6 @@ extern int tree_changed, nrn_matrix_cnt_; extern int diam_changed; extern int nrn_errno_check(int); extern void nrn_ba(NrnThread*, int); -extern int cvode_active_; extern NetCvode* net_cvode_instance; extern cTemplate** nrn_pnt_template_; extern double t, dt; @@ -86,9 +87,7 @@ extern ReceiveFunc* pnt_receive_init; extern short* pnt_receive_size; extern short* nrn_is_artificial_; // should be bool but not using that type in c extern short* nrn_artcell_qindex_; -extern "C" void net_send(void**, double*, Point_process*, double, double); extern "C" void net_move(void**, Point_process*, double); -extern "C" void artcell_net_send(void**, double*, Point_process*, double, double); extern "C" void artcell_net_move(void**, Point_process*, double); int nrn_use_selfqueue_; void nrn_pending_selfqueue(double tt, NrnThread*); @@ -117,7 +116,6 @@ extern hoc_Item* net_cvode_instance_psl(); extern PlayRecList* net_cvode_instance_prl(); extern void nrn_update_ps2nt(); extern void nrn_use_busywait(int); -extern "C" double* nrn_recalc_ptr(double*); void* nrn_interthread_enqueue(NrnThread*); extern void (*nrnthread_v_transfer_)(NrnThread*); Object* (*nrnpy_seg_from_sec_x)(Section*, double); @@ -148,7 +146,6 @@ extern int nrn_fornetcon_cnt_; extern int* nrn_fornetcon_index_; extern int* nrn_fornetcon_type_; void _nrn_free_fornetcon(void**); -// int _nrn_netcon_args(void*, double***); // for use in mod files double nrn_netcon_get_delay(NetCon* nc) { @@ -161,7 +158,7 @@ int nrn_netcon_weight(NetCon* nc, double** pw) { *pw = nc->weight_; return nc->cnt_; } -extern "C" double nrn_event_queue_stats(double* stats) { +double nrn_event_queue_stats(double* stats) { #if COLLECT_TQueue_STATISTICS net_cvode_instance_event_queue(nrn_threads)->spike_stat(stats); return (stats[0] - stats[2]); @@ -2408,7 +2405,7 @@ void NetCvode::remove_event(TQItem* q, int tid) { // for threads, revised net_send to use absolute time (in the // mod file we add the thread time when we call it). -extern "C" void net_send(void** v, double* weight, Point_process* pnt, double td, double flag) { +void nrn_net_send(void** v, double* weight, Point_process* pnt, double td, double flag) { STATISTICS(SelfEvent::selfevent_send_); NrnThread* nt = PP2NT(pnt); NetCvodeThreadData& p = net_cvode_instance->p[nt->id]; @@ -2443,11 +2440,7 @@ extern "C" void net_send(void** v, double* weight, Point_process* pnt, double td // printf("net_send %g %s %g %p\n", td, hoc_object_name(pnt->ob), flag, *v); } -extern "C" void artcell_net_send(void** v, - double* weight, - Point_process* pnt, - double td, - double flag) { +void artcell_net_send(void** v, double* weight, Point_process* pnt, double td, double flag) { if (nrn_use_selfqueue_ && flag == 1.0) { STATISTICS(SelfEvent::selfevent_send_); NrnThread* nt = PP2NT(pnt); @@ -2482,6 +2475,15 @@ extern "C" void artcell_net_send(void** v, } } +// Deprecated overloads for backwards compatibility +void artcell_net_send(void** v, double* weight, void* pnt, double td, double flag) { + artcell_net_send(v, weight, static_cast(pnt), td, flag); +} + +void nrn_net_send(void** v, double* weight, void* pnt, double td, double flag) { + nrn_net_send(v, weight, static_cast(pnt), td, flag); +} + extern "C" void net_event(Point_process* pnt, double time) { STATISTICS(net_event_cnt_); PreSyn* ps = (PreSyn*) pnt->presyn_; @@ -4233,7 +4235,7 @@ void NetCvode::fornetcon_prepare() { delete[] t2i; } -extern "C" int _nrn_netcon_args(void* v, double*** argslist) { +int _nrn_netcon_args(void* v, double*** argslist) { ForNetConsInfo* fnc = (ForNetConsInfo*) v; assert(fnc); *argslist = fnc->argslist; diff --git a/src/nrniv/CMakeLists.txt b/src/nrniv/CMakeLists.txt index 6acd9ba2e0..d18d75acfe 100644 --- a/src/nrniv/CMakeLists.txt +++ b/src/nrniv/CMakeLists.txt @@ -98,15 +98,15 @@ endif() # Translate all MOD files to C and mark them generated # ============================================================================= foreach(modfile ${NRN_MODFILE_BASE_NAMES}) - nocmodl_mod_to_c(${modfile}) + nocmodl_mod_to_cpp(${modfile}) set_property( - SOURCE ${modfile}.c + SOURCE ${modfile}.cpp APPEND PROPERTY COMPILE_OPTIONS ${NRN_EXTRA_MECH_CXX_FLAGS}) - list(APPEND NRN_MODFILE_C ${modfile}.c) + list(APPEND NRN_MODFILE_CPP ${modfile}.cpp) endforeach() -set_source_files_properties(${NRN_MODFILE_C} PROPERTIES GENERATED TRUE) +set_source_files_properties(${NRN_MODFILE_CPP} PROPERTIES GENERATED TRUE) # ============================================================================= # Bison parser for HOC interpreter @@ -137,7 +137,7 @@ set(NRN_NRNIV_LIB_SRC_FILES ${NRN_NRNOC_SRC_FILES} ${NRN_OC_SRC_FILES} ${NRN_MESCH_SRC_FILES} - ${NRN_MODFILE_C} + ${NRN_MODFILE_CPP} ${NRN_NRNGNU_SRC_FILES} ${NRN_SCOPMATH_SRC_FILES} ${NRN_SPARSE_SRC_FILES} diff --git a/src/nrniv/bbsavestate.cpp b/src/nrniv/bbsavestate.cpp index 913b953e4a..8d75a37928 100644 --- a/src/nrniv/bbsavestate.cpp +++ b/src/nrniv/bbsavestate.cpp @@ -170,6 +170,7 @@ callback to bbss_early when needed. #include "bbsavestate.h" #include "classreg.h" #include "ndatclas.h" +#include "nrncvode.h" #include "nrnoc2iv.h" #include "ocfile.h" #include @@ -214,16 +215,11 @@ extern double t; typedef void (*PFIO)(int, Object*); extern void nrn_gidout_iter(PFIO); extern short* nrn_is_artificial_; -extern "C" { -extern void net_send(void**, double*, Point_process*, double, double); -extern void nrn_fake_fire(int gid, double firetime, int fake_out); -} // extern "C" extern Object* nrn_gid2obj(int gid); extern PreSyn* nrn_gid2presyn(int gid); extern int nrn_gid_exists(int gid); #if NRNMPI -extern void nrn_spike_exchange(NrnThread*); extern void nrnmpi_barrier(); extern void nrnmpi_int_alltoallv(int*, int*, int*, int*, int*, int*); extern void nrnmpi_dbl_alltoallv(double*, int*, int*, double*, int*, int*); @@ -232,7 +228,6 @@ extern void nrnmpi_int_allgather(int* s, int* r, int n); extern void nrnmpi_int_allgatherv(int* s, int* r, int* n, int* dspl); extern void nrnmpi_dbl_allgatherv(double* s, double* r, int* n, int* dspl); #else -static void nrn_spike_exchange(NrnThread*) {} static void nrnmpi_barrier() {} static void nrnmpi_int_alltoallv(int* s, int* scnt, int* sdispl, int* r, int* rcnt, int* rdispl) { for (int i = 0; i < scnt[0]; ++i) { @@ -297,68 +292,6 @@ static TQItemList* tq_removal_list; static void bbss_queuecheck(); #endif -// API -// see save_test_bin and restore_test_bin for an example of -// the use of this following interface. Note in particular the -// use in restore_test_bin of a prior clear_event_queue() in order -// to allow bbss_buffer_counts to pass an assert during the restore -// process. - -extern "C" void* bbss_buffer_counts(int* len, int** gids, int** sizes, int* global_size); -// First call to return the information needed to make the other -// calls. Returns a pointer used by the other methods. -// Caller is reponsible for freeing (using free() and not delete []) -// the returned gids and sizes arrays -// when finished. The sizes array and global_size are needed for the -// caller to construct proper buffer sizes to pass to -// bbss_save_global and bbss_save for filling in. The size of these -// arrays is returned in *len. -// They are not needed for restoring -// (since the caller is passing already filled in buffers that are read -// by bbss_restore_global and bbss_restore -// The gids returned are base gids. It is the callers responsibility -// to somehow concatenate buffers with the same gid (from different hosts) -// either after save or before restore and preserve the piece count -// of the number of concatenated buffers for each base gid. -// Global_size will only be non_zero for host 0. - -extern "C" void bbss_save_global(void* bbss, char* buffer, int sz); -// call only on host 0 with a buffer of size equal to the -// global_size returned from the bbss_buffer_counts call on host 0 -// sz is the size of the buffer (for error checking only, buffer+sz is -// out of bounds) - -extern "C" void bbss_restore_global(void* bbss, char* buffer, int sz); -// call on all hosts with the buffer contents returned from the call -// to bbss_save_global -// This must be called prior to any calls to bbss_restore -// sz is the size of the buffer (error checking only) -// This also does some other important restore initializations. - -extern "C" void bbss_save(void* bbss, int gid, char* buffer, int sz); -// Call this for each item of the gids from bbss_buffer_counts along with -// a buffer of size from the corresponding sizes array. The buffer will -// be filled in with savestate information. The gid may be the same on -// different hosts, in which case it is the callers responsibility to -// concatentate buffers at some point to allow calling of bbss_restore -// sz is the size of the buffer (error checking only) - -extern "C" void bbss_restore(void* bbss, int gid, int npiece, char* buffer, int sz); -// Call this for each item of the gids from bbss_buffer_counts, the -// number of buffers that were concatenated for the gid, and the -// concatenated buffer (the concatenated buffer does NOT contain npiece -// as the first value in the char* buffer pointer) -// sz is the size of the buffer (error checking only) - -extern "C" void bbss_save_done(void* bbss); -// At the end of the save process, call this to cleanup. -// when this call returns, bbss will be invalid. - -extern "C" void bbss_restore_done(void* bbss); -// At the end of the restore process, call this to do -// some extra setting up and cleanup. -// when this call returns, bbss will be invalid. - // 0 no debug, 1 print to stdout, 2 read/write to IO file #define DEBUG 0 static int debug = DEBUG; @@ -787,7 +720,7 @@ static int ignored(Prop* p) { return 0; } -extern "C" void* bbss_buffer_counts(int* len, int** gids, int** sizes, int* global_size) { +void* bbss_buffer_counts(int* len, int** gids, int** sizes, int* global_size) { usebin_ = 1; BBSaveState* ss = new BBSaveState(); *global_size = 0; @@ -800,15 +733,15 @@ extern "C" void* bbss_buffer_counts(int* len, int** gids, int** sizes, int* glob *len = ss->counts(gids, sizes); return ss; } -extern "C" void bbss_save_global(void* bbss, char* buffer, - int sz) { // call only on host 0 +void bbss_save_global(void* bbss, char* buffer, + int sz) { // call only on host 0 usebin_ = 1; BBSS_IO* io = new BBSS_BufferOut(buffer, sz); io->d(1, nrn_threads->_t); delete io; } -extern "C" void bbss_restore_global(void* bbss, char* buffer, - int sz) { // call on all hosts +void bbss_restore_global(void* bbss, char* buffer, + int sz) { // call on all hosts usebin_ = 1; BBSS_IO* io = new BBSS_BufferIn(buffer, sz); io->d(1, nrn_threads->_t); @@ -816,7 +749,7 @@ extern "C" void bbss_restore_global(void* bbss, char* buffer, delete io; bbss_restore_begin(); } -extern "C" void bbss_save(void* bbss, int gid, char* buffer, int sz) { +void bbss_save(void* bbss, int gid, char* buffer, int sz) { usebin_ = 1; BBSaveState* ss = (BBSaveState*) bbss; BBSS_IO* io = new BBSS_BufferOut(buffer, sz); @@ -824,7 +757,7 @@ extern "C" void bbss_save(void* bbss, int gid, char* buffer, int sz) { ss->gidobj(gid); delete io; } -extern "C" void bbss_restore(void* bbss, int gid, int ngroup, char* buffer, int sz) { +void bbss_restore(void* bbss, int gid, int ngroup, char* buffer, int sz) { usebin_ = 1; BBSaveState* ss = (BBSaveState*) bbss; BBSS_IO* io = new BBSS_BufferIn(buffer, sz); @@ -835,7 +768,7 @@ extern "C" void bbss_restore(void* bbss, int gid, int ngroup, char* buffer, int } delete io; } -extern "C" void bbss_save_done(void* bbss) { +void bbss_save_done(void* bbss) { BBSaveState* ss = (BBSaveState*) bbss; delete ss; } @@ -873,7 +806,7 @@ static void bbss_remove_delivered() { delete tq_removal_list; } -extern "C" void bbss_restore_done(void* bbss) { +void bbss_restore_done(void* bbss) { if (bbss) { BBSaveState* ss = (BBSaveState*) bbss; delete ss; diff --git a/src/nrniv/bbsavestate.h b/src/nrniv/bbsavestate.h index ca14e62093..ad16ead53e 100644 --- a/src/nrniv/bbsavestate.h +++ b/src/nrniv/bbsavestate.h @@ -56,5 +56,65 @@ class BBSaveState { void del_pp2de(); }; +/** BBSaveState API + * See save_test_bin and restore_test_bin for an example of the use of this + * following interface. Note in particular the use in restore_test_bin of a + * prior clear_event_queue() in order to allow bbss_buffer_counts to pass an + * assert during the restore process. + */ + +/** First call to return the information needed to make the other calls. Returns + * a pointer used by the other methods. Caller is reponsible for freeing (using + * free() and not delete []) the returned gids and sizes arrays when finished. + * The sizes array and global_size are needed for the caller to construct + * proper buffer sizes to pass to bbss_save_global and bbss_save for filling + * in. The size of these arrays is returned in *len. They are not needed for + * restoring (since the caller is passing already filled in buffers that are + * read by bbss_restore_global and bbss_restore. The gids returned are base + * gids. It is the callers responsibility to somehow concatenate buffers with + * the same gid (from different hosts) either after save or before restore and + * preserve the piece count of the number of concatenated buffers for each base + * gid. Global_size will only be non_zero for host 0. + */ +void* bbss_buffer_counts(int* len, int** gids, int** sizes, int* global_size); + +/** Call only on host 0 with a buffer of size equal to the global_size returned + * from the bbss_buffer_counts call on host 0 sz is the size of the buffer + * (for error checking only, buffer+sz is out of bounds) + */ +void bbss_save_global(void* bbss, char* buffer, int sz); + +/** Call on all hosts with the buffer contents returned from the call to + * bbss_save_global. This must be called prior to any calls to bbss_restore sz + * is the size of the buffer (error checking only). This also does some other + * important restore initializations. + */ +void bbss_restore_global(void* bbss, char* buffer, int sz); + +/** Call this for each item of the gids from bbss_buffer_counts along with a + * buffer of size from the corresponding sizes array. The buffer will be filled + * in with savestate information. The gid may be the same on different hosts, + * in which case it is the callers responsibility to concatentate buffers at + * some point to allow calling of bbss_restore. sz is the size of the buffer + * (error checking only). + */ +void bbss_save(void* bbss, int gid, char* buffer, int sz); + +/** Call this for each item of the gids from bbss_buffer_counts, the number of + * buffers that were concatenated for the gid, and the concatenated buffer (the + * concatenated buffer does NOT contain npiece as the first value in the char* + * buffer pointer). sz is the size of the buffer (error checking only). + */ +void bbss_restore(void* bbss, int gid, int npiece, char* buffer, int sz); + +/** At the end of the save process, call this to cleanup. When this call + * returns, bbss will be invalid. + */ +void bbss_save_done(void* bbss); + +/** At the end of the restore process, call this to do some extra setting up and + * cleanup. When this call returns, bbss will be invalid. + */ +void bbss_restore_done(void* bbss); #endif diff --git a/src/nrniv/bgpdma.cpp b/src/nrniv/bgpdma.cpp index 5581e2048c..2dd725111f 100644 --- a/src/nrniv/bgpdma.cpp +++ b/src/nrniv/bgpdma.cpp @@ -26,16 +26,7 @@ At the end of a computation subinterval the even or odd buffer spikes are enqueued in the priority queue after checking that the number of spikes sent is equal to the number of spikes sent. */ - -extern "C" { - -extern IvocVect* vector_arg(int); -extern void vector_resize(IvocVect*, int); - -} // extern "C" extern void (*nrntimeout_call)(); - - // The initial idea behind use_phase2_ is to avoid the large overhead of // initiating a send of the up to 10k list of target hosts when a cell fires. // I.e. when there are a small number of cells on a processor, this causes diff --git a/src/nrniv/bgpdmasetup.cpp b/src/nrniv/bgpdmasetup.cpp index 58682f8bb4..524eae27b6 100644 --- a/src/nrniv/bgpdmasetup.cpp +++ b/src/nrniv/bgpdmasetup.cpp @@ -7,6 +7,7 @@ To reduce this setup time we experiment with a very different algorithm in which we construct a gid target host list on host gid%nhost and copy that list to the source host owning the gid. */ +#include "oc_ansi.h" #include "oc_ansi.h" diff --git a/src/nrniv/cachevec.cpp b/src/nrniv/cachevec.cpp index e02cc1e30e..ca512482a1 100644 --- a/src/nrniv/cachevec.cpp +++ b/src/nrniv/cachevec.cpp @@ -19,9 +19,9 @@ #include #include #include +#include "treeset.h" void nrniv_recalc_ptrs(); -extern "C" double* nrn_recalc_ptr(double*); extern NetCvode* net_cvode_instance; extern void nrn_linmod_update_ptrs(void*); diff --git a/src/nrniv/kssingle.cpp b/src/nrniv/kssingle.cpp index ab6e3489d5..797586ceb9 100644 --- a/src/nrniv/kssingle.cpp +++ b/src/nrniv/kssingle.cpp @@ -128,7 +128,6 @@ // double* KSSingleNodeData.statepop_ which points into the prop->param. //---------------- -extern int cvode_active_; extern NetCvode* net_cvode_instance; double KSSingle::vres_; diff --git a/src/nrniv/linmod1.cpp b/src/nrniv/linmod1.cpp index bb88796015..ea7664e56e 100644 --- a/src/nrniv/linmod1.cpp +++ b/src/nrniv/linmod1.cpp @@ -8,8 +8,8 @@ #include "classreg.h" #include "linmod.h" #include "nrnoc2iv.h" +#include "treeset.h" -extern "C" double* nrn_recalc_ptr(double*); // hoc interface to a LinearModelAddition // remember that the policy for equation additions to the tree matrix is // cmat*y' + gmat*y = b and where the first nnode rows specify diff --git a/src/nrniv/netpar.cpp b/src/nrniv/netpar.cpp index 5bf76b3cb7..136c758cac 100644 --- a/src/nrniv/netpar.cpp +++ b/src/nrniv/netpar.cpp @@ -2,6 +2,7 @@ #include <../../nrnconf.h> #include #include +#include "nrncvode.h" #include #include #include @@ -40,17 +41,11 @@ static void alloc_space(); extern NetCvode* net_cvode_instance; extern double t, dt; -extern int cvode_active_; extern "C" Point_process* ob2pntproc(Object*); extern int nrn_use_selfqueue_; extern void nrn_pending_selfqueue(double, NrnThread*); -extern int vector_capacity(IvocVect*); // ivocvect.h conflicts with STL -extern double* vector_vec(IvocVect*); extern Object* nrn_sec2cell(Section*); extern void ncs2nrn_integrate(double tstop); -extern "C" { -extern void nrn_fake_fire(int gid, double firetime, int fake_out); -} // extern "C" int nrnmpi_spike_compress(int nspike, bool gid_compress, int xchng_meth); void nrn_cleanup_presyn(PreSyn*); int nrn_set_timeout(int); @@ -99,7 +94,6 @@ static double set_mindelay(double maxdelay); #include "../nrnmpi/mpispike.h" void nrn_timeout(int); -void nrn_spike_exchange(NrnThread*); extern int nrnmpi_int_allmax(int); extern void nrnmpi_int_allgather(int*, int*, int); void nrn2ncs_outputevent(int netcon_output_index, double firetime); @@ -543,7 +537,9 @@ void nrn_spike_exchange_init() { // if (nrnmpi_myid == 0){printf("usable_mindelay_ = %g\n", usable_mindelay_);} } -#if NRNMPI +#if !NRNMPI +void nrn_spike_exchange(NrnThread*) {} +#else void nrn_spike_exchange(NrnThread* nt) { nrn::Instrumentor::phase p_spike_exchange("spike-exchange"); if (!active_) { @@ -902,7 +898,7 @@ static void mk_localgid_rep() { // ensures that all the target cells, regardless of what rank they are on // will get the spike delivered and nobody gets it twice. -extern "C" void nrn_fake_fire(int gid, double spiketime, int fake_out) { +void nrn_fake_fire(int gid, double spiketime, int fake_out) { PreSyn* ps{nullptr}; if (fake_out < 2) { auto iter = gid2in_.find(gid); diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp index 53c15a7a65..df20883498 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp @@ -1200,9 +1200,7 @@ void core2nrn_watch_activate(int tid, int type, int watch_begin, Core2NrnWatchIn // nrn<->corenrn PatternStim -extern "C" { void* nrn_patternstim_info_ref(Datum*); -} static int patternstim_type; // Info from NEURON PatternStim at beginning of psolve. diff --git a/src/nrniv/nrndae.cpp b/src/nrniv/nrndae.cpp index 17cda4c195..45fc467a61 100644 --- a/src/nrniv/nrndae.cpp +++ b/src/nrniv/nrndae.cpp @@ -13,7 +13,6 @@ extern void nrndae_dkres(double*, double*, double*); extern void nrndae_dkpsol(double); extern void nrndae_update(); extern void nrn_matrix_node_free(); -extern int cvode_active_; extern int nrn_use_daspk_; extern int secondorder; extern int nrndae_list_is_empty(); diff --git a/src/nrniv/partrans.cpp b/src/nrniv/partrans.cpp index ff5577920e..d2bdc59c5e 100644 --- a/src/nrniv/partrans.cpp +++ b/src/nrniv/partrans.cpp @@ -1,5 +1,7 @@ #include <../../nrnconf.h> +#include "treeset.h" + #include #include #include @@ -52,7 +54,6 @@ extern double t; extern "C" int v_structure_change; extern "C" int structure_change_cnt; extern int nrn_node_ptr_change_cnt_; -extern "C" double* nrn_recalc_ptr(double*); extern const char* bbcore_write_version; // see lengthy comment in ../nrnoc/fadvance.cpp // nrnmpi_v_transfer requires existence of nrnthread_v_transfer even if there diff --git a/src/nrniv/shape.cpp b/src/nrniv/shape.cpp index 1d4060b497..20f6dbb5e3 100644 --- a/src/nrniv/shape.cpp +++ b/src/nrniv/shape.cpp @@ -38,6 +38,7 @@ #include "ocobserv.h" #include "parse.hpp" #include "ivoc.h" +#include "treeset.h" #define Shape_Section_ "Section PlotShape" #define Shape_Rotate_ "Rotate3D PlotShape" @@ -50,7 +51,6 @@ extern int section_count; extern Section** secorder; extern "C" Point_process* ob2pntproc(Object*); extern "C" Point_process* ob2pntproc_0(Object*); -extern "C" double* nrn_recalc_ptr(double*); extern Object* (*nrnpy_seg_from_sec_x)(Section*, double); #if BEVELJOIN diff --git a/src/nrnjava/nrnjni.cpp b/src/nrnjava/nrnjni.cpp index 22f5ab8eb2..9574320891 100644 --- a/src/nrnjava/nrnjni.cpp +++ b/src/nrnjava/nrnjni.cpp @@ -250,7 +250,7 @@ JNIEXPORT jstring JNICALL Java_neuron_Neuron_getHocArgSig(JNIEnv* env, jclass) { } JNIEXPORT jlong JNICALL Java_neuron_Neuron_vectorNew(JNIEnv* env, jclass, jint size) { - jnisave Vect* v = vector_new1(size); + jnisave Vect* v = vector_new(size); Object* ho = hoc_new_object(nrn_vec_sym, v); hoc_obj_ref(ho); jlong jc = (jlong) ho; diff --git a/src/nrnoc/apcount.mod b/src/nrnoc/apcount.mod index e723d82c25..0464b17c08 100755 --- a/src/nrnoc/apcount.mod +++ b/src/nrnoc/apcount.mod @@ -19,21 +19,12 @@ ASSIGNED { space } -VERBATIM -extern void vector_resize(); -extern double* vector_vec(); -extern void* vector_arg(); -ENDVERBATIM - INITIAL { n = 0 firing = 0 VERBATIM - { void* vv; - vv = *((void**)(&space)); - if (vv) { - vector_resize(vv, 0); - } + if (auto* vv = *reinterpret_cast(&space)) { + vector_resize(vv, 0); } ENDVERBATIM check() @@ -46,12 +37,11 @@ BREAKPOINT { PROCEDURE check() { VERBATIM if (v >= thresh && !firing) { - int size; double* px; void* vv; + int size; double* px; firing = 1; time = t; n += 1.; - vv = *((void**)(&space)); - if (vv) { + if (auto* vv = *reinterpret_cast(&space)) { size = (int)n; vector_resize(vv, size); px = vector_vec(vv); @@ -66,10 +56,8 @@ ENDVERBATIM PROCEDURE record() { VERBATIM - extern void* vector_arg(); - void** vv; - vv = (void**)(&space); - *vv = (void*)0; + auto* vv = reinterpret_cast(&space); + *vv = nullptr; if (ifarg(1)) { *vv = vector_arg(1); } diff --git a/src/nrnoc/cabcode.cpp b/src/nrnoc/cabcode.cpp index 9454389d67..254276c5b4 100644 --- a/src/nrnoc/cabcode.cpp +++ b/src/nrnoc/cabcode.cpp @@ -1097,7 +1097,7 @@ Prop* nrn_mechanism_check(int type, Section* sec, int inode) { return m; } -extern "C" Prop* hoc_getdata_range(int type) { +Prop* hoc_getdata_range(int type) { int inode; Section* sec; double x; diff --git a/src/nrnoc/eion.cpp b/src/nrnoc/eion.cpp index 0787c3ce2b..973518d842 100644 --- a/src/nrnoc/eion.cpp +++ b/src/nrnoc/eion.cpp @@ -394,7 +394,7 @@ ion_style("name_ion", [c_style, e_style, einit, eadvance, cinit]) #define conci0 global_conci(type) #define conco0 global_conco(type) -extern "C" double nrn_nernst_coef(int type) { +double nrn_nernst_coef(int type) { /* for computing jacobian element dconc'/dconc */ return ktf / charge; } diff --git a/src/nrnoc/extcelln.cpp b/src/nrnoc/extcelln.cpp index a2cb7930ae..f708ce2f3a 100644 --- a/src/nrnoc/extcelln.cpp +++ b/src/nrnoc/extcelln.cpp @@ -9,7 +9,6 @@ #include "parse.hpp" -extern int cvode_active_; extern int nrn_use_daspk_; extern void nrn_delete_prop_pool(int type); diff --git a/src/nrnoc/hocprax.cpp b/src/nrnoc/hocprax.cpp index 7df94847cb..d47a86f22d 100644 --- a/src/nrnoc/hocprax.cpp +++ b/src/nrnoc/hocprax.cpp @@ -60,16 +60,9 @@ extern int praxis_stop(int); } #endif -extern int stoprun; extern double chkarg(int, double, double); - -extern void vector_resize(IvocVect*, int); -extern double* vector_vec(IvocVect*); -extern IvocVect* vector_arg(int); // TODO: IvocVect? extern IvocVect* vector_new2(IvocVect* vec); extern void vector_delete(IvocVect* vec); -extern int vector_capacity(IvocVect*); -extern Object** vector_pobj(IvocVect* v); extern int nrn_praxis_ran_index; extern Object** hoc_objgetarg(int); diff --git a/src/nrnoc/init.cpp b/src/nrnoc/init.cpp index 6150960a66..0b0e929c62 100644 --- a/src/nrnoc/init.cpp +++ b/src/nrnoc/init.cpp @@ -1,6 +1,6 @@ #include <../../nrnconf.h> #include - +#include "oc_ansi.h" #include #include #include @@ -143,7 +143,7 @@ int* nrn_dparam_ptr_start_; int* nrn_dparam_ptr_end_; NrnWatchAllocateFunc_t* nrn_watch_allocate_; -extern "C" void hoc_reg_watch_allocate(int type, NrnWatchAllocateFunc_t waf) { +void hoc_reg_watch_allocate(int type, NrnWatchAllocateFunc_t waf) { nrn_watch_allocate_[type] = waf; } @@ -152,21 +152,21 @@ using bbcore_write_t = void (*)(double*, int*, int*, int*, double*, Datum*, Datu bbcore_write_t* nrn_bbcore_write_; bbcore_write_t* nrn_bbcore_read_; -extern "C" void hoc_reg_bbcore_write(int type, bbcore_write_t f) { +void hoc_reg_bbcore_write(int type, bbcore_write_t f) { nrn_bbcore_write_[type] = f; } -extern "C" void hoc_reg_bbcore_read(int type, bbcore_write_t f) { +void hoc_reg_bbcore_read(int type, bbcore_write_t f) { nrn_bbcore_read_[type] = f; } const char** nrn_nmodl_text_; -extern "C" void hoc_reg_nmodl_text(int type, const char* txt) { +void hoc_reg_nmodl_text(int type, const char* txt) { nrn_nmodl_text_[type] = txt; } const char** nrn_nmodl_filename_; -extern "C" void hoc_reg_nmodl_filename(int type, const char* filename) { +void hoc_reg_nmodl_filename(int type, const char* filename) { nrn_nmodl_filename_[type] = filename; } @@ -262,7 +262,7 @@ int mswin_load_dll(const char* cp1) { if (mreg) { (*mreg)(); } else { - fprintf(stderr, "dlsym _modl_reg failed\n%s\n", dlerror()); + fprintf(stderr, "dlsym modl_reg failed\n%s\n", dlerror()); dlclose(handle); return 0; } @@ -864,7 +864,7 @@ extern "C" int nrn_pointing(double* pd) { } int state_discon_flag_ = 0; -extern "C" void state_discontinuity(int i, double* pd, double d) { +void state_discontinuity(int i, double* pd, double d) { if (state_discon_allowed_ && state_discon_flag_ == 0) { *pd = d; /*printf("state_discontinuity t=%g pd=%lx d=%g\n", t, (long)pd, d);*/ @@ -944,7 +944,7 @@ void hoc_reg_ba(int mt, nrn_bamech_t f, int type) { } } -extern "C" void _cvode_abstol(Symbol** s, double* tol, int i) { +void _cvode_abstol(Symbol** s, double* tol, int i) { #if CVODE if (s && s[i]->extra) { double x; @@ -1028,7 +1028,7 @@ extern "C" void hoc_register_tolerance(int type, HocStateTolerance* tol, Symbol* #endif // CVODE } -extern "C" void _nrn_thread_reg(int i, int cons, void (*f)(Datum*)) { +void _nrn_thread_reg(int i, int cons, void (*f)(Datum*)) { if (cons == 1) { memb_func[i].thread_mem_init_ = f; } else if (cons == 0) { @@ -1038,11 +1038,11 @@ extern "C" void _nrn_thread_reg(int i, int cons, void (*f)(Datum*)) { } } -extern "C" void _nrn_thread_table_reg(int i, void (*f)(double*, Datum*, Datum*, NrnThread*, int)) { +void _nrn_thread_table_reg(int i, void (*f)(double*, Datum*, Datum*, NrnThread*, int)) { memb_func[i].thread_table_check_ = f; } -extern "C" void _nrn_setdata_reg(int i, void (*call)(Prop*)) { +void _nrn_setdata_reg(int i, void (*call)(Prop*)) { memb_func[i].setdata_ = call; } /* there is some question about the _extcall_thread variables, if any. */ diff --git a/src/nrnoc/md1redef.h b/src/nrnoc/md1redef.h index e440db3dd4..f4e5a82019 100644 --- a/src/nrnoc/md1redef.h +++ b/src/nrnoc/md1redef.h @@ -12,7 +12,6 @@ #define i _i #define sec _sec -#undef Memb_list #undef nodelist #undef nodeindices #undef data @@ -21,7 +20,6 @@ #undef nodecount #undef type -#define Memb_list _Memb_list #define nodelist _nodelist #define nodeindices _nodeindices #define data _data diff --git a/src/nrnoc/md2redef.h b/src/nrnoc/md2redef.h index 57eed2a0c8..2f63bcf0ae 100755 --- a/src/nrnoc/md2redef.h +++ b/src/nrnoc/md2redef.h @@ -12,7 +12,6 @@ #undef i #undef sec -#undef Memb_list #undef nodelist #undef nodeindices #undef data diff --git a/src/nrnoc/netstim.mod b/src/nrnoc/netstim.mod index 44d7063b04..5db68ca1f1 100755 --- a/src/nrnoc/netstim.mod +++ b/src/nrnoc/netstim.mod @@ -16,42 +16,35 @@ : and vice versa. NEURON { - ARTIFICIAL_CELL NetStim - RANGE interval, number, start - RANGE noise - THREADSAFE : only true if every instance has its own distinct Random - BBCOREPOINTER donotuse + ARTIFICIAL_CELL NetStim + RANGE interval, number, start + RANGE noise + THREADSAFE : only true if every instance has its own distinct Random + BBCOREPOINTER donotuse } PARAMETER { - interval = 10 (ms) <1e-9,1e9>: time between spikes (msec) - number = 10 <0,1e9> : number of spikes (independent of noise) - start = 50 (ms) : start of first spike - noise = 0 <0,1> : amount of randomness (0.0 - 1.0) + interval = 10 (ms) <1e-9,1e9> : time between spikes (msec) + number = 10 <0,1e9> : number of spikes (independent of noise) + start = 50 (ms) : start of first spike + noise = 0 <0,1> : amount of randomness (0.0 - 1.0) } ASSIGNED { - event (ms) - on - ispike - donotuse + event (ms) + on + ispike + donotuse } VERBATIM -#if NRNBBCORE /* running in CoreNEURON */ - -#define IFNEWSTYLE(arg) arg - -#else /* running in NEURON */ - -/* - 1 means noiseFromRandom was called when _ran_compat was previously 0 . - 2 means noiseFromRandom123 was called when _ran_compat was previously 0. -*/ -static int _ran_compat; /* specifies the noise style for all instances */ -#define IFNEWSTYLE(arg) if(_ran_compat == 2) { arg } - -#endif /* running in NEURON */ +#if !NRNBBCORE +/** If we're running in NEURON, specify the noise style for all instances. + * 1 means noiseFromRandom was called when _ran_compat was previously 0. + * 2 means noiseFromRandom123 was called when _ran_compat was previously 0. + */ +static int _ran_compat; +#endif ENDVERBATIM :backward compatibility @@ -59,94 +52,96 @@ PROCEDURE seed(x) { VERBATIM #if !NRNBBCORE ENDVERBATIM - set_seed(x) + set_seed(x) VERBATIM #endif ENDVERBATIM } INITIAL { - - VERBATIM - if (_p_donotuse) { - /* only this style initializes the stream on finitialize */ - IFNEWSTYLE(nrnran123_setseq((nrnran123_State*)_p_donotuse, 0, 0);) - } - ENDVERBATIM - - on = 0 : off - ispike = 0 - if (noise < 0) { - noise = 0 - } - if (noise > 1) { - noise = 1 - } - if (start >= 0 && number > 0) { - on = 1 - : randomize the first spike so on average it occurs at - : start + noise*interval - event = start + invl(interval) - interval*(1. - noise) - : but not earlier than 0 - if (event < 0) { - event = 0 - } - net_send(event, 3) - } + VERBATIM +#if NRNBBCORE + if(_p_donotuse) { +#else + if(_p_donotuse && _ran_compat == 2) { +#endif + /* only this style initializes the stream on finitialize */ + nrnran123_setseq(reinterpret_cast(_p_donotuse), 0, 0); + } + ENDVERBATIM + on = 0 : off + ispike = 0 + if (noise < 0) { + noise = 0 + } + if (noise > 1) { + noise = 1 + } + if (start >= 0 && number > 0) { + on = 1 + : randomize the first spike so on average it occurs at + : start + noise*interval + event = start + invl(interval) - interval*(1. - noise) + : but not earlier than 0 + if (event < 0) { + event = 0 + } + net_send(event, 3) + } } PROCEDURE init_sequence(t(ms)) { - if (number > 0) { - on = 1 - event = 0 - ispike = 0 - } + if (number > 0) { + on = 1 + event = 0 + ispike = 0 + } } FUNCTION invl(mean (ms)) (ms) { - if (mean <= 0.) { - mean = .01 (ms) : I would worry if it were 0. - } - if (noise == 0) { - invl = mean - }else{ - invl = (1. - noise)*mean + noise*mean*erand() - } + if (mean <= 0.) { + mean = .01 (ms) : I would worry if it were 0. + } + if (noise == 0) { + invl = mean + } else { + invl = (1. - noise)*mean + noise*mean*erand() + } } FUNCTION erand() { VERBATIM - if (_p_donotuse) { - /* - :Supports separate independent but reproducible streams for - : each instance. However, the corresponding hoc Random - : distribution MUST be set to Random.negexp(1) - */ + if (_p_donotuse) { + /* + :Supports separate independent but reproducible streams for + : each instance. However, the corresponding hoc Random + : distribution MUST be set to Random.negexp(1) + */ #if !NRNBBCORE - if (_ran_compat == 2) { - _lerand = nrnran123_negexp((nrnran123_State*)_p_donotuse); - }else{ - _lerand = nrn_random_pick(_p_donotuse); - } + if (_ran_compat == 2) { + _lerand = nrnran123_negexp(reinterpret_cast(_p_donotuse)); + } else { + _lerand = nrn_random_pick(reinterpret_cast(_p_donotuse)); + } #else - _lerand = nrnran123_negexp((nrnran123_State*)_p_donotuse); + _lerand = nrnran123_negexp(reinterpret_cast(_p_donotuse)); #endif - return _lerand; - }else{ + return _lerand; + } else { #if NRNBBCORE - assert(0); + assert(0); #else - /* - : the old standby. Cannot use if reproducible parallel sim - : independent of nhost or which host this instance is on - : is desired, since each instance on this cpu draws from - : the same stream - */ + /* + : the old standby. Cannot use if reproducible parallel sim + : independent of nhost or which host this instance is on + : is desired, since each instance on this cpu draws from + : the same stream + */ #endif - } + } #if !NRNBBCORE ENDVERBATIM - erand = exprand(1) + erand = exprand(1) VERBATIM #endif ENDVERBATIM @@ -156,207 +151,203 @@ PROCEDURE noiseFromRandom() { VERBATIM #if !NRNBBCORE { - void** pv = (void**)(&_p_donotuse); - if (_ran_compat == 2) { - fprintf(stderr, "NetStim.noiseFromRandom123 was previously called\n"); - assert(0); - } - _ran_compat = 1; - if (ifarg(1)) { - *pv = nrn_random_arg(1); - }else{ - *pv = (void*)0; - } + if (_ran_compat == 2) { + fprintf(stderr, "NetStim.noiseFromRandom123 was previously called\n"); + assert(0); + } + _ran_compat = 1; + auto& randstate = reinterpret_cast(_p_donotuse); + if (ifarg(1)) { + randstate = nrn_random_arg(1); + } else { + randstate = nullptr; + } } #endif ENDVERBATIM } - PROCEDURE noiseFromRandom123() { VERBATIM #if !NRNBBCORE - { - nrnran123_State** pv = (nrnran123_State**)(&_p_donotuse); - if (_ran_compat == 1) { - fprintf(stderr, "NetStim.noiseFromRandom was previously called\n"); - assert(0); - } - _ran_compat = 2; - if (*pv) { - nrnran123_deletestream(*pv); - *pv = (nrnran123_State*)0; - } - if (ifarg(3)) { - *pv = nrnran123_newstream3((uint32_t)*getarg(1), (uint32_t)*getarg(2), (uint32_t)*getarg(3)); - }else if (ifarg(2)) { - *pv = nrnran123_newstream((uint32_t)*getarg(1), (uint32_t)*getarg(2)); - } - } + if (_ran_compat == 1) { + fprintf(stderr, "NetStim.noiseFromRandom was previously called\n"); + assert(0); + } + _ran_compat = 2; + auto& r123state = reinterpret_cast(_p_donotuse); + if (r123state) { + nrnran123_deletestream(r123state); + r123state = nullptr; + } + if (ifarg(3)) { + r123state = nrnran123_newstream3(static_cast(*getarg(1)), static_cast(*getarg(2)), static_cast(*getarg(3))); + } else if (ifarg(2)) { + r123state = nrnran123_newstream(static_cast(*getarg(1)), static_cast(*getarg(2))); + } #endif ENDVERBATIM } DESTRUCTOR { VERBATIM - if (!noise) { return; } - if (_p_donotuse) { + if (!noise) { return; } + if (_p_donotuse) { #if NRNBBCORE - { /* but note that mod2c does not translate DESTRUCTOR */ + { /* but note that mod2c does not translate DESTRUCTOR */ #else - if (_ran_compat == 2) { + if (_ran_compat == 2) { #endif - nrnran123_State** pv = (nrnran123_State**)(&_p_donotuse); - nrnran123_deletestream(*pv); - *pv = (nrnran123_State*)0; - } - } + auto& r123state = reinterpret_cast(_p_donotuse); + nrnran123_deletestream(r123state); + r123state = nullptr; + } + } ENDVERBATIM } VERBATIM static void bbcore_write(double* x, int* d, int* xx, int *offset, _threadargsproto_) { - if (!noise) { return; } - /* error if using the legacy scop_exprand */ - if (!_p_donotuse) { - fprintf(stderr, "NetStim: cannot use the legacy scop_negexp generator for the random stream.\n"); - assert(0); - } - if (d) { - char which; - uint32_t* di = ((uint32_t*)d) + *offset; + if (!noise) { return; } + /* error if using the legacy scop_exprand */ + if (!_p_donotuse) { + fprintf(stderr, "NetStim: cannot use the legacy scop_negexp generator for the random stream.\n"); + assert(0); + } + if (d) { + char which; + uint32_t* di = reinterpret_cast(d) + *offset; #if !NRNBBCORE - if (_ran_compat == 1) { - void** pv = (void**)(&_p_donotuse); - /* error if not using Random123 generator */ - if (!nrn_random_isran123(*pv, di, di+1, di+2)) { - fprintf(stderr, "NetStim: Random123 generator is required\n"); - assert(0); - } - nrn_random123_getseq(*pv, di+3, &which); - di[4] = (int)which; - }else{ + if (_ran_compat == 1) { + auto* rand = reinterpret_cast(_p_donotuse); + /* error if not using Random123 generator */ + if (!nrn_random_isran123(rand, di, di+1, di+2)) { + fprintf(stderr, "NetStim: Random123 generator is required\n"); + assert(0); + } + nrn_random123_getseq(rand, di+3, &which); + di[4] = which; + } else { #else { #endif - nrnran123_State** pv = (nrnran123_State**)(&_p_donotuse); - nrnran123_getids3(*pv, di, di+1, di+2); - nrnran123_getseq(*pv, di+3, &which); - di[4] = (int)which; + auto& r123state = reinterpret_cast(_p_donotuse); + nrnran123_getids3(r123state, di, di+1, di+2); + nrnran123_getseq(r123state, di+3, &which); + di[4] = which; #if NRNBBCORE - /* CORENeuron does not call DESTRUCTOR so... */ - nrnran123_deletestream(*pv); - *pv = (nrnran123_State*)0; + /* CoreNEURON does not call DESTRUCTOR so... */ + nrnran123_deletestream(r123state); + r123state = nullptr; #endif - } - /*printf("Netstim bbcore_write %d %d %d\n", di[0], di[1], di[3]);*/ - } - *offset += 5; + } + /*printf("Netstim bbcore_write %d %d %d\n", di[0], di[1], di[3]);*/ + } + *offset += 5; } static void bbcore_read(double* x, int* d, int* xx, int* offset, _threadargsproto_) { - if (!noise) { return; } - /* Generally, CoreNEURON, in the context of psolve, begins with - an empty model so this call takes place in the context of a freshly - created instance and _p_donotuse is not NULL. - However, this function - is also now called from NEURON at the end of coreneuron psolve - in order to transfer back the nrnran123 sequence state. That - allows continuation with a subsequent psolve within NEURON or - properly transfer back to CoreNEURON if we continue the psolve - there. So now, extra logic is needed for this call to work in - a NEURON context. - */ - - uint32_t* di = ((uint32_t*)d) + *offset; + if (!noise) { return; } + /* Generally, CoreNEURON, in the context of psolve, begins with an empty + * model, so this call takes place in the context of a freshly created + * instance and _p_donotuse is not NULL. + * However, this function is also now called from NEURON at the end of + * coreneuron psolve in order to transfer back the nrnran123 sequence state. + * That allows continuation with a subsequent psolve within NEURON or + * properly transfer back to CoreNEURON if we continue the psolve there. + * So now, extra logic is needed for this call to work in a NEURON context. + */ + uint32_t* di = reinterpret_cast(d) + *offset; #if NRNBBCORE - nrnran123_State** pv = (nrnran123_State**)(&_p_donotuse); - assert(!_p_donotuse); - *pv = nrnran123_newstream3(di[0], di[1], di[2]); - nrnran123_setseq(*pv, di[3], (char)di[4]); + auto& r123state = reinterpret_cast(_p_donotuse); + assert(!r123state); + r123state = nrnran123_newstream3(di[0], di[1], di[2]); + nrnran123_setseq(r123state, di[3], di[4]); #else - uint32_t id1, id2, id3; - assert(_p_donotuse); - if (_ran_compat == 1) { /* Hoc Random.Random123 */ - void** pv = (void**)(&_p_donotuse); - int b = nrn_random_isran123(*pv, &id1, &id2, &id3); - assert(b); - nrn_random123_setseq(*pv, di[3], (char)di[4]); - }else{ - assert(_ran_compat == 2); - nrnran123_State** pv = (nrnran123_State**)(&_p_donotuse); - nrnran123_getids3(*pv, &id1, &id2, &id3); - nrnran123_setseq(*pv, di[3], (char)di[4]); - } - /* Random123 on NEURON side has same ids as on CoreNEURON side */ - assert(di[0] == id1 && di[1] == id2 && di[2] == id3); + uint32_t id1, id2, id3; + assert(_p_donotuse); + if (_ran_compat == 1) { /* Hoc Random.Random123 */ + auto* pv = reinterpret_cast(_p_donotuse); + int b = nrn_random_isran123(pv, &id1, &id2, &id3); + assert(b); + nrn_random123_setseq(pv, di[3], (char)di[4]); + } else { + assert(_ran_compat == 2); + auto* r123state = reinterpret_cast(_p_donotuse); + nrnran123_getids3(r123state, &id1, &id2, &id3); + nrnran123_setseq(r123state, di[3], di[4]); + } + /* Random123 on NEURON side has same ids as on CoreNEURON side */ + assert(di[0] == id1 && di[1] == id2 && di[2] == id3); #endif - *offset += 5; + *offset += 5; } ENDVERBATIM PROCEDURE next_invl() { - if (number > 0) { - event = invl(interval) - } - if (ispike >= number) { - on = 0 - } + if (number > 0) { + event = invl(interval) + } + if (ispike >= number) { + on = 0 + } } NET_RECEIVE (w) { - if (flag == 0) { : external event - if (w > 0 && on == 0) { : turn on spike sequence - : but not if a netsend is on the queue - init_sequence(t) - : randomize the first spike so on average it occurs at - : noise*interval (most likely interval is always 0) - next_invl() - event = event - interval*(1. - noise) - net_send(event, 1) - }else if (w < 0) { : turn off spiking definitively - on = 0 - } - } - if (flag == 3) { : from INITIAL - if (on == 1) { : but ignore if turned off by external event - init_sequence(t) - net_send(0, 1) - } - } - if (flag == 1 && on == 1) { - ispike = ispike + 1 - net_event(t) - next_invl() - if (on == 1) { - net_send(event, 1) - } - } + if (flag == 0) { : external event + if (w > 0 && on == 0) { : turn on spike sequence + : but not if a netsend is on the queue + init_sequence(t) + : randomize the first spike so on average it occurs at + : noise*interval (most likely interval is always 0) + next_invl() + event = event - interval*(1. - noise) + net_send(event, 1) + }else if (w < 0) { : turn off spiking definitively + on = 0 + } + } + if (flag == 3) { : from INITIAL + if (on == 1) { : but ignore if turned off by external event + init_sequence(t) + net_send(0, 1) + } + } + if (flag == 1 && on == 1) { + ispike = ispike + 1 + net_event(t) + next_invl() + if (on == 1) { + net_send(event, 1) + } + } } FUNCTION bbsavestate() { - bbsavestate = 0 - : limited to noiseFromRandom123 + bbsavestate = 0 + : limited to noiseFromRandom123 VERBATIM #if !NRNBBCORE - if (_ran_compat == 2) { - nrnran123_State** pv = (nrnran123_State**)(&_p_donotuse); - if (!*pv) { return 0.0; } - char which; - uint32_t seq; - double *xdir, *xval; - xdir = hoc_pgetarg(1); - if (*xdir == -1.) { *xdir = 2; return 0.0; } - xval = hoc_pgetarg(2); - if (*xdir == 0.) { - nrnran123_getseq(*pv, &seq, &which); - xval[0] = (double)seq; - xval[1] = (double)which; - } - if (*xdir == 1) { - nrnran123_setseq(*pv, (uint32_t)xval[0], (char)xval[1]); + if (_ran_compat == 2) { + auto r123state = reinterpret_cast(_p_donotuse); + if (!r123state) { return 0.0; } + double* xdir = hoc_pgetarg(1); + if (*xdir == -1.) { + *xdir = 2; + return 0.0; + } + double* xval = hoc_pgetarg(2); + if (*xdir == 0.) { + char which; + uint32_t seq; + nrnran123_getseq(r123state, &seq, &which); + xval[0] = seq; + xval[1] = which; + } + if (*xdir == 1) { + nrnran123_setseq(r123state, xval[0], xval[1]); + } } - } /* else do nothing */ #endif ENDVERBATIM } diff --git a/src/nrnoc/neuron.h b/src/nrnoc/neuron.h index 2cc56360f8..c1d56148ee 100755 --- a/src/nrnoc/neuron.h +++ b/src/nrnoc/neuron.h @@ -34,7 +34,7 @@ extern int secondorder, diam_changed, nrn_shape_changed_; extern int nrn_netrec_state_adjust, nrn_sparse_partrans; extern double clamp_resist; extern double celsius; -extern int stoprun; +extern "C" int stoprun; extern void fit_praxis(), attr_praxis(), pval_praxis(), stop_praxis(); #if KEEP_NSEG_PARM extern void keep_nseg_parm(); diff --git a/src/nrnoc/nrncvode.h b/src/nrnoc/nrncvode.h index 7ca90720ab..146fc44594 100644 --- a/src/nrnoc/nrncvode.h +++ b/src/nrnoc/nrncvode.h @@ -1,30 +1,26 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif -void clear_event_queue(void); -void cvode_fadvance(double); -void nrn_random_play(); -#ifdef __cplusplus -} -extern bool nrn_use_bin_queue_; -#endif struct Memb_list; struct NrnThread; +void cvode_fadvance(double); extern void cvode_finitialize(double); extern void nrncvode_set_t(double); -extern void deliver_net_events(struct NrnThread*); -extern void nrn_deliver_events(struct NrnThread*); -extern void init_net_events(void); -extern void nrn_record_init(void); -extern void nrn_play_init(void); -extern void fixed_record_continuous(struct NrnThread* nt); -extern void fixed_play_continuous(struct NrnThread* nt); -extern void nrn_solver_prepare(void); +extern void deliver_net_events(NrnThread*); +extern void nrn_deliver_events(NrnThread*); +extern "C" void clear_event_queue(); +extern void init_net_events(); +extern void nrn_record_init(); +extern void nrn_play_init(); +extern void fixed_record_continuous(NrnThread* nt); +extern void fixed_play_continuous(NrnThread* nt); +extern void nrn_solver_prepare(); +extern "C" void nrn_random_play(); extern void nrn_daspk_init_step(double, double, int); -extern void nrndae_init(void); -extern void nrndae_update(void); -extern void nrn_update_2d(struct NrnThread*); -extern void nrn_capacity_current(struct NrnThread* _nt, struct Memb_list* ml); -extern void nrn_spike_exchange_init(void); -extern void nrn_spike_exchange(struct NrnThread* nt); +extern void nrndae_init(); +extern void nrndae_update(); +extern void nrn_update_2d(NrnThread*); +extern void nrn_capacity_current(NrnThread* _nt, Memb_list* ml); +extern void nrn_spike_exchange_init(); +void nrn_spike_exchange(NrnThread* nt); +extern bool nrn_use_bin_queue_; +double nrn_event_queue_stats(double* stats); +void nrn_fake_fire(int gid, double spiketime, int fake_out); diff --git a/src/nrnoc/nrniv_mf.h b/src/nrnoc/nrniv_mf.h index d0e8247ac0..ff08c64068 100644 --- a/src/nrnoc/nrniv_mf.h +++ b/src/nrnoc/nrniv_mf.h @@ -17,6 +17,19 @@ typedef void (*pnt_receive_init_t)(Point_process*, double*, double); extern Prop* need_memb_cl(Symbol*, int*, int*); extern Prop* prop_alloc(Prop**, int, Node*); +void artcell_net_send(void** v, double* weight, Point_process* pnt, double td, double flag); +[[deprecated("non-void* overloads are preferred")]] void artcell_net_send(void** v, + double* weight, + void* pnt, + double td, + double flag); +void nrn_net_send(void** v, double* weight, Point_process* pnt, double td, double flag); +[[deprecated("non-void* overloads are preferred")]] void nrn_net_send(void** v, + double* weight, + void* pnt, + double td, + double flag); + extern double nrn_ion_charge(Symbol*); #if defined(__cplusplus) extern "C" { @@ -126,7 +139,6 @@ extern Prop* nrn_point_prop_; extern int at_time(NrnThread*, double); -extern void artcell_net_send(void**, double*, Point_process*, double, double); extern void artcell_net_move(void**, Point_process*, double); extern int ifarg(int); @@ -140,7 +152,6 @@ extern int v_structure_change; extern pnt_receive_t* pnt_receive; extern pnt_receive_init_t* pnt_receive_init; extern short* pnt_receive_size; -extern void nrn_net_send(void**, double*, Point_process*, double, double); extern void nrn_net_event(Point_process*, double); extern void nrn_net_move(void**, Point_process*, double); diff --git a/src/nrnoc/pattern.mod b/src/nrnoc/pattern.mod index e031098db2..a22c842f5d 100755 --- a/src/nrnoc/pattern.mod +++ b/src/nrnoc/pattern.mod @@ -5,39 +5,32 @@ : as Info makes a copy of those, double for tvec, int for gidvec. NEURON { - ARTIFICIAL_CELL PatternStim - THREADSAFE - RANGE fake_output - BBCOREPOINTER ptr + ARTIFICIAL_CELL PatternStim + THREADSAFE + RANGE fake_output + BBCOREPOINTER ptr } PARAMETER { - fake_output = 0 + fake_output = 0 } ASSIGNED { - ptr + ptr } INITIAL { - if (initps() > 0) { net_send(0, 1) } + if (initps() > 0) { net_send(0, 1) } } NET_RECEIVE (w) {LOCAL nst - if (flag == 1) { - nst = sendgroup() - if (nst >= t) {net_send(nst - t, 1)} - } + if (flag == 1) { + nst = sendgroup() + if (nst >= t) {net_send(nst - t, 1)} + } } VERBATIM - -extern int ifarg(int iarg); -extern double* vector_vec(void* vv); -extern int vector_capacity(void* vv); -extern void* vector_arg(int iarg); -extern void nrn_fake_fire(int gid, double spiketime, int fake_out); - /* Changed Info definition to correspond to that of CoreNEURON pattern.mod in order to reduce memory requirements of separate copies of what used to here be an IvocVect of doubles for gidvec but in CoreNEURON was @@ -48,109 +41,104 @@ extern void nrn_fake_fire(int gid, double spiketime, int fake_out); potentially freed. On the other hand, it is now a simple matter to implement reading the Info directly from a file. */ -typedef struct { /* same as in CoreNEURON */ - int size; - double* tvec; - int* gidvec; - int index; -} Info; - -#define INFOCAST Info** ip = (Info**)(&(_p_ptr)) - +struct Info { /* same as in CoreNEURON */ + int size; + double* tvec; + int* gidvec; + int index; +}; +Info*& as_info(double*& vptr) { return reinterpret_cast(vptr); } ENDVERBATIM CONSTRUCTOR { VERBATIM { - INFOCAST; - Info* info = (Info*)hoc_Emalloc(sizeof(Info)); hoc_malchk(); - *ip = info; - info->size = 0; - info->tvec = (double*)0; - info->gidvec = (int*)0; - info->index = 0; + auto& info = as_info(_p_ptr); + assert(!info); + info = new Info{}; + info->size = 0; + info->tvec = nullptr; + info->gidvec = nullptr; + info->index = 0; } ENDVERBATIM } DESTRUCTOR { VERBATIM { - INFOCAST; Info* info = *ip; - if (info->size > 0) { - free(info->tvec); - free(info->gidvec); - } - free(info); + auto& info = as_info(_p_ptr); + if (info->size > 0) { + delete[] info->tvec; + delete[] info->gidvec; + } + delete info; + info = nullptr; } ENDVERBATIM } FUNCTION initps() { VERBATIM { - INFOCAST; Info* info = *ip; - info->index = 0; - if (info->tvec) { - _linitps = 1.; - }else{ - _linitps = 0.; - } + auto& info = as_info(_p_ptr); + info->index = 0; + if (info->tvec) { + _linitps = 1.; + }else{ + _linitps = 0.; + } } ENDVERBATIM } FUNCTION sendgroup() { VERBATIM { - INFOCAST; Info* info = *ip; - int size = info->size; - int fake_out; - double* tvec = info->tvec; - int* gidvec = info->gidvec; - int i; - fake_out = fake_output ? 1 : 0; - for (i=0; info->index < size; ++i) { - /* only if the gid is NOT on this machine */ - nrn_fake_fire((int)gidvec[info->index], tvec[info->index], fake_out); - ++info->index; - if (i > 100 && t < tvec[info->index]) { break; } - } - if (info->index >= size) { - _lsendgroup = t - 1.; - }else{ - _lsendgroup = tvec[info->index]; - } + auto& info = as_info(_p_ptr); + int size = info->size; + double* tvec = info->tvec; + int* gidvec = info->gidvec; + int fake_out = fake_output ? 1 : 0; + for (int i=0; info->index < size; ++i) { + /* only if the gid is NOT on this machine */ + nrn_fake_fire(gidvec[info->index], tvec[info->index], fake_out); + ++info->index; + if (i > 100 && t < tvec[info->index]) { break; } + } + if (info->index >= size) { + _lsendgroup = t - 1.; + }else{ + _lsendgroup = tvec[info->index]; + } } ENDVERBATIM } PROCEDURE play() { VERBATIM { - INFOCAST; Info* info = *ip; - if (info->size > 0) { - free(info->tvec); - free(info->gidvec); - info->size = 0; - info->tvec = (void*)0; - info->gidvec = (void*)0; - } - - if (ifarg(1)) { - int _i; - void* tvec = vector_arg(1); - void* gidvec = vector_arg(2); - int size = vector_capacity(tvec); - //assert(size == vector_capacity(gidvec); - double* tdata = vector_vec(tvec); - double* giddata = vector_vec(gidvec); - - info->size = size; - info->tvec = (double*)hoc_Emalloc(size*sizeof(double)); hoc_malchk(); - info->gidvec = (int*)hoc_Emalloc(size*sizeof(int)); hoc_malchk(); - - for (_i = 0; _i < size; ++_i) { - info->tvec[_i] = tdata[_i]; - info->gidvec[_i] = (int)giddata[_i]; - } - } + auto& info = as_info(_p_ptr); + if (info->size > 0) { + delete[] info->tvec; + delete[] info->gidvec; + info->tvec = nullptr; + info->gidvec = nullptr; + info->size = 0; + } + + if (ifarg(1)) { + int _i; + auto* tvec = vector_arg(1); + auto* gidvec = vector_arg(2); + int size = vector_capacity(tvec); + double* tdata = vector_vec(tvec); + double* giddata = vector_vec(gidvec); + + info->size = size; + info->tvec = new double[size]; + info->gidvec = new int[size]; + for (_i = 0; _i < size; ++_i) { + info->tvec[_i] = tdata[_i]; + info->gidvec[_i] = (int)giddata[_i]; + } + } } ENDVERBATIM } @@ -161,8 +149,7 @@ static void bbcore_write(double* x, int* d, int* xx, int *offset, _threadargspro static void bbcore_read(double* x, int* d, int* xx, int* offset, _threadargsproto_){} Info* nrn_patternstim_info_ref(Datum* _ppvar) { - // CoreNEURON PatternStim will use this Info* - INFOCAST; - return *ip; + // CoreNEURON PatternStim will use this Info* + return as_info(_p_ptr); } ENDVERBATIM diff --git a/src/nrnoc/section.h b/src/nrnoc/section.h index 59bf8b4e30..e2aa672112 100644 --- a/src/nrnoc/section.h +++ b/src/nrnoc/section.h @@ -321,7 +321,6 @@ extern int _method3; #include -extern int stoprun; #define tstopbit (1 << 15) #define tstopset stoprun |= tstopbit #define tstopunset stoprun &= (~tstopbit) diff --git a/src/nrnoc/treeset.cpp b/src/nrnoc/treeset.cpp index 36b8ffcb58..10a69e376c 100644 --- a/src/nrnoc/treeset.cpp +++ b/src/nrnoc/treeset.cpp @@ -15,16 +15,13 @@ #include "nrnmpi.h" #include "multisplit.h" #include "spmatrix.h" +#include "treeset.h" #include "nonvintblock.h" #include "nrndae_c.h" #include "utils/profile/profiler_interface.h" extern spREAL* spGetElement(char*, int, int); -#if CVODE -extern int cvode_active_; -#endif - int nrn_shape_changed_; /* for notifying Shape class in nrniv */ double* nrn_mech_wtime_; @@ -2177,7 +2174,7 @@ void nrn_old_thread_save(void) { static double* (*recalc_ptr_)(double*); -extern "C" double* nrn_recalc_ptr(double* old) { +double* nrn_recalc_ptr(double* old) { if (recalc_ptr_) { return (*recalc_ptr_)(old); } @@ -2193,7 +2190,7 @@ extern "C" double* nrn_recalc_ptr(double* old) { return old; } -extern "C" void nrn_register_recalc_ptr_callback(Pfrv f) { +void nrn_register_recalc_ptr_callback(Pfrv f) { if (n_recalc_ptr_callback >= 20) { Printf("More than 20 recalc_ptr_callback functions\n"); exit(1); diff --git a/src/nrnoc/treeset.h b/src/nrnoc/treeset.h new file mode 100644 index 0000000000..01a7d2bd47 --- /dev/null +++ b/src/nrnoc/treeset.h @@ -0,0 +1,3 @@ +#pragma once +double* nrn_recalc_ptr(double* old); +void nrn_register_recalc_ptr_callback(void (*f)()); diff --git a/src/nrnoc/vclmp.mod b/src/nrnoc/vclmp.mod index 1eff14cf04..fa275e34fa 100755 --- a/src/nrnoc/vclmp.mod +++ b/src/nrnoc/vclmp.mod @@ -99,10 +99,9 @@ INITIAL { : stopping cvode here if the clamp is on still allows : that tool to control a IClamp under cvode VERBATIM - {extern int cvode_active_; if (cvode_active_) { hoc_execerror("VClamp", " does not work with CVODE"); - }} + } ENDVERBATIM }} } diff --git a/src/oc/code.cpp b/src/oc/code.cpp index 29aaa2532e..8563ec3383 100644 --- a/src/oc/code.cpp +++ b/src/oc/code.cpp @@ -12,6 +12,7 @@ #include "parse.hpp" #include "ocfunc.h" #include "ocmisc.h" +#include "oc_ansi.h" #include "hocparse.h" #include "equation.h" #include @@ -758,7 +759,7 @@ int hoc_is_object_arg(int narg) { return (type == OBJECTVAR || type == OBJECTTMP); } -extern "C" int hoc_is_tempobj_arg(int narg) { +int hoc_is_tempobj_arg(int narg) { return (hoc_argtype(narg) == OBJECTTMP); } @@ -1627,7 +1628,7 @@ double* hoc_pgetarg(int narg) { /* return pointer to nth argument */ return fp->argn[(narg - fp->nargs) * 2].pval; } -extern "C" double* getarg(int narg) { /* return pointer to nth argument */ +double* hoc_getarg(int narg) { /* return pointer to nth argument */ if (narg > fp->nargs) execerror(fp->sp->name, "not enough arguments"); #if 1 diff --git a/src/oc/code2.cpp b/src/oc/code2.cpp index e042f49de7..b41dd511ce 100644 --- a/src/oc/code2.cpp +++ b/src/oc/code2.cpp @@ -637,7 +637,6 @@ void symbols(void) /* display the types above */ double chkarg(int arg, double low, double high) /* argument checking for user functions */ { - // double *getarg(),; double val; val = *getarg(arg); diff --git a/src/oc/hocdec.h b/src/oc/hocdec.h index 077c1e161b..b9b7f3ea4f 100644 --- a/src/oc/hocdec.h +++ b/src/oc/hocdec.h @@ -246,21 +246,21 @@ typedef struct Object { } Object; #endif -typedef struct { /* User Functions */ +struct VoidFunc { /* User Functions */ const char* name; void (*func)(void); -} VoidFunc; +}; -typedef struct { /* User Double Scalars */ +struct DoubScal { /* User Double Scalars */ const char* name; double* pdoub; -} DoubScal; +}; -typedef struct { /* User Vectors */ +struct DoubVec { /* User Vectors */ const char* name; double* pdoub; int index1; -} DoubVec; +}; typedef struct { /* recommended limits for symbol values */ const char* name; diff --git a/src/oc/math.cpp b/src/oc/math.cpp index 282e4c7082..b402a6f5f5 100644 --- a/src/oc/math.cpp +++ b/src/oc/math.cpp @@ -41,7 +41,7 @@ double Log10(double x) { } /* used by nmodl and other c, c++ code */ -extern "C" double hoc_Exp(double x) { +double hoc_Exp(double x) { if (x < -700.) { return 0.; } else if (x > 700 && nrn_feenableexcept_ == 0) { diff --git a/src/oc/mcran4.cpp b/src/oc/mcran4.cpp index 4b542f20a0..d5839f74be 100644 --- a/src/oc/mcran4.cpp +++ b/src/oc/mcran4.cpp @@ -50,11 +50,11 @@ contained the header: static uint32_t lowindex = 0; -extern "C" void mcell_ran4_init(uint32_t low) { +void mcell_ran4_init(uint32_t low) { lowindex = low; } -extern "C" double mcell_ran4(uint32_t* high, double* x, unsigned int n, double range) { +double mcell_ran4(uint32_t* high, double* x, unsigned int n, double range) { int i; for (i = 0; i < n; i++) { x[i] = range * nrnRan4dbl(high, lowindex); @@ -62,11 +62,16 @@ extern "C" double mcell_ran4(uint32_t* high, double* x, unsigned int n, double r return x[0]; } -extern "C" double mcell_ran4a(uint32_t* high) { +// Allow mcell_ran4 to be called from C code in praxis.c +extern "C" double mcell_ran4_legacy(uint32_t* idx1, double* x, unsigned int n, double range) { + return mcell_ran4(idx1, x, n, range); +} + +double mcell_ran4a(uint32_t* high) { return nrnRan4dbl(high, lowindex); } -extern "C" uint32_t mcell_iran4(uint32_t* high) { +uint32_t mcell_iran4(uint32_t* high) { return nrnRan4int(high, lowindex); } @@ -104,7 +109,7 @@ void hoc_usemcran4() { hoc_pushx(prev); } -extern "C" uint32_t nrnRan4int(uint32_t* idx1, uint32_t idx2) { +uint32_t nrnRan4int(uint32_t* idx1, uint32_t idx2) { uint32_t u, v, w, m, n; /* 64-bit hash */ n = (*idx1)++; @@ -159,7 +164,7 @@ extern "C" uint32_t nrnRan4int(uint32_t* idx1, uint32_t idx2) { // */ static const double SHIFT32 = 1.0 / 4294967296.0; /* 2^-32 */ -extern "C" double nrnRan4dbl(uint32_t* idx1, uint32_t idx2) { +double nrnRan4dbl(uint32_t* idx1, uint32_t idx2) { uint32_t hi, lo, extra; hi = (uint32_t) nrnRan4int(idx1, idx2); /*top 32 bits*/ /* diff --git a/src/oc/mcran4.h b/src/oc/mcran4.h index 1397335d97..7d251b4cc1 100644 --- a/src/oc/mcran4.h +++ b/src/oc/mcran4.h @@ -1,27 +1,12 @@ -#ifndef mcran4_h -#define mcran4_h +#pragma once +#include -#include -#if defined(HAVE_STDINT_H) -#include -#endif - -#if defined(__cplusplus) -extern "C" { -#endif - -extern void mcell_ran4_init(uint32_t); -extern double mcell_ran4(uint32_t* high, double* x, unsigned int n, double range); -extern double mcell_ran4a(uint32_t* idx1); -extern uint32_t mcell_iran4(uint32_t* idx1); -extern double nrnRan4dbl(uint32_t* idx1, uint32_t idx2); -extern uint32_t nrnRan4int(uint32_t* idx1, uint32_t idx2); - -#if defined(__cplusplus) -} -#endif - -#endif +void mcell_ran4_init(uint32_t); +double mcell_ran4(uint32_t* idx1, double* x, unsigned int n, double range); +double mcell_ran4a(uint32_t* idx1); +uint32_t mcell_iran4(uint32_t* idx1); +double nrnRan4dbl(uint32_t* idx1, uint32_t idx2); +uint32_t nrnRan4int(uint32_t* idx1, uint32_t idx2); /* The original ran4 generator was copyrighted by "Numerical Recipes in C" diff --git a/src/oc/mech_api.h b/src/oc/mech_api.h index b188d62ea8..e0b99c905e 100644 --- a/src/oc/mech_api.h +++ b/src/oc/mech_api.h @@ -9,9 +9,12 @@ * header has to be sandwiched between md1redef.h and md2redef.h, which * we leave to nocmodl. */ +#include "bbsavestate.h" #include "mcran4.h" #include "nrncvode.h" -#include "nrnrandom.h" #include "nrnran123.h" +#include "nrnrandom.h" +#include "oc_ansi.h" #include "nrnversionmacros.h" #include "scoplib.h" +#include "treeset.h" diff --git a/src/oc/mk_hocusr_h.py b/src/oc/mk_hocusr_h.py index 2aa1e42c98..36ad53c135 100644 --- a/src/oc/mk_hocusr_h.py +++ b/src/oc/mk_hocusr_h.py @@ -59,7 +59,11 @@ def process(type, names): names = line.replace(",", " ").replace(";", " ").split() if not skip and len(names) > 2: print(line) # entire filtered neuron.h file without pgcc added lines. - process(names[1], names[2:]) + assert names[0] == "extern" + names.pop(0) + if names[0] in {'"C"', '"C++"'}: + names.pop(0) + process(names[0], names[1:]) print( diff --git a/src/oc/nrnran123.cpp b/src/oc/nrnran123.cpp index 1bf55f3bda..942ef85273 100644 --- a/src/oc/nrnran123.cpp +++ b/src/oc/nrnran123.cpp @@ -42,7 +42,7 @@ extern "C" void nrnran123_deletestream(nrnran123_State* s) { free(s); } -extern "C" void nrnran123_getseq(nrnran123_State* s, uint32_t* seq, char* which) { +void nrnran123_getseq(nrnran123_State* s, uint32_t* seq, char* which) { *seq = s->c.v[0]; *which = s->which_; } diff --git a/src/oc/nrnran123.h b/src/oc/nrnran123.h index 1c10ed1b46..048471c301 100644 --- a/src/oc/nrnran123.h +++ b/src/oc/nrnran123.h @@ -67,5 +67,4 @@ extern nrnran123_array4x32 nrnran123_iran(uint32_t seq, uint32_t id1, uint32_t i extern nrnran123_array4x32 nrnran123_iran3(uint32_t seq, uint32_t id1, uint32_t id2, uint32_t id3); extern double nrnran123_uint2dbl(uint32_t); - #endif diff --git a/src/oc/nrnrandom.h b/src/oc/nrnrandom.h index 2d37659e8a..b986a71293 100644 --- a/src/oc/nrnrandom.h +++ b/src/oc/nrnrandom.h @@ -1,31 +1,28 @@ #pragma once -#ifdef __cplusplus -#error "This version of nrnrandom.h should never be compiled as C++." -#endif #include -/** Ideally the prototypes below would take Rand* in place of void*, but this - * would break several existing models. We do, however, want to declare the - * Rand type, as this makes it possible to write (for example) - * nrn_random_pick((Rand*)some_rand) now, which will be required to suppress - * deprecation warnings in NEURON 9+ where nrn_random_pick(void*) is a - * [[deprecated]] overload and the non-deprecated version takes Rand*. - */ -typedef struct Rand Rand; +class Rand; +long nrn_get_random_sequence(Rand* r); +Rand* nrn_random_arg(int); +int nrn_random_isran123(Rand* r, uint32_t* id1, uint32_t* id2, uint32_t* id3); +double nrn_random_pick(Rand* r); +void nrn_random_reset(Rand* r); +int nrn_random123_getseq(Rand* r, uint32_t* seq, char* which); +int nrn_random123_setseq(Rand* r, uint32_t seq, char which); +void nrn_set_random_sequence(Rand* r, long seq); -/** These declarations are wrong, in the sense that they are inconsistent with - * the definitions in ivocrand.cpp. This is an intentional, but possibly - * unwise, decision. - */ -long nrn_get_random_sequence(void* r); -void* nrn_random_arg(int); -int nrn_random_isran123(void* r, uint32_t* id1, uint32_t* id2, uint32_t* id3); -double nrn_random_pick(void* r); -void nrn_random_reset(void* r); -int nrn_random123_getseq(void* r, uint32_t* seq, char* which); -int nrn_random123_setseq(void* r, uint32_t seq, char which); - -/** Note that in addition to having void* in place of Rand*, this has int in - * place of long. - */ -void nrn_set_random_sequence(void* r, int seq); +[[deprecated("non-void* overloads are preferred")]] long nrn_get_random_sequence(void* r); +[[deprecated("non-void* overloads are preferred")]] int nrn_random_isran123(void* r, + uint32_t* id1, + uint32_t* id2, + uint32_t* id3); +[[deprecated("non-void* overloads are preferred")]] double nrn_random_pick(void* r); +[[deprecated("non-void* overloads are preferred")]] void nrn_random_reset(void* r); +[[deprecated("non-void* overloads are preferred")]] int nrn_random123_getseq(void* r, + uint32_t* seq, + char* which); +[[deprecated("non-void* overloads are preferred")]] int nrn_random123_setseq(void* r, + uint32_t seq, + char which); +// Note that in addition to having void* in place of Rand*, this has int in place of long. +[[deprecated("non-void* overloads are preferred")]] void nrn_set_random_sequence(void* r, int seq); diff --git a/src/oc/oc_ansi.h b/src/oc/oc_ansi.h index f996670423..3f2494841c 100644 --- a/src/oc/oc_ansi.h +++ b/src/oc/oc_ansi.h @@ -20,18 +20,25 @@ * @{ */ - -#if defined(__cplusplus) +struct Arrayinfo; +struct cTemplate; +union Datum; +struct DoubScal; +struct DoubVec; +struct HocSymExtension; class IvocVect; -#else -#define IvocVect void -#endif +struct Object; +union Objectdata; +struct Symbol; +struct Symlist; +struct VoidFunc; #if defined(__cplusplus) extern "C" { #endif // nocpout.cpp +extern Symbol* hoc_get_symbol(const char* var); extern void hoc_register_var(DoubScal*, DoubVec*, VoidFunc*); extern void ivoc_help(const char*); @@ -46,29 +53,53 @@ extern void hoc_execerr_ext(const char* fmt, ...); extern char* hoc_object_name(Object*); extern void hoc_retpushx(double); -extern double* getarg(int); +extern double* hoc_getarg(int); +double* hoc_pgetarg(int); extern int ifarg(int); extern int vector_instance_px(void*, double**); extern void install_vector_method(const char*, double (*)(void*)); -extern IvocVect* vector_arg(int); extern int vector_arg_px(int i, double** p); -extern double* vector_vec(IvocVect*); -extern int vector_capacity(IvocVect*); -extern void vector_resize(IvocVect*, int); #if defined(__cplusplus) } #endif +double hoc_Exp(double); +int hoc_is_tempobj_arg(int narg); +FILE* hoc_obj_file_arg(int i); +void hoc_reg_nmodl_text(int type, const char* txt); +void hoc_reg_nmodl_filename(int type, const char* filename); +size_t nrn_mallinfo(int item); +int nrn_mlh_gsort(double* vec, int* base_ptr, int total_elems, int (*cmp)(double, double)); +void state_discontinuity(int i, double* pd, double d); + +IvocVect* vector_arg(int); +int vector_buffer_size(IvocVect*); +int vector_capacity(IvocVect*); +IvocVect* vector_new(int, Object* = nullptr); +IvocVect* vector_new0(); +IvocVect* vector_new1(int); +IvocVect* vector_new2(IvocVect*); +Object** vector_pobj(IvocVect*); +void vector_resize(IvocVect*, int); +double* vector_vec(IvocVect*); + +// olupton 2022-01-21: These overloads are added for backwards compatibility +// with pre-C++ mechanisms. +[[deprecated("non-void* overloads are preferred")]] int vector_buffer_size(void*); +[[deprecated("non-void* overloads are preferred")]] int vector_capacity(void*); +[[deprecated("non-void* overloads are preferred")]] Object** vector_pobj(void*); +[[deprecated("non-void* overloads are preferred")]] void vector_resize(void*, int); +[[deprecated("non-void* overloads are preferred")]] double* vector_vec(void*); + extern int nrnignore; #if defined(__cplusplus) extern "C" { #endif - /** * \brief Brief explanation of hoc_obj_run * @@ -81,10 +112,9 @@ extern int hoc_is_double_arg(int); extern int hoc_is_pdouble_arg(int); extern int hoc_is_str_arg(int); extern int hoc_is_object_arg(int); -extern char* gargstr(int); +extern char* hoc_gargstr(int); extern char** hoc_pgargstr(int); -extern double* hoc_pgetarg(int); extern Object** hoc_objgetarg(int); extern Object* hoc_name2obj(const char* name, int index); @@ -187,15 +217,9 @@ extern void* hoc_pysec_name2ptr(const char* s, int eflag); extern void* nrn_parsing_pysec_; extern void vector_append(IvocVect*, double); -extern IvocVect* vector_new(int, Object*); /*use this if possible*/ -extern IvocVect* vector_new0(); -extern IvocVect* vector_new1(int); -extern IvocVect* vector_new2(IvocVect*); extern void vector_delete(IvocVect*); -extern int vector_buffer_size(IvocVect*); extern Object** vector_temp_objvar(IvocVect*); -extern Object** vector_pobj(IvocVect*); extern int is_vector_arg(int); @@ -260,7 +284,7 @@ extern void hoc_obj_disconnect(Object*); extern void hoc_free_object(Object*); extern void hoc_free_pstring(char**); extern int hoc_returning; -extern void hoc_on_init_register(Pfrv); +extern void hoc_on_init_register(void (*)()); extern int hoc_pid(void); extern int hoc_ired(const char*, int, int, int); extern double hoc_xred(const char*, double, double, double); @@ -274,27 +298,6 @@ extern int nrn_isdouble(double*, double, double); extern void* nrn_opaque_obj2pyobj(Object*); // PyObject reference not incremented extern Symbol* hoc_get_symbol(const char* var); -extern double hoc_Exp(double); -extern int hoc_is_tempobj_arg(int narg); -extern FILE* hoc_obj_file_arg(int i); -extern void hoc_reg_nmodl_text(int type, const char* txt); -extern void hoc_reg_nmodl_filename(int type, const char* filename); -extern size_t nrn_mallinfo(int item); -extern int nrn_mlh_gsort(double* vec, int* base_ptr, int total_elems, int (*cmp)(double, double)); -extern void state_discontinuity(int i, double* pd, double d); - -extern double nrn_event_queue_stats(double* stats); -extern double* nrn_recalc_ptr(double*); -extern void nrn_register_recalc_ptr_callback(Pfrv f); - -// BlueBrain -extern void* bbss_buffer_counts(int*, int**, int**, int*); -extern void bbss_save_global(void*, char*, int); -extern void bbss_restore_global(void*, char*, int); -extern void bbss_save(void*, int, char*, int); -extern void bbss_restore(void*, int, int, char*, int); -extern void bbss_save_done(void*); -extern void bbss_restore_done(void*); #if defined(__cplusplus) } @@ -304,7 +307,10 @@ extern int _nrnunit_use_legacy_; /* 1:legacy, 0:modern (default) */ extern void bbs_done(void); extern int hoc_main1(int, const char**, const char**); extern char* cxx_char_alloc(size_t size); -extern int stoprun; + +// olupton 2022-01-31: This has to have C linkage for now because it is used in +// praxis.c. +extern "C" int stoprun; extern int nrn_mpiabort_on_error_; #endif diff --git a/src/oc/symbol.cpp b/src/oc/symbol.cpp index 70ef8a0e1d..5ae439173d 100644 --- a/src/oc/symbol.cpp +++ b/src/oc/symbol.cpp @@ -17,6 +17,7 @@ #include #include #include "hoc.h" +#include "oc_ansi.h" #include "ocfunc.h" #include "parse.hpp" #include "hoclist.h" @@ -404,7 +405,7 @@ void hoc_free_pstring(char** p) { } } -extern "C" size_t nrn_mallinfo(int item) { +size_t nrn_mallinfo(int item) { #if defined(__APPLE__) && defined(__MACH__) /* OSX ------------------------------------------------------ * Returns the current resident set size (physical memory use) measured diff --git a/src/scopmath/newton.c b/src/scopmath/newton.c index f73c1984b3..810d533410 100755 --- a/src/scopmath/newton.c +++ b/src/scopmath/newton.c @@ -57,11 +57,7 @@ static char RCSid[] = #include #include "errcodes.h" -int newton(n, index, x, pfunc, value) -int n, (*pfunc) (); -double x[], value[]; -int *index; -{ +int newton(int n, int* index, double* x, int(*pfunc)(), double* value) { extern int freevector(), freematrix(), crout(), solve(); extern double *makevector(), **makematrix(); int i, count = 0, error, buildjacobian(), *perm; diff --git a/src/scopmath/praxis.c b/src/scopmath/praxis.c index 779fc7d17f..75d3f78f1d 100644 --- a/src/scopmath/praxis.c +++ b/src/scopmath/praxis.c @@ -1,5 +1,6 @@ #include <../../nrnconf.h> #include +#include #include #include #undef small @@ -1711,14 +1712,14 @@ integer *m, *n; goto L3; } /* maprnt_ */ -#include <../oc/mcran4.h> +double mcell_ran4_legacy(uint32_t *idx1, double *x, unsigned int n, double range); uint32_t nrn_praxis_ran_index; static doublereal random_(naught) integer *naught; { double x; - return mcell_ran4(&nrn_praxis_ran_index, &x, 1, 1.); + return mcell_ran4_legacy(&nrn_praxis_ran_index, &x, 1, 1.); #if 0 /* Initialized data */ diff --git a/src/scopmath/scoplib.h b/src/scopmath/scoplib.h index d334fd03bd..0f3382e653 100644 --- a/src/scopmath/scoplib.h +++ b/src/scopmath/scoplib.h @@ -121,7 +121,7 @@ int invert(int n, double** matrix); int crout(int n, double** a, int* perm); int solve(int n, double** a, double** b, int* perm, double* p, int* y); int tridiag(int n, double* a, double* b, double* c, double* d, double* soln); -int newton(int n, int* index, double* x, int (*pfunc)(), double* value); +int newton(int n, int* index, double* x, int(*pfunc)(), double* value); int simplex(int nparms, int* parms, double* pp, int (*pfunc)(), int* value); int buildjacobian(int n, int* index, double* x, int (*pfunc)(), double* value, double** jacobian); diff --git a/test/external/olfactory-bulb-3d/CMakeLists.txt b/test/external/olfactory-bulb-3d/CMakeLists.txt index 7c50714270..d703f215db 100644 --- a/test/external/olfactory-bulb-3d/CMakeLists.txt +++ b/test/external/olfactory-bulb-3d/CMakeLists.txt @@ -26,7 +26,8 @@ nrn_add_test( NAME neuron REQUIRES mpi python PROCESSORS ${olfactory_bulb_3d_mpi_ranks} - PRECOMMAND sed -i "s/runsim.build_part_model(.*/runsim.build_part_model([5], [])/g" bulb3dtest.py + PRECOMMAND sed -i.bak "s/runsim.build_part_model(.*/runsim.build_part_model([5], [])/g" + bulb3dtest.py COMMAND ${olfactory_bulb_3d_neuron_prefix} ${olfactory_bulb_3d_neuron_args} --tstop ${olfactory_bulb_3d_sim_time}) foreach(processor gpu cpu) @@ -46,7 +47,7 @@ foreach(processor gpu cpu) NAME coreneuron_${processor}_${mode} REQUIRES coreneuron python ${processor} PROCESSORS ${olfactory_bulb_3d_mpi_ranks} - PRECOMMAND sed -i "s/runsim.build_part_model(.*/runsim.build_part_model([5], [])/g" + PRECOMMAND sed -i.bak "s/runsim.build_part_model(.*/runsim.build_part_model([5], [])/g" bulb3dtest.py COMMAND ${olfactory_bulb_3d_neuron_prefix} ${olfactory_bulb_3d_neuron_args} --tstop