|
|
@ -10,7 +10,7 @@ import math |
|
|
|
|
|
|
|
|
|
|
|
import numpy as np |
|
|
|
import numpy as np |
|
|
|
|
|
|
|
|
|
|
|
from . import logic, hr_bytes |
|
|
|
from . import numba, logic, hr_bytes, sim |
|
|
|
from .sim import SimOps, SimPrim |
|
|
|
from .sim import SimOps, SimPrim |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -148,7 +148,7 @@ class LogicSim(SimOps): |
|
|
|
|
|
|
|
|
|
|
|
# return responses |
|
|
|
# return responses |
|
|
|
|
|
|
|
|
|
|
|
def c_prop(self, inject_cb=None): |
|
|
|
def c_prop(self, sims=None, inject_cb=None): |
|
|
|
"""Propagate the input values towards the outputs (Perform all logic operations in topological order). |
|
|
|
"""Propagate the input values towards the outputs (Perform all logic operations in topological order). |
|
|
|
|
|
|
|
|
|
|
|
If the circuit is sequential (it contains flip-flops), one call simulates one clock cycle. |
|
|
|
If the circuit is sequential (it contains flip-flops), one call simulates one clock cycle. |
|
|
@ -168,7 +168,12 @@ class LogicSim(SimOps): |
|
|
|
resumes with the manipulated values after the callback returns. |
|
|
|
resumes with the manipulated values after the callback returns. |
|
|
|
:type inject_cb: ``f(Line, ndarray)`` |
|
|
|
:type inject_cb: ``f(Line, ndarray)`` |
|
|
|
""" |
|
|
|
""" |
|
|
|
|
|
|
|
if sims is None: sims = self.sims |
|
|
|
|
|
|
|
nbytes = (sims - 1) // 8 + 1 |
|
|
|
if self.m == 2: |
|
|
|
if self.m == 2: |
|
|
|
|
|
|
|
if inject_cb is None: |
|
|
|
|
|
|
|
_prop_cpu(self.ops, self.vat, self.c[...,:nbytes]) |
|
|
|
|
|
|
|
else: |
|
|
|
for op, o0, i0, i1, i2, i3 in self.ops: |
|
|
|
for op, o0, i0, i1, i2, i3 in self.ops: |
|
|
|
o0, i0, i1, i2, i3 = [self.vat[x,0] for x in (o0, i0, i1, i2, i3)] |
|
|
|
o0, i0, i1, i2, i3 = [self.vat[x,0] for x in (o0, i0, i1, i2, i3)] |
|
|
|
if op == SimPrim.BUF1: self.c[o0]=self.c[i0] |
|
|
|
if op == SimPrim.BUF1: self.c[o0]=self.c[i0] |
|
|
@ -180,8 +185,7 @@ class LogicSim(SimOps): |
|
|
|
elif op == SimPrim.XOR2: self.c[o0] = self.c[i0] ^ self.c[i1] |
|
|
|
elif op == SimPrim.XOR2: self.c[o0] = self.c[i0] ^ self.c[i1] |
|
|
|
elif op == SimPrim.XNOR2: self.c[o0] = ~(self.c[i0] ^ self.c[i1]) |
|
|
|
elif op == SimPrim.XNOR2: self.c[o0] = ~(self.c[i0] ^ self.c[i1]) |
|
|
|
else: print(f'unknown SimPrim {op}') |
|
|
|
else: print(f'unknown SimPrim {op}') |
|
|
|
if inject_cb is not None: inject_cb(o0, self.s[o0]) |
|
|
|
inject_cb(o0, self.s[o0]) |
|
|
|
pass |
|
|
|
|
|
|
|
elif self.m == 4: |
|
|
|
elif self.m == 4: |
|
|
|
pass |
|
|
|
pass |
|
|
|
else: |
|
|
|
else: |
|
|
@ -286,3 +290,17 @@ class LogicSim(SimOps): |
|
|
|
# logic.bp_and(self.tmp[0], inputs[0], inputs[1]) |
|
|
|
# logic.bp_and(self.tmp[0], inputs[0], inputs[1]) |
|
|
|
# logic.bp_or(outputs[0], self.tmp[0], inputs[2]) |
|
|
|
# logic.bp_or(outputs[0], self.tmp[0], inputs[2]) |
|
|
|
# logic.bp_not(outputs[0], outputs[0]) |
|
|
|
# logic.bp_not(outputs[0], outputs[0]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@numba.njit() |
|
|
|
|
|
|
|
def _prop_cpu(ops, vat, c): |
|
|
|
|
|
|
|
for op, o0, i0, i1, i2, i3 in ops: |
|
|
|
|
|
|
|
o0, i0, i1, i2, i3 = [vat[x,0] for x in (o0, i0, i1, i2, i3)] |
|
|
|
|
|
|
|
if op == sim.BUF1: c[o0]=c[i0] |
|
|
|
|
|
|
|
elif op == sim.INV1: c[o0] = ~c[i0] |
|
|
|
|
|
|
|
elif op == sim.AND2: c[o0] = c[i0] & c[i1] |
|
|
|
|
|
|
|
elif op == sim.NAND2: c[o0] = ~(c[i0] & c[i1]) |
|
|
|
|
|
|
|
elif op == sim.OR2: c[o0] = c[i0] | c[i1] |
|
|
|
|
|
|
|
elif op == sim.NOR2: c[o0] = ~(c[i0] | c[i1]) |
|
|
|
|
|
|
|
elif op == sim.XOR2: c[o0] = c[i0] ^ c[i1] |
|
|
|
|
|
|
|
elif op == sim.XNOR2: c[o0] = ~(c[i0] ^ c[i1]) |
|
|
|
|
|
|
|
else: print(f'unknown SimPrim {op}') |
|
|
|