Skip to content

Commit

Permalink
Avoid use of ion variable in the CONSTANT block
Browse files Browse the repository at this point in the history
* certain mod files use read/write ion variables
  from USEION statements in CONSTANT {} block
* the generated code from such usage is not desired
  I believe. For example, cdp_spiny.mod from ModelDB
  model id 266799 has

  ```console
  NEURON {
  	SUFFIX cdp4Nsp
   	USEION ca READ cao, cai, ica WRITE cai
   	RANGE ica_pmp,scale
	...
  }

  ASSIGNED {
     diam      (um)
     ica       (mA/cm2)
     ica_pmp   (mA/cm2)
     parea     (um)     : pump area per unit length
     cai       (mM)
  }

  CONSTANT { cao = 2  (mM) }
  ```

  In this example, the generated code doesn't set ion variable `cao` to 2
  but declare a static variable `cao` with value 2 and that is not used
  anywhere:

  ```cpp
   #define ica _p[56]
   #define ica_columnindex 56
   #define parea _p[57]
   #define parea_columnindex 57
   #define cai _p[58]
   ...
   #define _ion_cao    *_ppvar[0]._pval
   #define _ion_cai    *_ppvar[1]._pval
   #define _ion_ica    *_ppvar[2]._pval
   #define _style_ca   *((int*)_ppvar[3]._pvoid)
   #define diam    *_ppvar[4]._pval
   ...
   static double cao = 2;
   ...
   static void nrn_state(NrnThread* _nt, _Memb_list* _ml, int _type) {

	...
	cao = _ion_cao;
        cai = _ion_cai;
        ica = _ion_ica;
        cai = _ion_cai;
        ...
   }
  ```

  Note that `cao` variable used/updated here is not ion variable but static one
  defined in the file scope.

  I believe this is not what user "expected" here.

* As we see this pattern in multiple mod files (including glia__dbbs_mod_collection__cdp5__CAM_GoC.mod
  mentioned in BlueBrain/nmodl#888), in this PR we disable
  declaring ion variables as CONSTANT. With this PR, we will get an error like:

  ```console
   $ ./bin/nocmodl /.../nmodldb/models/db/modeldb/266799/mod/cdp_spiny.mod
   ...
   cao used in USEION statement can not be re-declared in the CONSTANT block at line 299 in file /.../nmodldb/models/db/modeldb/266799/mod/cdp_spiny.mod
   ```
  • Loading branch information
pramodk committed Aug 17, 2022
1 parent fd31b25 commit 45dd314
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/nmodl/modl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ no longer adequate for saying we can not */
#endif
chk_thread_safe();
chk_global_state();
check_useion_variables();

parout(); /* print .var file.
* Also #defines which used to be in defs.h
* are printed into .c file at beginning.
Expand Down
1 change: 1 addition & 0 deletions src/nmodl/nmodlfunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ void net_init(Item* qinit, Item* qp2);
void fornetcon(Item* keyword, Item* par1, Item* args, Item* par2, Item* stmt, Item* qend);
void chk_thread_safe();
void chk_global_state();
void check_useion_variables();
void threadsafe_seen(Item* q1, Item* q2);
void explicit_decl(int level, Item* q);
void parm_array_install(Symbol* n, char* num, char* units, char* limits, int index);
Expand Down
36 changes: 36 additions & 0 deletions src/nmodl/nocpout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,42 @@ static void _destructor(Prop* _prop) {\n\
}
}


// Check if read/write variable from USEION is declared in a
// CONSTANT block. There are certain MOD files where this pattern
// is used and it doesn't produce a desired code. Hence, we check
// all ion variables and error if any variable is declared as CONSTANT.
void check_ion_vars_as_constant(char* ion_name, const List* ion_var_list) {
const Item* var;
ITERATE(var, ion_var_list) {
const Symbol *var_sym = SYM(var);
int type = iontype(var_sym->name, ion_name);
if (type == IONIN ||
type == IONOUT ||
type == IONCUR ||
type == IONCONC ||
type == IONEREV) {
if (var_sym->subtype & nmodlCONST) {
diag(var_sym->name, " used in USEION statement can not be re-declared in a CONSTANT block");
}
}
}
}


// check semantics of read & write variables from USEION statements
void check_useion_variables() {
const Item *ion_var;
ITERATE(ion_var, useion) {
// read variables
check_ion_vars_as_constant(SYM(ion_var)->name, LST(ion_var->next));
// write variables
check_ion_vars_as_constant(SYM(ion_var)->name, LST(ion_var->next->next));
ion_var = ion_var->next->next->next;
}
}


void warn_ignore(Symbol* s) {
int b;
double d1, d2;
Expand Down

0 comments on commit 45dd314

Please sign in to comment.