diff --git a/ivl_target.h b/ivl_target.h index 8da258a14..c62a00302 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.35 2001/03/20 01:44:13 steve Exp $" +#ident "$Id: ivl_target.h,v 1.36 2001/03/27 06:27:40 steve Exp $" #endif #ifdef __cplusplus @@ -144,6 +144,13 @@ typedef struct ivl_statement_s*ivl_statement_t; * changes and additions to the enumerations. */ + +typedef enum ivl_edge_type_e { + IVL_EDGE_ANY = 0, + IVL_EDGE_POS = 1, + IVL_EDGE_NEG = 2 +} ivl_edge_type_t; + /* This is the type of an ivl_expr_t object. */ typedef enum ivl_expr_type_e { IVL_EX_NONE = 0, @@ -628,6 +635,8 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net); /* IVL_ST_BLOCK */ extern unsigned ivl_stmt_block_count(ivl_statement_t net); + /* IVL_ST_WAIT */ +extern ivl_edge_type_t ivl_stmt_edge(ivl_statement_t net); /* IVL_ST_BLOCK */ extern ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net, unsigned i); /* IVL_ST_CONDIT */ @@ -650,6 +659,9 @@ extern const char* ivl_stmt_name(ivl_statement_t net); extern ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx); /* IVL_ST_STASK */ extern unsigned ivl_stmt_parm_count(ivl_statement_t net); + /* IVL_ST_WAIT */ +extern unsigned ivl_stmt_pins(ivl_statement_t net); +extern ivl_nexus_t ivl_stmt_pin(ivl_statement_t net, unsigned idx); /* IVL_ST_ASSIGN */ extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net); /* IVL_ST_DELAY, IVL_ST_WAIT, IVL_ST_WHILE */ @@ -673,6 +685,9 @@ _END_DECL /* * $Log: ivl_target.h,v $ + * Revision 1.36 2001/03/27 06:27:40 steve + * Generate code for simple @ statements. + * * Revision 1.35 2001/03/20 01:44:13 steve * Put processes in the proper scope. * diff --git a/t-dll-api.cc b/t-dll-api.cc index 88994dfec..ff0d94f7b 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.22 2001/03/20 01:44:13 steve Exp $" +#ident "$Id: t-dll-api.cc,v 1.23 2001/03/27 06:27:40 steve Exp $" #endif # include "t-dll.h" @@ -547,6 +547,12 @@ extern "C" unsigned long ivl_stmt_delay_val(ivl_statement_t net) return net->u_.delay_.delay_; } +extern "C" ivl_edge_type_t ivl_stmt_edge(ivl_statement_t net) +{ + assert(net->type_ == IVL_ST_WAIT); + return net->u_.wait_.edge_; +} + extern "C" ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx) { switch (net->type_) { @@ -621,6 +627,29 @@ extern "C" unsigned ivl_stmt_parm_count(ivl_statement_t net) return 0; } +extern "C" unsigned ivl_stmt_pins(ivl_statement_t net) +{ + switch (net->type_) { + case IVL_ST_WAIT: + return 1; + default: + assert(0); + } + return 0; +} + +extern "C" ivl_nexus_t ivl_stmt_pin(ivl_statement_t net, unsigned idx) +{ + switch (net->type_) { + case IVL_ST_WAIT: + assert(idx == 0); + return net->u_.wait_.cond_; + default: + assert(0); + } + return 0; +} + extern "C" ivl_expr_t ivl_stmt_rval(ivl_statement_t net) { switch (net->type_) { @@ -651,6 +680,9 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net) /* * $Log: t-dll-api.cc,v $ + * Revision 1.23 2001/03/27 06:27:40 steve + * Generate code for simple @ statements. + * * Revision 1.22 2001/03/20 01:44:13 steve * Put processes in the proper scope. * diff --git a/t-dll-proc.cc b/t-dll-proc.cc index 3bfd66eec..9a4536f0d 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.11 2001/03/20 01:44:14 steve Exp $" +#ident "$Id: t-dll-proc.cc,v 1.12 2001/03/27 06:27:40 steve Exp $" #endif # include "target.h" @@ -274,6 +274,34 @@ bool dll_target::proc_wait(const NetEvWait*net) stmt_cur_->u_.wait_.stmt_ = (struct ivl_statement_s*) calloc(1, sizeof(struct ivl_statement_s)); + if (net->nevents() != 1) { + cerr << "internal error: multiple events not supported." << endl; + return false; + } + + NetEvent*ev = net->event(0); + assert(ev->nprobe() == 1); + + const NetEvProbe*pr = ev->probe(0); + assert(pr->pin_count() == 1); + + switch (pr->edge()) { + case NetEvProbe::ANYEDGE: + stmt_cur_->u_.wait_.edge_ = IVL_EDGE_ANY; + break; + case NetEvProbe::NEGEDGE: + stmt_cur_->u_.wait_.edge_ = IVL_EDGE_NEG; + break; + case NetEvProbe::POSEDGE: + stmt_cur_->u_.wait_.edge_ = IVL_EDGE_POS; + break; + } + + const Nexus*nex = pr->pin(0).nexus(); + assert(nex); + assert(nex->t_cookie()); + stmt_cur_->u_.wait_.cond_ = (ivl_nexus_t) nex->t_cookie(); + ivl_statement_t save_cur_ = stmt_cur_; stmt_cur_ = stmt_cur_->u_.wait_.stmt_; bool flag = net->emit_recurse(this); @@ -305,6 +333,9 @@ void dll_target::proc_while(const NetWhile*net) /* * $Log: t-dll-proc.cc,v $ + * Revision 1.12 2001/03/27 06:27:40 steve + * Generate code for simple @ statements. + * * Revision 1.11 2001/03/20 01:44:14 steve * Put processes in the proper scope. * diff --git a/t-dll.h b/t-dll.h index 9bf6ba98f..4994f4395 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.23 2001/03/27 03:31:06 steve Exp $" +#ident "$Id: t-dll.h,v 1.24 2001/03/27 06:27:40 steve Exp $" #endif # include "target.h" @@ -356,7 +356,8 @@ struct ivl_statement_s { } trig_; struct { /* IVL_ST_WAIT */ - int cond_; /* XXXX */ + ivl_edge_type_t edge_; + ivl_nexus_t cond_; ivl_statement_t stmt_; } wait_; @@ -369,6 +370,9 @@ struct ivl_statement_s { /* * $Log: t-dll.h,v $ + * Revision 1.24 2001/03/27 06:27:40 steve + * Generate code for simple @ statements. + * * Revision 1.23 2001/03/27 03:31:06 steve * Support error code from target_t::end_design method. * diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 74cde5704..4ecd134c8 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.4 2001/03/27 03:31:07 steve Exp $" +#ident "$Id: vvp_priv.h,v 1.5 2001/03/27 06:27:41 steve Exp $" #endif # include "ivl_target.h" @@ -40,6 +40,14 @@ extern int draw_process(ivl_process_t net, void*x); extern int draw_scope(ivl_scope_t scope, ivl_scope_t parent); +/* + * Given a nexus, draw a string that represents the functor output + * that feeds the nexus. This function can be used to get the input to + * a functor, event, or even a %load in cases where I have the + * ivl_nexus_t object. + */ +extern void draw_nexus_input(ivl_nexus_t nex); + /* * The draw_eval_expr function writes out the code to evaluate a @@ -54,6 +62,9 @@ extern struct vector_info draw_eval_expr(ivl_expr_t exp); /* * $Log: vvp_priv.h,v $ + * Revision 1.5 2001/03/27 06:27:41 steve + * Generate code for simple @ statements. + * * Revision 1.4 2001/03/27 03:31:07 steve * Support error code from target_t::end_design method. * diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index d499d3368..6eb2183cf 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.8 2001/03/27 03:31:07 steve Exp $" +#ident "$Id: vvp_process.c,v 1.9 2001/03/27 06:27:41 steve Exp $" #endif # include "vvp_priv.h" @@ -145,21 +145,21 @@ static int show_stmt_condit(ivl_statement_t net) lab_false = local_count++; lab_out = local_count++; - fprintf(vvp_out, " %%jmp/0xz T_%05d.%d, %u;\n", + fprintf(vvp_out, " %%jmp/0xz T_%d.%d, %u;\n", thread_count, lab_false, cond.base); rc += show_statement(ivl_stmt_cond_true(net)); if (ivl_stmt_cond_false(net)) { - fprintf(vvp_out, " %%jmp T_%05d.%d;\n", thread_count, lab_out); - fprintf(vvp_out, "T_%05d.%u\n", thread_count, lab_false); + fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_out); + fprintf(vvp_out, "T_%d.%u\n", thread_count, lab_false); rc += show_statement(ivl_stmt_cond_false(net)); - fprintf(vvp_out, "T_%05d.%u\n", thread_count, lab_out); + fprintf(vvp_out, "T_%d.%u\n", thread_count, lab_out); } else { - fprintf(vvp_out, "T_%05d.%u\n", thread_count, lab_false); + fprintf(vvp_out, "T_%d.%u\n", thread_count, lab_false); } return rc; @@ -193,6 +193,18 @@ static int show_stmt_noop(ivl_statement_t net) return 0; } +static int show_stmt_wait(ivl_statement_t net) +{ + ivl_nexus_t nex; + + assert(ivl_stmt_pins(net) == 1); + nex = ivl_stmt_pin(net, 0); + + fprintf(vvp_out, " %%wait L_%s;\n", ivl_nexus_name(nex)); + + return show_statement(ivl_stmt_sub_stmt(net)); +} + static int show_system_task_call(ivl_statement_t net) { unsigned idx; @@ -269,6 +281,10 @@ static int show_statement(ivl_statement_t net) rc += show_system_task_call(net); break; + case IVL_ST_WAIT: + rc += show_stmt_wait(net); + break; + default: fprintf(stderr, "vvp.tgt: Unable to draw statement type %u\n", code); @@ -279,6 +295,48 @@ static int show_statement(ivl_statement_t net) return rc; } +static void show_stmt_event_wait(ivl_statement_t net) +{ + ivl_edge_type_t edge = ivl_stmt_edge(net); + ivl_nexus_t nex; + + const char*estr = ""; + + assert(ivl_stmt_pins(net) == 1); + nex = ivl_stmt_pin(net, 0); + + switch (edge) { + case IVL_EDGE_POS: + estr = "posedge"; + break; + case IVL_EDGE_NEG: + estr = "negedge"; + break; + case IVL_EDGE_ANY: + estr = "anyedge"; + break; + } + + fprintf(vvp_out, "L_%s .event %s, ", ivl_nexus_name(nex), estr); + draw_nexus_input(nex); + fprintf(vvp_out, ";\n"); + +} + +static void show_stmt_events(ivl_statement_t net) +{ + switch (ivl_statement_type(net)) { + case IVL_ST_WAIT: + show_stmt_event_wait(net); + return; + case IVL_ST_DELAY: + show_stmt_events(ivl_stmt_sub_stmt(net)); + return; + default: + return; + } +} + /* * The process as a whole is surrounded by this code. We generate a * start label that the .thread statement can use, and we generate @@ -289,16 +347,21 @@ int draw_process(ivl_process_t net, void*x) { int rc = 0; ivl_scope_t scope = ivl_process_scope(net); + ivl_statement_t stmt = ivl_process_stmt(net); local_count = 0; fprintf(vvp_out, " .scope S_%s;\n", ivl_scope_name(scope)); + /* Show any .event statements that are needed to support this + thread. */ + show_stmt_events(stmt); + /* Generate the entry label. Just give the thread a number so that we ar certain the label is unique. */ - fprintf(vvp_out, "T_%05d\n", thread_count); + fprintf(vvp_out, "T_%d\n", thread_count); /* Draw the contents of the thread. */ - rc += show_statement(ivl_process_stmt(net)); + rc += show_statement(stmt); /* Terminate the thread with either an %end instruction (initial @@ -311,13 +374,13 @@ int draw_process(ivl_process_t net, void*x) break; case IVL_PR_ALWAYS: - fprintf(vvp_out, " %%jmp T_%05d;\n", thread_count); + fprintf(vvp_out, " %%jmp T_%d;\n", thread_count); break; } /* Now write out the .thread directive that tells vvp where the thread starts. */ - fprintf(vvp_out, " .thread T_%05d;\n", thread_count); + fprintf(vvp_out, " .thread T_%d;\n", thread_count); thread_count += 1; @@ -326,6 +389,9 @@ int draw_process(ivl_process_t net, void*x) /* * $Log: vvp_process.c,v $ + * Revision 1.9 2001/03/27 06:27:41 steve + * Generate code for simple @ statements. + * * Revision 1.8 2001/03/27 03:31:07 steve * Support error code from target_t::end_design method. * diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index cbec5b996..f5ae1157e 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvp_scope.c,v 1.5 2001/03/25 19:36:12 steve Exp $" +#ident "$Id: vvp_scope.c,v 1.6 2001/03/27 06:27:41 steve Exp $" #endif # include "vvp_priv.h" @@ -36,7 +36,7 @@ * * XXXX This function does not yet support multiple drivers. */ -static void draw_nexus_input(ivl_nexus_t nex) +void draw_nexus_input(ivl_nexus_t nex) { ivl_net_logic_t lptr; ivl_signal_t sptr; @@ -103,6 +103,61 @@ static void draw_net_in_scope(ivl_signal_t sig) fprintf(vvp_out, ";\n"); } +static void draw_logic_in_scope(ivl_net_logic_t lptr) +{ + unsigned pdx; + const char*ltype = "?"; + unsigned init_val = 0; + + /* Skip BUFZ objects. Things that have a bufz as input + will use the input to bufz instead. */ + if (ivl_logic_type(lptr) == IVL_LO_BUFZ) + return; + + + switch (ivl_logic_type(lptr)) { + + case IVL_LO_AND: + ltype = "AND"; + init_val = 0x55; + break; + + case IVL_LO_NOR: + ltype = "NOR"; + break; + + case IVL_LO_NOT: + ltype = "NOT"; + break; + + case IVL_LO_OR: + ltype = "OR"; + break; + + default: + ltype = "?"; + break; + } + + assert(ivl_logic_pins(lptr) <= 5); + + for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) { + unsigned mask = 3 << (pdx - 1); + init_val = (init_val & ~mask) | (2 << (pdx - 1)); + } + + fprintf(vvp_out, "L_%s .functor %s, 0x%x", + ivl_logic_name(lptr), ltype, init_val); + + for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) { + ivl_nexus_t nex = ivl_logic_pin(lptr, pdx); + fprintf(vvp_out, ", "); + draw_nexus_input(nex); + } + + fprintf(vvp_out, ";\n"); +} + int draw_scope(ivl_scope_t net, ivl_scope_t parent) { unsigned idx; @@ -121,54 +176,8 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) remaining pins to inputs. */ for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1) { - unsigned pdx; ivl_net_logic_t lptr = ivl_scope_log(net, idx); - const char*ltype = "?"; - unsigned init_val = 0; - - /* Skip BUFZ objects. Things that have a bufz as input - will use the input to bufz instead. */ - if (ivl_logic_type(lptr) == IVL_LO_BUFZ) - continue; - - - switch (ivl_logic_type(lptr)) { - - case IVL_LO_AND: - ltype = "AND"; - init_val = 0x55; - break; - - case IVL_LO_NOR: - ltype = "NOR"; - break; - - case IVL_LO_NOT: - ltype = "NOT"; - break; - - default: - ltype = "?"; - break; - } - - assert(ivl_logic_pins(lptr) <= 5); - - for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) { - unsigned mask = 3 << (pdx - 1); - init_val = (init_val & ~mask) | (2 << (pdx - 1)); - } - - fprintf(vvp_out, "L_%s .functor %s, 0x%x", - ivl_logic_name(lptr), ltype, init_val); - - for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) { - ivl_nexus_t nex = ivl_logic_pin(lptr, pdx); - fprintf(vvp_out, ", "); - draw_nexus_input(nex); - } - - fprintf(vvp_out, ";\n"); + draw_logic_in_scope(lptr); } @@ -194,6 +203,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) /* * $Log: vvp_scope.c,v $ + * Revision 1.6 2001/03/27 06:27:41 steve + * Generate code for simple @ statements. + * * Revision 1.5 2001/03/25 19:36:12 steve * Draw AND NOR and NOT gates. *