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()
17
18 # The port expansion for sc_rvd_in and sc_rvd_out
19 def create_inport(self, t, meta):
20 return Tree('htype', [Token('TYPESTR', 'sc_in'), t], meta)
21
22 def create_outport(self, t, meta):
23 return Tree('htype', [Token('TYPESTR', 'sc_out'), t], meta)
24
25 def create_channel(self, t, meta):
26 return Tree('htype', [Token('TYPESTR', 'sc_signal'), t], meta)
27
28 def create_inport_decl(self, name, meta):
29 return Tree('inportdecl', [Token('ID', name)], meta)
30
31 def create_outport_decl(self, name, meta):
32 return Tree('outportdecl', [Token('ID', name)], meta)
33
34 def create_channel_decl(self, name, meta):
35 return Token('ID', name, meta)
36
37 def __expand_sc_rvd(self, tree, inout=None):
38 port_name, port_type = tree.children
39 port_type_meta = port_type.meta
40 if inout == 'channel':
41 port_name = port_name
42 elif inout in ['in', 'out']:
43 port_name = port_name.children[0].value
44
45 data_port = copy.deepcopy(port_type)
46 valid_port = copy.deepcopy(port_type)
47 ready_port = copy.deepcopy(port_type)
48
49 if inout == 'in':
50 data_valid_port_func = self.create_inport
51 data_valid_port_decl_func = self.create_inport_decl
52 ready_port_func = self.create_outport
53 ready_port_decl_func = self.create_outport_decl
54 elif inout == 'out':
55 data_valid_port_func = self.create_outport
56 data_valid_port_decl_func = self.create_outport_decl
57 ready_port_func = self.create_inport
58 ready_port_decl_func = self.create_inport_decl
59 elif inout == 'channel':
60 data_valid_port_func = self.create_channel
61 data_valid_port_decl_func = self.create_channel_decl
62 ready_port_func = self.create_channel
63 ready_port_decl_func = self.create_channel_decl
64
65 meta = data_port.children[0].meta
66
67 data_type = data_port.children[0].children[1]
68 data_port.children[0] = data_valid_port_func(data_type, meta)
69
70 signal_type = Tree('htype', [Token('TYPESTR', 'sc_uint'), 1])
71 valid_port.children[0] = data_valid_port_func(copy.deepcopy(signal_type), meta)
72 ready_port.children[0] = ready_port_func(copy.deepcopy(signal_type), meta)
73
74 meta = tree.meta
75
76 data_port_decl = copy.copy(tree)
77 valid_port_decl = copy.copy(tree)
78 ready_port_decl = copy.copy(tree)
79
80 data_port_decl.children = [data_valid_port_decl_func(port_name + '_data', meta), data_port]
81 valid_port_decl.children = [data_valid_port_decl_func(port_name + '_valid', meta), valid_port]
82 ready_port_decl.children = [ready_port_decl_func(port_name + '_ready', meta), ready_port]
83 return [data_port_decl, valid_port_decl, ready_port_decl]
84
86 _, sub, par = tree.children
87 par_name, par_type = self.__get_expanded(par.children[0])
88 if par_type:
89 assert par_type in ['sc_rvd', 'sc_rvd_in', 'sc_rvd_out']
90 new_trees = [copy.deepcopy(tree) for _ in range(3)]
91 sub_fields = ['data', 'valid', 'ready']
92 res = []
93 for t, f in zip(new_trees, sub_fields):
94 _, sub, par = t.children
95 sub_v = sub.children[0]
96 par_v = par.children[0]
97 t.children[0 + 1].children[0].value = sub_v + '_' + f
98 t.children[1 + 1].children[0].value = par_v + '_' + f
99 res.append(t)
100 return res
101 else:
102 return [tree]
103
104 def __expand_port(self, tree):
105 # TODO: remove this hack when hcode fixed
106 if len(tree.children) == 3:
107 tree.children = tree.children[0:2]
108 port_name, port_type = tree.children
109 port_to_expand = ['sc_rvd_in', 'sc_rvd_out']
110 port_type_name = port_type.children[0].children[0]
111 if port_type_name in port_to_expand:
112 self.__set_expanded(port_name.children[0], port_type_name)
113 if port_type_name == 'sc_rvd_in':
114 return self.__expand_sc_rvd(tree, 'in')
115 elif port_type_name == 'sc_rvd_out':
116 return self.__expand_sc_rvd(tree, 'out')
117 else:
118 assert False
119 else:
120 return [tree]
121
122 def __expand_vardecl(self, tree):
123 if len(tree.children) == 3:
124 # warnings.warn('Expansion of sc_rvd with initial value is not supported')
125 return [tree]
126 bundle_name, bundle_type = tree.children
127 bundle_to_expand = ['sc_rvd']
128 bundle_type_name = bundle_type.children[0].children[0]
129 if bundle_type_name in bundle_to_expand:
130 self.__set_expanded(bundle_name, bundle_type_name)
131 return self.__expand_sc_rvd(tree, 'channel')
132 else:
133 return [tree]
134
135 def __set_expanded(self, var_name, bundle_type_name):
136 if var_name in self.expanded[-1]:
137 assert False, "Duplicate bundle decl"
138 self.expanded[-1][var_name] = bundle_type_name
139
140 def __get_expanded(self, var_name):
141 if var_name in self.expanded[-1]:
142 return var_name, self.expanded[-1][var_name]
143 else:
144 return None, None
145
146 def modportsiglist(self, tree):
147 self.__push_up(tree)
148 new_children = []
149 for ch in tree.children:
150 if ch.data == 'portdecltype':
151 res = self.__expand_port(ch)
152 new_children.extend(res)
153 elif ch.data == 'vardeclinit':
154 res = self.__expand_vardecl(ch)
155 new_children.extend(res)
156 else:
157 new_children.append(ch)
158 tree.children = new_children
159 return tree
160
161
162 def portbindinglist(self, tree):
163 module_name, *bindings = tree.children
164 new_children = []
165 for binding in bindings:
166 res = self.__expand_sc_rvd_binding_pair(binding)
167 new_children.extend(res)
168 tree.children = module_name, *new_children
169 return tree
170
171 def hmodule(self, tree):
172 self.expanded.append(dict())
173 self.__push_up(tree)
174 self.expanded.pop()
175 return tree
__set_expanded(self, var_name, bundle_type_name)
__push_up(self, current_node)
Definition top_down.py:29