Update documentation to use correct repository name PeakRDL-BusDecoder and clarify project purpose (#7)
* Initial plan * Update documentation to use correct repository name PeakRDL-BusDecoder Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> * Update CONTRIBUTING.md and GitHub templates with correct repository name Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> * Update author to arnavsacheti and clarify bus decoder purpose in documentation Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> * Update author to 'Arnav Sacheti' and revise UDP documentation to reflect no current UDP support Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>
This commit is contained in:
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -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**
|
**Describe the bug**
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|||||||
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -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**
|
**Describe the problem/limitation you think should be addressed**
|
||||||
A clear and concise description of what the problem is.
|
A clear and concise description of what the problem is.
|
||||||
|
|||||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -6,6 +6,6 @@ this change.
|
|||||||
|
|
||||||
# Checklist
|
# 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)
|
- [ ] 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.
|
- [ ] If this change adds new features, I have added new unit tests that cover them.
|
||||||
|
|||||||
@@ -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
|
We love your input! We want to make contributing to this project as easy and
|
||||||
transparent as possible, whether it's:
|
transparent as possible, whether it's:
|
||||||
|
|
||||||
@@ -9,9 +9,9 @@ transparent as possible, whether it's:
|
|||||||
- Becoming a maintainer
|
- 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
|
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:
|
Issue submission expectations:
|
||||||
* Please keep each issue submission limited to one topic. This helps us stay organized.
|
* Please keep each issue submission limited to one topic. This helps us stay organized.
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -1,12 +1,12 @@
|
|||||||
[](http://peakrdl-busdecoder.readthedocs.io)
|
[](http://peakrdl-busdecoder.readthedocs.io)
|
||||||
[](https://github.com/arnavsacheti/PeakRDL-busdecoder/actions?query=workflow%3Abuild+branch%3Amain)
|
[](https://github.com/arnavsacheti/PeakRDL-BusDecoder/actions?query=workflow%3Abuild+branch%3Amain)
|
||||||
[](https://coveralls.io/github/arnavsacheti/PeakRDL-busdecoder?branch=main)
|
[](https://coveralls.io/github/arnavsacheti/PeakRDL-BusDecoder?branch=main)
|
||||||
[](https://pypi.org/project/peakrdl-busdecoder)
|
[](https://pypi.org/project/peakrdl-busdecoder)
|
||||||
|
|
||||||
# PeakRDL-busdecoder
|
# PeakRDL-BusDecoder
|
||||||
Compile SystemRDL into a SystemVerilog control/status register (CSR) block.
|
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).
|
For the command line tool, see the [PeakRDL project](https://peakrdl.readthedocs.io).
|
||||||
|
|
||||||
## Documentation
|
## 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
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
Register Block Architecture
|
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
|
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
|
.. figure:: diagrams/arch.png
|
||||||
|
|
||||||
@@ -17,14 +19,17 @@ CPU Interface
|
|||||||
The CPU interface logic layer provides an abstraction between the
|
The CPU interface logic layer provides an abstraction between the
|
||||||
application-specific bus protocol and the internal register file logic.
|
application-specific bus protocol and the internal register file logic.
|
||||||
This logic layer normalizes external CPU read & write transactions into a common
|
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
|
Address Decode
|
||||||
--------------
|
--------------
|
||||||
A common address decode operation is generated which computes individual access
|
A common address decode operation is generated which computes individual access
|
||||||
strobes for each software-accessible register in the design.
|
strobes for each software-accessible register or child addrmap in the design.
|
||||||
This operation is performed completely combinationally.
|
This operation is performed completely combinationally. The decoder determines
|
||||||
|
which sub-address space should handle each transaction based on the address range.
|
||||||
|
|
||||||
|
|
||||||
Field Logic
|
Field Logic
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ import datetime
|
|||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
project = "PeakRDL-busdecoder"
|
project = "PeakRDL-BusDecoder"
|
||||||
copyright = "%d, Alex Mykyta" % datetime.datetime.now().year
|
copyright = "%d, Arnav Sacheti" % datetime.datetime.now().year
|
||||||
author = "Alex Mykyta"
|
author = "Arnav Sacheti"
|
||||||
|
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
@@ -53,7 +53,7 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
|||||||
html_theme = "sphinx_book_theme"
|
html_theme = "sphinx_book_theme"
|
||||||
|
|
||||||
html_theme_options = {
|
html_theme_options = {
|
||||||
"repository_url": "https://github.com/arnavsacheti/PeakRDL-busdecoder",
|
"repository_url": "https://github.com/arnavsacheti/PeakRDL-BusDecoder",
|
||||||
"path_to_docs": "docs",
|
"path_to_docs": "docs",
|
||||||
"use_download_button": False,
|
"use_download_button": False,
|
||||||
"use_source_button": True,
|
"use_source_button": True,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.. _peakrdl_cfg:
|
.. _peakrdl_cfg:
|
||||||
|
|
||||||
Configuring PeakRDL-busdecoder
|
Configuring PeakRDL-BusDecoder
|
||||||
============================
|
============================
|
||||||
|
|
||||||
If using the `PeakRDL command line tool <https://peakrdl.readthedocs.io/>`_,
|
If using the `PeakRDL command line tool <https://peakrdl.readthedocs.io/>`_,
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ Via a package's entry point definition
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
If you are publishing a collection of PeakRDL plugins as an installable Python
|
If you are publishing a collection of PeakRDL plugins as an installable Python
|
||||||
package, you can advertise them to PeakRDL using an entry point.
|
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.
|
that should be loaded, and made available as a command-line option in PeakRDL.
|
||||||
|
|
||||||
.. code-block:: toml
|
.. 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
|
* ``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
|
search. Any cpuif plugins you create must be enclosed in this namespace in
|
||||||
order to be discovered.
|
order to be discovered.
|
||||||
* ``my_package.my_module:MyCPUIF``: This is the import path that
|
* ``my_package.my_module:MyCPUIF``: This is the import path that
|
||||||
|
|||||||
@@ -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
|
SystemVerilog coding styles vary wildly, and unfortunately there is little
|
||||||
consensus on this topic within the digital design community.
|
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
|
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
|
widely accepted coding style, but since this is a very opinionated space, it is
|
||||||
impossible to satisfy everyone.
|
impossible to satisfy everyone.
|
||||||
@@ -127,5 +127,5 @@ complexity to the tool.
|
|||||||
|
|
||||||
If you encounter a lint violation, please carefully review and consider waiving
|
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,
|
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 <https://github.com/arnavsacheti/PeakRDL-busdecoder/issues>`_
|
please let us know by `submitting an issue <https://github.com/arnavsacheti/PeakRDL-BusDecoder/issues>`_
|
||||||
that describes the problem.
|
that describes the problem.
|
||||||
|
|||||||
@@ -1,24 +1,32 @@
|
|||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
PeakRDL-busdecoder is a free and open-source control & status register (CSR) compiler.
|
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
|
This code generator translates your SystemRDL register description into a synthesizable
|
||||||
a synthesizable SystemVerilog RTL module that can be easily instantiated into
|
SystemVerilog RTL module that decodes CPU interface transactions and routes them to
|
||||||
your hardware design.
|
multiple sub-address spaces (child addrmaps). This is particularly useful for:
|
||||||
|
|
||||||
* Generates fully synthesizable SystemVerilog RTL (IEEE 1800-2012)
|
* Creating hierarchical register maps with multiple sub-components
|
||||||
* Options for many popular CPU interface protocols (AMBA APB, AXI4-Lite, and more)
|
* Splitting a single CPU interface bus to serve multiple independent register blocks
|
||||||
* Configurable pipelining options for designs with fast clock rates.
|
* 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
|
* Broad support for SystemRDL 2.0 features
|
||||||
|
|
||||||
|
|
||||||
Quick Start
|
Quick Start
|
||||||
-----------
|
-----------
|
||||||
The easiest way to use PeakRDL-busdecoder is via the `PeakRDL command line tool <https://peakrdl.readthedocs.io/>`_:
|
The easiest way to use PeakRDL-BusDecoder is via the `PeakRDL command line tool <https://peakrdl.readthedocs.io/>`_:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. 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]
|
python3 -m pip install peakrdl-busdecoder[cli]
|
||||||
|
|
||||||
# Export!
|
# Export!
|
||||||
@@ -29,15 +37,15 @@ Looking for VHDL?
|
|||||||
-----------------
|
-----------------
|
||||||
This project generates SystemVerilog RTL. If you prefer using VHDL, check out
|
This project generates SystemVerilog RTL. If you prefer using VHDL, check out
|
||||||
the sister project which aims to be a feature-equivalent fork of
|
the sister project which aims to be a feature-equivalent fork of
|
||||||
PeakRDL-busdecoder: `PeakRDL-busdecoder-VHDL <https://peakrdl-busdecoder-vhdl.readthedocs.io>`_
|
PeakRDL-BusDecoder: `PeakRDL-busdecoder-VHDL <https://peakrdl-busdecoder-vhdl.readthedocs.io>`_
|
||||||
|
|
||||||
|
|
||||||
Links
|
Links
|
||||||
-----
|
-----
|
||||||
|
|
||||||
- `Source repository <https://github.com/arnavsacheti/PeakRDL-busdecoder>`_
|
- `Source repository <https://github.com/arnavsacheti/PeakRDL-BusDecoder>`_
|
||||||
- `Release Notes <https://github.com/arnavsacheti/PeakRDL-busdecoder/releases>`_
|
- `Release Notes <https://github.com/arnavsacheti/PeakRDL-BusDecoder/releases>`_
|
||||||
- `Issue tracker <https://github.com/arnavsacheti/PeakRDL-busdecoder/issues>`_
|
- `Issue tracker <https://github.com/arnavsacheti/PeakRDL-BusDecoder/issues>`_
|
||||||
- `PyPi <https://pypi.org/project/peakrdl-busdecoder>`_
|
- `PyPi <https://pypi.org/project/peakrdl-busdecoder>`_
|
||||||
- `SystemRDL Specification <http://accellera.org/downloads/standards/systemrdl>`_
|
- `SystemRDL Specification <http://accellera.org/downloads/standards/systemrdl>`_
|
||||||
|
|
||||||
@@ -87,8 +95,3 @@ Links
|
|||||||
:caption: Extended Properties
|
:caption: Extended Properties
|
||||||
|
|
||||||
udps/intro
|
udps/intro
|
||||||
udps/read_buffering
|
|
||||||
udps/write_buffering
|
|
||||||
udps/extended_swacc
|
|
||||||
udps/signed
|
|
||||||
udps/fixedpoint
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
Licensing
|
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:
|
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?
|
Why LGPLv3?
|
||||||
@@ -23,19 +23,19 @@ explicitly mentioned in the exemptions below.
|
|||||||
|
|
||||||
What is exempt from the LGPLv3 license?
|
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.
|
considered LGPLv3 code.
|
||||||
|
|
||||||
The following are exempt and are free to use with no restrictions:
|
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
|
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
|
distribute it freely, use it in a proprietary ASIC, sell it as part of an
|
||||||
IP, whatever.
|
IP, whatever.
|
||||||
* Any code snippets in this documentation can be freely copy/pasted. These are
|
* Any code snippets in this documentation can be freely copy/pasted. These are
|
||||||
examples that are intended for this purpose.
|
examples that are intended for this purpose.
|
||||||
* All reference files that are downloadable from this documentation, which are
|
* All reference files that are downloadable from this documentation, which are
|
||||||
also available in the `hdl-src folder in the repository <https://github.com/arnavsacheti/PeakRDL-busdecoder/tree/main/hdl-src>`_
|
also available in the `hdl-src folder in the repository <https://github.com/arnavsacheti/PeakRDL-BusDecoder/tree/main/hdl-src>`_
|
||||||
|
|
||||||
|
|
||||||
Can I use this as part of my company's internally developed tools?
|
Can I use this as part of my company's internally developed tools?
|
||||||
|
|||||||
@@ -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.."}
|
|
||||||
]}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
.. _fixedpoint:
|
|
||||||
|
|
||||||
Fixed-Point Fields
|
|
||||||
==================
|
|
||||||
|
|
||||||
`Fixed-point <https://en.wikipedia.org/wiki/Fixed-point_arithmetic>`_ 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<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.
|
|
||||||
@@ -4,82 +4,76 @@ Introduction
|
|||||||
Although the official SystemRDL spec defines numerous properties that allow you
|
Although the official SystemRDL spec defines numerous properties that allow you
|
||||||
to define complex register map structures, sometimes they are not enough to
|
to define complex register map structures, sometimes they are not enough to
|
||||||
accurately describe a necessary feature. Fortunately the SystemRDL spec allows
|
accurately describe a necessary feature. Fortunately the SystemRDL spec allows
|
||||||
the language to be extended using "User Defined Properties" (UDPs). The
|
the language to be extended using "User Defined Properties" (UDPs).
|
||||||
PeakRDL-busdecoder tool understands several UDPs that are described in this
|
|
||||||
section.
|
|
||||||
|
|
||||||
To enable these UDPs, compile this RDL file prior to the rest of your design:
|
Current UDP Support
|
||||||
:download:`busdecoder_udps.rdl <../../hdl-src/busdecoder_udps.rdl>`.
|
-------------------
|
||||||
|
|
||||||
.. list-table:: Summary of UDPs
|
**Note:** PeakRDL-BusDecoder currently does not implement any User Defined Properties.
|
||||||
:header-rows: 1
|
The focus of this tool is on bus decoding and address space routing rather than
|
||||||
|
field-level or register-level behavioral extensions.
|
||||||
|
|
||||||
* - Name
|
If you need UDPs for field-level behaviors (such as buffering, signedness, or
|
||||||
- Component
|
fixed-point representations), consider using `PeakRDL-regblock <https://github.com/SystemRDL/PeakRDL-regblock>`_,
|
||||||
- Type
|
which is designed for comprehensive register block generation with extensive UDP support.
|
||||||
- Description
|
|
||||||
|
|
||||||
* - buffer_reads
|
Extending with Custom UDPs
|
||||||
- reg
|
---------------------------
|
||||||
- boolean
|
|
||||||
- If set, reads from the register are double-buffered.
|
|
||||||
|
|
||||||
See: :ref:`read_buffering`.
|
If your bus decoder design requires custom User Defined Properties, you can extend
|
||||||
|
PeakRDL-BusDecoder by:
|
||||||
|
|
||||||
* - rbuffer_trigger
|
1. **Define your UDP in SystemRDL**
|
||||||
- reg
|
|
||||||
- reference
|
|
||||||
- Defines the buffered read load trigger.
|
|
||||||
|
|
||||||
See: :ref:`read_buffering`.
|
Create a ``.rdl`` file that defines your custom properties:
|
||||||
|
|
||||||
* - buffer_writes
|
.. code-block:: systemrdl
|
||||||
- reg
|
|
||||||
- boolean
|
|
||||||
- If set, writes to the register are double-buffered.
|
|
||||||
|
|
||||||
See: :ref:`write_buffering`.
|
property my_custom_prop {
|
||||||
|
component = addrmap;
|
||||||
|
type = boolean;
|
||||||
|
};
|
||||||
|
|
||||||
* - wbuffer_trigger
|
2. **Implement the UDP in Python**
|
||||||
- reg
|
|
||||||
- reference
|
|
||||||
- Defines the buffered write commit trigger.
|
|
||||||
|
|
||||||
See: :ref:`write_buffering`.
|
Create a Python UDP definition class in your project:
|
||||||
|
|
||||||
* - rd_swacc
|
.. code-block:: python
|
||||||
- field
|
|
||||||
- boolean
|
|
||||||
- Enables an output strobe that is asserted on sw reads.
|
|
||||||
|
|
||||||
See: :ref:`extended_swacc`.
|
from systemrdl.udp import UDPDefinition
|
||||||
|
|
||||||
* - wr_swacc
|
class MyCustomUDP(UDPDefinition):
|
||||||
- field
|
name = "my_custom_prop"
|
||||||
- boolean
|
valid_components = {"addrmap"}
|
||||||
- Enables an output strobe that is asserted on sw writes.
|
valid_type = bool
|
||||||
|
default = False
|
||||||
|
|
||||||
See: :ref:`extended_swacc`.
|
3. **Register the UDP with the compiler**
|
||||||
|
|
||||||
* - is_signed
|
When using PeakRDL-BusDecoder programmatically, register your UDP:
|
||||||
- field
|
|
||||||
- boolean
|
|
||||||
- Defines the signedness of a field.
|
|
||||||
|
|
||||||
See: :ref:`signed`.
|
.. code-block:: python
|
||||||
|
|
||||||
* - intwidth
|
from systemrdl import RDLCompiler
|
||||||
- field
|
from peakrdl_busdecoder import BusDecoderExporter
|
||||||
- unsigned integer
|
|
||||||
- Defines the number of integer bits in the fixed-point representation
|
|
||||||
of a field.
|
|
||||||
|
|
||||||
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
|
4. **Access UDP values in your design**
|
||||||
- field
|
|
||||||
- unsigned integer
|
|
||||||
- Defines the number of fractional bits in the fixed-point representation
|
|
||||||
of a field.
|
|
||||||
|
|
||||||
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 <https://systemrdl-compiler.readthedocs.io/en/stable/model_structure.html#user-defined-properties>`_.
|
||||||
|
|||||||
@@ -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.
|
|
||||||
@@ -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;
|
|
||||||
@@ -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.
|
|
||||||
@@ -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;
|
|
||||||
};
|
|
||||||
@@ -9,13 +9,15 @@ requires-python = ">=3.10"
|
|||||||
dependencies = ["jinja2>=3.1.6", "systemrdl-compiler~=1.30.1"]
|
dependencies = ["jinja2>=3.1.6", "systemrdl-compiler~=1.30.1"]
|
||||||
|
|
||||||
authors = [{ name = "Alex Mykyta" }]
|
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"
|
readme = "README.md"
|
||||||
license = { text = "LGPLv3" }
|
license = { text = "LGPLv3" }
|
||||||
keywords = [
|
keywords = [
|
||||||
"SystemRDL",
|
"SystemRDL",
|
||||||
"PeakRDL",
|
"PeakRDL",
|
||||||
"CSR",
|
"bus decoder",
|
||||||
|
"address decoder",
|
||||||
|
"hierarchical addressing",
|
||||||
"compiler",
|
"compiler",
|
||||||
"tool",
|
"tool",
|
||||||
"registers",
|
"registers",
|
||||||
@@ -41,9 +43,9 @@ classifiers = [
|
|||||||
cli = ["peakrdl-cli >= 1.2.3"]
|
cli = ["peakrdl-cli >= 1.2.3"]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Source = "https://github.com/arnavsacheti/PeakRDL-busdecoder"
|
Source = "https://github.com/arnavsacheti/PeakRDL-BusDecoder"
|
||||||
Tracker = "https://github.com/arnavsacheti/PeakRDL-busdecoder/issues"
|
Tracker = "https://github.com/arnavsacheti/PeakRDL-BusDecoder/issues"
|
||||||
Changelog = "https://github.com/arnavsacheti/PeakRDL-busdecoder/releases"
|
Changelog = "https://github.com/arnavsacheti/PeakRDL-BusDecoder/releases"
|
||||||
Documentation = "https://peakrdl-busdecoder.readthedocs.io/"
|
Documentation = "https://peakrdl-busdecoder.readthedocs.io/"
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ def get_cpuifs(config: list[tuple[str, Any]]) -> dict[str, type[BaseCpuif]]:
|
|||||||
|
|
||||||
|
|
||||||
class Exporter(ExporterSubcommandPlugin):
|
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
|
udp_definitions = ALL_UDPS
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user