5. Language

THe SimStm language is a high-level, domain-specific language designed for modeling and simulating complex systems. It provides a simple but powerful set of constructs and features that allow users to define and manipulate various aspects of their simulations, including variables, operations, control flow, and more.

5.1. General

In SimStm instructions a line is a instruction, except empty lines or comment only lines. Subroutine labels are considered as instruction in this manner too.

The colon postfix of a subroutine label must end with a colon. No space is allowed between the label ID and the colon. Otherwise the SimStm language is not white space sensitive.

The SimStm language is case sensitive.

All constants, variables and label IDs are global within a SimStm project. The IDs must be unique.

There are no subroutine parameters or local variables. Values must be passed by unique global objects. This is an accommodation to having a simple SimStm interpreter and develops its own charm when using and debugging it.

The subroutine with the label testMain:is the entry point into the SimStm code for the simulator.

5.2. Comments

-- This is a full line comment
const aconst 0x03 -- This is an appended line comment
Comments in a line start with two hyphens.
There are only line comments, no block comments.

5.3. Namespaces

5.3.1. namespace

namespace a_namespace
        var a_var 0
end a_namespace

The namespace instruction declares the beginning of a namespace with an ID.

Variables, procedures etc. declared in a namespace are only visible inside that namespace, they can however be accessed using fully qualified IDs like namespaceID.varID, for example a_namespace.a_var in other namespaces. Namespaces are mandatory, wrapping every piece of code (except include statements) between a namespace declaration and end namespace instruction.

Multiple pieces of code in different files belong to the same namespace if they are wrapped by the same namespace ID.

5.4. Includes

5.4.1. include

include "aninclude.stm"

Include another child \*.stm file.

The include instructions should be the first instructions of a \*.stm file as they are not allowed inside a namespace. An included file can include further \*.stm files, thus nested includes are possible. The file path to be given either is prefixed with the generic stimulus_path given via the tb_simstm entity or is relative to the file with the respective include instruction if it contains ./ or ../ elements. Later nested relative includes of files from the same folder or into child folders are predictable; nested includes to files in parent folders may not be a good practice.

5.5. Arrays

5.5.1. array

array a_array 16

The instruction array declares an array with an ID and an unsigned 32-bit integer length.

Only arrays with one dimension are possible; the length is fixed.

5.5.2. array set

array set a_array p_var a_var
array set a_array p_var 5
array set b_array 3 b_var
array set b_array 3 4

The instruction array set sets the value of an array at a position to a certain value.

For example, the instruction array set a_array p_var a_var sets the value of a_array at position p_var to the value of a_var.

5.5.3. array get

array get b_array p_var t_var
array get b_array 5  t_var

The array get instruction gets the value of an array at a position and stores it in a variable.

For example, the instruction array get b_array p_var t_var gets the value of b_array at position p_var and stores it in t_var.

5.5.4. array verify

array verify b_array p_var e_var m_var
array verify b_array p_var 0x01 0x0F

The instruction array verify reads the value of an array at a position and compares it to an expected value with a given mask.

The expected value and mask can be variables, constants, or numeric values. On mismatch, the simulation stops with severity Failure if the global resume is set to 0; otherwise, it continues, reports an simulation error and counts up the SimStm testbench internal verify_failure_count variable.

The SimStm testbench internal verify_passes_count variable counts up the number verify instructions happened at all regardless if a simulation error occurs or not.

For example, the instruction array verify b_array p_var e_var m_var verifies that the value of b_array at position p_var is the same as the value of e_var, with the mask m_var.

5.5.5. array size

array size b_array t_var

The array size instruction gets the size of an array and stores it in a variable.

For example, array size b_array t_var stores the size of b_array in t_var.

5.5.6. array pointer copy

array pointer copy t_array s_array

The instruction array pointer copy creates an array pointer.

For example, t_array points to s_array after the execution of the instruction. Used, for instance, to hand over an array to a subroutine. Changes to the source array also apply to the target array.

5.6. Busses

5.6.1. bus

bus a_bus 10
bus a_bus a_const
bus a_bus a_global_var

The instruction bus declares a bus object with ID initialized with a global variable, constant or literal.

The signal object associates a SimStm bus name with a bus number. This bus number must be given in the tb_bus package by customization and attached to a bus.

5.6.2. bus write

bus write a_bus a_width an_address a_var
bus write a_bus 32 0x0004 0x12345678

The instruction bus write writes a variable, constant, or numeric value to a bus with a given width and address.

In the example, the value of a_var is being stored in a_bus.

5.6.3. bus read

bus read a_bus a_width an_address a_var

The instruction bus read reads the value of a bus with a given width and address into a variable.

In the example, the value of a_bus is stored in a_var.

5.6.4. bus verify

bus verify a_bus a_width an_address e_var m_var
bus verify a_bus a_width an_address 0x01 0x0F

The instruction bus verify reads the value of a bus with a given width and address and compares it to an expected value with a given mask. The expected values and masks can be variables, constants, or numeric values. On mismatch, the simulation stops with severity Failure if the global resume is set to 0; otherwise, it continues, reports an simulation error and counts up the SimStm testbench internal verify_failure_count variable.

The SimStm testbench internal verify_passes_count variable counts up the number of bus accesses happened at all regardless if a simulation error occurs or not.

In the example, it is verified that the value read from a_bus is the same as the value of e_var, with the mask m_var.

5.6.5. bus pointer copy

bus pointer copy t_bus s_bus

The instruction bus pointer copy creates a bus pointer;

In the example, t_bus points to s_bus after the execution of the instruction. Used, for instance, to hand over a bus to a subroutine. Changes to the source bus are applied to the target bus as well.

5.6.6. bus pointer set

bus pointer set t_bus 5
bus pointer set t_bus ptr_var

The instruction bus pointer set sets a bus pointer to an absolute address.

In the example, the pointer t_bus is set to 5.

5.6.7. bus pointer get

bus pointer get s_bus ptr_var

The instruction bus pointer get gets the value of a bus pointer and stores it in a variable.

In the example, the pointer s_bus is stored in ptr_var.

5.6.8. bus timeout set

bus timeout set a_bus s_var
bus timeout set a_bus 1000

The instruction bus timeout sets the timeout in nanoseconds to wait for a bus access to end. On timeout, the simulation stops with severity Failure if the global resume is set to 0; otherwise, it continues, reports an simulation error and counts up the simstm testbench internal bus_timeout_failure_count variable.

The simstm testbench internal bus_timeout_passes_count variable counts up the number of bus accesses at all regardless if a timeout occurs or not.

5.6.9. bus timeout get

bus timeout get s_bus to_var

The instruction bus timeout get gets a bus timeout and stores it in a variable;

In the example, the timeout s_bus is stored in to_var.

5.7. Debug

5.7.1. trace

trace t_var
trace 0b111

The trace instruction enables or disables the output of trace information when it is set at some point during the SimStm code execution. Thus, e.g., the flow through complex if, elsif … trees can be shown.

Predifined constants can be used to set the trace variable. The following bits are defined:

const TRACE_OFF 0
const TRACE_EXECUTED_LINES 0x1
const TRACE_INSTRUCTIONS 0x2
const TRACE_VARIABLES 0x4
const TRACE_FILES 0x8
const TRACE_IF_TREES 0x10
const TRACE_CALLS 0x20
const TRACE_ALL 0xFFFF

5.7.2. marker

marker n_var m_var
marker 0xF 0b1

The marker instruction sets a marker at a given number used to mark interesting points of time in the simulation wavefrom.

The tb_simstm entity has an output signal marker which is a std_logic_vector(15 downto 0). Thus there are 16 markers which can be set 0b1 or 0b0. This should be used to mark occurrences during the execution of the SimStm code so they can be found easily in the waveform display. Beneath this, the intern variables Executing_Line and Executing_File in the tb_simstm.vhd module are always present and show the currently executed line of code.

5.7.3. stop

stop

The stop instruction stops the simulation with the severity error. The simulation can be continued by pressing continue in the simulator.

5.8. Files

5.8.1. file

file a_file "filename.stm"
file a_file "filename{:d}{:d}.stm" index1 index2

The file instruction declares a file with an ID and a file name.

The latter must be a relative path to the location of the main.stm file. Text substitution by variables is allowed in file names. Thus, files can be accessed in an indexed manner. The variables are evaluated every time a reference to a file is used in another instruction accessing a file, e.g., file read all a_file a_lines.

5.8.2. file writable

file writable a_file r_var

The file writable instruction tests if a file is writable. If the file is not present, it is created without having content. The result for STATUSOK is 0, STATUSERROR is 1, STATUSNAMEERROR is 2, STATUSMODEERROR is 3 and may, in case of error, depend on the operating system.

In the example, the value of the test for a_file is stored in r_var.

5.8.3. file readable

file readable a_file r_var

The file readable instruction tests if a file is readable. The result for STATUSOK is 0, STATUSERROR is 1, STATUSNAMEERROR is 2, STATUSMODEERROR is 3 and may, in case of error, depend on the operating system.

In the example, the value of the test for a_file is stored in r_var.

5.8.4. file appendable

file appendable a_file r_var

The file appendable instruction tests if a file is appendable. The result for STATUSOK is 0, STATUSERROR is 1, STATUSNAMEERROR is 2, STATUSMODEERROR is 3 and may, in case of error, depend on the operating system.

In the example, the value of the test for a_file is stored in r_var.

5.8.5. file write

file write a_file a_lines

The file write instruction writes all lines of a lines object to a file. The file is overwritten if it exists.

In the example, a_lines is written into a_file.

5.8.6. file append

file append a_file a_lines

The file append instruction appends all lines of a lines object to a file. The method will fail if the file doesn’t exist.

In the example, a_lines is appended to a_file.

5.8.7. file read all

file read all a_file a_lines

The file read all instruction reads all lines of a file into a lines object.

In the example, the content of a_file is stored in a_lines.

5.8.8. file read

file read a_file a_lines n_var
file read a_file a_lines 10

The file read instruction reads a number of lines from a file into an lines object.

In the example, the first n_var lines of a_file are stored in a_lines.

The first read opens the file for read, following reads start at the line after the last line which has been read by the previous read. Thus a file can be read piecewise similar as it can be written piecewise by file append. The piecewise read process of the file must be terminated by a file read end instruction always. The number of concurrent file read processes is limited to 4.

5.8.9. file read end

file read end a_file

The file read end instruction ends the piecewise read process of a file.

5.8.10. file pointer copy

file pointer copy t_file s_file

The file pointer copy instruction creates a file pointer; for example, t_file points to s_file after the execution of the instruction.

In the example, t_file now points to s_file.

Used, for instance, to hand over a file to a subroutine. Changes to the source file are applied in the target file as well.

5.9. Labels

5.9.1. label

label lbl_var a_var

The instruction label declares and defines a label with an ID and an initial value.

A label can act as a placeholder for actual values which are modifiable through label equ, label set or label pointer copy.

5.9.2. label equ

label equ lbl_varA lbl_varB

The instruction label equ sets the value of a label to a different label.

In the example, lbl_var is set to the value of a_var.

5.9.3. label set

label set lbl_var a_var

5.9.4. label pointer copy

label pointer copy lbl_var a_var

The instruction label pointer copy creates a label pointer.

In the example, lbl_var points to a_var.

5.9.5. Powerful Usage Patterns

Labels become most powerful when used to decouple generic behaviour from concrete implementations. The following patterns demonstrate how labels enable dynamic dispatch, reusable templates, and shared configuration — all without recompiling HDL.

Pattern 1: Dynamic Dispatch — one generic poller, thousands of concrete bits

A single waitForBit wrapper can poll any status bit in the design. The concrete procedure to call is injected at the call site via label set. This avoids duplicating the polling logic for every single bit.

-- Generic poller: calls whatever procedure is injected via ToCall
proc waitForBit (
    label ToCall waitForBit_ToCall_template
    var IsExpectedValue 0
    var TimeoutCycles 1000
)
    var cycles 0
    loop
        call label ToCall (
            var pointer copy IsExpectedValue IsExpectedValue
        )
        if IsExpectedValue = 1 then
            return
        end if
        equ cycles cycles + 1
        if cycles >= TimeoutCycles then
            log message stm.ALWAYS "waitForBit: timeout waiting for bit"
            return
        end if
        wait 1
    end loop
end proc

-- Concrete bit reader for DMA done flag
proc isDmaDone (
    var IsExpectedValue 0
)
    bus read 32 0x4000_0010 IsExpectedValue
    and IsExpectedValue 0x1
end proc

-- Concrete bit reader for FIFO not full flag
proc isFifoNotFull (
    var IsExpectedValue 0
)
    bus read 32 0x4000_0020 IsExpectedValue
    shr IsExpectedValue 3
    and IsExpectedValue 0x1
end proc

-- Test: wait for DMA, then wait for FIFO ready
proc testDmaAndFifo ()
    var result 0
    call waitForBit (
        label set ToCall isDmaDone
        var pointer copy IsExpectedValue result
    )
    call waitForBit (
        label set ToCall isFifoNotFull
        var pointer copy IsExpectedValue result
    )
end proc

Pattern 2: Policy Injection — swap error-handling strategy at the call site

Use a label to inject a different error-handling procedure without modifying the generic test procedure. This is the equivalent of a strategy or policy pattern.

-- Generic register write with injected error policy
proc writeRegChecked (
    label OnError errorPolicy_template
    var Address 0
    var Value 0
)
    var readback 0
    bus write 32 Address Value
    bus read 32 Address readback
    if readback <> Value then
        call label OnError (
            var pointer copy Address Address
            var pointer copy Value Value
            var pointer copy readback readback
        )
    end if
end proc

-- Policy: log and continue
proc errorPolicy_logOnly (
    var Address 0
    var Value 0
    var readback 0
)
    log message stm.ALWAYS "Write verify failed at address"
    log var stm.ALWAYS Address
end proc

-- Policy: log and stop the simulation
proc errorPolicy_fatal (
    var Address 0
    var Value 0
    var readback 0
)
    log message stm.ALWAYS "Fatal: Write verify failed — stopping"
    stop
end proc

-- Smoke test uses soft policy; production test uses fatal policy
proc smokeTest ()
    call writeRegChecked (
        label set OnError errorPolicy_logOnly
        var set Address 0x4000_0000
        var set Value 0xDEAD
    )
end proc

proc productionTest ()
    call writeRegChecked (
        label set OnError errorPolicy_fatal
        var set Address 0x4000_0000
        var set Value 0xDEAD
    )
end proc

Pattern 3: Shared Configuration Label — one place to change, everywhere updated

Declare a single label for a base address or constant once and reference it everywhere. Changing the one declaration updates every use without touching the rest of the test.

-- Declare the DMA controller base address once
label DMA_BASE 0x4000_0000

proc startDma ()
    var ctrl 0
    label equ ctrl DMA_BASE
    add ctrl 0x00
    bus write 32 ctrl 0x1
end proc

proc resetDma ()
    var rst 0
    label equ rst DMA_BASE
    add rst 0x04
    bus write 32 rst 0xFF
end proc

-- Moving the peripheral to a new address only requires changing DMA_BASE above

5.10. Subroutines, Branches, and Loops

5.10.1. proc

proc a_proc ()
    --...
    --... local variable , array, files, lines, bus, signals, label declarations
    --...
    -- subroutine code
    --...
end proc

proc p_proc (
   --...
   --... parameter variable , array, file, lines, bus, signal, label declarations
   --...
 )
    --...
    --... local variable , array, file, lines, bus, signal, label declarations
    --...
    -- subroutine code
    --...
end proc

Code of a subroutine is placed between proc and end proc instructions.

A procedure can have parameters. The parameters are declared as usually with variables, arrays, files, lines, buses, signals, or labels between the parentheses after the procedure name. If the parameters are passed by reference or by value is decided by the assignments within the parentheses when calling the procedures.

The value given with the parameter declaration is the default value, which is used when the parameter is not assigned when calling the procedure. The default value can be any global variable, array, file, line, bus, signal, or label. It can also be a constant or a numeric value in case of variables, busses, signals.

This mechanism allows to have optional parameters, which can be used when the same procedure is called with different parameters in different places. In case of suitable default values, the calls can be very lean.

Parameter objects mustn’t have the same name as any local variable, array, file, line, bus, signal, or label within the same procedure. However, they can have the same name as global variables, arrays, files, lines, buses, signals, or labels.

5.10.2. call

call a_proc ()

call p_proc (
   --...
   --... parameter variable , array, file, lines, bus, signal, label assignments
   --...
 )

The call instruction branches execution to the subroutine with the given procedure name. Code execution proceeds until an end proc or a return statement.

  • Parameter variable assignments of a source variable to destination parameter variable can be passed by

  • equ d_var s_var to pass by value

  • var pointer copy d_var s_var to pass by reference

  • Parameter label assignments of a source label or direct procedure name to destination parameter label can be passed by

  • label equ d_label s_label to pass by value

  • var pointer copy a_par a_var to pass by reference

  • label set d_label proc_name to set it to a procedure directly

  • Parameter array assignments of a source array to destination parameter array can be passed by

  • array pointer copy d_array s_array to pass by reference only

  • Parameter file assignments of a source file to destination parameter file can be passed by

  • file pointer copy d_file s_file to pass by reference only

  • Parameter lines assignments of a source lines to destination parameter lines can be passed by

  • lines pointer copy d_lines s_lines to pass by reference only

  • Parameter bus assignments of a source bus to destination parameter bus can be passed by

  • bus pointer copy d_bus s_bus to pass by reference only

  • Parameter signal assignments of a source signal to destination parameter signal can be passed by

  • signal pointer copy d_signal s_signal to pass by reference only

Source variables, labels, arrays, files, lines, buses, or signals are taken with preceedence from the calling subroutine when present as locals there, otherwise from the global scope.

5.10.3. call label

call label a_label ()

call label p_label (
   --...
   --... parameter variable , array, file, lines, bus, signal, label assignments
   --...
 )

The call label instruction branches execution to the label given after the label keyword.

Thus a label must be declared in the same procedure or globally. The label can be passed as a parameter to the procedure as well, which allows to call different labels within the same procedure.

A label declaration especially when used in parameters must always point to a existing procedure, at least a dummy procedure in case it is always overridden.

5.10.4. return

return

The return instruction returns to calling code from a subroutine.

5.10.5. interrupt

interrupt an_interrupt ()
    --...
    -- interrupt subroutine code
    --...
end interrupt

Code of an interrupt subroutine is placed between interrupt and end interrupt instructions. The label an_interrupt must be given in the tb_signal package by customization and attached to a signal triggering the interrupt. If necessary, the handling of nested interrupts must be resolved there too.

5.10.6. if

if a_var = b_var
    -- ... some code
elsif a_var 0xABC
    -- ... some code
elsif 0x123} b_var
    -- ... some code
else
    -- ... some code
end if

Possible comparison operators are: >= <= > < != =.

The if or elsif instructions compares two variables, constants, or numeric values and branches execution to the next line after the end if if it resolves to true. Otherwise, it branches to the next elsif or else or end if instruction.

The if elsif or else instructions can be nested.

5.10.7. loop

loop l_var
    -- ... some code
end loop

loop 32
    -- ... some code
end loop

The loop instruction executes a loop of the code between the loop and end loop instruction.

The number of times the loop should be executed is given after the loop keyword. It can be a numeric value, a variable, or a constant.

In case of a variable, this number can be changed by code within the loop, e.g., to skip loops or end the loop earlier, due to the global nature of all variables. No break or continue instructions are supported therefore.

The loop can be terminated by a return instruction too at any time, which is a good practice.

5.10.8. abort

abort

The abort instruction aborts the simulation with severity Failure.

5.10.9. finish

finish

The finish instruction exits the simulation.

5.10.10. stop

stop

The stop instruction stops the simulation with the severity Failure. The simulation can be resumed.

5.10.11. resume

resume EXIT_ON_VERIFY_ERROR
resume 0
Usual practice is to use the following constants to set verbosity:
const RESUME_ON_VERIFY_ERROR 1
const EXIT_ON_VERIFY_ERROR 0

The resume instruction sets the global resume behavior for verify instructions. On a verify mismatch, the simulation stops with severity Failure if the global resume is set to 0; otherwise, it continues and reports an error.

5.11. Lines

5.11.1. lines

lines a_lines

The lines instruction declares a lines object with an ID.

The lines object contains an arbitrary number of line objects. It is defined to have no content when it is declared by default. It can grow or shrink dynamically by lines instructions accessing it, e.g., lines insert array a_lines 9 b_array.

5.11.2. lines get

lines get array a_lines p_var t_array r_var
lines get array a_lines 9 t_array r_var

The lines get array instruction gets a line from a lines object at a given position and write its content into an array. The number of extracted values is stored in a variable.

In the example, the content of the line at position p_var in a_lines is stored in t_array and the number of values is stored in r_var.

The line is expected to hold hex numbers (without 0x prefix) separated by spaces (e.g., A123 BCF11 123 E333 would be 4 hex numbers). The given array must be able to hold the number of found hex numbers. It will not be filled completely if fewer than its size are found. Numbers will be skipped if there are more hex numbers found than the array can hold. The number of detected hex numbers is reported in a result variable. Then the user can decide what action should follow a mismatch.

5.11.3. lines set

lines set array a_lines p_var s_array
lines set array a_lines 9 s_array
lines set message a_lines p_var "Some message to be written to a file later"
lines set message a_lines p_var "Value1: {} Value2: {} to be written to a file later" m_var1 m_var2

The lines set instruction sets a line at a given position of a lines object.

In the example, the content of s_array is stored at position p_var of a_lines.

The line currently at this position is overwritten. The line can be derived from an array or a message. The message string can contain {} placeholders, refer to the log message instruction, which are filled by values of variables given after the message string.

5.11.4. lines insert

lines insert array a_lines p_var s_array
lines insert array a_lines 9 s_array
lines insert message a_lines p_var "Some message to be written to a file later"
lines insert message a_lines p_var "Value1: {} Value2: {} to be written to a file later" mvar1 mvar2

The lines insert instruction inserts a line at a given position of a lines object.

The line currently at this position is moved to the next position. The line can be derived from an array or a message. The message string can contain {} placeholders, refer to the log message instruction, which are filled by values of variables given after the message string.

5.11.5. lines append

lines append array a_lines s_array
lines append message a_lines "Some message to be written to a file later"
lines append message a_lines "Value1: {} Value2: {} to be written to a file later" m_var1 m_var2

The lines append instruction appends a line at the end of a lines object.

In the example, the content of s_array is appended to a_lines.

The line can be derived from an array or a message. The message string can contain {} placeholders, refer to the log message instruction, which are filled by values of variables given after the message string.

5.11.6. lines delete

lines delete a_lines p_var
lines delete a_lines 3

The lines delete instruction deletes a line at a given position of a lines object. The next line is moved to the given position if it exists.

In the example, the line at position p_var in a_lines is deleted.

5.11.7. lines size

lines size a_lines r_var

The lines size instruction gets the size of a lines object, which is the number of lines it contains at that point.

In the example, the size of a_lines is stored in r_var.

5.11.8. lines pointer copy

lines pointer copy t_lines s_lines

The lines pointer copy instruction copies a lines pointer.

In the example, t_lines points to s_lines after the execution of the instruction.

Used, for instance, to hand over a file to a subroutine. Changes to the source object are applied to the target object as well.

5.12. Logs

5.12.1. log message

log message v_var "A message to the console"
log message v_var "A message to the console{}{}" m_var1 m_var2
log message v_var "A message to the console{:d}{:b}" m_var1 m_var2
log message v_var "A message to the console{:s}{:b}" lb>m_var1

The log message instruction prints a message at a given verbosity level to the console.

The message string can contain {} placeholders which are filled by values of variables given after the message string.

{} prints the value of the variable in hex format {:d} prints the value of the variable in decimal format {:b} prints the value of the variable in binary format {:o} prints the value of the variable in octal format {:s} prints the value of the variable as a string (only for label variables, prefix with lb>) {@c0} prints the called procedure name of the current call stack, {@c1} prints the called procedure name of the caller, {@c2} prints the called procedure name of the caller’s caller, etc. {@f0} prints the file name containing the called procedure name of the current call stack, {@f1} prints the file name containing the called procedure name of the caller, {@f2} prints the file name containing the called procedure name of the caller’s caller, etc. {@l0} prints the line number in the file containing the called procedure name of the current call stack, {@l1} prints the line number in the file containing the called procedure name of the caller, {@l2} prints the line number in the file containing the called procedure name of the caller’s caller, etc.

5.12.2. log lines

log lines v_var s_lines

The log lines instruction dumps a lines object at a given verbosity level to the console.

5.12.3. verbosity

verbosity v_var
verbosity 20

Usual practice is to use the following constants to set verbosity:

const FAILURE 0
const WARNING 10
const INFO 20

The verbosity instruction sets the global verbosity for log messages. Log messages with a verbosity level greater than the globally set verbosity are not printed to the console. Of course, the global verbosity can be changed at any point in the execution flow.

5.13. Objects

5.13.1. const

const a_const 0x03
const b_const 0b011
const c_const 3

The const instruction declares and defines a constant with an ID and a hex, binary, decimal unsigned value.

It isn’t possible to initialize a constant by referencing another constant.

5.13.2. var

var a_var 0x03
var b_var 0b011
var c_var 3

The var instruction declares and defines a variable with an ID and an initial hex, binary, or decimal unsigned value.

It isn’t possible to initialize a variable by referencing another variable or constant yet. The equ instruction must be used within a procedure for this purpose.

5.13.3. array

a_array 16

The array instruction declares an array with an ID and an unsigned 32-bit integer length.

Only arrays with one dimension are possible; the length is fixed.

5.13.4. file

file a_file "filename.stm"
file a_file "filename{:d}{:d}.stm" index1 index2

The file instruction declares a file with an ID and a file name.

The latter must be a relative path to the location of the main.stm file. Text substitution by variables is allowed in file names. Thus, files can be accessed in an indexed manner. The variables are evaluated every time a reference to a file is used in another instruction accessing a file, e.g., file read all a_file a_lines.

5.13.5. lines

lines a_lines

The lines instruction declares a lines object with an ID.

The lines object contains an arbitrary number of line objects. It is defined to have no content when it is declared by default. It can grow or shrink dynamically by lines instructions accessing it, e.g., lines insert array a_lines 9 b_array.

5.13.6. signal

signal a_signal

The signal instruction declares a signal object with an ID.

The signal object associates a SimStm signal name with a signal number. This signal number must be given in the tb_signal package by customization and attached to a signal.

5.13.7. bus

bus a_bus

The bus instruction declares a bus object with ID.

The signal object associates a SimStm bus name with a bus number. This bus number must be given in the tb_bus package by customization and attached to a bus.

5.13.8. namespace

namespace a
var l_var 0
end namespace

The namespace instruction declares a container-like space, that can hold variables, subroutines etc. These are defined only inside the namespace and therefore help organizing code and avoiding naming conflicts. In the given example, the variable l_var is only defined inside the namespace a.

5.13.9. label

label lbl_var a_var

The instruction label declares and defines a label with an ID and an initial value.

A label can act as a placeholder for actual values which are modifiable through label equ, label set or label pointer copy.

5.14. Equations and Arithmetic Operations

5.14.1. add

add operand1 operand2
add operand1 0xF0

The add instruction adds the value of operand2 (variable or constant) to the value of operand1 (variable) or adds the value 0xF0 to the value of operand1. The resulting value of the addition is stored in operand1 after the operation.

5.14.2. sub

sub operand1 operand2
sub operand1 0xF0`

The sub instruction subtracts the value of operand2 (variable or constant) from the value of operand1 (variable) or subtracts the value 0xF0 from the value operand1. The resulting value of the subtraction is stored in operand1 after the operation.

5.14.3. mul

mul operand1 operand2
mul operand1 0xF0

The mul instruction multiplies the value of operand2 (variable or constant) with the value of operand1 (variable) or multiplies the value 0xF0 with the value operand1. The resulting value of the multiplication is stored in operand1 after the operation.

5.14.4. div

div operand1 operand2
div operand1 0xF0

The div instruction divides the value of operand1 (variable) by the value of operand2 (variable or constant) or divides the value of operand1 by the value 0xF0. The resulting value of the division is stored in operand1 after the operation.

5.14.5. rem

rem operand1 operand2
rem operand1 0xF0

The rem instruction divides the value of operand1 (variable) by the value of operand2 (variable or constant) or divides the value of operand1 by the value 0xF0. The resulting remainder of the division is stored in operand1 after the operation.

5.14.6. and

and operand1 operand2
and operand1 0xF0

The and instruction does a bitwise and of the value of operand2 (variable or constant) with the value of operand1 (variable) or a bitwise and of value 0xF0 with the value of operand1. The resulting value of the bitwise and is stored in operand1 after the operation.

5.14.7. or

or operand1 operand2
or operand1 0xF0

The or instruction does a bitwise or of the value of operand2 (variable or constant) with the value of operand1 (variable) or a bitwise or of value 0xF0 with the value of operand1. The resulting value of the bitwise or is stored in operand1 after the operation.

5.14.8. xor

xor operand1 operand2
xor operand1 0xF0

The xor instruction does a bitwise xor of the value of operand2 (variable or constant) with the value of operand1 (variable) or a bitwise xor of value 0xF0 with the value of operand1. The resulting value of the bitwise xor is stored in operand1 after the operation.

5.14.9. shl

shl operand1 operand2
shl operand1 0xF0

The shl instruction does a bitwise left shift of the value of operand2 (variable or constant) with the value of operand1 (variable) or a bitwise left shift of value 0xF0 with the value of operand1. The resulting value of the bitwise left shift is stored in operand1 after the operation.

5.14.10. shr

shr operand1 operand2
shr operand1 0xF0

The shr instruction does a bitwise right shift of the value of operand2 (variable or constant) with the value ofoperand1 (variable) or a bitwise variable shift of value 0xF0 with the value of operand1. The resulting value of the bitwise right shift is stored in operand1 after the operation.

5.14.11. inv

inv operand1

The inv instruction does a bitwise inversion of the value of operand1 (variable). The resulting value of the bitwise inversion is stored in operand1 after the operation.

5.14.12. ld

ld operand1

The ld instruction calculates the logarithmus dualis of the value operand1 (variable). The resulting value is stored in operand1 after the operation. The function returns the index of the highest set bit, e.g., 4 for the input 16. It returns 0 for the input 0 too since this is the best approximation in a natural number range. The user should handle this discontinuity if another result or an error is expected.

5.15. Random Numbers

5.15.1. random

random t_var min_var max_var
random t_var 0 10

The random instruction generates a random number greater or equal to the min value given and less than the maximum number given.

5.15.2. seed

seed s_var
seed 10

The seed instruction sets the internal start value for the random number generator.

5.16. Signals

5.16.1. signal

signal a_signal 10
signal a_signal a_const
signal a_signal a_global_var

The instruction signal declares a signal object with an ID.

The signal object associates a SimStm signal name with a signal number. This signal number must be given in the tb_signal package by customization and be attached to a signal.

5.16.2. signal write

signal write a_signal s_var
signal write a_signal 0b11

The instruction signal write writes a variable, constant, or numeric value to a signal.

In the example, s_var is stored in a_signal.

5.16.3. signal read

signal read a_signal t_var

The instruction signal read reads the value of a signal into a variable.

In the example, the value of a_signal is stored in t_var.

5.16.4. signal verify

signal verify a_signal e_var m_var
signal verify a_signal 0x01 0x0F

The instruction signal verify reads the value of a signal and compares it to an expected value with a given mask.

In the example, it is verified that the value of a_signal``is the same as ``e_var, with the mask m_var.

The expected value and mask can be variables, constants, or numeric values. On mismatch, the simulation stops with severity failure if the global resume is set to 0; otherwise, it continues, reports an simulation error and counts up the SimStm testbench internal verify_failure_count variable.

The SimStm testbench internal verify_passes_count variable counts up the number of verify instructions happened at all regardless if a simulation error occurs or not.

5.16.5. signal pointer copy

signal pointer copy t_signal s_signal

The instruction signal pointer copy creates a signal pointer;

In the example, t_signal points to s_signal after the instruction of the execution.

Used, for instance, to hand over a signal to a subroutine. Changes to the source object are applied to the target object as well.

5.16.6. signal pointer set

signal pointer set t_signal 5
signal pointer set t_signal ptr_var

The instruction signal pointer set sets a signal pointer to an absolute address.

In the example, the pointer t_signal is set to 5.

5.16.7. signal pointer get

signal pointer get s_signal ptr_var

The instruction signal pointer get gets the value of a signal pointer and stores it in a variable.

In the example, the pointer s_signal is stored in ptr_var.

5.17. Variables

5.17.1. var

var a_var 0x03
var b_var 0b011
var c_var 3

The var instruction declares and defines a variable with an ID and an initial hex, binary, or decimal unsigned value.

It isn’t possible to initialize a variable by referencing another variable or constant yet. The equ instruction must be used within a procedure for this purpose.

5.17.2. equ

equ operand1 operand2
equ operand1 0xF0

The equ instruction sets the value of a variable or constant to a different variable.

In the example, the value of operand1 is set to operand2.

5.17.3. var verify

var verify a_var e_var m_var
var verify a_var 0x01 0x0F

The var verify instruction reads the value of a signal and compares it to an expected value with a given mask.

In the example, it is verified that the values of a_var and e_var are the same with mask m_var.

The expected value and mask can be variables, constants, or numeric values. On mismatch, the simulation stops with severity Failure if the global resume is set to 0; otherwise, it continues, reports an simulation error and counts up the SimStm testbench internal verify_failure_count variable.

The SimStm testbench internal verify_passes_count variable counts up the number of verify instructions happened at all regardless if a simulation error occurs or not.

5.17.4. var pointer copy

var pointer copy a_var b_var

The instruction var pointer copy creates a variable pointer.

For example, a_var points to B_var after the execution of the instruction.

5.18. Waits

5.18.1. wait

wait w_var
wait 10000

The wait instruction waits for the given number of nanoseconds.