def _create_pkgs(dut): writer_signal_aliases = {'debug_in': 'in', 'debug_in_ready': 'in_ready'} writer = NocDiWriter(dut, dut.clk, writer_signal_aliases) for i in range(STRESS_TEST_PKG_COUNT): is_reg_pkg = random.randint(0, 1) pkg = DiPacket() if is_reg_pkg: pkg.set_contents(dest=1, src=0, type=DiPacket.TYPE.REG.value, type_sub=DiPacket.TYPE_SUB.REQ_WRITE_REG_16.value, payload=[0xdead]) else: payload_len = random.randint(0, 5) payload = [] for _ in range(payload_len): payload.append(random.randint(0, 2**16 - 1)) pkg.set_contents(dest=1, src=0, type=DiPacket.TYPE.EVENT.value, type_sub=0x3, payload=payload) # wait a random number of cycles before sending the packet for s in range(random.randint(0, 100)): yield RisingEdge(dut.clk) _sent_pkgs.append(pkg) yield writer.send_packet(pkg)
def _trigger_reg_wr_req_err(dut, dest, src, word_width, regaddr, value): """ Sends a register write request to the module and checks if an error response gets returned. """ tx_packet = DiPacket() rx_packet = DiPacket() writer = NocDiWriter(dut, dut.clk) reader = NocDiReader(dut, dut.clk) if word_width == 16: type_sub = DiPacket.TYPE_SUB.REQ_WRITE_REG_16.value words = 1 elif word_width == 32: type_sub = DiPacket.TYPE_SUB.REQ_WRITE_REG_32.value words = 2 elif word_width == 64: type_sub = DiPacket.TYPE_SUB.REQ_WRITE_REG_64.value words = 4 elif word_width == 128: type_sub = DiPacket.TYPE_SUB.REQ_WRITE_REG_128.value words = 8 else: raise TestFailure("An invalid register width parameter was chosen! (%d)" %\ word_width) # Assemble payload of REG debug packet payload = [regaddr] for w in range(0, words): payload.append((value >> ((words - 1 - w) * 16)) & 0xFFFF) tx_packet.set_contents(dest=dest, src=src, type=DiPacket.TYPE.REG.value, type_sub=type_sub, payload=payload) yield writer.send_packet(tx_packet) rx_packet = yield reader.receive_packet(set_ready=True) if not rx_packet: raise TestFailure("No response packet received!") if rx_packet.type_sub != DiPacket.TYPE_SUB.RESP_WRITE_REG_ERROR.value: raise TestFailure( "Register write did not return RESP_WRITE_REG_ERROR " "when writing 0x%x to register 0x%x of module 0x%x." % (value, regaddr, dest))
def test_only_regaccess_ready(dut): """ Check if a register access packet passes through, even though the bypass ready signal is tied to 0. """ yield _init_dut(dut) dut.out_reg_ready <= 1 dut.out_bypass_ready <= 0 reg_reader_signal_aliases = { 'debug_out': 'out_reg', 'debug_out_ready': 'out_reg_ready' } reg_reader = NocDiReader(dut, dut.clk, reg_reader_signal_aliases) writer_signal_aliases = {'debug_in': 'in', 'debug_in_ready': 'in_ready'} writer = NocDiWriter(dut, dut.clk, writer_signal_aliases) reg_pkg = DiPacket() reg_pkg.set_contents(dest=1, src=0, type=DiPacket.TYPE.REG.value, type_sub=DiPacket.TYPE_SUB.REQ_WRITE_REG_16.value, payload=[0xdead]) # send a register write packet to the DUT write_thread = cocotb.fork(writer.send_packet(reg_pkg)) # ensure that the bypass valid signal isn't asserted checker_thread = cocotb.fork( _assert_signal_stays_low(dut.clk, dut.out_bypass.valid)) # get packet on reg output rcv_pkg = yield reg_reader.receive_packet() yield write_thread.join() checker_thread.kill() if not rcv_pkg: raise TestFailure("Register access packet not routed to output.") if not rcv_pkg.equal_to(dut, reg_pkg): raise TestFailure("Data corruption.")
def test_event_pkg(dut): """ Check if a register access packet passes through """ yield _init_dut(dut) dut.out_reg_ready <= 1 dut.out_bypass_ready <= 1 bypass_reader_signal_aliases = { 'debug_out': 'out_bypass', 'debug_out_ready': 'out_bypass_ready' } bypass_reader = NocDiReader(dut, dut.clk, bypass_reader_signal_aliases) writer_signal_aliases = {'debug_in': 'in', 'debug_in_ready': 'in_ready'} writer = NocDiWriter(dut, dut.clk, writer_signal_aliases) event_pkg = DiPacket() event_pkg.set_contents(dest=1, src=0, type=DiPacket.TYPE.EVENT.value, type_sub=0, payload=[0xdead]) # send an event packet to the DUT write_thread = cocotb.fork(writer.send_packet(event_pkg)) # ensure that the register output valid signal isn't asserted checker_thread = cocotb.fork( _assert_signal_stays_low(dut.clk, dut.out_reg.valid)) # get packet on bypass output rcv_pkg = yield bypass_reader.receive_packet() yield write_thread.join() checker_thread.kill() if not rcv_pkg: raise TestFailure("Event access packet not routed to output.") if not rcv_pkg.equal_to(dut, event_pkg): raise TestFailure("Data corruption.")
def _trigger_reg_rd_req_err(dut, dest, src, word_width, regaddr): """ Sends a register read request to the module and checks if an error response gets returned. """ tx_packet = DiPacket() rx_packet = DiPacket() writer = NocDiWriter(dut, dut.clk) reader = NocDiReader(dut, dut.clk) if word_width == 16: type_sub = DiPacket.TYPE_SUB.REQ_READ_REG_16.value elif word_width == 32: type_sub = DiPacket.TYPE_SUB.REQ_READ_REG_32.value elif word_width == 64: type_sub = DiPacket.TYPE_SUB.REQ_READ_REG_64.value elif word_width == 128: type_sub = DiPacket.TYPE_SUB.REQ_READ_REG_128.value else: raise TestFailure("An invalid register width parameter was chosen! (%d)" %\ word_width) tx_packet.set_contents(dest=dest, src=src, type=DiPacket.TYPE.REG.value, type_sub=type_sub, payload=[regaddr]) yield writer.send_packet(tx_packet) rx_packet = yield reader.receive_packet(set_ready=True) if not rx_packet: raise TestFailure("No response packet received!") if rx_packet.type_sub != DiPacket.TYPE_SUB.RESP_READ_REG_ERROR.value: raise TestFailure("Register read did not return RESP_READ_REG_ERROR " "when reading from register 0x%x of module 0x%x." % (regaddr, dest))
def _di_to_bus_tx(dut, num_transfers=500, max_delay=100, random_data=False): writer = NocDiWriter(dut, dut.clk); tx_packet = DiPacket(); for i in range(num_transfers): delay = random.randint(0, max_delay) for _ in range(delay): yield RisingEdge(dut.clk) data = random.randint(0, 255) if random_data else 0x42 tx_packet.set_contents(dest=MODULE_DI_ADDRESS, src=SENDER_DI_ADDRESS, type=DiPacket.TYPE.EVENT.value, type_sub=0, payload=[data]) yield writer.send_packet(tx_packet) yield RisingEdge(dut.clk) _di_to_bus_fifo.append(data)
class MamDiDriver: """ MAM memory transfer driver on the Debug Interconnect """ def __init__(self, entity, clock, di_writer=None, di_reader=None, MAX_PKT_LEN=12, MODULE_DI_ADDRESS=1, SENDER_DI_ADDRESS=0): self.entity = entity self.clock = clock self.log = entity._log self.MAX_PKT_LEN = MAX_PKT_LEN self.MODULE_DI_ADDRESS = MODULE_DI_ADDRESS self.SENDER_DI_ADDRESS = SENDER_DI_ADDRESS if di_writer: self.di_writer = di_writer else: self.di_writer = NocDiWriter(entity, clock) if di_reader: self.di_reader = di_reader else: self.di_reader = NocDiReader(entity, clock) def _create_mam_transfer(self, mem_transfer): """ Get MAM transfer bytearray representing the memory transfer """ mam_transfer = bytearray() we = (mem_transfer.operation == 'write') selsize = 0 if mem_transfer.burst: selsize = int(len(mem_transfer.data) / (mem_transfer.DW / 8)) else: selsize = mem_transfer.byteselect if selsize > 0xFF: raise TestFailure("selsize overflow detected") hdr0 = 0 hdr0 |= (we & 0x1) << 7 hdr0 |= (mem_transfer.burst & 0x1) << 6 hdr0 |= (mem_transfer.sync & 0x1) << 5 hdr1 = selsize mam_transfer.append(hdr0) mam_transfer.append(hdr1) mam_transfer.extend(mem_transfer.addr.to_bytes(int(mem_transfer.AW / 8), byteorder='big')) if mem_transfer.operation == 'write' and mem_transfer.data: mam_transfer.extend(mem_transfer.data) return mam_transfer def _create_di_pkgs(self, mam_transfer): """ Get DI packages representing the memory transfer """ pkgs = [] max_payload_bytes = (self.MAX_PKT_LEN - 3) * 2 number_of_pkgs = ceil(len(mam_transfer) / max_payload_bytes) b = 0 for _ in range(number_of_pkgs): pkg = DiPacket() pkg.dest = self.MODULE_DI_ADDRESS pkg.src = self.SENDER_DI_ADDRESS pkg.type = DiPacket.TYPE.EVENT.value pkg.type_sub = 0 for i in range(int(max_payload_bytes / 2)): payload_word = mam_transfer[b] << 8 | mam_transfer[b + 1] pkg.payload.append(payload_word) b += 2 if b >= len(mam_transfer): break pkgs.append(pkg) return pkgs @cocotb.coroutine def drive(self, mem_transfer): """ Drive the Debug Interconnect with a memory transfer and check the results """ # request mam_transfer_request = self._create_mam_transfer(mem_transfer) req_pkgs = self._create_di_pkgs(mam_transfer_request) for pkg in req_pkgs: yield self.di_writer.send_packet(pkg) # response if mem_transfer.operation == 'read': rcv_data = bytearray() while len(rcv_data) < len(mem_transfer.data): yield RisingEdge(self.clock) pkg = yield self.di_reader.receive_packet(set_ready=True) self.log.debug("Received memory read response " + str(pkg)) for payload_word in pkg.payload: rcv_data.extend(payload_word.to_bytes(2, byteorder='big')) # check received data if rcv_data != mem_transfer.data: raise TestFailure("Got invalid data.\nExpected: %s\nReceived: %s" % (mem_transfer.data.hex(), rcv_data.hex())) # for synchronous writes: check if we received a acknowledgement packet if mem_transfer.operation == 'write' and mem_transfer.sync: pkg = yield self.di_reader.receive_packet(set_ready=True) exp_sync_pkg = DiPacket() exp_sync_pkg.set_contents(self.SENDER_DI_ADDRESS, self.MODULE_DI_ADDRESS, DiPacket.TYPE.EVENT.value, 0, []) if not pkg.equal_to(self.entity, exp_sync_pkg): raise TestFailure( "Acknowledgement packet for sync write invalid.")