a fast 6v sim
This commit is contained in:
1 parent
fc030c6708
commit
f6baf9cb5e
2 files changed
+124
-1
No files matched your search
@@ -13,6 +13,7 @@ import numpy as np
|
|||||||
from . import numba, logic, hr_bytes, sim, eng, cdiv
|
from . import numba, logic, hr_bytes, sim, eng, cdiv
|
||||||
from .circuit import Circuit
|
from .circuit import Circuit
|
||||||
|
|
||||||
|
|
||||||
class LogicSim(sim.SimOps):
|
class LogicSim(sim.SimOps):
|
||||||
"""A bit-parallel naïve combinational simulator for 2-, 4-, or 8-valued logic.
|
"""A bit-parallel naïve combinational simulator for 2-, 4-, or 8-valued logic.
|
||||||
|
|
||||||
@@ -334,3 +335,101 @@ def _prop_cpu(ops, c_locs, c):
|
|||||||
elif op == sim.OAI211: 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}')
|
||||||
|
|
||||||
|
|
||||||
|
class LogicSim6V(sim.SimOps):
|
||||||
|
"""A bit-parallel naïve combinational simulator for 6-valued logic.
|
||||||
|
|
||||||
|
:param circuit: The circuit to simulate.
|
||||||
|
:param sims: The number of parallel logic simulations to perform.
|
||||||
|
:param c_reuse: If True, intermediate signal values may get overwritten when not needed anymore to save memory.
|
||||||
|
:param strip_forks: If True, forks are not included in the simulation model to save memory and simulation time.
|
||||||
|
"""
|
||||||
|
def __init__(self, circuit: Circuit, sims: int = 8, c_reuse: bool = False, strip_forks: bool = False):
|
||||||
|
super().__init__(circuit, c_reuse=c_reuse, strip_forks=strip_forks)
|
||||||
|
self.sims = sims
|
||||||
|
nbytes = cdiv(sims, 8)
|
||||||
|
|
||||||
|
self.c = np.zeros((self.c_len, 3, nbytes), dtype=np.uint8)
|
||||||
|
self.s = np.zeros((2, self.s_len, self.sims), dtype=np.uint8)
|
||||||
|
"""Logic values of the sequential elements (flip-flops) and ports.
|
||||||
|
|
||||||
|
It is a pair of arrays in mv storage format:
|
||||||
|
|
||||||
|
* ``s[0]`` Assigned values. Simulator will read (P)PI value from here.
|
||||||
|
* ``s[1]`` Result values. Simulator will write (P)PO values here.
|
||||||
|
|
||||||
|
Access this array to assign new values to the (P)PIs or read values from the (P)POs.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'{{name: "{self.circuit.name}", sims: {self.sims}, c_bytes: {eng(self.c.nbytes)}}}'
|
||||||
|
|
||||||
|
def s_to_c(self):
|
||||||
|
"""Assigns the values from ``s[0]`` to the inputs of the combinational portion.
|
||||||
|
"""
|
||||||
|
self.c[self.pippi_c_locs] = logic.mv_to_bp(self.s[0, self.pippi_s_locs])
|
||||||
|
|
||||||
|
def c_prop(self):
|
||||||
|
c_prop_cpu(self.ops, self.c, self.c_locs)
|
||||||
|
|
||||||
|
def c_to_s(self):
|
||||||
|
"""Captures the results of the combinational portion into ``s[1]``.
|
||||||
|
"""
|
||||||
|
self.s[1, self.poppo_s_locs] = logic.bp_to_mv(self.c[self.poppo_c_locs])[:,:self.sims]
|
||||||
|
|
||||||
|
|
||||||
|
@numba.njit
|
||||||
|
def c_prop_cpu(ops, c, c_locs):
|
||||||
|
inv_op = np.array([255, 255, 0], dtype=np.uint8)[np.newaxis, :, np.newaxis]
|
||||||
|
for op, o0l, i0l, i1l, i2l, i3l in ops[:,:6]:
|
||||||
|
o0, i0, i1, i2, i3 = [c[c_locs[x]] for x in (o0l, i0l, i1l, i2l, i3l)]
|
||||||
|
if op == sim.BUF1 or op == sim.INV1:
|
||||||
|
o0[...] = i0
|
||||||
|
elif op == sim.AND2 or op == sim.NAND2:
|
||||||
|
o0[0] = i0[0] & i1[0]
|
||||||
|
o0[1] = i0[1] & i1[1]
|
||||||
|
o0[2] = (i0[2]&(i1[0]|i1[1]|i1[2])|
|
||||||
|
i1[2]&(i0[0]|i0[1]|i0[2]))
|
||||||
|
elif op == sim.AND3 or op == sim.NAND3:
|
||||||
|
o0[0] = i0[0] & i1[0] & i2[0]
|
||||||
|
o0[1] = i0[1] & i1[1] & i2[1]
|
||||||
|
o0[2] = (i0[2]&(i1[0]|i1[1]|i1[2])&(i2[0]|i2[1]|i2[2])|
|
||||||
|
i1[2]&(i0[0]|i0[1]|i0[2])&(i2[0]|i2[1]|i2[2])|
|
||||||
|
i2[2]&(i0[0]|i0[1]|i0[2])&(i1[0]|i1[1]|i1[2]))
|
||||||
|
elif op == sim.AND4 or op == sim.NAND4:
|
||||||
|
o0[0] = i0[0] & i1[0] & i2[0] & i3[0]
|
||||||
|
o0[1] = i0[1] & i1[1] & i2[1] & i3[1]
|
||||||
|
o0[2] = (i0[2]&(i1[0]|i1[1]|i1[2])&(i2[0]|i2[1]|i2[2])&(i3[0]|i3[1]|i3[2])|
|
||||||
|
i1[2]&(i0[0]|i0[1]|i0[2])&(i2[0]|i2[1]|i2[2])&(i3[0]|i3[1]|i3[2])|
|
||||||
|
i2[2]&(i0[0]|i0[1]|i0[2])&(i1[0]|i1[1]|i1[2])&(i3[0]|i3[1]|i3[2])|
|
||||||
|
i3[2]&(i0[0]|i0[1]|i0[2])&(i1[0]|i1[1]|i1[2])&(i2[0]|i2[1]|i2[2]))
|
||||||
|
elif op == sim.OR2 or op == sim.NOR2:
|
||||||
|
o0[0] = i0[0] | i1[0]
|
||||||
|
o0[1] = i0[1] | i1[1]
|
||||||
|
o0[2] = (i0[2]&(~i1[0]|~i1[1]|i1[2])|
|
||||||
|
i1[2]&(~i0[0]|~i0[1]|i0[2]))
|
||||||
|
elif op == sim.OR3 or op == sim.NOR3:
|
||||||
|
o0[0] = i0[0] | i1[0] | i2[0]
|
||||||
|
o0[1] = i0[1] | i1[1] | i2[1]
|
||||||
|
o0[2] = (i0[2]&(~i1[0]|~i1[1]|i1[2])&(~i2[0]|~i2[1]|i2[2])|
|
||||||
|
i1[2]&(~i0[0]|~i0[1]|i0[2])&(~i2[0]|~i2[1]|i2[2])|
|
||||||
|
i2[2]&(~i0[0]|~i0[1]|i0[2])&(~i1[0]|~i1[1]|i1[2]))
|
||||||
|
elif op == sim.OR4 or op == sim.NOR4:
|
||||||
|
o0[0] = i0[0] | i1[0] | i2[0] | i3[0]
|
||||||
|
o0[1] = i0[1] | i1[1] | i2[1] | i3[1]
|
||||||
|
o0[2] = (i0[2]&(~i1[0]|~i1[1]|i1[2])&(~i2[0]|~i2[1]|i2[2])&(~i3[0]|~i3[1]|i3[2])|
|
||||||
|
i1[2]&(~i0[0]|~i0[1]|i0[2])&(~i2[0]|~i2[1]|i2[2])&(~i3[0]|~i3[1]|i3[2])|
|
||||||
|
i2[2]&(~i0[0]|~i0[1]|i0[2])&(~i1[0]|~i1[1]|i1[2])&(~i3[0]|~i3[1]|i3[2])|
|
||||||
|
i3[2]&(~i0[0]|~i0[1]|i0[2])&(~i1[0]|~i1[1]|i1[2])&(~i2[0]|~i2[1]|i2[2]))
|
||||||
|
elif op == sim.XOR2 or op == sim.XNOR2:
|
||||||
|
o0[0] = i0[0] ^ i1[0]
|
||||||
|
o0[1] = i0[1] ^ i1[1]
|
||||||
|
o0[2] = i0[2] | i1[2]
|
||||||
|
else: print(f'unknown op {op}')
|
||||||
|
|
||||||
|
if (op == sim.INV1 or
|
||||||
|
op == sim.NAND2 or op == sim.NAND3 or op == sim.NAND4 or
|
||||||
|
op == sim.NOR2 or op == sim.NOR3 or op == sim.NOR4 or
|
||||||
|
op == sim.XNOR2):
|
||||||
|
o0[...] = o0 ^ inv_op
|
||||||
+25
-1
@@ -1,6 +1,6 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from kyupy.logic_sim import LogicSim
|
from kyupy.logic_sim import LogicSim, LogicSim6V
|
||||||
from kyupy import bench, logic, sim
|
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
|
||||||
|
|
||||||
@@ -94,6 +94,30 @@ def test_4v():
|
|||||||
'--0XX', '--X1X', '--XXX', '--XXX'))
|
'--0XX', '--X1X', '--XXX', '--XXX'))
|
||||||
|
|
||||||
|
|
||||||
|
def test_6v():
|
||||||
|
c = bench.parse('input(x, y) output(a, o, n, xo, no) a=AND2(x,y) o=OR2(x,y) n=INV1(x) xo=XOR2(x,y) no=NOR2(x,y)')
|
||||||
|
s = LogicSim6V(c, 36)
|
||||||
|
assert s.s_len == 7
|
||||||
|
mva = mvarray(
|
||||||
|
'0000101', '0101110', '0R0R1RF', '0F0F1FR', '0P0P1PN', '0N0N1NP',
|
||||||
|
'1001010', '1111000', '1RR10F0', '1FF10R0', '1PP10N0', '1NN10P0',
|
||||||
|
'R00RFRF', 'R1R1FF0', 'RRRRFPF', 'RFPNFNP', 'RPPRFRF', 'RNRNFFP',
|
||||||
|
'F00FRFR', 'F1F1RR0', 'FRPNRNP', 'FFFFRPR', 'FPPFRFR', 'FNFNRRP',
|
||||||
|
'P00PNPN', 'P1P1NN0', 'PRPRNRF', 'PFPFNFR', 'PPPPNPN', 'PNPNNNP',
|
||||||
|
'N00NPNP', 'N1N1PP0', 'NRRNPFP', 'NFFNPRP', 'NPPNPNP', 'NNNNPPP')
|
||||||
|
tests = np.copy(mva)
|
||||||
|
tests[2:] = logic.ZERO
|
||||||
|
s.s[0] = tests
|
||||||
|
s.s_to_c()
|
||||||
|
s.c_prop()
|
||||||
|
s.c_to_s()
|
||||||
|
resp = s.s[1].copy()
|
||||||
|
|
||||||
|
exp_resp = np.copy(mva)
|
||||||
|
exp_resp[:2] = logic.ZERO
|
||||||
|
np.testing.assert_allclose(resp, exp_resp)
|
||||||
|
|
||||||
|
|
||||||
def test_8v():
|
def test_8v():
|
||||||
c = bench.parse('input(x, y) output(a, o, n, xo) a=and(x,y) o=or(x,y) n=not(x) xo=xor(x,y)')
|
c = bench.parse('input(x, y) output(a, o, n, xo) a=and(x,y) o=or(x,y) n=not(x) xo=xor(x,y)')
|
||||||
s = LogicSim(c, 64, m=8)
|
s = LogicSim(c, 64, m=8)
|
||||||
|
|||||||
Reference in new issue
Block a user