A testbench is reusable when a new test, a new bus width or a new checker means adding a file, not editing five. This topic covers the five patterns that make that true. Each one removes a specific kind of coupling between the parts of an environment.
Every lesson has a runnable, self-checking bench and names the change that makes it fail. The capstone of this part builds its environment from the policy and abstract-BFM patterns shown here.
WHAT EACH PATTERN DECOUPLES
test ──────────► stimulus rules policy classes (rules are objects, not subclasses)
env ──────────► pin-level details abstract BFM (env holds a class handle, not a vif)
env ──────────► bus parameters parameterized vifs (widths live in one typedef)
env ──────────► checker classes interface classes (registry knows contracts only)
test ──────────► protocol beats layered stimulus (scenario -> transaction -> beat)Lesson | What it covers |
|---|---|
Constraints as reusable objects instead of a subclass per combination; runtime policy lists and compile-time policy layers. | |
An abstract class API with the concrete BFM inside the interface, so the environment never sees a virtual interface or a width. | |
Why virtual bus_if #(W) spreads through an environment, and how typedefs, config objects and width guards contain it. | |
Contracts with interface class and implements for plug-in checkers and callbacks, including multiple API inheritance. | |
Scenario, transaction and beat layers joined by bounded mailboxes, with back-pressure flowing up and a monitor that rebuilds bursts. |
Parameterized Interfaces keeps the vif but makes the width a parameter that every class touching the vif carries. Abstract BFM hides the vif behind an abstract class, so the environment carries no parameter at all. The first is simpler for one width change; the second scales when many widths or variants coexist.