2 from operator
import itemgetter
4 from litex
.gen
.fhdl
.structure
import *
5 from litex
.gen
.fhdl
.structure
import (_Operator
, _Slice
, _Assign
, _ArrayProxy
,
10 def visit(self
, node
):
11 if isinstance(node
, Constant
):
12 self
.visit_Constant(node
)
13 elif isinstance(node
, Signal
):
14 self
.visit_Signal(node
)
15 elif isinstance(node
, ClockSignal
):
16 self
.visit_ClockSignal(node
)
17 elif isinstance(node
, ResetSignal
):
18 self
.visit_ResetSignal(node
)
19 elif isinstance(node
, _Operator
):
20 self
.visit_Operator(node
)
21 elif isinstance(node
, _Slice
):
22 self
.visit_Slice(node
)
23 elif isinstance(node
, Cat
):
25 elif isinstance(node
, Replicate
):
26 self
.visit_Replicate(node
)
27 elif isinstance(node
, _Assign
):
28 self
.visit_Assign(node
)
29 elif isinstance(node
, If
):
31 elif isinstance(node
, Case
):
33 elif isinstance(node
, _Fragment
):
34 self
.visit_Fragment(node
)
35 elif isinstance(node
, (list, tuple)):
36 self
.visit_statements(node
)
37 elif isinstance(node
, dict):
38 self
.visit_clock_domains(node
)
39 elif isinstance(node
, _ArrayProxy
):
40 self
.visit_ArrayProxy(node
)
42 self
.visit_unknown(node
)
44 def visit_Constant(self
, node
):
47 def visit_Signal(self
, node
):
50 def visit_ClockSignal(self
, node
):
53 def visit_ResetSignal(self
, node
):
56 def visit_Operator(self
, node
):
57 for o
in node
.operands
:
60 def visit_Slice(self
, node
):
61 self
.visit(node
.value
)
63 def visit_Cat(self
, node
):
67 def visit_Replicate(self
, node
):
70 def visit_Assign(self
, node
):
74 def visit_If(self
, node
):
79 def visit_Case(self
, node
):
81 for v
, statements
in sorted(node
.cases
.items(),
82 key
=lambda x
: str(x
[0])):
83 self
.visit(statements
)
85 def visit_Fragment(self
, node
):
89 def visit_statements(self
, node
):
90 for statement
in node
:
93 def visit_clock_domains(self
, node
):
94 for clockname
, statements
in sorted(node
.items(), key
=itemgetter(0)):
95 self
.visit(statements
)
97 def visit_ArrayProxy(self
, node
):
98 for choice
in node
.choices
:
102 def visit_unknown(self
, node
):
106 # Default methods always copy the node, except for:
107 # - Signals, ClockSignals and ResetSignals
109 # - All fragment fields except comb and sync
110 # In those cases, the original node is returned unchanged.
111 class NodeTransformer
:
112 def visit(self
, node
):
113 if isinstance(node
, Constant
):
114 return self
.visit_Constant(node
)
115 elif isinstance(node
, Signal
):
116 return self
.visit_Signal(node
)
117 elif isinstance(node
, ClockSignal
):
118 return self
.visit_ClockSignal(node
)
119 elif isinstance(node
, ResetSignal
):
120 return self
.visit_ResetSignal(node
)
121 elif isinstance(node
, _Operator
):
122 return self
.visit_Operator(node
)
123 elif isinstance(node
, _Slice
):
124 return self
.visit_Slice(node
)
125 elif isinstance(node
, Cat
):
126 return self
.visit_Cat(node
)
127 elif isinstance(node
, Replicate
):
128 return self
.visit_Replicate(node
)
129 elif isinstance(node
, _Assign
):
130 return self
.visit_Assign(node
)
131 elif isinstance(node
, If
):
132 return self
.visit_If(node
)
133 elif isinstance(node
, Case
):
134 return self
.visit_Case(node
)
135 elif isinstance(node
, _Fragment
):
136 return self
.visit_Fragment(node
)
137 elif isinstance(node
, (list, tuple)):
138 return self
.visit_statements(node
)
139 elif isinstance(node
, dict):
140 return self
.visit_clock_domains(node
)
141 elif isinstance(node
, _ArrayProxy
):
142 return self
.visit_ArrayProxy(node
)
144 return self
.visit_unknown(node
)
146 def visit_Constant(self
, node
):
149 def visit_Signal(self
, node
):
152 def visit_ClockSignal(self
, node
):
155 def visit_ResetSignal(self
, node
):
158 def visit_Operator(self
, node
):
159 return _Operator(node
.op
, [self
.visit(o
) for o
in node
.operands
])
161 def visit_Slice(self
, node
):
162 return _Slice(self
.visit(node
.value
), node
.start
, node
.stop
)
164 def visit_Cat(self
, node
):
165 return Cat(*[self
.visit(e
) for e
in node
.l
])
167 def visit_Replicate(self
, node
):
168 return Replicate(self
.visit(node
.v
), node
.n
)
170 def visit_Assign(self
, node
):
171 return _Assign(self
.visit(node
.l
), self
.visit(node
.r
))
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
)
179 def visit_Case(self
, node
):
180 cases
= {v
: self
.visit(statements
)
181 for v
, statements
in sorted(node
.cases
.items(),
182 key
=lambda x
: str(x
[0]))}
183 r
= Case(self
.visit(node
.test
), cases
)
186 def visit_Fragment(self
, node
):
188 r
.comb
= self
.visit(node
.comb
)
189 r
.sync
= self
.visit(node
.sync
)
192 # NOTE: this will always return a list, even if node is a tuple
193 def visit_statements(self
, node
):
194 return [self
.visit(statement
) for statement
in node
]
196 def visit_clock_domains(self
, node
):
197 return {clockname
: self
.visit(statements
)
198 for clockname
, statements
in sorted(node
.items(),
201 def visit_ArrayProxy(self
, node
):
202 return _ArrayProxy([self
.visit(choice
) for choice
in node
.choices
],
203 self
.visit(node
.key
))
205 def visit_unknown(self
, node
):