From b142be7fde3847c526b43a4080e81206e9bb78aa Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Tue, 1 Nov 2022 11:29:43 -0700 Subject: [PATCH] Add behavioral (LOGICEXP, PINDLY) test for 283 circuit. There are glitches in the simulation for some of the s* outputs. Probably due to not having inertial delays. And why not set 'zero' delays as close to zero as permitted by XSPICE. --- examples/p-to-n-examples/behav-283.cir | 91 ++++++++++++++++++++++++++ src/frontend/logicexp.c | 18 ++--- src/frontend/udevices.c | 12 ++-- 3 files changed, 106 insertions(+), 15 deletions(-) create mode 100644 examples/p-to-n-examples/behav-283.cir diff --git a/examples/p-to-n-examples/behav-283.cir b/examples/p-to-n-examples/behav-283.cir new file mode 100644 index 000000000..9711a6368 --- /dev/null +++ b/examples/p-to-n-examples/behav-283.cir @@ -0,0 +1,91 @@ +Behavioral CMOS 283 : 4-bit adder + +*-------------------------------------------------------------74AC283----- +* +* The 74AC283 4-Bit Binary Full Adder with Fast Carry +* (4 Page Fax) Harris Advanced CMOS Logic, File Number 1912 +* and Philips Semiconductors High-speed CMOS Logic Data Handbook +* for the logic diagram, 1994, page 564 +* jat 7/26/95 + +.SUBCKT 74AC283 ++ A0 A1 A2 A3 B0 B1 B2 B3 CIN COUT S0 S1 S2 S3 ++ OPTIONAL: DPWR=$G_DPWR DGND=$G_DGND ++ PARAMS: MNTYMXDLY=0 IO_LEVEL=0 + +U1 LOGICEXP(9,5) DPWR DGND ++ A0 A1 A2 A3 B0 B1 B2 B3 CIN ++ S_0 S_1 S_2 S_3 C_OUT ++ D0_GATE IO_AC ++ MNTYMXDLY={MNTYMXDLY} IO_LEVEL={IO_LEVEL} ++ LOGIC: ++ S_0 = {A0 ^ B0 ^ CIN} ++ NOR1 = {(A0 | B0) & (CIN | (A0 & B0))} ++ S_1 = {NOR1 ^ A1 ^ B1} ++ NOR2 = {~((~(A1 | B1)) | ((~(A0 | B0)) & (~(A1 & B1))) | ++ ((~(A1 & B1)) & (~(A0 & B0)) & (~CIN)))} ++ S_2 = {NOR2 ^ A2 ^ B2} ++ AND31 = {(~(A2 & B2)) & (~(A1 & B1)) & (~(A0 & B0)) & (~CIN)} ++ AND32 = {(~(A0 | B0)) & (~(A2 & B2)) & (~(A1 & B1))} ++ AND33 = {(~(A1 | B1)) & (~(A2 & B2))} ++ NOR3 = {~(AND31 | AND32 | AND33 | (~(A2 | B2)))} ++ S_3 = {NOR3 ^ A3 ^ B3} ++ ANDC1 = {(~(A3 & B3)) & (~(A2 & B2)) & (~(A1 & B1)) & ++ (~(A0 & B0)) & (~CIN)} ++ ANDC2 = {(~(A0 | B0)) & (~(A3 & B3)) & (~(A2 & B2)) & (~(A1 & B1))} ++ ANDC3 = {(~(A1 | B1)) & (~(A3 & B3)) & (~(A2 & B2))} ++ ANDC4 = {(~(A2 | B2)) & (~(A3 & B3))} ++ C_OUT = {~(ANDC1 | ANDC2 | ANDC3 | ANDC4 | (~(A3 | B3)))} + +U2 PINDLY(5,0,9) DPWR DGND ++ S_0 S_1 S_2 S_3 C_OUT ++ A0 A1 A2 A3 B0 B1 B2 B3 CIN ++ S0 S1 S2 S3 COUT ++ IO_AC ++ MNTYMXDLY={MNTYMXDLY} IO_LEVEL={IO_LEVEL} ++ BOOLEAN: ++ CARRYIN = {CHANGED(CIN,0)} ++ NUMBER = {CHANGED(A0,0) | CHANGED(A1,0) | CHANGED(A2,0) | ++ CHANGED(A3,0) | CHANGED(B0,0) | CHANGED(B1,0) | ++ CHANGED(B2,0) | CHANGED(B3,0)} ++ PINDLY: ++ S0 S1 S2 S3 = { ++ CASE( ++ NUMBER & (TRN_LH | TRN_HL), DELAY(4.7NS,-1,16.5NS), ++ CARRYIN & (TRN_LH | TRN_HL), DELAY(4.5NS,-1,16NS), ++ DELAY(5.7NS,-1,17.5NS))} ++ COUT = { ++ CASE( ++ NUMBER & (TRN_LH | TRN_HL), DELAY(4.5NS,-1,16NS), ++ CARRYIN & (TRN_LH | TRN_HL), DELAY(4.5NS,-1,16NS), ++ DELAY(5.7NS,-1,17.5NS))} + +.ENDS 74AC283 + +X1 a0 a1 a2 a3 b0 b1 b2 b3 cin cout s0 s1 s2 s3 74ac283 +a_1 [ a3 a2 a1 a0 b3 b2 b1 b0 cin ] input_vec1 +.model input_vec1 d_source(input_file = "ex283.stim") + +.tran 0.01ns 2us +.control +run +listing +edisplay +eprint a3 a2 a1 a0 b3 b2 b1 b0 cin +eprint s3 s2 s1 s0 cout +* save data to input directory +cd $inputdir +eprvcd a3 a2 a1 a0 b3 b2 b1 b0 cin s3 s2 s1 s0 cout > behav-283.vcd +* plotting the vcd file with GTKWave +if $oscompiled = 1 | $oscompiled = 8 ; MS Windows + shell start gtkwave behav-283.vcd --script nggtk.tcl +else + if $oscompiled = 7 ; macOS, manual tweaking required (mark, insert, Zoom Fit) + shell open -a gtkwave behav-283.vcd + else ; Linux and others + shell gtkwave behav-283.vcd --script nggtk.tcl & + end +end +quit +.endc +.end diff --git a/src/frontend/logicexp.c b/src/frontend/logicexp.c index 448459cf7..ff66e0a2b 100644 --- a/src/frontend/logicexp.c +++ b/src/frontend/logicexp.c @@ -629,47 +629,47 @@ static void gen_models(void) ds_clear(&model); ds_cat_printf(&model, - ".model d_inv_zero_delay d_inverter(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model d_inv_zero_delay d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__inverter__1 d_inverter(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model d__inverter__1 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__buffer__1 d_buffer(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model d__buffer__1 d_buffer(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__nand__1 d_nand(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model d__nand__1 d_nand(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__and__1 d_and(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model d__and__1 d_and(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__xnor__1 d_xnor(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model d__xnor__1 d_xnor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__xor__1 d_xor(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model d__xor__1 d_xor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__nor__1 d_nor(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model d__nor__1 d_nor(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_clear(&model); ds_cat_printf(&model, - ".model d__or__1 d_or(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model d__or__1 d_or(rise_delay=1.0e-12 fall_delay=1.0e-12)"); u_add_instance(ds_get_buf(&model)); ds_free(&model); diff --git a/src/frontend/udevices.c b/src/frontend/udevices.c index 000316e37..1f0dc76cd 100644 --- a/src/frontend/udevices.c +++ b/src/frontend/udevices.c @@ -720,7 +720,7 @@ struct card *replacement_udevice_cards(void) } if (add_zero_delay_inverter_model) { x = create_xlate_translated( - ".model d_zero_inv99 d_inverter(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model d_zero_inv99 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); } if (add_drive_hilo) { @@ -729,7 +729,7 @@ struct card *replacement_udevice_cards(void) x = create_xlate_translated("a1 0 drive___0 dbuf1"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated( - ".model dbuf1 d_buffer(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model dbuf1 d_buffer(rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated(".ends hilo_dollar___lo"); translated_p = add_xlator(translated_p, x); @@ -738,7 +738,7 @@ struct card *replacement_udevice_cards(void) x = create_xlate_translated("a2 0 drive___1 dinv1"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated( - ".model dinv1 d_inverter(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + ".model dinv1 d_inverter(rise_delay=1.0e-12 fall_delay=1.0e-12)"); translated_p = add_xlator(translated_p, x); x = create_xlate_translated(".ends hilo_dollar___hi"); translated_p = add_xlator(translated_p, x); @@ -2504,7 +2504,7 @@ static char *get_estimate(struct timing_data *tdp) */ static char *get_zero_rise_fall(void) { - return tprintf("(rise_delay=1.0e-11 fall_delay=1.0e-11)"); + return tprintf("(rise_delay=1.0e-12 fall_delay=1.0e-12)"); } static char *get_delays_ugate(char *rem) @@ -2549,10 +2549,10 @@ static char *get_delays_utgate(char *rem) if (strlen(rising) > 0 && strlen(falling) > 0) { delays = tprintf("(delay = %s)", rising); } else { - delays = tprintf("(delay=1.0e-11)"); + delays = tprintf("(delay=1.0e-12)"); } } else { - delays = tprintf("(delay=1.0e-11)"); + delays = tprintf("(delay=1.0e-12)"); } delete_timing_data(tdp1); delete_timing_data(tdp2);