Add a check for one real driver and rework the uwire check.

At the moment we only support one real driver. This patch adds a
combined error routine for a uwire or a real net with multiple
drivers. We display the top level net in the hierarchy. It also
reworks the nexus data_type calculation.
This commit is contained in:
Cary R 2010-11-16 17:51:53 -08:00 committed by Stephen Williams
parent bebdcd5adf
commit dba157600c
1 changed files with 86 additions and 18 deletions

View File

@ -58,16 +58,30 @@ static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex)
static ivl_variable_type_t signal_data_type_of_nexus(ivl_nexus_t nex)
{
unsigned idx;
ivl_variable_type_t out = IVL_VT_NO_TYPE;
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_variable_type_t vtype;
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
if (sig == 0) continue;
return ivl_signal_data_type(sig);
vtype = ivl_signal_data_type(sig);
if (out == IVL_VT_NO_TYPE && vtype == IVL_VT_BOOL) {
out = vtype;
continue;
}
if (out != IVL_VT_LOGIC && vtype == IVL_VT_LOGIC) {
out = vtype;
continue;
}
if (vtype == IVL_VT_REAL) {
out = vtype;
break;
}
}
return IVL_VT_NO_TYPE;
return out;
}
static void draw_C4_repeated_constant(char bit_char, unsigned width)
@ -537,6 +551,70 @@ static char* draw_island_port(ivl_island_t island, int island_input_flag,
}
}
/*
* This routine is called to display an error message when a uwire or
* wire real has multiple drivers.
*/
typedef enum mdriver_type_e {
MDRV_UWIRE = 0,
MDRV_REAL = 1
} mdriver_type_t;
static void display_multi_driver_error(ivl_nexus_t nex, unsigned ndrivers,
mdriver_type_t type)
{
unsigned idx;
unsigned scope_len = -1;
ivl_signal_t sig = 0;
/* Find the signal. */
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
ivl_signal_t tsig = ivl_nexus_ptr_sig(ptr);
if (tsig != 0) {
ivl_scope_t scope;
unsigned len;
if (ivl_signal_local(tsig)) continue;
/* If this is not a local signal then find the signal
* that has the shortest scope (is the furthest up
* the hierarchy). */
scope = ivl_signal_scope(tsig);
assert(scope);
len = strlen(ivl_scope_name(scope));
if (len < scope_len) {
scope_len = len;
sig = tsig;
}
}
}
assert(sig);
fprintf(stderr, "%s:%u: vvp.tgt error: ",
ivl_signal_file(sig), ivl_signal_lineno(sig));
switch (type) {
case MDRV_UWIRE:
if (ivl_signal_type(sig) != IVL_SIT_UWIRE) {
fprintf(stderr, "(implicit) ");
}
fprintf(stderr, "uwire");
break;
case MDRV_REAL:
assert(ivl_signal_type(sig) == IVL_SIT_TRI);
if (ivl_signal_data_type(sig) != IVL_VT_REAL) {
fprintf(stderr, "(implicit) ");
}
fprintf(stderr, "wire real");
break;
default:
assert(0);;
}
fprintf(stderr, " \"%s\" must have a single driver, found (%u).\n",
ivl_signal_basename(sig), ndrivers);
vvp_errors += 1;
}
/*
* This function draws the input to a net into a string. What that
* means is that it returns a static string that can be used to
@ -711,22 +789,7 @@ static void draw_net_input_x(ivl_nexus_t nex,
/* A uwire is a tri with only one driver. */
if (res == IVL_SIT_UWIRE) {
if (ndrivers > 1) {
unsigned uidx;
ivl_signal_t usig = 0;
/* Find the uwire signal. */
for (uidx = 0 ; uidx < ivl_nexus_ptrs(nex) ; uidx += 1) {
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, uidx);
usig = ivl_nexus_ptr_sig(ptr);
if (usig != 0) break;
}
assert(usig);
fprintf(stderr, "%s:%u: vvp.tgt error: uwire \"%s\" must "
"have a single driver, found (%u).\n",
ivl_signal_file(usig),
ivl_signal_lineno(usig),
ivl_signal_basename(usig), ndrivers);
vvp_errors += 1;
display_multi_driver_error(nex, ndrivers, MDRV_UWIRE);
}
res = IVL_SIT_TRI;
}
@ -757,6 +820,11 @@ static void draw_net_input_x(ivl_nexus_t nex,
return;
}
/* We currently only support one driver on real nets. */
if (ndrivers > 1 && signal_data_type_of_nexus(nex) == IVL_VT_REAL) {
display_multi_driver_error(nex, ndrivers, MDRV_REAL);
}
level = 0;
while (ndrivers) {
unsigned int inst;