f89cd02c32cd978b6b6bdee6c4bf1484d9a3af97
5 from migen
.fhdl
.structure
import *
6 from migen
.fhdl
.structure
import (_Value
, _Statement
,
7 _Operator
, _Slice
, _ArrayProxy
,
9 from migen
.fhdl
.bitcontainer
import value_bits_sign
10 from migen
.fhdl
.tools
import list_signals
, list_targets
, insert_resets
11 from migen
.fhdl
.simplify
import MemoryToArray
12 from migen
.fhdl
.specials
import _MemoryLocation
13 from migen
.sim
.vcd
import VCDWriter
, DummyVCDWriter
17 def __init__(self
, high
, half_period
, time_before_trans
):
19 self
.half_period
= half_period
20 self
.time_before_trans
= time_before_trans
24 def __init__(self
, description
):
27 for k
, period_phase
in description
.items():
28 if isinstance(period_phase
, tuple):
29 period
, phase
= period_phase
33 half_period
= period
//2
34 if phase
>= half_period
:
39 self
.clocks
[k
] = ClockState(high
, half_period
, half_period
- phase
)
44 dt
= min(cs
.time_before_trans
for cs
in self
.clocks
.values())
45 for k
, cs
in self
.clocks
.items():
46 if cs
.time_before_trans
== dt
:
52 cs
.time_before_trans
-= dt
53 if not cs
.time_before_trans
:
54 cs
.time_before_trans
+= cs
.half_period
55 return dt
, rising
, falling
64 ">>>": operator
.rshift
,
65 "<<<": operator
.lshift
,
80 def _truncate(value
, nbits
, signed
):
81 value
= value
& (2**nbits
- 1)
82 if signed
and (value
& 2**(nbits
- 1)):
88 def __init__(self
, clock_domains
, replaced_memories
):
89 self
.clock_domains
= clock_domains
90 self
.replaced_memories
= replaced_memories
91 self
.signal_values
= dict()
92 self
.modifications
= dict()
96 for k
, v
in self
.modifications
.items():
97 if k
not in self
.signal_values
or self
.signal_values
[k
] != v
:
98 self
.signal_values
[k
] = v
100 self
.modifications
.clear()
103 def eval(self
, node
, postcommit
=False):
104 if isinstance(node
, Constant
):
106 elif isinstance(node
, Signal
):
109 return self
.modifications
[node
]
113 return self
.signal_values
[node
]
115 return node
.reset
.value
116 elif isinstance(node
, _Operator
):
117 operands
= [self
.eval(o
, postcommit
) for o
in node
.operands
]
119 if len(operands
) == 1:
122 return operands
[0] - operands
[1]
124 return operands
[1] if operands
[0] else operands
[2]
126 return str2op
[node
.op
](*operands
)
127 elif isinstance(node
, _Slice
):
128 v
= self
.eval(node
.value
, postcommit
)
129 idx
= range(node
.start
, node
.stop
)
130 return sum(((v
>> i
) & 1) << j
for j
, i
in enumerate(idx
))
131 elif isinstance(node
, Cat
):
134 for element
in node
.l
:
136 # make value always positive
137 r |
= (self
.eval(element
, postcommit
) & (2**nbits
-1)) << shift
140 elif isinstance(node
, _ArrayProxy
):
141 return self
.eval(node
.choices
[self
.eval(node
.key
, postcommit
)],
143 elif isinstance(node
, _MemoryLocation
):
144 array
= self
.replaced_memories
[node
.memory
]
145 return self
.eval(array
[self
.eval(node
.index
, postcommit
)], postcommit
)
146 elif isinstance(node
, ClockSignal
):
147 return self
.eval(self
.clock_domains
[node
.cd
].clk
, postcommit
)
148 elif isinstance(node
, ResetSignal
):
149 rst
= self
.clock_domains
[node
.cd
].rst
151 if node
.allow_reset_less
:
154 raise ValueError("Attempted to get reset signal of resetless"
155 " domain '{}'".format(node
.cd
))
157 return self
.eval(rst
, postcommit
)
159 raise NotImplementedError
161 def assign(self
, node
, value
):
162 if isinstance(node
, Signal
):
163 assert not node
.variable
164 self
.modifications
[node
] = _truncate(value
,
165 node
.nbits
, node
.signed
)
166 elif isinstance(node
, Cat
):
167 for element
in node
.l
:
169 self
.assign(element
, value
& (2**nbits
-1))
171 elif isinstance(node
, _Slice
):
172 full_value
= self
.eval(node
.value
, True)
173 # clear bits assigned to by the slice
174 full_value
&= ~
((2**node
.stop
-1) - (2**node
.start
-1))
175 # set them to the new value
176 value
&= 2**(node
.stop
- node
.start
)-1
177 full_value |
= value
<< node
.start
178 self
.assign(node
.value
, full_value
)
179 elif isinstance(node
, _ArrayProxy
):
180 self
.assign(node
.choices
[self
.eval(node
.key
)], value
)
181 elif isinstance(node
, _MemoryLocation
):
182 array
= self
.replaced_memories
[node
.memory
]
183 self
.assign(array
[self
.eval(node
.index
)], value
)
185 raise NotImplementedError
187 def execute(self
, statements
):
189 if isinstance(s
, _Assign
):
190 self
.assign(s
.l
, self
.eval(s
.r
))
191 elif isinstance(s
, If
):
192 if self
.eval(s
.cond
) & (2**len(s
.cond
) - 1):
196 elif isinstance(s
, Case
):
197 nbits
, signed
= value_bits_sign(s
.test
)
198 test
= _truncate(self
.eval(s
.test
), nbits
, signed
)
200 for k
, v
in s
.cases
.items():
201 if isinstance(k
, Constant
) and k
.value
== test
:
205 if not found
and "default" in s
.cases
:
206 self
.execute(s
.cases
["default"])
207 elif isinstance(s
, collections
.Iterable
):
210 raise NotImplementedError
213 # TODO: instances via Iverilog/VPI
215 def __init__(self
, fragment_or_module
, generators
, clocks
={"sys": 10}, vcd_name
=None):
216 if isinstance(fragment_or_module
, _Fragment
):
217 self
.fragment
= fragment_or_module
219 self
.fragment
= fragment_or_module
.get_fragment()
220 if not isinstance(generators
, dict):
221 generators
= {"sys": generators
}
222 self
.generators
= dict()
223 for k
, v
in generators
.items():
224 if (isinstance(v
, collections
.Iterable
)
225 and not inspect
.isgenerator(v
)):
226 self
.generators
[k
] = list(v
)
228 self
.generators
[k
] = [v
]
230 self
.time
= TimeManager(clocks
)
231 for clock
in clocks
.keys():
232 if clock
not in self
.fragment
.clock_domains
:
233 cd
= ClockDomain(name
=clock
, reset_less
=True)
234 cd
.clk
.reset
= C(self
.time
.clocks
[clock
].high
)
235 self
.fragment
.clock_domains
.append(cd
)
237 mta
= MemoryToArray()
238 mta
.transform_fragment(None, self
.fragment
)
239 insert_resets(self
.fragment
)
240 # comb signals return to their reset value if nothing assigns them
241 self
.fragment
.comb
[0:0] = [s
.eq(s
.reset
)
242 for s
in list_targets(self
.fragment
.comb
)]
243 self
.evaluator
= Evaluator(self
.fragment
.clock_domains
,
247 self
.vcd
= DummyVCDWriter()
249 signals
= list_signals(self
.fragment
)
250 for cd
in self
.fragment
.clock_domains
:
252 if cd
.rst
is not None:
254 for memory_array
in mta
.replacements
.values():
255 signals |
= set(memory_array
)
256 signals
= sorted(signals
, key
=lambda x
: x
.duid
)
257 self
.vcd
= VCDWriter(vcd_name
, signals
)
262 def __exit__(self
, type, value
, traceback
):
268 def _commit_and_comb_propagate(self
):
271 modified
= self
.evaluator
.commit()
272 all_modified |
= modified
274 self
.evaluator
.execute(self
.fragment
.comb
)
275 modified
= self
.evaluator
.commit()
276 all_modified |
= modified
277 for signal
in all_modified
:
278 self
.vcd
.set(signal
, self
.evaluator
.signal_values
[signal
])
280 def _evalexec_nested_lists(self
, x
):
281 if isinstance(x
, list):
282 return [self
._evalexec
_nested
_lists
(e
) for e
in x
]
283 elif isinstance(x
, _Value
):
284 return self
.evaluator
.eval(x
)
285 elif isinstance(x
, _Statement
):
286 self
.evaluator
.execute([x
])
291 def _process_generators(self
, cd
):
293 for generator
in self
.generators
[cd
]:
297 request
= generator
.send(reply
)
301 reply
= self
._evalexec
_nested
_lists
(request
)
302 except StopIteration:
303 exhausted
.append(generator
)
305 for generator
in exhausted
:
306 self
.generators
[cd
].remove(generator
)
308 def _continue_simulation(self
):
309 # TODO: passive generators
310 return any(self
.generators
.values())
313 self
.evaluator
.execute(self
.fragment
.comb
)
314 self
._commit
_and
_comb
_propagate
()
317 dt
, rising
, falling
= self
.time
.tick()
320 self
.evaluator
.assign(self
.fragment
.clock_domains
[cd
].clk
, 1)
321 if cd
in self
.fragment
.sync
:
322 self
.evaluator
.execute(self
.fragment
.sync
[cd
])
323 if cd
in self
.generators
:
324 self
._process
_generators
(cd
)
326 self
.evaluator
.assign(self
.fragment
.clock_domains
[cd
].clk
, 0)
327 self
._commit
_and
_comb
_propagate
()
329 if not self
._continue
_simulation
():
333 def run_simulation(*args
, **kwargs
):
334 with
Simulator(*args
, **kwargs
) as s
: