systemc-clang 2.0.0
Parsing SystemC constructs
Loading...
Searching...
No Matches
port_expansion.py
Go to the documentation of this file.
1from .top_down import TopDown
2from lark import Token, Tree
3from ..utils import dprint
4import copy
5import warnings
6import logging
7
8
10 def __init__(self):
11 """
12 Expands mixed port objects such as sc_rvd into in-port and out-port
13 This pass should come **before** typedef expansion
14 """
15 super().__init__()
16 self.expanded = list()
18
19 # The port expansion for sc_rvd_in and sc_rvd_out
20 def create_inport(self, t, meta):
21 return Tree('htype', [Token('TYPESTR', 'sc_in'), t], meta)
22
23 def create_outport(self, t, meta):
24 return Tree('htype', [Token('TYPESTR', 'sc_out'), t], meta)
25
26 def create_channel(self, t, meta):
27 return Tree('htype', [Token('TYPESTR', 'sc_signal'), t], meta)
28
29 def create_inport_decl(self, name, meta):
30 return Tree('inportdecl', [Token('ID', name)], meta)
31
32 def create_outport_decl(self, name, meta):
33 return Tree('outportdecl', [Token('ID', name)], meta)
34
35 def create_channel_decl(self, name, meta):
36 return Token('ID', name, meta)
37
38 def __expand_sc_rvd(self, tree, inout=None):
39 port_name, port_type = tree.children
40 port_type_meta = port_type.meta
41 if inout == 'channel':
42 port_name = port_name
43 elif inout in ['in', 'out']:
44 port_name = port_name.children[0].value
45
46 data_port = copy.deepcopy(port_type)
47 valid_port = copy.deepcopy(port_type)
48 ready_port = copy.deepcopy(port_type)
49
50 if inout == 'in':
51 data_valid_port_func = self.create_inport
52 data_valid_port_decl_func = self.create_inport_decl
53 ready_port_func = self.create_outport
54 ready_port_decl_func = self.create_outport_decl
55 elif inout == 'out':
56 data_valid_port_func = self.create_outport
57 data_valid_port_decl_func = self.create_outport_decl
58 ready_port_func = self.create_inport
59 ready_port_decl_func = self.create_inport_decl
60 elif inout == 'channel':
61 data_valid_port_func = self.create_channel
62 data_valid_port_decl_func = self.create_channel_decl
63 ready_port_func = self.create_channel
64 ready_port_decl_func = self.create_channel_decl
65
66 meta = data_port.children[0].meta
67
68 data_type = data_port.children[0].children[1]
69 data_port.children[0] = data_valid_port_func(data_type, meta)
70
71 signal_type = Tree('htype', [Token('TYPESTR', 'sc_uint'), 1])
72 valid_port.children[0] = data_valid_port_func(copy.deepcopy(signal_type), meta)
73 ready_port.children[0] = ready_port_func(copy.deepcopy(signal_type), meta)
74
75 meta = tree.meta
76
77 data_port_decl = copy.copy(tree)
78 valid_port_decl = copy.copy(tree)
79 ready_port_decl = copy.copy(tree)
80
81 data_port_decl.children = [data_valid_port_decl_func(port_name + '_data', meta), data_port]
82 valid_port_decl.children = [data_valid_port_decl_func(port_name + '_valid', meta), valid_port]
83 ready_port_decl.children = [ready_port_decl_func(port_name + '_ready', meta), ready_port]
84 return [data_port_decl, valid_port_decl, ready_port_decl]
85
87 _, sub, par = tree.children
88 par_name, par_type = self.__get_expanded(par.children[0])
89 if par_type:
90 assert par_type in ['sc_rvd', 'sc_rvd_in', 'sc_rvd_out']
91 new_trees = [copy.deepcopy(tree) for _ in range(3)]
92 sub_fields = ['data', 'valid', 'ready']
93 res = []
94 for t, f in zip(new_trees, sub_fields):
95 _, sub, par = t.children
96 sub_v = sub.children[0]
97 par_v = par.children[0]
98 # t.children[0 + 1].children[0].value = sub_v + '_' + f
99 # t.children[1 + 1].children[0].value = par_v + '_' + f
100 t.children[0 + 1].children[0] = Token('ID', sub_v + '_' + f)
101 t.children[1 + 1].children[0] = Token('ID', par_v + '_' + f)
102 res.append(t)
103 return res
104 else:
105 return [tree]
106
107 def __expand_port(self, tree):
108 # TODO: remove this hack when hcode fixed
109 if len(tree.children) == 3:
110 tree.children = tree.children[0:2]
111 port_name, port_type = tree.children
112 port_to_expand = ['sc_rvd_in', 'sc_rvd_out']
113 port_type_name = port_type.children[0].children[0]
114 if port_type_name in port_to_expand:
115 self.__set_expanded(port_name.children[0], port_type_name)
116 if port_type_name == 'sc_rvd_in':
117 return self.__expand_sc_rvd(tree, 'in')
118 elif port_type_name == 'sc_rvd_out':
119 return self.__expand_sc_rvd(tree, 'out')
120 else:
121 assert False
122 else:
123 return [tree]
124
125 def __expand_vardecl(self, tree):
126 if len(tree.children) == 3:
127 # warnings.warn('Expansion of sc_rvd with initial value is not supported')
128 return [tree]
129 bundle_name, bundle_type = tree.children
130 bundle_to_expand = ['sc_rvd']
131 bundle_type_name = bundle_type.children[0].children[0]
132 if bundle_type_name in bundle_to_expand:
133 self.__set_expanded(bundle_name, bundle_type_name)
134 return self.__expand_sc_rvd(tree, 'channel')
135 else:
136 return [tree]
137
138 def __set_expanded(self, var_name, bundle_type_name):
139 if var_name in self.expanded[-1]:
140 assert False, "Duplicate bundle decl"
141 self.expanded[-1][var_name] = bundle_type_name
142
143 def __get_expanded(self, var_name):
144 if var_name in self.expanded[-1]:
145 return var_name, self.expanded[-1][var_name]
146 else:
147 return None, None
148
149 def modportsiglist(self, tree):
150 self.__push_up(tree)
151 new_children = []
152 for ch in tree.children:
153 if ch.data == 'portdecltype':
154 res = self.__expand_port(ch)
155 new_children.extend(res)
156 elif ch.data == 'vardeclinit':
157 res = self.__expand_vardecl(ch)
158 new_children.extend(res)
159 else:
160 new_children.append(ch)
161 tree.children = new_children
162 return tree
163
164 def hmodinitblock(self, tree):
166 self.__push_up(tree)
168 return tree
169
170 def stmts(self, tree):
171 self.__push_up(tree)
173 return tree
174 new_children = []
175 for ch in tree.children:
176 if isinstance(ch, list):
177 new_children.extend(ch)
178 else:
179 new_children.append(ch)
180 tree.children = new_children
181 return tree
182
183 def forbody(self, tree):
184 self.__push_up(tree)
186 return tree
187 new_children = []
188 for ch in tree.children:
189 if isinstance(ch, list):
190 new_children.extend(ch)
191 else:
192 new_children.append(ch)
193 tree.children = new_children
194 return tree
195
196
198 assert stmt.data == 'stmt'
199 # portbinding is the only child
200 if len(stmt.children) == 1 and stmt.children[0].data == 'portbinding':
201 return True
202 return False
203
204 def stmt(self, tree):
206 self.__push_up(tree)
207 return tree
208 if not self.__check_stmt_portbinding(tree):
209 self.__push_up(tree)
210 return tree
211 self.__push_up(tree)
212 assert len(tree.children) == 1
213 new_children = tree.children[0]
214 tree.children = []
215 res = [
216 copy.deepcopy(tree)
217 for child in new_children
218 ]
219 for r, ch in zip(res, new_children):
220 r.children = [ch]
221 return res
222
223
224 def portbinding(self, tree):
225 res = self.__expand_sc_rvd_binding_pair(tree)
226 return res
227
228 def portbindinglist(self, tree):
229 module_name, *bindings = tree.children
230 new_children = []
231 for binding in bindings:
232 res = self.__expand_sc_rvd_binding_pair(binding)
233 new_children.extend(res)
234 tree.children = module_name, *new_children
235 return tree
236
237 def hmodule(self, tree):
238 self.expanded.append(dict())
239 self.__push_up(tree)
240 self.expanded.pop()
241 return tree
__set_expanded(self, var_name, bundle_type_name)
__push_up(self, current_node)
Definition top_down.py:29