diff --git a/CMakeLists.txt b/CMakeLists.txt index fc9d9fb01..4b7ad757f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,7 +117,7 @@ if (ENABLE_NMODL) find_package(nmodl REQUIRED) set(MOD2C "${nmodl_BINARY}") set(NMODL_EXTRA_FLAGS "" CACHE STRING "Extra NMODL options such as passes") - separate_arguments(NMODL_EXTRA_FLAGS UNIX_COMMAND "${NMODL_EXTRA_FLAGS}") + separate_arguments(NMODL_EXTRA_FLAGS_LIST UNIX_COMMAND "${NMODL_EXTRA_FLAGS}") include_directories(${nmodl_INCLUDE}) if("$ENV{PYTHONPATH}" STREQUAL "") set(ENV{PYTHONPATH} "${nmodl_PYTHONPATH}") diff --git a/coreneuron/CMakeLists.txt b/coreneuron/CMakeLists.txt index 918bccd83..26611707d 100644 --- a/coreneuron/CMakeLists.txt +++ b/coreneuron/CMakeLists.txt @@ -113,11 +113,12 @@ macro(mod2c_target) unset(mod2c_wrapper_outname_) endif() list(APPEND MOD2C_${mod2c_KEY}_MODS "${mod2c_modname_}") - if(${NMODL_FOUND}) + if(ENABLE_NMODL AND NMODL_FOUND) add_custom_command(OUTPUT "${mod2c_output_}" "${mod2c_wrapper_output_}" DEPENDS ${mod2c_MODFILE} ${MOD2C_BINARY} COMMAND ${CMAKE_COMMAND} -E copy "${mod2c_source_}" "${CMAKE_CURRENT_BINARY_DIR}" - COMMAND ${MOD2C} "${mod2c_modname_}" -o "${CMAKE_CURRENT_BINARY_DIR}" host ${nmodl_modearg} ${NMODL_EXTRA_FLAGS} + COMMAND ${MOD2C} "${mod2c_modname_}" -o "${CMAKE_CURRENT_BINARY_DIR}" host ${nmodl_modearg} + ${NMODL_EXTRA_FLAGS_LIST} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") else() add_custom_command(OUTPUT "${mod2c_output_}" @@ -211,7 +212,7 @@ macro(mod2c_from_file name modlist searchpath) message(WARNING "Note: halfgap.mod is found in specified mechanism search directory!") else() set(GAPMOD "${PROJECT_SOURCE_DIR}/tests/integration/ring_gap/mod/halfgap.mod") - mod2c_target(KEY ${name} MODFILE "${GAPMOD}" TARGET ${M2C_TARGET}) + mod2c_target(KEY ${name} MODFILE "${GAPMOD}" TARGET ${M2C_TARGET}) list(APPEND MOD_PATHS ${GAPMOD}) message(STATUS "Adding halfgap.mod mod file for tests!") endif() @@ -403,6 +404,12 @@ set(CORENRN_LINK_LIBS "${CORENRN_LINK_LIBS}" PARENT_SCOPE) # Share built-in OPTIONAL MODS also with rest of project set(CORENRN_OPTMECH_MODS "${MOD2C_OPTMECH_MODS}" PARENT_SCOPE) +foreach(MOD ${MOD2C_OPTMECH_OUTPUTS}) + get_filename_component(OPTMECH_NAME ${MOD} NAME) + list(APPEND OPTMECH_OUTPUTS_LIST ${OPTMECH_NAME}) +endforeach() + +set(CORENRN_OPTMECH_OUTPUTS "${OPTMECH_OUTPUTS_LIST}" PARENT_SCOPE) # The scopmath lib - should not contain dimplic add_library(scopmath STATIC ${coreneuron_all_headers} ${scopmath_c_files}) @@ -443,7 +450,7 @@ install(FILES ${MOD2C_UNITS} if(ENABLE_HEADER_INSTALL) install(DIRECTORY . DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/coreneuron - FILES_MATCHING PATTERN "*.h*" PATTERN "*.ipp") + FILES_MATCHING PATTERN "*.h*" PATTERN "*.ipp" PATTERN "*.ispc") install(FILES ${KINDERIV_PY} ${MOD_FUNC_C_PL} ${DIMPLIC_C} ${ENGINEMECH_C} DESTINATION ${CMAKE_INSTALL_DATADIR}/coreneuron) diff --git a/coreneuron/nrniv/nrn_setup.cpp b/coreneuron/nrniv/nrn_setup.cpp index 0eb3c4a9b..3d6c7dc37 100644 --- a/coreneuron/nrniv/nrn_setup.cpp +++ b/coreneuron/nrniv/nrn_setup.cpp @@ -812,8 +812,8 @@ void nrn_setup(const char* filesdat, delete[] file_reader; model_size(); - delete [] gidgroups; - delete [] imult; + delete[] gidgroups; + delete[] imult; if (nrnmpi_myid == 0) { printf(" Setup Done : %.2lf seconds \n", nrn_wtime() - time); @@ -1011,7 +1011,7 @@ void nrn_cleanup(bool clean_ion_global_map) { // clean nrnthread_chkpnt if (nrnthread_chkpnt) { - delete [] nrnthread_chkpnt; + delete[] nrnthread_chkpnt; nrnthread_chkpnt = nullptr; } diff --git a/coreneuron/nrniv/output_spikes.cpp b/coreneuron/nrniv/output_spikes.cpp index 6b5128c94..3e43207d3 100644 --- a/coreneuron/nrniv/output_spikes.cpp +++ b/coreneuron/nrniv/output_spikes.cpp @@ -98,10 +98,10 @@ void local_spikevec_sort(std::vector& isvect, void sort_spikes(std::vector& spikevec_time, std::vector& spikevec_gid) { double lmin_time = std::numeric_limits::max(); double lmax_time = std::numeric_limits::min(); - if(!spikevec_time.empty()) { + if (!spikevec_time.empty()) { lmin_time = *(std::min_element(spikevec_time.begin(), spikevec_time.end())); lmax_time = *(std::max_element(spikevec_time.begin(), spikevec_time.end())); - } + } double min_time = nrnmpi_dbl_allmin(lmin_time); double max_time = nrnmpi_dbl_allmax(lmax_time); diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt index 8ab29311a..a0af5cfba 100644 --- a/extra/CMakeLists.txt +++ b/extra/CMakeLists.txt @@ -26,6 +26,7 @@ endforeach() # Additional mods string(REPLACE ";" " " CORENRN_OPTMODS "${CORENRN_OPTMECH_MODS}") +string(REPLACE ";" " " CORENRN_OPTMODS_OUTPUTS "${CORENRN_OPTMECH_OUTPUTS}") # PGI add --c++11;-A option for c++11 flag string(REPLACE ";" " " CXX11_STANDARD_COMPILE_OPTION "${CMAKE_CXX11_STANDARD_COMPILE_OPTION}") @@ -41,6 +42,15 @@ set(BUILD_TYPE_C_FLAGS "${CMAKE_C_FLAGS_${_BUILD_TYPE}}") set(BUILD_TYPE_CXX_FLAGS "${CMAKE_CXX_FLAGS_${_BUILD_TYPE}}") message("CXX Compile Flags from BUILD_TYPE: ${BUILD_TYPE_CXX_FLAGS}") +if(ENABLE_NMODL) + set(nmodl_arguments_c "host --c ${NMODL_EXTRA_FLAGS}") + set(nmodl_arguments_ispc "host --ispc ${NMODL_EXTRA_FLAGS}") + set(mod2c_install_bin "${nmodl_BINARY}") +else () + set(nmodl_arguments_c "") + set(nmodl_arguments_ispc "") + set(mod2c_install_bin "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/mod2c_core") +endif () configure_file(${nmodl_makefile}.in ${nmodl_makefile} @ONLY) diff --git a/extra/nrnivmodl-core b/extra/nrnivmodl-core index 413f36ae8..b8895c198 100755 --- a/extra/nrnivmodl-core +++ b/extra/nrnivmodl-core @@ -8,7 +8,7 @@ set -e APP_NAME=$(basename $0) _PARENT="$(dirname $BASH_SOURCE)/.." ROOTDIR=$(perl -e "use Cwd 'abs_path'; print abs_path('$_PARENT')") -MAKE_OPTIONS="MECH_NAME MECH_VERSION OUTPUT INCFLAGS LINKFLAGS MODS_PATH OPTMODS VERBOSE" +MAKE_OPTIONS="MECH_NAME MECH_VERSION OUTPUT INCFLAGS LINKFLAGS MODS_PATH OPTMODS OPTMODS_OUTPUTS VERBOSE" PARALLELISM=4 while getopts "n:v:o:i:l:p:chV" OPT; do @@ -24,7 +24,8 @@ while getopts "n:v:o:i:l:p:chV" OPT; do l) params_LINKFLAGS="$OPTARG";; c) - params_OPTMODS="";; + params_OPTMODS="" + params_OPTMODS_OUTPUTS="";; V) params_VERBOSE=1;; p) diff --git a/extra/nrnivmodl_core_makefile.in b/extra/nrnivmodl_core_makefile.in index 7d12b5f4e..9847b19d9 100644 --- a/extra/nrnivmodl_core_makefile.in +++ b/extra/nrnivmodl_core_makefile.in @@ -9,6 +9,7 @@ MECH_VERSION = 0.0 MODS_PATH = . OUTPUT = @CMAKE_HOST_SYSTEM_PROCESSOR@ OPTMODS = @CORENRN_OPTMODS@ +OPTMODS_OUTPUTS = @CORENRN_OPTMODS_OUTPUTS@ DESTDIR = # Coreneuron dirs @@ -18,6 +19,9 @@ incdir := @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@ datadir:= @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_DATADIR@/coreneuron datadir_mod2c := @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_DATADIR@/mod2c +# Binary of MOD2C/NMODL depending on what was activated +mod2c_install_bin := @mod2c_install_bin@ + # Additional variables set in CMAKE usable here # - @CORENRN_COMPILE_DEFS # - @CORENRN_LINK_DEFS @@ -41,13 +45,45 @@ CXXCOMPILE = $(CXX) $(CXXFLAGS) @CORENRN_COMPILE_DEFS@ $(INCLUDES) CXX_LINK_EXE = $(CXX) $(CXXFLAGS) @CMAKE_EXE_LINKER_FLAGS@ CXX_LINK_SHARED = $(CXX) $(CXXFLAGS) @CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS@ @CMAKE_SHARED_LIBRARY_CXX_FLAGS@ @CMAKE_SHARED_LINKER_FLAGS@ +ISPC = @CMAKE_ISPC_COMPILER@ +ISPC_FLAGS = @CMAKE_ISPC_FLAGS@ +ISPC_COMPILE = $(ISPC) $(ISPC_FLAGS) -I$(incdir) -I@nmodl_INCLUDE@ + +# Variables used in the "ARTIFICIAL_CELL" detection +mod_c_srcs_path = +mod_ispc_srcs_path = +mod_c_srcs_names = +mod_ispc_srcs_names = +define check_file + ifeq (@ENABLE_ISPC_TARGET@, ON) + ifeq ($(shell grep -q $(2) $(1); echo $$?), 0) + mod_c_srcs_path += $(MODC_DIR)/$(notdir $(1)) + mod_c_srcs_names += $(notdir $(1)) + else + mod_ispc_srcs_path += $(MODC_DIR)/$(notdir $(1)) + mod_ispc_srcs_names += $(notdir $(1)) + endif + else + mod_c_srcs_path += $(MODC_DIR)/$(notdir $(1)) + mod_c_srcs_names += $(notdir $(1)) + endif +endef + # File path config (internal) MODC_DIR = $(OUTPUT)/core/mod2c OBJS_DIR = $(OUTPUT)/core/build mod_files = $(sort $(notdir $(wildcard $(MODS_PATH)/*.mod))) +mod_paths = $(sort $(wildcard $(MODS_PATH)/*.mod)) mod_names = $(mod_files:.mod=) $(OPTMODS:.mod=) -modc_files = $(addprefix $(MODC_DIR)/,$(addsuffix .cpp,$(mod_names))) -mod_objs = $(addprefix $(OBJS_DIR)/,$(addsuffix .o,$(mod_names))) +mod_all_cpp_files = $(addprefix $(MODC_DIR)/,$(addsuffix .cpp,$(mod_names))) +mod_c_objs = $(addprefix $(OBJS_DIR)/,$(addsuffix .o,$(basename $(mod_c_srcs_names)))) $(addprefix $(OBJS_DIR)/,$(addsuffix .o,$(basename $(filter %.cpp, $(OPTMODS_OUTPUTS))))) +mod_ispc_objs = $(addprefix $(OBJS_DIR)/,$(addsuffix .obj,$(basename $(mod_ispc_srcs_names)))) $(addprefix $(OBJS_DIR)/,$(addsuffix .obj,$(basename $(filter %.ispc, $(OPTMODS_OUTPUTS))))) + +$(foreach ittxtfile, $(mod_paths), $(eval $(call check_file, $(ittxtfile), ARTIFICIAL_CELL))) + +mod_c_files = $(patsubst %.mod,%.cpp,$(mod_c_srcs_path)) +mod_ispc_files = $(patsubst %.mod,%.ispc,$(mod_ispc_srcs_path)) +mod_ispc_c_files = $(patsubst %.mod,%.cpp,$(mod_ispc_srcs_path)) kinderiv_h = $(MODC_DIR)/_kinderiv.h mod_func_o = $(OBJS_DIR)/_mod_func.o @@ -80,27 +116,42 @@ $(special): $(coremech_lib) -L $(OUTPUT) -l$(coremech_libname) $(CORENRNLIB_FLAGS) -Wl,-rpath,'$(DESTDIR_RPATH)' -Wl,-rpath,$(libdir) $(LDFLAGS) -$(coremech_lib): $(mod_func_o) $(dimplic_o) $(mod_objs) build_always +$(coremech_lib): $(mod_func_o) $(dimplic_o) $(mod_c_objs) $(mod_ispc_objs) build_always @printf " => $(C_GREEN)LINKING$(C_RESET) library $(coremech_lib) Mod files: $(mod_files) (+ $(OPTMODS))\n" $(CXX_LINK_SHARED) -I $(incdir) -DADDITIONAL_MECHS $(datadir)/enginemech.cpp -o ${coremech_lib} ${_SONAME} \ - $(mod_func_o) $(dimplic_o) $(mod_objs) $(datadir)/libscopmath.a $(CORENRNLIB_FLAGS) -Wl,-rpath,$(libdir) $(LDFLAGS) + $(mod_func_o) $(dimplic_o) $(mod_c_objs) $(mod_ispc_objs) $(datadir)/libscopmath.a $(CORENRNLIB_FLAGS) -Wl,-rpath,$(libdir) $(LDFLAGS) -# Generic build cpp->o. Need PIC for shared lib +# Generic build cpp->.o Need PIC for shared lib $(OBJS_DIR)/%.o: $(MODC_DIR)/%.cpp $(kinderiv_h) | $(OBJS_DIR) @printf " -> $(C_GREEN)Compiling$(C_RESET) $<\n" $(CXXCOMPILE) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c $< -o $@ +# Generic build ispc->.obj Need PIC for shared lib +$(OBJS_DIR)/%.obj: $(MODC_DIR)/%.ispc | $(OBJS_DIR) + @printf " -> $(C_GREEN)Compiling with ISPC$(C_RESET) $<\n" + $(ISPC_COMPILE) @CMAKE_ISPC_COMPILE_OPTIONS_PIC@ $< -o $@ -# Build cpp files with mod2c -$(MODC_DIR)/%.cpp: $(MODS_PATH)/%.mod | $(MODC_DIR) +# Build ispc files with mod2c/nmodl +$(mod_ispc_files): $(MODC_DIR)/%.ispc: $(MODS_PATH)/%.mod | $(MODC_DIR) @printf " -> $(C_GREEN)MOD2C$(C_RESET) $<\n" MODLUNIT=$(datadir_mod2c)/nrnunits.lib \ - $(bindir)/mod2c_core $< -o $(MODC_DIR)/ + $(mod2c_install_bin) $< -o $(MODC_DIR)/ @nmodl_arguments_ispc@ + +# Static pattern to set up the dependencies for the previous recipe. +$(mod_ispc_c_files): $(MODC_DIR)/%.cpp: $(MODC_DIR)/%.ispc + +# Build cpp files with mod2c/nmodl +$(mod_c_files): $(MODC_DIR)/%.cpp: $(MODS_PATH)/%.mod | $(MODC_DIR) + @printf " -> $(C_GREEN)MOD2C$(C_RESET) $<\n" + MODLUNIT=$(datadir_mod2c)/nrnunits.lib \ + $(mod2c_install_bin) $< -o $(MODC_DIR)/ @nmodl_arguments_c@ # If .mod doesnt exist attempt from previously built opt mods in shared/ $(MODC_DIR)/%.cpp: $(datadir_mod2c)/%.cpp | $(MODC_DIR) ln -s $< $@ +$(MODC_DIR)/%.ispc: $(datadir_mod2c)/%.ispc | $(MODC_DIR) + ln -s $< $@ # Mod registration. Compiled by generic rule. Dont overwrite if not changed @@ -112,10 +163,10 @@ $(mod_func_c): build_always | $(MODC_DIR) # Header to avoid function callbacks using function pointers # Move all mods to temp and bring back only those required -$(kinderiv_h): $(modc_files) build_always | $(MODC_DIR) +$(kinderiv_h): $(mod_all_cpp_files) build_always | $(MODC_DIR) @printf " -> $(C_GREEN)Generating$(C_RESET) $(kinderiv_h)\n" cd $(MODC_DIR) && mkdir -p _tmp && mv [^_]*.cpp _tmp/ && \ - mv $(addprefix _tmp/,$(notdir $(modc_files))) ./ || true + mv $(addprefix _tmp/,$(notdir $(mod_all_cpp_files))) ./ || true rm -rf $(MODC_DIR)/_tmp cd $(MODC_DIR) && python $(datadir)/kinderiv.py