2 from collections
import defaultdict
4 from migen
.fhdl
.std
import *
5 from migen
.fhdl
.structure
import _Operator
, _Assign
, _Fragment
6 from migen
.fhdl
.tools
import list_inputs
10 def __init__(self
, period
, times_before_tick
):
12 self
.times_before_tick
= times_before_tick
16 def __init__(self
, description
):
19 for k
, v
in description
.items():
20 if not isinstance(v
, tuple):
22 self
.clocks
[k
] = ClockState(v
[0], v
[0] - v
[1])
26 dt
= min(cs
.times_before_tick
for cs
in self
.clocks
.values())
27 for k
, cs
in self
.clocks
.items():
28 if cs
.times_before_tick
== dt
:
30 cs
.times_before_tick
-= dt
31 if not cs
.times_before_tick
:
32 cs
.times_before_tick
+= cs
.period
42 ">>>": operator
.rshift
,
43 "<<<": operator
.lshift
,
60 self
.signal_values
= dict()
61 self
.modifications
= dict()
65 for k
, v
in self
.modifications
.items():
66 if k
not in self
.signal_values
or self
.signal_values
[k
] != v
:
67 self
.signal_values
[k
] = v
69 self
.modifications
.clear()
72 def _eval(self
, node
):
73 if isinstance(node
, (int, bool)):
75 elif isinstance(node
, Signal
):
77 return self
.signal_values
[node
]
80 elif isinstance(node
, _Operator
):
81 operands
= [self
._eval
(o
) for o
in node
.operands
]
83 if len(operands
) == 1:
86 return operands
[0] - operands
[1]
88 return str2op
[node
.op
](*operands
)
90 # TODO: Cat, Slice, Array, ClockSignal, ResetSignal, Memory
91 raise NotImplementedError
93 def execute(self
, statements
):
95 if isinstance(s
, _Assign
):
96 value
= self
._eval
(s
.r
)
97 if isinstance(s
.l
, Signal
):
98 value
= value
& (2**s
.l
.nbits
- 1)
99 if s
.l
.signed
and (value
& 2**(s
.l
.nbits
- 1)):
100 value
-= 2**s
.l
.nbits
101 self
.modifications
[s
.l
] = value
103 # TODO: Cat, Slice, Array, ClockSignal, ResetSignal, Memory
104 raise NotImplementedError
105 elif isinstance(s
, If
):
106 if self
._eval
(s
.cond
):
112 raise NotImplementedError
115 # TODO: instances via Iverilog/VPI
118 def __init__(self
, fragment_or_module
, generators
, clocks
={"sys": 100}):
119 if isinstance(fragment_or_module
, _Fragment
):
120 self
.fragment
= fragment_or_module
122 self
.fragment
= fragment_or_module
.get_fragment()
123 if not isinstance(generators
, dict):
124 generators
= {"sys": generators
}
125 self
.generators
= dict()
126 for k
, v
in generators
.items():
127 if isinstance(v
, list):
128 self
.generators
[k
] = v
130 self
.generators
[k
] = [v
]
132 # TODO: insert_resets
133 self
.time
= TimeManager(clocks
)
134 self
.evaluator
= Evaluator()
136 self
.comb_dependent_statements
= defaultdict(list)
137 for statement
in self
.fragment
.comb
:
138 for signal
in list_inputs(statement
):
139 self
.comb_dependent_statements
[signal
].append(statement
)
141 def _comb_propagate(self
, modified
):
143 for signal
in modified
:
144 self
.evaluator
.execute(self
.comb_dependent_statements
[signal
])
145 modified
= self
.evaluator
.commit()
147 def _continue_simulation(self
):
148 # TODO: passive generators
149 return any(self
.generators
.values())
152 self
.evaluator
.execute(self
.fragment
.comb
)
153 self
._comb
_propagate
(self
.evaluator
.commit())
156 print(self
.evaluator
.signal_values
)
157 cds
= self
.time
.tick()
159 self
.evaluator
.execute(self
.fragment
.sync
[cd
])
160 self
._comb
_propagate
(self
.evaluator
.commit())
161 if not self
._continue
_simulation
():