diff --git a/elaborate.cc b/elaborate.cc index a54a4b822..fa799a22e 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -5691,7 +5691,7 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) const des->errors += 1; return 0; } - NetDisable*disa = new NetDisable(target); + NetDisable*disa = new NetDisable(target, true); disa->set_line( *this ); return disa; } @@ -5720,7 +5720,7 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) const assn->set_line( *this ); proc->append(assn); - NetDisable*disa = new NetDisable(target); + NetDisable*disa = new NetDisable(target, true); disa->set_line( *this ); proc->append( disa ); diff --git a/ivl.def b/ivl.def index f02fd0519..7c781eed4 100644 --- a/ivl.def +++ b/ivl.def @@ -292,8 +292,9 @@ ivl_stmt_delay_expr ivl_stmt_delay_val ivl_stmt_events ivl_stmt_file -ivl_stmt_lineno +ivl_stmt_flow_control ivl_stmt_lexp +ivl_stmt_lineno ivl_stmt_lval ivl_stmt_lvals ivl_stmt_lwidth diff --git a/ivl_target.h b/ivl_target.h index 7e41f6ecd..6afde3c27 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -21,6 +21,7 @@ # include # include +# include /* Re the _CLASS define: clang++ wants this to be class to match the * definition, but clang (the C) compiler needs it to be a struct @@ -2259,6 +2260,8 @@ extern uint64_t ivl_stmt_delay_val(ivl_statement_t net); extern unsigned ivl_stmt_needs_t0_trigger(ivl_statement_t net); extern unsigned ivl_stmt_nevent(ivl_statement_t net); extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx); + /* IVL_ST_DISABLE */ +extern bool ivl_stmt_flow_control(ivl_statement_t net); /* IVL_ST_CONTRIB */ extern ivl_expr_t ivl_stmt_lexp(ivl_statement_t net); /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_CASSIGN IVL_ST_DEASSIGN diff --git a/net_proc.cc b/net_proc.cc index b5d3d49ca..650be2af5 100644 --- a/net_proc.cc +++ b/net_proc.cc @@ -174,8 +174,8 @@ void NetCase::prune() } } -NetDisable::NetDisable(NetScope*tgt) -: target_(tgt) +NetDisable::NetDisable(NetScope*tgt, bool flow_control) +: target_(tgt), flow_control_(flow_control) { } diff --git a/netlist.h b/netlist.h index 093a05338..fdbe730ca 100644 --- a/netlist.h +++ b/netlist.h @@ -3272,10 +3272,11 @@ class NetDeassign : public NetAssignBase { class NetDisable : public NetProc { public: - explicit NetDisable(NetScope*tgt); + explicit NetDisable(NetScope*tgt, bool flow_control = false); ~NetDisable(); const NetScope*target() const; + bool flow_control() const { return flow_control_; } virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false, bool nested_func = false) const; @@ -3288,6 +3289,11 @@ class NetDisable : public NetProc { private: NetScope*target_; + // If false all threads in the target_ scope are disabled. If true only + // the closest thread in thread hierachy of the target_ scope is + // disabled. The latter is used to implement flow control statements like + // `return`. + bool flow_control_; private: // not implemented NetDisable(const NetDisable&); diff --git a/t-dll-api.cc b/t-dll-api.cc index e9e7d03ab..c25ab938d 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -2713,6 +2713,11 @@ extern "C" ivl_scope_t ivl_stmt_call(ivl_statement_t net) } } +extern "C" bool ivl_stmt_flow_control(ivl_statement_t net) +{ + return net->u_.disable_.flow_control; +} + extern "C" unsigned ivl_stmt_case_count(ivl_statement_t net) { assert(net); diff --git a/t-dll-proc.cc b/t-dll-proc.cc index a5179dcd7..e0469284c 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -657,6 +657,7 @@ bool dll_target::proc_disable(const NetDisable*net) FILE_NAME(stmt_cur_, net); stmt_cur_->type_ = IVL_ST_DISABLE; + stmt_cur_->u_.disable_.flow_control = net->flow_control(); const NetScope* dis_scope = net->target(); /* A normal disable. */ if (dis_scope) stmt_cur_->u_.disable_.scope = lookup_scope_(dis_scope); diff --git a/t-dll.h b/t-dll.h index 20f156608..3cdaba095 100644 --- a/t-dll.h +++ b/t-dll.h @@ -843,6 +843,7 @@ struct ivl_statement_s { struct { /* IVL_ST_DISABLE */ ivl_scope_t scope; + bool flow_control; } disable_; struct { /* IVL_ST_FOREVER */ diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 2abb7a025..9c42bcae6 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1340,8 +1340,13 @@ static int show_stmt_disable(ivl_statement_t net, ivl_scope_t sscope) /* A normal disable statement. */ if (target) { - show_stmt_file_line(net, "Disable statement."); - fprintf(vvp_out, " %%disable S_%p;\n", target); + if (ivl_stmt_flow_control(net)) { + show_stmt_file_line(net, "Flow control disable statement."); + fprintf(vvp_out, " %%disable/flow S_%p;\n", target); + } else { + show_stmt_file_line(net, "Disable statement."); + fprintf(vvp_out, " %%disable S_%p;\n", target); + } /* A SystemVerilog disable fork statement. */ } else { show_stmt_file_line(net, "Disable fork statement.");