Browse Source

fix simprim cells, add saed90

devel
Stefan Holst 1 year ago
parent
commit
d97555e9e9
  1. 140
      src/kyupy/logic_sim.py
  2. 13
      src/kyupy/sim.py
  3. 195
      src/kyupy/techlib.py
  4. 67
      tests/test_logic_sim.py

140
src/kyupy/logic_sim.py

@ -69,6 +69,8 @@ class LogicSim(sim.SimOps):
""" """
if sims is None: sims = self.sims if sims is None: sims = self.sims
nbytes = (sims - 1) // 8 + 1 nbytes = (sims - 1) // 8 + 1
t0 = self.c_locs[self.tmp_idx]
t1 = self.c_locs[self.tmp2_idx]
if self.m == 2: if self.m == 2:
if inject_cb is None: if inject_cb is None:
_prop_cpu(self.ops, self.c_locs, self.c[...,:nbytes]) _prop_cpu(self.ops, self.c_locs, self.c[...,:nbytes])
@ -103,6 +105,10 @@ class LogicSim(sim.SimOps):
elif op == sim.AOI22: self.c[o0] = ~((self.c[i0] & self.c[i1]) | (self.c[i2] & self.c[i3])) elif op == sim.AOI22: self.c[o0] = ~((self.c[i0] & self.c[i1]) | (self.c[i2] & self.c[i3]))
elif op == sim.OA22: self.c[o0] = (self.c[i0] | self.c[i1]) & (self.c[i2] | self.c[i3]) elif op == sim.OA22: self.c[o0] = (self.c[i0] | self.c[i1]) & (self.c[i2] | self.c[i3])
elif op == sim.OAI22: self.c[o0] = ~((self.c[i0] | self.c[i1]) & (self.c[i2] | self.c[i3])) elif op == sim.OAI22: self.c[o0] = ~((self.c[i0] | self.c[i1]) & (self.c[i2] | self.c[i3]))
elif op == sim.AO211: self.c[o0] = (self.c[i0] & self.c[i1]) | self.c[i2] | self.c[i3]
elif op == sim.AOI211:self.c[o0] = ~((self.c[i0] & self.c[i1]) | self.c[i2] | self.c[i3])
elif op == sim.OA211: self.c[o0] = (self.c[i0] | self.c[i1]) & self.c[i2] & self.c[i3]
elif op == sim.OAI211:self.c[o0] = ~((self.c[i0] | self.c[i1]) & self.c[i2] & self.c[i3])
elif op == sim.MUX21: self.c[o0] = (self.c[i0] & ~self.c[i2]) | (self.c[i1] & self.c[i2]) elif op == sim.MUX21: self.c[o0] = (self.c[i0] & ~self.c[i2]) | (self.c[i1] & self.c[i2])
else: print(f'unknown op {op}') else: print(f'unknown op {op}')
inject_cb(o0, self.s[o0]) inject_cb(o0, self.s[o0])
@ -130,42 +136,56 @@ class LogicSim(sim.SimOps):
elif op == sim.XNOR3: logic.bp4v_xor(self.c[o0], self.c[i0], self.c[i1], self.c[i2]); logic.bp4v_not(self.c[o0], self.c[o0]) elif op == sim.XNOR3: logic.bp4v_xor(self.c[o0], self.c[i0], self.c[i1], self.c[i2]); logic.bp4v_not(self.c[o0], self.c[o0])
elif op == sim.XNOR4: logic.bp4v_xor(self.c[o0], self.c[i0], self.c[i1], self.c[i2], self.c[i3]); logic.bp4v_not(self.c[o0], self.c[o0]) elif op == sim.XNOR4: logic.bp4v_xor(self.c[o0], self.c[i0], self.c[i1], self.c[i2], self.c[i3]); logic.bp4v_not(self.c[o0], self.c[o0])
elif op == sim.AO21: elif op == sim.AO21:
logic.bp4v_and(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp4v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_or(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[i2]) logic.bp4v_or(self.c[o0], self.c[t0], self.c[i2])
elif op == sim.AOI21: elif op == sim.AOI21:
logic.bp4v_and(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp4v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_or(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[i2]) logic.bp4v_or(self.c[o0], self.c[t0], self.c[i2])
logic.bp4v_not(self.c[o0], self.c[o0]) logic.bp4v_not(self.c[o0], self.c[o0])
elif op == sim.OA21: elif op == sim.OA21:
logic.bp4v_or(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp4v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_and(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[i2]) logic.bp4v_and(self.c[o0], self.c[t0], self.c[i2])
elif op == sim.OAI21: elif op == sim.OAI21:
logic.bp4v_or(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp4v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_and(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[i2]) logic.bp4v_and(self.c[o0], self.c[t0], self.c[i2])
logic.bp4v_not(self.c[o0], self.c[o0]) logic.bp4v_not(self.c[o0], self.c[o0])
elif op == sim.AO22: elif op == sim.AO22:
logic.bp4v_and(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp4v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_and(self.c[self.c_locs[self.tmp2_idx]], self.c[i2], self.c[i3]) logic.bp4v_and(self.c[t1], self.c[i2], self.c[i3])
logic.bp4v_or(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[self.c_locs[self.tmp2_idx]]) logic.bp4v_or(self.c[o0], self.c[t0], self.c[t1])
elif op == sim.AOI22: elif op == sim.AOI22:
logic.bp4v_and(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp4v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_and(self.c[self.c_locs[self.tmp2_idx]], self.c[i2], self.c[i3]) logic.bp4v_and(self.c[t1], self.c[i2], self.c[i3])
logic.bp4v_or(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[self.c_locs[self.tmp2_idx]]) logic.bp4v_or(self.c[o0], self.c[t0], self.c[t1])
logic.bp4v_not(self.c[o0], self.c[o0]) logic.bp4v_not(self.c[o0], self.c[o0])
elif op == sim.OA22: elif op == sim.OA22:
logic.bp4v_or(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp4v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_or(self.c[self.c_locs[self.tmp2_idx]], self.c[i2], self.c[i3]) logic.bp4v_or(self.c[t1], self.c[i2], self.c[i3])
logic.bp4v_and(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[self.c_locs[self.tmp2_idx]]) logic.bp4v_and(self.c[o0], self.c[t0], self.c[t1])
elif op == sim.OAI22: elif op == sim.OAI22:
logic.bp4v_or(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp4v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_or(self.c[self.c_locs[self.tmp2_idx]], self.c[i2], self.c[i3]) logic.bp4v_or(self.c[t1], self.c[i2], self.c[i3])
logic.bp4v_and(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[self.c_locs[self.tmp2_idx]]) logic.bp4v_and(self.c[o0], self.c[t0], self.c[t1])
logic.bp4v_not(self.c[o0], self.c[o0])
elif op == sim.AO211:
logic.bp4v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_or(self.c[o0], self.c[t0], self.c[i2], self.c[i3])
elif op == sim.AOI211:
logic.bp4v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_or(self.c[o0], self.c[t0], self.c[i2], self.c[i3])
logic.bp4v_not(self.c[o0], self.c[o0])
elif op == sim.OA211:
logic.bp4v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_and(self.c[o0], self.c[t0], self.c[i2], self.c[i3])
elif op == sim.OAI211:
logic.bp4v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp4v_and(self.c[o0], self.c[t0], self.c[i2], self.c[i3])
logic.bp4v_not(self.c[o0], self.c[o0]) logic.bp4v_not(self.c[o0], self.c[o0])
elif op == sim.MUX21: elif op == sim.MUX21:
logic.bp4v_not(self.c[self.c_locs[self.tmp2_idx]], self.c[i2]) logic.bp4v_not(self.c[t1], self.c[i2])
logic.bp4v_and(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[self.c_locs[self.tmp2_idx]]) logic.bp4v_and(self.c[t0], self.c[i0], self.c[t1])
logic.bp4v_and(self.c[self.c_locs[self.tmp2_idx]], self.c[i1], self.c[i2]) logic.bp4v_and(self.c[t1], self.c[i1], self.c[i2])
logic.bp4v_or(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[self.c_locs[self.tmp2_idx]]) logic.bp4v_or(self.c[o0], self.c[t0], self.c[t1])
else: print(f'unknown op {op}') else: print(f'unknown op {op}')
else: else:
for op, o0, i0, i1, i2, i3 in self.ops[:,:6]: for op, o0, i0, i1, i2, i3 in self.ops[:,:6]:
@ -191,42 +211,56 @@ class LogicSim(sim.SimOps):
elif op == sim.XNOR3: logic.bp8v_xor(self.c[o0], self.c[i0], self.c[i1], self.c[i2]); logic.bp8v_not(self.c[o0], self.c[o0]) elif op == sim.XNOR3: logic.bp8v_xor(self.c[o0], self.c[i0], self.c[i1], self.c[i2]); logic.bp8v_not(self.c[o0], self.c[o0])
elif op == sim.XNOR4: logic.bp8v_xor(self.c[o0], self.c[i0], self.c[i1], self.c[i2], self.c[i3]); logic.bp8v_not(self.c[o0], self.c[o0]) elif op == sim.XNOR4: logic.bp8v_xor(self.c[o0], self.c[i0], self.c[i1], self.c[i2], self.c[i3]); logic.bp8v_not(self.c[o0], self.c[o0])
elif op == sim.AO21: elif op == sim.AO21:
logic.bp8v_and(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp8v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_or(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[i2]) logic.bp8v_or(self.c[o0], self.c[t0], self.c[i2])
elif op == sim.AOI21: elif op == sim.AOI21:
logic.bp8v_and(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp8v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_or(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[i2]) logic.bp8v_or(self.c[o0], self.c[t0], self.c[i2])
logic.bp8v_not(self.c[o0], self.c[o0]) logic.bp8v_not(self.c[o0], self.c[o0])
elif op == sim.OA21: elif op == sim.OA21:
logic.bp8v_or(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp8v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_and(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[i2]) logic.bp8v_and(self.c[o0], self.c[t0], self.c[i2])
elif op == sim.OAI21: elif op == sim.OAI21:
logic.bp8v_or(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp8v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_and(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[i2]) logic.bp8v_and(self.c[o0], self.c[t0], self.c[i2])
logic.bp8v_not(self.c[o0], self.c[o0]) logic.bp8v_not(self.c[o0], self.c[o0])
elif op == sim.AO22: elif op == sim.AO22:
logic.bp8v_and(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp8v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_and(self.c[self.c_locs[self.tmp2_idx]], self.c[i2], self.c[i3]) logic.bp8v_and(self.c[t1], self.c[i2], self.c[i3])
logic.bp8v_or(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[self.c_locs[self.tmp2_idx]]) logic.bp8v_or(self.c[o0], self.c[t0], self.c[t1])
elif op == sim.AOI22: elif op == sim.AOI22:
logic.bp8v_and(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp8v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_and(self.c[self.c_locs[self.tmp2_idx]], self.c[i2], self.c[i3]) logic.bp8v_and(self.c[t1], self.c[i2], self.c[i3])
logic.bp8v_or(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[self.c_locs[self.tmp2_idx]]) logic.bp8v_or(self.c[o0], self.c[t0], self.c[t1])
logic.bp8v_not(self.c[o0], self.c[o0]) logic.bp8v_not(self.c[o0], self.c[o0])
elif op == sim.OA22: elif op == sim.OA22:
logic.bp8v_or(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp8v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_or(self.c[self.c_locs[self.tmp2_idx]], self.c[i2], self.c[i3]) logic.bp8v_or(self.c[t1], self.c[i2], self.c[i3])
logic.bp8v_and(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[self.c_locs[self.tmp2_idx]]) logic.bp8v_and(self.c[o0], self.c[t0], self.c[t1])
elif op == sim.OAI22: elif op == sim.OAI22:
logic.bp8v_or(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[i1]) logic.bp8v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_or(self.c[self.c_locs[self.tmp2_idx]], self.c[i2], self.c[i3]) logic.bp8v_or(self.c[t1], self.c[i2], self.c[i3])
logic.bp8v_and(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[self.c_locs[self.tmp2_idx]]) logic.bp8v_and(self.c[o0], self.c[t0], self.c[t1])
logic.bp8v_not(self.c[o0], self.c[o0])
elif op == sim.AO211:
logic.bp8v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_or(self.c[o0], self.c[t0], self.c[i2], self.c[i3])
elif op == sim.AOI211:
logic.bp8v_and(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_or(self.c[o0], self.c[t0], self.c[i2], self.c[i3])
logic.bp8v_not(self.c[o0], self.c[o0])
elif op == sim.OA211:
logic.bp8v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_and(self.c[o0], self.c[t0], self.c[i2], self.c[i3])
elif op == sim.OAI211:
logic.bp8v_or(self.c[t0], self.c[i0], self.c[i1])
logic.bp8v_and(self.c[o0], self.c[t0], self.c[i2], self.c[i3])
logic.bp8v_not(self.c[o0], self.c[o0]) logic.bp8v_not(self.c[o0], self.c[o0])
elif op == sim.MUX21: elif op == sim.MUX21:
logic.bp8v_not(self.c[self.c_locs[self.tmp2_idx]], self.c[i2]) logic.bp8v_not(self.c[t1], self.c[i2])
logic.bp8v_and(self.c[self.c_locs[self.tmp_idx]], self.c[i0], self.c[self.c_locs[self.tmp2_idx]]) logic.bp8v_and(self.c[t0], self.c[i0], self.c[t1])
logic.bp8v_and(self.c[self.c_locs[self.tmp2_idx]], self.c[i1], self.c[i2]) logic.bp8v_and(self.c[t1], self.c[i1], self.c[i2])
logic.bp8v_or(self.c[o0], self.c[self.c_locs[self.tmp_idx]], self.c[self.c_locs[self.tmp2_idx]]) logic.bp8v_or(self.c[o0], self.c[t0], self.c[t1])
else: print(f'unknown op {op}') else: print(f'unknown op {op}')
if inject_cb is not None: inject_cb(o0, self.s[o0]) if inject_cb is not None: inject_cb(o0, self.s[o0])
@ -286,12 +320,16 @@ def _prop_cpu(ops, c_locs, c):
elif op == sim.XNOR3: c[o0] = ~(c[i0] ^ c[i1] ^ c[i2]) elif op == sim.XNOR3: c[o0] = ~(c[i0] ^ c[i1] ^ c[i2])
elif op == sim.XNOR4: c[o0] = ~(c[i0] ^ c[i1] ^ c[i2] ^ c[i3]) elif op == sim.XNOR4: c[o0] = ~(c[i0] ^ c[i1] ^ c[i2] ^ c[i3])
elif op == sim.AO21: c[o0] = (c[i0] & c[i1]) | c[i2] elif op == sim.AO21: c[o0] = (c[i0] & c[i1]) | c[i2]
elif op == sim.AOI21: c[o0] = ~((c[i0] & c[i1]) | c[i2])
elif op == sim.OA21: c[o0] = (c[i0] | c[i1]) & c[i2] elif op == sim.OA21: c[o0] = (c[i0] | c[i1]) & c[i2]
elif op == sim.OAI21: c[o0] = ~((c[i0] | c[i1]) & c[i2])
elif op == sim.AO22: c[o0] = (c[i0] & c[i1]) | (c[i2] & c[i3]) elif op == sim.AO22: c[o0] = (c[i0] & c[i1]) | (c[i2] & c[i3])
elif op == sim.AOI22: c[o0] = ~((c[i0] & c[i1]) | (c[i2] & c[i3]))
elif op == sim.OA22: c[o0] = (c[i0] | c[i1]) & (c[i2] | c[i3]) elif op == sim.OA22: c[o0] = (c[i0] | c[i1]) & (c[i2] | c[i3])
elif op == sim.AOI21: c[o0] = ~((c[i0] & c[i1]) | c[i2])
elif op == sim.OAI21: c[o0] = ~((c[i0] | c[i1]) & c[i2])
elif op == sim.AOI22: c[o0] = ~((c[i0] & c[i1]) | (c[i2] & c[i3]))
elif op == sim.OAI22: c[o0] = ~((c[i0] | c[i1]) & (c[i2] | c[i3])) elif op == sim.OAI22: c[o0] = ~((c[i0] | c[i1]) & (c[i2] | c[i3]))
elif op == sim.AO211: c[o0] = (c[i0] & c[i1]) | c[i2] | c[i3]
elif op == sim.OA211: c[o0] = (c[i0] | c[i1]) & c[i2] & c[i3]
elif op == sim.AOI211: c[o0] = ~((c[i0] & c[i1]) | c[i2] | c[i3])
elif op == sim.OAI211: c[o0] = ~((c[i0] | c[i1]) & c[i2] & c[i3])
elif op == sim.MUX21: c[o0] = (c[i0] & ~c[i2]) | (c[i1] & c[i2]) elif op == sim.MUX21: c[o0] = (c[i0] & ~c[i2]) | (c[i1] & c[i2])
else: print(f'unknown op {op}') else: print(f'unknown op {op}')

13
src/kyupy/sim.py

@ -25,15 +25,15 @@ XOR4 = np.uint16(0b0110_1001_1001_0110)
XNOR2, XNOR3, XNOR4 = ~XOR2, ~XOR3, ~XOR4 XNOR2, XNOR3, XNOR4 = ~XOR2, ~XOR3, ~XOR4
AO21 = np.uint16(0b1110_1010_1110_1010) # i0 | (i1 & i2) AO21 = np.uint16(0b1111_1000_1111_1000) # (i0 & i1) | i2
AO22 = np.uint16(0b1111_1000_1000_1000) # (i0 & i1) | (i2 & i3) AO22 = np.uint16(0b1111_1000_1000_1000) # (i0 & i1) | (i2 & i3)
OA21 = np.uint16(0b1010_1000_1010_1000) # i0 & (i1 | i2) OA21 = np.uint16(0b1110_0000_1110_0000) # (i0 | i1) & i2
OA22 = np.uint16(0b1110_1110_1110_0000) # (i0 | i1) & (i2 | i3) OA22 = np.uint16(0b1110_1110_1110_0000) # (i0 | i1) & (i2 | i3)
AOI21, AOI22, OAI21, OAI22 = ~AO21, ~AO22, ~OA21, ~OA22 AOI21, AOI22, OAI21, OAI22 = ~AO21, ~AO22, ~OA21, ~OA22
AO211 = np.uint16(0b1111_1110_1110_1110) # i0 | i1 | (i2 & i3) AO211 = np.uint16(0b1111_1111_1111_1000) # (i0 & i1) | i2 | i3
OA211 = np.uint16(0b1000_1000_1000_0000) # i0 & i1 & (i2 | i3) OA211 = np.uint16(0b1110_0000_0000_0000) # (i0 | i1) & i2 & i3
AOI211, OAI211 = ~AO211, ~OA211 AOI211, OAI211 = ~AO211, ~OA211
@ -62,6 +62,11 @@ kind_prefixes = {
'__const0__': (BUF1, BUF1, BUF1), '__const0__': (BUF1, BUF1, BUF1),
'tiel': (BUF1, BUF1, BUF1), 'tiel': (BUF1, BUF1, BUF1),
'ao211': (AO211, AO211, AO211),
'oa211': (OA211, OA211, OA211),
'aoi211': (AOI211, AOI211, AOI211),
'oai211': (OAI211, OAI211, OAI211),
'ao22': (AO22, AO22, AO22), 'ao22': (AO22, AO22, AO22),
'aoi22': (AOI22, AOI22, AOI22), 'aoi22': (AOI22, AOI22, AOI22),
'ao21': (AO21, AO21, AO21), 'ao21': (AO21, AO21, AO21),

195
src/kyupy/techlib.py

@ -1,3 +1,6 @@
import re
from itertools import product
from .circuit import Node, Line from .circuit import Node, Line
from . import bench from . import bench
@ -94,3 +97,195 @@ class TechLib:
for k, v in tmap.items(): for k, v in tmap.items():
if n.kind.startswith(k): if n.kind.startswith(k):
circuit.substitute(n, v) circuit.substitute(n, v)
class TechLibNew:
def __init__(self, lib_src):
self.cells = dict()
for c_str in re.split(r';\s+', lib_src):
c_str = re.sub(r'^\s+', '', c_str)
name_len = c_str.find(' ')
if name_len <= 0: continue
c = bench.parse(c_str[name_len:])
c.name = c_str[:name_len]
c.eliminate_1to1_forks()
i_idx, o_idx = 0, 0
pin_dict = dict()
for n in c.io_nodes:
if len(n.ins) == 0:
pin_dict[n.name] = (i_idx, False)
i_idx += 1
else:
pin_dict[n.name] = (o_idx, True)
o_idx += 1
parts = [s[1:-1].split(',') if s[0] == '{' else [s] for s in re.split(r'({[^}]+})', c.name) if len(s) > 0]
for name in [''.join(item) for item in product(*parts)]:
self.cells[name] = (c, pin_dict)
def pin_index(self, kind, pin):
return self.cells[kind][1][pin][0]
def pin_is_output(self, kind, pin):
return self.cells[kind][1][pin][1]
def resolve(self, circuit):
for n in list(circuit.nodes):
if n.kind in self.cells:
circuit.substitute(n, self.cells[n.kind][0])
nangate = TechLibNew(r"""
FILLCELL_X{1,2,4,8,16,32} ;
LOGIC0_X1 output(Z) Z=__const0__() ;
LOGIC1_X1 output(Z) Z=__const1__() ;
BUF_X{1,2,4,8,16,32} input(A) output(Z) Z=BUF1(A) ;
CLKBUF_X{1,2,3} input(A) output(Z) Z=BUF1(A) ;
INV_X{1,2,4,8,16,32} input(A) output(ZN) ZN=INV1(A) ;
AND2_X{1,2,4} input(A1,A2) output(ZN) ZN=AND2(A1,A2) ;
AND3_X{1,2,4} input(A1,A2,A3) output(ZN) ZN=AND3(A1,A2,A3) ;
AND4_X{1,2,4} input(A1,A2,A3,A4) output(ZN) ZN=AND4(A1,A2,A3,A4) ;
NAND2_X{1,2,4} input(A1,A2) output(ZN) ZN=NAND2(A1,A2) ;
NAND3_X{1,2,4} input(A1,A2,A3) output(ZN) ZN=NAND3(A1,A2,A3) ;
NAND4_X{1,2,4} input(A1,A2,A3,A4) output(ZN) ZN=NAND4(A1,A2,A3,A4) ;
OR2_X{1,2,4} input(A1,A2) output(ZN) ZN=OR2(A1,A2) ;
OR3_X{1,2,4} input(A1,A2,A3) output(ZN) ZN=OR3(A1,A2,A3) ;
OR4_X{1,2,4} input(A1,A2,A3,A4) output(ZN) ZN=OR4(A1,A2,A3,A4) ;
NOR2_X{1,2,4} input(A1,A2) output(ZN) ZN=NOR2(A1,A2) ;
NOR3_X{1,2,4} input(A1,A2,A3) output(ZN) ZN=NOR3(A1,A2,A3) ;
NOR4_X{1,2,4} input(A1,A2,A3,A4) output(ZN) ZN=NOR4(A1,A2,A3,A4) ;
XOR2_X{1,2} input(A,B) output(Z) Z=XOR2(A,B) ;
XNOR2_X{1,2} input(A,B) output(ZN) ZN=XNOR2(A,B) ;
AOI21_X{1,2,4} input(A,B1,B2) output(ZN) ZN=AOI21(B1,B2,A) ;
OAI21_X{1,2,4} input(A,B1,B2) output(ZN) ZN=OAI21(B1,B2,A) ;
AOI22_X{1,2,4} input(A1,A2,B1,B2) output(ZN) ZN=AOI22(A1,A2,B1,B2) ;
OAI22_X{1,2,4} input(A1,A2,B1,B2) output(ZN) ZN=OAI22(A1,A2,B1,B2) ;
OAI211_X{1,2,4} input(A,B,C1,C2) output(ZN) ZN=OAI211(C1,C2,A,B) ;
AOI211_X{1,2,4} input(A,B,C1,C2) output(ZN) ZN=AOI211(C1,C2,A,B) ;
MUX2_X{1,2} input(A,B,S) output(Z) Z=MUX21(A,B,S) ;
AOI221_X{1,2,4} input(A,B1,B2,C1,C2) output(ZN) BC=AO22(B1,B2,C1,C2) ZN=NOR2(BC,A) ;
OAI221_X{1,2,4} input(A,B1,B2,C1,C2) output(ZN) BC=OA22(B1,B2,C1,C2) ZN=NAND2(BC,A) ;
AOI222_X{1,2,4} input(A1,A2,B1,B2,C1,C2) output(ZN) BC=AO22(B1,B2,C1,C2) ZN=AOI21(A1,A2,BC) ;
OAI222_X{1,2,4} input(A1,A2,B1,B2,C1,C2) output(ZN) BC=OA22(B1,B2,C1,C2) ZN=OAI21(A1,A2,BC) ;
OAI33_X1 input(A1,A2,A3,B1,B2,B3) output(ZN) AA=OR2(A1,A2) BB=OR2(B1,B2) ZN=OAI22(AA,A3,BB,B3) ;
HA_X1 input(A,B) output(CO,S) CO=XOR2(A,B) S=AND2(A,B) ;
FA_X1 input(A,B,CI) output(CO,S) AB=XOR2(A,B) CO=XOR2(AB,CI) S=AO22(CI,A,B) ;
CLKGATE_X{1,2,4,8} input(CK,E) output(GCK) GCK=AND2(CK,E) ;
CLKGATETST_X{1,2,4,8} input(CK,E,SE) output(GCK) GCK=OA21(CK,E,SE) ;
DFF_X{1,2} input(D,CK) output(Q,QN) Q=DFF(D,CK) QN=INV1(Q) ;
DFFR_X{1,2} input(D,RN,CK) output(Q,QN) DR=AND2(D,RN) Q=DFF(DR,CK) QN=INV1(Q) ;
DFFS_X{1,2} input(D,SN,CK) output(Q,QN) S=INV1(SN) DS=OR2(D,S) Q=DFF(DS,CK) QN=INV1(Q) ;
DFFRS_X{1,2} input(D,RN,SN,CK) output(Q,QN) S=INV1(SN) DS=OR2(D,S) DRS=AND2(DS,RN) Q=DFF(DRS,CK) QN=INV1(Q) ;
SDFF_X{1,2} input(D,SE,SI,CK) output(Q,QN) DI=MUX21(D,SI,SE) Q=DFF(DI,CK) QN=INV1(Q) ;
SDFFR_X{1,2} input(D,RN,SE,SI,CK) output(Q,QN) DR=AND2(D,RN) DI=MUX21(DR,SI,SE) Q=DFF(DI,CK) QN=INV1(Q) ;
SDFFS_X{1,2} input(D,SE,SI,SN,CK) output(Q,QN) S=INV1(SN) DS=OR2(D,S) DI=MUX21(DS,SI,SE) Q=DFF(DI,CK) QN=INV1(Q) ;
SDFFRS_X{1,2} input(D,RN,SE,SI,SN,CK) output(Q,QN) S=INV1(SN) DS=OR2(D,S) DRS=AND2(DS,RN) DI=MUX21(DRS,SI,SE) Q=DFF(DI,CK) QN=INV1(Q) ;
TBUF_X{1,2,4,8,16} input(A,EN) output(Z) Z=BUF1(A) ;
TINV_X1 input(I,EN) output(ZN) ZN=INV1(I) ;
TLAT_X1 input(D,G,OE) output(Q) Q=LATCH(D,G) ;
DLH_X{1,2} input(D,G) output(Q) Q=LATCH(D,G) ;
DLL_X{1,2} input(D,GN) output(Q) G=INV1(GN) Q=LATCH(D,G) ;
""")
# SAED90nm library. unsupported: negative-edge flip-flops, tri-state, latches, clock gating, level shifters
saed90 = TechLibNew(r"""
NBUFFX{2,4,8,16,32}$ input(INP) output(Z) Z=BUF1(INP) ;
AOBUFX{1,2,4}$ input(INP) output(Z) Z=BUF1(INP) ;
DELLN{1,2,3}X2$ input(INP) output(Z)Z=BUF1(INP) ;
INVX{0,1,2,4,8,16,32}$ input(INP) output(ZN) ZN=INV1(INP) ;
AOINVX{1,2,4}$ input(INP) output(ZN) ZN=INV1(INP) ;
IBUFFX{2,4,8,16,32}$ input(INP) output(ZN) ZN=INV1(INP) ;
TIEH$ output(Z) Z=__const1__() ;
TIEL$ output(ZN) ZN=__const0__() ;
HEAD2X{2,4,8,16,32}$ input(SLEEP) output(SLEEPOUT) SLEEPOUT=BUF1(SLEEP) ;
HEADX{2,4,8,16,32}$ input(SLEEP) ;
ANTENNA$ input(INP) ;
CLOAD1$ input(INP) ;
DCAP$ ;
DHFILL{HLH,LHL}2 ;
DHFILLHLHLS11$ ;
SHFILL{1,2,3,64,128}$ ;
AND2X{1,2,4}$ input(IN1,IN2) output(Q) Q=AND2(IN1,IN2) ;
AND3X{1,2,4}$ input(IN1,IN2,IN3) output(Q) Q=AND3(IN1,IN2,IN3) ;
AND4X{1,2,4}$ input(IN1,IN2,IN3,IN4) output(Q) Q=AND4(IN1,IN2,IN3,IN4) ;
OR2X{1,2,4}$ input(IN1,IN2) output(Q) Q=OR2(IN1,IN2) ;
OR3X{1,2,4}$ input(IN1,IN2,IN3) output(Q) Q=OR3(IN1,IN2,IN3) ;
OR4X{1,2,4}$ input(IN1,IN2,IN3,IN4) output(Q) Q=OR4(IN1,IN2,IN3,IN4) ;
XOR2X{1,2}$ input(IN1,IN2) output(Q) Q=XOR2(IN1,IN2) ;
XOR3X{1,2}$ input(IN1,IN2,IN3) output(Q) Q=XOR3(IN1,IN2,IN3) ;
NAND2X{0,1,2,4}$ input(IN1,IN2) output(QN) QN=NAND2(IN1,IN2) ;
NAND3X{0,1,2,4}$ input(IN1,IN2,IN3) output(QN) QN=NAND3(IN1,IN2,IN3) ;
NAND4X{0,1}$ input(IN1,IN2,IN3,IN4) output(QN) QN=NAND4(IN1,IN2,IN3,IN4) ;
NOR2X{0,1,2,4}$ input(IN1,IN2) output(QN) QN=NOR2(IN1,IN2) ;
NOR3X{0,1,2,4}$ input(IN1,IN2,IN3) output(QN) QN=NOR3(IN1,IN2,IN3) ;
NOR4X{0,1}$ input(IN1,IN2,IN3,IN4) output(QN) QN=NOR4(IN1,IN2,IN3,IN4) ;
XNOR2X{1,2}$ input(IN1,IN2) output(Q) Q=XNOR2(IN1,IN2) ;
XNOR3X{1,2}$ input(IN1,IN2,IN3) output(Q) Q=XNOR3(IN1,IN2,IN3) ;
ISOLAND{,AO}X{1,2,4,8}$ input(ISO,D) output(Q) ISOB=NOT1(ISO) Q=AND2(ISOB,D) ;
ISOLOR{,AO}X{1,2,4,8}$ input(ISO,D) output(Q) Q=OR2(ISO,D) ;
AO21X{1,2}$ input(IN1,IN2,IN3) output(Q) Q=AO21(IN1,IN2,IN3) ;
OA21X{1,2}$ input(IN1,IN2,IN3) output(Q) Q=OA21(IN1,IN2,IN3) ;
AOI21X{1,2}$ input(IN1,IN2,IN3) output(QN) QN=AOI21(IN1,IN2,IN3) ;
OAI21X{1,2}$ input(IN1,IN2,IN3) output(QN) QN=OAI21(IN1,IN2,IN3) ;
AO22X{1,2}$ input(IN1,IN2,IN3,IN4) output(Q) Q=AO22(IN1,IN2,IN3,IN4) ;
OA22X{1,2}$ input(IN1,IN2,IN3,IN4) output(Q) Q=OA22(IN1,IN2,IN3,IN4) ;
AOI22X{1,2}$ input(IN1,IN2,IN3,IN4) output(QN) QN=AOI22(IN1,IN2,IN3,IN4) ;
OAI22X{1,2}$ input(IN1,IN2,IN3,IN4) output(QN) QN=OAI22(IN1,IN2,IN3,IN4) ;
MUX21X{1,2}$ input(IN1,IN2,S) output(Q) Q=MUX21(IN1,IN2,S) ;
AO221X{1,2}$ input(IN1,IN2,IN3,IN4,IN5) output(Q) A=AO22(IN1,IN2,IN3,IN4) Q=OR2(IN5,A) ;
OA221X{1,2}$ input(IN1,IN2,IN3,IN4,IN5) output(Q) A=OA22(IN1,IN2,IN3,IN4) Q=AND2(IN5,A) ;
AOI221X{1,2}$ input(IN1,IN2,IN3,IN4,IN5) output(QN) A=AO22(IN1,IN2,IN3,IN4) QN=NOR2(IN5,A) ;
OAI221X{1,2}$ input(IN1,IN2,IN3,IN4,IN5) output(QN) A=OA22(IN1,IN2,IN3,IN4) QN=NAND2(IN5,A) ;
AO222X{1,2}$ input(IN1,IN2,IN3,IN4,IN5,IN6) output(Q) A=AO22(IN1,IN2,IN3,IN4) Q=AO21(IN5,IN6,A) ;
OA222X{1,2}$ input(IN1,IN2,IN3,IN4,IN5,IN6) output(Q) A=OA22(IN1,IN2,IN3,IN4) Q=OA21(IN5,IN6,A) ;
AOI222X{1,2}$ input(IN1,IN2,IN3,IN4,IN5,IN6) output(QN) A=AO22(IN1,IN2,IN3,IN4) QN=AOI21(IN5,IN6,A) ;
OAI222X{1,2}$ input(IN1,IN2,IN3,IN4,IN5,IN6) output(QN) A=OA22(IN1,IN2,IN3,IN4) QN=OAI21(IN5,IN6,A) ;
MUX41X{1,2}$ input(IN1,IN2,IN3,IN4,S0,S1) output(Q) A=MUX21(IN1,IN2,S0) B=MUX21(IN3,IN4,S0) Q=MUX21(A,B,S1) ;
DEC24X{1,2}$ input(IN1,IN2) output(Q0,Q1,Q2,Q3) IN1B=INV1(IN1) IN2B=INV1(IN2) Q0=NOR2(IN1,IN2) Q1=AND(IN1,IN2B) Q2=AND(IN1B,IN2) Q3=AND(IN1,IN2) ;
FADDX{1,2}$ input(A,B,CI) output(S,CO) AB=XOR2(A,B) CO=XOR(AB,CI) S=AO22(AB,CI,A,B) ;
HADDX{1,2}$ input(A0,B0) output(SO,C1) C1=XOR2(A0,B0) SO=AND2(A0,B0) ;
{,AO}DFFARX{1,2}$ input(D,CLK,RSTB) output(Q,QN) DR=AND2(D,RSTB) Q=DFF(DR,CLK) QN=INV1(Q) ;
DFFASRX{1,2}$ input(D,CLK,RSTB,SETB) output(Q,QN) DR=AND2(D,RSTB) SET=INV1(SETB) DRS=OR2(DR,SET) Q=DFF(DRS,CLK) QN=INV1(Q) ;
DFFASX{1,2}$ input(D,CLK,SETB) output(Q,QN) SET=INV1(SETB) DS=OR2(D,SET) Q=DFF(DS,CLK) QN=INV1(Q) ;
DFFSSRX{1,2}$ input(CLK,D,RSTB,SETB) output(Q,QN) DR=AND2(D,RSTB) SET=INV1(SETB) DRS=OR2(DR,SET) Q=DFF(DRS,CLK) QN=INV1(Q) ;
DFFX{1,2}$ input(D,CLK) output(Q,QN) Q=DFF(D,CLK) QN=INV1(Q) ;
SDFFARX{1,2}$ input(D,CLK,RSTB,SE,SI) output(Q,QN) DR=AND2(D,RSTB) DI=MUX21(DR,SI,SE) Q=DFF(DI,CLK) QN=INV1(Q) ;
SDFFASRSX{1,2}$ input(D,CLK,RSTB,SETB,SE,SI) output(Q,QN,S0) DR=AND2(D,RSTB) SET=INV1(SETB) DRS=OR2(DR,SET) DI=MUX21(DRS,SI,SE) Q=DFF(DI,CLK) QN=INV1(Q) S0=BUF1(Q) ;
SDFFASRX{1,2}$ input(D,CLK,RSTB,SETB,SE,SI) output(Q,QN) DR=AND2(D,RSTB) SET=INV1(SETB) DRS=OR2(DR,SET) DI=MUX21(DRS,SI,SE) Q=DFF(DI,CLK) QN=INV1(Q) ;
SDFFASX{1,2}$ input(D,CLK,SETB,SE,SI) output(Q,QN) SET=INV1(SETB) DS=OR2(D,SET) DI=MUX21(DS,SI,SE) Q=DFF(DI,CLK) QN=INV1(Q) ;
SDFFSSRX{1,2}$ input(CLK,D,RSTB,SETB,SI,SE) output(Q,QN) DR=AND2(D,RSTB) SET=INV1(SETB) DRS=OR2(DR,SET) DI=MUX21(DRS,SI,SE) Q=DFF(DI,CLK) QN=INV1(Q) ;
SDFFX{1,2}$ input(D,CLK,SE,SI) output(Q,QN) DI=MUX21(D,SI,SE) Q=DFF(DI,CLK) QN=INV1(Q) ;
""".replace('$','{,_LVT,_HVT}'))

67
tests/test_logic_sim.py

@ -1,9 +1,8 @@
import numpy as np import numpy as np
from kyupy.logic_sim import LogicSim from kyupy.logic_sim import LogicSim
from kyupy import bench from kyupy import bench, logic, sim
from kyupy.logic import mvarray, bparray, bp_to_mv, mv_to_bp from kyupy.logic import mvarray, bparray, bp_to_mv, mv_to_bp
from kyupy import logic
def assert_equal_shape_and_contents(actual, desired): def assert_equal_shape_and_contents(actual, desired):
desired = np.array(desired, dtype=np.uint8) desired = np.array(desired, dtype=np.uint8)
@ -11,17 +10,67 @@ def assert_equal_shape_and_contents(actual, desired):
np.testing.assert_allclose(actual, desired) np.testing.assert_allclose(actual, desired)
def test_2v(): def test_2v():
c = bench.parse('input(x, y) output(a, o, n) a=and(x,y) o=or(x,y) n=not(x)') c = bench.parse(f'''
s = LogicSim(c, 8, m=8) # FIXME: do m=2 input(i3, i2, i1, i0)
assert s.s_len == 5 output({",".join([f"o{i:02d}" for i in range(33)])})
bpa = bparray('00---', '01---', '10---', '11---') o00=BUF1(i0)
o01=INV1(i0)
o02=AND2(i0,i1)
o03=AND3(i0,i1,i2)
o04=AND4(i0,i1,i2,i3)
o05=NAND2(i0,i1)
o06=NAND3(i0,i1,i2)
o07=NAND4(i0,i1,i2,i3)
o08=OR2(i0,i1)
o09=OR3(i0,i1,i2)
o10=OR4(i0,i1,i2,i3)
o11=NOR2(i0,i1)
o12=NOR3(i0,i1,i2)
o13=NOR4(i0,i1,i2,i3)
o14=XOR2(i0,i1)
o15=XOR3(i0,i1,i2)
o16=XOR4(i0,i1,i2,i3)
o17=XNOR2(i0,i1)
o18=XNOR3(i0,i1,i2)
o19=XNOR4(i0,i1,i2,i3)
o20=AO21(i0,i1,i2)
o21=OA21(i0,i1,i2)
o22=AO22(i0,i1,i2,i3)
o23=OA22(i0,i1,i2,i3)
o24=AOI21(i0,i1,i2)
o25=OAI21(i0,i1,i2)
o26=AOI22(i0,i1,i2,i3)
o27=OAI22(i0,i1,i2,i3)
o28=AO211(i0,i1,i2,i3)
o29=OA211(i0,i1,i2,i3)
o30=AOI211(i0,i1,i2,i3)
o31=OAI211(i0,i1,i2,i3)
o32=MUX21(i0,i1,i2)
''')
s = LogicSim(c, 16, m=2)
bpa = logic.bparray([f'{i:04b}'+('-'*(s.s_len-4)) for i in range(16)])
s.s[0] = bpa s.s[0] = bpa
s.s_to_c() s.s_to_c()
s.c_prop() s.c_prop()
s.c_to_s() s.c_to_s()
mva = bp_to_mv(s.s[1]) mva = logic.bp_to_mv(s.s[1])
for res, exp in zip(logic.packbits(mva[4:], dtype=np.uint32), [
assert_equal_shape_and_contents(mva[...,:4], mvarray('--001', '--011', '--010', '--110')) sim.BUF1, sim.INV1,
sim.AND2, sim.AND3, sim.AND4,
sim.NAND2, sim.NAND3, sim.NAND4,
sim.OR2, sim.OR3, sim.OR4,
sim.NOR2, sim.NOR3, sim.NOR4,
sim.XOR2, sim.XOR3, sim.XOR4,
sim.XNOR2, sim.XNOR3, sim.XNOR4,
sim.AO21, sim.OA21,
sim.AO22, sim.OA22,
sim.AOI21, sim.OAI21,
sim.AOI22, sim.OAI22,
sim.AO211, sim.OA211,
sim.AOI211, sim.OAI211,
sim.MUX21
]):
assert res == exp, f'Mismatch for SimPrim {sim.names[exp]} res={bin(res)} exp={bin(exp)}'
def test_4v(): def test_4v():

Loading…
Cancel
Save