1from lark
import Tree, Token
4from ..utils
import dprint, is_tree_type, get_ids_in_tree_types, ContextManager, get_tree_types
5from pprint
import pprint
6from copy
import deepcopy
12 assert False,
"portbindinglist should not be present in the tree"
17 This pass collects portbinding nodes and transform them into a portbindinglist node.
18 We have this pass because portbindings are scattered in hModinitblock
19 These blocks cannot be directly translated to verilog uniformly
29 with self.
ctx.add_values(current_module=tree.children[0].value, module_type={}):
34 with self.
ctx.add_values(is_in_for_init=
True):
39 if self.
ctx.is_in_for_init
and self.
ctx.is_in_initblock:
40 self.
ctx.for_var_catcher.add(tree.children[0])
44 if not self.
ctx.is_in_initblock:
48 with self.
ctx.add_values(
50 for_has_portbinding=
False,
51 has_non_portbinding_stmt=
False,
56 assert not (self.
ctx.for_has_portbinding
and self.
ctx.has_non_portbinding_stmt), \
57 "portbinding and non-portbinding stmts should not be mixed in a for block"
60 if self.
ctx.is_in_initblock
and self.
ctx.for_has_portbinding
and self.
ctx.search_key_in_outer_context(
"is_in_for")
is None:
61 self.
ctx.for_port_bindings.append(tree)
71 if self.
ctx.is_in_initblock
and self.
ctx.is_in_for:
72 if tree.children[0].data
not in [
'portbinding',
'hcstmt',
'forstmt']:
73 self.
ctx.has_non_portbinding_stmt =
True
76 if len(tree.children) == 1
and tree.children[0]
is None:
83 if self.
ctx.is_in_initblock:
84 tree.children = list(filter(
lambda x: x
is not None, tree.children))
88 with self.
ctx.add_values(
90 simple_port_bindings=[],
96 portbindinglist_node = Tree(
'portbindinglist', [
98 [*self.
ctx.simple_port_bindings],
100 forbindinglist_node = Tree(
'genbindinglist', [
101 Tree(
'genvardecl', list(self.
ctx.for_var_catcher)),
102 Tree(
'genfor', self.
ctx.for_port_bindings)
106 tree.children.append(portbindinglist_node)
107 if len(self.
ctx.for_port_bindings) > 0:
108 tree.children.append(forbindinglist_node)
113 module_inst_name = str(tree.children[0])
114 module_type_name = tree.children[1].children[0].children[0].value
115 self.
ctx.module_type[module_inst_name] = module_type_name
120 module_inst_name = str(tree.children[0])
121 module_type_name = tree.children[1].children[0].children[1].children[0].value
122 self.
ctx.module_type[module_inst_name] = module_type_name
128 normal_name = tree.children[0].value
130 if 'NONAME' in normal_name:
131 module_name = get_ids_in_tree_types(tree.children[1])[0].value
136 normal_name = tree.children[0].value
137 if 'NONAME' in normal_name:
140 node = get_tree_types(tree, [
'hfieldaccess'])[0]
141 if node.data ==
'hfieldaccess':
142 return node.children[1].children[0].value
144 dprint(tree.pretty())
145 assert False,
"Unknown case"
147 return get_ids_in_tree_types(tree.children[1])[0].value
153 if self.
ctx.is_in_for:
154 self.
ctx.for_has_portbinding =
True
155 module_orig = tree.children[0].value
157 if module
not in self.
ctx.module_type:
158 logging.warn(f
"TODO: Module {module} not found in moduleinst, future fix is required")
160 module_type = self.
ctx.module_type[module]
166 port_dir = self.
ports[module_type][port_name]
169 if port_dir == PortDirectionCollector.OUTPUT:
170 tree.children[1:3] = tree.children[2:0:-1]
171 tree.swap_for_for_loop =
True
176 self.
ctx.simple_port_bindings.append(tree)
189 with self.
ctx.add_values(current_module=tree.children[0].value):
190 self.
ports[self.
ctx.current_module] = {}
195 self.
ports[self.
ctx.current_module][tree.children[0].value] = PortDirectionCollector.INPUT
199 self.
ports[self.
ctx.current_module][tree.children[0].value] = PortDirectionCollector.OUTPUT
204 if hasattr(tree.meta,
'direction'):
205 d = tree.meta.direction
207 self.
ports[self.
ctx.current_module][tree.children[0].children[0].value] = PortDirectionCollector.INPUT
209 self.
ports[self.
ctx.current_module][tree.children[0].children[0].value] = PortDirectionCollector.OUTPUT
211 raise ValueError(f
"Unknown direction {d}")
217 This pass simply lowers the the field access to a simple portbinding
225 with self.
ctx.add_values(is_in_genbindinglist=
True):
230 if not self.
ctx.is_in_genbindinglist:
233 assert len(tree.children) == 1,
"Internal error, hvarref should only have one child"
234 cur_mod = self.
ctx.current_module
241 port_decls = interface.interfaces
242 for port_decl
in port_decls:
244 if port_decl.name == tree.children[0]:
246 tree.children[0] = Token(
'ID',
247 value=f
'{interface.generate_interface_decl_name()}.{port_decl.name}')
249 return tree.children[0]
252 if not self.
ctx.is_in_genbindinglist:
254 self.
ctx.cur_depth += 1
256 self.
ctx.cur_depth -= 1
257 if self.
ctx.cur_depth == 0:
258 return '{}[{}]'.format(tree.children[0], tree.children[1])
260 return '{}[{}].dim'.format(tree.children[0], tree.children[1])
263 if not self.
ctx.is_in_genbindinglist:
265 return tree.children[0]
268 if not self.
ctx.is_in_genbindinglist:
270 return tree.children[0]
272 if self.
ctx.is_in_genbindinglist:
273 with self.
ctx.add_values(cur_depth=0):
275 return tree.children[0] +
".itf." + tree.children[1]
279 with self.
ctx.add_values(current_module=tree.children[0].value):