Fix Newton solver code generation#696
Conversation
|
Logfiles from GitLab pipeline #9336 (:white_check_mark:) have been uploaded here! Status and direct links: |
42c604b to
6f7f7f7
Compare
|
Logfiles from GitLab pipeline #9498 (:no_entry:) have been uploaded here! Status and direct links: |
|
Logfiles from GitLab pipeline #9500 (:white_check_mark:) have been uploaded here! Status and direct links: |
Codecov Report
@@ Coverage Diff @@
## master #696 +/- ##
=======================================
Coverage 60.47% 60.47%
=======================================
Files 200 200
Lines 33283 33345 +62
=======================================
+ Hits 20128 20167 +39
- Misses 13155 13178 +23
Continue to review full report at Codecov.
|
|
Logfiles from GitLab pipeline #9993 (:white_check_mark:) have been uploaded here! Status and direct links: |
|
Logfiles from GitLab pipeline #11672 (:white_check_mark:) have been uploaded here! Status and direct links: |
| // Create complete_block with both variable declarations (done in variable_block) and solver | ||
| // part (done in functor_block) to be able to run the SymtabVisitor and DefUseAnalyzeVisitor | ||
| // then and get the proper DUChains for the variables defined in the variable_block | ||
| ast::StatementBlock complete_block(functor_block); | ||
| // Typically variable_block has only one statement, a statement containing the declaration | ||
| // of the local variables | ||
| for (const auto& statement: variable_block.get_statements()) { | ||
| complete_block.insert_statement(complete_block.get_statements().begin(), statement); | ||
| } |
There was a problem hiding this comment.
Just as a suggestion: with the similar code, you can also create ast::Program and insert nodes into it. That will solve the problem that we were discussing.
There was a problem hiding this comment.
It's a bit pain to do this in the end. Simply adding the StatementBlocks to the Program doesn't work because then SymtabVisitor is crashing due to redefinition of LOCAL variables which are handled as GLOBAL being in the top level of the Program. Instead of this I created a new constructor for the SymtabVisitor to get an empty ModelSymbolTable and be able to process any kind of node.
There was a problem hiding this comment.
can't you just clone the variable block? Or are you filtering something out? I do not understand exactly why you do this copy. Clearly is intentional
There was a problem hiding this comment.
It's indeed optional. I am creating a new StatementBlock that just includes both the variable and functor_blocks
| if (modsymtab == nullptr) { | ||
| modsymtab = new symtab::ModelSymbolTable(); | ||
| } |
There was a problem hiding this comment.
see the previous comment about avoiding this.
|
may we add a small mod file that shows the problem in reduced_dentate? If I check the issue #691 I get a full repo and I do not know where is the problem |
This is the mod files I was testing this PR with https://github.com/pramodk/reduced_dentate/blob/master/mechanisms/Aradi_CadepK.mod |
cattabiani
left a comment
There was a problem hiding this comment.
I have a few questions and a suggestion for more unit tests. Overall very good job!
| // Create complete_block with both variable declarations (done in variable_block) and solver | ||
| // part (done in functor_block) to be able to run the SymtabVisitor and DefUseAnalyzeVisitor | ||
| // then and get the proper DUChains for the variables defined in the variable_block | ||
| ast::StatementBlock complete_block(functor_block); | ||
| // Typically variable_block has only one statement, a statement containing the declaration | ||
| // of the local variables | ||
| for (const auto& statement: variable_block.get_statements()) { | ||
| complete_block.insert_statement(complete_block.get_statements().begin(), statement); | ||
| } |
There was a problem hiding this comment.
can't you just clone the variable block? Or are you filtering something out? I do not understand exactly why you do this copy. Clearly is intentional
| if ((variable_type == DUVariableType::Global && | ||
| (child_state == DUState::U || child_state == DUState::D)) || | ||
| (variable_type == DUVariableType::Local && | ||
| (child_state == DUState::LU || child_state == DUState::LD))) { |
There was a problem hiding this comment.
can we have a DUState::LU or DUState::LD without being a local variable? Otherwise this can be simplified
There was a problem hiding this comment.
The discrimination between DUVariableType::Global and DUVariableType::Local is needed so that we can discard any LD or LU of the variable we are analyzing if it's not a local_var on the Symbol Table. I couldn't think of any better way to do this while being as explanatory as possible. It's certainly a quite complex analysis
There was a problem hiding this comment.
Just as a note: we discussed different alternatives to avoid introducing new DUVariableType (e.g. by using symbol table current_symtab directly. That avoids new type but we need some way to know the type).
We can go ahead with this implementation and revisit this if we see more use cases requiring further refactoring.
| if ((variable_type == DUVariableType::Global && child_state == DUState::U) || | ||
| (variable_type == DUVariableType::Local && child_state == DUState::LU)) { |
| if ((variable_type == DUVariableType::Global && child_state == DUState::D) || | ||
| (variable_type == DUVariableType::Local && child_state == DUState::LD) || | ||
| child_state == DUState::CD) { |
| /// Variable type processed by DefUseAnalyzeVisitor | ||
| enum class DUVariableType { Local, Global }; | ||
|
|
There was a problem hiding this comment.
is this necessary since it could be already specified with LU, LD
There was a problem hiding this comment.
EDIT: in this case maybe we could simplify, rework update_defuse_chain to use this new enum. Dunno
There was a problem hiding this comment.
Just to clarify, this enum is used to define whether we are looking for the L, U or CD states of variable if it's a global variable in the SymTab or LU, LD or CD if it's a local variable in the SymTab. I should add a comment about this here
| REQUIRE(chains[0].eval() == DUState::NONE); | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
a few questions:
- can you declare also GLOBAL inside the functor?
- may we have also the following tests:
- 2 local variables (used)
- 2 local variables (1 unused)
- 2 unused local variables
- no local variables
- a local variable in an IF ELSE block? Is it possible?
There was a problem hiding this comment.
I added a test that includes some of these cases that were not included before. I think it gives a good indication of how the DefUseAnalyzeVisitor works. Let me know if you want to add more cases 👍
GLOBAL variables are defined only in the NEURON block
there is not LOCAL inside a functor in this file. I do not connect the dots here. @iomaganaris ? |
The original problem is that in with NMODL master the function operator is while it writes variables which are members of the struct functor. |
|
Logfiles from GitLab pipeline #14671 (:no_entry:) have been uploaded here! Status and direct links: |
|
Logfiles from GitLab pipeline #14670 (:no_entry:) have been uploaded here! Status and direct links: |
|
Logfiles from GitLab pipeline #14674 (:no_entry:) have been uploaded here! Status and direct links: |
| if ((variable_type == DUVariableType::Global && | ||
| (child_state == DUState::U || child_state == DUState::D)) || | ||
| (variable_type == DUVariableType::Local && | ||
| (child_state == DUState::LU || child_state == DUState::LD))) { |
There was a problem hiding this comment.
Just as a note: we discussed different alternatives to avoid introducing new DUVariableType (e.g. by using symbol table current_symtab directly. That avoids new type but we need some way to know the type).
We can go ahead with this implementation and revisit this if we see more use cases requiring further refactoring.
|
Logfiles from GitLab pipeline #14773 (:no_entry:) have been uploaded here! Status and direct links: |
|
Logfiles from GitLab pipeline #14968 (:no_entry:) have been uploaded here! Status and direct links: |
|
Logfiles from GitLab pipeline #15023 (:white_check_mark:) have been uploaded here! Status and direct links: |
|
please retest |
we have discussed some of the comments and certain parts are already addressed.
* Fixes compilation issue when the operator() was declared as const while it changed some of values outside of its scope in the sympy solver * Use DefUseAnalyzeVisitor to find out whether the operator() is Using or Defining any of the variables outside its scope * Update DefUseAnalyzeVisitor to be able to process LOCAL variables as well, given precedence to GLOBAL/RANGE variables, when they have the same name * Added related unit tests * Fix codegen issue in CONSTRUCTOR and DESTRUCTOR blocks code when compiled for CoreNEURON Fixes BlueBrain/nmodl#691 FIxes BlueBrain/nmodl#692 NMODL Repo SHA: BlueBrain/nmodl@1321c7b
constqualifier to theoperator()offunctorstruct only if there is no external variable being defined inside the function#ifdef CORENEURON_BUILDin the code generated forCONSTRUCTORandDESTRUCTORDefUseAnalyzeVisitorto handle cases ofLOCALand GLOBAL` variables similar to this:In this case
taushould beDUState::Ufor example because as aGLOBALvariable we care about it's usage as aGLOBALvariable and not theLOCALvariabletauwhich is defined inside theIF-ELSEstatement.