def test_no_dup(self): sel = pyrtl.WireVector(3) a = pyrtl.WireVector(3) b = pyrtl.WireVector(3) res = muxes.sparse_mux(sel, {6: a, 2: b}) self.assertIsNot(res, a) self.assertIsNot(res, b)
def test_dup_consts2(self): sel = pyrtl.WireVector(3) c1 = pyrtl.Const(4) c2 = pyrtl.Const(4) res = muxes.sparse_mux(sel, {6: c1, 2: c2}) self.assertIsInstance(res, pyrtl.Const) self.assertEqual(res.val, 4)
def enum_mux(cntrl, table, default=None, strict=True): """ Build a mux for the control signals specified by an enum. :param cntrl: is a WireVector and control for the mux. :param table: is a dictionary of the form mapping enum->WireVector. :param default: is a WireVector to use when the key is not present. In addition it is possible to use the key 'otherwise' to specify a default value, but it is an error if both are supplied. :param strict: is flag, that when set, will cause enum_mux to check that the dictionary has an entry for every possible value in the enum. Note that if a default is set, then this check is not performed as the default will provide valid values for any underspecified keys. :return: a WireVector which is the result of the mux. Examples:: from enum import IntEnum class Command(IntEnum): ADD = 1 SUB = 2 enum_mux(cntrl, {Command.ADD: a+b, Command.SUB: a-b}) enum_mux(cntrl, {Command.ADD: a+b}, strict=False) # SUB case undefined enum_mux(cntrl, {Command.ADD: a+b, otherwise: a-b}) enum_mux(cntrl, {Command.ADD: a+b}, default=a-b) """ # check dictionary keys are of the right type keytypeset = set(type(x) for x in table.keys() if x is not otherwise) if len(keytypeset) != 1: raise PyrtlError( 'table mixes multiple types {} as keys'.format(keytypeset)) keytype = list(keytypeset)[0] # check that dictionary is complete for the enum try: enumkeys = list(keytype.__members__.values()) except AttributeError: raise PyrtlError( 'type {} not an Enum and does not support the same interface'. format(keytype)) missingkeys = [e for e in enumkeys if e not in table] # check for "otherwise" in table and move it to a default if otherwise in table: if default is not None: raise PyrtlError( 'both "otherwise" and default provided to enum_mux') else: default = table[otherwise] if strict and default is None and missingkeys: raise PyrtlError( 'table provided is incomplete, missing: {}'.format(missingkeys)) # generate the actual mux vals = {k.value: d for k, d in table.items() if k is not otherwise} if default is not None: vals['default'] = default return muxes.sparse_mux(cntrl, vals)
def test_multiple_bitwidths(self): sel = pyrtl.Input(3) a1, a1_vals = gen_in(3) a2, a2_vals = gen_in(8) a3, a3_vals = gen_in(5) res = pyrtl.Output(name="output") m = muxes.sparse_mux(sel, {2: a1, 3: a2, 6: a3}) self.assertEqual(len(m), 8) # the biggest one
def test_two_vals(self): sel, sel_vals = gen_in(1) a1, a1_vals = gen_in(3) a2, a2_vals = gen_in(3) res = pyrtl.Output(name="output") res <<= muxes.sparse_mux(sel, {0: a1, 1: a2}) in_vals = [sel_vals, a1_vals, a2_vals] out_res = utils.sim_and_ret_out(res, [sel, a1, a2], in_vals) expected_out = [e2 if sel else e1 for sel, e1, e2 in zip(*in_vals)] self.assertEqual(out_res, expected_out)
def test_two_big_close(self): sel = pyrtl.Input(3) a1, a1_vals = gen_in(3) a2, a2_vals = gen_in(3) res = pyrtl.Output(name="output") sel_vals = [utils.uniform_dist(1) for i in range(20)] real_sel = [6 if s else 5 for s in sel_vals] res <<= muxes.sparse_mux(sel, {5: a1, 6: a2}) out_res = utils.sim_and_ret_out(res, [sel, a1, a2], [real_sel, a1_vals, a2_vals]) expected_out = [e2 if sel else e1 for sel, e1, e2 in zip(sel_vals, a1_vals, a2_vals)] self.assertEqual(out_res, expected_out)
def test_default(self): sel, sel_vals = gen_in(3) a1, a1_vals = gen_in(3) a2, a2_vals = gen_in(3) default, default_vals = gen_in(3) res = pyrtl.Output(name="output") res <<= muxes.sparse_mux(sel, {5: a1, 6: a2, muxes.SparseDefault: default}) out_res = utils.sim_and_ret_out(res, [sel, a1, a2, default], [sel_vals, a1_vals, a2_vals, default_vals]) expected_out = [e2 if sel == 6 else e1 if sel == 5 else d for sel, e1, e2, d in zip(sel_vals, a1_vals, a2_vals, default_vals)] self.assertEqual(out_res, expected_out)
def test_one_value(self): sel = pyrtl.WireVector(3) a = pyrtl.WireVector(1) self.assertIs(muxes.sparse_mux(sel, {6: a}), a)
def test_no_dup_2(self): sel = pyrtl.WireVector(3) c1 = pyrtl.Const(4) c2 = pyrtl.Const(6) res = muxes.sparse_mux(sel, {6: c1, 2: c2}) self.assertNotIsInstance(res, pyrtl.Const)