Add option to override CPUIF address width. #25

This commit is contained in:
Alex Mykyta
2023-01-18 20:17:35 -08:00
parent 9db27145a3
commit c0427f5a73
4 changed files with 30 additions and 6 deletions

View File

@@ -25,9 +25,12 @@ only include the local offset.
For example, consider a fictional AXI4-Lite device that: For example, consider a fictional AXI4-Lite device that:
- Consumes 4 kB of address space (``0x000``-``0xFFF``). - Consumes 4 kB of address space (``0x000``-``0xFFF``).
- The device is instantiated in your system at global address ``0x80_0000``-``0x80_0FFF``. - The device is instantiated in your system at global address range ``0x30_0000 - 0x50_0FFF``.
- After decoding transactions destined to the device, the system interconnect shall - After decoding transactions destined to the device, the system interconnect shall
ensure that AxADDR values are presented to the device as relative addresses - within ensure that AxADDR values are presented to the device as relative addresses - within
the range of ``0x000``-``0xFFF``. the range of ``0x000``-``0xFFF``.
- If care is taken to align the global address offset to the size of the device, - If care is taken to align the global address offset to the size of the device,
creating a relative address is as simple as pruning down address bits. creating a relative address is as simple as pruning down address bits.
By default, the bit-width of the address bus will be the minimum size to span the contents
of the register block. If needed, the address width can be overridden to a larger range.

View File

@@ -1 +1 @@
__version__ = "0.9.0" __version__ = "0.10.0"

View File

@@ -88,6 +88,15 @@ class Exporter:
help="Generate a HWIF report file" help="Generate a HWIF report file"
) )
arg_group.add_argument(
"--addr-width",
type=int,
default=None,
help="""Override the CPU interface's address width. By default,
address width is sized to the contents of the regblock.
"""
)
def do_export(self, top_node: 'AddrmapNode', options: 'argparse.Namespace') -> None: def do_export(self, top_node: 'AddrmapNode', options: 'argparse.Namespace') -> None:
x = RegblockExporter() x = RegblockExporter()
@@ -101,4 +110,5 @@ class Exporter:
retime_read_fanin=options.rt_read_fanin, retime_read_fanin=options.rt_read_fanin,
retime_read_response=options.rt_read_response, retime_read_response=options.rt_read_response,
generate_hwif_report=options.hwif_report, generate_hwif_report=options.hwif_report,
address_width=options.addr_width,
) )

View File

@@ -1,5 +1,5 @@
import os import os
from typing import Union, Any, Type from typing import Union, Any, Type, Optional
import jinja2 as jj import jinja2 as jj
from systemrdl.node import AddrmapNode, RootNode from systemrdl.node import AddrmapNode, RootNode
@@ -98,14 +98,18 @@ class RegblockExporter:
Enabling this option will increase read transfer latency by 1 clock cycle. Enabling this option will increase read transfer latency by 1 clock cycle.
generate_hwif_report: bool generate_hwif_report: bool
If set, generates a hwif report that can help understand the structure If set, generates a hwif report that can help designers understand
of the hwif_in and hwif_out structures. the contents of the ``hwif_in`` and ``hwif_out`` structures.
address_width: int
Override the CPU interface's address width. By default, address width
is sized to the contents of the regblock.
""" """
# If it is the root node, skip to top addrmap # If it is the root node, skip to top addrmap
if isinstance(node, RootNode): if isinstance(node, RootNode):
self.top_node = node.top self.top_node = node.top
else: else:
self.top_node = node self.top_node = node
msg = self.top_node.env.msg
cpuif_cls = kwargs.pop("cpuif_cls", None) or APB4_Cpuif # type: Type[CpuifBase] cpuif_cls = kwargs.pop("cpuif_cls", None) or APB4_Cpuif # type: Type[CpuifBase]
@@ -113,6 +117,7 @@ class RegblockExporter:
package_name = kwargs.pop("package_name", None) or (module_name + "_pkg") # type: str package_name = kwargs.pop("package_name", None) or (module_name + "_pkg") # type: str
reuse_hwif_typedefs = kwargs.pop("reuse_hwif_typedefs", True) # type: bool reuse_hwif_typedefs = kwargs.pop("reuse_hwif_typedefs", True) # type: bool
generate_hwif_report = kwargs.pop("generate_hwif_report", False) # type: bool generate_hwif_report = kwargs.pop("generate_hwif_report", False) # type: bool
user_addr_width = kwargs.pop("address_width", None) # type: Optional[int]
# Pipelining options # Pipelining options
retime_read_fanin = kwargs.pop("retime_read_fanin", False) # type: bool retime_read_fanin = kwargs.pop("retime_read_fanin", False) # type: bool
@@ -129,6 +134,12 @@ class RegblockExporter:
if retime_read_response: if retime_read_response:
self.min_read_latency += 1 self.min_read_latency += 1
addr_width = self.top_node.size.bit_length()
if user_addr_width is not None:
if user_addr_width < addr_width:
msg.fatal(f"User-specified address width shall be greater than {addr_width}.")
addr_width = user_addr_width
# Scan the design for pre-export information # Scan the design for pre-export information
scanner = DesignScanner(self) scanner = DesignScanner(self)
scanner.do_scan() scanner.do_scan()
@@ -144,7 +155,7 @@ class RegblockExporter:
self, self,
cpuif_reset=self.top_node.cpuif_reset, cpuif_reset=self.top_node.cpuif_reset,
data_width=scanner.cpuif_data_width, data_width=scanner.cpuif_data_width,
addr_width=self.top_node.size.bit_length() addr_width=addr_width
) )
self.hwif = Hwif( self.hwif = Hwif(
self, self,