@@ -266,6 +266,73 @@ def field_name(name):
266
266
return MatchedFields (match , fields )
267
267
268
268
269
+ def bitpattern_to_val (bitpattern , * ordered_fields , ** named_fields ):
270
+ """ Return an unsigned integer representation of field format filled with the provided values.
271
+
272
+ :param bitpattern: A string holding the pattern (of bits and wildcards) to match
273
+ :param ordered_fields: A list of parameters to be matched to the provided bit pattern in
274
+ the order provided. If ordered_fields are provided then no named_fields can be used.
275
+ :param named_fields: A list of parameters to be matched to the provided bit pattern in
276
+ by the names provided. If named_fields are provided then no ordered_fields can be used.
277
+ :return: An unsigned integer carrying the result of the field substitution.
278
+
279
+ This function will compare take a specified pattern of bits, where some
280
+ of the pattern can be "wildcard" bits. The wildcard bits must all be named with a single
281
+ letter and, unlike the related function ``match_bitpattern``, no "?" can be used. The function
282
+ will take the provided bitpattern and create an integer that substitutes the provided fields
283
+ in for the given wildcards at the bit level. This sort of bit substitution is useful when
284
+ creating values for testing when the resulting values will be "chopped" up by the hardware
285
+ later (e.g. instruction decode or other bitfield heavy functions).
286
+
287
+ Examples::
288
+
289
+ bitpattern_to_val('0000000rrrrrsssss000ddddd0110011', r=1, s=2, d=3) # RISCV ADD instr
290
+ bitpattern_to_val('iiiiiiirrrrrsssss010iiiii0100011', i=0, r=3, s=4) # RISCV SW instr
291
+
292
+ """
293
+
294
+ if len (ordered_fields ) > 0 and len (named_fields ) > 0 :
295
+ raise PyrtlError ('named and ordered fields cannot be mixed' )
296
+
297
+ def letters_in_field_order ():
298
+ seen = []
299
+ for c in bitpattern :
300
+ if c != '0' and c != '1' and c not in seen :
301
+ seen .append (c )
302
+ return seen
303
+
304
+ bitlist = []
305
+ lifo = letters_in_field_order ()
306
+ if ordered_fields :
307
+ if len (lifo ) != len (ordered_fields ):
308
+ raise PyrtlError ('number of fields and number of unique patterns do not match' )
309
+ intfields = [int (f ) for f in ordered_fields ]
310
+ else :
311
+ if len (lifo ) != len (named_fields ):
312
+ raise PyrtlError ('number of fields and number of unique patterns do not match' )
313
+ try :
314
+ intfields = [int (named_fields [n ]) for n in lifo ]
315
+ except KeyError :
316
+ raise PyrtlError ('named field does not appear in bitpattern format string' )
317
+
318
+ fmap = dict (zip (lifo , intfields ))
319
+ for c in bitpattern [::- 1 ]:
320
+ if c == '0' or c == '1' :
321
+ bitlist .append (c )
322
+ elif c == '?' :
323
+ raise PyrtlError ('all fields in must have names' )
324
+ else :
325
+ bitlist .append (str (fmap [c ] & 0x1 )) # append lsb of the field
326
+ fmap [c ] = fmap [c ] >> 1 # and bit shift by one position
327
+ for f in fmap :
328
+ if fmap [f ] not in [0 , - 1 ]:
329
+ raise PyrtlError ('too many bits given to value to fit in field' )
330
+ if len (bitpattern ) != len (bitlist ):
331
+ raise PyrtlInternalError ('resulting values have different bitwidths' )
332
+ final_str = '' .join (bitlist [::- 1 ])
333
+ return int (final_str , 2 )
334
+
335
+
269
336
def chop (w , * segment_widths ):
270
337
""" Returns a list of WireVectors each a slice of the original 'w'
271
338
0 commit comments