def test(): args = ['I', In(Bit), 'O', Out(Bit)] args += ClockInterface(False, False, False) testcircuit = DefineCircuit('TestCircuit', *args) ff = PRIM_FF() wire(testcircuit.I, ff.D) wire(ff.Q, testcircuit.O) EndCircuit() sim = PythonSimulator(testcircuit, testcircuit.CLK) sim.evaluate() val = sim.get_value(testcircuit.O) assert (val == False) sim.advance() val = sim.get_value(testcircuit.O) assert (val == False) sim.set_value(testcircuit.I, True) sim.evaluate() val = sim.get_value(testcircuit.O) assert (val == False) sim.advance() val = sim.get_value(testcircuit.O) assert (val == True) sim.advance() val = sim.get_value(testcircuit.O) assert (val == True)
def test_shift_register(): N = 4 Register4 = DefineRegister(4) T = Bits(N) class ShiftRegister(Circuit): name = "ShiftRegister" IO = ["I", In(T), "O", Out(T), "CLK", In(Clock)] @classmethod def definition(io): regs = [Register4() for _ in range(N)] wireclock(io, regs) wire(io.I, regs[0].I) fold(regs, foldargs={"I": "O"}) wire(regs[-1].O, io.O) simulator = PythonSimulator(ShiftRegister, clock=ShiftRegister.CLK) expected = [0, 0, 0] + list(range(0, 1 << N, 3))[:-3] actual = [] for i in range(0, 1 << N, 3): simulator.set_value(ShiftRegister.I, uint(i, N)) simulator.advance(2) actual.append(seq2int(simulator.get_value(ShiftRegister.O))) assert actual == expected
def check(circuit, sim, number_of_cycles, inputs_generator=None): simulator = PythonSimulator(circuit, clock=circuit.CLK) failed = False for cycle in range(number_of_cycles): if inputs_generator is None: next(sim) else: inputs = [] for name, port in circuit.interface.ports.items(): if name in ["CLK", "CE"]: continue # Skip clocks, TODO: Check the type if port.isoutput(): # circuit input input_value = getattr(inputs_generator, name) inputs.append(input_value) simulator.set_value(getattr(circuit, name), input_value) next(inputs_generator) if len(inputs) > 1: sim.send(inputs) elif len(inputs) == 1: sim.send(inputs[0]) else: next(sim) simulator.advance(2) # Coroutine has an implicit __next__ call on construction so it already # is in it's initial state for name, port in circuit.interface.ports.items(): if port.isinput(): # circuit output if getattr(sim, name) != BitVector( simulator.get_value(getattr(circuit, name))): print( f"Failed on cycle {cycle}, port {name}, expected {getattr(sim, name)}, got {BitVector(simulator.get_value(getattr(circuit, name)))}" ) failed = True assert not failed, "Failed to pass simulation"
def test_shift_register(): N = 4 Register4 = DefineRegister(4) T = m.Bits[ N ] class ShiftRegister(m.Circuit): name = "ShiftRegister" IO = ["I", m.In(T), "O", m.Out(T), "CLK", m.In(m.Clock)] @classmethod def definition(io): regs = [Register4() for _ in range(N)] m.wire(io.I, regs[0].I) m.fold(regs, foldargs={"I": "O"}) m.wire(regs[-1].O, io.O) simulator = PythonSimulator(ShiftRegister, clock=ShiftRegister.CLK) expected = [0, 0, 0] + list(range(0, 1 << N, 3))[:-3] actual = [] for i in range(0, 1 << N, 3): simulator.set_value(ShiftRegister.I, i) simulator.advance(2) actual.append(simulator.get_value(ShiftRegister.O)) assert actual == expected m.compile("build/ShiftRegister", ShiftRegister, output="coreir") assert m.testing.check_files_equal(__file__, "build/ShiftRegister.json", "gold/ShiftRegister.json")
def test_shift_sim(): Shift = DefineLSL(8, 4) lsl_sim = PythonSimulator(Shift) I = BitVector(0x01, 8) O = BitVector(0x10, 8) lsl_sim.set_value(Shift.I, I) lsl_sim.evaluate() assert lsl_sim.get_value(Shift.O) == O
def test_ramb(): main = DefineCircuit("test_ramb", "RDATA", Out(Bits(8)), "WDATA", In(Bits(8)), "WE", In(Bit), "CLK", In(Clock)) ramb = RAMB(512, 8, [0b00000001, 0b11111111] + [0] * 510) wire(ramb.RADDR, uint(1, 9)) wire(ramb.RCLK, main.CLK) wire(ramb.RE, 1) wire(ramb.WADDR, uint(1, 9)) wire(ramb.WCLK, main.CLK) wire(ramb.WE, main.WE) wire(ramb.RDATA, main.RDATA) wire(ramb.WDATA, main.WDATA) EndCircuit() sim = PythonSimulator(main, clock=main.CLK) sim.set_value(main.WE, False) sim.evaluate() sim.advance(2) assert BitVector(sim.get_value(main.RDATA)) == BitVector(0b11111111, num_bits=8) # Write 0xBE to WADDR = 1 sim.set_value(main.WE, True) sim.set_value(main.WDATA, BitVector(0xBE, num_bits=8)) sim.advance(2) # Read RADDR = 1 again sim.set_value(main.WE, False) sim.evaluate() sim.advance(2) assert BitVector(sim.get_value(main.RDATA)) == BitVector(0xBE, num_bits=8)
def test(): args = ['I0', In(Bit), 'I1', In(Bit), 'O', Out(Bit)] + ClockInterface(False, False, False) testcircuit = DefineCircuit('TestCircuit', *args) andy = PRIM_AND() ori = PRIM_OR() ori2 = PRIM_OR() n = PRIM_NOT() wire(testcircuit.I0, andy.I0) wire(testcircuit.I1, andy.I1) wire(testcircuit.I0, ori.I0) wire(testcircuit.I1, n.I) wire(n.O, ori.I1) wire(ori.O, ori2.I0) wire(andy.O, ori2.I1) wire(ori2.O, testcircuit.O) EndCircuit() sim = PythonSimulator(testcircuit) sim.evaluate() v = sim.get_value(testcircuit.O) assert v == True sim.set_value(testcircuit.I1, True) sim.evaluate() v = sim.get_value(testcircuit.O) assert v == False sim.set_value(testcircuit.I0, True) sim.evaluate() v = sim.get_value(testcircuit.O) assert v == True
def test_rom(): main = DefineCircuit("test_romb", "RDATAOUT", Out(Bits(8)), "CLK", In(Clock)) # FIXME: hack romb = ROMB(512, 8, [0b00000001, 0b11111111] + [0] * 510) wire(romb.RADDR, uint(1, 9)) wire(romb.RCLK, main.CLK) wire(romb.RE, 1) wire(romb.RDATA, main.RDATAOUT) EndCircuit() sim = PythonSimulator(main, clock=main.CLK) sim.evaluate() sim.advance(2) assert sim.get_value(main.RDATAOUT) == BitVector(0b11111111, num_bits=8)
def test(): def FFs(n): return [PRIM_FF() for i in range(n)] def Register(n): args = ["I", In(Array[n, Bit]), "O", Out(Array[n, Bit])] + ClockInterface(False, False, False) RegCircuit = DefineCircuit('Register' + str(n), *args) ffs = join(FFs(n)) wire(RegCircuit.I, ffs.D) wire(ffs.Q, RegCircuit.O) EndCircuit() return RegCircuit() def IncOne(n): def sim_inc_one(self, value_store, state_store): I = value_store.get_value(self.I) n = len(I) val = seq2int(I) + 1 cout = val > ((1 << n) - 1) val = val % (1 << n) seq = int2seq(val, len(I)) seq = [bool(s) for s in seq] value_store.set_value(self.O, seq) value_store.set_value(self.COUT, cout) args = [ "I", In(Array[n, Bit]), "O", Out(Array[n, Bit]), "COUT", Out(Bit) ] return DeclareCircuit('IncOne' + str(n), *args, stateful=False, primitive=True, simulate=sim_inc_one)() def TestCounter(n): args = [] args += ["O", Array[n, Out(Bit)]] args += ["COUT", Out(Bit)] args += ClockInterface(False, False, False) Counter = DefineCircuit('Counter' + str(n), *args) inc = IncOne(n) reg = Register(n) wire(reg.O, inc.I) wire(inc.O, reg.I) wire(reg.O, Counter.O) wire(inc.COUT, Counter.COUT) wireclock(Counter, reg) EndCircuit() return Counter() args = ['O', Array[5, Out(Bit)], 'COUT', Out(Bit)] args += ClockInterface(False, False, False) testcircuit = DefineCircuit('Test', *args) counter = TestCounter(5) wire(counter.O, testcircuit.O) wire(counter.COUT, testcircuit.COUT) EndCircuit() sim = PythonSimulator(testcircuit, testcircuit.CLK) for i in range((1 << 5) - 1): sim.advance() val = sim.get_value(testcircuit.O) num = seq2int(val) assert num == i cout = sim.get_value(testcircuit.COUT) assert not cout sim.advance() val = sim.get_value(testcircuit.O) num = seq2int(val) assert num == 31 cout = sim.get_value(testcircuit.COUT) assert cout sim.advance() sim.advance() val = sim.get_value(testcircuit.O) num = seq2int(val) assert num == 0 cout = sim.get_value(testcircuit.COUT) assert not cout
from magma.backend.verilog import compile as compile_verilog print(compile_verilog(SimpleALU)) # In[3]: from magma.simulator import PythonSimulator from magma.bit_vector import BitVector simulator = PythonSimulator(SimpleALU) simulator.set_value(SimpleALU.a, BitVector(3, num_bits=4)) simulator.set_value(SimpleALU.b, BitVector(2, num_bits=4)) simulator.set_value(SimpleALU.opcode, BitVector(0, num_bits=2)) simulator.evaluate() assert simulator.get_value(SimpleALU.out) == BitVector(3 + 2, num_bits=4) simulator.set_value(SimpleALU.a, BitVector(3, num_bits=4)) simulator.set_value(SimpleALU.b, BitVector(2, num_bits=4)) simulator.set_value(SimpleALU.opcode, BitVector(1, num_bits=2)) simulator.evaluate() assert simulator.get_value(SimpleALU.out) == BitVector(3 - 2, num_bits=4) simulator.set_value(SimpleALU.a, BitVector(3, num_bits=4)) simulator.set_value(SimpleALU.b, BitVector(2, num_bits=4)) simulator.set_value(SimpleALU.opcode, BitVector(2, num_bits=2)) simulator.evaluate() assert simulator.get_value(SimpleALU.out) == BitVector(3, num_bits=4) simulator.set_value(SimpleALU.a, BitVector(3, num_bits=4)) simulator.set_value(SimpleALU.b, BitVector(2, num_bits=4))
def clb(a, b, c, d): return (a & b) | (~c & d) T = UInt(16) class Combinational(Circuit): name = "Combinational" IO = ["a", In(T), "b", In(T), "c", Out(T)] @classmethod def definition(io): wire(clb(io.a, io.b, io.a, io.b), io.c) # In[3]: from magma.simulator import PythonSimulator from magma.bit_vector import BitVector simulator = PythonSimulator(Combinational) a = BitVector(148, num_bits=16) b = BitVector(41, num_bits=16) simulator.set_value(Combinational.a, a) simulator.set_value(Combinational.b, b) simulator.evaluate() assert simulator.get_value(Combinational.c) == clb(a, b, a, b) print("Success!")
adder2 = FullAdder() wire(io.a[1], adder2.a) wire(io.b[1], adder2.b) wire(adder1.cout, adder2.cin) adder3 = FullAdder() wire(io.a[2], adder3.a) wire(io.b[2], adder3.b) wire(adder2.cout, adder3.cin) adder4 = FullAdder() wire(io.a[3], adder4.a) wire(io.b[3], adder4.b) wire(adder3.cout, adder4.cin) wire(adder4.cout, io.cout) wire(bits([adder1.out, adder2.out, adder3.out, adder4.out]), io.out) # In[3]: from magma.simulator import PythonSimulator from magma.bit_vector import BitVector simulator = PythonSimulator(Adder4) simulator.set_value(Adder4.a, BitVector(2, num_bits=4)) simulator.set_value(Adder4.b, BitVector(3, num_bits=4)) simulator.set_value(Adder4.cin, True) simulator.evaluate() assert simulator.get_value(Adder4.out) == BitVector(6, num_bits=4) assert simulator.get_value(Adder4.cout) == False print("Success!")
m.wire(io.I, getattr(regs[0], "in")) m.fold(regs, foldargs={"in":"out"}) m.wire(regs[-1].out, io.O) # In[2]: from magma.backend.verilog import compile as compile_verilog print(compile_verilog(ShiftRegister)) # In[3]: from magma.simulator import PythonSimulator from magma.bit_vector import BitVector simulator = PythonSimulator(ShiftRegister, clock=ShiftRegister.CLK) outputs = [] for i in range(0, 1 << N): simulator.set_value(ShiftRegister.I, BitVector(i, N)) for j in range(2): simulator.step() simulator.evaluate() O = simulator.get_value(ShiftRegister.O) outputs.append(BitVector(O)) print([val.as_int() for val in outputs])
class PythonTester(InteractiveTester): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.simulator = PythonSimulator(self._circuit, self.clock) def eval(self): self.simulator.evaluate() def _set_value(self, port, value): port, scope = _process_port(port) self.simulator.set_value(port, value, scope) def _poke(self, port, value, delay=None): if delay is not None: raise NotImplementedError("delay is not support in Python " "simulator") type_ = get_port_type(port) self._set_value(port, value) def process_result(self, type_, result): if issubclass(type_, m.Digital): return Bit(result) if issubclass(type_, m.Bits): return BitVector[len(type_)](result) if is_recursive_type(type_): return BitVector[len(type_)](result) return result def _get_value(self, port): port, scope = _process_port(port) if isinstance(port, (int, BitVector, Bit, list)): return port result = self.simulator.get_value(port, scope) return self.process_result(type(port), result) def _expect(self, port, value, strict=None, caller=None, **kwargs): got = self._get_value(port) port, scope = _process_port(port) value = make_value(type(port), value) expected = self._get_value(value) check(got, port, expected) def peek(self, port): return self._get_value(port) def print(self, format_str, *args): got = [self._get_value(port) for port in args] values = () for value, port in zip(got, args): if (isinstance(port, m.Array) and issubclass(port.T, m.Digital)): value = BitVector[len(port)](value).as_uint() elif isinstance(port, m.Array): raise NotImplementedError("Printing complex nested " "arrays") values += (value, ) print(format_str % values, end="") def assert_(self, expr, msg=""): assert expr, msg def delay(self, time): raise NotImplementedError() def get_value(self, port): raise NotImplementedError() def step(self, steps=1): """ Step the clock `steps` times. """ self.eval() self.simulator.advance(steps) def wait_until_low(self, signal): while self.peek(signal): self.step() def wait_until_high(self, signal): while ~self.peek(signal): self.step() def __call__(self, *args, **kwargs): result = super().__call__(*args, **kwargs) if isinstance(result, tuple): return tuple(self.peek(r.select_path) for r in result) return self.peek(result.select_path)
# coding: utf-8 # In[1]: from magma import * class Combinational(Circuit): name = "Combinational" IO = ["x", In(UInt(16)), "y", In(UInt(16)), "z", Out(UInt(16))] @classmethod def definition(io): wire(io.x + io.y, io.z) # In[2]: from magma.simulator import PythonSimulator from magma.bit_vector import BitVector simulator = PythonSimulator(Combinational) simulator.set_value(Combinational.x, BitVector(76, num_bits=16)) simulator.set_value(Combinational.y, BitVector(43, num_bits=16)) simulator.evaluate() assert simulator.get_value(Combinational.z) == BitVector(76 + 43, num_bits=16) print("Success!")
# In[2]: m.compile("build/SimpleALU", SimpleALU, output="coreir") get_ipython().magic('cat build/SimpleALU.json') # In[3]: from magma.simulator import PythonSimulator from magma.bit_vector import BitVector simulator = PythonSimulator(SimpleALU) simulator.set_value(SimpleALU.a, BitVector(3, num_bits=4)) simulator.set_value(SimpleALU.b, BitVector(2, num_bits=4)) simulator.set_value(SimpleALU.opcode, BitVector(0, num_bits=2)) simulator.evaluate() assert BitVector(simulator.get_value(SimpleALU.out)) == BitVector( 3 + 2, num_bits=4), simulator.get_value(SimpleALU.out) simulator.set_value(SimpleALU.a, BitVector(3, num_bits=4)) simulator.set_value(SimpleALU.b, BitVector(2, num_bits=4)) simulator.set_value(SimpleALU.opcode, BitVector(1, num_bits=2)) simulator.evaluate() assert BitVector(simulator.get_value(SimpleALU.out)) == BitVector(3 - 2, num_bits=4) simulator.set_value(SimpleALU.a, BitVector(3, num_bits=4)) simulator.set_value(SimpleALU.b, BitVector(2, num_bits=4)) simulator.set_value(SimpleALU.opcode, BitVector(2, num_bits=2)) simulator.evaluate() assert BitVector(simulator.get_value(SimpleALU.out)) == BitVector(3, num_bits=4)
class Combinational(m.Circuit): name = "Combinational" IO = ["a", m.In(T), "b", m.In(T), "c", m.Out(T)] @classmethod def definition(io): m.wire(clb(io.a, io.b, io.a, io.b), io.c) # In[3]: from magma.simulator import PythonSimulator from magma.bit_vector import BitVector simulator = PythonSimulator(Combinational) a = BitVector(148, num_bits=16) b = BitVector(41, num_bits=16) simulator.set_value(Combinational.a, a) simulator.set_value(Combinational.b, b) simulator.evaluate() assert BitVector(simulator.get_value(Combinational.c)) == clb(a, b, a, b) print("Success!") # In[4]: m.compile("build/Combinational", Combinational, output="coreir") get_ipython().magic('cat build/Combinational.json')
# In[2]: from magma.backend.verilog import compile as compile_verilog print(compile_verilog(ResetShiftRegister)) # In[3]: from magma.simulator import PythonSimulator from magma.bit_vector import BitVector simulator = PythonSimulator(ResetShiftRegister, clock=ResetShiftRegister.CLK) outputs = [] simulator.set_value(ResetShiftRegister.reset, True) for i in range(0, 1 << N): simulator.set_value(ResetShiftRegister.I, BitVector(i, N)) for j in range(2): if i == 9: if j == 0: simulator.set_value(ResetShiftRegister.reset, False) else: simulator.set_value(ResetShiftRegister.reset, True) simulator.step() simulator.evaluate() O = simulator.get_value(ResetShiftRegister.O) outputs.append(BitVector(O).as_int()) print(outputs)