From 31afec57b1bc47019ca8472e509199e5d4b4d0e3 Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Tue, 29 Jan 2008 08:59:55 -0800 Subject: [PATCH] Fix for pr1879226, large constant shift values Addresses pr1879226 on a couple of levels. Analysis: NetNet* PEBinary::elaborate_net_shift_() didn't flag dist==lwidth as a case where all bits of the input are shifted away, which made it create a real concatenator for this case. It attempted to create NetNet*tmp with zero width, which doesn't work; (lsb,msb) ends up as (0,-1), which is later interpreted as a 2-bit wide net. Added an assert to the NetNet constructor to catch any other lurking attempts to create zero-width nets. Added short-circuit code to handle the case where all bits of the input are shifted away. This case used to be "handled" by an assert failure. --- elab_net.cc | 16 ++++++++++------ netlist.cc | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/elab_net.cc b/elab_net.cc index 27c47137a..a04140f56 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -1110,12 +1110,6 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope, the left signal again. */ if (dist == 0) return lsig; - /* Another very special case: constant shift the entire - value away. The result is a const. */ - if (dist > lwidth) { - assert(0); - } - /* The construction that I'm making will ultimately connect its output to the osig here. This will be the result that I return from this function. */ @@ -1154,6 +1148,8 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope, zero->local_flag(true); zero->set_line(*this); + /* Padding bits are zero in most cases, but copies of + * the sign bit in the case of a signed right shift */ if (op_ == 'R') { NetPartSelect*sign_bit = new NetPartSelect(lsig, lsig->vector_width()-1, @@ -1180,6 +1176,14 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope, connect(zero->pin(0), zero_c->pin(0)); } + /* If all data bits get shifted away, connect the zero or + * padding bits directly to output, and stop before building the + * concatenation. */ + if (dist >= lwidth) { + connect(osig->pin(0), zero->pin(0)); + return osig; + } + /* Make a concatenation operator that will join the part-selected right expression at the pad values. */ NetConcat*cc = new NetConcat(scope, scope->local_symbol(), diff --git a/netlist.cc b/netlist.cc index a403a3f1b..485315e45 100644 --- a/netlist.cc +++ b/netlist.cc @@ -402,6 +402,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) local_flag_(false), eref_count_(0), lref_count_(0) { assert(s); + assert(npins>0); verinum::V init_value = verinum::Vz; Link::DIR dir = Link::PASSIVE;