def user_logic(): while True: yield clk.posedge # handle completer request if not cq_sink.empty(): pkt = cq_sink.recv() tlp = pcie_us.TLP_us().unpack_us_cq(pkt, dw) print(tlp) if (tlp.fmt_type == pcie.TLP_IO_READ): print("IO read") cpl = pcie_us.TLP_us() cpl.set_completion(tlp, pcie_us.PcieId(0, 0, 0)) cpl.fmt_type = pcie.TLP_CPL_DATA region = tlp.bar_id addr = tlp.address & 0xffff # TODO offset = 0 start_offset = None mask = tlp.first_be # perform operation data = bytearray(4) for k in range(4): if mask & (1 << k): if start_offset is None: start_offset = offset else: if start_offset is not None and offset != start_offset: data[start_offset:offset] = regions[region][ addr + start_offset:addr + offset] start_offset = None offset += 1 if start_offset is not None and offset != start_offset: data[start_offset:offset] = regions[region][ addr + start_offset:addr + offset] cpl.set_data(data) cpl.byte_count = 4 cpl.length = 1 cc_source.send(cpl.pack_us_cc(dw)) elif (tlp.fmt_type == pcie.TLP_IO_WRITE): print("IO write") cpl = pcie_us.TLP_us() cpl.set_completion(tlp, pcie_us.PcieId(0, 0, 0)) region = tlp.bar_id addr = tlp.address & 0xffff # TODO offset = 0 start_offset = None mask = tlp.first_be # perform operation data = tlp.get_data() for k in range(4): if mask & (1 << k): if start_offset is None: start_offset = offset else: if start_offset is not None and offset != start_offset: regions[region][addr + start_offset:addr + offset] = data[ start_offset:offset] start_offset = None offset += 1 if start_offset is not None and offset != start_offset: regions[region][addr + start_offset:addr + offset] = data[start_offset:offset] cc_source.send(cpl.pack_us_cc(dw)) if (tlp.fmt_type == pcie.TLP_MEM_READ or tlp.fmt_type == pcie.TLP_MEM_READ_64): print("Memory read") # perform operation region = tlp.bar_id addr = tlp.address & 0xffff # TODO offset = 0 length = tlp.length # perform read data = regions[region][addr:addr + length * 4] # prepare completion TLP(s) n = 0 offset = 0 addr = tlp.address + offset length = tlp.length * 4 while n < length: cpl = pcie_us.TLP_us() cpl.set_completion(tlp, pcie_us.PcieId(0, 0, 0)) byte_length = length - n cpl.byte_count = byte_length byte_length = min( byte_length, 128 << dev.functions[0].max_payload_size ) # max payload size if byte_length > 128: byte_length -= (addr + byte_length) % 128 # RCB align byte_length = min(byte_length, 0x1000 - (addr & 0xfff)) # 4k align cpl.lower_address = addr & 0x7f cpl.set_data(data[offset + n:offset + n + byte_length]) print("Completion: %s" % (repr(cpl))) cc_source.send(cpl.pack_us_cc(dw)) n += byte_length addr += byte_length if (tlp.fmt_type == pcie.TLP_MEM_WRITE or tlp.fmt_type == pcie.TLP_MEM_WRITE_64): print("Memory write") # perform operation region = tlp.bar_id addr = tlp.address & 0xffff # TODO offset = 0 start_offset = None mask = tlp.first_be length = tlp.length # perform write data = tlp.get_data() # first dword for k in range(4): if mask & (1 << k): if start_offset is None: start_offset = offset else: if start_offset is not None and offset != start_offset: regions[region][addr + start_offset:addr + offset] = data[ start_offset:offset] start_offset = None offset += 1 if length > 1: # middle dwords if start_offset is None: start_offset = offset offset += length * 4 # last dword mask = tlp.last_be for k in range(4): if mask & (1 << k): if start_offset is None: start_offset = offset else: if start_offset is not None and offset != start_offset: regions[region][addr + start_offset:addr + offset] = data[ start_offset:offset] start_offset = None offset += 1 if start_offset is not None and offset != start_offset: regions[region][addr + start_offset:addr + offset] = data[start_offset:offset]
def check(): yield delay(100) yield clk.posedge rst.next = 1 yield clk.posedge rst.next = 0 yield clk.posedge yield delay(100) yield clk.posedge current_tag = 1 yield clk.posedge print("test 1: enumeration") current_test.next = 1 yield rc.enumerate(enable_bus_mastering=True, configure_msi=True) yield delay(100) yield clk.posedge print("test 2: IO and memory read/write") current_test.next = 2 yield from rc.io_write(0x80000000, bytearray(range(16)), 100) assert regions[3][0:16] == bytearray(range(16)) val = yield from rc.io_read(0x80000000, 16, 100) assert val == bytearray(range(16)) yield from rc.mem_write(0x80000000, bytearray(range(16)), 100) yield delay(100) assert regions[0][0:16] == bytearray(range(16)) val = yield from rc.mem_read(0x80000000, 16, 100) assert val == bytearray(range(16)) yield from rc.mem_write(0x8000000000000000, bytearray(range(16)), 100) yield delay(100) assert regions[1][0:16] == bytearray(range(16)) val = yield from rc.mem_read(0x8000000000000000, 16, 100) assert val == bytearray(range(16)) yield delay(100) # yield clk.posedge # print("test 3: Large read/write") # current_test.next = 3 # yield from rc.mem_write(0x8000000000000000, bytearray(range(256))*32, 100) # yield delay(100) # assert ep.read_region(1, 0, 256*32) == bytearray(range(256))*32 # val = yield from rc.mem_read(0x8000000000000000, 256*32, 100) # assert val == bytearray(range(256))*32 # yield delay(100) yield clk.posedge print("test 4: DMA") current_test.next = 4 #yield ep.io_write(io_base, bytearray(range(16)), 100) data = bytearray(range(16)) addr = io_base n = 0 while n < len(data): tlp = pcie_us.TLP_us() tlp.fmt_type = pcie.TLP_IO_WRITE tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0) tlp.tag = current_tag first_pad = addr % 4 byte_length = min(len(data) - n, 4 - first_pad) tlp.set_be_data(addr, data[n:n + byte_length]) tlp.address = addr & ~3 current_tag = (current_tag % 31) + 1 rq_source.send(tlp.pack_us_rq(dw)) yield rc_sink.wait(100) pkt = rc_sink.recv() if not pkt: raise Exception("Timeout") cpl = pcie_us.TLP_us().unpack_us_rc(pkt, dw) if cpl.status != pcie.CPL_STATUS_SC: raise Exception("Unsuccessful completion") n += byte_length addr += byte_length assert io_data[0:16] == bytearray(range(16)) #val = yield from ep.io_read(io_base, 16, 100) length = 16 data = b'' addr = io_base n = 0 while n < length: tlp = pcie_us.TLP_us() tlp.fmt_type = pcie.TLP_IO_READ tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0) tlp.tag = current_tag first_pad = addr % 4 byte_length = min(length - n, 4 - first_pad) tlp.set_be(addr, byte_length) tlp.address = addr & ~3 current_tag = (current_tag % 31) + 1 rq_source.send(tlp.pack_us_rq(dw)) yield rc_sink.wait(100) pkt = rc_sink.recv() if not pkt: raise Exception("Timeout") cpl = pcie_us.TLP_us().unpack_us_rc(pkt, dw) if cpl.status != pcie.CPL_STATUS_SC: raise Exception("Unsuccessful completion") else: d = struct.pack('<L', cpl.data[0]) data += d[first_pad:] n += byte_length addr += byte_length data = data[:length] assert val == bytearray(range(16)) #yield ep.mem_write(mem_base, bytearray(range(16)), 100) data = bytearray(range(16)) addr = io_base n = 0 while n < len(data): tlp = pcie_us.TLP_us() if addr > 0xffffffff: tlp.fmt_type = pcie.TLP_MEM_WRITE_64 else: tlp.fmt_type = pcie.TLP_MEM_WRITE tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0) tlp.tag = current_tag first_pad = addr % 4 byte_length = len(data) - n byte_length = min(byte_length, (128 << dev.functions[0].max_payload_size) - first_pad) # max payload size byte_length = min(byte_length, 0x1000 - (addr & 0xfff)) # 4k align tlp.set_be_data(addr, data[n:n + byte_length]) tlp.address = addr & ~3 current_tag = (current_tag % 31) + 1 rq_source.send(tlp.pack_us_rq(dw)) n += byte_length addr += byte_length yield delay(100) assert mem_data[0:16] == bytearray(range(16)) #val = yield from ep.mem_read(mem_base, 16, 100) length = 16 data = b'' addr = mem_base n = 0 while n < length: tlp = pcie_us.TLP_us() if addr > 0xffffffff: tlp.fmt_type = pcie.TLP_MEM_READ_64 else: tlp.fmt_type = pcie.TLP_MEM_READ tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0) tlp.tag = current_tag first_pad = addr % 4 byte_length = length - n byte_length = min(byte_length, (128 << dev.functions[0].max_read_request_size) - first_pad) # max read request size byte_length = min(byte_length, 0x1000 - (addr & 0xfff)) # 4k align tlp.set_be(addr, byte_length) tlp.address = addr & ~3 current_tag = (current_tag % 31) + 1 rq_source.send(tlp.pack_us_rq(dw)) m = 0 while m < byte_length: yield rc_sink.wait(100) pkt = rc_sink.recv() if not pkt: raise Exception("Timeout") cpl = pcie_us.TLP_us().unpack_us_rc(pkt, dw) if cpl.status != pcie.CPL_STATUS_SC: raise Exception("Unsuccessful completion") else: dw_len = cpl.length if dw_len == 0: dw_len = 1024 d = bytearray() for k in range(dw_len): d.extend(struct.pack('<L', cpl.data[k])) offset = cpl.lower_address & 3 data += d[offset:offset + cpl.byte_count] m += len(d) - offset n += byte_length addr += byte_length assert val == bytearray(range(16)) yield delay(100) yield clk.posedge print("test 5: MSI") current_test.next = 5 yield user_clk.posedge cfg_interrupt_msi_int.next = 1 << 4 yield user_clk.posedge cfg_interrupt_msi_int.next = 0 yield rc.msi_get_signal(dev.functions[0].get_id(), 4) yield delay(100) raise StopSimulation
def check(): yield delay(100) yield clk.posedge rst.next = 1 yield clk.posedge rst.next = 0 yield clk.posedge yield delay(100) yield clk.posedge # testbench stimulus cur_tag = 1 completer_id.next = int(pcie_us.PcieId(4, 5, 6)) yield clk.posedge print("test 1: baseline") current_test.next = 1 data = axil_ram_inst.read_mem(0, 32) for i in range(0, len(data), 16): print(" ".join( ("{:02x}".format(c) for c in bytearray(data[i:i + 16])))) yield delay(100) yield clk.posedge print("test 2: memory write") current_test.next = 2 tlp = pcie_us.TLP_us() tlp.fmt_type = pcie_us.TLP_MEM_WRITE tlp.requester_id = pcie_us.PcieId(1, 2, 3) tlp.tag = cur_tag tlp.tc = 0 tlp.set_be_data(0x0000, b'\x11\x22\x33\x44') tlp.address = 0x0000 cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH)) yield delay(100) data = axil_ram_inst.read_mem(0, 32) for i in range(0, len(data), 16): print(" ".join( ("{:02x}".format(c) for c in bytearray(data[i:i + 16])))) assert axil_ram_inst.read_mem(0, 4) == b'\x11\x22\x33\x44' assert not status_error_cor_asserted assert not status_error_uncor_asserted cur_tag = (cur_tag + 1) % 32 yield delay(100) yield clk.posedge print("test 3: IO write") current_test.next = 3 tlp = pcie_us.TLP_us() tlp.fmt_type = pcie_us.TLP_IO_WRITE tlp.requester_id = pcie_us.PcieId(1, 2, 3) tlp.tag = cur_tag tlp.tc = 0 tlp.set_be_data(0x0000, b'\x11\x22\x33\x44') tlp.address = 0x0000 cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH)) yield cc_sink.wait(500) pkt = cc_sink.recv() rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH) print(rx_tlp) assert rx_tlp.status == pcie_us.CPL_STATUS_SC assert rx_tlp.tag == cur_tag assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6) data = axil_ram_inst.read_mem(0, 32) for i in range(0, len(data), 16): print(" ".join( ("{:02x}".format(c) for c in bytearray(data[i:i + 16])))) assert axil_ram_inst.read_mem(0, 4) == b'\x11\x22\x33\x44' assert not status_error_cor_asserted assert not status_error_uncor_asserted cur_tag = (cur_tag + 1) % 32 yield delay(100) yield clk.posedge print("test 4: memory read") current_test.next = 4 tlp = pcie_us.TLP_us() tlp.fmt_type = pcie_us.TLP_MEM_READ tlp.requester_id = pcie_us.PcieId(1, 2, 3) tlp.tag = cur_tag tlp.tc = 0 tlp.length = 1 tlp.set_be(0x0000, 4) tlp.address = 0x0000 cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH)) yield cc_sink.wait(500) pkt = cc_sink.recv() rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH) print(rx_tlp) data = rx_tlp.get_data() print(data) assert data == b'\x11\x22\x33\x44' assert rx_tlp.status == pcie_us.CPL_STATUS_SC assert rx_tlp.tag == cur_tag assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6) assert not status_error_cor_asserted assert not status_error_uncor_asserted cur_tag = (cur_tag + 1) % 32 yield delay(100) yield clk.posedge print("test 5: IO read") current_test.next = 5 tlp = pcie_us.TLP_us() tlp.fmt_type = pcie_us.TLP_IO_READ tlp.requester_id = pcie_us.PcieId(1, 2, 3) tlp.tag = cur_tag tlp.tc = 0 tlp.length = 1 tlp.set_be(0x0000, 4) tlp.address = 0x0000 cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH)) yield cc_sink.wait(500) pkt = cc_sink.recv() rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH) print(rx_tlp) data = rx_tlp.get_data() print(data) assert data == b'\x11\x22\x33\x44' assert rx_tlp.status == pcie_us.CPL_STATUS_SC assert rx_tlp.tag == cur_tag assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6) assert not status_error_cor_asserted assert not status_error_uncor_asserted cur_tag = (cur_tag + 1) % 32 yield delay(100) yield clk.posedge print("test 6: various writes") current_test.next = 6 for length in range(1, 5): for offset in range(4, 8 - length + 1): axil_ram_inst.write_mem(256 * (16 * offset + length), b'\xAA' * 32) tlp = pcie_us.TLP_us() tlp.fmt_type = pcie_us.TLP_MEM_WRITE tlp.requester_id = pcie_us.PcieId(1, 2, 3) tlp.tag = cur_tag tlp.tc = 0 tlp.set_be_data(256 * (16 * offset + length) + offset, b'\x11\x22\x33\x44'[0:length]) tlp.address = 256 * (16 * offset + length) + offset cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH)) yield delay(100) data = axil_ram_inst.read_mem(256 * (16 * offset + length), 32) for i in range(0, len(data), 16): print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i + 16])))) assert axil_ram_inst.read_mem( 256 * (16 * offset + length) + offset, length) == b'\x11\x22\x33\x44'[0:length] assert axil_ram_inst.read_mem( 256 * (16 * offset + length) + offset - 1, 1) == b'\xAA' assert axil_ram_inst.read_mem( 256 * (16 * offset + length) + offset + length, 1) == b'\xAA' assert not status_error_cor_asserted assert not status_error_uncor_asserted cur_tag = (cur_tag + 1) % 32 yield delay(100) yield clk.posedge print("test 7: various reads") current_test.next = 7 for length in range(1, 5): for offset in range(4, 8 - length + 1): tlp = pcie_us.TLP_us() tlp.fmt_type = pcie_us.TLP_MEM_READ tlp.requester_id = pcie_us.PcieId(1, 2, 3) tlp.tag = cur_tag tlp.tc = 0 tlp.length = 1 tlp.set_be(256 * (16 * offset + length) + offset, length) tlp.address = 256 * (16 * offset + length) + offset cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH)) yield cc_sink.wait(500) pkt = cc_sink.recv() rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH) print(rx_tlp) data = rx_tlp.get_data() print(data) assert data == b'\xAA' * (offset - 4) + b'\x11\x22\x33\x44'[ 0:length] + b'\xAA' * (8 - offset - length) assert rx_tlp.status == pcie_us.CPL_STATUS_SC assert rx_tlp.tag == cur_tag assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6) assert not status_error_cor_asserted assert not status_error_uncor_asserted cur_tag = (cur_tag + 1) % 32 yield delay(100) yield clk.posedge print("test 8: bad memory write") current_test.next = 8 tlp = pcie_us.TLP_us() tlp.fmt_type = pcie_us.TLP_MEM_WRITE tlp.requester_id = pcie_us.PcieId(1, 2, 3) tlp.tag = cur_tag tlp.tc = 0 tlp.set_be_data(0x0000, bytearray(range(64))) tlp.address = 0x0000 cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH)) yield delay(100) assert not status_error_cor_asserted assert status_error_uncor_asserted status_error_uncor_asserted.next = 0 cur_tag = (cur_tag + 1) % 32 yield delay(100) yield clk.posedge print("test 9: bad memory read") current_test.next = 9 tlp = pcie_us.TLP_us() tlp.fmt_type = pcie_us.TLP_MEM_READ tlp.requester_id = pcie_us.PcieId(1, 2, 3) tlp.tag = cur_tag tlp.tc = 0 tlp.set_be(0x0000, 64) tlp.address = 0x0000 cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH)) yield cc_sink.wait(500) pkt = cc_sink.recv() rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH) print(rx_tlp) assert rx_tlp.status == pcie_us.CPL_STATUS_CA assert rx_tlp.tag == cur_tag assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6) assert status_error_cor_asserted assert not status_error_uncor_asserted cur_tag = (cur_tag + 1) % 32 yield delay(100) raise StopSimulation