Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def prioritized_mux(selects, vals):
"""
Returns the value in the first wire for which its select bit is 1
:param [WireVector] selects: a list of WireVectors signaling whether
a wire should be chosen
:param [WireVector] vals: values to return when the corresponding select
value is 1
:return: WireVector
If none of the items are high, the last val is returned
"""
if len(selects) != len(vals):
raise pyrtl.PyrtlError("Number of select and val signals must match")
if len(vals) == 0:
raise pyrtl.PyrtlError("Must have a signal to mux")
if len(vals) == 1:
return vals[0]
else:
half = len(vals) // 2
return pyrtl.select(pyrtl.rtl_any(*selects[:half]),
truecase=prioritized_mux(selects[:half], vals[:half]),
falsecase=prioritized_mux(selects[half:], vals[half:]))
def calcuate_max_and_min_bitwidths(max_bitwidth=None, exact_bitwidth=None):
if max_bitwidth is not None:
min_bitwidth = 1
elif exact_bitwidth is not None:
min_bitwidth = max_bitwidth = exact_bitwidth
else:
raise pyrtl.PyrtlError("A max or exact bitwidth must be specified")
return min_bitwidth, max_bitwidth
def __getattr__(self, name):
try:
return self._pipeline_register_map[self._current_stage_num][name]
except KeyError:
raise pyrtl.PyrtlError(
'error, no pipeline register "%s" defined for stage %d'
% (name, self._current_stage_num))
def _add_signal(self, data_signals):
self._check_finalized()
if len(data_signals) != len(self.dest_wires):
raise pyrtl.PyrtlError("Incorrect number of data_signals for "
"instruction received {} , expected {}"
.format(len(data_signals), len(self.dest_wires)))
for dw, sig in zip(self.dest_wires, data_signals):
data_signal = pyrtl.as_wires(sig, dw.bitwidth)
self.dest_instrs_info[dw].append(data_signal)
It also supports a specified default value, SparseDefault
"""
import numbers
max_val = 2**len(sel) - 1
if SparseDefault in vals:
default_val = vals[SparseDefault]
del vals[SparseDefault]
for i in range(max_val + 1):
if i not in vals:
vals[i] = default_val
for key in vals.keys():
if not isinstance(key, numbers.Integral):
raise pyrtl.PyrtlError("value %s nust be either an integer or 'default'" % str(key))
if key < 0 or key > max_val:
raise pyrtl.PyrtlError("value %s is out of range of the sel wire" % str(key))
return _sparse_mux(sel, vals)
(0 = shift down, 1 = shift up)
:param shift_dist: WireVector representing offset to shift
:param wrap_around: ****currently not implemented****
:return: shifted WireVector
"""
# Implement with logN stages pyrtl.muxing between shifted and un-shifted values
val = bits_to_shift
append_val = bit_in
log_length = int(math.log(len(bits_to_shift)-1, 2)) # note the one offset
if wrap_around != 0:
raise NotImplementedError
if len(shift_dist) > log_length:
raise pyrtl.PyrtlError('the shift distance wirevector '
'has bits that are not used in the barrel shifter')
for i in range(min(len(shift_dist), log_length)):
shift_amt = pow(2, i) # stages shift 1,2,4,8,...
newval = pyrtl.select(direction, truecase=val[:-shift_amt], falsecase=val[shift_amt:])
newval = pyrtl.select(direction, truecase=pyrtl.concat(newval, append_val),
falsecase=pyrtl.concat(append_val, newval)) # Build shifted value
# pyrtl.mux shifted vs. unshifted by using i-th bit of shift amount signal
val = pyrtl.select(shift_dist[i], truecase=newval, falsecase=val)
append_val = pyrtl.concat(append_val, bit_in)
return val
def __getattr__(self, name):
try:
return self._pipeline_register_map[self._current_stage_num][name]
except KeyError:
raise pyrtl.PyrtlError(
'error, no pipeline register "%s" defined for stage %d'
% (name, self._current_stage_num))
"""
Creates a Fibonacci linear feedback shift register given the seed and bitwidth.
:param seed: the initial value of the LFSR
:param bitwidth: the bitwidth of LFSR
:param reset: one bit WireVector to set the LFSR to its seed state
:param enable: one bit WireVector to enable/disable the LFSR
:return: register storing the random value produced by the LFSR
The Fibonacci LFSR uses cascaded external xor gates to generate a 2^n - 1 cycles
pseudo random number sequence without repeating. It has a longer critical path
delay than the Galois LFSR.
"""
assert len(reset) == len(enable) == 1
if bitwidth not in tap_table:
raise pyrtl.PyrtlError(
'Bitwidth {} is either illegal or not supported'.format(bitwidth))
seed = pyrtl.as_wires(seed, bitwidth)
pyrtl.rtl_assert(seed != 0, pyrtl.PyrtlError(
'LFSR must start in non-zero seed state'))
lfsr = pyrtl.Register(bitwidth, 'lfsr')
feedback = lfsr[bitwidth - tap_table[bitwidth][0]]
for tap in tap_table[bitwidth][1:]:
# tap numbering is reversed for Fibonacci LFSRs
feedback = feedback ^ lfsr[bitwidth - tap]
with pyrtl.conditional_assignment:
with enable:
with reset:
lfsr.next |= seed
with pyrtl.otherwise:
lfsr.next |= pyrtl.concat(feedback, lfsr[1:])
return lfsr
"""
import numbers
max_val = 2**len(sel) - 1
if SparseDefault in vals:
default_val = vals[SparseDefault]
del vals[SparseDefault]
for i in range(max_val + 1):
if i not in vals:
vals[i] = default_val
for key in vals.keys():
if not isinstance(key, numbers.Integral):
raise pyrtl.PyrtlError("value %s nust be either an integer or 'default'" % str(key))
if key < 0 or key > max_val:
raise pyrtl.PyrtlError("value %s is out of range of the sel wire" % str(key))
return _sparse_mux(sel, vals)
def decryption(self, ciphertext, key):
"""
Builds a single cycle AES Decryption circuit
:param WireVector ciphertext: data to decrypt
:param WireVector key: AES key to use to encrypt (AES is symmetric)
:return: a WireVector containing the plaintext
"""
if len(ciphertext) != self._key_len:
raise pyrtl.PyrtlError("Ciphertext length is invalid")
if len(key) != self._key_len:
raise pyrtl.PyrtlError("key length is invalid")
key_list = self._key_gen(key)
t = self._add_round_key(ciphertext, key_list[10])
for round in range(1, 11):
t = self._inv_shift_rows(t)
t = self._sub_bytes(t, True)
t = self._add_round_key(t, key_list[10 - round])
if round != 10:
t = self._mix_columns(t, True)
return t