diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c85b7cf..f794526 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,7 +7,7 @@ assignees: '' --- -- [ ] I have reviewed this project's [contribution guidelines](https://github.com/arnavsacheti/PeakRDL-busdecoder/blob/main/CONTRIBUTING.md) +- [ ] I have reviewed this project's [contribution guidelines](https://github.com/arnavsacheti/PeakRDL-BusDecoder/blob/main/CONTRIBUTING.md) **Describe the bug** A clear and concise description of what the bug is. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 61c9d2a..c875947 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,7 +7,7 @@ assignees: '' --- -- [ ] I have reviewed this project's [contribution guidelines](https://github.com/arnavsacheti/PeakRDL-busdecoder/blob/main/CONTRIBUTING.md) +- [ ] I have reviewed this project's [contribution guidelines](https://github.com/arnavsacheti/PeakRDL-BusDecoder/blob/main/CONTRIBUTING.md) **Describe the problem/limitation you think should be addressed** A clear and concise description of what the problem is. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 69c8d44..001eb47 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,6 +6,6 @@ this change. # Checklist -- [ ] I have reviewed this project's [contribution guidelines](https://github.com/arnavsacheti/PeakRDL-busdecoder/blob/main/CONTRIBUTING.md) +- [ ] I have reviewed this project's [contribution guidelines](https://github.com/arnavsacheti/PeakRDL-BusDecoder/blob/main/CONTRIBUTING.md) - [ ] This change has been tested and does not break any of the existing unit tests. (if unable to run the tests, let us know) - [ ] If this change adds new features, I have added new unit tests that cover them. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bf7c895..1cd248f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributing to the PeakRDL-busdecoder code generator +# Contributing to the PeakRDL-BusDecoder code generator We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: @@ -9,9 +9,9 @@ transparent as possible, whether it's: - Becoming a maintainer -## Open an issue using the [Issue Tracker](https://github.com/arnavsacheti/PeakRDL-busdecoder/issues) +## Open an issue using the [Issue Tracker](https://github.com/arnavsacheti/PeakRDL-BusDecoder/issues) Talking to us is the easiest way to contribute! Report a bug or feature request by -[opening a new issue](https://github.com/arnavsacheti/PeakRDL-busdecoder/issues). +[opening a new issue](https://github.com/arnavsacheti/PeakRDL-BusDecoder/issues). Issue submission expectations: * Please keep each issue submission limited to one topic. This helps us stay organized. diff --git a/README.md b/README.md index 4081545..5e0d59d 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ [![Documentation Status](https://readthedocs.org/projects/peakrdl-busdecoder/badge/?version=latest)](http://peakrdl-busdecoder.readthedocs.io) -[![build](https://github.com/arnavsacheti/PeakRDL-busdecoder/workflows/build/badge.svg)](https://github.com/arnavsacheti/PeakRDL-busdecoder/actions?query=workflow%3Abuild+branch%3Amain) -[![Coverage Status](https://coveralls.io/repos/github/arnavsacheti/PeakRDL-busdecoder/badge.svg?branch=main)](https://coveralls.io/github/arnavsacheti/PeakRDL-busdecoder?branch=main) +[![build](https://github.com/arnavsacheti/PeakRDL-BusDecoder/workflows/build/badge.svg)](https://github.com/arnavsacheti/PeakRDL-BusDecoder/actions?query=workflow%3Abuild+branch%3Amain) +[![Coverage Status](https://coveralls.io/repos/github/arnavsacheti/PeakRDL-BusDecoder/badge.svg?branch=main)](https://coveralls.io/github/arnavsacheti/PeakRDL-BusDecoder?branch=main) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/peakrdl-busdecoder.svg)](https://pypi.org/project/peakrdl-busdecoder) -# PeakRDL-busdecoder -Compile SystemRDL into a SystemVerilog control/status register (CSR) block. +# PeakRDL-BusDecoder +Generate a SystemVerilog bus decoder from SystemRDL that splits CPU interface signals to multiple sub-address spaces. This tool is designed for creating hierarchical register address maps by decoding bus transactions and routing them to the appropriate child address maps. For the command line tool, see the [PeakRDL project](https://peakrdl.readthedocs.io). ## Documentation -See the [PeakRDL-busdecoder Documentation](https://peakrdl-busdecoder.readthedocs.io) for more details +See the [PeakRDL-BusDecoder Documentation](https://peakrdl-busdecoder.readthedocs.io) for more details diff --git a/docs/architecture.rst b/docs/architecture.rst index daa88f8..30abfa2 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -1,9 +1,11 @@ Register Block Architecture =========================== -The generated register block RTL is organized into several sections. +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 register block SystemVerilog RTL. +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. .. figure:: diagrams/arch.png @@ -17,14 +19,17 @@ 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. +: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. Address Decode -------------- A common address decode operation is generated which computes individual access -strobes for each software-accessible register in the design. -This operation is performed completely combinationally. +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. Field Logic diff --git a/docs/conf.py b/docs/conf.py index 8f63318..3ac801d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,9 +19,9 @@ import datetime # -- Project information ----------------------------------------------------- -project = "PeakRDL-busdecoder" -copyright = "%d, Alex Mykyta" % datetime.datetime.now().year -author = "Alex Mykyta" +project = "PeakRDL-BusDecoder" +copyright = "%d, Arnav Sacheti" % datetime.datetime.now().year +author = "Arnav Sacheti" # -- General configuration --------------------------------------------------- @@ -53,7 +53,7 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] html_theme = "sphinx_book_theme" html_theme_options = { - "repository_url": "https://github.com/arnavsacheti/PeakRDL-busdecoder", + "repository_url": "https://github.com/arnavsacheti/PeakRDL-BusDecoder", "path_to_docs": "docs", "use_download_button": False, "use_source_button": True, diff --git a/docs/configuring.rst b/docs/configuring.rst index 8bfc542..247c545 100644 --- a/docs/configuring.rst +++ b/docs/configuring.rst @@ -1,6 +1,6 @@ .. _peakrdl_cfg: -Configuring PeakRDL-busdecoder +Configuring PeakRDL-BusDecoder ============================ If using the `PeakRDL command line tool `_, diff --git a/docs/cpuif/customizing.rst b/docs/cpuif/customizing.rst index 8bd3c31..863b4dc 100644 --- a/docs/cpuif/customizing.rst +++ b/docs/cpuif/customizing.rst @@ -94,7 +94,7 @@ Via a package's entry point definition ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If you are publishing a collection of PeakRDL plugins as an installable Python package, you can advertise them to PeakRDL using an entry point. -This advertises your custom CPUIF class to the PeakRDL-busdecoder tool as a plugin +This advertises your custom CPUIF class to the PeakRDL-BusDecoder tool as a plugin that should be loaded, and made available as a command-line option in PeakRDL. .. code-block:: toml @@ -104,7 +104,7 @@ that should be loaded, and made available as a command-line option in PeakRDL. * ``my_package``: The name of your installable Python module -* ``peakrdl-busdecoder.cpuif``: This is the namespace that PeakRDL-busdecoder will +* ``peakrdl-busdecoder.cpuif``: This is the namespace that PeakRDL-BusDecoder will search. Any cpuif plugins you create must be enclosed in this namespace in order to be discovered. * ``my_package.my_module:MyCPUIF``: This is the import path that diff --git a/docs/faq.rst b/docs/faq.rst index a3ea5bf..6b082d6 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -101,7 +101,7 @@ 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, +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. @@ -127,5 +127,5 @@ 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 `_ +please let us know by `submitting an issue `_ that describes the problem. diff --git a/docs/index.rst b/docs/index.rst index 3085b3b..9d9f59a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,24 +1,32 @@ Introduction ============ -PeakRDL-busdecoder is a free and open-source control & status register (CSR) compiler. -This code generator translates your SystemRDL register description into -a synthesizable SystemVerilog RTL module that can be easily instantiated into -your hardware design. +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: -* Generates fully synthesizable SystemVerilog RTL (IEEE 1800-2012) -* Options for many popular CPU interface protocols (AMBA APB, AXI4-Lite, and more) -* Configurable pipelining options for designs with fast clock rates. +* 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 +* 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) +* 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 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 - # Install PeakRDL-busdecoder along with the command-line tool + # Install PeakRDL-BusDecoder along with the command-line tool python3 -m pip install peakrdl-busdecoder[cli] # Export! @@ -29,15 +37,15 @@ Looking for VHDL? ----------------- This project generates SystemVerilog RTL. If you prefer using VHDL, check out the sister project which aims to be a feature-equivalent fork of -PeakRDL-busdecoder: `PeakRDL-busdecoder-VHDL `_ +PeakRDL-BusDecoder: `PeakRDL-busdecoder-VHDL `_ Links ----- -- `Source repository `_ -- `Release Notes `_ -- `Issue tracker `_ +- `Source repository `_ +- `Release Notes `_ +- `Issue tracker `_ - `PyPi `_ - `SystemRDL Specification `_ @@ -87,8 +95,3 @@ Links :caption: Extended Properties udps/intro - udps/read_buffering - udps/write_buffering - udps/extended_swacc - udps/signed - udps/fixedpoint diff --git a/docs/licensing.rst b/docs/licensing.rst index 7ef2c56..bab9130 100644 --- a/docs/licensing.rst +++ b/docs/licensing.rst @@ -1,9 +1,9 @@ Licensing ========= -Re-distribution of the PeakRDL-busdecoder code generator tool shall adhere to the +Re-distribution of the PeakRDL-BusDecoder code generator tool shall adhere to the terms outlined by the GNU LGPL v3 license. For a copy of the license, see: -https://github.com/arnavsacheti/PeakRDL-busdecoder/blob/main/LICENSE +https://github.com/arnavsacheti/PeakRDL-BusDecoder/blob/main/LICENSE Why LGPLv3? @@ -23,19 +23,19 @@ explicitly mentioned in the exemptions below. What is exempt from the LGPLv3 license? --------------------------------------- -Don't worry. Not everything that the PeakRDL-busdecoder project touches is +Don't worry. Not everything that the PeakRDL-BusDecoder project touches is considered LGPLv3 code. The following are exempt and are free to use with no restrictions: -* Any code that is generated using PeakRDL-busdecoder is 100% yours. Since it +* Any code that is generated using PeakRDL-BusDecoder is 100% yours. Since it was derived from your busdecoder definition, it remains yours. You can distribute it freely, use it in a proprietary ASIC, sell it as part of an IP, whatever. * Any code snippets in this documentation can be freely copy/pasted. These are examples that are intended for this purpose. * All reference files that are downloadable from this documentation, which are - also available in the `hdl-src folder in the repository `_ + also available in the `hdl-src folder in the repository `_ Can I use this as part of my company's internally developed tools? diff --git a/docs/udps/extended_swacc.rst b/docs/udps/extended_swacc.rst deleted file mode 100644 index 5182cfd..0000000 --- a/docs/udps/extended_swacc.rst +++ /dev/null @@ -1,49 +0,0 @@ -.. _extended_swacc: - -Read/Write-specific swacc -========================= - -SystemRDL defines the ``swacc`` property, but it does not distinguish between -read and write operations - it is asserted on *all* software accesses. -Similarly, the spec defines ``swmod`` which gets asserted on software writes, -but can also get asserted if the field has on-read side-effects. - -What if you just wanted a plain and simple strobe that is asserted when software -reads or writes a field? The ``rd_swacc`` and ``wr_swacc`` UDPs provide this -functionality. - - -Properties ----------- -These UDP definitions, along with others supported by PeakRDL-busdecoder can be -enabled by compiling the following file along with your design: -:download:`busdecoder_udps.rdl <../../hdl-src/busdecoder_udps.rdl>`. - -.. describe:: rd_swacc - - If true, infers an output signal ``hwif_out..rd_swacc`` that is asserted - when accessed by a software read operation. The output signal is asserted - on the same clock cycle that the field is being sampled during the software - read operation. - - .. wavedrom:: - - {"signal": [ - {"name": "clk", "wave": "p...."}, - {"name": "hwif_in..next", "wave": "x.=x.", "data": ["D"]}, - {"name": "hwif_out..rd_swacc", "wave": "0.10."} - ]} - - -.. describe:: wr_swacc - - If true, infers an output signal ``hwif_out..wr_swacc`` that is asserted - as the field is being modified by a software write operation. - - .. wavedrom:: - - {"signal": [ - {"name": "clk", "wave": "p....."}, - {"name": "hwif_out..value", "wave": "=..=..", "data": ["old", "new"]}, - {"name": "hwif_out..wr_swacc", "wave": "0.10.."} - ]} diff --git a/docs/udps/fixedpoint.rst b/docs/udps/fixedpoint.rst deleted file mode 100644 index f3e313a..0000000 --- a/docs/udps/fixedpoint.rst +++ /dev/null @@ -1,103 +0,0 @@ -.. _fixedpoint: - -Fixed-Point Fields -================== - -`Fixed-point `_ numbers -can be used to efficiently represent real numbers using integers. Fixed-point -numbers consist of some combination of integer bits and fractional bits. The -number of integer/fractional bits is usually implicitly tracked (not stored) -for each number, unlike for floating-point numbers. - -For this SystemVerilog exporter, these properties only affect the signal type in -the the ``hwif`` structs. There is no special handling in the internals of -the busdecoder. - -Properties ----------- -Fields can be declared as fixed-point numbers using the following two properties: - -.. literalinclude:: ../../hdl-src/busdecoder_udps.rdl - :lines: 46-54 - -The :ref:`is_signed` property can be used in conjunction with these -properties to declare signed fixed-point fields. - -These UDP definitions, along with others supported by PeakRDL-busdecoder, can be -enabled by compiling the following file along with your design: -:download:`busdecoder_udps.rdl <../../hdl-src/busdecoder_udps.rdl>`. - -.. describe:: intwidth - - * The ``intwidth`` property defines the number of integer bits in the - fixed-point representation (including the sign bit, if present). - -.. describe:: fracwidth - - * The ``fracwidth`` property defines the number of fractional bits in the - fixed-point representation. - -Representable Numbers -^^^^^^^^^^^^^^^^^^^^^ - -The range of representable real numbers is summarized in the table below. - -.. list-table:: Representable Numbers - :header-rows: 1 - - * - Signedness - - Minimum Value - - Maximum Value - - Step Size - - * - Unsigned - - :math:`0` - - :math:`2^{\mathrm{intwidth}} - 2^{-\mathrm{fracwidth}}` - - :math:`2^{-\mathrm{fracwidth}}` - - * - Signed - - :math:`-2^{\mathrm{intwidth}-1}` - - :math:`2^{\mathrm{intwidth}-1} - 2^{-\mathrm{fracwidth}}` - - :math:`2^{-\mathrm{fracwidth}}` - -SystemVerilog Types -^^^^^^^^^^^^^^^^^^^ - -When either ``intwidth`` or ``fracwidth`` are defined for a field, that field's -type in the generated SystemVerilog ``hwif`` struct is -``logic (signed) [intwidth-1:-fracwidth]``. The bit at index :math:`i` contributes -a weight of :math:`2^i` to the real number represented. - -Other Rules -^^^^^^^^^^^ -* Only one of ``intwidth`` or ``fracwidth`` need be defined. The other is - inferred from the field bit width. -* The bit width of the field shall be equal to ``intwidth`` + ``fracwidth``. -* If both ``intwidth`` and ``fracwidth`` are defined for a field, it is an - error if their sum does not equal the bit width of the field. -* Either ``fracwidth`` or ``intwidth`` can be a negative integer. Because - SystemRDL does not have a signed integer type, the only way to achieve - this is to define one of the widths as larger than the bit width of the - component so that the other width is inferred as a negative number. -* The properties defined above are mutually exclusive with the ``counter`` - property. -* The properties defined above are mutually exclusive with the ``encode`` - property. - -Examples --------- - -A 12-bit signed fixed-point field with 4 integer bits and 8 fractional bits -can be declared with - -.. code-block:: systemrdl - :emphasize-lines: 3, 4 - - field { - sw=rw; hw=r; - intwidth = 4; - is_signed; - } fixedpoint_num[11:0] = 0; - -This field can represent values from -8.0 to 7.99609375 -in steps of 0.00390625. diff --git a/docs/udps/intro.rst b/docs/udps/intro.rst index 46da909..b019c29 100644 --- a/docs/udps/intro.rst +++ b/docs/udps/intro.rst @@ -4,82 +4,76 @@ 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). The -PeakRDL-busdecoder tool understands several UDPs that are described in this -section. +the language to be extended using "User Defined Properties" (UDPs). -To enable these UDPs, compile this RDL file prior to the rest of your design: -:download:`busdecoder_udps.rdl <../../hdl-src/busdecoder_udps.rdl>`. +Current UDP Support +------------------- -.. list-table:: Summary of UDPs - :header-rows: 1 +**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. - * - Name - - Component - - Type - - Description +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. - * - buffer_reads - - reg - - boolean - - If set, reads from the register are double-buffered. +Extending with Custom UDPs +--------------------------- - See: :ref:`read_buffering`. +If your bus decoder design requires custom User Defined Properties, you can extend +PeakRDL-BusDecoder by: - * - rbuffer_trigger - - reg - - reference - - Defines the buffered read load trigger. +1. **Define your UDP in SystemRDL** - See: :ref:`read_buffering`. + Create a ``.rdl`` file that defines your custom properties: - * - buffer_writes - - reg - - boolean - - If set, writes to the register are double-buffered. + .. code-block:: systemrdl - See: :ref:`write_buffering`. + property my_custom_prop { + component = addrmap; + type = boolean; + }; - * - wbuffer_trigger - - reg - - reference - - Defines the buffered write commit trigger. +2. **Implement the UDP in Python** - See: :ref:`write_buffering`. + Create a Python UDP definition class in your project: - * - rd_swacc - - field - - boolean - - Enables an output strobe that is asserted on sw reads. + .. code-block:: python - See: :ref:`extended_swacc`. + from systemrdl.udp import UDPDefinition - * - wr_swacc - - field - - boolean - - Enables an output strobe that is asserted on sw writes. + class MyCustomUDP(UDPDefinition): + name = "my_custom_prop" + valid_components = {"addrmap"} + valid_type = bool + default = False - See: :ref:`extended_swacc`. +3. **Register the UDP with the compiler** - * - is_signed - - field - - boolean - - Defines the signedness of a field. + When using PeakRDL-BusDecoder programmatically, register your UDP: - See: :ref:`signed`. + .. code-block:: python - * - intwidth - - field - - unsigned integer - - Defines the number of integer bits in the fixed-point representation - of a field. + from systemrdl import RDLCompiler + from peakrdl_busdecoder import BusDecoderExporter - See: :ref:`fixedpoint`. + 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/") - * - fracwidth - - field - - unsigned integer - - Defines the number of fractional bits in the fixed-point representation - of a field. +4. **Access UDP values in your design** - See: :ref:`fixedpoint`. + 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/docs/udps/read_buffering.rst b/docs/udps/read_buffering.rst deleted file mode 100644 index 43aa1e9..0000000 --- a/docs/udps/read_buffering.rst +++ /dev/null @@ -1,164 +0,0 @@ -.. _read_buffering: - -Read-buffered Registers -======================= - -Read buffering is a mechanism that allows for software accesses to read a -snapshot of one or more registers atomically. When enabled on a register, a -read buffer will latch the state of its fields when triggered such that software -can read a coherent snapshot of one or more registers' value. - -Some examples of when this is useful: - * A wide 64-bit status register needs to be read atomically, but the CPU - interface is only 32-bits. - * Software needs to be able to read the state of multiple registers - atomically. - * A hardware event latches the software-visible state of one or more - registers. - -.. figure:: ../diagrams/rbuf.png - - -Properties ----------- -The behavior of read-buffered registers is defined using the following two -properties: - -.. literalinclude:: ../../hdl-src/busdecoder_udps.rdl - :lines: 10-18 - -These UDP definitions, along with others supported by PeakRDL-busdecoder can be -enabled by compiling the following file along with your design: -:download:`busdecoder_udps.rdl <../../hdl-src/busdecoder_udps.rdl>`. - -.. describe:: buffer_reads - - * Assigned value is a boolean. - * If true, enables double-buffering of software reads of this register. - * The read buffer will load the register's field values when its trigger - event is asserted. - * Unless specified otherwise, the buffer trigger occurs when the lowest - address of the buffered register is read. - * When read by software the data returned is from the buffer contents, not - directly from the register's fields. - -.. describe:: rbuffer_trigger - - * Assigned value is a reference to a register, single-bit field, signal, or - single-bit property. - * Controls when the double-buffer loads the register's field vaues into the - buffer storage element. - * If reference is a single-bit value (signal, field, property reference), - then the assertion of that value triggers the buffer to be evicted. - * Signal references shall have either activehigh/activelow property set to - define the polarity. - * If the reference is a reg, then buffer is loaded when the register's - lowest address is read. - -Other Rules -^^^^^^^^^^^ -* It is an error to set ``buffer_reads`` if the register does not contain any - readable fields -* If ``buffer_reads`` is false, then anything assigned to ``rbuffer_trigger`` - is ignored. -* The buffered register and the trigger reference shall both be within the same - internal device. ie: one cannot be in an external scope with respect to the - other. -* Unless it is a register, the reference assigned to ``rbuffer_trigger`` shall - represent a single bit. -* The software read operation considered to take place when the buffer is loaded. - This influences the behavior of properties like ``swmod`` and ``swacc`` - - they are not asserted until the register's fields are actually sampled by the - buffer. -* If a read-buffered register is wide (accesswidth < regwidth) and is its own - trigger, the first sub-word's buffer is bypassed to ensure the first read - operation is atomically coherent with the rest of the sampled register. - - -Examples --------- -Below are several examples of what you can do with registers that are -read-buffered. - -Wide Atomic Register -^^^^^^^^^^^^^^^^^^^^ -In this example, a wide 64-bit read-clear counter is implemented. -Without read-buffering, it is impossible to coherently read the state of the -counter using a 32-bit CPU interface without risking a discontinuity. With -read-buffering enabled, the read of the lower half of the register will trigger -the upper half's value to be latched. A subsequent software access can then -coherently read the rest of the register's buffered value. - -.. code-block:: systemrdl - :emphasize-lines: 4 - - reg { - regwidth = 64; - accesswidth = 32; - buffer_reads = true; - field { - sw=r; hw=na; - counter; - incr; - } my_counter[63:0] = 0; - }; - - -Atomic Group of Registers -^^^^^^^^^^^^^^^^^^^^^^^^^ -Perhaps you have a group of registers that monitor some rapidly-changing state -within your design. Using the ``rbuffer_trigger`` property, you can define which -register read operation triggers the buffered registers' values to be latched. - -.. code-block:: systemrdl - :emphasize-lines: 11-14 - - reg my_status_reg { - field { - sw=r; hw=w; - } value[31:0]; - }; - - my_status_reg status1; - my_status_reg status2; - my_status_reg status3; - - status2->buffer_reads = true; - status2->rbuffer_trigger = status1; - status3->buffer_reads = true; - status3->rbuffer_trigger = status1; - -In this example, when software reads status1, this triggers status2-status3 -registers to latch their values into their respective read buffers. Subsequent -reads to status2 and status3 return the value that these registers contained at -the moment that status1 was read. This makes it possible for software to read -the state of multiple registers atomically. - - -Externally Triggered Register Sampling -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If needed, an external trigger can be used to load a read buffer. -This can be useful if precise timing of software's view of the register state is -required. - -.. code-block:: systemrdl - :emphasize-lines: 14-15 - - reg my_status_reg { - buffer_reads = true; - field { - sw=r; hw=w; - } value[31:0]; - }; - - my_status_reg status1; - my_status_reg status2; - - signal { - activehigh; - } trigger_signal; - status1->rbuffer_trigger = trigger_signal; - status2->rbuffer_trigger = trigger_signal; - -When ``hwif_in..trigger_signal`` is asserted, the state of registers ``status1`` -and ``status2`` is buffered. diff --git a/docs/udps/signed.rst b/docs/udps/signed.rst deleted file mode 100644 index 39ffebf..0000000 --- a/docs/udps/signed.rst +++ /dev/null @@ -1,74 +0,0 @@ -.. _signed: - -Signed Fields -============= - -SystemRDL does not natively provide a way to mark fields as signed or unsigned. -The ``is_signed`` user-defined property fills this need. - -For this SystemVerilog exporter, marking a field as signed only affects the -signal type in the ``hwif`` structs. There is no special handling in the internals -of the busdecoder. - -Properties ----------- -A field can be marked as signed using the following user-defined property: - -.. literalinclude:: ../../hdl-src/busdecoder_udps.rdl - :lines: 40-44 - -This UDP definition, along with others supported by PeakRDL-busdecoder, can be -enabled by compiling the following file along with your design: -:download:`busdecoder_udps.rdl <../../hdl-src/busdecoder_udps.rdl>`. - -.. describe:: is_signed - - * Assigned value is a boolean. - * If true, the hardware interface field will have the type - ``logic signed [width-1:0]``. - * If false or not defined for a field, the hardware interface field will - have the type ``logic [width-1:0]``, which is unsigned by definition. - -Other Rules -^^^^^^^^^^^ - -* ``is_signed=true`` is mutually exclusive with the ``counter`` property. -* ``is_signed=true`` is mutually exclusive with the ``encode`` property. - -Examples --------- -Below are some examples of fields with different signedness. - -Signed Fields -^^^^^^^^^^^^^ -.. code-block:: systemrdl - :emphasize-lines: 3, 8 - - field { - sw=rw; hw=r; - is_signed; - } signed_num[63:0] = 0; - - field { - sw=r; hw=w; - is_signed = true; - } another_signed_num[19:0] = 20'hFFFFF; // -1 - -SystemRDL's own integer type is always unsigned. In order to specify a negative -reset value, the two's complement value must be used as shown in the second -example above. - -Unsigned Fields -^^^^^^^^^^^^^^^ -.. code-block:: systemrdl - :emphasize-lines: 3, 8 - - field { - sw=rw; hw=r; - // fields are unsigned by default - } unsigned_num[63:0] = 0; - - field { - sw=r; hw=w; - is_signed = false; - } another_unsigned_num[19:0] = 0; diff --git a/docs/udps/write_buffering.rst b/docs/udps/write_buffering.rst deleted file mode 100644 index 529d08a..0000000 --- a/docs/udps/write_buffering.rst +++ /dev/null @@ -1,183 +0,0 @@ -.. _write_buffering: - -Write-buffered Registers -======================== - -In order to support larger software write accesses that are atomic, the -busdecoder generator understands several UDPs that implement write-buffering to -specific registers. This causes the busdecoder to delay the effect of a software -write operation until a defined trigger event. - -Some examples of when this is useful: - * You need to have software update a wide 64-bit register atomically, but - the CPU interface is only 32-bits. - * Software needs to be able to write multiple registers such that the - hardware is updated atomically. - * Software can pre-load one or more registers with their next value, and - trigger the update via an external hardware signal. - -If a register is write-buffered, a holding buffer stage is inserted between the -decode logic and the field logic. This effectively defers any software write -operations to that register until a trigger event occurs that releases it. -Write buffering storage is unique to each register that enables it. -If a register is not write buffered, this buffer stage is bypassed. - -.. figure:: ../diagrams/wbuf.png - - -Properties ----------- -The behavior of write-buffered registers is defined using the following two -properties: - -.. literalinclude:: ../../hdl-src/busdecoder_udps.rdl - :lines: 20-28 - -These UDP definitions, along with others supported by PeakRDL-busdecoder can be -enabled by compiling the following file along with your design: -:download:`busdecoder_udps.rdl <../../hdl-src/busdecoder_udps.rdl>`. - -.. describe:: buffer_writes - - * Assigned value is a boolean. - * If true, enables double-buffering of writes to this register. - * Any software write operation to a buffered register is held back in a - storage element unique to the register. - * The software write operation is committed to the register once triggered - to do so. - * Unless specified otherwise, the buffer trigger occurs when the highest - address of the buffered register is written. - -.. describe:: wbuffer_trigger - - * Assigned value is a reference to a register, single-bit field, signal, - or single-bit property. - * Controls when the double-buffer commits the software write operation to - the register's fields. - * If reference is a single-bit value (signal, field, property reference), - then the assertion of that value triggers the buffer to be evicted. - * Signal references shall have either activehigh/activelow property set to - define the polarity. - * If the reference is a reg, then buffer is evicted when the register's - highest address is written. - - -Other Rules -^^^^^^^^^^^ -* It is an error to set ``buffer_writes`` if the register does not contain any - writable fields -* If ``buffer_writes`` is false, then anything assigned to ``wbuffer_trigger`` - is ignored. -* The buffered register and the trigger reference shall both be within the - same internal device. ie: one cannot be in an external scope with respect to - the other. -* Unless it is a register, the reference assigned to ``wbuffer_trigger`` shall - represent a single bit. -* If a buffered register was not written, any trigger events are ignored. -* It is valid for a buffered register to be partially written (either via - write strobes, or partial addressing). -* The software write operation is not considered to take place until the - buffer is evicted by the trigger. This influences the behavior of properties - like ``swmod`` and ``swacc`` - they are not asserted until the register's - fields are actually written by the buffer. - - - -Examples --------- -Below are several examples of what you can do with registers that are -write-buffered. - -Wide Atomic Register -^^^^^^^^^^^^^^^^^^^^ -Without write-buffering, it is impossible to update the state of a 64-bit -register using a 32-bit CPU interface in a single clock-cycle. -In this example, it still requires two write-cycles to update the register, but -the register's storage element is not updated until both sub-words are written. -Upon writing the 2nd sub-word (the higher byte address), the write data for both -write cycles are committed to the register's storage element together on the -same clock cycle. The register is updated atomically. - -.. code-block:: systemrdl - :emphasize-lines: 4 - - reg { - regwidth = 64; - accesswidth = 32; - buffer_writes = true; - field { - sw=rw; hw=r; - } my_field[63:0] = 0; - }; - - -Atomic Group of Registers -^^^^^^^^^^^^^^^^^^^^^^^^^ -Perhaps you have a group of registers that need their state to be updated -atomically. Using the ``wbuffer_trigger`` property, you can define which -register write operation triggers the group to be updated. - - -.. code-block:: systemrdl - :emphasize-lines: 2, 18-20 - - reg my_buffered_reg { - buffer_writes = true; - field { - sw=rw; hw=r; - } my_field[31:0] = 0; - }; - - my_buffered_reg reg1; - my_buffered_reg reg2; - my_buffered_reg reg3; - - reg { - field { - sw=rw; hw=r; - } my_field[31:0] = 0; - } reg4; - - reg1->wbuffer_trigger = reg4; - reg2->wbuffer_trigger = reg4; - reg3->wbuffer_trigger = reg4; - - -In this example software may pre-write information into reg1-reg3, but the -register write operations do not take effect until software also writes to reg4. -The write operation to reg4 triggers the buffered data to be committed to -reg1-reg3. This is guaranteed to occur on the same clock-cycle. - - -Externally Triggered Register Update -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Some applications may require precise timing for when a register (or group of -registers) update their value. Often software cannot offer such timing -precision. - -In this example, the trigger event is bound to an external signal. When -asserted, any pending write operation the buffered register will be committed. -The hwif_out value presents the new register state on the clock cycle after the -trigger is asserted. - -.. code-block:: systemrdl - :emphasize-lines: 2, 11-13 - - reg my_buffered_reg { - buffer_writes = true; - field { - sw=rw; hw=r; - } my_field[31:0] = 0; - }; - - my_buffered_reg reg1; - my_buffered_reg reg2; - - signal { - activehigh; - } trigger_signal; - reg1->wbuffer_trigger = trigger_signal; - reg2->wbuffer_trigger = trigger_signal; - -After software writes to ``reg1`` & ``reg2``, the written data is held back in -the write buffer until ``hwif_in..trigger_signal`` is asserted by the hardware. diff --git a/hdl-src/regblock_udps.rdl b/hdl-src/regblock_udps.rdl deleted file mode 100644 index e11418c..0000000 --- a/hdl-src/regblock_udps.rdl +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file defines several property extensions that are understood by the - * PeakRDL-BusDecoder SystemVerilog code generator. - * - * Compile this file prior to your other SystemRDL sources. - * - * For more details, see: https://peakrdl-busdecoder.readthedocs.io/en/latest/udps/intro.html - */ - -property buffer_reads { - component = reg; - type = boolean; -}; - -property rbuffer_trigger { - component = reg; - type = ref; -}; - -property buffer_writes { - component = reg; - type = boolean; -}; - -property wbuffer_trigger { - component = reg; - type = ref; -}; - -property rd_swacc { - component = field; - type = boolean; -}; - -property wr_swacc { - component = field; - type = boolean; -}; - -property is_signed { - type = boolean; - component = field; - default = true; -}; - -property intwidth { - type = longint unsigned; - component = field; -}; - -property fracwidth { - type = longint unsigned; - component = field; -}; diff --git a/pyproject.toml b/pyproject.toml index 8b3e68c..f3f485a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,13 +9,15 @@ requires-python = ">=3.10" dependencies = ["jinja2>=3.1.6", "systemrdl-compiler~=1.30.1"] authors = [{ name = "Alex Mykyta" }] -description = "Compile SystemRDL into a SystemVerilog control/status register (CSR) block" +description = "Generate a SystemVerilog bus decoder from SystemRDL for splitting CPU interfaces to multiple sub-address spaces" readme = "README.md" license = { text = "LGPLv3" } keywords = [ "SystemRDL", "PeakRDL", - "CSR", + "bus decoder", + "address decoder", + "hierarchical addressing", "compiler", "tool", "registers", @@ -41,9 +43,9 @@ classifiers = [ cli = ["peakrdl-cli >= 1.2.3"] [project.urls] -Source = "https://github.com/arnavsacheti/PeakRDL-busdecoder" -Tracker = "https://github.com/arnavsacheti/PeakRDL-busdecoder/issues" -Changelog = "https://github.com/arnavsacheti/PeakRDL-busdecoder/releases" +Source = "https://github.com/arnavsacheti/PeakRDL-BusDecoder" +Tracker = "https://github.com/arnavsacheti/PeakRDL-BusDecoder/issues" +Changelog = "https://github.com/arnavsacheti/PeakRDL-BusDecoder/releases" Documentation = "https://peakrdl-busdecoder.readthedocs.io/" [dependency-groups] diff --git a/src/peakrdl_busdecoder/__peakrdl__.py b/src/peakrdl_busdecoder/__peakrdl__.py index 8cf700d..5977548 100644 --- a/src/peakrdl_busdecoder/__peakrdl__.py +++ b/src/peakrdl_busdecoder/__peakrdl__.py @@ -58,7 +58,7 @@ def get_cpuifs(config: list[tuple[str, Any]]) -> dict[str, type[BaseCpuif]]: class Exporter(ExporterSubcommandPlugin): - short_desc = "Generate a SystemVerilog control/status register (CSR) block" + short_desc = "Generate a SystemVerilog bus decoder for splitting CPU interfaces to sub-address spaces" udp_definitions = ALL_UDPS