Behavior/Script
Block Name: Script (Virtual_Machine)
Code File Location: VisualSim/actor/lib/Virtual_Machine
/*
Script
*/
count
= 0 /* Initialize
Count */
LABEL: BEGIN /* Block Inputs start here */
while (count < 10) /* Perform loop 10 times */
{
count = count + 1
SEND(output, "Count = " + count)
}
if (port_name == "input")
{
QUEUE ("MyQueue", port_token, 0, put)
Length = getBlockStatus(Block_Name, "MyQueue", "length", 0)
SEND(output, "MyQueue Length = " +
Length)
}
else if (port_name == "virtual")
{
throwMyException (Block_Name + " detected a virtual transaction.")
}
Parameter_Name
Parameter_Value
Description
Path
none
path to
block, can include "VS/" to be generic
Read_File
none
name of script.txt,
using above path
Save_Files
false
save parsed script, using
above path
Profile_File
none
profile
file name, "MyProfile.txt", for example
Listen_to_File
none
output listen to block to a
file, "MyListenToFile.txt", for example
Duplicate_Input
true
duplicate incoming data structure, if single
input and output, can improve performance
Profile
0
profile script as an array of instructions executed by
Virtual Machine, useful for estimating algorithm perf.
Maximum_Loops
10000000
maximum loops in a while loop,
million default, some models may need a larger value.
Block_Reference
Block_Name
Block_Reference is used to define a unique
Virtual_Machine block (Block_Path + Block_Name)
Port_Order_Array
{"input"} VM block will
add user added fields internally, else user can define order of reading
here
Add_Scheduler_Times_to_DS
false
default is false, no scheduler times added, or stats. Set to true
for all QUEUE, TIMEQ statistics
The Virtual Machine contains an initialize section, an input queue, the sequence of code execution and outputs. The initialize section is the portion of the code prior to LABEL: BEGIN. This is executed at the beginning of the simulation. The input queue is a non-priority queue and will list data structures arriving on all the input port and from virtual connections. The data structures will trigger the code in the order of arrival. The outputs can be a port of the block or a virtual device in the model. They can be triggered using a RegEx or the SEND function.
Note: Any Virtual Machine script located in the VS_AR/VisualSim/actor directory cannot be edited and saved. If you need to edit these files, save it in a different directory within the CLASSPATH and define it as a new Class.
The sequence of operation is as follows:
At the start of the simulation, all the initialize code is executed. No input or trigger is required to execute the code. There is no deterministic order of execution of all the virtual machines in the model. They can execute in any order.
When the data structure arrives at the input port or, via a virtual connection, it is placed in the input queue. If there Virtual Machine is free, the head of this queue is removed and is called port_token.
This is port_token executes through the code sequence, in order, beginning from the LABEL:BEGIN. If the data structure encounters a WAIT, EXIT, Queue, GTO(END), TIMEQ, Event or completes execution of all the code; then data structure stops there and the head of the queue becomes the current port_token and starts executing. The currently executing data structure is always called port_token.
When the data structure is released from the QUEUE (using a Pop) or a TIMEQ, it becomes the port_token and executes from the next line of the code.
If the data structure encounters a SEND, it is executed immediately. The code continues to execute until it reaches the END or encounters a delay point. At that point, the data structures in the output queue are sent to the appropriate destination, in the order received.
If the SEND is to a LABEL in the same block, this is treated as a separate thread. This can create a data structure that executes independent of the main sequence.
A WAIT completely stops execution of the Virtual Machine and nothing can execute. This is a blocking request. A TIMEQ delays the current transaction at the next execution line. The next transaction or any other transaction, already executing can continue. Only one transaction executes at any time. Only when it reaches a "end" state, it will release control to another transaction.
Each arriving data structure is assigned the name of the arriving port or "virtual", if from a virtual connection. The name of the data structure is used to identify the port that it arrived at. Unlike the Processing and Decision block, the name of the arriving port must not be used to address the transaction. As there are delays and blocking operations in this block, a new transaction can arrive at input_queue from the same port while the current one is executing. This can cause unwanted results. The special keyword- port_token is used to address the currently executing transaction. There can be multiple port_tokens in a block that are in various states, like at a TIMEQ, WAIT, or a thread.
Virtual_Machine, Smart_Controller now support cancellation of TIMEQ and WAIT events. There are both Block commands (CANCEL()) and RegEx commands (cancelEvent()), which are similar in operation. Details below.
To access the field of a variable or port_token, use the standard format of port_token.field_name, variable_name.field_name and parameter.field_name. Port name is used for making a control decision. For example, the port_name could be used as the SWITCH (port_name). Port name can also be used in a if-else as a test to see the source or origination.
Most Virtual Machine code operate as a single sequence or thread. It is possible to create model with Threads that can execute in parallel. The process to create a Thread is to define a LABEL:”Name” followed by a sequence of code that stands by itself. This will be a continuous loop in most cases. The main thread flow will start this new thread by calling it using the SEND operation. The format is SEND (Label_Name, value). The port_token is normally the best value to be sent out. When the SEND function is called, it starts the new Thread but does not start executing it immediately. When the executing Thread goes to a TIMEQ or a GTO (END) or completes the code execution for a port_token, then the new Thread starts executing as a synchronous (0.0 time event). Using the TIMEQ function allows one to enforce different rates for each thread.
Initialize
All code before the LABEL line, "LABEL: BEGIN" is considered initialize. During the Initialize phase, all the variables are defined and initial values are assigned. To improve simulation performance, parameter values are assigned to internal variables for use within this block. It is possible to define loops and execution sequence in the initialize that can execute any time in the future. This is used for starting the statistics gathering and reporting the same at the termination of a simulation.
Note: An alternate way to initialize is to add the hidden parameter Self_Start to the block and setting the value to true. In this case, the LABEL: BEGIN must not be in the code.
Execution
The sequence of code can utilize the incoming data structures field, variable (local, global and variable-defined inside this block), RegEx language and parameter values. Using the virtual connection methodology, the VM can use the built-in RegEx functions to send the Data Structures to Virtual Connection, Schedulers and other Virtual Machine blocks. The block has a set of standard functions, a set of specific methods and resource definition, and the complete RegEx language.
To access the code, Right-click on the block and select "Open Block". Alternately, the code can be located in a text file.
The block can be self-triggered (set Self_Start = true) or triggered by an incoming data structure (either ports or virtual connections). If the Self_start parameter is set to true for the block, do not use the LABEL: BEGIN. The Self_Start executes the initial code. Self_Start is used when the block will not receive any inputs and will execute in a continuous loop. This is useful for defining arbitration algorithms that run on clock cycles.
The code then execute in sequence. A WAIT in the code creates a blocking operation and prevents any further execution of any data structure until the time has elapsed. A WAIT can also contain an EVENT. This requires the EVENT to be triggered in another block in the model. Additional input/output ports can be added. Virtual_Machine supports both local and global virtual input/output. The input ports will be processed using an "OR" approach, meaning one at a time. The SEND function will send the values to the output ports, vitual connections, other Virtual Machine blocks or a LABEL.
The SEND operation behaves as a port activity of the block. When the SEND is executed, it can cause execution of code in another virtual machine (virtual connection) or a sequence of blocks if connected to the output port or a virtual connection block. The current code will start executing on the next line only when the transaction has encountered a delay, relation or a end of sequence. All of this will occur in zero time.
The Virtual Machine works like a function block in C programming or script. The simple logic expressions use a C/C++ syntax. Note the following:
To learn more about the Virtual Machine, click here for VM_Basic_Features model.
if, if-else, else, else-if |
single line if-else |
while |
LABEL |
SWITCH/CASE/BREAK |
CALL/ RETURN |
GTO |
EXIT or GTO(END) |
CANCEL |
for |
S.NO. |
KEYWORD |
SYNTAX |
DESCRIPTION |
1. |
LABEL |
LABEL:Nam |
|
2. |
If, else if, else |
if(<conditional statement>) { <true statements> } else if(<conditional statement>) { <true statements> } else { <false statements> } |
This is a traditional if condition. |
3. |
Single line If-else |
<conditional statement> ? <true statement> : <false statement |
|
4. |
SWITCH, CASE, BREAK |
SWITCH (port_token.ID) { /* Decodes ID integer field of Transaction */ CASE: 0 <RegEx statements> BREAK /* Exit from script */ CASE: DEFAULT /* Last CASE, unlike C code, must be DEFAULT */ <RegEx statements> GTO (END) /* Exit from script */ } |
This is similar to C format with some differences. |
5. |
While |
while (true) /* Loop */
/* Down Counter */ |
|
6. |
CALL, RETURN |
CALL
(Name) Note: The NAME is a LABEL |
2. Any actions within this routine that jumps out (example: GTO (END)), will prevent the token from returning to the original caller. This means that the lines following the CALL function will not be executed. 3. If there is a TIMEQ within the called routine, the token used in the TIMEQ must be port_token, else an error will be generated. 4. The CALL function stalls the current thread and start executing the called function. When a TIMEQ is encountered in the Called thread, the next item in the input queue starts executing. The code beyond the CALL function does not execute until the return from the called function. |
7. |
CANCEL | CANCEL
(“RemoteBlockName”,
“wait”)
// cancels
first, only event for WAIT CANCEL (“RemoteBlockName”, “MyTimeq”) // cancels first event for MyTimeq CANCEL (“MyTimeq”, Event_Time) // cancels first event with simulation Time = t, user needs to know when event fires. CANCEL (“RemoteBlockName”, “MyTimeq”, Event_ID) // cancels event with EventID > 0, user can copy DSs in TIMEQ to obtain Event_ID field CANCEL (“RemoteBlockName”, “wait”) // cancels first, only event for WAIT CANCEL (“RemoteBlockName”, “MyTimeq”) // cancels first event for MyTimeq CANCEL (“RemoteBlockName”, “MyTimeq”, Event_ID) // cancels event with EventID > 0, user can copy DSs in TIMEQ to obtain Event_ID field CANCEL (“RemoteBlockName”, “MyTimeq”, Event_Time) // cancels first event with simulation Time = t, user needs to know when event fires. public static double cancelEvent(String block_name, String name) { ... } public static double cancelEvent(String block_name, String name, int evt_id) { ... } public static double cancelEvent(String block_name, String name, double time) { ... } |
|
8. |
for |
for(idx=0;idx<10;idx++) { flag_arr(i) = true } |
|
9. |
EXIT or GTO(END) | EXIT |
|
FUNCTIONS |
DESCRIPTION |
SYNTAX |
fragment | this function is used to generate the fragments as per the word size specified | frag_arr=port_token.fragment(burst_word_size) Note: The data structure should contain A_Bytes field which specifies the total payload of the packet which has to be fragmented |
newToken |
this function is used for generating a new data structure |
newDS=newToken("Processor_DS") |
newArray |
this function is used for creating an array of saaid lenth with said values |
arr=newArray(10,true) |
getBlockStatus |
this fuction is used to get the statistics of resource blocks |
resource_data=getBlockStatus(Resource_Name,<option>,int index) <option> can be "copy","length","stats","take" |
1. |
WAIT (<time> or <event> or <clock_hertz>) |
5. |
QUEUE (<queue name>, <token>, <priority>, <queue operation>) |
2. |
SEND (<port name> or <Virtual_Machine(Block_Name)> or <virtual_connection> or <label>, <token expression>, optional <delay>) |
6. |
TIMEQ
(<queue name>, <token>, <priority>, <queue
operation>, <delay expression> or <clock_hertz>) |
3. |
PLOT(<plot_name>,<destination>,<plot_color>,<plot_offset>,<plot_value 1.0 or 0.0>) |
7. |
CLOCK(“MyEvent”) |
4. |
EVENT, newEvent, .event() |
WAIT |
DESCRIPTION: o This is a delay and holds the Virtual_Machine from operating on any data structure until the time has expired. o The WAIT is used for blocking delay, meaning no other statements will execute, till the WAIT() completes. o If the WAIT refers to a string "MyEvent", then it will wait on an EVENT. o If the WAIT refers to a clock_hertz as an integer or long, then it will wait for the specific clock time. |
SYNTAX: CLOCK(“MyEvent”) |
SEND |
S.NO. |
SYNTAX & SUPPORTED FORMATS |
DESCRIPTION |
1. |
SEND (<port name>or <virtual_connection> or <label>, <token expression>) Example: SEND (output, port_token) |
o This method
can send to a port, virtual connection, another Virtual_Machine or to a
LABEL. The first two are to send the data structure out of this
block, the latter to create a thread. o Port_name identifies the output destination. o Token_expression is the value to be output. This can be a string, RegEx operation or a token. o The send to LABEL creates a new Thread within the Virtual_Machine that can be executed parallelly. The <port name> can have the following options: port name of this block, port_token.field_name where the destination is in the field of the data structure, name of another Virtual Machine block in the model, Destination of a IN or MUX block and a LABEL of the current block. The output value can be the port_token, any variable name, field in a variable or a data structure field. The output value can be of any data type.
|
2. |
SEND (<port name>or <virtual_connection>, <token expression>, <delay>) Example: SEND (output, port_token, 1.0) SEND (output, port_token, delay) SEND (output, port_token, BlkVar.field) |
o This method
can send to a port, virtual connection with a delay. Delay can be
a double, block variable, or block variable with a field.
SEND supports (X.field, Y.field, Z.field) field arguments in a block
variable. o Port_name identifies the output destination. o Token_expression is the value to be output. This can be a string, RegEx operation or a token. |
3. |
MyLength =QUEUE (“MyQueueName”, “length”) | gets the statistics, places in block variable "MyStats". |
4. |
MyStats = QUEUE (“MyQueueName”, “stats”) | gets the statistics, places in block variable "MyStats". |
5. |
MyToken = QUEUE (“MyQueueName”, “pop”) | gets the first item out of the Queue, places in block variable "MyToken". |
PLOT |
DESCRIPTION: o One can plot values using the format, presumably with a delay in between one and zero values using a WAIT(), TIMEQ expression. o The plot_value is relative to the current value, to allow for multiple levels, meaning if the offset is 1, and the first value is 0.0, then the plot will go to 0.0, whereas a first value of 1.0 will plot a 2.0 o The supported colors are: |
SYNTAX: PLOT(<plot_name>,<destination>,<plot_color>,<plot_offset>,<plot_value 1.0 or 0.0>)
WAIT(1.0) PLOT("MyPlot","output","red",0,0.0) /* Plot 0.0 with 0 offset */ |
EVENT
|
DESCRIPTION: o A Model Event is similar to a time event, except generated by the user, and can occur at any time between blocks. o In other words, a model condition triggers a Model Event for synchronizing between blocks, or within clock-driven processes. o The most common use is to generate clocks from a single block to multiple blocks waiting for a clock event. |
SYNTAX: EVENT, newEvent, .event() |
S.NO. |
SYNTAX & SUPPORTED FORMATS |
DESCRIPTION |
1. |
newEvent (“MyEvent”) | o Model Events
can be generated from any RegEx block using the following RegEx
function. |
2. |
("MyEvent").event()
//A alternate and newer
format for any RegEx block |
o One can also place it an expression, and it will return true if a WAIT() is pending, else false. |
3. |
newEvent(MyParameter + “_MyEvent”) //for events inside hierarchical block | o The argument of newEvent must
evaluate to a string name. o This function can be applied in Processing, Decision, Virtual_Machine or Smart_Controller Blocks. |
4. |
EVENT (“MyEvent”) WAIT (“My_Event_Name”) |
o The
Virtual_Machine and Smart_Controller blocks also support the following
syntax which executes locally on the Virtual_Machine or
Smart_Controller block. o This notation is preferred over the newEvent() RegEx notation. Blocking event WAIT() does not allow any other statements to execute, till the WAIT() continues. The blocking WAIT (“My_Event_Name”) will not allow any other actions in the block, until an EVENT(“My_Event_Name”) is called. The WAIT (time) function and TIMEQ (…,time) functions can include a clock synchronization feature. Currently, the argument ‘time’ can be a double value, meaning the WAIT() or TIMEQ() will wait that amount of time, once it begins execution. If ‘time’ is represented as a long, then the statements will interpret ‘time’ as the clock speed in Hertz. This means that the delay will be based on the current simulation time and when the next clock cycle occurs. If the ‘time’ argument is 1, then this means every 1.0 second a clock will occur. If the statement is executes at 0.0 sec, then the WAIT() or TIMEQ() will complete at 1.0 sec, or one clock cycle later. If the statement executes at 0.5 sec, then the WAIT() or TIMEQ() will complete at 1.0 sec, or the next clock time. In other words, the clock synchronization feature synchronizes execution with this clock rate. |
5. |
WAIT (“MyEvent”) TIMEQ (“My_Event_Name”) |
In a corresponding Virtual_Machine or Smart_Controller block, the user needs a matching syntax as follows. This statement will continue processing on the next statement once it receives a newEvent() or EVENT(). If the newEvent() or EVENT() is generated before the WAIT() on event, characterized as a string argument, then the WAIT() will immediately go to the next statement. Finally, if two newEvent()’s or EVENT()’s are generated prior to a WAIT (“MyEvent”) only one will execute similar to an ‘OR’ of pending events. This is done to prevent the unintentional build up of events in a model, that may not execute as expected. Non-blocking event TIMEQ does allow other statements to execute. The non-blocking TIMEQ(“My_Event_Name”) will allow the block to process other inputs or events, prior to receiving an EVENT (“My_Event_Name”). |
QUEUE |
ATTRIBUTES: o queue_name is an unique identifier. Every queue will have an unique name. This is a string. o Token is the item that needs to be stored in the queue. o Priority is used to reorder the queue. This can be a field, variable or a value. This is an integer. o Queue_operation can be "put" or "pop". put puts the token into the queue and the pop takes it out. The string must be within " ". |
DESCRIPTION:
|
S.NO. |
SYNTAX & SUPPORTED FORMATS |
DESCRIPTION & EXAMPLES (Access within the same Virtual Machine ) |
1. |
QUEUE (<queue name>, <token>, <priority>, <queue operation>) |
QUEUE (queue_one, port_token, 1, "put") |
2. |
MyCopy =QUEUE (“MyQueueName”, “copy”) | gets the first item out of the Queue, places in block variable "MyCopy". |
3. |
MyLength =QUEUE (“MyQueueName”, “length”) | gets the statistics, places in block variable "MyStats". |
4. |
MyStats = QUEUE (“MyQueueName”, “stats”) | gets the statistics, places in block variable "MyStats". |
5. |
MyToken = QUEUE (“MyQueueName”, “pop”) | gets the first item out of the Queue, places in block variable "MyToken". |
STATISTICS OF THE QUEUE |
ATTRIBUTES: o The LHS is a variable that contains the result of the getBlockStatus operation. o o Virtual_Machine_Name is the Block_Reference (default Block_Name) of the Virtual_Machine containing the QUEUE. This is a string in "". o QUEUE_name is the queue for which the options are accessed. This is a string in "". o The options are "copy" (based on the Index number), "stats" (to get the current stats if index=1 and reset stats if index=-1), "length" (to get the current queue length) and "take" (remove the position in the queue based on index value). o Index is an integer value. For "copy", this is position in the queue. For "stats", this gets the stats (1) or resets the stats (-1). For length, this is not used but a value must be present. For "take", this is the position in the queue. |
FORMAT: getBlockStatus (Virtual_Machine Name, QUEUE_name, <option>, int Index) // one-based Index EXAMPLE: wr_data = getBlockStatus (VM1, "Cache_Access", "stats", 0) |
TIMEQ |
ATTRIBUTES: o queue_name is an unique identifier. Every queue will have an unique name with type string. o Delay_expression is service time for the token when it reaches the head of the queue. |
DESCRIPTION: o This stores the token in a queue in a FIFO fashion, delays it when it comes to the head of the queue and then sends it to the next line to execute. The queue is reordered based on the priority of the incoming token. o Events can be scheduled internal to the Virtual Machine using the TIMEQ much like a Timed Queue block. o Several TIMEQs can be executed in parallel without effecting the delay of other TIMEQs. o TIMEQ need not be declared before use. o TIMEQ "copy", "length", "set", "take" operations will also place the queue length in the block variable "length". This is useful if a "non_block" is performed, the "length" is automatically available.
|
S.NO. |
SYNTAX & SUPPORTED FORMATS |
DESCRIPTION & EXAMPLES (Access within the same Virtual Machine ) |
1. |
TIMEQ (<queue name>, <token>, <priority>, <delay expression>) |
TIMEQ (timequeue_one, port_token, 1, "non_block", port_token.A_Delay) |
2. |
MyCopy =TIMEQ(“MyTimeqName”, “copy”) | copy the first item out of the TIMEQ, places in block variable "MyCopy". |
3. |
MyLength =TIMEQ(“MyTimeqName”, “length”) | gets the statistics, places in block variable "MyLength". |
4. |
MyStats = TIMEQ(“MyTimeqName”, “stats”) | gets the statistics, places in block variable "MyStats". |
5. |
MyToken = TIMEQ(“MyTimeqName”,port_token, 0, 1.0) | gets the first item out of the Queue, places in variable "MyToken". |
6. |
TIMEQ (“MyEvent") | If the TIMEQ has a single parameter which is of type string, then it will wait on an EVENT that matches the string value. |
7. |
TIMEQ (“MyTimeqName”, port_token, 0, round (1.0E06 * Clock_Speed_Mhz)) | If the TIMEQ refers to a
clock_hertz as an integer or long, then it will wait for the specific
clock time. The clock time means that the value align to a clock
boundary. Refer to section Model Event . |
8. |
TIMEQ GTO(END) LABEL: BEGIN |
If a TIMEQ precedes LABEL: BEGIN, GTO (END) is required before LABEL: BEGIN to cause the TIMEQ thread to exit.I |
STATISTICS OF THE TIMEQ |
ATTRIBUTES: o The LHS is a variable that contains the result of the getBlockStatus operation. o Virtual_Machine_Name is the Block_Reference (default Block_Name) of the Virtual_Machine containing the TIMEQ. This is a string in "". o TIMEQ_name is the queue for which the options are accessed. This is a string in "". o The options are "copy" (Index is the position in the TIMEQ), "stats" (to get the current stats if index=1 and reset stats if index= -1), "length" (to get the current queue length) and "take" (remove the 'Index' position in the queue). o Index is an integer value. For "copy", this is position in the queue. For "stats", this gets the stats (1) or resets the stats (-1). For length, this is not used but a value must be present. For "take", this is the position in the queue. |
FORMAT: getBlockStatus (Virtual_Machine Name, TIMEQ_name, <option>, int Index) // one-based Index EXAMPLE: wr_data = getBlockStatus(VM1, "Cache_Access", "stats") |
CLOCK |
DESCRIPTION: oThis is an added variation of EVENT that will selectively fire a WAIT (“MyEvent”) or TIMEQ (“MyEvent”), only if the WAIT or TIMEQ instruction has a data structure waiting, else nothing is executed. o It acts like a virtual clock. |
SYNTAX: CLOCK(“MyEvent”) |
THREADS |
DESCRIPTION:
|
EXAMPLE:
|
HOW TO CREATE A THREAD:
2. The code between LABEL and the end will be a continuous loop in most cases. 3.The main thread flow will start this new thread by calling it using the SEND operation. The format is SEND (Label_Name, value). The port_token is normally the best value to be sent out. 4. When the SEND function is called, it starts the new Thread but does not start executing it immediately. When the executing Thread goes to a TIMEQ, EXIT or a GTO (END) or completes the code execution for a port_token, then the new Thread starts executing as a synchronous (0.0 time event). 5.Using the TIMEQ function allows one to enforce different rates for each thread. |
VARIABLE REFERENCE |
DESCRIPTION:
|
S.NO. |
SYNTAX |
DESCRIPTION |
1. |
public boolean setTrace (String trace_name, boolean flag) { ... } |
There is a new RegEx function to
enable tracing of Virtual_Machine, Smart_Controller, Global_variable,
Local_variable. This update allows for turning on/off trace, where
the flag set to true enables tracing, false turns it off. In
UtilityFunctions, this syntax is used. |
2. |
Listen_to_File = none /* by default , change none to the file name in which the listen to file have to be saved, then the file will be saved as per the name specifed in the path mentioned ( another optional parameter ) */ |
The
trace_name can be “variable” to trace global, local variable. So the
user can selectively listen to variable by turning flag on or off.
In the VM blocks, the flag sets, this expression is used. So, user can selectively listen to file by changing the default value "none". trace_name is the name of the specific VM block, useful for DI cases. If setTrace is not used, then the Optional_Parameters work as before defining Listen_to_File. |
3. |
RegEx myTrace (trace_name, trace) | User can send to the trace file without above
setTrace, using this only, just like myWarning.( can be seen in VisualSimTraceLog.txt file ). |
4. |
readAndClearTrace() |
Another RegEx funtion that reads the current trace file, and clears
the current one. This is useful for tracing specific areas, and obtaining the current trace. |
5. |
writeFile(file_name, string) | For saving to a separate file, using this RegEx command. |
6. |
Ref_Mem = ("GlobalVariableName").read() Ref_Mem = (local_variable + "LocalVariableName").read() Ref_Mem = ("BlockVariableName").read("Block_Name") ("GlobalVariableName").check() (local_variable + "LocalVariableName").check() ("BlockVariableName").check("Block_Name") |
In the Virtual_Machine,
Virtual_Machine_Untimed, Smart_Controller, Processing and Decision
blocks, Reference name to a variable (local or global) can be
created. There are variable
reference formats to access local,
global, and block level memory. The last three can be used to first check if the variable exists before reading it. |
7. |
("GlobalVariableName").write(MyToken) (local_variable + "LocalVariableName").write(MyToken) ("BlockVariableName").write("Block_Name", MyToken) |
There are newly supported variable
references for write operation for local, global, and block level variable. The variable local_variable is a keyword that references
the local variable. Writing to these variable locations will alter variable references previously executed. Note: If you place the GlobalVariableName or the Ref_Mem on the LHS of an equation and have an assignment on the RHS, the reference is lost and the two will behave like independent variable variables. |
For example, this is correct:
Ref_Var = (“GlobalVariableName”).read() Ref_Var.incr() Other_Variable = Ref_Var + 2 |
This is incorrect and will delink the variable. Ref_Var = (“GlobalVariableName”).read() Ref_Var = Ref_Var.incr() /* This creates a new space and the reference is lost */ GlobalVaribaleName = Ref_Var + 2 /* This delinks the original reference *. |
S.NO. |
OPERATIONS |
SYNTAX |
DESCRIPTION |
1. |
Fragmentation | fragment() | For the data structure "Processor_DS" , we can fragment the bytes using this function. |
2. |
Fragmentation limit | frag_arr = port_token.fragment(val) | In this format, val
defines the fragmentation limit. if the A_Bytes value is greater than
fragmentation limit, then they gets fragmented. For example: lets say A_Bytes=64 and val=16. Then the frag_arr will have 4 fragmented parts. frag_arr as a whole is a 2D array. In this case frag_arr will be of length 4 and can be accessed from index 0 to 3. |
3. |
Accessing statistics of Model Resources |
getBlockStatus(Resource_Name, <option>, int Index) |
The getBlockStatus is the easiest way to get access to the statistics,
length, first token in the queue and remove the first item in a queue. Usage: wr_data = getBlockStatus(Sched_1, "stats", 0) o The LHS is a variable that contains the result of the getBlockStatus operation. o Resource_Name is the Scheduler or Smart_Resource Block_Name. This is a string in "". o The options are "copy" (gets the head of the queue for the Smart_Resource and not available for the Scheduler), "stats" (current stats if index=1 and reset stats if index= -1for both the Smart_Resource and Scheduler), "length" (get the current queue length for the Smart_Resource and Scheduler) and "take" (remove the head of the queue for the Smart_Resource). o Index is an integer value. For "copy", this is the queue for the Smart_Resource. For "stats", this gets stats (1) or resets the stats (-1) for both the Smart_Resource and Scheduler. For length, this is the queue number of the Smart_Resource and needs any value for the Scheduler. For "take", this is the is the queue number of the Smart_Resource. |
4. |
Length of a specific queue | Smart_Resource_Name+"_"+Length(Queue Number) | The length of the Smart_Resource
is an array of multiple queue and is accessed a lot within the
Virtual_Machine to make a decision. To accelerate the access, the length of a specific queue inside the Smart_Resource can be accessed as given. |
5. |
Length of the Smart_Resource | Smart_Resource_Name+"_"+Length |
You can get the entire array by this format. This will contain an extra value in index 0 which is not used. The queue number to index start at 1. For example, this would beQueue_Length = Smart_Resource_1_Length(10) where Smart_Resource_1 is the name and we are looking for the 10th queue. |
6. |
Scheduler Acess |
scheduleTask(Token token, String return_name, String sched_name, double task_time, double tnow, int task_priority, int task_id, boolean mutex) |
The user can schedule to a Scheduler_HW or Scheduler_SW using the RegEx
scheduler function. This task will return to this Virtual Machine if the return_name, in the expression, is the same as the Block_Reference (Block_Name). |
1. Create a new Token from the VisualSim/data folder |
MyToken = newToken ("Processor_DS") |
2. Create a new variable or Field |
port_token.A_New_Field = Field_Value ("MyNewVariable").write(Variable_Value) where Field_Value or Variable_Value can be a parameter or block level variable.
|
3. Check if Data Structure contains field |
if (port_token.check("A_Command")) |
4. Read a variable or Field and insert into a field of port_token |
port_token.MyField = readField(port_token, Channel_Field_Name) port_token.MyField = port_token.get(Channel_Field_Name) port_token.MyField = (("MyVariable").read()).get(Variable_Field_Name) where Channel_Field_Name or Variable_Field_Name can be a parameter or block level variable.
|
5. Throw a model exception, stop the simulation |
throwMyException (Block_Name + " has a Channel value that is inconsistent.") |
6. Send statement to the Command Line (debug is block variable flag), do not stop the simulation |
debug ? sendToCommandLine (Block_Name + " next Cache Prefetch (" + C_Prefetch.ID + ") \t@ " + formatTime(TNow)) : Tnow |
7. Array processing for 1D operations incrementing, decrementing values; removing head, tail; and searching |
S.NO |
SYNTAX |
DESCRIPTION |
1. |
(MyArray(index)).incr() | can be used for block level arrays, or references to local, global arrays. Returns updated value. |
2. |
(MyArray(index)).decr() | can be used for block level arrays, or references to local, global arrays. Returns updated value. |
3. |
MyArray.removeHead() | removes from position 0. |
4. |
MyArray.removeTail() | removes from last position.Useful for queue-like operations. |
5. |
MyArray.search(matching_token, starting_index) | will return the index of the first matching token, whether integer, long, double, or string. |
6. |
MyArray.firstGreaterThanZero(starting_index) | will return the first index greater than zero, whether integer, long, double. |
8. Array processing for 2D operations incrementing, decrementing values |
S.NO |
SYNTAX |
DESCRIPTION |
1. |
MyArrayArray.incrementArrayArrayElement(index, index2) | increments the specific element. |
2. |
MyArrayArray.decrementArrayArrayElement(index, index2) | decrements the specific element. |
9. Format Time |
formatTime(TNow) ------ 25.43410 us ------ |
10. Identify a Architectural Library Hello Message and add a new device to the Routing Table |
if (port_token.A_Destination == Architecture_Name) | Using the Processor_DS or one
might simply pass the hello message. If A_Destination != Architecture_Name (parameter), then this can be the non-hello message flow |
S.NO |
FUNCTIONS |
SYNTAX & EXAMPLES |
DESCRIPTION |
1. |
++ -- |
++MyInt
// integer ++MyLong // long ++MyDouble // double ++MyDS.MyIntField // data structure integer ++MyDS.MyLongField // data structure long ++MyDS.MyDoubleField // data structure double ++MyArr(index) // array with int, long, double elements Here is an example: This works: Idx = 0 while (Idx < 10) { SEND (output, Idx) ++Idx } |
Applies to single variables only, not functions. These are some ++ examples, which also apply to -- The most common use is for loop indexes. This does not work: Idx = 0 while (++Idx < 10) { // cannot have ++ increment inside a conditional SEND (output, Idx) // or function, just single variables } |
2. |
+= -= *= /= %= |
MyInt
+=
MyInt2
// integer MyLong += MyLong2 // long MyDouble += MyDouble2 // double MyString += MyString2 // string MyInt += MyInt2 + MyInt3 // integer (2) MyLong += MyLong2 + MyLong3 // long (2) MyDouble += MyDouble2 + MySouble3 // double (2) MyString += MyString2 + MyString3 // string (2) |
applies to single and double values only.
Note: That this functional cannot have a expression on the RHS.
If you do so, you will get erroneous results. Here are some
+= examples, which also apply to -=, *=, /=, %=. These expressions are used in loops, conditional statements. The RHS cannot contain functions, just single variables. |
3. |
Address | Here is an example: LABEL: BEGIN |
A keyword that will obtain the current script address and
save as a variable. This is useful for executing Scheduler blocks from a Virtual_Machine by setting a field to address + 2, and computed GTO (port_token.Address). A scheduler will return to the port_name ‘scheduler’. With this mechanism one can process multiple Schedulers with returns in a single Virtual_Machine. |
For small scripts, less than 30 lines, right click the Virtual_Machine block and select Listen to Block. Use this approach to verify the correctness of the RegEx statement during execution. To debug larger scripts, enable the parameter Single_Cycle and set the block parameter Breakpoint to an expression that evaluates to true. The most common “Breakpoint” expression is TNow >= 1.0 (Some time unit). In addition, the "Breakpoint” expression can combine time and a specific address, such as
TNow >= 1.0 && address == 10
To start the debugging, the user must first select Listen to Block for this Virtual_Machine. The first time the "Breakpoint" is valid, a pop-up window will ask:
List_Memories? (Yes or No)
If you accept, all the memories and the current values of the optional parameters will be displayed. When user hits "Run or Resume (Ctrl + R) the model will move to the next execution point where the Breakpoint evaluates to true. After 10 instructions repetitions, a pop-up window will ask:
Continue Single Cycle? (Yes or No)
If the user selects no, then the model will continue to the end of the simulation. Another way to debug a portion of a script execution would be to define a time window:
Breakpoint TNow > 1.0E-03 && TNow < 2.0E-03
This will execute a breakpoint, asking List_Memories? after 1.0E-03 sim time, continue to execute 10 statements for every "Run or Resume..." selection, and once the simulation time, TNow is greater than 2.0E-03, the model will continue to run without single cycle. Users can enter a single line conditional statement to set a value, as long as the statement result is true or false:
Breakpoint TNow>1.0E-03 && TNow<2.0E-03 ? (MyMem == 3 ? (MyMem.newValue(4) == 4 ? true : false) : false) : false
This expression will stop on statement 10, if the Simulation time TNow >= 1.0. Everytime the Run/Resume is pushed, the next script line will execute. In addition, Block_Memories will be displayed prior to the execution of each Single_Cycle statement, so one can checkout the values.
Before each execution statement in Single_Cycle mode, one can see the following (typical) output:
Block Memories: @ 0.10 ns
statistics: {a=1,b=2}
self_start: false
port_token: {BLOCK="Transaction_Source",DELTA=0.0,DS_NAME="Header_Only",ID=1,INDEX=0,TIME=1.0E-10}
port_name: __LABEL__
main_Length: 1
local_variable: MultiThread_VM.
length: 0
input: {BLOCK="Transaction_Source",DELTA=0.0,DS_NAME="Header_Only",ID=1,INDEX=0,TIME=1.0E-10}
first_Length: 1
counter2: 199
counter1: 99
counter: 0
copy: {1,2}
address: 33
__LABEL___Length: 0
TStop: 10.0
TResolution: 1.0E-10
TNow: 1.0E-10
Save_Files: false
Read_File: none
Profile_File: none
Profile: 0
Port_Order_Array: {"input"}
Path: none
MyPlotThread2: true
MyPlotThread1: true
Maximum_Loops: 1000000
Listen_to_File: none
Input_Queue_Length: 0
Duplicate_Input: true
Block_Reference: Threads
Block_Path: MultiThread_VM.
Add_Scheduler_Times_to_DS: false
Expression (33): GTO (2)
Result : 35
*** SEND *** : 0.10 ns
Note: To stop the single cycle debugging, simply close the Listen to Block window and the model will simulate to the end. If you want to stoop the simulation, while in debugging model, click on Stop and then on Go. This will make the simulation stop.
The Script Profiler is embedded
in the block execution and keeps track of the number of times a
statement executes and also the average time the statement took to
execute down to the nano-second level. This feature provides all
users with the detailed execution information about his/her
script. In addition, it provides the script address, and the
script statement associated with that address. If the number of
times executed equals 0, then this provides feedback on whether a
certain function even executed. This may be useful information,
sometimes referred to as code coverage in lower level verification
testing.
Profile_File: The Script
Profiler can be turned on by adding a parameter to the Virtual_Machine
and Smart_Controller block called “Profile_File”. This identifies
the name of the file to be generated by the profiler.
If the parameter does not exist, or is set to “none”, then the Script
Profiler will be turned off. A typical Profile_File, Block_Name +
“_Profiler.txt”.
Path: One
can place the entire path in “Profile_File” variable, or add the “Path”
variable. A typical path, “C:/VisualSim/Profiles”.
The Listen to File is a text based version of listen to block, one just enters a parameter in the block.
Listen_to_File:
The Listen to File can be turned on by adding a parameter to the
Virtual_Machine and Smart_Controller block called
“Listen_to_File”. This identifies the name of the file to be
generated. If the parameter does not exist, or is set
to “none”, then Listen to File will be turned off. A typical
Listen_to_File value is Block_Name + “_Listen_to_File.txt”.
Path:
One can place the entire path in “Listen_to_File” variable, or add the
“Path” variable. A typical path is “C:/VisualSim/Listen_to_Files”.
The Profile is enabled when the Profile parameter is added to the Virtual Machine block and the value is set to true. The profile generates a Instruction Mnemonics for the sequence of execution of the script. The Profile generates the instructions and palces them in arrays. The length of each array is the Profile paramete value. The last array will have "END" in the last index position. The arrays can be output on a port of this block called "profile" The user must add this manually after instantiating the block. Alternately, the user can add a virtual connection called Block_Name + "_Profile". There are some limitations to the code type that can be profiled. All 'for' loops must be modified to a While. The user must also modify [] arrays to (). LHS of an array needs to be a single value, not a computation like i-1. View the example to understand the usage.
Profile parameter is an integer
that defines the maximum length array to be output to a port named
“profile”. This array can be added to a data structure, such as
Processor_DS and send to a Processor block for execution.
Here is a list of ADD instruction types generated from an internal script:
ADD
(int), ADD_l (long), ADD_d (double), ADD_a (array), ADD_m (matrix),
ADD_s (string), IMM (immediate) is x = y, IMM_b (boolean), IMM_r
(record)
Other arithmetic instructions, excluding types:
SUB
(subtract), MUL (multiply), DIV divide), INC (increment), DEC
(decrement), MOD (modulo), POW (power), SHIFT (<< or
>>), IMM (immediate), LT (less than), LTE (less than or
equal), GT (greater than), GTE (greater than or equal), EQ
(equal), FX (function), FXA (function with at least two args)
Script related instructions:
GTO
(goto), BCH (branch), SBR (subroutine), RTN (return), EVENT(event),
CLOCK (special event), WAIT (blocking), TIMEQ (non-blocking), QUEUE,
SEND (thread or port)
Here
is an example of a small loop in a script with the instruction array
generated by a Profile parameter of 1000 to the port added to
the block named “profile”:
Script (software)
------
MyBoolean = true
Idx = 0
while (Idx < 10) {
SEND (output, Idx)
++Idx
}
LABEL: BEGIN
profile Output (array of internal execution)
--------------
DISPLAY AT TIME ------ 0.0 ps ------
{"IMM_b",
"IMM", "LT", "SEND", "INC", "GTO", "LT", "SEND", "INC", "GTO", "LT",
"SEND", "INC", "GTO", "LT", "SEND", "INC", "GTO", "LT", "SEND", "INC",
"GTO", "LT", "SEND", "INC", "GTO", "LT", "SEND", "INC", "GTO", "LT",
"SEND", "INC", "GTO", "LT", "SEND", "INC", "GTO", "LT", "SEND", "INC",
"GTO", "LT", "EXIT"}
/* Clock_Generator_Block VM */ | /* Block_A Script, Clock Loop portion VM */ | /* Block_B Script, Clock Loop portion VM */ |
Speed_Hertz = round (1.0E06 * Speed_Mhz)
LABEL: Loop WAIT (Speed_Hertz) if (Block_A_Ready) { /* No clock if not ready */
EVENT
(“Block_A_Clock”)
/* Trigger Block_A_Clock */ if (Block_B_Ready) { /* No clock if not ready */
EVENT
(“Block_B_Clock”) /*
Trigger Block_B_Clock */ LABEL: BEGIN |
LABEL: Clock_Loop
...
WAIT (“Block_A_Clock”) /* Event from Clock_Generator_Block */ ... GTO (“Clock_Loop”) |
LABEL: Clock_Loop
...
WAIT (“Block_B_Clock”)
/* Event from Clock_Generator_Block */ ... GTO (“Clock_Loop”) |
For example, Block_A_Ready and Block_B_Ready are user generated Boolean values in a model that can mimimize clock events for blocks that have nothing to process.
Another way to generate clocks
for Block_A or Block_B may be to enable the clock when it needs to
process some data. In this case, the WAIT (Next_Cycle) would
appear in the functional blocks, while the enable would be generated
from a newEvent() or EVENT() in the same block or external block.
/* Source_Block requesting processing */ | /* Block_A Script, Clock Loop portion */ |
/* Block_B Script, Clock Loop portion */ |
....
EVENT (“Request_Processing_on_Next_Clock”) /* Trigger Block_A, Block_B */ .... |
Speed_Hertz = round (1.0E06 * Speed_Mhz)
LABEL: Clock_Loop
WAIT
("Request_Processing_on_Next_Clock") /* Event from Source_Block */
WAIT (Speed_Hertz )
/* Proper Clock Boundary */ .... if (Processing_Not_Done) { EVENT (“Request_Processing_on_Next_Clock”) |
Speed_Hertz = round (1.0E06 * Speed_Mhz) LABEL: Clock_Loop
WAIT
("Request_Processing_on_Next_Clock")
/* Event from Source_Block */
WAIT (Speed_Hertz )
/* Proper Clock Boundary */ .... if (Processing_Not_Done) { EVENT (“Request_Processing_on_Next_Clock”) |
The
EVENT() shown in Block_A, Block_B Clock_Loop can sustain the processing
until the task is complete. When the processing is complete
“Processing_Not_Done” would be set false based on user conditions.
The Virtual Machine name can be local or global. If local, then the name is accessible from within the hierarchy window. In case of global, the access is from the whole model. This is similar to the local and global IN and OUT blocks.
S.NO |
RESERVED WORDS |
DESCRIPTION |
1. |
port_name |
Name of input port, scheduler return, or virtual
virtual scheduler input, input2, input3, etc. |
2. |
port_token |
Active data structure from any input, scheduler return, or virtual |
3. |
TNow |
Current Simulation time |
4. |
TStop |
Simulation stop time |
5. |
TResolution |
Simulation resolution time |
6. |
address |
Address of executing statement used in Single_Cycle mode |
7. |
local_variable |
User can construct Local variable prefix, contains "ModelName.HierarchicalName." local variable name = local_variable + variable_name, contains "ModelName.HierarchicalName.VariableName" |
Explanation |
Type |
Example |
|
Block_Name |
Block_Name is a Parameter that needs to be unique in modeling space. |
String |
"MyMachine" |
Optional_Parameters |
List of parameters that are used infrequently. Previously called Hidden Parameters. If the current block has these parameter listed in a separate field, those values get precedence over this list. for more details on these parameter,s look at the list below. |
String |
Parameter_Name
Parameter_Value |
Single_Cycle |
This enables Single Cycle mode in conjunction with the setBreakpoints. Set to "Stop before Executing Timed Activity”. User can "Listen to Block" to see individual instructions executing. Single Cycle mode now supports the “address” of the executing statement and can be used in the “Breakpoint” parameter expression. This improves the debugging capabilities to allow the user to stop on a specific script address. |
Boolean |
- |
Breakpoint |
User can set a breakpoint RegEx expression that can cause the script to pause based on block inputs, variable values, or left-hand side of expression. |
String |
"Variable_Flag" |
Each parameter in this list has a value associated with it. The first line has Parameter_Name Parameter_Value. No suffix or line ending is required.
S.NO |
PARAMETER |
FUNCTIONS |
1. |
Path |
|
2. |
Read_File |
|
3. |
Save_Files |
|
4. |
Profile_File |
|
5. |
Listen_to_File |
|
6. |
Duplicate_Input(Default set to true) |
|
7. |
Profile |
|
8. |
Maximum_Loops |
|
9. |
Block_Reference |
|
10. |
Port_Order_Array |
|
11. |
Add_Scheduler_Times_to_DS |
|
12. |
Self_Start |
|
Explanation |
Type |
|
Input |
This is a default input port. |
General |
Output |
This is the default output port. |
General |
Created with the Personal Edition of HelpNDoc: Easy EPub and documentation editor