Skip to content

Commit 8a4a755

Browse files
will-keenimgtec-admin
authored andcommitted
Merge pull request #3 from imaginationtech/fixes
Create documentation, address code concerns
2 parents ba03d71 + 91beb30 commit 8a4a755

File tree

13 files changed

+1065
-445
lines changed

13 files changed

+1065
-445
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
__pycache__/
1+
__pycache__/
2+
docs/_build
3+
docs/_static
4+
docs/_templates
5+

README.md

Lines changed: 16 additions & 351 deletions
Large diffs are not rendered by default.

constrainedrandom/__init__.py

Lines changed: 325 additions & 80 deletions
Large diffs are not rendered by default.

docs/Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Minimal makefile for Sphinx documentation
2+
#
3+
4+
# You can set these variables from the command line, and also
5+
# from the environment for the first two.
6+
SPHINXOPTS ?=
7+
SPHINXBUILD ?= sphinx-build
8+
SOURCEDIR = .
9+
BUILDDIR = _build
10+
11+
# Put it first so that "make" without argument is like "make help".
12+
help:
13+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14+
15+
.PHONY: help Makefile
16+
17+
# Catch-all target: route all unknown targets to Sphinx using the new
18+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19+
%: Makefile
20+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

docs/conf.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import sys
2+
import os
3+
sys.path.insert(0, os.path.abspath('../'))
4+
5+
# Configuration file for the Sphinx documentation builder.
6+
#
7+
# For the full list of built-in configuration values, see the documentation:
8+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
9+
10+
# -- Project information -----------------------------------------------------
11+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
12+
13+
project = 'constrainedrandom'
14+
copyright = '2023, Imagination Technologies Ltd.'
15+
author = 'Will Keen'
16+
17+
# -- General configuration ---------------------------------------------------
18+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
19+
20+
extensions = ['sphinx.ext.autodoc']
21+
22+
templates_path = ['_templates']
23+
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
24+
25+
# -- Options for HTML output -------------------------------------------------
26+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
27+
28+
html_theme = 'sphinx_rtd_theme'
29+
html_static_path = []

docs/constrainedrandom.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
The ``constrainedrandom`` package
2+
=================================
3+
4+
This is the documentation generated from the code. It is intended as developer-facing documentation.
5+
6+
User-facing classes
7+
-------------------
8+
9+
These classes are user-facing and the API should remain the same.
10+
11+
.. autoclass:: constrainedrandom.Random
12+
:members:
13+
:undoc-members:
14+
:show-inheritance:
15+
16+
.. autoclass:: constrainedrandom.RandObj
17+
:members:
18+
:undoc-members:
19+
:show-inheritance:
20+
21+
Internal classes
22+
----------------
23+
24+
These classes are internal-facing and the design can change if required.
25+
26+
.. autoclass:: constrainedrandom.RandVar
27+
:members:
28+
:undoc-members:
29+
:show-inheritance:
30+
31+
.. autoclass:: constrainedrandom.MultiVarProblem
32+
:members:
33+
:undoc-members:
34+
:show-inheritance:

docs/examples.rst

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
Examples
2+
========
3+
4+
Here are some realistic examples implemented with ``constrainedrandom``.
5+
6+
Load instruction
7+
----------------
8+
9+
The following example makes use of all of ``constrainedrandom``'s features to randomise a fictional load instruction opcode.
10+
11+
.. code-block:: python
12+
13+
from constrainedrandom import RandObj, Random
14+
15+
class ldInstr(RandObj):
16+
'''
17+
A made-up load instruction has the following fields (starting at LSB):
18+
- imm0 (11 bits): immediate offset for memory address
19+
- src0 ( 5 bits): source register for memory address
20+
- dst0 ( 5 bits): destination register for load data
21+
- wb ( 1 bit ): enable for writeback of the address to the src0 register.
22+
- enc (10 bits): fixed encoding to signify this kind of load instruction.
23+
24+
And the following rules:
25+
- If writeback (wb) is set, src0 is written back with memory offset. In
26+
this case, do not allow dst0 to be the same register as src0.
27+
- The sum of the current contents of src0 and imm0 should be word-aligned.
28+
- The sum of the current contents of src0 and imm0 should not overflow 32
29+
bits.
30+
'''
31+
ENC = 0xfa800000
32+
33+
def __init__(self, random, *args, **kwargs):
34+
super().__init__(random, *args, **kwargs)
35+
36+
self.add_rand_var('src0', bits=5, order=0)
37+
def read_model_for_src0_value():
38+
# Pretend getter for src0 current value
39+
return 0xfffffbcd
40+
self.add_rand_var('src0_value', fn=read_model_for_src0_value, order=0)
41+
self.add_rand_var('wb', bits=1, order=0)
42+
self.add_rand_var('dst0', bits=5, order=1)
43+
self.add_rand_var('imm0', bits=11, order=2)
44+
def wb_dst_src(wb, dst0, src0):
45+
if wb:
46+
return dst0 != src0
47+
return True
48+
self.add_multi_var_constraint(wb_dst_src, ('wb', 'dst0', 'src0'))
49+
def sum_src0_imm0(src0_value, imm0):
50+
address = src0_value + imm0
51+
return (address & 3 == 0) and (address < 0xffffffff)
52+
self.add_multi_var_constraint(sum_src0_imm0, ('src0_value', 'imm0'))
53+
54+
def post_randomize(self):
55+
self.opcode = self.get_opcode()
56+
57+
def get_opcode(self):
58+
opcode = self.ENC
59+
opcode = opcode | self.imm0
60+
opcode = opcode | (self.src0 << 11)
61+
opcode = opcode | (self.dst0 << 5)
62+
opcode = opcode | (self.wb << 5)
63+
return opcode
64+
65+
66+
if __name__ == "__main__":
67+
# Use a seed of 0 so our results are repeatable
68+
random = Random(0)
69+
ld_instr = ldInstr(random)
70+
# Produce 5 random valid opcodes for this load instruction
71+
for _ in range(5):
72+
ld_instr.randomize()
73+
print(hex(ld_instr.opcode))
74+
75+
The user is free to either inherit from ``RandObj`` (for more complex cases like this one above), or just to instance it directly and use it (for more straightforward cases like those in :doc:`howto` and in the ``tests/`` directory).
76+
77+
In local testing, the instruction above can be randomized at a rate of approximately 2000Hz, which is 'fast enough' for most pre-silicon verification simulations.

0 commit comments

Comments
 (0)