systemc-clang 2.0.0
Parsing SystemC constructs
Loading...
Searching...
No Matches
function_transformation_pass.py
Go to the documentation of this file.
1"""transform functions such that have separate the parameters where input and output are separate"""
2from lark import Token
3
4from parselib.transforms import TopDown
5from ..utils import dprint, is_tree_type
6from ..grammar import UnexpectedHCodeStructureError
7from .name_stub import *
8import copy
9
10
12 """
13 Traverse all usage of function calls, convert function names into stubs (for duplicating functions)
14 And add prologue and epilogue for function calls
15 """
28 def hsenslist(self, tree):
29 proc_name = tree.children[0]
30 self.__sense_list_proc_name = proc_name
31 self.__current_module_sense_list[proc_name] = set()
32 self.__push_up(tree)
33 self.__sense_list_proc_name = None
34 return tree
35
36 def hsensvar(self, tree):
37 self.__current_module_sense_list[self.__sense_list_proc_name].add(tree.children[0])
38 return tree
39
40 @property
44 @current_module_function_nodes.setter
46 self.__current_functions = val
47
49 self.__current_process__current_process.func_name_stubs.append(FuncNameStub(func))
50
51 def __search_current_function(self, func_name):
53 if f.children[0] == func_name:
54 return f
55 # try fuzzy search
57 # dprint(f.children[0][:-1] == func_name[:-1])
58 if f.children[0][:-1] == func_name[:-1]:
59 return f
60 raise ValueError(f'Function {func_name} not found')
61
64 if id in self.__current_process__current_process.name_stub:
65 return self.__current_process__current_process.name_stub[id]
66 else:
67 return None
68
69 def modportsiglist(self, tree):
70 self.__in_module_scope = True
71 self.__push_up(tree)
72 self.__in_module_scope = False
73 return tree
74
75 def sigdecltype(self, tree):
76 if self.__in_module_scope:
77 if self.__in_module_scope:
78 var = tree.children[0].children[0]
79 self.__current_module_scope_vars[var] = True
80 return tree
81
82 def vardeclinit(self, tree):
83 if self.__in_module_scope:
84 if self.__in_module_scope:
85 var = tree.children[0]
86 self.__current_module_scope_vars[var] = True
87 return tree
88
89 def portdecltype(self, tree):
90 if self.__in_module_scope:
91 if self.__in_module_scope:
92 var = tree.children[0].children[0]
93 self.__current_module_scope_vars[var] = True
94 return tree
95
96 def hmodule(self, tree):
97 # for t in tree.children:
98 # if isinstance(t, Tree):
99 # dprint(t.data)
101 self.__current_module_scope_vars = dict()
102 self.__current_module_sense_list = dict()
104 self.__push_up(tree)
107 self.__current_module = None
108 return tree
109
110 def hthreadswitch(self, tree):
111 # Note for generated thread function, we will not need a stub
113 tree.func_name_stubs = []
114 self.__push_up(tree)
116 return tree
117
118 def hprocess(self, tree):
119 self.__current_process__current_process = tree # note down the process so that we can add temporary variables later
120 tree.func_name_stubs = []
121 self.__push_up(tree)
123
124 # generate prolog
125 body = None
126 for ch in tree.children:
127 if is_tree_type(ch, 'hcstmt'):
128 body = ch
129 break
130 if len(body.children) == 0:
131 body.children.append(Tree('stmts', children=[]))
132 body = body.children[0]
133 for name, stub in tree.name_stub.items():
134 blkassign = Tree('blkassign', children=[
135 stub.children[0],
136 name
137 ])
138 body.children.insert(0, Tree('stmt', children=[blkassign]))
139
140 # generate epilog
141 for name, stub in tree.name_stub.items():
142 blkassign = Tree('blkassign', children=[
143 name,
144 stub.children[0]
145 ])
146 body.children.append(Tree('stmt', children=[blkassign]))
147 return tree
148
149 def hfunctionlocalvars(self, tree):
150 stub_decl = []
151 for name, stub in self.__current_function.name_stub.items():
152 stub_decl.append(
153 Tree('vardeclinit', children=[stub.children[0], stub.children[1]])
154 )
155 for name, tpe in self.__current_function.phantom_vars.items():
156 t = self.strip_io_or_default(tpe)
157 stub_decl.append(
158 Tree('vardeclinit', children=[name, t])
159 )
160 tree.children.extend(stub_decl)
161 return tree
162
163 def strip_io_or_default(self, tpe):
164 # htypeinfo htype '__func_inout' *args
165 # htypeinfo htype *args
166 t = tpe
167 if tpe.children[0].children[0] in ['__func_inout', 'sc_in']:
168 t = copy.deepcopy(tpe)
169 t.children = t.children[0].children[1:]
170 return t
171
172
173 def prevardecl(self, tree):
174 stub_decl = []
175 for name, stub in self.__current_process__current_process.name_stub.items():
176 stub_decl.append(
177 Tree('vardecl', children=[
178 Tree('vardeclinit', children=[ stub.children[0], stub.children[1] ])
179 ]))
180 for name, tpe in self.__current_process__current_process.phantom_vars.items():
181 t = self.strip_io_or_default(tpe)
182 stub_decl.append(
183 Tree('vardecl', children=[
184 Tree('vardeclinit', children=[name, t])
185 ]))
186 tree.children.extend(stub_decl)
187 return tree
188
189 def __extract_func_def(self, tree):
190 func_name = tree.children[0]
191 ret_type = None
192 func_params = None
193 local_vars = None
194 func_body = None
195 for child in tree.children[1:]:
196 if child.data == 'hfunctionparams':
197 func_params = child
198 elif child.data == 'hfunctionrettype':
199 ret_type = child
200 elif child.data == 'hfunctionlocalvars':
201 local_vars = child
202 elif child.data == 'hfunctionbody':
203 func_body = child
204 return func_name, ret_type, func_params, local_vars, func_body
205
207 # dprint(tree)
208 # dprint(hasattr(tree, 'original_name'))
209 if hasattr(tree, 'phantom_var'):
210 return tree.phantom_var
211 elif isinstance(tree, str):
212 return tree
213 elif hasattr(tree, 'original_name'):
214 return tree.original_name
215 return tree.children[0]
216
217 @property
221 elif self.__current_function:
222 return self.__current_function
225 else:
226 return None
227
229 self.current_scope_object.func_name_stubs.append(FuncNameStub(func))
230
231 def check_blocking(self, var_name):
232 in_global_scope = var_name in self.__current_module_scope_vars
233 # A method might be called in another function
234 if self.__current_process__current_process is not None:
235 proc_name = self.__current_process__current_process.children[0]
236 in_sens_list = var_name in self.__current_module_sense_list[proc_name]
237 else:
238 in_sens_list = False
239 if not in_global_scope or (in_global_scope and in_sens_list):
240 return True
241 else:
242 return False
243
244
245
246 def hmethodcall(self, tree):
247 # process children
248 # Careful... this might cause issue
249 self.__push_up(tree)
250 # we translate methods manually
251 # dprint(tree.pretty())
252 orig_len = len(tree.children)
253
254
255 # tree.children = [
256 # self.hmethodcall(x) if is_tree_type(x, 'hmethodcall') else x for x in tree.children
257 # ] # for other vars, we will need to process the stubs
258 # self.__push_up(tree)
259 # dprint(tree.pretty())
260 func_name = tree.children[0]
262 orig_func_name = func_name
263 # dprint('Before: ', func_name)
264 func_node = self.__search_current_function(func_name)
265 func_name, ret_type, func_params, local_vars, func_body = self.__extract_func_def(func_node)
266 # dprint('After: ', func_name)
267 extra_args = []
268 func_args = tree.children[1:]
269 if func_params is not None:
270 for idx, _ in func_params.io_params:
271 arg = self.__extract_id_from_func_arg(func_args[idx])
272 stub = self.current_scope_object.name_stub[arg]
273 extra_args.append(Tree('hvarref', children=[stub.children[0]]))
274 tree.children.extend(extra_args)
275 # fuzzy
276 if orig_func_name != func_name:
277 tree.children[0] = func_name
278 for idx in range(orig_len):
279 arg = tree.children[idx]
280 if idx == 0:
281 continue
282 if is_tree_type(arg, 'hmethodcall'):
283 self.hmethodcall(arg)
284 elif isinstance(arg, str) and self.check_blocking(arg):
285 stub = self.__get_current_process_stub(arg)
286 if stub:
287 tree.children[idx] = stub.children[0]
288 # dprint(tree.pretty())
289 return tree
290
291 def hfunctionparams(self, tree):
292 self.__push_up(tree)
293 return tree
294
296 tree.children[1].children[0].children[0] = 'sc_in'
297
299 if id in self.__func_param_stubs:
300 return self.__func_param_stubs[id]
301 return id
302
303 def __extract_func_id(self, tree):
304 if is_tree_type(tree, 'func_param_name_stub'):
305 return tree.children[0]
306 return tree
307
308 def hvarref(self, tree):
309 if hasattr(tree, 'func_repl_id'):
310 tree.original_name = tree.children[0]
311 tree.children[0] = self.__get_func_param_stub(self.__extract_func_id(tree.children[0]))
312 else: # check for stub in process
313 stub = self.__get_current_process_stub(tree.children[0])
314 if stub:
315 tree.original_name = tree.children[0]
316 tree.children[0] = stub.children[0]
317
318 return tree
319
320 def harrayref(self, tree):
321 self.__push_up(tree)
322 return tree
323
324 def hfunction(self, tree):
325 tree.func_name_stubs = []
326 self.__current_function = tree
327 func_name, ret_type, func_params, local_vars, func_body = self.__extract_func_def(tree)
328 extra_params = []
329 self.__func_param_stubs = dict()
330 if func_params is not None:
331 for idx, par in func_params.io_params:
332 tpe = func_params.children[idx].children[1]
333 # dprint(func_params.children[idx].pretty())
334 stub = FuncParamNameStub(par, copy.deepcopy(tpe))
335 extra_params.append(stub)
336 self.__change_type_to_funcinput(func_params.children[idx])
337 self.__func_param_stubs[par] = stub
338 if extra_params:
339 # NOTE: this condition must be present as it implies that func_params is not None
340 func_params.children.extend(extra_params)
341 for assignment in tree.assignments:
342 pass
343 # dprint(assignment.pretty())
344 self.__push_up(tree)
345 self.__current_function = None
346 return tree
347
__push_up(self, current_node)
Definition top_down.py:29