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]); }