示例#1
0
    def unpack_us_cc(cls, pkt, check_parity=False):
        tlp = cls()

        tlp.fmt_type = TlpType.CPL

        tlp.lower_address = pkt.data[0] & 0x7f
        tlp.at = (pkt.data[0] >> 8) & 3
        tlp.byte_count = (pkt.data[0] >> 16) & 0x1fff
        if pkt.data[0] & (1 << 29):
            tlp.fmt_type = TlpType.CPL_LOCKED

        tlp.length = pkt.data[1] & 0x7ff
        if tlp.length > 0:
            tlp.fmt = TlpFmt.THREE_DW_DATA
        tlp.status = CplStatus((pkt.data[1] >> 11) & 7)
        tlp.requester_id = PcieId.from_int(pkt.data[1] >> 16)
        tlp.completer_id = PcieId.from_int(pkt.data[2] >> 8)
        tlp.completer_id_enable = pkt.data[2] >> 24 & 1 != 0
        tlp.tag = pkt.data[2] & 0xff
        tlp.completer_id_enable = bool(pkt.data[2] & (1 << 24))
        tlp.tc = (pkt.data[2] >> 25) & 0x7
        tlp.attr = (pkt.data[2] >> 28) & 0x7

        tlp.discontinue = pkt.discontinue

        if tlp.length > 0:
            tlp.data = pkt.data[3:3+tlp.length]

        # check parity
        if check_parity:
            assert pkt.check_parity()

        return tlp
示例#2
0
    def unpack_us_rc(cls, pkt, check_parity=False):
        tlp = cls()

        tlp.fmt_type = TlpType.CPL

        tlp.lower_address = pkt.data[0] & 0xfff
        tlp.error_code = (pkt.data[0] >> 12) & 0xf
        tlp.byte_count = (pkt.data[0] >> 16) & 0x1fff
        if pkt.data[0] & (1 << 29):
            tlp.fmt_type = TlpType.CPL_LOCKED
        tlp.request_completed = pkt.data[0] & (1 << 30)

        tlp.length = pkt.data[1] & 0x7ff
        if tlp.length > 0:
            tlp.fmt = TlpFmt.THREE_DW_DATA
        tlp.status = CplStatus((pkt.data[1] >> 11) & 7)
        tlp.ep = bool(pkt.data[1] & 1 << 14)
        tlp.requester_id = PcieId.from_int(pkt.data[1] >> 16)
        tlp.completer_id = PcieId.from_int(pkt.data[2] >> 8)
        tlp.tag = pkt.data[2] & 0xff
        tlp.tc = TlpTc((pkt.data[2] >> 25) & 0x7)
        tlp.attr = TlpAttr((pkt.data[2] >> 28) & 0x7)

        tlp.discontinue = pkt.discontinue

        if tlp.length > 0:
            for dw in pkt.data[3:3+tlp.length]:
                tlp.data.extend(struct.pack('<L', dw))

        # compute byte enables
        byte_en = [0]*3

        first_be = (0xf << (tlp.lower_address & 3)) & 0xf
        if tlp.byte_count+(tlp.lower_address & 3) > tlp.length*4:
            last_be = 0xf
        else:
            last_be = 0xf >> ((4-tlp.byte_count-tlp.lower_address) & 3)

        if tlp.get_payload_size_dw() == 1:
            first_be = first_be & last_be
            last_be = 0

        if tlp.get_payload_size_dw() >= 1:
            byte_en += [first_be]
        if tlp.get_payload_size_dw() > 2:
            byte_en += [0xf] * (tlp.get_payload_size_dw()-2)
        if tlp.get_payload_size_dw() > 1:
            byte_en += [last_be]

        # check byte enables
        assert byte_en == pkt.byte_en

        # check parity
        if check_parity:
            assert pkt.check_parity()

        return tlp
示例#3
0
    def unpack_us_rc(cls, pkt, check_parity=False):
        tlp = cls()

        tlp.fmt_type = TlpType.CPL

        tlp.lower_address = pkt.data[0] & 0xfff
        tlp.error_code = (pkt.data[0] >> 12) & 0xf
        tlp.byte_count = (pkt.data[0] >> 16) & 0x1fff
        if pkt.data[0] & (1 << 29):
            tlp.fmt_type = TlpType.CPL_LOCKED

        tlp.length = pkt.data[1] & 0x7ff
        if tlp.length > 0:
            tlp.fmt = TlpFmt.THREE_DW_DATA
        tlp.status = (pkt.data[1] >> 11) & 7
        tlp.requester_id = PcieId.from_int(pkt.data[1] >> 16)
        tlp.completer_id = PcieId.from_int(pkt.data[2] >> 8)
        tlp.tag = pkt.data[2] & 0xff
        tlp.tc = (pkt.data[2] >> 25) & 0x7
        tlp.attr = (pkt.data[2] >> 28) & 0x7

        tlp.discontinue = pkt.discontinue

        if tlp.length > 0:
            tlp.data = pkt.data[3:3+tlp.length]

        # compute byte enables
        byte_en = [0]*3

        first_be = (0xf << (tlp.lower_address & 3)) & 0xf
        if tlp.byte_count+(tlp.lower_address & 3) > tlp.length*4:
            last_be = 0xf
        else:
            last_be = 0xf >> ((4-tlp.byte_count-tlp.lower_address) & 3)

        if len(tlp.data) == 1:
            first_be = first_be & last_be
            last_be = 0

        if len(tlp.data) >= 1:
            byte_en += [first_be]
        if len(tlp.data) > 2:
            byte_en += [0xf] * (len(tlp.data)-2)
        if len(tlp.data) > 1:
            byte_en += [last_be]

        # check byte enables
        assert byte_en == pkt.byte_en

        # check parity
        if check_parity:
            assert pkt.check_parity()

        return tlp
示例#4
0
    def unpack_us_cq(cls, pkt, check_parity=False):
        tlp = cls()

        req_type = (pkt.data[2] >> 11) & 0xf

        tlp.fmt_type = req_type_to_tlp_type[req_type]

        tlp.length = pkt.data[2] & 0x7ff
        tlp.requester_id = PcieId.from_int(pkt.data[2] >> 16)
        tlp.tag = pkt.data[3] & 0xff
        tlp.tc = TlpTc((pkt.data[3] >> 25) & 0x7)
        tlp.attr = TlpAttr((pkt.data[3] >> 28) & 0x7)

        if req_type & 8 == 0:
            # memory, IO, or atomic operation
            tlp.at = TlpAt(pkt.data[0] & 3)
            tlp.address = (pkt.data[1] << 32) | (pkt.data[0] & 0xfffffffc)
            if tlp.address > 0xffffffff:
                if tlp.fmt == TlpFmt.THREE_DW:
                    tlp.fmt = TlpFmt.FOUR_DW
                elif tlp.fmt == TlpFmt.THREE_DW_DATA:
                    tlp.fmt = TlpFmt.FOUR_DW_DATA
            tlp.completer_id = PcieId(0, 0, (pkt.data[3] >> 8) & 0xff)
            tlp.bar_id = (pkt.data[3] >> 16) & 7
            tlp.bar_aperture = (pkt.data[3] >> 19) & 0x3f

            tlp.first_be = pkt.first_be
            tlp.last_be = pkt.last_be

            tlp.discontinue = pkt.discontinue

            for dw in pkt.data[4:]:
                tlp.data.extend(struct.pack('<L', dw))

            # compute byte enables
            byte_en = [0]*4

            if tlp.get_payload_size_dw() >= 1:
                byte_en += [tlp.first_be]
            if tlp.get_payload_size_dw() > 2:
                byte_en += [0xf] * (tlp.get_payload_size_dw()-2)
            if tlp.get_payload_size_dw() > 1:
                byte_en += [tlp.last_be]

            # check byte enables
            assert byte_en == pkt.byte_en

            # check parity
            if check_parity:
                assert pkt.check_parity()

        return tlp
示例#5
0
    async def dma_mem_write(self, addr, data, timeout=0, timeout_unit='ns'):
        n = 0

        while True:
            tlp = Tlp()
            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_max_payload) - 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.tx_source.send(S10PcieFrame.from_tlp(tlp))

            n += byte_length
            addr += byte_length

            if n >= len(data):
                break
示例#6
0
    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
示例#7
0
    async def dma_io_write(self, addr, data, timeout=0, timeout_unit='ns'):
        n = 0

        while True:
            tlp = Tlp()
            tlp.fmt_type = TlpType.IO_WRITE
            tlp.requester_id = PcieId(self.dev_bus_num, self.dev_device_num, 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.tx_source.send(S10PcieFrame.from_tlp(tlp))
            cpl = await self.recv_cpl(tlp.tag, timeout, timeout_unit)

            self.release_tag(tlp.tag)

            if not cpl:
                raise Exception("Timeout")

            if cpl.status != CplStatus.SC:
                raise Exception("Unsuccessful completion")

            n += byte_length
            addr += byte_length

            if n >= len(data):
                break
示例#8
0
    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
示例#9
0
    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
示例#10
0
    def unpack_us_rq(cls, pkt, check_parity=False):
        tlp = cls()

        req_type = (pkt.data[2] >> 11) & 0xf

        tlp.fmt_type = req_type_to_tlp_type[req_type]

        tlp.length = pkt.data[2] & 0x7ff
        tlp.ep = bool(pkt.data[2] & 1 << 15)
        tlp.requester_id = PcieId.from_int(pkt.data[2] >> 16)
        tlp.tag = pkt.data[3] & 0xff
        tlp.tc = TlpTc((pkt.data[3] >> 25) & 0x7)
        tlp.attr = TlpAttr((pkt.data[3] >> 28) & 0x7)

        if req_type < 12:
            if req_type < 8:
                # memory, IO, or atomic operation
                tlp.at = TlpAt(pkt.data[0] & 3)
                tlp.address = (pkt.data[1] << 32) | (pkt.data[0] & 0xfffffffc)
                if tlp.address > 0xffffffff:
                    if tlp.fmt == TlpFmt.THREE_DW:
                        tlp.fmt = TlpFmt.FOUR_DW
                    elif tlp.fmt == TlpFmt.THREE_DW_DATA:
                        tlp.fmt = TlpFmt.FOUR_DW_DATA
            else:
                # configuration
                tlp.register_number = (pkt.data[0] >> 2) & 0x3ff
            tlp.completer_id = PcieId.from_int(pkt.data[3] >> 8)
            tlp.requester_id_enable = bool(pkt.data[3] & (1 << 24))

            tlp.first_be = pkt.first_be
            tlp.last_be = pkt.last_be

            tlp.discontinue = pkt.discontinue

            tlp.seq_num = pkt.seq_num

            for dw in pkt.data[4:]:
                tlp.data.extend(struct.pack('<L', dw))

            # check parity
            if check_parity:
                assert pkt.check_parity()
        else:
            raise Exception("TODO")

        return tlp
示例#11
0
    async def dma_mem_read(self, addr, length, timeout=0, timeout_unit='ns'):
        data = b''
        n = 0

        while True:
            tlp = Tlp()
            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_max_read_req) - 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.tx_source.send(S10PcieFrame.from_tlp(tlp))

            m = 0

            while True:
                cpl = await self.recv_cpl(tlp.tag, timeout, timeout_unit)

                if not cpl:
                    raise Exception("Timeout")

                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]
示例#12
0
async def run_test_config(dut):

    tb = TB(dut)

    tb.rc.log.setLevel(logging.DEBUG)

    tb.log.info("Read complete config space")
    orig = await tb.rc.config_read(PcieId(0, 1, 0), 0x000, 256, 1000, 'ns')

    tb.log.info("Read and write IntLine and IntPin")
    await tb.rc.config_write(PcieId(0, 1, 0), 0x03c, b'\x12\x34', 1000, 'ns')
    val = await tb.rc.config_read(PcieId(0, 1, 0), 0x03c, 2, 1000, 'ns')

    assert val == b'\x12\x34'

    tb.log.info("Write complete config space")
    await tb.rc.config_write(PcieId(0, 1, 0), 0x000, orig, 1000, 'ns')
示例#13
0
async def run_test_config(dut):

    tb = TB(dut)

    tb.rc.log.setLevel(logging.DEBUG)

    tb.log.info("Read complete config space")
    orig = await tb.rc.config_read(PcieId(0, 1, 0), 0x000, 256, timeout=1000, timeout_unit='ns')

    tb.log.info("Read and write interrupt line register")
    await tb.rc.config_write(PcieId(0, 1, 0), 0x03c, b'\x12', timeout=1000, timeout_unit='ns')
    val = await tb.rc.config_read(PcieId(0, 1, 0), 0x03c, 1, timeout=1000, timeout_unit='ns')

    assert val == b'\x12'

    tb.log.info("Write complete config space")
    await tb.rc.config_write(PcieId(0, 1, 0), 0x000, orig, timeout=1000, timeout_unit='ns')
示例#14
0
    async def _run_cc_logic(self):
        while True:
            tlp = Tlp_us.unpack_us_cc(await self.cc_sink.recv(), self.enable_parity)

            if not tlp.completer_id_enable:
                tlp.completer_id = PcieId(self.bus_num, self.device_num, tlp.completer_id.function)

            if not tlp.discontinue:
                await self.send(Tlp(tlp))
示例#15
0
    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
示例#16
0
    async def _run_rq_logic(self):
        while True:
            tlp = Tlp_us.unpack_us_rq(await self.rq_sink.recv(), self.enable_parity)

            if not tlp.requester_id_enable:
                tlp.requester_id = PcieId(self.bus_num, self.device_num, tlp.requester_id.function)

            if not tlp.discontinue:
                if self.functions[tlp.requester_id.function].bus_master_enable:
                    self.rq_seq_num.append(tlp.seq_num)
                    await self.send(Tlp(tlp))
                else:
                    self.log.warning("Bus mastering disabled")
示例#17
0
    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]
示例#18
0
    async def dma_io_read(self, addr, length, timeout=0, timeout_unit='ns'):
        data = b''
        n = 0

        while True:
            tlp = Tlp()
            tlp.fmt_type = TlpType.IO_READ
            tlp.requester_id = PcieId(self.dev_bus_num, self.dev_device_num, 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.tx_source.send(S10PcieFrame.from_tlp(tlp))
            cpl = await self.recv_cpl(tlp.tag, timeout, timeout_unit)

            self.release_tag(tlp.tag)

            if not cpl:
                raise Exception("Timeout")

            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]
示例#19
0
    def check_dev(dev):
        tb.log.info("Check device at %s", dev.pcie_id)

        # ensure ID was assigned to device
        assert dev.pcie_id != PcieId(0, 0, 0)

        # get tree item
        ti = tb.rc.tree.find_child_dev(dev.pcie_id)
        assert ti is not None

        # check informational registers
        tb.log.info("Header type: 0x%02x", ti.header_type)
        tb.log.info("Vendor ID: 0x%04x", ti.vendor_id)
        tb.log.info("Device ID: 0x%04x", ti.device_id)
        tb.log.info("Revision ID: 0x%02x", ti.revision_id)
        tb.log.info("Class code: 0x%06x", ti.class_code)

        assert ti.header_type == dev.header_layout | (bool(dev.multifunction_device) << 7)
        assert ti.class_code == dev.class_code
        assert ti.revision_id == dev.revision_id

        assert ti.vendor_id == dev.vendor_id
        assert ti.device_id == dev.device_id

        if ti.header_type & 0x7f == 0x01:
            # bridge
            bar_cnt = 2

            # check bridge registers
            tb.log.info("Primary bus %d", ti.pri_bus_num)
            tb.log.info("Secondary bus %d", ti.sec_bus_num)
            tb.log.info("Subordinate bus %d", ti.sub_bus_num)
            tb.log.info("IO base 0x%08x", ti.io_base)
            tb.log.info("IO limit 0x%08x", ti.io_limit)
            tb.log.info("Mem base 0x%08x", ti.mem_base)
            tb.log.info("Mem limit 0x%08x", ti.mem_limit)
            tb.log.info("Prefetchable mem base 0x%016x", ti.prefetchable_mem_base)
            tb.log.info("Prefetchable mem limit 0x%016x", ti.prefetchable_mem_limit)

            assert ti.sec_bus_num == dev.sec_bus_num
            assert ti.sub_bus_num == dev.sub_bus_num

            assert ti.io_base == dev.io_base
            assert ti.io_limit == dev.io_limit
            assert ti.mem_base == dev.mem_base
            assert ti.mem_limit == dev.mem_limit
            assert ti.prefetchable_mem_base == dev.prefetchable_mem_base
            assert ti.prefetchable_mem_limit == dev.prefetchable_mem_limit
        else:
            bar_cnt = 6

            tb.log.info("Subsystem vendor ID: 0x%04x", ti.subsystem_vendor_id)
            tb.log.info("Subsystem ID: 0x%04x", ti.subsystem_id)

            assert ti.subsystem_vendor_id == dev.subsystem_vendor_id
            assert ti.subsystem_id == dev.subsystem_id

        # check BARs
        bar = 0
        while bar < bar_cnt:
            if d.bar_mask[bar] == 0:
                # unused bar
                assert ti.bar[bar] is None
                assert ti.bar_raw[bar] == 0
                assert ti.bar_addr[bar] is None
                assert ti.bar_size[bar] is None
                bar += 1
            elif d.bar[bar] & 1:
                # IO BAR
                tb.log.info("BAR%d: IO BAR addr 0x%08x, size %d", bar, ti.bar_addr[bar], ti.bar_size[bar])
                assert ti.bar[bar] == d.bar[bar]
                assert ti.bar_raw[bar] == d.bar[bar]
                assert ti.bar_addr[bar] == d.bar[bar] & ~0x3
                assert ti.bar_size[bar] == (~d.bar_mask[bar] & 0xfffffffc)+0x4
                bar += 1
            elif d.bar[bar] & 4:
                # 64 bit BAR
                tb.log.info("BAR%d: Mem BAR (32 bit) addr 0x%08x, size %d", bar, ti.bar_addr[bar], ti.bar_size[bar])
                assert ti.bar[bar] == d.bar[bar] | d.bar[bar+1] << 32
                assert ti.bar_raw[bar] == d.bar[bar]
                assert ti.bar_raw[bar+1] == d.bar[bar+1]
                assert ti.bar_addr[bar] == (d.bar[bar] | d.bar[bar+1] << 32) & ~0xf
                assert ti.bar_size[bar] == (~(d.bar_mask[bar] | d.bar_mask[bar+1] << 32) & 0xfffffffffffffff0)+0x10
                bar += 2
            else:
                # 32 bit BAR
                tb.log.info("BAR%d: Mem BAR (64 bit) addr 0x%08x, size %d", bar, ti.bar_addr[bar], ti.bar_size[bar])
                assert ti.bar[bar] == d.bar[bar]
                assert ti.bar_raw[bar] == d.bar[bar]
                assert ti.bar_addr[bar] == d.bar[bar] & ~0xf
                assert ti.bar_size[bar] == (~d.bar_mask[bar] & 0xfffffff0)+0x10
                bar += 1

        if d.expansion_rom_addr_mask == 0:
            assert ti.expansion_rom_raw == 0
            assert ti.expansion_rom_addr is None
            assert ti.expansion_rom_size is None
        else:
            assert ti.expansion_rom_raw & 0xfffff800 == dev.expansion_rom_addr
            assert ti.expansion_rom_addr == dev.expansion_rom_addr
            assert ti.expansion_rom_size == (~d.expansion_rom_addr_mask & 0xfffff800)+0x800
示例#20
0
    def unpack_us_rq(cls, pkt, check_parity=False):
        tlp = cls()

        req_type = (pkt.data[2] >> 11) & 0xf

        if req_type == ReqType.MEM_READ:
            tlp.fmt_type = TlpType.MEM_READ
        elif req_type == ReqType.MEM_WRITE:
            tlp.fmt_type = TlpType.MEM_WRITE
        elif req_type == ReqType.IO_READ:
            tlp.fmt_type = TlpType.IO_READ
        elif req_type == ReqType.IO_WRITE:
            tlp.fmt_type = TlpType.IO_WRITE
        elif req_type == ReqType.MEM_FETCH_ADD:
            tlp.fmt_type = TlpType.FETCH_ADD
        elif req_type == ReqType.MEM_SWAP:
            tlp.fmt_type = TlpType.SWAP
        elif req_type == ReqType.MEM_CAS:
            tlp.fmt_type = TlpType.CAS
        elif req_type == ReqType.MEM_READ_LOCKED:
            tlp.fmt_type = TlpType.MEM_READ_LOCKED
        elif req_type == ReqType.CFG_READ_0:
            tlp.fmt_type = TlpType.CFG_READ_0
        elif req_type == ReqType.CFG_READ_1:
            tlp.fmt_type = TlpType.CFG_READ_1
        elif req_type == ReqType.CFG_WRITE_0:
            tlp.fmt_type = TlpType.CFG_WRITE_0
        elif req_type == ReqType.CFG_WRITE_1:
            tlp.fmt_type = TlpType.CFG_WRITE_1
        else:
            raise Exception("Invalid packet type")

        tlp.length = pkt.data[2] & 0x7ff
        # TODO poisoned
        tlp.requester_id = PcieId.from_int(pkt.data[2] >> 16)
        tlp.tag = pkt.data[3] & 0xff
        tlp.tc = (pkt.data[3] >> 25) & 0x7
        tlp.attr = (pkt.data[3] >> 28) & 0x7

        if req_type < 12:
            if req_type < 8:
                # memory, IO, or atomic operation
                tlp.at = pkt.data[0] & 3
                tlp.address = (pkt.data[1] << 32) | (pkt.data[0] & 0xfffffffc)
                if tlp.address > 0xffffffff:
                    if tlp.fmt == TlpFmt.THREE_DW:
                        tlp.fmt = TlpFmt.FOUR_DW
                    elif tlp.fmt == TlpFmt.THREE_DW_DATA:
                        tlp.fmt = TlpFmt.FOUR_DW_DATA
            else:
                tlp.register_number = (pkt.data[0] >> 2) & 0x3ff
            tlp.completer_id = PcieId.from_int(pkt.data[3] >> 8)
            tlp.requester_id_enable = bool(pkt.data[3] & (1 << 24))

            tlp.first_be = pkt.first_be
            tlp.last_be = pkt.last_be

            tlp.discontinue = pkt.discontinue

            tlp.seq_num = pkt.seq_num

            tlp.data = pkt.data[4:]

            # check parity
            if check_parity:
                assert pkt.check_parity()
        else:
            raise Exception("TODO")

        return tlp
示例#21
0
    def unpack_us_cq(cls, pkt, check_parity=False):
        tlp = cls()

        req_type = (pkt.data[2] >> 11) & 0xf

        if req_type == ReqType.MEM_READ:
            tlp.fmt_type = TlpType.MEM_READ
        elif req_type == ReqType.MEM_WRITE:
            tlp.fmt_type = TlpType.MEM_WRITE
        elif req_type == ReqType.IO_READ:
            tlp.fmt_type = TlpType.IO_READ
        elif req_type == ReqType.IO_WRITE:
            tlp.fmt_type = TlpType.IO_WRITE
        elif req_type == ReqType.MEM_FETCH_ADD:
            tlp.fmt_type = TlpType.FETCH_ADD
        elif req_type == ReqType.MEM_SWAP:
            tlp.fmt_type = TlpType.SWAP
        elif req_type == ReqType.MEM_CAS:
            tlp.fmt_type = TlpType.CAS
        elif req_type == ReqType.MEM_READ_LOCKED:
            tlp.fmt_type = TlpType.MEM_READ_LOCKED
        else:
            raise Exception("Invalid packet type")

        tlp.length = pkt.data[2] & 0x7ff
        tlp.requester_id = PcieId.from_int(pkt.data[2] >> 16)
        tlp.tag = pkt.data[3] & 0xff
        tlp.tc = (pkt.data[3] >> 25) & 0x7
        tlp.attr = (pkt.data[3] >> 28) & 0x7

        if req_type & 8 == 0:
            # memory, IO, or atomic operation
            tlp.at = pkt.data[0] & 3
            tlp.address = (pkt.data[1] << 32) | (pkt.data[0] & 0xfffffffc)
            if tlp.address > 0xffffffff:
                if tlp.fmt == TlpFmt.THREE_DW:
                    tlp.fmt = TlpFmt.FOUR_DW
                elif tlp.fmt == TlpFmt.THREE_DW_DATA:
                    tlp.fmt = TlpFmt.FOUR_DW_DATA
            tlp.completer_id = PcieId(0, 0, (pkt.data[3] >> 8) & 0xff)
            tlp.bar_id = (pkt.data[3] >> 16) & 7
            tlp.bar_aperture = (pkt.data[3] >> 19) & 0x3f

            tlp.first_be = pkt.first_be
            tlp.last_be = pkt.last_be

            tlp.discontinue = pkt.discontinue

            tlp.data = pkt.data[4:]

            # compute byte enables
            byte_en = [0]*4

            if len(tlp.data) >= 1:
                byte_en += [tlp.first_be]
            if len(tlp.data) > 2:
                byte_en += [0xf] * (len(tlp.data)-2)
            if len(tlp.data) > 1:
                byte_en += [tlp.last_be]

            # check byte enables
            assert byte_en == pkt.byte_en

            # check parity
            if check_parity:
                assert pkt.check_parity()

        return tlp
示例#22
0
    async def upstream_recv(self, tlp):
        self.log.debug("Got downstream TLP: %r", tlp)

        if tlp.fmt_type in {TlpType.CFG_READ_0, TlpType.CFG_WRITE_0}:
            # config type 0

            # capture address information
            self.bus_num = tlp.dest_id.bus

            # pass TLP to function
            for f in self.functions:
                if f.pcie_id == tlp.dest_id:
                    await f.upstream_recv(tlp)
                    return

            tlp.release_fc()

            self.log.warning(
                "Function not found: failed to route config type 0 TLP: %r",
                tlp)
        elif tlp.fmt_type in {TlpType.CFG_READ_1, TlpType.CFG_WRITE_1}:
            # config type 1

            tlp.release_fc()

            self.log.warning(
                "Malformed TLP: endpoint received config type 1 TLP: %r", tlp)
        elif tlp.fmt_type in {
                TlpType.CPL, TlpType.CPL_DATA, TlpType.CPL_LOCKED,
                TlpType.CPL_LOCKED_DATA
        }:
            # Completion

            for f in self.functions:
                if f.pcie_id == tlp.requester_id:

                    frame = S10PcieFrame.from_tlp(tlp)

                    frame.func_num = tlp.requester_id.function

                    await self.rx_queue.put(frame)

                    tlp.release_fc()

                    return

            tlp.release_fc()

            self.log.warning(
                "Unexpected completion: failed to route completion to function: %r",
                tlp)
            return  # no UR response for completion
        elif tlp.fmt_type in {TlpType.IO_READ, TlpType.IO_WRITE}:
            # IO read/write

            for f in self.functions:
                bar = f.match_bar(tlp.address, True)
                if bar:

                    frame = S10PcieFrame.from_tlp(tlp)

                    frame.bar_range = 6
                    frame.func_num = tlp.requester_id.function

                    await self.rx_queue.put(frame)

                    tlp.release_fc()

                    return

            tlp.release_fc()

            self.log.warning(
                "No BAR match: IO request did not match any BARs: %r", tlp)
        elif tlp.fmt_type in {
                TlpType.MEM_READ, TlpType.MEM_READ_64, TlpType.MEM_WRITE,
                TlpType.MEM_WRITE_64
        }:
            # Memory read/write

            for f in self.functions:
                bar = f.match_bar(tlp.address)
                if bar:

                    frame = S10PcieFrame.from_tlp(tlp)

                    frame.bar_range = bar[0]
                    frame.func_num = tlp.requester_id.function

                    await self.rx_queue.put(frame)

                    tlp.release_fc()

                    return

            tlp.release_fc()

            if tlp.fmt_type in {TlpType.MEM_WRITE, TlpType.MEM_WRITE_64}:
                self.log.warning(
                    "No BAR match: memory write request did not match any BARs: %r",
                    tlp)
                return  # no UR response for write request
            else:
                self.log.warning(
                    "No BAR match: memory read request did not match any BARs: %r",
                    tlp)
        else:
            raise Exception("TODO")

        # Unsupported request
        cpl = Tlp.create_ur_completion_for_tlp(tlp, PcieId(self.bus_num, 0, 0))
        self.log.debug("UR Completion: %r", cpl)
        await self.upstream_send(cpl)
示例#23
0
    async def _run_rx_tlp(self):
        while True:
            frame = await self.rx_sink.recv()

            tlp = frame.to_tlp()

            self.log.debug("RX TLP: %s", repr(tlp))

            if tlp.fmt_type in {
                    TlpType.CPL, TlpType.CPL_DATA, TlpType.CPL_LOCKED,
                    TlpType.CPL_LOCKED_DATA
            }:
                self.log.info("Completion")

                self.rx_cpl_queues[tlp.tag].put_nowait(tlp)
                self.rx_cpl_sync[tlp.tag].set()

            elif tlp.fmt_type == TlpType.IO_READ:
                self.log.info("IO read")

                cpl = Tlp.create_completion_data_for_tlp(
                    tlp, PcieId(self.dev_bus_num, 0, 0))

                # region = tlp.bar_id
                region = 3
                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.tx_source.send(S10PcieFrame.from_tlp(cpl))

            elif tlp.fmt_type == TlpType.IO_WRITE:
                self.log.info("IO write")

                cpl = Tlp.create_completion_for_tlp(
                    tlp, PcieId(self.dev_bus_num, 0, 0))

                # region = tlp.bar_id
                region = 3
                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.tx_source.send(S10PcieFrame.from_tlp(cpl))

            elif tlp.fmt_type in {TlpType.MEM_READ, TlpType.MEM_READ_64}:
                self.log.info("Memory read")

                # perform operation
                region = frame.bar_range
                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.create_completion_data_for_tlp(
                        tlp, PcieId(self.dev_bus_num, 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.dev_max_payload:
                        # max payload size
                        cpl_dw_length = 32 << self.dev_max_payload
                        # 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.tx_source.send(S10PcieFrame.from_tlp(cpl))

                    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 = frame.bar_range
                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]
示例#24
0
    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]
示例#25
0
    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]
示例#26
0
    async def upstream_recv(self, tlp):
        self.log.debug("Got downstream TLP: %s", repr(tlp))

        if tlp.fmt_type == TlpType.CFG_READ_0 or tlp.fmt_type == TlpType.CFG_WRITE_0:
            # config type 0

            if not self.config_space_enable:
                self.log.warning("Configuraion space disabled")

                cpl = Tlp.create_crs_completion_for_tlp(tlp, PcieId(self.bus_num, self.device_num, 0))
                self.log.debug("CRS Completion: %s", repr(cpl))
                await self.upstream_send(cpl)
                return
            elif tlp.dest_id.device == self.device_num:
                # capture address information
                self.bus_num = tlp.dest_id.bus

                for f in self.functions:
                    f.pci_id = f.pcie_id._replace(bus=self.bus_num)

                # pass TLP to function
                for f in self.functions:
                    if f.function_num == tlp.dest_id.function:
                        await f.upstream_recv(tlp)
                        return

                self.log.info("Function not found")
            else:
                self.log.info("Device number mismatch")

            # Unsupported request
            cpl = Tlp.create_ur_completion_for_tlp(tlp, PcieId(self.bus_num, self.device_num, 0))
            self.log.debug("UR Completion: %s", repr(cpl))
            await self.upstream_send(cpl)
        elif (tlp.fmt_type == TlpType.CPL or tlp.fmt_type == TlpType.CPL_DATA or
                tlp.fmt_type == TlpType.CPL_LOCKED or tlp.fmt_type == TlpType.CPL_LOCKED_DATA):
            # Completion

            if tlp.requester_id.bus == self.bus_num and tlp.requester_id.device == self.device_num:
                for f in self.functions:
                    if f.function_num == tlp.requester_id.function:

                        tlp = Tlp_us(tlp)

                        tlp.error_code = ErrorCode.NORMAL_TERMINATION

                        if tlp.status != CplStatus.SC:
                            tlp.error = ErrorCode.BAD_STATUS

                        self.rc_queue.append(tlp)

                        return

                self.log.info("Function not found")
            else:
                self.log.info("Device number mismatch")
        elif (tlp.fmt_type == TlpType.IO_READ or tlp.fmt_type == TlpType.IO_WRITE):
            # IO read/write

            for f in self.functions:
                bar = f.match_bar(tlp.address, True)
                if len(bar) == 1:

                    tlp = Tlp_us(tlp)
                    tlp.bar_id = bar[0][0]
                    tlp.bar_aperture = (~self.functions[0].bar_mask[bar[0][0]] & 0xffffffff).bit_length()
                    tlp.completer_id = PcieId(self.bus_num, self.device_num, f.function_num)
                    self.cq_queue.append(tlp)

                    return

            self.log.info("IO request did not match any BARs")

            # Unsupported request
            cpl = Tlp.create_ur_completion_for_tlp(tlp, PcieId(self.bus_num, self.device_num, 0))
            self.log.debug("UR Completion: %s", repr(cpl))
            await self.upstream_send(cpl)
        elif (tlp.fmt_type == TlpType.MEM_READ or tlp.fmt_type == TlpType.MEM_READ_64 or
                tlp.fmt_type == TlpType.MEM_WRITE or tlp.fmt_type == TlpType.MEM_WRITE_64):
            # Memory read/write

            for f in self.functions:
                bar = f.match_bar(tlp.address)
                if len(bar) == 1:

                    tlp = Tlp_us(tlp)
                    tlp.bar_id = bar[0][0]
                    if self.functions[0].bar[bar[0][0]] & 4:
                        tlp.bar_aperture = (~(self.functions[0].bar_mask[bar[0][0]] |
                            (self.functions[0].bar_mask[bar[0][0]+1] << 32)) & 0xffffffffffffffff).bit_length()
                    else:
                        tlp.bar_aperture = (~self.functions[0].bar_mask[bar[0][0]] & 0xffffffff).bit_length()
                    tlp.completer_id = PcieId(self.bus_num, self.device_num, f.function_num)
                    self.cq_queue.append(tlp)

                    return

            self.log.info("Memory request did not match any BARs")

            if tlp.fmt_type == TlpType.MEM_READ or tlp.fmt_type == TlpType.MEM_READ_64:
                # Unsupported request
                cpl = Tlp.create_ur_completion_for_tlp(tlp, PcieId(self.bus_num, self.device_num, 0))
                self.log.debug("UR Completion: %s", repr(cpl))
                await self.upstream_send(cpl)
        else:
            raise Exception("TODO")