Skip to content

Commit 64c684a

Browse files
authored
Merge pull request #387 from pllab/bitfield-update
More tests, documentation for bitfield_update (incl. set)
2 parents fe49c46 + cd291ae commit 64c684a

File tree

2 files changed

+61
-14
lines changed

2 files changed

+61
-14
lines changed

pyrtl/corecircuits.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,10 @@ def bitfield_update(w, range_start, range_end, newvalue, truncating=False):
436436
w = bitfield_update(w, 20, 23, 0x7) # sets bits 20, 21, 22 to 1
437437
w = bitfield_update(w, 20, 23, 0x6) # sets bit 20 to 0, bits 21 and 22 to 1
438438
w = bitfield_update(w, 20, None, 0x7) # assuming w is 32 bits, sets bits 31..20 = 0x7
439-
w = bitfield_update(w, -1, None, 0x1) # set the LSB (bit) to 1
439+
w = bitfield_update(w, -1, None, 0x1) # set the MSB (bit) to 1
440+
w = bitfield_update(w, None, -1, 0x9) # set the bits before the MSB (bit) to 9
441+
w = bitfield_update(w, None, 1, 0x1) # set the LSB (bit) to 1
442+
w = bitfield_update(w, 1, None, 0x9) # set the bits after the LSB (bit) to 9
440443
"""
441444
from .corecircuits import concat_list
442445

@@ -482,8 +485,8 @@ def bitfield_update_set(w, update_set, truncating=False):
482485
w = bitfield_update_set(w, {
483486
(20, 23): 0x6, # sets bit 20 to 0, bits 21 and 22 to 1
484487
(26, None): 0x7, # assuming w is 32 bits, sets bits 31..26 to 0x7
485-
(-1, None): 0x0 # set the LSB (bit) to 0
486-
})
488+
(None, 1): 0x0, # set the LSB (bit) to 0
489+
})
487490
"""
488491
w = as_wires(w)
489492
# keep a list of bits that are updated to find overlaps

tests/test_helperfuncs.py

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -541,8 +541,6 @@ def ref(i, s, e, u):
541541
return (i & ~mask) | ((u << s) & mask)
542542
inp, inp_vals = utils.an_input_and_vals(input_width, test_vals=test_amt, name='inp')
543543
upd, upd_vals = utils.an_input_and_vals(update_width, test_vals=test_amt, name='upd')
544-
# inp_vals = [1,1,0,0]
545-
# upd_vals = [0x7,0x6,0x7,0x6]
546544
out = pyrtl.Output(input_width, "out")
547545
bfu_out = pyrtl.bitfield_update(inp, range_start, range_end, upd)
548546
self.assertEqual(len(out), len(bfu_out)) # output should have width of input
@@ -554,6 +552,34 @@ def ref(i, s, e, u):
554552
def test_bitfield(self):
555553
self.bitfield_update_checker(10, 3, 6, 3)
556554

555+
def test_bitfield_msb(self):
556+
a = pyrtl.Const(0, 8)
557+
pyrtl.probe(pyrtl.bitfield_update(a, -1, None, 1), 'out')
558+
sim = pyrtl.Simulation()
559+
sim.step({})
560+
self.assertEqual(sim.inspect('out'), 0b10000000)
561+
562+
def test_bitfield_all_but_msb(self):
563+
a = pyrtl.Const(0, 8)
564+
pyrtl.probe(pyrtl.bitfield_update(a, None, -1, 0b101110), 'out')
565+
sim = pyrtl.Simulation()
566+
sim.step({})
567+
self.assertEqual(sim.inspect('out'), 0b0101110)
568+
569+
def test_bitfield_lsb(self):
570+
a = pyrtl.Const(0, 8)
571+
pyrtl.probe(pyrtl.bitfield_update(a, None, 1, 1), 'out')
572+
sim = pyrtl.Simulation()
573+
sim.step({})
574+
self.assertEqual(sim.inspect('out'), 0b00000001)
575+
576+
def test_bitfield_all_but_lsb(self):
577+
a = pyrtl.Const(0, 8)
578+
pyrtl.probe(pyrtl.bitfield_update(a, 1, None, 0b1011101), 'out') # TODO
579+
sim = pyrtl.Simulation()
580+
sim.step({})
581+
self.assertEqual(sim.inspect('out'), 0b10111010)
582+
557583

558584
class TestBitField_Update_Set(unittest.TestCase):
559585
def setUp(self):
@@ -597,25 +623,43 @@ def test_overlapping_ranges(self):
597623
with self.assertRaises(pyrtl.PyrtlError):
598624
o = pyrtl.bitfield_update_set(a, {(None, 3): b, (0, 1): c}, truncating=True)
599625

600-
def bitfield_update_checker(self, input_width, range_start, range_end,
601-
update_width, test_amt=20):
626+
def bitfield_update_set_checker(self, input_width, update_set_constraints, test_amt=20):
627+
from functools import reduce
628+
from collections import namedtuple
629+
Update_Info = namedtuple('Update_Info', ['range_start', 'range_end',
630+
'update_wire', 'update_vals'])
631+
602632
def ref(i, s, e, u):
603633
mask = ((1 << (e)) - 1) - ((1 << s) - 1)
604634
return (i & ~mask) | ((u << s) & mask)
605635
inp, inp_vals = utils.an_input_and_vals(input_width, test_vals=test_amt, name='inp')
606-
upd, upd_vals = utils.an_input_and_vals(update_width, test_vals=test_amt, name='upd')
607-
# inp_vals = [1,1,0,0]
608-
# upd_vals = [0x7,0x6,0x7,0x6]
636+
update_set_list = []
637+
for ix, (range_start, range_end, update_width) in enumerate(update_set_constraints):
638+
upd, upd_vals = utils.an_input_and_vals(update_width, test_vals=test_amt,
639+
name='upd%d' % ix)
640+
update_set_list.append(Update_Info(range_start, range_end, upd, upd_vals))
609641
out = pyrtl.Output(input_width, "out")
610-
bfu_out = pyrtl.bitfield_update_set(inp, {(range_start, range_end): upd})
642+
bfu_out = pyrtl.bitfield_update_set(
643+
inp,
644+
{(ui.range_start, ui.range_end): ui.update_wire for ui in update_set_list}
645+
)
611646
self.assertEqual(len(out), len(bfu_out)) # output should have width of input
612647
out <<= bfu_out
613-
true_result = [ref(i, range_start, range_end, u) for i, u in zip(inp_vals, upd_vals)]
614-
upd_result = utils.sim_and_ret_out(out, [inp, upd], [inp_vals, upd_vals])
648+
true_result = []
649+
for ix, iv in enumerate(inp_vals):
650+
true_result.append(
651+
reduce(lambda w, ui: ref(w, ui.range_start, ui.range_end, ui.update_vals[ix]),
652+
update_set_list, iv)
653+
)
654+
upd_result = utils.sim_and_ret_out(
655+
out,
656+
[inp] + [ui.update_wire for ui in update_set_list],
657+
[inp_vals] + [ui.update_vals for ui in update_set_list],
658+
)
615659
self.assertEqual(upd_result, true_result)
616660

617661
def test_bitfield(self):
618-
self.bitfield_update_checker(10, 3, 6, 3)
662+
self.bitfield_update_set_checker(10, [(3, 6, 3), (0, 2, 2)])
619663

620664

621665
class TestAnyAll(unittest.TestCase):

0 commit comments

Comments
 (0)