Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
raise PyrtlError(
'Connection using <<= operator attempted on Input. '
'Inputs, such as "%s", cannot have values generated internally. '
"aka they can't have other wires driving it"
% str(self.name))
def __ior__(self, _):
""" This is an illegal op for Inputs. They cannot be assigned to in this way """
raise PyrtlError(
'Connection using |= operator attempted on Input. '
'Inputs, such as "%s", cannot have values generated internally. '
"aka they can't have other wires driving it"
% str(self.name))
class Output(WireVector):
""" A WireVector type denoting outputs of a block (no readers)
Even though Output seems to have valid ops such as __or__ , using
them will throw an error.
"""
_code = 'O'
def __init__(self, bitwidth=None, name='', block=None):
super(Output, self).__init__(bitwidth, name, block)
class Const(WireVector):
""" A WireVector representation of a constant value
Converts from bool, integer, or verilog-style strings to a constant
of the specified bitwidth. If the bitwidth is too short to represent
the specified constant then an error is raised. If a possitive
a list of arguments to concat together you will likely want index 0 to be the least
significant bit and so if you unpack the list into the arguements here it will be
backwards. The function concat_list is provided for that case specifically.
Example using concat to combine two bytes into a 16-bit quantity: ::
concat( msb, lsb )
"""
if len(args) <= 0:
raise PyrtlError('error, concat requires at least 1 argument')
if len(args) == 1:
return as_wires(args[0])
arg_wirevectors = tuple(as_wires(arg) for arg in args)
final_width = sum(len(arg) for arg in arg_wirevectors)
outwire = WireVector(bitwidth=final_width)
net = LogicNet(
op='c',
op_param=None,
args=arg_wirevectors,
dests=(outwire,))
working_block().add_net(net)
return outwire
def xing_event(win, wout, stages=2):
"""Clock domain crossing for an event from `win` to `wout`.
Use when passing a 1-bit event between clock domains.
An event is a signal that occassionally goes high for a single cycle,
and otherwise remains low.
Most designs require stages=2 to avoid metastability,
but some high-speed designs may require stages=3.
"""
if len(win) != 1 or len(wout) != 1:
raise PyrtlError('Event crossing only works on bitwidth 1')
rin = Register(bitwidth=1, clock=win.clock)
rin.next <<= win ^ rin
x = WireVector(bitwidth=1, clock=wout.clock)
xing_simple(rin, x, stages=stages, align=False)
rout = Register(bitwidth=1, clock=wout.clock)
rout.next <<= x
wout <<= x ^ rout
def extract_inputs(model):
start_names = [re.sub(r'\[([0-9]+)\]$', '', x) for x in model['input_list']]
name_counts = collections.Counter(start_names)
for input_name in name_counts:
bitwidth = name_counts[input_name]
if input_name == 'clk':
clk_set.add(input_name)
elif not merge_io_vectors or bitwidth == 1:
block.add_wirevector(Input(bitwidth=1, name=input_name))
else:
wire_in = Input(bitwidth=bitwidth, name=input_name, block=block)
for i in range(bitwidth):
bit_name = input_name + '[' + str(i) + ']'
bit_wire = WireVector(bitwidth=1, name=bit_name, block=block)
bit_wire <<= wire_in[i]
def twire(x):
""" find or make wire named x and return it """
s = block.get_wirevector_by_name(x)
if s is None:
s = WireVector(bitwidth=1, name=x)
return s
:param name: optional name for probe (defaults to an autogenerated name)
:return: original WireVector w
Probe can be inserted into a existing design easily as it returns the
original wire unmodified. For example ``y <<= x[0:3] + 4`` could be turned
into ``y <<= probe(x)[0:3] + 4`` to give visibility into both the origin of
``x`` (including the line that WireVector was originally created) and
the run-time values of ``x`` (which will be named and thus show up by
default in a trace. Likewise ``y <<= probe(x[0:3]) + 4``,
``y <<= probe(x[0:3] + 4)``, and ``probe(y) <<= x[0:3] + 4`` are all
valid uses of `probe`.
Note: `probe` does actually add a wire to the working block of w (which can
confuse various post-processing transforms such as output to verilog).
"""
if not isinstance(w, WireVector):
raise PyrtlError('Only WireVectors can be probed')
if name is None:
name = '(%s: %s)' % (probeIndexer.make_valid_string(), w.name)
print("Probe: " + name + ' ' + get_stack(w))
p = Output(name=name)
p <<= w # late assigns len from w automatically
return w
def sanity_check_wirevector(self, w):
""" Check that w is a valid wirevector type. """
from .wire import WireVector
if not isinstance(w, WireVector):
raise PyrtlError(
'error attempting to pass an input of type "%s" '
'instead of WireVector' % type(w))
def __getitem__(self, item):
""" Grabs a subset of the wires
:return Wirevector: a result wire for the operation
"""
if self.bitwidth is None:
raise PyrtlError('You cannot get a subset of a wire with no bitwidth')
allindex = range(self.bitwidth)
if isinstance(item, int):
selectednums = (allindex[item], ) # this method handles negative numbers correctly
else: # slice
selectednums = tuple(allindex[item])
if not selectednums:
raise PyrtlError('selection %s must have at least select one wire' % str(item))
outwire = WireVector(bitwidth=len(selectednums))
net = LogicNet(
op='s',
op_param=selectednums,
args=(self,),
dests=(outwire,))
working_block().add_net(net)
return outwire