Account for output drive of LPM mux devices.

LPM devices, and LPM MUX devices in particular, need to
have their drive strength accounted for.
This commit is contained in:
Stephen Williams 2010-03-16 14:25:00 -07:00
parent 47e68e21b1
commit bf4e7454eb
12 changed files with 127 additions and 73 deletions

View File

@ -96,6 +96,8 @@ ivl_lpm_data
ivl_lpm_datab ivl_lpm_datab
ivl_lpm_define ivl_lpm_define
ivl_lpm_delay ivl_lpm_delay
ivl_lpm_drive0
ivl_lpm_drive1
ivl_lpm_enable ivl_lpm_enable
ivl_lpm_file ivl_lpm_file
ivl_lpm_lineno ivl_lpm_lineno

View File

@ -1267,7 +1267,9 @@ extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW /* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW
IVL_LPM_SUB IVL_LPM_UFUNC */ IVL_LPM_SUB IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx); extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net);
extern ivl_drive_t ivl_lpm_drive0(ivl_lpm_t net);
extern ivl_drive_t ivl_lpm_drive1(ivl_lpm_t net);
/* IVL_LPM_MUX */ /* IVL_LPM_MUX */
extern unsigned ivl_lpm_selects(ivl_lpm_t net); extern unsigned ivl_lpm_selects(ivl_lpm_t net);
/* IVL_LPM_MUX */ /* IVL_LPM_MUX */

View File

@ -167,6 +167,26 @@ void Link::drivers_drive(strength_t drive0__, strength_t drive1__)
find_nexus_()->drivers_drive(drive0__, drive1__); find_nexus_()->drivers_drive(drive0__, drive1__);
} }
static ivl_drive_t link_to_drive(Link::strength_t dr)
{
switch (dr) {
case Link::HIGHZ:
return IVL_DR_HiZ;
case Link::WEAK:
return IVL_DR_WEAK;
case Link::PULL:
return IVL_DR_PULL;
case Link::STRONG:
return IVL_DR_STRONG;
case Link::SUPPLY:
return IVL_DR_SUPPLY;
}
assert(0);
return IVL_DR_HiZ;
}
void Link::drive0(Link::strength_t str) void Link::drive0(Link::strength_t str)
{ {
drive0_ = str; drive0_ = str;
@ -187,6 +207,15 @@ Link::strength_t Link::drive1() const
return drive1_; return drive1_;
} }
ivl_drive_t Link::ivl_drive0() const
{
return link_to_drive(drive0_);
}
ivl_drive_t Link::ivl_drive1() const
{
return link_to_drive(drive1_);
}
void Link::cur_link(NetPins*&net, unsigned &pin) void Link::cur_link(NetPins*&net, unsigned &pin)
{ {

View File

@ -114,6 +114,9 @@ class Link {
strength_t drive0() const; strength_t drive0() const;
strength_t drive1() const; strength_t drive1() const;
ivl_drive_t ivl_drive0() const;
ivl_drive_t ivl_drive1() const;
void cur_link(NetPins*&net, unsigned &pin); void cur_link(NetPins*&net, unsigned &pin);
void cur_link(const NetPins*&net, unsigned &pin) const; void cur_link(const NetPins*&net, unsigned &pin) const;

View File

@ -1098,7 +1098,7 @@ extern "C" const char* ivl_lpm_name(ivl_lpm_t net)
} }
extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx) extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net)
{ {
assert(net); assert(net);
@ -1118,15 +1118,12 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
case IVL_LPM_MULT: case IVL_LPM_MULT:
case IVL_LPM_POW: case IVL_LPM_POW:
case IVL_LPM_SUB: case IVL_LPM_SUB:
assert(idx == 0);
return net->u_.arith.q; return net->u_.arith.q;
case IVL_LPM_FF: case IVL_LPM_FF:
assert(idx == 0);
return net->u_.ff.q.pin; return net->u_.ff.q.pin;
case IVL_LPM_MUX: case IVL_LPM_MUX:
assert(idx == 0);
return net->u_.mux.q; return net->u_.mux.q;
case IVL_LPM_RE_AND: case IVL_LPM_RE_AND:
@ -1136,20 +1133,16 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
case IVL_LPM_RE_NOR: case IVL_LPM_RE_NOR:
case IVL_LPM_RE_XNOR: case IVL_LPM_RE_XNOR:
case IVL_LPM_SIGN_EXT: case IVL_LPM_SIGN_EXT:
assert(idx == 0);
return net->u_.reduce.q; return net->u_.reduce.q;
case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR: case IVL_LPM_SHIFTR:
assert(idx == 0);
return net->u_.shift.q; return net->u_.shift.q;
case IVL_LPM_SFUNC: case IVL_LPM_SFUNC:
assert(idx == 0);
return net->u_.sfunc.pins[0]; return net->u_.sfunc.pins[0];
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
assert(idx == 0);
return net->u_.ufunc.pins[0]; return net->u_.ufunc.pins[0];
case IVL_LPM_CONCAT: case IVL_LPM_CONCAT:
@ -1157,15 +1150,12 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
case IVL_LPM_PART_VP: case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV: case IVL_LPM_PART_PV:
assert(idx == 0);
return net->u_.part.q; return net->u_.part.q;
case IVL_LPM_REPEAT: case IVL_LPM_REPEAT:
assert(idx == 0);
return net->u_.repeat.q; return net->u_.repeat.q;
case IVL_LPM_ARRAY: case IVL_LPM_ARRAY:
assert(idx == 0);
return net->u_.array.q; return net->u_.array.q;
default: default:
@ -1174,6 +1164,40 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
} }
} }
extern "C" ivl_drive_t ivl_lpm_drive0(ivl_lpm_t net)
{
ivl_nexus_t nex = ivl_lpm_q(net);
for (unsigned idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_nexus_ptr_t cur = ivl_nexus_ptr(nex, idx);
if (ivl_nexus_ptr_lpm(cur) != net)
continue;
if (ivl_nexus_ptr_pin(cur) != 0)
continue;
return ivl_nexus_ptr_drive0(cur);
}
assert(0);
return IVL_DR_STRONG;
}
extern "C" ivl_drive_t ivl_lpm_drive1(ivl_lpm_t net)
{
ivl_nexus_t nex = ivl_lpm_q(net);
for (unsigned idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_nexus_ptr_t cur = ivl_nexus_ptr(nex, idx);
if (ivl_nexus_ptr_lpm(cur) != net)
continue;
if (ivl_nexus_ptr_pin(cur) != 0)
continue;
return ivl_nexus_ptr_drive1(cur);
}
assert(0);
return IVL_DR_STRONG;
}
extern "C" ivl_scope_t ivl_lpm_scope(ivl_lpm_t net) extern "C" ivl_scope_t ivl_lpm_scope(ivl_lpm_t net)
{ {
assert(net); assert(net);

View File

@ -2056,7 +2056,8 @@ void dll_target::lpm_mux(const NetMux*net)
assert(nex->t_cookie()); assert(nex->t_cookie());
obj->u_.mux.q = nex->t_cookie(); obj->u_.mux.q = nex->t_cookie();
nexus_lpm_add(obj->u_.mux.q, obj, 0, nexus_lpm_add(obj->u_.mux.q, obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG); net->pin_Result().ivl_drive0(),
net->pin_Result().ivl_drive1());
/* Connect the select bits. */ /* Connect the select bits. */
nex = net->pin_Sel().nexus(); nex = net->pin_Sel().nexus();

View File

@ -214,9 +214,9 @@ static void check_cmp_widths(ivl_lpm_t net)
stub_errors += 1; stub_errors += 1;
} }
if (width_of_nexus(ivl_lpm_q(net,0)) != 1) { if (width_of_nexus(ivl_lpm_q(net)) != 1) {
fprintf(out, " ERROR: Width of Q is %u, not 1\n", fprintf(out, " ERROR: Width of Q is %u, not 1\n",
width_of_nexus(ivl_lpm_q(net,0))); width_of_nexus(ivl_lpm_q(net)));
stub_errors += 1; stub_errors += 1;
} }
} }
@ -224,8 +224,8 @@ static void check_cmp_widths(ivl_lpm_t net)
static void show_lpm_arithmetic_pins(ivl_lpm_t net) static void show_lpm_arithmetic_pins(ivl_lpm_t net)
{ {
ivl_nexus_t nex; ivl_nexus_t nex;
nex = ivl_lpm_q(net, 0); nex = ivl_lpm_q(net);
fprintf(out, " Q: %p\n", ivl_lpm_q(net, 0)); fprintf(out, " Q: %p\n", ivl_lpm_q(net));
nex = ivl_lpm_data(net, 0); nex = ivl_lpm_data(net, 0);
fprintf(out, " DataA: %p\n", nex); fprintf(out, " DataA: %p\n", nex);
@ -242,8 +242,8 @@ static void show_lpm_abs(ivl_lpm_t net)
fprintf(out, " LPM_ABS %s: <width=%u>\n", fprintf(out, " LPM_ABS %s: <width=%u>\n",
ivl_lpm_basename(net), width); ivl_lpm_basename(net), width);
nex = ivl_lpm_q(net, 0); nex = ivl_lpm_q(net);
fprintf(out, " Q: %p\n", ivl_lpm_q(net, 0)); fprintf(out, " Q: %p\n", ivl_lpm_q(net));
nex = ivl_lpm_data(net, 0); nex = ivl_lpm_data(net, 0);
fprintf(out, " D: %p\n", nex); fprintf(out, " D: %p\n", nex);
@ -278,7 +278,7 @@ static void show_lpm_array(ivl_lpm_t net)
fprintf(out, " LPM_ARRAY: <width=%u, signal=%s>\n", fprintf(out, " LPM_ARRAY: <width=%u, signal=%s>\n",
width, ivl_signal_basename(array)); width, ivl_signal_basename(array));
nex = ivl_lpm_q(net, 0); nex = ivl_lpm_q(net);
assert(nex); assert(nex);
fprintf(out, " Q: %p\n", nex); fprintf(out, " Q: %p\n", nex);
nex = ivl_lpm_select(net); nex = ivl_lpm_select(net);
@ -286,9 +286,9 @@ static void show_lpm_array(ivl_lpm_t net)
fprintf(out, " Address: %p (address width=%u)\n", fprintf(out, " Address: %p (address width=%u)\n",
nex, ivl_lpm_selects(net)); nex, ivl_lpm_selects(net));
if (width_of_nexus(ivl_lpm_q(net,0)) != width) { if (width_of_nexus(ivl_lpm_q(net)) != width) {
fprintf(out, " ERROR: Data Q width doesn't match " fprintf(out, " ERROR: Data Q width doesn't match "
"nexus width=%u\n", width_of_nexus(ivl_lpm_q(net,0))); "nexus width=%u\n", width_of_nexus(ivl_lpm_q(net)));
stub_errors += 1; stub_errors += 1;
} }
@ -307,9 +307,9 @@ static void show_lpm_cast_int(ivl_lpm_t net)
fprintf(out, " LPM_CAST_INT %s: <width=%u>\n", fprintf(out, " LPM_CAST_INT %s: <width=%u>\n",
ivl_lpm_basename(net), width); ivl_lpm_basename(net), width);
q = ivl_lpm_q(net,0); q = ivl_lpm_q(net);
a = ivl_lpm_data(net,0); a = ivl_lpm_data(net,0);
fprintf(out, " O: %p\n", ivl_lpm_q(net,0)); fprintf(out, " O: %p\n", ivl_lpm_q(net));
fprintf(out, " A: %p\n", ivl_lpm_data(net,0)); fprintf(out, " A: %p\n", ivl_lpm_data(net,0));
if (type_of_nexus(q) == IVL_VT_REAL) { if (type_of_nexus(q) == IVL_VT_REAL) {
@ -333,9 +333,9 @@ static void show_lpm_cast_real(ivl_lpm_t net)
fprintf(out, " LPM_CAST_REAL %s: <width=%u>\n", fprintf(out, " LPM_CAST_REAL %s: <width=%u>\n",
ivl_lpm_basename(net), width); ivl_lpm_basename(net), width);
q = ivl_lpm_q(net,0); q = ivl_lpm_q(net);
a = ivl_lpm_data(net,0); a = ivl_lpm_data(net,0);
fprintf(out, " O: %p\n", ivl_lpm_q(net,0)); fprintf(out, " O: %p\n", ivl_lpm_q(net));
fprintf(out, " A: %p\n", ivl_lpm_data(net,0)); fprintf(out, " A: %p\n", ivl_lpm_data(net,0));
if (type_of_nexus(q) != IVL_VT_REAL) { if (type_of_nexus(q) != IVL_VT_REAL) {
@ -373,7 +373,7 @@ static void show_lpm_cmp_eeq(ivl_lpm_t net)
fprintf(out, " LPM_CMP_%s %s: <width=%u>\n", str, fprintf(out, " LPM_CMP_%s %s: <width=%u>\n", str,
ivl_lpm_basename(net), width); ivl_lpm_basename(net), width);
fprintf(out, " O: %p\n", ivl_lpm_q(net,0)); fprintf(out, " O: %p\n", ivl_lpm_q(net));
fprintf(out, " A: %p\n", ivl_lpm_data(net,0)); fprintf(out, " A: %p\n", ivl_lpm_data(net,0));
fprintf(out, " B: %p\n", ivl_lpm_data(net,1)); fprintf(out, " B: %p\n", ivl_lpm_data(net,1));
check_cmp_widths(net); check_cmp_widths(net);
@ -390,7 +390,7 @@ static void show_lpm_cmp_ge(ivl_lpm_t net)
ivl_lpm_basename(net), width, ivl_lpm_basename(net), width,
ivl_lpm_signed(net)? "signed" : "unsigned"); ivl_lpm_signed(net)? "signed" : "unsigned");
fprintf(out, " O: %p\n", ivl_lpm_q(net,0)); fprintf(out, " O: %p\n", ivl_lpm_q(net));
fprintf(out, " A: %p\n", ivl_lpm_data(net,0)); fprintf(out, " A: %p\n", ivl_lpm_data(net,0));
fprintf(out, " B: %p\n", ivl_lpm_data(net,1)); fprintf(out, " B: %p\n", ivl_lpm_data(net,1));
check_cmp_widths(net); check_cmp_widths(net);
@ -407,7 +407,7 @@ static void show_lpm_cmp_gt(ivl_lpm_t net)
ivl_lpm_basename(net), width, ivl_lpm_basename(net), width,
ivl_lpm_signed(net)? "signed" : "unsigned"); ivl_lpm_signed(net)? "signed" : "unsigned");
fprintf(out, " O: %p\n", ivl_lpm_q(net,0)); fprintf(out, " O: %p\n", ivl_lpm_q(net));
fprintf(out, " A: %p\n", ivl_lpm_data(net,0)); fprintf(out, " A: %p\n", ivl_lpm_data(net,0));
fprintf(out, " B: %p\n", ivl_lpm_data(net,1)); fprintf(out, " B: %p\n", ivl_lpm_data(net,1));
check_cmp_widths(net); check_cmp_widths(net);
@ -424,7 +424,7 @@ static void show_lpm_cmp_ne(ivl_lpm_t net)
fprintf(out, " LPM_CMP_NE %s: <width=%u>\n", fprintf(out, " LPM_CMP_NE %s: <width=%u>\n",
ivl_lpm_basename(net), width); ivl_lpm_basename(net), width);
fprintf(out, " O: %p\n", ivl_lpm_q(net,0)); fprintf(out, " O: %p\n", ivl_lpm_q(net));
fprintf(out, " A: %p\n", ivl_lpm_data(net,0)); fprintf(out, " A: %p\n", ivl_lpm_data(net,0));
fprintf(out, " B: %p\n", ivl_lpm_data(net,1)); fprintf(out, " B: %p\n", ivl_lpm_data(net,1));
check_cmp_widths(net); check_cmp_widths(net);
@ -446,7 +446,7 @@ static void show_lpm_concat(ivl_lpm_t net)
fprintf(out, " LPM_CONCAT %s: <width=%u, inputs=%u>\n", fprintf(out, " LPM_CONCAT %s: <width=%u, inputs=%u>\n",
ivl_lpm_basename(net), width, ivl_lpm_size(net)); ivl_lpm_basename(net), width, ivl_lpm_size(net));
fprintf(out, " O: %p\n", ivl_lpm_q(net,0)); fprintf(out, " O: %p\n", ivl_lpm_q(net));
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) { for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_data(net, idx); ivl_nexus_t nex = ivl_lpm_data(net, idx);
@ -496,7 +496,7 @@ static void show_lpm_ff(ivl_lpm_t net)
stub_errors += 1; stub_errors += 1;
} }
nex = ivl_lpm_q(net,0); nex = ivl_lpm_q(net);
fprintf(out, " Q: %p\n", nex); fprintf(out, " Q: %p\n", nex);
if (width_of_nexus(nex) != width) { if (width_of_nexus(nex) != width) {
fprintf(out, " Q: ERROR: Nexus width is %u\n", fprintf(out, " Q: ERROR: Nexus width is %u\n",
@ -527,15 +527,15 @@ static void show_lpm_mult(ivl_lpm_t net)
fprintf(out, " LPM_MULT %s: <width=%u>\n", fprintf(out, " LPM_MULT %s: <width=%u>\n",
ivl_lpm_basename(net), width); ivl_lpm_basename(net), width);
fprintf(out, " O: %p\n", ivl_lpm_q(net,0)); fprintf(out, " O: %p\n", ivl_lpm_q(net));
fprintf(out, " A: %p <width=%u>\n", fprintf(out, " A: %p <width=%u>\n",
ivl_lpm_data(net,0), width_of_nexus(ivl_lpm_data(net,0))); ivl_lpm_data(net,0), width_of_nexus(ivl_lpm_data(net,0)));
fprintf(out, " B: %p <width=%u>\n", fprintf(out, " B: %p <width=%u>\n",
ivl_lpm_data(net,1), width_of_nexus(ivl_lpm_data(net,1))); ivl_lpm_data(net,1), width_of_nexus(ivl_lpm_data(net,1)));
if (width != width_of_nexus(ivl_lpm_q(net,0))) { if (width != width_of_nexus(ivl_lpm_q(net))) {
fprintf(out, " ERROR: Width of Q is %u, not %u\n", fprintf(out, " ERROR: Width of Q is %u, not %u\n",
width_of_nexus(ivl_lpm_q(net,0)), width); width_of_nexus(ivl_lpm_q(net)), width);
stub_errors += 1; stub_errors += 1;
} }
} }
@ -553,12 +553,14 @@ static void show_lpm_mux(ivl_lpm_t net)
unsigned idx; unsigned idx;
unsigned width = ivl_lpm_width(net); unsigned width = ivl_lpm_width(net);
unsigned size = ivl_lpm_size(net); unsigned size = ivl_lpm_size(net);
ivl_drive_t drive0 = ivl_lpm_drive0(net);
ivl_drive_t drive1 = ivl_lpm_drive1(net);
fprintf(out, " LPM_MUX %s: <width=%u, size=%u>\n", fprintf(out, " LPM_MUX %s: <width=%u, size=%u>\n",
ivl_lpm_basename(net), width, size); ivl_lpm_basename(net), width, size);
nex = ivl_lpm_q(net,0); nex = ivl_lpm_q(net);
fprintf(out, " Q: %p\n", nex); fprintf(out, " Q: %p <drive0/1 = %u/%u>\n", nex, drive0, drive1);
if (width != width_of_nexus(nex)) { if (width != width_of_nexus(nex)) {
fprintf(out, " Q: ERROR: Nexus width is %u\n", fprintf(out, " Q: ERROR: Nexus width is %u\n",
width_of_nexus(nex)); width_of_nexus(nex));
@ -610,7 +612,7 @@ static void show_lpm_part(ivl_lpm_t net)
fprintf(out, " LPM_PART_%s %s: <width=%u, base=%u, signed=%d>\n", fprintf(out, " LPM_PART_%s %s: <width=%u, base=%u, signed=%d>\n",
part_type_string, ivl_lpm_basename(net), part_type_string, ivl_lpm_basename(net),
width, base, ivl_lpm_signed(net)); width, base, ivl_lpm_signed(net));
fprintf(out, " O: %p\n", ivl_lpm_q(net,0)); fprintf(out, " O: %p\n", ivl_lpm_q(net));
fprintf(out, " I: %p\n", ivl_lpm_data(net,0)); fprintf(out, " I: %p\n", ivl_lpm_data(net,0));
if (sel != 0) { if (sel != 0) {
@ -633,19 +635,19 @@ static void show_lpm_part(ivl_lpm_t net)
stub_errors += 1; stub_errors += 1;
} }
if (width_of_nexus(ivl_lpm_q(net,0)) != width) { if (width_of_nexus(ivl_lpm_q(net)) != width) {
fprintf(out, " ERROR: Part select input mismatch." fprintf(out, " ERROR: Part select input mismatch."
" Nexus width=%u, expect width=%u\n", " Nexus width=%u, expect width=%u\n",
width_of_nexus(ivl_lpm_q(net,0)), width); width_of_nexus(ivl_lpm_q(net)), width);
stub_errors += 1; stub_errors += 1;
} }
break; break;
case IVL_LPM_PART_PV: case IVL_LPM_PART_PV:
if (width_of_nexus(ivl_lpm_q(net,0)) < (width+base)) { if (width_of_nexus(ivl_lpm_q(net)) < (width+base)) {
fprintf(out, " ERROR: Part select is out of range." fprintf(out, " ERROR: Part select is out of range."
" Target nexus width=%u, width+base=%u\n", " Target nexus width=%u, width+base=%u\n",
width_of_nexus(ivl_lpm_q(net,0)), width+base); width_of_nexus(ivl_lpm_q(net)), width+base);
stub_errors += 1; stub_errors += 1;
} }
@ -696,13 +698,13 @@ static void show_lpm_re(ivl_lpm_t net)
fprintf(out, " LPM_RE_%s: %s <width=%u>\n", fprintf(out, " LPM_RE_%s: %s <width=%u>\n",
type, ivl_lpm_name(net),width); type, ivl_lpm_name(net),width);
nex = ivl_lpm_q(net, 0); nex = ivl_lpm_q(net);
fprintf(out, " Q: %p\n", nex); fprintf(out, " Q: %p\n", nex);
nex = ivl_lpm_data(net, 0); nex = ivl_lpm_data(net, 0);
fprintf(out, " D: %p\n", nex); fprintf(out, " D: %p\n", nex);
nex = ivl_lpm_q(net, 0); nex = ivl_lpm_q(net);
if (1 != width_of_nexus(nex)) { if (1 != width_of_nexus(nex)) {
fprintf(out, " ERROR: Width of Q is %u, expecting 1\n", fprintf(out, " ERROR: Width of Q is %u, expecting 1\n",
@ -722,7 +724,7 @@ static void show_lpm_repeat(ivl_lpm_t net)
{ {
unsigned width = ivl_lpm_width(net); unsigned width = ivl_lpm_width(net);
unsigned count = ivl_lpm_size(net); unsigned count = ivl_lpm_size(net);
ivl_nexus_t nex_q = ivl_lpm_q(net,0); ivl_nexus_t nex_q = ivl_lpm_q(net);
ivl_nexus_t nex_a = ivl_lpm_data(net,0); ivl_nexus_t nex_a = ivl_lpm_data(net,0);
fprintf(out, " LPM_REPEAT %s: <width=%u, count=%u>\n", fprintf(out, " LPM_REPEAT %s: <width=%u, count=%u>\n",
@ -757,7 +759,7 @@ static void show_lpm_shift(ivl_lpm_t net, const char*shift_dir)
ivl_lpm_basename(net), width, ivl_lpm_basename(net), width,
ivl_lpm_signed(net)? "" : "un"); ivl_lpm_signed(net)? "" : "un");
nex = ivl_lpm_q(net, 0); nex = ivl_lpm_q(net);
fprintf(out, " Q: %p\n", nex); fprintf(out, " Q: %p\n", nex);
if (width != width_of_nexus(nex)) { if (width != width_of_nexus(nex)) {
@ -782,7 +784,7 @@ static void show_lpm_shift(ivl_lpm_t net, const char*shift_dir)
static void show_lpm_sign_ext(ivl_lpm_t net) static void show_lpm_sign_ext(ivl_lpm_t net)
{ {
unsigned width = ivl_lpm_width(net); unsigned width = ivl_lpm_width(net);
ivl_nexus_t nex_q = ivl_lpm_q(net,0); ivl_nexus_t nex_q = ivl_lpm_q(net);
ivl_nexus_t nex_a = ivl_lpm_data(net,0); ivl_nexus_t nex_a = ivl_lpm_data(net,0);
fprintf(out, " LPM_SIGN_EXT %s: <width=%u>\n", fprintf(out, " LPM_SIGN_EXT %s: <width=%u>\n",
@ -812,7 +814,7 @@ static void show_lpm_sfunc(ivl_lpm_t net)
{ {
unsigned width = ivl_lpm_width(net); unsigned width = ivl_lpm_width(net);
unsigned ports = ivl_lpm_size(net); unsigned ports = ivl_lpm_size(net);
ivl_variable_type_t data_type = type_of_nexus(ivl_lpm_q(net,0)); ivl_variable_type_t data_type = type_of_nexus(ivl_lpm_q(net));
ivl_nexus_t nex; ivl_nexus_t nex;
unsigned idx; unsigned idx;
@ -820,7 +822,7 @@ static void show_lpm_sfunc(ivl_lpm_t net)
ivl_lpm_basename(net), ivl_lpm_string(net), ivl_lpm_basename(net), ivl_lpm_string(net),
width, data_type_string(data_type), ports); width, data_type_string(data_type), ports);
nex = ivl_lpm_q(net, 0); nex = ivl_lpm_q(net);
if (width != width_of_nexus(nex)) { if (width != width_of_nexus(nex)) {
fprintf(out, " ERROR: Q output nexus width=%u " fprintf(out, " ERROR: Q output nexus width=%u "
" does not match part width\n", width_of_nexus(nex)); " does not match part width\n", width_of_nexus(nex));
@ -874,7 +876,7 @@ static void show_lpm_ufunc(ivl_lpm_t net)
show_lpm_delays(net); show_lpm_delays(net);
nex = ivl_lpm_q(net, 0); nex = ivl_lpm_q(net);
if (width != width_of_nexus(nex)) { if (width != width_of_nexus(nex)) {
fprintf(out, " ERROR: Q output nexus width=%u " fprintf(out, " ERROR: Q output nexus width=%u "
" does not match part width\n", width_of_nexus(nex)); " does not match part width\n", width_of_nexus(nex));

View File

@ -315,7 +315,7 @@ static int draw_mux_lpm(vhdl_arch *arch, ivl_lpm_t lpm)
vhdl_expr *t1 = vhdl_expr *t1 =
new vhdl_binop_expr(sel, VHDL_BINOP_EQ, b1, vhdl_type::boolean()); new vhdl_binop_expr(sel, VHDL_BINOP_EQ, b1, vhdl_type::boolean());
vhdl_var_ref *out = nexus_to_var_ref(scope, ivl_lpm_q(lpm, 0)); vhdl_var_ref *out = nexus_to_var_ref(scope, ivl_lpm_q(lpm));
// Make sure s0 and s1 have the same type as the output // Make sure s0 and s1 have the same type as the output
s0 = s0->cast(out->get_type()); s0 = s0->cast(out->get_type());
@ -337,7 +337,7 @@ int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm)
if (NULL == f) if (NULL == f)
return 1; return 1;
vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm, 0)); vhdl_var_ref *out = nexus_to_var_ref(arch->get_scope(), ivl_lpm_q(lpm));
if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV) { if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV) {
vhdl_expr *off = part_select_base(arch->get_scope(), lpm); vhdl_expr *off = part_select_base(arch->get_scope(), lpm);
assert(off); assert(off);

View File

@ -249,7 +249,7 @@ void draw_nexus(ivl_nexus_t nexus)
// If this is connected to the LPM output then this nexus // If this is connected to the LPM output then this nexus
// is driven by the LPM // is driven by the LPM
if (ivl_lpm_q(lpm, 0) == nexus) if (ivl_lpm_q(lpm) == nexus)
ndrivers++; ndrivers++;
} }
else if ((con = ivl_nexus_ptr_con(nexus_ptr))) { else if ((con = ivl_nexus_ptr_con(nexus_ptr))) {

View File

@ -42,6 +42,9 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
d_fall = ivl_lpm_delay(net, 1); d_fall = ivl_lpm_delay(net, 1);
d_decay = ivl_lpm_delay(net, 2); d_decay = ivl_lpm_delay(net, 2);
ivl_drive_t str0 = ivl_lpm_drive0(net);
ivl_drive_t str1 = ivl_lpm_drive1(net);
dly = ""; dly = "";
if (d_rise != 0) { if (d_rise != 0) {
dly = "/d"; dly = "/d";
@ -97,6 +100,8 @@ static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
input[1] = draw_net_input(ivl_lpm_data(net,1)); input[1] = draw_net_input(ivl_lpm_data(net,1));
input[2] = draw_net_input(ivl_lpm_select(net)); 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, "L_%p%s .functor %s %u", net, dly, muxz, width);
if (str0!=IVL_DR_STRONG || str1!=IVL_DR_STRONG)
fprintf(vvp_out, " [%u %u]", str0, str1);
fprintf(vvp_out, ", %s", input[0]); fprintf(vvp_out, ", %s", input[0]);
fprintf(vvp_out, ", %s", input[1]); fprintf(vvp_out, ", %s", input[1]);
fprintf(vvp_out, ", %s", input[2]); fprintf(vvp_out, ", %s", input[2]);
@ -161,7 +166,7 @@ void draw_lpm_mux(ivl_lpm_t net)
/* The output of the mux defines the type of the mux. the /* The output of the mux defines the type of the mux. the
ivl_target should guarantee that all the inputs are the ivl_target should guarantee that all the inputs are the
same type as the output. */ same type as the output. */
switch (data_type_of_nexus(ivl_lpm_q(net,0))) { switch (data_type_of_nexus(ivl_lpm_q(net))) {
case IVL_VT_REAL: case IVL_VT_REAL:
muxz = "MUXR"; muxz = "MUXR";
break; break;

View File

@ -485,7 +485,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
case IVL_LPM_PART_VP: case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV: /* NOTE: This is only a partial driver. */ case IVL_LPM_PART_PV: /* NOTE: This is only a partial driver. */
case IVL_LPM_REPEAT: case IVL_LPM_REPEAT:
if (ivl_lpm_q(lpm, 0) == nex) { if (ivl_lpm_q(lpm) == nex) {
char tmp[128]; char tmp[128];
snprintf(tmp, sizeof tmp, "L_%p", lpm); snprintf(tmp, sizeof tmp, "L_%p", lpm);
return strdup(tmp); return strdup(tmp);

View File

@ -698,7 +698,8 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
unsigned vector_width = width_of_nexus(ivl_logic_pin(lptr, 0)); unsigned vector_width = width_of_nexus(ivl_logic_pin(lptr, 0));
ivl_drive_t str0, str1; ivl_drive_t str0 = ivl_logic_drive0(lptr);
ivl_drive_t str1 = ivl_logic_drive1(lptr);
int level; int level;
int ninp; int ninp;
@ -815,21 +816,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
break; break;
} }
{ ivl_nexus_t nex = ivl_logic_pin(lptr, 0);
ivl_nexus_ptr_t nptr = 0;
unsigned idx;
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
nptr = ivl_nexus_ptr(nex,idx);
if (ivl_nexus_ptr_log(nptr) != lptr)
continue;
if (ivl_nexus_ptr_pin(nptr) != 0)
continue;
break;
}
str0 = ivl_nexus_ptr_drive0(nptr);
str1 = ivl_nexus_ptr_drive1(nptr);
}
if (!lcasc) if (!lcasc)
lcasc = ltype; lcasc = ltype;
@ -1609,7 +1595,7 @@ static void draw_lpm_sfunc(ivl_lpm_t net)
/* Print the function type descriptor string. */ /* Print the function type descriptor string. */
fprintf(vvp_out, ", \""); fprintf(vvp_out, ", \"");
draw_type_string_of_nex(ivl_lpm_q(net,0)); draw_type_string_of_nex(ivl_lpm_q(net));
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1)
draw_type_string_of_nex(ivl_lpm_data(net,idx)); draw_type_string_of_nex(ivl_lpm_data(net,idx));
@ -1723,7 +1709,7 @@ static void draw_lpm_part_pv(ivl_lpm_t net)
{ {
unsigned width = ivl_lpm_width(net); unsigned width = ivl_lpm_width(net);
unsigned base = ivl_lpm_base(net); unsigned base = ivl_lpm_base(net);
unsigned signal_width = width_of_nexus(ivl_lpm_q(net,0)); unsigned signal_width = width_of_nexus(ivl_lpm_q(net));
fprintf(vvp_out, "L_%p .part/pv %s", fprintf(vvp_out, "L_%p .part/pv %s",
net, draw_net_input(ivl_lpm_data(net, 0))); net, draw_net_input(ivl_lpm_data(net, 0)));