def test_inspect_mem(self): a = pyrtl.Input(8, 'a') b = pyrtl.Input(8, 'b') mem = pyrtl.MemBlock(8, 8, 'mem') mem[b] <<= a sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=sim_trace) self.assertEqual(sim.inspect_mem(mem), {}) sim.step({a: 3, b: 23}) self.assertEqual(sim.inspect_mem(mem), {23: 3})
def test_combo_1(self): inwire, inwire2 = pyrtl.Input(bitwidth=1), pyrtl.Input(bitwidth=1) tempwire, tempwire2 = pyrtl.WireVector(), pyrtl.WireVector() inwire3 = pyrtl.Input(bitwidth=1) outwire = pyrtl.Output() tempwire <<= inwire | inwire2 tempwire2 <<= ~tempwire outwire <<= tempwire2 & inwire3 self.everything_t_procedure(252.3, 252.3)
def setUp(self): pyrtl.reset_working_block() self.bitwidth = 3 self.addrwidth = 5 self.output1 = pyrtl.Output(self.bitwidth, "output1") self.output2 = pyrtl.Output(self.bitwidth, "output2") self.mem_read_address1 = pyrtl.Input(self.addrwidth, name='mem_read_address1') self.mem_read_address2 = pyrtl.Input(self.addrwidth, name='mem_read_address2') self.mem_write_address = pyrtl.Input(self.addrwidth, name='mem_write_address') self.mem_write_data = pyrtl.Input(self.bitwidth, name='mem_write_data')
def test_timing_basic_2(self): inwire, inwire2 = pyrtl.Input(bitwidth=1), pyrtl.Input(bitwidth=1) inwire3 = pyrtl.Input(bitwidth=1) tempwire, tempwire2 = pyrtl.WireVector(), pyrtl.WireVector() outwire = pyrtl.Output() tempwire <<= inwire | inwire2 tempwire2 <<= ~tempwire outwire <<= tempwire2 & inwire3 self.everything_t_procedure(3, 3)
def test_romblock_does_not_throw_error(self): a = pyrtl.Input(bitwidth=3, name='a') b = pyrtl.Input(bitwidth=3, name='b') o = pyrtl.Output(bitwidth=3, name='o') sum, co = generate_full_adder(a, b) rdat = {0: 1, 1: 2, 2: 5, 5: 0} mixtable = pyrtl.RomBlock(addrwidth=3, bitwidth=3, romdata=rdat) o <<= mixtable[sum] with io.StringIO() as testbuffer: pyrtl.output_to_verilog(testbuffer)
def test_single_mul(self): ina, inb = pyrtl.Input(bitwidth=4, name='a'), pyrtl.Input(bitwidth=4, name='b') self.output <<= ina * inb pyrtl.synthesize() sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) for a in range(16): for b in range(16): sim.step({'a': a, 'b': b}) result = sim_trace.trace['r'] self.assertEqual(result, [a * b for a in range(16) for b in range(16)])
def test_over_max_read_ports(self): width = 6 rom = pyrtl.RomBlock(width, width, [2, 4, 7, 1]) for i in range(rom.max_read_ports): rom_read_address = pyrtl.Input(width) rom_out = pyrtl.Output(width) rom_out <<= rom[rom_read_address] rom_read_address = pyrtl.Input(width) rom_out = pyrtl.Output(width) with self.assertRaises(pyrtl.PyrtlError): rom_out <<= rom[rom_read_address]
def test_romblock_does_not_throw_error(self): from pyrtl.corecircuits import _basic_add a = pyrtl.Input(bitwidth=3, name='a') b = pyrtl.Input(bitwidth=3, name='b') o = pyrtl.Output(bitwidth=3, name='o') res = _basic_add(a,b) rdat = {0: 1, 1: 2, 2: 5, 5: 0} mixtable = pyrtl.RomBlock(addrwidth=3, bitwidth=3, pad_with_zeros=True, romdata=rdat) o <<= mixtable[res[:-1]] with io.StringIO() as testbuffer: pyrtl.output_to_verilog(testbuffer)
def setUp(self): pyrtl.reset_working_block() self.bitwidth = 3 self.addrwidth = 5 self.output1 = pyrtl.Output(self.bitwidth, "output1") self.in1 = pyrtl.Input(self.addrwidth, name='mem_write_address') self.in2 = pyrtl.Input(self.addrwidth, name='mem_write_address') self.memory = pyrtl.RomBlock(bitwidth=self.bitwidth, addrwidth=self.addrwidth, name='self.memory', romdata=self.data)
def test_output_to_graphviz_correct_output_without_arg_ordering(self): i = pyrtl.Input(8, 'i') j = pyrtl.Input(4, 'j') o = pyrtl.Output(8, 'o') q = pyrtl.Output(1, 'q') o <<= i < j q <<= j > i with io.StringIO() as vfile: pyrtl.output_to_graphviz(file=vfile) self.assertEqual(vfile.getvalue(), graphviz_string_arg_unordered)
def check_op(self, op): ina, inb = pyrtl.Input(bitwidth=4, name='a'), pyrtl.Input(bitwidth=4, name='b') self.output <<= op(ina, inb) pyrtl.synthesize() sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) for a in range(16): for b in range(16): sim.step({'a': a, 'b': b}) result = sim_trace.trace['r'] self.assertEqual(result, [op(a, b) for a in range(16) for b in range(16)])
def setUp(self): pyrtl.reset_working_block() in1 = pyrtl.Input(4, "in1") in2 = pyrtl.Input(4, "in2") out1 = pyrtl.Output(4, "out1") out1 <<= (in1 ^ in2) + pyrtl.Const(1) out2 = pyrtl.Output(4, "out2") out2 <<= in1 | in2 self.inputs = { 'in1': [0, 1, 3, 15, 14], 'in2': [6, 6, 6, 6, 6], }
def setUp(self): pyrtl.reset_working_block() self.bitwidth = 3 self.addrwidth = 5 self.output1 = pyrtl.Output(self.bitwidth, "output1") self.output2 = pyrtl.Output(self.bitwidth, "output2") self.mem_read_address1 = pyrtl.Input(self.addrwidth, name='mem_read_address1') self.mem_read_address2 = pyrtl.Input(self.addrwidth, name='mem_read_address2') self.mem_write_address = pyrtl.Input(self.addrwidth, name='mem_write_address') self.mem_write_data = pyrtl.Input(self.bitwidth, name='mem_write_data') self.memory = pyrtl.MemBlock(bitwidth=self.bitwidth, addrwidth=self.addrwidth, name='self.memory', max_read_ports=None)
def setUp(self): pyrtl.reset_working_block() bitwidth = 3 self.a = pyrtl.Input(bitwidth=bitwidth) self.b = pyrtl.Input(bitwidth=bitwidth) self.sel = pyrtl.Input(bitwidth=1) self.muxout = pyrtl.Output(bitwidth=bitwidth, name='muxout') self.muxout <<= generate_full_mux(self.a, self.b, self.sel) # build the actual simulation environment self.sim_trace = pyrtl.SimulationTrace() self.sim = pyrtl.FastSimulation(tracer=self.sim_trace)
def test_csprng_trivium(self): """ Trivium test vectors retrived from: https://www.sheffield.ac.uk/polopoly_fs/1.12164!/file/eSCARGOt_full_datasheet_v1.3.pdf bit ordering is modified to adapt to the Pyrtl implementation """ in_vector = pyrtl.Input(160, 'in_vector') load, req = pyrtl.Input(1, 'load'), pyrtl.Input(1, 'req') ready = pyrtl.Output(1, 'ready') out_vector = pyrtl.Output(128, 'out_vector') ready_out, rand_out = prngs.csprng_trivium(128, load, req, in_vector) ready <<= ready_out out_vector <<= rand_out sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) in_vals = [ 0x0100000000000000000000000000000000000000, 0x0a09080706050403020100000000000000000000, 0xfffefdfcfbfaf9f8f7f600000000000000000000, 0xfaa75401ae5b08b5620fc760f9922bc45df68f28, 0xf5a24ffca95603b05d0abe57f08922bb54ed861f, ] true_vals = [ 0x1cd761ffceb05e39f5b18f5c22042ab0, 0x372e6b86524afa71b5fee86d5cebb07d, 0xc100baca274287277ff49b9fb512af1c, 0xcb5996fcff373a953fc169e899e02f46, 0xf142d1df4b36c7652cba2e4a22ee51a0, ] for trial in range(5): sim.step({'load': 1, 'req': 0, 'in_vector': in_vals[trial]}) for cycle in range(1, 20): sim.step({'load': 0, 'req': 0, 'in_vector': 0x0}) sim.step({'load': 0, 'req': 1, 'in_vector': 0x0}) for cycle in range(21, 23): sim.step({'load': 0, 'req': 0, 'in_vector': 0x0}) circuit_out = sim.inspect(out_vector) self.assertEqual( circuit_out, true_vals[trial], "\nAssertion failed on trial {}\nExpected value: {}\nGotten value: {}" .format(trial, hex(true_vals[trial]), hex(circuit_out))) for ready_signal in sim_trace.trace['ready'][:19]: self.assertEqual(ready_signal, 0) self.assertEqual(sim_trace.trace['ready'][19], 1) for ready_signal in sim_trace.trace['ready'][20:22]: self.assertEqual(ready_signal, 0) self.assertEqual(sim_trace.trace['ready'][22], 1) self.assertEqual(sim_trace.trace['ready'][23], 0)
def test_aes_state_machine(self): # self.longMessage = True aes_key = pyrtl.Input(bitwidth=128, name='aes_key') reset = pyrtl.Input(1) ready = pyrtl.Output(1, name='ready') encrypt_ready, encrypt_out = self.aes_encrypt.encrypt_state_m( self.in_vector, aes_key, reset) self.out_vector <<= encrypt_out ready <<= encrypt_ready sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) sim.step({ self.in_vector: 0x00112233445566778899aabbccddeeff, aes_key: 0x000102030405060708090a0b0c0d0e0f, reset: 1 }) true_vals = [ 0x00112233445566778899aabbccddeeff, 0x00102030405060708090a0b0c0d0e0f0, 0x89d810e8855ace682d1843d8cb128fe4, 0x4915598f55e5d7a0daca94fa1f0a63f7, 0xfa636a2825b339c940668a3157244d17, 0x247240236966b3fa6ed2753288425b6c, 0xc81677bc9b7ac93b25027992b0261996, 0xc62fe109f75eedc3cc79395d84f9cf5d, 0xd1876c0f79c4300ab45594add66ff41f, 0xfde3bad205e5d0d73547964ef1fe37f1, 0xbd6e7c3df2b5779e0b61216e8b10b689, 0x69c4e0d86a7b0430d8cdb78070b4c55a, 0x69c4e0d86a7b0430d8cdb78070b4c55a, ] for cycle in range( 1, 13): # Bogus data for while the state machine churns sim.step({self.in_vector: 0x0, aes_key: 0x1, reset: 0}) circuit_out = sim_trace.trace[self.out_vector][cycle] sim_trace.render_trace(symbol_len=40) self.assertEqual( circuit_out, true_vals[cycle], "\nAssertion failed on cycle: " + str(cycle) + " Gotten value: " + hex(circuit_out)) for ready_signal in sim_trace.trace[ready][:11]: self.assertEquals(ready_signal, 0) for ready_signal in sim_trace.trace[ready][11:]: self.assertEquals(ready_signal, 1)
def setUp(self): pyrtl.reset_working_block() in1 = pyrtl.Input(4, "in1") in2 = pyrtl.Input(4, "in2") out1 = pyrtl.Output(4, "out1") out1 <<= (in1 ^ in2) + pyrtl.Const(1) out2 = pyrtl.Output(4, "out2") out2 <<= in1 | in2 self.inputs = { 'in1': [0, 1, 3, 15, 14], 'in2': '66666', # When a string, assumes each input is a single digit integer }
def test_loop_2(self): in_1 = pyrtl.Input(10) in_2 = pyrtl.Input(9) fake_loop_wire = pyrtl.WireVector(1) # Note the slight difference from the last test case on the next line comp_wire = pyrtl.concat(in_2[0:6], fake_loop_wire, in_2[6:9]) r_wire = in_1 & comp_wire fake_loop_wire <<= r_wire[3] out = pyrtl.Output(10) out <<= fake_loop_wire # It causes there to be a real loop self.assert_has_loop()
def test_aes_state_machine(self): # self.longMessage = True aes_key = pyrtl.Input(bitwidth=128, name='aes_key') reset = pyrtl.Input(1) ready = pyrtl.Output(1, name='ready') decrypt_ready, decrypt_out = self.aes_decrypt.decryption_statem( self.in_vector, aes_key, reset) self.out_vector <<= decrypt_out ready <<= decrypt_ready sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) sim.step({ self.in_vector: 0x69c4e0d86a7b0430d8cdb78070b4c55a, aes_key: 0x000102030405060708090a0b0c0d0e0f, reset: 1 }) true_vals = [ 0x69c4e0d86a7b0430d8cdb78070b4c55a, 0x7ad5fda789ef4e272bca100b3d9ff59f, 0x54d990a16ba09ab596bbf40ea111702f, 0x3e1c22c0b6fcbf768da85067f6170495, 0xb458124c68b68a014b99f82e5f15554c, 0xe8dab6901477d4653ff7f5e2e747dd4f, 0x36339d50f9b539269f2c092dc4406d23, 0x2d6d7ef03f33e334093602dd5bfb12c7, 0x3bd92268fc74fb735767cbe0c0590e2d, 0xa7be1a6997ad739bd8c9ca451f618b61, 0x6353e08c0960e104cd70b751bacad0e7, 0x00112233445566778899aabbccddeeff, 0x00112233445566778899aabbccddeeff, ] for cycle in range( 1, 13): # Bogus data for while the state machine churns sim.step({self.in_vector: 0x0, aes_key: 0x1, reset: 0}) circuit_out = sim_trace.trace[self.out_vector][cycle] self.assertEqual( circuit_out, true_vals[cycle], "\nAssertion failed on cycle: " + str(cycle) + " Gotten value: " + hex(circuit_out)) for ready_signal in sim_trace.trace[ready][:11]: self.assertEquals(ready_signal, 0) for ready_signal in sim_trace.trace[ready][11:]: self.assertEquals(ready_signal, 1)
def __init__(self, depth_width=2, data_width=32): aw = depth_width dw = data_width self.wr_data_i = pyrtl.Input(dw, 'wr_data_i') self.wr_en_i = pyrtl.Input(1, 'wr_en_i') self.rd_data_o = pyrtl.Output(dw, 'rd_data_o') self.rd_en_i = pyrtl.Input(1, 'rd_en_i') self.full_o = pyrtl.Output(1, 'full_o') self.empty_o = pyrtl.Output(1, 'empty_o') self.one_left = pyrtl.Output(1, 'one_left') self.reset = pyrtl.Input(1, 'reset') self.write_pointer = pyrtl.Register(aw + 1, 'write_pointer') self.read_pointer = pyrtl.Register(aw + 1, 'read_pointer') self.read_plus_1 = pyrtl.Const(1, 1) + self.read_pointer self.read_pointer.next <<= pyrtl.select(self.rd_en_i, truecase=self.read_plus_1, falsecase=self.read_pointer) self.write_pointer.next <<= pyrtl.select( self.reset, truecase=pyrtl.Const(0, aw + 1), falsecase=pyrtl.select(self.wr_en_i, truecase=self.write_pointer + 1, falsecase=self.write_pointer)) self.empty_int = pyrtl.WireVector(1, 'empty_int') self.full_or_empty = pyrtl.WireVector(1, 'full_or_empty') self.empty_int <<= self.write_pointer[aw] == self.read_pointer[aw] self.full_or_empty <<= self.write_pointer[0:aw] == self.read_pointer[ 0:aw] self.full_o <<= self.full_or_empty & ~self.empty_int self.empty_o <<= self.full_or_empty & self.empty_int self.one_left <<= (self.read_pointer + 1) == self.write_pointer self.mem = m = _RAM(num_entries=1 << aw, data_nbits=dw, name='FIFOStorage') m.wen <<= self.wr_en_i m.ren <<= self.rd_en_i m.raddr <<= self.read_pointer[0:aw] m.waddr <<= self.write_pointer[0:aw] m.wdata <<= self.wr_data_i self.rd_data_o <<= pyrtl.select(self.rd_en_i, truecase=m.rdata, falsecase=pyrtl.Const(0, dw))
def test_chained_mul(self): ina, inb, inc = ( pyrtl.Input(bitwidth=2, name='a'), pyrtl.Input(bitwidth=2, name='b'), pyrtl.Input(bitwidth=2, name='c')) self.output <<= ina * inb * inc pyrtl.synthesize() sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) for a in range(4): for b in range(4): for c in range(4): sim.step({'a': a, 'b': b, 'c': c}) result = sim_trace.trace['r'] self.assertEqual(result, [a * b * c for a in range(4) for b in range(4) for c in range(4)])
def test_timing_error(self): inwire, inwire2 = pyrtl.Input(bitwidth=1), pyrtl.Input(bitwidth=1) tempwire, tempwire2 = pyrtl.WireVector(1), pyrtl.WireVector(1) outwire = pyrtl.Output() tempwire <<= ~(inwire & tempwire2) tempwire2 <<= ~(inwire2 & tempwire) outwire <<= tempwire with self.assertRaises(pyrtl.PyrtlError): pyrtl.synthesize() pyrtl.optimize() block = pyrtl.working_block() timing = estimate.TimingAnalysis(block) timing_max_length = timing.max_length()
def test_unknown_wires(self): inp = pyrtl.Input(8, 'inp') out = pyrtl.Output(8, 'out') out <<= inp pyrtl.working_block().wirevector_set.discard(inp) with self.assertRaises(pyrtl.PyrtlInternalError): # sanity_check_net() self.sanity_error("Unknown wires")
def test_invalid_exception_type(self): w = pyrtl.Input(1) self.bad_rtl_assert(w, 1) self.bad_rtl_assert(w, "") self.bad_rtl_assert(w, w) self.bad_rtl_assert(w, KeyError())
def test_consts_from_int_enums(self): from enum import IntEnum class MyEnum(IntEnum): A = 0 B = 1 C = 3 i = pyrtl.Input(max(MyEnum).bit_length(), 'i') o = pyrtl.Output(1, 'o') with pyrtl.conditional_assignment: with (i == MyEnum.A) | (i == MyEnum.B): o |= 0 with pyrtl.otherwise: o |= 1 trace = pyrtl.SimulationTrace() sim = self.sim(tracer=trace) sim.step({'i': MyEnum.A}) self.assertEqual(sim.inspect(o), 0) sim.step({'i': MyEnum.B}) self.assertEqual(sim.inspect(o), 0) sim.step({'i': MyEnum.C}) self.assertEqual(sim.inspect(o), 1)
def test_weird_wire_names(self): """ Some simulations need to be careful when handling special names (eg Fastsim June 2016) """ i = pyrtl.Input(8, '"182&!!!\n') o = pyrtl.Output(8, '*^*)#*$\'*') o2 = pyrtl.Output(8, 'test@+') w = pyrtl.WireVector(8, '[][[-=--09888') r = pyrtl.Register(8, '&@#)^#@^&(asdfkhafkjh') w <<= i r.next <<= i o <<= w o2 <<= r trace = pyrtl.SimulationTrace() sim = self.sim(tracer=trace) sim.step({i: 28}) self.assertEqual(sim.inspect(o), 28) self.assertEqual(sim.inspect(o.name), 28) self.assertEqual(trace.trace[o.name], [28]) sim.step({i: 233}) self.assertEqual(sim.inspect(o), 233) self.assertEqual(sim.inspect(o2), 28) self.assertEqual(sim.inspect(o2.name), 28) self.assertEqual(trace.trace[o2.name], [0, 28])
def test_invalid_inspect(self): a = pyrtl.Input(8, 'a') sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=sim_trace) sim.step({a: 28}) with self.assertRaises(KeyError): sim.inspect('asd')
def test_rom_val_map(self): def rom_data_function(add): return int((add + 5) / 2) dummy_in = pyrtl.Input(1, "dummy") self.bitwidth = 4 self.addrwidth = 4 self.rom1 = pyrtl.RomBlock(bitwidth=self.bitwidth, addrwidth=self.addrwidth, name='rom1', romdata=rom_data_function) self.rom2 = pyrtl.RomBlock(bitwidth=self.bitwidth, addrwidth=self.addrwidth, name='rom2', romdata=rom_data_function) mem_val_map = { self.rom1: { 0: 0, 1: 1, 2: 2, 3: 3 }, self.rom2: { 0: 4, 1: 5, 2: 6, 3: 7 } } self.sim_trace = pyrtl.SimulationTrace() with self.assertRaises(pyrtl.PyrtlError): sim = self.sim(tracer=self.sim_trace, memory_value_map=mem_val_map)
def test_mem_val_map(self): read_addr3 = pyrtl.Input(self.addrwidth) self.output3 = pyrtl.Output(self.bitwidth, "o3") self.output3 <<= self.mem2[read_addr3] mem_val_map = {self.mem1: {0: 0, 1: 1, 2: 2, 3: 3}, self.mem2: {0: 4, 1: 5, 2: 6, 3: 7}} self.sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=self.sim_trace, memory_value_map=mem_val_map) # put new entries in for i in range(2): sim.step({ self.read_addr1: 4 + i, # d.c. self.read_addr2: 4 + i, # d.c. read_addr3: 2, self.write_addr: 4 + i, # put a 4 and a 5 in the 4th and 5th addr of mem1 self.write_data: 4 + i }) # modify existing entries for i in range(2): sim.step({ self.read_addr1: 1 + i, # d.c. self.read_addr2: 1 + i, # d.c. read_addr3: 2, self.write_addr: 1 + i, # put a 2 and a 3 in the 1st and 2nd addr of mem1 self.write_data: 2 + i }) # check consistency of memory_value_map assignment, insertion, and modification self.assertEquals(sim.inspect_mem(self.mem1), {0: 0, 1: 2, 2: 3, 3: 3, 4: 4, 5: 5})
def test_trace_to_html_repr_per_name_enum_is_bool(self): from enum import IntEnum class Foo(IntEnum): A = 0 B = 1 i = pyrtl.Input(2, 'i') state = pyrtl.Register(max(Foo).bit_length(), name='state') o = pyrtl.Output(name='o') o <<= state with pyrtl.conditional_assignment: with i == 0b01: state.next |= Foo.A with i == 0b10: state.next |= Foo.B sim = pyrtl.Simulation() sim.step_multiple({'i': [1, 2, 1, 2, 2]}) htmlstring = pyrtl.trace_to_html(sim.tracer, repr_per_name={'state': Foo}) expected = ( '<script type="WaveDrom">\n' '{\n' ' signal : [\n' ' { name: "i", wave: "====.", data: ["0x1", "0x2", "0x1", "0x2"] },\n' ' { name: "o", wave: "0.101" },\n' ' { name: "state", wave: "=.===", data: ["Foo.A", "Foo.B", "Foo.A", "Foo.B"] },\n' ' ],\n' ' config: { hscale: 2 }\n' '}\n' '</script>\n') self.assertEqual(htmlstring, expected)