import migen in litex/gen
[litex.git] / migen / fhdl / visit.py
1 from copy import copy
2
3 from migen.fhdl.structure import *
4 from migen.fhdl.structure import (_Operator, _Slice, _Assign, _ArrayProxy,
5 _Fragment)
6
7
8 class NodeVisitor:
9 def visit(self, node):
10 if isinstance(node, Constant):
11 self.visit_Constant(node)
12 elif isinstance(node, Signal):
13 self.visit_Signal(node)
14 elif isinstance(node, ClockSignal):
15 self.visit_ClockSignal(node)
16 elif isinstance(node, ResetSignal):
17 self.visit_ResetSignal(node)
18 elif isinstance(node, _Operator):
19 self.visit_Operator(node)
20 elif isinstance(node, _Slice):
21 self.visit_Slice(node)
22 elif isinstance(node, Cat):
23 self.visit_Cat(node)
24 elif isinstance(node, Replicate):
25 self.visit_Replicate(node)
26 elif isinstance(node, _Assign):
27 self.visit_Assign(node)
28 elif isinstance(node, If):
29 self.visit_If(node)
30 elif isinstance(node, Case):
31 self.visit_Case(node)
32 elif isinstance(node, _Fragment):
33 self.visit_Fragment(node)
34 elif isinstance(node, (list, tuple)):
35 self.visit_statements(node)
36 elif isinstance(node, dict):
37 self.visit_clock_domains(node)
38 elif isinstance(node, _ArrayProxy):
39 self.visit_ArrayProxy(node)
40 elif node is not None:
41 self.visit_unknown(node)
42
43 def visit_Constant(self, node):
44 pass
45
46 def visit_Signal(self, node):
47 pass
48
49 def visit_ClockSignal(self, node):
50 pass
51
52 def visit_ResetSignal(self, node):
53 pass
54
55 def visit_Operator(self, node):
56 for o in node.operands:
57 self.visit(o)
58
59 def visit_Slice(self, node):
60 self.visit(node.value)
61
62 def visit_Cat(self, node):
63 for e in node.l:
64 self.visit(e)
65
66 def visit_Replicate(self, node):
67 self.visit(node.v)
68
69 def visit_Assign(self, node):
70 self.visit(node.l)
71 self.visit(node.r)
72
73 def visit_If(self, node):
74 self.visit(node.cond)
75 self.visit(node.t)
76 self.visit(node.f)
77
78 def visit_Case(self, node):
79 self.visit(node.test)
80 for v, statements in node.cases.items():
81 self.visit(statements)
82
83 def visit_Fragment(self, node):
84 self.visit(node.comb)
85 self.visit(node.sync)
86
87 def visit_statements(self, node):
88 for statement in node:
89 self.visit(statement)
90
91 def visit_clock_domains(self, node):
92 for clockname, statements in node.items():
93 self.visit(statements)
94
95 def visit_ArrayProxy(self, node):
96 for choice in node.choices:
97 self.visit(choice)
98 self.visit(node.key)
99
100 def visit_unknown(self, node):
101 pass
102
103
104 # Default methods always copy the node, except for:
105 # - Signals, ClockSignals and ResetSignals
106 # - Unknown objects
107 # - All fragment fields except comb and sync
108 # In those cases, the original node is returned unchanged.
109 class NodeTransformer:
110 def visit(self, node):
111 if isinstance(node, Constant):
112 return self.visit_Constant(node)
113 elif isinstance(node, Signal):
114 return self.visit_Signal(node)
115 elif isinstance(node, ClockSignal):
116 return self.visit_ClockSignal(node)
117 elif isinstance(node, ResetSignal):
118 return self.visit_ResetSignal(node)
119 elif isinstance(node, _Operator):
120 return self.visit_Operator(node)
121 elif isinstance(node, _Slice):
122 return self.visit_Slice(node)
123 elif isinstance(node, Cat):
124 return self.visit_Cat(node)
125 elif isinstance(node, Replicate):
126 return self.visit_Replicate(node)
127 elif isinstance(node, _Assign):
128 return self.visit_Assign(node)
129 elif isinstance(node, If):
130 return self.visit_If(node)
131 elif isinstance(node, Case):
132 return self.visit_Case(node)
133 elif isinstance(node, _Fragment):
134 return self.visit_Fragment(node)
135 elif isinstance(node, (list, tuple)):
136 return self.visit_statements(node)
137 elif isinstance(node, dict):
138 return self.visit_clock_domains(node)
139 elif isinstance(node, _ArrayProxy):
140 return self.visit_ArrayProxy(node)
141 elif node is not None:
142 return self.visit_unknown(node)
143 else:
144 return None
145
146 def visit_Constant(self, node):
147 return node
148
149 def visit_Signal(self, node):
150 return node
151
152 def visit_ClockSignal(self, node):
153 return node
154
155 def visit_ResetSignal(self, node):
156 return node
157
158 def visit_Operator(self, node):
159 return _Operator(node.op, [self.visit(o) for o in node.operands])
160
161 def visit_Slice(self, node):
162 return _Slice(self.visit(node.value), node.start, node.stop)
163
164 def visit_Cat(self, node):
165 return Cat(*[self.visit(e) for e in node.l])
166
167 def visit_Replicate(self, node):
168 return Replicate(self.visit(node.v), node.n)
169
170 def visit_Assign(self, node):
171 return _Assign(self.visit(node.l), self.visit(node.r))
172
173 def visit_If(self, node):
174 r = If(self.visit(node.cond))
175 r.t = self.visit(node.t)
176 r.f = self.visit(node.f)
177 return r
178
179 def visit_Case(self, node):
180 cases = dict((v, self.visit(statements)) for v, statements in node.cases.items())
181 r = Case(self.visit(node.test), cases)
182 return r
183
184 def visit_Fragment(self, node):
185 r = copy(node)
186 r.comb = self.visit(node.comb)
187 r.sync = self.visit(node.sync)
188 return r
189
190 # NOTE: this will always return a list, even if node is a tuple
191 def visit_statements(self, node):
192 return [self.visit(statement) for statement in node]
193
194 def visit_clock_domains(self, node):
195 return dict((clockname, self.visit(statements)) for clockname, statements in node.items())
196
197 def visit_ArrayProxy(self, node):
198 return _ArrayProxy([self.visit(choice) for choice in node.choices],
199 self.visit(node.key))
200
201 def visit_unknown(self, node):
202 return node