2from .top_down
import TopDown
3from ..primitives
import Primitive
4from .node
import TypeDefType
5from ..compound
import aggregate
6from lark
import Tree, Token
9from ..utils
import dprint, is_tree_type, get_ids_in_tree, alternate_ids, get_tree_types, set_ids_in_tree_dfs, map_hvarref_ids, ContextManager
13 """Expands block assignment of custom types into primitive types"""
22 """expand non-primitive htype into primitive sub-field type"""
25 assert htype.data ==
'htype'
31 stack_top = stack.pop()
32 assert stack_top.data ==
'htype'
33 type_name, *type_params = stack_top.children
39 for child
in type_params:
40 if isinstance(child, Tree):
48 new_type = copy.deepcopy(htype)
49 stack.append(new_type)
51 stack_top = stack.pop()
52 type_name, *type_params = stack_top.children
54 stack_top.children = v.children
56 for child
in type_params:
57 if isinstance(child, Tree):
59 res.append((k, new_type))
62 assert False,
'Cannot expand more than 1 custom type'
65 assert typeinfo.data ==
'htypeinfo'
66 assert len(typeinfo.children) == 1
69 return [(x[0], Tree(typeinfo.data, [x[1]], typeinfo.meta))
for x
in res]
72 """portdecl is the name:
73 Tree(outportdecl, [Token(ID, 'dout')])
74 typeinfo is the real type info:
75 Tree(htypeinfo, [Tree(htype, [Token(TYPESTR, 'sc_out'), Tree(htype, [Token(TYPESTR, 'fp_t'), 52, 11])])])
79 for suffix, tpe
in res:
81 for x
in portdecl.children:
83 new_token = copy.deepcopy(x)
84 new_token = new_token.update(value=new_token.value + (
'_' + suffix
if suffix
else ''))
85 children.append(new_token)
86 port = Tree(portdecl.data, children, portdecl.meta)
87 res_types.append([port, tpe])
91 """The expansion is achieved by first traverse the type subtree to detect the expandable type,
92 then, any parent path is duplicated
94 Tree(portdecltype, [Tree(inportdecl, [Token(ID, 'clk')]), Tree(htypeinfo,
95 [Tree(htype, [Token(TYPESTR, 'sc_in'), Tree(htype, [Token(TYPESTR, '_Bool')])])])])
97 assert len(tree.children) == 2
98 expanded_ports = self.
__expand_helper(tree.children[0], tree.children[1])
99 res = [Tree(tree.data, x, tree.meta)
for x
in expanded_ports]
103 assert tree.data
in [
'vardeclinit',
'funcparami',
'funcparamio']
104 if len(tree.children) == 2:
106 expanded_ports = self.
__expand_helper(Tree(
'stub', [tree.children[0]]), tree.children[1])
107 expanded_ports = [[var.children[0], tpe]
for var, tpe
in expanded_ports]
108 res = [Tree(tree.data, x, tree.meta)
for x
in expanded_ports]
110 elif len(tree.children) == 3:
113 if expanded_type
is None:
117 new_node = copy.copy(tree)
118 new_node.children = tree.children[0:3:2]
121 new_node.children[0] = Tree(
'hliteral', children=[new_node.children[0]])
124 decls = self.
__expand_helper(new_node.children[0], Tree(data=
'htypeinfo', children=[expanded_type]))
125 for x
in zip(decls, res):
126 var_name_decl, var_type = x[0]
127 var_name, init_val = x[1].children
130 assert var_name_decl == var_name
131 x[1].children[0] = x[1].children[0].children[0]
132 x[1].children.insert(1, var_type)
136 assert False,
'vardeclinit/funcparami/funcparamio should contain 2 or 3 sub-trees'
142 """expand identifiers in sensitivity list with fields"""
145 for sense_var
in tree.children:
150 type_name = var_type.children[0]
151 type_params = var_type.children[1:]
154 for field_name, _
in fields:
155 new_children.append(sense_var +
'_' + field_name)
157 new_children.append(sense_var)
158 tree.children = new_children
162 """expand identifiers in sensitivity list with fields"""
166 sense_var = tree.children[1]
167 sense_var = get_ids_in_tree(sense_var)[0]
173 type_name = var_type.children[0]
174 type_params = var_type.children[1:]
181 for field_name, _
in fields:
182 new_child = copy.deepcopy(tree)
183 varrefs = get_tree_types(new_child, [
'hvarref'])
185 if vars.children[0].value == sense_var.value:
186 vars.children[0] = Token(
'ID', sense_var.value +
'_' + field_name)
187 res.append(new_child)
195 for node
in tree.children:
196 if node.data ==
'portdecltype':
197 var_name = node.children[0].children[0]
198 var_type = node.children[1].children[0]
199 var_type_name = var_type.children[1].children[0]
203 elif node.data ==
'sigdecltype':
204 var_name = node.children[0].children[0]
205 var_type = node.children[1].children[0]
208 var_tokens = map(
lambda x:
209 filter(
lambda y: isinstance(y, str), x.children),
210 var_type.iter_subtrees_topdown())
211 for var_type_name
in itertools.chain.from_iterable(var_tokens):
219 var_name = node.children[0]
220 var_type = node.children[1].children[0]
221 var_tokens = map(
lambda x:
222 filter(
lambda y: isinstance(y, str), x.children),
223 var_type.iter_subtrees_topdown())
224 type_name = var_type.children[0]
229 new_children.append(Tree(
'moduleinst', node.children, node.meta))
233 if type_name ==
'array':
235 sub_type_name = var_type.children[1].children[0]
236 if not Primitive.get_primitive(sub_type_name)
and not sub_type_name
in self.
typestypestypestypes:
240 new_node = Tree(
'modulearrayinst', node.children, node.meta)
241 new_children.append(new_node)
249 array_of_typedef =
False
250 for var_type_name
in itertools.chain.from_iterable(var_tokens):
254 elif var_type_name ==
"array":
257 new_children.extend(res)
262 tree.children = new_children
270 for subtree
in htype.iter_subtrees_topdown():
271 if isinstance(subtree, Tree)
and subtree.data ==
'htype' and subtree.children[0]
in self.
typestypestypestypes:
276 assert isinstance(tree, Tree)
277 if tree.data
in [
'hliteral',
'hvarref']:
278 var_name = tree.children[0]
281 elif tree.data ==
'harrayref':
284 if tree.children[0].data ==
'hsigassignr':
285 var_name = tree.children[1].children[0]
287 var_name = tree.children[0].children[0]
290 elif tree.data ==
'hbinop' and tree.children[0] ==
'ARRAYSUBSCRIPT':
291 var_name = tree.children[1].children[0]
294 elif tree.data ==
'hvarref':
295 var_name = tree.children[0]
298 elif tree.data ==
'syscread':
301 assert tree.children[1].data
in [
'hliteral',
'hvarref',
'harrayref'], f
'Actual: {tree.children[1].data} ({tree})'
302 if tree.children[1].data
in [
'harrayref']:
305 var_name = tree.children[1].children[0]
308 elif tree.data ==
'hvarinitlist':
311 for element
in tree.children:
317 """append the field_name to the expandable variable in tree"""
319 assert isinstance(tree, Tree)
320 if tree.data
in [
'hliteral',
'hvarref']:
321 var_name = tree.children[0]
323 tree.children[0] = var_name +
'_' + field_name
324 elif tree.data ==
'harrayref':
325 var_name = tree.children[0].children[0]
327 tree.children[0].children[0] = var_name +
'_' + field_name
328 elif tree.data ==
'hbinop' and tree.children[0] ==
'ARRAYSUBSCRIPT':
329 var_name = tree.children[1].children[0]
331 tree.children[1].children[0] = var_name +
'_' + field_name
332 elif tree.data ==
'syscread':
333 assert tree.children[1].data
in [
'hliteral',
'hvarref',
'harrayref']
334 if tree.children[1].data
in [
'harrayref']:
337 var_name = tree.children[1].children[0]
339 tree.children[1].children[0] = var_name +
'_' + field_name
340 elif tree.data ==
'hvarinitlist':
341 for t
in tree.children:
345 """checks if v is None or is a (nested) list containing only none"""
354 """detects the expandable variable on lhs and rhs and
355 expand them with the fields"""
357 lhs, rhs = tree.children
366 if lhs_var
is not None and (
not self.
__is_all_none(rhs_var)
or rhs.data ==
'hliteral')
and (rhs_var
is not None or rhs.data ==
'hliteral'):
368 assert lhs_expanded_type
is not None,
'{} should have expanded type'.format(lhs_var)
371 if isinstance(rhs_var,list):
373 if lhs_type.children[0] != rhs_type.children[0]:
374 raise RuntimeError(
'Type does not match between LHS and RHS')
375 for remaining_rhs_var
in rhs_var:
377 if rhs_type.children[0] != rhs_var_type.children[0]:
378 raise RuntimeError(
'Type does not match among RHS elements')
379 elif rhs.data !=
'hliteral':
382 if lhs_type.children[0] != rhs_type.children[0]:
383 raise RuntimeError(
'Type does not match between LHS and RHS')
386 assert rhs.data ==
'hliteral'
387 type_name = lhs_type.children[0]
388 type_params = lhs_type.children[1:]
392 for field_member, _
in fields:
393 new_assign = copy.deepcopy(tree)
394 if tree.data ==
'blkassign':
395 new_assign.must_block = tree.must_block
396 assert type(new_assign.must_block) == type(
False)
397 new_lhs, new_rhs = new_assign.children
399 if rhs.data ==
'hliteral':
400 new_assign.children[1] = Tree(
'hliteral', [0], meta=rhs.meta)
403 res.append(new_assign)
411 raise RuntimeError(
'Error while expanding blkassign, LHS and RHS expandability does not match')
423 raise RuntimeError(
'Duplicate variable ', var_name)
424 self.
expanded[-1][var_name] = var_type
428 """add another scope for a process"""
429 with self.
ctx.add_values(current_process=tree.children[0]):
454 for sense_var
in tree.children[1:]:
461 type_name = var_type.children[0]
462 type_params = var_type.children[1:]
465 for field_name, _
in fields:
466 new_sense_var = copy.deepcopy(sense_var)
471 new_children.append(new_sense_var)
473 new_children.append(sense_var)
474 tree.children[1:] = new_children
478 """for variable expansion in statement"""
489 if expand_data
is None:
490 expand_data = [
'vardeclinit']
492 for node
in tree.children:
493 if node.data
in expand_data:
494 var_name = node.children[0]
495 var_type = node.children[1].children[0]
496 var_tokens = map(
lambda x:
497 filter(
lambda y: isinstance(y, str), x.children),
498 var_type.iter_subtrees_topdown())
499 type_name = var_type.children[0]
500 if 'funcparamio' in expand_data:
505 assert False,
'Type {} not found or module instantiation cannot reside in process: {}, {}'.format(type_name, var_name, type_name)
506 for var_type_name
in itertools.chain.from_iterable(var_tokens):
511 new_children.extend(res)
513 new_children.append(node)
518 expands the hmodinitblock
519 hmodinitblock includes a initialization block and portdecl block, both of which can include
563 for child
in tree.children:
564 if isinstance(child, list):
565 new_children.extend(child)
567 new_children.append(child)
568 tree.children = new_children
576 for ch
in tree.children:
577 if isinstance(ch, list):
578 new_children.extend(ch)
580 new_children.append(ch)
581 tree.children = new_children
586 assert stmt.data ==
'stmt'
588 if len(stmt.children) == 1
and stmt.children[0].data ==
'portbinding':
599 for ch
in tree.children:
600 if isinstance(ch, list):
602 new_children.extend(ch)
603 elif ch.data ==
'blkassign':
605 new_children.extend(res)
607 new_children.append(ch)
608 tree.children = new_children
613 assert len(tree.children) == 1
614 new_children = tree.children[0]
618 for child
in new_children
620 for r, ch
in zip(res, new_children):
629 mod_name, sub, par = binding.children
630 sub_v = sub.children[0]
631 if is_tree_type(par,
'hbindingarrayref'):
632 par_v = get_ids_in_tree(par)[0]
634 par_v = par.children[0]
635 par_v_query = par_v.value.replace(
'##',
'_')
641 for field
in tpe.fields:
642 new_sub = copy.deepcopy(sub)
643 new_par = copy.deepcopy(par)
654 assert isinstance(x, Token)
655 return Token(
"ID", x.value +
'_' + field.children[0], x.pos_in_stream, x.line, x.column)
657 map_hvarref_ids(new_sub, [__map])
658 map_hvarref_ids(new_par, [__map])
662 new_binding = copy.copy(binding)
663 new_binding.children = [mod_name, new_sub, new_par]
664 b.append(new_binding)
665 new_bindings.extend(b)
667 new_bindings.append(binding)
674 if self.
ctx.current_module ==
'rvfifo_cc_sc_module_9':
677 module_name, *bindings = tree.children
679 for binding
in bindings:
680 mod_name, sub, par = binding.children
681 sub_v = sub.children[0]
682 if is_tree_type(par,
'hbindingarrayref'):
683 par_v = get_ids_in_tree(par)[0]
685 par_v = par.children[0]
691 for field
in tpe.fields:
692 new_sub = copy.deepcopy(sub)
693 new_par = copy.deepcopy(par)
697 x.value +=
'_' + field.children[0]
699 alternate_ids(new_sub, [__alternate])
700 alternate_ids(new_par, [__alternate])
703 new_binding = copy.copy(binding)
704 new_binding.children = [mod_name, new_sub, new_par]
705 b.append(new_binding)
706 new_bindings.extend(b)
708 new_bindings.append(binding)
709 tree.children = [module_name, new_bindings]
716 for sense_var
in tree.children[1:]:
718 var_ids = get_ids_in_tree(sense_var.children[0])
719 if len(var_ids) != 1:
720 raise ValueError(
'Sensitivity variable should only have one ID')
721 var_name = var_ids[0]
726 type_name = var_type.children[0]
727 type_params = var_type.children[1:]
731 def __alternate(x, y):
734 for field_name, _
in fields:
735 new_sense_var = copy.deepcopy(sense_var)
737 set_ids_in_tree_dfs(new_sense_var, [
lambda x: __alternate(x, field_name)])
738 new_children.append(new_sense_var)
741 new_children.append(sense_var)
742 tree.children[1:] = new_children
746 """add another scope for a module"""
747 with self.
ctx.add_values(current_module=tree.children[0]):