Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/pages-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ on:
- www/**
- docs/screenshots/**
- docs/brand/**
- ipynb-examples/**
- justfile

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
- name: Generate pages with Sphinx
- name: Generate pages with Sphinx and Jupyter
run: uv run just www
- name: Upload static files as artifact
id: deployment
uses: actions/upload-pages-artifact@v3
uses: actions/upload-pages-artifact@v5
with:
path: www/_build/html

Expand All @@ -35,4 +37,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@v5
56 changes: 13 additions & 43 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,57 +1,27 @@
*.py[cod]

# coverage
.coverage/
coverage.xml

# C extensions
*.so
__pycache__

# Packages
*.egg-info
dist
build
parts
bin
var
sdist
.installed.cfg
lib
lib64
__pycache__
dist/

# Unit test / coverage reports
.coverage
coverage.xml

# Apple and Windows crap
.DS_Store
Thumbs.db

# Translations
*.mo
# Sphinx
_build/

# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Jupyter
.ipynb_checkpoints
.jupyterlite.doit.db
_output/

# pycharm
.idea

# Apple crap
.DS_Store

# Stuff specifically for PyRTL
spice.net
_build

# Verilog files
# There must be a very good reason for someone to add a verilog file to the repo
.v

# VS Code
.vscode

# Python venv
pyvenv.cfg

# Jupyter
.ipynb_checkpoints
.jupyterlite.doit.db
_output
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ PyRTL
[![Build Status](https://github.com/UCSBarchlab/PyRTL/actions/workflows/python-test.yml/badge.svg)](https://github.com/UCSBarchlab/PyRTL/actions/workflows/python-test.yml)
[![Code Coverage](https://codecov.io/github/UCSBarchlab/PyRTL/coverage.svg?branch=development)](https://codecov.io/github/UCSBarchlab/PyRTL?branch=development)
[![Documentation Status](https://readthedocs.org/projects/pyrtl/badge/?version=latest)](http://pyrtl.readthedocs.org/en/latest/?badge=latest)
[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/UCSBarchlab/PyRTL/development?filepath=%2Fipynb-examples%2F)
[![JupyterLite](https://jupyterlite.readthedocs.io/en/latest/_static/badge.svg)](http://ucsbarchlab.github.io/PyRTL/lite/index.html)

PyRTL provides a collection of classes for Pythonic [register-transfer
level](https://en.wikipedia.org/wiki/Register-transfer_level) design,
Expand Down Expand Up @@ -41,8 +41,8 @@ written in PyRTL.
page](http://ucsbarchlab.github.io/PyRTL/).
* Try the examples in the
[`examples`](https://github.com/UCSBarchlab/PyRTL/tree/development/examples)
directory. You can also [try the examples on
MyBinder](https://mybinder.org/v2/gh/UCSBarchlab/PyRTL/development?filepath=%2Fipynb-examples%2F).
directory. You can also [try the examples in your
browser](http://ucsbarchlab.github.io/PyRTL/lite/index.html).
* [Full reference documentation](https://pyrtl.readthedocs.io/) is available.

### Package Contents
Expand Down Expand Up @@ -182,10 +182,12 @@ needed. `uv` caches installed software so future `uv` invocations will be fast.
information into annotations instead of docstrings.
* The Sphinx-generated documentation is published to
https://pyrtl.readthedocs.io/ .
* PyRTL's Sphinx build process is documented in
* PyRTL's documentation build process is documented in
[`docs/README.md`](https://github.com/UCSBarchlab/PyRTL/blob/development/docs/README.md).
* PyRTL's release process is documented in
[`docs/release/README.md`](https://github.com/UCSBarchlab/PyRTL/blob/development/docs/release/README.md).
* PyRTL's webpage build process is documented in
[`www/README.md`](https://github.com/UCSBarchlab/PyRTL/blob/development/www/README.md).

### Using PyRTL

Expand Down
11 changes: 6 additions & 5 deletions examples/Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
PYTHON=uv run
PY_FILES=$(wildcard example*.py) introduction-to-hardware.py
IPYNB_FILES=$(addprefix ../ipynb-examples/, $(PY_FILES:.py=.ipynb))
PYTHON := uv run
TO_IPYNB := tools/to_ipynb.py
PY_FILES := $(wildcard example*.py) introduction-to-hardware.py
IPYNB_FILES := $(addprefix ../ipynb-examples/, $(PY_FILES:.py=.ipynb))

all: $(IPYNB_FILES)

# Convert a PyRTL example Python script to a Jupyter notebook.
../ipynb-examples/%.ipynb: %.py tools/to_ipynb.py
$(PYTHON) tools/to_ipynb.py $< $@
../ipynb-examples/%.ipynb: %.py $(TO_IPYNB)
$(PYTHON) $(TO_IPYNB) $< $@
42 changes: 35 additions & 7 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
# PyRTL's Examples

PyRTL's examples are Python scripts that demonstrate various PyRTL features.
These scripts can be run with `python $SCRIPT_FILE_NAME`.

Each script is converted to an equivalent Jupyter notebook in the
`ipynb-examples` directory. These conversions are done by the `to_ipynb.py`
script in the `examples/tools` directory.
These scripts can be run with:

If you update an example script, be sure to update its corresponding Jupyter
notebook. These updates are handled by the `Makefile` in this directory, so all
Jupyter notebooks can be updated by running `make`.
```shell
$ uv run $SCRIPT_FILE
```

or interactively with:

```shell
uv run python3 -i $SCRIPT_FILE
```

PyRTL has examples in two directories:
[`examples`](https://github.com/UCSBarchlab/PyRTL/tree/development/examples)
and
[`www/examples`](https://github.com/UCSBarchlab/PyRTL/tree/development/www/examples).

## Generating Jupyter Notebooks

Each example script is automatically converted to a Jupyter notebook in a
corresponding `ipynb-examples` directory,
[`ipynb-examples`](https://github.com/UCSBarchlab/PyRTL/tree/development/ipynb-examples)
and
[`www/ipynb-examples`](https://github.com/UCSBarchlab/PyRTL/tree/development/www/ipynb-examples).
[`examples/tools/to_ipynb.py`](https://github.com/UCSBarchlab/PyRTL/blob/development/examples/tools/to_ipynb.py)
does these automatic conversions. Do not manually edit the generated Jupyter
notebooks! Any manual changes will be lost the next time someone runs
`to_ipynb.py`.

If you update an example script, re-run `to_ipynb.py` to update its
corresponding Jupyter notebook. This process is automated with
[`examples/Makefile`](https://github.com/UCSBarchlab/PyRTL/blob/development/examples/Makefile)
and
[`www/examples/Makefile`](https://github.com/UCSBarchlab/PyRTL/blob/development/www/examples/Makefile).
Running `make` in these directories will re-generate Jupyter notebooks for any
modified examples in their `examples` directory.
41 changes: 22 additions & 19 deletions examples/tools/to_ipynb.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Usage::

python to_ipynb.py example1-combologic.py example1-combologic.ipynb
$ uv run to_ipynb.py example1-combologic.py example1-combologic.ipynb

This converts comment blocks to Markdown cells, and code blocks to code cells, with some
PyRTL-specific transformations:
Expand Down Expand Up @@ -168,24 +168,27 @@ def _emit_code():
while current_code_source[-1].rstrip() == "":
current_code_source = current_code_source[:-1]

for code_line in current_code_source:
if not found_imports and (
code_line.startswith("import pyrtl")
or code_line.startswith("from pyrtl")
):
found_imports = True
pip_packages = "pyrtl"
if "verilog" in source_name:
pip_packages = "pyrtl pyparsing"

current_code_source = [
f"%pip install {pip_packages}\n",
"\n",
*current_code_source,
"\n",
"pyrtl.reset_working_block()\n",
]
break
for code_line in current_code_source:
if not found_imports and (
code_line.startswith("import pyrtl")
or code_line.startswith("from pyrtl")
):
found_imports = True
pip_packages = "pyrtl"
if "verilog" in source_name:
pip_packages = "pyrtl[blif]"

current_code_source = [
f"%pip install {pip_packages}\n",
"\n",
*current_code_source,
"\n",
"pyrtl.reset_working_block()",
]
break

# Remove any trailing whitespace from the code block's last line.
current_code_source[-1] = current_code_source[-1].rstrip()

cells.append(_code_template | {"source": current_code_source})
current_code_source = []
Expand Down
10 changes: 5 additions & 5 deletions ipynb-examples/example0-minimum-viable-hardware.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"\n",
"import pyrtl\n",
"\n",
"pyrtl.reset_working_block()\n"
"pyrtl.reset_working_block()"
]
},
{
Expand All @@ -43,7 +43,7 @@
"b = pyrtl.Input(bitwidth=8, name=\"b\")\n",
"\n",
"q = pyrtl.Output(bitwidth=8, name=\"q\")\n",
"gt5 = pyrtl.Output(bitwidth=1, name=\"gt5\")\n"
"gt5 = pyrtl.Output(bitwidth=1, name=\"gt5\")"
]
},
{
Expand All @@ -63,7 +63,7 @@
"source": [
"sum = a + b # Makes an 8-bit adder.\n",
"q <<= sum # Connects the adder's output to the `q` output pin.\n",
"gt5 <<= sum > 5 # Does a comparison and connects the result to the `gt5` output pin.\n"
"gt5 <<= sum > 5 # Does a comparison and connects the result to the `gt5` output pin."
]
},
{
Expand All @@ -82,7 +82,7 @@
"outputs": [],
"source": [
"sim = pyrtl.Simulation()\n",
"sim.step_multiple({\"a\": [0, 1, 2, 3, 4], \"b\": [2, 2, 3, 3, 4]})\n"
"sim.step_multiple({\"a\": [0, 1, 2, 3, 4], \"b\": [2, 2, 3, 3, 4]})"
]
},
{
Expand All @@ -100,7 +100,7 @@
},
"outputs": [],
"source": [
"sim.tracer.render_trace()\n"
"sim.tracer.render_trace()"
]
}
],
Expand Down
22 changes: 11 additions & 11 deletions ipynb-examples/example1-combologic.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"\n",
"import pyrtl\n",
"\n",
"pyrtl.reset_working_block()\n"
"pyrtl.reset_working_block()"
]
},
{
Expand All @@ -54,7 +54,7 @@
},
"outputs": [],
"source": [
"temp1 = pyrtl.WireVector(bitwidth=1, name=\"temp1\")\n"
"temp1 = pyrtl.WireVector(bitwidth=1, name=\"temp1\")"
]
},
{
Expand All @@ -73,7 +73,7 @@
},
"outputs": [],
"source": [
"temp2 = pyrtl.WireVector()\n"
"temp2 = pyrtl.WireVector()"
]
},
{
Expand All @@ -97,7 +97,7 @@
"c = pyrtl.Input(1, \"c\")\n",
"\n",
"sum = pyrtl.Output(1, \"sum\")\n",
"carry_out = pyrtl.Output(1, \"carry_out\")\n"
"carry_out = pyrtl.Output(1, \"carry_out\")"
]
},
{
Expand All @@ -118,7 +118,7 @@
},
"outputs": [],
"source": [
"sum <<= a ^ b ^ c\n"
"sum <<= a ^ b ^ c"
]
},
{
Expand All @@ -144,7 +144,7 @@
"temp1 <<= a & b # connect the result of a & b to the pre-allocated WireVector\n",
"temp2 <<= a & c\n",
"temp3 = b & c # temp3 IS the result of b & c (this is the first mention of temp3)\n",
"carry_out <<= temp1 | temp2 | temp3\n"
"carry_out <<= temp1 | temp2 | temp3"
]
},
{
Expand All @@ -168,7 +168,7 @@
"outputs": [],
"source": [
"print(\"--- One Bit Adder Implementation ---\")\n",
"print(pyrtl.working_block())\n"
"print(pyrtl.working_block())"
]
},
{
Expand All @@ -188,7 +188,7 @@
},
"outputs": [],
"source": [
"sim = pyrtl.Simulation()\n"
"sim = pyrtl.Simulation()"
]
},
{
Expand All @@ -214,7 +214,7 @@
"for _cycle in range(15):\n",
" sim.step(\n",
" {\"a\": random.randrange(2), \"b\": random.randrange(2), \"c\": random.randrange(2)}\n",
" )\n"
" )"
]
},
{
Expand All @@ -237,7 +237,7 @@
"sim.tracer.render_trace(symbol_len=2)\n",
"\n",
"a_value = sim.inspect(a)\n",
"print(\"The latest value of 'a' was: \", a_value)\n"
"print(\"The latest value of 'a' was: \", a_value)"
]
},
{
Expand Down Expand Up @@ -277,7 +277,7 @@
" or python_cout != sim.tracer.trace[\"carry_out\"][cycle]\n",
" ):\n",
" msg = \"This Example is Broken!!!\"\n",
" raise Exception(msg)\n"
" raise Exception(msg)"
]
}
],
Expand Down
Loading
Loading