@@ -20,8 +20,8 @@ def __init__(self, hwif: 'Hwif', hwif_name: str) -> None:
20
20
21
21
self .hwif_report_stack = [hwif_name ]
22
22
23
- def push_struct (self , type_name : str , inst_name : str , array_dimensions : Optional [List [int ]] = None ) -> None : # type: ignore
24
- super ().push_struct (type_name , inst_name , array_dimensions )
23
+ def push_struct (self , type_name : str , inst_name : str , array_dimensions : Optional [List [int ]] = None , packed : bool = False ) -> None : # type: ignore
24
+ super ().push_struct (type_name , inst_name , array_dimensions , packed )
25
25
26
26
if array_dimensions :
27
27
array_suffix = "" .join ([f"[0:{ dim - 1 } ]" for dim in array_dimensions ])
@@ -52,14 +52,14 @@ class InputStructGenerator_Hier(HWIFStructGenerator):
52
52
def __init__ (self , hwif : 'Hwif' ) -> None :
53
53
super ().__init__ (hwif , "hwif_in" )
54
54
55
- def get_typdef_name (self , node :'Node' ) -> str :
55
+ def get_typdef_name (self , node :'Node' , suffix : str = "" ) -> str :
56
56
base = node .get_rel_path (
57
57
self .top_node .parent ,
58
58
hier_separator = "__" ,
59
59
array_suffix = "x" ,
60
60
empty_array_suffix = "x"
61
61
)
62
- return f'{ base } __in_t'
62
+ return f'{ base } { suffix } __in_t'
63
63
64
64
def enter_Signal (self , node : 'SignalNode' ) -> None :
65
65
# only emit the signal if design scanner detected it is actually being used
@@ -95,15 +95,48 @@ def enter_Reg(self, node: 'RegNode') -> Optional[WalkerAction]:
95
95
super ().enter_Reg (node )
96
96
if node .external :
97
97
width = min (self .hwif .ds .cpuif_data_width , node .get_property ('regwidth' ))
98
+ n_subwords = node .get_property ("regwidth" ) // node .get_property ("accesswidth" )
98
99
if node .has_sw_readable :
99
100
self .add_member ("rd_ack" )
100
- self .add_member ( "rd_data" , width )
101
+ self .add_external_reg_rd_data ( node , width , n_subwords )
101
102
if node .has_sw_writable :
102
103
self .add_member ("wr_ack" )
103
104
return WalkerAction .SkipDescendants
104
105
105
106
return WalkerAction .Continue
106
107
108
+ def add_external_reg_rd_data (self , node : 'RegNode' , width : int , n_subwords : int ) -> None :
109
+ if n_subwords == 1 :
110
+ # External reg is 1 sub-word. Add a packed struct to represent it
111
+ type_name = self .get_typdef_name (node , "__fields" )
112
+ self .push_struct (type_name , "rd_data" , packed = True )
113
+ current_bit = 0
114
+ for field in node .fields ():
115
+ if not field .is_sw_readable :
116
+ continue
117
+ if field .low > current_bit :
118
+ # Add padding
119
+ self .add_member (
120
+ f"_reserved_{ field .low - 1 } _{ current_bit } " ,
121
+ field .low - current_bit
122
+ )
123
+ self .add_member (
124
+ kwf (field .inst_name ),
125
+ field .width
126
+ )
127
+ current_bit = field .high + 1
128
+
129
+ # Add end padding if needed
130
+ if current_bit != width :
131
+ self .add_member (
132
+ f"_reserved_{ width - 1 } _{ current_bit } " ,
133
+ width - current_bit
134
+ )
135
+ self .pop_struct ()
136
+ else :
137
+ # Multiple sub-words. Cannot generate a struct
138
+ self .add_member ("rd_data" , width )
139
+
107
140
def enter_Field (self , node : 'FieldNode' ) -> None :
108
141
type_name = self .get_typdef_name (node )
109
142
self .push_struct (type_name , kwf (node .inst_name ))
@@ -150,14 +183,14 @@ class OutputStructGenerator_Hier(HWIFStructGenerator):
150
183
def __init__ (self , hwif : 'Hwif' ) -> None :
151
184
super ().__init__ (hwif , "hwif_out" )
152
185
153
- def get_typdef_name (self , node :'Node' ) -> str :
186
+ def get_typdef_name (self , node :'Node' , suffix : str = "" ) -> str :
154
187
base = node .get_rel_path (
155
188
self .top_node .parent ,
156
189
hier_separator = "__" ,
157
190
array_suffix = "x" ,
158
191
empty_array_suffix = "x"
159
192
)
160
- return f'{ base } __out_t'
193
+ return f'{ base } { suffix } __out_t'
161
194
162
195
def _add_external_block_members (self , node : 'AddressableNode' ) -> None :
163
196
self .add_member ("req" )
@@ -193,12 +226,44 @@ def enter_Reg(self, node: 'RegNode') -> Optional[WalkerAction]:
193
226
self .add_member ("req" , n_subwords )
194
227
self .add_member ("req_is_wr" )
195
228
if node .has_sw_writable :
196
- self .add_member ("wr_data" , width )
197
- self .add_member ("wr_biten" , width )
229
+ self .add_external_reg_wr_data ("wr_data" , node , width , n_subwords )
230
+ self .add_external_reg_wr_data ("wr_biten" , node , width , n_subwords )
198
231
return WalkerAction .SkipDescendants
199
232
200
233
return WalkerAction .Continue
201
234
235
+ def add_external_reg_wr_data (self , name : str , node : 'RegNode' , width : int , n_subwords : int ) -> None :
236
+ if n_subwords == 1 :
237
+ # External reg is 1 sub-word. Add a packed struct to represent it
238
+ type_name = self .get_typdef_name (node , "__fields" )
239
+ self .push_struct (type_name , name , packed = True )
240
+ current_bit = 0
241
+ for field in node .fields ():
242
+ if not field .is_sw_writable :
243
+ continue
244
+ if field .low > current_bit :
245
+ # Add padding
246
+ self .add_member (
247
+ f"_reserved_{ field .low - 1 } _{ current_bit } " ,
248
+ field .low - current_bit
249
+ )
250
+ self .add_member (
251
+ kwf (field .inst_name ),
252
+ field .width
253
+ )
254
+ current_bit = field .high + 1
255
+
256
+ # Add end padding if needed
257
+ if current_bit != width :
258
+ self .add_member (
259
+ f"_reserved_{ width - 1 } _{ current_bit } " ,
260
+ width - current_bit
261
+ )
262
+ self .pop_struct ()
263
+ else :
264
+ # Multiple sub-words. Cannot generate a struct
265
+ self .add_member (name , width )
266
+
202
267
def enter_Field (self , node : 'FieldNode' ) -> None :
203
268
type_name = self .get_typdef_name (node )
204
269
self .push_struct (type_name , kwf (node .inst_name ))
@@ -229,7 +294,7 @@ def exit_Reg(self, node: 'RegNode') -> None:
229
294
230
295
#-------------------------------------------------------------------------------
231
296
class InputStructGenerator_TypeScope (InputStructGenerator_Hier ):
232
- def get_typdef_name (self , node :'Node' ) -> str :
297
+ def get_typdef_name (self , node :'Node' , suffix : str = "" ) -> str :
233
298
scope_path = node .get_global_type_name ("__" )
234
299
if scope_path is None :
235
300
# Unable to determine a reusable type name. Fall back to hierarchical path
@@ -242,10 +307,10 @@ def get_typdef_name(self, node:'Node') -> str:
242
307
else :
243
308
extra_suffix = ""
244
309
245
- return f'{ scope_path } { extra_suffix } __in_t'
310
+ return f'{ scope_path } { extra_suffix } { suffix } __in_t'
246
311
247
312
class OutputStructGenerator_TypeScope (OutputStructGenerator_Hier ):
248
- def get_typdef_name (self , node :'Node' ) -> str :
313
+ def get_typdef_name (self , node :'Node' , suffix : str = "" ) -> str :
249
314
scope_path = node .get_global_type_name ("__" )
250
315
if scope_path is None :
251
316
# Unable to determine a reusable type name. Fall back to hierarchical path
@@ -258,7 +323,7 @@ def get_typdef_name(self, node:'Node') -> str:
258
323
else :
259
324
extra_suffix = ""
260
325
261
- return f'{ scope_path } { extra_suffix } __out_t'
326
+ return f'{ scope_path } { extra_suffix } { suffix } __out_t'
262
327
263
328
#-------------------------------------------------------------------------------
264
329
class EnumGenerator :
0 commit comments