@@ -165,15 +165,16 @@ def __init__(self, layout_from, layout_to, ratio, reverse):
165
165
]
166
166
167
167
# data path
168
+ source_payload_raw_bits = Signal (len (source .payload .raw_bits ()))
168
169
cases = {}
169
170
for i in range (ratio ):
170
171
n = ratio - i - 1 if reverse else i
171
- cases [ i ] = []
172
- for name , width in layout_from :
173
- src = getattr ( self . sink , name )
174
- dst = getattr ( self . source , name )[ n * width :( n + 1 ) * width ]
175
- cases [ i ]. append ( dst . eq ( src ))
176
- self .sync += If ( load_part , Case ( demux , cases ) )
172
+ width = len ( sink . payload . raw_bits ())
173
+ src = sink . payload . raw_bits ()
174
+ dst = source_payload_raw_bits [ n * width :( n + 1 ) * width ]
175
+ cases [ i ] = dst . eq ( src )
176
+ self . sync += If ( load_part , Case ( demux , cases ))
177
+ self .comb += source . payload . raw_bits (). eq ( source_payload_raw_bits )
177
178
178
179
179
180
class _DownConverter (Module ):
@@ -202,79 +203,109 @@ def __init__(self, layout_from, layout_to, ratio, reverse):
202
203
)
203
204
204
205
# data path
206
+ sink_payload_raw_bits = Signal (len (sink .payload .raw_bits ()))
207
+ self .comb += sink_payload_raw_bits .eq (sink .payload .raw_bits ())
205
208
cases = {}
206
209
for i in range (ratio ):
207
210
n = ratio - i - 1 if reverse else i
208
- cases [i ] = []
209
- for name , width in layout_to :
210
- src = getattr (self .sink , name )[n * width :(n + 1 )* width ]
211
- dst = getattr (self .source , name )
212
- cases [i ].append (dst .eq (src ))
213
- self .comb += Case (mux , cases ).makedefault ()
211
+ width = len (source .payload .raw_bits ())
212
+ src = sink_payload_raw_bits [n * width :(n + 1 )* width ]
213
+ dst = source .payload .raw_bits ()
214
+ cases [i ] = dst .eq (src )
215
+ self .comb += Case (mux , cases ).makedefault (),
214
216
215
217
216
218
class _IdentityConverter (Module ):
217
219
def __init__ (self , layout_from , layout_to , ratio , reverse ):
218
- self .sink = Endpoint (layout_from )
219
- self .source = Endpoint (layout_to )
220
+ self .sink = sink = Endpoint (layout_from )
221
+ self .source = source = Endpoint (layout_to )
220
222
221
223
# # #
222
224
223
- self .comb += self . sink .connect (self . source )
225
+ self .comb += sink .connect (source )
224
226
225
227
226
228
def _get_converter_ratio (layout_from , layout_to ):
227
- if len (layout_from ) != len (layout_to ):
228
- raise ValueError ("Incompatible layouts (number of elements)" )
229
-
230
- converter = None
231
- ratio = None
232
- for f_from , f_to in zip (layout_from , layout_to ):
233
- name_from , width_from = f_from
234
- name_to , width_to = f_to
235
-
236
- # check layouts
237
- if not isinstance (width_to , int ) or not isinstance (width_to , int ):
238
- raise ValueError ("Sublayouts are not supported" )
239
- if name_from != name_to :
240
- raise ValueError ("Incompatible layouts (field names)" )
241
-
242
- # get current converter/ratio
243
- if width_from > width_to :
244
- current_converter = _DownConverter
245
- if width_from % width_to :
246
- raise ValueError ("Ratio must be an int" )
247
- current_ratio = width_from // width_to
248
- elif width_from < width_to :
249
- current_converter = _UpConverter
250
- if width_to % width_from :
251
- raise ValueError ("Ratio must be an int" )
252
- current_ratio = width_to // width_from
253
- else :
254
- current_converter = _IdentityConverter
255
- current_ratio = 1
229
+ width_from = len (Endpoint (layout_from ).payload .raw_bits ())
230
+ width_to = len (Endpoint (layout_to ).payload .raw_bits ())
231
+
232
+ if width_from > width_to :
233
+ converter_cls = _DownConverter
234
+ if width_from % width_to :
235
+ raise ValueError ("Ratio must be an int" )
236
+ ratio = width_from // width_to
237
+ elif width_from < width_to :
238
+ converter_cls = _UpConverter
239
+ if width_to % width_from :
240
+ raise ValueError ("Ratio must be an int" )
241
+ ratio = width_to // width_from
242
+ else :
243
+ converter_cls = _IdentityConverter
244
+ ratio = 1
245
+
246
+ return converter_cls , ratio
256
247
257
- # check converter
258
- if converter is None :
259
- converter = current_converter
260
- if current_converter != converter :
261
- raise ValueError ("Incoherent layout fields (converter type)" )
262
248
263
- # check ratio
264
- if ratio is None :
265
- ratio = current_ratio
266
- if current_ratio != ratio :
267
- raise ValueError ("Incoherent layout fields (ratio)" )
249
+ class Converter (Module ):
250
+ def __init__ (self , layout_from , layout_to , reverse = False ):
251
+ self .cls , self .ratio = _get_converter_ratio (layout_from , layout_to )
268
252
269
- return converter , ratio
253
+ # # #
270
254
255
+ converter = self .cls (layout_from , layout_to , self .ratio , reverse )
256
+ self .submodules += converter
271
257
272
- class Converter (Module ):
258
+ self .sink , self .source = converter .sink , converter .source
259
+
260
+
261
+ class StrideConverter (Module ):
273
262
def __init__ (self , layout_from , layout_to , reverse = False ):
274
- converter , ratio = _get_converter_ratio (layout_from , layout_to )
263
+ self .sink = sink = Endpoint (layout_from )
264
+ self .source = source = Endpoint (layout_to )
275
265
276
266
# # #
277
267
278
- self .submodules .converter = converter (layout_from , layout_to ,
279
- ratio , reverse )
280
- self .sink , self .source = self .converter .sink , self .converter .source
268
+ width_from = len (sink .payload .raw_bits ())
269
+ width_to = len (source .payload .raw_bits ())
270
+
271
+ converter = Converter ([("data" , width_from )],
272
+ [("data" , width_to )],
273
+ reverse )
274
+ self .submodules += converter
275
+
276
+ # cast sink to converter.sink (user fields --> raw bits)
277
+ self .comb += [
278
+ converter .sink .stb .eq (sink .stb ),
279
+ converter .sink .eop .eq (sink .eop ),
280
+ sink .ack .eq (converter .sink .ack )
281
+ ]
282
+ if converter .cls == _DownConverter :
283
+ ratio = converter .ratio
284
+ for i in range (ratio ):
285
+ j = 0
286
+ for name , width in layout_to :
287
+ src = getattr (sink , name )[i * width :(i + 1 )* width ]
288
+ dst = converter .sink .data [i * width_to + j :i * width_to + j + width ]
289
+ self .comb += dst .eq (src )
290
+ j += width
291
+ else :
292
+ self .comb += converter .sink .data .eq (sink .payload .raw_bits ())
293
+
294
+
295
+ # cast converter.source to source (raw bits --> user fields)
296
+ self .comb += [
297
+ source .stb .eq (converter .source .stb ),
298
+ source .eop .eq (converter .source .eop ),
299
+ converter .source .ack .eq (source .ack )
300
+ ]
301
+ if converter .cls == _UpConverter :
302
+ ratio = converter .ratio
303
+ for i in range (ratio ):
304
+ j = 0
305
+ for name , width in layout_from :
306
+ src = converter .source .data [i * width_from + j :i * width_from + j + width ]
307
+ dst = getattr (source , name )[i * width :(i + 1 )* width ]
308
+ self .comb += dst .eq (src )
309
+ j += width
310
+ else :
311
+ self .comb += source .payload .raw_bits ().eq (converter .source .data )
3 commit comments
sbourdeauducq commentedon Mar 13, 2016
What I meant is that the
Converter
should only be able to operate on layouts that are of the form[("data", nbits)]
. It could create its endpoints itself, and take only the bit sizes (integers) as parameter.sbourdeauducq commentedon Mar 13, 2016
This way you do not have to call
raw_bits
anywhere in the converter, and the addition of thechunks
fields is easier.enjoy-digital commentedon Mar 13, 2016
ok that's fine. I just did the changes and will test/commit it tomorrow.