1 #include <../../nmodlconf.h> 70 #define GETWD(buf) getcwd(buf, NRN_BUFSIZE) 92 #define NRNPRANGEIN 020 93 #define NRNPRANGEOUT 040 94 #define NRNGLOBAL 0100 95 #define NRNSTATIC 0200 97 #define NRNIONFLAG 01000 99 #define NRNSECTION 02000 100 #define NRNPOINTER 04000 101 #define IONCONC 010000 102 #define NRNBBCOREPOINTER 020000 159 int iontype(
char* s1,
char* s2);
175 List* state_discon_list_;
177 static int cvode_emit, cvode_ieq_index;
178 static int cond_index;
179 static int tqitem_index;
180 static int watch_index;
181 static int cvode_index;
182 static List* ion_synonym;
183 extern int singlechan_;
190 static Item* net_send_delivered_;
194 #define SYMITER(arg) ITERATE(q, syminorder){ \ 195 s = SYM(q); if (s->type == arg) 197 #define SYMLISTITER for (i = 'A'; i <= 'z'; i++)\ 198 ITERATE(q, symlist[i]) 200 #define IFTYPE(arg) if ((s->subtype & arg)\ 201 && ( (s->usage & EXPLICIT_DECL) != automatic) ) 210 extern int using_default_indep;
217 using_default_indep = 0;
219 using_default_indep = 1;
221 thread_cleanup_list =
newlist();
222 thread_mem_init_list =
newlist();
226 int i,
j, ioncount, pointercount, gind, emit_check_table_thread;
238 #if 1 || defined(__MINGW32__) 245 for (modbase = modprefix + strlen(modprefix); modbase !=
modprefix;
247 if (*modbase ==
'\\' || *modbase ==
'/') {
255 }
else if (strcmp(
mechname,
"nothing") == 0) {
264 fprintf(stderr,
"Notice: ARTIFICIAL_CELL models that would require thread specific data are not thread safe.\n");
274 \n#if METHOD3\nextern int _method3;\n#endif\n\ 277 \n#define exp hoc_Exp\nextern double hoc_Exp(double);\ 281 Lappendstr(defs_list,
"\n#include \"nmodlmutex.h\"");
287 #define nrn_init _nrn_init_%s\n\ 288 #define _nrn_initial _nrn_initial_%s\n\ 289 #define nrn_cur _nrn_cur_%s\n\ 290 #define _nrn_current _nrn_current_%s\n\ 291 #define nrn_jacob _nrn_jacob_%s\n\ 292 #define nrn_state _nrn_state_%s\n\ 293 #define _net_receive _net_receive_%s\ 309 #define _threadargscomma_ _p, _ppvar, _thread, _nt,\n\ 310 #define _threadargsprotocomma_ double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt,\n\ 311 #define _threadargs_ _p, _ppvar, _thread, _nt\n\ 312 #define _threadargsproto_ double* _p, Datum* _ppvar, Datum* _thread, NrnThread* _nt\n\ 316 #define _threadargscomma_ /**/\n\ 317 #define _threadargsprotocomma_ /**/\n\ 318 #define _threadargs_ /**/\n\ 319 #define _threadargsproto_ /**/\n\ 328 Lappendstr(defs_list,
"extern double *getarg();\n");
331 Sprintf(
buf,
"/* Thread safe. No static _p or _ppvar. */\n");
335 Sprintf(
buf,
"static double *_p; static Datum *_ppvar;\n");
342 ioncount =
iondef(&pointercount);
343 Lappendstr(defs_list,
"\n#if MAC\n#if !defined(v)\n#define v _mlhv\n#endif\n#if !defined(h)\n#define h _mlhh\n#endif\n#endif\n");
344 Lappendstr(defs_list,
"\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n");
345 Lappendstr(defs_list,
"static int hoc_nrnpointerindex = ");
347 q = nrnpointers->
next;
356 Lappendstr(defs_list,
"static Datum* _extcall_thread;\n static Prop* _extcall_prop;\n");
359 Lappendstr(defs_list,
"/* static variables special to NEURON */\n");
367 Lappendstr(defs_list,
"/* external NEURON variables */\n");
371 if (strcmp(s->
name,
"dt") == 0) {
continue; }
372 if (strcmp(s->
name,
"t") == 0) {
continue; }
382 Lappendstr(defs_list,
"/* declaration of user functions */\n");
395 Lappendstr(defs_list,
"static int _mechtype;\n\ 396 extern void _nrn_cacheloop_reg(int, int);\n\ 397 extern void hoc_register_prop_size(int, int, int);\n\ 398 extern void hoc_register_limits(int, HocParmLimits*);\n\ 399 extern void hoc_register_units(int, HocParmUnits*);\n\ 400 extern void nrn_promote(Prop*, int, int);\n\ 401 extern Memb_func* memb_func;\n\ 406 "#define NMODL_TEXT 1\n" 408 "static const char* nmodl_file_text;\n" 409 "static const char* nmodl_filename;\n" 410 "extern void hoc_reg_nmodl_text(int, const char*);\n" 411 "extern void hoc_reg_nmodl_filename(int, const char*);\n" 418 Lappendstr(defs_list,
"extern Prop* nrn_point_prop_;\n");
419 Lappendstr(defs_list,
"static int _pointtype;\n");
420 Lappendstr(defs_list,
"static void* _hoc_create_pnt(Object* _ho) { void* create_point_process(int, Object*);\n");
421 Lappendstr(defs_list,
"return create_point_process(_pointtype, _ho);\n}\n");
422 Lappendstr(defs_list,
"static void _hoc_destroy_pnt(void*);\n");
423 Lappendstr(defs_list,
"static double _hoc_loc_pnt(void* _vptr) {double loc_point_process(int, void*);\n");
424 Lappendstr(defs_list,
"return loc_point_process(_pointtype, _vptr);\n}\n");
425 Lappendstr(defs_list,
"static double _hoc_has_loc(void* _vptr) {double has_loc_point(void*);\n");
426 Lappendstr(defs_list,
"return has_loc_point(_vptr);\n}\n");
427 Lappendstr(defs_list,
"static double _hoc_get_loc_pnt(void* _vptr) {\n");
428 Lappendstr(defs_list,
"double get_loc_point_process(void*); return (get_loc_point_process(_vptr));\n}\n");
431 Lappendstr(defs_list,
"extern void _nrn_setdata_reg(int, void(*)(Prop*));\n");
432 Lappendstr(defs_list,
"static void _setdata(Prop* _prop) {\n");
435 Lappendstr(defs_list,
"_extcall_prop = _prop;\n");
439 Lappendstr(defs_list,
"_p = _prop->param; _ppvar = _prop->dparam;\n");
444 Lappendstr(defs_list,
"static void _hoc_setdata(void* _vptr) { Prop* _prop;\n");
445 Lappendstr(defs_list,
"_prop = ((Point_process*)_vptr)->_prop;\n");
447 Lappendstr(defs_list,
"static void _hoc_setdata() {\n Prop *_prop, *hoc_getdata_range(int);\n");
448 Sprintf(
buf,
"_prop = hoc_getdata_range(_mechtype);\n");
455 Lappendstr(defs_list,
"hoc_retpushx(1.);\n}\n");
459 Lappendstr(defs_list,
"/* connect user functions to hoc names */\n");
460 Lappendstr(defs_list,
"static VoidFunc hoc_intfunc[] = {\n");
463 Lappendstr(defs_list,
"static Member_func _member_func[] = {\n");
468 Sprintf(
buf,
"\"get_loc\", _hoc_get_loc_pnt,\n");
504 Lappendstr(defs_list,
"_threadargsprotocomma_");
509 for (j=0; j < s->
varnum; ++
j) {
520 emit_check_table_thread = 0;
522 emit_check_table_thread = 1;
531 if (
SYM(q)->assigned_to_ != 2) {
533 cnt +=
SYM(q)->araydim;
545 if (
SYM(q)->assigned_to_ != 2) {
548 cnt +=
SYM(q)->araydim;
568 if (s->nrntype & (
NRNGLOBAL) && s->assigned_to_ == 1) {
577 Lappendstr(defs_list,
"/* declare global and static user variables */\n");
581 sprintf(
buf,
" if (_thread1data_inuse) {_thread[_gth]._pval = (double*)ecalloc(%d, sizeof(double));\n }else{\n _thread[_gth]._pval = _thread1data; _thread1data_inuse = 1;\n }\n", gind);
583 lappendstr(thread_cleanup_list,
" if (_thread[_gth]._pval == _thread1data) {\n _thread1data_inuse = 0;\n }else{\n free((void*)_thread[_gth]._pval);\n }\n");
592 sprintf(
buf,
"#define %s%s (_thread1data + %d)\n\ 593 #define %s (_thread[_gth]._pval + %d)\n",
596 sprintf(
buf,
"#define %s%s _thread1data[%d]\n\ 597 #define %s _thread[_gth]._pval[%d]\n",
624 Lappendstr(defs_list,
"/* some parameters have upper and lower limits */\n");
625 Lappendstr(defs_list,
"static HocParmLimits _hoc_parm_limits[] = {\n");
649 diag(
"No statics allowed for thread safe models:", s->
name);
661 Lappendstr(defs_list,
"/* connect global user variables to hoc */\n");
662 Lappendstr(defs_list,
"static DoubScal hoc_scdoub[] = {\n");
673 Lappendstr(defs_list,
"static DoubVec hoc_vdoub[] = {\n");
682 Lappendstr(defs_list,
"static double _sav_indep;\n");
684 Lappendstr(defs_list,
"static void _ba1(Node*_nd, double* _pp, Datum* _ppd, Datum* _thread, NrnThread* _nt)");
686 sprintf(
buf,
", _ba%d(Node*_nd, double* _pp, Datum* _ppd, Datum* _thread, NrnThread* _nt)", i);
695 Lappendstr(defs_list,
"static void nrn_alloc(Prop*);\nstatic void nrn_init(NrnThread*, _Memb_list*, int);\nstatic void nrn_state(NrnThread*, _Memb_list*, int);\n\ 698 Lappendstr(defs_list,
"static void nrn_cur(NrnThread*, _Memb_list*, int);\nstatic void nrn_jacob(NrnThread*, _Memb_list*, int);\n");
703 if (net_send_seen_) {
710 for (i=0; i < watch_seen_ ; ++
i) {
714 sprintf(
buf,
"\n#define _watch_array _ppvar + %d", watch_index);
717 Lappendstr(defs_list,
"static void _watch_alloc(Datum*);\n");
718 Lappendstr(defs_list,
"extern void hoc_reg_watch_allocate(int, void(*)(Datum*));");
729 Lappendstr(defs_list,
"static void _hoc_destroy_pnt(void* _vptr) {\n");
731 Lappendstr(defs_list,
" Prop* _prop = ((Point_process*)_vptr)->_prop;\n");
734 sprintf(
buf,
" if (_prop) { _nrn_free_watch(_prop->dparam, %d, %d);}\n", watch_index, watch_seen_);
738 sprintf(
buf,
" if (_prop) { _nrn_free_fornetcon(&(_prop->dparam[_fnc_index]._pvoid));}\n");
741 Lappendstr(defs_list,
" destroy_point_process(_vptr);\n}\n");
752 diag(
"DESTRUCTOR only permitted for POINT_PROCESS", (
char*)0);
754 Lappendstr(defs_list,
"static void _destructor(Prop*);\n");
758 Lappendstr(defs_list,
"static void _constructor(Prop*);\n");
762 "/* connect range variables in _p that hoc is supposed to know about */\n");
764 static const char *_mechanism[] = {\n\ 815 Lappendstr(defs_list,
"static Symbol* _morphology_sym;\n");
818 Lappendstr(defs_list,
"extern Node* nrn_alloc_node_;\n");
832 extern Prop* need_memb(Symbol*);\n\n\ 833 static void nrn_alloc(Prop* _prop) {\n\ 835 double *_p; Datum *_ppvar;\n\ 838 Lappendstr(defs_list,
" if (nrn_point_prop_) {\n\ 839 _prop->_alloc_seq = nrn_point_prop_->_alloc_seq;\n\ 840 _p = nrn_point_prop_->param;\n\ 841 _ppvar = nrn_point_prop_->dparam;\n }else{\n");
845 Lappendstr(defs_list,
" /*initialize range parameters*/\n");
858 Lappendstr(defs_list,
"\t_prop->param = _p;\n");
863 Lappendstr(defs_list,
" if (!nrn_point_prop_) {\n");
870 Lappendstr(defs_list,
"\t_prop->dparam = _ppvar;\n");
871 Lappendstr(defs_list,
"\t/*connect ionic variables to this model*/\n");
874 Sprintf(
buf,
"prop_ion = need_memb(_morphology_sym);\n");
877 "\t_ppvar[%d]._pval = &prop_ion->param[0]; /* diam */\n",
878 ioncount + pointercount),
884 "\t_ppvar[%d]._pval = &nrn_alloc_node_->_area; /* diam */\n",
885 ioncount + pointercount +
diamdec),
910 "\t_ppvar[%d]._pval = &prop_ion->param[%d]; /* %s */\n",
920 SYM(q1)->nrntype &= ~NRNIONFLAG;
923 "\t_ppvar[%d]._pval = &prop_ion->param[%d]; /* %s */\n",
924 ioncount++, itype,
SYM(q1)->
name);
930 "\t_ppvar[%d]._pval = &prop_ion->param[%d]; /* _ion_di%sdv */\n",
940 "\t_ppvar[%d]._pvoid = (void*)(&(prop_ion->dparam[0]._i)); /* iontype for %s */\n",
941 ioncount++, sion->
name);
945 if (!dcurdef && ldifuslist) {
947 "\t_ppvar[%d]._pval = &prop_ion->param[%d]; /* _ion_di%sdv */\n",
954 Lappendstr(defs_list,
"if (!nrn_point_prop_) {_constructor(_prop);}\n");
957 static void _constructor(Prop* _prop) {\n\ 958 double* _p; Datum* _ppvar; Datum* _thread;\n\ 959 _thread = (Datum*)0;\n\ 960 _p = _prop->param; _ppvar = _prop->dparam;\n\ 965 static void _constructor(Prop* _prop) {\n\ 966 _p = _prop->param; _ppvar = _prop->dparam;\n\ 975 Lappendstr(defs_list,
"static void _initlists();\n");
978 Lappendstr(defs_list,
" /* some states have an absolute tolerance */\n");
979 Lappendstr(defs_list,
"static Symbol** _atollist;\n");
980 Lappendstr(defs_list,
"static HocStateTolerance _hoc_state_tol[] = {\n");
996 sprintf(
buf,
"static _singlechan_declare%d();\n", singlechan_);
1002 if (net_send_seen_) {
1004 diag(
"can't use net_send if there is no NET_RECEIVE block", (
char*)0);
1006 sprintf(
buf,
"\n#define _tqitem &(_ppvar[%d]._pvoid)\n", tqitem_index);
1008 if (net_send_delivered_) {
1009 insertstr(net_send_delivered_,
" if (_lflag == 1. ) {*(_tqitem) = 0;}\n");
1013 Lappendstr(defs_list,
"static void _net_receive(Point_process*, double*, double);\n");
1015 Lappendstr(defs_list,
"extern int _nrn_netcon_args(void*, double***);\n");
1018 Lappendstr(defs_list,
"static void _net_init(Point_process*, double*, double);\n");
1021 if (
vectorize && thread_mem_init_list->
next != thread_mem_init_list) {
1022 Lappendstr(defs_list,
"static void _thread_mem_init(Datum*);\n");
1024 if (
vectorize && thread_cleanup_list->
next != thread_cleanup_list) {
1025 Lappendstr(defs_list,
"static void _thread_cleanup(Datum*);\n");
1028 lappendstr(defs_list,
"static void _update_ion_pointer(Datum*);\n");
1031 lappendstr(defs_list,
"static void bbcore_write(double*, int*, int*, int*, _threadargsproto_);\n");
1032 lappendstr(defs_list,
"extern void hoc_reg_bbcore_write(int, void(*)(double*, int*, int*, int*, _threadargsproto_));\n");
1033 lappendstr(defs_list,
"static void bbcore_read(double*, int*, int*, int*, _threadargsproto_);\n");
1034 lappendstr(defs_list,
"extern void hoc_reg_bbcore_read(int, void(*)(double*, int*, int*, int*, _threadargsproto_));\n");
1037 extern Symbol* hoc_lookup(const char*);\n\ 1038 extern void _nrn_thread_reg(int, int, void(*)(Datum*));\n\ 1039 extern void _nrn_thread_table_reg(int, void(*)(double*, Datum*, Datum*, NrnThread*, int));\n\ 1040 extern void hoc_register_tolerance(int, HocStateTolerance*, Symbol***);\n\ 1041 extern void _cvode_abstol( Symbol**, double*, int);\n\n\ 1044 int _vectorized = %d;\n", modbase,
vectorize);
1049 Sprintf(
buf,
"void _%s_reg() {\n _initlists();\n", modbase);
1062 Lappendstr(defs_list,
"\t_morphology_sym = hoc_lookup(\"morphology\");\n");
1065 Sprintf(
buf,
"\t_%s_sym = hoc_lookup(\"%s_ion\");\n",
1073 _pointtype = point_register_mech(_mechanism,\n\ 1074 nrn_alloc,%s, nrn_init,\n\ 1075 hoc_nrnpointerindex, %d,\n\ 1076 _hoc_create_pnt, _hoc_destroy_pnt, _member_func);\n",
1080 Lappendstr(defs_list,
" register_destructor(_destructor);\n");
1090 if (thread_mem_init_list->
next != thread_mem_init_list) {
1091 Lappendstr(defs_list,
" _thread_mem_init(_extcall_thread);\n");
1092 if (gind) {
Lappendstr(defs_list,
" _thread1data_inuse = 0;\n");}
1096 Lappendstr(defs_list,
"_mechtype = nrn_get_mechtype(_mechanism[1]);\n");
1097 lappendstr(defs_list,
" _nrn_setdata_reg(_mechtype, _setdata);\n");
1098 if (
vectorize && thread_mem_init_list->
next != thread_mem_init_list) {
1099 lappendstr(defs_list,
" _nrn_thread_reg(_mechtype, 1, _thread_mem_init);\n");
1101 if (
vectorize && thread_cleanup_list->
next != thread_cleanup_list) {
1102 lappendstr(defs_list,
" _nrn_thread_reg(_mechtype, 0, _thread_cleanup);\n");
1105 lappendstr(defs_list,
" _nrn_thread_reg(_mechtype, 2, _update_ion_pointer);\n");
1107 if (emit_check_table_thread) {
1108 lappendstr(defs_list,
" _nrn_thread_table_reg(_mechtype, _check_table_thread);\n");
1111 lappendstr(defs_list,
" hoc_reg_bbcore_write(_mechtype, bbcore_write);\n");
1112 lappendstr(defs_list,
" hoc_reg_bbcore_read(_mechtype, bbcore_read);\n");
1115 lappendstr(defs_list,
"#if NMODL_TEXT\n hoc_reg_nmodl_text(_mechtype, nmodl_file_text);\n hoc_reg_nmodl_filename(_mechtype, nmodl_filename);\n#endif\n");
1120 Lappendstr(defs_list,
" hoc_reg_watch_allocate(_mechtype, _watch_alloc);\n");
1122 if (ppvar_semantics_)
ITERATE(q, ppvar_semantics_) {
1123 sprintf(
buf,
" hoc_register_dparam_semantics(_mechtype, %d, \"%s\");\n",
1141 Lappendstr(defs_list,
"\tnrn_writes_conc(_mechtype, 0);\n");
1147 hoc_register_cvode(_mechtype, _ode_count, _ode_map, _ode_spec, _ode_matsol);\n");
1149 hoc_register_tolerance(_mechtype, _hoc_state_tol, &_atollist);\n");
1151 Lappendstr(defs_list,
" hoc_register_synonym(_mechtype, _ode_synonym);\n");
1155 hoc_register_cvode(_mechtype, _ode_count, 0, 0, 0);\n");
1158 sprintf(
buf,
"hoc_reg_singlechan(_mechtype, _singlechan_declare%d);\n", singlechan_);
1164 || nrnpointers->
next != nrnpointers
1165 || useion->
next != useion
1168 "Notice: ARTIFICIAL_CELL is a synonym for POINT_PROCESS which hints that it\n\ 1169 only affects and is affected by discrete events. As such it is not\n\ 1170 located in a section and is not associated with an integrator\n" 1173 sprintf(
buf,
"add_nrn_artcell(_mechtype, %d);\n", tqitem_index);
1176 if (net_event_seen_) {
1177 Lappendstr(defs_list,
"add_nrn_has_net_event(_mechtype);\n");
1180 Lappendstr(defs_list,
"pnt_receive[_mechtype] = _net_receive;\n");
1182 Lappendstr(defs_list,
"pnt_receive_init[_mechtype] = _net_init;\n");
1188 sprintf(
buf,
"add_nrn_fornetcons(_mechtype, _fnc_index);\n");
1197 #if EXTRACELLULAR\n\ 1198 if (_nd->_extnode) {\n\ 1199 v = NODEV(_nd) +_nd->_extnode->_v[0];\n\ 1220 sprintf(
buf,
"\thoc_reg_ba(_mechtype, _ba%d, %s);\n", i,
STR(q));
1224 Lappendstr(defs_list,
"\thoc_register_ldifus1(_difusfunc);\n");
1225 Linsertstr(defs_list,
"static void _difusfunc(ldifusfunc2_t, NrnThread*);\n");
1229 hoc_register_var(hoc_scdoub, hoc_vdoub, hoc_intfunc);\n");
1233 #if HAVE_REALPATH && !defined(NRN_AVOID_ABSOLUTE_PATHS) 1237 if(pf) { free(pf); }
1241 Lappendstr(defs_list,
"hoc_register_limits(_mechtype, _hoc_parm_limits);\n");
1242 Lappendstr(defs_list,
"hoc_register_units(_mechtype, _hoc_parm_units);\n");
1245 if (
vectorize && thread_mem_init_list->
next != thread_mem_init_list) {
1250 if (
vectorize && thread_cleanup_list->
next != thread_cleanup_list) {
1261 static void _destructor(Prop* _prop) {\n\ 1262 double* _p; Datum* _ppvar; Datum* _thread;\n\ 1263 _thread = (Datum*)0;\n\ 1264 _p = _prop->param; _ppvar = _prop->dparam;\n\ 1269 static void _destructor(Prop* _prop) {\n\ 1270 _p = _prop->param; _ppvar = _prop->dparam;\n\ 1293 if (strcmp(s->
name,
"v") == 0) b = 1;
1296 if (d1 == 0.0) b = 0;
1298 printf(
"Warning: Default %g of PARAMETER %s will be ignored and set by NEURON.\n", d1, s->
name);
1303 Item*
q, *qdexp, *qb1, *qvexp, *qb2, *q1;
1304 char* cfindex, *dfdcur;
1317 cfindex =
STR(q); q = q->
next;
1320 sprintf(
buf,
"static void* _difspace%d;\nextern double nrn_nernst_coef();\n\ 1321 static double _difcoef%d(int _i, double* _p, Datum* _ppvar, double* _pdvol, double* _pdfcdc, Datum* _thread, NrnThread* _nt) {\n \ 1324 for (q1 = qvexp; q1 != qb2; q1 = q1->
next) {
1329 if (_i == %s) {\n *_pdfcdc = %s;\n }else{ *_pdfcdc=0.;}\n", cfindex, dfdcur);
1335 for (q1 = qdexp; q1 != qb1; q1 = q1->
next) {
1340 lappendstr(
procfunc,
"static void _difusfunc(ldifusfunc2_t _f, NrnThread* _nt) {int _i;\n");
1348 cfindex =
STR(q); q = q->
next;
1354 sprintf(
buf,
" for (_i=0; _i < %d; ++_i) mac_difusfunc(_f, _mechtype, _difcoef%d, &_difspace%d, _i, ", s->
araydim, n, n);
1356 sprintf(
buf,
" for (_i=0; _i < %d; ++_i) (*_f)(_mechtype, _difcoef%d, &_difspace%d, _i, ", s->
araydim, n, n);
1360 sprintf(
buf,
" mac_difusfunc(_f,_mechtype, _difcoef%d, &_difspace%d, 0, ", n, n);
1362 sprintf(
buf,
" (*_f)(_mechtype, _difcoef%d, &_difspace%d, 0, ", n, n);
1372 - (s->ioncount_ + 1), d->
varnum);
1390 for (n=0, cp = sym->
u.
str; *cp; ++cp) {
1399 i = sscanf(cp,
"%lf %lf\n", pg1, pg2);
1414 for (n=0, cp = sym->
u.
str; *cp; ++cp) {
1423 i = sscanf(cp,
"%lf\n", pg1);
1443 i = sscanf(sym->
u.
str,
"[%*d]\n%lf%*c%lf", pg1, pg2);
1445 i = sscanf(sym->
u.
str,
"%lf%*c%lf", pg1, pg2);
1448 for (n=0, cp = sym->
u.
str; n < 2;) {
1449 if (*cp++ ==
'\n') {
1453 for (cp1 = s; *cp !=
'\n';) {
1462 i = sscanf(sym->
u.
str,
"[%*d]\n%lf\n%s", pg1, s);
1464 i = sscanf(sym->
u.
str,
"%lf\n%s", pg1, s);
1473 diag(sym->
name,
" does not have a proper declaration");
1475 if (s[0] ==
'0') {s[0] =
'\0';}
1484 Lappendstr(defs_list,
"static HocParmUnits _hoc_parm_units[] = {\n");
1562 switch (
SYM(q1)->type) {
1572 if (strcmp(
SYM(q1)->
name,
"POINT_PROCESS") == 0) {
1574 }
else if (strcmp(
SYM(q1)->
name,
"ARTIFICIAL_CELL") == 0) {
1579 case ELECTRODE_CURRENT:
1588 diag(
"NEURON SECTION variables not implemented", (
char *)0);
1598 threadsafe(
"Use of EXTERNAL is not thread safe.");
1606 threadsafe(
"Use of POINTER is not thread safe.");
1613 threadsafe(
"Use of BBCOREPOINTER is not thread safe.");
1638 sprintf(
buf,
"static void _ba%d(Node*_nd, double* _pp, Datum* _ppd, Datum* _thread, NrnThread* _nt) ", ++
ba_index_);
1642 qv =
insertstr(q,
"_p = _pp; _ppvar = _ppd;\n");
1645 ba = (ba == BEFORE) ? 10 : 20;
1646 ba += (type == BREAKPOINT) ? 1 : 0;
1647 ba += (type == SOLVE) ? 2 : 0;
1648 ba += (type == INITIAL1) ? 3 : 0;
1649 ba += (type == STEP) ? 4 : 0;
1672 List *readlist, *writelist;
1679 diag(
"mergeing of neuron models not supported yet", (
char *)0);
1692 LST(qw) = writelist;
1733 if (strcmp(
buf, s1) == 0) {
1737 if (strcmp(
buf, s1) == 0) {
1741 if (strcmp(
buf, s1) == 0) {
1745 if (strcmp(
buf, s1) == 0) {
1748 Sprintf(
buf,
"%s is not a valid ionic variable for %s", s1, s2);
1768 s=
lookup(
"diam");
if (s) {
1770 diag(s->
name,
"cannot be a RANGE or GLOBAL variable for this mechanism");
1774 s=
lookup(
"area");
if (s) {
1776 diag(s->
name,
"cannot be a RANGE or GLOBAL variable for this mechanism");
1794 vectorize_substitute(
lappendstr(defs_list,
"\n#define t nrn_threads->_t\n#define dt nrn_threads->_dt\n"),
"\n#define t _nt->_t\n#define dt _nt->_dt\n");
1798 s=
lookup(
"celcius");
if (s)
diag(
"celcius should be spelled celsius",
1803 if (s->
type == NAME || s->
type == PRIME) {
1812 if (s != indepsym && !s->nrntype) {
1836 for (q = ((
Item *)range)->
next; q != (
Item *)range; q = q1) {
1887 Item *
q, *q1, *qconc;
1931 if (block == 2 && qconc) {
1935 }
else if (ic ==
IONOUT) {
1941 Sprintf(
buf,
" nrn_wrote_conc(_%s_sym, (&(_ion_%s)) - %d, _style_%s);\n",
1942 in,
SYM(qconc)->
name, ic, in);
1967 Fprintf(stderr,
"WARNING: Dimensions may be wrong for READ %s with POINT_PROCESS\n",
SYM(q1)->
name);
1975 if (
SYM(q1)->nrntype & IONCONC) {
1981 Fprintf(stderr,
"WARNING: WRITE %s with it a STATE may not be translated correctly\n",
SYM(q1)->
name);
1991 int ioncount, it, need_style;
1999 q =
lappendstr(defs_list,
"#define _nd_area *_ppvar[0]._pval\n");
2008 lappendstr(uip,
"extern void nrn_update_ion_pointer(Symbol*, Datum*, int, int);\n");
2009 lappendstr(uip,
"static void _update_ion_pointer(Datum* _ppvar) {\n");
2017 Sprintf(
buf,
"#define _ion_%s *_ppvar[%d]._pval\n",
2021 sprintf(
buf,
" nrn_update_ion_pointer(_%s_sym, _ppvar, %d, %d);\n",
2024 SYM(q1)->ioncount_ = ioncount;
2031 SYM(q1)->nrntype &= ~NRNIONFLAG;
2033 Sprintf(
buf,
"#define _ion_%s *_ppvar[%d]._pval\n",
2037 sprintf(
buf,
" nrn_update_ion_pointer(_%s_sym, _ppvar, %d, %d);\n",
2040 SYM(q1)->ioncount_ = ioncount;
2047 Sprintf(
buf,
"#define _ion_di%sdv\t*_ppvar[%d]._pval\n", sion->
name, ioncount);
2050 sprintf(
buf,
" nrn_update_ion_pointer(_%s_sym, _ppvar, %d, 4);\n",
2051 sion->
name, ioncount);
2061 Sprintf(
buf,
"#define _style_%s\t*((int*)_ppvar[%d]._pvoid)\n", sion->
name, ioncount);
2069 if (!dcurdef && ldifuslist) {
2070 Sprintf(
buf,
"#define _ion_di%sdv\t*_ppvar[%d]._pval\n", sion->
name, ioncount);
2073 sprintf(
buf,
" nrn_update_ion_pointer(_%s_sym, _ppvar, %d, 4);\n",
2074 sion->
name, ioncount);
2080 *p_pointercount = 0;
2083 Sprintf(
buf,
"#define %s *_ppvar[%d]._pval\n",
2084 sion->
name, ioncount + *p_pointercount);
2085 sion->
used = ioncount + *p_pointercount;
2088 Sprintf(
buf,
"#define _p_%s _ppvar[%d]._pval\n",
2089 sion->
name, ioncount + *p_pointercount);
2090 sion->
used = ioncount + *p_pointercount;
2098 (*p_pointercount)++;
2102 Sprintf(
buf,
"#define diam *_ppvar[%d]._pval\n", ioncount + *p_pointercount);
2108 Sprintf(
buf,
"#define area *_ppvar[%d]._pval\n", ioncount+ *p_pointercount +
diamdec);
2118 if (!ppvar_semantics_) { ppvar_semantics_ =
newlist(); }
2119 q =
Lappendstr(ppvar_semantics_, const_cast<char*>(name));
2125 Item *
q, *q1, *qbrak;
2132 strion =
SYM(q)->name;
2157 strion =
SYM(q)->name;
2162 Sprintf(
buf,
" _ion_di%sdv += (_di%s - %s)/%s",
2163 strion, strion,
SYM(q1)->
name, strdel);
2186 in =
SYM(qion)->name;
2198 if (type ==
IONIN) {
2199 Lappendstr(defs_list,
"nrn_check_conc_write(_prop, prop_ion, 1);\n");
2203 Lappendstr(defs_list,
"nrn_check_conc_write(_prop, prop_ion, 0);\n");
2211 Sprintf(
buf,
"nrn_promote(prop_ion, %d, %d);\n", conc, rev);
2216 #define NRNFIX(arg) if (strcmp(n, arg) == 0) e=1; 2221 if (s->assigned_to_ == 0) {
2222 s->assigned_to_ = 1;
2225 s->assigned_to_ = 2;
2235 diag(s->
name,
"is a special NEURON variable that should not be\n assigned a value\ 2236 in a model description file\n");
2242 static int cvode_valid_, using_cvode;
2243 static int cvode_num_, cvode_neq_;
2244 static Symbol* cvode_fun_;
2250 if (s->slist_info_) {
2253 n = s->slist_info_[0] + 1;
2255 for (i=2*(n-1); i > 0; --
i) {
2256 pi[
i] = s->slist_info_[
i];
2258 free(s->slist_info_);
2259 s->slist_info_ = pi;
2264 s->slist_info_ = pi = (
int*)
emalloc(3*
sizeof(
int));
2273 pi = s->slist_info_;
2274 if (pi == (
int*)0) {
2275 diag(s->
name,
"not really a STATE; Ie. No differential equation for it.\n");
2278 for (i=0; i < pi[0]; ++
i) {
2279 if (pi[1+2*i] ==
n) {
2287 static void cvode_conc_map() {
2299 Item*
q, *q1, *q2, *q3;
2349 diag(
SYM(q1)->
name,
"is WRITE but is not a STATE and has no assignment statement");
2360 Lappendstr(p,
" Node* _nd; double _v; int _iml, _cntml;\n\ 2361 _cntml = _ml->_nodecount;\n\ 2362 _thread = _ml->_thread;\n\ 2363 for (_iml = 0; _iml < _cntml; ++_iml) {\n\ 2364 _p = _ml->_data[_iml]; _ppvar = _ml->_pdata[_iml];\n\ 2365 _nd = _ml->_nodelist[_iml];\n\ 2375 static int _ode_count(int);\n");
2377 static int _ode_count(int _type){ hoc_execerror(\"%s\", \"cannot be used with CVODE\"); return 0;}\n",
2380 }
else if (cvode_emit) {
2383 static int _ode_count(int);\n\ 2384 static void _ode_map(int, double**, double**, double*, Datum*, double*, int);\n\ 2385 static void _ode_spec(NrnThread*, _Memb_list*, int);\n\ 2386 static void _ode_matsol(NrnThread*, _Memb_list*, int);\n\ 2389 static int _ode_count(int _type){ return %d;}\n",
2392 sprintf(
buf,
"\n#define _cvode_ieq _ppvar[%d]._i\n",cvode_ieq_index);
2398 Lappendstr(
procfunc,
"\nstatic void _ode_spec(NrnThread* _nt, _Memb_list* _ml, int _type) {\n");
2410 static void _ode_map(int _ieq, double** _pv, double** _pvdot, double* _pp, Datum* _ppd, double* _atol, int _type) {");
2412 double* _p; Datum* _ppvar;\n");
2414 int _i; _p = _pp; _ppvar = _ppd;\n\ 2415 _cvode_ieq = _ieq;\n\ 2416 for (_i=0; _i < %d; ++_i) {\n\ 2417 _pv[_i] = _pp + _slist%d[_i]; _pvdot[_i] = _pp + _dlist%d[_i];\n\ 2418 _cvode_abstol(_atollist, _atol, _i);\n\ 2420 cvode_neq_, cvode_num_, cvode_num_);
2427 Lappendstr(defs_list,
"static void _ode_synonym(int, double**, Datum**);\n");
2429 static void _ode_synonym(int _cnt, double** _pp, Datum** _ppd) {");
2431 double* _p; Datum* _ppvar;\n");
2434 for (_i=0; _i < _cnt; ++_i) {_p = _pp[_i]; _ppvar = _ppd[_i];\n");
2439 sprintf(
buf,
"static void _ode_matsol_instance%d(_threadargsproto_);\n", cvode_num_);
2441 sprintf(
buf,
"\nstatic void _ode_matsol_instance%d(_threadargsproto_) {\n", cvode_num_);
2445 sprintf(
buf,
"_cvode_sparse(&_cvsparseobj%d, %d, _dlist%d, _p, _ode_matsol%d, &_coef%d);\n",
2446 i, cvode_neq_, i, i, i);
2448 sprintf(
buf,
"_cvode_sparse_thread(&_thread[_cvspth%d]._pvoid, %d, _dlist%d, _p, _ode_matsol%d, _ppvar, _thread, _nt);\n",
2449 i, cvode_neq_, i, i);
2457 Lappendstr(
procfunc,
"\nstatic void _ode_matsol(NrnThread* _nt, _Memb_list* _ml, int _type) {\n");
2461 sprintf(
buf,
"_ode_matsol_instance%d(_threadargs_);\n", cvode_num_);
2466 if (state_discon_list_)
ITERATE(q, state_discon_list_) {
2482 static void _ode_spec(Node* _nd, double* _pp, Datum* _ppd) {\n\ 2483 _p = _pp; _ppvar = _ppd; v = NODEV(_nd);\n\ 2489 static void _ode_map(int _ieq, double** _pv, doubl** _pvdot, double* _pp){}\n");
2493 static void _ode_matsol(Node* _nd, double* _pp, Datum* _ppd){}\n");
2509 static int _ode_spec%d(_threadargsproto_);\n\ 2510 /*static int _ode_matsol%d(_threadargsproto_);*/\n\ 2517 if (!cvode_valid_ && !once++) {
2518 Fprintf(stderr,
"Notice: This mechanism cannot be used with CVODE\n");
2535 type =
SYM(q1)->nrntype;
2539 sprintf(b,
"if (_nt->_vcv) { _ode_spec%d(_p, _ppvar, _thread, _nt); }\n", cvode_num_);
2541 sprintf(b,
"if (_nt->_vcv) { _ode_spec%d(); }\n", cvode_num_);
2560 diag(
"Only one NET_RECEIVE block allowed", (
char*)0);
2563 diag(
"NET_RECEIVE can only exist in a POINT_PROCESS", (
char*)0);
2567 insertstr(qstmt,
"(Point_process* _pnt, double* _args, double _lflag)");
2571 sprintf(snew,
"_args[%d]", i);
2573 for (q = qstmt; q != qend; q = q->
next) {
2579 net_send_delivered_ = qstmt;
2583 insertstr(qstmt,
" int _watch_rm = 0;\n");
2585 q =
insertstr(qstmt,
" _p = _pnt->_prop->param; _ppvar = _pnt->_prop->dparam;\n");
2589 insertstr(qstmt,
" assert(_tsav <= t); _tsav = t;");
2591 insertstr(qstmt,
" if (_tsav > t){ extern char* hoc_object_name(); hoc_execerror(hoc_object_name(_pnt->ob), \":Event arrived out of order. Must call ParallelContext.set_maxstep AFTER assigning minimum NetCon.delay\");}\n _tsav = t;");
2596 Symbol* ions[10];
int j, nion=0;
2603 for (q = qstmt; q != qend; q = q->
next) {
2605 insertstr(qstmt,
" v = NODEV(_pnt->node);\n");
2606 insertstr(qend,
"\n NODEV(_pnt->node) = v;\n");
2616 for (q = qstmt; q != qend; q = q->
next) {
2622 if ((s->nrntype &
IONCONC) == 0) {
2623 diag(s->
name,
":only concentrations can be mentioned in a NET_RECEIVE block");
2626 for (j=0; j < nion; ++
j) {
2633 diag(
"too many ions mentioned in NET_RECEIVE block (limit 10", (
char*)0);
2640 for (j = 0; j < nion; ++
j) {
2644 for (j = 0; j < nion; ++
j) {
2662 replacstr(qinit,
"\nstatic void _net_init(Point_process* _pnt, double* _args, double _lflag)");
2663 sprintf(
buf,
" _p = _pnt->_prop->param; _ppvar = _pnt->_prop->dparam;\n");
2665 double* _p = _pnt->_prop->param;\n\ 2666 Datum* _ppvar = _pnt->_prop->dparam;\n\ 2667 Datum* _thread = (Datum*)0;\n\ 2668 NrnThread* _nt = (NrnThread*)_pnt->_vnt;\n\ 2671 diag(
"NET_RECEIVE block can contain only one INITIAL block", (
char*)0);
2673 net_init_q1_ = qinit;
2687 sprintf(
buf,
"{int _ifn%d, _nfn%d; double* _fnargs%d, **_fnargslist%d;\n\ 2688 \t_nfn%d = _nrn_netcon_args(_ppvar[_fnc_index]._pvoid, &_fnargslist%d);\n\ 2689 \tfor (_ifn%d = 0; _ifn%d < _nfn%d; ++_ifn%d) {\n",
2690 i,i,i,i,i,i,i,i,i,i);
2692 sprintf(
buf,
"\t _fnargs%d = _fnargslist%d[_ifn%d];\n", i,i,i);
2700 for (q = stmt; q != qend; q = q->
next) {
2714 if (s->nrntype & (
NRNGLOBAL) && s->assigned_to_ == 1) {
2715 sprintf(
buf,
"Assignment to the GLOBAL variable, \"%s\", is not thread safe", s->
name);
2727 SYM(q)->assigned_to_ = 2;
2734 if (blocktype != BREAKPOINT) {
2735 diag(
"CONDUCTANCE can only appear in BREAKPOINT block", (
char*)0);
2737 if (!conductance_) {
2741 if (q2 != q1->
next) {
2744 diag(s->
name,
"not declared as USEION in NEURON block");
2755 if (blocktype != BREAKPOINT) {
return; }
2758 char*
n =
SYM(q2)->name + 2;
2759 if (strcmp(
SYM(q)->
name, n) == 0) {
2760 if (!breakpoint_local_current_) {
2761 breakpoint_local_current_ =
newlist();
2771 if (breakpoint_local_current_) {
2773 ITERATE(q, breakpoint_local_current_) {
void deltokens(Item *q1, Item *q2)
char * stralloc(char *buf, char *rel)
void decode_ustr(Symbol *sym, double *pg1, double *pg2, char *s)
void nrn_var_assigned(Symbol *s)
List * get_ion_variables(int)
void nrn_list(Item *q1, Item *q2)
void net_init(Item *qinit, Item *qp2)
void nrn_use(Item *q1, Item *q2, Item *q3, Item *q4)
void bablk(int ba, int type, Item *q1, Item *q2)
#define ITERATE(itm, lst)
int iontype(char *s1, char *s2)
void threadsafe_seen(Item *q1, Item *q2)
static Symbol * ifnew_install(char *name)
void possible_local_current(int blocktype, List *symlist)
void cvode_emit_interface()
Item * lappendsym(List *list, Symbol *sym)
int decode_limits(Symbol *sym, double *pg1, double *pg2)
Symbol * breakpoint_current(Symbol *s)
List * set_ion_variables(int)
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
List * breakpoint_local_current_
static char * brkpnt_str_
int const size_t const size_t n
void parminstall(Symbol *n, char *num, char *units, char *limits)
static void ppvar_semantics(int, const char *)
int check_tables_threads(List *)
void movelist(Item *q1, Item *q2, List *s)
int slist_search(int listnum, Symbol *s)
Item * lappendstr(List *list, char *str)
int decode_tolerance(Symbol *sym, double *pg1)
void cvode_interface(Symbol *fun, int num, int neq)
void vectorize_substitute(Item *q, char *str)
static int use_bbcorepointer
void net_receive(Item *qarg, Item *qp1, Item *qp2, Item *qstmt, Item *qend)
List * thread_mem_init_list
void fornetcon(Item *keyword, Item *par1, Item *args, Item *par2, Item *stmt, Item *qend)
void indepinstall(Symbol *n, char *from, char *to, char *with, Item *qstart, char *units, int scop)
fprintf(stderr, "Don't know the location of params at %p\, pp)
static void var_count(Symbol *s)
static Item * net_init_q1_
char * emalloc(unsigned n)
NMODL parser global flags / functions.
Item * lappenditem(List *list, Item *item)
void conductance_hint(int blocktype, Item *q1, Item *q2)
Item * insertstr(Item *item, char *str)
void warn_ignore(Symbol *s)
void freelist(List **plist)
List * thread_cleanup_list
void out_nt_ml_frag(List *)
static Item * net_init_q2_
void replacstr(Item *q, char *s)
static List * nrnpointers
void cvode_rw_cur(char *)
int ion_declared(Symbol *s)
void slist_data(Symbol *s, int indx, int findx)
List * end_dion_stmt(char *strdel)
static List * ppvar_semantics_