Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable trivial cases of global state variables. #1130

Merged
merged 2 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 79 additions & 7 deletions src/codegen/codegen_neuron_cpp_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,13 @@
}


/// TODO: Edit for NEURON
std::string CodegenNeuronCppVisitor::global_variable_name(const SymbolType& symbol,
bool use_instance) const {
return symbol->get_name();
if (use_instance) {
return fmt::format("inst.{}->{}", naming::INST_GLOBAL_MEMBER, symbol->get_name());

Check warning on line 231 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L230-L231

Added lines #L230 - L231 were not covered by tests
} else {
return fmt::format("{}.{}", global_struct_instance(), symbol->get_name());

Check warning on line 233 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L233

Added line #L233 was not covered by tests
}
}


Expand Down Expand Up @@ -391,6 +394,8 @@


void CodegenNeuronCppVisitor::print_mechanism_global_var_structure(bool print_initializers) {
const auto value_initialize = print_initializers ? "{}" : "";

/// TODO: Print only global variables printed in NEURON
printer->add_newline(2);
printer->add_line("/* NEURON global variables */");
Expand All @@ -405,6 +410,73 @@
info.pointer_variables.size() > 0
? static_cast<int>(info.pointer_variables.size())
: -1);

// Start printing the CNRN-style global variables.
auto float_type = default_float_data_type();
printer->add_newline(2);
printer->add_line("/** all global variables */");
printer->fmt_push_block("struct {}", global_struct());

if (!info.ions.empty()) {
// TODO implement these when needed.
}

if (info.point_process) {
throw std::runtime_error("Not implemented, global point process.");

Check warning on line 425 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L425

Added line #L425 was not covered by tests
}

if (!info.vectorize && !info.top_local_variables.empty()) {
throw std::runtime_error("Not implemented, global vectorize something.");

Check warning on line 429 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L429

Added line #L429 was not covered by tests
}

if (!info.thread_variables.empty()) {
throw std::runtime_error("Not implemented, global thread variables.");

Check warning on line 433 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L433

Added line #L433 was not covered by tests
}

if (info.table_count > 0) {
throw std::runtime_error("Not implemented, global table count.");

Check warning on line 437 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L437

Added line #L437 was not covered by tests
}

for (const auto& var: info.state_vars) {
iomaganaris marked this conversation as resolved.
Show resolved Hide resolved
auto name = var->get_name() + "0";
auto symbol = program_symtab->lookup(name);
if (symbol == nullptr) {
1uc marked this conversation as resolved.
Show resolved Hide resolved
printer->fmt_line("{} {}{};", float_type, name, value_initialize);
codegen_global_variables.push_back(make_symbol(name));
}
}

for (const auto& var: info.global_variables) {
auto name = var->get_name();
auto length = var->get_length();
if (var->is_array()) {
1uc marked this conversation as resolved.
Show resolved Hide resolved
printer->fmt_line("{} {}[{}] /* TODO init const-array */;", float_type, name, length);

Check warning on line 453 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L450-L453

Added lines #L450 - L453 were not covered by tests
} else {
double value{};
if (auto const& value_ptr = var->get_value()) {
value = *value_ptr;

Check warning on line 457 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L455-L457

Added lines #L455 - L457 were not covered by tests
}
printer->fmt_line("{} {}{};",

Check warning on line 459 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L459

Added line #L459 was not covered by tests
float_type,
name,
print_initializers ? fmt::format("{{{:g}}}", value) : std::string{});

Check warning on line 462 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L462

Added line #L462 was not covered by tests
}
codegen_global_variables.push_back(var);

Check warning on line 464 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L464

Added line #L464 was not covered by tests
}


for (const auto& f: info.function_tables) {

Check warning on line 468 in src/codegen/codegen_neuron_cpp_visitor.cpp

View workflow job for this annotation

GitHub Actions / { "flag_warnings": "ON", "os": "ubuntu-22.04" }

unused variable ‘f’ [-Wunused-variable]

Check warning on line 468 in src/codegen/codegen_neuron_cpp_visitor.cpp

View workflow job for this annotation

GitHub Actions / { "flag_warnings": "ON", "os": "ubuntu-22.04", "sanitizer": "undefined" }

unused variable 'f' [-Wunused-variable]
throw std::runtime_error("Not implemented, global function tables.");

Check warning on line 469 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L469

Added line #L469 was not covered by tests
}

if (info.vectorize && info.thread_data_index) {
throw std::runtime_error("Not implemented, global vectorize something else.");

Check warning on line 473 in src/codegen/codegen_neuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_neuron_cpp_visitor.cpp#L473

Added line #L473 was not covered by tests
}

printer->pop_block(";");

print_global_var_struct_assertions();
print_global_var_struct_decl();
}


Expand Down Expand Up @@ -572,11 +644,11 @@
}
}

// printer->fmt_line("{}* {}{};",
// global_struct(),
// naming::INST_GLOBAL_MEMBER,
// print_initializers ? fmt::format("{{&{}}}", global_struct_instance())
// : std::string{});
printer->fmt_line("{}* {}{};",
global_struct(),
naming::INST_GLOBAL_MEMBER,
print_initializers ? fmt::format("{{&{}}}", global_struct_instance())
: std::string{});
printer->pop_block(";");
}

Expand Down
1 change: 1 addition & 0 deletions test/unit/codegen/codegen_neuron_cpp_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ void _nrn_mechanism_register_data_fields(Args&&... args) {
const double* ion_ena{};
double* ion_ina{};
double* ion_dinadv{};
pas_test_Store* global{&pas_test_global};
};)";

REQUIRE_THAT(generated, ContainsSubstring(reindent_and_trim_text(expected)));
Expand Down
2 changes: 1 addition & 1 deletion test/usecases/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(NMODL_USECASE_DIRS cnexp_scalar cnexp_array)
set(NMODL_USECASE_DIRS cnexp_scalar cnexp_array global_breakpoint)

foreach(usecase ${NMODL_USECASE_DIRS})
add_test(NAME usecase_${usecase}
Expand Down
20 changes: 20 additions & 0 deletions test/usecases/global_breakpoint/leonhard.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
NEURON {
SUFFIX leonhard
GLOBAL c
}

PARAMETER {
c = 2.0
}

STATE {
x
}

INITIAL {
x = 42
}

BREAKPOINT {
x = c
}
27 changes: 27 additions & 0 deletions test/usecases/global_breakpoint/simulate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import numpy as np

from neuron import h, gui
from neuron.units import ms

nseg = 1

s = h.Section()
s.insert("leonhard")
s.nseg = nseg

x_hoc = h.Vector().record(s(0.5)._ref_x_leonhard)
t_hoc = h.Vector().record(h._ref_t)

h.stdinit()
h.tstop = 1.0 * ms
h.run()

x = np.array(x_hoc.as_numpy())
t = np.array(t_hoc.as_numpy())

x_exact = 2.0 * np.ones_like(t)
x_exact[0] = 42;
abs_err = np.abs(x - x_exact)

assert np.all(abs_err < 1e-12), f"{abs_err=}"
1uc marked this conversation as resolved.
Show resolved Hide resolved
print("leonhard: success")
Loading