<<

SystemVerilog • extended tasks and functions • -like void functions

• pass by reference Ming-Hwa Wang, Ph.. • default arguments COEN 207 SoC (System-on-Chip) Verification • argument binding by name Department of Computer Engineering • optional arguments Santa Clara University • import/export function for DPI

• classes: object-oriented mechanism (abstraction, encapsulation, safe Introduction pointers) SystemVerilog is a standard (IEEE std 1800-2005) unified hardware design, • automatic testbench support with random constraints specification, and verification language, which provides a of extensions to • interprocess communication synchronization the IEEE 1364 HDL: • semaphores • design specification method for both abstract and detailed specifications • mailboxes • embedded assertions language and application programming extension, event variables, and event sequencing (API) for coverage and assertions • clarification and extension of the scheduling semantics • testbench language based on manual and automatic methodologies • cycle-based functionality: clocking blocks and cycle-based attributes • direct programming interface (DPI) • cycle-based signal drives and samples Purpose: provide a standard which improves productivity, readability, and • synchronous samples reusability of Verilog-based code, extends for higher level of abstraction for • race-free program context system modeling and verification, provides extensive support for directed • assertion mechanism and constrained-random testbench development, coverage-driven • property and sequence declarations verification, and formal assertion-based verification • assertions and coverage statements with action blocks

• extended hierarchy support Extensions to Verilog • packages for declaration encapsulation with import for controlled • extended data types access • : int, , struct, union, enum • compilation-unit nested modules and extern modules for • other data types: bounded queues, logic (0, 1, X, Z) and (0, 1), separation compilation support tagged unions • extension of port declarations to support interfaces, events, and • dynamic data types: string, class, dynamic queues, dynamic arrays, variables associated arrays including automatic • $root to provide unambiguous access using hierarchical references • dynamic casting and bit- casting • interfaces to encapsulate communication and facilitate communication- • automatic/ specification on per-variable-instance basis oriented design • extended operators • functional coverage • wild equality and inequality • DPI for clean, efficient interoperation with other languages (C provided) • built-in methods to extend the language • assertion API • operator overloading • coverage API • streaming operators • data read API • set membership • Verilog procedure interface (VPI) extension for SystemVerilog constructs • extended procedural statements • concurrent assertion formal semantics • on selection statements

• loop statements • Extended Literal Values C-like jump statements: return, break, continue • • integer literals and logic literals final blocks that execute at the end of simulation (inverse of initial) • • unsized literal with a preceding apostrophe ( ’), e.g., extended event control and sequence events ’0, ’1, ’X, ’x, ’Z, ’z // sets all to this value • extended process control • real literals: fixed-point format or exponent format • extensions to always blocks to include synthesis consistent • time literals: s, ms , us , ns , ps , fs , step simulation semantics • string literals enclosed in quotes: \v for vertical tab, \f for form feed, • extensions to fork … join to model pipelines \a for bell, \x02 for hex number • fine-gram process control • array literals: replicate operator ( {{}} ), index/type keys and default • chandles can be inserted into associative arrays, can be used within values, e.g., a class, can be passed as arguments to functions or tasks, and can int n[1:2][1:3] = ‘{‘{0,1,2}, ‘{3{4}}}; be returned from functions int m[1,2][1,6] = '{2{'{3{4,5}}}}; • chandles shall not be assigned to variables of any other type, shall // same as '{'{4,5,4,5,4,5},'{4,5,4,5,4,5}} not be used as follows: as ports, in sensitivity lists or event typedef int triple [1:3]; $mydisplay(triple'{0,1,2}); expressions, in continuous assignments, in untagged unions, in triple b = '{1:1, default:0}; // indexes 2 and 3 assigned 0 packed types • structure literals, e.g., • string : variable length array of indexed from 0 typedef struct {int a; shortreal b;} ab; • string operators: ==, !=, <, <=, >, >=, {str1, str2, …, strN), ab c = '{0, 0.0}; /* same as c = '{a:0, b:0.0}; c = '{default:0}; or c = ab'{int:0, shortreal:0.0}; */ {multiplier{str}}, str[index], string.method(…) • ab abarr[1:0] = '{'{1, 1.0}, '{2, 2.0}}; str.method(…): len( ), putc(int index, c), getc(int index), typedef struct {int a,b[4];} ab_t; toupper( ), tolower( ), compare(string s), icompare(string s), int a,b,c; substr(int i, int j), atoi( ), atohex( ), atooct( ), atobin( ), atoreal( ), ab_t v1[1:0] [2:0] = '{2{'{3{a,'{2{b,c}}}}}}; itoa(integer i), hextoa(integer i), atoreal( ), octtoa(integer i), // expands to '{'{3{'{a,{2{b,c}}}}}, '{3{{a,'{2{b,c}}}}}} bintoa(integer i), realtoa(real r) /* expands to • event : event variables can be explicitly triggered and '{'{'{a,'{2{b,c}}},'{a,'{2{b,c}}},'{a,'{2{b,c}}}}, waited for '{'{a,'{2{b,c}}},'{a,'{2{b,c}}},'{a,'{2{b,c}}} } } */ • syntax: event [= ( | null ) ]; /* expands to • user-defined types: typedef (forward definition and actual definition) '{'{'{a,'{b,c,b,c}},'{a,'{b,c,b,c}},'{a,'{b,c,b,c}}}, • enumeration data types with strong type checking '{'{a,'{b,c,b,c}},'{a,'{b,c,b,c}},'{a,'{b,c,b,c}}}} */ • methods: first( ), last( ), next(int unsigned i=1), prev(int unsigned

i=1), num( ), name(int unsigned i) Data Types • structures and unions A data type is a set of values and a set of operations that can be performed • packed and unpacked, signed and unsigned, 2-state and 4-state on those values. Data types can be used to declare data objects or to define • a saves a value and a tag (or a member name) for user-defined data types that are constructed from other data types. strong type access checking • integer types • class is declared using the class … endclass keywords • 2-state - can simulate faster and take less memory: shortint (16-bit • class properties signed), int (32-bit signed), longint (64-bit signed), byte (8-bit • methods signed or ASCII ), bit (unsigned with user-defined vector • casting: a data type can be changed by using a cast (‘) operation size) • static casting • 4-state - can have unknown (‘x) and high-impedance (‘z) values: • ‘ ( ) or ‘ { { , …, logic (unsigned with user-defined vector size), reg (unsigned with } } user-defined vector size), integer (32-bit signed), time (64-bit • ‘ ( ) unsigned) • signed ‘ ( ) • integral types - the data types that can represent a single basic integer • $shortrealtobits, $bitstoshortreal, $bits, $itor, $rtoi, $bitstoreal, data type: packed array , packed struct , packed union , enum, time . $realtobits, $signed, $unsigned A simple bit vector type is the data types that can directly represent a • dynamic casting: $cast one-dimensional packed array of bits. • bit-stream casting • real types: real (64-bit signed), shortreal (32-bit signed) • for converting between different aggregate types • void data type - for function returns nothing or represent nonexistent • example data uses bit-stream casting to model a control packet transfer over a • chandle data type - for storing pointers passed using DPI (default null ) • data stream: only allow the following operation with another chandle variable or typedef struct { null or Boolean values: equality ( == ), inequality ( != ), case equality shortint address; (=== ), case inequality ( !== ) reg [3:0] code; • only allow assignment from another chandle or null byte command [2]; } Control; typedef bit Bits [36:1]; Control p; • uses part-select to refer to a selection of one or more contiguous bits of Bits stream[$]; a single dimension packed array, use slice to refer to a selection of one p = ... // initialize control packet or more contiguous elements of an array // append packet to unpacked queue of bits • array querying functions: $left, $right, $low, $high, $increment, $size, stream = {stream, Bits'(p)} $dimensions, and $unpacked_dimensions Control q; • dynamic arrays: any dimension of an unpacked array whose size can be // convert stream back to a Control packet q = Control'(stream[0]); set or changed at run time • stream = stream[1:$]; // remove packet from stream new [ expression ] [ ( expression ) ] • uses bit-stream casting to model a data packet transfer over a byte size( ) • stream: delete( ) typedef struct { • array assignment between fixed-size arrays and dynamic arrays byte length; • arrays as arguments: pass by value shortint address; • associative arrays byte payload[]; • indexing operator: wildcard index type *, string index, class index, byte chksum; integer or int index, signed packed array index, unsigned packed } Packet; array index, packed struct index, user-defined type index function Packet genPkt(); • methods: num( ), delete( [ input index] ), exists( input index), Packet p; first( ref index), last( ref index), next( ref index), prev( ref index) void'( randomize( p.address, p.length, p.payload ) • assignment

with { p.length > 1 && p.payload.size == p.length; } • associative arrays are passed as arguments ); • associative array literals use the ‘ {index:value} syntax, index can p.chksum = p.payload.xor(); be default return p; • endfunction queues with position 0 represents the first element, and $ represent the last The byte stream is modeled using a queue, and a bit-stream cast is • queues are declared using the same syntax as unpacked arrays, but used to send the packet over the stream. typedef byte channel_type[$]; specifying $ as the array size channel_type channel; • empty queue { } channel = {channel, channel_type'(genPkt())}; • right bound [$:N], where N+1 is the maximum size of the queue And the code to receive the packet: • operators: indexing, concatenation, slicing, equality Packet p; • methods: size( ), insert( input int index, input type item), int size; delete( int index), pop_front( ), pop_back( ), push_front( input type size = channel[0] + 4; item), push_back( input type item), // convert stream to Packet • array manipulation methods p = Packet'( channel[0 : size - 1] ); • syntax: expr .array_method { attribute_instance } [ ( arguments ) ] // remove packet data from stream [ with ( expr ) ] channel = channel[ size, $ ]; • array locator methods: find( ), find_index( ), find_first( ), find_first_index( ), find_last( ), find_last_index( ), min( ), max( ), Arrays unique( 0, unique_index( ) • in Verilog, all data types can be declared as arrays • array ordering methods: reverse( ), sort( ), rsort( ), shuffle( ) • a dimension declared before the object name is referred to as the vector • array reduction methods: sum( ), product( ), and( ), or( ), xor( ) width dimension, and the dimensions declared after the object name are • index querying: index( ) referred to as the array dimensions • SystemVerilog uses the term packed array to refer to the dimensions Data Declarations declared before the object name, and the term unpacked array is used • data have to be declared before they are used, except implicit nets to refer to the dimensions declared after the object name; a packed • forms of data: literals, parameters, constants (genvars parameters, array is guaranteed to be represented as a contiguous set of bits, and an localparams, specparams), variables (static or dynamic), nets (reg, wire, unpacked array may or may not be so represented logic), attributes • multi-dimensional arrays • constants • 3 constructs for defining elaboration-time constants: the • constructor new ( ) parameter , localparam and specparam; the default value of a • static class properties shared by all instances of the class using static parameter of an instantiated module can be overridden in each • static class method with lifetime: static task foo( ); instance of the module using one of the following: … end task • implicit in-line parameter redefinition (e.g., foo #(value, value) • nonstatic class method with lifetime: task static foo( ); … u1 (...); ) end task • explicit in-line parameter redefinition (e.g., foo #(.name(value), • shallow copy (putting an object after new ) v.s. deep copy (custom code .name(value)) u1 (...); ) is typically needed) • defparam statements, using hierarchical path names to redefine • this and super each parameter • it is always legal to assign a subclass variable to a variable of a class • value parameters: a module, interface, program, or class can have higher in the inheritance , but it is never legal to directly assign a parameters, which are set during elaboration and are constant superclass variable to a variable of one of its subclasses; it is legal to during simulation assign a superclass handle to a subclass variable if the superclass handle • $ as a parameter value to represent unbounded range specification refers to an object of the given subclass, and use $cast( ) to check • $isunbounded(const_expr) whether the assignment is legal • type parameters: parameter type • unqualified (public), local (private), and protected • parameter port lists: the parameter keyword can be omitted, and a • const : read-only parameter can be depend on earlier parameter • global constants with initial values (optionally with static ), instance • const constants are set during simulation constants without • variables declared with var have default type of logic • abstract class using virtual type default • polymorphism 4-state integral ‘X • class scope resolution operator :: 2-state integral ‘0 • the extern qualifier for out-of-block declarations real, shortreal 0.0 • parameterized classes enumeration base type default initial value • the combination of a generic class and the actual parameter values string “” (empty string) is called a specialization (or variant) • event new event typedef class: for cross-referencing • class null memory management: automatic garbage collection

chandle (opaque handle) null Operators and Expressions • nets: trireg , wire , reg • assignment_operator ::= = | += | -= | *= | /= | %= | &= | |= | ^= • a net can be written by continuous assignments, by primitive output, | <<= | >>= | <<<= | >>>= or through module port • conditional_expression ::= cond_predicate ? { attribute_instance } • assign , force , release expression : expression • scope and lifetime: automatic and static • unary_operator ::= + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~ • global and static, local and static, local and automatic • binary_operator ::= + | - | * | / | % | == | != | === | !== | ==? | • signal aliasing: the members of an alias list are signals whose bits share !=? | && | || | ** | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << the same physical nets, aliasing is performed at elaboration time and | >>> | <<< can’t be undone • inc_or_dec_operator ::= ++ | -- • type compatibility: 5 levels • unary_module_path_operator ::= ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~ • matching type: typedef , anonymous enum, struct , or union • binary_module_path_operator ::= == | != | && | || | & | | | ^ | ^~ | • equivalent type ~^ • assignment compatible: have implicit casting rules • built-in package: std:: • cast compatible: have explicit casting rules • concatenation using braces ( { } ) or replication operator (multiple • nonequivalent or type incompatible concatenation) • type operator • assignment patterns for assigning struct fields and array elements using

( ‘{ } ) either by positions, by type :value, or by member :value or by Classes default:value • class properties and methods • array assignment pattern, structure assignment pattern, • tagged union expression and member access: union tagged { … } write values and create events • aggregate expressions after the events in the NBA region • operator overloading: bind op func_name ( formals ) are evaluated • match formal types exactly or the actual types are implicitly cast to observed for the evaluation of the property iterative formal types expressions when they are • the operators that can be overloaded are the arithmetic operators, triggered the relational operators, and assignment post-observed allows PLI application routines iterative • streaming operators (pack/unpack) (currently no PLI callback yet) to • >> causes data to be streamed in left-to-right order read values after properties are • << causes data to be streamed in right-to-left order evaluated • streaming dynamically sized data using with [ expr[ +|-]:expr ] reactive property pass/fail code shall be iterative • conditional operator scheduled here of the current time • set membership: expr inside { open_range_list } slot re-inactive a #0 control delay specified in a iterative Scheduling Semantics program block schedules the • evaluation event and simulation time process for resumption in this • time wheel or time-ordered set of linked lists region • a time slot is divided into a set of ordered regions as table below; pre-postponed allows PLI application routines IEEE1364 provide predictable interaction between the design and testbench (cbAtEndOfSimTime) to read and iterative code (including PLI callbacks) write values and create events after processing all other regions from previous time slot except the Postponed region postponed cbReadOnlySynch IEEE1364 region semantics note No new value changes are allowed preponed The #1step sampling delay IEEE1364 to happen in the time slot provides the ability to sample data to next time slot immediately before entering the current time slot • the SystemVerilog simulation reference algorithm pre-active allows PLI application routines IEEE1364 execute_simulation { (cbAfterDelay, cbNextSimTime, T = 0; cbAtStartOfSimTime) to read and initialize the values of all nets and variables; write values and create events schedule all initialization events into time 0 slot; before events in the Active region while (some time slot is nonempty) { are evaluated move to the next future nonempty time slot and set T; active holds current events being IEEE1364 execute_time_slot (T); } evaluated iterative } inactive holds the events to be evaluated IEEE1364 execute_time_slot { after all the active events are iterative execute_region (preponed); processed execute_region (pre-active); pre-NBA allows PLI application routines IEEE1364 while (any region in [active...pre-postponed] is (cbNBASynch, cbReadWriteSynch) iterative nonempty) { to read and write values and while (any region in [active...post-observed] is create events before the events in nonempty) { the NBA region are evaluated execute_region (active); NBA A nonblocking assignment creates IEEE1364 R = first nonempty region in [active...post- an event in this region iterative observed]; if (R is nonempty) move events in R to the active post-NBA allows PLI application routines IEEE1364 region; (cbReadWriteSynch) to read and iterative } while (any region in [reactive...re-inactive] is • sequence , triggered nonempty) { • level-sensitive sequence control: wait execute_region (reactive); sequence abc; R = first nonempty region in [reactive...re- @(posedge clk) a ##1 b ##1 c; inactive]; endsequence if (R is nonempty) sequence de; move events in R to the reactive region; @(negedge clk) d ##[2:5] e; } endsequence if (all regions in [active … re-inactive] are empty) program check; execute_region (pre-postponed); initial begin } wait( abc.triggered || de.triggered ); execute_region (postponed); if( abc.triggered ) } $display( "abc succeeded" ); execute_region { if( de.triggered ) while (region is nonempty) { $display( "de succeeded" ); E = any event from region; end remove E from the region; endprogram if (E is an update event) { update the modified object; Processes evaluate processes sensitive to the object and • New always blocks – design intent is understood - IEEE1800 does not possibly schedulefurther events for execution; specify which constructs are synthesizable and which are not, EDA } else { /* E is an evaluation event */ evaluate the process associated with the event and vendors implement differently and portability will be an issue • possibly schedule further events for execution; always_comb for modeling combinational logic behavior • } inferred/implicit sensitivity list (within the block or within any } function called within the block), automatically executes once at time } zero, the variables written on the LHS of assignment shall not be • the PLI callback control points written to by another process • 2 kinds of PLI callbacks: those are executed immediately when some • always_latch for modeling level triggered latch logic behavior specific activity occurs and those that are explicitly registered as a • always_ff for modeling edge triggered synthesizable sequential logic one-shot evaluation event behavior • Callbacks and their event region (in the table above) always_ff @(posedge clock iff reset == 0 or posedge reset) begin

r1 <= reset ? 0 : r2 + 1; Procedural Statements and • ... procedural statements: initial , final , always , always_comb , end always_latch , always_ff , task , function • fork … join for creating concurrent processes • control flow control option description • selection, loops, jumps join the parent process blocks until all the processes • task and function calls spawned by this fork complete • sequential and parallel blocks • timing control join_any the parent process blocks until any one of the • blocking ( = ) and nonblocking ( <= ) assignments processes spawned by this fork complete • selection statements: if , else if , else , case , casez , casex , default , join_none the parent process continues to execute endcase , unique (for mutual exclusive and can be executed in concurrently with all the processes spawned by this parallel), priority (ordered evaluation), inside (for set membership), fork, and the spawned processes do not start matches (using &&& in if statements), ?: executing until the parent thread executes a • loop statements: forever , repeat , while , for , do while , foreach blocking statement • jump statements: return , break , continue , disable • named blocks and statement labels: begin end , fork join , join_any , Assertions • join_none assertions specify behaviors of the system, and are primarily used to • • event control: @, #, iff , posedge , negedge validate the behavior of a design • provide functional coverage and generate input stimulus for validation. • immediate assertions follow simulation event semantics and are executed like a procedure statements • the immediate assertion statement is a test of an expression performed when the statement is executed in the procedure code; the expression is non-temporal and is interpreted the same way as an expression in the condition of a procedural if statement • syntax: assert ( expression ) [pass_statement] [ else fail_statement] • if an assertion fails and no else clause is specified, the tool shall, by default, call $error, unless a tool specific option, such as a command-line option, is enabled to suppress the failure • there are 4 severity levels: $fatal, $error, $warning, and $info; all the severity system tasks shall print a tool-specific message indicating the severity of the failure and specific information about the specific failure, which shall include the following information: • the file name and line number of the assertion statement • the hierarchical name of the assertion, if it is labeled, or the scope of the assertion if it is not labeled • a concurrent assertion is based on clock semantics and is evaluated only at the occurrence of a clock tick; the values of variables used in the evaluation are the sampled values, thus a predictable result can be obtained from the evaluation, regardless of the simulator’s internal mechanism of ordering events and evaluating events • syntax: assert property ( expression ) [pass_statement] [ else fail_statement]