Quirks UVM command set

Up: (dir)  

Top


Next: , Up: Top  

1 A Quirks program

A Quirks program is a set of procedures splitted into modules. Each module consists from one or more procedures and type declarations (optional).

<module> ::= <module_item> { <module_item> }

<module_item> ::= <procedure> | <type_declaration>

<type_declaration> ::= type <type_name> is <descriptor> ;

<procedure> ::= procedure <procedure_name> is <header> begin <body> 
                end <procedure_name> ;

<header> := { <prim_selector_decl> | <map_decl> }

<prim_selector_decl> ::= <prim_selector> is <descriptor> ;

<map_decl> ::= declare map <sec_selector_decl> { <sec_selector_decl> } 
               map is { <map_pair> } end map ;

<sec_selector_decl> ::= <sec_selector> is <descriptor> ;

<map_pair> ::= '(' <cell> , <cell> ')'

<body> ::= { <act_cmn> | <nop_cmn> | <block> | <mov_cmd> | 
              <if_block> | <loop_block> |
              <exit_cmd> | <call_cmd> | <debug_cmd> }

<block> ::= declare <header> begin <body> end ;

<if_block> ::= if [not] <cell> then <body> [ else <body> ] end if ;

<loop_block> ::= [<label_name> : ] <loop_start> <body> <loop_stop> ;

<loop_start> ::= loop | while [not] <cell> loop

<loop_stop> ::= end loop | until [not] <cell>

<descriptor> ::= <atomic_type> [ / <cell_mode> ] | 
                  '<' <complex_type> '>' | <type_name> [ / <cell_mode> ]

<atomic_type> ::= bit1 | int8 | int16 | int32 | int64 
                  | uint8 | uint16 | uint32 | uint64 

<complex_type> ::= <structure> | <array> | <discriminated_type>

<structure> ::= { <descriptor> } stu

<array> ::= <descriptor> arr (<num> | * [ <num> ]) 
            [.. (<num> | * [ <num> ]) ]

<discriminated_type> ::= '(' <atomic_type> { <atomic_type> } ')' 
                             <complex_type>

<cell_mode> ::= in | out | inout | na


<act_cmd> ::= * <au_selector> ;

<nop_cmd> ::= nop ;

<mov_cmd> ::= <cell> <- <cell> ;

<exit_cmd> ::= exit <loop_label> when [not] <cell> ;

<call_cmd> ::= call [ <selector_name> , ] <procedure_name> ;

<cell> ::= <selector_name> <order>

<order> ::= '[' <num> { : <num> } ']'

<debug_cmd> ::= <print_cmd>

<print_cmd> ::= print <cell> ; | printn <cell> ; | print <string> ; |
                printn <string> ;

The terminals are:


Next: , Previous: , Up: Top  

2 Declarative elements of a module

Each module can have type declarations in a form:

<type_declaration> ::= type <type_name> is <descriptor> ;

Such types can be used in any descriptor declarations that follows.

If the <type_name> is used with i/o mode (‘~T1/in’) such declaration is restriction of the original i/o modes for the type ~T1 by the new mode set. The table bellow shows how the original modes are changed (the first column is the original mode for elements, the others rows are mode restrictors):

Originalinoutinoutna
inoutinoutinoutna
inininnana
outaoutnainna
nanananana

Next: , Previous: , Up: Top  

3 The commands

We have 8 commands.


Next: , Up: Commands  

3.1 nop

<nop_cmd> ::= nop ;

Now it is like a tradition. Do nothing 1.


Next: , Previous: , Up: Commands  

3.2 block

<block> ::= declare <header> begin <body> end ;

block allocates new memory and defines new mapping relations. All disappears after the block exits2.

The <header> specification contains a set of new selector declarations. These selectors can be introduced in block: ‘lv’, ‘dn’, ‘au’, ‘dx’, ‘dy’ (i.e. all procedure-scoped selectors). The selectors in such declaration must not cross existing selectors - all selectors must be new.

The introduction of ‘lv’ and ‘dn’ selectors cause an immediate memory allocations. The size of the needed memory is determined by the descriptors bonded with these selectors. <map_def> is not allowed for these selectors.

The ‘au’, ‘dx’, ‘dy’ selectors, in contrast, don’t make additional allocation (conceptually) but demand <map_def> specification. This specification defines where the storage for the cells is come from3.

The block meaning is the same both for procedures and nested blocks.


Next: , Previous: , Up: Commands  

3.3 mov

<cell> <- <cell> ;

Move a value from the second cell to the first one. Check the cells modes before it.


Next: , Previous: , Up: Commands  

3.4 act

 * <selector_name> ;

The act code call the function of the corresponding AU module and all related modules (i.e. it cause a function in all AU modules bounded by a mapping relation).


Next: , Previous: , Up: Commands  

3.5 call

<call_cmd> ::= call [ <selector_name> , ] <procedure_name> ;

A procedure call is examined in details See The model of a procedure in Quirks UVM architecture overview. <selector_name> may be ommited if the callee doesn’t take any formal parameters and doesn’t return a result (except, may be, global variables changing), i.e. a parameter frame is not used.


Next: , Previous: , Up: Commands  

3.6 if_block

<if_block> ::= if [not] <cell> then <body> [ else <body> ] end if ;

Check the <cell>. If the <cell> is is from AU selector then perform act on it before branching. Perform then or else part depending on whether <cell> contains non zero vaule. If there is not prefix then performs then part when <cell> contains zero.


Next: , Previous: , Up: Commands  

3.7 loop

<loop_block> ::= [<label_name> : ] <loop_start> <body> <loop_stop> ;

<loop_start> ::= loop | while [not] <cell> loop

<loop_stop> ::= end loop | until [not] <cell>

There are 3 types of loops: with precondition, with postcondition and infinit loops. All are traditional. All types of loops can have labels for use with exit command.

If the <cell> is is from AU selector then perform act on it each time when check the condition.


Previous: , Up: Commands  

3.8 exit

<exit_cmd> ::= exit <loop_label> when [not] <cell> ;

Exit from labelled loop of any type when condition is true (i.e., <cell> is non zero and not is not present or <cell> is zero and not is present). If the <cell> is is from AU selector then perform act on it before jumping.


Previous: , Up: Top  

4 The debug commands

These commands intended for debugging. They are usually ignored, but if some key is given to ‘make instance’ then they are included in the code.


Up: Debug  

4.1 print and printn

print prints some debug information (on standard output). printn do the same but doesn’t feed line after printing.

<print_cmd> ::= print <cell> ; | printn <cell> ; | print <string> ; |
                printn <string> ;

If the argument of this command is <cell> then print the cell contents. If the argument is <string> - print the string.


Footnotes

(1)

The use of nop is not treated the same way as an absence of commands at all. For example, there is some difference between

if <cell> then else <body> end if;

and

if <cell> then nop; else <body> end if;

In the first case (no then part) the code will be equivalent to

if not <cell> then <body> end if;

and probably will be natively translated as:

CHECK <cell>
IF NOT ZERO THEN JUMP @L2
<body>
@L2:

but in the secong case it will be treated as then part with no action, i.e., that leads to a typicall translation to a native code with jumps:

CHECK <cell>
IF ZERO THEN JUMP @L1
JUMP @L2
@L1: <body>
@L2:

Thus, nop means "a command with no action" and not "an absence of command."

(2)

It is true for the "Stack Sparing" (SS) model.

UVM also supports 2 addition models for controlled performance:

  1. Deferred Undo (DU), when stack (and dynamic memory) is allocated when we enter each block but will deallocated only at the end of a procedure.
  2. Single Allocation (SA), when all possible blocks are allocated at the beginning of a procedure and deallocated at the end.

Which of these models will give a best performance is a question of underlying implementation of code execution/type_of_processor/program structure.

(3)

In the ‘au’ case - where the values come from also.