diff --git a/Makefile.in b/Makefile.in index 04422581b..3df9bb21b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,9 +16,6 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.181 2007/05/24 04:07:11 steve Exp $" -# -# SHELL = /bin/sh # This version string is only used in the version message printed @@ -51,6 +48,9 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ LEX = @LEX@ YACC = @YACC@ +MAN = @MAN@ +PS2PDF = @PS2PDF@ +GIT = @GIT@ CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@ CXXFLAGS = -Wall @CXXFLAGS@ @@ -65,7 +65,7 @@ all: dep version.h ivl@EXEEXT@ # In the windows world, the installer will need a dosify program to # dosify text files. -ifeq (@MING32@,yes) +ifeq (@MINGW32@,yes) all: dep dosify.exe dosify.exe: dosify.c $(CC) -o dosify.exe dosify.c @@ -177,19 +177,22 @@ lexor_keyword.cc: lexor_keyword.gperf gperf -o -i 7 -C -k 1-4,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false) iverilog-vpi.ps: $(srcdir)/iverilog-vpi.man - man -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps + $(MAN) -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps iverilog-vpi.pdf: iverilog-vpi.ps - ps2pdf iverilog-vpi.ps iverilog-vpi.pdf + $(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf # For VERSION_TAG in driver/main.c, first try git-describe, then look for a # version.h file in the source tree (included in snapshots and releases), and # finally use nothing. .PHONY: version.h version.h: +ifeq ($(GIT),none) + @echo '#define VERSION_TAG ""' > $@; +else @if test -d $(srcdir)/.git; then \ echo "Using git-describe for VERSION_TAG"; \ - tmp=`git --git-dir $(srcdir)/.git describe \ + tmp=`$(GIT) --git-dir $(srcdir)/.git describe \ | sed -e 's;\(.*\);#define VERSION_TAG "\1";'`; \ echo "$$tmp" | diff - $@ > /dev/null 2>&1 || echo "$$tmp" > $@ || exit 1; \ elif test -r $(srcdir)/$@; then \ @@ -199,11 +202,20 @@ version.h: echo "Using empty VERSION_TAG"; \ echo '#define VERSION_TAG ""' > $@; \ fi +endif -ifeq (@MING32@,yes) +ifeq (@MINGW32@,yes) +ifeq ($(MAN),none) +INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1 +else +ifeq ($(PS2PDF),none) +INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1 +else INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1 -INSTALL_DOCDIR = $(mandir)/man1 all: dep iverilog-vpi.pdf +endif +endif +INSTALL_DOCDIR = $(mandir)/man1 else INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1 INSTALL_DOCDIR = $(mandir)/man1 diff --git a/autoconf.sh b/autoconf.sh index 4bf779ebd..1ace2dc34 100644 --- a/autoconf.sh +++ b/autoconf.sh @@ -16,4 +16,4 @@ do done echo "Precompiling lexor_keyword.gperf" -gperf -o -i 7 -C -k 1-3,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc +gperf -o -i 7 -C -k 1-4,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc diff --git a/cadpli/Makefile.in b/cadpli/Makefile.in index e98089888..9d8885847 100644 --- a/cadpli/Makefile.in +++ b/cadpli/Makefile.in @@ -16,12 +16,9 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.13 2007/02/06 05:07:31 steve Exp $" -# -# SHELL = /bin/sh -VERSION = 0.0 +VERSION = 0.9.devel prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -63,7 +60,7 @@ dep: O = cadpli.o SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi -ifeq (@MING32@,yes) +ifeq (@MINGW32@,yes) SYSTEM_VPI_LDFLAGS += @EXTRALIBS@ endif diff --git a/compiler.h b/compiler.h index 6b654e6e2..2b38802be 100644 --- a/compiler.h +++ b/compiler.h @@ -86,6 +86,7 @@ extern bool debug_scopes; extern bool debug_eval_tree; extern bool debug_elaborate; extern bool debug_synth2; +extern bool debug_optimizer; /* Path to a directory useful for finding subcomponents. */ extern const char*basedir; diff --git a/configure.in b/configure.in index 4f4220c69..46529fbe9 100644 --- a/configure.in +++ b/configure.in @@ -9,6 +9,9 @@ AC_PROG_CC AC_PROG_CXX AC_CHECK_TOOL(STRIP, strip, true) AC_CHECK_PROGS(XGPERF,gperf,none) +AC_CHECK_PROGS(MAN,man,none) +AC_CHECK_PROGS(PS2PDF,ps2pdf,none) +AC_CHECK_PROGS(GIT,git,none) if test "$XGPERF" = "none" then echo "" diff --git a/cprop.cc b/cprop.cc index b3951ff0b..9345b9ea8 100644 --- a/cprop.cc +++ b/cprop.cc @@ -23,6 +23,7 @@ # include "netlist.h" # include "netmisc.h" # include "functor.h" +# include "compiler.h" # include "ivl_assert.h" @@ -828,6 +829,32 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj) count += 1; return; } + + /* If the select input is constant, then replace with a BUFZ */ + flag = obj->pin_Sel().nexus()->drivers_constant(); + verinum::V sel_val = flag? obj->pin_Sel().nexus()->driven_value() : verinum::Vx; + if ((sel_val != verinum::Vz) && (sel_val != verinum::Vx)) { + NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width()); + tmp->set_line(*obj); + + if (debug_optimizer) + cerr << obj->get_fileline() << ": debug: " + << "Replace binary MUX with constant select=" << sel_val + << " with a BUFZ to the selected input." << endl; + + tmp->rise_time(obj->rise_time()); + tmp->fall_time(obj->fall_time()); + tmp->decay_time(obj->decay_time()); + + connect(tmp->pin(0), obj->pin_Result()); + if (sel_val == verinum::V1) + connect(tmp->pin(1), obj->pin_Data(1)); + else + connect(tmp->pin(1), obj->pin_Data(0)); + delete obj; + des->add_node(tmp); + count += 1; + } } /* diff --git a/driver-vpi/Makefile.in b/driver-vpi/Makefile.in index f9cd6def6..a33053ae1 100644 --- a/driver-vpi/Makefile.in +++ b/driver-vpi/Makefile.in @@ -16,12 +16,9 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.7.2.1 2006/10/04 17:08:59 steve Exp $" -# -# SHELL = /bin/sh -VERSION = 0.8.3 +VERSION = 0.9.devel prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -48,6 +45,8 @@ LDFLAGS = @LDFLAGS@ all: iverilog-vpi@EXEEXT@ +check: all + clean: rm -f *.o config.h rm -f iverilog-vpi@EXEEXT@ diff --git a/driver-vpi/main.c b/driver-vpi/main.c index a249f9788..a5be8f8dc 100644 --- a/driver-vpi/main.c +++ b/driver-vpi/main.c @@ -336,6 +336,14 @@ static int parse(int argc, char *argv[]) assignn(&gstr.pOUT, argv[idx], strlen(argv[idx])-strlen(dot_o_ext)); } + /* Check for the -mingw option */ + else if (startsWith(mingw_option, argv[idx])) + assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1, + strlen(argv[idx])-(sizeof(mingw_option)-1)); + /* Check for the -ivl option */ + else if (startsWith(ivl_option, argv[idx])) + assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1, + strlen(argv[idx])-(sizeof(ivl_option)-1)); /* Check for the --name option */ else if (startsWith(name_option, argv[idx])) { assignn(&gstr.pOUT, argv[idx]+sizeof(name_option)-1, @@ -356,14 +364,6 @@ static int parse(int argc, char *argv[]) append(&gstr.pDEFS, " "); append(&gstr.pDEFS, argv[idx]); } - /* Check for the -mingw option */ - else if (startsWith(mingw_option, argv[idx])) - assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1, - strlen(argv[idx])-(sizeof(mingw_option)-1)); - /* Check for the -ivl option */ - else if (startsWith(ivl_option, argv[idx])) - assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1, - strlen(argv[idx])-(sizeof(ivl_option)-1)); /* Check for the --cflags option */ else if (stricmp("--cflags", argv[idx]) == 0) { setup_ivl_environment(); diff --git a/driver/Makefile.in b/driver/Makefile.in index 9968923e9..254b65dfd 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -16,9 +16,6 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.26 2007/02/06 05:07:31 steve Exp $" -# -# SHELL = /bin/sh VERSION = 0.9.devel @@ -41,6 +38,8 @@ CC = @CC@ INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ +MAN = @MAN@ +PS2PDF = @PS2PDF@ CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@ CFLAGS = -Wall @CFLAGS@ @@ -76,15 +75,23 @@ cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h cfparse.o: cfparse.c globals.h cfparse_misc.h iverilog.ps: $(srcdir)/iverilog.man - man -t $(srcdir)/iverilog.man > iverilog.ps + $(MAN) -t $(srcdir)/iverilog.man > iverilog.ps iverilog.pdf: iverilog.ps - ps2pdf iverilog.ps iverilog.pdf + $(PS2PDF) iverilog.ps iverilog.pdf -ifeq (@MING32@,yes) +ifeq (@MINGW32@,yes) +ifeq ($(MAN),none) +INSTALL_DOC = $(mandir)/man1/iverilog.1 +else +ifeq ($(PS2PDF),none) +INSTALL_DOC = $(mandir)/man1/iverilog.1 +else INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1 -INSTALL_DOCDIR = $(mandir)/man1 all: iverilog.pdf +endif +endif +INSTALL_DOCDIR = $(mandir)/man1 else INSTALL_DOC = $(mandir)/man1/iverilog.1 INSTALL_DOCDIR = $(mandir)/man1 diff --git a/driver/main.c b/driver/main.c index a9f5236e4..55fac84b3 100644 --- a/driver/main.c +++ b/driver/main.c @@ -327,6 +327,9 @@ static int t_default(char*cmd, unsigned ncmd) remove(defines_path); remove(compiled_defines_path); } +#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */ + return rc; +#else if (rc != 0) { if (rc == 127) { @@ -342,6 +345,7 @@ static int t_default(char*cmd, unsigned ncmd) } return 0; +#endif } diff --git a/elab_scope.cc b/elab_scope.cc index 0dee90151..04cce6626 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -22,6 +22,7 @@ # include "netmisc.h" # include # include +# include # include /* diff --git a/eval_tree.cc b/eval_tree.cc index b2ac5cb63..7cc7b9ac8 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1172,8 +1172,6 @@ NetExpr* NetEParam::eval_tree(int prune_to_width) assert(scope_); perm_string name = (*reference_).first; - const NetExpr*expr_msb = (*reference_).second.msb; - const NetExpr*expr_lsb = (*reference_).second.lsb; const NetExpr*expr = (*reference_).second.expr; ivl_assert(*this, expr); diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 08bdc3f66..098ef38f7 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -1616,7 +1616,11 @@ static int load_next_input() static void do_dump_precompiled_defines(FILE* out, struct define_t* table) { if (!table->keyword) +#ifdef __MINGW32__ /* MinGW does not know about z. */ + fprintf(out, "%s:%d:%d:%s\n", table->name, table->argc, strlen(table->value), table->value); +#else fprintf(out, "%s:%d:%zd:%s\n", table->name, table->argc, strlen(table->value), table->value); +#endif if (table->left) do_dump_precompiled_defines(out, table->left); @@ -1741,6 +1745,7 @@ void reset_lexor(FILE* out, char* paths[]) isp->ebs = 0; isp->next = 0; isp->lineno = 0; + isp->stringify_flag = 0; if (tail) tail->next = isp; diff --git a/main.cc b/main.cc index 679e321dc..640fcf4d3 100644 --- a/main.cc +++ b/main.cc @@ -124,6 +124,8 @@ bool debug_scopes = false; bool debug_eval_tree = false; bool debug_elaborate = false; bool debug_synth2 = false; +bool debug_optimizer = false; + /* * Verbose messages enabled. */ @@ -391,6 +393,9 @@ static void read_iconfig_file(const char*ipath) } else if (strcmp(cp,"synth2") == 0) { debug_synth2 = true; cerr << "debug: Enable synth2 debug" << endl; + } else if (strcmp(cp,"optimizer") == 0) { + debug_optimizer = true; + cerr << "debug: Enable optimizer debug" << endl; } else { } diff --git a/net_design.cc b/net_design.cc index 595a90817..071dd340c 100644 --- a/net_design.cc +++ b/net_design.cc @@ -20,6 +20,7 @@ # include "config.h" # include +# include /* * This source file contains all the implementations of the Design diff --git a/net_scope.cc b/net_scope.cc index 59cdb1790..4425a2a49 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -22,6 +22,7 @@ # include "netlist.h" # include +# include # include # include "ivl_assert.h" @@ -218,7 +219,7 @@ map::iterator NetScope::find_parameter(perm_ if (idx != localparams.end()) return idx; - return 0; + return (map::iterator) 0; } NetScope::TYPE NetScope::type() const diff --git a/pform_disciplines.cc b/pform_disciplines.cc index be07665d8..82f78708b 100644 --- a/pform_disciplines.cc +++ b/pform_disciplines.cc @@ -143,7 +143,7 @@ void pform_end_discipline(const struct vlltype&loc) { // If the domain is not otherwise specified, then take it to // be continuous if potential or flow natures are given. - if (discipline_domain == DD_NONE && discipline_potential||discipline_flow) + if (discipline_domain == DD_NONE && (discipline_potential||discipline_flow)) discipline_domain = DD_CONTINUOUS; discipline_t*tmp = new discipline_t(discipline_name, discipline_domain, diff --git a/tgt-null/Makefile.in b/tgt-null/Makefile.in index cba6d9c16..204e6a00c 100644 --- a/tgt-null/Makefile.in +++ b/tgt-null/Makefile.in @@ -16,12 +16,9 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.11 2004/02/10 19:25:01 steve Exp $" -# -# SHELL = /bin/sh -VERSION = 0.0 +VERSION = 0.9.devel prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -44,6 +41,8 @@ LDFLAGS = @LDFLAGS@ all: dep null.tgt +check: all + dep: mkdir dep diff --git a/tgt-stub/Makefile.in b/tgt-stub/Makefile.in index f8a4ebe82..679226758 100644 --- a/tgt-stub/Makefile.in +++ b/tgt-stub/Makefile.in @@ -16,12 +16,9 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.20 2007/02/06 05:07:32 steve Exp $" -# -# SHELL = /bin/sh -VERSION = 0.0 +VERSION = 0.9.devel prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -44,6 +41,8 @@ LDFLAGS = @LDFLAGS@ all: dep stub.tgt +check: all + dep: mkdir dep diff --git a/tgt-stub/statement.c b/tgt-stub/statement.c index 0dbaf55d2..efdb7094d 100644 --- a/tgt-stub/statement.c +++ b/tgt-stub/statement.c @@ -288,7 +288,7 @@ void show_statement(ivl_statement_t net, unsigned ind) break; case IVL_ST_DELAY: - fprintf(out, "%*s#%llu\n", ind, "", ivl_stmt_delay_val(net)); + fprintf(out, "%*s#%" PRIu64 "\n", ind, "", ivl_stmt_delay_val(net)); show_statement(ivl_stmt_sub_stmt(net), ind+2); break; diff --git a/tgt-vvp/draw_mux.c b/tgt-vvp/draw_mux.c index 73cb075f6..019ef32b7 100644 --- a/tgt-vvp/draw_mux.c +++ b/tgt-vvp/draw_mux.c @@ -57,10 +57,14 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz) get_number_immediate(d_rise), net); } + const char* input[3]; + input[0] = draw_net_input(ivl_lpm_data(net,0)); + input[1] = draw_net_input(ivl_lpm_data(net,1)); + input[2] = draw_net_input(ivl_lpm_select(net)); fprintf(vvp_out, "L_%p%s .functor %s %u", net, dly, muxz, width); - fprintf(vvp_out, ", %s", draw_input_from_net(ivl_lpm_data(net,0))); - fprintf(vvp_out, ", %s", draw_input_from_net(ivl_lpm_data(net,1))); - fprintf(vvp_out, ", %s", draw_input_from_net(ivl_lpm_select(net))); + fprintf(vvp_out, ", %s", input[0]); + fprintf(vvp_out, ", %s", input[1]); + fprintf(vvp_out, ", %s", input[2]); fprintf(vvp_out, ", C4<>;\n"); } diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 43821385f..ab290867c 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -25,6 +25,10 @@ # include # include +#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */ +#define snprintf _snprintf +#endif + static const char* magic_sfuncs[] = { "$time", "$stime", @@ -52,9 +56,12 @@ static int is_fixed_memory_word(ivl_expr_t net) sig = ivl_expr_signal(net); - if (ivl_signal_array_count(sig) == 1) + if (ivl_signal_dimensions(sig) == 0) return 1; + if (ivl_signal_type(sig) == IVL_SIT_REG) + return 0; + if (number_is_immediate(ivl_expr_oper1(net), 8*sizeof(unsigned))) return 1; @@ -69,9 +76,14 @@ static void draw_vpi_taskfunc_args(const char*call_string, unsigned parm_count = tnet ? ivl_stmt_parm_count(tnet) : ivl_expr_parms(fnet); - struct vector_info *vec = 0x0; - unsigned int vecs= 0; - unsigned int veci= 0; + + struct args_info { + char*text; + int vec_flag; /* True if the vec must be released. */ + struct vector_info vec; + } *args = calloc(parm_count, sizeof(struct args_info)); + + char buffer[4096]; ivl_parameter_t par; @@ -89,17 +101,56 @@ static void draw_vpi_taskfunc_args(const char*call_string, with VPI handles of their own. Therefore, skip them in the process of evaluating expressions. */ case IVL_EX_NONE: + args[idx].text = strdup("\" \""); + continue; + case IVL_EX_ARRAY: - case IVL_EX_NUMBER: + snprintf(buffer, sizeof buffer, + "v%p", ivl_expr_signal(expr)); + args[idx].text = strdup(buffer); + continue; + + case IVL_EX_NUMBER: { + unsigned bit, wid = ivl_expr_width(expr); + const char*bits = ivl_expr_bits(expr); + char*dp; + + snprintf(buffer, sizeof buffer, + "%u'%sb", wid, ivl_expr_signed(expr)? "s" : ""); + dp = buffer + strlen(buffer); + for (bit = wid ; bit > 0 ; bit -= 1) + *dp++ = bits[bit-1]; + *dp++ = 0; + assert(dp - buffer <= sizeof buffer); + args[idx].text = strdup(buffer); + continue; + } + case IVL_EX_STRING: + if (( par = ivl_expr_parameter(expr) )) { + snprintf(buffer, sizeof buffer, "P_%p", par); + + } else { + snprintf(buffer, sizeof buffer, "\"%s\"", ivl_expr_string(expr)); + } + args[idx].text = strdup(buffer); + continue; + case IVL_EX_EVENT: + snprintf(buffer, sizeof buffer, "E_%p", ivl_expr_event(expr)); + args[idx].text = strdup(buffer); + continue; case IVL_EX_SCOPE: + snprintf(buffer, sizeof buffer, "S_%p", ivl_expr_scope(expr)); + args[idx].text = strdup(buffer); continue; case IVL_EX_SFUNC: - if (is_magic_sfunc(ivl_expr_name(expr))) + if (is_magic_sfunc(ivl_expr_name(expr))) { + snprintf(buffer, sizeof buffer, "%s", ivl_expr_name(expr)); + args[idx].text = strdup(buffer); continue; - + } break; case IVL_EX_SIGNAL: @@ -122,21 +173,47 @@ static void draw_vpi_taskfunc_args(const char*call_string, } else if (ivl_expr_signed(expr) != ivl_signal_signed(ivl_expr_signal(expr))) { break; - } else if (! is_fixed_memory_word(expr)){ - break; - } else { - /* Some array selects need to be evaluated. */ + } else if (is_fixed_memory_word(expr)) { + /* This is a word of a non-array, or a word + of a net array, so we can address the + word directly. */ + ivl_signal_t sig = ivl_expr_signal(expr); + unsigned use_word = 0; ivl_expr_t word_ex = ivl_expr_oper1(expr); - if (word_ex && !number_is_immediate(word_ex, - 8*sizeof(unsigned))) { - break; + if (word_ex) { + /* Some array select have been evaluated. */ + if (number_is_immediate(word_ex, 8*sizeof(unsigned))) { + use_word = get_number_immediate(word_ex); + word_ex = 0; + } } + if (word_ex) + break; + + assert(word_ex == 0); + snprintf(buffer, sizeof buffer, "v%p_%u", sig, use_word); + args[idx].text = strdup(buffer); continue; - } + } else { + /* What's left, this is the work of a var + array. Create the right code to handle + it. */ + ivl_signal_t sig = ivl_expr_signal(expr); + unsigned use_word = 0; + ivl_expr_t word_ex = ivl_expr_oper1(expr); + if (word_ex) { + /* Some array select have been evaluated. */ + if (number_is_immediate(word_ex, 8*sizeof(unsigned))) { + use_word = get_number_immediate(word_ex); + word_ex = 0; + } + } + if (word_ex) + break; - case IVL_EX_MEMORY: - if (!ivl_expr_oper1(expr)) { + snprintf(buffer, sizeof buffer, "&A", sig, use_word); + args[idx].text = strdup(buffer); continue; } @@ -146,143 +223,43 @@ static void draw_vpi_taskfunc_args(const char*call_string, break; } - vec = (struct vector_info *) - realloc(vec, (vecs+1)*sizeof(struct vector_info)); - switch (ivl_expr_value(expr)) { case IVL_VT_LOGIC: case IVL_VT_BOOL: - vec[vecs] = draw_eval_expr(expr, 0); + args[idx].vec_flag = 1; + args[idx].vec = draw_eval_expr(expr, 0); + snprintf(buffer, sizeof buffer, + "T<%u,%u,%s>", args[idx].vec.base, args[idx].vec.wid, + ivl_expr_signed(expr)? "s" : "u"); break; case IVL_VT_REAL: - vec[vecs].base = draw_eval_real(expr); - vec[vecs].wid = 0; + args[idx].vec_flag = 1; + args[idx].vec.base = draw_eval_real(expr); + args[idx].vec.wid = 0; + snprintf(buffer, sizeof buffer, + "W<%u,r>", args[idx].vec.base); break; default: assert(0); } - vecs++; + args[idx].text = strdup(buffer); } fprintf(vvp_out, "%s", call_string); 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_ARRAY: - fprintf(vvp_out, ", v%p", ivl_expr_signal(expr)); - 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_width(ivl_expr_signal(expr))) { - break; - - } else if (ivl_expr_signed(expr) != - ivl_signal_signed(ivl_expr_signal(expr))) { - break; - - } else if (! is_fixed_memory_word(expr)){ - break; - - } else { - ivl_signal_t sig = ivl_expr_signal(expr); - unsigned use_word = 0; - ivl_expr_t word_ex = ivl_expr_oper1(expr); - if (word_ex) { - /* Some array select have been evaluated. */ - if (!number_is_immediate(word_ex, - 8*sizeof(unsigned))) { - break; - } - use_word = get_number_immediate(word_ex); - } - fprintf(vvp_out, ", v%p_%u", sig, use_word); - continue; - } - assert(0); - continue; - - case IVL_EX_STRING: - if (( par = ivl_expr_parameter(expr) )) { - fprintf(vvp_out, ", P_%p", par); - - } else { - fprintf(vvp_out, ", \"%s\"", - ivl_expr_string(expr)); - } - continue; - - case IVL_EX_EVENT: - fprintf(vvp_out, ", E_%p", ivl_expr_event(expr)); - continue; - - case IVL_EX_SCOPE: - fprintf(vvp_out, ", S_%p", ivl_expr_scope(expr)); - continue; - - case IVL_EX_SFUNC: - if (is_magic_sfunc(ivl_expr_name(expr))) { - fprintf(vvp_out, ", %s", ivl_expr_name(expr)); - continue; - } - break; - - default: - break; + fprintf(vvp_out, ", %s", args[idx].text); + free(args[idx].text); + if (args[idx].vec_flag) { + if (args[idx].vec.wid > 0) + clr_vector(args[idx].vec); + else + clr_word(args[idx].vec.base); } - assert(veci < vecs); - - switch (ivl_expr_value(expr)) { - - case IVL_VT_LOGIC: - case IVL_VT_BOOL: - 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]); - else if (vec[idx].wid == 0) - clr_word(vec[idx].base); - } - free(vec); - } + free(args); fprintf(vvp_out, ";\n"); } diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index f7c5ed27d..08080fe7e 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -138,8 +138,22 @@ static void eval_logic_into_integer(ivl_expr_t expr, unsigned ix) case IVL_EX_SIGNAL: { ivl_signal_t sig = ivl_expr_signal(expr); + unsigned word = 0; - if (ivl_signal_array_count(sig) > 1) { + if (ivl_signal_dimensions(sig) > 0) { + + /* Detect the special case that this is a + variable array. In this case, the ix/getv + will not work, so do it the hard way. */ + if (ivl_signal_type(sig) == IVL_SIT_REG) { + struct vector_info rv; + rv = draw_eval_expr(expr, 0); + fprintf(vvp_out, " %%ix/get %u, %u, %u;\n", + ix, rv.base, rv.wid); + clr_vector(rv); + break; + } + ivl_expr_t ixe = ivl_expr_oper1(expr); if (number_is_immediate(ixe, 8*sizeof(unsigned long))) word = get_number_immediate(ixe); @@ -1894,28 +1908,23 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res, /* If this is an access to an array, handle that by emitting a load/av instruction. */ - if (ivl_signal_array_count(sig) > 1) { + if (ivl_signal_dimensions(sig) > 0) { ivl_expr_t ix = ivl_expr_oper1(exp); - if (!number_is_immediate(ix, 8*sizeof(unsigned long))) { - draw_eval_expr_into_integer(ix, 3); - if (add_index < 0) { - fprintf(vvp_out, " %%load/av %u, v%p, %u;\n", - res.base, sig, swid); - } else { - assert(add_index == 0); - /* Add an immediate value to an array value. */ - fprintf(vvp_out, " %%ix/load 0, %lu;\n", immediate); - fprintf(vvp_out, " %%load/avp0 %u, v%p, %u;\n", - res.base, sig, swid); - } - pad_expr_in_place(exp, res, swid); - return; + draw_eval_expr_into_integer(ix, 3); + if (add_index < 0) { + fprintf(vvp_out, " %%load/av %u, v%p, %u;\n", + res.base, sig, swid); + } else { + assert(add_index == 0); + + /* Add an immediate value to an array value. */ + fprintf(vvp_out, " %%ix/load 0, %lu;\n", immediate); + fprintf(vvp_out, " %%load/avp0 %u, v%p, %u;\n", + res.base, sig, swid); } - - /* The index is constant, so we can return to direct - readout with the specific word selected. */ - word = get_number_immediate(ix); + pad_expr_in_place(exp, res, swid); + return; } @@ -2030,14 +2039,16 @@ static struct vector_info draw_select_signal(ivl_expr_t sube, unsigned use_word = 0; /* If this is an access to an array, try to get the index as a - constant. If it is, then this reduces to a signal access - and we stay here. If it is not constant, then give up and - do an array index in front of this part select. */ + constant. If it is (and the array is not a reg array then + this reduces to a signal access and we stay here. If it is + not constant, then give up and do an array index in front + of this part select. */ - if (ivl_signal_array_count(sig) > 1) { + if (ivl_signal_dimensions(sig) > 0) { ivl_expr_t ix = ivl_expr_oper1(sube); - if (!number_is_immediate(ix, 8*sizeof(unsigned long))) + if (ivl_signal_type(sig)==IVL_SIT_REG + || !number_is_immediate(ix, 8*sizeof(unsigned long))) return draw_select_array(sube, bit_idx, bit_wid, wid); /* The index is constant, so we can return to direct diff --git a/tgt-vvp/modpath.c b/tgt-vvp/modpath.c index 07b37df22..031257f70 100644 --- a/tgt-vvp/modpath.c +++ b/tgt-vvp/modpath.c @@ -22,6 +22,10 @@ # include # include +#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */ +#define snprintf _snprintf +#endif + static ivl_signal_t find_path_source_port(ivl_delaypath_t path) { int idx; diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 2af631538..f104175e1 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -99,7 +99,7 @@ static void set_to_lvariable(ivl_lval_t lval, if (ivl_lval_mux(lval)) part_off_ex = ivl_lval_mux(lval); - if (part_off_ex) { + if (part_off_ex && ivl_signal_dimensions(sig) == 0) { unsigned skip_set = transient_id++; /* There is a mux expression, so this must be a write to @@ -118,6 +118,39 @@ static void set_to_lvariable(ivl_lval_t lval, lookaside. */ save_signal_lookaside(bit, sig, use_word, 0); + } else if (part_off_ex && ivl_signal_dimensions(sig) > 0) { + + /* Here we have a part select write into an array word. */ + unsigned skip_set = transient_id++; + if (word_ix) { + draw_eval_expr_into_integer(word_ix, 3); + fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set); + } else { + fprintf(vvp_out, " %%ix/load 3, %lu;\n", use_word); + } + draw_eval_expr_into_integer(part_off_ex, 1); + fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set); + fprintf(vvp_out, " %%set/av v%p, %u, %u;\n", + sig, bit, wid); + fprintf(vvp_out, "t_%u ;\n", skip_set); + + } else if ((part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) + && ivl_signal_dimensions(sig) > 0) { + + /* Here we have a part select write into an array word. */ + unsigned skip_set = transient_id++; + if (word_ix) { + draw_eval_expr_into_integer(word_ix, 3); + fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set); + } else { + fprintf(vvp_out, " %%ix/load 3, %lu;\n", use_word); + } + fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off); + fprintf(vvp_out, " %%set/av v%p, %u, %u;\n", + sig, bit, wid); + if (word_ix) /* Only need this label if word_ix is set. */ + fprintf(vvp_out, "t_%u ;\n", skip_set); + } else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) { /* There is no mux expression, but a constant part offset. Load that into index x0 and generate a @@ -145,14 +178,16 @@ static void set_to_lvariable(ivl_lval_t lval, lookaside. */ save_signal_lookaside(bit, sig, use_word, 0); - } else if (ivl_signal_array_count(sig) > 1) { + } else if (ivl_signal_dimensions(sig) > 0) { /* If the word index is a constant, then we can write directly to the word and save the index calculation. */ if (word_ix == 0) { if (use_word < ivl_signal_array_count(sig)) { - fprintf(vvp_out, " %%set/v v%p_%lu, %u, %u;\n", - sig, use_word, bit, wid); + fprintf(vvp_out, " %%ix/load 1, 0;\n"); + fprintf(vvp_out, " %%ix/load 3, %lu;\n", use_word); + fprintf(vvp_out, " %%set/av v%p, %u, %u;\n", + sig, bit, wid); } else { fprintf(vvp_out, " ; %%set/v v%p_%lu, %u, %u " "OUT OF BOUNDS\n", sig, use_word, bit, wid); @@ -185,44 +220,70 @@ static void set_to_lvariable(ivl_lval_t lval, static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, unsigned bit, unsigned delay, ivl_expr_t dexp, - unsigned width) + ivl_expr_t part_off_ex, unsigned width) { unsigned skip_assign = transient_id++; + unsigned part_off = 0; + if (part_off_ex == 0) { + part_off = 0; + } else if (number_is_immediate(part_off_ex, 64)) { + part_off = get_number_immediate(part_off_ex); + part_off_ex = 0; + } + if (dexp == 0) { /* Constant delay... */ - /* Calculate array word index into index register 3 */ - draw_eval_expr_into_integer(word_ix, 3); - /* Skip assignment if word expression is not defined. */ - fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); - + if (number_is_immediate(word_ix, 64)) { + fprintf(vvp_out, " %%ix/load 3, %lu; address\n", + get_number_immediate(word_ix)); + } else { + /* Calculate array word index into index register 3 */ + draw_eval_expr_into_integer(word_ix, 3); + /* Skip assignment if word expression is not defined. */ + fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); + } /* Store expression width into index word 0 */ - fprintf(vvp_out, " %%ix/load 0, %u; // word width\n", width); - /* Store constant (0) word part select into index 1 */ - fprintf(vvp_out, " %%ix/load 1, 0;\n"); - + fprintf(vvp_out, " %%ix/load 0, %u; word width\n", width); + if (part_off_ex) { + draw_eval_expr_into_integer(part_off_ex, 1); + /* If the index expression has XZ bits, skip the assign. */ + fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); + } else { + /* Store word part select base into index 1 */ + fprintf(vvp_out, " %%ix/load 1, %u; part base\n", part_off); + } fprintf(vvp_out, " %%assign/av v%p, %u, %u;\n", lsig, delay, bit); - fprintf(vvp_out, "t_%u ;\n", skip_assign); } else { /* Calculated delay... */ int delay_index = allocate_word(); draw_eval_expr_into_integer(dexp, delay_index); - /* Calculate array word index into index register 3 */ - draw_eval_expr_into_integer(word_ix, 3); - /* Skip assignment if word expression is not defined. */ - fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); - + if (number_is_immediate(word_ix, 64)) { + fprintf(vvp_out, " %%ix/load 3, %lu; address\n", + get_number_immediate(word_ix)); + } else { + /* Calculate array word index into index register 3 */ + draw_eval_expr_into_integer(word_ix, 3); + /* Skip assignment if word expression is not defined. */ + fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); + } /* Store expression width into index word 0 */ - fprintf(vvp_out, " %%ix/load 0, %u; // word width\n", width); - /* Store constant (0) word part select into index 1 */ - fprintf(vvp_out, " %%ix/load 1, 0;\n"); - + fprintf(vvp_out, " %%ix/load 0, %u; word width\n", width); + if (part_off_ex) { + draw_eval_expr_into_integer(part_off_ex, 1); + /* If the index expression has XZ bits, skip the assign. */ + fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); + } else { + /* Store word part select into index 1 */ + fprintf(vvp_out, " %%ix/load 1, %u; part off\n", part_off); + } fprintf(vvp_out, " %%assign/av/d v%p, %d, %u;\n", lsig, delay_index, bit); - fprintf(vvp_out, "t_%u ;\n", skip_assign); } + fprintf(vvp_out, "t_%u ;\n", skip_assign); + clear_expression_lookaside(); } @@ -235,16 +296,12 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit, unsigned part_off = 0; ivl_expr_t word_ix = ivl_lval_idx(lval); - unsigned long use_word = 0; + const unsigned long use_word = 0; if (ivl_signal_array_count(sig) > 1) { assert(word_ix); - if (! number_is_immediate(word_ix, 8*sizeof(use_word))) { - assign_to_array_word(sig, word_ix, bit, delay, dexp, width); - return; - } - - use_word = get_number_immediate(word_ix); + assign_to_array_word(sig, word_ix, bit, delay, dexp, part_off_ex, width); + return; } if (part_off_ex == 0) { diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 05944f639..7900c30fb 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -27,6 +27,10 @@ # include # include +#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */ +#define snprintf _snprintf +#endif + struct vvp_nexus_data { /* draw_net_input uses this */ const char*net_input; @@ -615,6 +619,12 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) /* Input is a .var. This device may be a non-zero pin because it may be an array of reg vectors. */ snprintf(tmp, sizeof tmp, "v%p_%u", sptr, nptr_pin); + + if (ivl_signal_array_count(sptr) > 1) { + fprintf(vvp_out, "v%p_%u .array/port v%p, %u;\n", + sptr, nptr_pin, sptr, nptr_pin); + } + return strdup(tmp); } @@ -988,6 +998,8 @@ const char*draw_input_from_net(ivl_nexus_t nex) ivl_signal_t sig = signal_of_nexus(nex, &word); if (sig == 0) return draw_net_input(nex); + if (ivl_signal_type(sig)==IVL_SIT_REG && ivl_signal_dimensions(sig)>0) + return draw_net_input(nex); snprintf(result, sizeof result, "v%p_%u", sig, word); return result; @@ -1759,7 +1771,11 @@ static void draw_lpm_add(ivl_lpm_t net) type = "pow.s"; if (width > 8*sizeof(long)) { fprintf(stderr, "%s:%u: sorry (vvp-tgt): Signed power " +#ifdef __MINGW32__ /* MinGW does not know about z. */ + "result must be no more than %u bits.\n", +#else "result must be no more than %zu bits.\n", +#endif ivl_lpm_file(net), ivl_lpm_lineno(net), 8*sizeof(long)); exit(1); diff --git a/vpi/Makefile.in b/vpi/Makefile.in index ed719718b..4b8bca964 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -16,12 +16,9 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.61 2007/02/06 05:07:32 steve Exp $" -# -# SHELL = /bin/sh -VERSION = 0.0 +VERSION = 0.9.devel prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -48,6 +45,8 @@ LDFLAGS = @LDFLAGS@ all: dep system.vpi va_math.vpi $(ALL32) +check: all + dep: mkdir dep @@ -75,7 +74,7 @@ V = va_math.o LIBS = @LIBS@ SYSTEM_VPI_LDFLAGS = $(LIBS) VA_MATH_LDFLAGS = -ifeq (@MING32@,yes) +ifeq (@MINGW32@,yes) SYSTEM_VPI_LDFLAGS += @EXTRALIBS@ VA_MATH_LDFLAGS += @EXTRALIBS@ endif diff --git a/vpi/sys_display.c b/vpi/sys_display.c index e92ca15b6..c291d00e3 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -1122,6 +1122,7 @@ static PLI_INT32 sys_monitor_calltf(PLI_BYTE8*name) case vpiReg: case vpiIntegerVar: case vpiRealVar: + case vpiMemoryWord: /* Monitoring reg and net values involves setting a callback for value changes. Pass the storage pointer for the callback itself as user_data so diff --git a/vpi/sys_icarus.c b/vpi/sys_icarus.c index ff6998d5f..af92be7db 100644 --- a/vpi/sys_icarus.c +++ b/vpi/sys_icarus.c @@ -48,6 +48,93 @@ static PLI_INT32 size_32(PLI_BYTE8* ud) return 32; } + +/* + * Routine to finish the simulation and return a value to the + * calling environment. + */ +static PLI_INT32 finish_and_return_compiletf(PLI_BYTE8* ud) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle arg; + (void) ud; /* Not used! */ + + /* We must have at least one argument. */ + if (argv == 0) { + vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("$finish_and_return requires an argument.\n"); + vpi_control(vpiFinish, 1); + return 0; + } + + /* This must be a numeric argument. */ + arg = vpi_scan(argv); + switch(vpi_get(vpiType, arg)) { + case vpiConstant: + case vpiParameter: + /* String constants are invalid numeric values. */ + if (vpi_get(vpiConstType, arg) == vpiStringConst) { + vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("The argument to $finish_and_return must be numeric.\n"); + vpi_control(vpiFinish, 1); + return 0; + } + break; + + case vpiIntegerVar: + case vpiMemoryWord: + case vpiNet: + case vpiRealVar: + case vpiReg: + case vpiTimeVar: + break; + + default: + vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("The argument to $finish_and_return must be numeric.\n"); + vpi_control(vpiFinish, 1); + return 0; + break; + } + + /* We can only have one argument. */ + if (vpi_scan(argv) != 0) { + vpi_printf("ERROR: %s line %d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("$finish_and_return takes a single argument.\n"); + vpi_control(vpiFinish, 1); + return 0; + } + + return 0; +} + +static PLI_INT32 finish_and_return_calltf(PLI_BYTE8* ud) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle arg; + s_vpi_value val; + (void) ud; /* Not used! */ + + /* Get the return value. */ + arg = vpi_scan(argv); + vpi_free_object(argv); + val.format = vpiIntVal; + vpi_get_value(arg, &val); + + /* Set the return value. */ + vpip_set_return_value(val.value.integer); + + /* Now finish. */ + vpi_control(vpiFinish, 1); + return 0; +} + /* * Register the function with Verilog. */ @@ -55,7 +142,6 @@ void sys_special_register(void) { s_vpi_systf_data tf_data; - /* Register the single argument functions. */ tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiIntFunc; tf_data.calltf = vvp_cpu_wordsize_calltf; @@ -64,4 +150,12 @@ void sys_special_register(void) tf_data.tfname = "$vvp_cpu_wordsize"; tf_data.user_data = 0; vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.calltf = finish_and_return_calltf; + tf_data.compiletf = finish_and_return_compiletf; + tf_data.sizetf = 0; + tf_data.tfname = "$finish_and_return"; + tf_data.user_data = 0; + vpi_register_systf(&tf_data); } diff --git a/vpi/sys_readmem.c b/vpi/sys_readmem.c index 5e2cc2b92..a1a252f38 100644 --- a/vpi/sys_readmem.c +++ b/vpi/sys_readmem.c @@ -109,7 +109,6 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name) FILE*file; unsigned addr; s_vpi_value value; - vpiHandle words; vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle item = vpi_scan(argv); @@ -283,11 +282,7 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name) } } - - words = vpi_iterate(vpiMemoryWord, mitem); - assert(words); - - item = vpi_scan(words); + item = vpi_handle_by_index(mitem,min_addr); wwid = vpi_get(vpiSize, item); /* variable that will be uses by the lexer to pass values @@ -347,9 +342,6 @@ static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name) bailout: free(value.value.vector); - - if (item) - vpi_free_object(words); free(path); fclose(file); return 0; diff --git a/vpi_user.h b/vpi_user.h index 8c93d8c2e..0087b52b5 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -563,6 +563,7 @@ extern DLLEXPORT void (*vlog_startup_routines[])(); /* Format a scalar a la %v. The str points to a 4byte character buffer. The value must be a vpiStrengthVal. */ extern void vpip_format_strength(char*str, s_vpi_value*value, unsigned bit); +extern void vpip_set_return_value(int value); EXTERN_C_END diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 65cab97f4..39663272e 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -43,6 +43,8 @@ INSTALL_DATA = @INSTALL_DATA@ RANLIB = @RANLIB@ LEX = @LEX@ YACC = @YACC@ +MAN = @MAN@ +PS2PDF = @PS2PDF@ CPPFLAGS = @ident_support@ -I. -I.. -I $(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ CXXFLAGS = -Wall @CXXFLAGS@ @@ -70,14 +72,14 @@ check: all V = vpi_modules.o vpi_callback.o vpi_const.o vpi_event.o vpi_iter.o vpi_mcd.o \ vpi_priv.o vpi_scope.o vpi_real.o vpi_signal.o vpi_tasks.o vpi_time.o \ -vpi_memory.o vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \ +vpi_vthr_vector.o vpip_bin.o vpip_hex.o vpip_oct.o \ vpip_to_dec.o vpip_format.o vvp_vpi.o O = main.o parse.o parse_misc.o lexor.o arith.o array.o bufif.o compile.o \ concat.o \ dff.o extend.o npmos.o part.o reduce.o resolv.o sfunc.o stop.o symbols.o \ ufunc.o codes.o \ -vthread.o schedule.o statistics.o tables.o udp.o vvp_net.o memory.o \ +vthread.o schedule.o statistics.o tables.o udp.o vvp_net.o \ event.o logic.o delay.o words.o $V ifeq (@WIN32@,yes) @@ -133,12 +135,20 @@ lexor.cc: $(srcdir)/lexor.lex $(LEX) -s -olexor.cc $(srcdir)/lexor.lex vvp.pdf: $(srcdir)/vvp.man - man -t $(srcdir)/vvp.man | ps2pdf - vvp.pdf + $(MAN) -t $(srcdir)/vvp.man | $(PS2PDF) - vvp.pdf -ifeq (@MING32@,yes) +ifeq (@MINGW32@,yes) +ifeq ($(MAN),none) +INSTALL_DOC = $(mandir)/man1/vvp.1 +else +ifeq ($(PS2PDF),none) +INSTALL_DOC = $(mandir)/man1/vvp.1 +else INSTALL_DOC = $(prefix)/vvp.pdf $(mandir)/man1/vvp.1 -INSTALL_DOCDIR = $(mandir)/man1 all: vvp.pdf +endif +endif +INSTALL_DOCDIR = $(mandir)/man1 else INSTALL_DOC = $(mandir)/man1/vvp.1 INSTALL_DOCDIR = $(mandir)/man1 diff --git a/vvp/array.cc b/vvp/array.cc index e57bbc375..3593bbda5 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -35,7 +35,7 @@ static symbol_table_t array_table =0; class vvp_fun_arrayport; static void array_attach_port(vvp_array_t, vvp_fun_arrayport*); -vvp_array_t array_find(char*label) +vvp_array_t array_find(const char*label) { if (array_table == 0) return 0; @@ -55,9 +55,15 @@ struct __vpiArray { unsigned array_count; struct __vpiDecConst first_addr; struct __vpiDecConst last_addr; - vpiHandle*words; + // If this is a net array, nets lists the handles. + vpiHandle*nets; + // If this is a var array, then these are used instead of nets. + vvp_vector4_t *vals; + unsigned vals_width; + struct __vpiArrayWord*vals_words; class vvp_fun_arrayport*ports_; + struct __vpiCallback *vpi_callbacks; }; struct __vpiArrayIterator { @@ -72,6 +78,36 @@ struct __vpiArrayIndex { unsigned done; }; +struct __vpiArrayVthrA { + struct __vpiHandle base; + struct __vpiArray*array; + unsigned address; +}; + +/* + * The vpiArrayWord is magic. It is used as the handle to return when + * vpi code tries to index or scan an array of variable words. The + * array word handle contains no actual data. It is just a hook for + * the vpi methods and to point to the parent. + * + * How the point to the parent works is tricky. The vpiArrayWord + * objects for an array are themselves allocated as an array. All the + * ArrayWord objects in the array have a word0 that points to the base + * of the array. Thus, the position into the array (and the index into + * the memory) is calculated by subtracting word0 from the ArrayWord + * pointer. + * + * To then get to the parent, use word0[-1].parent. + */ +struct __vpiArrayWord { + struct __vpiHandle base; + union { + struct __vpiArray*parent; + struct __vpiArrayWord*word0; + }; +}; + + static int vpi_array_get(int code, vpiHandle ref); static char*vpi_array_get_str(int code, vpiHandle ref); static vpiHandle vpi_array_get_handle(int code, vpiHandle ref); @@ -84,6 +120,14 @@ static int array_iterator_free_object(vpiHandle ref); static vpiHandle array_index_scan(vpiHandle ref, int); static int array_index_free_object(vpiHandle ref); +static int vpi_array_var_word_get(int code, vpiHandle); +static void vpi_array_var_word_get_value(vpiHandle, p_vpi_value); +static vpiHandle vpi_array_var_word_put_value(vpiHandle, p_vpi_value, int); + +static int vpi_array_vthr_A_get(int code, vpiHandle); +static void vpi_array_vthr_A_get_value(vpiHandle, p_vpi_value); +static vpiHandle vpi_array_vthr_A_put_value(vpiHandle, p_vpi_value, int); + static const struct __vpirt vpip_arraymem_rt = { vpiMemory, vpi_array_get, @@ -122,9 +166,78 @@ static const struct __vpirt vpip_array_index_rt = { array_index_free_object }; +static const struct __vpirt vpip_array_var_word_rt = { + vpiMemoryWord, + &vpi_array_var_word_get, + 0, + &vpi_array_var_word_get_value, + &vpi_array_var_word_put_value, + 0, + 0, + 0, + 0 +}; + +static const struct __vpirt vpip_array_vthr_A_rt = { + vpiMemoryWord, + &vpi_array_vthr_A_get, + 0, + &vpi_array_vthr_A_get_value, + &vpi_array_vthr_A_put_value, + 0, + 0, + 0, + 0 +}; + # define ARRAY_HANDLE(ref) (assert(ref->vpi_type->type_code==vpiMemory), \ (struct __vpiArray*)ref) +static struct __vpiArrayWord* array_var_word_from_handle(vpiHandle ref) +{ + if (ref == 0) + return 0; + if (ref->vpi_type != &vpip_array_var_word_rt) + return 0; + + return (struct __vpiArrayWord*) ref; +} + +static struct __vpiArrayVthrA* array_vthr_a_from_handle(vpiHandle ref) +{ + if (ref == 0) + return 0; + if (ref->vpi_type != &vpip_array_vthr_A_rt) + return 0; + + return (struct __vpiArrayVthrA*) ref; +} + +static void array_make_vals_words(struct __vpiArray*parent) +{ + assert(parent->vals_words == 0); + parent->vals_words = new struct __vpiArrayWord[parent->array_count + 1]; + + // Make word[-1] point to the parent. + parent->vals_words->parent = parent; + // Now point to word-0 + parent->vals_words += 1; + + struct __vpiArrayWord*words = parent->vals_words; + for (unsigned idx = 0 ; idx < parent->array_count ; idx += 1) { + words[idx].base.vpi_type = &vpip_array_var_word_rt; + words[idx].word0 = words; + } +} + +static unsigned decode_array_word_pointer(struct __vpiArrayWord*word, + struct __vpiArray*&parent) +{ + struct __vpiArrayWord*word0 = word->word0; + parent = (word0 - 1) -> parent; + return word - word0; +} + static int vpi_array_get(int code, vpiHandle ref) { struct __vpiArray*obj = ARRAY_HANDLE(ref); @@ -205,7 +318,56 @@ static vpiHandle vpi_array_index(vpiHandle ref, int index) if (index < 0) return 0; - return obj->words[index]; + if (obj->nets != 0) { + return obj->nets[index]; + } + + if (obj->vals_words == 0) + array_make_vals_words(obj); + + return &(obj->vals_words[index].base); +} + +static int vpi_array_var_word_get(int code, vpiHandle ref) +{ + struct __vpiArrayWord*obj = array_var_word_from_handle(ref); + struct __vpiArray*parent; + + assert(obj); + decode_array_word_pointer(obj, parent); + + switch (code) { + case vpiSize: + return (int) parent->vals_width; + + default: + return 0; + } +} + +static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value) +{ + struct __vpiArrayWord*obj = array_var_word_from_handle(ref); + struct __vpiArray*parent; + + assert(obj); + unsigned index = decode_array_word_pointer(obj, parent); + + vpip_vec4_get_value(parent->vals[index], parent->vals_width, + false, value); +} + +static vpiHandle vpi_array_var_word_put_value(vpiHandle ref, p_vpi_value vp, int flags) +{ + struct __vpiArrayWord*obj = array_var_word_from_handle(ref); + struct __vpiArray*parent; + + assert(obj); + unsigned index = decode_array_word_pointer(obj, parent); + + vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width); + array_set_word(parent, index, 0, val); + return ref; } # define ARRAY_ITERATOR(ref) (assert(ref->vpi_type->type_code==vpiIterator), \ @@ -220,9 +382,18 @@ static vpiHandle array_iterator_scan(vpiHandle ref, int) return 0; } - vpiHandle res = obj->array->words[obj->next]; + unsigned use_index = obj->next; obj->next += 1; - return res; + + if (obj->array->nets) + return obj->array->nets[obj->next]; + + assert(obj->array->vals); + + if (obj->array->vals_words == 0) + array_make_vals_words(obj->array); + + return &(obj->array->vals_words[use_index].base); } static int array_iterator_free_object(vpiHandle ref) @@ -271,6 +442,56 @@ static int array_index_free_object(vpiHandle ref) return 1; } +static int vpi_array_vthr_A_get(int code, vpiHandle ref) +{ + struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref); + assert(obj); + struct __vpiArray*parent = obj->array; + + switch (code) { + case vpiLineNo: + return 0; // Not implemented for now! + + case vpiSize: + assert(parent->vals); + return parent->vals_width; + + default: + return 0; + } +} +static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value) +{ + struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref); + assert(obj); + struct __vpiArray*parent = obj->array; + + assert(parent); + assert(parent->vals); + assert(obj->address < parent->array_count); + + vpip_vec4_get_value(parent->vals[obj->address], + parent->vals_width, false, value); +} + +static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int) +{ + struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref); + assert(obj); + struct __vpiArray*parent = obj->array; + + unsigned index = obj->address; + + assert(parent); + assert(obj->address < parent->array_count); + + vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width); + array_set_word(parent, index, 0, val); + + return ref; +} + + void array_set_word(vvp_array_t arr, unsigned address, unsigned part_off, @@ -279,22 +500,61 @@ void array_set_word(vvp_array_t arr, if (address >= arr->array_count) return; + if (arr->vals) { + assert(arr->nets == 0); + if (part_off != 0 || val.size() != arr->vals_width) { + if (arr->vals[address].size() == 0) + arr->vals[address] = vvp_vector4_t(arr->vals_width, BIT4_X); + if ((part_off + val.size()) > arr->vals[address].size()) { + cerr << "part_off=" << part_off + << " val.size()=" << val.size() + << " arr->vals[address].size()=" << arr->vals[address].size() + << " arr->vals_width=" << arr->vals_width << endl; + assert(0); + } + arr->vals[address].set_vec(part_off, val); + } else { + arr->vals[address] = val; + } + array_word_change(arr, address); + return; + } + + assert(arr->nets != 0); + // Select the word of the array that we affect. - vpiHandle word = arr->words[address]; + vpiHandle word = arr->nets[address]; struct __vpiSignal*vsig = vpip_signal_from_handle(word); assert(vsig); vvp_net_ptr_t ptr (vsig->node, 0); vvp_send_vec4_pv(ptr, val, part_off, val.size(), vpip_size(vsig)); + array_word_change(arr, address); } vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) { + if (arr->vals) { + assert(arr->nets == 0); + + vvp_vector4_t tmp; + if (address < arr->array_count) + tmp = arr->vals[address]; + + if (tmp.size() == 0) + tmp = vvp_vector4_t(arr->vals_width, BIT4_X); + + return tmp; + } + + assert(arr->vals == 0); + assert(arr->nets != 0); + if (address >= arr->array_count) { // Reading outside the array. Return X's but get the // width by looking at a word that we know is present. assert(arr->array_count > 0); - vpiHandle word = arr->words[0]; + vpiHandle word = arr->nets[0]; struct __vpiSignal*vsig = vpip_signal_from_handle(word); assert(vsig); vvp_fun_signal_vec*sig = dynamic_cast (vsig->node->fun); @@ -302,7 +562,7 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) return vvp_vector4_t(sig->size(), BIT4_X); } - vpiHandle word = arr->words[address]; + vpiHandle word = arr->nets[address]; struct __vpiSignal*vsig = vpip_signal_from_handle(word); assert(vsig); vvp_fun_signal_vec*sig = dynamic_cast (vsig->node->fun); @@ -332,10 +592,15 @@ static vpiHandle vpip_make_array(char*label, const char*name, vpip_make_dec_const(&obj->first_addr, first_addr); vpip_make_dec_const(&obj->last_addr, last_addr); - obj->words = (vpiHandle*)calloc(array_count, sizeof(vpiHandle)); + // Start off now knowing if we are nets or variables. + obj->nets = 0; + obj->vals = 0; + obj->vals_width = 0; + obj->vals_words = 0; // Initialize (clear) the read-ports list. obj->ports_ = 0; + obj->vpi_callbacks = 0; /* Add this symbol to the array_symbols table for later lookup. */ if (!array_table) @@ -346,19 +611,29 @@ static vpiHandle vpip_make_array(char*label, const char*name, v.ptr = obj; sym_set_value(array_table, label, v); + /* Add this into the table of VPI objects. This is used for + contexts that try to look up VPI objects in + general. (i.e. arguments to vpi_task calls.) */ + compile_vpi_symbol(label, &(obj->base)); + + /* Blindly attach to the scope as an object. */ + vpip_attach_to_current_scope(&(obj->base)); + return &(obj->base); } void array_alias_word(vvp_array_t array, unsigned long addr, vpiHandle word) { assert(addr < array->array_count); - array->words[addr] = word; + assert(array->nets); + array->nets[addr] = word; } void array_attach_word(vvp_array_t array, unsigned long addr, vpiHandle word) { assert(addr < array->array_count); - array->words[addr] = word; + assert(array->nets); + array->nets[addr] = word; if (struct __vpiSignal*sig = vpip_signal_from_handle(word)) { vvp_net_t*net = sig->node; @@ -371,33 +646,16 @@ void array_attach_word(vvp_array_t array, unsigned long addr, vpiHandle word) } } -static vpiHandle common_array_build(char*label, char*name, int last, int first) -{ - vpiHandle obj = vpip_make_array(label, name, first, last); - /* Add this into the table of VPI objects. This is used for - contexts that try to look up VPI objects in - general. (i.e. arguments to vpi_task calls.) */ - compile_vpi_symbol(label, obj); - /* Blindly attach to the scope as an object. */ - vpip_attach_to_current_scope(obj); - - return obj; -} - void compile_var_array(char*label, char*name, int last, int first, int msb, int lsb, char signed_flag) { - vpiHandle obj = common_array_build(label, name, last, first); + vpiHandle obj = vpip_make_array(label, name, first, last); struct __vpiArray*arr = ARRAY_HANDLE(obj); - vvp_array_t array = array_find(label); /* Make the words. */ - for (unsigned idx = 0 ; idx < arr->array_count ; idx += 1) { - char buf[64]; - snprintf(buf, sizeof buf, "%s_%u", label, idx); - compile_variablew(strdup(buf), array, idx, msb, lsb, signed_flag); - } + arr->vals = new vvp_vector4_t[arr->array_count]; + arr->vals_width = labs(msb-lsb) + 1; free(label); free(name); @@ -406,7 +664,7 @@ void compile_var_array(char*label, char*name, int last, int first, void compile_real_array(char*label, char*name, int last, int first, int msb, int lsb) { - vpiHandle obj = common_array_build(label, name, last, first); + vpiHandle obj = vpip_make_array(label, name, first, last); struct __vpiArray*arr = ARRAY_HANDLE(obj); vvp_array_t array = array_find(label); @@ -424,7 +682,10 @@ void compile_real_array(char*label, char*name, int last, int first, void compile_net_array(char*label, char*name, int last, int first) { - /* vpiHandle obj = */ common_array_build(label, name, last, first); + vpiHandle obj = vpip_make_array(label, name, first, last); + + struct __vpiArray*arr = ARRAY_HANDLE(obj); + arr->nets = (vpiHandle*)calloc(arr->array_count, sizeof(vpiHandle)); free(label); free(name); @@ -434,6 +695,7 @@ class vvp_fun_arrayport : public vvp_net_fun_t { public: explicit vvp_fun_arrayport(vvp_array_t mem, vvp_net_t*net); + explicit vvp_fun_arrayport(vvp_array_t mem, vvp_net_t*net, long addr); ~vvp_fun_arrayport(); void check_word_change(unsigned long addr); @@ -456,6 +718,12 @@ vvp_fun_arrayport::vvp_fun_arrayport(vvp_array_t mem, vvp_net_t*net) next_ = 0; } +vvp_fun_arrayport::vvp_fun_arrayport(vvp_array_t mem, vvp_net_t*net, long addr) +: arr_(mem), net_(net), addr_(addr) +{ + next_ = 0; +} + vvp_fun_arrayport::~vvp_fun_arrayport() { } @@ -499,26 +767,121 @@ void array_word_change(vvp_array_t array, unsigned long addr) { for (vvp_fun_arrayport*cur = array->ports_; cur; cur = cur->next_) cur->check_word_change(addr); + + // Run callbacks attatched to the array itself. + struct __vpiCallback *next = array->vpi_callbacks; + struct __vpiCallback *prev = 0; + + while (next) { + struct __vpiCallback*cur = next; + next = cur->next; + + // Skip callbacks for callbacks not for me. + if (cur->extra_data != (long)addr) { + prev = cur; + continue; + } + + if (cur->cb_data.cb_rtn != 0) { + if (cur->cb_data.value) + vpip_vec4_get_value(array->vals[addr], array->vals_width, + false, cur->cb_data.value); + + callback_execute(cur); + prev = cur; + + } else if (prev == 0) { + + array->vpi_callbacks = next; + cur->next = 0; + delete_vpi_callback(cur); + + } else { + assert(prev->next == cur); + prev->next = next; + cur->next = 0; + delete_vpi_callback(cur); + } + } +} + +class array_port_resolv_list_t : public resolv_list_s { + + public: + explicit array_port_resolv_list_t(char*label) : resolv_list_s(label) { } + + vvp_net_t*ptr; + bool use_addr; + long addr; + bool resolve(bool mes); + + private: +}; + +bool array_port_resolv_list_t::resolve(bool mes) +{ + vvp_array_t mem = array_find(label()); + if (mem == 0) { + assert(mem || !mes); + return false; + } + + vvp_fun_arrayport*fun; + if (use_addr) + fun = new vvp_fun_arrayport(mem, ptr, addr); + else + fun = new vvp_fun_arrayport(mem, ptr); + ptr->fun = fun; + + array_attach_port(mem, fun); + + return true; +} + +void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle obj) +{ + struct __vpiArray*parent = 0; + if (struct __vpiArrayWord*word = array_var_word_from_handle(obj)) { + unsigned addr = decode_array_word_pointer(word, parent); + cb->extra_data = addr; + + } else if (struct __vpiArrayVthrA*word = array_vthr_a_from_handle(obj)) { + parent = word->array; + cb->extra_data = word->address; + } + + assert(parent); + cb->next = parent->vpi_callbacks; + parent->vpi_callbacks = cb; } void compile_array_port(char*label, char*array, char*addr) { - vvp_array_t mem = array_find(array); - assert(mem); - - vvp_net_t*ptr = new vvp_net_t; - vvp_fun_arrayport*fun = new vvp_fun_arrayport(mem, ptr); - ptr->fun = fun; - - define_functor_symbol(label, ptr); - // Connect the port-0 input as the address. - input_connect(ptr, 0, addr); - - array_attach_port(mem, fun); + array_port_resolv_list_t*resolv_mem + = new array_port_resolv_list_t(array); + resolv_mem->ptr = new vvp_net_t; + resolv_mem->use_addr = false; + define_functor_symbol(label, resolv_mem->ptr); free(label); - free(array); - // The input_connect arranges for the array string to be free'ed. + // Connect the port-0 input as the address. + input_connect(resolv_mem->ptr, 0, addr); + + resolv_submit(resolv_mem); +} + +void compile_array_port(char*label, char*array, long addr) +{ + array_port_resolv_list_t*resolv_mem + = new array_port_resolv_list_t(array); + + resolv_mem->ptr = new vvp_net_t; + resolv_mem->use_addr = true; + resolv_mem->addr = addr; + define_functor_symbol(label, resolv_mem->ptr); + free(label); + + resolv_submit(resolv_mem); } void compile_array_alias(char*label, char*name, char*src) @@ -539,7 +902,8 @@ void compile_array_alias(char*label, char*name, char*src) vpip_make_dec_const(&obj->last_addr, mem->last_addr.value); // Share the words with the source array. - obj->words = mem->words; + obj->nets = mem->nets; + obj->vals = mem->vals; obj->ports_ = 0; @@ -556,3 +920,19 @@ void compile_array_alias(char*label, char*name, char*src) free(name); free(src); } + +vpiHandle vpip_make_vthr_A(char*label, unsigned addr) +{ + struct __vpiArrayVthrA*obj = (struct __vpiArrayVthrA*) + malloc(sizeof (struct __vpiArrayVthrA)); + + obj->base.vpi_type = &vpip_array_vthr_A_rt; + + obj->array = array_find(label); + assert(obj->array); + + obj->address = addr; + assert(addr < obj->array->array_count); + + return &(obj->base); +} diff --git a/vvp/array.h b/vvp/array.h index f7ad35f70..e67832761 100644 --- a/vvp/array.h +++ b/vvp/array.h @@ -28,7 +28,7 @@ typedef struct __vpiArray* vvp_array_t; * This function tries to find the array (by label) in the global * table of all the arrays in the design. */ -extern vvp_array_t array_find(char*label); +extern vvp_array_t array_find(const char*label); extern vpiHandle array_index_iterate(int code, vpiHandle ref); extern void array_word_change(vvp_array_t array, unsigned long addr); @@ -45,6 +45,11 @@ extern void array_set_word(vvp_array_t arr, extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned adddress); +/* VPI hooks */ + +extern void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle word); + +/* Compile hooks */ extern void compile_variablew(char*label, vvp_array_t array, unsigned long array_addr, int msb, int lsb, char signed_flag); diff --git a/vvp/codes.h b/vvp/codes.h index cb033f16f..0e93f72de 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -97,7 +97,6 @@ extern bool of_JOIN(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AV(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVP0(vthread_t thr, vvp_code_t code); extern bool of_LOAD_AVX_P(vthread_t thr, vvp_code_t code); -extern bool of_LOAD_MV(vthread_t thr, vvp_code_t code); extern bool of_LOAD_NX(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code); extern bool of_LOAD_VP0(vthread_t thr, vvp_code_t code); @@ -127,7 +126,6 @@ extern bool of_RELEASE_NET(vthread_t thr, vvp_code_t code); extern bool of_RELEASE_REG(vthread_t thr, vvp_code_t code); extern bool of_RELEASE_WR(vthread_t thr, vvp_code_t code); extern bool of_SET_AV(vthread_t thr, vvp_code_t code); -extern bool of_SET_MV(vthread_t thr, vvp_code_t code); extern bool of_SET_VEC(vthread_t thr, vvp_code_t code); extern bool of_SET_WORDR(vthread_t thr, vvp_code_t code); extern bool of_SET_X0(vthread_t thr, vvp_code_t code); @@ -162,7 +160,6 @@ struct vvp_code_s { unsigned long number; vvp_net_t *net; vvp_code_t cptr; - vvp_memory_t mem; vvp_array_t array; struct __vpiHandle*handle; struct __vpiScope*scope; diff --git a/vvp/compile.cc b/vvp/compile.cc index 5d6e819a8..d2e1c96d8 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -22,7 +22,6 @@ # include "logic.h" # include "resolv.h" # include "udp.h" -# include "memory.h" # include "symbols.h" # include "codes.h" # include "schedule.h" @@ -67,8 +66,6 @@ enum operand_e { OA_FUNC_PTR, /* The operand is a second functor pointer */ OA_FUNC_PTR2, - /* The operand is a pointer to a memory */ - OA_MEM_PTR, /* The operand is a VPI handle */ OA_VPI_PTR, }; @@ -90,7 +87,6 @@ const static struct opcode_table_s opcode_table[] = { { "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%assign/av",of_ASSIGN_AV,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} }, { "%assign/av/d",of_ASSIGN_AVD,3,{OA_ARR_PTR,OA_BIT1, OA_BIT2} }, - { "%assign/mv",of_ASSIGN_MV,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} }, { "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%assign/v0/d",of_ASSIGN_V0D,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} }, { "%assign/v0/x1",of_ASSIGN_V0X1,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} }, @@ -144,7 +140,6 @@ const static struct opcode_table_s opcode_table[] = { { "%load/av",of_LOAD_AV,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avp0",of_LOAD_AVP0,3, {OA_BIT1, OA_ARR_PTR, OA_BIT2} }, { "%load/avx.p",of_LOAD_AVX_P,3,{OA_BIT1, OA_ARR_PTR, OA_BIT2} }, - { "%load/mv",of_LOAD_MV,3, {OA_BIT1, OA_MEM_PTR, OA_BIT2} }, { "%load/nx",of_LOAD_NX,3, {OA_BIT1, OA_VPI_PTR, OA_BIT2} }, { "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, { "%load/vp0",of_LOAD_VP0,3,{OA_BIT1, OA_FUNC_PTR, OA_BIT2} }, @@ -174,7 +169,6 @@ const static struct opcode_table_s opcode_table[] = { { "%release/reg",of_RELEASE_REG,3,{OA_FUNC_PTR,OA_BIT1,OA_BIT2} }, { "%release/wr",of_RELEASE_WR,2,{OA_FUNC_PTR,OA_BIT1,OA_NONE} }, { "%set/av", of_SET_AV, 3, {OA_ARR_PTR, OA_BIT1, OA_BIT2} }, - { "%set/mv", of_SET_MV, 3, {OA_MEM_PTR, OA_BIT1, OA_BIT2} }, { "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, { "%set/wr", of_SET_WORDR,2,{OA_VPI_PTR, OA_BIT1, OA_NONE} }, { "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} }, @@ -321,13 +315,12 @@ vvp_net_t* vvp_net_lookup(const char*label) */ static struct resolv_list_s*resolv_list = 0; -struct resolv_list_s { - virtual ~resolv_list_s() { } - struct resolv_list_s*next; - virtual bool resolve(bool mes = false) = 0; -}; +resolv_list_s::~resolv_list_s() +{ + free(label_); +} -static void resolv_submit(struct resolv_list_s*cur) +void resolv_submit(struct resolv_list_s*cur) { if (cur->resolve()) { delete cur; @@ -346,8 +339,8 @@ static void resolv_submit(struct resolv_list_s*cur) * put net->port[port] into the fan-out list for that node. */ struct vvp_net_resolv_list_s: public resolv_list_s { - // node to locate - char*source; + + vvp_net_resolv_list_s(char*l) : resolv_list_s(l) { } // port to be driven by the located node. vvp_net_ptr_t port; virtual bool resolve(bool mes); @@ -355,20 +348,18 @@ struct vvp_net_resolv_list_s: public resolv_list_s { bool vvp_net_resolv_list_s::resolve(bool mes) { - vvp_net_t*tmp = vvp_net_lookup(source); + vvp_net_t*tmp = vvp_net_lookup(label()); if (tmp) { // Link the input port to the located output. vvp_net_t*net = port.ptr(); net->port[port.port()] = tmp->out; tmp->out = port; - - free(source); return true; } if (mes) - fprintf(stderr, "unresolved vvp_net reference: %s\n", source); + fprintf(stderr, "unresolved vvp_net reference: %s\n", label()); return false; } @@ -376,10 +367,8 @@ bool vvp_net_resolv_list_s::resolve(bool mes) inline static void postpone_functor_input(vvp_net_ptr_t port, char*lab) { - struct vvp_net_resolv_list_s*res = new struct vvp_net_resolv_list_s; - + struct vvp_net_resolv_list_s*res = new struct vvp_net_resolv_list_s(lab); res->port = port; - res->source = lab; resolv_submit(res); } @@ -390,24 +379,22 @@ void postpone_functor_input(vvp_net_ptr_t port, char*lab) */ struct functor_gen_resolv_list_s: public resolv_list_s { - char*source; + explicit functor_gen_resolv_list_s(char*txt) : resolv_list_s(txt) { } vvp_net_t**ref; virtual bool resolve(bool mes); }; bool functor_gen_resolv_list_s::resolve(bool mes) { - vvp_net_t*tmp = vvp_net_lookup(source); + vvp_net_t*tmp = vvp_net_lookup(label()); if (tmp) { *ref = tmp; - - free(source); return true; } if (mes) - fprintf(stderr, "unresolved functor reference: %s\n", source); + fprintf(stderr, "unresolved functor reference: %s\n", label()); return false; } @@ -415,10 +402,9 @@ bool functor_gen_resolv_list_s::resolve(bool mes) void functor_ref_lookup(vvp_net_t**ref, char*lab) { struct functor_gen_resolv_list_s*res = - new struct functor_gen_resolv_list_s; + new struct functor_gen_resolv_list_s(lab); res->ref = ref; - res->source = lab; resolv_submit(res); } @@ -428,27 +414,27 @@ void functor_ref_lookup(vvp_net_t**ref, char*lab) */ struct vpi_handle_resolv_list_s: public resolv_list_s { - vpiHandle *handle; - char *label; + explicit vpi_handle_resolv_list_s(char*label) : resolv_list_s(label) { } virtual bool resolve(bool mes); + vpiHandle *handle; }; bool vpi_handle_resolv_list_s::resolve(bool mes) { - symbol_value_t val = sym_get_value(sym_vpi, label); + symbol_value_t val = sym_get_value(sym_vpi, label()); if (!val.ptr) { // check for thread vector T unsigned base, wid; unsigned n = 0; char ss[32]; - if (2 <= sscanf(label, "T<%u,%u>%n", &base, &wid, &n) - && n == strlen(label)) { + if (2 <= sscanf(label(), "T<%u,%u>%n", &base, &wid, &n) + && n == strlen(label())) { val.ptr = vpip_make_vthr_vector(base, wid, false); - sym_set_value(sym_vpi, label, val); + sym_set_value(sym_vpi, label(), val); - } else if (3 <= sscanf(label, "T<%u,%u,%[su]>%n", &base, + } else if (3 <= sscanf(label(), "T<%u,%u,%[su]>%n", &base, &wid, ss, &n) - && n == strlen(label)) { + && n == strlen(label())) { bool signed_flag = false; for (char*fp = ss ; *fp ; fp += 1) switch (*fp) { @@ -463,13 +449,13 @@ bool vpi_handle_resolv_list_s::resolve(bool mes) } val.ptr = vpip_make_vthr_vector(base, wid, signed_flag); - sym_set_value(sym_vpi, label, val); + sym_set_value(sym_vpi, label(), val); - } else if (2 == sscanf(label, "W<%u,%[r]>%n", &base, ss, &n) - && n == strlen(label)) { + } else if (2 == sscanf(label(), "W<%u,%[r]>%n", &base, ss, &n) + && n == strlen(label())) { val.ptr = vpip_make_vthr_word(base, ss); - sym_set_value(sym_vpi, label, val); + sym_set_value(sym_vpi, label(), val); } } @@ -480,12 +466,11 @@ bool vpi_handle_resolv_list_s::resolve(bool mes) if (val.ptr) { *handle = (vpiHandle) val.ptr; - free(label); return true; } if (mes) - fprintf(stderr, "unresolved vpi name lookup: %s\n", label); + fprintf(stderr, "unresolved vpi name lookup: %s\n", label()); return false; } @@ -517,10 +502,9 @@ void compile_vpi_lookup(vpiHandle *handle, char*label) } struct vpi_handle_resolv_list_s*res - = new struct vpi_handle_resolv_list_s; + = new struct vpi_handle_resolv_list_s(label); res->handle = handle; - res->label = label; resolv_submit(res); } @@ -529,27 +513,24 @@ void compile_vpi_lookup(vpiHandle *handle, char*label) */ struct code_label_resolv_list_s: public resolv_list_s { + code_label_resolv_list_s(char*label) : resolv_list_s(label) { } struct vvp_code_s *code; - char *label; virtual bool resolve(bool mes); }; bool code_label_resolv_list_s::resolve(bool mes) { - symbol_value_t val = sym_get_value(sym_codespace, label); + symbol_value_t val = sym_get_value(sym_codespace, label()); if (val.num) { if (code->opcode == of_FORK) code->cptr2 = reinterpret_cast(val.ptr); else code->cptr = reinterpret_cast(val.ptr); - free(label); return true; } if (mes) - fprintf(stderr, - "unresolved code label: %s\n", - label); + fprintf(stderr, "unresolved code label: %s\n", label()); return false; } @@ -557,75 +538,38 @@ bool code_label_resolv_list_s::resolve(bool mes) void code_label_lookup(struct vvp_code_s *code, char *label) { struct code_label_resolv_list_s *res - = new struct code_label_resolv_list_s; + = new struct code_label_resolv_list_s(label); res->code = code; - res->label = label; resolv_submit(res); } -/* - * Lookup memories. - */ -struct memory_resolv_list_s: public resolv_list_s { +struct code_array_resolv_list_s: public resolv_list_s { + code_array_resolv_list_s(char*label) : resolv_list_s(label) { } struct vvp_code_s *code; - char *label; virtual bool resolve(bool mes); }; -bool memory_resolv_list_s::resolve(bool mes) +bool code_array_resolv_list_s::resolve(bool mes) { - code->mem = memory_find(label); - if (code->mem != 0) { - free(label); - return true; - } - - if (mes) - fprintf(stderr, "Memory unresolved: %s\n", label); - - return false; -} - -static void compile_mem_lookup(struct vvp_code_s *code, char *label) -{ - struct memory_resolv_list_s *res - = new struct memory_resolv_list_s; - - res->code = code; - res->label = label; - - resolv_submit(res); -} - -struct array_resolv_list_s: public resolv_list_s { - struct vvp_code_s *code; - char *label; - virtual bool resolve(bool mes); -}; - -bool array_resolv_list_s::resolve(bool mes) -{ - code->array = array_find(label); + code->array = array_find(label()); if (code->array != 0) { - free(label); return true; } if (mes) - fprintf(stderr, "Array unresolved: %s\n", label); + fprintf(stderr, "Array unresolved: %s\n", label()); return false; } static void compile_array_lookup(struct vvp_code_s*code, char*label) { - struct array_resolv_list_s *res - = new struct array_resolv_list_s; + struct code_array_resolv_list_s *res + = new struct code_array_resolv_list_s(label); res->code = code; - res->label = label; resolv_submit(res); } @@ -1522,90 +1466,6 @@ char **compile_udp_table(char **table, char *row) return table; } -/* - * Take the detailed parse items from a .mem statement and generate - * the necessary internal structures. - * - *