1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

Add bus objects for DMA RAM

This commit is contained in:
Alex Forencich 2021-03-17 22:12:42 -07:00
parent bdfeaa84ca
commit 04cbbeb879
6 changed files with 107 additions and 68 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)