A python module for parsing, processing, and simulating gate-level circuits.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

231 lines
7.1 KiB

import numpy as np
from kyupy import sdf, verilog, bench
from kyupy.wave_sim import WaveSim, TMAX, TMIN
from kyupy.techlib import SAED32, SAED90
def test_parse():
test = '''
(DELAYFILE
(SDFVERSION "OVI 2.1")
(DESIGN "test")
(DATE "Wed May 31 14:46:06 2017")
(VENDOR "saed90nm_max")
(PROGRAM "Synopsys Design Compiler cmos-annotated")
(VERSION "I-2013.12-ICC-SP3")
(DIVIDER /)
(VOLTAGE 1.20:1.20:1.20)
(PROCESS "TYPICAL")
(TEMPERATURE 25.00:25.00:25.00)
(TIMESCALE 1ns)
(CELL
(CELLTYPE "b14")
(INSTANCE)
(DELAY
(ABSOLUTE
(INTERCONNECT U621/ZN U19246/IN1 (0.000:0.000:0.000))
(INTERCONNECT U13292/QN U19246/IN2 (0.001:0.001:0.001))
(INTERCONNECT U15050/QN U19247/IN1 (0.000:0.000:0.000))
(INTERCONNECT U13293/QN U19247/IN2 (0.000:0.000:0.000) (0.000:0.000:0.000))
)
)
)
(CELL
(CELLTYPE "INVX2")
(INSTANCE U78)
(DELAY
(ABSOLUTE
(IOPATH INP ZN (0.201:0.227:0.227) (0.250:0.271:0.271))
)
)
)
(CELL
(CELLTYPE "SDFFARX1")
(INSTANCE reg3_reg_1_0)
(DELAY
(ABSOLUTE
(IOPATH (posedge CLK) Q (0.707:0.710:0.710) (0.737:0.740:0.740))
(IOPATH (negedge RSTB) Q () (0.909:0.948:0.948))
(IOPATH (posedge CLK) QN (0.585:0.589:0.589) (0.545:0.550:0.550))
(IOPATH (negedge RSTB) QN (1.546:1.593:1.593) ())
)
)
(TIMINGCHECK
(WIDTH (posedge CLK) (0.284:0.284:0.284))
(WIDTH (negedge CLK) (0.642:0.642:0.642))
(SETUP (posedge D) (posedge CLK) (0.544:0.553:0.553))
(SETUP (negedge D) (posedge CLK) (0.620:0.643:0.643))
(HOLD (posedge D) (posedge CLK) (-0.321:-0.331:-0.331))
(HOLD (negedge D) (posedge CLK) (-0.196:-0.219:-0.219))
(RECOVERY (posedge RSTB) (posedge CLK) (-1.390:-1.455:-1.455))
(HOLD (posedge RSTB) (posedge CLK) (1.448:1.509:1.509))
(SETUP (posedge SE) (posedge CLK) (0.662:0.670:0.670))
(SETUP (negedge SE) (posedge CLK) (0.698:0.702:0.702))
(HOLD (posedge SE) (posedge CLK) (-0.435:-0.444:-0.444))
(HOLD (negedge SE) (posedge CLK) (-0.291:-0.295:-0.295))
(SETUP (posedge SI) (posedge CLK) (0.544:0.544:0.544))
(SETUP (negedge SI) (posedge CLK) (0.634:0.688:0.688))
(HOLD (posedge SI) (posedge CLK) (-0.317:-0.318:-0.318))
(HOLD (negedge SI) (posedge CLK) (-0.198:-0.247:-0.247))
(WIDTH (negedge RSTB) (0.345:0.345:0.345))
)))
'''
df = sdf.parse(test)
assert df.name == 'test'
def test_b15(mydir):
df = sdf.load(mydir / 'b15_2ig.sdf.gz')
assert df.name == 'b15'
def test_gates(mydir):
c = verilog.load(mydir / 'gates.v', tlib=SAED90)
df = sdf.load(mydir / 'gates.sdf')
lt = df.iopaths(c, tlib=SAED90)[1]
nand_a = c.cells['nandgate'].ins[0]
nand_b = c.cells['nandgate'].ins[1]
and_a = c.cells['andgate'].ins[0]
and_b = c.cells['andgate'].ins[1]
assert lt[nand_a, 0, 0] == 0.103
assert lt[nand_a, 0, 1] == 0.127
assert lt[nand_b, 0, 0] == 0.086
assert lt[nand_b, 0, 1] == 0.104
assert lt[and_a, 0, 0] == 0.378
assert lt[and_a, 0, 1] == 0.377
assert lt[and_b, 0, 0] == 0.375
assert lt[and_b, 0, 1] == 0.370
def test_nand_xor():
c = bench.parse("""
input(A1,A2)
output(lt_1237_U91,lt_1237_U92)
lt_1237_U91 = NAND2X0_RVT(A1,A2)
lt_1237_U92 = XOR2X1_RVT(A1,A2)
""")
df = sdf.parse("""
(DELAYFILE
(CELL
(CELLTYPE "NAND2X0_RVT")
(INSTANCE lt_1237_U91)
(DELAY
(ABSOLUTE
(IOPATH A1 Y (0.018:0.022:0.021) (0.017:0.019:0.019))
(IOPATH A2 Y (0.021:0.024:0.024) (0.018:0.021:0.021))
)
)
)
(CELL
(CELLTYPE "XOR2X1_RVT")
(INSTANCE lt_1237_U92)
(DELAY
(ABSOLUTE
(IOPATH (posedge A1) Y (0.035:0.038:0.038) (0.037:0.062:0.062))
(IOPATH (negedge A1) Y (0.035:0.061:0.061) (0.036:0.040:0.040))
(IOPATH (posedge A2) Y (0.042:0.043:0.043) (0.051:0.064:0.064))
(IOPATH (negedge A2) Y (0.041:0.066:0.066) (0.051:0.053:0.053))
)
)
)
)
""")
d = df.iopaths(c, tlib=SAED32)[1]
c.resolve_tlib_cells(SAED32)
sim = WaveSim(c, delays=d, sims=16)
# input A1
sim.s[0,0] = [0,1,0,1] * 4 # initial values 0101010101010101
sim.s[1,0] = 0.0 # transition time
sim.s[2,0] = [0,0,1,1] * 4 # final values 0011001100110011
# input A2
sim.s[0,1] = ([0]*4 + [1]*4)*2 # initial values 0000111100001111
sim.s[1,1] = 0.0 # transition time
sim.s[2,1] = [0]*8 + [1]*8 # final values 0000000011111111
# A1: 0FR10FR10FR10FR1
# A2: 0000FFFFRRRR1111
# nand: 11111RNR1NFF1RF0
# xor: 0FR1FPPRRNPF1RF0
sim.s_to_c()
sim.c_prop()
sim.c_to_s()
eat = sim.s[4,2:]
lst = sim.s[5,2:]
# NAND-gate output
assert np.allclose(eat[0], [
TMAX, TMAX, TMAX, TMAX, TMAX,
0.022, # FF -> rising Y: min(0.022, 0.024)
TMAX, # RF: pulse filtered
0.024, # falling A2 -> rising Y
TMAX,
TMAX, # FR: pulse filtered
0.021, # RR -> falling Y: max(0.019, 0.021)
0.021, # rising A2 -> falling Y
TMAX,
0.022, # falling A1 -> rising Y
0.019, # rising A1 -> falling Y
TMAX
])
assert np.allclose(lst[0], [
TMIN, TMIN, TMIN, TMIN, TMIN,
0.022, # FF -> rising Y: min(0.022, 0.024)
TMIN, # RF: pulse filtered
0.024, # falling A2 -> rising Y
TMIN,
TMIN, # FR: pulse filtered
0.021, # RR -> falling Y: max(0.019, 0.021)
0.021, # rising A2 -> falling Y
TMIN,
0.022, # falling A1 -> rising Y
0.019, # rising A1 -> falling Y
TMIN
])
#XOR-gate output
assert np.allclose(eat[1], [
TMAX,
0.040, # A1:F -> Y:F
0.038, # A1:R -> Y:R
TMAX,
0.053, # A2:F -> Y:F
TMAX, # P filtered
TMAX, # P filtered
0.066, # A2:F -> Y:R
0.043, # A2:R -> Y:R
TMAX, # N filtered
TMAX, # P filtered
0.064, # A2:R -> Y:F
TMAX,
0.061, # A1:F -> Y:R
0.062, # A1:R -> Y:F
TMAX,
])
assert np.allclose(lst[1], [
TMIN,
0.040, # A1:F -> Y:F
0.038, # A1:R -> Y:R
TMIN,
0.053, # A2:F -> Y:F
TMIN, # P filtered
TMIN, # P filtered
0.066, # A2:F -> Y:R
0.043, # A2:R -> Y:R
TMIN, # N filtered
TMIN, # P filtered
0.064, # A2:R -> Y:F
TMIN,
0.061, # A1:F -> Y:R
0.062, # A1:R -> Y:F
TMIN,
])