async def dma_mem_read(self, addr, length, timeout=0, timeout_unit='ns'): data = b'' n = 0 while n < length: tlp = Tlp_us() if addr > 0xffffffff: tlp.fmt_type = TlpType.MEM_READ_64 else: tlp.fmt_type = TlpType.MEM_READ tlp.requester_id = PcieId(self.dev.bus_num, self.dev.device_num, 0) first_pad = addr % 4 byte_length = length - n # max read request size byte_length = min( byte_length, (128 << self.dev.functions[0].max_read_request_size) - first_pad) # 4k address align byte_length = min(byte_length, 0x1000 - (addr & 0xfff)) tlp.set_addr_be(addr, byte_length) tlp.tag = await self.alloc_tag() await self.rq_source.send(tlp.pack_us_rq()) m = 0 while m < byte_length: pkt = await self.rc_sink.recv() if not pkt: raise Exception("Timeout") cpl = Tlp_us.unpack_us_rc(pkt) if cpl.status != CplStatus.SC: raise Exception("Unsuccessful completion") else: d = bytearray() for k in range(cpl.length): d.extend(struct.pack('<L', cpl.data[k])) offset = cpl.lower_address & 3 data += d[offset:offset + cpl.byte_count] m += len(d) - offset self.release_tag(tlp.tag) n += byte_length addr += byte_length return data
async def dma_io_write(self, addr, data, timeout=0, timeout_unit='ns'): n = 0 while True: tlp = Tlp_us() tlp.fmt_type = TlpType.IO_WRITE tlp.requester_id = PcieId(0, 0, 0) first_pad = addr % 4 byte_length = min(len(data) - n, 4 - first_pad) tlp.set_addr_be_data(addr, data[n:n + byte_length]) tlp.tag = await self.alloc_tag() await self.rq_source.send(tlp.pack_us_rq()) pkt = await self.rc_sink.recv() self.release_tag(tlp.tag) if not pkt: raise Exception("Timeout") cpl = Tlp_us.unpack_us_rc(pkt) if cpl.status != CplStatus.SC: raise Exception("Unsuccessful completion") n += byte_length addr += byte_length if n >= len(data): break
async def dma_mem_write(self, addr, data, timeout=0, timeout_unit='ns'): n = 0 while True: tlp = Tlp_us() if addr > 0xffffffff: tlp.fmt_type = TlpType.MEM_WRITE_64 else: tlp.fmt_type = TlpType.MEM_WRITE tlp.requester_id = PcieId(0, 0, 0) first_pad = addr % 4 byte_length = len(data) - n # max payload size byte_length = min(byte_length, (128 << self.dut.cfg_max_payload.value.integer) - first_pad) # 4k address align byte_length = min(byte_length, 0x1000 - (addr & 0xfff)) tlp.set_addr_be_data(addr, data[n:n + byte_length]) await self.rq_source.send(tlp.pack_us_rq()) n += byte_length addr += byte_length if n >= len(data): break
async def dma_mem_write(self, addr, data, timeout=0, timeout_unit='ns'): n = 0 while n < len(data): tlp = Tlp_us() if addr > 0xffffffff: tlp.fmt_type = TlpType.MEM_WRITE_64 else: tlp.fmt_type = TlpType.MEM_WRITE tlp.requester_id = PcieId(self.dev.bus_num, self.dev.device_num, 0) first_pad = addr % 4 byte_length = len(data) - n # max payload size byte_length = min(byte_length, (128 << self.dev.functions[0].max_payload_size) - first_pad) # 4k address align byte_length = min(byte_length, 0x1000 - (addr & 0xfff)) tlp.set_addr_be_data(addr, data[n:n + byte_length]) await self.rq_source.send(tlp.pack_us_rq()) n += byte_length addr += byte_length
async def dma_io_read(self, addr, length, timeout=0, timeout_unit='ns'): data = b'' n = 0 while True: tlp = Tlp_us() tlp.fmt_type = TlpType.IO_READ tlp.requester_id = PcieId(0, 0, 0) first_pad = addr % 4 byte_length = min(length - n, 4 - first_pad) tlp.set_addr_be(addr, byte_length) tlp.tag = await self.alloc_tag() await self.rq_source.send(tlp.pack_us_rq()) pkt = await self.rc_sink.recv() self.release_tag(tlp.tag) if not pkt: raise Exception("Timeout") cpl = Tlp_us.unpack_us_rc(pkt) if cpl.status != CplStatus.SC: raise Exception("Unsuccessful completion") else: d = cpl.get_data() data += d[first_pad:] n += byte_length addr += byte_length if n >= length: break return data[:length]
async def _run_cq(self): while True: pkt = await self.cq_sink.recv() tlp = Tlp_us.unpack_us_cq(pkt) self.log.debug("CQ TLP: %s", repr(tlp)) if tlp.fmt_type == TlpType.IO_READ: self.log.info("IO read") cpl = Tlp_us.create_completion_data_for_tlp( tlp, PcieId(0, 0, 0)) region = tlp.bar_id addr = tlp.address % len(self.regions[region]) 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] = self.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] = self.regions[region][ addr + start_offset:addr + offset] cpl.set_data(data) cpl.byte_count = 4 cpl.length = 1 self.log.debug("Completion: %s", repr(cpl)) await self.cc_source.send(cpl.pack_us_cc()) elif tlp.fmt_type == TlpType.IO_WRITE: self.log.info("IO write") cpl = Tlp_us.create_completion_for_tlp(tlp, PcieId(0, 0, 0)) region = tlp.bar_id addr = tlp.address % len(self.regions[region]) 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: self.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: self.regions[region][addr + start_offset:addr + offset] = data[start_offset:offset] self.log.debug("Completion: %s", repr(cpl)) await self.cc_source.send(cpl.pack_us_cc()) elif tlp.fmt_type in {TlpType.MEM_READ, TlpType.MEM_READ_64}: self.log.info("Memory read") # perform operation region = tlp.bar_id addr = tlp.address % len(self.regions[region]) offset = 0 length = tlp.length # perform read data = self.regions[region][addr:addr + length * 4] # prepare completion TLP(s) m = 0 n = 0 addr = tlp.address + tlp.get_first_be_offset() dw_length = tlp.length byte_length = tlp.get_be_byte_count() while m < dw_length: cpl = Tlp_us.create_completion_data_for_tlp( tlp, PcieId(0, 0, 0)) cpl_dw_length = dw_length - m cpl_byte_length = byte_length - n cpl.byte_count = cpl_byte_length if cpl_dw_length > 32 << self.dut.cfg_max_payload.value.integer: # max payload size cpl_dw_length = 32 << self.dut.cfg_max_payload.value.integer # RCB align cpl_dw_length -= (addr & 0x7c) >> 2 cpl.lower_address = addr & 0x7f cpl.set_data(data[m * 4:(m + cpl_dw_length) * 4]) self.log.debug("Completion: %s", repr(cpl)) await self.cc_source.send(cpl.pack_us_cc()) m += cpl_dw_length n += cpl_dw_length * 4 - (addr & 3) addr += cpl_dw_length * 4 - (addr & 3) elif tlp.fmt_type in {TlpType.MEM_WRITE, TlpType.MEM_WRITE_64}: self.log.info("Memory write") # perform operation region = tlp.bar_id addr = tlp.address % len(self.regions[region]) 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: self.regions[region][addr + start_offset:addr + offset] = data[ start_offset:offset] start_offset = None offset += 1 if length > 2: # middle dwords if start_offset is None: start_offset = offset offset += (length - 2) * 4 if length > 1: # 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: self.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: self.regions[region][addr + start_offset:addr + offset] = data[start_offset:offset]
async def dma_mem_read(self, addr, length, timeout=0, timeout_unit='ns'): data = b'' n = 0 while True: tlp = Tlp_us() if addr > 0xffffffff: tlp.fmt_type = TlpType.MEM_READ_64 else: tlp.fmt_type = TlpType.MEM_READ tlp.requester_id = PcieId(0, 0, 0) first_pad = addr % 4 byte_length = length - n # max read request size byte_length = min( byte_length, (128 << self.dut.cfg_max_read_req.value.integer) - first_pad) # 4k address align byte_length = min(byte_length, 0x1000 - (addr & 0xfff)) tlp.set_addr_be(addr, byte_length) tlp.tag = await self.alloc_tag() await self.rq_source.send(tlp.pack_us_rq()) m = 0 while True: pkt = await self.rc_sink.recv() if not pkt: raise Exception("Timeout") cpl = Tlp_us.unpack_us_rc(pkt) if cpl.status != CplStatus.SC: raise Exception("Unsuccessful completion") else: assert cpl.byte_count + 3 + (cpl.lower_address & 3) >= cpl.length * 4 assert cpl.byte_count == max(byte_length - m, 1) d = cpl.get_data() offset = cpl.lower_address & 3 data += d[offset:offset + cpl.byte_count] m += len(d) - offset if m >= byte_length: break self.release_tag(tlp.tag) n += byte_length addr += byte_length if n >= length: break return data[:length]