Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af377b2c11 | ||
|
|
cfb52c6130 | ||
|
|
7e32e584ff | ||
|
|
50cf2af49f | ||
|
|
ddfa1e3c92 | ||
|
|
5e8b246159 | ||
|
|
62c2eef4ec | ||
|
|
ad6012aea5 | ||
|
|
432bd81011 | ||
|
|
bde123e05f | ||
|
|
8604017159 | ||
|
|
e21b9ffcc8 | ||
|
|
47cd74eb6c | ||
|
|
4bf5945aa3 |
2
.github/workflows/regression-tests.yml
vendored
2
.github/workflows/regression-tests.yml
vendored
@@ -5,7 +5,7 @@ on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
name: Python ${{matrix.python-version}}
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
|
||||
18
README.md
18
README.md
@@ -155,7 +155,7 @@ It is also possible to extend these modules; operation can be customized by over
|
||||
|
||||
### AXI and AXI lite RAM
|
||||
|
||||
The `AxiRam` and `AxiLiteRam` classes implement AXI RAMs and are capable of completing read and write operations from upstream AXI masters. The `AxiRam` module is capable of handling narrow bursts. These modules are extensions of the corresponding `AxiSlave` and `AxiLiteSlave` modules.
|
||||
The `AxiRam` and `AxiLiteRam` classes implement AXI RAMs and are capable of completing read and write operations from upstream AXI masters. The `AxiRam` module is capable of handling narrow bursts. These modules are extensions of the corresponding `AxiSlave` and `AxiLiteSlave` modules. Internally, `SparseMemory` is used to support emulating very large memories.
|
||||
|
||||
The `AxiRam` is a wrapper around `AxiRamWrite` and `AxiRamRead`. Similarly, `AxiLiteRam` is a wrapper around `AxiLiteRamWrite` and `AxiLiteRamRead`. If a read-only or write-only interface is required instead of a full interface, use the corresponding read-only or write-only variant, the usage and API are exactly the same.
|
||||
|
||||
@@ -163,7 +163,7 @@ To use these modules, import the one you need and connect it to the DUT:
|
||||
|
||||
from cocotbext.axi import AxiBus, AxiRam
|
||||
|
||||
axi_ram = AxiRam(AxiBus.from_prefix(dut, "m_axi"), dut.clk, dut.rst, size=2**16)
|
||||
axi_ram = AxiRam(AxiBus.from_prefix(dut, "m_axi"), dut.clk, dut.rst, size=2**32)
|
||||
|
||||
The first argument to the constructor accepts an `AxiBus` or `AxiLiteBus` object. These objects are containers for the interface signals and include class methods to automate connections.
|
||||
|
||||
@@ -175,7 +175,7 @@ Once the module is instantiated, the memory contents can be accessed in a couple
|
||||
|
||||
Multi-port memories can be constructed by passing the `mem` object of the first instance to the other instances. For example, here is how to create a four-port RAM:
|
||||
|
||||
axi_ram_p1 = AxiRam(AxiBus.from_prefix(dut, "m00_axi"), dut.clk, dut.rst, size=2**16)
|
||||
axi_ram_p1 = AxiRam(AxiBus.from_prefix(dut, "m00_axi"), dut.clk, dut.rst, size=2**32)
|
||||
axi_ram_p2 = AxiRam(AxiBus.from_prefix(dut, "m01_axi"), dut.clk, dut.rst, mem=axi_ram_p1.mem)
|
||||
axi_ram_p3 = AxiRam(AxiBus.from_prefix(dut, "m02_axi"), dut.clk, dut.rst, mem=axi_ram_p1.mem)
|
||||
axi_ram_p4 = AxiRam(AxiBus.from_prefix(dut, "m03_axi"), dut.clk, dut.rst, mem=axi_ram_p1.mem)
|
||||
@@ -186,12 +186,12 @@ Multi-port memories can be constructed by passing the `mem` object of the first
|
||||
* _clock_: clock signal
|
||||
* _reset_: reset signal (optional)
|
||||
* _reset_active_level_: reset active level (optional, default `True`)
|
||||
* _size_: memory size in bytes (optional, default 1024)
|
||||
* _mem_: mmap object to use (optional, overrides _size_)
|
||||
* _size_: memory size in bytes (optional, default `2**64`)
|
||||
* _mem_: `mmap` or `SparseMemory` backing object to use (optional, overrides _size_)
|
||||
|
||||
#### Attributes:
|
||||
|
||||
* _mem_: directly access shared `mmap` object
|
||||
* _mem_: directly access shared `mmap` or `SparseMemory` backing object
|
||||
|
||||
#### Methods
|
||||
|
||||
@@ -334,6 +334,8 @@ The address space abstraction provides a framework for cross-connecting multiple
|
||||
|
||||
`MemoryRegion` is an extension of `Region` that uses an `mmap` instance to handle memory operations. `MemoryRegion` also provides hex dump methods as well as indexing and slicing.
|
||||
|
||||
`SparseMemoryRegion` is similar to `MemoryRegion` but is backed by `SparseMemory` instead of `mmap` and as such can emulate extremely large regions of address space.
|
||||
|
||||
`PeripheralRegion` is an extension of `Region` that can wrap another object that implements `read()` and `write()`, as an alternative to extending `Region`.
|
||||
|
||||
`AddressSpace` is the core object for handling address spaces. `Region` objects can be registered with `AddressSpace` with specified base address, size, and offset. The `AddressSpace` object will then direct `read()` and `write()` operations to the appropriate `Region`s, splitting requests appropriately when necessary and translating addresses. Regions registered with `offset` other than `None` are translated such that accesses to base address + N map to N + offset. Regions registered with an `offset` of `None` are not translated. `Region` objects registered with the same `AddressSpace` cannot overlap, however the same `Region` can be registered multiple times. `AddressSpace` also provides a method for creating `Pool` objects.
|
||||
@@ -344,14 +346,14 @@ The address space abstraction provides a framework for cross-connecting multiple
|
||||
|
||||
This is a simple example that shows how the address space abstraction components can be used to connect a DUT to a simulated host system, including simulated RAM, an AXI interface from the DUT for DMA, and an AXI lite interface to the DUT for control.
|
||||
|
||||
from cocotbext.axi import AddressSpace, MemoryRegion
|
||||
from cocotbext.axi import AddressSpace, SparseMemoryRegion
|
||||
from cocotbext.axi import AxiBus, AxiLiteMaster, AxiSlave
|
||||
|
||||
# system address space
|
||||
address_space = AddressSpace(2**32)
|
||||
|
||||
# RAM
|
||||
ram = MemoryRegion(2**24)
|
||||
ram = SparseMemoryRegion(2**24)
|
||||
address_space.register_region(ram, 0x0000_0000)
|
||||
ram_pool = address_space.create_window_pool(0x0000_0000, 2**20)
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ from .version import __version__
|
||||
from .constants import AxiBurstType, AxiBurstSize, AxiLockType, AxiCacheBit, AxiProt, AxiResp
|
||||
|
||||
from .address_space import MemoryInterface, Window, WindowPool
|
||||
from .address_space import Region, MemoryRegion, PeripheralRegion
|
||||
from .address_space import Region, MemoryRegion, SparseMemoryRegion, PeripheralRegion
|
||||
from .address_space import AddressSpace, Pool
|
||||
|
||||
from .axis import AxiStreamFrame, AxiStreamBus, AxiStreamSource, AxiStreamSink, AxiStreamMonitor
|
||||
|
||||
@@ -25,6 +25,7 @@ THE SOFTWARE.
|
||||
import mmap
|
||||
|
||||
from .buddy_allocator import BuddyAllocator
|
||||
from .sparse_memory import SparseMemory
|
||||
from .utils import hexdump, hexdump_lines, hexdump_str
|
||||
|
||||
|
||||
@@ -216,6 +217,35 @@ class MemoryRegion(Region):
|
||||
return bytes(self.mem)
|
||||
|
||||
|
||||
class SparseMemoryRegion(Region):
|
||||
def __init__(self, size=2**64, mem=None, **kwargs):
|
||||
super().__init__(size, **kwargs)
|
||||
if mem is None:
|
||||
mem = SparseMemory(size)
|
||||
self.mem = mem
|
||||
|
||||
async def _read(self, address, length, **kwargs):
|
||||
return self.mem.read(address, length)
|
||||
|
||||
async def _write(self, address, data, **kwargs):
|
||||
self.mem.write(address, data)
|
||||
|
||||
def hexdump(self, address, length, prefix=""):
|
||||
self.mem.hexdump(address, length, prefix=prefix)
|
||||
|
||||
def hexdump_lines(self, address, length, prefix=""):
|
||||
return self.mem.hexdump_lines(address, length, prefix=prefix)
|
||||
|
||||
def hexdump_str(self, address, length, prefix=""):
|
||||
return self.mem.hexdump_str(address, length, prefix=prefix)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.mem[key]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.mem[key] = value
|
||||
|
||||
|
||||
class PeripheralRegion(Region):
|
||||
def __init__(self, obj, size, **kwargs):
|
||||
super().__init__(size, **kwargs)
|
||||
|
||||
@@ -291,6 +291,9 @@ class AxiMasterWrite(Region, Reset):
|
||||
if isinstance(data, int):
|
||||
raise ValueError("Expected bytes or bytearray for data")
|
||||
|
||||
if burst != AxiBurstType.FIXED and address+len(data) > 2**self.address_width:
|
||||
raise ValueError("Requested transfer overruns end of address space")
|
||||
|
||||
if awid is None or awid < 0:
|
||||
awid = None
|
||||
elif awid > self.id_count:
|
||||
@@ -357,6 +360,9 @@ class AxiMasterWrite(Region, Reset):
|
||||
if isinstance(data, int):
|
||||
raise ValueError("Expected bytes or bytearray for data")
|
||||
|
||||
if burst != AxiBurstType.FIXED and address+len(data) > 2**self.address_width:
|
||||
raise ValueError("Requested transfer overruns end of address space")
|
||||
|
||||
if awid is None or awid < 0:
|
||||
awid = None
|
||||
elif awid > self.id_count:
|
||||
@@ -563,7 +569,9 @@ class AxiMasterWrite(Region, Reset):
|
||||
|
||||
await self.w_channel.send(w)
|
||||
|
||||
if k == 0:
|
||||
if cmd.burst == AxiBurstType.FIXED:
|
||||
cur_addr = cmd.address
|
||||
elif k == 0:
|
||||
cur_addr = aligned_addr + num_bytes
|
||||
else:
|
||||
cur_addr += num_bytes
|
||||
@@ -715,6 +723,9 @@ class AxiMasterRead(Region, Reset):
|
||||
if length < 0:
|
||||
raise ValueError("Read length must be positive")
|
||||
|
||||
if burst != AxiBurstType.FIXED and address+length > 2**self.address_width:
|
||||
raise ValueError("Requested transfer overruns end of address space")
|
||||
|
||||
if arid is None or arid < 0:
|
||||
arid = None
|
||||
elif arid > self.id_count:
|
||||
@@ -769,6 +780,9 @@ class AxiMasterRead(Region, Reset):
|
||||
if length < 0:
|
||||
raise ValueError("Read length must be positive")
|
||||
|
||||
if burst != AxiBurstType.FIXED and address+length > 2**self.address_width:
|
||||
raise ValueError("Requested transfer overruns end of address space")
|
||||
|
||||
if arid is None or arid < 0:
|
||||
arid = None
|
||||
elif arid > self.id_count:
|
||||
@@ -918,7 +932,9 @@ class AxiMasterRead(Region, Reset):
|
||||
self.log.info("Read burst start arid: 0x%x araddr: 0x%08x arlen: %d arsize: %d arprot: %s",
|
||||
arid, cur_addr, burst_length-1, cmd.size, cmd.prot)
|
||||
|
||||
if k == 0:
|
||||
if cmd.burst == AxiBurstType.FIXED:
|
||||
cur_addr = cmd.address
|
||||
elif k == 0:
|
||||
cur_addr = aligned_addr + num_bytes
|
||||
else:
|
||||
cur_addr += num_bytes
|
||||
|
||||
@@ -27,7 +27,7 @@ from .memory import Memory
|
||||
|
||||
|
||||
class AxiRamWrite(AxiSlaveWrite, Memory):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=1024, mem=None, **kwargs):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=2**64, mem=None, **kwargs):
|
||||
super().__init__(bus, clock, reset, reset_active_level=reset_active_level, size=size, mem=mem, **kwargs)
|
||||
|
||||
async def _write(self, address, data):
|
||||
@@ -35,7 +35,7 @@ class AxiRamWrite(AxiSlaveWrite, Memory):
|
||||
|
||||
|
||||
class AxiRamRead(AxiSlaveRead, Memory):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=1024, mem=None, **kwargs):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=2**64, mem=None, **kwargs):
|
||||
super().__init__(bus, clock, reset, reset_active_level=reset_active_level, size=size, mem=mem, **kwargs)
|
||||
|
||||
async def _read(self, address, length):
|
||||
@@ -43,7 +43,7 @@ class AxiRamRead(AxiSlaveRead, Memory):
|
||||
|
||||
|
||||
class AxiRam(Memory):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=1024, mem=None, **kwargs):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=2**64, mem=None, **kwargs):
|
||||
self.write_if = None
|
||||
self.read_if = None
|
||||
|
||||
|
||||
@@ -159,6 +159,9 @@ class AxiLiteMasterWrite(Region, Reset):
|
||||
if isinstance(data, int):
|
||||
raise ValueError("Expected bytes or bytearray for data")
|
||||
|
||||
if address+len(data) > 2**self.address_width:
|
||||
raise ValueError("Requested transfer overruns end of address space")
|
||||
|
||||
if not self.awprot_present and prot != AxiProt.NONSECURE:
|
||||
raise ValueError("awprot sideband signal value specified, but signal is not connected")
|
||||
|
||||
@@ -182,6 +185,9 @@ class AxiLiteMasterWrite(Region, Reset):
|
||||
if isinstance(data, int):
|
||||
raise ValueError("Expected bytes or bytearray for data")
|
||||
|
||||
if address+len(data) > 2**self.address_width:
|
||||
raise ValueError("Requested transfer overruns end of address space")
|
||||
|
||||
if not self.awprot_present and prot != AxiProt.NONSECURE:
|
||||
raise ValueError("awprot sideband signal value specified, but signal is not connected")
|
||||
|
||||
@@ -401,6 +407,12 @@ class AxiLiteMasterRead(Region, Reset):
|
||||
if address < 0 or address >= 2**self.address_width:
|
||||
raise ValueError("Address out of range")
|
||||
|
||||
if length < 0:
|
||||
raise ValueError("Read length must be positive")
|
||||
|
||||
if address+length > 2**self.address_width:
|
||||
raise ValueError("Requested transfer overruns end of address space")
|
||||
|
||||
if not self.arprot_present and prot != AxiProt.NONSECURE:
|
||||
raise ValueError("arprot sideband signal value specified, but signal is not connected")
|
||||
|
||||
@@ -419,6 +431,12 @@ class AxiLiteMasterRead(Region, Reset):
|
||||
if address < 0 or address >= 2**self.address_width:
|
||||
raise ValueError("Address out of range")
|
||||
|
||||
if length < 0:
|
||||
raise ValueError("Read length must be positive")
|
||||
|
||||
if address+length > 2**self.address_width:
|
||||
raise ValueError("Requested transfer overruns end of address space")
|
||||
|
||||
if not self.arprot_present and prot != AxiProt.NONSECURE:
|
||||
raise ValueError("arprot sideband signal value specified, but signal is not connected")
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ from .memory import Memory
|
||||
|
||||
|
||||
class AxiLiteRamWrite(AxiLiteSlaveWrite, Memory):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=1024, mem=None, **kwargs):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=2**64, mem=None, **kwargs):
|
||||
super().__init__(bus, clock, reset, reset_active_level=reset_active_level, size=size, mem=mem, **kwargs)
|
||||
|
||||
async def _write(self, address, data):
|
||||
@@ -35,7 +35,7 @@ class AxiLiteRamWrite(AxiLiteSlaveWrite, Memory):
|
||||
|
||||
|
||||
class AxiLiteRamRead(AxiLiteSlaveRead, Memory):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=1024, mem=None, **kwargs):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=2**64, mem=None, **kwargs):
|
||||
super().__init__(bus, clock, reset, reset_active_level=reset_active_level, size=size, mem=mem, **kwargs)
|
||||
|
||||
async def _read(self, address, length):
|
||||
@@ -43,7 +43,7 @@ class AxiLiteRamRead(AxiLiteSlaveRead, Memory):
|
||||
|
||||
|
||||
class AxiLiteRam(Memory):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=1024, mem=None, **kwargs):
|
||||
def __init__(self, bus, clock, reset=None, reset_active_level=True, size=2**64, mem=None, **kwargs):
|
||||
self.write_if = None
|
||||
self.read_if = None
|
||||
|
||||
|
||||
@@ -22,27 +22,24 @@ THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import mmap
|
||||
|
||||
from .sparse_memory import SparseMemory
|
||||
from .utils import hexdump, hexdump_lines, hexdump_str
|
||||
|
||||
|
||||
class Memory:
|
||||
def __init__(self, size=1024, mem=None, **kwargs):
|
||||
def __init__(self, size=2**64, mem=None, **kwargs):
|
||||
if mem is not None:
|
||||
self.mem = mem
|
||||
else:
|
||||
self.mem = mmap.mmap(-1, size)
|
||||
self.mem = SparseMemory(size)
|
||||
self.size = len(self.mem)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def read(self, address, length):
|
||||
self.mem.seek(address)
|
||||
return self.mem.read(length)
|
||||
return self.mem[address:address+length]
|
||||
|
||||
def write(self, address, data):
|
||||
self.mem.seek(address)
|
||||
self.mem.write(bytes(data))
|
||||
self.mem[address:address+len(data)] = data
|
||||
|
||||
def write_words(self, address, data, byteorder='little', ws=2):
|
||||
words = data
|
||||
|
||||
111
cocotbext/axi/sparse_memory.py
Normal file
111
cocotbext/axi/sparse_memory.py
Normal file
@@ -0,0 +1,111 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2023 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from .utils import hexdump, hexdump_lines, hexdump_str
|
||||
|
||||
|
||||
class SparseMemory:
|
||||
def __init__(self, size):
|
||||
self.size = size
|
||||
self.segs = {}
|
||||
|
||||
def read(self, address, length, **kwargs):
|
||||
if address < 0 or address >= self.size:
|
||||
raise ValueError("address out of range")
|
||||
if length < 0:
|
||||
raise ValueError("invalid length")
|
||||
if address+length > self.size:
|
||||
raise ValueError("operation out of range")
|
||||
data = bytearray()
|
||||
while length > 0:
|
||||
block_offset = address & 0xfff
|
||||
block_addr = address - block_offset
|
||||
block_len = min(4096 - block_offset, length)
|
||||
try:
|
||||
block = self.segs[block_addr]
|
||||
except KeyError:
|
||||
block = b'\x00'*4096
|
||||
data.extend(block[block_offset:block_offset+block_len])
|
||||
address += block_len
|
||||
length -= block_len
|
||||
return bytes(data)
|
||||
|
||||
def write(self, address, data, **kwargs):
|
||||
if address < 0 or address >= self.size:
|
||||
raise ValueError("address out of range")
|
||||
if address+len(data) > self.size:
|
||||
raise ValueError("operation out of range")
|
||||
offset = 0
|
||||
length = len(data)
|
||||
while length > 0:
|
||||
block_offset = address & 0xfff
|
||||
block_addr = address - block_offset
|
||||
block_len = min(4096 - block_offset, length)
|
||||
try:
|
||||
block = self.segs[block_addr]
|
||||
except KeyError:
|
||||
block = bytearray(4096)
|
||||
self.segs[block_addr] = block
|
||||
block[block_offset:block_offset+block_len] = data[offset:offset+block_len]
|
||||
address += block_len
|
||||
offset += block_len
|
||||
length -= block_len
|
||||
|
||||
def clear(self):
|
||||
self.segs.clear()
|
||||
|
||||
def hexdump(self, address, length, prefix=""):
|
||||
hexdump(self.read(address, length), prefix=prefix, offset=address)
|
||||
|
||||
def hexdump_lines(self, address, length, prefix=""):
|
||||
return hexdump_lines(self.read(address, length), prefix=prefix, offset=address)
|
||||
|
||||
def hexdump_str(self, address, length, prefix=""):
|
||||
return hexdump_str(self.read(address, length), prefix=prefix, offset=address)
|
||||
|
||||
def __len__(self):
|
||||
return self.size
|
||||
|
||||
def __getitem__(self, key):
|
||||
if isinstance(key, int):
|
||||
return self.read(key, 1)[0]
|
||||
elif isinstance(key, slice):
|
||||
start, stop, step = key.indices(self.size)
|
||||
if step == 1:
|
||||
return self.read(start, stop-start)
|
||||
else:
|
||||
raise IndexError("specified step size is not supported")
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if isinstance(key, int):
|
||||
self.write(key, [value])
|
||||
elif isinstance(key, slice):
|
||||
start, stop, step = key.indices(self.size)
|
||||
if step == 1:
|
||||
value = bytes(value)
|
||||
if stop-start != len(value):
|
||||
raise IndexError("slice assignment is wrong size")
|
||||
return self.write(start, value)
|
||||
else:
|
||||
raise IndexError("specified step size is not supported")
|
||||
@@ -1 +1 @@
|
||||
__version__ = "0.1.20"
|
||||
__version__ = "0.1.24"
|
||||
|
||||
@@ -45,15 +45,7 @@ export PARAM_RUSER_WIDTH ?= 1
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).ADDR_WIDTH=$(PARAM_ADDR_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).STRB_WIDTH=$(PARAM_STRB_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).ID_WIDTH=$(PARAM_ID_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AWUSER_WIDTH=$(PARAM_AWUSER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).WUSER_WIDTH=$(PARAM_WUSER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).BUSER_WIDTH=$(PARAM_BUSER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).ARUSER_WIDTH=$(PARAM_ARUSER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RUSER_WIDTH=$(PARAM_RUSER_WIDTH)
|
||||
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
@@ -62,15 +54,7 @@ ifeq ($(SIM), icarus)
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH -Wno-CASEINCOMPLETE
|
||||
|
||||
COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GADDR_WIDTH=$(PARAM_ADDR_WIDTH)
|
||||
COMPILE_ARGS += -GSTRB_WIDTH=$(PARAM_STRB_WIDTH)
|
||||
COMPILE_ARGS += -GID_WIDTH=$(PARAM_ID_WIDTH)
|
||||
COMPILE_ARGS += -GAWUSER_WIDTH=$(PARAM_AWUSER_WIDTH)
|
||||
COMPILE_ARGS += -GWUSER_WIDTH=$(PARAM_WUSER_WIDTH)
|
||||
COMPILE_ARGS += -GBUSER_WIDTH=$(PARAM_BUSER_WIDTH)
|
||||
COMPILE_ARGS += -GARUSER_WIDTH=$(PARAM_ARUSER_WIDTH)
|
||||
COMPILE_ARGS += -GRUSER_WIDTH=$(PARAM_RUSER_WIDTH)
|
||||
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
|
||||
@@ -39,9 +39,7 @@ export PARAM_STRB_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 )
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).ADDR_WIDTH=$(PARAM_ADDR_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).STRB_WIDTH=$(PARAM_STRB_WIDTH)
|
||||
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
@@ -50,9 +48,7 @@ ifeq ($(SIM), icarus)
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GADDR_WIDTH=$(PARAM_ADDR_WIDTH)
|
||||
COMPILE_ARGS += -GSTRB_WIDTH=$(PARAM_STRB_WIDTH)
|
||||
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
|
||||
@@ -41,11 +41,7 @@ export PARAM_USER_WIDTH ?= 1
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).KEEP_WIDTH=$(PARAM_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).ID_WIDTH=$(PARAM_ID_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).DEST_WIDTH=$(PARAM_DEST_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_WIDTH)
|
||||
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
@@ -54,11 +50,7 @@ ifeq ($(SIM), icarus)
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GDATA_WIDTH=$(PARAM_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GKEEP_WIDTH=$(PARAM_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GID_WIDTH=$(PARAM_ID_WIDTH)
|
||||
COMPILE_ARGS += -GDEST_WIDTH=$(PARAM_DEST_WIDTH)
|
||||
COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH)
|
||||
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
|
||||
Reference in New Issue
Block a user