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
38 changes: 12 additions & 26 deletions examples/example4-debuggingtools.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
# PyRTL provides some additional challenges when it comes to debugging, as a problem may
# surface long after the error was made. Fortunately, PyRTL comes with various features
# to help you find mistakes.
import io
import random

import pyrtl
Expand Down Expand Up @@ -130,7 +129,7 @@
print("\n--- Probe w/ debugging: ---")
pyrtl.set_debug_mode()
pyrtl.probe(multout - 16, "debugsubtr_probe")
pyrtl.set_debug_mode(debug=False)
pyrtl.set_debug_mode(False)


# ## `WireVector` Stack Trace
Expand Down Expand Up @@ -183,30 +182,17 @@
dummy_wv.my_custom_property_name = "John Clow is great"
dummy_wv.custom_value_028493 = 13

# Remove the `WireVector` from the `Block` to prevent problems with the rest of this
# example.
pyrtl.working_block().remove_wirevector(dummy_wv)

# ## Trivial Graph Format
# ## Graphviz
#
# Finally, there is a handy way to view your hardware creations as a graph. The function
# `output_to_trivialgraph()` will render your hardware in a format that you can then
# open with the free software "yEd" (http://en.wikipedia.org/wiki/YEd). There are
# options under the "hierarchical" rendering to draw something that looks quite like a
# circuit.
# Finally, there is a handy way to view your hardware creations.
# `block_to_graphviz_string()` produces a description of your hardware in the `graphviz`
# language, which can be converted to an image with the `dot` graph drawing tool
# (https://graphviz.org/docs/layouts/dot/).
#
# Also see `block_to_svg()`.
pyrtl.working_block().sanity_check()

# So that `output_to_trivial_graph()` will work.
pyrtl.passes._remove_unused_wires(pyrtl.working_block())

print("\n--- Trivial Graph Format (first 10 lines) ---")
with io.StringIO() as tgf:
pyrtl.output_to_trivialgraph(tgf)
for i, line in enumerate(tgf.getvalue().split("\n")):
if i == 10:
break
print(line)
# Also see `block_to_svg()`, which automates running `dot`.
print("\n--- Graphviz Format (first 10 lines) ---")
graphviz_string = pyrtl.block_to_graphviz_string()

print("...")
for line in graphviz_string.split("\n")[:10]:
print(line)
print("...")
2 changes: 1 addition & 1 deletion examples/tools/to_ipynb.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ def foo(bar):
"kogge_stone()": "https://pyrtl.readthedocs.io/en/latest/rtllib.html#pyrtl.rtllib.adders.kogge_stone",
"mux()": "https://pyrtl.readthedocs.io/en/latest/helpers.html#pyrtl.mux",
"otherwise": "https://pyrtl.readthedocs.io/en/latest/basic.html#pyrtl.otherwise",
"block_to_graphviz_string()": "https://pyrtl.readthedocs.io/en/latest/export.html#pyrtl.block_to_graphviz_string",
"block_to_svg()": "https://pyrtl.readthedocs.io/en/latest/export.html#pyrtl.block_to_svg",
"output_to_trivialgraph()": "https://pyrtl.readthedocs.io/en/latest/export.html#pyrtl.output_to_trivialgraph",
"output_verilog_testbench()": "https://pyrtl.readthedocs.io/en/latest/export.html#pyrtl.output_verilog_testbench",
"probe()": "https://pyrtl.readthedocs.io/en/latest/helpers.html#pyrtl.probe",
"render_trace()": "https://pyrtl.readthedocs.io/en/latest/simtest.html#pyrtl.SimulationTrace.render_trace",
Expand Down
68 changes: 12 additions & 56 deletions ipynb-examples/example4-debuggingtools.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"source": [
"%pip install pyrtl\n",
"\n",
"import io\n",
"import random\n",
"\n",
"import pyrtl\n",
Expand Down Expand Up @@ -374,7 +373,7 @@
"print(\"\\n--- Probe w/ debugging: ---\")\n",
"pyrtl.set_debug_mode()\n",
"pyrtl.probe(multout - 16, \"debugsubtr_probe\")\n",
"pyrtl.set_debug_mode(debug=False)\n"
"pyrtl.set_debug_mode(False)\n"
]
},
{
Expand Down Expand Up @@ -521,34 +520,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
" Remove the [WireVector](https://pyrtl.readthedocs.io/en/latest/basic.html#pyrtl.WireVector) from the [Block](https://pyrtl.readthedocs.io/en/latest/blocks.html#pyrtl.Block) to prevent problems with the rest of this\n",
" example.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"pyrtl.working_block().remove_wirevector(dummy_wv)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" ## Trivial Graph Format\n",
" ## Graphviz\n",
"\n",
" Finally, there is a handy way to view your hardware creations as a graph. The function\n",
" [output_to_trivialgraph()](https://pyrtl.readthedocs.io/en/latest/export.html#pyrtl.output_to_trivialgraph) will render your hardware in a format that you can then\n",
" open with the free software \"yEd\" (http://en.wikipedia.org/wiki/YEd). There are\n",
" options under the \"hierarchical\" rendering to draw something that looks quite like a\n",
" circuit.\n",
" Finally, there is a handy way to view your hardware creations.\n",
" [block_to_graphviz_string()](https://pyrtl.readthedocs.io/en/latest/export.html#pyrtl.block_to_graphviz_string) produces a description of your hardware in the `graphviz`\n",
" language, which can be converted to an image with the `dot` graph drawing tool\n",
" (https://graphviz.org/docs/layouts/dot/).\n",
"\n",
" Also see [block_to_svg()](https://pyrtl.readthedocs.io/en/latest/export.html#pyrtl.block_to_svg).\n"
" Also see [block_to_svg()](https://pyrtl.readthedocs.io/en/latest/export.html#pyrtl.block_to_svg), which automates running `dot`.\n"
]
},
{
Expand All @@ -559,35 +538,12 @@
},
"outputs": [],
"source": [
"pyrtl.working_block().sanity_check()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" So that `output_to_trivial_graph()` will work.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"pyrtl.passes._remove_unused_wires(pyrtl.working_block())\n",
"\n",
"print(\"\\n--- Trivial Graph Format (first 10 lines) ---\")\n",
"with io.StringIO() as tgf:\n",
" pyrtl.output_to_trivialgraph(tgf)\n",
" for i, line in enumerate(tgf.getvalue().split(\"\\n\")):\n",
" if i == 10:\n",
" break\n",
" print(line)\n",
"print(\"\\n--- Graphviz Format (first 10 lines) ---\")\n",
"graphviz_string = pyrtl.block_to_graphviz_string()\n",
"\n",
" print(\"...\")\n"
"for line in graphviz_string.split(\"\\n\")[:10]:\n",
" print(line)\n",
"print(\"...\")\n"
]
}
],
Expand Down
13 changes: 8 additions & 5 deletions pyrtl/rtllib/adders.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def kogge_stone(
a, b = pyrtl.match_bitwidth(a, b)

prop_orig = a ^ b
prop_bits = list(prop_orig)
prop_bits = [prop_orig[i] if i > 0 else None for i in range(prop_orig.bitwidth)]
gen_bits = list(a & b)
prop_dist = 1

Expand Down Expand Up @@ -205,11 +205,13 @@ def _cla_adder_unit(a, b, cin):
their values don't rely on the sum. Every unit generates a cout signal which is used
as cin for the next unit.
"""
gen = a & b
prop = a ^ b
gen = list(a & b)
prop = list(a ^ b)
assert len(prop) == len(gen)

carry = [gen[0] | prop[0] & cin]
carry = None
if len(prop) > 1:
carry = [gen[0] | prop[0] & cin]
sum_bit = prop[0] ^ cin

cur_gen = gen[0]
Expand All @@ -218,7 +220,8 @@ def _cla_adder_unit(a, b, cin):
cur_gen = gen[i] | (prop[i] & cur_gen)
cur_prop = cur_prop & prop[i]
sum_bit = pyrtl.concat(prop[i] ^ carry[i - 1], sum_bit)
carry.append(gen[i] | (prop[i] & carry[i - 1]))
if i < len(prop) - 1:
carry.append(gen[i] | (prop[i] & carry[i - 1]))
cout = cur_gen | (cur_prop & cin)
return sum_bit, cout

Expand Down
11 changes: 11 additions & 0 deletions tests/rtllib/test_adders.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import doctest
import io
import random
import sys
import unittest

import pyrtl
Expand Down Expand Up @@ -37,6 +39,15 @@ def adder_t_base(self, adder_func, **kwargs):
outwire = pyrtl.Output(name="test")
outwire <<= adder_func(*wires)

# Check that there are no sanity_check errors or warnings in debug_mode.
pyrtl.set_debug_mode()
output = io.StringIO()
sys.stdout = output
pyrtl.working_block().sanity_check()
sys.stdout = sys.__stdout__
pyrtl.set_debug_mode(False)

self.assertEqual("", output.getvalue())
out_vals = utils.sim_and_ret_out(outwire, wires, vals)
true_result = [sum(cycle_vals) for cycle_vals in zip(*vals, strict=True)]
self.assertEqual(out_vals, true_result)
Expand Down
Loading