Skip to content

Commit 6f5d009

Browse files
wanda-phiwhitequark
authored andcommitted
sim: fix LRHS evaluation.
Fixes #1269.
1 parent 49a8a94 commit 6f5d009

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

amaranth/sim/_pyrtl.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,16 @@ def on_Initial(self, value):
153153

154154

155155
class _RHSValueCompiler(_ValueCompiler):
156-
def __init__(self, state, emitter, *, mode, inputs=None):
156+
def __init__(self, state, emitter, *, mode, inputs=None, rrhs=None):
157157
super().__init__(state, emitter)
158158
assert mode in ("curr", "next")
159159
self.mode = mode
160160
# If not None, `inputs` gets populated with RHS signals.
161161
self.inputs = inputs
162+
# When this compiler is used to grab the "next" value from within _LHSValueCompiler,
163+
# we still need to use "curr" mode for reading part offsets etc. Allow setting a separate
164+
# _RhsValueCompiler for these contexts.
165+
self.rrhs = rrhs or self
162166

163167
def sign(self, value):
164168
value_mask = (1 << len(value)) - 1
@@ -251,7 +255,7 @@ def on_Slice(self, value):
251255

252256
def on_Part(self, value):
253257
offset_mask = (1 << len(value.offset)) - 1
254-
offset = f"({value.stride} * ({offset_mask:#x} & {self(value.offset)}))"
258+
offset = f"({value.stride} * ({offset_mask:#x} & {self.rrhs(value.offset)}))"
255259
return f"({(1 << value.width) - 1} & " \
256260
f"{self(value.value)} >> {offset})"
257261

@@ -267,7 +271,7 @@ def on_Concat(self, value):
267271
return f"0"
268272

269273
def on_SwitchValue(self, value):
270-
gen_test = self.emitter.def_var("test", f"{(1 << len(value.test)) - 1:#x} & {self(value.test)}")
274+
gen_test = self.emitter.def_var("test", f"{(1 << len(value.test)) - 1:#x} & {self.rrhs(value.test)}")
271275
gen_value = self.emitter.def_var("rhs_switch", "0")
272276
def case_handler(patterns, elem):
273277
self.emitter.append(f"{gen_value} = {self.sign(elem)}")
@@ -290,7 +294,7 @@ def __init__(self, state, emitter, *, rhs, outputs=None):
290294
self.rrhs = rhs
291295
# `lrhs` is used to translate the read part of a read-modify-write cycle during partial
292296
# update of an lvalue.
293-
self.lrhs = _RHSValueCompiler(state, emitter, mode="next", inputs=None)
297+
self.lrhs = _RHSValueCompiler(state, emitter, mode="next", inputs=None, rrhs=rhs)
294298
# If not None, `outputs` gets populated with signals on LHS.
295299
self.outputs = outputs
296300

tests/test_sim.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,16 @@ def test_array_lhs_heterogenous(self):
366366
self.assertStatement(stmt, [C(1), C(0b010)], C(0b001110101, 9))
367367
self.assertStatement(stmt, [C(2), C(0b100)], C(0b001001001, 9))
368368

369+
def test_array_lhs_heterogenous_slice(self):
370+
l = Signal(1, init=1)
371+
m = Signal(3, init=4)
372+
n = Signal(5, init=7)
373+
array = Array([l, m, n])
374+
stmt = lambda y, a, b: [array[a].as_value()[2:].eq(b), y.eq(Cat(*array))]
375+
self.assertStatement(stmt, [C(0), C(0b000)], C(0b001111001, 9))
376+
self.assertStatement(stmt, [C(1), C(0b010)], C(0b001110001, 9))
377+
self.assertStatement(stmt, [C(2), C(0b100)], C(0b100111001, 9))
378+
369379
def test_array_lhs_oob(self):
370380
l = Signal(3)
371381
m = Signal(3)

0 commit comments

Comments
 (0)