once we start modifying (especially removing) older constructs from ast then we should run symtab visitor in update mode so that old symbols (e.g. prime variables) are not lost
-Definition at line 63 of file main.cpp.
+Definition at line 64 of file main.cpp.
diff --git a/html/doxygen/src_2main_8cpp_source.html b/html/doxygen/src_2main_8cpp_source.html
index bfef294d95..f68b046ee0 100644
--- a/html/doxygen/src_2main_8cpp_source.html
+++ b/html/doxygen/src_2main_8cpp_source.html
@@ -121,550 +121,557 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 56 namespace fs = std::filesystem;
- 57 using namespace nmodl;
- 58 using namespace codegen;
- 59 using namespace visitor;
-
-
-
- 63 int main(
int argc,
const char* argv[]) {
- 64 CLI::App app{fmt::format(
"NMODL : Source-to-Source Code Generation Framework [{}]",
-
-
-
- 68 std::vector<fs::path> mod_files;
-
-
- 71 std::string verbose(
"info");
-
-
- 74 bool neuron_code(
false);
-
-
- 77 bool coreneuron_code(
true);
-
-
- 80 bool cpp_backend(
true);
-
-
- 83 bool oacc_backend(
false);
-
-
- 86 bool sympy_analytic(
false);
-
-
- 89 bool sympy_pade(
false);
-
-
- 92 bool sympy_cse(
false);
-
-
- 95 bool sympy_conductance(
false);
-
-
- 98 bool nmodl_inline(
false);
-
-
- 101 bool nmodl_unroll(
false);
-
-
- 104 bool nmodl_const_folding(
false);
-
-
- 107 bool nmodl_localize(
false);
-
-
- 110 bool nmodl_global_to_range(
false);
-
-
- 113 bool nmodl_local_to_range(
false);
-
-
- 116 bool localize_verbatim(
false);
-
-
- 119 bool local_rename(
true);
-
-
- 122 bool verbatim_inline(
false);
-
-
- 125 bool verbatim_rename(
true);
-
-
-
- 129 bool force_codegen(
false);
-
-
- 132 bool only_check_compatibility(
false);
-
-
- 135 bool optimize_ionvar_copies_codegen(
false);
-
-
- 138 std::string output_dir(
".");
-
-
- 141 std::string scratch_dir(
"tmp");
-
-
-
-
-
- 147 bool json_ast(
false);
-
-
- 150 bool nmodl_ast(
false);
-
-
- 153 bool json_perfstat(
false);
-
-
- 156 bool show_symtab(
false);
-
-
- 159 std::string data_type(
"double");
-
-
- 162 app.get_formatter()->column_width(40);
- 163 app.set_help_all_flag(
"-H,--help-all",
"Print this help message including all sub-commands");
-
- 165 app.add_option(
"--verbose", verbose,
"Verbosity of logger output")
- 166 ->capture_default_str()
-
- 168 ->check(CLI::IsMember({
"trace",
"debug",
"info",
"warning",
"error",
"critical",
"off"}));
-
- 170 app.add_option(
"file", mod_files,
"One or more MOD files to process")
-
-
- 173 ->check(CLI::ExistingFile);
-
- 175 app.add_option(
"-o,--output", output_dir,
"Directory for backend code output")
- 176 ->capture_default_str()
-
- 178 app.add_option(
"--scratch", scratch_dir,
"Directory for intermediate code output")
- 179 ->capture_default_str()
-
- 181 app.add_option(
"--units", units_dir,
"Directory of units lib file")
- 182 ->capture_default_str()
-
- 184 app.add_flag(
"--neuron", neuron_code,
"Generate C++ code for NEURON");
- 185 app.add_flag(
"--coreneuron", coreneuron_code,
"Generate C++ code for CoreNEURON (Default)");
-
- 187 auto host_opt = app.add_subcommand(
"host",
"HOST/CPU code backends")->ignore_case();
- 188 host_opt->add_flag(
"--c,--cpp", cpp_backend, fmt::format(
"C++ backend ({})", cpp_backend))
-
-
- 191 auto acc_opt = app.add_subcommand(
"acc",
"Accelerator code backends")->ignore_case();
-
-
-
- 195 fmt::format(
"C++ backend with OpenACC ({})", oacc_backend))
-
-
-
- 199 auto sympy_opt = app.add_subcommand(
"sympy",
"SymPy based analysis and optimizations")->ignore_case();
- 200 sympy_opt->add_flag(
"--analytic",
-
- 202 fmt::format(
"Solve ODEs using SymPy analytic integration ({})", sympy_analytic))->ignore_case();
- 203 sympy_opt->add_flag(
"--pade",
-
- 205 fmt::format(
"Pade approximation in SymPy analytic integration ({})", sympy_pade))->ignore_case();
- 206 sympy_opt->add_flag(
"--cse",
-
- 208 fmt::format(
"CSE (Common Subexpression Elimination) in SymPy analytic integration ({})", sympy_cse))->ignore_case();
- 209 sympy_opt->add_flag(
"--conductance",
-
- 211 fmt::format(
"Add CONDUCTANCE keyword in BREAKPOINT ({})", sympy_conductance))->ignore_case();
-
- 213 auto passes_opt = app.add_subcommand(
"passes",
"Analyse/Optimization passes")->ignore_case();
- 214 passes_opt->add_flag(
"--inline",
-
- 216 fmt::format(
"Perform inlining at NMODL level ({})", nmodl_inline))->ignore_case();
- 217 passes_opt->add_flag(
"--unroll",
-
- 219 fmt::format(
"Perform loop unroll at NMODL level ({})", nmodl_unroll))->ignore_case();
- 220 passes_opt->add_flag(
"--const-folding",
-
- 222 fmt::format(
"Perform constant folding at NMODL level ({})", nmodl_const_folding))->ignore_case();
- 223 passes_opt->add_flag(
"--localize",
-
- 225 fmt::format(
"Convert RANGE variables to LOCAL ({})", nmodl_localize))->ignore_case();
- 226 passes_opt->add_flag(
"--global-to-range",
- 227 nmodl_global_to_range,
- 228 fmt::format(
"Convert GLOBAL variables to RANGE ({})", nmodl_global_to_range))->ignore_case();
- 229 passes_opt->add_flag(
"--local-to-range",
- 230 nmodl_local_to_range,
- 231 fmt::format(
"Convert top level LOCAL variables to RANGE ({})", nmodl_local_to_range))->ignore_case();
- 232 passes_opt->add_flag(
"--localize-verbatim",
-
- 234 fmt::format(
"Convert RANGE variables to LOCAL even if verbatim block exist ({})", localize_verbatim))->ignore_case();
- 235 passes_opt->add_flag(
"--local-rename",
-
- 237 fmt::format(
"Rename LOCAL variable if variable of same name exist in global scope ({})", local_rename))->ignore_case();
- 238 passes_opt->add_flag(
"--verbatim-inline",
-
- 240 fmt::format(
"Inline even if verbatim block exist ({})", verbatim_inline))->ignore_case();
- 241 passes_opt->add_flag(
"--verbatim-rename",
-
- 243 fmt::format(
"Rename variables in verbatim block ({})", verbatim_rename))->ignore_case();
- 244 passes_opt->add_flag(
"--json-ast",
-
- 246 fmt::format(
"Write AST to JSON file ({})", json_ast))->ignore_case();
- 247 passes_opt->add_flag(
"--nmodl-ast",
-
- 249 fmt::format(
"Write AST to NMODL file ({})", nmodl_ast))->ignore_case();
- 250 passes_opt->add_flag(
"--json-perf",
-
- 252 fmt::format(
"Write performance statistics to JSON file ({})", json_perfstat))->ignore_case();
- 253 passes_opt->add_flag(
"--show-symtab",
-
- 255 fmt::format(
"Write symbol table to stdout ({})", show_symtab))->ignore_case();
-
- 257 auto codegen_opt = app.add_subcommand(
"codegen",
"Code generation options")->ignore_case();
- 258 codegen_opt->add_option(
"--datatype",
-
- 260 "Data type for floating point variables")->capture_default_str()->ignore_case()->check(CLI::IsMember({
"float",
"double"}));
- 261 codegen_opt->add_flag(
"--force",
-
- 263 "Force code generation even if there is any incompatibility");
- 264 codegen_opt->add_flag(
"--only-check-compatibility",
- 265 only_check_compatibility,
- 266 "Check compatibility and return without generating code");
- 267 codegen_opt->add_flag(
"--opt-ionvar-copy",
- 268 optimize_ionvar_copies_codegen,
- 269 fmt::format(
"Optimize copies of ion variables ({})", optimize_ionvar_copies_codegen))->ignore_case();
-
-
-
- 273 CLI11_PARSE(app, argc, argv);
-
- 275 fs::create_directories(output_dir);
- 276 fs::create_directories(scratch_dir);
-
-
-
-
-
-
-
- 284 logger->set_level(spdlog::level::from_str(verbose));
-
-
- 287 const auto ast_to_nmodl = [nmodl_ast](
ast::Program& ast,
const std::string& filepath) {
-
- 289 NmodlPrintVisitor(filepath).visit_program(ast);
- 290 logger->info(
"AST to NMODL transformation written to {}", filepath);
-
-
-
- 294 for (
const auto& file: mod_files) {
- 295 logger->info(
"Processing {}", file.string());
-
- 297 const auto modfile = file.stem().string();
-
-
- 300 auto filepath = [scratch_dir, modfile](
const std::string& suffix) {
- 301 static int count = 0;
-
- 303 "{}/{}.{}.{}.mod", scratch_dir, modfile,
std::to_string(count++), suffix);
-
-
-
-
-
-
-
-
-
-
- 314 bool update_symtab =
false;
-
-
- 317 AstVisitor().visit_program(*ast);
-
-
-
- 321 logger->info(
"Running symtab visitor");
-
-
-
-
-
- 327 logger->info(
"Running semantic analysis visitor");
-
-
-
-
-
-
-
- 335 logger->info(
"Running CVode to cnexp visitor");
- 336 AfterCVodeToCnexpVisitor().visit_program(*ast);
- 337 ast_to_nmodl(*ast, filepath(
"after_cvode_to_cnexp"));
-
-
-
- 341 if (nmodl_global_to_range) {
-
-
- 344 PerfVisitor().visit_program(*ast);
-
-
- 347 logger->info(
"Running GlobalToRange visitor");
- 348 GlobalToRangeVisitor(*ast).visit_program(*ast);
-
- 350 ast_to_nmodl(*ast, filepath(
"global_to_range"));
-
-
-
- 354 if (nmodl_local_to_range) {
- 355 logger->info(
"Running LOCAL to ASSIGNED visitor");
- 356 PerfVisitor().visit_program(*ast);
- 357 LocalToAssignedVisitor().visit_program(*ast);
-
- 359 ast_to_nmodl(*ast, filepath(
"local_to_assigned"));
-
-
-
-
- 364 logger->info(
"Running code compatibility checker");
-
- 366 PerfVisitor().visit_program(*ast);
-
-
- 369 if (only_check_compatibility) {
-
-
-
-
-
-
-
-
-
-
- 380 logger->info(
"Printing symbol table");
-
- 382 symtab->
print(std::cout);
-
-
- 385 ast_to_nmodl(*ast, filepath(
"ast"));
-
-
- 388 std::string file{scratch_dir};
-
-
-
- 392 logger->info(
"Writing AST into {}", file);
- 393 JSONVisitor(file).write(*ast);
-
-
- 396 if (verbatim_rename) {
- 397 logger->info(
"Running verbatim rename visitor");
- 398 VerbatimVarRenameVisitor().visit_program(*ast);
- 399 ast_to_nmodl(*ast, filepath(
"verbatim_rename"));
-
-
- 402 if (nmodl_const_folding) {
- 403 logger->info(
"Running nmodl constant folding visitor");
- 404 ConstantFolderVisitor().visit_program(*ast);
- 405 ast_to_nmodl(*ast, filepath(
"constfold"));
-
-
-
- 409 logger->info(
"Running nmodl loop unroll visitor");
- 410 LoopUnrollVisitor().visit_program(*ast);
- 411 ConstantFolderVisitor().visit_program(*ast);
- 412 ast_to_nmodl(*ast, filepath(
"unroll"));
-
-
-
-
-
-
-
- 420 logger->info(
"Running KINETIC block visitor");
- 421 auto kineticBlockVisitor = KineticBlockVisitor();
- 422 kineticBlockVisitor.visit_program(*ast);
-
- 424 const auto filename = filepath(
"kinetic");
- 425 ast_to_nmodl(*ast, filename);
- 426 if (nmodl_ast && kineticBlockVisitor.get_conserve_statement_count()) {
-
- 428 fmt::format(
"{} presents non-standard CONSERVE statements in DERIVATIVE "
- 429 "blocks. Use it only for debugging/developing",
-
-
-
-
-
- 435 logger->info(
"Running STEADYSTATE visitor");
- 436 SteadystateVisitor().visit_program(*ast);
-
- 438 ast_to_nmodl(*ast, filepath(
"steadystate"));
-
-
-
-
- 443 logger->info(
"Parsing Units");
- 444 UnitsVisitor(units_dir).visit_program(*ast);
-
-
-
-
-
- 450 update_symtab =
true;
-
-
- 453 logger->info(
"Running nmodl inline visitor");
- 454 InlineVisitor().visit_program(*ast);
-
- 456 ast_to_nmodl(*ast, filepath(
"inline"));
-
-
-
- 460 logger->info(
"Running local variable rename visitor");
- 461 LocalVarRenameVisitor().visit_program(*ast);
-
- 463 ast_to_nmodl(*ast, filepath(
"local_rename"));
-
-
- 466 if (nmodl_localize) {
-
- 468 logger->info(
"Running localize visitor");
- 469 LocalizeVisitor(localize_verbatim).visit_program(*ast);
- 470 LocalVarRenameVisitor().visit_program(*ast);
-
- 472 ast_to_nmodl(*ast, filepath(
"localize"));
-
-
- 475 if (sympy_conductance) {
- 476 logger->info(
"Running sympy conductance visitor");
- 477 SympyConductanceVisitor().visit_program(*ast);
-
- 479 ast_to_nmodl(*ast, filepath(
"sympy_conductance"));
-
-
-
- 483 if (!sympy_analytic) {
-
- 485 "Automatically enable sympy_analytic because it exists solver of type sparse");
-
- 487 logger->info(
"Running sympy solve visitor");
- 488 SympySolverVisitor(sympy_pade, sympy_cse).visit_program(*ast);
-
- 490 ast_to_nmodl(*ast, filepath(
"sympy_solve"));
-
-
-
- 494 logger->info(
"Running cnexp visitor");
- 495 NeuronSolveVisitor().visit_program(*ast);
- 496 ast_to_nmodl(*ast, filepath(
"cnexp"));
-
-
-
- 500 SolveBlockVisitor().visit_program(*ast);
-
- 502 ast_to_nmodl(*ast, filepath(
"solveblock"));
-
-
-
- 506 std::string file{scratch_dir};
-
- 508 file.append(modfile);
- 509 file.append(
".perf.json");
- 510 logger->info(
"Writing performance statistics to {}", file);
- 511 PerfVisitor(file).visit_program(*ast);
-
-
-
-
- 516 ImplicitArgumentVisitor{}.visit_program(*ast);
-
-
-
-
-
- 522 PerfVisitor().visit_program(*ast);
-
-
-
-
- 527 ast_to_nmodl(*ast, filepath(
"TransformVisitor"));
-
-
-
-
- 532 if (coreneuron_code && oacc_backend) {
- 533 logger->info(
"Running OpenACC backend code generator for CoreNEURON");
-
-
-
- 537 optimize_ionvar_copies_codegen);
-
-
-
- 541 else if (coreneuron_code && !neuron_code && cpp_backend) {
- 542 logger->info(
"Running C++ backend code generator for CoreNEURON");
-
-
-
- 546 optimize_ionvar_copies_codegen);
-
-
-
- 550 else if (neuron_code && cpp_backend) {
- 551 logger->info(
"Running C++ backend code generator for NEURON");
-
-
-
- 555 optimize_ionvar_copies_codegen);
-
-
-
-
- 560 throw std::runtime_error(
- 561 "Non valid code generation configuration. Code generation with NMODL is "
- 562 "supported for NEURON with C++ backend or CoreNEURON with C++/OpenACC "
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 57 namespace fs = std::filesystem;
+ 58 using namespace nmodl;
+ 59 using namespace codegen;
+ 60 using namespace visitor;
+
+
+
+ 64 int main(
int argc,
const char* argv[]) {
+ 65 CLI::App app{fmt::format(
"NMODL : Source-to-Source Code Generation Framework [{}]",
+
+
+
+ 69 std::vector<fs::path> mod_files;
+
+
+ 72 std::string verbose(
"info");
+
+
+ 75 bool neuron_code(
false);
+
+
+ 78 bool coreneuron_code(
true);
+
+
+ 81 bool cpp_backend(
true);
+
+
+ 84 bool oacc_backend(
false);
+
+
+ 87 bool sympy_analytic(
false);
+
+
+ 90 bool sympy_pade(
false);
+
+
+ 93 bool sympy_cse(
false);
+
+
+ 96 bool sympy_conductance(
false);
+
+
+ 99 bool nmodl_inline(
false);
+
+
+ 102 bool nmodl_unroll(
false);
+
+
+ 105 bool nmodl_const_folding(
false);
+
+
+ 108 bool nmodl_localize(
false);
+
+
+ 111 bool nmodl_global_to_range(
false);
+
+
+ 114 bool nmodl_local_to_range(
false);
+
+
+ 117 bool localize_verbatim(
false);
+
+
+ 120 bool local_rename(
true);
+
+
+ 123 bool verbatim_inline(
false);
+
+
+ 126 bool verbatim_rename(
true);
+
+
+
+ 130 bool force_codegen(
false);
+
+
+ 133 bool only_check_compatibility(
false);
+
+
+ 136 bool optimize_ionvar_copies_codegen(
false);
+
+
+ 139 std::string output_dir(
".");
+
+
+ 142 std::string scratch_dir(
"tmp");
+
+
+
+
+
+ 148 bool json_ast(
false);
+
+
+ 151 bool nmodl_ast(
false);
+
+
+ 154 bool json_perfstat(
false);
+
+
+ 157 bool show_symtab(
false);
+
+
+ 160 std::string data_type(
"double");
+
+
+ 163 app.get_formatter()->column_width(40);
+ 164 app.set_help_all_flag(
"-H,--help-all",
"Print this help message including all sub-commands");
+
+ 166 app.add_option(
"--verbose", verbose,
"Verbosity of logger output")
+ 167 ->capture_default_str()
+
+ 169 ->check(CLI::IsMember({
"trace",
"debug",
"info",
"warning",
"error",
"critical",
"off"}));
+
+ 171 app.add_option(
"file", mod_files,
"One or more MOD files to process")
+
+
+ 174 ->check(CLI::ExistingFile);
+
+ 176 app.add_option(
"-o,--output", output_dir,
"Directory for backend code output")
+ 177 ->capture_default_str()
+
+ 179 app.add_option(
"--scratch", scratch_dir,
"Directory for intermediate code output")
+ 180 ->capture_default_str()
+
+ 182 app.add_option(
"--units", units_dir,
"Directory of units lib file")
+ 183 ->capture_default_str()
+
+ 185 app.add_flag(
"--neuron", neuron_code,
"Generate C++ code for NEURON");
+ 186 app.add_flag(
"--coreneuron", coreneuron_code,
"Generate C++ code for CoreNEURON (Default)");
+
+ 188 auto host_opt = app.add_subcommand(
"host",
"HOST/CPU code backends")->ignore_case();
+ 189 host_opt->add_flag(
"--c,--cpp", cpp_backend, fmt::format(
"C++ backend ({})", cpp_backend))
+
+
+ 192 auto acc_opt = app.add_subcommand(
"acc",
"Accelerator code backends")->ignore_case();
+
+
+
+ 196 fmt::format(
"C++ backend with OpenACC ({})", oacc_backend))
+
+
+
+ 200 auto sympy_opt = app.add_subcommand(
"sympy",
"SymPy based analysis and optimizations")->ignore_case();
+ 201 sympy_opt->add_flag(
"--analytic",
+
+ 203 fmt::format(
"Solve ODEs using SymPy analytic integration ({})", sympy_analytic))->ignore_case();
+ 204 sympy_opt->add_flag(
"--pade",
+
+ 206 fmt::format(
"Pade approximation in SymPy analytic integration ({})", sympy_pade))->ignore_case();
+ 207 sympy_opt->add_flag(
"--cse",
+
+ 209 fmt::format(
"CSE (Common Subexpression Elimination) in SymPy analytic integration ({})", sympy_cse))->ignore_case();
+ 210 sympy_opt->add_flag(
"--conductance",
+
+ 212 fmt::format(
"Add CONDUCTANCE keyword in BREAKPOINT ({})", sympy_conductance))->ignore_case();
+
+ 214 auto passes_opt = app.add_subcommand(
"passes",
"Analyse/Optimization passes")->ignore_case();
+ 215 passes_opt->add_flag(
"--inline",
+
+ 217 fmt::format(
"Perform inlining at NMODL level ({})", nmodl_inline))->ignore_case();
+ 218 passes_opt->add_flag(
"--unroll",
+
+ 220 fmt::format(
"Perform loop unroll at NMODL level ({})", nmodl_unroll))->ignore_case();
+ 221 passes_opt->add_flag(
"--const-folding",
+
+ 223 fmt::format(
"Perform constant folding at NMODL level ({})", nmodl_const_folding))->ignore_case();
+ 224 passes_opt->add_flag(
"--localize",
+
+ 226 fmt::format(
"Convert RANGE variables to LOCAL ({})", nmodl_localize))->ignore_case();
+ 227 passes_opt->add_flag(
"--global-to-range",
+ 228 nmodl_global_to_range,
+ 229 fmt::format(
"Convert GLOBAL variables to RANGE ({})", nmodl_global_to_range))->ignore_case();
+ 230 passes_opt->add_flag(
"--local-to-range",
+ 231 nmodl_local_to_range,
+ 232 fmt::format(
"Convert top level LOCAL variables to RANGE ({})", nmodl_local_to_range))->ignore_case();
+ 233 passes_opt->add_flag(
"--localize-verbatim",
+
+ 235 fmt::format(
"Convert RANGE variables to LOCAL even if verbatim block exist ({})", localize_verbatim))->ignore_case();
+ 236 passes_opt->add_flag(
"--local-rename",
+
+ 238 fmt::format(
"Rename LOCAL variable if variable of same name exist in global scope ({})", local_rename))->ignore_case();
+ 239 passes_opt->add_flag(
"--verbatim-inline",
+
+ 241 fmt::format(
"Inline even if verbatim block exist ({})", verbatim_inline))->ignore_case();
+ 242 passes_opt->add_flag(
"--verbatim-rename",
+
+ 244 fmt::format(
"Rename variables in verbatim block ({})", verbatim_rename))->ignore_case();
+ 245 passes_opt->add_flag(
"--json-ast",
+
+ 247 fmt::format(
"Write AST to JSON file ({})", json_ast))->ignore_case();
+ 248 passes_opt->add_flag(
"--nmodl-ast",
+
+ 250 fmt::format(
"Write AST to NMODL file ({})", nmodl_ast))->ignore_case();
+ 251 passes_opt->add_flag(
"--json-perf",
+
+ 253 fmt::format(
"Write performance statistics to JSON file ({})", json_perfstat))->ignore_case();
+ 254 passes_opt->add_flag(
"--show-symtab",
+
+ 256 fmt::format(
"Write symbol table to stdout ({})", show_symtab))->ignore_case();
+
+ 258 auto codegen_opt = app.add_subcommand(
"codegen",
"Code generation options")->ignore_case();
+ 259 codegen_opt->add_option(
"--datatype",
+
+ 261 "Data type for floating point variables")->capture_default_str()->ignore_case()->check(CLI::IsMember({
"float",
"double"}));
+ 262 codegen_opt->add_flag(
"--force",
+
+ 264 "Force code generation even if there is any incompatibility");
+ 265 codegen_opt->add_flag(
"--only-check-compatibility",
+ 266 only_check_compatibility,
+ 267 "Check compatibility and return without generating code");
+ 268 codegen_opt->add_flag(
"--opt-ionvar-copy",
+ 269 optimize_ionvar_copies_codegen,
+ 270 fmt::format(
"Optimize copies of ion variables ({})", optimize_ionvar_copies_codegen))->ignore_case();
+
+
+
+ 274 CLI11_PARSE(app, argc, argv);
+
+ 276 fs::create_directories(output_dir);
+ 277 fs::create_directories(scratch_dir);
+
+
+
+
+
+
+
+ 285 logger->set_level(spdlog::level::from_str(verbose));
+
+
+ 288 const auto ast_to_nmodl = [nmodl_ast](
ast::Program& ast,
const std::string& filepath) {
+
+ 290 NmodlPrintVisitor(filepath).visit_program(ast);
+ 291 logger->info(
"AST to NMODL transformation written to {}", filepath);
+
+
+
+ 295 for (
const auto& file: mod_files) {
+ 296 logger->info(
"Processing {}", file.string());
+
+ 298 const auto modfile = file.stem().string();
+
+
+ 301 auto filepath = [scratch_dir, modfile](
const std::string& suffix) {
+ 302 static int count = 0;
+
+ 304 "{}/{}.{}.{}.mod", scratch_dir, modfile,
std::to_string(count++), suffix);
+
+
+
+
+
+
+
+
+
+
+ 315 bool update_symtab =
false;
+
+
+ 318 AstVisitor().visit_program(*ast);
+
+
+
+ 322 logger->info(
"Running symtab visitor");
+
+
+
+
+
+ 328 logger->info(
"Running semantic analysis visitor");
+
+
+
+
+
+
+
+ 336 logger->info(
"Running CVode to cnexp visitor");
+ 337 AfterCVodeToCnexpVisitor().visit_program(*ast);
+ 338 ast_to_nmodl(*ast, filepath(
"after_cvode_to_cnexp"));
+
+
+
+ 342 if (nmodl_global_to_range) {
+
+
+ 345 PerfVisitor().visit_program(*ast);
+
+
+ 348 logger->info(
"Running GlobalToRange visitor");
+ 349 GlobalToRangeVisitor(*ast).visit_program(*ast);
+
+ 351 ast_to_nmodl(*ast, filepath(
"global_to_range"));
+
+
+
+ 355 if (nmodl_local_to_range) {
+ 356 logger->info(
"Running LOCAL to ASSIGNED visitor");
+ 357 PerfVisitor().visit_program(*ast);
+ 358 LocalToAssignedVisitor().visit_program(*ast);
+
+ 360 ast_to_nmodl(*ast, filepath(
"local_to_assigned"));
+
+
+
+
+ 365 logger->info(
"Running code compatibility checker");
+
+ 367 PerfVisitor().visit_program(*ast);
+
+
+ 370 if (only_check_compatibility) {
+
+
+
+
+
+
+
+
+
+
+ 381 logger->info(
"Printing symbol table");
+
+ 383 symtab->
print(std::cout);
+
+
+ 386 ast_to_nmodl(*ast, filepath(
"ast"));
+
+
+ 389 std::string file{scratch_dir};
+
+
+
+ 393 logger->info(
"Writing AST into {}", file);
+ 394 JSONVisitor(file).write(*ast);
+
+
+ 397 if (verbatim_rename) {
+ 398 logger->info(
"Running verbatim rename visitor");
+ 399 VerbatimVarRenameVisitor().visit_program(*ast);
+ 400 ast_to_nmodl(*ast, filepath(
"verbatim_rename"));
+
+
+ 403 if (nmodl_const_folding) {
+ 404 logger->info(
"Running nmodl constant folding visitor");
+ 405 ConstantFolderVisitor().visit_program(*ast);
+ 406 ast_to_nmodl(*ast, filepath(
"constfold"));
+
+
+
+ 410 logger->info(
"Running nmodl loop unroll visitor");
+ 411 LoopUnrollVisitor().visit_program(*ast);
+ 412 ConstantFolderVisitor().visit_program(*ast);
+ 413 ast_to_nmodl(*ast, filepath(
"unroll"));
+
+
+
+
+
+
+
+ 421 logger->info(
"Running KINETIC block visitor");
+ 422 auto kineticBlockVisitor = KineticBlockVisitor();
+ 423 kineticBlockVisitor.visit_program(*ast);
+
+ 425 const auto filename = filepath(
"kinetic");
+ 426 ast_to_nmodl(*ast, filename);
+ 427 if (nmodl_ast && kineticBlockVisitor.get_conserve_statement_count()) {
+
+ 429 fmt::format(
"{} presents non-standard CONSERVE statements in DERIVATIVE "
+ 430 "blocks. Use it only for debugging/developing",
+
+
+
+
+
+ 436 logger->info(
"Running STEADYSTATE visitor");
+ 437 SteadystateVisitor().visit_program(*ast);
+
+ 439 ast_to_nmodl(*ast, filepath(
"steadystate"));
+
+
+
+
+ 444 logger->info(
"Parsing Units");
+ 445 UnitsVisitor(units_dir).visit_program(*ast);
+
+
+
+
+
+ 451 update_symtab =
true;
+
+
+ 454 logger->info(
"Running nmodl inline visitor");
+ 455 InlineVisitor().visit_program(*ast);
+
+ 457 ast_to_nmodl(*ast, filepath(
"inline"));
+
+
+
+ 461 logger->info(
"Running local variable rename visitor");
+ 462 LocalVarRenameVisitor().visit_program(*ast);
+
+ 464 ast_to_nmodl(*ast, filepath(
"local_rename"));
+
+
+ 467 if (nmodl_localize) {
+
+ 469 logger->info(
"Running localize visitor");
+ 470 LocalizeVisitor(localize_verbatim).visit_program(*ast);
+ 471 LocalVarRenameVisitor().visit_program(*ast);
+
+ 473 ast_to_nmodl(*ast, filepath(
"localize"));
+
+
+ 476 if (sympy_conductance) {
+ 477 logger->info(
"Running sympy conductance visitor");
+ 478 SympyConductanceVisitor().visit_program(*ast);
+
+ 480 ast_to_nmodl(*ast, filepath(
"sympy_conductance"));
+
+
+
+ 484 if (!sympy_analytic) {
+
+ 486 "Automatically enable sympy_analytic because it exists solver of type sparse");
+
+ 488 logger->info(
"Running sympy solve visitor");
+ 489 SympySolverVisitor(sympy_pade, sympy_cse).visit_program(*ast);
+
+ 491 ast_to_nmodl(*ast, filepath(
"sympy_solve"));
+
+
+
+ 495 logger->info(
"Running cnexp visitor");
+ 496 NeuronSolveVisitor().visit_program(*ast);
+ 497 ast_to_nmodl(*ast, filepath(
"cnexp"));
+
+
+
+ 501 SolveBlockVisitor().visit_program(*ast);
+
+ 503 ast_to_nmodl(*ast, filepath(
"solveblock"));
+
+
+
+ 507 std::string file{scratch_dir};
+
+ 509 file.append(modfile);
+ 510 file.append(
".perf.json");
+ 511 logger->info(
"Writing performance statistics to {}", file);
+ 512 PerfVisitor(file).visit_program(*ast);
+
+
+
+
+ 517 ImplicitArgumentVisitor{}.visit_program(*ast);
+
+
+
+
+
+ 523 PerfVisitor().visit_program(*ast);
+
+
+
+
+ 528 ast_to_nmodl(*ast, filepath(
"TransformVisitor"));
+
+
+
+
+ 533 FunctionCallpathVisitor{}.visit_program(*ast);
+ 534 ast_to_nmodl(*ast, filepath(
"FunctionCallpathVisitor"));
+
+
+
+
+ 539 if (coreneuron_code && oacc_backend) {
+ 540 logger->info(
"Running OpenACC backend code generator for CoreNEURON");
+
+
+
+ 544 optimize_ionvar_copies_codegen);
+
+
+
+ 548 else if (coreneuron_code && !neuron_code && cpp_backend) {
+ 549 logger->info(
"Running C++ backend code generator for CoreNEURON");
+
+
+
+ 553 optimize_ionvar_copies_codegen);
+
+
+
+ 557 else if (neuron_code && cpp_backend) {
+ 558 logger->info(
"Running C++ backend code generator for NEURON");
+
+
+
+ 562 optimize_ionvar_copies_codegen);
+
-
-
-
-
-
-
-
+
+
+ 567 throw std::runtime_error(
+ 568 "Non valid code generation configuration. Code generation with NMODL is "
+ 569 "supported for NEURON with C++ backend or CoreNEURON with C++/OpenACC "
+
+
+
+
+
+
+
+
+
symtab::ModelSymbolTable * get_model_symbol_table()
Return global symbol table for the mod file.
@@ -701,7 +708,7 @@
Visitor for printing C++ code compatible with legacy api of CoreNEURON
Rename variable in verbatim block.
Visitor for printing compatibility issues of the mod file
-std::string to_string(const T &obj)
+std::string to_string(const T &obj)
Visitor for printing C++ code with OpenACC backend
Visitor to rename local variables conflicting with global scope
@@ -709,6 +716,7 @@
Visitor for verbatim blocks of AST
Visitor for Units blocks of AST.
Visitor to change usage of after_cvode solver to cnexp.
+Visitor for traversing FunctionBlock s and ProcedureBlocks through their FunctionCall s
Visitor for printing C++ code compatible with legacy api of NEURON
Implement logger based on spdlog library.
bool find_unhandled_ast_nodes(Ast &node) const
Search the ast::Ast for nodes that are incompatible with NMODL C++ code generator.
@@ -720,7 +728,7 @@
Represents top level AST node for whole NMODL input.
bool sparse_solver_exists(const ast::Ast &node)
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
-int main(int argc, const char *argv[])
+int main(int argc, const char *argv[])
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
static std::string get_path()
Return path of units database file.
bool parse_file(const std::string &filename)
parse Units file
diff --git a/html/doxygen/src_2symtab_2symbol__table_8cpp_source.html b/html/doxygen/src_2symtab_2symbol__table_8cpp_source.html
index 7745c0915d..34b16960d1 100644
--- a/html/doxygen/src_2symtab_2symbol__table_8cpp_source.html
+++ b/html/doxygen/src_2symtab_2symbol__table_8cpp_source.html
@@ -657,7 +657,7 @@
std::string title() const
construct title for symbol table
std::shared_ptr< Symbol > update_mode_insert(const std::shared_ptr< Symbol > &symbol)
insert symbol table in update mode
Implement generic table data structure.
-std::string to_string(const T &obj)
+std::string to_string(const T &obj)
SymbolTable * current_symtab
current symbol table being constructed
void insert_table(const std::string &name, const std::shared_ptr< SymbolTable > &table)
insert new symbol table as one of the children block
std::shared_ptr< Symbol > lookup(const std::string &name)
lookup for symbol into current as well as all parent tables
diff --git a/html/doxygen/src_2visitors_2main_8cpp_source.html b/html/doxygen/src_2visitors_2main_8cpp_source.html
index ada83f545f..cd50278c6b 100644
--- a/html/doxygen/src_2visitors_2main_8cpp_source.html
+++ b/html/doxygen/src_2visitors_2main_8cpp_source.html
@@ -262,7 +262,7 @@
Version information and units file path.
Represents top level AST node for whole NMODL input.
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
-int main(int argc, const char *argv[])
+int main(int argc, const char *argv[])
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
static std::string get_path()
Return path of units database file.
bool parse_file(const std::string &filename)
parse Units file
diff --git a/html/doxygen/symbol_8cpp_source.html b/html/doxygen/symbol_8cpp_source.html
index c480c866db..bcb99adb19 100644
--- a/html/doxygen/symbol_8cpp_source.html
+++ b/html/doxygen/symbol_8cpp_source.html
@@ -167,7 +167,7 @@
encapsulates code generation backend implementations
Status
state during various compiler passes
bool has_any_property(syminfo::NmodlType new_properties) const noexcept
check if symbol has any of the given property
-std::string to_string(const T &obj)
+std::string to_string(const T &obj)
syminfo::Status status
status of symbol after processing through various passes
Auto generated AST classes declaration.
std::string name
name of the symbol
diff --git a/html/doxygen/symbol__properties_8cpp_source.html b/html/doxygen/symbol__properties_8cpp_source.html
index 90f7f3596a..189107fe9e 100644
--- a/html/doxygen/symbol__properties_8cpp_source.html
+++ b/html/doxygen/symbol__properties_8cpp_source.html
@@ -257,65 +257,70 @@
161 properties.emplace_back(
"codegen_var");
-
- 165 properties.emplace_back(
"random_var");
+
+ 165 properties.emplace_back(
"use_range_ptr_var");
-
-
-
-
- 172 std::vector<std::string> status;
-
-
-
-
- 177 status.emplace_back(
"localized");
-
+
+ 169 properties.emplace_back(
"random_var");
+
+
+
+
+
+
+ 176 std::vector<std::string> status;
+
+
-
- 181 status.emplace_back(
"globalized");
+
+ 181 status.emplace_back(
"localized");
-
- 185 status.emplace_back(
"inlined");
+
+ 185 status.emplace_back(
"globalized");
-
- 189 status.emplace_back(
"renamed");
+
+ 189 status.emplace_back(
"inlined");
-
- 193 status.emplace_back(
"created");
+
+ 193 status.emplace_back(
"renamed");
-
- 197 status.emplace_back(
"from_state");
+
+ 197 status.emplace_back(
"created");
-
- 201 status.emplace_back(
"thread_safe");
+
+ 201 status.emplace_back(
"from_state");
-
-
-
-
-
+
+ 205 status.emplace_back(
"thread_safe");
+
+
+
-
+
-
-
-
+
+
+
+
+
+
+
-bool has_status(const Status &obj, Status state)
check if any status is set
+bool has_status(const Status &obj, Status state)
check if any status is set
@ from_state
derived from state
@ write_ion_var
Write Ion.
+@ use_range_ptr_var
FUNCTION or PROCEDURE needs setdata check.
@ extern_method
neuron solver methods and math functions
@ globalized
converted to global
@ thread_safe
variable marked as thread safe
@@ -334,7 +339,7 @@
@ codegen_var
Codegen specific variable.
@ range_var
Range Variable.
-std::ostream & operator<<(std::ostream &os, const NmodlType &obj)
+std::ostream & operator<<(std::ostream &os, const NmodlType &obj)
@ kinetic_block
Kinetic Block.
@@ -345,7 +350,7 @@
@ define
Define variable / macro.
@ factor_def
factor in unit block
-std::string to_string(const T &obj)
+std::string to_string(const T &obj)
@ nonspecific_cur_var
Non Specific Current.
@ assigned_definition
Assigned Definition.
@ param_assign
Parameter Variable.
@@ -365,7 +370,7 @@
@ discrete_block
Discrete Block.
@ extern_neuron_variable
neuron variable accessible in mod file
@ electrode_cur_var
Electrode Current.
-bool has_property(const NmodlType &obj, NmodlType property)
check if any property is set
+bool has_property(const NmodlType &obj, NmodlType property)
check if any property is set
diff --git a/html/doxygen/symbol__properties_8hpp.html b/html/doxygen/symbol__properties_8hpp.html
index e04dbf2522..15350a0be5 100644
--- a/html/doxygen/symbol__properties_8hpp.html
+++ b/html/doxygen/symbol__properties_8hpp.html
@@ -210,7 +210,9 @@
nmodl::symtab::syminfo::NmodlType::discrete_block = 1LL << 31,
nmodl::symtab::syminfo::NmodlType::define = 1LL << 32,
nmodl::symtab::syminfo::NmodlType::codegen_var = 1LL << 33,
-
nmodl::symtab::syminfo::NmodlType::random_var = 1LL << 34
+
nmodl::symtab::syminfo::NmodlType::random_var = 1LL << 34,
+
+
nmodl::symtab::syminfo::NmodlType::use_range_ptr_var = 1LL << 35
}
| NMODL variable properties. More...
|
diff --git a/html/doxygen/symbol__properties_8hpp.js b/html/doxygen/symbol__properties_8hpp.js
index 1cf07779af..9e513d30d2 100644
--- a/html/doxygen/symbol__properties_8hpp.js
+++ b/html/doxygen/symbol__properties_8hpp.js
@@ -45,7 +45,8 @@ var symbol__properties_8hpp =
[ "discrete_block", "symbol__properties_8hpp.html#ad9b6b8559b36d0a500ef5110badcc4dbaeca37f2a89583c9c95ca500d9a3da84b", null ],
[ "define", "symbol__properties_8hpp.html#ad9b6b8559b36d0a500ef5110badcc4dbaf1edc500eb1136f10c17eeffb9eecbc5", null ],
[ "codegen_var", "symbol__properties_8hpp.html#ad9b6b8559b36d0a500ef5110badcc4dbaf502fdd34c60ff3223d4f18ec72f4cc8", null ],
- [ "random_var", "symbol__properties_8hpp.html#ad9b6b8559b36d0a500ef5110badcc4dba697324bc2a726114814b9ae77caa789a", null ]
+ [ "random_var", "symbol__properties_8hpp.html#ad9b6b8559b36d0a500ef5110badcc4dba697324bc2a726114814b9ae77caa789a", null ],
+ [ "use_range_ptr_var", "symbol__properties_8hpp.html#ad9b6b8559b36d0a500ef5110badcc4dba1cd9364d44a46a92179c359099d0e7c7", null ]
] ],
[ "Scope", "symbol__properties_8hpp.html#a901f9299d7c59b1694463d26928f2a75", [
[ "local", "symbol__properties_8hpp.html#a901f9299d7c59b1694463d26928f2a75af5ddaf0ca7929578b408c909429f68f2", null ],
diff --git a/html/doxygen/symbol__properties_8hpp_source.html b/html/doxygen/symbol__properties_8hpp_source.html
index ff48ade980..63a0fef468 100644
--- a/html/doxygen/symbol__properties_8hpp_source.html
+++ b/html/doxygen/symbol__properties_8hpp_source.html
@@ -316,84 +316,88 @@
-
-
-
-
226 template <
typename T>
-
-
-
229 return static_cast<T
>(~static_cast<utype>(arg));
-
-
-
232 template <
typename T>
-
-
-
235 return static_cast<T
>(
static_cast<utype
>(lhs) |
static_cast<utype
>(rhs));
-
-
-
238 template <
typename T>
-
-
-
241 return static_cast<T
>(
static_cast<utype
>(lhs) &
static_cast<utype
>(rhs));
-
-
-
244 template <
typename T>
-
-
-
-
-
-
250 template <
typename T>
-
-
-
-
-
-
-
-
258 return static_cast<bool>(obj & property);
-
-
-
-
-
263 return static_cast<bool>(obj & state);
-
-
-
-
-
-
-
+
+
+
+
+
+
+
229 template <
typename T>
+
+
+
232 return static_cast<T
>(~static_cast<utype>(arg));
+
+
+
235 template <
typename T>
+
+
+
238 return static_cast<T
>(
static_cast<utype
>(lhs) |
static_cast<utype
>(rhs));
+
+
+
241 template <
typename T>
+
+
+
244 return static_cast<T
>(
static_cast<utype
>(lhs) &
static_cast<utype
>(rhs));
+
+
+
247 template <
typename T>
+
+
+
+
+
+
253 template <
typename T>
+
+
+
+
+
+
+
+
261 return static_cast<bool>(obj & property);
+
+
+
+
+
266 return static_cast<bool>(obj & state);
+
+
+
+
-
-
-
-
275 template <
typename T>
-
-
-
-
-
-
-
-
-
284 text +=
" " + element;
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
278 template <
typename T>
+
+
+
+
+
+
+
+
+
287 text +=
" " + element;
+
+
+
+
+
+
+
+
-bool has_status(const Status &obj, Status state)
check if any status is set
+bool has_status(const Status &obj, Status state)
check if any status is set
VariableType
usage of mod file as array or scalar
@ from_state
derived from state
@ write
variable is written only
@ write_ion_var
Write Ion.
DeclarationType
kind of symbol
+@ use_range_ptr_var
FUNCTION or PROCEDURE needs setdata check.
@ extern_method
neuron solver methods and math functions
@ globalized
converted to global
@ thread_safe
variable marked as thread safe
@@ -406,7 +410,7 @@
@ constant_var
constant variable
@ to_solve
need to solve : used in solve statement
@ function_table_block
FunctionTable Block.
-T operator&(T lhs, T rhs)
+T operator&(T lhs, T rhs)
@ local_var
Local Variable.
Status
state during various compiler passes
Implement string manipulation functions.
@@ -415,7 +419,7 @@
@ scalar
scalar / single value
@ range_var
Range Variable.
-std::ostream & operator<<(std::ostream &os, const NmodlType &obj)
+std::ostream & operator<<(std::ostream &os, const NmodlType &obj)
@ kinetic_block
Kinetic Block.
@@ -426,9 +430,9 @@
@ define
Define variable / macro.
@ factor_def
factor in unit block
-std::string to_string(const T &obj)
+std::string to_string(const T &obj)
-T & operator&=(T &lhs, T rhs)
+T & operator&=(T &lhs, T rhs)
Scope
scope within a mod file
@ nonspecific_cur_var
Non Specific Current.
@@ -438,7 +442,7 @@
NmodlType
NMODL variable properties.
@ pointer_var
Pointer Type.
-T & operator|=(T &lhs, T rhs)
+T & operator|=(T &lhs, T rhs)
@ bbcore_pointer_var
Bbcorepointer Type.
@ state_var
state variable
@@ -450,16 +454,16 @@
std::vector< std::string > to_string_vector(const NmodlType &obj)
helper function to convert nmodl properties to string
@ random_var
Randomvar Type.
-T operator|(T lhs, T rhs)
+T operator|(T lhs, T rhs)
-
+
@ localized
converted to local
@ discrete_block
Discrete Block.
@ extern_neuron_variable
neuron variable accessible in mod file
@ electrode_cur_var
Electrode Current.
-bool has_property(const NmodlType &obj, NmodlType property)
check if any property is set
+bool has_property(const NmodlType &obj, NmodlType property)
check if any property is set
diff --git a/html/doxygen/sympy__solver__visitor_8cpp_source.html b/html/doxygen/sympy__solver__visitor_8cpp_source.html
index b36789f178..7f91ea93d3 100644
--- a/html/doxygen/sympy__solver__visitor_8cpp_source.html
+++ b/html/doxygen/sympy__solver__visitor_8cpp_source.html
@@ -841,7 +841,7 @@
ast::StatementBlock * block_with_expression_statements
block where expression statements appear (to check there is only one)
static void replace_diffeq_expression(ast::DiffEqExpression &expr, const std::string &new_expr)
replace binary expression with new expression provided as string
std::string get_node_name() const override
Return name of the node.
-
std::string to_string(const T &obj)
+
std::string to_string(const T &obj)
void visit_children(visitor::Visitor &v) override
visit children i.e.
void visit_var_name(ast::VarName &node) override
visit node of type ast::VarName
void visit_expression_statement(ast::ExpressionStatement &node) override
visit node of type ast::ExpressionStatement
diff --git a/html/doxygen/test_2unit_2codegen_2codegen__neuron__cpp__visitor_8cpp.html b/html/doxygen/test_2unit_2codegen_2codegen__neuron__cpp__visitor_8cpp.html
index af7b699ed0..a32d5696d7 100644
--- a/html/doxygen/test_2unit_2codegen_2codegen__neuron__cpp__visitor_8cpp.html
+++ b/html/doxygen/test_2unit_2codegen_2codegen__neuron__cpp__visitor_8cpp.html
@@ -102,6 +102,7 @@
#include "codegen/codegen_neuron_cpp_visitor.hpp"
#include "parser/nmodl_driver.hpp"
#include "test/unit/utils/test_utils.hpp"
+
#include "visitors/function_callpath_visitor.hpp"
#include "visitors/inline_visitor.hpp"
#include "visitors/neuron_solve_visitor.hpp"
#include "visitors/solve_block_visitor.hpp"
@@ -114,11 +115,13 @@
std::shared_ptr< CodegenNeuronCppVisitor > | create_neuron_cpp_visitor (const std::shared_ptr< ast::Program > &ast, const std::string &, std::stringstream &ss) |
| Helper for creating C codegen visitor. More...
|
|
-
std::string | get_neuron_cpp_code (const std::string &nmodl_text, const bool generate_gpu_code=false) |
-
| print entire code More...
|
-
|
+
std::string | get_neuron_cpp_code (const std::string &nmodl_text) |
+
| print entire code More...
|
+
|
| SCENARIO ("Check NEURON codegen for simple MOD file", "[codegen][neuron_boilerplate]") |
|
+
| SCENARIO ("Check whether PROCEDURE and FUNCTION need setdata call", "[codegen][needsetdata]") |
+
|