Merge vpi_call and vpi_func draw functions.

This commit is contained in:
steve 2003-02-28 20:21:13 +00:00
parent feee40603c
commit 970c4950f4
5 changed files with 263 additions and 288 deletions

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.14 2003/02/27 22:13:22 steve Exp $"
#ident "$Id: Makefile.in,v 1.15 2003/02/28 20:21:13 steve Exp $"
#
#
SHELL = /bin/sh
@ -52,7 +52,8 @@ dep:
$(CC) -Wall @ident_support@ -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
mv $*.d dep
O = vvp.o draw_mux.o eval_expr.o eval_real.o vector.o vvp_process.o vvp_scope.o
O = vvp.o draw_mux.o draw_vpi.o eval_expr.o eval_real.o vector.o \
vvp_process.o vvp_scope.o
ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl

236
tgt-vvp/draw_vpi.c Normal file
View File

@ -0,0 +1,236 @@
/*
* Copyright (c) 2003 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: draw_vpi.c,v 1.1 2003/02/28 20:21:13 steve Exp $"
#endif
# include "vvp_priv.h"
# include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdlib.h>
# include <assert.h>
struct vector_info draw_vpi_taskfunc_call(ivl_statement_t tnet,
ivl_expr_t fnet, unsigned wid)
{
unsigned idx;
unsigned parm_count = tnet
? ivl_stmt_parm_count(tnet)
: ivl_expr_parms(fnet);
struct vector_info res;
struct vector_info *vec = 0x0;
unsigned int vecs= 0;
unsigned int veci= 0;
/* Figure out how many expressions are going to be evaluated
for this task call. I won't need to evaluate expressions
for items that are VPI objects directly. */
for (idx = 0 ; idx < parm_count ; idx += 1) {
ivl_expr_t expr = tnet
? ivl_stmt_parm(tnet, idx)
: ivl_expr_parm(fnet, idx);
switch (ivl_expr_type(expr)) {
/* These expression types can be handled directly,
with VPI handles of their own. Therefore, skip
them in the process of evaluating expressions. */
case IVL_EX_NONE:
case IVL_EX_NUMBER:
case IVL_EX_STRING:
case IVL_EX_SCOPE:
case IVL_EX_SFUNC:
case IVL_EX_VARIABLE:
continue;
case IVL_EX_SIGNAL:
/* If the signal node is narrower then the signal
itself, then this is a part select so I'm going
to need to evaluate the expression.
If I don't need to do any evaluating, then skip
it as I'll be passing the handle to the signal
itself. */
if (ivl_expr_width(expr) !=
ivl_signal_pins(ivl_expr_signal(expr))) {
break;
} else {
continue;
}
case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) {
continue;
}
/* Everything else will need to be evaluated and
passed as a constant to the vpi task. */
default:
break;
}
vec = (struct vector_info *)
realloc(vec, (vecs+1)*sizeof(struct vector_info));
switch (ivl_expr_value(expr)) {
case IVL_VT_VECTOR:
vec[vecs] = draw_eval_expr(expr, 0);
break;
case IVL_VT_REAL:
vec[vecs].base = draw_eval_real(expr);
vec[vecs].wid = 0;
break;
default:
assert(0);
}
vecs++;
}
if (tnet != 0) {
/* for task calls, the res vector is not used. */
res.base = 0;
res.wid = 0;
fprintf(vvp_out, " %%vpi_call \"%s\"", ivl_stmt_name(tnet));
} else {
res.base = allocate_vector(wid);
res.wid = wid;
fprintf(vvp_out, " %%vpi_func \"%s\", %u, %u",
ivl_expr_name(fnet), res.base, res.wid);
}
for (idx = 0 ; idx < parm_count ; idx += 1) {
ivl_expr_t expr = tnet
? ivl_stmt_parm(tnet, idx)
: ivl_expr_parm(fnet, idx);
switch (ivl_expr_type(expr)) {
case IVL_EX_NONE:
fprintf(vvp_out, ", \" \"");
continue;
case IVL_EX_NUMBER: {
unsigned bit, wid = ivl_expr_width(expr);
const char*bits = ivl_expr_bits(expr);
fprintf(vvp_out, ", %u'%sb", wid,
ivl_expr_signed(expr)? "s" : "");
for (bit = wid ; bit > 0 ; bit -= 1)
fputc(bits[bit-1], vvp_out);
continue;
}
case IVL_EX_SIGNAL:
/* If this is a part select, then the value was
calculated above. Otherwise, just pass the
signal. */
if (ivl_expr_width(expr) !=
ivl_signal_pins(ivl_expr_signal(expr))) {
break;
} else {
fprintf(vvp_out, ", V_%s",
vvp_signal_label(ivl_expr_signal(expr)));
continue;
}
case IVL_EX_VARIABLE: {
ivl_variable_t var = ivl_expr_variable(expr);
fprintf(vvp_out, ", W_%s", vvp_word_label(var));
continue;
}
case IVL_EX_STRING:
fprintf(vvp_out, ", \"%s\"",
ivl_expr_string(expr));
continue;
case IVL_EX_SCOPE:
fprintf(vvp_out, ", S_%s",
vvp_mangle_id(ivl_scope_name(ivl_expr_scope(expr))));
continue;
case IVL_EX_SFUNC:
if (strcmp("$time", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $time");
else if (strcmp("$stime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $stime");
else if (strcmp("$realtime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $realtime");
else if (strcmp("$simtime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $simtime");
else
fprintf(vvp_out, ", ?%s?", ivl_expr_name(expr));
continue;
case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) {
fprintf(vvp_out, ", M_%s",
vvp_memory_label(ivl_expr_memory(expr)));
continue;
}
break;
default:
break;
}
assert(veci < vecs);
switch (ivl_expr_value(expr)) {
case IVL_VT_VECTOR:
fprintf(vvp_out, ", T<%u,%u,%s>", vec[veci].base,
vec[veci].wid, ivl_expr_signed(expr)? "s" : "u");
break;
case IVL_VT_REAL:
fprintf(vvp_out, ", W<%u,r>", vec[veci].base);
break;
default:
assert(0);
}
veci++;
}
assert(veci == vecs);
if (vecs) {
for (idx = 0; idx < vecs; idx++) {
if (vec[idx].wid > 0)
clr_vector(vec[idx]);
}
free(vec);
}
fprintf(vvp_out, ";\n");
return res;
}
/*
* $Log: draw_vpi.c,v $
* Revision 1.1 2003/02/28 20:21:13 steve
* Merge vpi_call and vpi_func draw functions.
*
*/

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.91 2003/02/07 02:46:16 steve Exp $"
#ident "$Id: eval_expr.c,v 1.92 2003/02/28 20:21:13 steve Exp $"
#endif
# include "vvp_priv.h"
@ -1604,11 +1604,6 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
{
unsigned idx;
struct vector_info *vec = 0x0;
unsigned int vecs= 0;
unsigned int veci= 0;
unsigned parm_count = ivl_expr_parms(exp);
struct vector_info res;
@ -1624,118 +1619,11 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
}
/* Evaluate any expressions that need to be evaluated by the
run-time before passed to the system task. The results are
stored in the vec array. */
for (idx = 0 ; idx < parm_count ; idx += 1) {
ivl_expr_t expr = ivl_expr_parm(exp, idx);
switch (ivl_expr_type(expr)) {
case IVL_EX_NONE:
case IVL_EX_NUMBER:
case IVL_EX_SIGNAL:
case IVL_EX_STRING:
case IVL_EX_SCOPE:
case IVL_EX_SFUNC:
continue;
case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) {
continue;
}
default:
break;
}
vec = (struct vector_info *)
realloc(vec, (vecs+1)*sizeof(struct vector_info));
vec[vecs] = draw_eval_expr(expr, 0);
vecs++;
}
/* Start the complicated expression. */
res.base = allocate_vector(wid);
res.wid = wid;
fprintf(vvp_out, " %%vpi_func \"%s\", %u, %u",
ivl_expr_name(exp), res.base, res.wid);
/* Now draw all the parameters to the function. */
for (idx = 0 ; idx < parm_count ; idx += 1) {
ivl_expr_t expr = ivl_expr_parm(exp, idx);
switch (ivl_expr_type(expr)) {
case IVL_EX_NONE:
fprintf(vvp_out, ", \" \"");
continue;
case IVL_EX_NUMBER: {
unsigned bit, wid = ivl_expr_width(expr);
const char*bits = ivl_expr_bits(expr);
fprintf(vvp_out, ", %u'b", wid);
for (bit = wid ; bit > 0 ; bit -= 1)
fputc(bits[bit-1], vvp_out);
continue;
}
case IVL_EX_SIGNAL:
fprintf(vvp_out, ", V_%s",
vvp_signal_label(ivl_expr_signal(expr)));
continue;
case IVL_EX_STRING:
fprintf(vvp_out, ", \"%s\"",
ivl_expr_string(expr));
continue;
case IVL_EX_SCOPE:
fprintf(vvp_out, ", S_%s",
vvp_mangle_id(ivl_scope_name(ivl_expr_scope(expr))));
continue;
case IVL_EX_SFUNC:
if (strcmp("$time", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $time");
else if (strcmp("$stime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $stime");
else if (strcmp("$realtime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $realtime");
else
fprintf(vvp_out, ", ?%s?", ivl_expr_name(expr));
continue;
case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) {
fprintf(vvp_out, ", M_%s",
vvp_memory_label(ivl_expr_memory(expr)));
continue;
}
break;
default:
break;
}
fprintf(vvp_out, ", T<%u,%u>",
vec[veci].base,
vec[veci].wid);
veci++;
}
assert(veci == vecs);
if (vecs) {
for (idx = 0; idx < vecs; idx++)
clr_vector(vec[idx]);
free(vec);
}
res = draw_vpi_taskfunc_call(0, exp, wid);
/* New basic block starts after VPI calls. */
clear_expression_lookaside();
fprintf(vvp_out, ";\n");
return res;
}
@ -2114,6 +2002,9 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
/*
* $Log: eval_expr.c,v $
* Revision 1.92 2003/02/28 20:21:13 steve
* Merge vpi_call and vpi_func draw functions.
*
* Revision 1.91 2003/02/07 02:46:16 steve
* Handle real value subtract and comparisons.
*

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.23 2003/01/26 21:16:00 steve Exp $"
#ident "$Id: vvp_priv.h,v 1.24 2003/02/28 20:21:13 steve Exp $"
#endif
# include "ivl_target.h"
@ -64,6 +64,16 @@ extern int draw_scope(ivl_scope_t scope, ivl_scope_t parent);
extern void draw_lpm_mux(ivl_lpm_t net);
/*
* This function draws the execution of a vpi_call statement, along
* with the tricky handling of arguments. If this is called with a
* statement handle, it will generate a %vpi_call
* instruction. Otherwise, it will generate a %vpi_func instruction.
*/
extern struct vector_info draw_vpi_taskfunc_call(ivl_statement_t net,
ivl_expr_t exp,
unsigned wid);
/*
* 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
@ -181,6 +191,9 @@ extern unsigned thread_count;
/*
* $Log: vvp_priv.h,v $
* Revision 1.24 2003/02/28 20:21:13 steve
* Merge vpi_call and vpi_func draw functions.
*
* Revision 1.23 2003/01/26 21:16:00 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.

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.80 2003/02/27 20:38:12 steve Exp $"
#ident "$Id: vvp_process.c,v 1.81 2003/02/28 20:21:13 steve Exp $"
#endif
# include "vvp_priv.h"
@ -1224,11 +1224,7 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
static int show_system_task_call(ivl_statement_t net)
{
unsigned idx;
unsigned parm_count = ivl_stmt_parm_count(net);
struct vector_info *vec = 0x0;
unsigned int vecs= 0;
unsigned int veci= 0;
if (parm_count == 0) {
fprintf(vvp_out, " %%vpi_call \"%s\";\n", ivl_stmt_name(net));
@ -1236,172 +1232,7 @@ static int show_system_task_call(ivl_statement_t net)
return 0;
}
/* Figure out how many expressions are going to be evaluated
for this task call. I won't need to evaluate expressions
for items that are VPI objects directly. */
for (idx = 0 ; idx < parm_count ; idx += 1) {
ivl_expr_t expr = ivl_stmt_parm(net, idx);
switch (ivl_expr_type(expr)) {
/* These expression types can be handled directly,
with VPI handles of their own. Therefore, skip
them in the process of evaluating expressions. */
case IVL_EX_NONE:
case IVL_EX_NUMBER:
case IVL_EX_STRING:
case IVL_EX_SCOPE:
case IVL_EX_SFUNC:
case IVL_EX_VARIABLE:
continue;
case IVL_EX_SIGNAL:
/* If the signal node is narrower then the signal
itself, then this is a part select so I'm going
to need to evaluate the expression.
If I don't need to do any evaluating, then skip
it as I'll be passing the handle to the signal
itself. */
if (ivl_expr_width(expr) !=
ivl_signal_pins(ivl_expr_signal(expr))) {
break;
} else {
continue;
}
case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) {
continue;
}
/* Everything else will need to be evaluated and
passed as a constant to the vpi task. */
default:
break;
}
vec = (struct vector_info *)
realloc(vec, (vecs+1)*sizeof(struct vector_info));
switch (ivl_expr_value(expr)) {
case IVL_VT_VECTOR:
vec[vecs] = draw_eval_expr(expr, 0);
break;
case IVL_VT_REAL:
vec[vecs].base = draw_eval_real(expr);
vec[vecs].wid = 0;
break;
default:
assert(0);
}
vecs++;
}
fprintf(vvp_out, " %%vpi_call \"%s\"", ivl_stmt_name(net));
for (idx = 0 ; idx < parm_count ; idx += 1) {
ivl_expr_t expr = ivl_stmt_parm(net, idx);
switch (ivl_expr_type(expr)) {
case IVL_EX_NONE:
fprintf(vvp_out, ", \" \"");
continue;
case IVL_EX_NUMBER: {
unsigned bit, wid = ivl_expr_width(expr);
const char*bits = ivl_expr_bits(expr);
fprintf(vvp_out, ", %u'%sb", wid,
ivl_expr_signed(expr)? "s" : "");
for (bit = wid ; bit > 0 ; bit -= 1)
fputc(bits[bit-1], vvp_out);
continue;
}
case IVL_EX_SIGNAL:
/* If this is a part select, then the value was
calculated above. Otherwise, just pass the
signal. */
if (ivl_expr_width(expr) !=
ivl_signal_pins(ivl_expr_signal(expr))) {
break;
} else {
fprintf(vvp_out, ", V_%s",
vvp_signal_label(ivl_expr_signal(expr)));
continue;
}
case IVL_EX_VARIABLE: {
ivl_variable_t var = ivl_expr_variable(expr);
fprintf(vvp_out, ", W_%s", vvp_word_label(var));
continue;
}
case IVL_EX_STRING:
fprintf(vvp_out, ", \"%s\"",
ivl_expr_string(expr));
continue;
case IVL_EX_SCOPE:
fprintf(vvp_out, ", S_%s",
vvp_mangle_id(ivl_scope_name(ivl_expr_scope(expr))));
continue;
case IVL_EX_SFUNC:
if (strcmp("$time", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $time");
else if (strcmp("$stime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $stime");
else if (strcmp("$realtime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $realtime");
else if (strcmp("$simtime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $simtime");
else
fprintf(vvp_out, ", ?%s?", ivl_expr_name(expr));
continue;
case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) {
fprintf(vvp_out, ", M_%s",
vvp_memory_label(ivl_expr_memory(expr)));
continue;
}
break;
default:
break;
}
assert(veci < vecs);
switch (ivl_expr_value(expr)) {
case IVL_VT_VECTOR:
fprintf(vvp_out, ", T<%u,%u,%s>", vec[veci].base,
vec[veci].wid, ivl_expr_signed(expr)? "s" : "u");
break;
case IVL_VT_REAL:
fprintf(vvp_out, ", W<%u,r>", vec[veci].base);
break;
default:
assert(0);
}
veci++;
}
assert(veci == vecs);
if (vecs) {
for (idx = 0; idx < vecs; idx++) {
if (vec[idx].wid > 0)
clr_vector(vec[idx]);
}
free(vec);
}
fprintf(vvp_out, ";\n");
(void) draw_vpi_taskfunc_call(net, 0, 0);
/* VPI calls can manipulate anything, so clear the expression
lookahead table after the call. */
@ -1606,6 +1437,9 @@ int draw_func_definition(ivl_scope_t scope)
/*
* $Log: vvp_process.c,v $
* Revision 1.81 2003/02/28 20:21:13 steve
* Merge vpi_call and vpi_func draw functions.
*
* Revision 1.80 2003/02/27 20:38:12 steve
* Handle assign of real values to vectors.
*