def get(self, signal):
return self.curr[signal]
- def set_curr(self, signal, value):
- assert isinstance(value, int)
- if self.curr[signal] != value:
- self.curr_dirty.add(signal)
- self.curr[signal] = value
-
- def set_next(self, signal, value):
+ def set(self, signal, value):
assert isinstance(value, int)
if self.next[signal] != value:
self.next_dirty.add(signal)
new_value = self.curr[signal]
return old_value, new_value
- def iter_dirty(self):
- dirty, self.dirty = self.dirty, ValueSet()
- for signal in dirty:
- yield signal, self.curr[signal], self.next[signal]
-
normalize = Const.normalize
return lambda state: normalize(~arg(state), shape)
if value.op == "-":
return lambda state: normalize(-arg(state), shape)
+ if value.op == "b":
+ return lambda state: normalize(bool(arg(state)), shape)
elif len(value.operands) == 2:
lhs, rhs = map(self, value.operands)
if value.op == "+":
return lambda state: normalize(lhs(state) ^ rhs(state), shape)
if value.op == "==":
return lambda state: normalize(lhs(state) == rhs(state), shape)
+ if value.op == "!=":
+ return lambda state: normalize(lhs(state) != rhs(state), shape)
+ if value.op == "<":
+ return lambda state: normalize(lhs(state) < rhs(state), shape)
+ if value.op == "<=":
+ return lambda state: normalize(lhs(state) <= rhs(state), shape)
+ if value.op == ">":
+ return lambda state: normalize(lhs(state) > rhs(state), shape)
+ if value.op == ">=":
+ return lambda state: normalize(lhs(state) >= rhs(state), shape)
elif len(value.operands) == 3:
if value.op == "m":
sel, val1, val0 = map(self, value.operands)
return lambda state: val1(state) if sel(state) else val0(state)
- raise NotImplementedError("Operator '{}' not implemented".format(value.op))
+ raise NotImplementedError("Operator '{!r}' not implemented".format(value.op)) # :nocov:
def on_Slice(self, value):
shape = value.shape()
def lhs_compiler(self, value):
# TODO
- return lambda state, arg: state.set_next(value, arg)
+ return lambda state, arg: state.set(value, arg)
def on_Assign(self, stmt):
assert isinstance(stmt.lhs, Signal)
--- /dev/null
+from .tools import *
+from ..fhdl.ast import *
+from ..fhdl.ir import *
+from ..back.pysim import *
+
+
+class SimulatorUnitTestCase(FHDLTestCase):
+ def assertOperator(self, stmt, inputs, output):
+ inputs = [Value.wrap(i) for i in inputs]
+ output = Value.wrap(output)
+
+ isigs = [Signal(i.shape(), name=n) for i, n in zip(inputs, "abcd")]
+ osig = Signal(output.shape(), name="y")
+
+ frag = Fragment()
+ frag.add_statements(osig.eq(stmt(*isigs)))
+ frag.drive(osig)
+
+ with Simulator(frag,
+ vcd_file =open("test.vcd", "w"),
+ gtkw_file=open("test.gtkw", "w"),
+ gtkw_signals=[*isigs, osig]) as sim:
+ def process():
+ for isig, input in zip(isigs, inputs):
+ yield isig.eq(input)
+ yield Delay()
+ self.assertEqual((yield osig), output.value)
+ sim.add_process(process)
+ sim.run()
+
+ def test_invert(self):
+ stmt = lambda a: ~a
+ self.assertOperator(stmt, [C(0b0000, 4)], C(0b1111, 4))
+ self.assertOperator(stmt, [C(0b1010, 4)], C(0b0101, 4))
+ self.assertOperator(stmt, [C(0, 4)], C(-1, 4))
+
+ def test_neg(self):
+ stmt = lambda a: -a
+ self.assertOperator(stmt, [C(0b0000, 4)], C(0b0000, 4))
+ self.assertOperator(stmt, [C(0b0001, 4)], C(0b1111, 4))
+ self.assertOperator(stmt, [C(0b1010, 4)], C(0b0110, 4))
+ self.assertOperator(stmt, [C(1, 4)], C(-1, 4))
+ self.assertOperator(stmt, [C(5, 4)], C(-5, 4))
+
+ def test_bool(self):
+ stmt = lambda a: a.bool()
+ self.assertOperator(stmt, [C(0, 4)], C(0))
+ self.assertOperator(stmt, [C(1, 4)], C(1))
+ self.assertOperator(stmt, [C(2, 4)], C(1))
+
+ def test_add(self):
+ stmt = lambda a, b: a + b
+ self.assertOperator(stmt, [C(0, 4), C(1, 4)], C(1, 4))
+ self.assertOperator(stmt, [C(-5, 4), C(-5, 4)], C(-10, 5))
+
+ def test_sub(self):
+ stmt = lambda a, b: a - b
+ self.assertOperator(stmt, [C(2, 4), C(1, 4)], C(1, 4))
+ self.assertOperator(stmt, [C(0, 4), C(1, 4)], C(-1, 4))
+ self.assertOperator(stmt, [C(0, 4), C(10, 4)], C(-10, 5))
+
+ def test_and(self):
+ stmt = lambda a, b: a & b
+ self.assertOperator(stmt, [C(0b1100, 4), C(0b1010, 4)], C(0b1000, 4))
+
+ def test_or(self):
+ stmt = lambda a, b: a | b
+ self.assertOperator(stmt, [C(0b1100, 4), C(0b1010, 4)], C(0b1110, 4))
+
+ def test_xor(self):
+ stmt = lambda a, b: a ^ b
+ self.assertOperator(stmt, [C(0b1100, 4), C(0b1010, 4)], C(0b0110, 4))
+
+ def test_eq(self):
+ stmt = lambda a, b: a == b
+ self.assertOperator(stmt, [C(0, 4), C(0, 4)], C(1))
+ self.assertOperator(stmt, [C(0, 4), C(1, 4)], C(0))
+ self.assertOperator(stmt, [C(1, 4), C(0, 4)], C(0))
+
+ def test_ne(self):
+ stmt = lambda a, b: a != b
+ self.assertOperator(stmt, [C(0, 4), C(0, 4)], C(0))
+ self.assertOperator(stmt, [C(0, 4), C(1, 4)], C(1))
+ self.assertOperator(stmt, [C(1, 4), C(0, 4)], C(1))
+
+ def test_lt(self):
+ stmt = lambda a, b: a < b
+ self.assertOperator(stmt, [C(0, 4), C(0, 4)], C(0))
+ self.assertOperator(stmt, [C(0, 4), C(1, 4)], C(1))
+ self.assertOperator(stmt, [C(1, 4), C(0, 4)], C(0))
+
+ def test_ge(self):
+ stmt = lambda a, b: a >= b
+ self.assertOperator(stmt, [C(0, 4), C(0, 4)], C(1))
+ self.assertOperator(stmt, [C(0, 4), C(1, 4)], C(0))
+ self.assertOperator(stmt, [C(1, 4), C(0, 4)], C(1))
+
+ def test_gt(self):
+ stmt = lambda a, b: a > b
+ self.assertOperator(stmt, [C(0, 4), C(0, 4)], C(0))
+ self.assertOperator(stmt, [C(0, 4), C(1, 4)], C(0))
+ self.assertOperator(stmt, [C(1, 4), C(0, 4)], C(1))
+
+ def test_le(self):
+ stmt = lambda a, b: a <= b
+ self.assertOperator(stmt, [C(0, 4), C(0, 4)], C(1))
+ self.assertOperator(stmt, [C(0, 4), C(1, 4)], C(1))
+ self.assertOperator(stmt, [C(1, 4), C(0, 4)], C(0))
+
+ def test_mux(self):
+ stmt = lambda a, b, c: Mux(c, a, b)
+ self.assertOperator(stmt, [C(2, 4), C(3, 4), C(0)], C(3, 4))
+ self.assertOperator(stmt, [C(2, 4), C(3, 4), C(1)], C(2, 4))