diff --git a/tgt-vvp/Makefile.in b/tgt-vvp/Makefile.in index 5e1d12344..2a103ec97 100644 --- a/tgt-vvp/Makefile.in +++ b/tgt-vvp/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.10 2002/08/12 00:27:10 steve Exp $" +#ident "$Id: Makefile.in,v 1.11 2002/09/27 16:33:34 steve Exp $" # # SHELL = /bin/sh @@ -50,7 +50,7 @@ all: vvp.tgt $(CC) -Wall @ident_support@ -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o mv $*.d dep -O = vvp.o draw_mux.o eval_expr.o vvp_process.o vvp_scope.o +O = vvp.o draw_mux.o eval_expr.o vector.o vvp_process.o vvp_scope.o ifeq (@WIN32@,yes) TGTLDFLAGS=-L.. -livl diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 1bf83b817..0e9d83e86 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: eval_expr.c,v 1.79 2002/09/24 04:20:32 steve Exp $" +#ident "$Id: eval_expr.c,v 1.80 2002/09/27 16:33:34 steve Exp $" #endif # include "vvp_priv.h" @@ -29,70 +29,6 @@ # include -static unsigned char allocation_map[0x10000/8]; - -static inline int peek_bit(unsigned addr) -{ - unsigned bit = addr % 8; - addr /= 8; - return 1 & (allocation_map[addr] >> bit); -} - -static inline void set_bit(unsigned addr) -{ - unsigned bit = addr % 8; - addr /= 8; - allocation_map[addr] |= (1 << bit); -} - -static inline void clr_bit(unsigned addr) -{ - unsigned bit = addr % 8; - addr /= 8; - allocation_map[addr] &= ~(1 << bit); -} - -/* - * This clears a vector that was previously allocated by - * allocate_vector. That is, it unmarks all the bits of the map that - * represent this vector. - * - * If the vector is based in one of 4 constant bit values, then there - * are no bits to clear. If the vector is based in the 4-8 result - * area, then someone is broken. - */ -void clr_vector(struct vector_info vec) -{ - unsigned idx; - if (vec.base < 4) - return; - assert(vec.base >= 8); - for (idx = 0 ; idx < vec.wid ; idx += 1) - clr_bit(vec.base + idx); -} - -unsigned short allocate_vector(unsigned short wid) -{ - unsigned short base = 8; - - unsigned short idx = 0; - while (idx < wid) { - assert((base + idx) < 0x10000); - if (peek_bit(base+idx)) { - base = base + idx + 1; - idx = 0; - - } else { - idx += 1; - } - } - - for (idx = 0 ; idx < wid ; idx += 1) - set_bit(base+idx); - - return base; -} - int number_is_unknown(ivl_expr_t ex) { const char*bits; @@ -958,6 +894,8 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp, assert(0); } + if (rv.base >= 8) + save_expression_lookaside(rv.base, exp, wid); return rv; } @@ -989,6 +927,8 @@ static struct vector_info draw_bitsel_expr(ivl_expr_t exp, unsigned wid) break; } + if (res.base >= 8) + save_expression_lookaside(res.base, exp, wid); return res; } @@ -1026,10 +966,22 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid) ivl_expr_t arg = ivl_expr_parm(exp, idx-1); unsigned awid = ivl_expr_width(arg); - /* Evaluate this sub expression. */ - struct vector_info avec = draw_eval_expr_wid(arg, awid, 0); + unsigned trans; + struct vector_info avec; - unsigned trans = awid; + /* Try to locate the subexpression in the + lookaside map. */ + avec.base = allocate_vector_exp(arg, awid); + avec.wid = awid; + + /* If it's not in the lookaside map, then + evaluate the expression here. */ + if (avec.base == 0) { + /* Evaluate this sub expression. */ + avec = draw_eval_expr_wid(arg, awid, 0); + } + + trans = awid; if ((off + awid) > wid) trans = wid - off; @@ -1052,6 +1004,10 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid) res.base+off, wid-off); } + /* Save the accumulated result in the lookaside map. */ + if (res.base >= 8) + save_expression_lookaside(res.base, exp, wid); + return res; } @@ -1137,6 +1093,9 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid) if (idx < wid) fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx); + if (res.base >= 8) + save_expression_lookaside(res.base, exp, wid); + return res; } @@ -1184,6 +1143,9 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid) if (idx < wid) fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx); + if (res.base >= 8) + save_expression_lookaside(res.base, exp, wid); + return res; } @@ -1204,8 +1166,16 @@ static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid) if (swid > wid) swid = wid; - res.base = allocate_vector(wid); - res.wid = wid; + res.base = allocate_vector_exp(exp, wid); + res.wid = wid; + if (res.base != 0) + return res; + + if (res.base == 0) { + res.base = allocate_vector(wid); + res.wid = wid; + save_expression_lookaside(res.base, exp, wid); + } for (idx = 0 ; idx < swid ; idx += 1) fprintf(vvp_out, " %%load %u, V_%s[%u];\n", @@ -1296,6 +1266,9 @@ static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid) fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+swid, wid-swid); + if (res.base >= 8) + save_expression_lookaside(res.base, exp, wid); + return res; } @@ -1345,6 +1318,9 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid) res = subv; } + if (res.base >= 8) + save_expression_lookaside(res.base, exp, wid); + return res; } @@ -1412,6 +1388,9 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid) /* This is the out label. */ fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out); + if (res.base >= 8) + save_expression_lookaside(res.base, exp, wid); + return res; } @@ -1541,6 +1520,9 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid) free(vec); } + /* New basic block starts after VPI calls. */ + clear_expression_lookaside(); + fprintf(vvp_out, ";\n"); @@ -1595,6 +1577,9 @@ static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid) fprintf(vvp_out, ", S_%s;\n", vvp_mangle_id(ivl_scope_name(def))); fprintf(vvp_out, " %%join;\n"); + /* Fresh basic block starts after the join. */ + clear_expression_lookaside(); + /* The return value is in a signal that has the name of the expression. Load that into the thread and return the vector result. */ @@ -1784,6 +1769,9 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid) assert(0); } + if (res.base >= 8) + save_expression_lookaside(res.base, exp, wid); + return res; } @@ -1792,6 +1780,10 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid, { struct vector_info res; + /* This is too conservative, but is certainly safe. Relaxing + this will require extensive testing. */ + clear_expression_lookaside(); + switch (ivl_expr_type(exp)) { default: fprintf(stderr, "vvp error: unhandled expr type: %u\n", @@ -1861,6 +1853,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag) /* * $Log: eval_expr.c,v $ + * Revision 1.80 2002/09/27 16:33:34 steve + * Add thread expression lookaside map. + * * Revision 1.79 2002/09/24 04:20:32 steve * Allow results in register bits 47 in certain cases. * @@ -1907,93 +1902,5 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag) * generate vvp labels. -tdll target does not * used hierarchical name string to look up the * memory objects in the design. - * - * Revision 1.66 2002/08/03 22:30:48 steve - * Eliminate use of ivl_signal_name for signal labels. - * - * Revision 1.65 2002/07/12 18:10:45 steve - * Use all bits of ?: condit expression. - * - * Revision 1.64 2002/07/01 00:52:47 steve - * Carry can propagate to the otp in addi. - * - * Revision 1.63 2002/06/02 18:57:17 steve - * Generate %cmpi/u where appropriate. - * - * Revision 1.62 2002/05/31 20:04:57 steve - * Generate %muli instructions when possible. - * - * Revision 1.61 2002/05/30 01:57:23 steve - * Use addi with wide immediate values. - * - * Revision 1.60 2002/05/29 16:29:34 steve - * Add %addi, which is faster to simulate. - * - * Revision 1.59 2002/05/07 03:49:58 steve - * Handle x case of unary ! properly. - * - * Revision 1.58 2002/04/22 02:41:30 steve - * Reduce the while loop expression if needed. - * - * Revision 1.57 2002/04/14 18:41:34 steve - * Support signed integer division. - * - * Revision 1.56 2002/02/03 05:53:00 steve - * Fix parameter bit select check for magic constants. - * - * Revision 1.55 2002/01/28 00:52:42 steve - * Add support for bit select of parameters. - * This leads to a NetESelect node and the - * vvp code generator to support that. - * - * Revision 1.54 2002/01/11 05:23:05 steve - * Handle certain special cases of stime. - * - * Revision 1.53 2001/11/19 04:25:46 steve - * Handle padding out of logical values. - * - * Revision 1.52 2001/10/24 05:06:54 steve - * The ! expression returns 0 to x and z values. - * - * Revision 1.51 2001/10/18 16:41:49 steve - * Evaluate string expressions (Philip Blundell) - * - * Revision 1.50 2001/10/16 01:27:17 steve - * Generate %div instructions for binary /. - * - * Revision 1.49 2001/10/14 03:24:35 steve - * Handle constant bits in arithmetic expressions. - * - * Revision 1.48 2001/10/10 04:47:43 steve - * Support vectors as operands to logical and. - * - * Revision 1.47 2001/09/29 04:37:44 steve - * Generate code for unary minus (PR#272) - * - * Revision 1.46 2001/09/29 01:53:22 steve - * Fix the size of unsized constant operants to compare (PR#274) - * - * Revision 1.45 2001/09/20 03:46:38 steve - * Handle short l-values to concatenation. - * - * Revision 1.44 2001/09/15 18:27:04 steve - * Make configure detect malloc.h - * - * Revision 1.43 2001/08/31 01:37:56 steve - * Handle update in place of repeat constants. - * - * Revision 1.42 2001/08/23 02:54:15 steve - * Handle wide assignment to narrow return value. - * - * Revision 1.41 2001/08/03 17:06:10 steve - * More detailed messages about unsupported things. - * - * Revision 1.40 2001/07/27 04:51:45 steve - * Handle part select expressions as variants of - * NetESignal/IVL_EX_SIGNAL objects, instead of - * creating new and useless temporary signals. - * - * Revision 1.39 2001/07/27 02:41:56 steve - * Fix binding of dangling function ports. do not elide them. */ diff --git a/tgt-vvp/vector.c b/tgt-vvp/vector.c new file mode 100644 index 000000000..36d743295 --- /dev/null +++ b/tgt-vvp/vector.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2002 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifdef HAVE_CVS_IDENT +#ident "$Id: vector.c,v 1.1 2002/09/27 16:33:34 steve Exp $" +#endif + +# include "vvp_priv.h" +# include + +static struct allocation_score_s { + ivl_expr_t exp; + unsigned bit :16; + unsigned alloc : 1; +} allocation_map[0x10000] = { {0} }; + +/* This is the largest bit to have lookaside values. */ +static unsigned lookaside_top = 0; + +static inline int peek_bit(unsigned addr) +{ + return allocation_map[addr].alloc; +} + +static inline void set_bit(unsigned addr) +{ + allocation_map[addr].alloc = 1; +} + +static inline void clr_bit(unsigned addr) +{ + allocation_map[addr].alloc = 0; +} + +/* + * This clears a vector that was previously allocated by + * allocate_vector. That is, it unmarks all the bits of the map that + * represent this vector. + * + * If the vector is based in one of 4 constant bit values, then there + * are no bits to clear. If the vector is based in the 4-8 result + * area, then someone is broken. + */ +void clr_vector(struct vector_info vec) +{ + unsigned idx; + if (vec.base < 4) + return; + assert(vec.base >= 8); + for (idx = 0 ; idx < vec.wid ; idx += 1) + clr_bit(vec.base + idx); +} + +/* + * This unconditionally allocates a stretch of bits from the register + * set. It never returns a bit addressed <8 (0-3 are constant, 4-7 are + * condition codes). + */ +unsigned short allocate_vector(unsigned short wid) +{ + unsigned short base = 8; + + unsigned short idx = 0; + while (idx < wid) { + assert((base + idx) < 0x10000); + if (peek_bit(base+idx)) { + base = base + idx + 1; + idx = 0; + + } else { + idx += 1; + } + } + + for (idx = 0 ; idx < wid ; idx += 1) { + allocation_map[base+idx].alloc = 1; + allocation_map[base+idx].exp = 0; + } + + return base; +} + +/* + * This clears the expression cache of the allocation map. It is + * called to prevent reuse of existing expressions, normally at the + * start of a basic block. + */ +void clear_expression_lookaside(void) +{ + unsigned idx; + for (idx = 0 ; idx < lookaside_top ; idx += 1) { + allocation_map[idx].exp = 0; + } + + lookaside_top = 0; +} + +void save_expression_lookaside(unsigned short addr, ivl_expr_t exp, + unsigned short wid) +{ + unsigned idx; + assert(addr >= 8); + assert((addr+wid) <= 0x10000); + + for (idx = 0 ; idx < wid ; idx += 1) { + allocation_map[addr+idx].exp = exp; + allocation_map[addr+idx].bit = idx; + } + + if ((addr+wid) > lookaside_top) + lookaside_top = addr+wid; +} + +static int compare_exp(ivl_expr_t l, ivl_expr_t r) +{ + if (! (l && r)) + return 0; + if (l == r) + return 1; + + if (ivl_expr_type(l) != ivl_expr_type(r)) + return 0; + + switch (ivl_expr_type(l)) { + case IVL_EX_SIGNAL: + if (ivl_expr_signal(l) != ivl_expr_signal(r)) + return 0; + + if (ivl_expr_lsi(l) != ivl_expr_lsi(r)) + return 0; + + if (ivl_expr_width(l) != ivl_expr_width(r)) + return 0; + + return 1; + + default: + break; + } + + return 0; +} + +static unsigned short find_expression_lookaside(ivl_expr_t exp, + unsigned short wid) +{ + unsigned top; + unsigned idx, match; + + if (lookaside_top <= wid) + return 0; + + top = lookaside_top - wid + 1; + + assert(exp); + match = 0; + for (idx = 8 ; idx < top ; idx += 1) { + if (! compare_exp(allocation_map[idx].exp, exp)) { + match = 0; + continue; + } + + if (allocation_map[idx].bit != match) { + match = 0; + continue; + } + + match += 1; + if (match == wid) + return idx-match+1; + } + + return 0; +} + +unsigned short allocate_vector_exp(ivl_expr_t exp, unsigned short wid) +{ + unsigned idx; + unsigned short la = find_expression_lookaside(exp, wid); + + for (idx = 0 ; idx < wid ; idx += 1) + if (allocation_map[la+idx].alloc) + return 0; + + for (idx = 0 ; idx < wid ; idx += 1) + allocation_map[la+idx].alloc = 1; + + return la; +} + +/* + * $Log: vector.c,v $ + * Revision 1.1 2002/09/27 16:33:34 steve + * Add thread expression lookaside map. + * + */ + diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 4ed900e02..52f303b07 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vvp_priv.h,v 1.21 2002/09/24 04:20:32 steve Exp $" +#ident "$Id: vvp_priv.h,v 1.22 2002/09/27 16:33:34 steve Exp $" #endif # include "ivl_target.h" @@ -114,9 +114,46 @@ extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w, */ extern void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t exp); +/* + * These functions manage vector allocation in the thread register + * space. They presume that we work on one thread at a time, to + * completion. + * + * allocate_vector + * Return the base of an allocated vector in the thread. The bits + * are marked allocated in the process. + * + * clr_bector + * Clear a vector previously allocated. + * + * The thread vector allocator also keeps a lookaside of expression + * results that are stored in register bit. This lookaside can be used + * by the code generator to notice that certain expression bits are + * already calculated, and can be reused. + * + * clear_expression_lookaside + * Clear the lookaside tables for the current thread. + * + * save_expression_lookaside + * Mark the given expression as available in the given register + * bits. This remains until the lookaside is cleared. + * + * allocate_vector_exp + * This function attempts to locate the expression in the + * lookaside. If it finds it, return a reallocated base for the + * expression. Otherwise, return 0. + */ extern unsigned short allocate_vector(unsigned short wid); extern void clr_vector(struct vector_info vec); +extern void clear_expression_lookaside(void); +extern void save_expression_lookaside(unsigned short addr, + ivl_expr_t exp, + unsigned short wid); + +extern unsigned short allocate_vector_exp(ivl_expr_t exp, + unsigned short wid); + extern int number_is_unknown(ivl_expr_t ex); extern int number_is_immediate(ivl_expr_t ex, unsigned lim_wid); extern unsigned long get_number_immediate(ivl_expr_t ex); @@ -129,6 +166,9 @@ extern unsigned thread_count; /* * $Log: vvp_priv.h,v $ + * Revision 1.22 2002/09/27 16:33:34 steve + * Add thread expression lookaside map. + * * Revision 1.21 2002/09/24 04:20:32 steve * Allow results in register bits 47 in certain cases. * diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 71161d443..0770c7e6a 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: vvp_process.c,v 1.69 2002/09/24 04:20:32 steve Exp $" +#ident "$Id: vvp_process.c,v 1.70 2002/09/27 16:33:34 steve Exp $" #endif # include "vvp_priv.h" @@ -480,6 +480,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope) fprintf(vvp_out, " %%end;\n"); fprintf(vvp_out, "t_%u %%join;\n", out_id); + clear_expression_lookaside(); return rc; } @@ -584,6 +585,8 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) if (idx == default_case) continue; + clear_expression_lookaside(); + fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+idx); show_statement(cst, sscope); @@ -592,6 +595,8 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) } + clear_expression_lookaside(); + /* The out of the case. */ fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+count); @@ -668,12 +673,15 @@ static int show_stmt_condit(ivl_statement_t net, ivl_scope_t sscope) if (ivl_stmt_cond_true(net)) rc += show_statement(ivl_stmt_cond_true(net), sscope); + clear_expression_lookaside(); + if (ivl_stmt_cond_false(net)) { 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), sscope); + clear_expression_lookaside(); fprintf(vvp_out, "T_%d.%u ;\n", thread_count, lab_out); } else { @@ -698,6 +706,9 @@ static int show_stmt_delay(ivl_statement_t net, ivl_scope_t sscope) ivl_statement_t stmt = ivl_stmt_sub_stmt(net); fprintf(vvp_out, " %%delay %lu;\n", delay); + /* Lots of things can happen during a delay. */ + clear_expression_lookaside(); + rc += show_statement(stmt, sscope); return rc; @@ -721,6 +732,8 @@ static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope) } fprintf(vvp_out, " %%delayx 0;\n"); + /* Lots of things can happen during a delay. */ + clear_expression_lookaside(); rc += show_statement(stmt, sscope); return rc; @@ -809,12 +822,14 @@ static int show_stmt_fork(ivl_statement_t net, ivl_scope_t sscope) for (idx = 0 ; idx < cnt-1 ; idx += 1) { fprintf(vvp_out, "t_%u ;\n", id_base+idx); + clear_expression_lookaside(); rc += show_statement(ivl_stmt_block_stmt(net, idx), sscope); fprintf(vvp_out, " %%end;\n"); } /* This is the label for the out. Use this to branch around the implementations of all the child threads. */ + clear_expression_lookaside(); fprintf(vvp_out, "t_%u ;\n", out); return rc; @@ -881,6 +896,7 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope) rc += show_statement(ivl_stmt_sub_stmt(net), sscope); fprintf(vvp_out, " %%jmp T_%u.%u;\n", thread_count, lab_top); + clear_expression_lookaside(); fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_out); clr_vector(cnt); @@ -906,6 +922,7 @@ static int show_stmt_utask(ivl_statement_t net) fprintf(vvp_out, ", S_%s;\n", vvp_mangle_id(ivl_scope_name(task))); fprintf(vvp_out, " %%join;\n"); + clear_expression_lookaside(); return 0; } @@ -915,6 +932,8 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope) fprintf(vvp_out, " %%wait E_%s;\n", vvp_mangle_id(ivl_event_name(ev))); + clear_expression_lookaside(); + return show_statement(ivl_stmt_sub_stmt(net), sscope); } @@ -976,6 +995,7 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope) /* This is the bottom of the loop. branch to the top where the test is repeased, and also draw the out label. */ fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, top_label); + clear_expression_lookaside(); fprintf(vvp_out, "T_%d.%d ;\n", thread_count, out_label); return rc; } @@ -990,6 +1010,7 @@ static int show_system_task_call(ivl_statement_t net) if (parm_count == 0) { fprintf(vvp_out, " %%vpi_call \"%s\";\n", ivl_stmt_name(net)); + clear_expression_lookaside(); return 0; } @@ -1108,6 +1129,8 @@ static int show_system_task_call(ivl_statement_t net) fprintf(vvp_out, ";\n"); + clear_expression_lookaside(); + return 0; } @@ -1121,6 +1144,10 @@ static int show_statement(ivl_statement_t net, ivl_scope_t sscope) const ivl_statement_type_t code = ivl_statement_type(net); int rc = 0; + /* This is more conservitive then it needs to be, but + relaxing this will require extensive testing. */ + clear_expression_lookaside(); + switch (code) { case IVL_ST_ASSIGN: @@ -1242,6 +1269,7 @@ int draw_process(ivl_process_t net, void*x) /* Generate the entry label. Just give the thread a number so that we ar certain the label is unique. */ fprintf(vvp_out, "T_%d ;\n", thread_count); + clear_expression_lookaside(); /* Draw the contents of the thread. */ rc += show_statement(stmt, scope); @@ -1276,6 +1304,7 @@ int draw_task_definition(ivl_scope_t scope) ivl_statement_t def = ivl_scope_def(scope); fprintf(vvp_out, "TD_%s ;\n", vvp_mangle_id(ivl_scope_name(scope))); + clear_expression_lookaside(); assert(def); rc += show_statement(def, scope); @@ -1292,6 +1321,7 @@ int draw_func_definition(ivl_scope_t scope) ivl_statement_t def = ivl_scope_def(scope); fprintf(vvp_out, "TD_%s ;\n", vvp_mangle_id(ivl_scope_name(scope))); + clear_expression_lookaside(); assert(def); rc += show_statement(def, scope); @@ -1304,6 +1334,9 @@ int draw_func_definition(ivl_scope_t scope) /* * $Log: vvp_process.c,v $ + * Revision 1.70 2002/09/27 16:33:34 steve + * Add thread expression lookaside map. + * * Revision 1.69 2002/09/24 04:20:32 steve * Allow results in register bits 47 in certain cases. * @@ -1392,99 +1425,5 @@ int draw_func_definition(ivl_scope_t scope) * * Revision 1.44 2001/09/01 00:58:16 steve * dead comments. - * - * Revision 1.43 2001/08/26 23:00:13 steve - * Generate code for l-value bit selects. - * - * Revision 1.42 2001/08/25 23:50:03 steve - * Change the NetAssign_ class to refer to the signal - * instead of link into the netlist. This is faster - * and uses less space. Make the NetAssignNB carry - * the delays instead of the NetAssign_ lval objects. - * - * Change the vvp code generator to support multiple - * l-values, i.e. concatenations of part selects. - * - * Revision 1.41 2001/08/16 03:45:17 steve - * statement ends after while loop labels. - * - * Revision 1.40 2001/07/28 01:18:07 steve - * Evaluate part selects when passed to system tasks. - * - * Revision 1.39 2001/07/19 04:55:06 steve - * Support calculated delays in vvp.tgt. - * - * Revision 1.38 2001/06/29 02:41:05 steve - * Handle null parameters to system tasks. - * - * Revision 1.37 2001/06/23 00:30:42 steve - * Handle short inputs to tasks. (Stephan Boettcher) - * - * Revision 1.36 2001/06/18 03:10:34 steve - * 1. Logic with more than 4 inputs - * 2. Id and name mangling - * 3. A memory leak in draw_net_in_scope() - * (Stephan Boettcher) - * - * Revision 1.35 2001/05/24 04:31:00 steve - * Attach noops to case labels. - * - * Revision 1.34 2001/05/17 04:37:02 steve - * Behavioral ternary operators for vvp. - * - * Revision 1.33 2001/05/10 00:26:53 steve - * VVP support for memories in expressions, - * including general support for thread bit - * vectors as system task parameters. - * (Stephan Boettcher) - * - * Revision 1.32 2001/05/08 23:59:33 steve - * Add ivl and vvp.tgt support for memories in - * expressions and l-values. (Stephan Boettcher) - * - * Revision 1.31 2001/05/03 04:55:28 steve - * Generate null statements for conditional labels. - * - * Revision 1.30 2001/04/21 03:26:23 steve - * Right shift by constant. - * - * Revision 1.29 2001/04/21 00:55:46 steve - * Generate code for disable. - * - * Revision 1.28 2001/04/18 05:12:03 steve - * Use the new %fork syntax. - * - * Revision 1.27 2001/04/15 02:58:11 steve - * vvp support for <= with internal delay. - * - * Revision 1.26 2001/04/06 02:28:03 steve - * Generate vvp code for functions with ports. - * - * Revision 1.25 2001/04/05 03:20:58 steve - * Generate vvp code for the repeat statement. - * - * Revision 1.24 2001/04/04 04:50:35 steve - * Support forever loops in the tgt-vvp target. - * - * Revision 1.23 2001/04/04 04:28:41 steve - * Fix broken look scanning down bits of number. - * - * Revision 1.22 2001/04/04 04:14:09 steve - * emit vpi parameters values as vectors. - * - * Revision 1.21 2001/04/03 04:50:37 steve - * Support non-blocking assignments. - * - * Revision 1.20 2001/04/02 04:09:20 steve - * thread bit allocation leak in assign. - * - * Revision 1.19 2001/04/02 02:28:13 steve - * Generate code for task calls. - * - * Revision 1.18 2001/04/02 00:27:53 steve - * Scopes and numbers as vpi_call parameters. - * - * Revision 1.17 2001/04/01 06:49:04 steve - * Generate code for while statements. */