From 7f152eb86b7935929b6b0c94872d48540f73d2f5 Mon Sep 17 00:00:00 2001 From: Jeremy Lau <30300826+fdxmw@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:02:46 -0700 Subject: [PATCH] Improve `render_trace`'s ASCII output. This makes it easier to visually distinguish high and low, for 1-bit signals. --- .../screenshots/pyrtl-renderer-demo-ascii.png | Bin 16777 -> 16111 bytes examples/renderer-demo.py | 4 +- pyrtl/simulation.py | 43 ++++++++++-------- tests/test_simulation.py | 18 ++++---- 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/docs/screenshots/pyrtl-renderer-demo-ascii.png b/docs/screenshots/pyrtl-renderer-demo-ascii.png index 4e3023e1c6e94b5e4bbececeb4cca7055a2dc560..30d0413634599f911cb0cec75af03dc3661e6455 100644 GIT binary patch literal 16111 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%0AWfuKhlcDO+U0qskF_dhd{8YY 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. - Enable this renderer by default by setting the ``PYRTL_RENDERER`` environment - variable to ``powerline``:: + Use this renderer by default by setting the ``PYRTL_RENDERER`` environment variable + to ``powerline``:: - export PYRTL_RENDERER=powerline + $ export PYRTL_RENDERER=powerline .. image:: ../docs/screenshots/pyrtl-renderer-demo-powerline.png :width: 35em @@ -1487,10 +1487,10 @@ class Utf8BasicRendererConstants(RendererConstants): codes `_, which makes its output suitable for inclusion in text files. - Enable this renderer by default by setting the ``PYRTL_RENDERER`` environment - variable to ``utf-8-basic``:: + Use this renderer by default by setting the ``PYRTL_RENDERER`` environment variable + to ``utf-8-basic``:: - export PYRTL_RENDERER=utf-8-basic + $ export PYRTL_RENDERER=utf-8-basic .. image:: ../docs/screenshots/pyrtl-renderer-demo-utf-8-basic.png :width: 25em @@ -1515,14 +1515,14 @@ class Utf8BasicRendererConstants(RendererConstants): class AsciiRendererConstants(RendererConstants): """7-bit ASCII renderer constants. These should work anywhere. - Single-bit :class:`WireVectors` are rendered as waveforms with sloped - rising and falling edges. Multi-bit :class:`WireVector` values are rendered between - vertical bars. + Single-bit :class:`WireVectors` are rendered as square waveforms with + vertical rising and falling edges. Multi-bit :class:`WireVector` values are rendered + between vertical bars. - Enable this renderer by default by setting the ``PYRTL_RENDERER`` environment - variable to ``ascii``:: + Use this renderer by default by setting the ``PYRTL_RENDERER`` environment variable + to ``ascii``:: - export PYRTL_RENDERER=ascii + $ export PYRTL_RENDERER=ascii .. image:: ../docs/screenshots/pyrtl-renderer-demo-ascii.png :width: 25em @@ -1530,8 +1530,11 @@ class AsciiRendererConstants(RendererConstants): _tick = "|" - _up, _down = ",", "." - _low, _high = "_", "-" + _up, _down = "|", "|" + _low, _high = "_", " " + + _prev_line_up, _prev_line_down = " ", " " + _prev_line_low, _prev_line_high = " ", "_" _x = "|" _zero_x = "|" diff --git a/tests/test_simulation.py b/tests/test_simulation.py index 00ddd6e5..f5e8e347 100644 --- a/tests/test_simulation.py +++ b/tests/test_simulation.py @@ -186,7 +186,7 @@ def check_rendered_trace(self, expected, **kwargs): ) buff = io.StringIO() sim.tracer.render_trace(file=buff, renderer=self.renderer, **kwargs) - self.assertEqual(buff.getvalue(), expected) + self.assertEqual(expected, buff.getvalue()) def test_hex_trace(self): expected = ( @@ -195,8 +195,8 @@ def test_hex_trace(self): "a 0x1 |0x4 |0x9 |0xb |0xc\n" " \n" "b 0x2 |0x17|0x2b|0x78|----\n" - " \n" - "c ____,---------.____,----\n" + " _________ ____\n" + "c ____| |____|\n" ) self.check_rendered_trace(expected) @@ -207,8 +207,8 @@ def test_oct_trace(self): "a 0o1 |0o4 |0o11 |0o13 |0o14\n" " \n" "b 0o2 |0o27 |0o53 |0o170|-----\n" - " \n" - "c _____,-----------._____,-----\n" + " ___________ _____\n" + "c _____| |_____|\n" ) self.check_rendered_trace(expected, repr_func=oct) @@ -220,8 +220,8 @@ def test_bin_trace(self): "a 0b1 |0b100 |0b1001 |0b1011 |0b1100\n" " \n" "b 0b10 |0b10111 |0b101011 |0b1111000|---------\n" - " \n" - "c _________,-------------------._________,---------\n" + " ___________________ _________\n" + "c _________| |_________|\n" ) self.check_rendered_trace(expected, repr_func=bin) @@ -233,8 +233,8 @@ def test_decimal_trace(self): "a 1 |4 |9 |11 |12\n" " \n" "b 2 |23 |43 |120|---\n" - " \n" - "c ___,-------.___,---\n" + " _______ ___\n" + "c ___| |___|\n" ) self.check_rendered_trace(expected, repr_func=str)