Skip to content

Introduction

Most testbenches require two types of component to operate:

  • Drivers stimulate interfaces on the design according to the implementation's signalling protocols. They convert transactions from the representation used by the testbench into the state of the different signals on the boundary of the design.

  • Monitors act in the opposite way to drivers, monitoring the signals wiggling on the boundary of the design and capturing those into transactions that the testbench analyses.

Different interfaces will require custom drivers and monitors, but there is a common core of shared functionality - this is why Forastero provides two base classes BaseDriver and BaseMonitor.

Events

The Component class inherits from the EventEmitter class, which supports the publishing of and subscription to events. This mechanism can be used to drive models, co-ordinate stimulus, or generally observe the state of monitors and drivers.

The documentation for Drivers and Monitors will go further into how these mechanisms can be used.

Logging

Both BaseDriver and BaseMonitor inherit from Component, and this root class provides a number of utility features. One of the most useful is a hierarchical log specific to the driver or monitor.

  • All drivers will be given a logging context of tb.driver.<NAME>;
  • All monitors will be given a logging context of tb.monitor.<NAME>.

These logs can be accessed using self.log, for example:

tb/stream/monitor.py
class StreamMonitor(BaseMonitor):
    async def monitor(self, capture) -> None:
        while True:
            await RisingEdge(self.clk)
            if self.rst.value == 1:
                continue
            if self.io.get("valid", 1) and self.io.get("ready", 1):
                self.log.debug("Hello! I saw a transaction!")
                capture(StreamTransaction(data=self.io.get("data", 0)))

In the simulation log, you will see the logging context appear along with the timestamp, verbosity, and log message - for example:

1229.00ns INFO  tb.driver.driver_a    Starting to send transaction
1230.00ns INFO  tb.driver.driver_b    Finished sending a transaction
1231.00ns INFO  tb.monitor.monitor_a  Hello! I saw a transaction!

More details on logging can be found here.


forastero.component.Component

Bases: EventEmitter

Base component type for working with BaseIO interfaces, can be extended to form drivers, monitors, and other signalling protocol aware components.

Parameters:

Name Type Description Default
tb Any

Handle to the testbench

required
io BaseIO

Handle to the BaseIO interface

required
clk ModifiableObject

Clock signal to use when driving/sampling the interface

required
rst ModifiableObject

Reset signal to use when driving/sampling the interface

required
random Random | None

Random number generator to use (optional)

None
name str | None

Unique name for this component instance (optional)

None
blocking bool

Whether this component should block shutdown (default: True)

True

busy property

Determine if the component is currently busy

idle() async

Blocks until the component is no longer busy

lock() async

Lock the component's internal lock

release()

Release the component's internal lock

seed(random)

Set up the random seed (used by testbench when registering a component)

Parameters:

Name Type Description Default
random Random

The random instance to seed from

required

forastero.event.EventEmitter

Core support for publishing events and subscribing to them

publish(event, obj)

Publish an event and deliver it to any registered subscribers.

Parameters:

Name Type Description Default
event Enum

Enumerated event

required
obj Any

Object associated to the event

required

subscribe(event, callback)

Subscribe to an event being published by this component.

Parameters:

Name Type Description Default
event Enum

Enumerated event

required
callback Callable

Method to call when the event occurs, this must accept arguments of component, event type, and an associated object

required

subscribe_all(callback)

Subscribe to all events published by this component.

Parameters:

Name Type Description Default
callback Callable

Method to call when the event occurs, this must accept arguments of component, event type, and an associated object

required

unsubscribe_all(event=None)

De-register all subscribers for a given event (when event is not None), or all subscribers from all events (when event is None).

Parameters:

Name Type Description Default
event Enum | None

Optional enumerated event to unsubscribe, or None to unsubscribe all subscribers for all events

None

wait_for(event) async

Wait for a specific enumerated event to occur and return the data that was associated to it.

Parameters:

Name Type Description Default
event Enum

Enumerated event trigger

required

Returns:

Type Description
Any

Data associated with the event