Skip to content

Commit 998ad91

Browse files
committed
bitpattern_to_val initial implementation
1 parent e81e59e commit 998ad91

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

pyrtl/helperfuncs.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,73 @@ def field_name(name):
266266
return MatchedFields(match, fields)
267267

268268

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+
269336
def chop(w, *segment_widths):
270337
""" Returns a list of WireVectors each a slice of the original 'w'
271338

0 commit comments

Comments
 (0)