0% found this document useful (0 votes)
926 views41 pages

I Didn't Know Constraints Could Do That!: John Dickol Samsung Austin R&D Center

This document discusses advanced constraint techniques in SystemVerilog, including: - Soft constraints that can be overridden. - Unique constraints to ensure variables have unique values. - Array constraints like foreach to apply to each element, and reduction operations like sum. - Global constraints to constrain lower-level rand class members from a top-level object. - Policy classes that define reusable constraints that can be extended and applied to parent objects.

Uploaded by

ninja
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
926 views41 pages

I Didn't Know Constraints Could Do That!: John Dickol Samsung Austin R&D Center

This document discusses advanced constraint techniques in SystemVerilog, including: - Soft constraints that can be overridden. - Unique constraints to ensure variables have unique values. - Array constraints like foreach to apply to each element, and reduction operations like sum. - Global constraints to constrain lower-level rand class members from a top-level object. - Policy classes that define reusable constraints that can be extended and applied to parent objects.

Uploaded by

ninja
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

I Didn’t Know Constraints Could Do That!

John Dickol
Samsung Austin R&D Center

6 February 2018
DVClub Europe

DVClub Europe 6 Feb 2018 1


Agenda

Introduction
SystemVerilog Constraint Techniques
Constraint Examples

DVClub Europe 6 Feb 2018 2


Introduction

• SystemVerilog constraint solvers continue to improve

• Solvers can handle more complex constraint problems

• Why use complex constraints?


– Use constraints to define legal stimulus
– Add constraints to steer stimulus
– Complex stimulus needs complex constraints

DVClub Europe 6 Feb 2018 3


Constraint Techniques

DVClub Europe 6 Feb 2018 4


Constraint Basics

• SystemVerilog constraints are declarative, not procedural.


– Describe what you want - Solver will figure out how
– Constraints specify expressions which must be true
– Can be any SV expression using variables & constants of integral type
– Constraint solver chooses values for random variables to ensure all constraints are satisfied
– All constraints solved simultaneously (usually – some exceptions)

• Full specification in SystemVerilog Language Reference


– Latest version: IEEE Std 1800-2012  1800-2017
– Download free copy from IEEE Get Program:
http://standards.ieee.org/getieee/1800/download/1800-2012.pdf

DVClub Europe 6 Feb 2018 5


Constraint Expressions

Simple Complex

1; x < y; foreach(n_txns_per_slave[s]) {
0; (x + y) == z; n_txns_per_slave[s] == txn_map.sum with(
(item.index(2) == s) ? item : 0);
x == 1; if(a>b) c<d; );
x inside {[0:10]}; }
if(x==y) {
0;
} map.ranges.or(r) with (
item.addr inside
{[r.start_addr : (r.end_addr - item.size)]}
&& item.cache_type == r.cache_type
);

DVClub Europe 6 Feb 2018 6


Soft Constraints

• Are applied only if not contradicted by other constraints with higher priority
• In general, last constraint specified has higher priority
• See SV LRM for complete list of priorities
• Good for specifying default values for UVM sequence/sequence_item
which can be overridden in higher-level sequence

DVClub Europe 6 Feb 2018 7


Soft Constraint Example
class myseq extends uvm_sequence#(mytxn); Default constraint for count
rand int count // number of transactions Soft constraint may be overridden
constraint c_count {
soft count inside {[10:20]};
}

task body;
class topseq extends uvm_sequence#(mytxn);
mytxn txn;
task body; Default soft constraint applies
repeat(count) begin
myseq seq;
`uvm_do(txn)
end
`uvm_do(seq)
endtask
endclass
`uvm_do_with(seq, {count == 1000;}
endtask
endclass
Inline hard constraint
overrides soft constraint

DVClub Europe 6 Feb 2018 8


Unique Constraints

• Constrain set of variables to have unique values:


– Scalar integral values
– Unpacked arrays of integral values

rand int x, y, z; Equivalent to:


rand int arr[10]; x!=y; y!=z; z!=x;
int q[$] = ‘{1, 2, 7, 11};

constraint c_unique { Fill arr with unique values


unique {x, y, z};
unique {arr};
unique {x, y, arr}; Can mix scalars and arrays
unique {x, y, q};
}
Pick x & y not equal to
elements of non-rand queue
DVClub Europe 6 Feb 2018 9
Array Iterative Constraints

• foreach constraint applies to each element of array


• Array size can be constrained
• LRM requirement: array size solved before iterative constraints
rand int arr[10];
rand int q[$];
Constrain each array
constraint c_foreach { element
foreach(arr[i]) arr[i] inside {[0:15]};
Constrain queue size
q.size() inside {[5:10]};

foreach(q[i]) { Create sorted queue:


if(i>0) q[i] > q[i-1]; q[0] < q[1], q[2] …
}
} Constraint guard avoids
DVClub Europe 6 Feb 2018
index out of bounds error 10
Array Reduction Constraints

• Operate on unpacked arrays of integral values


• Apply specified operation between each element of the array
rand int a[10];
a.sum == a[0] + a[1] + …
a.product == a[0] * a[1] * …
a.and == a[0] & a[1] & …
a.or == a[0] | a[1] | …
a.xor == a[0] ^ a[1] ^ …
• Methods return single value of the same type as array element
i.e sum of int returns int. xor of bit returns bit, etc.
• Optional “with” expression applied to each element before reduction operation
• Inside “with” expression:
– “item” refers to current array element
– “item.index” refers to current array index
DVClub Europe 6 Feb 2018 11
Array Reduction Constraint Examples

• Constrain number of 1s in array of bits:


rand bit bq[$]; sum() of bit is single bit
Cast to int to avoid overflow
constraint c_sum {
bq.size inside {[10:20]};
(bq.sum with (int’(item))) == 7;
}
sum with(…) equivalent to:
• Constrain sum of first 3 elements of array: foreach(a[i]) if(i<3) sum+= a[i]

rand int a[10];

constraint c_sum_first_3 {
(a.sum with ((item.index < 3) ? item : 0)) == 10;
}

item.index equivalent to i item equivalent to a[i]


DVClub Europe 6 Feb 2018 12
Global (Hierarchical) Constraints

• Class with rand variables may be rand member of another class


• When top-level object is randomized, all rand class members are also
randomized
• Top-level object may constrain lower-level object variables

DVClub Europe 6 Feb 2018 13


Global Constraint Example: Line Drawing
class Line;
Rand instances of rand XY pt1;
XY point class rand XY pt2;
rand enum {HORIZONTAL, VERTICAL} direction;

class XY; function new;


rand int x; if(pt1==null) pt1 = new;
rand int y; if(pt2==null) pt2 = new;
endfunction
constraint c_valid {
x inside {[0:100]}; constraint c_valid {
y inside {[0:100]}; if(direction == VERTICAL) {
} pt1.x == pt2.x;
endclass pt1.y != pt2.y;
}

Top-level object if(direction == HORIZONTAL) {


constrains lower-level pt1.y == pt2.y;
pt1.x != pt2.x;
}
}
endclass
DVClub Europe 6 Feb 2018 14
Reusing Constraints: Policy Classes

• Problem:
– Define constraints once and reuse in multiple objects
– Add additional constraints to object at runtime
• Implementation:
– Variation of hierarchical constraints: Lower-level object constrains parent object
– Define reusable constraints in “policy class” container
– Policy classes extended from common base class
– “item” variable in policy class refers to parent object
– Parent object has rand queue of policy base class

• More info in DVCon 2015 paper:


SystemVerilog Constraint Layering via Reusable Randomization Policy Classes
DVClub Europe 6 Feb 2018 15
Policy Class Example
Rand queue of policy base class
class Line;
rand enum {HORIZ, VERT} direction;
class rand_policy_base #(type T=uvm_object); rand rand_policy_base#(Line) pcy[$];
T item;

virtual function void set_item(T item); function void pre_randomize;


this.item = item; foreach(pcy[i]) pcy[i].set_item(this);
endfunction endfunction
endclass ...
endclass
Set “item” in policy objects to
class line_direction_policy point to this Line instance
extends rand_policy_base#(Line);
Test case
constraint c_direction { Line l = new;
item.direction dist { line_direction_policy dir_pcy = new;
“item” refers Line::VERT := 5,
to parent Line::HORIZ := 1 l.pcy = {dir_pcy};
Line object };
} l.randomize;
endclass Add policy to queue
DVClub Europe 6 Feb 2018 16
Example 1: Bus Interconnect Testbench

DVClub Europe 6 Feb 2018 17


Bus Interconnect Testbench

Tests may want to control:


Master Master
Agent
  
Agent • Total number of transactions for all
masters
• Number of transactions per master
Bus Interconnect • Number of transactions per slave
DUT • Number of transactions from one
master to a particular slave
• Use/avoid using certain masters or
Slave Slave slaves
  
Agent Agent
• Etc.

DVClub Europe 6 Feb 2018 18


Bus Interconnect Configuration Constraints

• Use 2-D array to model number of transactions


rand int unsigned txn_map[N_MASTER][N_SLAVE];
• Add rand variables and constraints for provide “knobs” controllable by test
Sum rows to get
txns per master
Total txns
S0 S1 S2 S3 S4 S5 per master
M0 2 18 6 17 0 246 289
M1 1 0 3 128 0 155 287
M2 3 55 10 211 0 7 286 Sum entire array
Sum columns to get to get total txns
txns per slave M3 15 0 97 2 0 175 286
M4 0 0 0 0 0 0 0
Total Txns Total txns
per slave 21 73 116 358 0 583 1151
DVClub Europe 6 Feb 2018 19
Constrain Total Number of Transactions

class ms_config#(N_MASTER=5, N_SLAVE=6);


rand int unsigned txn_map[N_MASTER][N_SLAVE];
sum with(…)is equivalent to:
foreach(txn_map[M,S])
rand int unsigned total_txns; sum += txn_map[M][S];

constraint c_valid {
total_txns == txn_map.sum;
}

endclass

DVClub Europe 6 Feb 2018 20


Constrain Transactions Per Master

class ms_config#(N_MASTER=5, N_SLAVE=6);


rand int unsigned txn_map[N_MASTER][N_SLAVE];

rand int unsigned n_txns_per_master[N_MASTER]; Sum each row of txn_map array

constraint c_valid {
foreach(n_txns_per_master[m]) {
n_txns_per_master[m] == txn_map[m].sum;
}
}

endclass

DVClub Europe 6 Feb 2018 21


Constrain Transactions Per Slave

sum with(…) is equivalent to:


foreach(txn_map[M,S])
class ms_config#(N_MASTER=5, N_SLAVE=6); if(S == s) sum += txn_map[M][S];
... else sum += 0;
rand int unsigned n_txns_per_slave[N_SLAVE];

constraint c_valid {
foreach(n_txns_per_slave[s]) {
n_txns_per_slave[s] == txn_map.sum with(
(item.index(2) == s) ? item : 0);
);
}
}

endclass

item.index(2) returns
Index for 2nd array dimension;

DVClub Europe 6 Feb 2018 22


Constrain Individual Masters/Slaves
class ms_config#(N_MASTER=5, N_SLAVE=6);
...
rand bit use_master[N_MASTER];
rand bit use_slave[N_MASTER]; Master is used if it has
rand int unsigned use_n_masters; at least 1 transaction
rand int unsigned use_n_slaves;

constraint c_valid {
foreach(use_master[m]) {
Count number of used
(use_master[m] == 1) == (n_txns_per_master[m] > 0);
}
masters
use_n_masters == use_master.sum with (int'(item));

foreach(use_slave[s]) {
(use_slave[s] == 1) == (n_txns_per_slave[s] > 0);
}
use_n_slaves == use_slave.sum with (int'(item))
}
endclass

DVClub Europe 6 Feb 2018 23


Test Scenario Constraints

Generate a total of
10000 transactions
ms_config cfg = new;

cfg.randomize with {
total_txns == 10000; Use between 2 and 4 masters
use_n_masters inside {[2:4]};
use_master[1] == 1;
use_slave[3] == 0;
} Use Master 1

Don’t use Slave 3

DVClub Europe 6 Feb 2018 24


Command Line Control of Constraints
function void ms_config::get_plusargs;
If plusarg specified on command line,
if($value$plusargs("total_txns=%d", total_txns))
total_txns.rand_mode(0); disable randomization for
corresponding variable
if($value$plusargs("use_n_masters=%d", use_n_masters))
use_n_masters.rand_mode(0); Compute plusarg names for
individual array elements
foreach(use_master[m]) begin
string format = $sformatf("use_master[%0d]=%%b", m);
if($value$plusargs(format, use_master[m]))
use_master[m].rand_mode(0); Test case configuration
end ms_config cfg = new;
... cfg.get_plusargs;
endfunction cfg.randomize;

Simulator command line


{irun|simv|vsim} +total_txns=10000 +use_n_masters=3 ‘+use_master[1]=1’ ...

DVClub Europe 6 Feb 2018 25


Example 2: Memory Map Generation
See Appendix

DVClub Europe 6 Feb 2018 26


Summary

• Constraint techniques:
– Soft constraints
– Unique constraints
– Array constraints (foreach, size)
– Array reduction constraints (sum, and, …)
– Reusable constraints: policy classes

• Constraint solver can handle complex problems – use it!

DVClub Europe 6 Feb 2018 27


Thank You

DVClub Europe 6 Feb 2018 28


Appendix

DVClub Europe 6 Feb 2018 29


Example 2: Memory Map Generation

DVClub Europe 6 Feb 2018 30


Memory Map Generation

Memory Management Unit Features:


• 32-bit address
• 3 address range (page) sizes: 1KB, 4KB, 1MB
• Range starting address aligned to range size
• Range can be Non-cacheable, Write-through cacheable, write-back cacheable

Problem:
• Generate “interesting” sets of non-overlapping memory ranges
• Select memory transactions from mapped ranges

DVClub Europe 6 Feb 2018 31


Memory Map Generation

Implementation:
• mem_range class describes single range
• mem_map class has rand array of mem_range (plus constraints)
• mem_range array fixed maximum size; randomize number of valid ranges
(workaround for solve size before foreach limitation)
• Configurable constraint policy classes select number & types of ranges
map
range[0] range[1] range[2] range[3] range[N-1] range[N]
valid valid valid valid invalid invalid
size
cache
size
cache
size
cache
size
cache
... size
cache
size
cache
... ... ... ... ... ...

DVClub Europe 6 Feb 2018 32


Memory Range Class
typedef bit [31:0] addr_t;
typedef enum addr_t { SIZE_1K='h400,
SIZE_4K='h1000,
SIZE_1M='h100000} size_t;

typedef enum { NONCACHEABLE,


WT_CACHEABLE, This range is valid
WB_CACHEABLE } cache_t; (will be constrained)
class mem_range;
rand bit valid;
rand size_t size;
rand addr_t start_addr;
rand addr_t end_addr;
rand cache_t cache_type;

constraint c_valid { Ensure size, start, end are in sync


size == (1 + end_addr - start_addr);
(start_addr & (size - 1)) == 0;
}
endclass
Size-align start address

DVClub Europe 6 Feb 2018 33


Memory Map Class
class mem_map;
int max_ranges = 10;
rand int num_ranges; Rand array of mem_ranges
rand mem_range ranges[];
rand rand_policy_base#(mem_map) pcy[$];

function new(int max_ranges);


this.max_ranges = max_ranges;
endfunction
Ensure all mem_range
function void pre_randomize; instances are constructed
ranges = new[max_ranges];
before randomizing
foreach (ranges[i])
ranges[i] = new();
foreach(pcy[i])
pcy[i].set_item(this);
endfunction
...

DVClub Europe 6 Feb 2018 34


Memory Map Class
class mem_map; Non-overlapping valid ranges
int max_ranges = 10; sorted by address
rand int num_ranges;
rand mem_range ranges[];
rand rand_policy_base#(mem_map) pcy[$];

function new(int max_ranges);


...
this.max_ranges = max_ranges;
constraint c_valid {
endfunction
foreach(ranges[i])
if(i>0) {
function void pre_randomize;
if(ranges[i].valid)
ranges = new[max_ranges];
ranges[i].start_addr > ranges[i-1].end_addr;
foreach (ranges[i])
}
ranges[i] = new();
foreach(pcy[i])
num_ranges inside {[1:max_ranges]};
pcy[i].set_item(this);
foreach(ranges[i]) {
endfunction
ranges[i].valid == ((i < num_ranges) ? 1 : 0);
...
Ensure first num_ranges entries }
are valid, remainder invalid }
endclass
DVClub Europe 6 Feb 2018 35
Memory Range Allocation Policies

Allocate between min and max pages of specified size

class page_count_policy extends rand_policy_base#(mem_map);


addr_t size;
int min; // minimum number of pages of given size Constrain number of valid
int max; // maximum number of pages of given size pages of desired size

constraint c_count {
item.ranges.sum(r) with (int'(r.valid && (r.size == size)))
inside {[min:max]};
}

function new(addr_t size, int min, int max=min);


this.size = size;
this.min = min;
this.max = max;
endfunction
endclass

DVClub Europe 6 Feb 2018 36


Memory Range Allocation Policies

Allocate between min and max bytes of a specified cache type


class cache_size_policy extends rand_policy_base#(mem_map);
cache_t cache_type;
addr_t min; Constrain number of valid
addr_t max;
pages of desired cache type
constraint c_cache {
item.ranges.sum(r) with (
(r.valid && (r.cache_type == cache_type))? r.size : 0
) inside {[min:max]};
}

function new(cache_t cache_type, addr_t min, addr_t max='1);


this.cache_type = cache_type;
this.min = min;
this.max = max;
endfunction
endclass

DVClub Europe 6 Feb 2018 37


Configuring the Memory Map
// Allocate memory map with:
// Any number of 1K pages
// At most 2 4KB pages
// No 1MB pages
// At least 4KB of non-cacheable memory
// At least 8KB of write-back cacheable memory Construct policies with
// No write-though cacheable memory desired characteristics

mem_map map = new;

page_count_policy count_4K_pcy = new(SIZE_4K, 0, 2);


page_count_policy count_1M_pcy = new(SIZE_1M, 0); Add policies to map
cache_size_policy NC_pcy = new(NONCACHEABLE, SIZE_4K);
cache_size_policy WB_pcy = new(WB_CACHEABLE, 2*SIZE_4K);
cache_size_policy WT_pcy = new(WT_CACHEABLE, 0,0);

map.pcy = { NC_pcy, WB_pcy, WT_pcy, count_4K_pcy, count_1M_pcy};

map.randomize;

DVClub Europe 6 Feb 2018 38


Using the Memory Map

Problem: Generate Memory Transactions Using Memory Map


• Transactions may be 1, 2 or 4 bytes.
• All bytes of a transaction must be within a single memory range
• Transaction addresses must be size-aligned
• Transaction’s cache type must match its memory range cache type

Implementation
• Use policy class to inject memory map constraints into memory transaction

DVClub Europe 6 Feb 2018 39


Memory Transaction
class mem_txn; Constrain sizes and alignment
rand addr_t addr;
rand addr_t size;
rand cache_t cache_type;
rand rand_policy_base#(mem_txn) pcy[$];

constraint c_size { size inside {1, 2, 4};}


constraint c_align { (addr & (size-1)) == 0;}

function void pre_randomize;


foreach(pcy[i]) pcy[i].set_item(this);
endfunction
endclass

DVClub Europe 6 Feb 2018 40


Transaction Selection Policy
class mem_txn; Non-rand mem_map used as
rand addr_t addr; state variable
rand addr_t size;
rand cache_t cache_type;
rand rand_policy_base#(mem_txn) pcy[$];
class txn_pick_policy extends rand_policy_base#(mem_txn);
constraint c_size { size
mem_map inside {1, 2, 4};}
map;
constraint c_align { (addr & (size-1)) == 0;}
Use OR-reduction to constrain
function new(mem_map map);
function void pre_randomize;
this.map = map;
txn to fit within range with same
foreach(pcy[i]) pcy[i].set_item(this);
endfunction cache type
endfunction
endclass constraint c_pick {
map.ranges.or(r) with (
item.addr inside {[r.start_addr : (r.end_addr - item.size)]}
&& item.cache_type == r.cache_type
);
} txn_pick_policy pick_pcy = new(mem_map);
endclass mem_txn txn = new;
Use the policy when
randomizing txn txn.pcy = {pick_pcy};
txn.randomize;
DVClub Europe 6 Feb 2018 41

You might also like