parent
49a8a942e8
commit
6f5d009fad
|
@ -153,12 +153,16 @@ class _ValueCompiler(ValueVisitor, _Compiler):
|
||||||
|
|
||||||
|
|
||||||
class _RHSValueCompiler(_ValueCompiler):
|
class _RHSValueCompiler(_ValueCompiler):
|
||||||
def __init__(self, state, emitter, *, mode, inputs=None):
|
def __init__(self, state, emitter, *, mode, inputs=None, rrhs=None):
|
||||||
super().__init__(state, emitter)
|
super().__init__(state, emitter)
|
||||||
assert mode in ("curr", "next")
|
assert mode in ("curr", "next")
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
# If not None, `inputs` gets populated with RHS signals.
|
# If not None, `inputs` gets populated with RHS signals.
|
||||||
self.inputs = inputs
|
self.inputs = inputs
|
||||||
|
# When this compiler is used to grab the "next" value from within _LHSValueCompiler,
|
||||||
|
# we still need to use "curr" mode for reading part offsets etc. Allow setting a separate
|
||||||
|
# _RhsValueCompiler for these contexts.
|
||||||
|
self.rrhs = rrhs or self
|
||||||
|
|
||||||
def sign(self, value):
|
def sign(self, value):
|
||||||
value_mask = (1 << len(value)) - 1
|
value_mask = (1 << len(value)) - 1
|
||||||
|
@ -251,7 +255,7 @@ class _RHSValueCompiler(_ValueCompiler):
|
||||||
|
|
||||||
def on_Part(self, value):
|
def on_Part(self, value):
|
||||||
offset_mask = (1 << len(value.offset)) - 1
|
offset_mask = (1 << len(value.offset)) - 1
|
||||||
offset = f"({value.stride} * ({offset_mask:#x} & {self(value.offset)}))"
|
offset = f"({value.stride} * ({offset_mask:#x} & {self.rrhs(value.offset)}))"
|
||||||
return f"({(1 << value.width) - 1} & " \
|
return f"({(1 << value.width) - 1} & " \
|
||||||
f"{self(value.value)} >> {offset})"
|
f"{self(value.value)} >> {offset})"
|
||||||
|
|
||||||
|
@ -267,7 +271,7 @@ class _RHSValueCompiler(_ValueCompiler):
|
||||||
return f"0"
|
return f"0"
|
||||||
|
|
||||||
def on_SwitchValue(self, value):
|
def on_SwitchValue(self, value):
|
||||||
gen_test = self.emitter.def_var("test", f"{(1 << len(value.test)) - 1:#x} & {self(value.test)}")
|
gen_test = self.emitter.def_var("test", f"{(1 << len(value.test)) - 1:#x} & {self.rrhs(value.test)}")
|
||||||
gen_value = self.emitter.def_var("rhs_switch", "0")
|
gen_value = self.emitter.def_var("rhs_switch", "0")
|
||||||
def case_handler(patterns, elem):
|
def case_handler(patterns, elem):
|
||||||
self.emitter.append(f"{gen_value} = {self.sign(elem)}")
|
self.emitter.append(f"{gen_value} = {self.sign(elem)}")
|
||||||
|
@ -290,7 +294,7 @@ class _LHSValueCompiler(_ValueCompiler):
|
||||||
self.rrhs = rhs
|
self.rrhs = rhs
|
||||||
# `lrhs` is used to translate the read part of a read-modify-write cycle during partial
|
# `lrhs` is used to translate the read part of a read-modify-write cycle during partial
|
||||||
# update of an lvalue.
|
# update of an lvalue.
|
||||||
self.lrhs = _RHSValueCompiler(state, emitter, mode="next", inputs=None)
|
self.lrhs = _RHSValueCompiler(state, emitter, mode="next", inputs=None, rrhs=rhs)
|
||||||
# If not None, `outputs` gets populated with signals on LHS.
|
# If not None, `outputs` gets populated with signals on LHS.
|
||||||
self.outputs = outputs
|
self.outputs = outputs
|
||||||
|
|
||||||
|
|
|
@ -366,6 +366,16 @@ class SimulatorUnitTestCase(FHDLTestCase):
|
||||||
self.assertStatement(stmt, [C(1), C(0b010)], C(0b001110101, 9))
|
self.assertStatement(stmt, [C(1), C(0b010)], C(0b001110101, 9))
|
||||||
self.assertStatement(stmt, [C(2), C(0b100)], C(0b001001001, 9))
|
self.assertStatement(stmt, [C(2), C(0b100)], C(0b001001001, 9))
|
||||||
|
|
||||||
|
def test_array_lhs_heterogenous_slice(self):
|
||||||
|
l = Signal(1, init=1)
|
||||||
|
m = Signal(3, init=4)
|
||||||
|
n = Signal(5, init=7)
|
||||||
|
array = Array([l, m, n])
|
||||||
|
stmt = lambda y, a, b: [array[a].as_value()[2:].eq(b), y.eq(Cat(*array))]
|
||||||
|
self.assertStatement(stmt, [C(0), C(0b000)], C(0b001111001, 9))
|
||||||
|
self.assertStatement(stmt, [C(1), C(0b010)], C(0b001110001, 9))
|
||||||
|
self.assertStatement(stmt, [C(2), C(0b100)], C(0b100111001, 9))
|
||||||
|
|
||||||
def test_array_lhs_oob(self):
|
def test_array_lhs_oob(self):
|
||||||
l = Signal(3)
|
l = Signal(3)
|
||||||
m = Signal(3)
|
m = Signal(3)
|
||||||
|
|
Loading…
Reference in a new issue