-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for Breakpoint block (nrn_cur) for code generation #645
Conversation
b662f8e
to
fde6b9d
Compare
@georgemitenkov : this is still WIP in terms of completing full/correct functionality of But all those changes will be inside In my test example: NEURON {
SUFFIX hh
NONSPECIFIC_CURRENT il
RANGE minf, mtau, gl, el
USEION na WRITE nai
}
STATE {
m
}
ASSIGNED {
v (mV)
minf
mtau (ms)
il
el
gl
}
BREAKPOINT {
SOLVE states METHOD cnexp
il = gl*(v - el)
}
DERIVATIVE states {
m = minf + mtau + 0.1
:printf("%lf %d %lf", m, ion_nai_id, nai)
} produces: → ./bin/nmodl ../test.mod -o tmp llvm --vector-width 2 --ir benchmark --run --instance-size 10 --repeat 5 passes --nmodl-ast
[NMODL] [info] :: Processing ../test.mod
...
[NMODL] [warning] :: RenameVisitor :: Renaming variable v at 23.14 to epilogue_v
VOID nrn_cur_hh(INSTANCE_STRUCT *mech){
INTEGER id
INTEGER node_id, nai_id, ion_nai_id
DOUBLE v
for(id = 0; id<mech->node_count-1; id = id+2) {
node_id = mech->node_index[id]
nai_id = mech->ion_nai_index[id]
ion_nai_id = mech->ion_nai_index[id]
v = mech->voltage[node_id]
mech->nai[id] = mech->ion_nai[nai_id]
mech->il[id] = mech->gl[id]*(v-mech->el[id])
mech->ion_nai[ion_nai_id] = mech->nai[id]
}
INTEGER epilogue_node_id, epilogue_nai_id, epilogue_ion_nai_id
DOUBLE epilogue_v
for(; id<mech->node_count; id = id+1) {
epilogue_node_id = mech->node_index[id]
epilogue_nai_id = mech->ion_nai_index[id]
epilogue_ion_nai_id = mech->ion_nai_index[id]
epilogue_v = mech->voltage[epilogue_node_id]
mech->nai[id] = mech->ion_nai[epilogue_nai_id]
mech->il[id] = mech->gl[id]*(epilogue_v-mech->el[id])
mech->ion_nai[epilogue_ion_nai_id] = mech->nai[id]
}
}
[NMODL] [warning] :: RenameVisitor :: Renaming variable node_id at 1.21-27 to epilogue_node_id
...
[NMODL] [warning] :: RenameVisitor :: Renaming variable v at 1.21 to epilogue_v
VOID nrn_state_hh(INSTANCE_STRUCT *mech){
INTEGER id
INTEGER node_id, nai_id, ion_nai_id
DOUBLE v
for(id = 0; id<mech->node_count-1; id = id+2) {
node_id = mech->node_index[id]
nai_id = mech->ion_nai_index[id]
ion_nai_id = mech->ion_nai_index[id]
v = mech->voltage[node_id]
mech->nai[id] = mech->ion_nai[nai_id]
mech->m[id] = mech->minf[id]+mech->mtau[id]+0.1
printf("%lf %d %lf", mech->m[id], ion_nai_id, mech->nai[id])
mech->ion_nai[ion_nai_id] = mech->nai[id]
}
INTEGER epilogue_node_id, epilogue_nai_id, epilogue_ion_nai_id
DOUBLE epilogue_v
for(; id<mech->node_count; id = id+1) {
epilogue_node_id = mech->node_index[id]
epilogue_nai_id = mech->ion_nai_index[id]
epilogue_ion_nai_id = mech->ion_nai_index[id]
epilogue_v = mech->voltage[epilogue_node_id]
mech->nai[id] = mech->ion_nai[epilogue_nai_id]
mech->m[id] = mech->minf[id]+mech->mtau[id]+0.1
printf("%lf %d %lf", mech->m[id], epilogue_ion_nai_id, mech->nai[id])
mech->ion_nai[epilogue_ion_nai_id] = mech->nai[id]
}
} At the moment, Let me know if you have any questions. |
bd29085
to
c83510f
Compare
Yeah, IR is generating fine. |
bc5a4c4
to
c80a44d
Compare
934caf5
to
6ac7e2c
Compare
Logfiles from GitLab pipeline #47891 (:no_entry:) have been uploaded here! Status and direct links: |
I have rebased this PR now on latest llvm branch. By using NEURON {
SUFFIX hh
USEION na READ ena WRITE ina
NONSPECIFIC_CURRENT il
RANGE gnabar, gkbar, gl, el, gna, gk
RANGE minf, hinf, ninf, mtau, htau, ntau
}
STATE {
m h
}
ASSIGNED {
v (mV)
ena (mV)
gna (S/cm2)
ina (mA/cm2)
minf hinf ninf
mtau (ms) htau (ms) ntau (ms)
gnabar
}
BREAKPOINT {
SOLVE states METHOD cnexp
gna = gnabar*m*m*m*h
ina = gna*(v - ena)
}
DERIVATIVE states {
m' = (minf-m)/mtau
} we get now below error: ./bin/nmodl test.mod llvm --ir
[NMODL] [info] :: Processing test.mod
[NMODL] [info] :: Running semantic analysis visitor
[NMODL] [info] :: Running symtab visitor
[NMODL] [info] :: Running CVode to cnexp visitor
[NMODL] [info] :: Running code compatibility checker
[NMODL] [info] :: Running verbatim rename visitor
[NMODL] [info] :: Running KINETIC block visitor
[NMODL] [info] :: Running STEADYSTATE visitor
[NMODL] [info] :: Parsing Units
[NMODL] [info] :: Running local variable rename visitor
[NMODL] [info] :: Running cnexp visitor
[NMODL] [info] :: Running C backend code generator
[NMODL] [info] :: Running LLVM backend code generator
[NMODL] [info] :: Running CodegenLLVMHelperVisitor
VOID nrn_cur_hh(INSTANCE_STRUCT *mech){
INTEGER id
INTEGER node_id, ena_id, ion_ina_id
DOUBLE v
for(id = 0; id<mech->node_count; id = id+1) {
node_id = mech->node_index[id]
ena_id = mech->ion_ena_index[id]
ion_ina_id = mech->ion_ina_index[id]
v = mech->voltage[node_id]
mech->ena[id] = mech->ion_ena[ena_id]
mech->gna[id] = mech->gnabar[id]*mech->m[id]*mech->m[id]*mech->m[id]*mech->h[id]
mech->ina[id] = mech->gna[id]*(v-mech->ena[id])
mech->ion_ina[ion_ina_id] += mech->ina[id]
}
}
VOID nrn_state_hh(INSTANCE_STRUCT *mech){
INTEGER id
INTEGER node_id, ena_id
DOUBLE v
for(id = 0; id<mech->node_count; id = id+1) {
node_id = mech->node_index[id]
ena_id = mech->ion_ena_index[id]
v = mech->voltage[node_id]
mech->ena[id] = mech->ion_ena[ena_id]
mech->m[id] = mech->m[id]+(1.0-exp(mech->dt*((((-1.0)))/mech->mtau[id])))*(-(((mech->minf[id]))/mech->mtau[id])/((((-1.0)))/mech->mtau[id])-mech->m[id])
}
}
libc++abi: terminating with uncaught exception of type std::runtime_error:
Error: only assignment is supported for CodegenAtomicStatement The reason is that @georgemitenkov: in this case,
There is #834 where we want to support atomic but that is for GPU backend only. |
Logfiles from GitLab pipeline #47986 (:no_entry:) have been uploaded here! Status and direct links: |
By the way, I am reading the code here:
but, addition of the form: a[i] += b can be written as a[i] = a[i] + b So the error we are throwing is not correct / consistent. |
Logfiles from GitLab pipeline #47996 (:no_entry:) have been uploaded here! Status and direct links: |
I think you're right about that. The variables that should be updated atomically in the end is |
Logfiles from GitLab pipeline #50520 (:white_check_mark:) have been uploaded here! Status and direct links: |
Logfiles from GitLab pipeline #50524 (:white_check_mark:) have been uploaded here! Status and direct links: |
@iomaganaris / @georgemitenkov : with latest fixes, all tests should pass. Now there are two kernels generated: 110: ; Function Attrs: nofree nounwind
110: define void @nrn_cur_hh(%__instance_var__type* noalias nocapture readonly %mech1) #0 {
110: %mech = alloca %__instance_var__type*, align 8
110: %id = alloca i32, align 4
110: %node_id = alloca i32, align 4
110: %ena_id = alloca i32, align 4
110: %ek_id = alloca i32, align 4
110: %ion_ina_id = alloca i32, align 4
110: %ion_ik_id = alloca i32, align 4
110: %v = alloca double, align 8
110: store %__instance_var__type* %mech1, %__instance_var__type** %mech, align 8
110: store i32 0, i32* %id, align 4
110: br label %for.cond
110:
110: for.cond: ; preds = %for.inc, %0
110: %1 = load %__instance_var__type*, %__instance_var__type** %mech, align 8
110: %2 = getelementptr inbounds %__instance_var__type, %__instance_var__type* %1, i32 0, i32 43
110: %3 = load i32, i32* %2, align 4
110: %4 = load i32, i32* %id, align 4
110: %5 = icmp slt i32 %4, %3
110: br i1 %5, label %for.body, label %for.exit, !llvm.loop !0
110:...
...
110:
110: ; Function Attrs: nofree nounwind
110: define void @nrn_state_hh(%__instance_var__type.0* noalias nocapture readonly %mech1) #0 {
110: %mech = alloca %__instance_var__type.0*, align 8
110: %id = alloca i32, align 4
110: %node_id = alloca i32, align 4
110: %ena_id = alloca i32, align 4
110: %ek_id = alloca i32, align 4
110: %v = alloca double, align 8
110: store %__instance_var__type.0* %mech1, %__instance_var__type.0** %mech, align 8
110: store i32 0, i32* %id, align 4
110: br label %for.cond
110:
110: for.cond: ; preds = %for.inc, %0
110: %1 = load %__instance_var__type.0*, %__instance_var__type.0** %mech, align 8
110: %2 = getelementptr inbounds %__instance_var__type.0, %__instance_var__type.0* %1, i32 0, i32 43
110: %3 = load i32, i32* %2, align 4
110: %4 = load i32, i32* %id, align 4
110: %5 = icmp slt i32 %4, %3
110: br i1 %5, label %for.body, label %for.exit, !llvm.loop !2 I have still one todo to take care of but that's not a blocker i.e. it just makes the code "computationally same" as neuron/coreneuron. I think you can already see if/how the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM at the moment.
Benchmark is also running both nrn_cur
and nrn_state
kernels
cd6575a
to
574f135
Compare
* similar to DERIVATIVE (nrn_state), handle BREAKPOINT (nrn_cur) blocks with AST level transformation * TODOs: - complete the implementation with the correct code - refactor nrn_state & nrn_cur to use common code to avoid code duplication fixes #644
Logfiles from GitLab pipeline #51556 (:white_check_mark:) have been uploaded here! Status and direct links: |
574f135
to
0d86377
Compare
* complete implementation * vanilla hh.mod and expsyn.mod compiles fine now * some cleanup
0d86377
to
7cc17f6
Compare
@iomaganaris : I have completed ➜ ./bin/nmodl ~/workarena/repos/bbp/coreneuron/coreneuron/mechanism/mech/modfile/expsyn.mod llvm --ir passes
VOID nrn_cur_expsyn(INSTANCE_STRUCT *mech){
INTEGER id
INTEGER node_id, node_area_id
DOUBLE v, g, rhs, v_org, current, mfactor
for(id = 0; id<mech->node_count; id = id+1) {
node_id = mech->node_index[id]
node_area_id = mech->node_area_index[id]
v = mech->voltage[node_id]
v_org = v
v = v+0.001
{
current = 0
mech->i[id] = mech->g[id]*(v-mech->e[id])
current = current+mech->i[id]
mech->g[id] = current
}
v = v_org
{
current = 0
mech->i[id] = mech->g[id]*(v-mech->e[id])
current = current+mech->i[id]
rhs = current
}
mech->g[id] = (mech->g[id]-rhs)/0.001
mfactor = 1.e2/mech->node_area[node_area_id]
mech->g[id] = mech->g[id]*mfactor
rhs = rhs*mfactor
mech->vec_rhs[node_id] = mech->vec_rhs[node_id]-rhs
mech->vec_d[node_id] = mech->vec_d[node_id]+mech->g[id]
}
}
VOID nrn_state_expsyn(INSTANCE_STRUCT *mech){
INTEGER id
INTEGER node_id
DOUBLE v
for(id = 0; id<mech->node_count; id = id+1) {
node_id = mech->node_index[id]
v = mech->voltage[node_id]
mech->g[id] = mech->g[id]+(1.0-exp(mech->dt*((-1.0)/mech->tau[id])))*(-(0.0)/((-1.0)/mech->tau[id])-mech->g[id])
}
}
➜ ./bin/nmodl ~/workarena/repos/bbp/coreneuron/coreneuron/mechanism/mech/modfile/hh.mod llvm --ir passes
VOID nrn_cur_hh(INSTANCE_STRUCT *mech){
INTEGER id
INTEGER node_id, ena_id, ek_id, ion_dinadv_id, ion_dikdv_id, ion_ina_id, ion_ik_id
DOUBLE v, g, rhs, v_org, current, dina, dik
for(id = 0; id<mech->node_count; id = id+1) {
node_id = mech->node_index[id]
ena_id = mech->ion_ena_index[id]
ek_id = mech->ion_ek_index[id]
ion_dinadv_id = mech->ion_dinadv_index[id]
ion_dikdv_id = mech->ion_dikdv_index[id]
ion_ina_id = mech->ion_ina_index[id]
ion_ik_id = mech->ion_ik_index[id]
v = mech->voltage[node_id]
mech->ena[id] = mech->ion_ena[ena_id]
mech->ek[id] = mech->ion_ek[ek_id]
v_org = v
v = v+0.001
{
current = 0
mech->gna[id] = mech->gnabar[id]*mech->m[id]*mech->m[id]*mech->m[id]*mech->h[id]
mech->ina[id] = mech->gna[id]*(v-mech->ena[id])
mech->gk[id] = mech->gkbar[id]*mech->n[id]*mech->n[id]*mech->n[id]*mech->n[id]
mech->ik[id] = mech->gk[id]*(v-mech->ek[id])
mech->il[id] = mech->gl[id]*(v-mech->el[id])
current = current+mech->il[id]
current = current+mech->ina[id]
current = current+mech->ik[id]
g = current
}
dina = mech->ina[id]
dik = mech->ik[id]
v = v_org
{
current = 0
mech->gna[id] = mech->gnabar[id]*mech->m[id]*mech->m[id]*mech->m[id]*mech->h[id]
mech->ina[id] = mech->gna[id]*(v-mech->ena[id])
mech->gk[id] = mech->gkbar[id]*mech->n[id]*mech->n[id]*mech->n[id]*mech->n[id]
mech->ik[id] = mech->gk[id]*(v-mech->ek[id])
mech->il[id] = mech->gl[id]*(v-mech->el[id])
current = current+mech->il[id]
current = current+mech->ina[id]
current = current+mech->ik[id]
rhs = current
}
g = (g-rhs)/0.001
mech->ion_dinadv[ion_dinadv_id] = mech->ion_dinadv[ion_dinadv_id]+(dina-mech->ina[id])/0.001
mech->ion_dikdv[ion_dikdv_id] = mech->ion_dikdv[ion_dikdv_id]+(dik-mech->ik[id])/0.001
mech->ion_ina[ion_ina_id] = mech->ion_ina[ion_ina_id]+mech->ina[id]
mech->ion_ik[ion_ik_id] = mech->ion_ik[ion_ik_id]+mech->ik[id]
mech->vec_rhs[node_id] = mech->vec_rhs[node_id]-rhs
mech->vec_d[node_id] = mech->vec_d[node_id]+g
}
}
VOID nrn_state_hh(INSTANCE_STRUCT *mech){
INTEGER id
INTEGER node_id, ena_id, ek_id
DOUBLE v
for(id = 0; id<mech->node_count; id = id+1) {
node_id = mech->node_index[id]
ena_id = mech->ion_ena_index[id]
ek_id = mech->ion_ek_index[id]
v = mech->voltage[node_id]
mech->ena[id] = mech->ion_ena[ena_id]
mech->ek[id] = mech->ion_ek[ek_id]
{
DOUBLE alpha, beta, sum, q10, vtrap_in_0, vtrap_in_1, v_in_1
v_in_1 = v
UNITSOFF
q10 = 3^((mech->celsius-6.3)/10)
{
DOUBLE x_in_0, y_in_0
x_in_0 = -(v_in_1+40)
y_in_0 = 10
IF (fabs(x_in_0/y_in_0)<1e-6) {
vtrap_in_0 = y_in_0*(1-x_in_0/y_in_0/2)
} ELSE {
vtrap_in_0 = x_in_0/(exp(x_in_0/y_in_0)-1)
}
}
alpha = .1*vtrap_in_0
beta = 4*exp(-(v_in_1+65)/18)
sum = alpha+beta
mech->mtau[id] = 1/(q10*sum)
mech->minf[id] = alpha/sum
alpha = .07*exp(-(v_in_1+65)/20)
beta = 1/(exp(-(v_in_1+35)/10)+1)
sum = alpha+beta
mech->htau[id] = 1/(q10*sum)
mech->hinf[id] = alpha/sum
{
DOUBLE x_in_1, y_in_1
x_in_1 = -(v_in_1+55)
y_in_1 = 10
IF (fabs(x_in_1/y_in_1)<1e-6) {
vtrap_in_1 = y_in_1*(1-x_in_1/y_in_1/2)
} ELSE {
vtrap_in_1 = x_in_1/(exp(x_in_1/y_in_1)-1)
}
}
alpha = .01*vtrap_in_1
beta = .125*exp(-(v_in_1+65)/80)
sum = alpha+beta
mech->ntau[id] = 1/(q10*sum)
mech->ninf[id] = alpha/sum
}
mech->m[id] = mech->m[id]+(1.0-exp(mech->dt*((((-1.0)))/mech->mtau[id])))*(-(((mech->minf[id]))/mech->mtau[id])/((((-1.0)))/mech->mtau[id])-mech->m[id])
mech->h[id] = mech->h[id]+(1.0-exp(mech->dt*((((-1.0)))/mech->htau[id])))*(-(((mech->hinf[id]))/mech->htau[id])/((((-1.0)))/mech->htau[id])-mech->h[id])
mech->n[id] = mech->n[id]+(1.0-exp(mech->dt*((((-1.0)))/mech->ntau[id])))*(-(((mech->ninf[id]))/mech->ntau[id])/((((-1.0)))/mech->ntau[id])-mech->n[id])
}
} The only thing I wish to add is one test for synapse's BREAKPOINT block. So this is now ready for review. |
Logfiles from GitLab pipeline #51560 (:white_check_mark:) have been uploaded here! Status and direct links: |
@pramodk I rebased atomic support on top of your PR and noticed that 2 tests fail in |
Sure, will do! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
As discussed offline we should just add an issue regarding the atomic reduction of the rhs
and d
variables
(I will approve once you add the tests)
de741cc
to
b9410dc
Compare
@iomaganaris : b9410dc add necessary test and addresses review comments. |
Logfiles from GitLab pipeline #51875 (:white_check_mark:) have been uploaded here! Status and direct links: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after George's fix is merged
* Fixed instance struct type creation * Fixed tests
Logfiles from GitLab pipeline #52089 (:white_check_mark:) have been uploaded here! Status and direct links: |
* Support for Breakpoint block (nrn_cur) for code generation * similar to DERIVATIVE (nrn_state), handle BREAKPOINT (nrn_cur) blocks with AST level transformation * Move common code from CodegenCVisitor to CodegenInfo * Add tests fixes #644 Co-authored-by: George Mitenkov <georgemitenk0v@gmail.com>
* Support for Breakpoint block (nrn_cur) for code generation * similar to DERIVATIVE (nrn_state), handle BREAKPOINT (nrn_cur) blocks with AST level transformation * Move common code from CodegenCVisitor to CodegenInfo * Add tests fixes #644 Co-authored-by: George Mitenkov <georgemitenk0v@gmail.com>
* Support for Breakpoint block (nrn_cur) for code generation * similar to DERIVATIVE (nrn_state), handle BREAKPOINT (nrn_cur) blocks with AST level transformation * Move common code from CodegenCVisitor to CodegenInfo * Add tests fixes #644 Co-authored-by: George Mitenkov <georgemitenk0v@gmail.com>
* Support for Breakpoint block (nrn_cur) for code generation * similar to DERIVATIVE (nrn_state), handle BREAKPOINT (nrn_cur) blocks with AST level transformation * Move common code from CodegenCVisitor to CodegenInfo * Add tests fixes #644 Co-authored-by: George Mitenkov <georgemitenk0v@gmail.com>
fixes #644