fixed simulation engine, no more bidirectional devices allowed

This commit is contained in:
Stefan Frederik 2021-10-30 03:12:06 +02:00
parent 8dbe8b7771
commit ebf0f0cf95
12 changed files with 117 additions and 65 deletions

View File

@ -1083,10 +1083,12 @@ void propagate_hilights(int set, int clear, int mode)
}
/* use negative values to bypass the normal hilight color enumeration */
#define LOGIC_0 -12 /* 0 */
#define LOGIC_1 -5 /* 1 */
#define LOGIC_X -1 /* 2 */
#define LOGIC_Z -13 /* 3 */
#define LOGIC_0 -12 /* 0 */
#define LOGIC_1 -5 /* 1 */
#define LOGIC_X -1 /* 2 */
#define LOGIC_Z -13 /* 3 */
#define LOGIC_NOUP 0 /* 4 don't update */
#define STACKMAX 200
int get_logic_value(int inst, int n)
@ -1127,6 +1129,7 @@ int eval_logic_expr(int inst, int output)
char *str;
int res = 0;
stack[0] = 2; /* default if nothing is calculated: LOGIC_X */
str = xctx->simdata[inst].pin[output].function;
dbg(1, "eval_logic_expr(): inst=%d pin=%d function=%s\n", inst, output, str ? str : "NULL");
if(!str) return 2; /* no logic function defined, return LOGIC_X */
@ -1167,6 +1170,19 @@ int eval_logic_expr(int inst, int output)
sp--;
}
break;
case 'R': /* resolution operator, resolve output based on 2 inputs */
if(sp > 1) {
s = stack[sp - 1];
i = stack[sp - 2];
if(s == 2 || i == 2) res = 2; /* s 0 1 X Z */
else if(s == 3) res = i; /* i ------- */
else if(i == 3) res = s; /* 0 | 0 X X 0 */
else if(i == s) res = i; /* 1 | X 1 X 1 */
else res = 2; /* X | X X X X */
stack[sp - 2] = res; /* Z | 0 1 X Z */
sp--;
}
break;
case 'M': /* mux operator */
if(sp > 2) {
s = stack[sp - 1];
@ -1180,6 +1196,8 @@ int eval_logic_expr(int inst, int output)
case 'm': /* mux operator , lower priority*/
if(sp > 2) {
s = stack[sp - 1];
stack[sp - 3] = (stack[sp - 3] == 2) ? 4 : stack[sp - 3]; /* if LOGIC_X set to don't update */
stack[sp - 2] = (stack[sp - 2] == 2) ? 4 : stack[sp - 2]; /* if LOGIC_X set to don't update */
if(s < 2) {
stack[sp - 3] = (s == 0) ? stack[sp - 3] : stack[sp - 2];
}
@ -1321,31 +1339,28 @@ void free_simdata(void)
xctx->simdata_ninst = 0;
}
#define DELAYED_ASSIGN /* fixes bidirectional devices (avoid infinite loops) */
void propagate_logic()
{
/* char *propagated_net=NULL; */
int found, iter = 0 /* , mult */;
int i, j, npin;
int propagate;
int min_iter = 3; /* set to 3 to simulate up to 3 series bidirectional pass-devices */
struct hilight_hashentry *entry;
int val, oldval, newval;
static int map[] = {LOGIC_0, LOGIC_1, LOGIC_X, LOGIC_Z};
#ifdef DELAYED_ASSIGN
int *newval_arr = NULL;
#endif
int val, newval;
static int map[] = {LOGIC_0, LOGIC_1, LOGIC_X, LOGIC_Z, LOGIC_NOUP};
prepare_netlist_structs(0);
if(!xctx->simdata) create_simdata();
for(i=0; i<xctx->instances; i++)
for(j=0;j < xctx->simdata[i].npin; j++)
xctx->simdata[i].pin[j].value=-10000;
while(1) {
dbg(0, "propagate_logic(): main loop iteration\n");
found=0;
for(i=0; i<xctx->instances; i++) {
npin = xctx->simdata[i].npin;
#ifdef DELAYED_ASSIGN
my_realloc(778, &newval_arr, npin * sizeof(int));
for(j=0; j<npin;j++) newval_arr[j] = -10000;
#endif
for(j=0; j<npin;j++) {
if(xctx->simdata && xctx->simdata[i].pin && xctx->simdata[i].pin[j].go_to) {
int n = 1;
@ -1361,11 +1376,11 @@ void propagate_logic()
if(clock_pin == 0) { /* clock falling edge */
if( clock_val == clock_oldval) continue;
if( clock_val != LOGIC_0) continue;
if(entry && entry->time != xctx->hilight_time) continue;
if(entry && (entry->time < xctx->hilight_time)) continue;
} else if(clock_pin == 1) { /* clock rising edge */
if( clock_val == clock_oldval) continue;
if( clock_val != LOGIC_1) continue;
if(entry && entry->time != xctx->hilight_time) continue;
if(entry && (entry->time < xctx->hilight_time)) continue;
} else if(clock_pin == 2) { /* set/clear active low */
if( clock_val != LOGIC_0) continue;
} else if(clock_pin == 3) { /* set/clear active high */
@ -1397,40 +1412,49 @@ void propagate_logic()
* dbg(1, "propagate_logic(): propagated_net=%s\n", propagated_net); */
/* add net to highlight list */
/* no bus_hilight_lookup --> no bus expansion */
entry = hilight_lookup(xctx->inst[i].node[propagate], 0, XLOOKUP); /* destination pin */
oldval = (!entry) ? LOGIC_X : entry->value;
newval = eval_logic_expr(i, propagate);
val = map[newval];
if( newval !=4 && (iter < min_iter || (newval !=3 && oldval != val) )) {
dbg(1, "propagate_logic(): inst %d pin %d oldval %d newval %d to pin %s\n",
i, j, oldval, val, xctx->inst[i].node[propagate]);
#ifdef DELAYED_ASSIGN
newval_arr[propagate] = val;
#else
hilight_lookup(xctx->inst[i].node[propagate], val, XINSERT);
#endif
if(newval != 4 && xctx->simdata[i].pin[propagate].value != val ) {
found=1; /* keep looping until no more nets are found. */
}
xctx->simdata[i].pin[propagate].value = val;
dbg(0, "propagate_logic(): DRIVERS inst %s pin %d, net %s --> value %d\n",
xctx->inst[i].instname, j, xctx->inst[i].node[propagate], val);
}
} /* while( ith-goto ) */
} /* if((xctx->simdata && xctx->simdata[i].pin && xctx->simdata[i].pin[j].go_to) */
} /* for(j...) */
} /* for(i...) */
xctx->hilight_time++;
/* update all values */
for(i=0; i<xctx->instances; i++) {
for(j=0;j < xctx->simdata[i].npin; j++) {
if(xctx->simdata[i].pin[j].value != -10000) {
entry = hilight_lookup(xctx->inst[i].node[j], 0, XLOOKUP);
if(!entry || xctx->hilight_time != entry->time) {
hilight_lookup(xctx->inst[i].node[j], xctx->simdata[i].pin[j].value, XINSERT);
dbg(0, "propagate_logic(): UPDATE1 inst %s pin %d, net %s --> value %d\n",
xctx->inst[i].instname, j, xctx->inst[i].node[j], xctx->simdata[i].pin[j].value);
} else if(entry->value != xctx->simdata[i].pin[j].value &&
xctx->simdata[i].pin[j].value != LOGIC_Z) {
hilight_lookup(xctx->inst[i].node[j], xctx->simdata[i].pin[j].value, XINSERT);
dbg(0, "propagate_logic(): UPDATE2 inst %s pin %d, net %s --> value %d\n",
xctx->inst[i].instname, j, xctx->inst[i].node[j], xctx->simdata[i].pin[j].value);
} else {
dbg(0, "propagate_logic(): UPDATE3 inst %s pin %d, net %s --> value %d NOT assigned\n",
xctx->inst[i].instname, j, xctx->inst[i].node[j], xctx->simdata[i].pin[j].value);
}
}
} /* for(j...) */
#ifdef DELAYED_ASSIGN
for(j=0;j<npin;j++) {
if(newval_arr[j] != -10000) hilight_lookup(xctx->inst[i].node[j], newval_arr[j], XINSERT);
}
#endif
} /* for(i...) */
xctx->hilight_time++;
}
if(!found) break;
/* get out from infinite loops (circuit is oscillating) */
Tcl_VarEval(interp, "update; if {$::tclstop == 1} {return 1} else {return 0}", NULL);
if( tclresult()[0] == '1') break;
iter++;
} /* while(1) */
#ifdef DELAYED_ASSIGN
my_free(779, &newval_arr);
#endif
/* my_free(1222, &propagated_net); */
}
@ -1440,7 +1464,7 @@ void logic_set(int value, int num)
char *type;
xRect boundbox;
int big = xctx->wires> 2000 || xctx->instances > 2000 ;
static int map[] = {LOGIC_0, LOGIC_1, LOGIC_X, LOGIC_Z};
static int map[] = {LOGIC_0, LOGIC_1, LOGIC_X, LOGIC_Z, LOGIC_NOUP};
struct hilight_hashentry *entry;
tclsetvar("tclstop", "0");

View File

@ -492,6 +492,7 @@ struct iterator_ctx {
struct simdata_pin {
char *function;
char *go_to;
int value;
short clock;
};

View File

@ -1,4 +1,4 @@
v {xschem version=2.9.9 file_version=1.2 }
v {xschem version=3.0.0 file_version=1.2 }
G {}
K {type=label
function0="L"

View File

@ -1,4 +1,4 @@
v {xschem version=2.9.9 file_version=1.2 }
v {xschem version=3.0.0 file_version=1.2 }
G {}
K {type=label
function0="H"

View File

@ -1,7 +1,6 @@
v {xschem version=3.0.0 file_version=1.2 }
G {}
K {type=switch
function0="1 2 3 m"
function1="0 Z 3 m"
function2="Z 0 3 m"
template="name=s1"
@ -14,10 +13,12 @@ L 4 -30 0 -10 0 {}
L 4 0 -40 0 0 {}
L 4 10 10 30 10 {}
L 4 -10 0 10 0 {}
L 4 -20 -5 -10 0 {}
L 4 -20 5 -10 0 {}
B 5 -32.5 -2.5 -27.5 2.5 {name=t0 dir=inout}
B 5 27.5 7.5 32.5 12.5 {name=t1 dir=inout }
B 5 27.5 -12.5 32.5 -7.5 {name=t2 dir=inout }
B 5 -2.5 -42.5 2.5 -37.5 {name=g dir=inout goto=0,1,2}
B 5 -2.5 -42.5 2.5 -37.5 {name=g dir=inout goto=1,2}
A 4 -8.75 0 1.25 360 360 {fill=true}
A 4 10 -10 1.25 0 360 {fill=true}
A 4 10 10 1.25 0 360 {fill=true}

View File

@ -0,0 +1,25 @@
v {xschem version=3.0.0 file_version=1.2 }
G {}
K {type=switch
function0="1 2 3 m"
template="name=s1"
}
V {}
S {}
E {}
L 4 10 -10 30 -10 {}
L 4 -30 0 -10 0 {}
L 4 0 -40 0 0 {}
L 4 10 10 30 10 {}
L 4 -10 0 10 0 {}
L 4 -20 0 -10 -5 {}
L 4 -20 0 -10 5 {}
B 5 -32.5 -2.5 -27.5 2.5 {name=t0 dir=inout}
B 5 27.5 7.5 32.5 12.5 {name=t1 dir=inout }
B 5 27.5 -12.5 32.5 -7.5 {name=t2 dir=inout }
B 5 -2.5 -42.5 2.5 -37.5 {name=g dir=inout goto=0}
A 4 -8.75 0 1.25 360 360 {fill=true}
A 4 10 -10 1.25 0 360 {fill=true}
A 4 10 10 1.25 0 360 {fill=true}
T {1} 20 -17.5 0 0 0.1 0.1 {}
T {0} 20 2.5 0 0 0.1 0.1 {}

View File

@ -1,4 +1,4 @@
v {xschem version=2.9.9 file_version=1.2 }
v {xschem version=3.0.0 file_version=1.2 }
G {}
K {type=primitive
format="@name @@D @@GATE @@RESET_B @VGND @VNB @VPB @VPWR @@Q @prefix\\\\dlrtp_1"
@ -21,7 +21,7 @@ B 5 -92.5 -22.5 -87.5 -17.5 {name=D dir=in
goto=3}
B 5 -92.5 -2.5 -87.5 2.5 {name=GATE dir=in
goto=3}
B 5 -92.5 17.5 -87.5 22.5 {name=RESET_B dir=in }
B 5 -92.5 17.5 -87.5 22.5 {name=RESET_B dir=in goto=3}
B 5 87.5 -22.5 92.5 -17.5 {name=Q dir=out }
T {@symname} 0 -6 0 0 0.3 0.3 {hcenter=true}
T {@name} 75 -42 0 0 0.2 0.2 {}

View File

@ -1,8 +1,6 @@
v {xschem version=3.0.0 file_version=1.2 }
G {}
K {type=switch
function0="3 2 4 m"
function1="2 3 4 m"
function2="1 0 4 m"
function3="0 1 4 m"
template="name=s1"
@ -19,11 +17,15 @@ L 4 -5 5 5 -5 {}
L 4 -5 -5 5 5 {}
L 4 -5 -10 5 -10 {}
L 4 -5 10 5 10 {}
L 4 -20 5 -10 10 {}
L 4 -20 15 -10 10 {}
L 4 -20 -15 -10 -10 {}
L 4 -20 -5 -10 -10 {}
B 5 -32.5 -12.5 -27.5 -7.5 {name=t0 dir=inout}
B 5 -32.5 7.5 -27.5 12.5 {name=t1 dir=inout}
B 5 27.5 7.5 32.5 12.5 {name=t2 dir=inout }
B 5 27.5 -12.5 32.5 -7.5 {name=t3 dir=inout }
B 5 -2.5 -42.5 2.5 -37.5 {name=g dir=inout goto=0,1,2,3}
B 5 -2.5 -42.5 2.5 -37.5 {name=g dir=inout goto=2,3}
A 4 -10 -10 1.25 0 360 {fill=true}
A 4 10 -10 1.25 0 360 {fill=true}
A 4 10 10 1.25 0 360 {fill=true}

View File

@ -1,8 +1,7 @@
v {xschem version=2.9.9 file_version=1.2 }
v {xschem version=3.0.0 file_version=1.2 }
G {}
K {type=nmos
function0="Z 2 1 m"
function2="Z 0 1 m"
function0="Z 2 1 M"
verilog_format="nmos #(@risedel , @falldel , @offdel ) @name ( @@d , @@s , @@g );"
format="@name @pinlist @model w=@w l=@l
+ ad='@w *4.3u' as='@w *4.3u'
@ -42,8 +41,8 @@ L 4 10 0 20 0 {}
L 4 5 -5 10 0 {}
L 4 5 5 10 0 {}
B 5 17.5 -32.5 22.5 -27.5 {name=d dir=inout}
B 5 -22.5 -2.5 -17.5 2.5 {name=g dir=in goto=0,2}
B 5 17.5 27.5 22.5 32.5 {name=s dir=inout }
B 5 -22.5 -2.5 -17.5 2.5 {name=g dir=in goto=0}
B 5 17.5 27.5 22.5 32.5 {name=s dir=inout}
B 5 17.5 -2.5 22.5 2.5 {name=b dir=in}
T {@w\\/@l\\/@m} 7.5 -17.5 0 0 0.2 0.2 {}
T {@name} 7.5 5 0 0 0.2 0.2 {}

View File

@ -1,8 +1,7 @@
v {xschem version=2.9.9 file_version=1.2 }
v {xschem version=3.0.0 file_version=1.2 }
G {}
K {type=pmos
function0="2 Z 1 m"
function2="0 Z 1 m"
function0="2 Z 1 M"
verilog_format="pmos #(@risedel , @falldel , @offdel ) @name ( @@d , @@s , @@g );"
format="@name @pinlist @model w=@w l=@l
+ ad='@w *4.6u' as='@w *4.6u'
@ -39,8 +38,8 @@ L 4 5 -5 10 0 {}
L 4 5 5 10 0 {}
L 4 10 0 20 0 {}
B 5 17.5 27.5 22.5 32.5 {name=d dir=inout}
B 5 -22.5 -2.5 -17.5 2.5 {name=g dir=in goto=0,2}
B 5 17.5 -32.5 22.5 -27.5 {name=s dir=inout }
B 5 -22.5 -2.5 -17.5 2.5 {name=g dir=in goto=0}
B 5 17.5 -32.5 22.5 -27.5 {name=s dir=inout}
B 5 17.5 -2.5 22.5 2.5 {name=b dir=in}
T {@w\\/@l\\/@m} 7.5 -17.5 0 0 0.2 0.2 {}
T {@name} 7.5 5 0 0 0.2 0.2 {999}

View File

@ -1,7 +1,6 @@
v {xschem version=3.0.0 file_version=1.2 }
G {}
K {type=switch
function0="Z 1 2 M"
function1="Z 0 2 M"
template="name=s1"
}
@ -12,9 +11,11 @@ L 4 10 0 30 0 {}
L 4 -30 0 -10 0 {}
L 4 -10 0 10 -10 {}
L 4 0 -40 0 -5 {}
L 4 -25 -5 -15 0 {}
L 4 -25 5 -15 0 {}
B 5 -32.5 -2.5 -27.5 2.5 {name=t0 dir=inout}
B 5 27.5 -2.5 32.5 2.5 {name=t1 dir=inout }
B 5 -2.5 -43.75 2.5 -38.75 {name=g dir=inout goto=0,1}
B 5 -2.5 -43.75 2.5 -38.75 {name=g dir=inout goto=1}
A 4 10 0 1.25 0 360 {fill=true}
A 4 -10 0 1.25 0 360 {fill=true}
T {1} 20 -7.5 0 0 0.1 0.1 {}

View File

@ -296,14 +296,14 @@ C {p.sym} 300 -1210 3 0 {name=m12 model=cmosp w=wp l=lp m=1 }
C {lab_pin.sym} 300 -1230 3 1 {name=p34 lab=VCC}
C {vdd.sym} 100 -1290 0 0 {name=l5 lab=VCC}
C {gnd.sym} 100 -1030 0 0 {name=l6 lab=GND}
C {n.sym} 650 -1110 1 0 {name=m13 model=cmosn w=wn l=lln m=1}
C {n.sym} 650 -1110 3 1 {name=m13 model=cmosn w=wn l=lln m=1}
C {lab_pin.sym} 650 -1090 1 1 {name=p35 lab=GND}
C {p.sym} 650 -950 3 0 {name=m14 model=cmosp w=wp l=lp m=1 }
C {p.sym} 650 -950 1 1 {name=m14 model=cmosp w=wp l=lp m=1 }
C {lab_pin.sym} 650 -970 3 1 {name=p36 lab=VCC}
C {inv_2.sym} 740 -1160 0 1 {name=x19 VGND=VGND VNB=VNB VPB=VPB VPWR=VPWR prefix=sky130_fd_sc_hd__ }
C {n.sym} 650 -1370 1 0 {name=m15 model=cmosn w=wn l=lln m=1}
C {n.sym} 650 -1370 3 1 {name=m15 model=cmosn w=wn l=lln m=1}
C {lab_pin.sym} 650 -1350 1 1 {name=p37 lab=GND}
C {p.sym} 650 -1210 3 0 {name=m16 model=cmosp w=wp l=lp m=1 }
C {p.sym} 650 -1210 1 1 {name=m16 model=cmosp w=wp l=lp m=1 }
C {lab_pin.sym} 650 -1230 3 1 {name=p38 lab=VCC}
C {vdd.sym} 850 -1290 0 1 {name=l7 lab=VCC}
C {gnd.sym} 850 -1030 0 1 {name=l8 lab=GND}
@ -312,7 +312,7 @@ C {switch-1.sym} 1370 -1260 0 0 {name=s4}
C {inv_2.sym} 1370 -1190 0 0 {name=x20 VGND=VGND VNB=VNB VPB=VPB VPWR=VPWR prefix=sky130_fd_sc_hd__ }
C {diode_3.sym} 1270 -1280 0 0 {name=x12 VTH=0.6 RON=10 ROFF=1G}
C {ipin.sym} 70 -170 0 0 { name=p19 lab=B }
C {dev-1.sym} 1530 -620 0 1 {name=s3}
C {dev-2.sym} 1530 -620 0 1 {name=s3}
C {invert-1.sym} 1370 -620 0 0 {name=s1}
C {dev-1.sym} 1210 -620 0 0 {name=s2}
C {vdd.sym} 1080 -620 0 0 {name=l9 lab=VCC}