1. Field of the Invention
This invention pertains in general to hardware functional verification and in particular to techniques for evaluating a temporal description within a general purpose programming language.
2. Background Art
Using a temporal description to verify a hardware design is increasingly common. Hardware description languages such as the problem statement language (PSL) are becoming standards to verify hardware designs and various electronic design automation (EDA) tools are beginning to support the evaluation of such a temporal description. For example, a hardware description language such as System Verilog uses the temporal description mechanism to check the correctness of a hardware behavior during hardware simulation. Special purpose programming languages developed for designing hardware can adopt such a new language construct (i.e., temporal description) with an additional syntax.
Another trend of hardware design is to use a general purpose programming language such as C++ to simulate a hardware behavior. In such an environment, users use a general purpose programming language with various hardware modeling support libraries to construct a simulation model to verify hardware behaviors. Because the hardware model is written in a general purpose programming language, it is easy to mix simulation codes, which are constructed using the general purpose programming language with software.
In a general purpose programming language, however, the language syntax cannot be easily changed to support hardware simulation. It is desirable for the general purpose programming language to have a mechanism to evaluate a temporal description during hardware simulation. Moreover, it is desirable that such a mechanism be able to express a temporal description within the context of the general purpose programming language such that the temporal description is constructed with the general purpose programming language's native expression, and that variables used within the temporal description are taken from the name scope of the temporal description's location.
In addition, because the temporal logic mechanism is useful in specifying the sequence of hardware behaviors, it is desirable to use it as an ordinal expression within a general purpose programming language. In such an expression, there will be a mixture of temporal constructs and ordinal expressions. To evaluate such a mixed expression, the ordinal expression is repeatedly evaluated over the program execution. However, the ordinal execution mechanism provided by general purpose programming language compilers cannot handle such a situation.
Therefore, there is a need for a technique that effectively evaluates a temporal description within a general purpose programming language.
The above need is met by a translation module that translates a temporal description into a temporal expression. The translation module is adapted to translate a temporal description in the form of an extended syntax or a preprocessing macro to the temporal expression. The temporal expression includes a native expression of a general purpose programming language. The temporal expression may also include one or more construct functions. A parsing module generates a data structure that represents the temporal expression without evaluating the native expression. Particularly, the parsing module is adapted to parse the temporal expression to generate the data structure. During the parse phase, the parsing module creates a data structure, copies a return address in a stack to a data structure for future evaluation. Then it avoids evaluating the native expression during the parse phase by controlling a construct function's return value to be false.
An evaluation module evaluates the data structure to execute the temporal expression including the native expression. For example, the evaluation module returns to the address stored in the data structure instead of the actual return address in the stack and evaluates the native expression by controlling the construct function's return value to be true. The evaluation module also evaluates a variable within the native expression from a name scope of the native expression's program location. According to an embodiment of the invention, the evaluation module creates one or more nondeterministic finite automata (NFA) state structures that include data to be evaluated at one or more clock cycles. The evaluation module stores the one or more NFA state structures in a queue. The evaluation module then retrieves a NFA state structure from the queue in response to the passing of clock cycles to evaluate the retrieved NFA state structure.
The figures depict an embodiment of the present invention for purposes of illustration only. One skilled in the art will readily recognize from the following description that alternative embodiments of the structures and methods illustrated herein may be employed without departing from the principles of the invention described herein.
In an embodiment of the invention, a temporal description is written within a general purpose programming language such as C++. The temporal description can be expressed with either an extended syntax or a preprocessor macro. In the case of an extended syntax, the transformation module 102 (e.g., a parser program or a compiler) parses the extended syntax and translates it into the general purpose programming language's native expression. In the case of a preprocessor macro, the preprocessing module 104 (e.g., a preprocessor such as the c preprocessor (CPP)) parses the macro and translates it into the native expression.
As a result of the translation by the transformation module 102 or by the preprocessing module 104, the temporal description is expanded to one or more construct functions and/or native expressions, which may be connected by one or more logical “and” operators and/or “select” operators.
As an example, the temporal description that “x=5” is true within 0 to 2 cycles may be expressed with the syntax “@[0,2]x=5.” This temporal description can also be represented by the macro “NSC_SEQ(0, 2, NSC_BOOL(x=5)).” The transformation module 102 or the preprocessing module 104 then translates the temporal description (either in an extended syntax to be translated by the transformation module 102 or in a preprocessing module to be translated by the preprocessing module 104) into the following temporal expression that includes one or more function calls and native expressions:
This exemplary temporal expression includes one or more function calls and/or native expressions. Therefore, this temporal expression can be processed by a general purpose programming language's ordinal compiler. In addition, the temporal expression is a pure expression that can be placed anywhere in a program where an expression can be placed (e.g., as a condition in an “if” statement). Since a native expression is expanded in a program location, the native expression can use a variable that can be accessed at a location of the program where the native expression is expanded. For example, the variable “x” in the native expression above can be a local variable, which is usually not accessible from outside of the program function. Thus, a variable within the native expression can be evaluated from a name scope of the native expression's program location.
In the exemplary temporal description (in the extended syntax form) “@[0,2]x=5,” “@[0,2]” is a special temporal expression operator, and “x=5” is a general purpose programming language's native expression. In an embodiment, the transformation module 102 is adapted to translate “@[0,2]” into the temporal expression:
The transformation module 102 is further adapted to translate the native expression “x=5” into:
Similarly, the preprocessing module 104 is adapted to translate the macro NSC_BOOL(x=5) into:
Thus, the transformation module 102 (if the temporal description is in the extended syntax form) and the preprocessing module 104 (if the temporal description is a macro) are adapted to parse the temporal description into one or more native expressions and function calls that can be understood by a general purpose programming language's compiler. APPENDIX A provides the constructs for various syntax and their translations into a general purpose programming language such as C++. APPENDIX B provides the descriptions of the various construct fictions. Both Appendix A and Appendix B are a part of the instant specification.
In an embodiment of the invention, the execution module 106 is configured to parse the temporal expression generated by the transformation module 102 or the preprocessing module 104 to create a data structure representing the temporal expression. The execution module 106 is further configured to evaluate the created data structure to evaluate and execute the temporal expression.
The execution module 106 executes the generated temporal expression in two phases: a parsing phase and an evaluation phase. According to an embodiment of the invention, the parsing module 202 is adapted to parse the temporal expression to generate a data structure without evaluating the native expression within the temporal expression. Evaluating a native expression during the parsing phase is undesirable because the native expression may have side effects (e.g., the native expression “x++=5” increments x during evaluation. Thus, in the example given above, the native expression “x=5” is embedded in the temporal expression generated by the transformation module 102 or the preprocessing module 104 such that the parsing module 202 can avoid evaluating the native expression by controlling the return value of the NSCA_BOOL( ) function to be false. During the parsing phase conducted by the parsing module 202, the NSCA_BOOL( ) function returns false (i.e., “0”) so that the “select” operator “?” elects to call the NSCA_END( ) function.
At the parsing phase, the parsing module 202 evaluates the temporal expression and calls one or more construct functions to generate a data structure that represents the temporal expression's logical view. The parsing phase is processed by executing the translated temporal expression as the natural evaluation of the general purpose programming language. As the result, the execution calls various construct functions and transfers control to the parsing module 202. According to the function types, the parsing module 202 generates a data structure representing the temporal expression's logical view.
Various CPU architectures employ various sets of general purpose registers to evaluate the general purpose programming language, and its usage of the registers vary per CPU architecture. But in general, almost all the CPU architectures employ the stack, stack pointer register, and frame pointer register to implement the function call/return mechanism. In this embodiment, we explain the call/return activity based on a virtual CPU architecture with stack, SP (stack pointer register), and FP (frame pointer register). Implementing this scheme into a specific CPU architecture can be easily achieved because of the similarity of call/return mechanism used in various CPU architectures.
When various construction functions are called to transfer the control to the parsing module 202, a general purpose programming language's compiler uses one register as a frame pointer (FP) to identify the function's local variable boundary. A stack pointer (SP) registers one or more points to the end of the stack, and the local variables are located between FP and SP. The function's return address is placed before FP, and the previous FP value is saved in the stack where the FP register is pointing to. This configuration is shown in
The stack-shown in
In such an execution mechanism, the function return address can be read from the stack frame. The actual returning address can also be modified by writing a different value to the return address location in the stack frame (e.g., by using an assembly code). APPENDIX C provides four assembler functions used to execute a temporal expression. Appendix C is a part of this specification.
As discussed, the transformation module 102 or the preprocessing module 104 translates the temporal description that “x=5” is true within 0 to 2 cycles into:
During the parsing phase, the parsing module 202 calls the construct functions in the following order:
However, the parsing module 202 does not evaluate the expression “((X=5)? NSCA_TRUE( ): NSCA_FALSE( )” because the NSCA_BOOL( ) function returns false or “0” during the parsing phase. After the parsing module 202 completes the parsing phase, it evaluates the temporal expression and constructs a data structure. An exemplary data structure constructed by the parsing module 202 for the exemplary temporal expression is shown in
As shown in
If the parsing module 202 detects that the NSCA_END( ) function closes the top level structure, it knows that the entire temporal expression has been parsed. Accordingly, the evaluation module 204 can evaluate the constructed data structure that represents the temporal expression.
In an embodiment of the invention, the evaluation module 204 evaluates the temporal expression using an NFA mechanism. Specifically, the evaluation module 204 constructs another data structure representing an active state within an NFA. In such an implementation, the evaluation module 204 creates a bubble (i.e., the NFA state structure) that points to the top data structure. The evaluation module 204 places the bubble in an active queue to be evaluated. The evaluation module 204 then processes one or more bubbles in the active queue. The evaluation module 204 can place a bubble in a delay queue if the bubble is to be delayed for one or more cycles. APPENDIX D provides a description of the NFA mechanism for evaluating a temporal expression. Appendix D is a part of this specification.
In
As shown in
APPENDIX E provides the various functions that may be executed during the parsing phase and the evaluation phase. Appendix E is a part of this specification.
With this evaluation mechanism, a temporal expression can be embedded as an ordinal expression in a general purpose programming language. A native expression used within the temporal expression can use a variable within the scope of the embedded point. The text below provides an exemplary code in a general purpose programming language.
In the exemplary code above, the temporal description “@[3,5] data=x” can be used as a condition of the “if” statement, and the local variable “x” can be used in a temporal expression. The transformation module 102 or the preprocessing module 104 is configured to translate this exemplary code into the form of “NSCA_DLY(3, 5) && . . . && NSCA_END( )” that is acceptable in a general purpose programming language's syntax.
In another example, the transformation module 102 or the preprocessing module 104 is adapted to translate a property expression and a sequence expression into the following form:
The corresponding property function has the structure of:
The corresponding sequence function has the structure of:
During the parsing phase, if the NSCA_CALL( ) function is called, the data structure that represents the subroutine call is created, and the return address of the NSCA_CALL( ) is recorded as the evaluation point of the subroutine. The NSCA_CALL( ) function then returns “1,” and the evaluation module 204 calls the corresponding sub-function.
Within the sub-function, in response to the local variable being created in the stack frame, either the NSCA_PROP_BEGIN( ) function or the NSCA_SEQ_BEGIN( ) function is called. Within the function, a new structured (coupled under the call structure created by the NSCA_CALL( ) function) and a copy of the local variable are created. This is accomplished by creating a copy of the current stack call frame (e.g., a copy from the FP to the current SP). The parsing module 202 then parses the property expression or the sequence expression within the corresponding function during the parsing phase. The parsing module 202 further constructs the property or sequence structure under the current function structure.
A translation module translates 1102 a temporal description into a temporal expression. For example, the transformation module 102 translates a temporal description in the form of an extended syntax into the temporal expression. Alternatively, the preprocessing module 104 translates a temporal description in the form of a preprocessing macro into the temporal expression. The temporal expression includes a native expression of a general purpose programming language. The temporal expression may also include one or more construct functions.
The parsing module 202 generates 1104 a data structure that represents the temporal expression without evaluating the native expression. Specifically, the parsing module 202 is adapted to parse the temporal expression to generate the data structure. To generate the data structure, the parsing module 202 stores a return address in a stack and avoids evaluating the native expression by controlling a construct function's return value to be false.
The evaluation module 204 evaluates 1106 the data structure to execute the temporal expression including the native expression. For example, the evaluation module 204 returns to the return address stored in the stack and evaluates the native expression by controlling the construct function's return value to be true. The evaluation module 204 also evaluates a variable within the native expression from a name scope of the native expression's program location. According to an embodiment of the invention, the evaluation module 204 creates one or more NFA state structures that include data to be evaluated at one or more clock cycles. The evaluation module 204 stores the one or more NFA state structures in a queue. The evaluation module 204 then retrieves a NFA state structure from the queue in response to the passing of clock cycles to evaluate the retrieved NFA state structure.
The above description is included to illustrate the operation of the preferred embodiments and is not meant to limit the scope of the invention. Where the description refers to “one” embodiment and/or “another” embodiment, it will be understood that the description is not necessarily referring to different embodiments. The scope of the invention is to be limited only by the following claims. From the above discussion, many variations will be apparent to one skilled in the relevant art that would yet be encompassed by the spirit and scope of the invention.
APPENDIX A provides the constructs for various syntax and their translations into a general purpose programming language such as C++.
Property Description
A property (the temporal condition over a design) is described as a property description. The syntax of a property is:
The property is translated into a function with two fictions NSCA_PROP_BEGIN( ) and NSCA_PROP_END( ) that specify the beginning and end of the property. For example, a property is expressed as a function as:
Assert Statement
The following syntax provides an assert statement to activate the property.
For example:
The property is activated for evaluation if the function is invoked as a thread in a computing environment. The assert statement above will be translated into:
Property Expression
A property expression expresses the property of the target design. The syntax of a property expression is:
The negation of property “nsc_not” can be expressed with the macro:
The syntax of the “and” operation is:
This expression can be specified with a macro:
The syntax of “or” operation is:
This expression can be specified with a macro:
The syntax of an implication property is:
The first line with ‘|−>’ is an overlapped implication that the match of the first property_expr is the starting point of the second property_expr evaluation. The second line with ‘|=>’ is a non-overlapped implication that the evaluation of the second property_expr starts one cycle after the match of the first property_expr.
This can be written with a macro:
Using the “not” operation, this macro can be used as:
The final translation for each implication is respectively:
Sequence Expression
The syntax of a sequence is:
This can be specified with a macro:
This is translated as:
Sequence Item
A sequence item is a unit to construct a sequence. Multiple items can be listed to specify the flow of a temporal sequence. The syntax of a sequence item is:
An expression “@[m,n] X”, where m and n are constant integer and X is a sequence_expr, means the sequence matches if X becomes true between m and n cycles.
The same sequence item can be expressed with a macro:
Sequence_expr is a primitive sequence element. The syntax of sequence_expr is:
Boolean Expression
A Boolean expression is expressed with the NSC_BOOL macro:
This macro is expanded as the function form:
Sequence Match Item
A sequence match item is expressed with the NSC_MATCH macro:
This macro is expanded as the function form:
Consecutive Repetition
For an expression “X [*m:n]”, X is a sequence and m and n are integer constants. For example, n can be −1 that represents an infinite cycle. The consecutive repetition specifies finitely many iterative matches of X, with a delay of one cycle from the end of one match to the beginning of the next match.
This expression can be specified with a macro:
For an expression “X [−>m:n]”, X is a sequence and m and n are integer constants. For example, n can be −1 that represents an infinite cycle. The goto repetition specifies finitely many iterative matches of X with a delay of one or more cycles from the end of one match to the beginning of the next match. The overall repetition sequence matches at the last iterative matches of the operand.
This expression can be specified with a macro:
For an expression “X [=m:n]”, X is a sequence and m and n are integer constants. For example, n can be −1 that represents an infinite cycle. The non-consecutive repetition specifies finitely many iterative matches of X with a delay of one or more cycles from the end of one match to the beginning of the next match and no match of the sequence strictly in between.
This expression can be specified with a macro:
The syntax for the “and” operation of two sequences is:
This expression can be specified with a macro:
The syntax for the “or” operation of two sequences is:
This expression can be specified with a macro:
The syntax for the “or” operation is:
This expression can be specified with a macro:
The syntax for the “within” operation is:
This expression can be specified with a macro:
The syntax for the “throughout” operation is:
This expression can be specified with a macro:
The syntax for the first match operation is:
This expression can be specified with a macro:
A sequence can be described as a sequence declaration (e.g., a function).
A sequence declaration is translated as an integer type function. Two macros NSCFUNC and NSCFUNCEND are used before and end of the sequence translation.
Sequence Instantiation
The sequence instantiation is used to call another sequence description.
This can be written with a macro as:
The translated temporal expression is connected with various construct functions to construct the data structure during the parsing phase. APPENDIX B provides the descriptions of such construct functions.
The NSCA_PROP_BEGIN( ) function creates a new nsca_assert_expr structure. It keeps the return address to ret_addr. The NSCA_PROP_BEGIN( ) function calls the “nsca_top.set_expr_to_body( )” function to attach the expression to the body. If this property is not the top of the temporal expression, then the function creates the local stack copy for repetitive execution. The function then returns 1 to continue the evaluation.
The NSCA_PROP_END( ) fictions is called at the end of the property. If the current property is the top of the temporal expression, it invokes the “nsca_top.eval_engine( )” function to evaluate the assertion.
During the parsing phase, the NSCA_SEQ_BEGIN( ) function creates a new “nsca_assert_expr” structure (type=nsca_t_sequence). The function keeps the return address to ret_addr. If this sequence is not the top of the temporal expression, then it creates the local stack copy for repetitive execution. The function then returns 1 to continue the evaluation. During the evaluation phase, the function calls the evaluation module 204.
The NSCA_SEQ_END( ) function is called at the end of the sequence. The function keeps its return address to exit_addr field of the current sequence structure. If the current sequence is the top of the temporal expression, it invokes the “nsca_top.eval_engine( )” function to evaluate the assertion.
The NSCA_NEXT( ) function is called in the middle of the two operand operation. The function moves the current expr pointer to the parent, and switches the child pointer usage to the child_b side.
The NSCA_END( ) function is called at the end of a primitive sequence. The function keeps the return address as the exit address of the current expr, and closes the current expr.
The NSCA_BOOL( ) function constructs a new expr structure with type=nsca_t_bool. The function saves the return address to ret_addr field of the expr. The function returns 0 to avoid the actual execution of the Boolean section.
The NSCA_NOT( ) function constructs a new expr structure with type=nsca_t_not. The function saves the return address to ret_addr field of the expr.
The following NSCA_PAND( ) to NSCA_FIRST_MATCH functions have similar code as the NSCA_NOT( ) function, but with different type field.
The NSCA_PAND( ) function constructs a new expr structure with type=nscat_pand.
The NSCA_POR( ) function constructs a new expr structure with type=nsca_t_por.
The NSCA_AND( ) function constructs a new expr structure with type=nsca_t_and.
The NSCA_OR( ) function constructs a new expr structure with type=nsca_t_or.
The NSCA_IMP( ) function constructs a new expr structure with type=nsca_t_imp.
The NSCA_NOIMP( ) function constructs a new expr structure with type=nsca_t_noimp.
The NSCA_CALL( ) function constructs a new expr structure with type=nsca_t_call. The function keeps the return address to the structure.
The NSCA_CALL_END( ) function returns 1 during the parsing phase. The function calls the evaluation module 204 during the evaluation phase.
The NSCA_SEQUENCE( ) function is called at the beginning of the sequence expression. The function constructs a new expr structure with type=nsca_t_sequence.
The NSCA_INTERSECT( ) function constructs a new expr structure with type=nsca_t_intersect.
The NSCA_WITHIN( ) function constructs a new expr structure with type=nsca_t_within.
The NSCA_THROUGHOUT( ) function constructs a new expr structure with type=nsca_t_throughout.
The NSCA_FIRST_MATCHED( ) function constructs a new expr structure with type=nsca_t_first_match.
The NSCA_DLY( ) function constructs a new expr structure with type=nsca_t_dly. The function sets m and n values to start_count and end_count fields.
The following NSCA_CREP( ) to NSCA_FIRST_GOTO functions have similar code as the NSCA_DLY( ) function, but with different type field.
The NSCA_CREP(int m, int n) function constructs a new expr structure with type=nsca_t_crep. The function sets m and n values to start_count and end_count fields.
The NSCA_NREP(int m, int n) function constructs a new expr structure with type=nsca_t_nrep. The function sets m and n values to start_count and end_count fields.
The NSCA_GOTO(int m, int n) function constructs a new expr structure with type=nsca_t_goto. The function set m and n values to start_count and end_count fields.
The NSCA_TRUE( ) function and the NSCA_FALSe function are called at the evaluation phase. The NSCA_TRUE( ) function is used to capture the Boolean expression that ends with the true result. The NSCA_FALSE( ) function is used to capture the Boolean expression that ends with the false result. The evaluation module 204 evaluates the Boolean expression that is represented as an instance of a structure called “bool_expr.” The evaluation module 204 sets the captured return address of the NSCA_BOOL( ) function to the “ret_addr” variable and returns 1. The lower NSCA functions set this “ret_addr” variable as the return address and return with the value passed from the evaluation module 204. In response to the evaluation module 204 completing the evaluation of the Boolean expression, the NSCA_TRUE( ) or NSCA_FALSE( ) function captures the result. These functions pass the result as an argument and call the evaluation module 204 again.
APPENDIX C provides four assembler functions used to execute a temporal expression.
The nsc_asm_get_ret_addr( ) function reads and calls the stack frame of the current function and returns the return address of the function.
The nsc_asm_set_ret_addr( ) function takes an address as the argument and sets it to the return address location of the current call stack frame.
The nsc_asm_copy_stack( ) function copies the local stack frame between the base pointer and the current stack pointer to the allocated memory table and returns the table address.
The nsc_set_stack( ) function takes the table address and set it to the stack frame.
APPENDIX D provides a description of the NFA mechanism for evaluating a temporal expression. The actual evaluation of the temporal expression is executed with the nsca_top.eval_engine( ) function. The evaluation is done with an NFA mechanism. Each active state over the temporal structure is represented with the “nsca_nfa_bubble” structure, as shown below.
The bubble has the fields “state” and “sub_state” to represent the status.
Table 1 shows the status field condition.
Depending on the state, each bubble is placed in different queues (e.g., a linked list). The “nsca_active_queue” queue holds the active bubbles. The “nsca delay_queue” queue holds the bubbles that wait for a cycle delay. The “nsca_wait_queue” queue holds the bubbles that wait for child evaluation. The “nsca_zombie_queue” queue holds the dead bubbles that are being cleaned. The bubbles are connected as double-linked list using previous and next pointers. The queue field in the bubble structure points to the queue that it belongs. If a bubble is placed in the delay queue, it is given the waiting count to the count field. It is then placed in a proper location in the queue such that the queue conforms to a linked list of decrement counter. The count value is adjusted such that the actual wait count is the sum of the count values of the bubbles located before the corresponding bubble. For example:
delay_queue−>A(count=5)−>B(count=3)−>C (count=2)−>. .
The actual wait cycle of the bubble C is 5+3+2=10. With this structure, the count decrement can be done by decrementing the count in the top of the queue.
The “eval_engine” flnction handles the evaluation of the temporal logic.
The pseudo code for the function is shown below:
Each active bubble is evaluated from the eval_engine( ) function. The bubble class provides the evaluation fictions as the following:
The evalo function is called if the bubble is placed in the active queue. The action for the evaluation is determined by the sequence structure where it is located at.
The done( ) function is called at the completion of Boolean or sequence match item evaluation.
The matched( ) function is called if a bubble evaluation reaches to a “match” condition and the bubble informs the condition to its parent bubble.
The unmatched( ) function is called if a bubble evaluation reaches to an “unmatched” condition and the bubble informs the condition to its parent bubble.
Depending on the sequence expr where the active bubble is located, the proper evaluation action will be taken via the eval( ) function. The following text explains the action flow of various expr types.
nsca_t_property
For the property expression, if the child type is not nsca_t_pand or nsca_t_por, a new bubble for the child is created each cycle and placed to the active queue. The bubble itself is placed in the delay queue for one cycle to be ready for the bubble in the next cycle. If the child is nsca_t_and or nsca_t_por, a single bubble is created for the child and placed in the active queue at the beginning. The bubble itself is placed in the wait queue. In response to receiving the matched( ) call, the matched( ) function of the parent is called, if a parent exists. In response to receiving the unmatched( ) call, the unmatched( ) function of the parent is called. If this is the top, the nsca_assertion_error( ) function is reported.
nsca_t_sequence
For the sequence expression, a new bubble for the child is created and placed to the active queue. The bubble itself is placed in the wait queue. In response to receiving the matched( ) call, the matched( ) function of the parent is called, if a parent exist. Otherwise, “1” is returned as the evaluation result, if there is no active child bubble. In response to receiving the unmatched( ) call, the unmatched( ) function of the parent is called. If this is the top and there is no active child bubble, “0” is returned as the evaluation result.
nsca_t_imply
If sub_state is idle, a new bubble for the child is created and placed to the active queue. This bubble itself is placed in the wait queue with sub_state=s0. In response to receiving the matched( ) call, if sub_state=s0, then the sub_state is changed to s1 (stays in wait queue), and a new bubble for its child_b is created and placed to the active queue. If sub_state=s1, then the matched( ) function of its parent is called, and the bubbled is placed to the zombie queue. In response to receiving the unmatched( ) call, if the sub_state=s0, then the bubble places itself to the zombie queue. If sub_state=s1, then the unmatched( ) function of the parent is called.
nsca_t_noimply
If sub_state is idle, a new bubble for the child is created and placed to the active queue. This bubble itself is placed in the wait queue with sub_state=s0. In response to receiving the matched( ) call, if sub_state=s0, then the sub_state is changed to s1 and placed in the delay queue for one cycle. In response to exiting from the delay queue, the bubble moves to the wait queue again, and a new bubble for its child_b is created and placed to the active queue. If sub_state=s1, then the matched( ) function of the parent is called, and the bubble places itself to the zombie queue. In response to receiving the unmatched( ) call, if sub_state=s0, then the bubble places itself to the zombie queue. If sub_state=s1, then the unmatched( ) function of the parent is called.
nsca_t_not
A new bubble for the child is created and placed to the active queue. This bubble itself is placed in the wait queue with sub_state=s0. In response to receiving the matched( ) call, the unmatched( ) function of the parent is called. In response to receiving the unmatched( ) call, the matched( ) function of the parent is called.
nsca_t_pand
Two new bubbles for the children are created and placed to the active queue each cycle. The bubble itself is placed in the wait queue to wait for child completion with sub_state=s0. In response to receiving the matched( ) call, the condition that the two child properties are both matched is detected, and the parent's matched( ) function is called. In response to receiving the unmatched( ) call, the parent's unmatched( ) function is called.
nsca_t_por
Two new bubbles for the children are created and placed to the active queue each cycle. The bubble itself is placed in the wait queue to wait for child completion with sub_state=s0. In response to receiving the matched( ) call, the parent's matched( ) function is called. In response to receiving the unmatched( ) call, if sub_state=s0, the sub_state changes to s1 and stays in the wait queue. If sub_state=s1, the parent's unmatched( ) function is called.
nsca_t_and
Two new bubbles for the children are created and placed to the active queue. The bubble itself is placed in the wait queue to wait for child completion with sub_state=s0. In response to receiving the matched( ) call, the condition that the two child sequences are both matched is detected, and the parent's matched( ) function is called. In response to receiving the unmatched( ) call, the parent's unmatched( ) function is called.
nsca_t_or
Two new bubbles for the children are created and placed to the active queue. The bubble itself is placed in the wait queue to wait for child completion with sub_state=s0. In response to receiving the matched( ) call, the parent's matched( ) function is called. In response to receiving the unmatched( ) call, if sub_state=s0, the sub_state changes to s1 and stays in the wait queue, if sub_state=s1, the parent's unmatched( ) function is called.
nsca_t_intersect
Two new bubbles for the children are created and placed to the active queue. The bubble itself is placed in the wait queue to wait for child completion with sub_state=s0. In response to receiving the matched( ) call, and if sub_state=s0, the sub_state changes to s1 and moves to the ready queue. If the bubble is reached to be executed, and if the state is still s1, the sub_state changes to s0 and moves back in the wait queue. If sub_state=s1, then the parent's matched( ) function is called, and the sub_state is changed to s2. In response to receiving the unmatched( ) call, the parent's unmatched( ) function is called.
nsca_t_within
Two new bubbles for the children are created and placed to the active queue. The bubble itself is placed in the wait queue to wait for child completion with sub_state=s0. In response to receiving the matched( ) call, it is checked if the first sequence is within the second sequence. Otherwise, the parent's unmatched( ) function is called. In response to receiving the unmatched( ) call, the parent's unmatched( ) function is called.
nsca_t_throughout
A new bubble for the children sequence is created and placed to the active queue. Until the matched( ) item is received from the sequence, a new bubble for evaluating the Boolean expression is created each cycle. In response to receiving the unmatched( ) call from the first Boolean bubble, the parent's unmatched( ) function is called. In response to receiving the matched( ) call from the second sequence, the parent's matched( ) function is called. In response to receiving the unmatched( ) call from the second sequence, the parent's unmatched( ) function is called.
nsca_t_first match
A new bubble for the child is created and placed to the active queue. The bubble itself is placed in the wait queue to wait for the child. In response to receiving the matched( ) call, the child bubble is cleaned up and the parent's matched( ) function is called. In response to receiving the unmatched( ) call, the parent's unmatched( ) function is called.
nsca_t_dly
The bubble is placed in the delay queue for the initial delay value (start_count). Then a new bubble for the child is created and placed to the active queue each cycle till the end_count is reached. Then the bubble itself is placed in the wait queue to wait for children completion. In response to receiving the matched( ) call, the parent's matched( ) function is called. In response to receiving the unmatched( ) call, and no child bubble is left, the parent's unmatched( ) function is called.
nsca_t_crep
A new bubbles for the child is created and placed to the active queue. In response to receiving the matched( ) call (or if “zero” match is the condition), a new bubble is created for the child till the end_count is reached. The counter is counted up, and the condition is checked for match. If the count is larger than the start_count, the matched( ) flnction of the parent is called. In response to receiving the unmatched( ) call, the parent's unmatched( ) function is called.
nsca_t_goto
A new bubble for the child is created and placed to the active queue each cycle till the match count reaches the end_count. In response to receiving the matched( ) call (or if “zero” match is the condition), the counter is counted up. If the condition matched, the parent's matched( ) function is called. If not consecutive, the parent's unmatched( ) function is called.
nsca_t_nrep
A new bubble for the child is created and placed to the active queue each cycle till the first match is detected. In response to receiving the first matched( ) call (or if “zero” match is the condition), the parent's matched( ) function is called each cycle.
nsca_t_call
A new bubble for the child is created and placed to the active queue. The pointer to this bubble is copied to the fcall pointer of the child, and the pointer value inherits the bubbles under the child (until a new call is encountered). The bubble itself is placed in the wait queue. In response to evaluating the Boolean expression or sequence match item, the fcall pointer is checked. If the fcall pointer is not null, the function call sequence is processed by returning before the function call and capturing at the NSCA_SEQ_BEGIN( ) call. In response to capturing at the sequence begin, the local variable is copied to the stack to continue the Boolean evaluation. In response to completing the Boolean or sequence match item evaluation, the local variable is copied and returned at the exit address. The exit is recaptured at the NSCA_SEQ_END( ) function. If the call is nested, multiple call sequences are executed. The bubble is purged if the parent is cleaning up the children bubbles.
nsca_t_bool
The Boolean expression is evaluated by setting the return address and returning “1.” The result is returned with reactivation. The sub-status is used to handle the condition, before the evaluation and after the evaluation. If the result is “true,” then the parent's matched( ) function is called. Otherwise, the parent's unmatched( ) function is called.
nsca_t_match
The sequence match item expression is evaluated by setting the return address and returning with “1.” The result is returned with reactivation. The sub-status is used to handle the condition, before the evaluation and after the evaluation. The parent's matched( ) function is called.
During the parsing phase, the temporal expression is parsed and the data structure that represents the temporal expression is dynamically constructed. The temporal data structure is created under a thread structure. There is one active temporal expression structure per single thread. The temporal data structure per thread is hold within a class called “nsca_assertion_top.” The instance “nsca_top” provides various service calls to let the construction and evaluation functions do the proper tasks. This APPENDIX E provides the functions provided by “nsca_top.”
The “set_expr_to_body(nsca_assert_exp*exp)” function sets the given assert to the body and sets this exp as the current expression. If there is no current expr, the new exp is connected as the current active expr for the thread. If the current expr is open, the new one is connected to its child. There are two child pointers, and which one is used depends on whether NSCA_NEXT( ) is called or not. If the current expr is not open, the new one is connected to its next.
The “end_expr( )” function closes the current expression. If the current expression is not open, it moves the current expr to its parent before closing it.
The “close_expr( )” function closes the current expression and moves the current expr to its parent.
The “get_current( )” function returns a pointer to the current active expr structure.
The “eval_engine(int value)” function invokes the evaluation module 204.
The “set_return_addr(return_address ret)” function sets the return address for future use.
The “get_return_addr( )” function reads out the return address set by the “set_return_addr” function to actually returning to the address.
The “gen_top_bubble( )” function creates the top bubble for evaluation.
The temporal structure uses a common data structure “nsca_assert_expr” to represent various types of nodes indicating the temporal property. The type field in the “nsca_assert_expr” data structure shows which kind of information a node holds. Table 2 shows the type information.
The member fields in the temporal_expr hold the at least one of the following information shown in Table 3: