def test_backwards_compatibility(): """ Test backwards-compatibility wrappers for BinaryValue """ # bits is deprecated in favor of n_bits with pytest.deprecated_call(): vec = BinaryValue(value=0, bits=16) assert vec.n_bits == 16 vec = BinaryValue(0, 16) assert vec.n_bits == 16 with pytest.raises(TypeError): BinaryValue(value=0, bits=16, n_bits=17)
def wrxact(self, addr, data, addr_delay=0, data_delay=0, resp_delay=0): addr = BinaryValue(addr, bits=self._bits, bigEndian=False) data = BinaryValue(data, bits=self._bits, bigEndian=False) addr_phase = cocotb.fork(self._wrxact_addr_phase(addr, addr_delay)) data_phase = cocotb.fork(self._wrxact_data_phase(data, data_delay)) resp_phase = cocotb.fork(self._wrxact_resp_phase(addr, resp_delay)) yield addr_phase.join() yield data_phase.join() yield resp_phase.join() resp = self._entity.bresp if int(resp): raise AxiError("axi4 lite master", false, int(addr), resp)
def test_init_little_endian_signed(): bin1 = BinaryValue(value=3, n_bits=3, bigEndian=False, binaryRepresentation=BinaryRepresentation.SIGNED_MAGNITUDE) assert bin1._str == "011" assert bin1.binstr == "011" assert bin1.integer == 3 bin2 = BinaryValue(value=-1, n_bits=2, bigEndian=False, binaryRepresentation=BinaryRepresentation.SIGNED_MAGNITUDE) assert bin2._str == "11" assert bin2.binstr == "11" assert bin2.integer == -1 bin3 = BinaryValue(value="1001011", bigEndian=False, binaryRepresentation=BinaryRepresentation.SIGNED_MAGNITUDE) assert bin3._str == "1001011" assert bin3.binstr == "1001011" assert bin3.integer == -11
def __init__(self, entity): BusDriver.__init__(self, entity, "", entity.BUS_CLK) # Create an appropriately sized high-impedance value self._high_impedance = BinaryValue(n_bits=len(self.bus.BUS_DATA_IN)) self._high_impedance.binstr = "Z" * len(self.bus.BUS_DATA_IN) # Create an appropriately sized high-impedance value self._x = BinaryValue(n_bits=len(self.bus.BUS_ADD)) self._x.binstr = "x" * len(self.bus.BUS_ADD) self._has_byte_acces = False # Kick off a clock generator cocotb.fork(Clock(self.clock, 5000).start())
async def test_cdbus(dut): dut._log.info('test_cdbus start.') sys_clk = 40000000 clk_period = 1000000000000 / sys_clk cocotb.fork(Clock(dut.clk0, clk_period).start()) cocotb.fork(Clock(dut.clk1, clk_period).start()) cocotb.fork(Clock(dut.clk2, clk_period).start()) await reset(dut, 0) await reset(dut, 1) await reset(dut, 2) await check_version(dut, 0) await check_version(dut, 1) await check_version(dut, 2) val = await csr_read(dut, 0, REG_SETTING) dut._log.info(f'idx0 REG_SETTING: 0x{int(val):02x}') await csr_write(dut, 0, REG_SETTING, BinaryValue('00010001')) await csr_write(dut, 1, REG_SETTING, BinaryValue('00010001')) await csr_write(dut, 1, REG_INT_MASK, BinaryValue('11011110')) await set_div(dut, 0, 39, 2) # 1Mbps, 13.333Mbps await set_div(dut, 1, 39, 2) await csr_write(dut, 0, REG_FILTER, 0x01) # set local filter to 0x01 await csr_write(dut, 1, REG_FILTER, 0x02) # set local filter to 0x02 await write_tx(dut, 0, b'\x01\x02\x01\xcd') # node 0x01 send to 0x02 await csr_write(dut, 0, REG_TX_CTRL, BIT_TX_START | BIT_TX_RST_POINTER) await RisingEdge(dut.irq1) val = await csr_read(dut, 1, REG_INT_FLAG) dut._log.info(f'REG_INT_FLAG: 0x{int(val):02x}') str_ = (await read_rx(dut, 1, 6)).hex() # read 6 bytes (include crc) dut._log.info(f'idx1: received: {str_}') if str_ != '010201cd601d': dut._log.error(f'idx1: receive mismatch') await exit_err() await csr_write(dut, 1, REG_RX_CTRL, BIT_RX_CLR_PENDING | BIT_RX_RST_POINTER) await FallingEdge(dut.irq1) dut._log.info('test_cdbus done.') await exit_ok()
def _set_value(self, value, call_sim): """Set the value of the underlying simulation object to *value*. This operation will fail unless the handle refers to a modifiable object, e.g. net, signal or variable. We determine the library call to make based on the type of the value because assigning integers less than 32 bits is faster. Args: value (ctypes.Structure, cocotb.binary.BinaryValue, int, double): The value to drive onto the simulator object. Raises: TypeError: If target is not wide enough or has an unsupported type for value assignment. """ value, set_action = self._check_for_set_action(value) if isinstance(value, int) and value < 0x7fffffff and len(self) <= 32: call_sim(self._handle.set_signal_val_long, set_action, value) return if isinstance(value, ctypes.Structure): value = BinaryValue(value=cocotb.utils.pack(value), n_bits=len(self)) elif isinstance(value, int): value = BinaryValue(value=value, n_bits=len(self), bigEndian=False) elif isinstance(value, dict): # We're given a dictionary with a list of values and a bit size... num = 0 vallist = list(value["values"]) vallist.reverse() if len(vallist) * value["bits"] != len(self): raise TypeError( "Unable to set with array length %d of %d bit entries = %d total, target is only %d bits long" % (len(value["values"]), value["bits"], len(value["values"]) * value["bits"], len(self))) for val in vallist: num = (num << value["bits"]) + val value = BinaryValue(value=num, n_bits=len(self), bigEndian=False) elif not isinstance(value, BinaryValue): raise TypeError( "Unsupported type for value assignment: {} ({!r})".format( type(value), value)) call_sim(self._handle.set_signal_val_binstr, set_action, value.binstr)
async def random_wires(dut): """ Test simple wires logic with random bits """ for i in range(10000): # Create random values to send to model and dut # Random int value with max 16 bits. unsigned. random_dec_value = random.randint(0, 65536) # Convert random decimal to a string to represnt binary. a_binary = f'{random_dec_value:016b}' # Convert to cocotb structure BinaryValue, 16 bits long. a_bin_cocotb = BinaryValue(n_bits=16) a_bin_cocotb.binstr = a_binary # Set high and low values to compare with the DUT a_bin_cocotb_hi = str(a_bin_cocotb[0:7]) a_bin_cocotb_lo = str(a_bin_cocotb[8:15]) # Send random values to dut dut.vec <= int(random_dec_value) # Wait for dut to do its thing await Timer(1, units='ns') # Get values from DUT dut_out_hi = BinaryValue(n_bits=16) dut_out_hi = dut.out_hi.value dut_out_lo = BinaryValue(n_bits=16) dut_out_lo = dut.out_lo.value print("---------------------------------") print("Test ", i) print("Input value ", a_binary) print("DUT Output dut.out_hi.value ", dut.out_hi.value) print("DUT Output dut.out_lo.value ", dut.out_lo.value) print("---------------------------------\n") # Compare results if str(dut.out_hi.value) != a_bin_cocotb_hi: raise cocotb.result.TestFailure( "DUT recorded %d value but model recorded %d" % (int(dut.out_hi.value), a_bin_cocotb_hi)) if str(dut.out_lo.value) != a_bin_cocotb_lo: raise cocotb.result.TestFailure( "DUT recorded %d value but model recorded %d" % (int(dut.out_lo.value), a_bin_cocotb_lo))
async def _monitor_recv(self): #Wait for reset while True: await RisingEdge(self.clock) await ReadOnly() if self.bus.reset.value: break self.dut._log.info(f'Sha Type in Monitor = {self.bus.sha.value}') H_out_next = self.hash_init(self.bus.sha.value) # self.dut._log.info(f'Initialized H_out_next = {hex(H_out_next[0])}') while True: await RisingEdge(self.clock) await ReadOnly() H_out = H_out_next H_out_next = self.bus.H_out.value if self.bus.update.value: sha = self.bus.sha.value update = self.bus.update.value H_in = self.bus.H_in.value H_out_next = [ BinaryValue( self.sum(H_in[i], H_out_next[i], sha&0x2) ) for i in range(N_WORDS) ] if self.bus.reset.value: H_out_next = self.hash_init(self.bus.sha.value) else: self._recv(H_out)
def issue_142_overflow_error(dut): """Tranparently convert ints too long to pass through the GPI interface natively into BinaryValues""" cocotb.fork(Clock(dut.clk, 2500).start()) def _compare(value): if int(dut.stream_in_data_wide.value) != int(value): raise TestFailure("Expecting 0x%x but got 0x%x on %s" % (int(value), int(dut.stream_in_data_wide.value), str(dut.stream_in_data_wide))) # Wider values are transparently converted to BinaryValues for value in [ 0, 0x7FFFFFFF, 0x7FFFFFFFFFFF, BinaryValue(0x7FFFFFFFFFFFFF, len(dut.stream_in_data_wide), bigEndian=False) ]: dut.stream_in_data_wide <= value yield RisingEdge(dut.clk) _compare(value) dut.stream_in_data_wide = value yield RisingEdge(dut.clk) _compare(value)
def run_file(dut, filepath): """Load and run Dat file in processor.""" cocotb.fork(clock_gen(dut.clk)) clkedge = RisingEdge(dut.clk) dut.reset <= 1 dut.loadedAdr <= 0 yield clkedge file = open(filepath, "r") data = file.read().strip() file.close() # print(data) for i, line in enumerate(data.split("\n")): dut.reset <= 0 vec = BinaryValue() vec.integer = int(line, 16) dut.memory.ram[i].setimmediatevalue(vec) if line == "0000": break cycles = 0 last_pc = 0 pcs_in_row = 0 while pcs_in_row < 10: # and (cycles < 5000): yield clkedge pc = dut.proc.dp.progcount.count.value.integer if last_pc == pc: pcs_in_row += 1 else: pcs_in_row = 0 last_pc = pc # print("RA", dut.proc.dp.regFile.RAM[0]) # print("T0", dut.proc.dp.regFile.RAM[1]) # print("T1", dut.proc.dp.regFile.RAM[2]) # print("SP", dut.proc.dp.regFile.RAM[15]) # print("BP", dut.proc.dp.regFile.RAM[14]) # print("PP", dut.proc.dp.regFile.RAM[13]) # print("RAM <sp>", dut.memory.ram[57344]) # print("RAM <sp-1>", dut.memory.ram[57343]) # print("RAM <sp-2>", dut.memory.ram[57342]) # print("RAM <sp-3>", dut.memory.ram[57341]) # print("RAM <pp>", dut.memory.ram[49152]) # print("RAM <pp-1>", dut.memory.ram[49151]) # print("RAM <ffff>", dut.memory.ram[65535]) # print("RAM <fffd>", dut.memory.ram[65533]) # print("RAM <fffb>", dut.memory.ram[65531]) # print("---> pc", pc, ":", data.split("\n")[pc]) cycles += 1 # print("prog over ----------") cycles -= 10 # remove cycles from in loop print("took {} / 1 = {} cycles to complete...".format(cycles-346, (cycles-346)/1)) return dut.proc.dp.regFile.RAM[0].value.integer
def __dout(self): while True: yield RisingEdge(self.clk) if any((c in self.address.value.binstr) for c in 'UX'): self.dout <= BinaryValue('U', len(self.address.value)) else: self.dout <= self.array[self.address.value.integer]
def run_dut(dut, in_data, out_count): # pragma: no cover # dut.enable = 1 # dut.in0 = 0 cocotb.fork(Clock(dut.clk, 5000).start()) yield reset(dut) ret = [] # print('Input data: {}'.format(in_data)) count = 0 for x in tqdm(in_data, file=sys.stderr): # print(count) count += 1 # put input # print('Processing slice: {}'.format(x)) for i, xi in enumerate(x): # print('Set {} to {}'.format('in' + str(i), str(xi))) v = getattr(dut, 'in' + str(i)) bval = BinaryValue(str(xi), len(xi)) v.setimmediatevalue(bval) yield RisingEdge(dut.clk) # collect output tmp = [] for i in range(out_count): var = 'out' + str(i) # val = getattr(dut, var).value.signed_integer val = str(getattr(dut, var).value) # print(val) tmp.append(val) ret.append(tmp) # print('Finish, ret: {}'.format(ret)) raise ReturnValue(ret)
def __init__(self, tb=None, cacheLineOut=None, cacheHit=0, cacheMiss=0, oldAddress=None): """For expected transactions, value 'None' means don't care. tb must be an instance of the Testbench class.""" if cacheLineOut is not None and isinstance(cacheLineOut, int): cacheLineOut = BinaryValue(cacheLineOut, tb.data_bits, False) if cacheHit is not None and isinstance(cacheHit, int): cacheHit = BinaryValue(cacheHit, 1) if cacheMiss is not None and isinstance(cacheMiss, int): cacheMiss = BinaryValue(cacheMiss, 1) if oldAddress is not None and isinstance(oldAddress, int): oldAddress = BinaryValue(oldAddress, tb.address_bits, False) self.value = (cacheLineOut, cacheHit, cacheMiss, oldAddress)
async def issue_142_overflow_error(dut): """Tranparently convert ints too long to pass through the GPI interface natively into BinaryValues""" cocotb.start_soon(Clock(dut.clk, 10, "ns").start()) def _compare(value): assert int(dut.stream_in_data_wide.value) == int( value), "Expecting 0x{:x} but got 0x{:x} on {}".format( int(value), int(dut.stream_in_data_wide.value), str(dut.stream_in_data_wide)) # Wider values are transparently converted to BinaryValues for value in [ 0, 0x7FFFFFFF, 0x7FFFFFFFFFFF, BinaryValue(0x7FFFFFFFFFFFFF, len(dut.stream_in_data_wide), bigEndian=False), ]: dut.stream_in_data_wide.value = value await RisingEdge(dut.clk) _compare(value) dut.stream_in_data_wide.value = value await RisingEdge(dut.clk) _compare(value)
async def check_fft(dut, y, test_num): # threshold = 10 # maximum difference between expected and actual threshold = 100 # maximum difference between expected and actual full_sig = np.zeros((N_FRAMES, RFFT_LEN), dtype=np.cdouble) for i in range(N_FRAMES): while (dut.aco_inst.fft_valid_o != 1): # wait until output is valid await FallingEdge(dut.clk_i) sig = np.zeros(RFFT_LEN, dtype=np.cdouble) for j in range(RFFT_LEN): await Timer(1, units='us') binstr = dut.aco_inst.fft_data_o.value.get_binstr() split_binstr = [binstr[:21], binstr[21:]] output_arr = [BinaryValue(x).signed_integer for x in split_binstr] sig[j] = output_arr[0] + output_arr[1] * 1j if j == RFFT_LEN - 1: assert dut.aco_inst.fft_last_o == 1 else: assert dut.aco_inst.power_spectrum_last_o == 0 await FallingEdge(dut.clk_i) absmax = np.abs(y[i, :] - sig).max() assert absmax <= threshold, ( 'FFT: deviation of {} exceeds threshold'.format(absmax)) full_sig[i, :] = sig print('\r{}/50'.format(i + 1), end='') percent_err = np.abs(full_sig - y) / np.abs(y).max() * 100 print('FFT: max percent error: {:.03f}%'.format(percent_err.max())) print('FFT: received expected output.') plot_features((y, full_sig), test_num, '1FFT') return full_sig
def hash_init(self, sha_type): sha_type = sha_type.integer # shift = int(WIDTH_WORDS/2) if (~sha_type & 0x2) else 0 shift = 0 H_out_next = [BinaryValue(h_init[sha_type][i] << (shift)) for i in range(N_WORDS)] H_out_next.reverse() return H_out_next
def test_backpressure(dut): ''' Perform a backpressure test. ''' TOTAL_WORDS = 1024 TOTAL_TIME_NS = TOTAL_WORDS * 40 # Create and start the test environment, however configure the read interfaces # such that back pressure occurs. te = TestEnvironment(dut, wrStartAllow=AlwaysAllow, rdStartAllow=NeverAllow) yield te.start() # Write the words for each_word in range(TOTAL_WORDS): te.write( BinaryValue(value=randint(0, (1 << te.W) - 1), bits=te.W, bigEndian=False)) # Wait some time before enabling read interfaces. yield Timer(TOTAL_TIME_NS // 2, "ns") te.setRdAllow(AlwaysAllow) yield Timer(TOTAL_TIME_NS // 2, "ns")
def __init__(self, entity): BusDriver.__init__(self, entity, "", entity.CLK_BX) self.cmd = BinaryValue(bits=len(self.bus.CMD)) self.cmd <= 0 self.bus.TRIG_EXT <= 0 self.bus.CMD <= self.cmd
def __init__(self, dut): """ Setup testbench. """ # Some internal state self.dut = dut self.stopped = False # Create input driver and output monitor self.input_drv = BitDriver(dut.enable, dut.clk, input_gen()) dut.enable <= 0 self.output_mon = BitMonitor("output", dut.impulse, dut.clk) # Create a scoreboard on the outputs self.expected_output = [BinaryValue(0, 1)] self.scoreboard = Scoreboard(dut) self.scoreboard.add_interface(self.output_mon, self.expected_output) # Reconstruct the input transactions from the pins # and send them to our 'model' self.input_mon = BitMonitor("input", dut.enable, dut.clk, callback=self.model) # Model variables self.triggered = False self.counter = 0
async def run_test(dut, data_in=None, codec='sha256', backpressure_inserter=None): # dut._log.setLevel(logging.DEBUG) dut.m_axis_tready <= 0; """ Setup testbench and run a test. """ clock = Clock(dut.axis_aclk, 10, units="ns") # Create a 10ns period clock on port clk cocotb.fork(clock.start()) # Start the clock tb = WtUnitTB(dut, codec, True) await tb.reset() dut.m_axis_tready <= 1; if backpressure_inserter is not None: tb.backpressure.start(backpressure_inserter()) # Send in the packets for transaction in data_in(Sha.blocks512(codec)): tb.s_axis.bus.tuser <= BinaryValue(80*'0'+little_endian_codec(codec)+32*'0') await tb.s_axis.send(transaction) # Wait for last transmission while not ( dut.m_axis_tlast.value and dut.m_axis_tvalid.value and dut.m_axis_tready.value): await RisingEdge(dut.axis_aclk) await RisingEdge(dut.axis_aclk) dut._log.info("DUT testbench finished!") raise tb.scoreboard.result
def value(self) -> BinaryValue: binstr = self._handle.get_signal_val_binstr() # Skip BinaryValue.assign() as we know we are using a binstr result = BinaryValue(n_bits=len(binstr)) # Skip the permitted characters check as we trust the simulator result._set_trusted_binstr(binstr) return result
def __init__(self, nbytes, interleaved=True): """ Args: nbytes (int): The number of bytes transferred per clock cycle (usually 8 for SDR, 4 for DDR) Kwargs: interleaved (bool): The arrangement of control bits on the bus. If interleaved we have a bus with 9-bits per byte, the control bit being the 9th bit of each byte. If not interleaved then we have a byte per data byte plus a control bit per byte in the MSBs. """ self._value = BinaryValue(bits=nbytes * 9, bigEndian=False) self._integer = long(0) self._interleaved = interleaved self._nbytes = nbytes # Default to idle for i in range(nbytes): self[i] = (0x07, True)
async def run_test(dut, codec=0x12, data_in=None, backpressure_inserter=None): dut._log.info(f"Init testbench with codec={codec}") dut.m_axis_tready <= 0 #dut._log.setLevel(logging.DEBUG) """ Setup testbench and run a test. """ clock = Clock(dut.axis_aclk, 10, units="ns") # Create a 10ns period clock on port clk cocotb.fork(clock.start()) # Start the clock tb = HcuTb(dut, codec) await tb.reset() dut.m_axis_tready <= 1 if backpressure_inserter is not None: tb.backpressure.start(backpressure_inserter()) dut._log.info('Send Wt parsed from message') # Send in the packets for transaction in format_wt(codec): tb.s_axis.bus.tuser <= BinaryValue(80*'0'+little_endian_codec(codec)+32*'0') #transaction = format_wt_message(transaction, sha_type=sha_type) await tb.s_axis.send(transaction) dut._log.info('Wait for last outgoing transaction to be monitored') # Wait for last transmission while not (dut.m_axis_tlast.value and dut.m_axis_tvalid.value and dut.m_axis_tready.value): await RisingEdge(dut.axis_aclk) for _ in range(3): await RisingEdge(dut.axis_aclk) dut._log.info("DUT testbench finished!") raise tb.scoreboard.result
async def write( self, address: int, value: int, byte_enable: Optional[int] = None, address_latency: int = 0, data_latency: int = 0, sync: bool = True ) -> BinaryValue: """Write a value to an address. Args: address: The address to write to. value: The data value to write. byte_enable: Which bytes in value to actually write. Defaults to None (write all bytes). address_latency: Delay before setting the address (in clock cycles). Default is no delay. data_latency: Delay before setting the data value (in clock cycles). Default is no delay. sync: Wait for rising edge on clock initially. Defaults to True. Returns: The write response value. Raises: ValueError: If any of the input parameters is invalid. AXIProtocolError: If write response from AXI is not ``OKAY``. """ if isinstance(value, collections.abc.Sequence): raise ValueError("AXI4-Lite does not support burst transfers") await super().write( address=address, value=value, size=None, burst=AXIBurst.INCR, byte_enable=byte_enable, address_latency=address_latency, data_latency=data_latency, sync=sync) # Needed for backwards compatibility return BinaryValue(value=AXIxRESP.OKAY.value, n_bits=2)
def send_bytes(dut, bytes, factor, is_z=True): yield Timer(1000) factor += 1 for byte in bytes: dut.bus_a = 0 yield Timer(factor * CLK_PERIOD) for i in range(0, 8): if byte & 0x01 == 0: dut.bus_a = 0 else: dut.bus_a = BinaryValue("z") if is_z else 1 yield Timer(factor * CLK_PERIOD) byte = byte >> 1 dut.bus_a = BinaryValue("z") if is_z else 1 yield Timer(factor * CLK_PERIOD) dut.bus_a = BinaryValue("z")
async def _drive(self, we, adr, datwr, sel, idle): """ Drive the Wishbone Master Out Lines """ clkedge = RisingEdge(self.clock) if self.busy: # insert requested idle cycles if idle is not None: idlecnt = idle while idlecnt > 0: idlecnt -= 1 await clkedge # drive outputs self.bus.stb.value = 1 self.bus.adr.value = adr if hasattr(self.bus, "sel"): self.bus.sel.value = sel if sel is not None else BinaryValue( "1" * len(self.bus.sel)) self.bus.datwr.value = datwr self.bus.we.value = we await clkedge #deal with flow control (pipelined wishbone) stalled = await self._wait_stall() #append operation and meta info to auxiliary buffer self._aux_buf.append( WBAux(sel, adr, datwr, stalled, idle, self._clk_cycle_count)) await self._wait_ack() self.bus.we.value = 0 else: self.log.error("Cannot drive the Wishbone bus outside a cycle!")
async def drive_transaction(self, rw): if rw.read is False: wdata = BinaryValue(value=rw.data,n_bits=self.n_bits) await RisingEdge(self.dut.clk) await Timer(0) self.dut.we <= 1 self.dut.data_in <= wdata self.dut.addr_in <= rw.addr for i in range(2): await RisingEdge(self.dut.clk) await Timer(0) self.dut.we <= 0 uvm_info("REG_DRIVER WRITE", "Wrote value to DUT: " + str(rw.data) + ' addr:' + str(rw.addr), UVM_LOW) else: await RisingEdge(self.dut.clk) self.dut.addr_in <= rw.addr self.dut.read <= 0x1 await RisingEdge(self.dut.clk) rw.data = self.dut.data_out.value.integer await RisingEdge(self.dut.clk) self.dut.read <= 0x0 uvm_info("REG_DRIVER READ", "Read value from DUT: " + str(rw.data) + ' addr:' + str(rw.addr), UVM_LOW)
def test_binary_value(dut): """ Test out the cocotb supplied BinaryValue class for manipulating values in a style familiar to rtl coders. """ vec = BinaryValue(value=0, n_bits=16) dut._log.info("Checking read access to the n_bits property") if vec.n_bits != 16: raise TestFailure("n_bits is not set correctly - expected %d, got %d" % (16, vec.n_bits)) dut._log.info("Checking default endianness is Big Endian.") if not vec.big_endian: raise TestFailure("The default endianness is Little Endian - was expecting Big Endian.") if vec.integer != 0: raise TestFailure("Expecting our BinaryValue object to have the value 0.") dut._log.info("Checking single index assignment works as expected on a Little Endian BinaryValue.") vec = BinaryValue(value=0, bits=16, bigEndian=False) if vec.big_endian: raise TestFailure("Our BinaryValue object is reporting it is Big Endian - was expecting Little Endian.") for x in range(vec.n_bits): vec[x] = '1' dut._log.info("Trying vec[%s] = 1" % x) expected_value = 2**(x+1) - 1 if vec.integer != expected_value: raise TestFailure("Failed on assignment to vec[%s] - expecting %s - got %s" % (x, expected_value, vec.integer)) if vec[x] != 1: raise TestFailure("Failed on index compare on vec[%s] - expecting 1 - got %s" % (x, vec[x])) dut._log.info("vec = 'b%s" % vec.binstr) dut._log.info("Checking slice assignment works as expected on a Little Endian BinaryValue.") if vec.integer != 65535: raise TestFailure("Expecting our BinaryValue object to be 65535 after the end of the previous test.") vec[7:0] = '00110101' if vec.binstr != '1111111100110101': raise TestFailure("Set lower 8-bits to 00110101 but read back %s" % vec.binstr) if vec[7:0].binstr != '00110101': raise TestFailure("Set lower 8-bits to 00110101 but read back %s from vec[7:0]" % vec[7:0].binstr) dut._log.info("vec[7:0] = 'b%s" % vec[7:0].binstr) dut._log.info("vec[15:8] = 'b%s" % vec[15:8].binstr) dut._log.info("vec = 'b%s" % vec.binstr) yield Timer(100) # Make it do something with time
async def test_cb(dut): clock = Clock(dut.scan_clk, 10000, units="ps") cocotb.fork(clock.start()) width = dut.CHANNEL_ONEWAY_WIDTH.value dut._log.info("Found CB with channel oneway width %d" % (width)) # random config generation out_config = [random.randint(0, 3) for i in range(2)] out_config_binary = int_list_to_bitstream(out_config, 2) # random input generation tracks_0 = random.randint(0, 2 ** width - 1) tracks_1 = random.randint(0, 2 ** width - 1) bitstream = out_config_binary total_scan_size = len(bitstream) print(bitstream) # scan in config dut.scan_en <= 1 for i in range(total_scan_size): # push the last value into the scan chain # scan in MSB first dut.scan_in <= bitstream.pop(-1) await RisingEdge(dut.scan_clk) dut.scan_en <= 0 dut.tracks_0 <= tracks_0 dut.tracks_1 <= tracks_1 await Timer(100, units='ps') out_0 = dut.out_0.value out_1 = dut.out_1.value # convert int to cocotb BinaryValue for easy bit select tracks_0 = BinaryValue(tracks_0, n_bits=4, bigEndian=False) tracks_1 = BinaryValue(tracks_1, n_bits=4, bigEndian=False) golden_out_0 = {0: tracks_0[0], 1: tracks_1[0], 2: tracks_0[2], 3: tracks_1[2]} golden_out_1 = {0: tracks_0[1], 1: tracks_1[1], 2: tracks_0[3], 3: tracks_1[3]} assert out_0 == golden_out_0[out_config[0]], "out_0 expecting %d, getting %d" % (golden_out_0[out_config[0]], out_0) assert out_1 == golden_out_1[out_config[1]], "out_1 expecting %d, getting %d" % (golden_out_1[out_config[1]], out_1)
def make_meta(pkts_in): meta_in = [] for p in pkts_in: meta = Metadata(pkt_len=len(p), dst_port=1) tuser = BinaryValue(bits=len(meta) * 8, bigEndian=False) tuser.set_buff(str(meta)) meta_in.append(tuser) return meta_in