Language Overview
Scope and model
A TScript file is a sequence of commands and expressions.
-
A line can execute a global command, an object command method, an assignment, or an expression.
-
Newline is a statement separator (internally treated like
;). -
;can also be used explicitly to separate statements. -
Lines can be continued with a trailing
\. -
Blocks use
{ … }.
File Extensions
By convention TScript is written in files using the extension .temu.
TEMU also recognise .ts, and .tscript but the ts-extension may clash with TypeScript.
Comments
TScript supports comments using either of the single line shell style (#) or C style (//).
The shell-style comments has been supported since TEMU 2 while the C-style comments were added in TEMU 3.
C-style comments are the preferred style since TEMU 3.
echo Hello // trailing comment
echo World # trailing comment
Lexical elements
Literals
-
Integers: decimal, binary (
0b…), octal (0o…), hexadecimal (0x…) -
Reals: decimal floating-point (supports exponent notation)
-
Strings: single-quoted or double-quoted
Numeric literals may contain _ for readability.
a = 123
b = 0xDEAD_BEEF
c = 0b1010_0011
d = 3.1415
e = 1.2e-3
s = "hello"
t = 'world'
Commands and Command Methods
Commands are stand alone global commands. This was the only type of command in TEMU 2. TEMU 3 introduces command method, a command that is associated to a specific class and invoked on objects.
The difference is that when interacting with objects using a traditional command, the object must be passed explicitly and the command must verify the type or compliance of the object to what the command expects, for a command method, this is not the case since they can only be invoked on objects that are already compliant to whatever rules are imposed on the object.
Meta Classes and Class Objects
In TEMU 3, TScript has been extended with meta classes and class objects.
This primarily means that an object can be created using the class objects new method.
The new method does by default only take one argument (the object name) but classes can (in C or C++) customise the new method by querying for it by name from the class objects meta class and adding named required or optional arguments to the method reference.
Each registered class has a class object with the name of the class, in addition each class object is associated with a meta class, with the name @{CLASS_NAME}. In addition a root meta class responsible for constructing class and meta class pairs exists, this root class is named @MetaClass.
You should normally not be interacting with the meta classes directly, but they exist there to maintain property and methods registries for the class objects.
Variables and Assignments
Assignment uses =:
answer = 42
path = ./my/file
Variable reads use $name or ${name}:
echo $answer
load file=${TEST_ROOT}/image.elf obj=cpu0
Inside defcmd, parameters become scoped variables and are typically read via $paramName.
Expressions
Tscript supports expressions. The operators supported depends on the type of the left and right hand sides.
| Operator | Kind | Types |
|---|---|---|
+ |
Binary |
integer, float |
- |
Binary, Unary |
integer, float |
/ |
Binary |
integer, float, paths |
* |
Binary |
integer, float |
./ |
Unary |
paths |
<< |
Binary |
integers |
>> |
Binary |
integers |
| |
Binary |
integers |
& |
Binary |
integers |
~ |
Unary |
integers |
! |
Unary |
integers |
The condition in if/elif must evaluate to an integer (0 = false, non-zero = true).
Error Handling
The TScript language supports emitting command errors. In-non-interactive mode, a command error aborts the executing script.
There are two ways of interacting with command errors in the TScript language itself.
These are the try and raise keywords.
try
The try keywords executes a command and converts any errors to integers.
In non-interactive mode this can be used to prevent a failing command
from stopping the interpreter.
More importantly though is that it can be used in if-else constructs
to conditionally run code when a command succeeds or fails.
try <command> executes a command and returns an integer status:
-
1on success -
0on failure (error is suppressed)
if try load file=missing.elf obj=cpu0 {
echo "loaded"
} else {
echo "failed"
}
raise
Raises a command error with a string message:
raise "Danger Will Robinson"
A raised error stops the command execution in non-interactive mode.
By it self it is less useful, but serves a purpose in the custom commands
defined with defcmd.
In these cases the command in question fails, and the failure can be handled by the script using if else.
// Simulate bootloader
defcmd boot(file: path) {
if !try load obj=mem0 file=$file {
raise "Could not load file"
}
cpu0.setPC pc=0x40000000
}
if try boot file="foo.elf" {
echo "Boot succeeded"
} else {
echo "Boot failed"
}
Commands and Command Methods
Commands are entities that can fail. A command halts execution of a script if running non interactivelly. Functions however are expressions and cannot fail.
Commands can be converted to expression values which will prevent non-interactive scripts from terminating by using the try keyword which converts the result of the command to a 1 for success and 0 for failure.
Command Definitions
It is possible to define commands both using the TEMU API and by defining commands in a TScript file.
defcmd mycmdname(a: string, b: path) {
echo $a
echo $b
}
mycmdname a=hello b=file.txt
A command can be failed using the raise statement.
A common use of a command would be to implement boot software emulation. The following example shows how a LEON3 processor can be booted:
defcmd boot(app: path) {
if try load obj=mem0 file=${app} start-addr-var=startpc {
if defined(startpc) {
cpu0.setPC pc=$startpc
}
// Scaler reload register should be freq in MHz - 1
grTimer0.scalerReload = cpu0.freq / 1e6 - 1
// Prepare stack and frame pointer registers
cpu0.setReg reg="%fp" value=0x40000000 + ram0.size - 4
cpu0.setReg reg="%sp" value=0x40000000 + ram0.size - 4 - 92
} else {
raise "Failed to load file"
}
}
Command Argument Types
The argument list is in the form of name type pairs, the argument name comes first, followed by a colon and then the typename. A number of types are supported at the moment:
-
int: integer type
-
real: double precision floating point
-
string: string type
-
path: string type (path indicates to auto completion to complete paths)
-
object: temu object type
-
class: temu class object
-
iface: interface reference
-
prop: property reference
The arguments are available as scoped variables in the command body.
Object properties and indexing
Property access uses .. Indexed properties use [index].
cpu0.steps = 1234
cpu0.steps
cpu0.extraRegs[0] = 42
cpu0.extraRegs[1] = 50
cpu0.extraRegs[0]
Property writes are type-checked by the property type.
Interface references
Interface references use object:IfaceName and indexed form object:IfaceName[index].
These are commonly passed to typed command arguments.
connect a=mem0.postTransaction b=tracer0:PostAccessIface
connect a=mdiobus0.phyDevices b=phy0:MDIOIface
Built-in functions
Built-in functions can be used in expressions.
| Function | Signature | Description |
|---|---|---|
|
|
Returns |
|
|
Returns |
|
|
Returns |
|
|
Returns |
|
|
Binary string formatting ( |
|
|
Compact binary formatting ( |
|
|
Octal string formatting ( |
|
|
Compact octal formatting. |
|
|
Decimal string formatting ( |
|
|
Compact decimal formatting. |
|
|
Hex string formatting ( |
|
|
Compact hex formatting. |
|
|
Returns TEMU major version. |
|
|
Returns TEMU minor version. |
|
|
Returns TEMU patch version. |