Add thread expression lookaside map.

This commit is contained in:
steve 2002-09-27 16:33:34 +00:00
parent e3eb89fb12
commit 778e96330d
5 changed files with 353 additions and 256 deletions

View File

@ -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

View File

@ -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 <assert.h>
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.
*/

211
tgt-vvp/vector.c Normal file
View File

@ -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 <assert.h>
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.
*
*/

View File

@ -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.
*

View File

@ -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.
*/