Vendorize 'riscv-config' tool in order to test/support local extensions. (#2045)

This commit is contained in:
Zbigniew Chamski 2024-04-16 13:56:06 +02:00 committed by GitHub
parent 75f695f665
commit c51fad1d0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
59 changed files with 40518 additions and 0 deletions

View file

@ -0,0 +1,31 @@
#!/bin/bash
### Pre Commit Hook For The Shakti BLUESPEC codebase
status=0;
### Check for Dependencies
yapf --help
status=$?;
if [ $status -ne 0 ]; then
echo "Please install yapf from :: https://github.com/google/yapf "
exit $status;
fi
### Hook Script Body
echo "Running Pre-Commit YAPF Hook";
files=`git diff --cached --name-status | awk '$1 != "D" { print $2 }'`
echo "$files"
for f in $files
do
if [[ $f == *.py ]]; then
echo "Formatting $f using YAPF."
yapf -i --style google $f
git add $f
fi
done
status=$?;
exit $status;

View file

@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Setup the git hooks
echo "Setting up git-hooks"
echo "===================="
echo "Launched from" $(pwd)
echo ""
echo "Setting up pre-commit"
ln -s -f ../../.git_hooks/pre-commit ./.git/hooks/pre-commit
chmod a+x ./.git/hooks/pre-commit
echo "Done"

15
vendor/riscv/riscv-config/.gitignore vendored Normal file
View file

@ -0,0 +1,15 @@
docs/build
docs/source/schema_isa.rst
docs/source/schema_platform.rst
docs/source/schema_debug.rst
run.log
__pycache__/*
*.pyc
riscv_config_work/*
.python-version
riscv_config.egg-info/

458
vendor/riscv/riscv-config/CHANGELOG.md vendored Normal file
View file

@ -0,0 +1,458 @@
# Changelog
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.18.1] - 2024-04-10
- mprv should not be implemented when U mode is absent.
## [3.18.0] - 2024-04-02
- mabi generation to account for E extension
## [3.17.1] - 2024-02-25
- add unratified Ssdbltrp, Smdbltrp, and Sddbltrp extensions
## [3.17.0] - 2024-01-09
- support march generation without custom extensions
## [3.16.0] - 2024-01-03
- use the "hartX" naming for the merged dict
- improve logging statements
- update the "fields" node of each csr in the normalized custom yaml
## [3.15.0] - 2024-01-01
- Added function that returns the march and mabi for gcc from a given ISA
## [3.14.3] - 2023-12-01
- Add support for Zimop extension
## [3.14.2] - 2023-12-01
- Add Zcmop extension.
## [3.14.1] - 2023-12-01
- Add support for Zicfilp and Zicfiss extensions
## [3.14.0] - 2023-11-30
- Include Sdext in the list of S extensions
## [3.13.4] - 2023-10-30
- Add support for Zabha extension
## [3.13.3] - 2023-09-23
- do not assign subfield to None
## [3.13.2] - 2023-09-20
- Perform satp checks only when the CSR is accessible.
## [3.13.1] - 2023-08-21
- Add support for Code Size Reduction (Zce) extension
## [3.13.0] - 2023-08-14
- Fixed issue #110
- Fixed issue #108
- Fixed issue #114
- Fixed issue #127
- Fixed issue #82
- Fixed issue #103
- updated contribution guidelines on versioning
- added docs for indexed CSRs
## [3.12.0] - 2023-08-12
- Add support for Svadu extension
## [3.11.0] - 2023-08-12
- Add support for Zacas extension
## [3.10.0] - 2023-08-12
- Add support for Zfa extension
## [3.9.2] - 2023-07-21
- Fix Checks for FCSR, FFLAGS and FRM to depend on F instead of U.
## [3.9.1] - 2023-06-21
- Check if YAMLs are None before they're merged for performing CSR checks.
- Perform XLEN specific satp checks based on XLEN value.
- Check triggers only when debug CSRs are available.
## [3.9.0] - 2023-05-06
- Add support to include hidden uarch dependencies in YAML definitions of CSRs.
- Perform checks on all CSRs together instead of handling each spec seperately.
- Add a schema for custom CSR specification. Add a node for listing uarch signals.
## [3.8.1] - 2023-04-25
- fix the address for mnstatus
## [3.8.0] - 2023-04-18
- Add support for Srnmi extension
- All extension existence checks to be performed on extension\_list from isa validator.
## [3.7.2] - 2023-04-06
- Add support for Zicond extension
## [3.7.1] - 2023-03-14
- change all hpmcounters to be read-only shadows of the corresponding machine mode mhpmcounters.
## [3.7.0] - 2023-03-13
- adding Zicntr and Zihpm extensions
## [3.6.0] - 2023-03-07
- add V extensions ISA string constraints check
## [3.5.2] - 2022-12-26
- special checks for vxsat csr added which apply only the max-xlen subsections of the csr
## [3.5.1] - 2022-12-12
- Added Zbpbo, Zpn, Zpsfoperand into constants.py
- Added ISA string legality checker for Zp* extension into isa_validator.py
- Added vxsat CSR into schema_isa.yaml (Credits: chuanhua)
## [3.5.0] - 2022-10-28
- Add support for indexed registers
- Add schemas for triggers
- Fix bugs in WARL class
- Add function to get a legal value from WARL fields.
## [3.4.0] - 2022-10-13
- support x-extension parsing in ISA string
- added check to capture duplicates in the extensions present in the isa string
## [3.3.1] - 2022-09-26
- documentation cleanup for adding new extensions in riscv-config
- disabled pdf asset generation for each release.
## [3.3.0] - 2022-09-24
- rewrote regular expression for determining legal ISA/extension strings to fix bugs and simplify maintenance. (#104)
- updated example and regex in new-extensions.rst to match
## [3.2.0] - 2022-09-07
- adding new function to get a legal value from a warl node
## [3.1.2] - 2022-08-23
- if the value being tested is out of bounds, then skip with error immediately
## [3.1.1] - 2022-08-18
- fix pypi dependencies for docs
## [3.1.0] - 2022-08-17
- scounteren can be a ro\_constant now
- the maxval checks for mask/fixedval should be based on the length of the part
- adding support for mtval\_update field
- adding support for pte\_ad\_hw\_update field
- cleaned up documentation
## [3.0.0] - 2022-08-16
- created new warl class for warl node handling
- better comments
- more functions to keep things simple
- fixed a lot of bugs in checking legal values
- bitmask and range values can now co-exist in a legal string
- added new and improved checks for syntax validity of warl strings
- fixed validationError function to correctly print all errors (dict and/or list)
- removed wr\_illegal checks from the schema since they are now done as part of the new warl class
checks
- updates to the new warl checks and reset-value checks
- satp.mode should have one of sv\* translation schemes as a legal value. (#89)
- default setters for pmps fixed
- pmp checks have been improved (#88)
- improve WARL documentation
## [2.17.0] - 2022-08-08
- Support for Zfinx, Zdinx, Zfh, Zhinx, Zhinxmin in ISA string added.
## [2.16.1] - 2022-07-21
- fixed bug in regex where Zk and Zknh were missing an underscore
## [2.16.0] - 2022-07-20
- fixed overlap checks for crypto extensions
- removing K and P extension strings from regex
## [2.15.1] - 2022-06-18
- added missing Z extensions from Kcrypto
- fixed ordering of the Z extensions as per isa spec.
## [2.15.0] - 2022-06-16
- moved ISA validation as a separate api function to enable import in other python tools
## [2.14.1] - 2022-06-02
- add support for Zicbo* extensions
- add new node in platform_schema: zicbo_cache_block_sz
## [2.14.0] - 2022-05-13
- fix for index-based dependency checks in warl string.
## [2.13.1] - 2022-03-23
- Added setup.cfg to automate bumpversion
- Fix wording for legal strings in dependency warl fields.
## [2.13.0] - 2022-03-09
- add support for detection of svnapot in ISA string
- genralize conversion of hex, oct, bin values to int in warl functions
- machine flat schema to include wlrl types as well
## [2.12.1] - 2021-12-18
### Fixed
- added mbe and sbe fields in mstatush
- fixed default setter for vsstatus in RV32 mode
## [2.12.0] - 2021-12-10
### Added
- support for hypervisor csrs
- change default for dcsr.v and fix the `check_with` function for the same
- ensures proper checks for csrs defined as 32-bit only registers
## [2.11.2] - 2021-11-29
### Fixed
- Fixed the relationship between fflags, frm and fcsr
- Enable subfield to be shadow field of whole csr, and vice versa
## [2.11.1] - 2021-11-19
### Added
- adding the missing shadow_type field for hpmcounter17
## [2.11.0] - 2021-10-15
### Fixed
- canonical ordering requirement of `_Z` extensions fixed
### Added
- adding support for Zmmul extension in ISA regex
## [2.10.2] - 2021-10-06
### Fixed
- islegal function under the warl_interpreter class fixed. The based and bound values are not
extracted correctly as either hex or decimal values. Also removed the logic to truncate values
## [2.10.1] - 2021-08-26
### Fixed
- Changed the default value of 'accessible' to false so input yamls need not declare unsupported xlen
## [2.10.0] - 2021-07-30
### Added
- added default-setters for misa's reset value to match the ISA extensions, to modify warl function of extensions under misa
- added default setter for reset value of mstatus
### Fixed
- changed default values of types for subfields in mstatus
- changed default values of types for mhpmevent*, mcountinhibit, mcounteren and mhpmcounter* to read only constant 0
- changed default values of types for fflags, frm and fcsr to warl if F is present, else read-only constant 0
- changed default values of types for mcycle[h], minstret[h] to warl
- changed default values of types and added checks for subfields of scause, satp, stvec, sie, sip and sstatus
## [2.9.1] - 2021-06-02
### Fixed
- removed an unadded feature in rv32i_platform.yaml
- removed debug_interrupts under mip in rv64i_isa.yaml
## [2.9.0] - 2021-05-24
### Fixed
- fixed issue #58 by adding extra checks for bitmask
- fixed issue #59 by removing custom cause from platform yaml
- resolved inconsistencies in the use of "xlen" and "supported_xlen" in schemaValidator
### Added
- added extra "shadow_type" fields in the csr schemas. These indicate the nature of shadow
(read-only, read-write, etc).
- added parking_loop node in debug_schema to indicate the address of debug rom. Can be empty in
implementations which do not have this feature
## [2.8.0] - 2021-03-02
### Added
- Added checks for K (sub)extension(s)
- Updated docs with information on adding new extension, csrs or specs.
- Added github actions based CI
## [2.7.0] - 2021-02-25
### Added
- added new debug schema for debug based csrs and spec
- cli now takes debug spec as input as well along with isa-spec
- added support for defining custom exceptions and interrupts
## [2.6.3] - 2021-01-19
### Fixed
- added priv_mode field to sedeleg and sideleg csrs
## [2.6.2] - 2021-01-18
### Fixed
- Allow B extension in ISA schema
## [2.6.1] - 2021-01-13
### Fixed
- msb,lsb values of "SD" field in mstatus must be 63 in rv64 mode
- added checks for reset value of misa to adhere to the extensions enabled in the input yaml
- fixed dead-link in the docs.
## [2.6.0] - 2021-01-5
### Added
- Added support for custom csr yaml
- Added new nodes in isa_schema: pmp_granularity and physical_addr_sz
- Checks for pmp, counters and custom csrs
- medeleg, mideleg check for S or N extension
- updated the warl syntax slightly for easier parsing.
### Changed
- fixed warl parsing and islegal function to check reset values
## [2.5.1] - 2020-11-6
### Changed
- modified sn_check and su_check
- scounteren checks to make it depend only on u
- medeleg, mideleg check for S or N extension
## [2.5.0] - 2020-11-6
### Added
- added all n extension csrs
- added missing supervisor csrs
- added default setters for subfields in sip, sie , uip and uie to make it depend as shadows on machine csrs
## [2.4.1] - 2020-10-22
### Changed
- default mpp value to 0
- adding defaults to sub-fields of mtvec
## [2.4.0] - 2020-10-19
### Added
- Added support for pmp csrs in the schema
- Added support for mcycleh and minstreth
- Added special checks for ensuring the shadows are implemented correctly.
- Added support for the following supervisor csrs in the schema: sstatus, sie, sip, stvec, sepc, stval, scause and satp
- Added support for user performance counters, frm, fcsr, time[h], cycle[h] and instret[h] csrs in
the schema.
### Changed
- all fields are now subsumed under a hartid. This allows specifying multiple harts in the same
yaml
- logging mechanism improved.
- isa spec is now validated independently of the platform spec
- privilege and unprivilege version checks are no longer required. This satisfied via the
"allowed" field now.
- improved the 'implemented/accessible' checks for s, u and n extensions
- the "fields" node is now populated by subfields in the increasing order of the placement in the
csr.
- using aliases to reduce the code size
## [2.3.1] - 2020-10-6
### Changed
- Added Zihintpause to ISA string (for PAUSE Hint instruction extension)..
## [2.3.0] - 2020-07-27
### Changed
- Size of the isa schema has been reduced significantly.
- Using anchors in the schema.
- Provided a command line argument to disable anchors in the checked yaml dump.
- adding mycycle, minstret, pmpcfgs and pmpaddrs
- added support for defining multiple harts
## [2.2.2] - 2020-06-09
### Changed
- Changed quickstart 'riscv_config' to 'riscv-config'
- Changed checker.py to add check_reset_fill_fields() description
## [2.2.1] - 2020-05-18
### Changed
- Changed minimum python version requirement to 3.6.0 which is typically easy to install on all
major distributions
- Updated readme with better installation instructions
## [2.2.0] - 2020-04-07
### Changed
- Renamed the 'implemented' field in rv32 and rv64 nodes to 'accessible'.
- Modified appropriate definitions for fields dependent on specific extensions like NSU.
## [2.1.1] - 2020-03-29
## [Fixed
- doc issue for mtimecmp
- mimpid is now part of the default setters list
## [2.1.0] - 2020-03-29
## [Fixed
- Moved machine timer nodes to platform yaml.
## [Added
- `--version` option to arguments to print version and exit when specified.
- Print help and exit when no options/arguments are specified.
## [2.0.2] - 2020-03-28
### Fixed
- Redundant reset-val check for mtvec and misa registers.
## [2.0.1] - 2020-03-25
### Fixed
- typos in quickstart doc
- disabled deployment to repository until authentication issue is fixed.
## [2.0.0] - 2020-03-25
### Added
- adding support for warl fields and support
- documentation for the warl fields added
- reset-value checks added
### Changed
- using a new common template for defining all csrs
- updated docs with new template
- using special function within conf.py to extract comments from yaml file as docs.
### Fixed
- closed issues #10, #11, #12, #13
## [1.0.2] - 2019-08-09
### Changed
- Log is generated only if specified(for API calls to checker.check_specs).
### Fixed
- link in readme now points to github instead of gitlab.
## [1.0.0] - 2019-07-30
### Changed
- Work directory isnt deleted if the directory exists, although the files of the same name will be overwritten.
### Fixed
- Checked yaml passes validation too.
## [0.1.0] - 2019-07-29
### Added
- Added work_dir as arg and always outputs to that dir.
- Added reset vector and nmi vector to platform.yaml
- Vendor description fields in schema.
- An xlen field added for internal use.
### Fixed
- In ISA field in isa_specs subsequent 'Z' extensions should be prefixed by an underscore '_'
- Fixed `cerberus.validator.DocumentError: document is missing` error when platform specs is empty.
- mtvec:mode max value is set to 1.
- privilege-spec and user-spec are taken as strings instead of float.
### Changed
- The representation of the int fields is preserved in the checked-yaml.
- mepc is a required field.
- check_specs function now returns the paths to the dumped normalized files.
- No other entries in node where implemented is False.
- Readonly fields are purged by default.
- Multiple values/entries for the same node is not allowed.
### Removed
- remove *_checked.yaml files from Examples.
- changed templates_platform.yaml to template_platform.yaml in docs.
## [0.0.3] - 2019-07-19
### Fixed
- doc update
## [0.0.2] - 2019-07-19
### Fixed
- pdf documentation
- ci-cd to host pdf as well
## [0.0.1] - 2019-07-18
### Added
- Documentation to install and use pyenv
## [0.0.0] - 2019-07-18
### Added
- Initial schemas for M mode and S mode csrs with constraints as specified in the spec.

View file

@ -0,0 +1,92 @@
.. See LICENSE.incore for details
.. highlight:: shell
============
Contributing
============
Contributions are welcome, and they are greatly appreciated and credit will always be given.
You can contribute in many ways:
Types of Contributions
----------------------
Report Bugs
~~~~~~~~~~~
Report bugs at https://github.com/riscv-software-src/riscv-config/issues/ .
Submit Feedback
~~~~~~~~~~~~~~~
The best way to send feedback is to file an issue at https://github.com/riscv-software-src/riscv-config/issues/.
If you are proposing a feature:
* Explain in detail how it would work.
* Keep the scope as narrow as possible, to make it easier to implement.
* Remember that this is a volunteer-driven project, and that contributions
are welcome :)
Get Started!
------------
Ready to contribute? Here's how to set up `riscv_config` for local development.
1. Fork the `riscv_config` repo on GitHub.
2. Clone your fork locally::
$ git clone https://github.com/riscv-software-src/riscv-config.git
3. Create an issue and WIP merge request that creates a working branch for you::
$ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
5. Commit your changes and push your branch to GitLab::
$ git add .
$ git commit -m "Your detailed description of your changes."
$ git push origin name-of-your-bugfix-or-feature
6. Submit a merge request through the GitHub website.
Versioning
----------
When issuing pull requests, an entry in the CHANGELOG.md is mandatory. The tool adheres to
the [`Semantic Versioning`](https://semver.org/spec/v2.0.0.html) scheme. Following guidelines must
be followed while assigning a new version number :
- Patch-updates: all doc updates (like typos, more clarification,etc).
- Minor-updates: Fixing bugs in current features, adding new features which do not break current
features or working. Adding new extensions.
- Major-updates: Backward incompatible changes.
Note: You can have either a patch or minor or major update.
Note: In case of a conflict, the maintainers will decide the final version to be assigned.
To update the version of the python package for deployment you can use `bumpversion` (installed
using ``pip install bumpversion``)::
$ bumpversion --no-tag --config-file setup.cfg patch # last arg can be: major or minor or patch
If you don't have bumpversion installed you can manually update the version in the following files:
- change the value of variable ``current_version`` in `./setup.cfg`
- change the value of variable ``__version__`` in `./riscv-config/__init__.py`
Merge Request Guidelines
----------------------------
Before you submit a merge request, check that it meets these guidelines:
1. The merge request should include tests (if any).
2. If the merge request adds functionality, the docs should be updated.

29
vendor/riscv/riscv-config/LICENSE vendored Normal file
View file

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2019, InCore Semiconductors Pvt. Ltd.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

2
vendor/riscv/riscv-config/MANIFEST.in vendored Normal file
View file

@ -0,0 +1,2 @@
recursive-include schemas *.yaml
exclude *.pyc

8
vendor/riscv/riscv-config/README.rst vendored Normal file
View file

@ -0,0 +1,8 @@
RISCV-Config
==============
RISC-V Configuration Validator
LICENSE: BSD-3 Clause.
Latest Documentation of RISCV-Config: `HTML <https://riscv-config.readthedocs.io/>`_

26
vendor/riscv/riscv-config/docs/Makefile vendored Normal file
View file

@ -0,0 +1,26 @@
# See LICENSE for details
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = riscv_config
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
clean:
@$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View file

@ -0,0 +1,15 @@
# Build the docs
## For PDF
```
pip install -r requirements.txt
make latexpdf
evince build/latex/*.pdf
```
## HTML
```
pip install -r requirements.txt
make html
firefox build/html/index.html
```

View file

@ -0,0 +1,38 @@
alabaster==0.7.12
Babel==2.7.0
Cerberus==1.3.1
certifi==2019.6.16
chardet==3.0.4
doc8==0.8.0
docutils==0.14
gitdb2==2.0.5
idna==2.8
imagesize==1.1.0
Jinja2==2.10.1
MarkupSafe==1.1.1
oyaml==0.9
packaging==19.0
pbr==5.3.1
Pygments==2.4.2
pyparsing==2.4.0
python-dateutil==2.8.0
pytz==2019.1
PyYAML==5.1.1
requests==2.22.0
restructuredtext-lint==1.3.0
ruamel.yaml==0.15.97
six==1.12.0
smmap2==2.0.5
snowballstemmer==1.2.1
Sphinx==3.0.4
sphinx-rtd-theme==0.4.3
sphinxcontrib-autoyaml==0.5.0
sphinxcontrib-mermaid
sphinxcontrib-websupport==1.1.2
sphinxcontrib-bibtex==1.0.0
stevedore==1.30.1
urllib3==1.25.3
twine==1.13.0
sphinx_tabs
m2r2==0.2.7
mistune==0.8.4

View file

@ -0,0 +1,92 @@
.. See LICENSE.incore for details
.. highlight:: shell
============
Contributing
============
Contributions are welcome, and they are greatly appreciated and credit will always be given.
You can contribute in many ways:
Types of Contributions
----------------------
Report Bugs
~~~~~~~~~~~
Report bugs at https://github.com/riscv-software-src/riscv-config/issues/ .
Submit Feedback
~~~~~~~~~~~~~~~
The best way to send feedback is to file an issue at https://github.com/riscv-software-src/riscv-config/issues/.
If you are proposing a feature:
* Explain in detail how it would work.
* Keep the scope as narrow as possible, to make it easier to implement.
* Remember that this is a volunteer-driven project, and that contributions
are welcome :)
Get Started!
------------
Ready to contribute? Here's how to set up `riscv_config` for local development.
1. Fork the `riscv_config` repo on GitHub.
2. Clone your fork locally::
$ git clone https://github.com/riscv-software-src/riscv-config.git
3. Create an issue and WIP merge request that creates a working branch for you::
$ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
5. Commit your changes and push your branch to GitLab::
$ git add .
$ git commit -m "Your detailed description of your changes."
$ git push origin name-of-your-bugfix-or-feature
6. Submit a merge request through the GitHub website.
Versioning
----------
When issuing pull requests, an entry in the CHANGELOG.md is mandatory. The tool adheres to
the [`Semantic Versioning`](https://semver.org/spec/v2.0.0.html) scheme. Following guidelines must
be followed while assigning a new version number :
- Patch-updates: all doc updates (like typos, more clarification,etc).
- Minor-updates: Fixing bugs in current features, adding new features which do not break current
features or working. Adding new extensions.
- Major-updates: Backward incompatible changes.
Note: You can have either a patch or minor or major update.
Note: In case of a conflict, the maintainers will decide the final version to be assigned.
To update the version of the python package for deployment you can use `bumpversion` (installed
using ``pip install bumpversion``)::
$ bumpversion --no-tag --config-file setup.cfg patch # last arg can be: major or minor or patch
If you don't have bumpversion installed you can manually update the version in the following files:
- change the value of variable ``current_version`` in `./setup.cfg`
- change the value of variable ``__version__`` in `./riscv-config/__init__.py`
Merge Request Guidelines
----------------------------
Before you submit a merge request, check that it meets these guidelines:
1. The merge request should include tests (if any).
2. If the merge request adds functionality, the docs should be updated.

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -0,0 +1,305 @@
/* -- Extra CSS styles for Zephyr content (RTD theme) ----------------------- */
/* make the page width fill the window */
.wy-nav-content {
max-width: none;
}
/* pygments tweak for white-on-black console */
/* hold off on this change for now
.highlight-console .highlight {
background-color: black;
}
.highlight-console .highlight .go, .highlight-console .highlight .gp {
color: white;
}
.highlight-console .highlight .hll {
background-color: white;
}
.highlight-console .highlight .hll .go, .highlight-console .highlight .hll .gp {
color: black;
font-weight: bold;
}
*/
/* tweak doc version selection */
.rst-versions {
position: static !important;
}
.rst-versions .rst-current-version {
padding: 5px;
background-color: #2980B9;
color: #80FF80;
}
.rst-versions .rst-other-versions {
padding: 5px;
}
div.rst-other-versions dl {
margin-bottom: 0;
}
/* tweak spacing after a toctree, fixing issue from sphinx-tabs */
.toctree-wrapper ul, ul.simple ol.simple {
margin-bottom: 24px !important;
}
/* code block highlight color in rtd changed to lime green, no no no */
.rst-content tt.literal, .rst-content code.literal, .highlight {
background: #f0f0f0;
}
.rst-content tt.literal, .rst-content code.literal {
color: #000000;
}
/* code literal links should be blue, and purple after visiting */
a.internal code.literal {
color: #2980B9;
}
a.internal:visited code.literal {
color: #9B59B9;
}
/* Make the version number more visible */
.wy-side-nav-search>div.version {
color: rgba(255,255,255,1);
}
/* squish the space between a paragraph before a list */
div > p + ul, div > p + ol {
margin-top: -20px;
}
/* squish space before an hlist in a list */
li table.hlist {
margin-top: -10px;
margin-bottom: 5px;
}
/* add some space before the figure caption */
p.caption {
# border-top: 1px solid;
margin-top: 1em;
}
/* decrease line leading a bit, 24px is too wide */
p {
line-height: 22px;
}
/* add a colon after the figure/table number (before the caption) */
span.caption-number::after {
content: ": ";
}
p.extrafooter {
text-align: right;
margin-top: -36px;
}
table.align-center {
display: table !important;
}
/* put the table caption at the bottom, as done for figures */
table {
caption-side: bottom;
}
.code-block-caption {
color: #000;
font: italic 85%/1 arial,sans-serif;
padding: 1em 0;
text-align: center;
}
/* make .. hlist:: tables fill the page */
table.hlist {
width: 95% !important;
table-layout: fixed;
}
/* override rtd theme white-space no-wrap in table heading and content */
th,td {
white-space: normal !important;
}
/* dbk tweak for doxygen-generated API headings (for RTD theme) */
.rst-content dl.group>dt, .rst-content dl.group>dd>p {
display:none !important;
}
.rst-content dl.group {
margin: 0 0 12px 0px;
}
.rst-content dl.group>dd {
margin-left: 0 !important;
}
.rst-content p.breathe-sectiondef-title {
text-decoration: underline; /* dbk for API sub-headings */
font-size: 1.25rem;
font-weight: bold;
margin-bottom: 12px;
}
.rst-content div.breathe-sectiondef {
padding-left: 0 !important;
}
/* doxygenXX item color tweaks, light blue background with dark blue top border */
.rst-content dl:not(.docutils) dl dt, dl:not(.docutils,.rst-other-versions) dt {
background: #e7f2fa !important;
border-top: none !important;
border-left: none !important; */
}
/* tweak display of option tables to make first column wider */
col.option {
width: 25%;
}
/* tweak format for <kbd> (:kbd:`F10`) */
kbd
{
-moz-border-radius:3px;
-moz-box-shadow:0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset;
-webkit-border-radius:3px;
-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset;
background-color:#f7f7f7;
border:1px solid #ccc;
border-radius:3px;
box-shadow:0 1px 0 rgba(0,0,0,0.2),0 0 0 2px #fff inset;
color:#333;
display:inline-block;
font-family:Arial,Helvetica,sans-serif;
font-size:11px;
line-height:1.4;
margin:0 .1em;
padding:.1em .6em;
text-shadow:0 1px 0 #fff;
}
/* home page grid display */
.grid {
list-style-type: none !important;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
margin: 1rem auto;
max-width: calc((250px + 2rem) * 4);
}
.grid-item {
list-style-type: none !important;
-webkit-box-flex: 0;
-ms-flex: 0 0 auto;
flex: 0 0 auto;
width: 200px;
text-align: center;
margin: 1rem;
}
.grid-item a {
display: block;
width: 200px;
height: 200px;
padding: 20px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
border: 1px solid #c6cbce;
background-color: #1ab4e7;
color: white;
}
.grid-item h2 {
font-size: 1.1rem;
}
.grid-item img {
margin-bottom: 1.1rem;
max-width: 75%;
}
.grid-item a:hover {
background-color: #1892BA;
color: white;
}
.grid-item p {
margin-top: 0.5rem;
color: #333e48;
}
.grid-icon {
line-height: 1.8;
font-size: 4rem;
color: white;
}
/* add a class for multi-column support
* in docs to replace use of .hlist with
* a .. rst-class:: rst-columns
*/
.rst-columns {
column-width: 18em;
}
/* numbered "h2" steps */
body {
counter-reset: step-count;
}
div.numbered-step h2::before {
counter-increment: step-count;
content: counter(step-count);
background: #cccccc;
border-radius: 0.8em;
-moz-border-radius: 0.8em;
-webkit-border-radius: 0.8em;
color: #ffffff;
display: inline-block;
font-weight: bold;
line-height: 1.6em;
margin-right: 5px;
text-align: center;
width: 1.6em;
}
/* tweak bottom margin of a code block in a list */
.tab div[class^='highlight']:last-child {
margin-bottom: 1em;
}
/* force table content font-size in responsive tables to be 100%
* fixing larger font size for paragraphs in the kconfig tables */
.wy-table-responsive td p {
font-size:100%;
}

View file

@ -0,0 +1,13 @@
/* override table width restrictions */
@media screen and (min-width: 767px) {
.wy-table-responsive table td {
/* !important prevents the common CSS stylesheets from overriding
this as on RTD they are loaded after this stylesheet */
white-space: normal !important;
}
.wy-table-responsive {
overflow: visible !important;
}
}

View file

@ -0,0 +1,14 @@
{% extends "!breadcrumbs.html" %}
{% block breadcrumbs %}
<!-- {{ docs_title }} -->
{# parameterize default name "Docs" in breadcrumb via docs_title in conf.py #}
{% if not docs_title %}
{% set docs_title = "Docs" %}
{% endif %}
<li><a href="{{ pathto(master_doc) }}">{{ docs_title }}</a> &raquo;</li>
{% for doc in parents %}
<li><a href="{{ doc.link|e }}">{{ doc.title }}</a> &raquo;</li>
{% endfor %}
<li>{{ title }}</li>
{% endblock %}

View file

@ -0,0 +1,14 @@
{% extends "!layout.html" %}
{% block document %}
{% if is_release %}
<div class="wy-alert wy-alert-danger">
The <a href="/latest/{{ pagename }}.html">latest development version</a>
of this page may be more current than this released {{ version }} version.
</div>
{% endif %}
{{ super() }}
{% endblock %}
{% block menu %}
{% include "versions.html" %}
{{ super() }}
{% endblock %}

View file

@ -0,0 +1,25 @@
{# Add rst-badge after rst-versions for small badge style. #}
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
<span class="rst-current-version" data-toggle="rst-current-version">
<span class="fa fa-book"> RISC-V Compatibility Test Generator </span>
v: {{ current_version }}
<span class="fa fa-caret-down"></span>
</span>
<div class="rst-other-versions">
<dl>
<dt>{{ _('Release Versions') }}</dt>
{% for slug, url in versions %}
<dd><a href="{{ url }}">{{ slug }}</a></dd>
{% endfor %}
</dl>
<dl>
<dt>{{ _('Quick Links') }}</dt>
<dd>
<a href="https://github.com/riscv/riscv-config">Project Home</a>
</dd>
<dd>
<a href="https://github.com/riscv/riscv-config/tags">Releases</a>
</dd>
</dl>
</div>
</div>

View file

@ -0,0 +1,38 @@
##################
Code Documentation
##################
.. _checker:
riscv_config.checker
---------------------
.. automodule:: riscv_config.checker
:members:
:special-members:
:private-members:
.. _schemaValidator:
riscv_config.schemaValidator
----------------------------
.. automodule:: riscv_config.schemaValidator
:members:
:special-members:
:private-members:
Utils
-----
.. automodule:: riscv_config.utils
:members:
:special-members:
:private-members:
WARL
----
.. automodule:: riscv_config.warl
:members:
:special-members:
:private-members:

View file

@ -0,0 +1,456 @@
# See LICENSE for details
# riscv_config documentation build configuration file,
import sys
import os
import shlex
import re
import textwrap
def gen_schema_doc(infile, outfile):
text = open(infile,'r').read()
rst_file = open(outfile,'w')
x = re.findall("^\s*###(?:(?:\r\n|[\r\n]).+$)*",text,re.M|re.U)
for y in x:
y = y.replace('#','')
y = textwrap.dedent(y)
rst_file.write(y+'\n')
rst_file.close()
def get_version():
changelog = open('../../CHANGELOG.md','r').read()
x = re.findall(r'## \[(.*?)\] -',changelog)[0]
return str(x)
gen_schema_doc('../../riscv_config/schemas/schema_isa.yaml', 'schema_isa.rst')
gen_schema_doc('../../riscv_config/schemas/schema_platform.yaml', 'schema_platform.rst')
gen_schema_doc('../../riscv_config/schemas/schema_debug.yaml', 'schema_debug.rst')
sys.path.insert(0, os.path.abspath('../..'))
sys.setrecursionlimit(1500)
# General information about the project.
project = 'RISC-V Configuration Validator'
copyright = u'2022 InCore Semiconductors Pvt. Ltd'
author = ''
version = str(get_version())
# The full version, including alpha/beta/rc tags
release = version
def setup(app):
app.add_stylesheet("custom.css")
app.add_css_file("_static/custom.css")
# -- General configuration ---------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
needs_sphinx = '1.7.5'
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.mathjax',
'sphinx.ext.viewcode',
'sphinxcontrib.autoyaml',
'sphinxcontrib.bibtex',
'sphinx_tabs.tabs',
'm2r2'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
source_suffix = ['.rst', '.md']
#source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# -- Options for HTML output -------------------------------------------------
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
# -- Options for HTML output ----------------------------------------------
github_url = 'https://github.com/riscv-software-src/riscv-config'
html_show_sourcelink = True
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
#html_theme = 'bootstrap'
#html_theme = 'alabaster'
import sphinx_rtd_theme
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_theme = 'sphinx_rtd_theme'
html_theme_options = {
'prev_next_buttons_location': 'both',
'display_version': True,
'includehidden': False,
'collapse_navigation':True,
'sticky_navigation': True,
'navigation_depth': 4,
'includehidden': True,
'titles_only': False
}
#html_sidebars = {
# "**": ["about.html", "navigation.html", "searchbox.html", "donate.html"]
#}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_logo='_static/Tall_2.png'
html_show_license = True
docs_title = 'Docs / %s' %(version)
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = '_static/onlyC.png'
html_context = {
'show_license': html_show_license,
'docs_title': docs_title,
'is_release': False,
'theme_logo_only': False,
'current_version': version,
}
html_last_updated_fmt = '%b %d, %Y'
# If false, no module index is generated.
html_domain_indices = False
# If false, no index is generated.
html_use_index = True
# If true, the index is split into individual pages for each letter.
html_split_index = True
# If true, links to the reST sources are added to the pages.
html_show_sourcelink = False
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
html_show_sphinx = False
# If true, license is shown in the HTML footer. Default is True.
html_show_license = True
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# The default sidebars (for documents that don't match any pattern) are
# defined by theme itself. Builtin themes are using these templates by
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
# 'searchbox.html']``.
#
# html_sidebars = {}
# Output file base name for HTML help builder.
htmlhelp_basename = 'RISCV-Configdoc'
# -- Options for LaTeX output ---------------------------------------------
# -- Options for LaTeX output ------------------------------------------------
latex_engine='xelatex'
numfig = True
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
'papersize': 'letterpaper',
'releasename':version,
'extraclassoptions': 'openany, twoside',
# Sonny, Lenny, Glenn, Conny, Rejne, Bjarne and Bjornstrup
#'fncychap': '\\usepackage[Bjornstrup]{fncychap}',
'fncychap': '\\usepackage{fancyhdr}',
'fontpkg': '\\usepackage{amsmath,amsfonts,amssymb,amsthm}',
'figure_align':'htbp',
# The font size ('10pt', '11pt' or '12pt').
#
'pointsize': '12pt',
# Additional stuff for the LaTeX preamble.
#
'preamble': r'''
% change the fon to san-serif
%\renewcommand{\familydefault}{\sfdefault}
%%%%%%%%%%%%%%%%%%%% Meher %%%%%%%%%%%%%%%%%%
%%%add number to subsubsection 2=subsection, 3=subsubsection
%%% below subsubsection is not good idea.
\setcounter{secnumdepth}{3}
%
%%%% Table of content upto 2=subsection, 3=subsubsection
\setcounter{tocdepth}{2}
\usepackage{amsmath,amsfonts,amssymb,amsthm}
\usepackage{graphicx}
\usepackage{array, caption, tabularx, ragged2e, booktabs, longtable}
\usepackage{stfloats}
\usepackage{multirow}
\usepackage{gensymb}
\usepackage{fontspec}
\setmainfont{Ubuntu Light}
\definecolor{light-gray}{gray}{0.85}
\usepackage{color,xesearch}
\usepackage{soul}
\sethlcolor{light-gray}
\makeatletter
%%% reduce spaces for Table of contents, figures and tables
%%% it is used "\addtocontents{toc}{\vskip -1.2cm}" etc. in the document
\usepackage[notlot,nottoc,notlof]{}
\usepackage{color}
\usepackage{transparent}
\usepackage{eso-pic}
\usepackage{lipsum}
\usepackage{footnotebackref} %%link at the footnote to go to the place of footnote in the text
%% spacing between line
\usepackage{setspace}
%%%%\onehalfspacing
%%%%\doublespacing
\singlespacing
%%%%%%%%%%% datetime
\usepackage{datetime}
\newdateformat{MonthYearFormat}{%
\monthname[\THEMONTH], \THEYEAR}
%% RO, LE will not work for 'oneside' layout.
%% Change oneside to twoside in document class
\pagestyle{fancy}
\makeatletter
\fancypagestyle{normal}{
\fancyhf{}
%%% Alternating Header for oneside
%\fancyhead[L]{\ifthenelse{\isodd{\value{page}}}{ \small \nouppercase{\leftmark} }{}}
%\fancyhead[R]{\ifthenelse{\isodd{\value{page}}}{}{ \small \nouppercase{\rightmark} }}
%%% Alternating Header for two side
\fancyhead[RO]{\small \nouppercase{\leftmark}}
\fancyhead[RE]{\small \nouppercase{\leftmark}}
\fancyhead[LE,LO]{\py@HeaderFamily \@title\sphinxheadercomma\releasename}
%\fancyhead[RE,RO]{\py@HeaderFamily \c@chapter}
%% for oneside: change footer at right side. If you want to use Left and right then use same as header defined above.
%\fancyfoot[R]{\ifthenelse{\isodd{\value{page}}}{{\tiny Meher Krishna Patel} }{\href{http://pythondsp.readthedocs.io/en/latest/pythondsp/toc.html}{\tiny PythonDSP}}}
%%% Alternating Footer for two side
\fancyfoot[LO, LE]{\small \bf{Copyright \textcopyright \the\year \textbf{ } InCore Semiconductors Pvt. Ltd.}}
%\fancyfoot[LO, LE]{\scriptsize \bf{RISC-V Config}}
%%% page number
\fancyfoot[RO, RE]{\thepage}
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0.4pt}
}
\makeatother
\RequirePackage{tocbibind} %%% comment this to remove page number for following
\addto\captionsenglish{\renewcommand{\contentsname}{Table of contents}}
\addto\captionsenglish{\renewcommand{\listfigurename}{List of figures}}
\addto\captionsenglish{\renewcommand{\listtablename}{List of tables}}
% \addto\captionsenglish{\renewcommand{\chaptername}{Chapter}}
%%reduce spacing for itemize
\usepackage{enumitem}
\setlist{nosep}
%%%%%%%%%%% Quote Styles at the top of chapter
\usepackage{epigraph}
\setlength{\epigraphwidth}{0.8\columnwidth}
\newcommand{\chapterquote}[2]{\epigraphhead[60]{\epigraph{\textit{#1}}{\textbf {\textit{--#2}}}}}
%%%%%%%%%%% Quote for all places except Chapter
\newcommand{\sectionquote}[2]{{\quote{\textit{``#1''}}{\textbf {\textit{--#2}}}}}
\linespread{1}
''',
'maketitle': r'''
\pagenumbering{Roman} %%% to avoid page 1 conflict with actual page 1
\begin{titlepage}
\centering
\begin{figure}[!h]
\centering
\includegraphics[scale=0.2]{incore_logo.png}
\end{figure}
\vspace*{40mm} %%% * is used to give space from top
\textbf{\Huge {RISC-V Configuration Validator}}
\vspace*{40mm} %%% * is used to give space from top
\vspace{10mm}
\Large \textbf{{Release: \releasename}}
\vspace{10mm}
Last update on : \today
\vspace*{0mm}
%\small Last updated : \MonthYearFormat\today
%% \vfill adds at the bottom
\vfill
Copyright \textcopyright \the\year \textbf{ } InCore Semiconductors Pvt. Ltd.
\end{titlepage}
\sloppy
\clearpage
% \pagenumbering{roman}
\tableofcontents
\clearpage
\listoffigures
\clearpage
\listoftables
\clearpage
\pagenumbering{arabic}
''',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
'sphinxsetup': \
'hmargin={0.7in,0.7in}, vmargin={1in,1in}, \
verbatimwithframe=true, \
TitleColor={rgb}{0,0,0}, \
HeaderFamily=\\rmfamily\\bfseries, \
InnerLinkColor={rgb}{0,0,1}, \
OuterLinkColor={rgb}{0,0,1}',
'tableofcontents':' ',
}
#latex_elements = {
# # The paper size ('letterpaper' or 'a4paper').
# #
# 'papersize': 'letterpaper',
#
# # The font size ('10pt', '11pt' or '12pt').
# #
# 'pointsize': '10pt',
#
# # Additional stuff for the LaTeX preamble.
# #
# 'preamble': '',
#
# # Latex figure (float) alignment
# #
# 'figure_align': 'htbp',
#
# 'atendofbody' : ' InCore Semiconductors Pvt. Ltd.'
#}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'riscv_config.tex', 'RISC-V Configuration Validator Documentation',
'InCore Semiconductors Pvt. Ltd.', 'manual'),
]
#latex_logo = '_static/incore_logo.png'
latex_show_pagerefs = True
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'riscvfeaturelegalizer', 'RISC-V Configuration Validator Documentation',
[author], 1)
]
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'riscv_config', 'RISC-V Configuration Validator Documentation',
author, 'InCore Semicondutors', 'One line description of project.',
'Miscellaneous'),
]
# -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
epub_author = author
epub_publisher = author
epub_copyright = copyright
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#
# epub_identifier = ''
# A unique identification for the text.
#
# epub_uid = ''
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
# -- Extension configuration -------------------------------------------------
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'https://docs.python.org/': None}
# -- Options for todo extension ----------------------------------------------
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True

View file

@ -0,0 +1,29 @@
#######################
Welcome to RISCV-Config
#######################
Welcome to RISC-V Configuration Validator documentation.
For information about the changes and additions for releases,
please refer to the :ref:`Revisions <revisions>` documentation.
.. toctree::
:glob:
:numbered:
intro
overview
quickstart
yaml-specs
new-extensions
CONTRIBUTING
code-doc
revisions
Indices and tables
------------------
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View file

@ -0,0 +1,13 @@
############
Introduction
############
**RISCV-Config** (RISCV Configuration Leagalizer) is a YAML based framework which can be used to validate the specifications of a RISC-V implementation against the RISC-V privileged and unprivileged ISA spec and generate standard specification yaml file.
**Caution**: This is still a work in progress and non-backward compatible changes are expected to happen.
For more information on the official RISC-V spec please visit: `RISC-V Specs <https://riscv.org/specifications/>`_
RISCV-Config [`Repository <https://github.com/riscv/riscv-config>`_]

View file

@ -0,0 +1,326 @@
#################################
Adding support for new Extensions
#################################
Adding support for a new ISA extension or an adjoining spec to RISCV-CONFIG could entail one or more of the following updates:
1. Updating the ISA string and its constraints to recognize valid configurations of the new
extension
2. Updating the schema_isa.yaml with new CSRs defined by the new ISA extension
3. Adding new schemas and a new cli argument for supporting adjoining RISC-V specs like debug, trace, etc.
This chapter will descrive how one can go about RISC-V achieving the above tasks.
Updates to the ISA string
=========================
Modifications in constants.py
----------------------------------------
As shown in the example below, any new extensions and sub extensions have to be enabled by adding them in
the regex expression of the `isa_regex <https://github.com/riscv/riscv-config/blob/master/riscv_config/constants.py>`_ node. Following is an instance of the node
for reference:
.. code-block:: python
Z_extensions = [
"Zicbom", "Zicbop", "Zicboz", "Zicsr", "Zifencei", "Zihintpause",
"Zam",
"Zfh",
"Zfinx", "Zdinx", "Zhinx", "Zhinxmin",
"Ztso",
"Zba", "Zbb", "Zbc", "Zbe", "Zbf", "Zbkb", "Zbkc", "Zbkx", "Zbm", "Zbp", "Zbr", "Zbs", "Zbt",
"Zk", "Zkn", "Zknd", "Zkne", "Zknh", "Zkr", "Zks", "Zksed", "Zksh", "Zkt",
"Zmmul",
"Svnapot"
]
isa_regex = \
re.compile("^RV(32|64|128)[IE][ACDFGHJLMNPQSTUVX]*(("+'|'.join(Z_extensions)+")(_("+'|'.join(Z_extensions)+"))*){,1}$")
.. note:: If you are adding a new Z extension, note that it must be added to the list (Z_extensions) above the regex.
This list will be used to generate the correct matching regex, with two instances of each Z extension; first one
immediately after the standard extension in the format `|Zgargle`. This is to support
that fact that the new Z extension could start immediately after the standard extensions which an
underscore. The second will be after the first set of Z extensions in the format `(_(...|Zgargle)`.
Adding constraints in the isa_validator.py file
---------------------------------------------------------
While adding a new extension to the ISA string, there can be certain legal and illegal combinations which cannot be
easily expressed using the regex above. These checks need to be added to the function
`get_extension_list <https://github.com/riscv-software-src/riscv-config/blob/master/riscv_config/isa_validator.py#L4>`_
present in the `isa_validatory.py` file.
The above function returns a tuple of 3 elements:
1. ``extension_list``: A list of all valid extensions that can be extracted from the ISA string.
2. ``err``: a boolean value indicating if an error exists in the ISA string
3. ``err_list``: A list of all errors encountered during the parsing of the string.
The function behaves as follows:
1. The input ISA string is matched against the above regex. A mismatch will cause a return from the
function with ``err`` set to True and ``extension_list`` containing the required message
(`here <https://github.com/riscv-software-src/riscv-config/blob/master/riscv_config/isa_validator.py#L8-L11>`_).
2. Next we split the string into a list where each element is a valid extension (standard,
Z-extension or S-extension) present in the ISA string. The ordering of the extensions in the
list corresponds to their ordering present in the ISA string (`here <https://github.com/riscv-software-src/riscv-config/blob/master/riscv_config/isa_validator.py#L14-L28>`_).
3. We then check for valid canonical ordering of extensions in the ISA string. If any issues are
found, then ``err`` is set to True and ``err_list`` is updated with a corresponding error message.
(`here <https://github.com/riscv-software-src/riscv-config/blob/master/riscv_config/isa_validator.py#L29-L38>`_)
4. Similar canonical ordering checks for performed for the Z extension subsets as well
(`here <https://github.com/riscv-software-src/riscv-config/blob/master/riscv_config/isa_validator.py#L40-L51>`_).
5. Finally, a series of `if` based checks are performed on the ``extension_list`` to see if any
illegal combination exists (`here <https://github.com/riscv-software-src/riscv-config/blob/master/riscv_config/isa_validator.py#L53-L58>`_)
For a majority of new extension additions - only point 5 above needs attention.
Following is an example of the constraints imposed by the Crypto-Scalar extesions which require
additional checks according to point-5 above. The sub-extensions Zkn and Zks are supersets of a
combination of other Zk* abbreviations. Thus, if the superset extension exists in the ISA,
none of the corresponding subset ZK* should be present in the ISA at the same time.
**Constraints used here** :
1.If Zkn is present , its subset extensions Zkne, Zknh, Zknd, Zbkc and Zbkb cannot be present in the ISA string.
2.If Zks is present , its subset extensions Zksed, Zksh, Zbkx, Zbkc and Zbkb cannot be present in the ISA string.
The pythone snippet to capture the above is presented below:
.. code-block:: python
(...)
if 'Zkn' in extension_list and ( set(['Zbkb', 'Zbkc', 'Zbkx', 'Zkne', 'Zknd', 'Zknh']) & set(extension_list)):
err_list.append( "Zkn is a superset of Zbkb, Zbkc, Zbkx, Zkne, Zknd, Zknh. In presence of Zkn the subsets must be ignored in the ISA string.")
err = True
if 'Zks' in extension_list and ( set(['Zbkb', 'Zbkc', 'Zbkx', 'Zksed', 'Zksh']) & set(extension_list) ):
err_list.append( "Zks is a superset of Zbkb, Zbkc, Zbkx, Zksed, Zksh. In presence of Zks the subsets must be ignored in the ISA string.")
err = True
At the end, the function returns the tuple ``(extension_list, err, err_list)``. One should consider
treating the contents of the ``extension_list`` as valid, only when ``err`` is set to False.
Assing new CSR definitions
===========================
There are two parts to addition of a new csr definition to riscv-config
Addition of new csrs to schema
------------------------------
The first step is to add the schema of the new csr in the `schema_isa.yaml
<https://github.com/riscv/riscv-config/blob/master/riscv_config/schemas/schema_isa.yaml>`_ file.
Following is an example of how the `stval` csr of the "S" extension is a added to the schema.
For each csr the author is free to define and re-use existing ``check_with`` functions to impose
further legal conditions. These ``check_with`` functions are defined in the file:
`schemaValidator.py <https://github.com/riscv/riscv-config/blob/master/riscv_config/schemaValidator.py>`_.
.. note:: in the schemaValidator the function name must be prefixed with ``_check_with`` followed by
the name of the function defined in the ``check_with`` field of the csr.
.. code-block:: yaml
stval:
type: dict
schema:
description:
type: string
default: The stval is a warl register that holds the address of the instruction
which caused the exception.
address: {type: integer, default: 0x143, allowed: [0x143]}
priv_mode: {type: string, default: S, allowed: [S]}
reset-val:
type: integer
default: 0
check_with: max_length
rv32:
type: dict
check_with: s_check
schema:
fields: {type: list, default: []}
shadow: {type: string, default: , nullable: True}
msb: {type: integer, default: 31, allowed: [31]}
lsb: {type: integer, default: 0, allowed: [0]}
type:
type: dict
schema: { warl: *ref_warl }
default:
warl:
dependency_fields: []
legal:
- stval[31:0] in [0x00000000:0xFFFFFFFF]
wr_illegal:
- unchanged
accessible:
type: boolean
default: true
check_with: rv32_check
default: {accessible: false}
rv64:
type: dict
check_with: s_check
schema:
fields: {type: list, default: []}
shadow: {type: string, default: , nullable: True}
msb: {type: integer, default: 63, allowed: [63]}
lsb: {type: integer, default: 0, allowed: [0]}
type:
type: dict
schema: { warl: *ref_warl }
default:
warl:
dependency_fields: []
legal:
- stval[63:0] in [0x00000000:0xFFFFFFFFFFFFFFFF]
wr_illegal:
- unchanged
accessible:
default: true
check_with: rv64_check
default: {accessible: false}
The check_with function used in stval above would be defined as follows :
.. code-block:: python
def _check_with_rv32_check(self, field, value):
global xlen
if value:
if not rv32:
self._error( field, "Register cannot be implemented in rv32 mode due to unsupported xlen.")
def _check_with_rv64_check(self, field, value):
global xlen
if value:
if not rv64:
self._error( field, "Register cannot be implemented in rv64 mode due to unsupported xlen.")
def _check_with_max_length(self, field, value):
'''Function to check whether the given value is less than the maximum value that can be stored(2^xlen-1).'''
global supported_xlen
global extensions
maxv = max(supported_xlen)
if value > (2**maxv) - 1:
self._error(field, "Value exceeds max supported length")
def _check_with_s_check(self, field, value):
s = 18
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - s:66 - s] != '1'):
self._error(field, "should not be implemented since S is not present")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - s:34 - s] != '1'):
self._error(field, "should not be implemented S is not present")
Adding default setters in checker.py
------------------------------------
The next step in adding a new csr definition is to add its default values. This is done in
`checker.py <https://github.com/riscv/riscv-config/blob/master/riscv_config/checker.py>`_
Example of adding a default setter for `stval` is show below. This code basically makes the stval
csr accessible by default when the "S" extension is enabled in the ISA string.
.. code-block:: python
schema_yaml['stval']['default_setter'] = sregsetter
.. code-block:: python
def sregset():
'''Function to set defaults based on presence of 'S' extension.'''
global inp_yaml
temp = {'rv32': {'accessible': False}, 'rv64': {'accessible': False}}
if 'S' in inp_yaml['ISA']:
if 32 in inp_yaml['supported_xlen']:
temp['rv32']['accessible'] = True
if 64 in inp_yaml['supported_xlen']:
temp['rv64']['accessible'] = True
return temp
Adding support for Adjoining RISC-V specs
=========================================
Adding new CLI
--------------
For supporting any new adjoining specs, they need to be supplied via a new cli (command line
interface) argument. This new argument needs to be added in the to the parser module in
`Utils.py <https://github.com/riscv/riscv-config/tree/master/riscv_config/utils.py#L106>`_.
The code below shows an example of how the debug spec is added as an argument to the cli parser
module:
.. code-block:: python
parser.add_argument('--debug_spec', '-dspec', type=str, metavar='YAML', default=None, help='The YAML which contains the debug csr specs.')
Adding a new schema
-------------------
Each new adjoining spec must have a YAML schema defined in the `schemas
<https://github.com/riscv/riscv-config/tree/master/riscv_config/schemas>`_ directory.
Adding checks through checker.py and SchemaValidator.py
-------------------------------------------------------
The user might want to add more custom checks in checker.py and SchemaValidator.py for the adjoining
spec.
For example the check_debug_specs() is a function that ensures the isa and debug specifications
conform to their schemas. For details on check_debug_specs() check here : :ref:`checker`.
Details on the checks like s_debug_check() and u_debug_check, that can also be added to
SchemaValidator.py are here: :ref:`schemaValidator`.
Modifications in Constants.py
-----------------------------
The new schema must be added in the constants.py to detect its path globally across other files.
.. code-block:: python
debug_schema = os.path.join(root, 'schemas/schema_debug.yaml')
Performing new spec checks
--------------------------
Finally, in the main.py file the user must call the relevant functions from checker.py for
validating the inputs against the schema.
.. code-block:: python
if args.debug_spec is not None:
if args.isa_spec is None:
logger.error(' Isa spec missing, Compulsory for debug')
checker.check_debug_specs(os.path.abspath(args.debug_spec), isa_file, work_dir, True, args.no_anchors)

View file

@ -0,0 +1,20 @@
########
Overview
########
The following diagram captures the overall-flow of RISCV-Config.
.. image:: riscv_config-flow.png
:align: center
:alt: riscof-flow
The user is required to provide 2 YAML files as input:
1. **ISA Spec**: This YAML file is meant to capture the ISA related features implemented by the user. Details of this input file can be found here : :ref:`isa_yaml_spec`.
2. **Platform Spec**: This YAML file is meant to capture the platform specific features implemented by the user. Details of this input file can be found here : :ref:`platform_yaml_spec`.
Working
=======
The ISA and Platform spec are first checked by the validator for any inconsistencies. Checks like 'F' to exist for 'D' are performed by the validator. The validator exits with an error if any illegal configuration for the spec is provided. Once the validator checks pass, two separate standard yaml files are generated, one for each input type. These standard yaml files contain all fields elaborated and additional info for each node. While the user need not specify all the fields in the input yaml files, the validator will assign defaults to those fields and generate a standard exhaustive yaml for both ISA and Platform spec.

View file

@ -0,0 +1,174 @@
##########
Quickstart
##########
This doc is meant to serve as a quick-guide to setup RISCV-CONFIG and perform a \
sample validation of target specifications.
Install Python
==============
RISCV-CONFIG requires `pip` and `python` (>=3.6) to be available on your system.
Ubuntu
------
Ubuntu 17.10 and 18.04 by default come with python-3.6.9 which is sufficient for using riscv-config.
If you are are Ubuntu 16.10 and 17.04 you can directly install python3.6 using the Universe
repository::
$ sudo apt-get install python3.6
$ pip3 install --upgrade pip
If you are using Ubuntu 14.04 or 16.04 you need to get python3.6 from a Personal Package Archive
(PPA)::
$ sudo add-apt-repository ppa:deadsnakes/ppa
$ sudo apt-get update
$ sudo apt-get install python3.6 -y
$ pip3 install --upgrade pip
You should now have 2 binaries: ``python3`` and ``pip3`` available in your $PATH.
You can check the versions as below::
$ python3 --version
Python 3.6.9
$ pip3 --version
pip 20.1 from <user-path>.local/lib/python3.6/site-packages/pip (python 3.6)
Centos:7
--------
The CentOS 7 Linux distribution includes Python 2 by default. However, as of CentOS 7.7, Python 3
is available in the base package repository which can be installed using the following commands::
$ sudo yum update -y
$ sudo yum install -y python3
$ pip3 install --upgrade pip
For versions prior to 7.7 you can install python3.6 using third-party repositories, such as the
IUS repository::
$ sudo yum update -y
$ sudo yum install yum-utils
$ sudo yum install https://centos7.iuscommunity.org/ius-release.rpm
$ sudo yum install python36u
$ pip3 install --upgrade pip
You can check the versions::
$ python3 --version
Python 3.6.8
$ pip --version
pip 20.1 from <user-path>.local/lib/python3.6/site-packages/pip (python 3.6)
Using Virtualenv for Python
---------------------------
Many a times folks face issues in installing and managing python versions, which is actually a
major issue as many gui elements in Linux use the default python versions. In which case installing
python3.6 using the above methods might break other software. We thus advise the use of **pyenv** to
install python3.6.
For Ubuntu and CentosOS, please follow the steps here: https://github.com/pyenv/pyenv#basic-github-checkout
RHEL users can find more detailed guides for virtual-env here: https://developers.redhat.com/blog/2018/08/13/install-python3-rhel/#create-env
Once you have pyenv installed do the following to install python 3.6.0::
$ pyenv install 3.6.0
$ pip3 install --upgrade pip
$ pyenv shell 3.6.0
You can check the version in the **same shell**::
$ python --version
Python 3.6.0
$ pip --version
pip 20.1 from <user-path>.local/lib/python3.6/site-packages/pip (python 3.6)
Install RISCV-CONFIG
====================
.. note:: If you are using a virtual environment make sure to enable that environment before
performing the following steps.
.. code-block:: bash
$ pip3 install riscv-config
To update an already installed version of RISCV-CONFIG to the latest version:
.. code-block:: bash
$ pip3 install -U riscv-config
To checkout a specific version of riscv-config:
.. code-block:: bash
$ pip3 install riscv-config--1.x.x
Once you have RISCV-CONFIG installed, executing ``riscv-config --help`` should print the following
output ::
riscv-config [-h] [--version] [--isa_spec YAML] [--platform_spec YAML]
[--work_dir DIR] [--verbose]
RISC-V Configuration Validator
optional arguments:
--isa_spec YAML, -ispec YAML
The YAML which contains the ISA specs.
--platform_spec YAML, -pspec YAML
The YAML which contains the Platfrorm specs.
--verbose debug | info | warning | error
--version, -v Print version of RISCV-CONFIG being used
--work_dir DIR The name of the work dir to dump the output files to.
-h, --help show this help message and exit
RISCV-CONFIG for Developers
===========================
Clone the repository from git and install required dependencies.
.. note:: you will still need python (>=3.6.0) and pip.
If you are using `pyenv` as mentioned above, make sure to enable that environment before
performing the following steps.
.. code-block:: bash
$ git clone https://github.com/riscv/riscv-config.git
$ cd riscv-config
$ pip3 install -r requirements.txt
Executing ``python -m riscv-config.main --help`` should display the same help message as above.
Usage Example
=============
.. code-block:: bash
$ riscv-config -ispec examples/rv32i_isa.yaml -pspec examples/rv32i_platform.yaml
Executing the above command should display the following on the terminal:
.. code-block:: bash
[INFO] : Input-ISA file
[INFO] : Loading input file: /scratch/git-repo/github/riscv-config/examples/rv32i_isa.yaml
[INFO] : Load Schema /scratch/git-repo/github/riscv-config/riscv-config/schemas/schema_isa.yaml
[INFO] : Initiating Validation
[INFO] : No Syntax errors in Input ISA Yaml. :)
[INFO] : Initiating post processing and reset value checks.
[INFO] : Dumping out Normalized Checked YAML: /scratch/git-repo/github/riscv-config/riscv_config_work/rv32i_isa_checked.yaml
[INFO] : Input-Platform file
[INFO] : Loading input file: /scratch/git-repo/github/riscv-config/examples/rv32i_platform.yaml
[INFO] : Load Schema /scratch/git-repo/github/riscv-config/riscv_config/schemas/schema_platform.yaml
[INFO] : Initiating Validation
[INFO] : No Syntax errors in Input Platform Yaml. :)
[INFO] : Dumping out Normalized Checked YAML: /scratch/git-repo/github/riscv-config/riscv_config_work/rv32i_platform_checked.yaml

View file

@ -0,0 +1,7 @@
.. raw:: latex
\pagebreak
.. _revisions:
.. mdinclude:: ../../CHANGELOG.md

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -0,0 +1,33 @@
Any Custom CSR
--------------
All custom CSRs follow the same schema as an architecture-defined CSR.
uArch signals
-------------
- **^uarch_ signal/group name**
All signal or group names must contain the ``uarch_`` prefix.
- **msb**
An integer value indicating the msb position of the signal.
- **lsb**
An integer indicating the lsb position of the group.
- **reset-val**
An integer indicating the reset value of a signal/group.
In case of a group, this value resides outside the subfields dict.
- **legal**
A list of legal values for this signal.
- **subfields**
An optional way to structure signals. A subfield would contain msb, lsb, legal fields.

View file

@ -0,0 +1,636 @@
###################
YAML Specifications
###################
This section provides details of the ISA and Platform spec YAML files that need to be provided by the user.
.. _isa_yaml_spec:
ISA YAML Spec
=============
.. note::
All integer fields accept values as integers or hexadecimals (can be used interchangeably) unless specified otherwise.
Different examples of the input yamls and the generated checked YAMLs can be found here : `Examples <https://github.com/riscv/riscv-config/tree/master/examples>`_
.. include:: schema_isa.rst
.. include:: schema_custom.rst
CSR Template
============
All csrs are defined using a common template. Two variants are available: csrs with subfields and
those without
CSRs with sub-fields
--------------------
.. code-block:: yaml
<name>: # name of the csr
description: <text> # textual description of the csr
address: <hex> # address of the csr
priv_mode: <D/M/H/S/U> # privilege mode that owns the register
reset-val: <hex> # Reset value of the register. This an accumulation
# of the all reset values of the sub-fields
rv32: # this node and its subsequent fields can exist
# if [M/S/U]XL value can be 1
accessible: <boolean> # indicates if the csr is accessible in rv32 mode or not.
# When False, all fields below will be trimmed off
# in the checked yaml. False also indicates that
# access-exception should be generated.
fields: # a quick summary of the list of all fields of the
# csr including a list of WPRI fields of the csr.
- <field_name1>
- <field_name2>
- - [23,30] # A list which contains a squashed pair
- 6 # (of form [lsb,msb]) of all WPRI bits within the
# csr. Does not exist if there are no WPRI bits
<field_name1>: # name of the field
description: <text> # textual description of the csr
shadow: <csr-name>::<field> # which this field shadows,'none' indicates that
# this field does not shadow anything.
shadow_type: <text> # indicates the type of shadowing used. Can be one of -
# rw or ro
msb: <integer> # msb index of the field. max: 31, min:0
lsb: <integer> # lsb index of the field. max: 31, min:0
implemented: <boolean> # indicates if the user has implemented this field
# or not. When False, all
# fields below this will be trimmed.
type: # type of field. Can be only one of the following
wlrl: [list of value-descriptors] # field is wlrl and the set of legal values.
ro_constant: <hex> # field is readonly and will return the same value.
ro_variable: True # field is readonly but the value returned depends
# on other arch-states
warl: # field is warl type. Refer to WARL section
dependency_fields: [list]
legal: [list of warl-string]
wr_illegal: [list of warl-string]
rv64: # this node and its subsequent fields can exist
# if [M/S/U]XL value can be 2
accessible: <boolean> # indicates if this register exists in rv64 mode
# or not. Same definition as for rv32 node.
rv128: # this node and its subsequent fields can exist if
# [M/S/U]XL value can be 3
accessible: <boolean> # indicates if this register exists in rv128 mode
# or not. Same definition as for rv32 node.
See register `mstatus` for an example.
CSRs without sub-fields
-----------------------
.. code-block:: yaml
<name>: # name of the csr
description: <text> # textual description of the csr
address: <hex> # address of the csr
priv_mode: <D/M/H/S/U> # privilege mode that owns the register
reset-val: <hex> # Reset value of the register. This an accumulation
# of the all reset values of the sub-fields
rv32: # this node and its subsequent fields can exist
# if [M/S/U]XL value can be 1
accessible: <boolean> # indicates if the csr is accessible in rv32 mode or not.
# When False, all fields below will be trimmed off
# in the checked yaml. False also indicates that
# access-exception should be generated
fields: [] # This should be empty always.
shadow: <csr-name>::<register> # which this register shadows,'none' indicates that
# this register does not shadow anything.
shadow_type: <text> # indicates the type of shadowing used. Can be one of -
# rw or ro
msb: <int> # msb index of the csr. max: 31, min:0
lsb: <int> # lsb index of the csr. max: 31, min:0
type: # type of field. Can be only one of the following
wlrl: [list of value-descriptors] # field is wlrl and the set of legal values.
ro_constant: <hex> # field is readonly and will return the same value.
ro_variable: True # field is readonly but the value returned depends
# on other arch-states
warl: # field is warl type. Refer to WARL section
dependency_fields: [list]
legal: [list of warl-string]
wr_illegal: [list of warl-string]
rv64: # this node and its subsequent fields can exist
# if [M/S/U]XL value can be 2
accessible: <boolean> # indicates if this register exists in rv64 mode
# or not. Same definition as for rv32 node.
rv128: # this node and its subsequent fields can exist if
# [M/S/U]XL value can be 3
accessible: <boolean> # indicates if this register exists in rv128 mode
See register `mscratch` for an example.
Indexed CSRs
------------
.. code-block:: yaml
<name>: # name of the csr
description: <text> # textual description of the csr
address: <hex> # address of the csr
priv_mode: <D/M/H/S/U> # privilege mode that owns the register
indexing_reg: <true/false> # indicates that this register is an indexed type CSR
rv32: # this node and its subsequent fields can exist
# if [M/S/U]XL value can be 1
accessible: <boolean> # indicates if the csr is accessible in rv32 mode or not.
# When False, all fields below will be trimmed off
# in the checked yaml. False also indicates that
# access-exception should be generated
msb: <int> # msb index of the csr. max: 31, min:0
lsb: <int> # lsb index of the csr. max: 31, min:0
index_select_reg: <text> # this field should contain the name the CSR that is used
# as an index select register
index_list: <dictionary> # this field is a list of dictionaries.
- index_val: # value of the index select register that will select
# this particular element
reset-val: # reset value of this element in the list
shadow: <csr-name>::<register> # which this register shadows,'none' indicates that
# this register does not shadow anything.
shadow_type: <text> # indicates the type of shadowing used. Can be one of -
# rw or ro
type: # type of field. Can be only one of the following
wlrl: [list of value-descriptors] # field is wlrl and the set of legal values.
ro_constant: <hex> # field is readonly and will return the same value.
ro_variable: True # field is readonly but the value returned depends
# on other arch-states
warl: # field is warl type. Refer to WARL section
dependency_fields: [list]
legal: [list of warl-string]
wr_illegal: [list of warl-string]
rv64: # this node and its subsequent fields can exist
# if [M/S/U]XL value can be 2
accessible: <boolean> # indicates if this register exists in rv64 mode
# or not. Same definition as for rv32 node.
rv128: # this node and its subsequent fields can exist if
# [M/S/U]XL value can be 3
accessible: <boolean> # indicates if this register exists in rv128 mode
See register `tdata` in debug yaml for an example.
Constraints
-----------
Each csr undergoes the following checks:
1. All implemented fields at the csr-level, if set to True, are checked if
they comply with the supported_xlen field of the ISA yaml.
2. The reset-val is checked against compliance with the type field specified
by the user. All unimplemented fields are considered to be hardwired to 0.
For each of the above templates the following fields for all standard csrs
defined by the spec are frozen and **CANNOT** be modified by the user.
* description
* address
* priv_mode
* fields
* shadow
* msb
* lsb
* The type field for certain csrs (like readonly) is also constrained.
* fields names also cannot be modified for standard csrs
Only the following fields can be modified by the user:
* reset-value
* type
* implemented
Example
-------
Following is an example of how a user can define the mtvec csr in the input ISA YAML for a
32-bit core:
.. code-block:: yaml
mtvec:
reset-val: 0x80010000
rv32:
accessible: true
base:
implemented: true
type:
warl:
dependency_fields: [mtvec::mode]
legal:
- "mode[1:0] in [0] -> base[29:0] in [0x20000000, 0x20004000]" # can take only 2 fixed values in direct mode.
- "mode[1:0] in [1] -> base[29:6] in [0x000000:0xF00000] base[5:0] in [0x00]" # 256 byte aligned values only in vectored mode.
wr_illegal:
- "mode[1:0] in [0] -> Unchanged"
- "mode[1:0] in [1] && writeval in [0x2000000:0x4000000] -> 0x2000000"
- "mode[1:0] in [1] && writeval in [0x4000001:0x3FFFFFFF] -> Unchanged"
mode:
implemented: true
type:
warl:
dependency_fields: []
legal:
- "mode[1:0] in [0x0:0x1] # Range of 0 to 1 (inclusive)"
wr_illegal:
- "Unchanged"
The following is what the riscv-config will output after performing relevant checks on the
above user-input:
.. code-block:: yaml
mtvec:
description: MXLEN-bit read/write register that holds trap vector configuration.
address: 773
priv_mode: M
reset-val: 0x80010000
rv32:
accessible: true
base:
implemented: true
type:
warl:
dependency_fields: [mtvec::mode, writeval]
legal:
- 'mode[1:0] in [0] -> base[29:0] in [0x20000000, 0x20004000]' # can take only 2 fixed values in direct mode.
- 'mode[1:0] in [1] -> base[29:6] in [0x000000:0xF00000] base[5:0] in [0x00]' # 256 byte aligned values only in vectored mode.
wr_illegal:
- 'mode[1:0] in [0] -> Unchanged'
- 'mode[1:0] in [1] && writeval in [0x2000000:0x4000000] -> 0x2000000'
- 'mode[1:0] in [1] && writeval in [0x4000001:0x3FFFFFFF] -> Unchanged'
description: Vector base address.
shadow: none
msb: 31
lsb: 2
mode:
implemented: true
type:
warl:
dependency_fields: []
legal:
- 'mode[1:0] in [0x0:0x1] # Range of 0 to 1 (inclusive)'
wr_illegal:
- Unchanged
description: Vector mode.
shadow: none
msb: 1
lsb: 0
fields:
- mode
- base
rv64:
accessible: false
WARL field Definition
=====================
Since the RISC-V privilege spec indicates several csrs and sub-fields of csrs to be WARL (Write-Any-Read-Legal),
it is necessary to provide a common scheme of representation which can precisely
define the functionality of any such WARL field/register.
Value Descriptors
-----------------
Value descriptors are standard syntaxes that are used to define values in any
part of the WARL string. The 2 basic descriptors are : distinct-values and
range-values as described below:
* **distinct-values** - This specifies that only the particular value should be added to the set.
.. code-block:: python
val
* **range** - This specifies that all the values greater than or equal to lower and less than or equal to upper is to be included in the set.
.. code-block:: python
lower:upper
For any variable in the WARL string, the values can an amalgamation of
distinct-values and/or range-values. They are typically captured in a list as
shown in the below examples:
Example:
.. code-block:: python
# To represent the set {0, 1, 2, 3, 4, 5}
[0:5]
# To represent the set {5, 10, 31}
[5, 10, 31]
# To represent the set {2, 3, 4, 5, 10, 11, 12, 13, 50}
[2:5, 10:13, 50]
WARL Node definition
--------------------
A typical WARL node (used for a WARL csr or subfield) has the following skeleton
in the riscv-config:
.. code-block:: yaml
warl:
dependency_fields: [list of csrs/subfields that legal values depend on]
legal: [list of strings adhering to the warl-syntax for legal assignments]
wr_illegal: [list of strings ahdering to the warl-syntax for illegal assignments]
- **dependency_fields** : This is a list of csrs/subfields whose values affect
the legal values of the csr under question. ``::`` is used as a hierarchy
separator to indicate subfields. This list can be empty to indicate that the
csr under question is not affected by any other architectural state. The
ordering of the csr/subfields has no consequence. Examples of the list are
provided below:
.. code-block:: yaml
- dependency_fields: [mtvec::mode]
- dependency_fields: [misa::mxl, mepc]
The following keywords are reserved and can be used accordingly in the
dependency_fields list:
- ``writeval`` : to represent dependency on the current value being written
to the csr/subfield
- ``currval`` : to represent dependency on the value of the csr/subfield
before performing the write operation
**Restrictions imposed**: The following restrictions are imposed on the
elements of the list:
1. The csrs/subfields mentioned in the list must have their
accessible/implemented fields set to True in the isa yaml.
**Micro-Architectural Dependencies**
riscv-config supports the notion of listing micro-architectural dependencies
in the dependency_fields list.
**Listing uArch Dependencies**
All uArch dependencies need to be listed in the custom specification. An example
node has been described as follows:
.. code-block:: yaml
uarch_signals:
uarch_signal_1:
msb: integer
lsb: integer
reset-val: integer
legal: list
uarch_signal_2:
msb: integer
lsb: integer
reset-val: integer
legal: list
uarch_group_1:
subfields:
uarch_signal_3:
msb: integer
lsb: integer
reset-val: integer
legal: list
uarch_signal_4:
msb: integer
lsb: integer
reset-val: integer
legal: list
.. note:: The custom csr specification is now validated using a custom_schema.yaml
**Restrictions imposed**:
1. uArch depedencies can be listed in either of the two ways,
as a uArch group or as an independent list of uArch signals. While using a uArch
group, the name of the group must have a ``uarch_`` prefix. The following is
an example of a uArch group listed in the dependencies:
.. code-block:: yaml
warl:
dependency_fields: [uarch_cachecontrol::global_valid, uarch_cachecontrol::global_dirty]
legal:
- global_valid[3:0] in [0] and global_dirty[3:0] in [0]
-> base[61:0] bitmask [0x3FFFFFFFFFFFFFFF, 0x0000000000000000]
wr_illegal:
- Unchanged
**NOTE**: The above example shows a dependency string only consisting of uArch
signals grouped under the name ``uarch_cachecontrol``. We can also include other
spec based dependencies in the same list.
2. While listing the uArch dependencies as an independent list, the name of the
uArch signals must not have a ``uarch_`` prefix. The following is an example
of a uArch dependency listed as an independent list:
.. code-block:: yaml
warl:
dependency_fields: [uarch_global_valid, uarch_global_dirty, mstatus::mpp]
legal:
- uarch_global_valid[3:0] in [0] and uarch_global_dirty[3:0] in [0]
-> base[61:0] bitmask [0x3FFFFFFFFFFFFFFF, 0x0000000000000000]
wr_illegal:
- Unchanged
**NOTE**: In the above example, the uArch signals are listed as independent
signals, not grouped under any name. The riscv-config tool will automatically
group them under the name ``uarch_signals`` (internally) for ease of
parsing the rest of the YAML. These signals would be expected to reside as
independent uArch signals in the custom specification.
**Parsing uArch dependencies**
riscv-config internally creates a ``uarch_depends`` dictionary in a ``warl_class``
object. This dictionary is used to store the uArch dependencies. It performs
a lookup on the ``uarch_signals`` node from the custom spec for all checks.
None of these dependencies are removed while generating the checked output YAML.
- **legal** : This field is a list of strings which define the warl functions of
the csr/subfield. Each string needs to adhere to the following warl-syntax:
.. code-block::
dependency_string -> legal_value_string
The ``dependency_string`` substring is basically a string defining a boolean
condition based on the dependent csrs (those listed in the
``dependency_fields``). Only when the boolean condition is satisfied, the
corresponding warl function defined in ``legal_value_string`` substring is
evaluated. A write only occurs when the evaluation of the
``legal_value_string`` also is True. The symbol ``->`` is used to denote
`implies` and is primarily used to split the string in to the above two
substrings. If none of the entries in the list evaluate to True, then the
current write value is considered illegal and the actions defined by the
`wr_illegal` field is carried out.
The substrings ``dependency_string ->`` is optional. If the ``dependency_fields`` list is
empty, then the substring ``dependency_string ->`` must be omitted from the warl string.
The ``dependency_string`` and the ``legal_value_string`` both follow the same
legal syntax:
.. code-block::
<variable-name>[<hi-index>:<lo-index>] <op> <value-descriptors>
The ``variable-name`` field can be the name a csr or a subfield (without the
hierarchical delimiter ``::``). Within the ``dependency_string`` substring the variable
names can only be those listed in the ``dependency_fields`` list. In the
``legal_value_string`` substring however, the ``variable-name`` should be
either `writeval` or the name the csr or the subfield (without the
hierarchical delimiter ``::``) that the warl node belongs to.
The indices fields ``hi-index`` and ``lo-index`` are used to indicate the bit
range of the variable that being looked-up or modified. The basic constraints
are that ``hi-index`` must be greater than the ``lo-index``. If only a
single-bit is being looked-up/assigned, then ``:lo-index`` can be skipped.
This definition applies to both the ``dependency_string`` and the
``legal_value_string``.
The ``op`` field in the ``dependency_string`` substring can be one of ``in``
or ``not in`` to indicate that the variable takes the values defined in the
``value-descriptors`` field or does not take those values respectively. In
addition to the above operators, the ``legal_value_string`` can include one
more operator : ``bitmask``. When using the ``bitmask`` operator the
value-descriptors have to be a list of two distinct-values as follows:
.. code-block:: yaml
csr_name[hi:lo] bitmask [mask, fixedval]
Both the ``mask`` and ``fixedval`` fields are integers. All bits set in the
mask indicates writable bits of the variable. All bits bits cleared in the
mask indicate bits with a constant value which is derived from the
corresponding bit in the fixedval field.
Since the ``dependency_string`` is supposed to represent a boolean condition,
it also has the flexibility to use basic boolean operators like ``&&`` and
``||`` around the above legal syntax. Examples are provided below:
.. code-block:: yaml
(csrA[2:0] in [0, 1]) && (csrB[5:0] in [0:25] || csrB[5:0] in [31,30]) ->
**Restrictions imposed**: The following restrictions are imposed on the above
substrings:
1. No element of the value-descriptors must exceed the maximum value which
can be supported by the indices of the csr/subfield.
2. The csrs/subfields used in the ``dependency_string`` must be in those
listed in the ``dependency_fields`` list.
3. Valid operators in the ``dependency_string`` substring are ``in`` and ``not in``.
4. Valid operators in the ``legal_value_string`` substring are ``in``, ``not in`` and ``bitmask``
5. Within the ``legal_value_string`` substrings the legal values of all bits
of the csr/subfield must be specified. No bits must be left undefined.
6. If the ``dependency_fields`` is empty, then only one legal string must be
defined in this list.
7. The first combination of the ``dependency_string`` and ``legal_value_string``
to evaluate to True, starting from the top of the list is given highest
priority to define the next legal value of the csr/subfield.
8. The reset-value of the csr/subfield must cause atleast one of the legal
strings in the list to evaluate to True.
**Assumptions**
1. Since the list of all ``dependency_string`` substrings is not required to
be exhaustively defined
by the user, if none of the ``dependency_strings`` in the list evaluate to
true, then the current write operation should be treated as an illegal
write operation, and the action defined by the ``wr_illegal`` node must be
carried out.
2. If one of the dependent csrs/subfield defined in the
``dependency_fields`` is not used in the ``dependency_strings``, then it
implictly assumed that, the variable does not affect the legal value for
that string
- **wr_illegal** : This field takes in a list of strings which define the next
legal value of the field when an illegal value is being written to the
csr/subfield. Each string needs to adhere to the following syntax:
.. code-block:: yaml
dependency_string -> update_mode
The ``dependency_string`` follows the same rules, assumptions and restrictions
described above. When the ``dependency_string`` evaluates to True the
``update_mode`` substring defines the next legal value of the csr/subfield.
The supported values of the ``update_mode`` string are :
- **Unchanged**: The value remains unchanged to the current legal value held in the csr/subfield.
- **<val>**: A single value can also be specified
- **Nextup**: ceiling(*writeval*) i.e. the next larger or the largest element of the legal list
- **Nextdown**: floor(*writeval*) i.e. the next smallest or the smallest element of the legal list
- **Nearup**: celing(*writeval*) i.e. the closest element in the list, with the larger element being chosen in case of a tie.
- **Neardown**: floor(*writeval*) i.e. the closes element in the list, with the smaller element being chosen in case of a tie
- **Max**: maximum of all legal values
- **Min**: minimum of all legal values
- **Addr**:
.. code-block:: python
if ( val < base || val > bound)
return Flip-MSB of field
Examples
--------
.. code-block:: yaml
# When base of mtvec depends on the mode field.
WARL:
dependency_fields: [mtvec::mode]
legal:
- "mode[1:0] in [0] -> base[29:0] in [0x20000000, 0x20004000]" # can take only 2 fixed values when mode==0.
- "mode[1:0] in [1] -> base[29:6] in [0x000000:0xF00000] base[5:0] in [0x00]" # 256 byte aligned when mode==1
wr_illegal:
- "mode[1:0] in [0] -> unchanged"
- "mode[1:0] in [1] && writeval in [0x2000000:0x4000000] -> 0x2000000" # predefined value if write value is
- "mode[1:0] in [1] && writeval in [0x4000001:0x3FFFFFFF] -> unchanged"
# When base of mtvec depends on the mode field. Using bitmask instead of range
WARL:
dependency_fields: [mtvec::mode]
legal:
- "mode[1:0] in [0] -> base[29:0] in [0x20000000, 0x20004000]" # can take only 2 fixed values when mode==0.
- "mode[1:0] in [1] -> base[29:0] bitmask [0x3FFFFFC0, 0x00000000]" # 256 byte aligned when mode==1
wr_illegal:
- "mode[1:0] in [0] -> unchanged" # no illegal for bitmask defined legal strings.
- Unchanged
# no dependencies. Mode field of mtvec can take only 2 legal values using range-descriptor
WARL:
dependency_fields:
legal:
- "mode[1:0] in [0x0:0x1] # Range of 0 to 1 (inclusive)"
wr_illegal:
- "0x00"
# no dependencies. using single-value-descriptors
WARL:
dependency_fields:
legal:
- "mode[1:0] in [0x0,0x1] # Range of 0 to 1 (inclusive)"
wr_illegal:
- "0x00"
.. _platform_yaml_spec:
Platform YAML Spec
==================
This section describes each node of the PLATFORM-YAML. For each node, we have identified the fields required from the user and also the various constraints involved.
.. include:: schema_platform.rst
Debug YAML Spec
===============
.. include:: schema_debug.rst

View file

@ -0,0 +1,64 @@
hart_ids: [0]
hart0:
dtim_base:
reset-val: 0x0
rv64:
accessible: false
rv32:
accessible: true
type:
ro_constant: 0x0
shadow:
shadow_type:
msb: 31
lsb: 0
fields:
description: dtim base
address: 0x7C3
priv_mode: M
customcontrol:
reset-val: 0x7
rv64:
accessible: false
rv32:
accessible: true
ienable:
implemented: true
type:
ro_constant: 0x1
description: bit for cache-enable of instruction cache, part of rg_customcontrol
shadow:
shadow_type:
msb: 0
lsb: 0
denable:
implemented: true
type:
ro_constant: 0x1
description: bit for cache-enable of data cache, part of rg_customcontrol
shadow:
shadow_type:
msb: 1
lsb: 1
bpuenable:
implemented: true
type:
ro_constant: 0x1
description: bit for enabling branch predictor unit, part of rg_customcontrol
shadow:
shadow_type:
msb: 2
lsb: 2
arith_excep:
implemented: true
type:
ro_constant: 0x0
description: bit for enabling arithmetic exceptions, part of rg_customcontrol
shadow:
shadow_type:
msb: 3
lsb: 3
fields:
description: the register holds enable bits for arithmetic exceptions, branch predictor unit, i-cache, d-cache units
address: 0x800
priv_mode: U

View file

@ -0,0 +1,67 @@
hart_ids: [0]
hart0: &hart0
Debug_Spec_Version: '1.0.0'
supported_xlen: [32]
debug_mode: true
dcsr:
reset-val: 0x0
rv64:
accessible: false
rv32:
accessible: true
prv:
implemented: true
step:
implemented: true
nmip:
implemented: true
type:
ro_constant: 0x0
mprven:
implemented: true
v:
implemented: True
type:
ro_constant: 0x0
cause:
implemented: True
type:
ro_constant: 0x0
stoptime:
implemented: True
stopcount:
implemented: True
stepie:
implemented: True
ebreaku:
implemented: True
ebreaks:
implemented: True
ebreakm:
implemented: True
ebreakvu:
implemented: True
ebreakvs:
implemented: True
debugver:
implemented: True
type:
ro_constant: 0x0
dpc:
reset-val: 0x0
rv32:
accessible: true
rv64:
accessible: false
dscratch0:
reset-val: 0x0
rv32:
accessible: true
rv64:
accessible: false
dscratch1:
reset-val: 0x0
rv32:
accessible: true
rv64:
accessible: false

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
nmi:
label: nmi_vector
reset:
label: reset_vector
mtime:
implemented: True
address: 0x20000

View file

@ -0,0 +1,16 @@
nmi:
label: nmi_vector
reset:
label: reset_vector
mtime:
implemented: false
mtimecmp:
implemented: false
mcause_non_standard:
implemented: true
mtval_condition_writes:
implemented: false
scause_non_standard:
implemented: false
stval_condition_writes:
implemented: false

View file

@ -0,0 +1,57 @@
hart_ids: [0]
hart0:
dtim_base:
reset-val: 0x0
rv32:
accessible: false
rv64:
accessible: true
type:
ro_constant: 0x0
shadow:
msb: 63
lsb: 0
description: dtim base
address: 0x7C3
priv_mode: M
customcontrol:
reset-val: 0x7
rv32:
accessible: false
rv64:
accessible: true
ienable:
implemented: true
type:
ro_constant: 0x1
description: bit for cache-enable of instruction cache, part of rg_customcontrol
shadow:
msb: 0
lsb: 0
denable:
implemented: true
type:
ro_constant: 0x1
description: bit for cache-enable of data cache, part of rg_customcontrol
shadow:
msb: 1
lsb: 1
bpuenable:
implemented: true
type:
ro_constant: 0x1
description: bit for enabling branch predictor unit, part of rg_customcontrol
shadow:
msb: 2
lsb: 2
arith_excep:
implemented: true
type:
ro_constant: 0x0
description: bit for enabling arithmetic exceptions, part of rg_customcontrol
shadow:
msb: 3
lsb: 3
description: the register holds enable bits for arithmetic exceptions, branch predictor unit, i-cache, d-cache units
address: 0x800
priv_mode: U

View file

@ -0,0 +1,138 @@
hart_ids: [0]
hart0: &hart0
Debug_Spec_Version: '1.0.0'
supported_xlen: [64]
debug_mode: true
parking_loop: 0x800
tselect:
rv32:
accessible: False
rv64:
accessible: True
type:
warl:
dependency_fields: []
legal:
- tselect[63:0] in [0x00000000:0x3]
wr_illegal:
- unchanged
tinfo:
rv32:
accessible: False
rv64:
accessible: True
index_select_reg: tselect
index_list:
- reset-val: 0x78
index_val: 0
shadow:
shadow_type:
type:
ro_constant: 0x78
- reset-val: 0x8
index_val: 1
shadow:
shadow_type:
type:
ro_constant: 0x8
- reset-val: 0x10
index_val: 2
shadow:
shadow_type:
type:
ro_constant: 0x10
tdata1:
rv32:
accessible: False
rv64:
accessible: True
index_select_reg: tselect
index_list:
- reset-val: 0xdeadbeef
index_val: 0
shadow:
shadow_type:
type:
ro_constant: 0xdeadbeef
- reset-val: 0
index_val: 1
shadow:
shadow_type:
type: &mywarl
warl:
dependency_fields: []
legal:
- writeval[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]
wr_illegal:
- Unchanged
- reset-val: 0
index_val: 2
shadow:
shadow_type:
type:
warl:
dependency_fields: []
legal:
- writeval[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]
wr_illegal:
- Unchanged
dcsr:
reset-val: 0x40000003
rv32:
accessible: false
rv64:
accessible: true
prv:
implemented: true
step:
implemented: true
nmip:
implemented: true
type:
ro_variable: true
mprven:
implemented: true
v:
implemented: True
cause:
implemented: True
type:
ro_variable: true
stoptime:
implemented: True
stopcount:
implemented: True
stepie:
implemented: True
ebreaku:
implemented: True
ebreaks:
implemented: True
ebreakm:
implemented: True
ebreakvu:
implemented: True
ebreakvs:
implemented: True
debugver:
implemented: True
type:
ro_constant: 0x4
dpc:
reset-val: 0x0
rv64:
accessible: true
rv32:
accessible: false
dscratch0:
reset-val: 0x0
rv64:
accessible: true
rv32:
accessible: false
dscratch1:
reset-val: 0x0
rv64:
accessible: true
rv32:
accessible: false

View file

@ -0,0 +1,449 @@
hart_ids: [0]
hart0:
custom_exceptions:
- cause_val: 25
cause_name: halt_ebreak
priv_mode: M
- cause_val: 26
cause_name: halt_trigger
priv_mode: M
- cause_val: 28
cause_name: halt_step
priv_mode: M
- cause_val: 29
cause_name: halt_reset
priv_mode: M
custom_interrupts:
- cause_val: 16
cause_name: debug_interrupt
on_reset_enable: 1
priv_mode : M
ISA: RV64IMAFDCNSUZicsr_Zifencei
User_Spec_Version: '2.3'
pmp_granularity: 1
physical_addr_sz: 32
supported_xlen:
- 64
sscratch:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- sscratch[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]
wr_illegal:
- Unchanged
reset-val: 0
sepc:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- "sepc[63:60] in [1,2] spec[59:0] not in [1,2]"
wr_illegal:
- "Unchanged"
reset-val: 0x2000000000000000
stval:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- stval[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]
wr_illegal:
- Unchanged
reset-val: 0
scause:
rv32:
accessible: false
rv64:
accessible: true
exception_code:
implemented: True
interrupt:
implemented: True
reset-val: 0
mepc:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- "mepc[63:0] bitmask [0xFFFFFFFFFFFFFFFE, 0x0000000000000000]"
wr_illegal:
- "Unchanged"
reset-val: 0
mtval:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- mtval[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]
wr_illegal:
- Unchanged
reset-val: 0
mcause:
rv32:
accessible: false
rv64:
accessible: true
reset-val: 0
mcycle:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- mcycle[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]
wr_illegal:
- Unchanged
reset-val: 0
minstret:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- minstret[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]
wr_illegal:
- Unchanged
reset-val: 0
fcsr:
rv32:
accessible: false
rv64:
accessible: true
fflags:
implemented: true
type:
warl:
dependency_fields: []
legal:
- fflags[4:0] in [0x00:0x1F]
wr_illegal:
- Unchanged
frm:
implemented: true
type:
warl:
dependency_fields: []
legal:
- frm[2:0] in [0x0:0x7]
wr_illegal:
- Unchanged
time:
rv32:
accessible: false
rv64:
accessible: true
type:
ro_variable: true
reset-val: 0
mideleg:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- mideleg[63:0] bitmask [0x000000000000F7FF,0x0000000000000000]
wr_illegal:
- Unchanged
medeleg:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- medeleg[63:0] bitmask [0x000000000000F7FF,0x0000000000000000]
wr_illegal:
- Unchanged
pmpcfg0:
reset-val: 0
rv32:
accessible: false
rv64:
accessible: true
pmp0cfg:
implemented: true
type:
warl:
dependency_fields: [pmpcfg0::pmp0cfg]
legal:
- "pmp0cfg[7] in [0] -> pmp0cfg[7] in [0x0:0x1] pmp0cfg[6:5] in [0] pmp0cfg[4:3] not in [2] pmp0cfg[2:0] not in [2,6]"
wr_illegal:
- Unchanged
pmp1cfg:
implemented: true
type:
warl:
dependency_fields: [pmpcfg0::pmp1cfg]
legal:
- "pmp1cfg[7] in [0] -> pmp1cfg[7] in [0x0,0x1] pmp1cfg[6:5] in [0] pmp1cfg[4:3] not in [2] pmp1cfg[2:0] not in [2,6]"
wr_illegal:
- Unchanged
pmp2cfg:
implemented: true
type:
warl:
dependency_fields: [pmpcfg0::pmp2cfg]
legal:
- "pmp2cfg[7] in [0] -> pmp2cfg[7] in [0x0,0x1] pmp2cfg[6:5] in [0] pmp2cfg[4:3] not in [2] pmp2cfg[2:0] not in [2,6]"
wr_illegal:
- Unchanged
pmp3cfg:
implemented: true
type:
warl:
dependency_fields: [pmpcfg0::pmp3cfg]
legal:
- "pmp3cfg[7] in [0] -> pmp3cfg[7] in [0x0,0x1] pmp3cfg[6:5] in [0] pmp3cfg[4:3] not in [2] pmp3cfg[2:0] not in [2,6]"
wr_illegal:
- Unchanged
pmp4cfg:
implemented: true
type:
ro_constant: 0
pmp5cfg:
implemented: true
type:
ro_constant: 0
pmp6cfg:
implemented: true
type:
ro_constant: 0
pmp7cfg:
implemented: true
type:
ro_constant: 0
pmpcfg2:
reset-val: 0
rv32:
accessible: false
rv64:
accessible: true
pmp8cfg:
implemented: true
type:
ro_constant: 0
pmp9cfg:
implemented: true
type:
ro_constant: 0
pmp10cfg:
implemented: true
type:
ro_constant: 0
pmp11cfg:
implemented: true
type:
ro_constant: 0
pmp12cfg:
implemented: true
type:
ro_constant: 0
pmp13cfg:
implemented: true
type:
ro_constant: 0
pmp14cfg:
implemented: true
type:
ro_constant: 0
pmp15cfg:
implemented: true
type:
ro_constant: 0
pmpaddr0:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: [pmpcfg0::pmp0cfg]
legal:
- "pmp0cfg[7] in [0] -> pmpaddr0[63:0] bitmask [0xFFFFFFFFFFFFFFFE,0x0000000000000000]"
wr_illegal:
- Unchanged
reset-val: 0
pmpaddr1:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: [pmpcfg0::pmp1cfg]
legal:
- "pmp1cfg[7] in [0] -> pmpaddr1[63:0] bitmask [0xFFFFFFFFFFFFFFFE,0x0000000000000000]"
wr_illegal:
- Unchanged
reset-val: 0
pmpaddr2:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: [pmpcfg0::pmp2cfg]
legal:
- "pmp2cfg[7] in [0] -> pmpaddr2[63:0] bitmask [0xFFFFFFFFFFFFFFFE,0x0000000000000000]"
wr_illegal:
- Unchanged
reset-val: 0
pmpaddr3:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: [pmpcfg0::pmp3cfg]
legal:
- "pmp3cfg[7] in [0] -> pmpaddr3[63:0] bitmask [0xFFFFFFFFFFFFFFFE,0x0000000000000000]"
wr_illegal:
- Unchanged
reset-val: 0
pmpaddr4: &pmp_const
rv32:
accessible: False
rv64:
accessible: True
type:
ro_constant : 0
pmpaddr5:
<<: *pmp_const
pmpaddr6:
<<: *pmp_const
pmpaddr7:
<<: *pmp_const
pmpaddr8:
<<: *pmp_const
pmpaddr9:
<<: *pmp_const
pmpaddr10:
<<: *pmp_const
pmpaddr11:
<<: *pmp_const
pmpaddr12:
<<: *pmp_const
pmpaddr13:
<<: *pmp_const
pmpaddr14:
<<: *pmp_const
pmpaddr15:
<<: *pmp_const
mhpmcounter3:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- "mhpmcounter3[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]"
wr_illegal:
- Unchanged
reset-val: 0
mhpmcounter4:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- "mhpmcounter4[63:0] in [0x0000000000000000:0xFFFFFFFFFFFFFFFF]"
wr_illegal:
- Unchanged
reset-val: 0
mhpmevent3:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- "mhpmevent3[63:0] in [0x0000000000000000:0x000000000000001C]"
wr_illegal:
- Unchanged
reset-val: 0
mhpmevent4:
rv32:
accessible: false
rv64:
accessible: true
type:
warl:
dependency_fields: []
legal:
- "mhpmevent4[63:0] in [0x0000000000000000:0x000000000000001C]"
wr_illegal:
- Unchanged
reset-val: 0
satp:
rv32:
accessible: false
rv64:
accessible: true
ppn:
type:
warl:
dependency_fields: []
legal:
- "ppn[43:0] in [0x00000000000:0xFFFFFFFFFFF]"
wr_illegal:
- Unchanged
asid:
type:
warl:
dependency_fields: []
legal:
- "asid[15:0] in [0x0000:0x00FF]"
wr_illegal:
- Unchanged
mode:
type:
warl:
dependency_fields: []
legal:
- "mode[3:0] in [0,8]"
wr_illegal:
- Unchanged
reset-val: 0x0000000000000000

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
nmi:
label: nmi_vector
address: 12288
reset:
label: reset_vector
address: 16384
mtime:
implemented: false
mtimecmp:
implemented: false
mcause_non_standard:
implemented: true
mtval_condition_writes:
implemented: false
scause_non_standard:
implemented: false
stval_condition_writes:
implemented: false

View file

@ -0,0 +1,16 @@
nmi:
label: nmi_vector
reset:
label: reset_vector
mtime:
implemented: false
mtimecmp:
implemented: false
mcause_non_standard:
implemented: true
mtval_condition_writes:
implemented: false
scause_non_standard:
implemented: false
stval_condition_writes:
implemented: false

View file

@ -0,0 +1,3 @@
Cerberus>=1.3.1
ruamel.yaml==0.17.16
pyyaml==5.2

View file

@ -0,0 +1,4 @@
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
__version__ = '3.18.1'

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,41 @@
import os
import re
root = os.path.abspath(os.path.dirname(__file__))
isa_schema = os.path.join(root, 'schemas/schema_isa.yaml')
debug_schema = os.path.join(root, 'schemas/schema_debug.yaml')
platform_schema = os.path.join(root, 'schemas/schema_platform.yaml')
custom_schema = os.path.join(root, 'schemas/schema_custom.yaml')
Zvl_extensions = [
"Zvl32b", "Zvl64b", "Zvl128b", "Zvl256b", "Zve512b", "Zvl1024b"
]
Zvef_extensions = [
"Zve32f", "Zve64f"
]
Zved_extensions = [
"Zve64d"
]
Zve_extensions = [
"Zve32x", "Zve64x"
] + Zvef_extensions + Zved_extensions
Z_extensions = [
"Zicbom", "Zicbop", "Zicboz", "Zicntr", "Zicsr", "Zicond", "Zicfilp", "Zicfiss", "Zifencei", "Zihintpause", "Zihpm", "Zimop",
"Zmmul",
"Zam", "Zabha", "Zacas",
"Zca", "Zcb", "Zcf", "Zcd" , "Zcmp", "Zcmt", "Zcmop",
"Zfh", "Zfa",
"Zfinx", "Zdinx", "Zhinx", "Zhinxmin",
"Ztso",
"Zba", "Zbb", "Zbc", "Zbe", "Zbf", "Zbkb", "Zbkc", "Zbkx", "Zbm", "Zbp", "Zbpbo", "Zbr", "Zbs", "Zbt",
"Zk", "Zkn", "Zknd", "Zkne", "Zknh", "Zkr", "Zks", "Zksed", "Zksh", "Zkt",
"Zpn", "Zpsf"
] + Zve_extensions + Zvl_extensions
S_extensions = ['Smrnmi','Smdbltrp', 'Ssdbltrp', 'Svnapot','Svadu', 'Sddbltrp', 'Sdext']
sub_extensions = Z_extensions + S_extensions
isa_regex = \
re.compile("^RV(32|64|128)[IE][ACDFGHJLMNPQSTUV]*(("+'|'.join(sub_extensions)+")(_("+'|'.join(sub_extensions)+"))*){,1}(X[a-z0-9]*)*(_X[a-z0-9]*)*$")

View file

@ -0,0 +1,29 @@
class ValidationError(Exception):
def __init__(self, message, errors):
super().__init__(message)
self.message = message
self.errors = errors
def __errPrint__(self, foo, space=' '):
'''
Function to petty print the error from cerberus.
'''
error = ''
for key in foo.keys():
error += space + str(key) + ":"
if isinstance(foo[key], list):
for e in foo[key]:
error += f'\n{space} - {e}'
elif isinstance(foo[key][0], dict):
error += "\n" + self.__errPrint__(foo[key][0], space + space)
elif isinstance(foo[key][0], list):
for e in foo[key][0]:
error += f'\n{space} - {e}'
else:
error += str(foo[key][0])
error += "\n"
return error.rstrip()
def __str__(self):
return self.message + "\n" + self.__errPrint__(self.errors)

View file

@ -0,0 +1,248 @@
import riscv_config.constants as constants
from collections import Counter
import re
def get_extension_list(isa):
extension_list = []
err = False
err_list = []
if not constants.isa_regex.match(isa):
err = True
err_list.append(f'Input ISA string : {isa} does not match accepted canonical ordering')
return (extension_list, err, err_list)
str_match = re.findall('(?P<stdisa>[^\d]*?)(?!_)*(?P<zext>Z.*?)*(?P<sext>S[a-z]*)*(?P<xext>X[a-z0-9]*)*(_|$)',isa)
extension_list= []
standard_isa = ''
zext_list = []
for match in str_match:
stdisa, zext, sext, xext, ignore = match
if stdisa != '':
for e in stdisa:
extension_list.append(e)
standard_isa = stdisa
if zext != '':
extension_list.append(zext)
zext_list.append(zext)
if sext != '':
extension_list.append(sext)
if xext != '':
extension_list.append(xext)
# check for duplicates
counts = Counter(extension_list)
duplicate_list = list([item for item in counts if counts[item]>1])
if duplicate_list:
err = True
err_list.append(f'Found duplicate extensions in ISA string: {duplicate_list}')
return (extension_list, err, err_list)
# check ordering of ISA
canonical_ordering = 'IEMAFDQLCBJKTPVNSHU'
order_index = {c: i for i, c in enumerate(canonical_ordering)}
for i in range(len(standard_isa)-1):
a1 = standard_isa[i]
a2 = standard_isa[i+1]
if order_index[a1] > order_index[a2]:
err = True
err_list.append( "Alphabet '" + a1 + "' should occur after '" + a2)
# check canonical ordering within Zextensions
for i in range(len(zext_list)-1):
a1 = zext_list[i][1].upper()
a2 = zext_list[i+1][1].upper()
a3 = zext_list[i][2]
a4 = zext_list[i+1][2]
if order_index[a1] > order_index[a2]:
err = True
err_list.append( f"Z extension {zext_list[i]} must occur after {zext_list[i+1]}")
elif a1 == a2 and a3 > a4:
err = True
err_list.append( f"Within the Z{a1.lower()} category extension {zext_list[i]} must occur after {zext_list[i+1]}")
if 'I' not in extension_list and 'E' not in extension_list:
err_list.append( 'Either of I or E base extensions need to be present in the ISA string')
err = True
if 'F' in extension_list and not "Zicsr" in extension_list:
err_list.append( "F cannot exist without Zicsr.")
err = True
if 'D' in extension_list and not 'F' in extension_list:
err_list.append( "D cannot exist without F.")
err = True
if 'Q' in extension_list and not 'D' in extension_list:
err_list.append( "Q cannot exist without D and F.")
err = True
if 'Zam' in extension_list and not 'A' in extension_list:
err_list.append( "Zam cannot exist without A.")
err = True
if 'N' in extension_list and not 'U' in extension_list:
err_list.append( "N cannot exist without U.")
err = True
if 'S' in extension_list and not 'U' in extension_list:
err_list.append( "S cannot exist without U.")
err = True
if 'Zkn' in extension_list and ( set(['Zbkb', 'Zbkc', 'Zbkx', 'Zkne', 'Zknd', 'Zknh']) & set(extension_list)):
err_list.append( "Zkn is a superset of Zbkb, Zbkc, Zbkx, Zkne, Zknd, Zknh. In presence of Zkn the subsets must be ignored in the ISA string.")
err = True
if 'Zks' in extension_list and ( set(['Zbkb', 'Zbkc', 'Zbkx', 'Zksed', 'Zksh']) & set(extension_list) ):
err_list.append( "Zks is a superset of Zbkb, Zbkc, Zbkx, Zksed, Zksh. In presence of Zks the subsets must be ignored in the ISA string.")
err = True
if 'Zk' in extension_list and ( set(['Zbkb', 'Zbkc', 'Zbkx', 'Zkne', 'Zknd',
'Zknh', 'Zkn','Zkr','Zkt']) & set(extension_list)):
err_list.append( "Zk is a superset of Zbkb, Zbkc, Zbkx, Zkne, Zknd, Zknh, Zkn, Zkt, Zkr. In presence of Zk the subsets must be ignored in the ISA string.")
err = True
if 'Zfinx' in extension_list and not "Zicsr" in extension_list:
err_list.append( "Zfinx cannot exist without Zicsr.")
err = True
if 'F' in extension_list and "Zfinx" in extension_list:
err_list.append( "F and Zfinx cannot exist together")
err = True
if 'Zdinx' in extension_list and not 'Zfinx' in extension_list:
err_list.append( "Zdinx cannot exist without Zfinx.")
err = True
if 'Zhinx' in extension_list and not 'Zfinx' in extension_list:
err_list.append( "Zhinx cannot exist without Zfinx.")
err = True
if 'Zhinx' in extension_list and 'Zfh' in extension_list:
err_list.append( "Zhinx and Zfh cannot exist together.")
err = True
if 'Zhinxmin' in extension_list and not 'Zfinx' in extension_list:
err_list.append( "Zhinxmin cannot exist without Zfinx.")
err = True
if 'Zhinxmin' in extension_list and 'Zfh' in extension_list:
err_list.append( "Zhinxmin and Zfh cannot exist together.")
err = True
if 'Zfa' in extension_list and not 'Zfh' in extension_list:
err_list.append( "Zfa cannot exist without Zfh.")
if 'Zbpbo' in extension_list :
if not 'Zpn' in extension_list :
err_list.append( "'Zpn' is required.")
err = True
if 'Zpn' in extension_list :
if not 'Zbpbo' in extension_list :
err_list.append( "'Zbpbo' is required.")
err = True
if '64' in isa and not 'Zpsf' in extension_list :
err_list.append( "RV64 requires 'Zpsf'.")
err = True
if not ('M' in extension_list or 'Zmmul' in extension_list):
err_list.append("baseline multiplication extension not found.")
if 'Zpsf' in extension_list and not err :
if not 'Zbpbo' in extension_list :
err_list.append( "'Zbpbo' is required.")
err = True
if not 'Zpn' in extension_list :
err_list.append( "'Zpn' is required.")
err = True
# Check V extensions
if 'V' in extension_list and 'D' not in extension_list:
err_list.append("V cannot exist without D and F.")
err = True
if len(set(['V'] + constants.Zve_extensions) & set(extension_list)) > 1:
err_list.append(f"V and Zve* cannot exist together.")
err = True
if (set(constants.Zvl_extensions) & set(extension_list)) and not (
set(['V'] + constants.Zve_extensions) & set(extension_list)
):
err_list.append("Zvl* cannot exist without V or Zve*.")
err = True
if set(constants.Zvef_extensions) & set(extension_list) and (
{"F", "Zfinx"} & set(extension_list)
):
err_list.append("Zve*f cannot exist without F or Zfinx.")
err = True
if (set(constants.Zved_extensions) & set(extension_list)) and not (
{"D", "Zdinx"} & set(extension_list)
):
err_list.append("Zve64d cannot exist without D or Zdinx.")
err = True
return (extension_list, err, err_list)
def get_march_mabi (isa : str, opt_remove_custom_exts: bool = False):
'''
This function returns the corresponding march and mabi argument values
for RISC-V GCC
arguments:
isa: (string) this is the isa string in canonical order
returns:
march: (string) this is the string to be passed to -march to gcc for a given isa
mabi: (string) this is the string to be passed to -mabi for given isa
march_list: (list) gives march as a list of all extensions as elements
None: if ISA validation throws error
'''
# march generation
march = 'rv32' if '32' in isa else 'rv64'
march_list = []
march_list.append(march)
# get extension list
(ext_list, err, err_list) = get_extension_list(isa)
# if isa validation throws errors, return None
if err:
return None
# extensions to be nullified
null_ext = [
# privilege modes
'U',
'S',
# rnmi
'Smrnmi',
# debug mode
'Sdext',
# performance counter
'Zicntr',
'Zihpm',
# unratified Zb* extensions
'Zbe',
'Zbf',
'Zbm',
'Zbr',
]
# add Zbp and Zbt to null_ext if Zbpbo is present
if 'Zbpbo' in ext_list:
null_ext += ['Zbp', 'Zbt']
# remove all custom extensions
for ext in ext_list:
if ext.startswith('X'):
if opt_remove_custom_exts:
ext_list.remove(ext)
# construct march
for ext in ext_list:
if ext not in null_ext:
march_list.append(ext.lower())
# suffix multicharacter extensions with '_'
if len(ext) == 1:
march += ext.lower()
else:
# suffix multiline extensions with '_'
march = march + '_' + ext.lower()
# mabi generation
mabi = 'ilp32'
if 'E' in ext_list:
mabi += 'e'
if 'F' in ext_list and 'D' in ext_list:
mabi += 'd'
elif 'F' in ext_list:
mabi += 'f'
if 'rv64' in march:
mabi = mabi.replace('ilp32', 'lp64')
return (march, mabi, march_list)

View file

@ -0,0 +1,60 @@
import logging
import os
import sys
import shutil
from riscv_config import __version__ as version
import riscv_config.checker as checker
import riscv_config.utils as utils
from riscv_config.errors import ValidationError
def main():
'''
Entry point for riscv_config.
'''
# Set up the parser
parser = utils.riscv_config_cmdline_args()
args = parser.parse_args()
if len(sys.argv) < 2:
parser.print_help()
raise SystemExit
if (args.version):
print('RISCV-CONFIG: RISC-V Configuration Validator')
print('Version: ' + version)
return 0
# Set up the logger
utils.setup_logging(args.verbose)
logger = logging.getLogger()
logger.handlers = []
ch = logging.StreamHandler()
ch.setFormatter(utils.ColoredFormatter())
logger.addHandler(ch)
fh = logging.FileHandler('run.log', 'w')
logger.addHandler(fh)
work_dir = os.path.join(os.getcwd(), args.work_dir)
if not os.path.exists(work_dir):
logger.debug('Creating new work directory: ' + work_dir)
os.mkdir(work_dir)
try:
checked_specs = checker.check_csr_specs(ispec=args.isa_spec,
customspec=args.custom_spec,
dspec=args.debug_spec,
pspec=args.platform_spec,
work_dir=work_dir,
logging=True,
no_anchors=args.no_anchors)
isa_file = checked_specs[0]
custom_file = checked_specs[1]
debug_file = checked_specs[2]
platform_file = checked_specs[3]
except ValidationError as msg:
logger.error(str(msg))
return 1
logger.info('Done.')
if __name__ == "__main__":
exit(main())

View file

@ -0,0 +1,450 @@
from cerberus import Validator
import riscv_config.constants as constants
from riscv_config.isa_validator import *
import re
from riscv_config.warl import warl_class
class schemaValidator(Validator):
''' Custom validator for schema having the custom rules necessary for implementation and checks.'''
def __init__(self, *args, **kwargs):
global rv32
global rv64
global extensions
global xlen
global supported_xlen
supported_xlen = kwargs.get('xlen')
xlen = 0 if len(supported_xlen)==0 else max(supported_xlen)
global isa_string
isa_string = kwargs.get('isa_string')
global extension_list
global ext_err
global ext_err_list
if isa_string :
(extension_list, ext_err, ext_err_list) = get_extension_list(isa_string)
if 32 in supported_xlen:
rv32 = True
else:
rv32 = False
if 64 in supported_xlen:
rv64 = True
else:
rv64 = False
super(schemaValidator, self).__init__(*args, **kwargs)
def _check_with_smrnmi_check(self, field, value):
global extension_list
if value and 'Smrnmi' not in extension_list:
self._error(field,
"Register cannot be implemented without Smrnmi extension in ISA."
)
def _check_with_zicfiss_check(self, field, value):
global extension_list
if value and 'Zicfiss' not in extension_list:
self._error(field,
"Register cannot be implemented without Zicfiss extension in ISA."
)
def _check_with_satp_modes64(self, field, value):
pass
def _check_with_isa_xlen(self, field, value):
global supported_xlen
global isa_string
if str(max(supported_xlen)) not in isa_string:
self._error(field, 'XLEN in ISA and supported_xlen fields do not match')
def _check_with_phy_addr(self, field, value):
if rv32 and value > 34:
self._error(field, "Physical address size should not exceed 34 for RV32")
if rv64 and value > 56:
self._error(field, "Physical address size should not exceed 56 for RV64")
def _check_with_cache_block_size(self, field, value):
if value & (value - 1) != 0:
self._error(field, "Cache block size should be power of 2")
def _check_with_cannot_be_false_rv64(self, field, value):
''' Functions ensures that the field cannot be False in rv64 mode'''
if rv64 and not value:
self._error(field, "This field cannot be False")
def _check_with_cannot_be_false_rv64f(self, field, value):
''' Functions ensures that the field cannot be False in rv64 mode when F is present'''
global extension_list
if rv64 and 'F' in extension_list and not value:
self._error(field, "This field cannot be False")
def _check_with_cannot_be_false_rv32f(self, field, value):
''' Functions ensures that the field cannot be False in rv32 mode when F is present'''
if rv32 and 'F' in extension_list and not value:
self._error(field, "This field cannot be False")
def _check_with_cannot_be_false_rv32(self, field, value):
''' Functions ensures that the field cannot be False in rv32 mode'''
if rv32 and not value:
self._error(field, "This field cannot be False")
def _check_with_capture_isa_specifics(self, field, value):
'''
Function to extract and store ISA specific information(such as xlen,user
spec version and extensions present)
and check whether the dependencies in ISA extensions are satisfied.
'''
global xlen
global extensions
global extension_list
global ext_err_list
global ext_err
extension_enc = list("00000000000000000000000000")
if "32" in value:
xlen = 32
ext = value[4:]
elif "64" in value:
xlen = 64
ext = value[4:]
elif "128" in value:
xlen = 128
ext = value[5:]
else:
self._error(field, "Invalid width in ISA.")
if not constants.isa_regex.match(value):
self._error(field, 'Input ISA string does not match regex')
if ext_err:
for e in ext_err_list:
self._error(field, e)
#ISA encoding for future use.
for x in "ABCDEFHIJKLMNPQSTUVX":
if (x in extension_list):
extension_enc[25 - int(ord(x) - ord('A'))] = "1"
extensions = int("".join(extension_enc), 2)
extensions = int("".join(extension_enc), 2)
def _check_with_rv32_check(self, field, value):
global xlen
if value:
if not rv32:
self._error(
field,
"Register cannot be implemented in rv32 mode due to unsupported xlen."
)
def _check_with_rv64_check(self, field, value):
global xlen
if value:
if not rv64:
self._error(
field,
"Register cannot be implemented in rv64 mode due to unsupported xlen."
)
def _check_with_max_length(self, field, value):
'''Function to check whether the given value is less than the maximum value that can be stored(2^xlen-1).'''
global supported_xlen
global extensions
maxv = max(supported_xlen)
if value > (2**maxv) - 1:
self._error(field, "Value exceeds max supported length")
def _check_with_max_length32(self, field, value):
'''Function to check whether the given value is less than the maximum value that can be stored(2^xlen-1).'''
maxv = 32
if value > (2**maxv) - 1:
self._error(field, "Value exceeds max supported length")
def _check_with_xtveccheck(self, field, value):
'''Function to check whether the inputs in range type in mtvec are valid.'''
global xlen
maxv = 2**(xlen - 2)
for list in value:
if (len(list) > 2):
self._error(field,
"Only two values are allowed in each sub list.")
for val in list:
if not (val < maxv):
self._error(field, "Invalid values.")
def _check_with_s_exists(self, field, value):
'''Function to check that the value can be true only when 'S' mode
exists in the ISA string'''
global extension_list
if value and 'S' not in extension_list:
self._error(field, "cannot be set to True without 'S' mode support")
def _check_with_mtval_update(self, field, value):
'''Function to check if the mtval_update bitmap adhered to the required
restrictions.
'''
global extension_list
if (((value & 0xFFFF000F4000) != 0) or (value > 0xFFFFFFFFFFFFFFFF)):
self._error(field, 'Bits corresponding to reserved cause values should not be set')
if (value & 0xB000) != 0 and 'S' not in extension_list:
self._error(field, 'Bits corresponding to page-faults can only be set when S mode is supported')
if (value & 0xF00000) != 0 and 'H' not in extension_list:
self._error(field, 'Bits corresponding to guest-page faults can only be set when H mode is supported')
def _check_with_s_check(self, field, value):
s = 18
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - s:66 - s] != '1'):
self._error(field, "should not be implemented since S is not present")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - s:34 - s] != '1'):
self._error(field, "should not be implemented S is not present")
def _check_with_fs_check(self, field, value):
f = 5
s = 18
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - s:66 - s] != '1') and (mxl[65 - f:66 - f] != '1'):
self._error(field, "neither S nor F is present")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - s:34 - s] != '1') and (mxl[33 - f:34 - f] != '1'):
self._error(field, "neither S nor F is present")
def _check_with_f_check(self, field, value):
f = 5
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - f:66 - f] != '1'):
self._error(field, "should not be implemented since F is not present")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - f:34 - f] != '1'):
self._error(field, "should not be implemented since F is not present")
def _check_with_u_check(self, field, value):
u = 20
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - u:66 - u] != '1'):
self._error(field, "should not be implemented since U is not present")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - u:34 - u] != '1'):
self._error(field, "should not be implemented since U is not present")
def _check_with_s_debug_check(self, field, value):
''' Function ensures that the ro_constant is hardwired to zero when S is present in the ISA string
Used mainly for debug schema'''
global extension_list
if 'S' not in extension_list :
if 'ro_constant' not in value:
self._error(field, "S is not present to dcsr.v should be ro_constant = 0")
elif value['ro_constant'] != 0:
self._error(field, "S is not present but ro constant is not hardwired to zero")
def _check_with_u_debug_check(self, field, value):
''' Function ensures that the ro_constant is hardwired to zero when U is present in the ISA string
Used mainly for debug schema'''
global extension_list
if 'U' not in extension_list :
if value['ro_constant'] != 0:
self._error(field, "U is not present but ro constant is not hardwired to zero")
def _check_with_su_check(self, field, value):
s = 18
u = 20
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - s:66 - s] != '1') and (mxl[65 - u:66 - u] != '1'):
self._error(field, "neither S nor U is present")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - s:34 - s] != '1') and (mxl[33 - u:34 - u] != '1'):
self._error(field, "neither S nor U is present")
def _check_with_reset_ext(self, field, value):
if rv64:
mxl = format(extensions, '#066b')
reset = format(value, '#066b')
if (mxl[40:66] != reset[40:66] ):
self._error(field, "reset value does not match with extensions enabled")
elif rv32 :
mxl = format(extensions, '#034b')
reset = format(value, '#034b')
if (mxl[8:34] != reset[8:34] ):
self._error(field, "reset value does not match with extensions enabled")
def _check_with_sn_check(self, field, value):
s = 18
n = 13
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - s:66 - s] != '1') and (mxl[65 - n:66 - n] != '1'):
self._error(field, "neither S nor N is present")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - s:34 - s] != '1') and (mxl[33 - n:34 - n] != '1'):
self._error(field, "neither S nor N is present")
def _check_with_n_check(self, field, value):
n = 13
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - n:66 - n] != '1'):
self._error(field, "should not be implemented since N is not present")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - n:34 - n] != '1'):
self._error(field, "should not be implemented since N is not present")
def _check_with_h_check(self, field, value):
h = 7
check = False
if 'implemented' in value:
if value['implemented']:
check = True
if 'accessible' in value:
if value['accessible']:
check = True
if rv64 and check:
mxl = format(extensions, '#066b')
if (mxl[65 - h:66 - h] != '1'):
self._error(field, "h is not present")
elif rv32 and check:
mxl = format(extensions, '#034b')
if (mxl[33 - h:34 - h] != '1'):
self._error(field, "h is not present")
def _check_with_mdeleg_checks(self, field, value):
global extension_list
if rv32:
if (value['rv32']['accessible'] == True and
(not 'S' in extension_list and
not 'N' in extension_list)):
value['rv32']['accessible'] = False
self._error(field, "S and N are not present")
if rv64:
if (value['rv64']['accessible'] == True and
(not 'S' in extension_list and
not 'N' in extension_list)):
value['rv64']['accessible'] = False
self._error(field, "S and N are not present")
def _check_with_ndeleg_checks(self, field, value):
global extension_list
if rv32:
if (value['rv32']['accessible'] == True and
not 'N' in extension_list):
value['rv32']['accessible'] = False
self._error(field, "should not be implemented since N is not present")
if rv64:
if (value['rv64']['accessible'] == True and
not 'N' in extension_list):
value['rv64']['accessible'] = False
self._error(field, "should not be implemented since N is not present")
def _check_with_xcause_check(self, field, value):
'''Function to verify the inputs for mcause.'''
if (min(value) < 16):
self._error(
field, "Invalid platform specific values for exception cause.")
def _check_with_key_check(self, field, value):
if value['base']['type']['warl']['dependency_fields'] != []:
par = re.split(
"::", value['base']['type']['warl']['dependency_fields'][0])
if not par[1] in value:
self._error(field, " {} not present".format(par[1]))
def _check_with_medeleg_reset(self, field, value):
global supported_xlen
s = format(value, '#{}b'.format(supported_xlen[0] + 2))
if (s[-11:-10]) != '0' and value >= int("0x400", 16):
self._error(field, " 11th bit must be hardwired to 0")
def _check_with_sedeleg_reset(self, field, value):
global supported_xlen
s = format(value, '#{}b'.format(supported_xlen[0] + 2))
if (s[-11:-8]) != '000' and value >= int("400", 16):
self._error(field, " 11,10,9 bits should be hardwired to 0")
def _check_with_vxsat_check(self, field, value):
check = False
xlen_str = 'rv32' if rv32 else 'rv64'
global extension_list
if 'Zpn' in extension_list and not value[xlen_str]['accessible']:
self._error(field,f'[{xlen_str}] Field should be accessible since Zpn is present')
if not 'Zpn' in extension_list and value[xlen_str]['accessible']:
self._error(field,f'[{xlen_str}] Field should be accessible only when Zpn is present')
if not 'Zpn' in extension_list and value[xlen_str]['ov']['implemented']:
self._error(field, f'[{xlen_str}] Subfield ov should not be implemented since Zpn is not present')
if 'Zpn' in extension_list and not value[xlen_str]['ov']['implemented']:
self._error(field, f'[{xlen_str}] Subfield ov should be implemented since Zpn is present in isa')

View file

@ -0,0 +1,175 @@
hart_schema:
type: dict
schema:
keysrules:
regex: '^(?!uarch_)'
type: dict
schema:
description:
type: string
default: custom csr.
address:
type: integer
priv_mode:
type: string
default: M
reset-val:
type: integer
default: 0x0
rv32:
type: dict
schema:
fields:
type: list
default: []
keysrules:
type: dict
regex: '[a-zA_Z0-9_]*'
schema:
description:
type: string
default: subfield.
shadow:
type: string
default:
nullable: True
shadow_type:
type: string
default: rw
nullable: True
allowed: ['rw', 'ro']
msb:
type: integer
lsb:
type: integer
implemented:
type: boolean
default: false
type:
type: dict
oneof:
- schema:
ro_constant:
type: integer
- schema:
ro_variable:
type: boolean
- schema:
warl:
type: dict
schema:
dependency_fields:
type: list
empty: true
schema:
type: string
nullable: true
legal:
type: list
schema:
type: string
wr_illegal:
type: list
schema:
type: string
rv64:
type: dict
schema:
fields:
type: list
default: []
keysrules:
type: dict
regex: '[a-zA_Z0-9_]*'
schema:
description:
type: string
default: subfield.
shadow:
type: string
default:
nullable: True
shadow_type:
type: string
default: rw
nullable: True
allowed: ['rw', 'ro']
msb:
type: integer
lsb:
type: integer
implemented:
type: boolean
default: false
type:
type: dict
oneof:
- schema:
ro_constant:
type: integer
- schema:
ro_variable:
type: boolean
- schema:
warl:
type: dict
schema:
dependency_fields:
type: list
empty: true
schema:
type: string
nullable: true
legal:
type: list
schema:
type: string
wr_illegal:
type: list
schema:
type: string
uarch_signals:
required: false
type: dict
schema:
keysrules:
regex: '^uarch_'
type: dict
oneof:
- schema:
msb:
type: integer
required: true
lsb:
type: integer
required: true
reset-val:
type: integer
required: true
min: 0
legal:
type: list
required: false
nullable: true
schema:
type: integer
- schema:
subfields:
type: dict
schema:
msb:
type: integer
required: true
lsb:
type: integer
required: true
legal:
type: list
required: false
nullable: true
schema:
type: integer
reset-val:
type: integer
required: true
min: 0

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,328 @@
###
#reset
#-----
#
# - **Description**: Stores the value for the reset vector. It can either be a label or an address.
#
# * label: A string field equal to the label in the assembly code
# * address: A value equal to the absolute address where the vector is present
# - **Constraints**: label and address both cannot be defined
# - **Examples**:
#
# .. code-block:: yaml
#
# reset:
# label: reset_vector
# reset:
# label: 0x80000000
reset:
type: dict
schema:
label:
type: string
excludes: ['address']
address:
type: integer
excludes: ['label']
required: True
###
#nmi
#---
#
# - **Description**: Stores the value for the nmi vector. It can either be a label or an address.
#
# * label: A string field equal to the label in the assembly code.
# * address: A value equal to the absolute address where the vector is present.
# - **Constraints**: label and address both cannot be defined
# - **Examples**:
#
# .. code-block:: yaml
#
# nmi:
# label: nmi_vector
# address: 0x8000000
nmi:
type: dict
schema:
label:
type: string
excludes: ['address']
address:
type: integer
excludes: ['label']
required: False
default:
label: nmi_vector
address: 0x0
###
#mtime
#-----
#
# - **Description**: Stores the fields for memory mapped *mtime* register.
#
# * implemented: A boolean field indicating that the register has been implemented.
# * address: A value equal to the physical address at which the register is present.
#
# - **Examples**:
#
# .. code-block:: yaml
#
# mtime:
# implemented: True
# address: 0x458
mtime:
type: dict
schema:
address:
type: integer
implemented:
type: boolean
default: False
default:
implemented: False
###
#mtimecmp
#--------
#
# - **Description**: Stores the fields for memory mapped *mtimecmp* register.
#
# * implemented: A boolean field indicating that the register has been implemented.
# * address: A value equal to the physical address at which the register is present.
#
# - **Examples**:
#
# .. code-block:: yaml
#
# mtimecmp:
# implemented: True
# address: 0x458
mtimecmp:
type: dict
schema:
address:
type: integer
implemented:
type: boolean
default: False
default:
implemented: False
###
#mtval_condition_writes
#----------------------
#
# - **Description**: Stores the fields for *mtval_condition_writes* register.
#
# * implemented: A Boolean value indicating whether the register is implemented.
# * behaviour: A dictionary type to specify which of the exceptions modify the mtval_condition_writes reg
#
# - e0: A string type describing the behaviour of exception 0.
# - e1: A string type describing the behaviour of exception 1.
# - e2: A string type describing the behaviour of exception 2.
# - e3: A string type describing the behaviour of exception 3.
# - e4: A string type describing the behaviour of exception 4.
# - e5: A string type describing the behaviour of exception 5.
# - e6: A string type describing the behaviour of exception 6.
# - e7: A string type describing the behaviour of exception 7.
# - e8: A string type describing the behaviour of exception 8.
# - e9: A string type describing the behaviour of exception 9.
# - e10: A string type describing the behaviour of exception 10.
# - e11: A string type describing the behaviour of exception 11.
# - e12: A string type describing the behaviour of exception 12.
# - e13: A string type describing the behaviour of exception 13.
# - e15: A string type describing the behaviour of exception 15.
#
# - **Examples**:
#
# .. code-block:: yaml
#
# TBD: Provide a concrete use-case for the above.
mtval_condition_writes:
type: dict
schema:
implemented:
type: boolean
default: False
behaviour:
type: dict
schema:
e00:
type: string
e01:
type: string
e02:
type: string
e03:
type: string
e04:
type: string
e05:
type: string
e06:
type: string
e07:
type: string
e08:
type: string
e09:
type: string
e10:
type: string
e11:
type: string
e12:
type: string
e13:
type: string
e15:
type: string
default:
implemented: False
###
#scause_non_standard
#-------------------
#
# - **Description**: Stores the fields for the *scause* register.
#
# * implemented: A boolean field indicating that the register has been implemented.
# * values: The list of exception values greater than 16 as assumed by the platform as integers.
#
# - **Examples**:
#
# .. code-block:: yaml
#
# scause_non_standard:
# implemented: True
# value: [16,17,20]
scause_non_standard:
type: dict
schema:
implemented:
type: boolean
values:
type: list
check_with: xcause_check
default:
implemented: False
###
#stval_condition_writes
#----------------------
#
# - **Description**: Stores the fields for *stval_condition_writes* register.
#
# - implemented: A Boolean value indicating whether the field is implemented.
# - behaviour: A dictionary type to specify which of the exceptions modify the stval_condition_writes reg
#
# - e0: A string type describing the behaviour of exception 0.
# - e1: A string type describing the behaviour of exception 1.
# - e2: A string type describing the behaviour of exception 2.
# - e3: A string type describing the behaviour of exception 3.
# - e4: A string type describing the behaviour of exception 4.
# - e5: A string type describing the behaviour of exception 5.
# - e6: A string type describing the behaviour of exception 6.
# - e7: A string type describing the behaviour of exception 7.
# - e8: A string type describing the behaviour of exception 8.
# - e9: A string type describing the behaviour of exception 9.
# - e10: A string type describing the behaviour of exception 10.
# - e11: A string type describing the behaviour of exception 11.
# - e12: A string type describing the behaviour of exception 12.
# - e13: A string type describing the behaviour of exception 13.
# - e15: A string type describing the behaviour of exception 15.
#
# - **Examples**:
#
# .. code-block:: yaml
#
# TBD: Provide a concrete use-case for the above.
stval_condition_writes:
type: dict
schema:
implemented:
type: boolean
default: False
behaviour:
type: dict
schema:
e00:
type: string
e01:
type: string
e02:
type: string
e03:
type: string
e04:
type: string
e05:
type: string
e06:
type: string
e07:
type: string
e08:
type: string
e09:
type: string
e10:
type: string
e11:
type: string
e12:
type: string
e13:
type: string
e15:
type: string
default:
implemented: False
###
#zicbo_cache_block_sz
#--------------------
#
# - **Description**: byte size of the cache block
# - **Constraints**:
#
# - zicbom_sz cannot exceed 4096
# - zicboz_sz cannot exceed 4096
# - for both the above variables the integer must be a power of 2
#
# - **Examples**:
#
# .. code-block:: yaml
#
# zicbo_cache_block_sz :
# implemented: true
# zicbom_sz: 64
# zicboz_sz: 64
zicbo_cache_block_sz:
type: dict
schema:
implemented:
type: boolean
default: False
zicbom_sz:
type: integer
max: [4096]
default: 0
check_with: cache_block_size
zicboz_sz:
type: integer
max: [4096]
default: 0
check_with: cache_block_size
default:
implemented: False

View file

@ -0,0 +1,160 @@
import logging
import argparse
import operator
import ruamel
from ruamel.yaml import YAML
import yaml as pyyaml
def hexint_presenter(dumper, data):
return dumper.represent_int(hex(data))
class NoAliasDumper(pyyaml.Dumper):
def ignore_aliases(self, data):
return True
def dump_yaml(foo, outfile, no_anchors=False):
if no_anchors:
pyyaml.add_representer(int, hexint_presenter)
pyyaml.dump(foo, outfile, Dumper=NoAliasDumper)
else:
yaml = YAML(typ="rt")
yaml.default_flow_style = False
yaml.allow_unicode = True
yaml.compact(seq_seq=False, seq_map=False)
yaml.indent = 4
yaml.block_seq_indent = 2
yaml.dump(foo, outfile)
def load_yaml(foo, no_anchors=False):
if no_anchors:
yaml = YAML(typ="safe")
else:
yaml = YAML(typ="rt")
yaml.default_flow_style = False
yaml.allow_unicode = True
yaml.compact(seq_seq=False, seq_map=False)
yaml.indent = 4
yaml.block_seq_indent = 2
try:
with open(foo, "r") as file:
return yaml.load(file)
except ruamel.yaml.constructor.DuplicateKeyError as msg:
logger = logging.getLogger(__name__)
error = "\n".join(str(msg).split("\n")[2:-7])
logger.error(error)
raise SystemExit
class ColoredFormatter(logging.Formatter):
"""
Class to create a log output which is colored based on level.
"""
def __init__(self, *args, **kwargs):
super(ColoredFormatter, self).__init__(*args, **kwargs)
self.colors = {
'DEBUG': '\033[94m',
'INFO': '\033[92m',
'WARNING': '\033[93m',
'ERROR': '\033[91m',
}
self.reset = '\033[0m'
def format(self, record):
msg = str(record.msg)
level_name = str(record.levelname)
name = str(record.name)
color_prefix = self.colors[level_name]
return '{0}{1:<9s} {4}: {2}{3}'.format(color_prefix,
'[' + level_name + ']', msg,
self.reset, name)
def setup_logging(log_level):
"""Setup logging
Verbosity decided on user input
:param log_level: User defined log level
:type log_level: str
"""
numeric_level = getattr(logging, log_level.upper(), None)
if not isinstance(numeric_level, int):
print(
"\033[91mInvalid log level passed. Please select from debug | info | warning | error\033[0m"
)
raise ValueError("{}-Invalid log level.".format(log_level))
logging.basicConfig(level=numeric_level)
class SortingHelpFormatter(argparse.HelpFormatter):
def add_arguments(self, actions):
actions = sorted(actions, key=operator.attrgetter('option_strings'))
super(SortingHelpFormatter, self).add_arguments(actions)
def riscv_config_cmdline_args():
parser = argparse.ArgumentParser(
formatter_class=SortingHelpFormatter,
prog="riscv_config",
description="RISC-V Configuration Validator")
parser.add_argument('--version',
'-v',
help='Print version of RISCV-CONFIG being used',
action='store_true')
parser.add_argument('--isa_spec',
'-ispec',
type=str,
metavar='YAML',
default=None,
help='The YAML which contains the ISA specs.')
parser.add_argument('--platform_spec',
'-pspec',
type=str,
metavar='YAML',
default=None,
help='The YAML which contains the Platfrorm specs.')
parser.add_argument('--debug_spec',
'-dspec',
type=str,
metavar='YAML',
default=None,
help='The YAML which contains the debug csr specs.')
parser.add_argument('--custom_spec',
'-cspec',
type=str,
metavar='YAML',
default=None,
help='The YAML which contains the custom csr specs.')
parser.add_argument(
'--work_dir',
type=str,
default="riscv_config_work",
metavar='DIR',
help='The name of the work dir to dump the output files to.')
parser.add_argument('--verbose',
action='store',
default='info',
help='debug | info | warning | error',
metavar="")
parser.add_argument('--no_anchors',
action='store_true',
help='Unroll/Disable all anchors')
return parser
def pretty_print_yaml(yaml):
res = ''''''
for line in ruamel.yaml.round_trip_dump(yaml, indent=5, block_seq_indent=3).splitlines(True):
res += line
return res

View file

@ -0,0 +1,750 @@
import re
import os
import logging
import riscv_config.utils as utils
import textwrap
import random
import pprint as pp
logger = logging.getLogger(__name__)
class warl_class():
"""This is a class for handling various operations and checks for the WARL
type of registers and/or subfields as defined by the riscv-config spec<TODO:
link here>. While riscv-config remains to be the major user of this package,
this class can be used as an importable python package as well in several
other scenarios to perform checks on a particular WARL string.
The basic WARL node should be dict adhering to the following syntax:
.. code-block:: yaml
warl:
dependency_fields: [list]
legal: [list of warl-string]
wr_illegal: [list of warl-string]
:param node: This input is the dict adhering to the above syntax.
:type node: dict
:param csrname: this is string indicating the name of the csr or
csr::subfield which is defined as a WARL type. This primarily used to
generate a series of legible error and debug messages. If the input warl
node is for a subfield, then use ``::`` as the delimiter between the csr
name and the subfield name.
:type csrname: str
:param f_msb: the max msb location of the csr or subfield.
:type f_msb: int
:param f_lsb: the min lsb location of the csr or subfield.
:type f_lsb: int
:param spec: This is the entire isa-spec of a single hart. This dict is
primarily used by this class to perform specific checks on reset-vals
and on dependency_vals string validity.
:type spec: dict
"""
def __init__(self, node, csrname, f_msb, f_lsb, spec=None):
"""Constructor Method
"""
self.node = node
self.f_msb = f_msb
self.f_lsb = f_lsb
self.bitlen = f_msb - f_lsb + 1
self.maxval = (2**(self.bitlen))-1
self.spec = spec
self.regex_legal = re.compile('\[(.*?)\]\s*(bitmask|in|not in)\s*\[(.*?)\]')
self.regex_dep_legal = re.compile('(?P<csrname>.*?)\s*\[(?P<indices>.*?)\]\s*(?P<op>in|not in.*?)\s*\[(?P<values>.*?)\]\s*')
self.dependencies = node['dependency_fields']
self.uarch_depends = {'uarch_signals': []}
try:
if spec is not None:
self.uarch_signals = spec['uarch_signals']
else:
self.uarch_signals = {}
except KeyError:
self.uarch_signals = {}
self.csrname = csrname
if spec is not None:
self.isa = 'rv32' if '32' in spec['ISA'] else 'rv64'
self.create_uarch_depends(self.uarch_signals)
def check_subval_legal(self, legalstr, value):
"""This function checks if a given value satifies the conditions present
in a given legal string.
:param legalstr: This is a string following the warl-legal syntax.
:type legalstr: str
:param value: The value whose legality to be checked against the
warl-legal string
:type value: int
:return: A list of error strings encountered while performing the
checks on a legal string
:rtype: list(str)
The legal string is first broken down into smaller substrings, each of
which assigns certain bits a specific value. Each substring should match
the following regular-expression: ``\[(.*?)\]\s*(bitmask|in|not in)\s*\[(.*?)\]``
For each substring, we then extract the indicies of the csr/subfield
that are being assigned, the operation used (one of `bitmask`, `in` or
`not in`) and values being assigned. Using the indices we extract the
relevant sub-value of the input value argument which applies to these
indices (we refer to this as subval).
In case of a ``bitmask`` operation all values of the input are considered
legal - since the mask and fixedval will ensure only legal values are
set.
In case of an ``in`` operation, the values list (extracted from the
substring) is split into individual elements. Each element can either be
a range or a single integer. In case of a range we check if the input
subval falls within this range or not. In case of a single integer we
perform a direct match. We parse the entire values list and stop as soon
as atleast on match is detected.
In case of a ``not in`` operation, the procedure is the same as above,
except we parse through the entire values list to ensure the subval
doesn't match any of those values, only then the subval is treated as a
legal value.
"""
assigns = self.regex_legal.findall(legalstr)
err = []
for a in assigns:
(indices, op, vals) = a
msb = int(indices.split(':')[0], 0)
if ':' in indices:
lsb = int(indices.split(':')[1], 0)
else:
# if its a single value, then lsb and msb are the same
lsb = msb
bitlen = msb - lsb + 1
if value > self.maxval:
err.append(f' for csr "{self.csrname}" the value {hex(value)} is out of bounds')
continue
# extract the value of the bits for which this particular substring
# is applicable.
subval = (value >> lsb) & ((1 << bitlen)-1)
values = vals.split(',')
# for `in` atleast one of the vals must be a hit. If none is a hit,
# then the value is illegal.
if op == 'in':
atleast_one_pass = False
for v in values:
base = int(v.split(':')[0], 0)
if ':' in v:
bound = int(v.split(':')[1], 0)
else:
bound = base
if subval >= base and subval <= bound:
atleast_one_pass = True
break
if not atleast_one_pass:
err.append(f' for csr "{self.csrname}" and warl \
sub-string "{legalstr}" the value "{hex(value)}" is not legal since it fails the condition \
"[{indices}] {op} [{vals}]"')
break
# for `not in` even a single match will treat the value as illegal.
elif op == 'not in':
all_pass = True
for v in values:
base = int(v.split(':')[0], 0)
if ':' in v:
bound = int(v.split(':')[1], 0)
else:
bound = base
if subval >= base and subval <= bound:
all_pass = False
if not all_pass:
err.append(f' for csr "{self.csrname}" and warl \
sub-string "{legalstr}" the value "{value}" is not legal since it fails the condition \
"[{indices}] {op} [{vals}]"')
break
# for bitmask all values are treated as legal.
elif op == 'bitmask':
continue
else:
err.append(f' found op:"{op}" in legal string :"{legalstr}" \
which is not supported')
break
return err
def getlegal(self, dependency_vals=[]):
'''
This function is used to return a legal value for a given set of
dependency_vals. If the dependency_vals is empty and self.dependencies
is not empty, then the first legal string is picked and the
assignment-string substring is dierctly evaluated to get a legal value.
:param dependency_vals: This is dictionary of csr:value pairs which
indicates the current value of csrs/subfields present in the
dependency_fields of the warl node.
:type dependency_vals: dict
:return: A single integer value which is considered legal for the csr
under the provided dependency_vals arg
:rtype: int
'''
logger.debug(f'Deriving a legal value for csr:{self.csrname}')
err = []
value = 0
index = -1
if self.dependencies and dependency_vals:
for legalstr in self.node['legal']:
index = index + 1
depstr = legalstr.split('->')[0]
# we replace all boolean operators first to simple parse and the
# check if the (in|not in|bitmask) operators are infact legal or
# not.
raw_depstr = re.sub('\(|\)|and|or','',depstr)
# implicitly assume it passes - in case of writeval and currval.
dep_pass = False
for m in self.regex_dep_legal.finditer(raw_depstr):
(csrname, indices, op, vals) = m.groups()
matchstr = m.group()
# in case the dependency is on writeval then we
# assume the condition is always true.
if csrname in ['writeval']:
depstr = depstr.replace(matchstr, 'True')
continue
# in case the dependency is on the current val of the same
# csr (before performing the write), then we continue by
# replacing the currval string with the csrname::subfield
# syntax
if csrname == 'currval':
if '::' in self.csrname:
renamed_csr = self.csrname.split('::')[0]
subfield = self.csrname.split('::')[1]
else:
renamed_csr = self.csrname
subfield = ''
else:
_csrname = re.sub('{\d*}','',csrname)
renamed_csr = list(filter(re.compile(f'[a-zA-Z0-9]*[:]*{_csrname}\s*$').match, self.dependencies))[0]
if '::' in renamed_csr:
subfield = renamed_csr.split('::')[1]
else:
subfield = ''
renamed_csr = renamed_csr.split('::')[0]
# if the dependency_vals dict is not empty, then pick the
# values of the csrs/subfields from there. Here we expect
# the key in the dependency_vals dict to be a subfield
# name without the `::` delimiter.
if csrname not in dependency_vals:
err.append(f'in warl string of {self.csrname}, \
the value of dependency field {csrname} not present in dependency_vals')
return err, value
else:
dep_csr_val = dependency_vals[csrname]
step_err = self.check_subval_legal(matchstr, dep_csr_val)
err = err + step_err
step_pass = True if step_err == [] else False
depstr = depstr.replace(matchstr, str(step_pass))
dep_pass = eval(depstr)
if not dep_pass:
continue
else:
break
else:
index = 0
dep_pass = True
if not dep_pass:
err.append(f'Cannot find a single legal string for which dependencies are satisfied')
return err, value
lstr = self.node['legal'][index].split('->')[-1]
for assigns in self.regex_legal.findall(lstr):
(indices, operation, vals) = assigns
msb = int(indices.split(':')[0], 0)
if ':' in indices:
lsb = int(indices.split(':')[1], 0)
else:
# if its a single value, then lsb and msb are the same
lsb = msb
bitlen = msb - lsb + 1
if operation == 'in':
v = random.choice(vals.split(','))
base = int(v.split(':')[0], 0)
if ':' in v:
bound = int(v.split(':')[1], 0)
else:
bound = base
myval = random.randrange(base, bound+1)
value = value | (myval << lsb)
elif operation == 'not in':
exclude_list = []
for v in vals.split(','):
base = int(v.split(':')[0], 0)
if ':' in v:
bound = int(v.split(':')[1], 0)
else:
bound = base
exclude_list += list(range(base, bound+1))
full_list = range(0,2**bitlen)
select_list = list(set(full_list) - set(exclude_list))
if not select_list:
err.append(f'Cannot find a legal value since \
{assigns} uses a not-in operation across the entire range')
return err,value
myval = random.choice(select_list)
value = value | (myval << lsb)
elif operation == 'bitmask':
mask = int(vals.split(',')[0], 0)
fixedval = int(vals.split(',')[1], 0)
myval = random.randrange(0,2**bitlen)
myval = (myval & mask) | (~mask & fixedval)
value = (myval << lsb)
return err, value
def islegal(self, value, dependency_vals=None):
"""This function is used to check if an input value is a legal value for
csr for given set of dependency values. The legality is checked against
all warl string listed under the `legal` node of the warl dictionary.
:param value: input integer whose legality needs to be checked for the
csr/subfield warl node.
:type value: int
:param dependency_vals: This is dictionary of csr:value pairs which
indicates the current value of csrs/subfields present in the
dependency_fields of the warl node.
:type dependency_vals: dict
If the dependency_fields of the warl node is empty, then the single
legal string in the legal list, is simply processed by the function
:py:func:`check_subval_legal` and result of which is simply returned as
is.
However, if the dependency_fields is not empty, then for each legal
string we check if both dependency_vals substring is satisfied and the
assignment substring is also satisfied, else an error is generated.
for the dependency_vals substring the values of the csrs in the
dependency_fields if obtained either from the input dependency_vals
argument or else the reset-vals of the csr in the isa spec (self.spec)
are used. If neither is available, then an error is posted about the
same.
The dependency_vals substring is again split further down to process
each condition individually. The checks for the dependency_vals
substring include:
- checking is the csrs in the substring are indeed present in the
dependency_fields list of the warl node
- if writeval or currval is detected, then that part of the
conditions is ignored.
The dependency_vals substring is treated as a boolean condition. Hence,
when when each part of the substring is evaluated, we replace that part
of the string with either True or False, and at the end perform an
`eval` on the new replaced dependency_vals substring. If this condition
evaluates to True, the corresponing assign string also evaluates to
True, then the input value is considered legal.
Things this function does not do:
- this does not check if the warl strings are valid. It is assumed
that they are valid. If not, pass them through the function iserr
to check for validity.
- in case of dependency_fields being not empty, this function
doesn't check if the possible values of the dependency
csrs/subfields are indeed legal for them. This causes a nesting
problem, which is probably doesn't warrant an immediate solution ??
-
"""
logger.debug(f'---- WARL Value Legality Check: value:{value} csr:{self.csrname} dependency_vals:{dependency_vals}')
err = []
# if no dependencies then only one legal string is present. Simply use
# check_subval_legal function to detect legality.
if not self.dependencies:
for legalstr in self.node['legal']:
err = self.check_subval_legal(legalstr, value)
# in case of dependencies there can be multiple legal strings. We split
# the legal strings into dependency strings and assign strings. Each
# substring needs to be validated to indicate that value is indeed legal
# for the current set of dependency vals.
else:
for legalstr in self.node['legal']:
depstr = legalstr.split('->')[0]
# we replace all boolean operators first to simple parse and the
# check if the (in|not in|bitmask) operators are infact legal or
# not.
raw_depstr = re.sub('\(|\)|and|or','',depstr)
# implicitly assume it passes - in case of writeval and currval.
dep_pass = True
for m in self.regex_dep_legal.finditer(raw_depstr):
(csrname, indices, op, vals) = m.groups()
matchstr = m.group()
# in case the dependency is on writeval then we
# assume the condition is always true.
if csrname in ['writeval']:
depstr = depstr.replace(matchstr, 'True')
continue
# in case the dependency is on the current val of the same
# csr (before performing the write), then we continue by
# replacing the currval string with the csrname::subfield
# syntax
if csrname == 'currval':
if '::' in self.csrname:
renamed_csr = self.csrname.split('::')[0]
subfield = self.csrname.split('::')[1]
else:
renamed_csr = self.csrname
subfield = ''
else:
_csrname = re.sub('{\d*}','',csrname)
renamed_csr = list(filter(re.compile(f'[a-zA-Z0-9_]*[:]*{_csrname}\s*$').match, self.dependencies))[0]
if '::' in renamed_csr:
subfield = renamed_csr.split('::')[1]
else:
subfield = ''
renamed_csr = renamed_csr.split('::')[0]
# if the dependency_vals dict is not empty, then pick the
# values of the csrs/subfields from there. Here we expect
# the key in the dependency_vals dict to be a subfield
# name without the `::` delimiter.
if dependency_vals is not None:
if csrname not in dependency_vals:
err.append(f'in warl string of {self.csrname}, \
the value of dependency field {csrname} not present in dependency_vals')
return err
else:
dep_csr_val = dependency_vals[csrname]
# else we pick the reset-vals from the isa spec (if the isa
# spec was provided during contruction of the class). If the
# dependency field is a subfield, then the reset-val of the
# subfield has to be extracted from the reset-val of the csr
elif self.spec is not None:
if '{' in csrname:
index_val = int(re.findall('{(\d*?)}',csrname)[0],0)
logger.debug(f'dependent csr is indexed with val {index_val}')
for i in self.spec[renamed_csr][self.isa]['index_list']:
logger.debug(f'parsing {i["index_val"]}')
if index_val == i['index_val']:
dep_csr_val = i['reset-val']
break
else:
if 'uarch_' in renamed_csr:
dep_csr_val = self.uarch_signals[renamed_csr]['reset-val']
else:
dep_csr_val = self.spec[renamed_csr]['reset-val']
if subfield != '':
if 'uarch_' in renamed_csr:
msb = self.uarch_signals[renamed_csr]['subfields'][subfield]['msb']
lsb = self.uarch_signals[renamed_csr]['subfields'][subfield]['lsb']
else:
msb = self.spec[renamed_csr][self.isa][subfield]['msb']
lsb = self.spec[renamed_csr][self.isa][subfield]['lsb']
bitlen = msb - lsb + 1
dep_csr_val = (dep_csr_val >> lsb) & \
((1 << bitlen)-1)
else:
err.append(f'No dependency_vals or spec exists to \
check the values of the csrs in the dependency_fields of csr {self.csrname}')
return err
step_err = self.check_subval_legal(matchstr, dep_csr_val)
err = err + step_err
step_pass = True if step_err == [] else False
depstr = depstr.replace(matchstr.strip(), str(step_pass))
dep_pass = eval(depstr)
assignstr = legalstr.split('->')[1]
assign_err = self.check_subval_legal(assignstr, value)
err = err + assign_err
assign_legal = True if assign_err == [] else False
# if at any point both dependency strings and the assign strings
# pass, then throw away the errors and treat it as a pass.
if assign_legal and dep_pass:
logger.debug(f' warl legal string "{legalstr}" treats the \
input value {value} as legal')
err = []
break
return err
def create_uarch_depends(self, uarch_signals):
'''
This function populates the uarch_depends dict with the csr/subfield
'''
csrname = self.csrname
reg_lsb = 0
if self.f_lsb != 0:
reg_msb = self.f_msb - self.f_lsb
else:
reg_msb = self.f_msb
reg_bitlen = reg_msb - reg_lsb + 1
for legalstr in self.node['legal']:
depstr = legalstr.split('->')[0]
raw_depstr = re.sub('\(|\)|and|or|\&\&|\|\|','',depstr)
dep_str_matches = self.regex_dep_legal.findall(raw_depstr)
if '->' in legalstr:
dependencies = self.node['dependency_fields']
if dependencies != [] and self.spec is not None:
for d in dependencies:
subfield = ''
if '::' in d:
depcsrname = d.split('::')[0]
subfield = d.split('::')[1]
else:
depcsrname = d
# if the depcsrname has the 'uarch_' prefix, then drop that dependency for all checks entirely
if depcsrname.startswith('uarch_'):
subfield_str = '' if subfield == '' else f'{subfield} field from '
logger.warning(f'WARL for csr {csrname} depends on \
{subfield_str}uarch csr {depcsrname}. Treating this as a uarch dependency.')
if subfield == '':
subfield = depcsrname
depcsrname = 'uarch_signals'
if depcsrname not in self.uarch_depends:
self.uarch_depends[depcsrname] = []
if subfield != '' and subfield not in self.uarch_depends[depcsrname]:
self.uarch_depends[depcsrname].append(subfield)
logger.debug(f'uArch dependencies are: {self.uarch_depends}')
for entry, signode in self.uarch_depends.items():
if signode == []:
continue
else:
# grouped uarch signals
if entry in uarch_signals:
for subfield in signode:
if subfield in uarch_signals[entry]['subfields']:
logger.debug(f'found csr {csrname} to depend on uArch signal {entry} \
for the following subfields: {signode}.')
else:
logger.error(f'csr {csrname} depends on uArch signal {entry} \
for the following subfields: {signode} but the uArch signal is not defined.')
# ungrouped uarch signals
else:
for entry in signode:
if entry in uarch_signals:
logger.debug(f'found csr {csrname} to depend on uArch signal {entry}.')
else:
logger.error(f'csr {csrname} depends on uArch signal {entry} \
but the uArch signal is not defined.')
def iserr(self):
logger.debug(f'---- Checking for Errors in {self.csrname}')
csrname = self.csrname
reg_lsb = 0
if self.f_lsb != 0:
reg_msb = self.f_msb - self.f_lsb
else:
reg_msb = self.f_msb
reg_bitlen = reg_msb - reg_lsb + 1
err = []
#basic checks
#if dependencies is empty, then there should be only one legal string
if self.dependencies == [] and len(self.node['legal']) > 1:
err.append(f'for In absence of dependencies there should be only \
1 legal string, instead found {len(self.node["legal"])}')
if err:
return err
# start checking legality of all legal strings
for legalstr in self.node['legal']:
depstr = legalstr.split('->')[0]
raw_depstr = re.sub('\(|\)|and|or|\&\&|\|\|','',depstr)
dep_str_matches = self.regex_dep_legal.findall(raw_depstr)
# if there are no dependencies then "->" should never be used in the
# warl legal strings
if '->' in legalstr and self.dependencies == []:
err.append(f' found "->" in legal string "legalstr" when \
dependency_fields is empty.')
return err
if self.dependencies != [] and not '->' in legalstr:
err.append(f' missing "->" in legalstr since dependency_fields \
is non empty')
return err
if '->' in legalstr:
dependencies = self.node['dependency_fields']
if dependencies != [] and self.spec is not None:
for d in dependencies:
subfield = ''
if '::' in d:
depcsrname = d.split('::')[0]
subfield = d.split('::')[1]
else:
depcsrname = d
# if the csr is a uarch dependency and also exists in the spec, throw an error
if depcsrname in self.uarch_depends and depcsrname in self.spec:
err.append(f' csr {csrname} depends on uarch csr \
{depcsrname} which is also present in the spec. This is not allowed.')
# if the dependency is on writeval or currval of the
# same csr, or is a uArch dependency, then no more checks required.
if depcsrname not in ['writeval', 'currval'] and depcsrname not in self.uarch_depends and depcsrname not in self.uarch_depends['uarch_signals']:
# if the csr doesn't exist then its probably a typo
if depcsrname not in self.spec:
err.append(f' warl for csr {csrname} depends on csr \
{depcsrname} is not a valid csrname as per spec')
# if csr exists, but is not accessible, then its a
# pointless dependency
elif not self.spec[depcsrname][self.isa]['accessible']:
err.append(f' warl for csr {csrname} depends on csr \
{depcsrname} is not accessible or not implemented in the isa yaml')
# if csr exists and is accessible but subfield
# doesn't exist, then its another typo
elif subfield != '' and subfield not in self.spec[depcsrname][self.isa]:
err.append(f' warl for csr {csrname} depends on \
subfield {depcsrname}::{subfield} which does not exist as per spec')
# if subfield is valid, but is not implemented, then
# its another pointless dependency
elif subfield !='' and not self.spec[depcsrname][self.isa][subfield]['implemented']:
err.append(f' warl for csr {csrname} depends \
on subfield {depcsrname}::{subfield} which is not implemented')
# ensure that all dependency csrs/subfields found in the
# strings, are indeed present in the dependency_fields list
# of the warl node.
for matches in dep_str_matches:
(csr, ind, op, val) = matches
csr = re.sub('{\d*}','', csr)
csr_in_dependencies = list(filter(re.compile(f'[a-zA-Z0-9_]*[:]*{csr}\s*$').match, dependencies))
if csr_in_dependencies == []:
for entry, subfields in self.uarch_signals.items():
if csr == entry:
csr_in_dependencies.append(csr)
elif csr in subfields['subfields']:
csr_in_dependencies.append(f'{csr}::{subfield}')
if csr_in_dependencies == []:
err.append(f' dependency_vals string "{depstr}" for csr \
{csrname} is dependent on field {csr} which is not present in the \
dependency_fields list of the node')
for matches in dep_str_matches:
(csr, indices, op, val) = matches
# only in and not-in are supported inside dependency
# strings. Bitmask do not make sense as a boolean operation.
if op not in ['in', 'not in']:
err.append(f' the dependency_vals string {depstr} for csr \
{csr} uses operation "{op}" which is not supported. Use only "in" and "not in" \
operations only')
msb = int(indices.split(':')[0], 0)
if ':' in indices:
lsb = int(indices.split(':')[1], 0)
else:
lsb = msb
# for range value strings, indices msb::lsb syntax to be
# followed where msb > lsb
if msb < lsb:
err.append(f'msb < lsb for one of the \
dependency_vals in warl string {legalstr} in csr {csrname}')
maxval = 2**(msb - lsb + 1 )
values = val.split(',')
# for each range value, check if the base and bound are
# correctly ordered and within the possible values of the
# csr/subfield
for v in values:
base = int(v.split(':')[0], 0)
if ':' in v:
bound = int(v.split(':')[1], 0)
else:
bound = base
if base >= maxval or bound >= maxval:
err.append(f'The range values in dependency_vals of warl\
string "{legalstr}" for csr {csrname} are out of bounds wrt the indices used \
in that string')
if base > bound:
err.append(f' base > bound for range \
values in dependency_vals of the warl string "{legalstr}" for csr {csrname}')
lstr = legalstr.split('->')[-1]
bitcount = reg_bitlen
assigns = self.regex_legal.findall(lstr)
# if there is not match, then something is wrong in the string.
if assigns == []:
err.append(f' The legal string "{legalstr}" for csr \
{csrname} does not follow warl syntax')
# split the assignment string and process each individually.
for a in assigns:
(indices, op, vals) = a
# msb lsb checks just as before
msb = int(indices.split(':')[0], 0)
if ':' in indices:
lsb = int(indices.split(':')[1], 0)
else:
lsb = msb
if msb < lsb:
err.append(f'msb < lsb for one of the \
range values in warl string {legalstr} in csr {csrname}')
if msb > reg_msb or lsb < reg_lsb:
err.append(f' The indices used in warl \
string "{legalstr}" of csr {csrname} do not comply with the msb[{reg_msb}] and lsb[{reg_lsb}] values \
of the register')
# we need to ensure that the assignment string eventually
# defines the legal value for all the bits (and not just a few).
# To check this we use a counter (bitcount) which is initialized
# to the size of the register/subfield. And each time a part of
# the assignment string is evaluated, we decrease the bitcount
# by the size of the assigment. At the end, if the bitcount is
# not zero then there is something wrong in the entire
# assignment string.
bitcount = bitcount - (msb-lsb+1)
bitlength = msb - lsb + 1
reg_maxval = 2**bitlength
maxval = 2**bitlength
if op not in ['in', 'not in', 'bitmask']:
err.append(f' the warl string {legalstr} for csr \
{csr} uses operation "{op}" which is not supported. Use only "in", "bitmask" and "not in" \
operations only')
if 'bitmask' in op:
if len(vals.split(',')) != 2:
err.append(f'bitmask syntax is wrong in legal string \
{legalstr}')
break
mask = int(vals.split(',')[0], 0)
fixedval = int(vals.split(',')[1], 0)
if mask > reg_maxval or fixedval > reg_maxval:
err.append(f' The mask and/or fixedval used in \
bitmask string "{legalstr}" of csr {csrname} have values exceeding the \
maxvalue the csr can take.')
else:
values = vals.split(',')
for v in values:
base = int(v.split(':')[0], 0)
if ':' in v:
bound = int(v.split(':')[1], 0)
else:
bound = base
if base >= maxval or bound >= maxval:
err.append(f'The range values in warl \
string "{legalstr} for csr {csrname} are out of bounds wrt the indices used \
in that string')
if base > bound:
err.append(f' base > bound for range \
values in warl string "{legalstr}" for csr {csrname}')
if bitcount < 0:
err.append(f' warl string "{legalstr}" defines values for bits \
outside the size of the register "{reg_bitlen}"')
elif bitcount != 0:
err.append(f' warl string "{legalstr}" for csr \
"{csrname}" either does not define values for all bits or has overlapping ranges \
defining the same bits multiple times')
return err

16
vendor/riscv/riscv-config/setup.cfg vendored Normal file
View file

@ -0,0 +1,16 @@
[bumpversion]
current_version = 3.18.1
commit = True
tag = True
[bumpversion:file:riscv_config/__init__.py]
search = __version__ = '{current_version}'
replace = __version__ = '{new_version}'
[bdist_wheel]
universal = 1
[flake8]
exclude = docs
[aliases]

41
vendor/riscv/riscv-config/setup.py vendored Normal file
View file

@ -0,0 +1,41 @@
import os
import codecs
from setuptools import setup, find_packages
import riscv_config
# Base directory of package
here = os.path.abspath(os.path.dirname(__file__))
def read(*parts):
with codecs.open(os.path.join(here, *parts), 'r') as fp:
return fp.read()
#Long Description
with open("README.rst", "r") as fh:
long_description = fh.read()
setup(name="riscv_config",
version=riscv_config.__version__,
description="RISC-V Configuration Validator",
long_description=long_description,
classifiers=[
"Programming Language :: Python :: 3.6",
"License :: OSI Approved :: BSD License",
"Development Status :: 4 - Beta"
],
url='https://github.com/riscv/riscv-config',
author='InCore Semiconductors Pvt. Ltd.',
author_email='neelgala@incoresemi.com',
license='BSD-3-Clause',
packages=find_packages(),
install_package_data=True,
package_dir={'riscv_config': 'riscv_config/'},
package_data={'riscv_config': ['schemas/*']},
install_requires=['Cerberus>=1.3.1', 'ruamel.yaml>=0.17.16', 'pyyaml==5.2'],
python_requires=">=3.7.0",
entry_points={
"console_scripts": ["riscv-config=riscv_config.main:main"],
})

14
vendor/riscv_riscv-config.lock.hjson vendored Normal file
View file

@ -0,0 +1,14 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// This file is generated by the util/vendor script. Please do not modify it
// manually.
{
upstream:
{
url: https://github.com/riscv/riscv-config.git
rev: 3416efeb219b0b743013266c0341697b3580b625
}
}

28
vendor/riscv_riscv-config.vendor.hjson vendored Normal file
View file

@ -0,0 +1,28 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2024 Thales DIS France SAS
// SPDX-License-Identifier: Apache-2.0.
// Original Author: Zbigniew Chamski (Thales)
{
// Name of the project
name: "riscv-config",
// Target directory: relative to the location of this script.
target_dir: "riscv/riscv-config",
// Upstream repository
upstream: {
// URL
url: "https://github.com/riscv/riscv-config.git",
// revision
rev: "3.18.1",
}
// Patch dir for local changes
patch_dir: "patches/riscv/riscv-config",
// Exclusions from upstream content
exclude_from_upstream: [
".github",
]
}