diff --git a/ivl_target.h b/ivl_target.h index e9b61df72..627172ad5 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: ivl_target.h,v 1.39 2001/03/30 05:49:52 steve Exp $" +#ident "$Id: ivl_target.h,v 1.40 2001/03/31 17:36:38 steve Exp $" #endif #ifdef __cplusplus @@ -247,6 +247,9 @@ typedef enum ivl_statement_type_e { IVL_ST_NOOP = 1, IVL_ST_ASSIGN, IVL_ST_BLOCK, + IVL_ST_CASE, + IVL_ST_CASEX, + IVL_ST_CASEZ, IVL_ST_CONDIT, IVL_ST_DELAY, IVL_ST_DELAYX, @@ -676,7 +679,13 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net); extern unsigned ivl_stmt_block_count(ivl_statement_t net); /* IVL_ST_BLOCK, IVL_ST_FORK */ extern ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net, unsigned i); - /* IVL_ST_CONDIT */ + /* IVL_ST_CASE */ +extern unsigned ivl_stmt_case_count(ivl_statement_t net); + /* IVL_ST_CASE */ +extern ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned i); + /* IVL_ST_CASE */ +extern ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned i); + /* IVL_ST_CONDIT, IVL_ST_CASE */ extern ivl_expr_t ivl_stmt_cond_expr(ivl_statement_t net); /* IVL_ST_CONDIT */ extern ivl_statement_t ivl_stmt_cond_false(ivl_statement_t net); @@ -721,6 +730,9 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.40 2001/03/31 17:36:38 steve + * Generate vvp code for case statements. + * * Revision 1.39 2001/03/30 05:49:52 steve * Generate code for fork/join statements. * diff --git a/t-dll-api.cc b/t-dll-api.cc index fbae3d3e6..f3309a2e0 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-dll-api.cc,v 1.27 2001/03/30 05:49:52 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.28 2001/03/31 17:36:38 steve Exp $" #endif # include "t-dll.h" @@ -580,10 +580,64 @@ extern "C" ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net, } } +extern "C" unsigned ivl_stmt_case_count(ivl_statement_t net) +{ + switch (net->type_) { + case IVL_ST_CASE: + case IVL_ST_CASEX: + case IVL_ST_CASEZ: + return net->u_.case_.ncase; + default: + assert(0); + return 0; + } +} + +extern "C" ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned idx) +{ + switch (net->type_) { + case IVL_ST_CASE: + case IVL_ST_CASEX: + case IVL_ST_CASEZ: + assert(idx < net->u_.case_.ncase); + return net->u_.case_.case_ex[idx]; + + default: + assert(0); + return 0; + } +} + +extern "C" ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned idx) +{ + switch (net->type_) { + case IVL_ST_CASE: + case IVL_ST_CASEX: + case IVL_ST_CASEZ: + assert(idx < net->u_.case_.ncase); + return net->u_.case_.case_st + idx; + + default: + assert(0); + return 0; + } +} + extern "C" ivl_expr_t ivl_stmt_cond_expr(ivl_statement_t net) { - assert(net && (net->type_ == IVL_ST_CONDIT)); - return net->u_.condit_.cond_; + switch (net->type_) { + case IVL_ST_CONDIT: + return net->u_.condit_.cond_; + + case IVL_ST_CASE: + case IVL_ST_CASEX: + case IVL_ST_CASEZ: + return net->u_.case_.cond; + + default: + assert(0); + return 0; + } } extern "C" ivl_statement_t ivl_stmt_cond_false(ivl_statement_t net) @@ -727,6 +781,9 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.28 2001/03/31 17:36:38 steve + * Generate vvp code for case statements. + * * Revision 1.27 2001/03/30 05:49:52 steve * Generate code for fork/join statements. * diff --git a/t-dll-proc.cc b/t-dll-proc.cc index a2867a052..986bb2f0b 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-dll-proc.cc,v 1.16 2001/03/30 23:24:02 steve Exp $" +#ident "$Id: t-dll-proc.cc,v 1.17 2001/03/31 17:36:39 steve Exp $" #endif # include "target.h" @@ -177,6 +177,54 @@ bool dll_target::proc_block(const NetBlock*net) return flag; } +void dll_target::proc_case(const NetCase*net) +{ + assert(stmt_cur_); + assert(stmt_cur_->type_ == IVL_ST_NONE); + + switch (net->type()) { + case NetCase::EQ: + stmt_cur_->type_ = IVL_ST_CASE; + break; + case NetCase::EQX: + stmt_cur_->type_ = IVL_ST_CASEX; + break; + case NetCase::EQZ: + stmt_cur_->type_ = IVL_ST_CASEZ; + break; + } + assert(stmt_cur_->type_ != IVL_ST_NONE); + + assert(expr_ == 0); + net->expr()->expr_scan(this); + stmt_cur_->u_.case_.cond = expr_; + expr_ = 0; + + unsigned ncase = net->nitems(); + stmt_cur_->u_.case_.ncase = ncase; + + stmt_cur_->u_.case_.case_ex = new ivl_expr_t[ncase]; + stmt_cur_->u_.case_.case_st = new struct ivl_statement_s[ncase]; + + ivl_statement_t save_cur = stmt_cur_; + + for (unsigned idx = 0 ; idx < ncase ; idx += 1) { + const NetExpr*ex = net->expr(idx); + if (ex) { + net->expr(idx)->expr_scan(this); + save_cur->u_.case_.case_ex[idx] = expr_; + expr_ = 0; + } else { + save_cur->u_.case_.case_ex[idx] = 0; + } + + stmt_cur_ = save_cur->u_.case_.case_st + idx; + net->stat(idx)->emit_proc(this); + } + + stmt_cur_ = save_cur; +} + void dll_target::proc_condit(const NetCondit*net) { assert(stmt_cur_); @@ -364,6 +412,9 @@ void dll_target::proc_while(const NetWhile*net) /* * $Log: t-dll-proc.cc,v $ + * Revision 1.17 2001/03/31 17:36:39 steve + * Generate vvp code for case statements. + * * Revision 1.16 2001/03/30 23:24:02 steve * Make empty event sub-expression a noop. * diff --git a/t-dll.h b/t-dll.h index ad8205269..0aab77097 100644 --- a/t-dll.h +++ b/t-dll.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: t-dll.h,v 1.27 2001/03/30 05:49:52 steve Exp $" +#ident "$Id: t-dll.h,v 1.28 2001/03/31 17:36:39 steve Exp $" #endif # include "target.h" @@ -79,6 +79,7 @@ struct dll_target : public target_t, public expr_scan_t { struct ivl_statement_s*stmt_cur_; void proc_assign(const NetAssign*); bool proc_block(const NetBlock*); + void proc_case(const NetCase*); void proc_condit(const NetCondit*); bool proc_delay(const NetPDelay*); void proc_stask(const NetSTask*); @@ -346,6 +347,13 @@ struct ivl_statement_s { unsigned nstmt_; } block_; + struct { /* IVL_ST_CASE, IVL_ST_CASEX, IVL_ST_CASEZ */ + ivl_expr_t cond; + unsigned ncase; + ivl_expr_t*case_ex; + struct ivl_statement_s*case_st; + } case_; + struct { /* IVL_ST_CONDIT */ /* This is the condition expression */ ivl_expr_t cond_; @@ -387,6 +395,9 @@ struct ivl_statement_s { /* * $Log: t-dll.h,v $ + * Revision 1.28 2001/03/31 17:36:39 steve + * Generate vvp code for case statements. + * * Revision 1.27 2001/03/30 05:49:52 steve * Generate code for fork/join statements. * diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 6e1f9c145..cd79bc782 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: stub.c,v 1.32 2001/03/30 05:49:52 steve Exp $" +#ident "$Id: stub.c,v 1.33 2001/03/31 17:36:39 steve Exp $" #endif /* @@ -164,6 +164,29 @@ static void show_statement(ivl_statement_t net, unsigned ind) break; } + case IVL_ST_CASEX: + case IVL_ST_CASEZ: + case IVL_ST_CASE: { + unsigned cnt = ivl_stmt_case_count(net); + unsigned idx; + fprintf(out, "%*scase (...) <%u cases>\n", ind, "", cnt); + show_expression(ivl_stmt_cond_expr(net), ind+4); + + for (idx = 0 ; idx < cnt ; idx += 1) { + ivl_expr_t ex = ivl_stmt_case_expr(net, idx); + ivl_statement_t st = ivl_stmt_case_stmt(net, idx); + if (ex == 0) + fprintf(out, "%*sdefault\n", ind+4, ""); + else + show_expression(ex, ind+4); + + show_statement(st, ind+4); + } + + fprintf(out, "%*sendcase\n", ind, ""); + break; + } + case IVL_ST_CONDIT: { ivl_statement_t t = ivl_stmt_cond_true(net); ivl_statement_t f = ivl_stmt_cond_false(net); @@ -460,6 +483,9 @@ DECLARE_CYGWIN_DLL(DllMain); /* * $Log: stub.c,v $ + * Revision 1.33 2001/03/31 17:36:39 steve + * Generate vvp code for case statements. + * * Revision 1.32 2001/03/30 05:49:52 steve * Generate code for fork/join statements. * diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index f0041be59..24a92ad34 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: eval_expr.c,v 1.6 2001/03/31 02:00:44 steve Exp $" +#ident "$Id: eval_expr.c,v 1.7 2001/03/31 17:36:39 steve Exp $" #endif # include "vvp_priv.h" @@ -48,7 +48,7 @@ static inline void clr_bit(unsigned addr) allocation_map[addr] &= ~(1 << bit); } -static inline void clr_vector(struct vector_info vec) +void clr_vector(struct vector_info vec) { unsigned idx; for (idx = 0 ; idx < vec.wid ; idx += 1) @@ -400,6 +400,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp) /* * $Log: eval_expr.c,v $ + * Revision 1.7 2001/03/31 17:36:39 steve + * Generate vvp code for case statements. + * * Revision 1.6 2001/03/31 02:00:44 steve * Generate code for + and concat expressions. * diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 4ecd134c8..cfbf50cbb 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvp_priv.h,v 1.5 2001/03/27 06:27:41 steve Exp $" +#ident "$Id: vvp_priv.h,v 1.6 2001/03/31 17:36:39 steve Exp $" #endif # include "ivl_target.h" @@ -52,6 +52,12 @@ extern void draw_nexus_input(ivl_nexus_t nex); /* * The draw_eval_expr function writes out the code to evaluate a * behavioral expression. + * + * Expression results are placed into a vector allocated in the bit + * space of the thread. The vector_info structure represents that + * allocation. When the caller is done with the bits, it must release + * the vector with clr_vector so that the code generator can reuse + * those bits. */ struct vector_info { unsigned short base; @@ -59,9 +65,15 @@ struct vector_info { }; extern struct vector_info draw_eval_expr(ivl_expr_t exp); +extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w); + +extern void clr_vector(struct vector_info vec); /* * $Log: vvp_priv.h,v $ + * Revision 1.6 2001/03/31 17:36:39 steve + * Generate vvp code for case statements. + * * Revision 1.5 2001/03/27 06:27:41 steve * Generate code for simple @ statements. * diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index c1ee332c4..8e6461256 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvp_process.c,v 1.12 2001/03/30 05:49:53 steve Exp $" +#ident "$Id: vvp_process.c,v 1.13 2001/03/31 17:36:39 steve Exp $" #endif # include "vvp_priv.h" @@ -133,6 +133,77 @@ static int show_stmt_assign(ivl_statement_t net) return 0; } +static int show_stmt_case(ivl_statement_t net) +{ + ivl_expr_t exp = ivl_stmt_cond_expr(net); + struct vector_info cond = draw_eval_expr(exp); + unsigned count = ivl_stmt_case_count(net); + + unsigned local_base = local_count; + + unsigned idx, default_case; + + local_count += count + 1; + + /* First draw the branch table. All the non-default cases + generate a branch out of here, to the code that implements + the case. The default will fall through all the tests. */ + default_case = count; + + for (idx = 0 ; idx < count ; idx += 1) { + ivl_expr_t cex = ivl_stmt_case_expr(net, idx); + struct vector_info cvec; + + if (cex == 0) { + default_case = idx; + continue; + } + + cvec = draw_eval_expr_wid(cex, cond.wid); + + fprintf(vvp_out, " %%cmp/u %u, %u, %u;\n", cond.base, + cvec.base, cond.wid); + fprintf(vvp_out, " %%jmp/1 T_%d.%d, 6;\n", + thread_count, local_base+idx); + + + /* Done with the case expression */ + clr_vector(cvec); + } + + /* Done with the condition expression */ + clr_vector(cond); + + /* Emit code for the default case. */ + if (default_case < count) { + ivl_statement_t cst = ivl_stmt_case_stmt(net, default_case); + show_statement(cst); + } + + /* Jump to the out of the case. */ + fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, + local_base+count); + + for (idx = 0 ; idx < count ; idx += 1) { + ivl_statement_t cst = ivl_stmt_case_stmt(net, idx); + + if (idx == default_case) + continue; + + fprintf(vvp_out, "T_%d.%d\n", thread_count, local_base+idx); + show_statement(cst); + + fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, + local_base+count); + + } + + /* The out of the case. */ + fprintf(vvp_out, "T_%d.%d\n", thread_count, local_base+count); + + return 0; +} + static int show_stmt_condit(ivl_statement_t net) { int rc = 0; @@ -307,6 +378,10 @@ static int show_statement(ivl_statement_t net) break; } + case IVL_ST_CASE: + rc += show_stmt_case(net); + break; + case IVL_ST_CONDIT: rc += show_stmt_condit(net); break; @@ -394,6 +469,9 @@ int draw_process(ivl_process_t net, void*x) /* * $Log: vvp_process.c,v $ + * Revision 1.13 2001/03/31 17:36:39 steve + * Generate vvp code for case statements. + * * Revision 1.12 2001/03/30 05:49:53 steve * Generate code for fork/join statements. *