Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into neuron_nmodl_2
Browse files Browse the repository at this point in the history
  • Loading branch information
iomaganaris committed Nov 6, 2023
2 parents 3b1bc4a + 6f6db3b commit f352e04
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 13 deletions.
5 changes: 0 additions & 5 deletions share/nrnunits.lib
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ c 2.99792458+8 m/sec fuzz
g 9.80665 m/sec2
au 1.49597871+11 m fuzz
mole 6.02214076+23 fuzz
mol 1
/ mol is explicitly defined as a constant
/ with value 1 to avoid "undefined unit"
/ error with mod files that don't define
/ it themselves
e 1.602176634-19 coul fuzz
energy c2
force g
Expand Down
18 changes: 12 additions & 6 deletions src/codegen/codegen_coreneuron_cpp_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1679,7 +1679,15 @@ void CodegenCoreneuronCppVisitor::print_sdlists_init(bool print_initializers) {
if (info.primes_size == 0) {
return;
}
if (info.primes_size != info.prime_variables_by_order.size()) {
const auto count_prime_variables = [](auto size, const SymbolType& symbol) {
return size += symbol->get_length();
};
const auto prime_variables_by_order_size =
std::accumulate(info.prime_variables_by_order.begin(),
info.prime_variables_by_order.end(),
0,
count_prime_variables);
if (info.primes_size != prime_variables_by_order_size) {
throw std::runtime_error{
fmt::format("primes_size = {} differs from prime_variables_by_order.size() = {}, "
"this should not happen.",
Expand Down Expand Up @@ -2478,11 +2486,9 @@ void CodegenCoreneuronCppVisitor::print_initial_block(const InitialBlock* node)
auto lhs = get_variable_name(name);
auto rhs = get_variable_name(name + "0");
if (var->is_array()) {
printer->fmt_push_block(
"for (std::size_t arr_index = 0; arr_index < {}; ++arr_index)",
var->get_length());
printer->add_line(lhs, "[arr_index] = ", rhs, ";");
printer->pop_block();
for (int i = 0; i < var->get_length(); ++i) {
printer->fmt_line("{}[{}] = {};", lhs, i, rhs);
}
} else {
printer->fmt_line("{} = {};", lhs, rhs);
}
Expand Down
5 changes: 4 additions & 1 deletion src/visitors/defuse_analyze_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,10 +422,13 @@ DUChain DefUseAnalyzeVisitor::analyze(const ast::Ast& node, const std::string& n
visiting_lhs = false;
current_symtab = global_symtab;
unsupported_node = false;

// variable types that we try to localise: RANGE, GLOBAL and ASSIGNED
auto global_symbol_properties = NmodlType::global_var | NmodlType::range_var |
NmodlType::assigned_definition;
auto global_symbol = global_symtab->lookup_in_scope(variable_name);
// If global_symbol exists in the global_symtab then search for a global variable. Otherwise the
// variable can only be local if it exists
auto global_symbol_properties = NmodlType::global_var | NmodlType::range_var;
if (global_symbol != nullptr && global_symbol->has_any_property(global_symbol_properties)) {
variable_type = DUVariableType::Global;
} else {
Expand Down
8 changes: 7 additions & 1 deletion src/visitors/localize_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ std::vector<std::string> LocalizeVisitor::variables_to_optimize() const {
| NmodlType::nonspecific_cur_var
| NmodlType::pointer_var
| NmodlType::bbcore_pointer_var
| NmodlType::electrode_cur_var;
| NmodlType::electrode_cur_var
| NmodlType::state_var;

const NmodlType global_var_properties = NmodlType::range_var
| NmodlType::assigned_definition
Expand Down Expand Up @@ -112,13 +113,18 @@ void LocalizeVisitor::visit_program(const ast::Program& node) {
const auto& blocks = node.get_blocks();
std::map<DUState, std::vector<std::shared_ptr<ast::Node>>> block_usage;

logger->debug("LocalizeVisitor: Checking DU chains for {}", varname);

/// compute def use chains
for (const auto& block: blocks) {
if (node_for_def_use_analysis(*block)) {
DefUseAnalyzeVisitor v(*program_symtab, ignore_verbatim);
const auto& usages = v.analyze(*block, varname);
auto result = usages.eval();
block_usage[result].push_back(block);
logger->debug("\tDU chain in block {} is {}",
block->get_node_type_name(),
usages.to_string());
}
}

Expand Down
54 changes: 54 additions & 0 deletions test/unit/codegen/codegen_coreneuron_cpp_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1183,3 +1183,57 @@ SCENARIO("Check codegen for MUTEX and PROTECT", "[codegen][mutex_protect]") {
}
}
}


SCENARIO("Array STATE variable", "[codegen][array_state]") {
GIVEN("A mod file containing an array STATE variable") {
std::string const nmodl_text = R"(
DEFINE NANN 4
NEURON {
SUFFIX ca_test
}
STATE {
ca[NANN]
k
}
)";

THEN("nrn_init is printed with proper initialization of the whole array") {
auto const generated = get_coreneuron_cpp_code(nmodl_text);
std::string expected_code_init =
R"(/** initialize channel */
void nrn_init_ca_test(NrnThread* nt, Memb_list* ml, int type) {
int nodecount = ml->nodecount;
int pnodecount = ml->_nodecount_padded;
const int* node_index = ml->nodeindices;
double* data = ml->data;
const double* voltage = nt->_actual_v;
Datum* indexes = ml->pdata;
ThreadDatum* thread = ml->_thread;
setup_instance(nt, ml);
auto* const inst = static_cast<ca_test_Instance*>(ml->instance);
if (_nrn_skip_initmodel == 0) {
#pragma omp simd
#pragma ivdep
for (int id = 0; id < nodecount; id++) {
int node_id = node_index[id];
double v = voltage[node_id];
#if NRN_PRCELLSTATE
inst->v_unused[id] = v;
#endif
(inst->ca+id*4)[0] = inst->global->ca0;
(inst->ca+id*4)[1] = inst->global->ca0;
(inst->ca+id*4)[2] = inst->global->ca0;
(inst->ca+id*4)[3] = inst->global->ca0;
inst->k[id] = inst->global->k0;
}
}
})";

REQUIRE_THAT(generated, ContainsSubstring(expected_code_init));
}
}
}
29 changes: 29 additions & 0 deletions test/unit/visitor/defuse_analyze.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,35 @@ SCENARIO("Perform DefUse analysis on NMODL constructs") {
}
}

GIVEN("Simple check of assigned variables") {
const std::string nmodl_text = R"(
NEURON {
SUFFIX foo
}
ASSIGNED {
y
}
DERIVATIVE states {
y = 1
y = y + 2
}
)";

const std::string expected_text_y =
R"({"DerivativeBlock":[{"name":"D"},{"name":"U"},{"name":"D"}]})";

THEN("assigned variables are correctly analyzed") {
const std::string input = reindent_text(nmodl_text);
// Assigned variable "y" should be DU as it's defined and used as well
const auto& chains_y = run_defuse_visitor(input, "y");
REQUIRE(chains_y[0].to_string() == expected_text_y);
REQUIRE(chains_y[0].eval() == DUState::D);
}
}


GIVEN("global variable definition in if-else block") {
std::string nmodl_text = R"(
NEURON {
Expand Down

0 comments on commit f352e04

Please sign in to comment.