diff --git a/net_send/coreneuron/toggle.cpp b/net_send/coreneuron/toggle.cpp new file mode 100644 index 0000000..28436cc --- /dev/null +++ b/net_send/coreneuron/toggle.cpp @@ -0,0 +1,379 @@ +/********************************************************* +Model Name : toggle +Filename : toggle.mod +NMODL Version : 7.7.0 +Vectorized : true +Threadsafe : true +Created : DATE +Simulator : CoreNEURON +Backend : C++ (api-compatibility) +NMODL Compiler : VERSION +*********************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace coreneuron { + #ifndef NRN_PRCELLSTATE + #define NRN_PRCELLSTATE 0 + #endif + + + /** channel information */ + static const char *mechanism_info[] = { + "7.7.0", + "toggle", + 0, + "y", + 0, + 0, + 0 + }; + + + /** all global variables */ + struct toggle_Store { + int point_type{}; + int reset{}; + int mech_type{}; + }; + static_assert(std::is_trivially_copy_constructible_v); + static_assert(std::is_trivially_move_constructible_v); + static_assert(std::is_trivially_copy_assignable_v); + static_assert(std::is_trivially_move_assignable_v); + static_assert(std::is_trivially_destructible_v); + toggle_Store toggle_global; + + + /** all mechanism instance variables and global variables */ + struct toggle_Instance { + double* y{}; + double* v_unused{}; + double* tsave{}; + const double* node_area{}; + const int* point_process{}; + const int* tqitem{}; + toggle_Store* global{&toggle_global}; + }; + + + /** connect global (scalar) variables to hoc -- */ + static DoubScal hoc_scalar_double[] = { + {nullptr, nullptr} + }; + + + /** connect global (array) variables to hoc -- */ + static DoubVec hoc_vector_double[] = { + {nullptr, nullptr, 0} + }; + + + static inline int first_pointer_var_index() { + return -1; + } + + + static inline int first_random_var_index() { + return -1; + } + + + static inline int num_net_receive_args() { + return 1; + } + + + static inline int float_variables_size() { + return 3; + } + + + static inline int int_variables_size() { + return 3; + } + + + static inline int get_mech_type() { + return toggle_global.mech_type; + } + + + static inline Memb_list* get_memb_list(NrnThread* nt) { + if (!nt->_ml_list) { + return nullptr; + } + return nt->_ml_list[get_mech_type()]; + } + + + static inline void* mem_alloc(size_t num, size_t size, size_t alignment = 16) { + void* ptr; + posix_memalign(&ptr, alignment, num*size); + memset(ptr, 0, size); + return ptr; + } + + + static inline void mem_free(void* ptr) { + free(ptr); + } + + + static inline void coreneuron_abort() { + abort(); + } + + // Allocate instance structure + static void nrn_private_constructor_toggle(NrnThread* nt, Memb_list* ml, int type) { + assert(!ml->instance); + assert(!ml->global_variables); + assert(ml->global_variables_size == 0); + auto* const inst = new toggle_Instance{}; + assert(inst->global == &toggle_global); + ml->instance = inst; + ml->global_variables = inst->global; + ml->global_variables_size = sizeof(toggle_Store); + } + + // Deallocate the instance structure + static void nrn_private_destructor_toggle(NrnThread* nt, Memb_list* ml, int type) { + auto* const inst = static_cast(ml->instance); + assert(inst); + assert(inst->global); + assert(inst->global == &toggle_global); + assert(inst->global == ml->global_variables); + assert(ml->global_variables_size == sizeof(toggle_Store)); + delete inst; + ml->instance = nullptr; + ml->global_variables = nullptr; + ml->global_variables_size = 0; + } + + /** initialize mechanism instance variables */ + static inline void setup_instance(NrnThread* nt, Memb_list* ml) { + auto* const inst = static_cast(ml->instance); + assert(inst); + assert(inst->global); + assert(inst->global == &toggle_global); + assert(inst->global == ml->global_variables); + assert(ml->global_variables_size == sizeof(toggle_Store)); + int pnodecount = ml->_nodecount_padded; + Datum* indexes = ml->pdata; + inst->y = ml->data+0*pnodecount; + inst->v_unused = ml->data+1*pnodecount; + inst->tsave = ml->data+2*pnodecount; + inst->node_area = nt->_data; + inst->point_process = ml->pdata; + inst->tqitem = ml->pdata; + } + + + + static void nrn_alloc_toggle(double* data, Datum* indexes, int type) { + // do nothing + } + + + void nrn_constructor_toggle(NrnThread* nt, Memb_list* ml, int type) { + #ifndef CORENEURON_BUILD + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #endif + } + + + void nrn_destructor_toggle(NrnThread* nt, Memb_list* ml, int type) { + #ifndef CORENEURON_BUILD + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + auto* const inst = static_cast(ml->instance); + + #endif + } + + + static inline void net_send_buffering(const NrnThread* nt, NetSendBuffer_t* nsb, int type, int vdata_index, int weight_index, int point_index, double t, double flag) { + int i = 0; + i = nsb->_cnt++; + if (i >= nsb->_size) { + nsb->grow(); + } + if (i < nsb->_size) { + nsb->_sendtype[i] = type; + nsb->_vdata_index[i] = vdata_index; + nsb->_weight_index[i] = weight_index; + nsb->_pnt_index[i] = point_index; + nsb->_nsb_t[i] = t; + nsb->_nsb_flag[i] = flag; + } + } + + + static inline void net_receive_kernel_toggle(double t, Point_process* pnt, toggle_Instance* inst, NrnThread* nt, Memb_list* ml, int weight_index, double flag) { + int tid = pnt->_tid; + int id = pnt->_i_instance; + double v = 0; + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + double* data = ml->data; + double* weights = nt->weights; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + + inst->tsave[id] = t; + { + inst->y[id] = 1.0; + } + } + + + static void net_receive_toggle(Point_process* pnt, int weight_index, double flag) { + NrnThread* nt = nrn_threads + pnt->_tid; + Memb_list* ml = get_memb_list(nt); + NetReceiveBuffer_t* nrb = ml->_net_receive_buffer; + if (nrb->_cnt >= nrb->_size) { + realloc_net_receive_buffer(nt, ml); + } + int id = nrb->_cnt; + nrb->_pnt_index[id] = pnt-nt->pntprocs; + nrb->_weight_index[id] = weight_index; + nrb->_nrb_t[id] = nt->_t; + nrb->_nrb_flag[id] = flag; + nrb->_cnt++; + } + + + void net_buf_receive_toggle(NrnThread* nt) { + Memb_list* ml = get_memb_list(nt); + if (!ml) { + return; + } + + NetReceiveBuffer_t* nrb = ml->_net_receive_buffer; + auto* const inst = static_cast(ml->instance); + int count = nrb->_displ_cnt; + #pragma omp simd + #pragma ivdep + for (int i = 0; i < count; i++) { + int start = nrb->_displ[i]; + int end = nrb->_displ[i+1]; + for (int j = start; j < end; j++) { + int index = nrb->_nrb_index[j]; + int offset = nrb->_pnt_index[index]; + double t = nrb->_nrb_t[index]; + int weight_index = nrb->_weight_index[index]; + double flag = nrb->_nrb_flag[index]; + Point_process* point_process = nt->pntprocs + offset; + net_receive_kernel_toggle(t, point_process, inst, nt, ml, weight_index, flag); + } + } + nrb->_displ_cnt = 0; + nrb->_cnt = 0; + + NetSendBuffer_t* nsb = ml->_net_send_buffer; + for (int i=0; i < nsb->_cnt; i++) { + int type = nsb->_sendtype[i]; + int tid = nt->id; + double t = nsb->_nsb_t[i]; + double flag = nsb->_nsb_flag[i]; + int vdata_index = nsb->_vdata_index[i]; + int weight_index = nsb->_weight_index[i]; + int point_index = nsb->_pnt_index[i]; + net_sem_from_gpu(type, vdata_index, weight_index, tid, point_index, t, flag); + } + nsb->_cnt = 0; + } + + + /** initialize channel */ + void nrn_init_toggle(NrnThread* nt, Memb_list* ml, int type) { + int nodecount = ml->nodecount; + int pnodecount = ml->_nodecount_padded; + const int* node_index = ml->nodeindices; + double* data = ml->data; + const double* voltage = nt->_actual_v; + Datum* indexes = ml->pdata; + ThreadDatum* thread = ml->_thread; + + setup_instance(nt, ml); + auto* const inst = static_cast(ml->instance); + + if (_nrn_skip_initmodel == 0) { + #pragma omp simd + #pragma ivdep + for (int id = 0; id < nodecount; id++) { + inst->tsave[id] = -1e20; + int node_id = node_index[id]; + double v = voltage[node_id]; + #if NRN_PRCELLSTATE + inst->v_unused[id] = v; + #endif + inst->y[id] = 0.0; + net_send_buffering(nt, ml->_net_send_buffer, 0, inst->tqitem[2*pnodecount+id], 0, inst->point_process[1*pnodecount+id], nt->_t+2.0, 1.0); + } + } + + NetSendBuffer_t* nsb = ml->_net_send_buffer; + for (int i=0; i < nsb->_cnt; i++) { + int type = nsb->_sendtype[i]; + int tid = nt->id; + double t = nsb->_nsb_t[i]; + double flag = nsb->_nsb_flag[i]; + int vdata_index = nsb->_vdata_index[i]; + int weight_index = nsb->_weight_index[i]; + int point_index = nsb->_pnt_index[i]; + net_sem_from_gpu(type, vdata_index, weight_index, tid, point_index, t, flag); + } + nsb->_cnt = 0; + } + + + /** register channel with the simulator */ + void _toggle_reg() { + + int mech_type = nrn_get_mechtype("toggle"); + toggle_global.mech_type = mech_type; + if (mech_type == -1) { + return; + } + + _nrn_layout_reg(mech_type, 0); + point_register_mech(mechanism_info, nrn_alloc_toggle, nullptr, nullptr, nullptr, nrn_init_toggle, nrn_private_constructor_toggle, nrn_private_destructor_toggle, first_pointer_var_index(), nullptr, nullptr, 1); + + hoc_register_prop_size(mech_type, float_variables_size(), int_variables_size()); + hoc_register_dparam_semantics(mech_type, 0, "area"); + hoc_register_dparam_semantics(mech_type, 1, "pntproc"); + hoc_register_dparam_semantics(mech_type, 2, "netsend"); + hoc_register_net_receive_buffering(net_buf_receive_toggle, mech_type); + set_pnt_receive(mech_type, net_receive_toggle, nullptr, num_net_receive_args()); + hoc_register_net_send_buffering(mech_type); + hoc_register_var(hoc_scalar_double, hoc_vector_double, NULL); + } +} diff --git a/net_send/neuron/toggle.cpp b/net_send/neuron/toggle.cpp new file mode 100644 index 0000000..41992b5 --- /dev/null +++ b/net_send/neuron/toggle.cpp @@ -0,0 +1,268 @@ +/********************************************************* +Model Name : toggle +Filename : toggle.mod +NMODL Version : 7.7.0 +Vectorized : true +Threadsafe : true +Created : DATE +Simulator : NEURON +Backend : C++ (api-compatibility) +NMODL Compiler : VERSION +*********************************************************/ + +#include +#include +#include + +#include "mech_api.h" +#include "neuron/cache/mechanism_range.hpp" +#include "nrniv_mf.h" +#include "section_fwd.hpp" + +/* NEURON global macro definitions */ +/* VECTORIZED */ +#define NRN_VECTORIZED 1 + +static constexpr auto number_of_datum_variables = 3; +static constexpr auto number_of_floating_point_variables = 3; + +namespace { +template +using _nrn_mechanism_std_vector = std::vector; +using _nrn_model_sorted_token = neuron::model_sorted_token; +using _nrn_mechanism_cache_range = neuron::cache::MechanismRange; +using _nrn_mechanism_cache_instance = neuron::cache::MechanismInstance; +using _nrn_non_owning_id_without_container = neuron::container::non_owning_identifier_without_container; +template +using _nrn_mechanism_field = neuron::mechanism::field; +template +void _nrn_mechanism_register_data_fields(Args&&... args) { + neuron::mechanism::register_data_fields(std::forward(args)...); +} +} // namespace + +extern Prop* nrn_point_prop_; + + +namespace neuron { + #ifndef NRN_PRCELLSTATE + #define NRN_PRCELLSTATE 0 + #endif + + + /** channel information */ + static const char *mechanism_info[] = { + "7.7.0", + "toggle", + 0, + "y", + 0, + 0, + 0 + }; + + + /* NEURON global variables */ + static int mech_type; + static int _pointtype; + static int hoc_nrnpointerindex = -1; + static _nrn_mechanism_std_vector _extcall_thread; + + + /** all global variables */ + struct toggle_Store { + }; + static_assert(std::is_trivially_copy_constructible_v); + static_assert(std::is_trivially_move_constructible_v); + static_assert(std::is_trivially_copy_assignable_v); + static_assert(std::is_trivially_move_assignable_v); + static_assert(std::is_trivially_destructible_v); + toggle_Store toggle_global; + + + /** all mechanism instance variables and global variables */ + struct toggle_Instance { + double* y{}; + double* v_unused{}; + double* tsave{}; + const double* const* node_area{}; + const int* const* tqitem{}; + toggle_Store* global{&toggle_global}; + }; + + + struct toggle_NodeData { + int const * nodeindices; + double const * node_voltages; + double * node_diagonal; + double * node_rhs; + int nodecount; + }; + + + static toggle_Instance make_instance_toggle(_nrn_mechanism_cache_range& _ml) { + return toggle_Instance { + _ml.template fpfield_ptr<0>(), + _ml.template fpfield_ptr<1>(), + _ml.template fpfield_ptr<2>(), + _ml.template dptr_field_ptr<0>() + }; + } + + + static toggle_NodeData make_node_data_toggle(NrnThread& _nt, Memb_list& _ml_arg) { + return toggle_NodeData { + _ml_arg.nodeindices, + _nt.node_voltage_storage(), + _nt.node_d_storage(), + _nt.node_rhs_storage(), + _ml_arg.nodecount + }; + } + + + static void nrn_alloc_toggle(Prop* _prop) { + Prop *prop_ion{}; + Datum *_ppvar{}; + if (nrn_point_prop_) { + _nrn_mechanism_access_alloc_seq(_prop) = _nrn_mechanism_access_alloc_seq(nrn_point_prop_); + _ppvar = _nrn_mechanism_access_dparam(nrn_point_prop_); + } else { + _ppvar = nrn_prop_datum_alloc(mech_type, 3, _prop); + _nrn_mechanism_access_dparam(_prop) = _ppvar; + _nrn_mechanism_cache_instance _ml_real{_prop}; + auto* const _ml = &_ml_real; + size_t const _iml{}; + assert(_nrn_mechanism_get_num_vars(_prop) == 3); + /*initialize range parameters*/ + } + _nrn_mechanism_access_dparam(_prop) = _ppvar; + } + + + /* Point Process specific functions */ + static void* _hoc_create_pnt(Object* _ho) { + return create_point_process(_pointtype, _ho); + } + static void _hoc_destroy_pnt(void* _vptr) { + destroy_point_process(_vptr); + } + static double _hoc_loc_pnt(void* _vptr) { + return loc_point_process(_pointtype, _vptr); + } + static double _hoc_has_loc(void* _vptr) { + return has_loc_point(_vptr); + } + static double _hoc_get_loc_pnt(void* _vptr) { + return (get_loc_point_process(_vptr)); + } + /* Neuron setdata functions */ + extern void _nrn_setdata_reg(int, void(*)(Prop*)); + static void _setdata(Prop* _prop) { + } + static void _hoc_setdata(void* _vptr) { + Prop* _prop; + _prop = ((Point_process*)_vptr)->prop; + _setdata(_prop); + } + /* Mechanism procedures and functions */ + + + /** connect global (scalar) variables to hoc -- */ + static DoubScal hoc_scalar_double[] = { + {nullptr, nullptr} + }; + + + /** connect global (array) variables to hoc -- */ + static DoubVec hoc_vector_double[] = { + {nullptr, nullptr, 0} + }; + + + /* declaration of user functions */ + + + /* connect user functions to hoc names */ + static VoidFunc hoc_intfunc[] = { + {0, 0} + }; + static Member_func _member_func[] = { + {"loc", _hoc_loc_pnt}, + {"has_loc", _hoc_has_loc}, + {"get_loc", _hoc_get_loc_pnt}, + {0, 0} + }; + + + void nrn_init_toggle(_nrn_model_sorted_token const& _sorted_token, NrnThread* _nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml_arg, _type}; + auto inst = make_instance_toggle(_lmr); + auto node_data = make_node_data_toggle(*_nt, *_ml_arg); + auto nodecount = _ml_arg->nodecount; + auto* const _ml = &_lmr; + auto* _thread = _ml_arg->_thread; + for (int id = 0; id < nodecount; id++) { + + int node_id = node_data.nodeindices[id]; + auto* _ppvar = _ml_arg->pdata[id]; + auto v = node_data.node_voltages[node_id]; + inst.v_unused[id] = v; + inst.y[id] = 0.0; + net_send(/* tqitem */ &_ppvar[2], nullptr, _ppvar[1].get(), _nt->_t + 2.0, 1.0); + } + } + + + /** nrn_jacob function */ + static void nrn_jacob_toggle(_nrn_model_sorted_token const& _sorted_token, NrnThread* _nt, Memb_list* _ml_arg, int _type) { + _nrn_mechanism_cache_range _lmr{_sorted_token, *_nt, *_ml_arg, _type}; + auto inst = make_instance_toggle(_lmr); + auto node_data = make_node_data_toggle(*_nt, *_ml_arg); + auto nodecount = _ml_arg->nodecount; + for (int id = 0; id < nodecount; id++) { + } + } + static void nrn_net_receive_toggle(Point_process* _pnt, double* _args, double _lflag) { + _nrn_mechanism_cache_instance _ml_obj{_pnt->prop}; + auto * _nt = static_cast(_pnt->_vnt); + auto * _ml = &_ml_obj; + auto inst = make_instance_toggle(_ml_obj); + size_t id = 0; + double t = _nt->_t; + inst.y[id] = 1.0; + + } + + + static void _initlists() { + } + + + /** register channel with the simulator */ + extern "C" void _toggle_reg() { + _initlists(); + + + + _pointtype = point_register_mech(mechanism_info, nrn_alloc_toggle, nullptr, nullptr, nullptr, nrn_init_toggle, hoc_nrnpointerindex, 1, _hoc_create_pnt, _hoc_destroy_pnt, _member_func); + + mech_type = nrn_get_mechtype(mechanism_info[1]); + _nrn_mechanism_register_data_fields(mech_type, + _nrn_mechanism_field{"y"} /* 0 */, + _nrn_mechanism_field{"v_unused"} /* 1 */, + _nrn_mechanism_field{"tsave"} /* 2 */, + _nrn_mechanism_field{"node_area", "area"} /* 0 */, + _nrn_mechanism_field{"point_process", "pntproc"} /* 1 */, + _nrn_mechanism_field{"tqitem", "netsend"} /* 2 */ + ); + + hoc_register_prop_size(mech_type, 3, 3); + hoc_register_dparam_semantics(mech_type, 0, "area"); + hoc_register_dparam_semantics(mech_type, 1, "pntproc"); + hoc_register_dparam_semantics(mech_type, 2, "netsend"); + hoc_register_var(hoc_scalar_double, hoc_vector_double, hoc_intfunc); + pnt_receive[mech_type] = nrn_net_receive_toggle; + pnt_receive_size[mech_type] = 1; + } +}