def test_wallace_tree_1(self): """ Arithmatic tester version 2015.05 """ # Creating the logic nets a, b = pyrtl.Input(13, "a"), pyrtl.Input(14, "b") product = pyrtl.Output(27, "product") product <<= multipliers.tree_multiplier(a, b) # creating the testing values and the correct results xvals = [int(random.uniform(0, 2**13-1)) for i in range(20)] yvals = [int(random.uniform(0, 2**14-1)) for i in range(20)] true_result = [i * j for i, j in zip(xvals, yvals)] # Setting up and running the tests sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) for cycle in range(len(xvals)): sim.step({a: xvals[cycle], b: yvals[cycle]}) # Extracting the values and verifying correctness multiplier_result = sim_trace.trace[product] self.assertEqual(multiplier_result, true_result) # now executing the same test using FastSim sim_trace = pyrtl.SimulationTrace() sim = pyrtl.FastSimulation(tracer=sim_trace) for cycle in range(len(xvals)): sim.step({a: xvals[cycle], b: yvals[cycle]}) multiplier_result = sim_trace.trace[product] self.assertEqual(multiplier_result, true_result)
def test_step_multiple_many_errors_report_only_first(self): sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=sim_trace) expected = { 'out1': [7, 9, 4, 10, 9], 'out2': [6, 2, 7, 8, 14], } output = six.StringIO() sim.step_multiple(self.inputs, expected, file=output, stop_after_first_error=True) # Test the output about unexpected values correct_output = ( "Unexpected output (stopped after step with first error):\n" " step name expected actual\n" " 1 out1 9 8\n" " 1 out2 2 7\n") self.assertEqual(output.getvalue(), correct_output) # Test that the trace stopped after the step with the first error correct_output = (" --- Values in base 10 ---\n" "in1 0 1\n" "in2 6 6\n" "out1 7 8\n" "out2 6 7\n") output = six.StringIO() sim_trace.print_trace(output) self.assertEqual(output.getvalue(), correct_output)
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_step_multiple_many_errors_report_all(self): sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=sim_trace) expected = { 'out1': [7, 9, 4, 10, 9], 'out2': [6, 2, 7, 8, 14], } output = six.StringIO() sim.step_multiple(self.inputs, expected, file=output) # Test the output about unexpected values correct_output = ("Unexpected output on one or more steps:\n" " step name expected actual\n" " 1 out1 9 8\n" " 1 out2 2 7\n" " 2 out1 4 6\n" " 3 out2 8 15\n") self.assertEqual(output.getvalue(), correct_output) # Test that the trace still produced all the steps correct_output = (" --- Values in base 10 ---\n" "in1 0 1 3 15 14\n" "in2 6 6 6 6 6\n" "out1 7 8 6 10 9\n" "out2 6 7 7 15 14\n") output = six.StringIO() sim_trace.print_trace(output) self.assertEqual(output.getvalue(), correct_output)
def test_function_RomBlock(self): def rom_data_function(add): return int((add + 5) / 2) pyrtl.reset_working_block() self.bitwidth = 4 self.addrwidth = 4 self.output1 = pyrtl.Output(self.bitwidth, "o1") self.output2 = pyrtl.Output(self.bitwidth, "o2") self.read_addr1 = pyrtl.Input(self.addrwidth) self.read_addr2 = pyrtl.Input(self.addrwidth) self.rom = pyrtl.RomBlock(bitwidth=self.bitwidth, addrwidth=self.addrwidth, name='rom', romdata=rom_data_function) self.output1 <<= self.rom[self.read_addr1] self.output2 <<= self.rom[self.read_addr2] # build the actual simulation environment self.sim_trace = pyrtl.SimulationTrace() self.sim = pyrtl.FastSimulation(tracer=self.sim_trace) input_signals = {} for i in range(0, 5): input_signals[i] = {self.read_addr1: i, self.read_addr2: 2 * i} self.sim.step(input_signals[i]) exp_out = self.generate_expected_output( (("o1", lambda x: rom_data_function(x)), ("o2", lambda x: rom_data_function(2 * x))), 6) self.compareIO(self.sim_trace, exp_out)
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_blif_input_simulates_correctly_with_merged_outputs(self): # The 'counter_blif' string contains a model of a standard 4-bit synchronous-reset # counter with enable. In particular, the model has 4 1-bit outputs named "count[0]", # "count[1]", "count[2]", and "count[3]". The internal PyRTL representation will by # default convert these related 1-bit wires into a single 4-bit wire called "count". # This test simulates the design and, among other things, ensures that this output # wire conversion occurred correctly. pyrtl.input_from_blif(counter4bit_blif) io_vectors = pyrtl.working_block().wirevector_subset( (pyrtl.Input, pyrtl.Output)) sim_trace = pyrtl.SimulationTrace(wires_to_track=io_vectors) sim = pyrtl.Simulation(sim_trace) inputs = { 'rst': [1] + [0] * 20, 'en': [1] + [1] * 20, } expected = {'count': [0] + list(range(0, 16)) + list(range(0, 4))} sim.step_multiple(inputs, expected) correct_output = ( " --- Values in base 10 ---\n" "count 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3\n" "en 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1\n" "rst 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" ) output = six.StringIO() sim_trace.print_trace(output) self.assertEqual(output.getvalue(), correct_output)
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_one_bit_adder_matches_expected(self): temp1 = pyrtl.WireVector(bitwidth=1, name='temp1') temp2 = pyrtl.WireVector() a, b, c = pyrtl.Input(1, 'a'), pyrtl.Input(1, 'b'), pyrtl.Input(1, 'c') sum, carry_out = pyrtl.Output(1, 'sum'), pyrtl.Output(1, 'carry_out') sum <<= a ^ b ^ c temp1 <<= a & b # connect the result of a & b to the pre-allocated wirevector temp2 <<= a & c temp3 = b & c # temp3 IS the result of b & c (this is the first mention of temp3) carry_out <<= temp1 | temp2 | temp3 sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) for cycle in range(15): sim.step({ 'a': random.choice([0, 1]), 'b': random.choice([0, 1]), 'c': random.choice([0, 1]) }) htmlstring = inputoutput.trace_to_html( sim_trace) # tests if it compiles or not
def test_fastsim_wire_names(self): """ Testing ability to use wire names instead of wires in input""" in1 = pyrtl.Input(8, "in1") in2 = pyrtl.Input(8, "in2") in3 = pyrtl.Input(8, "in3") truth = pyrtl.Const(1, 1) out1 = pyrtl.Output(16, "out2") out2 = pyrtl.Output(16, "out3") out1 <<= in1 + in2 out2 <<= in3 | truth sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=sim_trace) for i in range(10): sim.step({ 'in1': 2 * i, 'in2': 3 * i, 'in3': 40 - 2 * i }) correct_outp = (" --- Values in base 10 ---\n" "in1 0 2 4 6 8 10 12 14 16 18\n" "in2 0 3 6 9 12 15 18 21 24 27\n" "in3 40 38 36 34 32 30 28 26 24 22\n" "out2 0 5 10 15 20 25 30 35 40 45\n" "out3 41 39 37 35 33 31 29 27 25 23\n") output = six.StringIO() sim_trace.print_trace(output) self.assertEqual(output.getvalue(), correct_outp)
def mult_t_base(self, len_a, len_b, shifts): a, b = pyrtl.Input(len_a, 'a'), pyrtl.Input(len_b, 'b') reset = pyrtl.Input(1, 'reset') product, done = pyrtl.Output(name='product'), pyrtl.Output(name='done') m_prod, m_done = multipliers.complex_mult(a, b, shifts, reset) product <<= m_prod done <<= m_done self.assertEqual(len(product), len_a + len_b) xvals = [int(random.uniform(0, 2**len_a - 1)) for i in range(20)] yvals = [int(random.uniform(0, 2**len_b - 1)) for i in range(20)] true_result = [i * j for i, j in zip(xvals, yvals)] mult_results = [] for x_val, y_val, true_res in zip(xvals, yvals, true_result): sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) sim.step({a: x_val, b: y_val, reset: 1}) if shifts <= len_a: length = len_a // shifts + (1 if len_a % shifts == 0 else 2) else: length = len_a + 1 for cycle in range(length): sim.step({a: 0, b: 0, reset: 0}) # Extracting the values and verifying correctness mult_results.append(sim.inspect('product')) self.assertEqual(sim.inspect('done'), 1) self.assertEqual(mult_results, true_result)
def test_prng_xoroshiro128(self): seed = pyrtl.Input(128, 'seed') load, req = pyrtl.Input(1, 'load'), pyrtl.Input(1, 'req') ready = pyrtl.Output(1, 'ready') rand = pyrtl.Output(128, 'rand') ready_out, rand_out = prngs.prng_xoroshiro128(128, load, req, seed) ready <<= ready_out rand <<= rand_out sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) in_vals = [random.randrange(1, 2**128) for i in range(5)] for trial in range(5): true_val = 0 for word in islice(TestPrngs.xoroshiro128plus(in_vals[trial]), 2): true_val = true_val << 64 | word sim.step({'load': 1, 'req': 0, 'seed': in_vals[trial]}) sim.step({'load': 0, 'req': 1, 'seed': 0x0}) for cycle in range(2, 4): sim.step({'load': 0, 'req': 0, 'seed': 0x0}) circuit_out = sim.inspect(rand) self.assertEqual( circuit_out, true_val, "\nAssertion failed on trial {}\nExpected value: {}\nGotten value: {}" .format(trial, hex(true_val), hex(circuit_out))) for ready_signal in sim_trace.trace['ready'][:3]: self.assertEqual(ready_signal, 0) self.assertEqual(sim_trace.trace['ready'][3], 1) self.assertEqual(sim_trace.trace['ready'][4], 0)
def mult_t_base(self, len_a, len_b): a, b, reset = pyrtl.Input(len_a, "a"), pyrtl.Input(len_b, "b"), pyrtl.Input( 1, 'reset') product, done = pyrtl.Output(name="product"), pyrtl.Output(name="done") m_prod, m_done = multipliers.simple_mult(a, b, reset) product <<= m_prod done <<= m_done self.assertEqual(len(product), len_a + len_b) xvals = [int(random.uniform(0, 2**len_a - 1)) for i in range(20)] yvals = [int(random.uniform(0, 2**len_b - 1)) for i in range(20)] true_result = [i * j for i, j in zip(xvals, yvals)] mult_results = [] for x_val, y_val, true_res in zip(xvals, yvals, true_result): sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) sim.step({a: x_val, b: y_val, reset: 1}) for cycle in range(len(a) + 1): sim.step({a: 0, b: 0, reset: 0}) # Extracting the values and verifying correctness mult_results.append(sim.inspect("product")) self.assertEqual(sim.inspect("done"), 1) self.assertEqual(mult_results, true_result)
def mult_t_base(self, len_a, len_b, **mult_args): # Creating the logic nets a, b = pyrtl.Input(len_a, "a"), pyrtl.Input(len_b, "b") product = pyrtl.Output(name="product") product <<= multipliers.signed_tree_multiplier(a, b, **mult_args) self.assertEqual(len(product), len_a + len_b) # creating the testing values and the correct results bound_a = 2**(len_a - 1) - 1 bound_b = 2**(len_b - 1) - 1 xvals = [int(random.uniform(-bound_a, bound_a)) for i in range(20)] yvals = [int(random.uniform(-bound_b, bound_b)) for i in range(20)] true_result = [i * j for i, j in zip(xvals, yvals)] # Setting up and running the tests sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) for cycle in range(len(xvals)): sim.step({ a: libutils.twos_comp_repr(xvals[cycle], len_a), b: libutils.twos_comp_repr(yvals[cycle], len_b) }) # Extracting the values and verifying correctness multiplier_result = [ libutils.rev_twos_comp_repr(p, len(product)) for p in sim_trace.trace[product.name] ] self.assertEqual(multiplier_result, true_result)
def test_read_memindexed_ior(self): self.mem = pyrtl.MemBlock(8, 8) self.mem_val_map = {self.mem: {0: 5, 1: 4, 2: 3, 3: 2, 4: 1, 5: 0}} decide = pyrtl.Input(1) ind = pyrtl.Input(3) x = self.mem[ind] y = pyrtl.Output(8, 'y') z = pyrtl.Output(8, 'z') w = pyrtl.Output(8, 'w') with pyrtl.conditional_assignment: with decide: y |= x z |= x with pyrtl.otherwise: w |= x sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace, memory_value_map=self.mem_val_map) for i in range(5): sim.step({decide: i % 2, ind: i}) if i == 0: y_exp, z_exp, w_exp = 0, 0, 5 elif i == 1: y_exp, z_exp, w_exp = 4, 4, 0 elif i == 2: y_exp, z_exp, w_exp = 0, 0, 3 elif i == 3: y_exp, z_exp, w_exp = 2, 2, 0 else: y_exp, z_exp, w_exp = 0, 0, 1 self.assertEqual(sim.inspect(y), y_exp) self.assertEqual(sim.inspect(z), z_exp) self.assertEqual(sim.inspect(w), w_exp) self.assertEqual(self.mem.num_read_ports, 1)
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_twos_comp_sim(self): self.out <<= self.in1 + self.in2 sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) for i in range(10): sim.step({'in1': i, 'in2': libutils.twos_comp_repr(-2 * i, 8)}) self.assertEquals( -i, libutils.rev_twos_comp_repr(sim.inspect('out'), 8))
def test_step_multiple_bad_nsteps2(self): sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=sim_trace) with self.assertRaises(pyrtl.PyrtlError) as error: sim.step_multiple(self.inputs, nsteps=-1) self.assertEqual(str(error.exception), 'must simulate at least one step')
def check_trace(self, correct_string): sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=sim_trace) for i in range(8): sim.step({}) output = six.StringIO() sim_trace.print_trace(output, compact=True) self.assertEqual(output.getvalue(), correct_string)
def test_no_named_wires_erro(self): a = pyrtl.Const(-1, bitwidth=8) b = pyrtl.Input(8) c = pyrtl.Output() c <<= a + b with self.assertRaises(pyrtl.PyrtlError): sim_trace = pyrtl.SimulationTrace()
def check_trace(self, correct_string): sim_trace = pyrtl.SimulationTrace() sim = pyrtl.FastSimulation(tracer=sim_trace) for i in range(8): sim.step({}) output = io.StringIO() sim_trace.print_trace(output) self.assertEqual(output.getvalue(), correct_string)
def test_step_multiple_nsteps_gt_ninputs(self): sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=sim_trace) with self.assertRaises(pyrtl.PyrtlError) as error: sim.step_multiple(self.inputs, nsteps=6) self.assertEqual(str(error.exception), 'nsteps is specified but is greater than the ' 'number of values supplied for each input')
def check_trace(self, correct_string, **kwargs): wtt = pyrtl.working_block().wirevector_subset(pyrtl.Output) sim_trace = pyrtl.SimulationTrace(wires_to_track=wtt) sim = self.sim(tracer=sim_trace, **kwargs) for i in range(8): sim.step({self.i: i}) output = six.StringIO() sim_trace.print_trace(output, compact=True) self.assertEqual(output.getvalue(), correct_string)
def check_trace(self, correct_string): sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace) for i in range(8): sim.step({}) output = six.StringIO() sim_trace.print_trace(output, compact=True) spaced_output = ' '.join(output.getvalue()) # add spaces to string self.assertEqual(spaced_output, correct_string)
def test_step_multiple_no_inputs(self): sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=sim_trace) with self.assertRaises(pyrtl.PyrtlError) as error: sim.step_multiple() self.assertEqual( str(error.exception), 'need to supply either input values ' 'or a number of steps to simulate')
def test_step_multiple_no_values_for_each_step_of_input(self): sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=sim_trace) with self.assertRaises(pyrtl.PyrtlError) as error: sim.step_multiple({'in1': [0, 1, 3], 'in2': [1]}) self.assertEqual( str(error.exception), 'must supply a value for each provided wire ' 'for each step of simulation')
def init_sim(testname): file = open("tests/{}.s".format(testname), 'r') enc_asm = file.readlines()[0][1:].strip() asm = loads(b64decode(enc_asm).decode("UTF-8")) i_mem_init = {int(k): v for k, v in asm.items()} sim_trace = pyrtl.SimulationTrace() sim = pyrtl.Simulation(tracer=sim_trace, memory_value_map={ i_mem : i_mem_init }) return sim, sim_trace
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_invalid_base(self): self.in1 = pyrtl.Input(8, "in1") self.out = pyrtl.Output(8, "out") self.out <<= self.in1 self.sim_trace = pyrtl.SimulationTrace() sim = self.sim(tracer=self.sim_trace) for i in range(5): sim.step({self.in1: i}) with self.assertRaises(pyrtl.PyrtlError): self.sim_trace.print_trace(base=4)