vvp: Add `%disable/flow` instruction
The `%disable` instruction will stop the execution of all active threads of a specific scope. This is what is required to implement the semantics of the Verilog `disable` statement. But it is not suited to implement the SystemVerilog flow control statements such as `return`, `continue` and `break`. These only affect the thread hierarchy from which it is called, but not other concurrently running threads from the same scope. Add a new `%disable/flow` instruction that will only disable the thread closest to the current thread in the thread hierarchy. This can either be the thread itself or one of its parents. This will leave other concurrent threads of the same scope untouched and also allows function recursion since only the closest parent thread is disabled. Note that it is not possible to implement this using `%jmp` instructions since a block in a function with variable declarations will be its own sub-thread, but using flow control instructions it is possible to exit from that thread to the parent scope, which is not possible with `%jmp` instructions. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
7c5694e516
commit
ca919b3ce0
|
|
@ -103,6 +103,7 @@ extern bool of_DELETE_ELEM(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_DELETE_OBJ(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DELETE_TAIL(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DISABLE(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DISABLE_FLOW(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DISABLE_FORK(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DIV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DIV_S(vthread_t thr, vvp_code_t code);
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ static const struct opcode_table_s opcode_table[] = {
|
|||
{ "%delete/obj",of_DELETE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} },
|
||||
{ "%delete/tail",of_DELETE_TAIL,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} },
|
||||
{ "%disable", of_DISABLE, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} },
|
||||
{ "%disable/flow", of_DISABLE_FLOW, 1, {OA_VPI_PTR,OA_NONE, OA_NONE} },
|
||||
{ "%disable/fork",of_DISABLE_FORK,0,{OA_NONE,OA_NONE, OA_NONE} },
|
||||
{ "%div", of_DIV, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%div/s", of_DIV_S, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
|
|
|
|||
|
|
@ -469,6 +469,17 @@ This instruction terminates threads that are part of a specific
|
|||
scope. The label identifies the scope in question, and the threads are
|
||||
the threads that are currently within that scope.
|
||||
|
||||
* %disable/flow <scope-label>
|
||||
|
||||
This instruction is similar to `%disable` except that it will only disable a
|
||||
single thread of the specified scope. The disabled thread will be the thread
|
||||
closest to the current thread in the thread hierarchy. This can either be thread
|
||||
itself or one of its parents.
|
||||
|
||||
It is used to implement flow control statements called from within a thread that
|
||||
only affect the thread or its parents. E.g. SystemVerilog `return`, `continue`
|
||||
or `break`.
|
||||
|
||||
* %disable/fork
|
||||
|
||||
This instruction terminates all the detached children for the current
|
||||
|
|
|
|||
|
|
@ -2718,6 +2718,30 @@ bool of_DISABLE(vthread_t thr, vvp_code_t cp)
|
|||
return ! disabled_myself_flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to `of_DISABLE`. But will only disable a single thread of the
|
||||
* specified scope. The disabled thread will be the thread closest to the
|
||||
* current thread in thread hierarchy. This can either be the current thread,
|
||||
* either the thread itself or one of its parents.
|
||||
* This is used for SystemVerilog flow control instructions like `return`,
|
||||
* `continue` and `break`.
|
||||
*/
|
||||
|
||||
bool of_DISABLE_FLOW(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
__vpiScope*scope = static_cast<__vpiScope*>(cp->handle);
|
||||
vthread_t cur = thr;
|
||||
|
||||
while (cur && cur->parent_scope != scope)
|
||||
cur = cur->parent;
|
||||
|
||||
assert(cur);
|
||||
if (cur)
|
||||
return !do_disable(cur, thr);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the %disable/fork (SystemVerilog) instruction by disabling
|
||||
* all the detached children of the given thread.
|
||||
|
|
|
|||
Loading…
Reference in New Issue