diff --git a/fpga/lib/pcie/tb/dma_client_axis_sink/test_dma_client_axis_sink.py b/fpga/lib/pcie/tb/dma_client_axis_sink/test_dma_client_axis_sink.py index 25eb114a2..097bc0f5f 100644 --- a/fpga/lib/pcie/tb/dma_client_axis_sink/test_dma_client_axis_sink.py +++ b/fpga/lib/pcie/tb/dma_client_axis_sink/test_dma_client_axis_sink.py @@ -39,12 +39,12 @@ from cocotbext.axi import AxiStreamBus, AxiStreamFrame, AxiStreamSource from cocotbext.axi.stream import define_stream try: - from dma_psdp_ram import PsdpRamWrite + from dma_psdp_ram import PsdpRamWrite, PsdpRamWriteBus except ImportError: # attempt import from current directory sys.path.insert(0, os.path.join(os.path.dirname(__file__))) try: - from dma_psdp_ram import PsdpRamWrite + from dma_psdp_ram import PsdpRamWrite, PsdpRamWriteBus finally: del sys.path[0] @@ -74,7 +74,7 @@ class TB(object): self.write_data_source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis_write_data"), dut.clk, dut.rst) # DMA RAM - self.dma_ram = PsdpRamWrite(dut, "ram", dut.clk, dut.rst, size=2**16) + self.dma_ram = PsdpRamWrite(PsdpRamWriteBus.from_prefix(dut, "ram"), dut.clk, dut.rst, size=2**16) dut.enable.setimmediatevalue(0) dut.abort.setimmediatevalue(0) diff --git a/fpga/lib/pcie/tb/dma_client_axis_source/test_dma_client_axis_source.py b/fpga/lib/pcie/tb/dma_client_axis_source/test_dma_client_axis_source.py index 5dbcfe4f2..337bd4b1c 100644 --- a/fpga/lib/pcie/tb/dma_client_axis_source/test_dma_client_axis_source.py +++ b/fpga/lib/pcie/tb/dma_client_axis_source/test_dma_client_axis_source.py @@ -39,12 +39,12 @@ from cocotbext.axi import AxiStreamBus, AxiStreamSink from cocotbext.axi.stream import define_stream try: - from dma_psdp_ram import PsdpRamRead + from dma_psdp_ram import PsdpRamRead, PsdpRamReadBus except ImportError: # attempt import from current directory sys.path.insert(0, os.path.join(os.path.dirname(__file__))) try: - from dma_psdp_ram import PsdpRamRead + from dma_psdp_ram import PsdpRamRead, PsdpRamReadBus finally: del sys.path[0] @@ -74,7 +74,7 @@ class TB(object): self.read_data_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis_read_data"), dut.clk, dut.rst) # DMA RAM - self.dma_ram = PsdpRamRead(dut, "ram", dut.clk, dut.rst, size=2**16) + self.dma_ram = PsdpRamRead(PsdpRamReadBus.from_prefix(dut, "ram"), dut.clk, dut.rst, size=2**16) dut.enable.setimmediatevalue(0) diff --git a/fpga/lib/pcie/tb/dma_if_pcie_us/test_dma_if_pcie_us.py b/fpga/lib/pcie/tb/dma_if_pcie_us/test_dma_if_pcie_us.py index 3695190cc..e67169524 100644 --- a/fpga/lib/pcie/tb/dma_if_pcie_us/test_dma_if_pcie_us.py +++ b/fpga/lib/pcie/tb/dma_if_pcie_us/test_dma_if_pcie_us.py @@ -42,12 +42,12 @@ from cocotbext.axi.stream import define_stream from cocotbext.axi.utils import hexdump_str try: - from dma_psdp_ram import PsdpRam + from dma_psdp_ram import PsdpRam, PsdpRamBus except ImportError: # attempt import from current directory sys.path.insert(0, os.path.join(os.path.dirname(__file__))) try: - from dma_psdp_ram import PsdpRam + from dma_psdp_ram import PsdpRam, PsdpRamBus finally: del sys.path[0] @@ -117,7 +117,7 @@ class TB(object): self.rc.make_port().connect(self.dev) # DMA RAM - self.dma_ram = PsdpRam(dut, "ram", dut.clk, dut.rst, size=2**16) + self.dma_ram = PsdpRam(PsdpRamBus.from_prefix(dut, "ram"), dut.clk, dut.rst, size=2**16) # Control self.read_desc_source = DescSource(DescBus.from_prefix(dut, "s_axis_read_desc"), dut.clk, dut.rst) diff --git a/fpga/lib/pcie/tb/dma_if_pcie_us_rd/test_dma_if_pcie_us_rd.py b/fpga/lib/pcie/tb/dma_if_pcie_us_rd/test_dma_if_pcie_us_rd.py index 67c013e6e..05036c366 100644 --- a/fpga/lib/pcie/tb/dma_if_pcie_us_rd/test_dma_if_pcie_us_rd.py +++ b/fpga/lib/pcie/tb/dma_if_pcie_us_rd/test_dma_if_pcie_us_rd.py @@ -42,12 +42,12 @@ from cocotbext.axi.stream import define_stream from cocotbext.axi.utils import hexdump_str try: - from dma_psdp_ram import PsdpRamWrite + from dma_psdp_ram import PsdpRamWrite, PsdpRamWriteBus except ImportError: # attempt import from current directory sys.path.insert(0, os.path.join(os.path.dirname(__file__))) try: - from dma_psdp_ram import PsdpRamWrite + from dma_psdp_ram import PsdpRamWrite, PsdpRamWriteBus finally: del sys.path[0] @@ -113,7 +113,7 @@ class TB(object): self.rc.make_port().connect(self.dev) # DMA RAM - self.dma_ram = PsdpRamWrite(dut, "ram", dut.clk, dut.rst, size=2**16) + self.dma_ram = PsdpRamWrite(PsdpRamWriteBus.from_prefix(dut, "ram"), dut.clk, dut.rst, size=2**16) # Control self.read_desc_source = DescSource(DescBus.from_prefix(dut, "s_axis_read_desc"), dut.clk, dut.rst) diff --git a/fpga/lib/pcie/tb/dma_if_pcie_us_wr/test_dma_if_pcie_us_wr.py b/fpga/lib/pcie/tb/dma_if_pcie_us_wr/test_dma_if_pcie_us_wr.py index 9015847bf..6e10412e1 100644 --- a/fpga/lib/pcie/tb/dma_if_pcie_us_wr/test_dma_if_pcie_us_wr.py +++ b/fpga/lib/pcie/tb/dma_if_pcie_us_wr/test_dma_if_pcie_us_wr.py @@ -42,12 +42,12 @@ from cocotbext.axi.stream import define_stream from cocotbext.axi.utils import hexdump_str try: - from dma_psdp_ram import PsdpRamRead + from dma_psdp_ram import PsdpRamRead, PsdpRamReadBus except ImportError: # attempt import from current directory sys.path.insert(0, os.path.join(os.path.dirname(__file__))) try: - from dma_psdp_ram import PsdpRamRead + from dma_psdp_ram import PsdpRamRead, PsdpRamReadBus finally: del sys.path[0] @@ -119,7 +119,7 @@ class TB(object): dut.s_axis_rq_tvalid.setimmediatevalue(0) # DMA RAM - self.dma_ram = PsdpRamRead(dut, "ram", dut.clk, dut.rst, size=2**16) + self.dma_ram = PsdpRamRead(PsdpRamReadBus.from_prefix(dut, "ram"), dut.clk, dut.rst, size=2**16) # Control self.write_desc_source = DescSource(DescBus.from_prefix(dut, "s_axis_write_desc"), dut.clk, dut.rst) diff --git a/fpga/lib/pcie/tb/dma_psdp_ram.py b/fpga/lib/pcie/tb/dma_psdp_ram.py index 0cc048ac7..b7ec33b59 100644 --- a/fpga/lib/pcie/tb/dma_psdp_ram.py +++ b/fpga/lib/pcie/tb/dma_psdp_ram.py @@ -26,23 +26,67 @@ import logging import cocotb from cocotb.triggers import RisingEdge -from cocotb.bus import Bus +from cocotb_bus.bus import Bus from cocotbext.axi.memory import Memory +class BaseBus(Bus): + + _signals = ["data"] + _optional_signals = [] + + def __init__(self, entity=None, prefix=None, **kwargs): + super().__init__(entity, prefix, self._signals, optional_signals=self._optional_signals, **kwargs) + + @classmethod + def from_entity(cls, entity, **kwargs): + return cls(entity, **kwargs) + + @classmethod + def from_prefix(cls, entity, prefix, **kwargs): + return cls(entity, prefix, **kwargs) + + +class PsdpRamWriteBus(BaseBus): + _signals = ["wr_cmd_be", "wr_cmd_addr", "wr_cmd_data", "wr_cmd_valid", "wr_cmd_ready", "wr_done"] + + +class PsdpRamReadBus(BaseBus): + _signals = ["rd_cmd_addr", "rd_cmd_valid", "rd_cmd_ready", "rd_resp_data", "rd_resp_valid", "rd_resp_ready"] + + +class PsdpRamBus: + def __init__(self, write=None, read=None, **kwargs): + self.write = write + self.read = read + + @classmethod + def from_entity(cls, entity, **kwargs): + write = PsdpRamWriteBus.from_entity(entity, **kwargs) + read = PsdpRamReadBus.from_entity(entity, **kwargs) + return cls(write, read) + + @classmethod + def from_prefix(cls, entity, prefix, **kwargs): + write = PsdpRamWriteBus.from_prefix(entity, prefix, **kwargs) + read = PsdpRamReadBus.from_prefix(entity, prefix, **kwargs) + return cls(write, read) + + @classmethod + def from_channels(cls, wr, rd): + write = PsdpRamWriteBus.from_channels(wr) + read = PsdpRamReadBus.from_channels(rd) + return cls(write, read) + + class PsdpRamWrite(Memory): - _cmd_signals = ["wr_cmd_be", "wr_cmd_addr", "wr_cmd_data", "wr_cmd_valid", "wr_cmd_ready"] - _resp_signals = ["wr_done"] - - def __init__(self, entity, name, clock, reset=None, size=1024, mem=None, *args, **kwargs): - self.log = logging.getLogger(f"cocotb.{entity._name}.{name}") - self.entity = entity + def __init__(self, bus, clock, reset=None, size=1024, mem=None, *args, **kwargs): + self.bus = bus self.clock = clock self.reset = reset - self.cmd_bus = Bus(self.entity, name, self._cmd_signals, **kwargs) - self.resp_bus = Bus(self.entity, name, self._resp_signals, **kwargs) + self.log = logging.getLogger(f"cocotb.{bus._entity._name}.{bus._name}") self.log.info("Parallel Simple Dual Port RAM model (write)") self.log.info("Copyright (c) 2020 Alex Forencich") @@ -53,13 +97,13 @@ class PsdpRamWrite(Memory): self._pause_generator = None self._pause_cr = None - self.width = len(self.cmd_bus.wr_cmd_data) - self.byte_width = len(self.cmd_bus.wr_cmd_be) + self.width = len(self.bus.wr_cmd_data) + self.byte_width = len(self.bus.wr_cmd_be) - self.seg_count = len(self.cmd_bus.wr_cmd_valid) + self.seg_count = len(self.bus.wr_cmd_valid) self.seg_data_width = self.width // self.seg_count self.seg_byte_width = self.seg_data_width // 8 - self.seg_addr_width = len(self.cmd_bus.wr_cmd_addr) // self.seg_count + self.seg_addr_width = len(self.bus.wr_cmd_addr) // self.seg_count self.seg_be_width = self.seg_data_width // 8 self.seg_data_mask = 2**self.seg_data_width-1 @@ -73,10 +117,10 @@ class PsdpRamWrite(Memory): self.log.info(" Segment data width: %d bits (%d bytes)", self.seg_data_width, self.seg_byte_width) self.log.info(" Total data width: %d bits (%d bytes)", self.width, self.width // 8) - assert self.seg_be_width*self.seg_count == len(self.cmd_bus.wr_cmd_be) + assert self.seg_be_width*self.seg_count == len(self.bus.wr_cmd_be) - self.cmd_bus.wr_cmd_ready.setimmediatevalue(0) - self.resp_bus.wr_done.setimmediatevalue(0) + self.bus.wr_cmd_ready.setimmediatevalue(0) + self.bus.wr_done.setimmediatevalue(0) cocotb.fork(self._run()) @@ -99,15 +143,15 @@ class PsdpRamWrite(Memory): wr_done = 0 - cmd_be_sample = self.cmd_bus.wr_cmd_be.value - cmd_addr_sample = self.cmd_bus.wr_cmd_addr.value - cmd_data_sample = self.cmd_bus.wr_cmd_data.value - cmd_ready_sample = self.cmd_bus.wr_cmd_ready.value - cmd_valid_sample = self.cmd_bus.wr_cmd_valid.value + cmd_be_sample = self.bus.wr_cmd_be.value + cmd_addr_sample = self.bus.wr_cmd_addr.value + cmd_data_sample = self.bus.wr_cmd_data.value + cmd_ready_sample = self.bus.wr_cmd_ready.value + cmd_valid_sample = self.bus.wr_cmd_valid.value if self.reset is not None and self.reset.value: - self.cmd_bus.wr_cmd_ready.setimmediatevalue(0) - self.resp_bus.wr_done.setimmediatevalue(0) + self.bus.wr_cmd_ready.setimmediatevalue(0) + self.bus.wr_done.setimmediatevalue(0) continue # process segments @@ -135,11 +179,11 @@ class PsdpRamWrite(Memory): seg, addr, seg_be, ' '.join((f'{c:02x}' for c in data))) if self.pause: - self.cmd_bus.wr_cmd_ready <= 0 + self.bus.wr_cmd_ready <= 0 else: - self.cmd_bus.wr_cmd_ready <= 2**self.seg_count-1 + self.bus.wr_cmd_ready <= 2**self.seg_count-1 - self.resp_bus.wr_done <= wr_done + self.bus.wr_done <= wr_done async def _run_pause(self): for val in self._pause_generator: @@ -149,16 +193,11 @@ class PsdpRamWrite(Memory): class PsdpRamRead(Memory): - _cmd_signals = ["rd_cmd_addr", "rd_cmd_valid", "rd_cmd_ready"] - _resp_signals = ["rd_resp_data", "rd_resp_valid", "rd_resp_ready"] - - def __init__(self, entity, name, clock, reset=None, size=1024, mem=None, *args, **kwargs): - self.log = logging.getLogger(f"cocotb.{entity._name}.{name}") - self.entity = entity + def __init__(self, bus, clock, reset=None, size=1024, mem=None, *args, **kwargs): + self.bus = bus self.clock = clock self.reset = reset - self.cmd_bus = Bus(self.entity, name, self._cmd_signals, **kwargs) - self.resp_bus = Bus(self.entity, name, self._resp_signals, **kwargs) + self.log = logging.getLogger(f"cocotb.{bus._entity._name}.{bus._name}") self.log.info("Parallel Simple Dual Port RAM model (read)") self.log.info("Copyright (c) 2020 Alex Forencich") @@ -169,13 +208,13 @@ class PsdpRamRead(Memory): self._pause_generator = None self._pause_cr = None - self.width = len(self.resp_bus.rd_resp_data) + self.width = len(self.bus.rd_resp_data) self.byte_width = self.width // 8 - self.seg_count = len(self.cmd_bus.rd_cmd_valid) + self.seg_count = len(self.bus.rd_cmd_valid) self.seg_data_width = self.width // self.seg_count self.seg_byte_width = self.seg_data_width // 8 - self.seg_addr_width = len(self.cmd_bus.rd_cmd_addr) // self.seg_count + self.seg_addr_width = len(self.bus.rd_cmd_addr) // self.seg_count self.seg_data_mask = 2**self.seg_data_width-1 self.seg_addr_mask = 2**self.seg_addr_width-1 @@ -187,8 +226,8 @@ class PsdpRamRead(Memory): self.log.info(" Segment data width: %d bits (%d bytes)", self.seg_data_width, self.seg_byte_width) self.log.info(" Total data width: %d bits (%d bytes)", self.width, self.width // 8) - self.cmd_bus.rd_cmd_ready.setimmediatevalue(0) - self.resp_bus.rd_resp_valid.setimmediatevalue(0) + self.bus.rd_cmd_ready.setimmediatevalue(0) + self.bus.rd_resp_valid.setimmediatevalue(0) cocotb.fork(self._run()) @@ -215,16 +254,16 @@ class PsdpRamRead(Memory): while True: await RisingEdge(self.clock) - cmd_addr_sample = self.cmd_bus.rd_cmd_addr.value - cmd_ready_sample = self.cmd_bus.rd_cmd_ready.value - cmd_valid_sample = self.cmd_bus.rd_cmd_valid.value + cmd_addr_sample = self.bus.rd_cmd_addr.value + cmd_ready_sample = self.bus.rd_cmd_ready.value + cmd_valid_sample = self.bus.rd_cmd_valid.value - resp_ready_sample = self.resp_bus.rd_resp_ready.value - resp_valid_sample = self.resp_bus.rd_resp_valid.value + resp_ready_sample = self.bus.rd_resp_ready.value + resp_valid_sample = self.bus.rd_resp_valid.value if self.reset is not None and self.reset.value: - self.cmd_bus.rd_cmd_ready.setimmediatevalue(0) - self.resp_bus.rd_resp_valid.setimmediatevalue(0) + self.bus.rd_cmd_ready.setimmediatevalue(0) + self.bus.rd_resp_valid.setimmediatevalue(0) cmd_ready = 0 resp_valid = 0 continue @@ -266,12 +305,12 @@ class PsdpRamRead(Memory): cmd_ready &= ~seg_mask if self.pause: - self.cmd_bus.rd_cmd_ready <= 0 + self.bus.rd_cmd_ready <= 0 else: - self.cmd_bus.rd_cmd_ready <= cmd_ready + self.bus.rd_cmd_ready <= cmd_ready - self.resp_bus.rd_resp_data <= resp_data - self.resp_bus.rd_resp_valid <= resp_valid + self.bus.rd_resp_data <= resp_data + self.bus.rd_resp_valid <= resp_valid async def _run_pause(self): for val in self._pause_generator: @@ -280,11 +319,11 @@ class PsdpRamRead(Memory): class PsdpRam(Memory): - def __init__(self, entity, name, clock, reset=None, size=1024, mem=None, *args, **kwargs): + def __init__(self, bus, clock, reset=None, size=1024, mem=None, *args, **kwargs): self.write_if = None self.read_if = None super().__init__(size, mem, *args, **kwargs) - self.write_if = PsdpRamWrite(entity, name, clock, reset, mem=self.mem) - self.read_if = PsdpRamRead(entity, name, clock, reset, mem=self.mem) + self.write_if = PsdpRamWrite(bus.write, clock, reset, mem=self.mem) + self.read_if = PsdpRamRead(bus.read, clock, reset, mem=self.mem) diff --git a/fpga/lib/pcie/tox.ini b/fpga/lib/pcie/tox.ini index 116a820d9..896cc4376 100644 --- a/fpga/lib/pcie/tox.ini +++ b/fpga/lib/pcie/tox.ini @@ -12,8 +12,7 @@ deps = pytest pytest-xdist pytest-split - #cocotb - git+https://github.com/cocotb/cocotb.git@e892a3ea48#egg=cocotb + cocotb cocotb-test cocotbext-axi cocotbext-pcie