diff --git a/vvp/compile.cc b/vvp/compile.cc index 91f5ab953..7a8c8364c 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: compile.cc,v 1.68 2001/05/24 04:20:10 steve Exp $" +#ident "$Id: compile.cc,v 1.69 2001/05/30 03:02:35 steve Exp $" #endif # include "compile.h" @@ -271,37 +271,37 @@ static void inputs_connect(vvp_ipoint_t fdx, unsigned argc, struct symb_s*argv) if (strcmp(argv[idx].text, "C<0>") == 0) { free(argv[idx].text); - functor_put_input(iobj, idx, 0, 6, 6); + functor_put_input(iobj, idx, 0, St0); continue; } if (strcmp(argv[idx].text, "C") == 0) { free(argv[idx].text); - functor_put_input(iobj, idx, 0, 5, 5); + functor_put_input(iobj, idx, 0, Pu0); continue; } if (strcmp(argv[idx].text, "C<1>") == 0) { free(argv[idx].text); - functor_put_input(iobj, idx, 1, 6, 6); + functor_put_input(iobj, idx, 1, St1); continue; } if (strcmp(argv[idx].text, "C") == 0) { free(argv[idx].text); - functor_put_input(iobj, idx, 1, 5, 5); + functor_put_input(iobj, idx, 1, Pu1); continue; } if (strcmp(argv[idx].text, "C") == 0) { free(argv[idx].text); - functor_put_input(iobj, idx, 2, 6, 6); + functor_put_input(iobj, idx, 2, StX); continue; } if (strcmp(argv[idx].text, "C") == 0) { free(argv[idx].text); - functor_put_input(iobj, idx, 3, 6, 6); + functor_put_input(iobj, idx, 3, HiZ); continue; } @@ -1207,6 +1207,9 @@ vvp_ipoint_t debug_lookup_functor(const char*name) /* * $Log: compile.cc,v $ + * Revision 1.69 2001/05/30 03:02:35 steve + * Propagate strength-values instead of drive strengths. + * * Revision 1.68 2001/05/24 04:20:10 steve * Add behavioral modulus. * diff --git a/vvp/debug.cc b/vvp/debug.cc index 0ab1cf828..f265aa33c 100644 --- a/vvp/debug.cc +++ b/vvp/debug.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: debug.cc,v 1.2 2001/05/08 23:32:26 steve Exp $" +#ident "$Id: debug.cc,v 1.3 2001/05/30 03:02:35 steve Exp $" #endif /* @@ -91,15 +91,13 @@ static void cmd_functor(unsigned argc, char*argv[]) } printf("out pointer = 0x%x\n", fp->out); - printf("input values = %c %c %c %c\n", - bitval_tab[fp->ival&3], - bitval_tab[(fp->ival>>2)&3], - bitval_tab[(fp->ival>>4)&3], - bitval_tab[(fp->ival>>6)&3]); - printf("out value = %c (%s0 %s1)\n", - bitval_tab[fp->oval], - strength_tab[fp->odrive0], - strength_tab[fp->odrive1]); + printf("input values = %c (%02x) %c (%02x) %c (%02x) %c (%02x)\n", + bitval_tab[fp->ival&3], fp->istr[0], + bitval_tab[(fp->ival>>2)&3], fp->istr[1], + bitval_tab[(fp->ival>>4)&3], fp->istr[2], + bitval_tab[(fp->ival>>6)&3], fp->istr[3]); + printf("out value = %c (%02x)\n", + bitval_tab[fp->oval], 0 /*xxxx*/); } } @@ -169,6 +167,9 @@ void breakpoint(void) #endif /* * $Log: debug.cc,v $ + * Revision 1.3 2001/05/30 03:02:35 steve + * Propagate strength-values instead of drive strengths. + * * Revision 1.2 2001/05/08 23:32:26 steve * Add to the debugger the ability to view and * break on functors. diff --git a/vvp/functor.cc b/vvp/functor.cc index 5eeb71866..699609c94 100644 --- a/vvp/functor.cc +++ b/vvp/functor.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: functor.cc,v 1.20 2001/05/12 20:38:06 steve Exp $" +#ident "$Id: functor.cc,v 1.21 2001/05/30 03:02:35 steve Exp $" #endif # include "functor.h" @@ -134,21 +134,15 @@ functor_t functor_index(vvp_ipoint_t point) return functor_table[point]->table[index1]->table + index0; } -void functor_put_input(functor_t fp, unsigned pp, unsigned val, - unsigned drive0, unsigned drive1) +void functor_put_input(functor_t fp, unsigned pp, unsigned val, unsigned str) { /* Change the bits of the input. */ static const unsigned char ival_mask[4] = { 0xfc, 0xf3, 0xcf, 0x3f }; unsigned char imask = ival_mask[pp]; fp->ival = (fp->ival & imask) | ((val & 3) << (2*pp)); - /* change the bits of the drive. */ - static const unsigned drive_mask[4] = { 0xffffc0, 0xfff03f, - 0xfc0fff, 0x03ffff }; - unsigned dmask = drive_mask[pp]; - fp->idrive = (fp->idrive & dmask) - | (drive1 << (3+6*pp)) - | (drive0 << 6*pp); + /* Save the strength aware input value. */ + fp->istr[pp] = str; } static void functor_set_mode0(vvp_ipoint_t ptr, functor_t fp, bool push) @@ -251,19 +245,14 @@ static void functor_set_mode2(functor_t fp) * output. If the output changes any, then generate the necessary * propagation events to pass the output on. */ -void functor_set(vvp_ipoint_t ptr, unsigned bit, - unsigned drive0, unsigned drive1, - bool push) +void functor_set(vvp_ipoint_t ptr, unsigned bit, unsigned str, bool push) { functor_t fp = functor_index(ptr); unsigned pp = ipoint_port(ptr); assert(fp); - assert(drive0 <= 8); - assert(drive1 <= 8); - /* Store the value and strengths in the input bits. */ - functor_put_input(fp, pp, bit, drive0, drive1); + functor_put_input(fp, pp, bit, str); switch (fp->mode) { case 0: @@ -319,11 +308,28 @@ void functor_propagate(vvp_ipoint_t ptr) unsigned drive0 = fp->odrive0; unsigned drive1 = fp->odrive1; + unsigned str; + switch (oval) { + case 0: + str = 0x00 | (drive0<<0) | (drive0<<4); + break; + case 1: + str = 0x88 | (drive1<<0) | (drive1<<4); + break; + case 2: + str = 0x80 | (drive0<<0) | (drive1<<4); + break; + case 3: + str = 0x00; + break; + } + vvp_ipoint_t idx = fp->out; while (idx) { functor_t idxp = functor_index(idx); vvp_ipoint_t next = idxp->port[ipoint_port(idx)]; - functor_set(idx, oval, drive0, drive1); + + functor_set(idx, oval, str, false); idx = next; } } @@ -354,6 +360,9 @@ const unsigned char ft_var[16] = { /* * $Log: functor.cc,v $ + * Revision 1.21 2001/05/30 03:02:35 steve + * Propagate strength-values instead of drive strengths. + * * Revision 1.20 2001/05/12 20:38:06 steve * A resolver that understands some simple strengths. * diff --git a/vvp/functor.h b/vvp/functor.h index 4a466e419..4b5b574c8 100644 --- a/vvp/functor.h +++ b/vvp/functor.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: functor.h,v 1.22 2001/05/12 20:38:06 steve Exp $" +#ident "$Id: functor.h,v 1.23 2001/05/30 03:02:35 steve Exp $" #endif # include "pointers.h" @@ -83,14 +83,14 @@ * methods for receiving and retrieving values. See the vvp_fobj_s * definition below. * - * STRENGTHS: + * DRIVE STRENGTHS: * * The normal functor (modes 0, 1 and 2) is not aware of strengths. It * generates strength simply by virtue of having strength - * specifications. + * specifications. The drive strength specification includes a drive0 + * and drive1 strength, each with 8 possible values (that can be + * represented in 3 bits) as given in this table: * - * When the bit value is read out of the functor, only the val bits - * are read. There are 8 drive values available in the 3 bits: * HiZ = 0, * SMALL = 1, * MEDIUM = 2, @@ -100,7 +100,14 @@ * STRONG = 6, * SUPPLY = 7 * - * Only mode-42 functors are strength-aware. + * OUTPUT STRENGTHS: + * + * The strength-aware outputs are specified as an 8 bit value, that is + * two 4 bit numbers. The value is encoded with two drive strengths (0-7) + * and two drive values (0 or 1). Each nibble contains three bits of + * strength and one bit of value, like so: VSSS. The high nible has + * the strength-value closest to supply1, and the low nibble has the + * strength-value closest to supply0. */ struct functor_s { @@ -115,11 +122,11 @@ struct functor_s { vvp_ipoint_t out; /* These are the input ports. */ vvp_ipoint_t port[4]; - /* These are the input values. */ + /* Input with strengths, for strength aware functors. */ + unsigned char istr[4]; + /* Input values without strengths. */ unsigned ival : 8; - /* Input strengths, for strength aware functors. */ - unsigned idrive : 4*6; - /* Output value (low bits, and drive1 and drive0 strength. */ + /* Output value (low bits) and drive1 and drive0 strength. */ unsigned oval : 2; unsigned odrive0 : 3; unsigned odrive1 : 3; @@ -137,6 +144,15 @@ struct functor_s { typedef struct functor_s *functor_t; +enum strength_e { + HiZ = 0x00, + St0 = 0x66, /* St0-St0 */ + Pu0 = 0x55, /* Pu0-Pu0 */ + St1 = 0x66|0x88, /* St1 - St1 */ + Pu1 = 0x55|0x88, /* Pu1 - Pu1 */ + StX = 0x66|0x80, /* St0 - St1 */ +}; + /* * This a an `obj' structute for mode-42 functors. * Each instance implements the get and set methods in a type specific @@ -200,9 +216,12 @@ extern vvp_ipoint_t functor_allocate(unsigned wid); * This function is used by the compile time to initialize the value * of an input, and by the run time to manipulate the bits of the * input in a uniform manner. + * + * The val parameter is the 2bit representation of the input value, + * and the str is a strength aware version. */ -extern void functor_put_input(functor_t fp, unsigned pp, unsigned val, - unsigned drive0, unsigned drive1); +extern void functor_put_input(functor_t fp, unsigned pp, + unsigned val, unsigned str); /* * functor_set sets the addressed input to the specified value, and @@ -210,13 +229,12 @@ extern void functor_put_input(functor_t fp, unsigned pp, unsigned val, * propagation events are created. Propagation calls further * functor_set methods for the functors connected to the output. * - * The val contains 2 bits two represent the 4-value bit. The drive0 - * and drive1 values are also passed, and typically just stored in the + * The val contains 2 bits two represent the 4-value bit. The str + * version is also passed, and typically just stored in the * functor. */ extern void functor_set(vvp_ipoint_t point, unsigned val, - unsigned drive0, unsigned drive1, - bool push=false); + unsigned str, bool push); /* * Read the value of the functor. In fact, only the *value* is read -- @@ -264,6 +282,9 @@ extern const unsigned char ft_var[]; /* * $Log: functor.h,v $ + * Revision 1.23 2001/05/30 03:02:35 steve + * Propagate strength-values instead of drive strengths. + * * Revision 1.22 2001/05/12 20:38:06 steve * A resolver that understands some simple strengths. * diff --git a/vvp/resolv.cc b/vvp/resolv.cc index 3abd94883..b37524db6 100644 --- a/vvp/resolv.cc +++ b/vvp/resolv.cc @@ -17,104 +17,104 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: resolv.cc,v 1.2 2001/05/12 20:38:06 steve Exp $" +#ident "$Id: resolv.cc,v 1.3 2001/05/30 03:02:35 steve Exp $" #endif # include "resolv.h" # include "schedule.h" -static void blend(unsigned&val, unsigned&drv0, unsigned drv1, - unsigned inp, unsigned inp0, unsigned inp1) +/* + * A signal value is unambiguous if the top 4 bits and the bottom 4 + * bits are identical. This means that the VSSSvsss bits of the 8bit + * value have V==v and SSS==sss. + */ +# define UNAMBIG(v) (((v) & 0x0f) == (((v) >> 4) & 0x0f)) + +# define STREN1(v) ( ((v)&0x80)? ((v)&0xf0) : (0x70 - ((v)&0xf0)) ) +# define STREN0(v) ( ((v)&0x08)? ((v)&0x0f) : (0x07 - ((v)&0x0f)) ) + +static unsigned blend(unsigned a, unsigned b) { - switch (val) { - case 3: - val = inp; - drv0 = inp0; - drv1 = inp1; - break; + if (a == HiZ) + return b; - case 0: - switch (inp) { - case 0: - if (drv0 < inp0) - drv0 = inp0; - break; + if (b == HiZ) + return a; - case 1: - if (drv0 < inp1) { - val = 1; - drv1 = inp1; - } - break; + unsigned res = a; - case 2: - if (drv0 < inp1) { - val = 2; - if (drv0 < inp0) - drv0 = inp0; - if (drv1 < inp1) - drv0 = inp1; - } - break; + if (UNAMBIG(a) && UNAMBIG(b)) { + + /* If both signals are unambiguous, simply choose + the stronger. If they have the same strength + but different values, then this becomes + ambiguous. */ + + if (a == b) { + + /* values are equal. do nothing. */ + + } else if ((b&0x07) > (res&0x07)) { + + /* New value is stronger. Take it. */ + res = b; + + } else if ((b&0x77) == (res&0x77)) { + + /* Strengths are the same. Make value ambiguous. */ + res = (res&0x70) | (b&0x07) | 0x80; + + } else { + + /* Must be res is the stronger one. */ } - break; - case 1: - switch (inp) { - case 0: - if (drv1 < inp0) { - val = 0; - drv1 = inp1; - } - break; + } else if (UNAMBIG(res) || UNAMBIG(b)) { - case 1: - if (drv1 < inp1) { - drv1 = inp1; - } - break; + /* If one of the signals is unambiguous, then it + will sweep up the weaker parts of the ambiguous + signal. The result may be ambiguous, or maybe not. */ - case 2: - if (drv1 < inp0) { - val = 2; - if (drv0 < inp0) - drv0 = inp0; - if (drv1 < inp1) - drv0 = inp1; - } - break; - } - break; + unsigned tmp = 0; + if ((res&0x70) > (b&0x70)) + tmp |= res&0xf0; + else + tmp |= b&0xf0; - case 2: - switch (inp) { - case 0: - if (drv1 < inp0) { - val = 0; - drv0 = inp0; - drv1 = inp1; - } - break; + if ((res&0x07) > (b&0x07)) + tmp |= res&0x0f; + else + tmp |= b&0x0f; - case 1: - if (drv0 < inp1) { - val = 1; - drv0 = inp0; - drv1 = inp1; - } - break; + res = tmp; - case 2: - if (drv0 < inp0) - drv0 = inp0; - if (drv1 < inp1) - drv0 = inp1; - break; - } - break; + } else { + /* If both signals are ambiguous, then the result + has an even wider ambiguity. */ + + unsigned tmp = 0; + + if (STREN1(b) > STREN1(res)) + tmp |= b&0xf0; + else + tmp |= res&0xf0; + + if (STREN0(b) < STREN0(res)) + tmp |= b&0x0f; + else + tmp |= res&0x0f; + + res = tmp; } + + + /* Cannonicalize the HiZ value. */ + if ((res&0x77) == 0) + res = HiZ; + + return res; } /* @@ -124,31 +124,31 @@ static void blend(unsigned&val, unsigned&drv0, unsigned drv1, */ void vvp_resolv_s::set(vvp_ipoint_t ptr, functor_t fp, bool push) { - unsigned val = (fp->ival >> 0) & 3; - unsigned drv0 = (fp->idrive >> 0) & 7; - unsigned drv1 = (fp->idrive >> 3) & 7; + unsigned val = fp->istr[0]; - blend(val, drv0, drv1, - (fp->ival >> 2) & 3, - (fp->idrive >> 6) & 7, - (fp->idrive >> 9) & 7); + val = blend(val, fp->istr[1]); + val = blend(val, fp->istr[2]); + val = blend(val, fp->istr[3]); - blend(val, drv0, drv1, - (fp->ival >> 4) & 3, - (fp->idrive >>12) & 7, - (fp->idrive >>15) & 7); + unsigned oval; + if (val == HiZ) { + oval = 3; - blend(val, drv0, drv1, - (fp->ival >> 6) & 3, - (fp->idrive >>18) & 7, - (fp->idrive >>21) & 7); - - fp->odrive0 = drv0; - fp->odrive1 = drv1; + } else switch (val & 0x88) { + case 0x00: + oval = 0; + break; + case 0x88: + oval = 1; + break; + default: + oval = 2; + break; + } /* If the output changes, then create a propagation event. */ - if (val != fp->oval) { - fp->oval = val; + if (oval != fp->oval) { + fp->oval = oval; if (push) functor_propagate(ptr); else @@ -158,6 +158,9 @@ void vvp_resolv_s::set(vvp_ipoint_t ptr, functor_t fp, bool push) /* * $Log: resolv.cc,v $ + * Revision 1.3 2001/05/30 03:02:35 steve + * Propagate strength-values instead of drive strengths. + * * Revision 1.2 2001/05/12 20:38:06 steve * A resolver that understands some simple strengths. * diff --git a/vvp/schedule.cc b/vvp/schedule.cc index 30309834e..74d5830c0 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: schedule.cc,v 1.9 2001/05/08 23:32:26 steve Exp $" +#ident "$Id: schedule.cc,v 1.10 2001/05/30 03:02:35 steve Exp $" #endif # include "schedule.h" @@ -255,7 +255,20 @@ void schedule_simulate(void) break; case TYPE_ASSIGN: - functor_set(cur->fun, cur->val, 6, 6); + switch (cur->val) { + case 0: + functor_set(cur->fun, cur->val, St0, false); + break; + case 1: + functor_set(cur->fun, cur->val, St1, false); + break; + case 2: + functor_set(cur->fun, cur->val, StX, false); + break; + case 3: + functor_set(cur->fun, cur->val, HiZ, false); + break; + } break; case TYPE_GEN: @@ -271,6 +284,9 @@ void schedule_simulate(void) /* * $Log: schedule.cc,v $ + * Revision 1.10 2001/05/30 03:02:35 steve + * Propagate strength-values instead of drive strengths. + * * Revision 1.9 2001/05/08 23:32:26 steve * Add to the debugger the ability to view and * break on functors. diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 2a214744c..447ee6b7f 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vpi_signal.cc,v 1.14 2001/05/22 04:08:49 steve Exp $" +#ident "$Id: vpi_signal.cc,v 1.15 2001/05/30 03:02:35 steve Exp $" #endif /* @@ -301,7 +301,7 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp, long val = vp->value.integer; for (unsigned idx = 0 ; idx < wid ; idx += 1) { functor_set(ipoint_index(rfp->bits,idx), val&1, - 6, 6, true); + (val&1)? St1 : St0, true); val >>= 1; } break; @@ -310,16 +310,16 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp, case vpiScalarVal: switch (vp->value.scalar) { case vpi0: - functor_set(rfp->bits, 0, 6, 6, true); + functor_set(rfp->bits, 0, St0, true); break; case vpi1: - functor_set(rfp->bits, 1, 6, 6, true); + functor_set(rfp->bits, 1, St1, true); break; case vpiX: - functor_set(rfp->bits, 2, 6, 6, true); + functor_set(rfp->bits, 2, StX, true); break; case vpiZ: - functor_set(rfp->bits, 3, 6, 6, true); + functor_set(rfp->bits, 3, HiZ, true); break; default: assert(0); @@ -336,19 +336,19 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp, switch (bit) { case 0: /* zero */ functor_set(ipoint_index(rfp->bits,idx), - 0, 6, 6, true); + 0, St0, true); break; case 1: /* one */ functor_set(ipoint_index(rfp->bits,idx), - 1, 6, 6, true); + 1, St1, true); break; case 2: /* z */ functor_set(ipoint_index(rfp->bits,idx), - 3, 6, 6, true); + 3, HiZ, true); break; case 3: /* x */ functor_set(ipoint_index(rfp->bits,idx), - 2, 6, 6, true); + 2, StX, true); break; } aval >>= 1; @@ -432,6 +432,9 @@ vpiHandle vpip_make_net(char*name, int msb, int lsb, bool signed_flag, /* * $Log: vpi_signal.cc,v $ + * Revision 1.15 2001/05/30 03:02:35 steve + * Propagate strength-values instead of drive strengths. + * * Revision 1.14 2001/05/22 04:08:49 steve * correctly interpret signed decimal values. * diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 9a4daa4d7..609aa64ea 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vthread.cc,v 1.41 2001/05/24 04:20:10 steve Exp $" +#ident "$Id: vthread.cc,v 1.42 2001/05/30 03:02:35 steve Exp $" #endif # include "vthread.h" @@ -879,10 +879,12 @@ bool of_OR(vthread_t thr, vvp_code_t cp) return true; } +static const unsigned char strong_values[4] = {St0, St1, StX, HiZ}; + bool of_SET(vthread_t thr, vvp_code_t cp) { unsigned char bit_val = thr_get_bit(thr, cp->bit_idx1); - functor_set(cp->iptr, bit_val, 6, 6, true); + functor_set(cp->iptr, bit_val, strong_values[bit_val], true); return true; } @@ -1045,6 +1047,9 @@ bool of_ZOMBIE(vthread_t thr, vvp_code_t) /* * $Log: vthread.cc,v $ + * Revision 1.42 2001/05/30 03:02:35 steve + * Propagate strength-values instead of drive strengths. + * * Revision 1.41 2001/05/24 04:20:10 steve * Add behavioral modulus. *