From 5c69e243acbb99abe52c23fbb077c8cddf6e54c7 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 31 Oct 2007 21:45:34 -0700 Subject: [PATCH] Put modpaths in correct scope. Modpaths need to be in the proper scope in order to be available to vpi functions. The code generator manages that by writing the modpath records with scope switch functions. Batch the modpath records at the end of the structural stuff so that the scope switching doesn't cause trouble. Also seperate the modpath code into its own source file. Signed-off-by: Stephen Williams --- tgt-vvp/Makefile.in | 2 +- tgt-vvp/modpath.c | 123 +++++++++++++++++++++++++++++++++++++++ tgt-vvp/vvp.c | 4 ++ tgt-vvp/vvp_priv.h | 138 +++++--------------------------------------- tgt-vvp/vvp_scope.c | 64 +------------------- 5 files changed, 144 insertions(+), 187 deletions(-) create mode 100644 tgt-vvp/modpath.c diff --git a/tgt-vvp/Makefile.in b/tgt-vvp/Makefile.in index 399e033a2..c9b6b5098 100644 --- a/tgt-vvp/Makefile.in +++ b/tgt-vvp/Makefile.in @@ -52,7 +52,7 @@ dep: mv $*.d dep O = vvp.o draw_mux.o draw_ufunc.o draw_vpi.o eval_bool.o eval_expr.o \ -eval_real.o vector.o \ +eval_real.o modpath.o vector.o \ vvp_process.o vvp_scope.o ifeq (@WIN32@,yes) diff --git a/tgt-vvp/modpath.c b/tgt-vvp/modpath.c new file mode 100644 index 000000000..ba9f80819 --- /dev/null +++ b/tgt-vvp/modpath.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2007 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 + */ + +# include "vvp_priv.h" +# include +# include +# include + +/* +* Draw a .modpath record. The label is the label to use for this +* record. The driver is the label of the net that feeds into the +* modpath device. (Note that there is only 1 driver.) The path_sig is +* the signal that is the output of this modpath. From that signal we +* can find all the modpath source nodes to generate the complete +* modpath record. +*/ +static void draw_modpath_record(const char*label, const char*driver, + ivl_signal_t path_sig) +{ + unsigned idx; + typedef const char*ccharp; + ccharp*src_drivers; + ccharp*con_drivers; + + src_drivers = calloc(ivl_signal_npath(path_sig), sizeof(ccharp)); + con_drivers = calloc(ivl_signal_npath(path_sig), sizeof(ccharp)); + for (idx = 0 ; idx < ivl_signal_npath(path_sig) ; idx += 1) { + ivl_delaypath_t path = ivl_signal_path(path_sig, idx); + ivl_nexus_t src = ivl_path_source(path); + ivl_nexus_t con = ivl_path_condit(path); + + src_drivers[idx] = draw_net_input(src); + + if (con) con_drivers[idx] = draw_net_input(con); + else con_drivers[idx] = 0; + } + + fprintf(vvp_out, " .scope S_%p;\n", ivl_path_scope(ivl_signal_path(path_sig,0))); + fprintf(vvp_out, "%s .modpath %s", label, driver); + + for (idx = 0 ; idx < ivl_signal_npath(path_sig); idx += 1) { + ivl_delaypath_t path = ivl_signal_path(path_sig, idx); + int ppos = ivl_path_source_posedge(path); + int pneg = ivl_path_source_negedge(path); + const char*edge = ppos? " +" : pneg ? " -" : ""; + fprintf(vvp_out, ",\n %s%s", src_drivers[idx], edge); + fprintf(vvp_out, + " (%"PRIu64",%"PRIu64",%"PRIu64 + ", %"PRIu64",%"PRIu64",%"PRIu64 + ", %"PRIu64",%"PRIu64",%"PRIu64 + ", %"PRIu64",%"PRIu64",%"PRIu64, + ivl_path_delay(path, IVL_PE_01), + ivl_path_delay(path, IVL_PE_10), + ivl_path_delay(path, IVL_PE_0z), + ivl_path_delay(path, IVL_PE_z1), + ivl_path_delay(path, IVL_PE_1z), + ivl_path_delay(path, IVL_PE_z0), + ivl_path_delay(path, IVL_PE_0x), + ivl_path_delay(path, IVL_PE_x1), + ivl_path_delay(path, IVL_PE_1x), + ivl_path_delay(path, IVL_PE_x0), + ivl_path_delay(path, IVL_PE_xz), + ivl_path_delay(path, IVL_PE_zx)); + + if (con_drivers[idx]) { + fprintf(vvp_out, " ? %s", con_drivers[idx]); + } + + fprintf(vvp_out, ")"); + } + + fprintf(vvp_out, ";\n"); + + free(src_drivers); + free(con_drivers); +} + +struct modpath_item { + ivl_signal_t path_sig; + char*drive_label; + struct modpath_item*next; +}; + +static struct modpath_item*modpath_list = 0; + +void draw_modpath(ivl_signal_t path_sig, char*drive_label) +{ + struct modpath_item*cur = calloc(1, sizeof(struct modpath_item)); + cur->path_sig = path_sig; + cur->drive_label = drive_label; + cur->next = modpath_list; + modpath_list = cur; +} + +void cleanup_modpath(void) +{ + while (modpath_list) { + struct modpath_item*cur = modpath_list; + modpath_list = cur->next; + + char modpath_label[64]; + snprintf(modpath_label, sizeof modpath_label, "V_%p/m", cur->path_sig); + draw_modpath_record(modpath_label, cur->drive_label, cur->path_sig); + free(cur->drive_label); + free(cur); + } +} diff --git a/tgt-vvp/vvp.c b/tgt-vvp/vvp.c index ef714e2fb..597e171bd 100644 --- a/tgt-vvp/vvp.c +++ b/tgt-vvp/vvp.c @@ -95,10 +95,14 @@ int target_design(ivl_design_t des) draw_module_declarations(des); + /* This causes all structural records to be drawn. */ ivl_design_roots(des, &roots, &nroots); for (i = 0; i < nroots; i++) draw_scope(roots[i], 0); + /* Finish up any modpaths that are not yet emitted. */ + cleanup_modpath(); + rc = ivl_design_process(des, draw_process, 0); fclose(vvp_out); diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 69cf61e4e..02a94b9cb 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -18,9 +18,6 @@ * 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: vvp_priv.h,v 1.43 2007/02/26 19:49:50 steve Exp $" -#endif # include "vvp_config.h" # include "ivl_target.h" @@ -69,6 +66,20 @@ extern void draw_lpm_mux(ivl_lpm_t net); extern struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid); extern int draw_ufunc_real(ivl_expr_t exp); +/* + * modpath.c symbols. + * + * draw_modpath arranges for a .modpath record to be written out. + * + * cleanup_modpath() cleans up any pending .modpath records that may + * have been scheduled by draw_modpath() but not yet writte. + * + * Note: draw_modpath drive_label must be malloc'ed by the + * caller. This function will free the string sometime in the future. + */ +extern void draw_modpath(ivl_signal_t path_sig, char*drive_label); +extern void cleanup_modpath(void); + /* * This function draws the execution of a vpi_call statement, along * with the tricky handling of arguments. If this is called with a @@ -242,125 +253,4 @@ extern void clr_word(int idx); extern unsigned local_count; extern unsigned thread_count; -/* - * $Log: vvp_priv.h,v $ - * Revision 1.43 2007/02/26 19:49:50 steve - * Spelling fixes (larry doolittle) - * - * Revision 1.42 2007/01/17 04:39:18 steve - * Remove dead code related to memories. - * - * Revision 1.41 2007/01/16 05:44:16 steve - * Major rework of array handling. Memories are replaced with the - * more general concept of arrays. The NetMemory and NetEMemory - * classes are removed from the ivl core program, and the IVL_LPM_RAM - * lpm type is removed from the ivl_target API. - * - * Revision 1.40 2006/02/02 02:43:59 steve - * Allow part selects of memory words in l-values. - * - * Revision 1.39 2005/10/12 17:26:17 steve - * MUX nodes get inputs from nets, not from net inputs, - * Detect and draw alias nodes to reduce net size and - * handle force confusion. - * - * Revision 1.38 2005/10/11 18:30:50 steve - * Remove obsolete vvp_memory_label function. - * - * Revision 1.37 2005/10/10 04:16:13 steve - * Remove dead dram_input_from_net and lpm_inputs_a_b - * - * Revision 1.36 2005/09/17 01:01:00 steve - * More robust use of precalculated expressions, and - * Separate lookaside for written variables that can - * also be reused. - * - * Revision 1.35 2005/09/15 02:50:13 steve - * Preserve precalculated expressions when possible. - * - * Revision 1.34 2005/09/14 02:53:15 steve - * Support bool expressions and compares handle them optimally. - * - * Revision 1.33 2005/09/01 04:11:37 steve - * Generate code to handle real valued muxes. - * - * Revision 1.32 2005/08/06 17:58:16 steve - * Implement bi-directional part selects. - * - * Revision 1.31 2005/07/13 04:52:31 steve - * Handle functions with real values. - * - * Revision 1.30 2005/07/11 16:56:51 steve - * Remove NetVariable and ivl_variable_t structures. - * - * Revision 1.29 2004/12/11 02:31:28 steve - * Rework of internals to carry vectors through nexus instead - * of single bits. Make the ivl, tgt-vvp and vvp initial changes - * down this path. - * - * Revision 1.28 2004/01/20 21:00:47 steve - * Isolate configure from containing config.h - * - * Revision 1.27 2003/06/17 19:17:42 steve - * Remove short int restrictions from vvp opcodes. - * - * Revision 1.26 2003/06/05 04:18:50 steve - * Better width testing for thread vector allocation. - * - * Revision 1.25 2003/03/15 04:45:18 steve - * Allow real-valued vpi functions to have arguments. - * - * 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. - * - * 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. - * - * Revision 1.20 2002/09/13 03:12:50 steve - * Optimize ==1 when in context where x vs z doesnt matter. - * - * Revision 1.19 2002/08/27 05:39:57 steve - * Fix l-value indexing of memories and vectors so that - * an unknown (x) index causes so cell to be addresses. - * - * Fix tangling of label identifiers in the fork-join - * code generator. - * - * Revision 1.18 2002/08/12 01:35:04 steve - * conditional ident string using autoconfig. - * - * Revision 1.17 2002/08/04 18:28:15 steve - * Do not use hierarchical names of memories to - * generate vvp labels. -tdll target does not - * used hierarchical name string to look up the - * memory objects in the design. - * - * Revision 1.16 2002/08/03 22:30:48 steve - * Eliminate use of ivl_signal_name for signal labels. - * - * Revision 1.15 2002/07/08 04:04:07 steve - * Generate code for wide muxes. - * - * Revision 1.14 2002/06/02 18:57:17 steve - * Generate %cmpi/u where appropriate. - * - * Revision 1.13 2002/04/22 02:41:30 steve - * Reduce the while loop expression if needed. - * - * Revision 1.12 2001/11/01 04:26:57 steve - * Generate code for deassign and cassign. - * - * Revision 1.11 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) - */ #endif diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 026c70816..45cbed5ae 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -680,66 +680,6 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) return strdup("C"); } -static void draw_modpath(const char*label, const char*driver, - ivl_signal_t path_sig) -{ - unsigned idx; - typedef const char*ccharp; - ccharp*src_drivers; - ccharp*con_drivers; - - src_drivers = calloc(ivl_signal_npath(path_sig), sizeof(ccharp)); - con_drivers = calloc(ivl_signal_npath(path_sig), sizeof(ccharp)); - for (idx = 0 ; idx < ivl_signal_npath(path_sig) ; idx += 1) { - ivl_delaypath_t path = ivl_signal_path(path_sig, idx); - ivl_nexus_t src = ivl_path_source(path); - ivl_nexus_t con = ivl_path_condit(path); - - src_drivers[idx] = draw_net_input(src); - - if (con) con_drivers[idx] = draw_net_input(con); - else con_drivers[idx] = 0; - } - - fprintf(vvp_out, "%s .modpath %s", label, driver); - - for (idx = 0 ; idx < ivl_signal_npath(path_sig); idx += 1) { - ivl_delaypath_t path = ivl_signal_path(path_sig, idx); - int ppos = ivl_path_source_posedge(path); - int pneg = ivl_path_source_negedge(path); - const char*edge = ppos? " +" : pneg ? " -" : ""; - fprintf(vvp_out, ",\n %s%s", src_drivers[idx], edge); - fprintf(vvp_out, - " (%"PRIu64",%"PRIu64",%"PRIu64 - ", %"PRIu64",%"PRIu64",%"PRIu64 - ", %"PRIu64",%"PRIu64",%"PRIu64 - ", %"PRIu64",%"PRIu64",%"PRIu64, - ivl_path_delay(path, IVL_PE_01), - ivl_path_delay(path, IVL_PE_10), - ivl_path_delay(path, IVL_PE_0z), - ivl_path_delay(path, IVL_PE_z1), - ivl_path_delay(path, IVL_PE_1z), - ivl_path_delay(path, IVL_PE_z0), - ivl_path_delay(path, IVL_PE_0x), - ivl_path_delay(path, IVL_PE_x1), - ivl_path_delay(path, IVL_PE_1x), - ivl_path_delay(path, IVL_PE_x0), - ivl_path_delay(path, IVL_PE_xz), - ivl_path_delay(path, IVL_PE_zx)); - - if (con_drivers[idx]) { - fprintf(vvp_out, " ? %s", con_drivers[idx]); - } - - fprintf(vvp_out, ")"); - } - - fprintf(vvp_out, ";\n"); - - free(src_drivers); - free(con_drivers); -} - static int nexus_drive_is_strength_aware(ivl_nexus_ptr_t nptr) { if (ivl_nexus_ptr_drive0(nptr) != IVL_DR_STRONG) @@ -908,9 +848,9 @@ static char* draw_net_input_x(ivl_nexus_t nex, char modpath_label[64]; snprintf(modpath_label, sizeof modpath_label, "V_%p/m", path_sig); - draw_modpath(modpath_label, nex_str, path_sig); nex_private = strdup(modpath_label); - free(nex_str); + draw_modpath(path_sig, nex_str); + } else { nex_private = draw_net_input_drive(nex, drivers[0]); }