diff --git a/CMakeLists.txt b/CMakeLists.txt index bb59cb4ff..9c88dc4e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,6 +161,7 @@ endif() # ============================================================================= message(STATUS "CHECKING FOR PYTHON") find_package(PythonInterp 3.8 REQUIRED) +cpp_cc_strip_python_shims(EXECUTABLE "${PYTHON_EXECUTABLE}" OUTPUT PYTHON_EXECUTABLE) include(cmake/hpc-coding-conventions/cpp/cmake/bbp-find-python-module.cmake) cpp_cc_find_python_module(jinja2 2.9.3 REQUIRED) cpp_cc_find_python_module(pytest 3.3.0 REQUIRED) diff --git a/src/codegen/codegen_cpp_visitor.cpp b/src/codegen/codegen_cpp_visitor.cpp index 84288f070..056042e5a 100644 --- a/src/codegen/codegen_cpp_visitor.cpp +++ b/src/codegen/codegen_cpp_visitor.cpp @@ -598,6 +598,10 @@ std::vector CodegenCVisitor::ion_read_statements(BlockType type) { for (const auto& ion: info.ions) { auto name = ion.name; for (const auto& var: ion.reads) { + auto const iter = std::find(ion.implicit_reads.begin(), ion.implicit_reads.end(), var); + if (iter != ion.implicit_reads.end()) { + continue; + } auto variable_names = read_ion_variable_name(var); auto first = get_variable_name(variable_names.first); auto second = get_variable_name(variable_names.second); @@ -776,6 +780,7 @@ void CodegenCVisitor::update_index_semantics() { } } if (ion.need_style) { + info.semantics.emplace_back(index++, fmt::format("{}_ion", ion.name), 1); info.semantics.emplace_back(index++, fmt::format("#{}_ion", ion.name), 1); } } @@ -900,11 +905,28 @@ std::vector CodegenCVisitor::get_int_variables() { } } - for (const auto& ion: info.ions) { + for (auto& ion: info.ions) { bool need_style = false; std::unordered_map ion_vars; // used to keep track of the variables to // not have doubles between read/write. Same // name variables are allowed + // See if we need to add extra readion statements to match NEURON with SoA data + auto const has_var = [&ion](const char* suffix) -> bool { + auto const pred = [name = ion.name + suffix](auto const& x) { return x == name; }; + return std::any_of(ion.reads.begin(), ion.reads.end(), pred) || + std::any_of(ion.writes.begin(), ion.writes.end(), pred); + }; + auto const add_implicit_read = [&ion](const char* suffix) { + auto name = ion.name + suffix; + ion.reads.push_back(name); + ion.implicit_reads.push_back(std::move(name)); + }; + bool const have_ionin{has_var("i")}, have_ionout{has_var("o")}; + if (have_ionin && !have_ionout) { + add_implicit_read("o"); + } else if (have_ionout && !have_ionin) { + add_implicit_read("i"); + } for (const auto& var: ion.reads) { const std::string name = naming::ION_VARNAME_PREFIX + var; variables.emplace_back(make_symbol(name)); @@ -939,6 +961,7 @@ std::vector CodegenCVisitor::get_int_variables() { } if (need_style) { + variables.emplace_back(make_symbol(naming::ION_VARNAME_PREFIX + ion.name + "_erev")); variables.emplace_back(make_symbol("style_" + ion.name), false, true); variables.back().is_constant = true; } @@ -4296,7 +4319,7 @@ void CodegenCVisitor::print_nrn_state() { print_global_function_common_code(BlockType::State); print_channel_iteration_block_parallel_hint(BlockType::State, info.nrn_state_block); printer->start_block("for (int id = 0; id < nodecount; id++)"); - + printer->add_line("int node_id = node_index[id];"); printer->add_line("double v = voltage[node_id];"); print_v_unused(); diff --git a/src/codegen/codegen_info.hpp b/src/codegen/codegen_info.hpp index 3602fbfa8..af41ffffe 100644 --- a/src/codegen/codegen_info.hpp +++ b/src/codegen/codegen_info.hpp @@ -51,6 +51,9 @@ struct Ion { /// ion variables that are being read std::vector reads; + /// ion variables that are being implicitly read + std::vector implicit_reads; + /// ion variables that are being written std::vector writes; diff --git a/test/unit/codegen/codegen_cpp_visitor.cpp b/test/unit/codegen/codegen_cpp_visitor.cpp index 80cb62334..9a41b4a41 100644 --- a/test/unit/codegen/codegen_cpp_visitor.cpp +++ b/test/unit/codegen/codegen_cpp_visitor.cpp @@ -214,7 +214,8 @@ SCENARIO("Check instance variable definition order", "[codegen][var_order]") { SUFFIX ccanl USEION nca READ ncai, inca, enca WRITE enca, ncai VALENCE 2 USEION lca READ lcai, ilca, elca WRITE elca, lcai VALENCE 2 - RANGE caiinf, catau, cai, ncai, lcai, eca, elca, enca, g + USEION k WRITE ko + RANGE caiinf, catau, cai, ncai, lcai, eca, elca, enca, g, ko } UNITS { FARADAY = 96520(coul) @@ -236,6 +237,7 @@ SCENARIO("Check instance variable definition order", "[codegen][var_order]") { elca(mV) eca(mV) g(S/cm2) + ko(mA / cm2) } STATE { ncai(mM) @@ -266,18 +268,27 @@ SCENARIO("Check instance variable definition order", "[codegen][var_order]") { inst->ilca = ml->data+7*pnodecount; inst->enca = ml->data+8*pnodecount; inst->elca = ml->data+9*pnodecount; - inst->ncai = ml->data+10*pnodecount; - inst->Dncai = ml->data+11*pnodecount; - inst->lcai = ml->data+12*pnodecount; - inst->Dlcai = ml->data+13*pnodecount; + inst->ko = ml->data+10*pnodecount; + inst->ncai = ml->data+11*pnodecount; + inst->Dncai = ml->data+12*pnodecount; + inst->lcai = ml->data+13*pnodecount; + inst->Dlcai = ml->data+14*pnodecount; inst->ion_ncai = nt->_data; inst->ion_inca = nt->_data; inst->ion_enca = nt->_data; + inst->ion_ncao = nt->_data; + inst->ion_nca_erev = nt->_data; inst->style_nca = ml->pdata; inst->ion_lcai = nt->_data; inst->ion_ilca = nt->_data; inst->ion_elca = nt->_data; + inst->ion_lcao = nt->_data; + inst->ion_lca_erev = nt->_data; inst->style_lca = ml->pdata; + inst->ion_ki = nt->_data; + inst->ion_ko = nt->_data; + inst->ion_k_erev = nt->_data; + inst->style_k = ml->pdata; } )";