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

Commit

Permalink
NMODL integration in CoreNeuron nrnivmodl-core workflow (#193)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
st4rl3ss authored and pramodk committed Oct 2, 2019
1 parent 8d962da commit 0cfa056
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 22 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}")
Expand Down
15 changes: 11 additions & 4 deletions coreneuron/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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_}"
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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})
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions coreneuron/nrniv/nrn_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions coreneuron/nrniv/output_spikes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ void local_spikevec_sort(std::vector<double>& isvect,
void sort_spikes(std::vector<double>& spikevec_time, std::vector<int>& spikevec_gid) {
double lmin_time = std::numeric_limits<double>::max();
double lmax_time = std::numeric_limits<double>::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);

Expand Down
10 changes: 10 additions & 0 deletions extra/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}")
Expand All @@ -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)

Expand Down
5 changes: 3 additions & 2 deletions extra/nrnivmodl-core
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
71 changes: 61 additions & 10 deletions extra/nrnivmodl_core_makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down

0 comments on commit 0cfa056

Please sign in to comment.