systemc-clang 2.0.0
Parsing SystemC constructs
Loading...
Searching...
No Matches
interface_generation.py
Go to the documentation of this file.
1from lark import Tree, Token
2from parselib.utils import dprint
3from parselib.transforms import TopDown
4from ..utils import ContextManager, is_tree_type
5from dataclasses import dataclass
6import typing
7
8@dataclass(frozen=True)
9class PortDecl:
10 name: str
11 type: ...
12 direction: str
13
14@dataclass(frozen=True)
16 module_name: str
17 interface_name: str # we might need this for user to provide extra information
18 interfaces: typing.List[PortDecl]
19
20 @staticmethod
21 def generate_instance_name(instance_name, is_array) -> str:
22 if is_array:
23 return 'itf'
24 else:
25 return f'{instance_name}_itf'
26
28 return f'itf'
29
31 """
32 This module generate interface definitions, and put them in the start of the nodes
33 """
34 def __init__(self):
37 super().__init__()
38
39 def modulelist(self, tree):
40 with self.ctx.add_values(interfaces=[]):
41 self.__push_up(tree)
42 interfaces_tree_node = Tree(
43 'interfaces', []
44 )
45 for interface in self.ctx.interfaces:
46 interface_tree_node = Tree(
47 'interface', [
48 interface.interface_name,
49 ] + interface.interfaces
50 )
51 if interface.interfaces:
52 interfaces_tree_node.children.append(interface_tree_node)
53 if interfaces_tree_node.children:
54 tree.children.insert(0, interfaces_tree_node)
55
56 for interface in self.ctx.interfaces:
57 if interface.interfaces:
58 self.interface_meta_data[interface.module_name] = interface
59 return tree
60
61 def hmodule(self, tree):
62 with self.ctx.add_values(current_ports=[]):
63 self.__push_up(tree)
64 self.ctx.interfaces.append(
66 module_name=tree.children[0].value,
67 interface_name=tree.children[0].value + '_interface',
68 interfaces=self.ctx.current_ports
69 )
70 )
71 return tree
72
73 def htypeinfo(self, tree):
74 self.ctx.htype = tree.children[0]
75 return tree
76
77 def inportdecl(self, tree):
78 self.ctx.name = tree.children[0].value
79 self.ctx.direction = 'input'
80 return tree
81
82 def outportdecl(self, tree):
83 self.ctx.name = tree.children[0].value
84 self.ctx.direction = 'output'
85 return tree
86
87 def portdecltype(self, tree):
88 with self.ctx.add_values(htype=None, name=None, direction=None):
89 self.__push_up(tree)
90 self.ctx.current_ports.append(
92 name=self.ctx.name,
93 type=self.ctx.htype,
94 direction=self.ctx.direction,
95 )
96 )
97 return tree
98
99
101 assert tree.data == 'portdecltype', "Expecting portdecltype"
102 new_tree = Tree('sigdecltype', tree.children, meta=tree.meta)
103 new_tree.children[0] = Tree('sigdecl', [tree.children[0].children[0]])
104 new_tree.meta.direction = tree.direction
105 return new_tree
106
107 def _modportsiglist(self, tree):
108 with self.ctx.add_values(port_decl_to_remove=[]):
109 self.__push_up(tree)
110 if self.ctx.port_decl_to_remove:
111 tree.children = list(filter(lambda x: x not in self.ctx.port_decl_to_remove, tree.children))
112 # move it to varlist
113 insertion_pos = -1
114 # find the last sigdecltype, or last portdecltype if no sigdecltype exists
115 for i in range(len(tree.children) - 1, -1, -1):
116 if tree.children[i].data == 'sigdecltype':
117 insertion_pos = i
118 break
119 elif tree.children[i].data == 'portdecltype':
120 insertion_pos = i
121 break
122 new_sig_decls = list(map(self.portdecltype_to_sigdecltype, self.ctx.port_decl_to_remove))
123 tree.children = tree.children[:insertion_pos + 1] + new_sig_decls + tree.children[insertion_pos + 1:]
124
125 # for port in self.ctx.port_decl_to_remove:
126 # tree.children.append(
127 # self.portdecltype_to_sigdecltype(port)
128 # )
129
130 return tree
131
132 def _portdecltype(self, tree):
133 with self.ctx.add_values(current_port_decl_node=tree):
134 self.__push_up(tree)
135 return tree
136
137 def _htype(self, tree):
138 # If this is a port array
139 if self.ctx.current_port_decl_node and tree.children[0] == 'array':
140 if self.ctx.current_port_decl_node.children[0].data == 'inportdecl':
141 with self.ctx.add_values(port_erasure=True):
142 self.__push_up(tree)
143 self.ctx.current_port_decl_node.direction = 'input'
144 self.ctx.port_decl_to_remove.append(self.ctx.current_port_decl_node)
145 elif self.ctx.current_port_decl_node.children[0].data == 'outportdecl':
146 self.ctx.current_port_decl_node.direction = 'output'
147 else:
148 raise ValueError("Unknown port type")
149 elif self.ctx.port_erasure:
150 if tree.children[0] in ['sc_in', 'sc_out']:
151 return tree.children[1]
152 return tree
153 return tree
154
155
157 """Now we replace any interface port reference with the actual interface"""
158
159 def __init__(self, port_meta):
160 self.port_meta = port_meta
162 super().__init__()
163
164 def hmodule(self, tree):
165 with self.ctx.add_values(current_module=tree.children[0].value):
166 self.__push_up(tree)
167 return tree
168
169 # def hportbinding(self, tree):
170 # # we need to handle LHS case and RHS case
171 # # LHS should be the signal of the module,
172 # # RHS could be from
173 # # 1. the parent module
174 # # 2. internal signals
175 # pass
176 def genbindinglist(self, tree):
177 with self.ctx.add_values(is_in_genbindinglist=True):
178 self.__push_up(tree)
179 return tree
180
181 def portbindinglist(self, tree):
182 # this node is not automatically enumerated
183 port_bindings: list = tree.children[1]
184 for binding in port_bindings:
185 assert len(binding.children) == 3, "Internal error, length of port binding should be 3"
186 # only goes into right hand side
187 assert is_tree_type(binding.children[2], 'hvarref'), "Internal error, only hvarref is supported"
188 binding.children[2] = self.hvarref(binding.children[2])
189 return tree
190
191 # def portbinding(self, tree):
192 # if self.ctx.is_in_genbindinglist:
193 # if hasattr(tree, 'swap_for_for_loop'):
194 # if is_tree_type(tree.children[1], 'hvarref'):
195 # tree.children[1] = self.hvarref(tree.children[1])
196 # else:
197 # self.__push_up(tree.children[1])
198 # else:
199 # if is_tree_type(tree.children[1], 'hvarref'):
200 # tree.children[1] = self.hvarref(tree.children[1])
201 # else:
202 # self.__push_up(tree.children[1])
203
204 # tree.children[2] = self.hvarref(tree.children[2])
205 # return tree
206 # else:
207 # self.__push_up(tree)
208 # return tree
209
210 def hvarref(self, tree):
211 self.__push_up(tree)
212 assert len(tree.children) == 1, "Internal error, hvarref should only have one child"
213 cur_mod = self.ctx.current_module
214 if cur_mod not in self.port_meta:
215 return tree
216
217 # TODO: this checks whether a varref is a port of current module
218 # we could refactor this to be a function call such as _is_port_of_current_module()
219 interface = self.port_meta[cur_mod]
220 port_decls = interface.interfaces
221 for port_decl in port_decls:
222 # PortDecl
223 if port_decl.name == tree.children[0]:
224 # if this vardef is a local port
225 new_token = Token('INTF_ID', value=f'{interface.generate_interface_decl_name()}.{port_decl.name}', )
226 tree.children[0] = new_token
227 break
228 return tree
229
230 def hprocess(self, tree):
231 self.__push_up(tree)
232
233 if hasattr(tree, 'force_sensevar'):
234 self.__push_up(tree.force_sensevar)
235
236 return tree
__push_up(self, current_node)
Definition top_down.py:29