diff --git a/examples/example4-debuggingtools.py b/examples/example4-debuggingtools.py index 3214b6fa..056981c9 100644 --- a/examples/example4-debuggingtools.py +++ b/examples/example4-debuggingtools.py @@ -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 @@ -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 @@ -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("...") diff --git a/examples/tools/to_ipynb.py b/examples/tools/to_ipynb.py index 12e43e65..2cd2f38a 100644 --- a/examples/tools/to_ipynb.py +++ b/examples/tools/to_ipynb.py @@ -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", diff --git a/ipynb-examples/example4-debuggingtools.ipynb b/ipynb-examples/example4-debuggingtools.ipynb index 4b430ffb..20d0b895 100644 --- a/ipynb-examples/example4-debuggingtools.ipynb +++ b/ipynb-examples/example4-debuggingtools.ipynb @@ -22,7 +22,6 @@ "source": [ "%pip install pyrtl\n", "\n", - "import io\n", "import random\n", "\n", "import pyrtl\n", @@ -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" ] }, { @@ -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" ] }, { @@ -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" ] } ], diff --git a/pyrtl/rtllib/adders.py b/pyrtl/rtllib/adders.py index 2777f15f..5d1d2277 100644 --- a/pyrtl/rtllib/adders.py +++ b/pyrtl/rtllib/adders.py @@ -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 @@ -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] @@ -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 diff --git a/tests/rtllib/test_adders.py b/tests/rtllib/test_adders.py index c3b9367a..dabc9c53 100644 --- a/tests/rtllib/test_adders.py +++ b/tests/rtllib/test_adders.py @@ -1,5 +1,7 @@ import doctest +import io import random +import sys import unittest import pyrtl @@ -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)