Compare commits
2
Commits
7a69ce9016
...
ed9b5c6cd6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed9b5c6cd6 | ||
|
|
e19463d249 |
No files matched your search
@@ -51,6 +51,7 @@ class LogicSim(sim.SimOps):
|
|||||||
nbytes = cdiv(sims, 8)
|
nbytes = cdiv(sims, 8)
|
||||||
|
|
||||||
self.c = np.zeros((self.c_len, self.mdim, nbytes), dtype=np.uint8)
|
self.c = np.zeros((self.c_len, self.mdim, nbytes), dtype=np.uint8)
|
||||||
|
self.c_dirty = np.full(self.c_len, 1, dtype=np.uint8)
|
||||||
self.s = np.zeros((2, self.s_len, 3, nbytes), dtype=np.uint8)
|
self.s = np.zeros((2, self.s_len, 3, nbytes), dtype=np.uint8)
|
||||||
"""Logic values of the sequential elements (flip-flops) and ports.
|
"""Logic values of the sequential elements (flip-flops) and ports.
|
||||||
|
|
||||||
@@ -97,7 +98,7 @@ class LogicSim(sim.SimOps):
|
|||||||
t1 = self.c_locs[self.tmp2_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:
|
||||||
c_prop_2v_cpu(self.ops, self.c_locs, self.c, int(fault_line), fault_mask, int(fault_model))
|
c_prop_2v_cpu(self.ops, self.c_locs, self.c, self.c_dirty, int(fault_line), fault_mask, int(fault_model))
|
||||||
else:
|
else:
|
||||||
for op, o0l, i0l, i1l, i2l, i3l in self.ops[:,:6]:
|
for op, o0l, i0l, i1l, i2l, i3l in self.ops[:,:6]:
|
||||||
o0, i0, i1, i2, i3 = [self.c_locs[x] for x in (o0l, i0l, i1l, i2l, i3l)]
|
o0, i0, i1, i2, i3 = [self.c_locs[x] for x in (o0l, i0l, i1l, i2l, i3l)]
|
||||||
|
|||||||
+22
-4
@@ -189,10 +189,10 @@ class SimOps:
|
|||||||
levels = []
|
levels = []
|
||||||
|
|
||||||
ppio2idx = dict((n, i) for i, n in enumerate(circuit.s_nodes(KYUPY)))
|
ppio2idx = dict((n, i) for i, n in enumerate(circuit.s_nodes(KYUPY)))
|
||||||
root_nodes = set([n for n in circuit.s_nodes(KYUPY) if len(n.ins) > 0] + [n for n in circuit.nodes if len(n.outs) == 0]) # start from POs, PPOs, and any dangling nodes
|
root_nodes = set([n for n in circuit.nodes if len(n.outs) == 0 or KYUPY.is_dff(n.kind)]) # start from POs (that are unused by circuit itself), PPOs, and any dangling nodes
|
||||||
readers = np.array([1 if l.reader in root_nodes else len(l.reader.outs) for l in circuit.lines], dtype=np.int32) # for ref-counting forks
|
readers = np.array([1 if l.reader in root_nodes else len(l.reader.outs) for l in circuit.lines], dtype=np.int32) # for ref-counting forks
|
||||||
|
|
||||||
level_lines = [n.ins[0] for n in root_nodes if len(n.ins) > 0 ]
|
level_lines = [n.ins[0] for n in sorted(root_nodes, key=lambda n: n.index) if len(n.ins) > 0 ]
|
||||||
# FIXME: Should probably instanciate buffers for PPOs and attach DFF clocks
|
# FIXME: Should probably instanciate buffers for PPOs and attach DFF clocks
|
||||||
|
|
||||||
while len(level_lines) > 0: # traverse the circuit level-wise back towards (P)PIs
|
while len(level_lines) > 0: # traverse the circuit level-wise back towards (P)PIs
|
||||||
@@ -201,10 +201,14 @@ class SimOps:
|
|||||||
|
|
||||||
for l in level_lines:
|
for l in level_lines:
|
||||||
n = l.driver
|
n = l.driver
|
||||||
assert len(n.ins) <= 4, f'Too many input pins for node {n}. Map circuit to KYUPY techlib first using resolce_tlib_cells().'
|
assert len(n.ins) <= 4, f'Too many input pins for node {n}. Map circuit to KYUPY techlib first using resolve_tlib_cells().'
|
||||||
in_idxs = [n.ins[x].index if len(n.ins) > x and n.ins[x] is not None else self.zero_idx for x in [0,1,2,3]]
|
in_idxs = [n.ins[x].index if len(n.ins) > x and n.ins[x] is not None else self.zero_idx for x in [0,1,2,3]]
|
||||||
if n in ppio2idx:
|
if n in ppio2idx:
|
||||||
in_idxs[0] = self.ppi_offset + ppio2idx[n]
|
if 'dff' in n.kind.lower() or in_idxs[0] == self.zero_idx:
|
||||||
|
in_idxs[0] = self.ppi_offset + ppio2idx[n]
|
||||||
|
else: # this is a PO that is also used within the circuit. Treat as normal fork with ref counting. TODO: check strip_forks=True case for this.
|
||||||
|
readers[n.ins[0]] -= 1
|
||||||
|
if readers[n.ins[0]] == 0: prev_level_lines.append(n.ins[0])
|
||||||
if l.driver_pin == 1 and 'dff' in n.kind.lower(): # second output of DFF is inverted
|
if l.driver_pin == 1 and 'dff' in n.kind.lower(): # second output of DFF is inverted
|
||||||
level_ops.append((INV1, l.index, *in_idxs, *a_ctrl[l]))
|
level_ops.append((INV1, l.index, *in_idxs, *a_ctrl[l]))
|
||||||
else:
|
else:
|
||||||
@@ -312,6 +316,11 @@ class SimOps:
|
|||||||
if len(n.ins) > 0:
|
if len(n.ins) > 0:
|
||||||
self.c_locs[self.ppo_offset + i], self.c_caps[self.ppo_offset + i] = self.c_locs[n.ins[0]], self.c_caps[n.ins[0]]
|
self.c_locs[self.ppo_offset + i], self.c_caps[self.ppo_offset + i] = self.c_locs[n.ins[0]], self.c_caps[n.ins[0]]
|
||||||
|
|
||||||
|
# sanity check
|
||||||
|
for oidx, io in zip(*np.nonzero(self.c_locs[self.ops[:, 1:6]] < 0)):
|
||||||
|
log.error(f'unallocated {["o0","i0","i1","i2","i3"][io]} in op {self.ops[oidx]}')
|
||||||
|
assert np.min(self.c_locs[self.ops[:, 1:6]]) >= 0, "Unallocated signal lines."
|
||||||
|
|
||||||
# line use information
|
# line use information
|
||||||
self.line_use_start = np.full(self.c_locs_len, -1, dtype=np.int32)
|
self.line_use_start = np.full(self.c_locs_len, -1, dtype=np.int32)
|
||||||
self.line_use_stop = np.full(self.c_locs_len, len(self.levels), dtype=np.int32)
|
self.line_use_stop = np.full(self.c_locs_len, len(self.levels), dtype=np.int32)
|
||||||
@@ -346,3 +355,12 @@ class SimOps:
|
|||||||
|
|
||||||
self.pippi_c_locs = np.concatenate([self.pi_c_locs, self.ppi_c_locs])
|
self.pippi_c_locs = np.concatenate([self.pi_c_locs, self.ppi_c_locs])
|
||||||
self.poppo_c_locs = np.concatenate([self.po_c_locs, self.ppo_c_locs])
|
self.poppo_c_locs = np.concatenate([self.po_c_locs, self.ppo_c_locs])
|
||||||
|
|
||||||
|
def cone_ops(self, origin_lines: set[int]):
|
||||||
|
active_lines = {l for l in origin_lines}
|
||||||
|
ops = []
|
||||||
|
for kind, out0, in0, in1, in2, in3, *params in self.ops:
|
||||||
|
if in0 in active_lines or in1 in active_lines or in2 in active_lines or in3 in active_lines or out0 in origin_lines:
|
||||||
|
ops.append((kind, out0, in0, in1, in2, in3, *params))
|
||||||
|
active_lines.add(out0)
|
||||||
|
return np.asarray(ops, dtype=np.int32)
|
||||||
@@ -20,6 +20,18 @@ def test_dangling():
|
|||||||
sim.simulate(p)
|
sim.simulate(p)
|
||||||
assert p[1,0] == logic.ONE
|
assert p[1,0] == logic.ONE
|
||||||
|
|
||||||
|
def test_used_output():
|
||||||
|
c = bench.parse('input(i0) output(o0) output(o1) o0=BUF1(i0) o1=BUF(o0)')
|
||||||
|
sim = LogicSim2V(c)
|
||||||
|
expect = mvarray('000', '111')
|
||||||
|
actual = sim.simulate(expect.copy())
|
||||||
|
np.testing.assert_array_equal(
|
||||||
|
expect[c.io_locs('o0')],
|
||||||
|
actual[c.io_locs('o0')])
|
||||||
|
np.testing.assert_array_equal(
|
||||||
|
expect[c.io_locs('o1')],
|
||||||
|
actual[c.io_locs('o1')])
|
||||||
|
|
||||||
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)
|
||||||
assert actual.shape == desired.shape
|
assert actual.shape == desired.shape
|
||||||
|
|||||||
Reference in new issue
Block a user