Skip to content

Latest commit

 

History

History
executable file
·
737 lines (472 loc) · 41.3 KB

README.md

File metadata and controls

executable file
·
737 lines (472 loc) · 41.3 KB

SimStm

SimStm is a VHDL testbench designed to facilitate testing driven by external stimulus files with a ".stm" extension. This testbench is provided by Eccelerators GmbH and aims to simplify test script creation by introducing the SimStm language. Eccelerators GmbH provides IDE support for this language through Visual Studio Code and Eclipse by SimStm plugins; visit Eccelerators. The full power of SimStm is achieved together with the HxS tool of Eccelerators GmbH since all necessary SimStm code for the HW/SW interfaces is generated by HxS.

History and License

The original VHDL testbench was coded by Ken Campbell; visit GitHub. Therefore, the SimStm repository is forked from this original. The complete VHDL source code of the SimStm VHDL testbench is distributed under the same license as the original. However, Eccelerators GmbH has substantially repartitioned and changed the code. The original copyright notice has been retained within all source files related to the original.

The IDE plugins are available for free on the Eccelerators GmbH web page. They may also be available for free on the respective IDE marketplaces once deployed. The source code of the SimStm language IDE plugins is the property of Eccelerators GmbH and is closed source.

Focus

It is common practice to use the file I/O features of VHDL for VHDL testbenches. Typically, each developer creates their own format for commands in an input stimuli text file, along with a unique file name and extension. The command set is focused on the tasks currently being solved.

The general advantage of this technique is that the VHDL code of the testbench doesn't need to be changed and recompiled for different stimuli command sets. Different command set files can be presented to the VHDL testbench, or command files can be interactively changed during debugging.

While the advantage of not having to recompile the VHDL testbench has decreased due to increased computer and tool performance, a major part of the advantage remains valid for reusability and having a first decoupled level of abstraction for stimuli above the VHDL code.

This is particularly applicable to CPUs attached or integrated into components under development. For example, an IP such as an I2C-controller with a HW/SW interface can be tested with the same stimuli, whether attached to an AXI-bus in a SOC of the latest generation or to a plain microcontroller bus connected via copper on a PCB to an FPGA housing the I2C controller IP.

SimStm focuses on this purpose. It delivers a command set that is fixed and suitable for all needs in this context. The command set is defined by a domain-specific language that provides and controls all necessary keywords and object references, called the SimStm language. The commands are referred to as instructions.

The SimStm language is edited within respective IDE plugins for Eclipse or Visual Studio Code editors, supplying state-of-the-art coding support such as syntax highlighting, auto-completion, error detection, and more.

The user starts editing a top.stm file and as many child.stm files as needed. The latter are included by include instructions, which may be nested. Child.stm files can be used in a library manner for reuse.

The SimStm instructions are purposely very close to HW to avoid debugging through too much overhead. All objects declared, such as variables, constants, arrays, implicit labels, etc., are global within one SimStm project. All objects representing values consider the values to be unsigned 32-bit integer values.

Future development steps of SimStm may introduce larger unsigned integer values, e.g., 64-bit, 128-bit, if specified in a new package to be customized by the user. Other parameters may be opened to the user, such as the maximum object ID string length, and others, once their modification has been tested to work as expected. Further development steps may introduce namespaces together with the abilities of the IDE plugins.

The SimStm testbench presents a bus and a signal package source file to the user. These packages can be customized by the user to add busses, signals, or interrupts to the testbench. All other files shall be used unchanged. Eccelerator samples for Wishbone, Avalon, and AXI4lite busses for single read/write accesses are already included.

The primary focus of SimStm is to have a functional verification of all connected IPs via multiple busses with high coverage in a short time. It is not prepared to be used to verify the different conditions and sequences of accesses to the busses like other testbenches. However, it could control these testbenches via respective bus adapters. Eccelerators uses its own HxS tool to design and generate HW/SW interfaces. The patterns used by the generators are verified to work with all circumstances happening on the supported busses all the way to having counterparts in other asynchronous clock domains. The generated instances do not have to be verified again at this depth.

The SimStm language can be transpiled into Python, C, and other programming languages to use the code written in SimStm for a first test of a target HW. Thus, a functional coverage test is achieved very fast when the real target HW arrives. The transport and isolation of problems from the real application to the simulation environment and vice versa are simplified. Interaction between SW and HW developers is simplified too since SW developers can work with SimStm code rather than VHDL.

Features and Advantages

  • Compact and lightweight
  • Pure VHDL 2008, no use of a vendor-specific simulator interface
  • Easy to debug within any simulator, instructions close to HW
  • Abstraction of test code by SimStm language
  • State-of-the-art SimStm language IDE support for rapid test case creation
  • Test case code change and test without recompilation
  • SimStm language transpiles to Python or C, thus simulation code can be reused for the test of real target HW
  • Easily customizable to support user-defined busses, signals, and interrupts
  • Standard busses Axi4Lite, Avalon, and Wishbone are included

Installation and Usage of the Plugins

Visual Studio Code

  • Open Visual Studio Code.
  • Go to the Extensions Marketplace.
  • Search for "SimStm" and install the plugin.
  • Create or open a ".stm" test script file.
  • Leverage the plugin's IDE features to enhance your testing workflow.

Eclipse

  • Navigate to Eccelerators.
  • Download the "SimStm" Eclipse plugin.
  • Unpack it to a local folder.
  • Open Eclipse and navigate via the menu to "Help", "Install new Software..."
  • Press the "Add" button.
  • Choose "Local", enter SimStm as the plugin name.
  • Browse to the folder you have unpacked as the location.
  • Press the "Install" button.
  • Create or open a ".stm" test script file within a project.
  • Leverage the plugin's IDE features to enhance your testing workflow.

Overview and Integration into User Testbench

The following picture illustrates how the tb_simstm module is integrated into the user testbench. The tb_simstm module should not be changed by the user. The signals and interrupts that the user wants to control the DUT or the Mocks shall be defined in tb_signals_pkg. The buses the user wants to connect to the DUT or the Mocks shall be defined in tb_bus_pkg, and eventually, a new bus type package if the predefined buses aren't sufficient. All other packages shall not be changed.

simstm-overview

Contributions and Bugs

Eccelerators accepts GitHub pull requests, GitHub issues, or an email to trigger a bug fix. Reported issues with samples cut down to reproduce a bug are highly appreciated. In the case of email, please send it to [email protected].

Eccelerators may accept pull requests for small improvements.

SimStm language instructions

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. A dollar sign as prefix is used to reference to object content e.g. variables. No space is allowed between the dollar sign and referenced object ID. Otherwise the SimStm language is not white space sensitive.

The SimStm language is case sensitive.

All constant, variable or label ID 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 Main:is the entry point into the SimStm code for the simulator.

Comments

${\color{green}\texttt{-- This is a full line comment}}$
${\color{purple}\texttt{const} \space \color{black}\texttt{aconst 0x03} \color{green}\texttt{ -- This is an appended line comment}}$

Comments in a line start with two hyphens.
There are only line comments but no block comments.

Includes, Language Objects, and Declarations

Include

${\color{purple}\texttt{include} \space \color{blue}\texttt{"aninclude.stm"}}$

Include another child *.stm file.

Include instructions should be the first instructions of a *.stm file. An included file can include further *.stm files, thus nested includes are possible. The file path to be given is relative to the file with the respective include instruction. Nested includes of files from the same folder or in child folders are predictable; nested includes to files in parent folders would be bad practice.

Const

${\color{purple}\texttt{const} \space \color{black}\texttt{aconst 0x03}}$
${\color{purple}\texttt{const} \space \color{black}\texttt{bconst 0b011}}$
${\color{purple}\texttt{const} \space \color{black}\texttt{cconst 3}}$

Declare and define a constant with ID and hex, binary, or decimal unsigned 32-bit integer value.
It isn't possible to initialize a constant by referencing another constant or variable.

Var

${\color{purple}\texttt{var} \space \color{black}\texttt{avar 0x03}}$
${\color{purple}\texttt{var} \space \color{black}\texttt{bvar 0b011}}$
${\color{purple}\texttt{var} \space \color{black}\texttt{cvar 3}}$

Declare and define a variable with ID and initial hex, binary, or decimal unsigned 32-bit integer value.
It isn't possible to initialize a variable by referencing another variable or constant yet. The ${\color{purple}\texttt{equ}}$ instruction must be used within a procedure for this purpose.

Array

${\color{purple}\texttt{var} \space \color{black}\texttt{barray 16}}$

Declare an array with ID and an unsigned 32-bit integer length.
Only arrays with one dimension are possible; the length must be fixed.

File

${\color{purple}\texttt{file} \space \color{black}\texttt{afile} \space \color{blue}\texttt{"filename.stm"}}$
${\color{purple}\texttt{file} \space \color{black}\texttt{afile} \space \color{blue}\texttt{"filename\{\}\{\}.stm"} \space \color{grey}\texttt{\$} \color{black}\texttt{index1} \space \color{grey}\texttt{\$} \color{black}\texttt{index2}}$

Declare a file with ID and 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 each time when a reference to a file is used in another instruction accessing a file, e.g., ${\color{purple}\texttt{file read all} \space \color{black}\texttt{afile} \space \color{black}\texttt{alines}}$.

Lines

${\color{purple}\texttt{lines} \space \color{black}\texttt{alines}}$

Declare a lines object with 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., ${\color{purple}\texttt{lines insert array} \space \color{black}\texttt{alines} \space \color{black}\texttt{9} \space \color{black}\texttt{barray}}$.

Signal

${\color{purple}\texttt{signal} \space \color{black}\texttt{asignal}}$

Declare a signal object with 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.

Bus

${\color{purple}\texttt{bus} \space \color{black}\texttt{abus}}$

Declare 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.

Equations and Arithmetic Operations

equ

${\color{purple}\texttt{equ} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{equ} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Copy the value of operand2 variable, constant, or numeric value into variable operand1 value or copy the value 0xF0 into variable operand1 value.

add

${\color{purple}\texttt{add} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{add} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Add variable or constant operand2 value to variable operand1 value or add value 0xF0 to variable operand1 value. The resulting value of the addition is in variable operand1 value after the operation.

sub

${\color{purple}\texttt{sub} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{sub} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Subtract variable or constant operand2 value from variable operand1 value or subtract value 0xF0 from variable operand1 value. The resulting value of the subtraction is in variable operand1 value after the operation.

mul

${\color{purple}\texttt{mul} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{mul} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Multiply variable or constant operand2 value with variable operand1 value or multiply value 0xF0 with variable operand1 value. The resulting value of the multiplication is in variable operand1 value after the operation.

div

${\color{purple}\texttt{div} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{div} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Divide variable operand1 value by variable or constant operand2 value or divide variable operand1 value by value 0xF0. The resulting value of the division is in variable operand1 value after the operation.

and

${\color{purple}\texttt{and} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{and} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Bitwise and variable or constant operand2 value with variable operand1 value or bitwise and value 0xF0 with variable operand1 value. The resulting value of the bitwise and is in variable operand1 value after the operation.

or

${\color{purple}\texttt{or} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{or} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Bitwise or variable or constant operand2 value with variable operand1 value or bitwise or value 0xF0 with variable operand1 value. The resulting value of the bitwise or is in variable operand1 value after the operation.

xor

${\color{purple}\texttt{xor} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{xor} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Bitwise xor variable or constant operand2 value with variable operand1 value or bitwise xor value 0xF0 with variable operand1 value. The resulting value of the bitwise xor is in variable operand1 value after the operation.

shl

${\color{purple}\texttt{shl} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{shl} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Bitwise shift left variable or constant operand2 value with variable operand1 value or bitwise shift left value 0xF0 with variable operand1 value. The resulting value of the bitwise shift left is in variable operand1 value after the operation.

shr

${\color{purple}\texttt{shr} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{shr} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Bitwise shift right variable or constant operand2 value with variable operand1 value or bitwise shift right value 0xF0 with variable operand1 value. The resulting value of the bitwise shift right is in variable operand1 value after the operation.

inv

${\color{purple}\texttt{inv} \space \color{black}\texttt{operand1} \space \color{grey}\texttt{\$} \color{black}\texttt{operand2}}$
${\color{purple}\texttt{inv} \space \color{black}\texttt{operand1} \space \color{black}\texttt{0xF0}}$

Bitwise invert variable operand1 value. The resulting value of the bitwise invert is in variable operand1 value after the operation.

ld

${\color{purple}\texttt{ld} \space \color{black}\texttt{operand1}}$

Calculate logarithmus dualis of variable operand1 value. The resulting value is in variable operand1 value after the operation. The function returns the number of the utmost 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.

Subroutines, Branches, and Loops

proc and end proc

${\color{black}\texttt{aproc} \space \color{grey}\texttt{:}}$
${\color{purple}\texttt{proc}}$
${\color{black}\texttt{...}}$
${\color{black}\texttt{subroutine code}}$
${\color{black}\texttt{...}}$
${\color{purple}\texttt{end proc}}$

Code of a subroutine is placed between a proc and end proc instruction. The subroutine name is a label placed on the line before the proc instruction, e.g., aproc. The label ends with a colon as a label indicator.

call

${\color{purple}\texttt{call} \space \color{grey}\texttt{\$} \color{black}\texttt{aproc}}$

Branches execution to the subroutine with the label aproc and continues execution with the next line when it returns from the subroutine after it has reached an end proc or return instruction there.

return

${\color{purple}\texttt{return}}$

Returns to calling code from a subroutine.

interrupt and end interrupt

${\color{black}\texttt{ainterrupt} \space \color{grey}\texttt{:}}$
${\color{purple}\texttt{proc} \space \color{black}\texttt{ainterrupt}}$
${\color{black}\texttt{...}}$
${\color{black}\texttt{subroutine code}}$
${\color{black}\texttt{...}}$
${\color{purple}\texttt{end proc}}$

Code of an interrupt subroutine is placed between an interrupt and end interrupt instruction. The interrupt subroutine name is a label placed on the line before the proc instruction, e.g., ainterrupt. The label ends with a colon as a label indicator. The label must be given in the tbsignal package by customization and attached to a signal triggering the interrupt. If necessary, the handling of nested interrupts must be resolved there too.

if, elsif, else, and end if

${\color{purple}\texttt{if} \space \color{grey}\texttt{\$} \color{black}\texttt{avar} \space \color{grey}\texttt{=} \space \color{grey}\texttt{\$} \color{black}\texttt{bvar}}$
${\color{black}\texttt{...}}$
${\color{purple}\texttt{elsif} \space \color{grey}\texttt{\$} \color{black}\texttt{avar} \space \color{grey}\texttt{>} \space \color{black}\texttt{0xABC}}$
${\color{black}\texttt{...}}$
${\color{purple}\texttt{elsif} \space \color{black}\texttt{0x123} \space \color{grey}\texttt{<=} \space \color{grey}\texttt{\$} \color{black}\texttt{bvar}}$
${\color{black}\texttt{...}}$
${\color{purple}\texttt{else}}$
${\color{black}\texttt{...}}$
${\color{purple}\texttt{end if}}$

Possible comparison operators are: ${\space \color{grey}\texttt{>= <= > < != =}}$

Compares 2 variables, constants, or numeric values and branches execution to the next line if resolving to true. Otherwise, it branches to the next elsif or else or end if instruction. The if instructions can be nested.

loop

${\color{purple}\texttt{loop} \space \color{grey}\texttt{\$} \color{black}\texttt{lvar}}$
${\color{black}\texttt{...}}$
${\color{purple}\texttt{end loop}}$
${\color{purple}\texttt{loop} \space \color{black}\texttt{32}}$
${\color{black}\texttt{...}}$
${\color{purple}\texttt{end loop} \space }$

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.

abort

${\color{purple}\texttt{abort}}$

Aborts the simulation with severity failure.

finish

${\color{purple}\texttt{abort}}$

Exits the simulation with severity note or error. The latter occurs only if resume has been set to other values than 0, and there were verify errors in verify instructions.

Array Access

Array Set

${\color{purple}\texttt{array set} \space \color{black}\texttt{barray} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar} \space \color{grey}\texttt{\$} \color{black}\texttt{avar}}$
${\color{purple}\texttt{array set} \space \color{black}\texttt{barray} \space \color{black}\texttt{5} \space \color{grey}\texttt{\$} \color{black}\texttt{avar}}$
${\color{purple}\texttt{array set} \space \color{black}\texttt{barray} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar} \space \color{black}\texttt{5}}$
${\color{purple}\texttt{array set} \space \color{black}\texttt{barray} \space \color{black}\texttt{3} \space \color{black}\texttt{5}}$

Set the value of an array at a position.

Array Get

${\color{purple}\texttt{array get} \space \color{black}\texttt{barray} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar} \space \color{black}\texttt{tvar}}$
${\color{purple}\texttt{array get} \space \color{black}\texttt{barray} \space \color{black}\texttt{5} \space \color{black}\texttt{tvar}}$

Get the value of an array from a position.

Array Size

${\color{purple}\texttt{array size} \space \color{black}\texttt{barray} \space \color{grey}\texttt{\$} \color{black}\texttt{tvar}}$

Get the size of an array.

Array Pointer Copy

${\color{purple}\texttt{array pointer copy} \space \color{black}\texttt{tarray} \space \color{black}\texttt{sarray}}$

Copy an array pointer; for example, tarray pointer is a copy of sarray pointer after the execution of the instruction. Used, for instance, to hand over an array to a subroutine. Changes to the source array happen in the target array too.

File Access

File Writeable

${\color{purple}\texttt{file writeable} \space \color{black}\texttt{afile} \space \color{black}\texttt{rvar}}$

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

File Readable

${\color{purple}\texttt{file readable} \space \color{black}\texttt{afile} \space \color{black}\texttt{rvar}}$

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

File Appendable

${\color{purple}\texttt{file appendable} \space \color{black}\texttt{afile} \space \color{black}\texttt{rvar}}$

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

File Write

${\color{purple}\texttt{file write} \space \color{black}\texttt{afile} \space \color{black}\texttt{alines}}$

Write all lines of an alines object to a file. The file is overwritten if it exists.

File Append

${\color{purple}\texttt{file write} \space \color{black}\texttt{afile} \space \color{black}\texttt{alines}}$

Append all lines of an alines object to a file. The method will fail if the file doesn't exist.

File Read All

${\color{purple}\texttt{file read all} \space \color{black}\texttt{afile} \space \color{black}\texttt{alines}}$

Read all lines of a file into an alines object.

File Read

${\color{purple}\texttt{file read} \space \color{black}\texttt{afile} \space \color{black}\texttt{alines} \space \color{grey}\texttt{\$} \color{black}\texttt{nvar}}$
${\color{purple}\texttt{file read} \space \color{black}\texttt{afile} \space \color{black}\texttt{alines} \space \color{black}\texttt{10}}$

Read a number of lines from a file into an alines object. 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.

File Read End

${\color{purple}\texttt{file read end} \space \color{black}\texttt{afile}}$

End the piecewise read process of a file.

File Pointer Copy

${\color{purple}\texttt{file pointer copy} \space \color{black}\texttt{tfile} \space \color{black}\texttt{sfile}}$

Copy a file pointer; for example, tfile pointer is a copy of sfile pointer after the execution of the instruction. Used, for instance, to hand over a file to a subroutine. Changes to the source file happen in the target file too.

Lines Access

Lines Get

${\color{purple}\texttt{lines get array} \space \color{black}\texttt{alines} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar} \space \color{black}\texttt{tarray} \space \color{black}\texttt{rvar}}$
${\color{purple}\texttt{lines set array} \space \color{black}\texttt{alines} \space \color{black}\texttt{9} \space \color{black}\texttt{tarray} \space \color{black}\texttt{rvar}}$

Get a line from a lines object at a given position and write its content into an array. 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.

Lines Set

${\color{purple}\texttt{lines set array} \space \color{black}\texttt{alines} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar} \space \color{black}\texttt{sarray}}$
${\color{purple}\texttt{lines set array} \space \color{black}\texttt{alines} \space \color{black}\texttt{9} \space \color{black}\texttt{sarray}}$
${\color{purple}\texttt{lines set message} \space \color{black}\texttt{alines} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar} \space \color{blue}\texttt{"Some message to be written to a file later"}}$
${\color{purple}\texttt{lines set message} \space \color{black}\texttt{alines} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar} \space \color{blue}\texttt{"Value1: \{\} Value2: \{\} to be written to a file later"}\space \color{grey}\texttt{\$} \color{black}\texttt{mvar1} \space \color{grey}\texttt{\$} \color{black}\texttt{mvar2}}$

Set a line at a given position of a lines object. 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 which are filled by values of variables given after the message string.

Lines Insert

${\color{purple}\texttt{lines insert array} \space \color{black}\texttt{alines} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar} \space \color{black}\texttt{sarray}}$
${\color{purple}\texttt{lines insert array} \space \color{black}\texttt{alines} \space \color{black}\texttt{9} \space \color{black}\texttt{sarray}}$
${\color{purple}\texttt{lines insert message} \space \color{black}\texttt{alines} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar} \space \color{blue}\texttt{"Some message to be written to a file later"}}$
${\color{purple}\texttt{lines insert message} \space \color{black}\texttt{alines} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar} \space \color{blue}\texttt{"Value1: \{\} Value2: \{\} to be written to a file later"} \space \color{grey}\texttt{\$} \color{black}\texttt{mvar1} \space \color{grey}\texttt{\$} \color{black}\texttt{mvar2}}$

Insert 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 which are filled by values of variables given after the message string.

Lines Append

${\color{purple}\texttt{lines append array} \space \color{black}\texttt{alines} \space \color{black}\texttt{sarray}}$
${\color{purple}\texttt{lines append message} \space \color{black}\texttt{alines} \space \color{blue}\texttt{"Some message to be written to a file later"}}$
${\color{purple}\texttt{lines append message} \space \color{black}\texttt{alines} \space \color{blue}\texttt{"Value1: \{\} Value2: \{\} to be written to a file later"}\space \color{grey}\texttt{\$} \color{black}\texttt{mvar1} \space \color{grey}\texttt{\$} \color{black}\texttt{mvar2}}$

Append a line at the end of a lines object. The line can be derived from an array or a message. The message string can contain {} placeholders which are filled by values of variables given after the message string.

Lines Delete

${\color{purple}\texttt{lines delete} \space \color{black}\texttt{alines} \space \color{grey}\texttt{\$} \color{black}\texttt{pvar}}$
${\color{purple}\texttt{lines delete} \space \color{black}\texttt{alines} \space \color{black}\texttt{3}}$

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

Lines Size

${\color{purple}\texttt{lines size} \space \color{black}\texttt{alines} \space \color{black}\texttt{rvar}}$

Get the size of a lines object, which is the number of lines it contains currently.

Lines Pointer Copy

${\color{purple}\texttt{lines pointer copy} \space \color{black}\texttt{tlines} \space \color{black}\texttt{slines}}$

Copy a lines pointer; for example, tlines pointer is a copy of slines

Log

Log Message

${\color{purple}\texttt{log message} \space \color{grey}\texttt{\$} \color{black}\texttt{vvar} \space \color{blue}\texttt{"A message to the console"}}$
${\color{purple}\texttt{log message} \space \color{grey}\texttt{\$} \color{black}\texttt{vvar} \space \color{blue}\texttt{"A message to the console\{\}\{\}"} \space \color{grey}\texttt{\$} \color{black}\texttt{mvar1} \space \color{grey}\texttt{\$} \color{black}\texttt{mvar2}}$

Print 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.

Log Lines

${\color{purple}\texttt{log lines} \space \color{grey}\texttt{\$} \space \color{black}\texttt{vvar} \space \color{black}\texttt{slines}}$

Dump a lines object at a given verbosity level to the console.

Verbosity

${\color{purple}\texttt{verbosity} \space \color{grey}\texttt{\$} \color{black}\texttt{vvar}}$
${\color{purple}\texttt{verbosity} \space \color{black}\texttt{20}}$

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

${\color{purple}\texttt{const} \space \color{black}\texttt{FAILURE} \space \color{black}\texttt{0}}$
${\color{purple}\texttt{const} \space \color{black}\texttt{WARNING} \space \color{black}\texttt{10}}$
${\color{purple}\texttt{const} \space \color{black}\texttt{INFO} \space \color{black}\texttt{20}}$

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.

Wait

${\color{purple}\texttt{wait} \space \color{grey}\texttt{\$} \color{black}\texttt{wvar}}$
${\color{purple}\texttt{wait} \space \color{black}\texttt{10000}}$

Waits for the given number of nanoseconds.

Random Numbers

Random

${\color{purple}\texttt{random} \space \color{black}\texttt{tvar} \space \color{grey}\texttt{\$} \color{black}\texttt{minvar} \color{grey}\texttt{\$} \space \color{black}\texttt{maxvar}}$
${\color{purple}\texttt{random} \space \color{black}\texttt{tvar} \space \color{black}\texttt{0} \space \color{black}\texttt{10}}$

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

Seed

${\color{purple}\texttt{seed} \space \color{grey}\texttt{\$} \color{black}\texttt{svar}}$
${\color{purple}\texttt{seed} \space \color{black}\texttt{10}}$

Set the internal start value for the random number generator.

Debug

Trace

${\color{purple}\texttt{trace} \space \color{grey}\texttt{\$} \color{black}\texttt{svar}}$
${\color{purple}\texttt{trace} \space \color{black}\texttt{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.

  • Setting the bit 0 in the given value prints the lines of code with some additional information.
  • Setting the bit 1 dumps all(!) objects before a line is executed.
  • Setting the bit 2 dumps all file names currently in use.

Marker

${\color{purple}\texttt{marker} \space \color{grey}\texttt{\$} \color{black}\texttt{svar} \space \color{grey}\texttt{\$} \color{black}\texttt{lvar}}$
${\color{purple}\texttt{marker} \space \color{black}\texttt{0xF} \space \color{black}\texttt{0b1}}$

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 Executing_Line and Executing_File tb_simstm intern variables are always present and show the currently executed line of code.

Signal and Bus Access

Signal Write

${\color{purple}\texttt{signal write} \space \color{black}\texttt{asignal} \space \color{grey}\texttt{\$} \color{black}\texttt{svar}}$
${\color{purple}\texttt{signal write} \space \color{black}\texttt{asignal} \space \color{black}\texttt{0b11}}$

Write variable, constant, or numeric value to a signal.

Signal Read

${\color{purple}\texttt{signal read} \space \color{black}\texttt{asignal} \space \color{black}\texttt{tvar}}$

Read the value of a signal into a variable.

Signal Verify

${\color{purple}\texttt{signal verify} \space \color{black}\texttt{asignal} \space \color{black}\texttt{tvar} \space \color{grey}\texttt{\$} \color{black}\texttt{evar} \space \color{grey}\texttt{\$} \color{black}\texttt{mvar}}$
${\color{purple}\texttt{signal verify} \space \color{black}\texttt{asignal} \space \color{black}\texttt{tvar} \space \color{black}\texttt{0x01} \space \color{black}\texttt{0x0F}}$

Read the value of a signal into a variable and compare 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.

Bus Write

${\color{purple}\texttt{bus write} \space \color{black}\texttt{abus} \space \color{grey}\texttt{\$} \color{black}\texttt{svar}}$
${\color{purple}\texttt{bus write} \space \color{black}\texttt{abus} \space \color{black}\texttt{0b11}}$

Write a variable, constant, or numeric value to a bus.

Bus Read

${\color{purple}\texttt{bus read} \space \color{black}\texttt{abus} \space \color{black}\texttt{tvar}}$

Read the value of a bus into a variable.

Bus Verify

${\color{purple}\texttt{bus verify} \space \color{black}\texttt{abus} \space \color{black}\texttt{tvar} \space \color{grey}\texttt{\$} \color{black}\texttt{evar} \space \color{grey}\texttt{\$} \color{black}\texttt{mvar}}$
${\color{purple}\texttt{bus verify} \space \color{black}\texttt{abus} \space \color{black}\texttt{tvar} \space \color{black}\texttt{0x01} \space \color{black}\texttt{0x0F}}$

Read the value of a bus into a variable and compare 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 and reports an error.

Bus Timeout

${\color{purple}\texttt{bus timeout} \space \color{black}\texttt{abus} \space \color{grey}\texttt{\$} \color{black}\texttt{svar}}$
${\color{purple}\texttt{bus timeout} \space \color{black}\texttt{abus} \space \color{black}\texttt{1000}}$

Sets the timeout in nanoseconds to wait for a bus access to end. On violation, the simulation stops with severity failure always.

Resume

${\color{purple}\texttt{resume} \space \color{grey}\texttt{\$} \color{black}\texttt{EXIT\_ON\_VERIFY\_ERROR}}$
${\color{purple}\texttt{resume} \space \color{black}\texttt{0}}$

Usual practice is to use the following constants to set verbosity:
${\color{purple}\texttt{const} \space \color{black}\texttt{RESUME\_ON\_VERIFY\_ERROR} \space \color{black}\texttt{1}}$
${\color{purple}\texttt{const} \space \color{black}\texttt{EXIT\_ON\_VERIFY\_ERROR} \space \color{black}\texttt{0}}$

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.

Examples

Hello World

${\color{purple}\texttt{const} \space \color{black}\texttt{YEAR} \space \color{black}\texttt{0x2023} }$
${\color{purple}\texttt{var} \space \color{black}\texttt{month} \space \color{black}\texttt{0x11}}$
${\color{purple}\texttt{var} \space \color{black}\texttt{day} \space \color{black}\texttt{0x22}}$

${\color{black}\texttt{Main} \space \color{grey}\texttt{:}}$
${\color{purple}\texttt{proc}}$
${\space \space \space \space \color{purple}\texttt{loop} \space \color{black}\texttt{3} }$
${\space \space \space \space \space \space \space \space \color{green}\texttt{-- currently values are printed in hex format only}}$
${\space \space \space \space \space \space \space \space \color{purple}\texttt{log message} \space \color{black}\texttt{0} \space \color{blue}\texttt{"Hello World \{\}-\{\}-\{\}"} \space \color{grey}\texttt{\$} \color{black}\texttt{YEAR} \space \color{grey}\texttt{\$} \color{black}\texttt{month} \space \color{grey}\texttt{\$} \color{black}\texttt{day}}$
${\space \space \space \space \color{purple}\texttt{end loop}}$

${\color{purple}\texttt{finish}}$
${\color{purple}\texttt{end proc}}$

This example is a unit test too and can be found in the repository folder test/others/hello_world.

An demonstration of all commands is in the file command_list.stm in the repository root folder..

Unit Tests

The test folder contains unittest for all commands. Thus all commands are verified for each release by regression tests.

SPI Controller

A complex real-world example is found in the eccelerators spi_controller repository on GitHub, see https://github.com/eccelerators/spi-controller.