Peeker Groups

Peeker objects are normally stored in a global list, but sometimes you might want to create a group of Peekers for a set of signals. This is easily done using the PeekerGroup class. Once again, I'll use the hierarchical adder example to illustrate the use of PeekerGroups.


In [12]:
from myhdl import *
from myhdlpeek import PeekerGroup

def adder_bit(a, b, c_in, sum_, c_out):
    '''Single bit adder.'''
    @always_comb
    def adder_logic():
        sum_.next = a ^ b ^ c_in
        c_out.next = (a & b) | (a & c_in) | (b & c_in)
    
    # Add some global peekers to monitor the inputs and outputs.
    Peeker(a, 'a')
    Peeker(b, 'b')
    Peeker(c_in, 'c_in')
    Peeker(sum_, 'sum')
    Peeker(c_out, 'c_out')
    return adder_logic

def adder(a, b, sum_):
    '''Connect single-bit adders to create a complete adder.'''
    c = [Signal(bool(0)) for _ in range(len(a)+1)] # Carry signals between stages.
    s = [Signal(bool(0)) for _ in range(len(a))] # Sum bit for each stage.
    stages = []  # Storage for adder bit instances.
    # Create the adder bits and connect them together.
    for i in range(len(a)):
        stages.append( adder_bit(a=a(i), b=b(i), sum_=s[i], c_in=c[i], c_out=c[i+1]) )
    # Concatenate the sum bits and send them out on the sum_ output.
    @always_comb
    def make_sum():
        sum_.next = ConcatSignal(*reversed(s))
    return instances()  # Return all the adder stage instances.

# Create signals for interfacing to the adder.
a, b, sum_ = [Signal(intbv(0,0,8)) for _ in range(3)]

# Clear-out any existing peeker stuff before instantiating the adder.
Peeker.clear()

# Instantiate the adder.
add_1 = adder(a=a, b=b, sum_=sum_)

# Create a group of peekers to monitor the top-level buses.
# Each argument to PeekerGroup assigns a signal to a name for a peeker.
top_pkr = PeekerGroup(a_bus=a, b_bus=b, sum_bus=sum_)

# Create a testbench generator that applies random inputs to the adder.
from random import randrange
def test():
    for _ in range(8):
        a.next, b.next = randrange(0, a.max), randrange(0, a.max)
        yield delay(1)

# Simulate the adder, testbench and peekers.
Simulation(add_1, test(), *Peeker.instances()).run()

# Display only the peekers for the top-level buses.
# The global peekers in the adder bits won't show up.
top_pkr.to_wavedrom('a_bus b_bus sum_bus')
top_pkr.to_html_table('a_bus b_bus sum_bus')


<class 'myhdl.StopSimulation'>: No more events
Time a_bus b_bus sum_bus
0 1 7 0
1 7 7 6
2 3 3 6
3 2 6 0
4 0 7 7
5 7 4 3
6 4 1 5
7 7 2 1