RTL Library

This is a set of files that contain useful miscellaneous functions and classes

Adders

pyrtl.rtllib.adders.kogge_stone(a, b, cin=0)

Creates a Kogge-Stone adder given two inputs

Parameters:
  • a, b (WireVector) – The two WireVectors to add up (bitwidths don’t need to match)
  • cin – An optimal carry in WireVector or value
Returns:

a Wirevector representing the output of the adder

The Kogge-Stone adder is a fast tree-based adder with O(log(n)) propagation delay, useful for performance critical designs. However, it has O(n log(n)) area usage, and large fan out.

pyrtl.rtllib.adders.one_bit_add(a, b, cin=0)
pyrtl.rtllib.adders.half_adder(a, b)
pyrtl.rtllib.adders.ripple_add(a, b, cin=0)
pyrtl.rtllib.adders.ripple_half_add(a, cin=0)
pyrtl.rtllib.adders.carrysave_adder(a, b, c, final_adder=<function ripple_add>)

Adds three wirevectors up in an efficient manner :param WireVector a, b, c : the three wires to add up :param function final_adder : The adder to use to do the final addition :return: a wirevector with length 2 longer than the largest input

pyrtl.rtllib.adders.cla_adder(a, b, cin=0, la_unit_len=4)

Carry Lookahead Adder :param int la_unit_len: the length of input that every unit processes

A Carry LookAhead Adder is an adder that is faster than a ripple carry adder, as it calculates the carry bits faster. It is not as fast as a Kogge-Stone adder, but uses less area.

pyrtl.rtllib.adders.wallace_reducer(wire_array_2, result_bitwidth, final_adder=<function kogge_stone>)

The reduction and final adding part of a dada tree. Useful for adding many numbers together The use of single bitwidth wires is to allow for additional flexibility

Parameters:
  • wire_array_2 ([[Wirevector]]) – An array of arrays of single bitwidth wirevectors
  • result_bitwidth (int) – The bitwidth you want for the resulting wire. Used to eliminate unnessary wires.
  • final_adder – The adder used for the final addition
Returns:

wirevector of length result_wirevector

pyrtl.rtllib.adders.dada_reducer(wire_array_2, result_bitwidth, final_adder=<function kogge_stone>)

The reduction and final adding part of a dada tree. Useful for adding many numbers together The use of single bitwidth wires is to allow for additional flexibility

Parameters:
  • wire_array_2 ([[Wirevector]]) – An array of arrays of single bitwidth wirevectors
  • result_bitwidth (int) – The bitwidth you want for the resulting wire. Used to eliminate unnessary wires.
  • final_adder – The adder used for the final addition
Returns:

wirevector of length result_wirevector

pyrtl.rtllib.adders.fast_group_adder(wires_to_add, reducer=<function wallace_reducer>, final_adder=<function kogge_stone>)

A generalization of the carry save adder, this is designed to add many numbers together in a both area and time efficient manner. Uses a tree reducer to achieve this performance

Parameters:
  • wires_to_add ([WireVector]) – an array of wirevectors to add
  • reducer – the tree reducer to use
  • final_adder – The two value adder to use at the end
Returns:

a wirevector with the result of the addition The length of the result is: max(len(w) for w in wires_to_add) + ceil(len(wires_to_add))

Back to top of page

AES-128

A class for building a PyRTL AES circuit.

Currently this class only supports 128 bit AES encryption/decryption

Example:

aes = AES()
plaintext = pyrtl.Input(bitwidth=128, name='aes_plaintext')
key = pyrtl.Input(bitwidth=128, name='aes_key')
aes_ciphertext = pyrtl.Output(bitwidth=128, name='aes_ciphertext')
reset = pyrtl.Input(1)
ready = pyrtl.Output(1, name='ready')
ready_out, aes_cipher = aes.encryption_statem(plaintext, key, reset)
ready <<= ready_out
aes_ciphertext <<= aes_cipher
sim_trace = pyrtl.SimulationTrace()
sim = pyrtl.Simulation(tracer=sim_trace)
sim.step ({
    aes_plaintext: 0x00112233445566778899aabbccddeeff,
    aes_key: 0x000102030405060708090a0b0c0d0e0f,
    reset: 1
})
for cycle in range(1,10):
    sim.step ({
        aes_plaintext: 0x00112233445566778899aabbccddeeff,
        aes_key: 0x000102030405060708090a0b0c0d0e0f,
        reset: 0
    })
sim_trace.render_trace(symbol_len=40, segment_size=1)
class pyrtl.rtllib.aes.AES

Bases: :class:`object`

__init__()

x.__init__(…) initializes x; see help(type(x)) for signature

encryption(plaintext, key)

Builds a single cycle AES Encryption circuit

Parameters:
Returns:

a WireVector containing the ciphertext

encrypt_state_m(plaintext_in, key_in, reset)

Builds a multiple cycle AES Encryption state machine circuit

Parameters:reset – a one bit signal telling the state machine to reset and accept the current plaintext and key
Return ready, cipher_text:
 ready is a one bit signal showing that the encryption result (cipher_text) has been calculated.
decryption(ciphertext, key)

Builds a single cycle AES Decryption circuit

Parameters:
  • ciphertext (WireVector) – data to decrypt
  • key (WireVector) – AES key to use to encrypt (AES is symmetric)
Returns:

a WireVector containing the plaintext

decryption_statem(ciphertext_in, key_in, reset)

Builds a multiple cycle AES Decryption state machine circuit

Parameters:reset – a one bit signal telling the state machine to reset and accept the current plaintext and key
Return ready, plain_text:
 ready is a one bit signal showing that the decryption result (plain_text) has been calculated.

Back to top of page

Barrel

pyrtl.rtllib.barrel.barrel_shifter(bits_to_shift, bit_in, direction, shift_dist, wrap_around=0)

Create a barrel shifter that operates on data based on the wire width.

Parameters:
  • bits_to_shift – the input wire
  • bit_in – the 1-bit wire giving the value to shift in
  • direction – a one bit WireVector representing shift direction (0 = shift down, 1 = shift up)
  • shift_dist – WireVector representing offset to shift
  • wrap_around**currently not implemented**
Returns:

shifted WireVector

Back to top of page

Library Utilities

pyrtl.rtllib.libutils.match_bitwidth(*args)

Matches the bitwidth of all of the input arguments.

Parameters:args (WireVector) – input arguments
Returns:tuple of args in order with extended bits
pyrtl.rtllib.libutils.partition_wire(wire, partition_size)
pyrtl.rtllib.libutils.str_to_int_array(string, base=16)

Converts a string to an array of integer values according to the base specified (int numbers must be whitespace delimited).

Example: “13 a3 3c” => [0x13, 0xa3, 0x3c]

Returns:[int]
pyrtl.rtllib.libutils.twos_comp_repr(val, bitwidth)

Converts a value to it’s two’s-complement (positive) integer representation using a given bitwidth (only converts the value if it is negative). For use with Simulation.step() etc. in passing negative numbers, which it does not accept

pyrtl.rtllib.libutils.rev_twos_comp_repr(val, bitwidth)

Takes a two’s-complement represented value and converts it to a signed integer based on the provided bitwidth. For use with Simulation.inspect() etc. when expecting negative numbers, which it does not recognize

Back to top of page

Multipliers

Multipliers contains various PyRTL sample multipliers for people to use

pyrtl.rtllib.multipliers.simple_mult(A, B, start)

Builds a slow, small multiplier using the simple shift-and-add algorithm. Requires very small area (it uses only a single adder), but has long delay (worst case is len(A) cycles). start is a one-bit input to indicate inputs are ready. done is a one-bit output signal raised when the multiplication is finished.

Parameters:A, B (WireVector) – two input wires for the multiplication
Returns:Register containing the product; the “done” signal
pyrtl.rtllib.multipliers.complex_mult(A, B, shifts, start)

Generate shift-and-add multiplier that can shift and add multiple bits per clock cycle. Uses substantially more space than simple_mult() but is much faster.

Parameters:
  • A, B (WireVector) – two input wires for the multiplication
  • shifts (int) – number of spaces Register is to be shifted per clk cycle (cannot be greater than the length of A or B)
  • start (bool) – start signal
Returns:

Register containing the product; the “done” signal

pyrtl.rtllib.multipliers.tree_multiplier(A, B, reducer=<function wallace_reducer>, adder_func=<function kogge_stone>)

Build an fast unclocked multiplier for inputs A and B using a Wallace or Dada Tree.

Parameters:
  • A, B (WireVector) – two input wires for the multiplication
  • reducer (function) – Reduce the tree using either a Dada recuder or a Wallace reducer determines whether it is a Wallace tree multiplier or a Dada tree multiplier
  • adder_func (function) – an adder function that will be used to do the last addition
Return WireVector:
 

The multiplied result

Delay is order logN, while area is order N^2.

pyrtl.rtllib.multipliers.signed_tree_multiplier(A, B, reducer=<function wallace_reducer>, adder_func=<function kogge_stone>)

Same as tree_multiplier, but uses two’s-complement signed integers

pyrtl.rtllib.multipliers.fused_multiply_adder(mult_A, mult_B, add, signed=False, reducer=<function wallace_reducer>, adder_func=<function kogge_stone>)

Generate efficient hardware for a*b+c.

Multiplies two wirevectors together and adds a third wirevector to the multiplication result, all in one step. By doing it this way (instead of separately), one reduces both the area and the timing delay of the circuit.

Parameters:
  • signed (Bool) – Currently not supported (will be added in the future) The default will likely be changed to True, so if you want the smallest set of wires in the future, specify this as False
  • reducer – (advanced) The tree reducer to use
  • adder_func – (advanced) The adder to use to add the two results at the end
Return WireVector:
 

The result WireVector

pyrtl.rtllib.multipliers.generalized_fma(mult_pairs, add_wires, signed=False, reducer=<function wallace_reducer>, adder_func=<function kogge_stone>)

Generated an opimitized fused multiply adder.

A generalized FMA unit that multiplies each pair of numbers in mult_pairs, then adds the resulting numbers and and the values of the add wires all together to form an answer. This is faster than separate adders and multipliers because you avoid unnecessary adder structures for intermediate representations.

Parameters:
  • mult_pairs – Either None (if there are no pairs to multiply) or a list of pairs of wires to multiply: [(mult1_1, mult1_2), …]
  • add_wires – Either None (if there are no individual items to add other than the mult_pairs), or a list of wires for adding on top of the result of the pair multiplication.
  • signed (Bool) – Currently not supported (will be added in the future) The default will likely be changed to True, so if you want the smallest set of wires in the future, specify this as False
  • reducer – (advanced) The tree reducer to use
  • adder_func – (advanced) The adder to use to add the two results at the end
Return WireVector:
 

The result WireVector

Back to top of page

Muxes

pyrtl.rtllib.muxes.prioritized_mux(selects, vals)

Returns the value in the first wire for which its select bit is 1

Parameters:
  • selects ([WireVector]) – a list of WireVectors signaling whether a wire should be chosen
  • vals ([WireVector]) – values to return when the corresponding select value is 1
Returns:

WireVector

If none of the items are high, the last val is returned

pyrtl.rtllib.muxes.sparse_mux(sel, vals)

Mux that avoids instantiating unnecessary mux_2s when possible.

Parameters:
  • sel (WireVector) – Select wire, determines what is selected on a given cycle
  • vals (dictionary) – dictionary of values at mux inputs (of type {int:WireVector})
Returns:

WireVector that signifies the change

This mux supports not having a full specification. Indices that are not specified are treated as don’t-cares

It also supports a specified default value, SparseDefault

class pyrtl.rtllib.muxes.MultiSelector(signal_wire, *dest_wires)

Bases: :class:`object`

The MultiSelector allows you to specify multiple wire value results for a single select wire.

Useful for processors, finite state machines and other places where the result of many wire values are determined by a common wire signal (such as a ‘state’ wire).

Example:

with muxes.MultiSelector(select, res0, res1, res2, …) as ms:
ms.option(val1, data0, data1, data2, …) ms.option(val2, data0_2, data1_2, data2_2, …)

This means that when the select wire equals the val1 wire the results will have the values in the coresponding data wires (all ints are converted to wires)

__init__(signal_wire, *dest_wires)

x.__init__(…) initializes x; see help(type(x)) for signature

__enter__()
For compatibility with with statements, which is the recommended
method of using a MultiSelector
option(select_val, *data_signals)
default(*data_signals)
finalize()

Connects the wires.

pyrtl.rtllib.muxes.demux(select)

Demultiplexes a wire of arbitrary bitwidth

Parameters:select (WireVector) – indicates which wire to set on
Return (WireVector, …):
 a tuple of wires corresponding to each demultiplexed wire

Back to top of page

Testing Utilities

pyrtl.rtllib.testingutils.calcuate_max_and_min_bitwidths(max_bitwidth=None, exact_bitwidth=None)
pyrtl.rtllib.testingutils.inverse_power_dist(bitwidth)
pyrtl.rtllib.testingutils.uniform_dist(bitwidth)
pyrtl.rtllib.testingutils.make_inputs_and_values(num_wires, max_bitwidth=None, exact_bitwidth=None, dist=<function uniform_dist>, test_vals=20)

Generates multiple input wires and sets of test values for testing purposes

Parameters:dist (function) – function to generate the random values
Returns:wires; list of values for the wires

The list of values is a list of lists. the interior lists represent the values of a single wire for all of the simulation cycles

pyrtl.rtllib.testingutils.an_input_and_vals(bitwidth, test_vals=20, name='', random_dist=<function uniform_dist>)

Generates an input wire and a set of test values for testing purposes

Parameters:
  • bitwidth – The bitwidth of the value to be generated
  • test_vals (int) – number of values to generate per wire
  • name – name for the input wire to be generated
Returns:

tuple consisting of input_wire, test_values

pyrtl.rtllib.testingutils.generate_in_wire_and_values(bitwidth, test_vals=20, name='', random_dist=<function uniform_dist>)

Generates an input wire and a set of test values for testing purposes

Parameters:
  • bitwidth – The bitwidth of the value to be generated
  • test_vals (int) – number of values to generate per wire
  • name – name for the input wire to be generated
Returns:

tuple consisting of input_wire, test_values

pyrtl.rtllib.testingutils.make_consts(num_wires, max_bitwidth=None, exact_bitwidth=None, random_dist=<function inverse_power_dist>)
Returns:[Const_wires]; [Const_vals]
pyrtl.rtllib.testingutils.sim_and_ret_out(outwire, inwires, invals)

Simulates the net using inwires and invalues, and returns the output array. Used for rapid test development.

Parameters:
  • outwire – The wire to return the output of
  • inwires – a list of wires to read in from ([Input, …])
  • invals – a list of input value lists ([ [int, …], …])
Returns:

a list of values from the output wire simulation result

pyrtl.rtllib.testingutils.sim_and_ret_outws(inwires, invals)

Simulates the net using inwires and invalues, and returns the output array. Used for rapid test development.

Parameters:
  • inwires – a list of wires to read in from ([Input, …])
  • invals – a list of input value lists ([[int, …], …])
Returns:

a list of values from the output wire simulation result

pyrtl.rtllib.testingutils.sim_multicycle(in_dict, hold_dict, hold_cycles, sim=None)

Simulation of a circuit that takes multiple cycles to complete.

Parameters:
  • in_dict
  • hold_dict
  • hold_cycles
  • sim
Returns:

pyrtl.rtllib.testingutils.multi_sim_multicycle(in_dict, hold_dict, hold_cycles, sim=None)

Simulates a circuit that takes multiple cycles to complete multiple times.

Parameters:
  • in_dict – {in_wire: [in_values, …], …}
  • hold_dict – {hold_wire: hold_value} The hold values for the
  • hold_cycles
  • sim
Returns:

Back to top of page