systemc-clang 2.0.0
Parsing SystemC constructs
Loading...
Searching...
No Matches
sensevar_movement.py
Go to the documentation of this file.
1from lark import Tree
2from parselib.transforms import TopDown
3from parselib.transforms.node import TypeDefType
4from ..utils import dprint, is_tree_type, get_ids_in_tree_types, get_ids_in_tree, alternate_ids, set_ids_in_tree_dfs
5from pprint import pprint
6from copy import deepcopy
7
8
10 """This pass moves sensevar declaration within a for loop to the top of the module,
11 and generate a generate block for each sensevar"""
12 def __init__(self):
13 super().__init__()
14 self.is_in_initblock = False
15 self.is_for_stmt = False
16 self.only_sensevar = False
17 self.current_for_stmt = None
18 self.current_module = None
19 self.initblock_vardecls = []
20
21 def __decl_referred_in_sensvar(self, sensvar, vardecl):
22 var_ids = get_ids_in_tree_types(vardecl, ['vardeclrn'])
23 sensvar_ids = get_ids_in_tree_types(sensvar, ['hvarref'])
24 if set(var_ids).intersection(set(sensvar_ids)):
25 return True
26 return False
27
28 def __create_sensevar_generate_block(self, tree):
29 assert is_tree_type(tree, "hmodule"), "tree should be a hmodule when creating generate blocks for sensitivity variables"
30 if self.sensevar_dict == {}: return
31 genblk = Tree("hgenerateblock", [ ])
32 external_decl = set()
33 for_list = []
34 for sensvar, (process, for_stmt) in self.sensevar_dict.items():
35 # create a generate block for each sensevar
36 for vardecl in self.initblock_vardecls:
37 if self.__decl_referred_in_sensvar(sensvar, vardecl):
38 external_decl.add(vardecl)
39
40 process_node = self.processes.get(process, None)
41 assert process_node is not None, f"sensvar {sensvar} defined for unknown process {process}"
42 for_stmt_duplicate = deepcopy(for_stmt)
43 proc = deepcopy(process_node)
44 setattr(proc, 'force_sensevar', sensvar)
45 for_stmt_duplicate.children[3].children = [proc]
46 for_list.append(for_stmt_duplicate)
47
48 genblk.children = [Tree("hgenvardecl", list(external_decl))] + for_list
49 tree.children.append(genblk)
50
51 def hmodule(self, tree):
52 self.current_module = tree.children[0].value
53 self.initblock_vardecls = []
54 self.sensevar_dict = {}
55 self.processes = dict()
56
57 self.__push_up(tree)
58
59 self.__create_sensevar_generate_block(tree)
60
61 self.current_module = None
62 self.sensevar_dict = {}
63 self.initblock_vardecls = []
64 return tree
65
66 def hprocess(self, tree):
67 # we don't need to push up the process for now.
68 self.processes[tree.children[0].value] = tree
69 return tree
70
71 def hmodinitblock(self, tree):
72 self.is_in_initblock = True
73 self.__push_up(tree)
74 tree.children = list(filter(lambda x: x is not None, tree.children)) # we might remove for loops
75 self.is_in_initblock = False
76 return tree
77
78 def vardecl(self, tree):
79 if self.is_in_initblock:
80 self.__push_up(tree)
81 self.initblock_vardecls.append(tree)
82 return tree
83 else:
84 self.__push_up(tree)
85 return tree
86
87 def forstmt(self, tree):
88 self.is_for_stmt = True
89 self.only_sensevar = False
90 self.current_for_stmt = tree
91
92 for_loop_sensevar = self.is_in_initblock and self.is_for_stmt
93
94 self.__push_up(tree)
95 # init, cond, step, body = tree.children
96
97
98 self.is_for_stmt = False
99 self.current_for_stmt = None
100 if self.only_sensevar:
101 self.only_sensevar = False
102 return None # In this case we simply remove the for loop statement
103 else:
104 self.only_sensevar = False
105 return tree
106
107
108 def stmt(self, tree):
109 if self.is_for_stmt and self.is_in_initblock:
110 is_sensvar = map(lambda x: is_tree_type(x, "hnamedsensvar") , tree.children)
111 if all(is_sensvar):
112 self.only_sensevar = True
113 self.__push_up(tree)
114 # In this case, all the sensevar declaration should be moved to the top of the module
115 return Tree("hnoop", [])
116 elif any(is_sensvar):
117 raise ValueError("sensevar declaration should be the only statement in for loop init block, if it contains a sensevar declaration")
118 else:
119 self.__push_up(tree)
120 return tree
121 else:
122 self.__push_up(tree)
123 return tree
124
125 def hnamedsensvar(self, tree):
126 for_loop_sensevar = self.is_in_initblock and self.is_for_stmt
127 assert for_loop_sensevar, "named sensevar is only allowed in for loop init block"
128
129 process = tree.children[0].value
130 sensevar = tree.children[1]
131 self.sensevar_dict[sensevar] = (process, self.current_for_stmt)
132
133 # remove the sensevar declaration from the original for loop
134 return None
135