Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def tree_reduce(op, vector):
if len(vector) < 1:
raise PyrtlError("Cannot reduce empty vectors")
if len(vector) == 1:
return vector[0]
left = tree_reduce(op, vector[:len(vector) // 2])
right = tree_reduce(op, vector[len(vector) // 2:])
return op(left, right)
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 _to_verilog_combinational(file, block, varname):
""" Print the combinational logic of the verilog implementation. """
print(' // Combinational', file=file)
# assign constants (these could be folded for readability later)
for const in block.wirevector_subset(Const):
print(' assign {:s} = {:d};'.format(varname(const), const.val), file=file)
# walk the block and output combination logic
for net in block.logic:
if net.op in 'w~': # unary ops
opstr = '' if net.op == 'w' else net.op
t = (varname(net.dests[0]), opstr, varname(net.args[0]))
print(' assign %s = %s%s;' % t, file=file)
elif net.op in '&|^+-*<>': # binary ops
t = (varname(net.dests[0]), varname(net.args[0]),
net.op, varname(net.args[1]))
print(' assign %s = %s %s %s;' % t, file=file)
elif net.op == '=':
t = (varname(net.dests[0]), varname(net.args[0]),
varname(net.args[1]))
print(' assign %s = %s == %s;' % t, file=file)
}
# for simulation purposes, we can give the spots in memory an initial value
# note that in the actual circuit, the values are initially undefined
# below, we are building the data with which to initialize memory
mem1_init = {addr: 0 for addr in range(8)}
mem2_init = {addr: 0 for addr in range(8)}
# The simulation only recognizes initial values of memories when they are in a
# dictionary composing of memory : mem_values pairs.
memvals = {mem1: mem1_init, mem2: mem2_init}
# now run the simulation like before. Note the adding of the memory
# value map.
print("---------memories----------")
print(pyrtl.working_block())
sim_trace = pyrtl.SimulationTrace()
sim = pyrtl.Simulation(tracer=sim_trace, memory_value_map=memvals)
for cycle in range(len(simvals['we'])):
sim.step({k: int(v[cycle]) for k, v in simvals.items()})
sim_trace.render_trace()
toFirrtl_new.translate_to_firrtl(pyrtl.working_block(), "./firrtl_result.fir")
with open('./firrtl_result.fir', 'r') as myfile:
firrtl_str = myfile.read()
toFirrtl_new.wrap_firrtl_test(sim_trace, pyrtl.working_block(), firrtl_str, "example6tester", "/Users/shannon/Desktop/firrtl-interpreter/src/test/scala/firrtl_interpreter/")
# cleanup in preparation for the rom example
pyrtl.reset_working_block()
# --- Part 2: ROMs -----------------------------------------------------------
counter = pyrtl.Register(bitwidth=3, name='counter')
sum, carry_out = ripple_add(counter, pyrtl.Const("1'b1"))
counter.next <<= sum
# A couple new things in the above code. The two remaining types of basic
# WireVectors, Const and Register, both appear. Const, unsurprisingly, is just for
# holding constants (such as the 0 in ripple_add), but here we create one directly
# from a Verilog-like string which includes both the value and the bitwidth.
# Registers are just like wires, except their updates are delayed to the next
# clock cycle. This is made explicit in the syntax through the property '.next'
# which should always be set for registers. In this simple example, we take
# counter next cycle equal to counter this cycle plus one.
# Now let's run the bugger. No need for inputs, as it doesn't have any.
# Finally we'll print the trace to the screen and check that it counts up correctly.
print(pyrtl.working_block())
sim_trace = pyrtl.SimulationTrace()
sim = pyrtl.Simulation(tracer=sim_trace)
for cycle in range(20):
sim.step({})
assert sim.value[counter] == cycle % 8
sim_trace.render_trace()
# all done.
toFirrtl_new.translate_to_firrtl(pyrtl.working_block(), "./firrtl_result.fir")
with open('./firrtl_result.fir', 'r') as myfile:
firrtl_str = myfile.read()
toFirrtl_new.wrap_firrtl_test(sim_trace, pyrtl.working_block(), firrtl_str, "example2tester", "/Users/shannon/Desktop/firrtl-interpreter/src/test/scala/firrtl_interpreter/")
def test_no_bits_to_update(self):
a = pyrtl.WireVector(name='a', bitwidth=3)
b = pyrtl.WireVector(name='b', bitwidth=3)
with self.assertRaises(pyrtl.PyrtlError):
o = pyrtl.bitfield_update(a,1,1,b,truncating=True)
def test_prng_lfsr(self):
seed = pyrtl.Input(127, 'seed')
load, req = pyrtl.Input(1, 'load'), pyrtl.Input(1, 'req')
rand = pyrtl.Output(128, 'rand')
rand <<= prngs.prng_lfsr(128, load, req, seed)
sim_trace = pyrtl.SimulationTrace()
sim = pyrtl.Simulation(tracer=sim_trace)
in_vals = [random.randrange(1, 2**127) for i in range(5)]
for trial in range(5):
true_val = 0
for bit in islice(TestPrngs.fibonacci_lfsr(in_vals[trial]), 128):
true_val = true_val << 1 | bit
sim.step({'load': 1, 'req': 0, 'seed': in_vals[trial]})
sim.step({'load': 0, 'req': 1, 'seed': 0x0})
sim.step({'load': 0, 'req': 0, 'seed': 0x0})
circuit_out = sim.inspect(rand)
self.assertEqual(circuit_out, true_val,
"\nAssertion failed on trial {}\nExpected value: {}\nGotten value: {}"
def test_invalid_inspect(self):
a = pyrtl.Input(8, 'a')
sim_trace = pyrtl.SimulationTrace()
sim = self.sim(tracer=sim_trace)
sim.step({a: 28})
with self.assertRaises(KeyError):
sim.inspect('asd')
def test_aes_state_machine(self):
# self.longMessage = True
aes_key = pyrtl.Input(bitwidth=128, name='aes_key')
reset = pyrtl.Input(1)
ready = pyrtl.Output(1, name='ready')
decrypt_ready, decrypt_out = self.aes.decryption_statem(self.in_vector, aes_key, reset)
self.out_vector <<= decrypt_out
ready <<= decrypt_ready
sim_trace = pyrtl.SimulationTrace()
sim = pyrtl.Simulation(tracer=sim_trace)
sim.step({
self.in_vector: 0x69c4e0d86a7b0430d8cdb78070b4c55a,
aes_key: 0x000102030405060708090a0b0c0d0e0f,
reset: 1
})
def test_function_RomBlock_with_optimization(self):
def rom_data_function(add):
return int((add + 5)/2)
pyrtl.reset_working_block()
self.bitwidth = 4
self.addrwidth = 4
self.output1 = pyrtl.Output(self.bitwidth, "o1")
self.output2 = pyrtl.Output(self.bitwidth, "o2")
# self.output3 = pyrtl.Output(self.bitwidth, "o3")
# self.read_out = pyrtl.WireVector(self.bitwidth)
self.read_addr1 = pyrtl.Input(self.addrwidth)
self.read_addr2 = pyrtl.Input(self.addrwidth)
self.rom = pyrtl.RomBlock(bitwidth=self.bitwidth, addrwidth=self.addrwidth,
name='rom', romdata=rom_data_function)
# self.read_out <<= self.rom[self.read_addr1]
# self.output1 <<= self.read_out - 1
self.output1 <<= self.rom[self.read_addr1]
self.output2 <<= self.rom[self.read_addr2]
pyrtl.synthesize()
pyrtl.optimize()
# build the actual simulation environment
self.sim_trace = pyrtl.SimulationTrace()
self.sim = pyrtl.FastSimulation(tracer=self.sim_trace)
input_signals = {}
for i in range(0, 5):
input_signals[i] = {self.read_addr1: i, self.read_addr2: 2*i}