Packages are explicitly named scopes appearing at the outermost level of the source text (at the same level as top-level modules and primitives). Types, variables, tasks, functions, sequences, and properties may be declared within a package.
Packages must not contain any processes. Therefore, wire declarations with implicit continuous assignments are not allowed.
Items within packages are generally type definitions, tasks, and functions. Items within packages cannot have hierarchical references. It is also possible to populate packages with parameters, variables, and nets.
One way to use declarations made in a package is to reference them using the class scope resolution operator ::.
ComplexPkg::Complex cout = ComplexPkg::mul(a, b);
Explicit import allows control over precisely which symbols are imported:
import ComplexPkg::Complex;
An alternate method for utilizing package declarations is via the import statement.
Showing posts with label systemverilog. Show all posts
Showing posts with label systemverilog. Show all posts
Monday, November 15, 2010
Thursday, June 10, 2010
virtual things
Virtual class
If a base class is not intended to be instantiated, it can be made abstract by specifying the class to be virtual.
An abstract class cannot be instantiated; it can only be derived.
Abstract classes can also have virtual methods.
Virtual method(function)
Virtual methods are a basic polymorphic construct. A virtual method overrides a method in all the base classes, whereas a normal method only overrides a method in that class and its descendants.(only a virtual method can be overrided.) One way to view this is that there is only one implementation of a virtual method per class hierarchy, and it is always the one in the latest derived class. When subclasses override virtual methods, they must follow the prototype exactly.
example:
virtual class BasePacket;
virtual function integer send(bit[31:0] data);
endfunction
endclass
class EtherPacket extends BasePacket;
function integer send(bit[31:0] data);
// body of the function
...
endfunction
endclass
Virtual interface
Virtual interfaces provide a mechanism for separating abstract models and test programs from the actual signals that make up the design. A virtual interface allows the same subprogram to operate on different portions of a design and to dynamically control the set of signals associated with the subprogram. Instead of referring to the actual set of signals directly, users are able to manipulate a set of virtual signals. Changes to the underlying design do not require the code using virtual interfaces to be rewritten. By abstracting the connectivity and functionality of a set of blocks, virtual interfaces promote code reuse.
A virtual interface is a variable that represents an interface instance.
Virtual interface variables can be passed as arguments to tasks, functions, or methods. A single virtual interface variable can thus represent different interface instances at different times throughout the simulation. A virtual interface must be initialized before it can be used; it has the value null before it is initialized.
A virtual interface must be initialized before it can be used; it has the value null before it is initialized.
Once a virtual interface has been initialized, all the components of the underlying interface instance are directly available to the virtual interface via the dot notation.
Virtual interfaces can be declared as class properties, which can be initialized procedurally or by an argument to new().
example:
interface SBus; // A Simple bus interface
logic req, grant;
logic [7:0] addr, data;
endinterface
class SBusTransctor; // SBus transactor class
virtual SBus bus; // virtual interface of type Sbus
function new( virtual SBus s );
bus = s; // initialize the virtual interface
endfunction
endclass
module devA( Sbus s ) ... endmodule // devices that use SBus
module top;
SBus s[1:4] (); // instantiate 4 interfaces
devA a1( s[1] ); // instantiate 4 devices
...
initial begin
SbusTransactor t[1:4]; // create 4 bus-transactors and bind
t[1] = new( s[1] );
...
end
endmodule
In the preceding example, the transaction class SbusTransctor is a simple reusable component. It is written without any global or hierarchical references and is unaware of the particular device with which it will interact. Nevertheless, the class can interact with any number of devices (four in the example) that adhere to the interface’s protocol.
(设想一下,在SBusTransctor中如果没有virtual修饰 SBus s, s就成为一个实在的interface, 所有对s的操作都在局限在SBusTransctor中,"到此为止"。有了virtual修饰,在SBusTransctor梨花的时候,通过把virtual interface和外部实际interface连接,相应的操作就能传递到理想的real DUT上。 所以virtual interface 常用于 ovm driver 设计中。
If a base class is not intended to be instantiated, it can be made abstract by specifying the class to be virtual.
An abstract class cannot be instantiated; it can only be derived.
Abstract classes can also have virtual methods.
Virtual method(function)
Virtual methods are a basic polymorphic construct. A virtual method overrides a method in all the base classes, whereas a normal method only overrides a method in that class and its descendants.(only a virtual method can be overrided.) One way to view this is that there is only one implementation of a virtual method per class hierarchy, and it is always the one in the latest derived class. When subclasses override virtual methods, they must follow the prototype exactly.
example:
virtual class BasePacket;
virtual function integer send(bit[31:0] data);
endfunction
endclass
class EtherPacket extends BasePacket;
function integer send(bit[31:0] data);
// body of the function
...
endfunction
endclass
Virtual interface
Virtual interfaces provide a mechanism for separating abstract models and test programs from the actual signals that make up the design. A virtual interface allows the same subprogram to operate on different portions of a design and to dynamically control the set of signals associated with the subprogram. Instead of referring to the actual set of signals directly, users are able to manipulate a set of virtual signals. Changes to the underlying design do not require the code using virtual interfaces to be rewritten. By abstracting the connectivity and functionality of a set of blocks, virtual interfaces promote code reuse.
A virtual interface is a variable that represents an interface instance.
Virtual interface variables can be passed as arguments to tasks, functions, or methods. A single virtual interface variable can thus represent different interface instances at different times throughout the simulation. A virtual interface must be initialized before it can be used; it has the value null before it is initialized.
A virtual interface must be initialized before it can be used; it has the value null before it is initialized.
Once a virtual interface has been initialized, all the components of the underlying interface instance are directly available to the virtual interface via the dot notation.
Virtual interfaces can be declared as class properties, which can be initialized procedurally or by an argument to new().
example:
interface SBus; // A Simple bus interface
logic req, grant;
logic [7:0] addr, data;
endinterface
class SBusTransctor; // SBus transactor class
virtual SBus bus; // virtual interface of type Sbus
function new( virtual SBus s );
bus = s; // initialize the virtual interface
endfunction
endclass
module devA( Sbus s ) ... endmodule // devices that use SBus
module top;
SBus s[1:4] (); // instantiate 4 interfaces
devA a1( s[1] ); // instantiate 4 devices
...
initial begin
SbusTransactor t[1:4]; // create 4 bus-transactors and bind
t[1] = new( s[1] );
...
end
endmodule
In the preceding example, the transaction class SbusTransctor is a simple reusable component. It is written without any global or hierarchical references and is unaware of the particular device with which it will interact. Nevertheless, the class can interact with any number of devices (four in the example) that adhere to the interface’s protocol.
(设想一下,在SBusTransctor中如果没有virtual修饰 SBus s, s就成为一个实在的interface, 所有对s的操作都在局限在SBusTransctor中,"到此为止"。有了virtual修饰,在SBusTransctor梨花的时候,通过把virtual interface和外部实际interface连接,相应的操作就能传递到理想的real DUT上。 所以virtual interface 常用于 ovm driver 设计中。
semaphore, mailbox and event
semaphore
a semaphore is a bucket to store 1 or more keys. Any process using semaphore must procure a key before it can continue to execute.
To declare a semaphore:
semaphore smTx
Semaphore is a built-in class that provides the following methods:
Create a semaphore with a specified number of keys:
function new(int keyCount = 0 );
Obtain one or more keys from the bucket. If the specified number of keys is not available, the process blocks until the keys become available.
task get(int keyCount = 1);
Return one or more keys into the bucket. If the specified number of keys is available, the method returns a positive integer and execution continues.
task put(int keyCount = 1);
Try to obtain one or more keys without blocking. The semaphore try_get() method is used to procure a specified number of keys from a semaphore, but without blocking.
function int try_get(int keyCount = 1);
mailbox
A mailbox is a communication mechanism that allows messages to be exchanged between processes. Data can be sent to a mailbox by one process and retrieved by another.
Conceptually, mailboxes behave like real mailboxes.
When a letter is delivered and put into the mailbox, one can retrieve the letter (and any data stored within). However, if the letter has not been delivered when one checks the mailbox, one must choose whether to wait for the letter or to retrieve the letter on a subsequent trip to the mailbox. Similarly, SystemVerilog's mailboxes provide processes to transfer and retrieve data in a controlled manner.
size: Mailboxes are created as having either a bounded or unbounded queue size.
A bounded mailbox becomes full when it contains the bounded number of messages. A process that attempts to place a message into a full mailbox shall be suspended until enough room becomes available in the mailbox queue.
Unbounded mailboxes never suspend a thread in a send operation.
An example of creating a mailbox is as follows:
mailbox mbxRcv;
Mailbox is a built-in class that provides the following methods:
Create a new mailbox
function new(int bound = 0);
If the bound argument is 0, then the mailbox is unbounded
The number of messages in a mailbox can be obtained via the num() method.
function int num();
The put() method places a message in a mailbox.
task put( singular message);
The message is any singular expression, including object handles.
If the mailbox was created with a bounded queue, the process shall be suspended until there is enough room in the queue.
The try_put() method attempts to place a message in a mailbox.
function int try_put( singular message);
The try_put() method stores a message in the mailbox in strict FIFO order. Meaningful only for bounded mailboxes. If the mailbox is full, the method returns 0.
The get() method retrieves a message from a mailbox.
task get( ref singular message );
The get() method retrieves one message from the mailbox, that is, removes one message from the mailbox queue. If the mailbox is empty, then the current process blocks until a message is placed in the mailbox.
try_get() method attempts to retrieves a message from a mailbox without blocking.
function int try_get( ref singular message );
The peek() method copies a message from a mailbox without removing the message from the queue.
task peek( ref singular message );
The peek() method copies one message from the mailbox without removing the message from the mailbox queue.
The try_peek() method attempts to copy a message from a mailbox without blocking.
function int try_peek( ref singular message );
Event
Nonblocking event trigger are supported in systemverilog using the ->> operator.
The basic mechanism to wait for an event to be triggered is via the event control operator, @.
@ hierarchical_event_identifier;
SystemVerilog can distinguish the event trigger itself, which is instantaneous. The triggered property is invoked using a method-like syntax:
hierarchical_event_identifier.triggered.
The triggered event property is most useful when used in the context of a wait construct:
wait ( hierarchical_event_identifier.triggered )
Tuesday, December 30, 2008
systemverilog wordfile
copied from http://avm-users.googlegroups.com/web/systemverilog.txt?hl=en&gsc=Lb4u6AsAAADWzOiV2TvclJOPyNlia6Gs
/L20"Verilog 1364-2001" Line Comment = // Block Comment On = /* Block Comment Off = */ String Chars = " File Extensions = SV SVL/Delimiters = ~!@%^&*()-+=|\/{}[]:;"<> , .?#/Function String = "%[a-z0-9]+[ ^t]+[a-z_0-9]+[ ^t]+("
/Indent Strings = "begin" "fork" "specify" "config"
/Unindent Strings = "end" "join" "join_any" "join_none" "endspecify" "endconfig"
/C1"Keywords"
alias always always_comb always_ff always_latch and assert assign assume automatic
before begin bind bins binsof bit break buf bufif0 bufif1 byte
case casex casez cell chandle class clocking cmos config const constraint context continue cover covergroup coverpoint cross
deassign default defparam design disable dist do
edge else end endcase endclass endclocking endconfig endfunction endgenerate endgroup endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask enum event expect export extends extern
final first_match for force foreach forever fork forkjoin function
generate genvar
highz0 highz1
if iff ifnone ignore_bins illegal_bins import incdir include initial inout input inside instance int integer interface intersect join
join_any join_none
large liblist library local localparam logic longint
macromodule matches medium modport module
nand negedge new nmos nor noshowcancelled not notif0 notif1 null
or output
package packed parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup pulsestyle_onevent pulsestyle_ondetect pure
rand randc randcase randsequence rcmos real realtime ref reg release repeat return rnmos rpmos rtran rtranif0 rtranif1
scalared sequence shortint shortreal showcancelled signed small solve specify specparam static string strong0 strong1 struct super supply0 supply1
table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior trireg type typedef
union unique unsigned use
var vectored virtual void
wait wait_order wand weak0 weak1 while wildcard wire with within wor
xnor xor
/C2"System"
** 'b 'B 'o 'O 'd 'D 'h 'H 'sb 'sB 'so 'sO 'sd 'sD 'sh 'sH 'Sb 'SB 'So 'SO 'Sd 'SD 'Sh 'SH
** _
$assertkill $assertoff $asserton $async$and$array $async$nand$array $async$or$array $async$nor$array $async$and$plane $async$nand$plane $async$or$plane $async$nor$plane
$bits $bitstoreal $bitstoshortreal
$cast $comment $countdrivers $countones
$date $dimensions $display $displayb $displayh $displayo $dist_chi_square $dist_erlang $dist_exponential $dist_normal $dist_poisson $dist_t $dist_uniform $dumpall $dumpflush $dumpfile $dumplimit $dumpoff $dumpon $dumpports $dumpportsall $dumpportsflush $dumpportslimit $dumpportsoff $dumpportson $dumpvars
$enddefinitions $error $exit
$fatal $fdisplay $fdisplayf $fdisplayb $fdisplayh $fdisplayo $fell $feof $ferror $fflush $fgetc $fgets $finish $fopen $fmonitor $fmonitorb $fmonitorf $fmonitorh $fmonitoro $fclose $fread $fscanf $fseek $fsscanf $fstrobe $fstrobeb $fstrobef $fstrobeh $fstrobeo $ftell $fullskew $fwrite $fwriteb $fwritef $fwriteh $fwriteo
$get_coverage $getpattern
$high $hold $history
$increment $incsave $info $input $isunbounded $isunknown $itor
$key
$left $list $load_coverage_db $log $low
$monitor $monitorb $monitorh $monitoro $monitoron $monitoroff
$nochange $nokey $nolog $onehot $onehot0
$past $period $printtimescale
$q_add $q_exam $q_full $q_initialize $q_remove $q_random
$random $readmemb $readmemh $realtime $realtobits $recovery $recrem $removal $reset $reset_count $reset_value $restart $rewind $right $root $rose $rtoi
$sampled $save $scale $scope $sdf_annotate $set_coverage_db_name $setup $setuphold $sformat $shortrealtobits $showvariables $showscopes $showvars $signed $size $skew $sreadmemb $sreadmemh $sscanf $stable $stime $stop $strobe $strobeb $strobeh $strobeo $swrite $swriteb $swriteh $swriteo $sync$and$array $sync$nand$array $sync$or$array $sync$nor$array $sync$and$plane $sync$nand$plane $sync$or$plane $sync$nor$plane
$test$plusargs $time $timeformat $timescale $timeskew $typename $typeof
$ungetc $unit $unpacked_dimensions $unsigned $upscope $urandom $urandom_range
$value$plusargs $var $vcdclose $version
$warning $width $write $writeb $writeh $writeo $writememb $writememh
/C3"Operators"
->
+:
-:
@
@*
*>
,
;
.*
{
}
+
-
// /
*
**
%
>
>=
>>
>>>
<
<=
<<
<<<
!
!=
!==
&
&&
|
||
=
==
===
^
^~
~
~^
~&
~|
?
:
|->
|=>
/C4"Directives"
** `
`begin_keywords
`accelerate `autoexepand_vectornets
`celldefine
`default_nettype `define `default_decay_time `default_trieg_distributed `default_trireg_strength `delay_mode_distributed `delay_mode_path `delay_mode_unit `delay_mode_zero
`else `elsif `endcelldefine `endif `end_keywords `endprotect `endprotected `expand_vectornets
`file
`ifdef `ifndef `include
`line
`noaccelerate `noexpand_vectornets `noremove_gatenames `noremove_netnames `nounconnected_drive
`pragma `protect `protected
`remove_gatenames `remove_netnames `resetall
`timescale
`unconnected_drive `undef `uselib
/C5"DelaysAndParameters"
#
##
/L20"Verilog 1364-2001" Line Comment = // Block Comment On = /* Block Comment Off = */ String Chars = " File Extensions = SV SVL/Delimiters = ~!@%^&*()-+=|\/{}[]:;"<> , .?#/Function String = "%[a-z0-9]+[ ^t]+[a-z_0-9]+[ ^t]+("
/Indent Strings = "begin" "fork" "specify" "config"
/Unindent Strings = "end" "join" "join_any" "join_none" "endspecify" "endconfig"
/C1"Keywords"
alias always always_comb always_ff always_latch and assert assign assume automatic
before begin bind bins binsof bit break buf bufif0 bufif1 byte
case casex casez cell chandle class clocking cmos config const constraint context continue cover covergroup coverpoint cross
deassign default defparam design disable dist do
edge else end endcase endclass endclocking endconfig endfunction endgenerate endgroup endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask enum event expect export extends extern
final first_match for force foreach forever fork forkjoin function
generate genvar
highz0 highz1
if iff ifnone ignore_bins illegal_bins import incdir include initial inout input inside instance int integer interface intersect join
join_any join_none
large liblist library local localparam logic longint
macromodule matches medium modport module
nand negedge new nmos nor noshowcancelled not notif0 notif1 null
or output
package packed parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup pulsestyle_onevent pulsestyle_ondetect pure
rand randc randcase randsequence rcmos real realtime ref reg release repeat return rnmos rpmos rtran rtranif0 rtranif1
scalared sequence shortint shortreal showcancelled signed small solve specify specparam static string strong0 strong1 struct super supply0 supply1
table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior trireg type typedef
union unique unsigned use
var vectored virtual void
wait wait_order wand weak0 weak1 while wildcard wire with within wor
xnor xor
/C2"System"
** 'b 'B 'o 'O 'd 'D 'h 'H 'sb 'sB 'so 'sO 'sd 'sD 'sh 'sH 'Sb 'SB 'So 'SO 'Sd 'SD 'Sh 'SH
** _
$assertkill $assertoff $asserton $async$and$array $async$nand$array $async$or$array $async$nor$array $async$and$plane $async$nand$plane $async$or$plane $async$nor$plane
$bits $bitstoreal $bitstoshortreal
$cast $comment $countdrivers $countones
$date $dimensions $display $displayb $displayh $displayo $dist_chi_square $dist_erlang $dist_exponential $dist_normal $dist_poisson $dist_t $dist_uniform $dumpall $dumpflush $dumpfile $dumplimit $dumpoff $dumpon $dumpports $dumpportsall $dumpportsflush $dumpportslimit $dumpportsoff $dumpportson $dumpvars
$enddefinitions $error $exit
$fatal $fdisplay $fdisplayf $fdisplayb $fdisplayh $fdisplayo $fell $feof $ferror $fflush $fgetc $fgets $finish $fopen $fmonitor $fmonitorb $fmonitorf $fmonitorh $fmonitoro $fclose $fread $fscanf $fseek $fsscanf $fstrobe $fstrobeb $fstrobef $fstrobeh $fstrobeo $ftell $fullskew $fwrite $fwriteb $fwritef $fwriteh $fwriteo
$get_coverage $getpattern
$high $hold $history
$increment $incsave $info $input $isunbounded $isunknown $itor
$key
$left $list $load_coverage_db $log $low
$monitor $monitorb $monitorh $monitoro $monitoron $monitoroff
$nochange $nokey $nolog $onehot $onehot0
$past $period $printtimescale
$q_add $q_exam $q_full $q_initialize $q_remove $q_random
$random $readmemb $readmemh $realtime $realtobits $recovery $recrem $removal $reset $reset_count $reset_value $restart $rewind $right $root $rose $rtoi
$sampled $save $scale $scope $sdf_annotate $set_coverage_db_name $setup $setuphold $sformat $shortrealtobits $showvariables $showscopes $showvars $signed $size $skew $sreadmemb $sreadmemh $sscanf $stable $stime $stop $strobe $strobeb $strobeh $strobeo $swrite $swriteb $swriteh $swriteo $sync$and$array $sync$nand$array $sync$or$array $sync$nor$array $sync$and$plane $sync$nand$plane $sync$or$plane $sync$nor$plane
$test$plusargs $time $timeformat $timescale $timeskew $typename $typeof
$ungetc $unit $unpacked_dimensions $unsigned $upscope $urandom $urandom_range
$value$plusargs $var $vcdclose $version
$warning $width $write $writeb $writeh $writeo $writememb $writememh
/C3"Operators"
->
+:
-:
@
@*
*>
,
;
.*
{
}
+
-
// /
*
**
%
>
>=
>>
>>>
<
<=
<<
<<<
!
!=
!==
&
&&
|
||
=
==
===
^
^~
~
~^
~&
~|
?
:
|->
|=>
/C4"Directives"
** `
`begin_keywords
`accelerate `autoexepand_vectornets
`celldefine
`default_nettype `define `default_decay_time `default_trieg_distributed `default_trireg_strength `delay_mode_distributed `delay_mode_path `delay_mode_unit `delay_mode_zero
`else `elsif `endcelldefine `endif `end_keywords `endprotect `endprotected `expand_vectornets
`file
`ifdef `ifndef `include
`line
`noaccelerate `noexpand_vectornets `noremove_gatenames `noremove_netnames `nounconnected_drive
`pragma `protect `protected
`remove_gatenames `remove_netnames `resetall
`timescale
`unconnected_drive `undef `uselib
/C5"DelaysAndParameters"
#
##
System Verilog by example by example
System Verilog by example(constraint, random, covergroup)
module top;
typedef enum bit { BAD_PARITY, GOOD_PARITY } parity_e;
class packet_c;
rand bit [5:0] pkt_length;
bit[63:0][7:0] pkt_payload;
bit[7:0] parity;
rand parity_e parity_type;
function bit [7:0] calc_parity();
calc_parity = { pkt_length, pkt_addr };
for (int i = 0; i calc_parity ^= pkt_payload[i];
endfunction :calc_parity
function void randomize_payload();
pkt_addr = $urandom ;
pkt_length = $urandom ;
for (int i=0; i < pkt_length; i ++)
pkt_payload[i]= $urandom;
endfunction:randomize_payload
function void post_randomize();
randomize_payload();
if (parity_type == GOOD_PARITY)
parity = calc_parity();
else
do
parity = $urandom;
while (parity == calc_parity());
endfunction:post_randomize
endmodule
class packet_c;
typedef enum bit { BAD_PARITY , GOOD_PARITY } parity_e;
typedef enum bit[1:0] { SMALL,MEDIUM, LARGE } payload_e;
constraint c { parity_type == GOOD_PARITY ;}
constraint c1 { payload_type == LARGE ;}
constraint c3 { pkt_addr == 2; }
constraint length_range {
(payload_type == SMALL) -> pkt_length inside { [1 : 20] };
(payload_type == MEDIUM) -> pkt_length inside { [21 : 44]};
(payload_type == LARGE) -> pkt_length inside { [45 : 63]};
}
// Define the Coverage module for the packet defined
covergroup cg @ (pkt_event);
coverpoint pkt_length {
bins usb_range = {[0 : 20]};
bins pci_range = {[21 : 44]};
bins ahb_range = {[45 : 63 ]};
}
coverpoint pkt_addr;
coverpoint parity;
endgroup
module top;
typedef enum bit { BAD_PARITY, GOOD_PARITY } parity_e;
class packet_c;
rand bit [5:0] pkt_length;
bit[63:0][7:0] pkt_payload;
bit[7:0] parity;
rand parity_e parity_type;
function bit [7:0] calc_parity();
calc_parity = { pkt_length, pkt_addr };
for (int i = 0; i
endfunction :calc_parity
function void randomize_payload();
pkt_addr = $urandom ;
pkt_length = $urandom ;
for (int i=0; i < pkt_length; i ++)
pkt_payload[i]= $urandom;
endfunction:randomize_payload
function void post_randomize();
randomize_payload();
if (parity_type == GOOD_PARITY)
parity = calc_parity();
else
do
parity = $urandom;
while (parity == calc_parity());
endfunction:post_randomize
endmodule
class packet_c;
typedef enum bit { BAD_PARITY , GOOD_PARITY } parity_e;
typedef enum bit[1:0] { SMALL,MEDIUM, LARGE } payload_e;
constraint c { parity_type == GOOD_PARITY ;}
constraint c1 { payload_type == LARGE ;}
constraint c3 { pkt_addr == 2; }
constraint length_range {
(payload_type == SMALL) -> pkt_length inside { [1 : 20] };
(payload_type == MEDIUM) -> pkt_length inside { [21 : 44]};
(payload_type == LARGE) -> pkt_length inside { [45 : 63]};
}
// Define the Coverage module for the packet defined
covergroup cg @ (pkt_event);
coverpoint pkt_length {
bins usb_range = {[0 : 20]};
bins pci_range = {[21 : 44]};
bins ahb_range = {[45 : 63 ]};
}
coverpoint pkt_addr;
coverpoint parity;
endgroup
Sunday, November 30, 2008
coverage
cited from http://www.ovmworld.org/forums/showthread.php?t=121
Code coverage: This will give information about how many lines are exected, how many times expressions, branches executed. This coverage is collected by the simulation tools. Users use this coverage to reach those corner cases which are not hit by the random testcases. Users have to write the directed testcases to reach the missing code covearage areas.
Functional coverage: This coverage will be defined by the user. User will define the coverage points for the functions to be covered in DUT. This is completly under user control. like covergroup definition defined in SV
Both of them have equal importance in the verification. 100% functional coverage does not mean that the DUT is completly exercised and vice-versa. Verification engineers will consider both coverages to measure the verifcation progress.
Coverage tool
All the HVL simulators have Functional Coverage tool with it.You have to write coverage code and then switch ON the coverage during simulation.
And use a coverage viewing tool (again, the same EDA company will have it) to view the coverage.
For Cadence IES/IUS:
1. For switching coverage ON:Use +nccovfile+dut_cov.txt while compiling.
The content of dut_cov.txt is:
select_coverage -all -module top
...
select_functional
select_fsm
During simulation use:-covoverwrite -covtest mycov.cov
2. To view coverage:
Do:
iccr -keywords+detail iccr.cmd
or:
iccr -keywords+summary iccr.cmd
or:
iccr -keywords+dontmerge iccr.cmd
The respective content of iccr.cmd is:
load_test cov_work/design/*merge * -output ALL
reset_coverage
load_test cov_work/design/ALL
report_detail -instance -betsafd -cgopt top... > detail.rpt
load_test cov_work/design/*merge * -output ALL
reset_coverage
load_test cov_work/design/ALL
report_summary -instance -cgopt top... > summary.rpt
load_test cov_work/design/*
report_summary -instance -cgopt top... > summary.rpt
There is a coverage quick start guide included with IUS as well in order to get you started. Search for "icc quick start guide" in cdnshelp
Code coverage: This will give information about how many lines are exected, how many times expressions, branches executed. This coverage is collected by the simulation tools. Users use this coverage to reach those corner cases which are not hit by the random testcases. Users have to write the directed testcases to reach the missing code covearage areas.
Functional coverage: This coverage will be defined by the user. User will define the coverage points for the functions to be covered in DUT. This is completly under user control. like covergroup definition defined in SV
Both of them have equal importance in the verification. 100% functional coverage does not mean that the DUT is completly exercised and vice-versa. Verification engineers will consider both coverages to measure the verifcation progress.
Coverage tool
All the HVL simulators have Functional Coverage tool with it.You have to write coverage code and then switch ON the coverage during simulation.
And use a coverage viewing tool (again, the same EDA company will have it) to view the coverage.
For Cadence IES/IUS:
1. For switching coverage ON:Use +nccovfile+dut_cov.txt while compiling.
The content of dut_cov.txt is:
select_coverage -all -module top
...
select_functional
select_fsm
During simulation use:-covoverwrite -covtest mycov.cov
2. To view coverage:
Do:
iccr -keywords+detail iccr.cmd
or:
iccr -keywords+summary iccr.cmd
or:
iccr -keywords+dontmerge iccr.cmd
The respective content of iccr.cmd is:
load_test cov_work/design/*merge * -output ALL
reset_coverage
load_test cov_work/design/ALL
report_detail -instance -betsafd -cgopt top... > detail.rpt
load_test cov_work/design/*merge * -output ALL
reset_coverage
load_test cov_work/design/ALL
report_summary -instance -cgopt top... > summary.rpt
load_test cov_work/design/*
report_summary -instance -cgopt top... > summary.rpt
There is a coverage quick start guide included with IUS as well in order to get you started. Search for "icc quick start guide" in cdnshelp
Tuesday, November 18, 2008
systemverilog keywords supported by synplify
Supported SystemVerilog Keywords:
always_comb, always_ff, always_latch, assert, bit byte, const, do, endinterface, enum, import, int, interface, logic, longint, modport, packed, priority, shortint, struct, typedef, unique.
Unsupported SystemVerilog Keywords:
assume, break, continue, endproperty, endsequence, expect, property, return, sequence, timeprecision, timeunit, union, void.
always_comb, always_ff, always_latch, assert, bit byte, const, do, endinterface, enum, import, int, interface, logic, longint, modport, packed, priority, shortint, struct, typedef, unique.
Unsupported SystemVerilog Keywords:
assume, break, continue, endproperty, endsequence, expect, property, return, sequence, timeprecision, timeunit, union, void.
Wednesday, November 12, 2008
systemverilog/ovm training
OVM overview
Data items represent the input to the DUT. Examples include networking packets, bus transactions, andinstructions
Driver(BFM): A driver is an active entity that emulates logic that drives the DUT. A typical driver repeatedly receivesa data item and drives it to the DUT by sampling and driving the DUT signals.
A sequencer is an advanced stimulus generator that controls the items that are provided to the driverfor execution.
A monitor is a passive entity that samples DUT signals but does not drive them. Monitors collectcoverage information and perform checking.
Agent: Sequencers, drivers, and monitors can be reused independently. OVM recommends that environment developers create a more abstract container, agent to emulate and verify DUTdevices. They encapsulate a driver, sequencer, and monitor. Active agents emulate devices and drive transactions according totest directives. Passive agents only monitor DUT activity.
Environment: The environment (env) is the top-level component of the OVC. It contains one or more agents, as wellas other components such as a bus monitor.
to start a general verification process
create a base class for pattern generation
define the control signals
define utility functions
define default constraint for each control signal, e.g. checker, printer..
create a class that inherits the base class
define specific contraints for control signals (if necessary, disable base class's constraints)
ovm provides additional features:
printing
packing
transaction layer recording
...
0. basic functions and usage
** my_class_inst.print(); // print name, type, size, value of vars
** class_inst1.set_name("inst_tst"); // rename the class
** $cast(class_inst2, class_inst1.clone()); // clone
** void '(begin_tr(class_inst); //start of transaction recording
//body
end_tr(class_inst)); //end of recording
1. class definition keyword and usage
** `ovm_object_utils_begin(my_classname)
`ovm_field_int( my_int_var, OVM_ALL_ON)
`ovm_field_enum( my_enum_typename, my_enum_var, OVM_ALL_ON + OVM_NOCOMPARE)
...
`ovm_object_utils_end
== description
** `ovm_object_utils macro implements a set of utility functions for OVM objects: get_type_name() and create() methods implemented, print(), clone(), etc are configured.
** `ovm_field_* macros specify the automation requirements for each field of the data item
** OVM_ALL_ON Turns on the COPY, COMPARE, PRINT, RECORD, PACK , UNPACK and DEEP flags
OVM Message Control
`message(, ( ) )
is a formatted string with arguments similar to $display = OVM_NONE, OVM_LOW, OVM_MEDIUM, OVM_HIGH, OVM_FULL
OVM_LOW shows test scope
Three ways to change verbosity:
1.+MSG_DETAIL argument to irun% irun …. +MSG_DETAIL=NONE
The default verbosity is OVM_LOW
2.In the test:set_report_verbosity_level(int VERBOSITY);
3.TCL APIovm_message command
OVM Data Item
class uart_frame extends ovm_sequence_item;
OVM Sequences
Derived from ovm_sequence base class
Use the `ovm_sequence_utils macro to associate the sequence with the relevant sequencertype and to declare the various automation utilities.
e.g.: class rand_retry_seq extends ovm_sequence;
`over_do
An object is created using the factory settings and assigned to the specifiedvariable. Based on the processing, when the driver requests an item from thesequencer, the item is randomized and provided to the driver.
`over_do_with
Similiar to `over_do. This enables adding different inline constraints, while still using the same item or sequence variable.
The body() task is the actual logic of the sequence.
[0] ovm_random_sequence executes a random number of sequences(does not call itself)
[1] ovm_exhaustive_sequence randomly executes each defined sequence without repetition until all are executed(does not call random or itself)
[2] ovm_simple_sequence executes a single data transaction Default_sequence = ovm_random_sequence
sequence flow
`ovm_do(subsequence);
Call pre_do() task with is_item = 0
Call mid_do()
trigger subsequence.started
Call subsequence.body()
trigger subsequence.ended
Call post_do()
End of do subsequence
The Driver (BFM)
class uart_tx_driver extends ovm_driver;
`ovm_sequence_item item;
uart_frame this_tx_frame;
`ovm_component_utils(uart_tx_driver)
agent
Agents provide all the verification logic for a device in the system. Instantiation and connection logic is done by the developer in a standard manner
–Integrator does not need to worry about this.
Agents share a common configuration or common signals
to add a user defined phase, derive a subclass of ovm_phase that implements either the call_task() or call_funcmethod, depending on whether the new phase is to be time-consuming (a task) or not (a function). Register the phase with the OVM phase controller, ovm_top.
Creating and Adding a New Sequence
To create a user-defined sequence:
1. Derive a sequence from the ovm_sequence base class.
2. Use the `ovm_sequence_utils macro to associate the sequence with the relevant sequencer type and to declare the various automation utilities.
This macro is similar to the`ovm_object_utils macro (and its variations) except that it takes another argument, whichis the sequencer type name this sequence is associated with. This macro also provides ap_sequencer variable that is of the type specified by the second argument of the macro. This allows access to derived type-specific sequencer properties.
3. Implement the sequence's body task with the specific scenario you want the sequence to execute.
In the body, you can execute data items and other sequences using “`ovm_do” and“`ovm_do_with”.
Executing Multiple Sequences Concurrently
There are two ways you can create concurrently-executing sequences:
• Using the ovm_do Macros with fork/join.
• Starting Several Sequences in Parallel using the start() method.
Using the ovm_do Macros with fork/join
e.g.:
a_seq a;
b_seq b;
virtual task body();
fork
`ovm_do(a)
`ovm_do(b)
join
endtask : body
Starting Several Sequences in Parallel
a_seq a;
b_seq b;
virtual task body();// Initialize the sequence variables with the factory.
`ovm_create(a)
`ovm_create(b)// Start each subsequence as a new thread.
fork
a.start(p_sequencer);
b.start(p_sequencer);
join
endtask : body
Randomizing the Kind of Generated Sequences
The use of `ovm_sequence_utils registers a sequence type with a particular sequencer’s sequence library. The seq_kind property is used to identify a specific type in the sequence library based on the sequence type. For example, get_seq_kind(“simple_seq_do”) returns an integer that can be used to identify the sequence type simple_seq_do.
A test name is provided to run_test() via a simulator command-line argument. If the top modulecalls run_test() without an argument, the +OVM_TESTNAME=test_name simulator command-line argument is always checked. otherwise a default test_name must be provided.
target side:
Data items represent the input to the DUT. Examples include networking packets, bus transactions, andinstructions
Driver(BFM): A driver is an active entity that emulates logic that drives the DUT. A typical driver repeatedly receivesa data item and drives it to the DUT by sampling and driving the DUT signals.
A sequencer is an advanced stimulus generator that controls the items that are provided to the driverfor execution.
A monitor is a passive entity that samples DUT signals but does not drive them. Monitors collectcoverage information and perform checking.
Agent: Sequencers, drivers, and monitors can be reused independently. OVM recommends that environment developers create a more abstract container, agent to emulate and verify DUTdevices. They encapsulate a driver, sequencer, and monitor. Active agents emulate devices and drive transactions according totest directives. Passive agents only monitor DUT activity.
Environment: The environment (env) is the top-level component of the OVC. It contains one or more agents, as wellas other components such as a bus monitor.
to start a general verification process
create a base class for pattern generation
define the control signals
define utility functions
define default constraint for each control signal, e.g. checker, printer..
create a class that inherits the base class
define specific contraints for control signals (if necessary, disable base class's constraints)
ovm provides additional features:
printing
packing
transaction layer recording
...
0. basic functions and usage
** my_class_inst.print(); // print name, type, size, value of vars
** class_inst1.set_name("inst_tst"); // rename the class
** $cast(class_inst2, class_inst1.clone()); // clone
** void '(begin_tr(class_inst); //start of transaction recording
//body
end_tr(class_inst)); //end of recording
1. class definition keyword and usage
** `ovm_object_utils_begin(my_classname)
`ovm_field_int( my_int_var, OVM_ALL_ON)
`ovm_field_enum( my_enum_typename, my_enum_var, OVM_ALL_ON + OVM_NOCOMPARE)
...
`ovm_object_utils_end
== description
** `ovm_object_utils macro implements a set of utility functions for OVM objects: get_type_name() and create() methods implemented, print(), clone(), etc are configured.
** `ovm_field_* macros specify the automation requirements for each field of the data item
** OVM_ALL_ON Turns on the COPY, COMPARE, PRINT, RECORD, PACK , UNPACK and DEEP flags
OVM Message Control
`message(
OVM_LOW shows test scope
Three ways to change verbosity:
1.+MSG_DETAIL argument to irun% irun …. +MSG_DETAIL=NONE
The default verbosity is OVM_LOW
2.In the test:set_report_verbosity_level(int VERBOSITY);
3.TCL APIovm_message command
OVM Data Item
class uart_frame extends ovm_sequence_item;
OVM Sequences
Derived from ovm_sequence base class
Use the `ovm_sequence_utils macro to associate the sequence with the relevant sequencertype and to declare the various automation utilities.
e.g.: class rand_retry_seq extends ovm_sequence;
`over_do
An object is created using the factory settings and assigned to the specifiedvariable. Based on the processing, when the driver requests an item from thesequencer, the item is randomized and provided to the driver.
`over_do_with
Similiar to `over_do. This enables adding different inline constraints, while still using the same item or sequence variable.
The body() task is the actual logic of the sequence.
[0] ovm_random_sequence executes a random number of sequences(does not call itself)
[1] ovm_exhaustive_sequence randomly executes each defined sequence without repetition until all are executed(does not call random or itself)
sequence flow
`ovm_do(subsequence);
Call pre_do() task with is_item = 0
Call mid_do()
trigger subsequence.started
Call subsequence.body()
trigger subsequence.ended
Call post_do()
End of do subsequence
The Driver (BFM)
class uart_tx_driver extends ovm_driver;
`ovm_sequence_item item;
uart_frame this_tx_frame;
`ovm_component_utils(uart_tx_driver)
agent
Agents provide all the verification logic for a device in the system. Instantiation and connection logic is done by the developer in a standard manner
–Integrator does not need to worry about this.
Agents share a common configuration or common signals
A Standard agent has:
–Sequencer for generating traffic
–Driver to drive the DUT
–Monitor
e.g.
class master_agent extends ovm_agent;
master_driver driver;
master_sequencer sequencer;
master_monitor monitor;
–Sequencer for generating traffic
–Driver to drive the DUT
–Monitor
e.g.
class master_agent extends ovm_agent;
master_driver driver;
master_sequencer sequencer;
master_monitor monitor;
virtual function void build();
virtual function void connect();
endclass
OVM Simulation Phases
OVM Built-in Phases – run in order
build Build Top-Level Testbench Topology
connect Connect environment topology
start_of_simulation Configure verification components
end_of_elaboration Post-elaboration activity (e.g. print topology)
end_of_elaboration Post-elaboration activity (e.g. print topology)
run task - Run-time execution of the test
extract Gathers details on the final DUT state
check Processes and checks the simulation results.
report Simulation results analysis and reporting
to add a user defined phase, derive a subclass of ovm_phase that implements either the call_task() or call_funcmethod, depending on whether the new phase is to be time-consuming (a task) or not (a function). Register the phase with the OVM phase controller, ovm_top.
Creating and Adding a New Sequence
To create a user-defined sequence:
1. Derive a sequence from the ovm_sequence base class.
2. Use the `ovm_sequence_utils macro to associate the sequence with the relevant sequencer type and to declare the various automation utilities.
This macro is similar to the`ovm_object_utils macro (and its variations) except that it takes another argument, whichis the sequencer type name this sequence is associated with. This macro also provides ap_sequencer variable that is of the type specified by the second argument of the macro. This allows access to derived type-specific sequencer properties.
3. Implement the sequence's body task with the specific scenario you want the sequence to execute.
In the body, you can execute data items and other sequences using “`ovm_do” and“`ovm_do_with”.
Executing Multiple Sequences Concurrently
There are two ways you can create concurrently-executing sequences:
• Using the ovm_do Macros with fork/join.
• Starting Several Sequences in Parallel using the start() method.
Using the ovm_do Macros with fork/join
e.g.:
a_seq a;
b_seq b;
virtual task body();
fork
`ovm_do(a)
`ovm_do(b)
join
endtask : body
Starting Several Sequences in Parallel
a_seq a;
b_seq b;
virtual task body();// Initialize the sequence variables with the factory.
`ovm_create(a)
`ovm_create(b)// Start each subsequence as a new thread.
fork
a.start(p_sequencer);
b.start(p_sequencer);
join
endtask : body
Randomizing the Kind of Generated Sequences
The use of `ovm_sequence_utils registers a sequence type with a particular sequencer’s sequence library. The seq_kind property is used to identify a specific type in the sequence library based on the sequence type. For example, get_seq_kind(“simple_seq_do”) returns an integer that can be used to identify the sequence type simple_seq_do.
A test name is provided to run_test() via a simulator command-line argument. If the top modulecalls run_test() without an argument, the +OVM_TESTNAME=test_name simulator command-line argument is always checked. otherwise a default test_name must be provided.
Virtual sequencer
with virtual sequencer, we can
1. provide sequence to multiple channels that need sequences
2. timing the sequences between channels
how to do:
1. define virtual sequencer class
1.1. define virtual sequencer class that derives from ovm_virtual_sequencer class
note: use `ovm_update_sequencer_lib to register in new() function
1.2. define 1 or more sequence consumer interfaces (to connect to interface sequencers)
use add_seq_cons_if("my_name") in build() function to generate interface
these consumer interfaces has built-in function named seq_cons_if(), which can be connected to seq_prod_if of normal sequencer
1.3 instantiate normal sequencer to be attached to
2. define virtual sequences class
each virtual sequence has all possible instance of interface sequences
the instances of interface sequence are activated in virtual task body() using `ovm_do_seq(seq_name, p_sequencer.seq_cons_if["myname"])
in this way, virtual sequencer take the virtual sequence interface as output explicitly
3. define tb class (extends ovm_threaded_component or ovm_env?) to
connect virtual sequencer to interface sequencer in the testbench(sve, tb, etc)
3.0 the tb class may extend directly from previous class with all env but without virtual sequencer to simply the process
3.1. instantiate the virtual sequencer
e.g.: simple_vsequencer vsequencer0;
and build it in the function build()
3.2. connect virtual sequencer's sequence consumer interfaces to the interface sequencers in virtual function connect()
e.g.: agent0.sequencer.seq_prod_if.connect_if(vsequencer0.seq_cons_if["bar"]);
4. define a class extends ovm_test
instantiate the tb class
invoke a virtual sequence
use task set_config_string(), set_config_int() in function build() to configure the virtual sequencer
use following command in task run() to print info
use following command in task run() to print info
ovm_factory::print_all_overrides();
ovm_print_topology();
ovm_print_topology();
TLM
TLM – Transaction Level Modeling
TLM is used for Architecture design and (performance) analysis
Interfaces = API’s
Interfaces = API’s
interface types
Put interfaces
tlm_blocking_put_if #(type T=int)
tlm_nonblocking_put_if
tlm_put_if
Get interfaces
tlm_blocking_get_if
tlm_nonblocking_get_if
tlm_get_if
Peek interfaces
tlm_blocking_peek_if
tlm_nonblocking_peek_if
tlm_peek_if
Transport interfaces
tlm_blocking_transport_if #(type REQ=int, type RSP=int)
Analysis interface
analysis_if #(type T=int) non_blocking, broadcast
port vs export
initiator vs target
e.g.
initiator side:
class yapp_m_monitor extends ovm_monitor;
ovm_analysis_port #(yapp_packet) ingress_out= new(“ingress_out", this);
ingress_out.write(collected_packet);
target side:
class sys_monitor extends ovm_threaded_component;
`ovm_analysis_imp_decl(_ingress)
ovm_analysis_imp_ingress#(yapp_packet, sys_mon) ingress_in = new(“sys_mon”, this);
function write_ingress(input yapp_packet packet);
…
endfunction
ovm_analysis_imp_ingress#(yapp_packet, sys_mon) ingress_in = new(“sys_mon”, this);
function write_ingress(input yapp_packet packet);
…
endfunction
testbench side:
class yapp_router_testbench extends ovm_threaded_component;
virtual function void connect();
input_uvc.master.monitor.ingress_out.connect(router_mod_uvc.sys_mon.ingress_in);
endfunction
Subscribe to:
Posts (Atom)