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 <steve@icarus.com>
This commit is contained in:
parent
0d9ed65e8c
commit
5c69e243ac
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -680,66 +680,6 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
|||
return strdup("C<z>");
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue