Introduction to
2
Agenda
Introduction
Methodology Introduction
Getting Started
Testbench Environment
Language Basics
OOP Basics
Randomization
Controlling Threads
Virtual Interfaces
Functional Coverage
Coverage Driven Verification
3
By the end of this class, you should be able to:
Lecture Objectives
Develop self checking testbenches using VCS and
SystemVerilog
How to connect your Design to a SV testbench
How to perform random constrained testing
How to take advantage of powerful concurrency
How to implement Functional Coverage
Look for coding tips!
4
Based on IEEE P1800-2005 Standard
Detailed in Language Reference Manual Verification-specific language features Constrained random stimulus generation Functional coverage
SystemVerilog Assertions (SVA)
SystemVerilog for Verification
5
Agenda
Introduction
Methodology Introduction
Getting Started
Testbench Environment
Language Basics
OOP Basics
Randomization
Controlling Threads
Virtual Interfaces
Functional Coverage
Coverage Driven Verification
6
Verification Environment
DefinitionsDUT
Driver
Monitor
Supplies data
to the DUT
Observes
data
from DUT
Assertions
Transactor
Executes
transactions
Identifies
transactions
Checker
Checks
correctness
Creates
stimulus
Test
Scoreboard
Verification
Environment
Testbench
7
Methodology Introduction
To maximize design quality
Provides guidance:
Find bugs fast!
Identify the best practices
Make the most of Synopsys tools
Methodology
One verification environment, many tests
Minimize test-specific code
Reuse
Across tests Across blocks Across systems Across projects
8
Methodology Introduction
Testbench Design
Start with a fully randomizable testbench
Run many randomized simulation runs
Analyze cumulative coverage and coverage holes Then with minimal code changes:
Add constrained stimulus to fill coverage holes Finally:
9
Coverage-Driven Verification
Time
%
C
ov
er
age
GoalDirected
Methodology
Measure progress using functional coverage
Self-checking
random environment
development time
Coverage-Driven
Methodology
Productivity
gain
With
VIP
10
Key Benefits: Testbench Environment
Environment Creation takes less time
Testbench is easy constrain from the top level file
All Legal Device Configurations are tested
Regression can select different DUT configurations Configuration object is randomized and constrained
11
Agenda
Introduction
Methodology Introduction
Getting Started
Testbench Environment
Language Basics
OOP Basics
Randomization
Controlling Threads
Virtual Interfaces
Functional Coverage
Coverage Driven Verification
12
What are We Going to Discuss?
Getting Started
SystemVerilog Testbench Verification Flow
Compiling and Running in VCS
13
Compile:
vcs -sverilog –debug top.sv test.sv dut.sv -sverilog Enable SystemVerilog constructs -debug Enable debug except line stepping -debug_all Enable debug including line stepping
Run:
simv +user_tb_runtime_options -l logfile Create log file
-gui Run GUI
-ucli Run with new command line debugger -i cmd.key Execute UCLI commands
Getting Started
Compiling and Running with VCS
14
SystemVerilog has dozens of new reserved keywords such as
bit
,
packed,
logicthat might conflict with existing Verilog code
Keep your Verilog-2001 code separate from SystemVerilog
code and compile with:
vcs –sverilog new.v
+verilog2001ext+.v2k
old.
v2k
or
vcs
+systemverilogext+.sv
old.v new.
sv
Getting Started
Legacy Code Issues
// Old Verilog-1995/2001 legacy code integer
bit
, count;initial begin count = 0;
for (bit = 0; bit < 8; bit = bit + 1) if (adrs[bit] === 1'bx)
15
Debug: Getting Started
Invoke DVE
> simv –gui -tbugSource code tracing Local variables Active threads
16
Getting Started
SystemVerilog documentation
Examples
$VCS_HOME/doc/examples
Email Support:
[email protected]
On-line knowledge database
http://solvnet.synopsys.com
Testbench Discussion Forum
http://verificationguild.com
SystemVerilog LRM
www.Accellera.org or www.eda.org/sv
Documentation and Support
17
Agenda
Introduction
Methodology Introduction
Getting Started
Testbench Environment
Language Basics
OOP Basics
Randomization
Controlling Threads
Virtual Interfaces
Functional Coverage
Coverage Driven Verification
18
Testbench Environment
Someone gives you a DUT, now what?
How Should You Connect to DUT
reset
request[1:0] grant[1:0] clock
19
Testbench Environment
top.sv
clock
test.sv
arb.sv
1.
Create DUT interface with
modports and clocking
blocks
2.
Create testbench program
3.
Create top module
4.
Compile and run
20
Testbench Environment -- Interfaces
Introduction
The complexity of communication between
blocks requires a new design entity
Top level net-lists are too verbose and error prone
An interface encapsulates this communication
Connectivity (signals)
Directional information (modports)
Timing (clocking blocks)
Functionality (routines, assertions, initial/always blocks)
An interface can be:
Connected at compile-time (default)
Connected at run-time – virtual interfaces
An interface can not:
21
top
Testbench Environment -- Interfaces
Before Interfaces
The RTL code was connect with a netlist
cpu
module mem (
input bit req, bit clk, bit start,
wire [1:0] mode, wire [7:0] addr, inout wire [7:0] data, output bit gnt, bit rdy); … mem module cpu ( input bit clk, bit gnt, bit rdy,
inout wire [7:0] data, output bit req,
bit start,
wire [1:0] mode, wire [7:0] addr); …
module top;
logic req, gnt, start, rdy; bit clk;
always #10 clk = !clk; logic [1:0] mode;
logic [7:0] addr; wire [7:0] data;
mem m1(req, clk, start, mode, addr, data, gnt, rdy); cpu c1(clk, gnt, rdy, data, req, start, mode, addr); endmodule
22
simple_bus clk
top
Testbench Environment -- Interfaces
Named Bundle of Signals
cpu interface simple_bus; logic req, gnt; logic [7:0] addr; wire [7:0] data; logic [1:0] mode; logic start, rdy; endinterface mem module mem( simple_bus sb, input bit clk); … endmodule module top; logic clk = 0; always #10 clk = !clk; simple_bus sb(); mem m1(sb, clk); cpu c1(sb, clk); module cpu( simple_bus sb, input bit clk); … endmodule
23
Testbench Environment -- Interfaces
Referencing Signals in Interface
Use hierarchical names for interface signals in a module
Signals with multiple drivers must be wire
Signals driven by procedural assignment must be logic
interface simple_bus; logic req, gnt;
logic [7:0] addr; wire [7:0] data; logic [1:0] mode; logic start, rdy;
endinterface: simple_bus
module cpu(simple_bus sb, input bit clk); logic addr_reg; always @(posedge clk) sb.addr <= addr_reg; endmodule : cpu Label on end statement
24
Testbench Environment -- Interfaces
Dividing an Interface
Not every device has the same access to an interface
Restrict signal access & direction with
modport
interface simple_bus; logic req, gnt;
logic [7:0] addr; wire [7:0] data; logic [1:0] mode; logic start, rdy;
modport SLAVE (input addr, gnt, mode, start, output req, rdy,
inout data);
modport MASTER (output addr, gnt, start, mode, input req, rdy,
inout data); endinterface: simple_bus
module cpu(simple_bus.MASTER sb, input bit clk);
…
module mem(simple_bus.SLAVE sb, input bit clk);
25
Testbench Environment -- Interfaces
Adding Timing
An interface can use a clocking block to control timing
Directions are relative to program block
interface arb_if (input bit clk);logic [1:0] grant, request; logic reset;
clocking cb @(posedge clk);
input grant; // TB input output request; // TB output endclocking
modport DUT (input clk,
input request, reset, // Design under test output grant);
modport TB (clocking cb, // Synch signals output reset); // Async signals endinterface: arb_if
Step 1
reset request[1:0] grant[1:0] clockarb.sv
26
Testbench Environment -- Interfaces
Use in the interface, just for testbench
Benefits
:
Creates explicit synchronous timing domains
Provides race-free operation if input skew > 0
Your testbench will always drive the signals at the right time!
Functionality:
An interface can contain multiple clocking blocks
There is one clock per clocking block.
Default is “default input #1step output #0;”
“1step” specifies that the values are sampled immediately
upon entering this time slot in Prepone region, before any
design activity
27
SystemVerilog Scheduling
Each time slot is divided into 5 major regions (plus PLI)
Prepone Sample signals before any changes (#1step)
Active Design simulation (module), including NBA
Observed Assertions evaluated after design executes
Reactive Testbench activity (program)
Postpone Read only phaseSystemVerilog Scheduling Details
clock
data
REGION
ACTIVITY Next PreviousPrepone Active Observed Reactive Postpone
design
sample assertions testbench $monitor
Current
Assertion and testbench events can trigger more design evaluations in this time slot
28
Testbench Environment - Program Block
Benefits:
Encapsulates the testbench
Separates the testbench from the DUT
Provides an entry point for execution
Creates a scope to encapsulate program-wide data
Functionality:
Can be instantiated in any hierarchical location
Typically at the top level
Interfaces and ports can be connected in the same
manner as any other module
Leaf node, can not contain any hierarchy, just classes
Code goes in initial blocks & routines, no always blocks
Executes in the Reactive region
29
Testbench Environment – Program
Create testbench program: test.sv
program test(arb_if.TB arbif); initial begin
// Asynch drive reset arbif.reset <= 0; #15ns arbif.reset <= 1; #35ns arbif.reset <= 0;
// Synch drive request
##1 arbif.cb.request <= 1; ##1 arbif.cb.request <= 0; wait (arbif.cb.grant == 1); end
endprogram
interface arb_if (input bit clk); logic grant, request, reset; clocking cb @(posedge clk); input grant; output request; endclocking modport TB (clocking cb, output reset); endinterface: arb_if
Step 2
Wait 1 clock cycle
Common mistake: forgetting “cb.” in signal reference
Error: arbif.request not visible via modport
clk reset request
30
Using the Clocking Block
Clocking Block signals are referenced by
pre-pending the clocking block name to the signal:
Assignment will happen at next active clock edge
Time will NOT advance unless you use #1 or ##1
Synchronous Signal Access
interface arb_if (input bit clk); logic grant, request, reset; clocking cb @(posedge clk);
input grant; output request; endclocking
modport TB (clocking cb, output reset);
arbif.cb.request <= 1; // drive value = arbif.cb.grant; // sample
31
Driving, Sampling, Synchronizing
Synchronize to active clock edge specified in clocking block
Synchronize to any edge of signal
Wait for N clock cycles with ##n – blocking statement
Signal Synchronization
@arbif.cb; // continue on posedge of arb_if clk repeat (3) @arbif.cb; // Wait for 3 posedges
@arbif.cb.grant; // continue on any edge of grant @(posedge arbif.cb.grant); // continue on posedge
@(negedge arbif.cb.grant); // continue on negedge wait (arbif.cb.grant==1); // wait for expression
// no delay if already true
##2 arbif.cb.request <= 0; // Wait 2 cycles // then assign
32
Testbench Timing
When you are using interfaces with a clocking block:
There is a 1-cycle delay from DUT output to testbench input “Virtual synchronizer” added to TB input
No delay from testbench output to DUT input default input #1step output #0;”SystemVerilog Testbench in Simulation
clock
Sample inputs before clock Drive outputs at clockDesign
Testbench
33
Testbench Environment – Top Block
Create top module
// Synchronous TB
program test(arb_if.TB arbif); … endprogram module top; bit clk; test t1 (.*); arb d1 (.*); arb_if arbif(.*); always #50 clk = !clk; endmodule
module arb(arb_if.DUT arbif, bit clk);
// Some logic here… endmodule
Step 3
interface arb_if (input bit clk); …
endinterface: arb_if The syntax .* connect ports
34
Testbench Environment - Scoping
Scoping Rules
`timescale 1ns/1ns
typedef enum {IDLE, RUN, WAIT} fsm_state_t; parameter TIMEOUT = 1_000_000;
SystemVerilog defines a global scope,
$root
,
outside any module or program
Define global items such as shared enums
Use parameters for global constants, not macros
module state_machine(…);
fsm_state_t state, next_state; endmodule
program test;
fsm_state_t state;
initial #TIMEOUT $finish;
root.sv
dut.sv
35
Testbench Environment -- Communication
DUT visibility
The program block can see all signals & routines in
the design
A module can not see anything in program block
Use absolute hierarchical path to access DUT
Start with $root, then top-level instance name, DUT, etc.
Use care when calling DUT routines from program
Good practice is to use a function to get info
Don’t try to trigger DUT code
SV accesses ports & XMR signals immediately
(asynchronously)
dstate = top.dut.state; // Immediate XMR sample dstate = $root.top.dut.state; // Absolute path
36
SV Language Basics
Check signal values
program test (arb_if arbif); initial begin
arbif.cb.request <= 1; repeat (2) @arbif.cb;
a1: assert (arbif.cb.grant==1); end
SystemVerilog Assertion
Check a SVA procedurally
Non-blocking statement
“test.sv", 7: top.t1.a1: started at 55ns failed at 55ns Offending '(arbif.cb.grant == 1)‘
37
SV Language Basics
Check signal values
program test (arb_if arbif); initial begin
arbif.cb.request <= 1; repeat (2) @arbif.cb;
a1: assert (arbif.cb.grant==1) success++;
else
$error(“No grant received”); end
Optional then & else clauses for success / failure
If SVA failure and no else-clause, a generic error is printed
Use $info, $warn, $error, and $failure for reporting
These are only valid in SVA’s (IEEE-1800)
Custom message
38
> vcs -sverilog -debug
root.sv top.sv arb_if.sv test.sv arb.sv > simv –gui -tbug
Testbench Environment – Compile and Run
Compile and run
Run with debugger
39
Agenda
Introduction
Methodology Introduction
Getting Started
Testbench Environment
Language Basics
OOP Basics
Randomization
Controlling Threads
Virtual Interfaces
Functional Coverage
Coverage Driven Verification
40
SV Language Basics
SystemVerilog basics
Data types Arrays Subroutines Interfaces
This class assumes you already know most Verilog-1995
and 2001 constructs
41
Basic SystemVerilog Data Types
reg [31:0] r; // 4-state logic [7:0] w; // 4-state
Explicit 2-state variables give better performance, but they will not propagate X or Z, so keep away from DUT
assert(!$isunknown(ifc.cb.data));
SystemVerilog Data Types
In SystemVerilog, the old reg type has been extended so it can be driven by single drivers (gates, modules, continuous assignments) like a wire. It has a new name logic. It can not have multiple drivers – use a wire.
bit [31:0] b; // 2-state bit 0 or 1 integer i; // 4-state, 32-bits, signed Verilog-1995 int i; // 2-state, 32-bit signed integer
byte b8; // 2-state, 8-bit signed integer shortint s; // 2-state, 16-bit signed integer longint l; // 2-state, 64-bit signed integer
42
SV Language Basics
User defined types
Use typedef to create a synonym for another type
Define a structure with multiple variables
Use union for merged storage
SystemVerilog Data Types
typedef bit [31:0] uint;
typedef bit [0:5] bsix_t; // Define new type
bsix_t my_var; // Create 6-bit variable
typedef union {int i; shortreal f; } num_t; num_t un;
un.f = 0.0; // set n in floating point format typedef struct {bit [7:0] opcode;
bit [23:0] addr; }
instruction; // named structure type instruction IR; // define variable
Use classes instead!
Useful type
43
SV Language Basics
Enumerated type
Explicitly typed and scoped (program or class-level)
Can only create variables at class level, not typedef Allows compile time error checking
SystemVerilog Data Types
// Declare single enum variable enum {RED, BLUE, GREEN} color;
// declare data type
typedef enum {INIT, DECODE, IDLE} fsmstate_t;
fsmstate_t pstate, nstate; // declare variables int i = 1;
case (pstate)
IDLE: nstate = INIT; // data assignment INIT: nstate = DECODE;
default: nstate = IDLE; endcase
$display(“Next state is %0s”, nstate.name);
nstate = fsmstate_t’(i); // cast integer to enum
Print the symbolic
44
SV Language Basics
Fast, static size
Multiple dimensions supported Out-of-bounds write ignored
Out-of-bounds read returns X, even for 2-state Array data stored in 32-bit words
Fixed Size Arrays
int twoD1[0:7][0:23]; // 2D array
int twoD2[8][24]; // same as above twoD1 = twoD2; // Array copy if (twoD1==twoD2)… // Array compare
bytes[1] bytes[2] bytes[0] 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 7 6 5 4 3 2 1 0 0 1 2 3 4 5 6 7 7 6 5 4 3 2 1 0
type name [constant];
bytes[0][3] bytes[0][1][6]
Use bit & word subs together with fixed arrays
45
SV Language Basics
Fast, variable sized with call to new()
Similar to a fixed size array, but size given at run time
Single dimension only, never packed
Out-of-bounds access causes run-time errorDynamic Arrays
int d[], b[]; // Two dynamic arrays
d = new[5]; // Make array with 5 elements foreach (d[j]) // Initialize
d[j] = j;
b = d; // Copy a dynamic array b[0] = 5;
$display(d[0],b[0]); // See both values (0 & 5) d = new[20](d); // Expand and copy
d = new[100]; // Allocate 100 new integers // Old values are lost
d.delete(); // Delete all elements
type name [ ];
46
SV Language Basics
Flexible – size can easily change
Variable size array with automatic sizing, single dimension
Many searching, sorting, and insertion methods (see LRM)
Constant time to read, write, and insert at front & back
Out of bounds access causes run-time error
Queues
int q[$] = {0,1,3,6}; int j = 2, b[$] = {4,5};
q.insert(2, j); // {0,1,2,3,6} Insert before s[2] q.insert(4, b); // {0,1,2,3,4,5,6} Insert whole queue q.delete(1); // {0,2,3,4,5,6} Delete element #1 q.push_front(7); // {7,0,2,3,4,5,6} Insert at front j = q.pop_back(); // {7,0,2,3,4,5} j = 6
q.push_back(8); // {7,0,2,3,4,5,8} Insert at back j = q.pop_front(); // {0,2,3,4,5,8} j = 7
$display(q.size); // “6”
foreach (q[i]) $display(q[i]);
type name [$];
F
AST
47
Checking Results with Queues
What if transactions get out of order, are dropped or are
corrupted in the DUT?
Store expected transactions in a queue, with a timestamp
Contents are addressable, push/pop
Look up transaction ID on arrival for out-of-order delivery
If actual transaction not found: corrupted data
Periodically scan array for old transactions. Mark them as
dropped and remove
Tr2 @3000 Tr1 @1000 Tr4 @2000
DUT
Driver
Monitor
Transactor
Checker
48
SV Language Basics
Great for sparse memories
Dynamically allocated, non-contiguous elements
Accessed with integer, or string index, single dimension
Great for sparse arrays with wide ranging index
Array functions: exists, first, last, next, prev int aa[*], i;reg[7:0] mydata[string];
Associative Arrays
// Print full array foreach(aa[i]) $display(i,,aa[i]);
type name [*];
All memory allocated, even unused elements Associative array Standard array Unused elements don’t use memory49
SV Language Basics
Search through arrays (fixed, dynamic, queue, assoc.)
Many more methods will be implemented, such as sort…
Returns a queue or scalar
a.sum
of single bit values returns 0/1
Unless you compare to wider value: a.sum == 32’h3
Also available: product, and, or, xor
Array Methods
int q[$] = {1,3,5,7}, tq[$]; int d[] = {9,1,8,3,4}; int f[6] = {1,6,2,6,8,6}; $display(q.sum, q.product); // 16 105 tq = q.min(); // {1} tq = q.max(); // {7} tq = f.unique; // {1,6,2,8} tq = d.find with (item > 3); // {9,8,4} tq = d.find_index with (item > 3); // {0,2,4} LRM requiresa queue
IEEE changed array
const from {0,1} to ’{0,1} (VCS issues Warning for old usage)
50
SV Language Basics
Arbitrary length array of chars (like C), grows automatically
Compare operators ==, !=, and compare() and icompare()
methods
Use { } for concatenation
Built-in conversion
itoa,
atoi,
atohex,
atooct,
atobin string s = “SystemVerilog”;$display(s.getc(0),, s.toupper());
s = {s, “3.1b”}; // string concat s.putc(s.len()-1, “a”); // change b-> a $display(s);
$display(s.substr(2, 5)); // 4 characters
// Create temporary string, note format my_log($psprintf(“%s %5d”, s, 42));
51
SV Language Basics
Tasks and Functions
task reset(); reset_l = 1’b0; #100
reset_l = 1’b1; endtask
function void print_sum(ref int a[], input int start=0); int sum = 0;
for (int j=start; j<a.size; j++) sum += a[j];
$display(“Sum of array is %0d”, sum); endfunction
…
print_sum(my_array); print_sum(my_array, );
Default value Function can never contain blocking statements or calls to tasks Void functions do not return a value
function int add2(int n); return n + 2;
52
SV Language Basics
Static vs. Automatic Tasks and Functions
All calls to static routine shares the same storage space within a module instance. It can’t be reentrant or recursive. (Verilog-1995) An automatic routine allocates new space for each call. (This is
the default in other languages.) (Verilog-2001)
Class routines are automatic by default, while routines in modules and program are static by default. (SystemVerilog) The print_sum example on the previous slide will NOT work
with static storage as sum will only be initialized at time 0.
Tasks and Functions
program automatic test; task is_automatic();
Change storage default for programs
53
SV Language Basics
Argument Passing
Type is sticky, following arguments default to that type
input
- copy value in at beginning - default
output
- copy value out at end
inout
- copy in at beginning and out at end
ref
- pass by reference (effects seen right away)
Saves time and memory for passing arrays to tasks & functions Modifier: const - argument is not allowed to be modified
Tasks and Functions
task T3(a, b, output bit [15:0] u, v); Default dir is input,
default type is logic
a, b: input logic
u, v: output bit [15:0]
Watch out for ref followed by input…
54
Lab 1
Verify an arbiter
Objective
Verify the arbiter’s reset
Verify arbiter handles simple requests and grants
Verify proper handling of request sequences
Key Topics
Port list, clocking block, program block, assert, drive samples
and check responses.
Time Allotted
45 minutes55
Agenda
Introduction
Methodology Introduction
Getting Started
Testbench Environment
Language Basics
OOP Basics
Randomization
Controlling Threads
Virtual Interfaces
Functional Coverage
Coverage Driven Verification
56
OOP Basics
What Are We Going to Discuss?
What is OOP
Terminology
An example class
Default methods for classes
Static attribute
Assignment and copying
Inheritance
57
Introduction to OOP
OOP: Object Oriented Programming
Traditional programming deals with data structures and
algorithms separately
OOP organizes transactions and transactors better
Objects group data and algorithms together logically Routines are actions that work on the grouped data
OOP closely ties data and functions together
-encapsulation
Extend the functionality of existing objects
-inheritance
Wait until runtime to bind data with functions
-polymorphism
58
OOP Basics
OOP breaks a testbench into blocks that work together
to accomplish the verification goal
Advantages
• Objects are easily reused and extended
• Allows for complex data structures
• Allows access to advanced SystemVerilog
testbench features
• Variables, functions, and tasks are protected from
side effects or misuse by other code
• Debug small sections of code, one class at a time
59
OOP Basics
HDL
OOP
Verilog
SystemVerilog
Block definition module class
Block instance instance object
Block name instance name handle
Data Types registers & wires Properties: Variables
Executable Code behavioral blocks (always, initial), tasks, functions Methods: tasks and functions Communication between blocks Ports or cross-module task calls
calls,
mailboxes, semaphores, etc.
60
OOP Basics
Class
Programming element “containing” related group of features and functionality
Encapsulates functionality
Provides a template for building objects Can be used as data structures
Object
An object is an instance of a class
Handle
Type-safe pointer to an object – can not be corrupted
Properties
Variables contained in the instance of the class
Methods
Tasks/functions (algorithms) that operate on the properties in this instance of the class
Terminology
Blueprint for a house A complete house Light switches Turn on/off switches Address of a house61
OOP Basics
class Transaction;
// properties (variables)
logic [31:0] src, dst, data[1024], crc;
logic [7:0] kind;
// methods
function void display;
$display(“Tr: %h, %h”, src, dst);
endfunction
function void calc_crc();
crc = src ^ dst ^ data.xor;
endfunction
endclass
program automatic test; endprogram
Class Example
Variables & methods are public by default
In a class, methods are always automatic
62
OOP Basics
Call
new()to create an object
The class constructor allocates memory and initializes variables Result stored in a handle to the object
You must to call new() for every handle in an array
SystemVerilog uses a predefined new() for every class,
but you can redefine your own
Coding style: don’t call new in declaration
Otherwise objects are created before any procedural code task init;
Transaction tr; // A single handle
Transaction tr_arr[5]; // An array of handles // Handles are null until initialized
tr = new(); // Create a new object foreach (tr_arr[i]) // Create an array
tr_arr[i] = new(); // of new objects
Creating an Object From a Class
Declare first then construct
63
OOP Basics
Call new(), assigned values to the object
properties
Handles have the default value of null
Using a null handle is an error
Every call to the constructor creates a new
object that is independent of all other objects
Properties and methods accessed through handle
Handles are type safe – can’t misused or modified, unlike C
Class Destruction/De-allocation
Automatic Garbage Collection taken care of by SystemVerilog (like Java, unlike C++)
When an object is no longer being referenced, it is garbage collected
No segmentation faults from manual memory deallocation No memory leaks or unexpected side effects
if (tr.done) // No longer needed? tr = null; // clear handle
Working with Objects
64
Where are all the objects?
Drives
transactions
into the DUT
Scoreboard holds
transactions
Extended
class
Self Check
Verification
Environment
Executes
transactions
Compares
transactions
Puts data
into
transactions
A transactor can be an object too!
Driver
Monitor
DUT
Checker
Transactor
65
OOP Basics
Accessing Class Members
Reference properties by pre-pending the object handle
class Transaction;
bit [31:0] src, dst, data[1024]; bit [7:0] kind;
function void display;
$display(“Tr: %h, %h”, src, dst); endfunction endclass Transaction tr; initial begin tr = new(); tr.src = 5; tr.dst = 7; tr.display(); end
66
OOP Basics
Initializing Class Properties
program automatic test1; class Transaction; bit [31:0] src, dst; function new(); src = 5; dst = 3; endfunction endclass Transaction tr; initial tr = new();
program automatic test2; class Transaction;
bit [31:0] src, dst;
function new (int src, int dst=3);
this.src = src; // Disambiguate this.dst = dst; endfunction endclass Transaction tr; initial
tr = new(5); // dst uses default
Initialize the class properties in the constructor when the
object is created
67
Static attribute
How do I create a variable shared by all objects of a
class, but not make a global?
A static property is associated with the class
definition, not the instantiated object.
It is often used to store meta-data, such as number of
instances created
It is shared by all objects of that class.
class Transaction;static int count = 0; int id; … function new(); id = count++; endfunction endclass
Using a id field can help keep track of transactions as they
68
Assignment is not a copy
Assignment of one handle to another only affects
the handles. It does not copy data
class Thing; int data; endclass
…
Thing t1, t2; // Two handles initial begin
t1 = new(); // Allocate first thing t1.data = 1;
t2 = new(); // Allocate second t2.data = 2;
t2 = t1; // Second Thing is lost t2.data = 5; // Modifies first thing $display(t1.data); // Displays “5”
end
data=1 t1
69
Assignment is not a copy
Assignment of one handle to another only affects
the handles. It does not copy data
class Thing; int data; endclass
…
Thing t1, t2; // Two handles initial begin
t1 = new(); // Allocate first thing t1.data = 1;
t2 = new(); // Allocate second t2.data = 2;
t2 = t1; // Second Thing is lost t2.data = 5; // Modifies first thing $display(t1.data); // Displays “5” end data=1 t1 t2 data=2
70
Assignment is not a copy
Assignment of one handle to another only affects
the handles. It does not copy data
class Thing; int data; endclass
…
Thing t1, t2; // Two handles initial begin
t1 = new(); // Allocate first thing t1.data = 1;
t2 = new(); // Allocate second t2.data = 2;
t2 = t1; // Second Thing is lost
t2.data = 5; // Modifies first thing $display(t1.data); // Displays “5” end data=1 t1 t2 data=2
71
Assignment is not a copy
Assignment of one handle to another only affects
the handles. It does not copy data
class Thing; int data; endclass
…
Thing t1, t2; // Two handles initial begin
t1 = new(); // Allocate first thing t1.data = 1;
t2 = new(); // Allocate second t2.data = 2;
t2 = t1; // Second Thing is lost t2.data = 5; // Modifies first thing $display(t1.data); // Displays “5”
end
data=5
t1
72
How to copy objects
Assigning handles does not change objects
To copy the data, pass it into new:
This is a shallow copy, only data in top object is copied.
Your new() is not called!
SystemVerilog does not currently support deep
object copy – look for it in a future IEEE version
To do a deep copy of all objects, make a copy() method
for all objects nested inside the class.
t2 = new t1; id=5 body t2 t1 stuff id=5 body t1 stuff id=5 body t2
73
Inheritance
How do I share code between classes?
Instantiate a class within another class
Inherit from one class to another (inheritance/derivation)
Inheritance allows you to ‘add’ extra:
Add extra Properties (data members)
Add extra Methods
Change the behavior of a method
Common code can be grouped into a base class
Additions and changes can go into the derived class
Advantages:
Reuse existing classes from previous projects with less
debug
74
Inheritance
Add additional functionality to an existing class
class Transaction;
reg [31:0] src, dst, data[1024], crc; endclass
Extended a class with new fields
class BadTr extends Transaction; rand bit bad_crc;
endclass BadTr = Transaction + bad_crc Transaction src data BadTr bad_crc dst crc BadTr bt; bt = new; bt.src = 42; bt.bad_crc = 1;
75
Inheritance
Change the current functionality of a class
class Transaction;
reg [31:0] src, dst, data[1024], crc; function void calc_crc();
crc = src ^ dst ^ data.xor; endfunction
endclass
Override existing fields to a class
class BadTr extends Transaction; rand bit bad_crc;
function void calc_crc(); crc = super.calc_crc(); if (bad_crc) crc = ~crc; endfunction endclass Transaction src data dst crc BadTr bad_crc calc_crc calc_crc
76
program good_test; Transaction tr; task main(); assert(tr.randomize()); my_driver.send(tr); endtask class BadTr extends Transaction;rand bit bad_crc;
function void calc_crc(); class Transaction;
function void calc_crc(); endclass
Inheritance
Create a transactor that works with a base object
Extend the transaction class to inject errors
Send these into the transactor from the test
Error injection
class Driver;
task send(Transaction tr); tr.calc_crc();
// Drive interface signals endtask
endclass
class Transaction;
virtual function void calc_crc(); endclass
class BadTr extends Transaction; rand bit bad_crc;
virtual function void calc_crc();
program BadTest; BadTr bt = new; task main(); assert(bt.randomize()); my_driver.send(bt); endtask
77
Transaction BadTr src data dst crc bad_crc calc_crc calc_crcOverriding Methods
By default, a method is found using the handle type
What happens when extended object is referenced
by a base handle?
Inheritance allows methods to be overridden
task main(); Transaction tr; BadTr bt; tr = new(); bt = new(); tr.calc_crc(); bt.calc_crc(); tr = bt; tr.calc_crc(); endtask class Transaction; reg [31:0] crc;
function void calc_crc(); endclass
class BadTr
extends Transaction; bit bad_crc;
function void calc_crc(); endclass
Oops, this extended object just used base class method!
78
Transaction BadTr src data dst crc bad_crc calc_crc calc_crc task main(); Transaction tr; BadTr bt; tr = new(); bt = new(); tr.calc_crc(); bt.calc_crc(); tr = bt; tr.calc_crc(); endtaskPolymorphism
Allow a single name refer to many methods
class Transaction; reg [31:0] crc;
virtual function void calc_crc(); endclass
class BadTr
extends Transaction; bit bad_crc;
virtual function void calc_crc(); endclass Virtual method so…
‘tr’ is really ‘bt’ => BadTr
Virtual
– lookup method at runtime, not compile
The object’s type is used to find the right method
79
Handle Assignment
Handles for base and extended class
class Transaction;
reg [31:0] src, dst;
virtual function void calc_crc(); endclass
class BadTr extends Transaction; bit bad_crc;
virtual function void calc_crc(); endclass
Extend
src, dst Base
bad_crc
The handles for the base and extended classes are
not interchangeable
A base handle can not access extended properties
Transaction tr; BadTr bt, b2;
bt = new(); // Allocate extended object tr = bt; // Assign to base handle tr.calc_crc(); // Calculate CRC
b2 = tr; // Error! Not allowed
$cast(b2, tr); // Allow assign if ($cast(b2, tr)) // Check if legal
b2.calc_crc(); Compile check
80
Inheritance
Why do I want all this complexity?
Driver will treat all transactions the same way Transaction class knows how to perform actions
Cell.display()
Print ATM cell data if I’m at ATM cell
Print Ethernet MCA data if I’m an Ethernet packet Print Sonet frame data if I’m a Sonet frame
Print USB packet data if I’m a USB packet
Code calling display doesn’t need to know what type of
cell/packet ‘cell’ handle references
Classes are self-contained, they know how to perform
actions on themselves based on their type
81
Agenda
Introduction
Methodology Introduction
Getting Started
Testbench Environment
Language Basics
OOP Basics
Randomization
Controlling Threads
Virtual Interfaces
Functional Coverage
Coverage Driven Verification
82
Randomization
What Are We Going to Discuss?
Why use randomization
Randomization options
Randomization of objects
Class constraints and distributions
In-line constraints and distributions
Tricks and techniques
83
Randomization
Why Use Randomization?
Automatic stimulus generation
Change the characteristics of the data driving the DUT
Random setting of parameters
Select ports, addresses, operational parameters randomly.
Directed testing detects the bugs you expect.
Random testing detects the bugs you did not expect.
A random test’s behavior depends on the seed
If you run the same test with the same seed, you will get the
same behavior
If you run the same test with many different seeds, you will get
84
Randomization
Randomization Example
program automatic test;
class Transaction;
rand bit [31:0] src, dst, data[]; // Dynamic array randc bit [2:0] kind; // Cycle through all kinds constraint c_len
{ data.size inside {[1:1000]}; } // Limit array size endclass Transaction tr; initial begin tr = new(); assert(tr.randomize()); send(tr); end endprogram
rand
: rolling dice
randc: dealing cards
85
Randomization
Randomization of Objects
Random variables
rand – returns values over the entire range
randc – random cyclic value up to 16 bits
Object variables are randomized by randomize()
The method is
automatically
available to classes with random
variables.
Returns a 1 upon success, 0 on failure
Optional: pre_randomize() & post_randomize() void
functions which will be called automatically
pre_randomize()
– set up random weights
post_randomize()
– cleanup calculations like CRC
Remember calc_crc ?Always check randomize()
86
Randomization
Constraining Randomness
Purely random stimulus takes too long to do something
interesting
Specify the interesting subset of all possible stimulus with
constraint blocks
You can define separate, non-overlapping constraints for different
tests
Constraints and distribution weights can form the basis for a
“test writer interface” to your testbench
User-Created Test:
- subset of legal stimulus vectors - subset of legal stimulus sequences
Your Testbench:
- all legal stimulus vectors - all legal stimulus sequences
87
constraint c_default { data.size <= 1000; data.size > 0;
kind == 0; // Equivalent, not assignment cntrl inside {[2:10], 20, 40, [100:107]}; if (test_mode == CONGEST) dest inside {[src-100:src+100]}; } constraint c_long { data.size > 5000; }
Randomization
Class Constraints
Constraint Blocks
Made of relational expressions, not assignments
Constraints can be dynamically enabled/disabled with:
handle.[constraint_name.]constraint_mode(1/0)
Unsolvable or conflicting constraints cause a run-time error
Disable this with:
88
constraint c_0 {
src
dist
{0:=30, [1:3]:=60};
dst
dist
{0:/30, [1:3]:/60};
}
Randomization
Distributions
dist
constraint
Distribution weights can be variables or constants
Weighted probabilities
:=
assigns weight to each element
:/
divides weight evenly in range
Distributions do not have to add up to 100%
Value Dist 0 30/90 1 20/90 2 20/90 3 20/90 Value Dist 0 30/210 1 60/210 2 60/210 3 60/210
89
Randomization
In-Line Constraints and Distributions
initial begin
Transaction t = new();
s = t.randomize() with {src >= 50; src <= 1500; dst < 10;}; driveBus(t);
// force src to a specific value
s = t.randomize() with { src == 2000; dst > 10;}; driveBus(t);
end
Constraints may be defined at the time of randomization
Allows test-specific constraints
Don’t modify the original class for just a single test
In-line constraints are additive with existing class constraints
Supports all SystemVerilog constraints and distributions
class Transaction;
rand bit [31:0] src, dst, data[1024];
constraint valid {src inside{[0:100], [1000:2000]}; }
endclass src: 50-100, 1000-1500
dst<10
src==2000 dst>10
90
Randomization
The solver has to handle algebraic factoring, complex Boolean
expressions, mixed integer and bit expressions and more
All constraints interact bidirectionally and are solved
concurrently
Keep in mind rules regarding precedence, sign extension,
truncation and wrap-around when creating constraints
SystemVerilog requires a strong constraint solver!
class Parameters;
rand bit [15:0] a, b, c, d, e, f;
constraint c_0 {
(a + b) < 4;
0<c; c<d; d<e; e<150;
f == e % 16’d6; // Restrict width for: * % /
}
91
Randomization
Conditional operator:
if … else if … else
Behaves like a procedural “if”, except the conditionals
are evaluated bi-directionally. Equivalent to implication.
Implication Operator:
->
Short version of “if”
Ex: (mode == SMALL) -> (data.size < 10);
Global Constraints:
x < other_object.y;
References to rand object data members in the
constraints get solved simultaneously
Variable ordering:
solve x before y;
Otherwise VCS solves all constraints simultaneously
92
Randomization
Create a random array
Constrain its size, individual elements, or all elements class C;
rand bit [5:0] a[]; constraint cc { a.size inside {[1:5]}; array[0] > 0; foreach (a[i]) if (i > 0) a[i] > a[i-1]); }
function void pre_randomize;
a.delete; // Needed in 2005.06 endfunction endclass // Output a[0] = 1; a[1] = 2; a[2] = 33; a[3] = 39; a[4] = 40;
Array constraints
Array size Single element Multiple elements93
Randomization
Set valid on 3 cycles out of 5
Two foreach loops with relationships
Constraints solved
simultaneously
x[] in 1:8
y[] in 2:9
Array Constraints
class ValidOn;
rand bit valid[5];
constraint cv
{valid.sum == 32’d3;}
endclass
class E;
rand bit [15:0] x[10], y[10]; constraint size_cons {
foreach (x[i]){
x[i] > 0; x[i] < y[i]; foreach (y[i])
y[i] inside {[1:9]}; }
94
Randomization
Watch out for signed variables
What are legal values for first and second?
Make instances rand
Or they won’t be randomized
Don’t call randomize() in new() constructor
Test may want to change constraints first
Use rand_mode to make a variable random / non-random
env.first.rand_mode(0);
Tricks and Techniques
class Nesting;
rand SubClass data; endclass
class Environment;
rand byte first, second; constraint c { first + second < 8’h40; } endclass first second 9. ‘h09 20. ‘h14 85. ‘h55 -70. ‘hba -20. ‘hec -32. ‘he0
95
Randomization
Need to modify a constraint in a test?
Use a variable in the constraint
Extend the base class to override original constraint
Use constraint_mode() to turn it off
More Tricks and Techniques
class Base;
rand int size;
constraint
c
{
size inside {[1:10]};}
endclass
class Bigger extends Base;
constraint
c
{
size inside {[1:1000]};}
endclass
rand int size;
int
max_size
= 100;
constraint c {
96
Randomization
Want to randomize without a class?
Use randcase or $urandom_range
Good for creating single variable, stateless
code, or nested set of actions