Skip to content
This repository was archived by the owner on Mar 20, 2023. It is now read-only.

Commit 0cfa056

Browse files
st4rl3sspramodk
authored andcommitted
NMODL integration in CoreNeuron nrnivmodl-core workflow (#193)
This PR is to allow us use NMODL with CoreNEURON using nrnivmodl-core workflow: * nmodl support for nrnivmodl-core * Added support for ispc workflow. * Fixed ispc support for halfgap.mod * Fixes nrnivmodl-core not correctly setting the OPTMODS_OUTPUTS variable in the Makefile when running on a clean run
1 parent 8d962da commit 0cfa056

File tree

7 files changed

+91
-22
lines changed

7 files changed

+91
-22
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ if (ENABLE_NMODL)
117117
find_package(nmodl REQUIRED)
118118
set(MOD2C "${nmodl_BINARY}")
119119
set(NMODL_EXTRA_FLAGS "" CACHE STRING "Extra NMODL options such as passes")
120-
separate_arguments(NMODL_EXTRA_FLAGS UNIX_COMMAND "${NMODL_EXTRA_FLAGS}")
120+
separate_arguments(NMODL_EXTRA_FLAGS_LIST UNIX_COMMAND "${NMODL_EXTRA_FLAGS}")
121121
include_directories(${nmodl_INCLUDE})
122122
if("$ENV{PYTHONPATH}" STREQUAL "")
123123
set(ENV{PYTHONPATH} "${nmodl_PYTHONPATH}")

coreneuron/CMakeLists.txt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,12 @@ macro(mod2c_target)
113113
unset(mod2c_wrapper_outname_)
114114
endif()
115115
list(APPEND MOD2C_${mod2c_KEY}_MODS "${mod2c_modname_}")
116-
if(${NMODL_FOUND})
116+
if(ENABLE_NMODL AND NMODL_FOUND)
117117
add_custom_command(OUTPUT "${mod2c_output_}" "${mod2c_wrapper_output_}"
118118
DEPENDS ${mod2c_MODFILE} ${MOD2C_BINARY}
119119
COMMAND ${CMAKE_COMMAND} -E copy "${mod2c_source_}" "${CMAKE_CURRENT_BINARY_DIR}"
120-
COMMAND ${MOD2C} "${mod2c_modname_}" -o "${CMAKE_CURRENT_BINARY_DIR}" host ${nmodl_modearg} ${NMODL_EXTRA_FLAGS}
120+
COMMAND ${MOD2C} "${mod2c_modname_}" -o "${CMAKE_CURRENT_BINARY_DIR}" host ${nmodl_modearg}
121+
${NMODL_EXTRA_FLAGS_LIST}
121122
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
122123
else()
123124
add_custom_command(OUTPUT "${mod2c_output_}"
@@ -211,7 +212,7 @@ macro(mod2c_from_file name modlist searchpath)
211212
message(WARNING "Note: halfgap.mod is found in specified mechanism search directory!")
212213
else()
213214
set(GAPMOD "${PROJECT_SOURCE_DIR}/tests/integration/ring_gap/mod/halfgap.mod")
214-
mod2c_target(KEY ${name} MODFILE "${GAPMOD}" TARGET ${M2C_TARGET})
215+
mod2c_target(KEY ${name} MODFILE "${GAPMOD}" TARGET ${M2C_TARGET})
215216
list(APPEND MOD_PATHS ${GAPMOD})
216217
message(STATUS "Adding halfgap.mod mod file for tests!")
217218
endif()
@@ -403,6 +404,12 @@ set(CORENRN_LINK_LIBS "${CORENRN_LINK_LIBS}" PARENT_SCOPE)
403404
# Share built-in OPTIONAL MODS also with rest of project
404405
set(CORENRN_OPTMECH_MODS "${MOD2C_OPTMECH_MODS}" PARENT_SCOPE)
405406

407+
foreach(MOD ${MOD2C_OPTMECH_OUTPUTS})
408+
get_filename_component(OPTMECH_NAME ${MOD} NAME)
409+
list(APPEND OPTMECH_OUTPUTS_LIST ${OPTMECH_NAME})
410+
endforeach()
411+
412+
set(CORENRN_OPTMECH_OUTPUTS "${OPTMECH_OUTPUTS_LIST}" PARENT_SCOPE)
406413

407414
# The scopmath lib - should not contain dimplic
408415
add_library(scopmath STATIC ${coreneuron_all_headers} ${scopmath_c_files})
@@ -443,7 +450,7 @@ install(FILES ${MOD2C_UNITS}
443450
if(ENABLE_HEADER_INSTALL)
444451
install(DIRECTORY .
445452
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/coreneuron
446-
FILES_MATCHING PATTERN "*.h*" PATTERN "*.ipp")
453+
FILES_MATCHING PATTERN "*.h*" PATTERN "*.ipp" PATTERN "*.ispc")
447454

448455
install(FILES ${KINDERIV_PY} ${MOD_FUNC_C_PL} ${DIMPLIC_C} ${ENGINEMECH_C}
449456
DESTINATION ${CMAKE_INSTALL_DATADIR}/coreneuron)

coreneuron/nrniv/nrn_setup.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -812,8 +812,8 @@ void nrn_setup(const char* filesdat,
812812
delete[] file_reader;
813813

814814
model_size();
815-
delete [] gidgroups;
816-
delete [] imult;
815+
delete[] gidgroups;
816+
delete[] imult;
817817

818818
if (nrnmpi_myid == 0) {
819819
printf(" Setup Done : %.2lf seconds \n", nrn_wtime() - time);
@@ -1011,7 +1011,7 @@ void nrn_cleanup(bool clean_ion_global_map) {
10111011

10121012
// clean nrnthread_chkpnt
10131013
if (nrnthread_chkpnt) {
1014-
delete [] nrnthread_chkpnt;
1014+
delete[] nrnthread_chkpnt;
10151015
nrnthread_chkpnt = nullptr;
10161016
}
10171017

coreneuron/nrniv/output_spikes.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ void local_spikevec_sort(std::vector<double>& isvect,
9898
void sort_spikes(std::vector<double>& spikevec_time, std::vector<int>& spikevec_gid) {
9999
double lmin_time = std::numeric_limits<double>::max();
100100
double lmax_time = std::numeric_limits<double>::min();
101-
if(!spikevec_time.empty()) {
101+
if (!spikevec_time.empty()) {
102102
lmin_time = *(std::min_element(spikevec_time.begin(), spikevec_time.end()));
103103
lmax_time = *(std::max_element(spikevec_time.begin(), spikevec_time.end()));
104-
}
104+
}
105105
double min_time = nrnmpi_dbl_allmin(lmin_time);
106106
double max_time = nrnmpi_dbl_allmax(lmax_time);
107107

extra/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ endforeach()
2626

2727
# Additional mods
2828
string(REPLACE ";" " " CORENRN_OPTMODS "${CORENRN_OPTMECH_MODS}")
29+
string(REPLACE ";" " " CORENRN_OPTMODS_OUTPUTS "${CORENRN_OPTMECH_OUTPUTS}")
2930

3031
# PGI add --c++11;-A option for c++11 flag
3132
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}}")
4142
set(BUILD_TYPE_CXX_FLAGS "${CMAKE_CXX_FLAGS_${_BUILD_TYPE}}")
4243
message("CXX Compile Flags from BUILD_TYPE: ${BUILD_TYPE_CXX_FLAGS}")
4344

45+
if(ENABLE_NMODL)
46+
set(nmodl_arguments_c "host --c ${NMODL_EXTRA_FLAGS}")
47+
set(nmodl_arguments_ispc "host --ispc ${NMODL_EXTRA_FLAGS}")
48+
set(mod2c_install_bin "${nmodl_BINARY}")
49+
else ()
50+
set(nmodl_arguments_c "")
51+
set(nmodl_arguments_ispc "")
52+
set(mod2c_install_bin "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/mod2c_core")
53+
endif ()
4454

4555
configure_file(${nmodl_makefile}.in ${nmodl_makefile} @ONLY)
4656

extra/nrnivmodl-core

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ set -e
88
APP_NAME=$(basename $0)
99
_PARENT="$(dirname $BASH_SOURCE)/.."
1010
ROOTDIR=$(perl -e "use Cwd 'abs_path'; print abs_path('$_PARENT')")
11-
MAKE_OPTIONS="MECH_NAME MECH_VERSION OUTPUT INCFLAGS LINKFLAGS MODS_PATH OPTMODS VERBOSE"
11+
MAKE_OPTIONS="MECH_NAME MECH_VERSION OUTPUT INCFLAGS LINKFLAGS MODS_PATH OPTMODS OPTMODS_OUTPUTS VERBOSE"
1212
PARALLELISM=4
1313

1414
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
2424
l)
2525
params_LINKFLAGS="$OPTARG";;
2626
c)
27-
params_OPTMODS="";;
27+
params_OPTMODS=""
28+
params_OPTMODS_OUTPUTS="";;
2829
V)
2930
params_VERBOSE=1;;
3031
p)

extra/nrnivmodl_core_makefile.in

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ MECH_VERSION = 0.0
99
MODS_PATH = .
1010
OUTPUT = @CMAKE_HOST_SYSTEM_PROCESSOR@
1111
OPTMODS = @CORENRN_OPTMODS@
12+
OPTMODS_OUTPUTS = @CORENRN_OPTMODS_OUTPUTS@
1213
DESTDIR =
1314

1415
# Coreneuron dirs
@@ -18,6 +19,9 @@ incdir := @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@
1819
datadir:= @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_DATADIR@/coreneuron
1920
datadir_mod2c := @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_DATADIR@/mod2c
2021

22+
# Binary of MOD2C/NMODL depending on what was activated
23+
mod2c_install_bin := @mod2c_install_bin@
24+
2125
# Additional variables set in CMAKE usable here
2226
# - @CORENRN_COMPILE_DEFS
2327
# - @CORENRN_LINK_DEFS
@@ -41,13 +45,45 @@ CXXCOMPILE = $(CXX) $(CXXFLAGS) @CORENRN_COMPILE_DEFS@ $(INCLUDES)
4145
CXX_LINK_EXE = $(CXX) $(CXXFLAGS) @CMAKE_EXE_LINKER_FLAGS@
4246
CXX_LINK_SHARED = $(CXX) $(CXXFLAGS) @CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS@ @CMAKE_SHARED_LIBRARY_CXX_FLAGS@ @CMAKE_SHARED_LINKER_FLAGS@
4347

48+
ISPC = @CMAKE_ISPC_COMPILER@
49+
ISPC_FLAGS = @CMAKE_ISPC_FLAGS@
50+
ISPC_COMPILE = $(ISPC) $(ISPC_FLAGS) -I$(incdir) -I@nmodl_INCLUDE@
51+
52+
# Variables used in the "ARTIFICIAL_CELL" detection
53+
mod_c_srcs_path =
54+
mod_ispc_srcs_path =
55+
mod_c_srcs_names =
56+
mod_ispc_srcs_names =
57+
define check_file
58+
ifeq (@ENABLE_ISPC_TARGET@, ON)
59+
ifeq ($(shell grep -q $(2) $(1); echo $$?), 0)
60+
mod_c_srcs_path += $(MODC_DIR)/$(notdir $(1))
61+
mod_c_srcs_names += $(notdir $(1))
62+
else
63+
mod_ispc_srcs_path += $(MODC_DIR)/$(notdir $(1))
64+
mod_ispc_srcs_names += $(notdir $(1))
65+
endif
66+
else
67+
mod_c_srcs_path += $(MODC_DIR)/$(notdir $(1))
68+
mod_c_srcs_names += $(notdir $(1))
69+
endif
70+
endef
71+
4472
# File path config (internal)
4573
MODC_DIR = $(OUTPUT)/core/mod2c
4674
OBJS_DIR = $(OUTPUT)/core/build
4775
mod_files = $(sort $(notdir $(wildcard $(MODS_PATH)/*.mod)))
76+
mod_paths = $(sort $(wildcard $(MODS_PATH)/*.mod))
4877
mod_names = $(mod_files:.mod=) $(OPTMODS:.mod=)
49-
modc_files = $(addprefix $(MODC_DIR)/,$(addsuffix .cpp,$(mod_names)))
50-
mod_objs = $(addprefix $(OBJS_DIR)/,$(addsuffix .o,$(mod_names)))
78+
mod_all_cpp_files = $(addprefix $(MODC_DIR)/,$(addsuffix .cpp,$(mod_names)))
79+
mod_c_objs = $(addprefix $(OBJS_DIR)/,$(addsuffix .o,$(basename $(mod_c_srcs_names)))) $(addprefix $(OBJS_DIR)/,$(addsuffix .o,$(basename $(filter %.cpp, $(OPTMODS_OUTPUTS)))))
80+
mod_ispc_objs = $(addprefix $(OBJS_DIR)/,$(addsuffix .obj,$(basename $(mod_ispc_srcs_names)))) $(addprefix $(OBJS_DIR)/,$(addsuffix .obj,$(basename $(filter %.ispc, $(OPTMODS_OUTPUTS)))))
81+
82+
$(foreach ittxtfile, $(mod_paths), $(eval $(call check_file, $(ittxtfile), ARTIFICIAL_CELL)))
83+
84+
mod_c_files = $(patsubst %.mod,%.cpp,$(mod_c_srcs_path))
85+
mod_ispc_files = $(patsubst %.mod,%.ispc,$(mod_ispc_srcs_path))
86+
mod_ispc_c_files = $(patsubst %.mod,%.cpp,$(mod_ispc_srcs_path))
5187

5288
kinderiv_h = $(MODC_DIR)/_kinderiv.h
5389
mod_func_o = $(OBJS_DIR)/_mod_func.o
@@ -80,27 +116,42 @@ $(special): $(coremech_lib)
80116
-L $(OUTPUT) -l$(coremech_libname) $(CORENRNLIB_FLAGS) -Wl,-rpath,'$(DESTDIR_RPATH)' -Wl,-rpath,$(libdir) $(LDFLAGS)
81117

82118

83-
$(coremech_lib): $(mod_func_o) $(dimplic_o) $(mod_objs) build_always
119+
$(coremech_lib): $(mod_func_o) $(dimplic_o) $(mod_c_objs) $(mod_ispc_objs) build_always
84120
@printf " => $(C_GREEN)LINKING$(C_RESET) library $(coremech_lib) Mod files: $(mod_files) (+ $(OPTMODS))\n"
85121
$(CXX_LINK_SHARED) -I $(incdir) -DADDITIONAL_MECHS $(datadir)/enginemech.cpp -o ${coremech_lib} ${_SONAME} \
86-
$(mod_func_o) $(dimplic_o) $(mod_objs) $(datadir)/libscopmath.a $(CORENRNLIB_FLAGS) -Wl,-rpath,$(libdir) $(LDFLAGS)
122+
$(mod_func_o) $(dimplic_o) $(mod_c_objs) $(mod_ispc_objs) $(datadir)/libscopmath.a $(CORENRNLIB_FLAGS) -Wl,-rpath,$(libdir) $(LDFLAGS)
87123

88124

89-
# Generic build cpp->o. Need PIC for shared lib
125+
# Generic build cpp->.o Need PIC for shared lib
90126
$(OBJS_DIR)/%.o: $(MODC_DIR)/%.cpp $(kinderiv_h) | $(OBJS_DIR)
91127
@printf " -> $(C_GREEN)Compiling$(C_RESET) $<\n"
92128
$(CXXCOMPILE) @CMAKE_CXX_COMPILE_OPTIONS_PIC@ -c $< -o $@
93129

130+
# Generic build ispc->.obj Need PIC for shared lib
131+
$(OBJS_DIR)/%.obj: $(MODC_DIR)/%.ispc | $(OBJS_DIR)
132+
@printf " -> $(C_GREEN)Compiling with ISPC$(C_RESET) $<\n"
133+
$(ISPC_COMPILE) @CMAKE_ISPC_COMPILE_OPTIONS_PIC@ $< -o $@
94134

95-
# Build cpp files with mod2c
96-
$(MODC_DIR)/%.cpp: $(MODS_PATH)/%.mod | $(MODC_DIR)
135+
# Build ispc files with mod2c/nmodl
136+
$(mod_ispc_files): $(MODC_DIR)/%.ispc: $(MODS_PATH)/%.mod | $(MODC_DIR)
97137
@printf " -> $(C_GREEN)MOD2C$(C_RESET) $<\n"
98138
MODLUNIT=$(datadir_mod2c)/nrnunits.lib \
99-
$(bindir)/mod2c_core $< -o $(MODC_DIR)/
139+
$(mod2c_install_bin) $< -o $(MODC_DIR)/ @nmodl_arguments_ispc@
140+
141+
# Static pattern to set up the dependencies for the previous recipe.
142+
$(mod_ispc_c_files): $(MODC_DIR)/%.cpp: $(MODC_DIR)/%.ispc
143+
144+
# Build cpp files with mod2c/nmodl
145+
$(mod_c_files): $(MODC_DIR)/%.cpp: $(MODS_PATH)/%.mod | $(MODC_DIR)
146+
@printf " -> $(C_GREEN)MOD2C$(C_RESET) $<\n"
147+
MODLUNIT=$(datadir_mod2c)/nrnunits.lib \
148+
$(mod2c_install_bin) $< -o $(MODC_DIR)/ @nmodl_arguments_c@
100149

101150
# If .mod doesnt exist attempt from previously built opt mods in shared/
102151
$(MODC_DIR)/%.cpp: $(datadir_mod2c)/%.cpp | $(MODC_DIR)
103152
ln -s $< $@
153+
$(MODC_DIR)/%.ispc: $(datadir_mod2c)/%.ispc | $(MODC_DIR)
154+
ln -s $< $@
104155

105156

106157
# Mod registration. Compiled by generic rule. Dont overwrite if not changed
@@ -112,10 +163,10 @@ $(mod_func_c): build_always | $(MODC_DIR)
112163

113164
# Header to avoid function callbacks using function pointers
114165
# Move all mods to temp and bring back only those required
115-
$(kinderiv_h): $(modc_files) build_always | $(MODC_DIR)
166+
$(kinderiv_h): $(mod_all_cpp_files) build_always | $(MODC_DIR)
116167
@printf " -> $(C_GREEN)Generating$(C_RESET) $(kinderiv_h)\n"
117168
cd $(MODC_DIR) && mkdir -p _tmp && mv [^_]*.cpp _tmp/ && \
118-
mv $(addprefix _tmp/,$(notdir $(modc_files))) ./ || true
169+
mv $(addprefix _tmp/,$(notdir $(mod_all_cpp_files))) ./ || true
119170
rm -rf $(MODC_DIR)/_tmp
120171
cd $(MODC_DIR) && python $(datadir)/kinderiv.py
121172

0 commit comments

Comments
 (0)