From 244bd8d773a2c6c63843354266ef5d953ba82cf0 Mon Sep 17 00:00:00 2001 From: Arnav Sacheti <36746504+arnavsacheti@users.noreply.github.com> Date: Tue, 3 Feb 2026 08:47:18 +0000 Subject: [PATCH] revamp docs --- docs/api.rst | 11 +- docs/architecture.rst | 92 +++--- docs/conf.py | 4 +- docs/configuring.rst | 33 +-- docs/cpuif/apb.rst | 12 +- docs/cpuif/avalon.rst | 33 --- docs/cpuif/axi4lite.rst | 23 +- docs/cpuif/customizing.rst | 8 +- docs/cpuif/internal_protocol.rst | 217 ++------------ docs/cpuif/introduction.rst | 18 +- docs/cpuif/passthrough.rst | 10 - docs/faq.rst | 131 --------- docs/hwif.rst | 61 ---- docs/index.rst | 64 ++-- docs/limitations.rst | 66 ++--- docs/props/addrmap.rst | 28 -- docs/props/field.rst | 491 ------------------------------- docs/props/reg.rst | 14 - docs/props/rhs_props.rst | 182 ------------ docs/props/signal.rst | 28 -- docs/rdl_features/external.rst | 155 ---------- docs/requirements.txt | 1 - docs/udps/intro.rst | 79 ----- pyproject.toml | 1 - 24 files changed, 178 insertions(+), 1584 deletions(-) delete mode 100644 docs/cpuif/avalon.rst delete mode 100644 docs/cpuif/passthrough.rst delete mode 100644 docs/faq.rst delete mode 100644 docs/hwif.rst delete mode 100644 docs/props/addrmap.rst delete mode 100644 docs/props/field.rst delete mode 100644 docs/props/reg.rst delete mode 100644 docs/props/rhs_props.rst delete mode 100644 docs/props/signal.rst delete mode 100644 docs/rdl_features/external.rst delete mode 100644 docs/udps/intro.rst diff --git a/docs/api.rst b/docs/api.rst index 5da2c00..02f1954 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -15,10 +15,11 @@ implementation from SystemRDL source. .. code-block:: python :emphasize-lines: 2-4, 29-33 + import sys + from systemrdl import RDLCompiler, RDLCompileError from peakrdl_busdecoder import BusDecoderExporter - from peakrdl_busdecoder.cpuif.axi4lite import AXI4Lite_Cpuif - from peakrdl_busdecoder.udps import ALL_UDPS + from peakrdl_busdecoder.cpuif.axi4lite import AXI4LiteCpuif input_files = [ "PATH/TO/my_register_block.rdl" @@ -27,10 +28,6 @@ implementation from SystemRDL source. # Create an instance of the compiler rdlc = RDLCompiler() - # Register all UDPs that 'busdecoder' requires - for udp in ALL_UDPS: - rdlc.register_udp(udp) - try: # Compile your RDL files for input_file in input_files: @@ -46,5 +43,5 @@ implementation from SystemRDL source. exporter = BusDecoderExporter() exporter.export( root, "path/to/output_dir", - cpuif_cls=AXI4Lite_Cpuif + cpuif_cls=AXI4LiteCpuif ) diff --git a/docs/architecture.rst b/docs/architecture.rst index 30abfa2..3ea1e00 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -1,64 +1,54 @@ -Register Block Architecture -=========================== +Bus Decoder Architecture +======================== -The generated bus decoder RTL is organized into several sections. -Each section is automatically generated based on the source register model and -is rendered into the output SystemVerilog RTL module. The bus decoder serves as -an address decode and routing layer that splits a single CPU interface into -multiple sub-address spaces corresponding to child addrmaps in your SystemRDL design. +The generated RTL is a pure bus-routing layer. It accepts a single CPU interface +on the slave side and fans transactions out to a set of child interfaces on the +master side. No register storage or field logic is generated. -.. figure:: diagrams/arch.png - -Although it is not completely necessary to know the inner workings of the -generated RTL, it can be helpful to understand the implications of various -exporter configuration options. +Although you do not need to know the inner workings to use the exporter, the +sections below explain the structure of the generated module and how it maps to +SystemRDL hierarchy. -CPU Interface -------------- -The CPU interface logic layer provides an abstraction between the -application-specific bus protocol and the internal register file logic. -This logic layer normalizes external CPU read & write transactions into a common -:ref:`cpuif_protocol` that is used to interact with the register file. When the -design contains multiple child addrmaps, the CPU interface handles fanout of -transactions to the appropriate sub-address space. +CPU Interface Adapter +--------------------- +Each supported CPU interface protocol (APB3, APB4, AXI4-Lite) provides a small +adapter that translates the external bus protocol into internal request/response +signals. These internal signals are then used by the address decoder and fanout +logic. + +If you write a custom CPU interface, it must implement the internal signals +described in :ref:`cpuif_protocol`. Address Decode -------------- -A common address decode operation is generated which computes individual access -strobes for each software-accessible register or child addrmap in the design. -This operation is performed completely combinationally. The decoder determines -which sub-address space should handle each transaction based on the address range. +The address decoder computes per-child select signals based on address ranges. +The decode boundary is controlled by ``max_decode_depth``: + +* ``0``: Decode all the way down to leaf registers +* ``1`` (default): Decode only top-level children +* ``N``: Decode down to depth ``N`` from the top-level + +This allows you to choose whether the bus decoder routes to large blocks (e.g., +child addrmaps) or to smaller sub-blocks. -Field Logic ------------ -This layer of the register block implements the storage elements and state-change -logic for every field in the design. Field state is updated based on address -decode strobes from software read/write actions, as well as events from the -hardware interface input struct. -This section also assigns any hardware interface outputs. +Fanout to Child Interfaces +-------------------------- +For each decoded child, the bus decoder drives a master-side CPU interface. +All address, data, and control signals are forwarded to the selected child. + +Arrayed children can be kept as arrays or unrolled into discrete interfaces using +``--unroll``. This only affects port structure and naming; decode semantics are +unchanged. -Readback --------- -The readback layer aggregates and reduces all readable registers into a single -read response. During a read operation, the same address decode strobes are used -to select the active register that is being accessed. -This allows for a simple OR-reduction operation to be used to compute the read -data response. +Fanin and Error Handling +------------------------ +Read and write responses are muxed back from the selected child to the slave +interface. If no child is selected for a transaction, the decoder generates an +error response on the slave interface. -For designs with a large number of software-readable registers, an optional -fanin re-timing stage can be enabled. This stage is automatically inserted at a -balanced point in the read-data reduction so that fanin and logic-levels are -optimally reduced. - -.. figure:: diagrams/readback.png - :width: 65% - :align: center - -A second optional read response retiming register can be enabled in-line with the -path back to the CPU interface layer. This can be useful if the CPU interface protocol -used has a fully combinational response path, and the design's complexity requires -this path to be retimed further. +The exact error signaling depends on the chosen CPU interface protocol (e.g., +``PSLVERR`` for APB, ``RRESP/BRESP`` for AXI4-Lite). diff --git a/docs/conf.py b/docs/conf.py index 3ac801d..bf9da04 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -32,9 +32,7 @@ author = "Arnav Sacheti" extensions = [ "sphinx.ext.autodoc", "sphinx.ext.napoleon", - "sphinxcontrib.wavedrom", ] -render_using_wavedrompy = True # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] @@ -42,7 +40,7 @@ templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "dev_notes", "dev_notes/**"] # -- Options for HTML output ------------------------------------------------- diff --git a/docs/configuring.rst b/docs/configuring.rst index 4e18f7a..20967ba 100644 --- a/docs/configuring.rst +++ b/docs/configuring.rst @@ -4,10 +4,10 @@ Configuring PeakRDL-BusDecoder ============================== If using the `PeakRDL command line tool `_, -some aspects of the ``busdecoder`` command have additional configuration options -available via the PeakRDL TOML file. +some aspects of the ``busdecoder`` command can be configured via the PeakRDL +TOML file. -All busdecoder-specific options are defined under the ``[busdecoder]`` TOML heading. +All busdecoder-specific options are defined under the ``[busdecoder]`` heading. .. data:: cpuifs @@ -24,22 +24,15 @@ All busdecoder-specific options are defined under the ``[busdecoder]`` TOML head cpuifs.my-cpuif-name = "my_cpuif_module:MyCPUInterfaceClass" -.. data:: default_reset +Command-Line Options +-------------------- - Choose the default style of reset signal if not explicitly - specified by the SystemRDL design. If unspecified, the default reset - is active-high and synchronous. +The following options are available on the ``peakrdl busdecoder`` command: - Choice of: - - * ``rst`` (default) - * ``rst_n`` - * ``arst`` - * ``arst_n`` - - For example: - - .. code-block:: toml - - [busdecoder] - default_reset = "arst" +* ``--cpuif``: Select the CPU interface (``apb3``, ``apb3-flat``, ``apb4``, + ``apb4-flat``, ``axi4-lite``, ``axi4-lite-flat``) +* ``--module-name``: Override the generated module name +* ``--package-name``: Override the generated package name +* ``--addr-width``: Override the slave address width +* ``--unroll``: Unroll arrayed children into discrete interfaces +* ``--max-decode-depth``: Control how far the decoder descends into hierarchy diff --git a/docs/cpuif/apb.rst b/docs/cpuif/apb.rst index e5d9998..44af40b 100644 --- a/docs/cpuif/apb.rst +++ b/docs/cpuif/apb.rst @@ -20,7 +20,7 @@ Both APB3 and APB4 standards are supported. APB3 ---- -Implements the register block using an +Implements the bus decoder using an `AMBA 3 APB `_ CPU interface. @@ -29,19 +29,19 @@ The APB3 CPU interface comes in two i/o port flavors: SystemVerilog Interface * Command line: ``--cpuif apb3`` * Interface Definition: :download:`apb3_intf.sv <../../hdl-src/apb3_intf.sv>` - * Class: :class:`peakrdl_busdecoder.cpuif.apb3.APB3_Cpuif` + * Class: :class:`peakrdl_busdecoder.cpuif.apb3.APB3Cpuif` Flattened inputs/outputs Flattens the interface into discrete input and output ports. * Command line: ``--cpuif apb3-flat`` - * Class: :class:`peakrdl_busdecoder.cpuif.apb3.APB3_Cpuif_flattened` + * Class: :class:`peakrdl_busdecoder.cpuif.apb3.APB3CpuifFlat` APB4 ---- -Implements the register block using an +Implements the bus decoder using an `AMBA 4 APB `_ CPU interface. @@ -50,10 +50,10 @@ The APB4 CPU interface comes in two i/o port flavors: SystemVerilog Interface * Command line: ``--cpuif apb4`` * Interface Definition: :download:`apb4_intf.sv <../../hdl-src/apb4_intf.sv>` - * Class: :class:`peakrdl_busdecoder.cpuif.apb4.APB4_Cpuif` + * Class: :class:`peakrdl_busdecoder.cpuif.apb4.APB4Cpuif` Flattened inputs/outputs Flattens the interface into discrete input and output ports. * Command line: ``--cpuif apb4-flat`` - * Class: :class:`peakrdl_busdecoder.cpuif.apb4.APB4_Cpuif_flattened` + * Class: :class:`peakrdl_busdecoder.cpuif.apb4.APB4CpuifFlat` diff --git a/docs/cpuif/avalon.rst b/docs/cpuif/avalon.rst deleted file mode 100644 index 7455d0a..0000000 --- a/docs/cpuif/avalon.rst +++ /dev/null @@ -1,33 +0,0 @@ -Intel Avalon -============ - -Implements the register block using an -`Intel Avalon MM `_ -CPU interface. - -The Avalon interface comes in two i/o port flavors: - -SystemVerilog Interface - * Command line: ``--cpuif avalon-mm`` - * Interface Definition: :download:`avalon_mm_intf.sv <../../hdl-src/avalon_mm_intf.sv>` - * Class: :class:`peakrdl_busdecoder.cpuif.avalon.Avalon_Cpuif` - -Flattened inputs/outputs - Flattens the interface into discrete input and output ports. - - * Command line: ``--cpuif avalon-mm-flat`` - * Class: :class:`peakrdl_busdecoder.cpuif.avalon.Avalon_Cpuif_flattened` - - -Implementation Details ----------------------- -This implementation of the Avalon protocol has the following features: - -* Interface uses word addressing. -* Supports `pipelined transfers `_ -* Responses may have variable latency - - In most cases, latency is fixed and is determined by how many retiming - stages are enabled in your design. - However if your design contains external components, access latency is - not guaranteed to be uniform. diff --git a/docs/cpuif/axi4lite.rst b/docs/cpuif/axi4lite.rst index 0fc68cb..82915e6 100644 --- a/docs/cpuif/axi4lite.rst +++ b/docs/cpuif/axi4lite.rst @@ -3,7 +3,7 @@ AMBA AXI4-Lite ============== -Implements the register block using an +Implements the bus decoder using an `AMBA AXI4-Lite `_ CPU interface. @@ -12,21 +12,22 @@ The AXI4-Lite CPU interface comes in two i/o port flavors: SystemVerilog Interface * Command line: ``--cpuif axi4-lite`` * Interface Definition: :download:`axi4lite_intf.sv <../../hdl-src/axi4lite_intf.sv>` - * Class: :class:`peakrdl_busdecoder.cpuif.axi4lite.AXI4Lite_Cpuif` + * Class: :class:`peakrdl_busdecoder.cpuif.axi4lite.AXI4LiteCpuif` Flattened inputs/outputs Flattens the interface into discrete input and output ports. * Command line: ``--cpuif axi4-lite-flat`` - * Class: :class:`peakrdl_busdecoder.cpuif.axi4lite.AXI4Lite_Cpuif_flattened` + * Class: :class:`peakrdl_busdecoder.cpuif.axi4lite.AXI4LiteCpuifFlat` -Pipelined Performance ---------------------- -This implementation of the AXI4-Lite interface supports transaction pipelining -which can significantly improve performance of back-to-back transfers. +Protocol Notes +-------------- +The AXI4-Lite adapter is intentionally simplified: -In order to support transaction pipelining, the CPU interface will accept multiple -concurrent transactions. The number of outstanding transactions allowed is automatically -determined based on the register file pipeline depth (affected by retiming options), -and influences the depth of the internal transaction response skid buffer. +* AW and W channels must be asserted together for writes. The adapter does not + support decoupled address/data for writes. +* Only a single outstanding transaction is supported. Masters should wait for + the corresponding response before issuing the next request. +* Burst transfers are not supported (single-beat transfers only), consistent + with AXI4-Lite. diff --git a/docs/cpuif/customizing.rst b/docs/cpuif/customizing.rst index 863b4dc..75091de 100644 --- a/docs/cpuif/customizing.rst +++ b/docs/cpuif/customizing.rst @@ -29,15 +29,15 @@ Rather than rewriting a new CPU interface definition, you can extend and adjust .. code-block:: python - from peakrdl_busdecoder.cpuif.axi4lite import AXI4Lite_Cpuif + from peakrdl_busdecoder.cpuif.axi4lite import AXI4LiteCpuif - class My_AXI4Lite(AXI4Lite_Cpuif): + class My_AXI4Lite(AXI4LiteCpuif): @property def port_declaration(self) -> str: # Override the port declaration text to use the alternate interface name and modport style return "axi4_lite_interface.Slave_mp s_axil" - def signal(self, name:str) -> str: + def signal(self, name: str, node=None, indexer=None) -> str: # Override the signal names to be lowercase instead return "s_axil." + name.lower() @@ -72,7 +72,7 @@ you can define your own. 2. Create a Python class that defines your CPUIF - Extend your class from :class:`peakrdl_busdecoder.cpuif.CpuifBase`. + Extend your class from :class:`peakrdl_busdecoder.cpuif.BaseCpuif`. Define the port declaration string, and provide a reference to your template file. 3. Use your new CPUIF definition when exporting. diff --git a/docs/cpuif/internal_protocol.rst b/docs/cpuif/internal_protocol.rst index a47face..d6c8d86 100644 --- a/docs/cpuif/internal_protocol.rst +++ b/docs/cpuif/internal_protocol.rst @@ -3,10 +3,10 @@ Internal CPUIF Protocol ======================= -Internally, the busdecoder generator uses a common CPU interface handshake -protocol. This strobe-based protocol is designed to add minimal overhead to the -busdecoder implementation, while also being flexible enough to support advanced -features of a variety of bus interface standards. +Internally, the bus decoder uses a small set of common request/response signals +that each CPU interface adapter must drive. This protocol is intentionally simple +and supports a single outstanding transaction at a time. The CPU interface logic +is responsible for holding request signals stable until the transaction completes. Signal Descriptions @@ -15,62 +15,49 @@ Signal Descriptions Request ^^^^^^^ cpuif_req - When asserted, a read or write transfer will be initiated. - Denotes that the following signals are valid: ``cpuif_addr``, - ``cpuif_req_is_wr``, and ``cpuif_wr_data``. + When asserted, a read or write transfer is in progress. Request signals must + remain stable until the transfer completes. - A transfer will only initiate if the relevant stall signal is not asserted. - If stalled, the request shall be held until accepted. A request's parameters - (type, address, etc) shall remain static throughout the stall. +cpuif_wr_en + When asserted alongside ``cpuif_req``, denotes a write transfer. -cpuif_addr - Byte-address of the transfer. +cpuif_rd_en + When asserted alongside ``cpuif_req``, denotes a read transfer. -cpuif_req_is_wr - If ``1``, denotes that the current transfer is a write. Otherwise transfer is - a read. +cpuif_wr_addr / cpuif_rd_addr + Byte address of the write or read transfer, respectively. cpuif_wr_data - Data to be written for the write transfer. This signal is ignored for read - transfers. + Data to be written for the write transfer. -cpuif_wr_biten - Active-high bit-level write-enable strobes. - Only asserted bit positions will change the register value during a write - transfer. - -cpuif_req_stall_rd - If asserted, and the next pending request is a read operation, then the - transfer will not be accepted until this signal is deasserted. - -cpuif_req_stall_wr - If asserted, and the next pending request is a write operation, then the - transfer will not be accepted until this signal is deasserted. +cpuif_wr_byte_en + Active-high byte-enable strobes for writes. Some CPU interfaces do not + provide byte enables and may drive this as all-ones. Read Response ^^^^^^^^^^^^^ cpuif_rd_ack Single-cycle strobe indicating a read transfer has completed. - Qualifies that the following signals are valid: ``cpuif_rd_err`` and - ``cpuif_rd_data`` + Qualifies ``cpuif_rd_err`` and ``cpuif_rd_data``. cpuif_rd_err - If set, indicates that the read transaction failed and the CPUIF logic - should return an error response if possible. + Indicates that the read transaction failed. The CPU interface should return + an error response if possible. cpuif_rd_data - Read data. Is sampled on the same cycle that ``cpuif_rd_ack`` is asserted. + Read data. Sampled on the same cycle that ``cpuif_rd_ack`` is asserted. + Write Response ^^^^^^^^^^^^^^ cpuif_wr_ack Single-cycle strobe indicating a write transfer has completed. - Qualifies that the ``cpuif_wr_err`` signal is valid. + Qualifies ``cpuif_wr_err``. cpuif_wr_err - If set, indicates that the write transaction failed and the CPUIF logic - should return an error response if possible. + Indicates that the write transaction failed. The CPU interface should return + an error response if possible. Transfers @@ -78,155 +65,7 @@ Transfers Transfers have the following characteristics: -* Only one transfer can be initiated per clock-cycle. This is implicit as there - is only one set of request signals. -* The register block implementation shall guarantee that only one response can be - asserted in a given clock cycle. Only one ``cpuif_*_ack`` signal can be - asserted at a time. -* Responses shall arrive in the same order as their corresponding request was - dispatched. - - -Basic Transfer -^^^^^^^^^^^^^^ - -Depending on the configuration of the exported register block, transfers can be -fully combinational or they may require one or more clock cycles to complete. -Both are valid and CPU interface logic shall be designed to anticipate either. - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p...."}, - {"name": "cpuif_req", "wave": "010.."}, - {"name": "cpuif_req_is_wr", "wave": "x2x.."}, - {"name": "cpuif_addr", "wave": "x2x..", "data": ["A"]}, - {}, - {"name": "cpuif_*_ack", "wave": "010.."}, - {"name": "cpuif_*_err", "wave": "x2x.."} - ], - "foot": { - "text": "Zero-latency transfer" - } - } - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p..|..."}, - {"name": "cpuif_req", "wave": "010|..."}, - {"name": "cpuif_req_is_wr", "wave": "x2x|..."}, - {"name": "cpuif_addr", "wave": "x2x|...", "data": ["A"]}, - {}, - {"name": "cpuif_*_ack", "wave": "0..|10."}, - {"name": "cpuif_*_err", "wave": "x..|2x."} - ], - "foot": { - "text": "Transfer with non-zero latency" - } - } - - -Read & Write Transactions -------------------------- - -Waveforms below show the timing relationship of simple read/write transactions. -For brevity, only showing non-zero latency transfers. - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p..|..."}, - {"name": "cpuif_req", "wave": "010|..."}, - {"name": "cpuif_req_is_wr", "wave": "x0x|..."}, - {"name": "cpuif_addr", "wave": "x3x|...", "data": ["A"]}, - {}, - {"name": "cpuif_rd_ack", "wave": "0..|10."}, - {"name": "cpuif_rd_err", "wave": "x..|0x."}, - {"name": "cpuif_rd_data", "wave": "x..|5x.", "data": ["D"]} - ], - "foot": { - "text": "Read Transaction" - } - } - - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p..|..."}, - {"name": "cpuif_req", "wave": "010|..."}, - {"name": "cpuif_req_is_wr", "wave": "x1x|..."}, - {"name": "cpuif_addr", "wave": "x3x|...", "data": ["A"]}, - {"name": "cpuif_wr_data", "wave": "x5x|...", "data": ["D"]}, - {}, - {"name": "cpuif_wr_ack", "wave": "0..|10."}, - {"name": "cpuif_wr_err", "wave": "x..|0x."} - ], - "foot": { - "text": "Write Transaction" - } - } - - -Transaction Pipelining & Stalls -------------------------------- -If the CPU interface supports it, read and write operations can be pipelined. - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p......"}, - {"name": "cpuif_req", "wave": "01..0.."}, - {"name": "cpuif_req_is_wr", "wave": "x0..x.."}, - {"name": "cpuif_addr", "wave": "x333x..", "data": ["A1", "A2", "A3"]}, - {}, - {"name": "cpuif_rd_ack", "wave": "0.1..0."}, - {"name": "cpuif_rd_err", "wave": "x.0..x."}, - {"name": "cpuif_rd_data", "wave": "x.555x.", "data": ["D1", "D2", "D3"]} - ] - } - -It is very likely that the transfer latency of a read transaction will not -be the same as a write for a given register block configuration. Typically read -operations will be more deeply pipelined. This latency asymmetry would create a -hazard for response collisions. - -In order to eliminate this hazard, additional stall signals (``cpuif_req_stall_rd`` -and ``cpuif_req_stall_wr``) are provided to delay the next incoming transfer -request if necessary. When asserted, the CPU interface shall hold the next pending -request until the stall is cleared. - -For non-pipelined CPU interfaces that only allow one outstanding transaction at a time, -these stall signals can be safely ignored. - -In the following example, the busdecoder is configured such that: - -* A read transaction takes 1 clock cycle to complete -* A write transaction takes 0 clock cycles to complete - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p......."}, - {"name": "cpuif_req", "wave": "01.....0"}, - {"name": "cpuif_req_is_wr", "wave": "x1.0.1.x"}, - {"name": "cpuif_addr", "wave": "x33443.x", "data": ["W1", "W2", "R1", "R2", "W3"]}, - {"name": "cpuif_req_stall_wr", "wave": "0...1.0."}, - {}, - {"name": "cpuif_rd_ack", "wave": "0...220.", "data": ["R1", "R2"]}, - {"name": "cpuif_wr_ack", "wave": "0220..20", "data": ["W1", "W2", "W3"]} - ] - } - -In the above waveform, observe that: - -* The ``R2`` read request is not affected by the assertion of the write stall, - since the write stall only applies to write requests. -* The ``W3`` write request is stalled for one cycle, and is accepted once the stall is cleared. +* Only one outstanding transaction is supported. +* The CPU interface must hold ``cpuif_req`` and request parameters stable until + the corresponding ``cpuif_*_ack`` is asserted. +* Responses shall arrive in the same order as requests. diff --git a/docs/cpuif/introduction.rst b/docs/cpuif/introduction.rst index cc34574..4720f46 100644 --- a/docs/cpuif/introduction.rst +++ b/docs/cpuif/introduction.rst @@ -2,16 +2,17 @@ Introduction ============ The CPU interface logic layer provides an abstraction between the -application-specific bus protocol and the internal register file logic. -When exporting a design, you can select from a variety of popular CPU interface -protocols. These are described in more detail in the pages that follow. +application-specific bus protocol and the internal bus decoder logic. +When exporting a design, you can select from supported CPU interface protocols. +These are described in more detail in the pages that follow. Bus Width ^^^^^^^^^ -The CPU interface bus width is automatically determined from the contents of the -design being exported. The bus width is equal to the widest ``accesswidth`` -encountered in the design. +The CPU interface bus width is inferred from the contents of the design. +It is intended to be equal to the widest ``accesswidth`` encountered in the +design. If the exported addrmap contains only external components, the width +cannot be inferred and will default to 32 bits. Addressing @@ -32,5 +33,6 @@ For example, consider a fictional AXI4-Lite device that: - 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. -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. +By default, the bit-width of the address bus will be the minimum size to span the +contents of the decoded address space. If needed, the address width can be +overridden to a larger range using ``--addr-width``. diff --git a/docs/cpuif/passthrough.rst b/docs/cpuif/passthrough.rst deleted file mode 100644 index 9426e06..0000000 --- a/docs/cpuif/passthrough.rst +++ /dev/null @@ -1,10 +0,0 @@ -CPUIF Passthrough -================= - -This CPUIF mode bypasses the protocol converter stage and directly exposes the -internal CPUIF handshake signals to the user. - -* Command line: ``--cpuif passthrough`` -* Class: :class:`peakrdl_busdecoder.cpuif.passthrough.PassthroughCpuif` - -For more details on the protocol itself, see: :ref:`cpuif_protocol`. diff --git a/docs/faq.rst b/docs/faq.rst deleted file mode 100644 index 6b082d6..0000000 --- a/docs/faq.rst +++ /dev/null @@ -1,131 +0,0 @@ -Frequently Asked Questions -========================== - -Why isn't there an option for a flat non-struct hardware interface? -------------------------------------------------------------------- -SystemRDL is inherently a very hierarchical language. -For small register blocks, flattening the hardware interface may be acceptable, -but this ends up scaling very poorly as the design becomes larger and has more -complex hierarchy. -Using struct compositions for the hardware interface has the benefit of -preserving conceptual hierarchy and arrays exactly as defined in the original -SystemRDL. - -How do I know I connected everything? Structs are harder to review -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Initially this can be daunting, but fortunately the tool has an option to generate a -flattened hardware interface report upon export. Try using the ``--hwif-report`` -command line option when exporting. This is the easiest way to quickly -understand the structure of the hardware interface. - - - -Why does the tool generate un-packed structs? I prefer packed structs. ----------------------------------------------------------------------- -Packed structs are great when describing vectors that have bit-level structure. -In this tool, the use of un-packed structs is intentional since the hardware -interface is not something that is meant to be bit-accessible. In the case of -the hardware interface structs, using a packed struct is semantically inappropriate. - -... Then how can I initialize the struct? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -We get this request most often because designers want to initialize the ``hwif_in`` -struct with a simple assignment: - -.. code:: systemverilog - - always_comb begin - hwif_in = '0; - end - -Of course since the struct actually is **unpacked**, this will result in a -compile error which usually leads to the inappropriate assumption that it ought -to be packed. (See this amusing blog post about `X/Y problems `_) - -If your goal is to initialize the packed struct, fortunately SystemVerilog already -has syntax to do this: - -.. code:: systemverilog - - always_comb begin - hwif_in = '{default: '0}; - end - -This is lesser-known syntax, but still very well supported by synthesis -tools, and is the recommended way to handle this. - -... What if I want to assign it to a bit-vector? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Assigning the hwif struct to a bit-vector is strongly discouraged. This tool makes -no guarantees regarding the field ordering of the hwif structure, so doing so -should be considered functionally dangerous. - -That said, if you still need to do this, it is still trivially possible to -without requiring packed structs. Instead, use the SystemVerilog streaming operator: - -.. code:: systemverilog - - my_packed_vector = {<<{hwif_out}}; - - -... Why are unpacked structs preferred? -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In the case of the hardware interface ports, unpacked structs help prevent -mistakes that are very easy to make. -Consider the following situation - a designer has a field that sets the following -properties: ``sw=rw; hw=rw; we;``, and wants to assign the hardware input value, -so they erroneously do the following assignment in Verilog: - -.. code:: systemverilog - - assign hwif_in.my_register.my_field = ; - -This is actually a bug since the ``my_field`` member is actually a struct that -has two members: ``we`` and ``next``. If this were a packed struct, this would -silently compile and you would potentially have a bug that may not be noticed -(depending on how thorough the test campaign is). -With an unpacked struct, this gets flagged immediately as a compile error since -the assignment is invalid. - -The designer may have simply forgotten that the field is an aggregate of multiple -members and intended to do the following: - -.. code:: systemverilog - - assign hwif.my_register.my_field.next = ; - assign hwif.my_register.my_field.we = ; - - -The generated output does not match our organization's coding style -------------------------------------------------------------------- -SystemVerilog coding styles vary wildly, and unfortunately there is little -consensus on this topic within the digital design community. - -The output generated by PeakRDL-BusDecoder strives to be as human-readable as possible, -and follow consistent indentation and styling. We do our best to use the most -widely accepted coding style, but since this is a very opinionated space, it is -impossible to satisfy everyone. - -In general, we strive to follow the -`SystemVerilog style guide by lowRISC `_, -but may deviate in some areas if not practical or would impose excessive complexity on the code generator. - - -The lint tool I am using is flagging violations in generated code ------------------------------------------------------------------ -Code linting tools are a great way to check for user-error, flag inconsistencies, -and enforce best-practices within an organization. In many cases, linter tools -may be configured to also enforce stylistic preferences. -Unfortunately just like coding styles, lint rules can often be more -opinionated than practical. - -In general, we will not address lint violations unless they flag actual -structural issues or semantically dangerous code. -Stylistic violations that pose no actual danger to the correctness of the design -will rarely be addressed, especially if the change would add unreasonable -complexity to the tool. - -If you encounter a lint violation, please carefully review and consider waiving -it if it does not pose an actual danger. If you still believe it is a problem, -please let us know by `submitting an issue `_ -that describes the problem. diff --git a/docs/hwif.rst b/docs/hwif.rst deleted file mode 100644 index 3bf50db..0000000 --- a/docs/hwif.rst +++ /dev/null @@ -1,61 +0,0 @@ -Hardware Interface ------------------- - -The generated register block will present the entire hardware interface to the user -using two struct ports: - -* ``hwif_in`` -* ``hwif_out`` - -All field inputs and outputs as well as signals are consolidated into these -struct ports. The presence of each depends on the specific contents of the design -being exported. - - -Using structs for the hardware interface has the following benefits: - -* Preserves register map component grouping, arrays, and hierarchy. -* Avoids naming collisions and cumbersome signal name flattening. -* Allows for more natural mapping and distribution of register block signals to a design's hardware components. -* Use of unpacked arrays/structs prevents common assignment mistakes as they are enforced by the compiler. - - -Structs are organized as follows: ``hwif_out..`` - -For example, a simple design such as: - -.. code-block:: systemrdl - - addrmap my_design { - reg { - field { - sw = rw; - hw = rw; - we; - } my_field; - } my_reg[2]; - }; - -... results in the following struct members: - -.. code-block:: text - - hwif_out.my_reg[0].my_field.value - hwif_in.my_reg[0].my_field.next - hwif_in.my_reg[0].my_field.we - hwif_out.my_reg[1].my_field.value - hwif_in.my_reg[1].my_field.next - hwif_in.my_reg[1].my_field.we - -For brevity in this documentation, hwif features will be described using shorthand -notation that omits the hierarchical path: ``hwif_out..`` - - -.. important:: - - The PeakRDL tool makes no guarantees on the field order of the hwif structs. - For this reason, it is strongly recommended to always access struct members - directly, by name. - - If using the SystemVerilog streaming operator to assign the hwif struct to a - packed vector, be extremely careful to avoid assumptions on the resulting bit-position of a field. diff --git a/docs/index.rst b/docs/index.rst index 9d9f59a..7a74a64 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,28 +1,34 @@ Introduction ============ -PeakRDL-BusDecoder is a free and open-source bus decoder generator for hierarchical register address maps. -This code generator translates your SystemRDL register description into a synthesizable -SystemVerilog RTL module that decodes CPU interface transactions and routes them to -multiple sub-address spaces (child addrmaps). This is particularly useful for: +PeakRDL-BusDecoder is a free and open-source bus decoder generator for hierarchical +SystemRDL address maps. It produces a synthesizable SystemVerilog RTL module that +accepts a single CPU interface (slave side) and fans transactions out to multiple +child address spaces (master side). + +This tool **does not** generate register storage or field logic. It is strictly a +bus-routing layer that decodes addresses and forwards requests to child blocks. + +This is particularly useful for: * Creating hierarchical register maps with multiple sub-components * Splitting a single CPU interface bus to serve multiple independent register blocks -* Organizing large register designs into logical sub-address spaces +* Organizing large address spaces into logical sub-regions * Implementing address decode logic for multi-drop bus architectures The generated bus decoder provides: * Fully synthesizable SystemVerilog RTL (IEEE 1800-2012) -* Support for many popular CPU interface protocols (AMBA APB, AXI4-Lite, and more) +* A top-level slave CPU interface and per-child master CPU interfaces * Address decode logic that routes transactions to child address maps -* Configurable pipelining options for designs with fast clock rates -* Broad support for SystemRDL 2.0 features +* Support for APB3, APB4, and AXI4-Lite (plus plugin-defined CPU interfaces) +* Configurable decode depth and array unrolling Quick Start ----------- -The easiest way to use PeakRDL-BusDecoder is via the `PeakRDL command line tool `_: +The easiest way to use PeakRDL-BusDecoder is via the +`PeakRDL command line tool `_: .. code-block:: bash @@ -32,6 +38,20 @@ The easiest way to use PeakRDL-BusDecoder is via the `PeakRDL command line tool # Export! peakrdl busdecoder atxmega_spi.rdl -o busdecoder/ --cpuif axi4-lite +The exporter writes two files: + +* A SystemVerilog module (the bus decoder) +* A SystemVerilog package (constants like data width and per-child address widths) + +Key command-line options: + +* ``--cpuif``: Select the CPU interface (``apb3``, ``apb3-flat``, ``apb4``, ``apb4-flat``, ``axi4-lite``, ``axi4-lite-flat``) +* ``--module-name``: Override the generated module name +* ``--package-name``: Override the generated package name +* ``--addr-width``: Override the slave address width +* ``--unroll``: Unroll arrayed children into discrete interfaces +* ``--max-decode-depth``: Control how far the decoder descends into hierarchy + Looking for VHDL? ----------------- @@ -55,10 +75,8 @@ Links self architecture - hwif configuring limitations - faq licensing api @@ -69,29 +87,5 @@ Links cpuif/introduction cpuif/apb cpuif/axi4lite - cpuif/avalon - cpuif/passthrough cpuif/internal_protocol cpuif/customizing - -.. toctree:: - :hidden: - :caption: SystemRDL Properties - - props/field - props/reg - props/addrmap - props/signal - props/rhs_props - -.. toctree:: - :hidden: - :caption: Other SystemRDL Features - - rdl_features/external - -.. toctree:: - :hidden: - :caption: Extended Properties - - udps/intro diff --git a/docs/limitations.rst b/docs/limitations.rst index 2f0afc4..3911e8b 100644 --- a/docs/limitations.rst +++ b/docs/limitations.rst @@ -1,53 +1,47 @@ Known Limitations ================= -Not all SystemRDL features are supported by this exporter. For a listing of -supported properties, see the appropriate property listing page in the sections -that follow. +The busdecoder exporter intentionally focuses on address decode and routing. +Some SystemRDL features are ignored, and a few are explicitly disallowed. -Alias Registers ---------------- -Registers instantiated using the ``alias`` keyword are not supported yet. +Address Alignment +----------------- +All address offsets and array strides must be aligned to the CPU interface data +bus width (in bytes). Misaligned offsets/strides are rejected. -Unaligned Registers -------------------- -All address offsets & strides shall be a multiple of the cpuif bus width used. Specifically: - -* Bus width is inferred by the maximum accesswidth used in the busdecoder. -* Each component's address and array stride shall be aligned to the bus width. +Wide Registers +-------------- +If a register is wider than its ``accesswidth`` (a multi-word register), its +``accesswidth`` must match the CPU interface data width. Multi-word registers +with a smaller accesswidth are not supported. -Uniform accesswidth -------------------- -All registers within a register block shall use the same accesswidth. +Fields Spanning Sub-Words +------------------------- +If a field spans multiple sub-words of a wide register: -One exception is that registers with regwidth that is narrower than the cpuif -bus width are permitted, provided that their regwidth is equal to their accesswidth. +* Software-writable fields must have write buffering enabled +* Fields with ``onread`` side-effects must have read buffering enabled -For example: +These rules are enforced to avoid ambiguous multi-word access behavior. -.. code-block:: systemrdl - // (Largest accesswidth used is 32, therefore the CPUIF bus width is 32) +External Boundary References +---------------------------- +Property references are not allowed to cross the internal/external boundary of +the exported addrmap. References must point to components that are internal to +the busdecoder being generated. - reg { - regwidth = 32; - accesswidth = 32; - } reg_a @ 0x00; // OK. Regular 32-bit register +CPU Interface Reset Location +---------------------------- +Only ``cpuif_reset`` signals instantiated at the top-level addrmap (or above) +are honored. Nested ``cpuif_reset`` signals are ignored. - reg { - regwidth = 64; - accesswidth = 32; - } reg_b @ 0x08; // OK. "Wide" register of 64-bits, but is accessed using 32-bit subwords - reg { - regwidth = 8; - accesswidth = 8; - } reg_c @ 0x10; // OK. Is aligned to the cpuif bus width +Unsupported Properties +---------------------- +The following SystemRDL properties are explicitly rejected: - reg { - regwidth = 32; - accesswidth = 8; - } bad_reg @ 0x14; // NOT OK. accesswidth conflicts with cpuif width +* ``sharedextbus`` on addrmap/regfile components diff --git a/docs/props/addrmap.rst b/docs/props/addrmap.rst deleted file mode 100644 index 888056a..0000000 --- a/docs/props/addrmap.rst +++ /dev/null @@ -1,28 +0,0 @@ -Addrmap/Regfile Properties -========================== - -.. note:: Any properties not explicitly listed here are either implicitly - supported, or are not relevant to the busdecoder exporter and are ignored. - - -errextbus ---------- -|NO| - -sharedextbus ------------- -|NO| - - --------------------------------------------------------------------------------- - -Addrmap Properties -================== - -bigendian/littleendian ----------------------- -|NO| - -rsvdset -------- -|NO| diff --git a/docs/props/field.rst b/docs/props/field.rst deleted file mode 100644 index 2e869ad..0000000 --- a/docs/props/field.rst +++ /dev/null @@ -1,491 +0,0 @@ -Field Properties -================ - -.. note:: Any properties not explicitly listed here are either implicitly - supported, or are not relevant to the busdecoder exporter and are ignored. - -Software Access Properties --------------------------- - -onread/onwrite -^^^^^^^^^^^^^^ - -All onread/onwrite actions are supported (except for ruser/wuser) - -rclr/rset -^^^^^^^^^ - -See ``onread``. These are effectively aliases of the onread property. - -singlepulse -^^^^^^^^^^^ - -If set, field will get cleared back to zero after being written. - -.. wavedrom:: - - {"signal": [ - {"name": "clk", "wave": "p....."}, - {"name": "", "wave": "0.10.."}, - {"name": "hwif_out..value", "wave": "0..10."} - ]} - -sw -^^^ -All sw access modes are supported except for ``w1`` and ``rw1``. - -swacc -^^^^^ - -If true, infers an output signal ``hwif_out..swacc`` that is asserted when -accessed by software. Specifically, on the same clock cycle that the field is -being sampled during a software read operation, or as it is being written. - -.. wavedrom:: - - {"signal": [ - {"name": "clk", "wave": "p...."}, - {"name": "hwif_in..next", "wave": "x.=x.", "data": ["D"]}, - {"name": "hwif_out..swacc", "wave": "0.10."} - ]} - - -swmod -^^^^^ - -If true, infers an output signal ``hwif_out..swmod`` that is asserted as the -field is being modified by software. This can be due to a software write -operation, or a software read operation that has clear/set side-effects. - - -.. wavedrom:: - - {"signal": [ - {"name": "clk", "wave": "p....."}, - {"name": "hwif_out..value", "wave": "=..=..", "data": ["old", "new"]}, - {"name": "hwif_out..swmod", "wave": "0.10.."} - ]} - - -swwe/swwel -^^^^^^^^^^ - -Provides a mechanism that allows hardware to override whether the field is -writable by software. - -boolean - If True, infers an input signal ``hwif_in..swwe`` or ``hwif_in..swwel``. - -reference - Single-bit reference controls field's behavior. - - -woclr/woset -^^^^^^^^^^^ -See ``onwrite``. These are effectively aliases of the onwrite property. - --------------------------------------------------------------------------------- - -Hardware Access Properties --------------------------- - -anded/ored/xored -^^^^^^^^^^^^^^^^ -If true, infers the existence of output signal: ``hwif_out..anded``, -``hwif_out..ored``, ``hwif_out..xored`` - - -hw -^^^ -Controls hardware access to the field. - -If readable, enables output signal ``hwif_out..value``. If writable, enables -input ``hwif_in..next``. - -Hardware-writable fields can optionally define the ``next`` property which replaces -the inferred ``hwif_in..next`` input with an alternate reference. - - -hwclr/hwset -^^^^^^^^^^^ -If both ``hwclr`` and ``hwset`` properties are used, and both are asserted at -the same clock cycle, then ``hwset`` will take precedence. - -boolean - If true, infers the existence of input signal: ``hwif_in..hwclr``, ``hwif_in..hwset`` - -reference - Reference to any single-bit internal object to drive this control. - - -hwenable/hwmask -^^^^^^^^^^^^^^^ -Reference to a component that provides bit-level control of hardware writeability. - - -we/wel -^^^^^^ -Write-enable control from hardware interface. - -If true, infers the existence of input signal: ``hwif_in..we``, ``hwif_in..wel`` - -.. wavedrom:: - - {"signal": [ - {"name": "clk", "wave": "p...."}, - {"name": "hwif_in..next", "wave": "x.=x.", "data": ["D"]}, - {"name": "hwif_in..we", "wave": "0.10."}, - {"name": "hwif_in..wel", "wave": "1.01."}, - {"name": "", "wave": "x..=.", "data": ["D"]} - ]} - -boolean - If true, infers the existence of input signal ``hwif_in..we`` or ``hwif_in..wel`` - -reference - Reference to any single-bit internal object to drive this control. - --------------------------------------------------------------------------------- - -Counter Properties ------------------- - -counter -^^^^^^^ -If true, marks this field as a counter. The counter direction is inferred based -based on which properties are assigned. By default, an up-counter is implemented. -If any of the properties associated with an up-counter are used, then up-counting -capabilities will be implemented. The same is true for down-counters and up/down -counters. - -Unless alternate control signals are specified, the existence of input signals -``hwif_in..incr`` and ``hwif_in..decr`` will be inferred depending on the type -of counter described. - - -incr -^^^^ -Assign a reference to an alternate control signal to increment the counter. -If assigned, the inferred ``hwif_in..incr`` input will not be generated. - -incrsaturate/saturate -^^^^^^^^^^^^^^^^^^^^^ -If assigned, indicates that the counter will saturate instead of wrapping. -If an alternate saturation point is specified, the counter value will be -adjusted so that it does not exceed that limit, even after non-increment actions. - -boolean - If true, saturation point is at the counter's maximum count value. (2^width - 1) - -integer - Specify a static saturation value. - -reference - Specify a dynamic saturation value. - - -incrthreshold/threshold -^^^^^^^^^^^^^^^^^^^^^^^ -If assigned, infers a ``hwif_out..incrthreshold`` output signal. This signal is -asserted if the counter value is greater or equal to the threshold. - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p......"}, - {"name": "hwif_in..incr", "wave": "01...0."}, - {"name": "", "wave": "=.=3==..", "data": [4,5,6,7,8,9]}, - {"name": "hwif_out..incrthreshold", "wave": "0..1...."} - ], - "foot": { - "text": "Example where incrthreshold = 6" - } - } - - -boolean - If true, threshold is the counter's maximum count value. (2^width - 1) - -integer - Specify a static threshold value. - -reference - Specify a dynamic threshold value. - - -incrvalue -^^^^^^^^^ -Override the counter's increment step size. - -integer - Specify a static increment step size. - -reference - Reference a component that controls the step size. - -incrwidth -^^^^^^^^^ -If assigned, infers an input signal ``hwif_in..incrvalue``. The value of this -property defines the signal's width. - - -overflow -^^^^^^^^ -If true, infers an output signal ``hwif_out..overflow`` that is asserted when -the counter is about to wrap. - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p......."}, - {"name": "hwif_in..incr", "wave": "0101010."}, - {"name": "", "wave": "=.=.=.=.", "data": [14,15,0,1]}, - {"name": "hwif_out..overflow", "wave": "0..10..."} - ], - "foot": { - "text": "A 4-bit counter overflowing" - } - } - - -decr -^^^^ -Assign a reference to an alternate control signal to decrement the counter. -If assigned, the inferred ``hwif_in..decr`` input will not be generated. - - -decrsaturate -^^^^^^^^^^^^ -If assigned, indicates that the counter will saturate instead of wrapping. -If an alternate saturation point is specified, the counter value will be -adjusted so that it does not exceed that limit, even after non-decrement actions. - -boolean - If true, saturation point is when the counter reaches 0. - -integer - Specify a static saturation value. - -reference - Specify a dynamic saturation value. - - -decrthreshold -^^^^^^^^^^^^^ -If assigned, infers a ``hwif_out..decrthreshold`` output signal. This signal is -asserted if the counter value is less than or equal to the threshold. - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p......"}, - {"name": "hwif_in..decr", "wave": "01...0."}, - {"name": "", "wave": "=.=3==.", "data": [9,8,7,6,5,4]}, - {"name": "hwif_out..decrthreshold", "wave": "0..1..."} - ], - "foot": { - "text": "Example where incrthreshold = 7" - } - } - - -boolean - If true, threshold is 0. - -integer - Specify a static threshold value. - -reference - Specify a dynamic threshold value. - - -decrvalue -^^^^^^^^^ -Override the counter's decrement step size. - -integer - Specify a static step size. - -reference - Reference to a component that controls the step size. - - -decrwidth -^^^^^^^^^ -If assigned, infers an input signal ``hwif_in..decrvalue``. The value of this -property defines the signal's width. - - -underflow -^^^^^^^^^ -If true, infers an output signal ``hwif_out..underflow`` that is asserted when -the counter is about to wrap. - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p......."}, - {"name": "hwif_in..decr", "wave": "0101010."}, - {"name": "", "wave": "=.=.=.=.", "data": [1,0,15,14]}, - {"name": "hwif_out..underflow", "wave": "0..10..."} - ], - "foot": { - "text": "A 4-bit counter underflowing" - } - } - --------------------------------------------------------------------------------- - -Interrupt Properties --------------------- - -intr -^^^^ - -If set, this field becomes an interrupt field. -The enclosing register infers an output signal ``hwif_out..intr`` which denotes -that an interrupt is active. This is an or-reduction of all interrupt fields -after applying the appropriate ``enable`` or ``mask`` to the field value. - -level (default) - Interrupt is level-sensitive. If a bit on the field's ``hwif_in..next`` input - is '1', it will trigger an interrupt event. - -posedge - If a bit on the field's ``hwif_in..next`` input transitions from '0' to '1', - it will trigger an interrupt event. This transition shall still be synchronous - to the register block's clock. - -negedge - If a bit on the field's ``hwif_in..next`` input transitions from '1' to '0', - it will trigger an interrupt event. This transition shall still be synchronous - to the register block's clock. - -bothedge - If a bit on the field's ``hwif_in..next`` input transitions from '0' to '1' or '1' to '0', - it will trigger an interrupt event. This transition shall still be synchronous - to the register block's clock. - -nonsticky - Interrupt event is not sticky. - - -enable -^^^^^^ -Reference to a field or signal that, if set to 1, define which bits in the field -are used to assert an interrupt. - - -mask -^^^^ -Reference to a field or signal that, if set to 1, define which bits in the field -are *not* used to assert an interrupt. - - -haltenable -^^^^^^^^^^ -Reference to a field or signal that, if set to 1, define which bits in the field -are used to assert the halt output. - -If this property is set, the enclosing register will infer a ``hwif_out..halt`` output. - - -haltmask -^^^^^^^^ -Reference to a field or signal that, if set to 1, define which bits in the field -are *not* used to assert the halt output. - -If this property is set, the enclosing register will infer a ``hwif_out..halt`` output. - - -stickybit -^^^^^^^^^ -When an interrupt trigger occurs, a stickybit field will set the corresponding -bit to '1' and hold it until it is cleared by a software access. - -The interrupt trigger depends on the interrupt type. By default, interrupts are -level-sensitive, but the interrupt modifiers allow for edge-sensitive triggers as -well. - -The waveform below demonstrates a level-sensitive interrupt: - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p....."}, - {"name": "hwif_in..next", "wave": "010..."}, - {"name": "", "wave": "0.1..."} - ] - } - - -sticky -^^^^^^ -Unlike ``stickybit`` fields, a sticky field will latch an entire value. The -value is latched as soon as ``hwif_in..next`` is nonzero, and is held until the -field contents are cleared back to 0 by a software access. - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p....."}, - {"name": "hwif_in..next", "wave": "23.22.", "data": [0,10,20,30]}, - {"name": "", "wave": "2.3...", "data": [0, 10]} - ] - } - - --------------------------------------------------------------------------------- - -Misc ----- - -encode -^^^^^^ -If assigned a user-defined enumeration, the resulting package file will include -its definition. Due to limitations from type-strictness rules in SystemVerilog, -the field will remain as a ``logic`` datatype. - - -next -^^^^ -If assigned, replaces the inferred ``hwif_in..next`` input with an explicit reference. - - -paritycheck -^^^^^^^^^^^ -If set, enables parity checking for this field. - -Adds a ``parity_error`` output signal to the module. - -.. note:: - - If this field does not implement storage, the ``partycheck`` property is ignored. - - - -precedence -^^^^^^^^^^ -Control whether hardware or software has precedence when field value update -contention occurs. Software has precedence by default. - -reset -^^^^^ -Control the reset value of the field's storage element. -If not specified, the field will not be reset. - -integer - Static reset value - -reference - Reference to a dynamic reset value. - -resetsignal -^^^^^^^^^^^ -Provide an alternate reset trigger for this field. diff --git a/docs/props/reg.rst b/docs/props/reg.rst deleted file mode 100644 index 8472f07..0000000 --- a/docs/props/reg.rst +++ /dev/null @@ -1,14 +0,0 @@ -Register Properties -=================== - -.. note:: Any properties not explicitly listed here are either implicitly - supported, or are not relevant to the busdecoder exporter and are ignored. - -accesswidth ------------ -Control the software access width. The register block's CPUIF bus width is -determined by the maximum accesswidth encountered. - -regwidth --------- -Control the bit-width of the register. diff --git a/docs/props/rhs_props.rst b/docs/props/rhs_props.rst deleted file mode 100644 index 6234bd5..0000000 --- a/docs/props/rhs_props.rst +++ /dev/null @@ -1,182 +0,0 @@ -RHS Property References -======================= - -SystemRDL allows some properties to be referenced in the righthand-side of -property assignment expressions: - - .. code-block:: systemrdl - - some_property = my_reg.my_field -> some_property; - -The official SystemRDL spec refers to these as "Ref targets" in Table G1, but -unfortunately does not describe their semantics in much detail. - -The text below describes the interpretations used for this exporter. - --------------------------------------------------------------------------------- - -Field ------ - -field -> swacc -^^^^^^^^^^^^^^ -Single-cycle strobe that indicates the field is being accessed by software -(read or write). - - -field -> swmod -^^^^^^^^^^^^^^^ -Single-cycle strobe that indicates the field is being modified during a software -access operation. - - -field -> swwe/swwel -^^^^^^^^^^^^^^^^^^^ -Represents the signal that controls the field's swwe/swwel behavior. - - -field -> anded/ored/xored -^^^^^^^^^^^^^^^^^^^^^^^^^ -Represents the current and/or/xor reduction of the field's value. - - -field -> hwclr/hwset -^^^^^^^^^^^^^^^^^^^^ -|EX| - -Represents the signal that controls the field's hwclr/hwset behavior. - - -field -> hwenable/hwmask -^^^^^^^^^^^^^^^^^^^^^^^^ -Represents the signal that controls the field's hwenable/hwmask behavior. - -field -> we/wel -^^^^^^^^^^^^^^^ -Represents the signal that controls the field's we/wel behavior. - -field -> next -^^^^^^^^^^^^^ -|EX| - -field -> reset -^^^^^^^^^^^^^^ -Represents the value that was assigned to this property. - -field -> resetsignal -^^^^^^^^^^^^^^^^^^^^ -Represents the value that was assigned to this property. - --------------------------------------------------------------------------------- - -Field Counter Properties ------------------------- - -field -> incr -^^^^^^^^^^^^^ -Represents the signal that controls the field's counter increment control. - - -field -> incrsaturate/saturate -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Represents the internal 1-bit event signal that indicates whether the counter is saturated -at its saturation value. - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p......"}, - {"name": "hwif_in..decr", "wave": "0101010"}, - {"name": "", "wave": "=.=....", "data": [1,0]}, - {"name": "", "wave": "0.1...."} - ], - "foot": { - "text": "A 4-bit counter saturating" - } - } - - -field -> incrthreshold/threshold -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Represents the 1-bit event signal that indicates whether the counter has met or -exceeded its incrthreshold. - -field -> incrvalue -^^^^^^^^^^^^^^^^^^ -Represents the value that was assigned to this property. - -field -> overflow -^^^^^^^^^^^^^^^^^ -Represents the event signal that is asserted when the counter is about to wrap. - -field -> decr -^^^^^^^^^^^^^ -Represents the signal that controls the field's counter decrement control. - -field -> decrsaturate -^^^^^^^^^^^^^^^^^^^^^ -Represents the internal 1-bit event signal that indicates whether the counter is saturated -at its saturation value. - -.. wavedrom:: - - { - "signal": [ - {"name": "clk", "wave": "p......"}, - {"name": "hwif_in..incr", "wave": "0101010"}, - {"name": "", "wave": "=.=....", "data": [14,15]}, - {"name": "", "wave": "0.1...."} - ], - "foot": { - "text": "A 4-bit counter saturating" - } - } - -field -> decrthreshold -^^^^^^^^^^^^^^^^^^^^^^ -Represents the 1-bit event signal that indicates whether the counter has met or -exceeded its incrthreshold. - -field -> decrvalue -^^^^^^^^^^^^^^^^^^ -Represents the value that was assigned to this property. - -field -> underflow -^^^^^^^^^^^^^^^^^^ -Represents the event signal that is asserted when the counter is about to wrap. - --------------------------------------------------------------------------------- - -Field Interrupt Properties --------------------------- - -field -> enable -^^^^^^^^^^^^^^^ -Represents the value that was assigned to this property. - -field -> mask -^^^^^^^^^^^^^ -Represents the value that was assigned to this property. - -field -> haltenable -^^^^^^^^^^^^^^^^^^^ -Represents the value that was assigned to this property. - -field -> haltmask -^^^^^^^^^^^^^^^^^ -Represents the value that was assigned to this property. - - --------------------------------------------------------------------------------- - -Register --------- - -reg -> intr -^^^^^^^^^^^ -References the register's ``hwif_out..intr`` signal. - -reg -> halt -^^^^^^^^^^^ -References the register's ``hwif_out..halt`` signal. diff --git a/docs/props/signal.rst b/docs/props/signal.rst deleted file mode 100644 index 2a34ead..0000000 --- a/docs/props/signal.rst +++ /dev/null @@ -1,28 +0,0 @@ -Signal Properties -================= - -.. note:: Any properties not explicitly listed here are either implicitly - supported, or are not relevant to the busdecoder exporter and are ignored. - - -activehigh/activelow --------------------- -Only relevant for signals used as resets. Defines the reset signal's polarity. - - -sync/async ----------- -Only supported for signals used as resets to infer edge-sensitive reset. -Ignored in all other contexts. - - -cpuif_reset ------------ -Specify that this signal shall be used as alternate reset signal for the CPU -interface for this busdecoder. - - -field_reset ------------ -Specify that this signal is used as an alternate reset signal for all fields -instantiated in sub-hierarchies relative to this signal. diff --git a/docs/rdl_features/external.rst b/docs/rdl_features/external.rst deleted file mode 100644 index ee12f39..0000000 --- a/docs/rdl_features/external.rst +++ /dev/null @@ -1,155 +0,0 @@ -External Components -=================== -SystemRDL allows some component instances to be defined as "external" elements -of an address space definition. In the context of this busdecoder generator, -the implementation of an external component is left up to the designer. When -generating the RTL for a busdecoder, the implementations of external components -are omitted and instead a user-interface is presented on the -``hwif_in``/``hwif_out`` i/o structs. - -External component signals on the hardware interface closely follow the semantics -of the :ref:`cpuif_protocol`. - - -Things you should know ----------------------- - -* By default external ``hwif_out`` signals are driven combinationally. An - optional output retiming stage can be enabled if needed. -* Due to the uncertain access latency of external components, the busdecoder will - only issue one outstanding transaction to an external component at a time. - This is enforced even if the CPUIF is capable of pipelined accesses such as - AXI4-Lite. - - -External Registers ------------------- -External registers can be useful if it is necessary to implement a register that -cannot easily be expressed using SystemRDL semantics. This could be a unique -access policy, or FIFO-like push/pop registers. - -External registers are annotated as such by using the ``external`` keyword: - -.. code-block:: systemrdl - - // An internal register - my_reg int_reg; - - // An external register - external my_reg ext_reg; - -Request -^^^^^^^ -hwif_out..req - When asserted, a read or write transfer will be initiated. - Qualifies all other request signals. - - If the register is wide (``regwidth`` > ``accesswidth``), then the - ``hwif_out..req`` will consist of multiple bits, representing the access - strobe for each sub-word of the register. - - If the register does not contain any readable fields, this strobe will be - suppressed for read operations. - - If the register does not contain any writable readable fields, this strobe - will be suppressed for write operations. - -hwif_out..req_is_wr - If ``1``, denotes that the current transfer is a write. Otherwise transfer is - a read. - -hwif_out..wr_data - Data to be written for the write transfer. This signal is ignored for read - transfers. - - The bit-width of this signal always matches the CPUIF's bus width, - regardless of the regwidth. - - If the register does not contain any writable fields, this signal is omitted. - -hwif_out..wr_biten - Active-high bit-level write-enable strobes. - Only asserted bit positions will change the register value during a write - transfer. - - If the register does not contain any writable fields, this signal is omitted. - - -Read Response -^^^^^^^^^^^^^ -hwif_in..rd_ack - Single-cycle strobe indicating a read transfer has completed. - Qualifies all other read response signals. - - If the transfer is always completed in the same cycle, it is acceptable to - tie this signal to ``hwif_out..req && !hwif_out..req_is_wr``. - - If the register does not contain any readable fields, this signal is omitted. - -hwif_in..rd_data - Read response data. - - If the register does not contain any readable fields, this signal is omitted. - -Write Response -^^^^^^^^^^^^^^ -hwif_in..wr_ack - Single-cycle strobe indicating a write transfer has completed. - - If the transfer is always completed in the same cycle, it is acceptable to - tie this signal to ``hwif_out..req && hwif_out..req_is_wr``. - - If the register does not contain any writable fields, this signal is omitted. - - - -External Blocks ---------------- -Broader external address regions can be represented by external block-like -components such as ``addrmap``, ``regfile`` or ``mem`` elements. - -To ensure address decoding for external blocks is simple (only requires simple bit-pruning), -blocks that are external to an exported busdecoder shall be aligned to their size. - -Request -^^^^^^^ -hwif_out..req - When asserted, a read or write transfer will be initiated. - Qualifies all other request signals. - -hwif_out..addr - Byte-address of the transfer. - - Address is always relative to the block's local addressing. i.e: The first - byte within an external block is represented as ``hwif_out..addr`` == 0, - regardless of the absolute address of the block. - -hwif_out..req_is_wr - If ``1``, denotes that the current transfer is a write. Otherwise transfer is - a read. - -hwif_out..wr_data - Data to be written for the write transfer. This signal is ignored for read - transfers. - - The bit-width of this signal always matches the CPUIF's bus width, - regardless of the contents of the block. - -hwif_out..wr_biten - Active-high bit-level write-enable strobes. - Only asserted bit positions will change the register value during a write - transfer. - -Read Response -^^^^^^^^^^^^^ -hwif_in..rd_ack - Single-cycle strobe indicating a read transfer has completed. - Qualifies all other read response signals. - -hwif_in..rd_data - Read response data. - -Write Response -^^^^^^^^^^^^^^ -hwif_in..wr_ack - Single-cycle strobe indicating a write transfer has completed. diff --git a/docs/requirements.txt b/docs/requirements.txt index d37f57f..ce1be3f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,2 @@ pygments-systemrdl -sphinxcontrib-wavedrom sphinx-book-theme diff --git a/docs/udps/intro.rst b/docs/udps/intro.rst deleted file mode 100644 index b019c29..0000000 --- a/docs/udps/intro.rst +++ /dev/null @@ -1,79 +0,0 @@ -Introduction -============ - -Although the official SystemRDL spec defines numerous properties that allow you -to define complex register map structures, sometimes they are not enough to -accurately describe a necessary feature. Fortunately the SystemRDL spec allows -the language to be extended using "User Defined Properties" (UDPs). - -Current UDP Support -------------------- - -**Note:** PeakRDL-BusDecoder currently does not implement any User Defined Properties. -The focus of this tool is on bus decoding and address space routing rather than -field-level or register-level behavioral extensions. - -If you need UDPs for field-level behaviors (such as buffering, signedness, or -fixed-point representations), consider using `PeakRDL-regblock `_, -which is designed for comprehensive register block generation with extensive UDP support. - -Extending with Custom UDPs ---------------------------- - -If your bus decoder design requires custom User Defined Properties, you can extend -PeakRDL-BusDecoder by: - -1. **Define your UDP in SystemRDL** - - Create a ``.rdl`` file that defines your custom properties: - - .. code-block:: systemrdl - - property my_custom_prop { - component = addrmap; - type = boolean; - }; - -2. **Implement the UDP in Python** - - Create a Python UDP definition class in your project: - - .. code-block:: python - - from systemrdl.udp import UDPDefinition - - class MyCustomUDP(UDPDefinition): - name = "my_custom_prop" - valid_components = {"addrmap"} - valid_type = bool - default = False - -3. **Register the UDP with the compiler** - - When using PeakRDL-BusDecoder programmatically, register your UDP: - - .. code-block:: python - - from systemrdl import RDLCompiler - from peakrdl_busdecoder import BusDecoderExporter - - rdlc = RDLCompiler() - rdlc.register_udp(MyCustomUDP) - - # Compile your RDL files - rdlc.compile_file("my_udp_defs.rdl") - rdlc.compile_file("my_design.rdl") - - root = rdlc.elaborate() - - # Export - exporter = BusDecoderExporter() - exporter.export(root, "output/") - -4. **Access UDP values in your design** - - UDP values can be accessed from nodes in the SystemRDL tree and used to - customize the generated bus decoder logic as needed. - -For more information on creating User Defined Properties, see the -`SystemRDL Compiler documentation `_. diff --git a/pyproject.toml b/pyproject.toml index c5fe61d..bc8e139 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,6 @@ Documentation = "https://peakrdl-busdecoder.readthedocs.io/" docs = [ "pygments-systemrdl>=1.3.0", "sphinx-book-theme>=1.1.4", - "sphinxcontrib-wavedrom>=3.0.4", ] test = [ "parameterized>=0.9.0",