Skip to content

Commit eebffc1

Browse files
wanda-phiwhitequark
authored andcommitted
sim: add eval_format function.
This will be used in an upcoming PR for VCD output.
1 parent 580706f commit eebffc1

File tree

3 files changed

+68
-13
lines changed

3 files changed

+68
-13
lines changed

amaranth/sim/_pyeval.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,33 @@ def eval_value(sim, value):
128128
assert False # :nocov:
129129

130130

131+
def value_to_string(value):
132+
"""Unpack a Verilog-like (but LSB-first) string of unknown width from an integer."""
133+
msg = bytearray()
134+
while value:
135+
byte = value & 0xff
136+
value >>= 8
137+
if byte:
138+
msg.append(byte)
139+
return msg.decode()
140+
141+
142+
def eval_format(sim, fmt):
143+
fmt = Format("{}", fmt)
144+
chunks = []
145+
for chunk in fmt._chunks:
146+
if isinstance(chunk, str):
147+
chunks.append(chunk)
148+
else:
149+
value, spec = chunk
150+
value = eval_value(sim, value)
151+
if spec.endswith("s"):
152+
chunks.append(format(value_to_string(value), spec[:-1]))
153+
else:
154+
chunks.append(format(value, spec))
155+
return "".join(chunks)
156+
157+
131158
def _eval_assign_inner(sim, lhs, lhs_start, rhs, rhs_len):
132159
if isinstance(lhs, Operator) and lhs.operator in ("u", "s"):
133160
_eval_assign_inner(sim, lhs.operands[0], lhs_start, rhs, rhs_len)

amaranth/sim/_pyrtl.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from ..hdl._xfrm import ValueVisitor, StatementVisitor
99
from ..hdl._mem import MemoryInstance
1010
from ._base import BaseProcess
11+
from ._pyeval import value_to_string
1112

1213

1314
__all__ = ["PyRTLProcess"]
@@ -356,17 +357,6 @@ def case_handler(patterns, elem):
356357
return gen
357358

358359

359-
def value_to_string(value):
360-
"""Unpack a Verilog-like (but LSB-first) string of unknown width from an integer."""
361-
msg = bytearray()
362-
while value:
363-
byte = value & 0xff
364-
value >>= 8
365-
if byte:
366-
msg.append(byte)
367-
return msg.decode()
368-
369-
370360
def pin_blame(src_loc, exc):
371361
if src_loc is None:
372362
raise exc

tests/test_sim.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
from amaranth.hdl._dsl import *
1414
from amaranth.hdl._ir import *
1515
from amaranth.sim import *
16+
from amaranth.sim._pyeval import eval_format
1617
from amaranth.lib.memory import Memory
17-
from amaranth.lib.data import View, StructLayout
18-
from amaranth.lib import enum
18+
from amaranth.lib import enum, data
1919

2020
from .utils import *
2121
from amaranth._utils import _ignore_deprecated
@@ -1302,6 +1302,44 @@ def testbench():
13021302
with sim.write_vcd("test.vcd", fs_per_delta=1):
13031303
sim.run()
13041304

1305+
def test_eval_format(self):
1306+
class MyEnum(enum.Enum, shape=2):
1307+
A = 0
1308+
B = 1
1309+
C = 2
1310+
1311+
sig = Signal(8)
1312+
sig2 = Signal(MyEnum)
1313+
sig3 = Signal(data.StructLayout({"a": signed(3), "b": 2}))
1314+
sig4 = Signal(data.ArrayLayout(2, 4))
1315+
sig5 = Signal(32, init=0x44434241)
1316+
1317+
def testbench():
1318+
state = sim._engine._state
1319+
yield sig.eq(123)
1320+
self.assertEqual(eval_format(state, sig._format), "123")
1321+
self.assertEqual(eval_format(state, Format("{:#04x}", sig)), "0x7b")
1322+
self.assertEqual(eval_format(state, Format("sig={}", sig)), "sig=123")
1323+
1324+
self.assertEqual(eval_format(state, sig2.as_value()._format), "A")
1325+
yield sig2.eq(1)
1326+
self.assertEqual(eval_format(state, sig2.as_value()._format), "B")
1327+
yield sig2.eq(3)
1328+
self.assertEqual(eval_format(state, sig2.as_value()._format), "[unknown]")
1329+
1330+
yield sig3.eq(0xc)
1331+
self.assertEqual(eval_format(state, sig3.as_value()._format), "{a=-4, b=1}")
1332+
1333+
yield sig4.eq(0x1e)
1334+
self.assertEqual(eval_format(state, sig4.as_value()._format), "[2, 3, 1, 0]")
1335+
1336+
self.assertEqual(eval_format(state, Format("{:s}", sig5)), "ABCD")
1337+
self.assertEqual(eval_format(state, Format("{:<5s}", sig5)), "ABCD ")
1338+
1339+
sim = Simulator(Module())
1340+
sim.add_testbench(testbench)
1341+
with sim.write_vcd("test.vcd", fs_per_delta=1):
1342+
sim.run()
13051343

13061344
class SimulatorRegressionTestCase(FHDLTestCase):
13071345
def test_bug_325(self):

0 commit comments

Comments
 (0)