Skip to content

Commit 9420aab

Browse files
committedSep 19, 2015
sim: support arrays, and cat+slice in assignment target
1 parent 563231f commit 9420aab

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed
 

Diff for: ‎migen/sim.py

+43-19
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import operator
22

33
from migen.fhdl.structure import *
4-
from migen.fhdl.structure import _Operator, _Slice, _Assign, _Fragment
4+
from migen.fhdl.structure import (_Operator, _Slice, _ArrayProxy,
5+
_Assign, _Fragment)
56
from migen.fhdl.bitcontainer import flen
67
from migen.fhdl.tools import list_targets
78

@@ -72,16 +73,21 @@ def commit(self):
7273
self.modifications.clear()
7374
return r
7475

75-
def eval(self, node):
76+
def eval(self, node, postcommit=False):
7677
if isinstance(node, Constant):
7778
return node.value
7879
elif isinstance(node, Signal):
80+
if postcommit:
81+
try:
82+
return self.modifications[node]
83+
except KeyError:
84+
pass
7985
try:
8086
return self.signal_values[node]
8187
except KeyError:
8288
return node.reset.value
8389
elif isinstance(node, _Operator):
84-
operands = [self.eval(o) for o in node.operands]
90+
operands = [self.eval(o, postcommit) for o in node.operands]
8591
if node.op == "-":
8692
if len(operands) == 1:
8793
return -operands[0]
@@ -92,7 +98,7 @@ def eval(self, node):
9298
else:
9399
return str2op[node.op](*operands)
94100
elif isinstance(node, _Slice):
95-
v = self.eval(node.value)
101+
v = self.eval(node.value, postcommit)
96102
idx = range(node.start, node.stop)
97103
return sum(((v >> i) & 1) << j for j, i in enumerate(idx))
98104
elif isinstance(node, Cat):
@@ -101,29 +107,46 @@ def eval(self, node):
101107
for element in node.l:
102108
nbits = flen(element)
103109
# make value always positive
104-
r |= (self.eval(element) & (2**nbits-1)) << shift
110+
r |= (self.eval(element, postcommit) & (2**nbits-1)) << shift
105111
shift += nbits
106112
return r
113+
elif isinstance(node, _ArrayProxy):
114+
return self.eval(node.choices[self.eval(node.key, postcommit)],
115+
postcommit)
107116
else:
108-
# TODO: Array, ClockSignal, ResetSignal, Memory
117+
# TODO: ClockSignal, ResetSignal, Memory
109118
raise NotImplementedError
110119

111-
def assign(self, signal, value):
112-
assert not signal.variable
113-
value = value & (2**signal.nbits - 1)
114-
if signal.signed and (value & 2**(signal.nbits - 1)):
115-
value -= 2**signal.nbits
116-
self.modifications[signal] = value
120+
def assign(self, node, value):
121+
if isinstance(node, Signal):
122+
assert not node.variable
123+
value = value & (2**node.nbits - 1)
124+
if node.signed and (value & 2**(node.nbits - 1)):
125+
value -= 2**node.nbits
126+
self.modifications[node] = value
127+
elif isinstance(node, Cat):
128+
for element in node.l:
129+
nbits = flen(element)
130+
self.assign(element, value & (2**nbits-1))
131+
value >>= nbits
132+
elif isinstance(node, Slice):
133+
full_value = self.eval(node, True)
134+
# clear bits assigned to by the slice
135+
full_value &= ~((2**node.stop-1) - (2**node.start-1))
136+
# set them to the new value
137+
value &= 2**(node.stop - node.start)-1
138+
full_value |= value << node.start
139+
self.assign(node, full_value)
140+
elif isinstance(node, _ArrayProxy):
141+
self.assign(node.choices[self.eval(node.key)], value)
142+
else:
143+
# TODO: ClockSignal, ResetSignal, Memory
144+
raise NotImplementedError
117145

118146
def execute(self, statements):
119147
for s in statements:
120148
if isinstance(s, _Assign):
121-
value = self.eval(s.r)
122-
if isinstance(s.l, Signal):
123-
self.assign(s.l, value)
124-
else:
125-
# TODO: Cat, Slice, Array, ClockSignal, ResetSignal, Memory
126-
raise NotImplementedError
149+
self.assign(s.l, self.eval(s.r))
127150
elif isinstance(s, If):
128151
if self.eval(s.cond):
129152
self.execute(s.t)
@@ -158,7 +181,8 @@ def __init__(self, fragment_or_module, generators, clocks={"sys": 100}):
158181
else:
159182
self.generators[k] = [v]
160183

161-
# TODO: insert_resets
184+
# TODO: insert_resets on sync
185+
# comb signals return to their reset value if nothing assigns them
162186
self.fragment.comb[0:0] = [s.eq(s.reset)
163187
for s in list_targets(self.fragment.comb)]
164188

0 commit comments

Comments
 (0)
Please sign in to comment.