diff --git a/vvp/codes.h b/vvp/codes.h index 35f2776a6..4a730bec0 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -90,6 +90,7 @@ extern bool of_DELAY(vthread_t thr, vvp_code_t code); extern bool of_DELAYX(vthread_t thr, vvp_code_t code); extern bool of_DELETE_OBJ(vthread_t thr, vvp_code_t code); extern bool of_DISABLE(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); extern bool of_DIV_WR(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 56ef37aad..40a16300c 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -140,6 +140,7 @@ static const struct opcode_table_s opcode_table[] = { { "%delay", of_DELAY, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, { "%delayx", of_DELAYX, 1, {OA_NUMBER, OA_NONE, OA_NONE} }, { "%delete/obj",of_DELETE_OBJ,1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, + { "%disable/fork",of_DISABLE_FORK,0,{OA_NONE,OA_NONE, OA_NONE} }, { "%div", of_DIV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%div/s", of_DIV_S, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%div/wr", of_DIV_WR, 0, {OA_NONE, OA_NONE, OA_NONE} }, diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 69c72ab59..daaacba5d 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -280,7 +280,7 @@ number that the vector is compared with. Compare real values for equality and less-then. This opcode pops to values from the real-value stack and writes the comparison result to bits 4/5. The expressions (a < b) and (a==b) are calculated, with (b) -poped from the stack first, then (a). +popped from the stack first, then (a). * %cmp/ws , * %cmp/wu , @@ -314,7 +314,7 @@ instruction removes two strings from the stack. * %concati/str Pop the top string, and concatenate it to the new top string. Or think -of it as possing the tail, then the head, concatenating them, and +of it as passing the tail, then the head, concatenating them, and pushing the result. The stack starts with two strings in the stack, and ends with one string in the stack. @@ -401,6 +401,11 @@ 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/fork + +This instruction terminates all the detached children for the current +thread. There should not be any non-detached children. + * %div , , * %div/s , , @@ -1038,9 +1043,9 @@ top of the object stack. The cobject is NOT popped. * %store/reala , This pops the top of the real variable stack and write it to the -object variable given bu the label. +object variable given by the label. -The areal version is similar, but writes to a real array using the +The reala version is similar, but writes to a real array using the index in the index register * %store/str diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 38d133774..04896e7a4 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2215,6 +2215,36 @@ bool of_DISABLE(vthread_t thr, vvp_code_t cp) return ! disabled_myself_flag; } +/* + * Implement the %disable/fork (SystemVerilog) instruction by disabling + * all the detached children of the given thread. + */ +bool of_DISABLE_FORK(vthread_t thr, vvp_code_t) +{ + /* If a %disable/fork is being executed then the parent thread + * cannot be waiting in a join. */ + assert(thr->i_am_joining == 0); + + /* There should be no active children to disable. */ + assert(thr->children.empty()); + + /* Disable any detached children. */ +fprintf(stderr, "Sorry: %%disable/fork has not been implemented. It " + "will be ignored.\n"); +#if 0 + while (!thr->children.empty()) { + vthread_t tmp = *(thr->children.begin()); + assert(tmp); + assert(tmp->parent == thr); + /* Disabling the children can never match the parent thread. */ + assert(! do_disable(tmp, thr)); + vthread_reap(tmp); + } +#endif + + return true; +} + /* * This function divides a 2-word number {high, a} by a 1-word * number. Assume that high < b.