Support shifts and divide.

This commit is contained in:
steve 2005-02-19 02:43:38 +00:00
parent 5fe5d9184d
commit 257e1f9516
10 changed files with 328 additions and 373 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.151 2005/02/12 06:25:40 steve Exp $"
#ident "$Id: elab_net.cc,v 1.152 2005/02/19 02:43:38 steve Exp $"
#endif
# include "config.h"
@ -723,23 +723,23 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
unsigned rwidth = lwidth;
if (rwidth == 0) {
rwidth = lsig->pin_count();
if (rsig->pin_count() > rwidth)
rwidth = rsig->pin_count();
rwidth = lsig->vector_width();
if (rsig->vector_width() > rwidth)
rwidth = rsig->vector_width();
lwidth = rwidth;
}
if ((rwidth > lsig->pin_count()) && (rwidth > rsig->pin_count())) {
rwidth = lsig->pin_count();
if (rsig->pin_count() > rwidth)
rwidth = rsig->pin_count();
if ((rwidth > lsig->vector_width()) && (rwidth > rsig->vector_width())) {
rwidth = lsig->vector_width();
if (rsig->vector_width() > rwidth)
rwidth = rsig->vector_width();
}
// Create a device with the calculated dimensions.
NetDivide*div = new NetDivide(scope, scope->local_symbol(), rwidth,
lsig->pin_count(),
rsig->pin_count());
lsig->vector_width(),
rsig->vector_width());
des->add_node(div);
div->set_signed(lsig->get_signed() && rsig->get_signed());
@ -747,10 +747,8 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
// Connect the left and right inputs of the divider to the
// nets that are the left and right expressions.
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(div->pin_DataA(idx), lsig->pin(idx));
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(div->pin_DataB(idx), rsig->pin(idx));
connect(div->pin_DataA(), lsig->pin(0));
connect(div->pin_DataB(), rsig->pin(0));
// Make an output signal that is the width of the l-value.
@ -763,24 +761,9 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
osig->local_flag(true);
osig->set_signed(div->get_signed());
for (unsigned idx = 0 ; idx < rwidth ; idx += 1)
connect(div->pin_Result(idx), osig->pin(idx));
connect(div->pin_Result(), osig->pin(0));
// If the lvalue is larger then the result, then pad the
// output with constant 0. This can happen for example in
// cases like this:
// wire [3;0] a, b;
// wire [7:0] r = a / b;
if (rwidth < osig->pin_count()) {
NetConst*tmp = new NetConst(scope, scope->local_symbol(),
verinum::V0);
des->add_node(tmp);
for (unsigned idx = rwidth ; idx < osig->pin_count() ; idx += 1)
connect(osig->pin(idx), tmp->pin(0));
}
return osig;
}
@ -1004,8 +987,8 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
if (lsig == 0) return 0;
if (lsig->pin_count() > lwidth)
lwidth = lsig->pin_count();
if (lsig->vector_width() > lwidth)
lwidth = lsig->vector_width();
bool right_flag = op_ == 'r' || op_ == 'R';
bool signed_flag = op_ == 'R';
@ -1013,56 +996,123 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
/* Handle the special case of a constant shift amount. There
is no reason in this case to create a gate at all, just
connect the lsig to the osig with the bit positions
shifted. */
shifted. Use a NetPartSelect to select the parts of the
left expression that survive the shift, and a NetConcat to
concatenate a constant for padding. */
if (verinum*rval = right_->eval_const(des, scope)) {
assert(rval->is_defined());
unsigned dist = rval->as_ulong();
if (dist > lwidth)
dist = lwidth;
/* Very special case, constant 0 shift. */
/* Very special case: constant 0 shift. Simply return
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. */
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, lwidth);
osig->local_flag(true);
NetConst*zero = new NetConst(scope, scope->local_symbol(),
verinum::V0);
des->add_node(zero);
if (op_ == 'l') {
/* Left shift means put some zeros on the bottom
of the vector. */
unsigned idx;
for (idx = 0 ; idx < dist ; idx += 1)
connect(osig->pin(idx), zero->pin(0));
for ( ; (idx<lwidth) && ((idx-dist) < lsig->pin_count())
; idx += 1)
connect(osig->pin(idx), lsig->pin(idx-dist));
for ( ; idx < lwidth ; idx += 1)
connect(osig->pin(idx), zero->pin(0));
/* Make the constant zero's that I'm going to pad to the
top or bottom of the left expression. Attach a signal
to its output so that I don't have to worry about it
later. If the left expression is less then the
desired width (and we are doing right shifts) then we
can combine the expression padding with the distance
padding to reduce nodes. */
unsigned pad_width = dist;
unsigned part_width = lwidth - dist;
if (op_ == 'r' || op_ == 'R') {
if (lsig->vector_width() < lwidth) {
pad_width += lwidth - lsig->vector_width();
part_width -= lwidth - lsig->vector_width();
}
} else {
} else if (op_ == 'R') {
/* Signed right shift. */
unsigned idx;
unsigned keep = lsig->pin_count()-dist;
for (idx = 0 ; idx < keep ; idx += 1)
connect(osig->pin(idx), lsig->pin(idx+dist));
for (idx = keep ; idx < lwidth ; idx += 1)
connect(osig->pin(idx), lsig->pin(keep+dist-1));
/* The left net must be the same width as the
result. The part select that I'm about to make relies
on that. */
lsig = pad_to_width(des, lsig, lwidth);
}
NetNet*zero = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, pad_width);
zero->local_flag(true);
zero->set_line(*this);
if (op_ == 'R') {
NetPartSelect*sign_bit
= new NetPartSelect(lsig, lsig->vector_width()-1,
1, NetPartSelect::VP);
des->add_node(sign_bit);
NetReplicate*sign_pad
= new NetReplicate(scope, scope->local_symbol(),
pad_width, pad_width);
des->add_node(sign_pad);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, 1);
connect(sign_bit->pin(0), tmp->pin(0));
connect(sign_bit->pin(0), sign_pad->pin(1));
connect(zero->pin(0), sign_pad->pin(0));
} else {
/* Unsigned right shift. */
assert(op_ == 'r');
unsigned idx;
unsigned keep = lsig->pin_count()-dist;
for (idx = 0 ; idx < keep ; idx += 1)
connect(osig->pin(idx), lsig->pin(idx+dist));
for (idx = keep ; idx < lwidth ; idx += 1)
connect(osig->pin(idx), zero->pin(0));
NetConst*zero_c = new NetConst(scope, scope->local_symbol(),
verinum(verinum::V0, pad_width));
des->add_node(zero_c);
connect(zero->pin(0), zero_c->pin(0));
}
/* Make a concatenation operator that will join the
part-selected right expression at the pad values. */
NetConcat*cc = new NetConcat(scope, scope->local_symbol(),
lwidth, 2);
cc->set_line(*this);
des->add_node(cc);
connect(cc->pin(0), osig->pin(0));
/* Make the part select of the left expression and
connect it to the lsb or msb of the concatenation,
depending on the direction of the shift. */
NetPartSelect*part;
switch (op_) {
case 'l': // Left shift === {lsig, zero}
part = new NetPartSelect(lsig, 0, part_width,
NetPartSelect::VP);
connect(cc->pin(1), zero->pin(0));
connect(cc->pin(2), part->pin(0));
break;
case 'R':
case 'r': // right-shift === {zero, lsig}
part = new NetPartSelect(lsig, dist, part_width,
NetPartSelect::VP);
connect(cc->pin(1), part->pin(0));
connect(cc->pin(2), zero->pin(0));
break;
default:
assert(0);
}
des->add_node(part);
/* Attach a signal to the part select output (NetConcat
input) */
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, part_width);
tmp->local_flag(true);
tmp->set_line(*this);
connect(part->pin(0), tmp->pin(0));
return osig;
}
@ -1078,39 +1128,31 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
// Make the shift device itself, and the output
// NetNet. Connect the Result output pins to the osig signal
NetCLShift*gate = new NetCLShift(scope, scope->local_symbol(),
lwidth, rsig->pin_count(),
lwidth, rsig->vector_width(),
right_flag, signed_flag);
des->add_node(gate);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, lwidth);
osig->local_flag(true);
osig->set_signed(signed_flag);
for (unsigned idx = 0 ; idx < lwidth ; idx += 1)
connect(osig->pin(idx), gate->pin_Result(idx));
connect(osig->pin(0), gate->pin_Result());
// Connect the lsig (the left expression) to the Data input,
// and pad it if necessary with constant zeros.
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(lsig->pin(idx), gate->pin_Data(idx));
if (lsig->pin_count() < lwidth) {
NetConst*zero = new NetConst(scope, scope->local_symbol(),
verinum::V0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
tmp->local_flag(true);
des->add_node(zero);
connect(zero->pin(0), tmp->pin(0));
for (unsigned idx = lsig->pin_count() ; idx < lwidth ; idx += 1)
connect(zero->pin(0), gate->pin_Data(idx));
}
assert(lsig->vector_width() == lwidth);
connect(lsig->pin(0), gate->pin_Data());
// Connect the rsig (the shift amount expression) to the
// Distance input.
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(rsig->pin(idx), gate->pin_Distance(idx));
connect(rsig->pin(0), gate->pin_Distance());
des->add_node(gate);
if (debug_elaborate) {
cerr << get_line() << ": debug: "
<< "Elaborate LPM_SHIFT: width="<<gate->width()
<< ", swidth="<< gate->width_dist() << endl;
}
return osig;
}
@ -2462,6 +2504,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* Revision 1.152 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.151 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.318 2005/02/10 04:56:58 steve Exp $"
#ident "$Id: elaborate.cc,v 1.319 2005/02/19 02:43:38 steve Exp $"
#endif
# include "config.h"
@ -94,7 +94,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
assert(lval->pin_count() == 1);
if (debug_elaborate) {
cerr << lval->get_line() << ": debug: PGassign: elaborated l-value"
cerr << get_line() << ": debug: PGassign: elaborated l-value"
<< " width=" << lval->vector_width() << endl;
}
@ -2938,6 +2938,9 @@ Design* elaborate(list<perm_string>roots)
/*
* $Log: elaborate.cc,v $
* Revision 1.319 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.318 2005/02/10 04:56:58 steve
* distinguish between single port namy instances, and single instances many sub-ports.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: expr_synth.cc,v 1.63 2005/02/12 06:25:40 steve Exp $"
#ident "$Id: expr_synth.cc,v 1.64 2005/02/19 02:43:38 steve Exp $"
#endif
# include "config.h"
@ -371,16 +371,13 @@ NetNet* NetEBDiv::synthesize(Design*des)
case '/': {
NetDivide*div = new NetDivide(scope, scope->local_symbol(),
expr_width(),
lsig->pin_count(),
rsig->pin_count());
lsig->vector_width(),
rsig->vector_width());
des->add_node(div);
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
connect(div->pin_DataA(idx), lsig->pin(idx));
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
connect(div->pin_DataB(idx), rsig->pin(idx));
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
connect(div->pin_Result(idx), osig->pin(idx));
connect(div->pin_DataA(), lsig->pin(0));
connect(div->pin_DataB(), rsig->pin(0));
connect(div->pin_Result(),osig->pin(0));
break;
}
@ -562,20 +559,18 @@ NetNet* NetEBShift::synthesize(Design*des)
assert(op() == 'l');
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
osig->pin_count(),
rsig->pin_count(),
osig->vector_width(),
rsig->vector_width(),
right_flag, signed_flag);
dev->set_line(*this);
des->add_node(dev);
for (unsigned idx = 0 ; idx < dev->width() ; idx += 1)
connect(dev->pin_Result(idx), osig->pin(idx));
connect(dev->pin_Result(), osig->pin(0));
assert(lsig->pin_count() >= dev->width());
for (unsigned idx = 0 ; idx < dev->width() ; idx += 1)
connect(dev->pin_Data(idx), lsig->pin(idx));
assert(lsig->vector_width() == dev->width());
connect(dev->pin_Data(), lsig->pin(0));
for (unsigned idx = 0 ; idx < dev->width_dist() ; idx += 1)
connect(dev->pin_Distance(idx), rsig->pin(idx));
connect(dev->pin_Distance(), rsig->pin(0));
return osig;
}
@ -850,6 +845,9 @@ NetNet* NetESignal::synthesize(Design*des)
/*
* $Log: expr_synth.cc,v $
* Revision 1.64 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.63 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.142 2005/02/14 01:51:39 steve Exp $"
#ident "$Id: ivl_target.h,v 1.143 2005/02/19 02:43:38 steve Exp $"
#endif
#ifdef __cplusplus
@ -766,6 +766,11 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* the concatentation. The ivl_lpm_size function returns the number of
* inputs help by the device.
*
* - Divide (IVL_LPM_DIVIDE)
* The divide operators take two inputs and generate an output. The
* ivl_lpm_width returns the width of the result. The width of the
* inputs are their own.
*
* - Multiply (IVL_LPM_MULT)
* The multiply takes two inputs and generates an output. Unlike other
* arithmetic nodes, the width only refers to the output. The inputs
@ -833,6 +838,12 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* vector. The ivl_lpm_size() returns the number of times the input is
* repeated to get the desired width. The ivl core assures that the
* input vector is exactly ivl_lpm_width() / ivl_lpm_size() bits.
*
* - Shifts (IVL_LPM_SHIFTL/SHIFTR)
* This node takes two inputs, a vector and a shift distance. The
* ivl_lpm_data(0) nexus is the vector input, and the ivl_lpm_data(1)
* the shift distance. The vector input is the same width as the
* output, but the distance has its own width.
*/
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
@ -858,7 +869,7 @@ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SUB */
IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB */
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
@ -1516,6 +1527,9 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.143 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.142 2005/02/14 01:51:39 steve
* Handle bit selects in l-values to assignments.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.237 2005/02/12 06:25:40 steve Exp $"
#ident "$Id: netlist.cc,v 1.238 2005/02/19 02:43:38 steve Exp $"
#endif
# include "config.h"
@ -842,39 +842,23 @@ const Link& NetAddSub::pin_Result() const
/*
* The pinout for the NetCLShift is:
* 0 -- Direction
* 1 -- Underflow
* 2 -- Overflow
* 3 -- Data(0)
* 3+W -- Result(0)
* 3+2W -- Distance(0)
* 0 -- Result
* 1 -- Data
* 2 -- Distance
*/
NetCLShift::NetCLShift(NetScope*s, perm_string n,
unsigned width, unsigned width_dist,
bool right_flag, bool signed_flag)
: NetNode(s, n, 3+2*width+width_dist),
: NetNode(s, n, 3),
width_(width), width_dist_(width_dist),
right_flag_(right_flag), signed_flag_(signed_flag)
{
pin(0).set_dir(Link::INPUT); pin(0).set_name(
perm_string::literal("Direction"), 0);
pin(1).set_dir(Link::OUTPUT); pin(1).set_name(
perm_string::literal("Underflow"), 0);
pin(2).set_dir(Link::OUTPUT); pin(2).set_name(
perm_string::literal("Overflow"), 0);
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
pin(3+idx).set_dir(Link::INPUT);
pin(3+idx).set_name(perm_string::literal("Data"), idx);
pin(3+width_+idx).set_dir(Link::OUTPUT);
pin(3+width_+idx).set_name(perm_string::literal("Result"), idx);
}
for (unsigned idx = 0 ; idx < width_dist_ ; idx += 1) {
pin(3+2*width_+idx).set_dir(Link::INPUT);
pin(3+2*width_+idx).set_name(perm_string::literal("Distance"), idx);
}
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("Data"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("Distance"), 0);
}
NetCLShift::~NetCLShift()
@ -901,74 +885,36 @@ bool NetCLShift::signed_flag() const
return signed_flag_;
}
#if 0
Link& NetCLShift::pin_Direction()
{
return pin(0);
}
const Link& NetCLShift::pin_Direction() const
{
return pin(0);
}
#endif
Link& NetCLShift::pin_Underflow()
Link& NetCLShift::pin_Data()
{
return pin(1);
}
const Link& NetCLShift::pin_Underflow() const
const Link& NetCLShift::pin_Data() const
{
return pin(1);
}
Link& NetCLShift::pin_Overflow()
Link& NetCLShift::pin_Result()
{
return pin(0);
}
const Link& NetCLShift::pin_Result() const
{
return pin(0);
}
Link& NetCLShift::pin_Distance()
{
return pin(2);
}
const Link& NetCLShift::pin_Overflow() const
const Link& NetCLShift::pin_Distance() const
{
return pin(2);
}
Link& NetCLShift::pin_Data(unsigned idx)
{
assert(idx < width_);
return pin(3+idx);
}
const Link& NetCLShift::pin_Data(unsigned idx) const
{
assert(idx < width_);
return pin(3+idx);
}
Link& NetCLShift::pin_Result(unsigned idx)
{
assert(idx < width_);
return pin(3+width_+idx);
}
const Link& NetCLShift::pin_Result(unsigned idx) const
{
assert(idx < width_);
return pin(3+width_+idx);
}
Link& NetCLShift::pin_Distance(unsigned idx)
{
assert(idx < width_dist_);
return pin(3+2*width_+idx);
}
const Link& NetCLShift::pin_Distance(unsigned idx) const
{
assert(idx < width_dist_);
return pin(3+2*width_+idx);
}
NetCompare::NetCompare(NetScope*s, perm_string n, unsigned wi)
: NetNode(s, n, 10), width_(wi)
{
@ -1116,22 +1062,15 @@ const Link& NetCompare::pin_DataB() const
NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
unsigned wa, unsigned wb)
: NetNode(sc, n, wr+wa+wb),
: NetNode(sc, n, 3),
width_r_(wr), width_a_(wa), width_b_(wb), signed_flag_(false)
{
unsigned p = 0;
for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) {
pin(p).set_dir(Link::OUTPUT);
pin(p).set_name(perm_string::literal("Result"), idx);
}
for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) {
pin(p).set_dir(Link::INPUT);
pin(p).set_name(perm_string::literal("DataA"), idx);
}
for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) {
pin(p).set_dir(Link::INPUT);
pin(p).set_name(perm_string::literal("DataB"), idx);
}
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
}
NetDivide::~NetDivide()
@ -1163,40 +1102,34 @@ bool NetDivide::get_signed() const
return signed_flag_;
}
Link& NetDivide::pin_Result(unsigned idx)
Link& NetDivide::pin_Result()
{
assert(idx < width_r_);
return pin(idx);
return pin(0);
}
const Link& NetDivide::pin_Result(unsigned idx) const
const Link& NetDivide::pin_Result() const
{
assert(idx < width_r_);
return pin(idx);
return pin(0);
}
Link& NetDivide::pin_DataA(unsigned idx)
Link& NetDivide::pin_DataA()
{
assert(idx < width_a_);
return pin(idx+width_r_);
return pin(1);
}
const Link& NetDivide::pin_DataA(unsigned idx) const
const Link& NetDivide::pin_DataA() const
{
assert(idx < width_a_);
return pin(idx+width_r_);
return pin(1);
}
Link& NetDivide::pin_DataB(unsigned idx)
Link& NetDivide::pin_DataB()
{
assert(idx < width_b_);
return pin(idx+width_r_+width_a_);
return pin(2);
}
const Link& NetDivide::pin_DataB(unsigned idx) const
const Link& NetDivide::pin_DataB() const
{
assert(idx < width_b_);
return pin(idx+width_r_+width_a_);
return pin(2);
}
NetMult::NetMult(NetScope*sc, perm_string n, unsigned wr,
@ -2258,6 +2191,9 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.238 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.237 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.334 2005/02/12 06:25:40 steve Exp $"
#ident "$Id: netlist.h,v 1.335 2005/02/19 02:43:38 steve Exp $"
#endif
/*
@ -506,19 +506,13 @@ class NetCLShift : public NetNode {
bool right_flag() const;
bool signed_flag() const;
Link& pin_Direction();
Link& pin_Underflow();
Link& pin_Overflow();
Link& pin_Data(unsigned idx);
Link& pin_Result(unsigned idx);
Link& pin_Distance(unsigned idx);
Link& pin_Data();
Link& pin_Result();
Link& pin_Distance();
const Link& pin_Direction() const;
const Link& pin_Underflow() const;
const Link& pin_Overflow() const;
const Link& pin_Data(unsigned idx) const;
const Link& pin_Result(unsigned idx) const;
const Link& pin_Distance(unsigned idx) const;
const Link& pin_Data() const;
const Link& pin_Result() const;
const Link& pin_Distance() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
@ -639,13 +633,13 @@ class NetDivide : public NetNode {
void set_signed(bool);
bool get_signed() const;
Link& pin_DataA(unsigned idx);
Link& pin_DataB(unsigned idx);
Link& pin_Result(unsigned idx);
Link& pin_DataA();
Link& pin_DataB();
Link& pin_Result();
const Link& pin_DataA(unsigned idx) const;
const Link& pin_DataB(unsigned idx) const;
const Link& pin_Result(unsigned idx) const;
const Link& pin_DataA() const;
const Link& pin_DataB() const;
const Link& pin_Result() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
@ -3420,6 +3414,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.335 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.334 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.118 2005/02/12 06:25:40 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.119 2005/02/19 02:43:38 steve Exp $"
#endif
# include "config.h"
@ -770,8 +770,11 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
assert(idx < net->u_.shift.width);
return net->u_.shift.d[idx];
assert(idx <= 1);
if (idx == 0)
return net->u_.shift.d;
else
return net->u_.shift.s;
case IVL_LPM_FF:
case IVL_LPM_RAM:
@ -933,8 +936,8 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
assert(idx < net->u_.shift.width);
return net->u_.shift.q[idx];
assert(idx == 0);
return net->u_.shift.q;
case IVL_LPM_UFUNC:
assert(idx < net->u_.ufunc.port_wid[0]);
@ -978,11 +981,6 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
assert(idx == 0);
return net->u_.mux.s;
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
assert(idx < net->u_.shift.select);
return net->u_.shift.s[idx];
default:
assert(0);
return 0;
@ -996,9 +994,6 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
return net->u_.ff.swid;
case IVL_LPM_MUX:
return net->u_.mux.swid;
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
return net->u_.shift.select;
case IVL_LPM_CONCAT:
return net->u_.concat.inputs;
default:
@ -1992,6 +1987,9 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.119 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.118 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,

111
t-dll.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.141 2005/02/13 01:15:07 steve Exp $"
#ident "$Id: t-dll.cc,v 1.142 2005/02/19 02:43:38 steve Exp $"
#endif
# include "config.h"
@ -1211,46 +1211,26 @@ void dll_target::lpm_clshift(const NetCLShift*net)
obj->u_.shift.width = net->width();
obj->u_.shift.select = net->width_dist();
unsigned nex_count = obj->u_.shift.width * 2 + obj->u_.shift.select;
obj->u_.shift.q = new ivl_nexus_t[nex_count];
obj->u_.shift.d = obj->u_.shift.q + obj->u_.shift.width;
obj->u_.shift.s = obj->u_.shift.d + obj->u_.shift.width;
for (unsigned idx = 0 ; idx < nex_count ; idx += 1)
obj->u_.shift.q[idx] = 0;
const Nexus*nex;
for (unsigned idx = 0 ; idx < net->width() ; idx += 1) {
const Nexus*nex;
nex = net->pin_Result().nexus();
assert(nex->t_cookie());
nex = net->pin_Result(idx).nexus();
assert(nex && nex->t_cookie());
obj->u_.shift.q = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.shift.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
obj->u_.shift.q[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.shift.q[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
}
nex = net->pin_Data().nexus();
assert(nex->t_cookie());
for (unsigned idx = 0 ; idx < net->width() ; idx += 1) {
const Nexus*nex;
obj->u_.shift.d = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.shift.d, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
nex = net->pin_Data(idx).nexus();
assert(nex && nex->t_cookie());
nex = net->pin_Distance().nexus();
assert(nex->t_cookie());
obj->u_.shift.d[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.shift.q[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
for (unsigned idx = 0 ; idx < net->width_dist() ; idx += 1) {
const Nexus*nex;
nex = net->pin_Distance(idx).nexus();
assert(nex && nex->t_cookie());
obj->u_.shift.s[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.shift.s[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
obj->u_.shift.s = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.shift.s, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
scope_add_lpm(obj->scope, obj);
}
@ -1373,62 +1353,28 @@ void dll_target::lpm_divide(const NetDivide*net)
obj->u_.arith.width = wid;
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
#if 0
obj->u_.arith.q = new ivl_nexus_t[3 * obj->u_.arith.width];
obj->u_.arith.a = obj->u_.arith.q + obj->u_.arith.width;
obj->u_.arith.b = obj->u_.arith.a + obj->u_.arith.width;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
const Nexus*nex;
const Nexus*nex;
nex = net->pin_Result(idx).nexus();
assert(nex->t_cookie());
nex = net->pin_Result().nexus();
assert(nex->t_cookie());
obj->u_.arith.q[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.q[idx], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
if (idx < net->width_a()) {
nex = net->pin_DataA(idx).nexus();
assert(nex);
assert(nex->t_cookie());
nex = net->pin_DataA().nexus();
assert(nex->t_cookie());
obj->u_.arith.a[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.a[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
} else if (obj->u_.arith.signed_flag) {
/* If this is signed divide, sign extend the perand. */
nex = net->pin_DataA(net->width_a()-1).nexus();
assert(nex);
assert(nex->t_cookie());
nex = net->pin_DataB().nexus();
assert(nex->t_cookie());
obj->u_.arith.a[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.a[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
} else {
/* Unsigned divide: pad the operand. */
obj->u_.arith.a[idx] = 0;
}
obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
if (idx < net->width_b()) {
nex = net->pin_DataB(idx).nexus();
assert(nex);
assert(nex->t_cookie());
obj->u_.arith.b[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.arith.b[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
} else {
obj->u_.arith.b[idx] = 0;
}
}
#else
cerr << "XXXX t-dll.cc: Forgot how to handle lpm_divide." << endl;
#endif
scope_add_lpm(obj->scope, obj);
}
@ -2222,6 +2168,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.142 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.141 2005/02/13 01:15:07 steve
* Replace supply nets with wires connected to pullup/down supply devices.
*

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.121 2005/02/12 06:25:40 steve Exp $"
#ident "$Id: t-dll.h,v 1.122 2005/02/19 02:43:39 steve Exp $"
#endif
# include "target.h"
@ -325,9 +325,7 @@ struct ivl_lpm_s {
unsigned width;
unsigned select;
unsigned signed_flag :1;
ivl_nexus_t*q;
ivl_nexus_t*d;
ivl_nexus_t*s;
ivl_nexus_t q, d, s;
} shift;
struct ivl_lpm_arith_s {
@ -687,6 +685,9 @@ struct ivl_variable_s {
/*
* $Log: t-dll.h,v $
* Revision 1.122 2005/02/19 02:43:39 steve
* Support shifts and divide.
*
* Revision 1.121 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.110 2005/02/13 01:15:07 steve Exp $"
#ident "$Id: stub.c,v 1.111 2005/02/19 02:43:39 steve Exp $"
#endif
# include "config.h"
@ -270,6 +270,16 @@ static void show_lpm_add(ivl_lpm_t net)
show_lpm_arithmetic_pins(net);
}
static void show_lpm_divide(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
fprintf(out, " LPM_DIVIDE %s: <width=%u>\n",
ivl_lpm_basename(net), width);
show_lpm_arithmetic_pins(net);
}
/* IVL_LPM_CMP_EEQ
* This LPM node supports two-input compare. The output width is
* actually always 1, the lpm_width is the expected width of the inputs.
@ -430,6 +440,36 @@ static void show_lpm_mux(ivl_lpm_t net)
}
}
static void show_lpm_part(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
unsigned base = ivl_lpm_base(net);
const char*part_type_string = "";
switch (ivl_lpm_type(net)) {
case IVL_LPM_PART_VP:
part_type_string = "VP";
break;
case IVL_LPM_PART_PV:
part_type_string = "PV";
break;
default:
break;
}
fprintf(out, " LPM_PART_%s %s: <width=%u, base=%u, signed=%d>\n",
part_type_string, ivl_lpm_basename(net),
width, base, ivl_lpm_signed(net));
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
fprintf(out, " I: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
/* The compiler must assure that the base plus the part select
width fits within the input to the part select. */
if (width_of_nexus(ivl_lpm_data(net,0)) < (width+base)) {
fprintf(out, " ERROR: Part select is out of range.\n");
stub_errors += 1;
}
}
/*
* The reduction operators have similar characteristics and are
@ -524,25 +564,9 @@ static void show_lpm(ivl_lpm_t net)
show_lpm_add(net);
break;
case IVL_LPM_DIVIDE: {
fprintf(out, " LPM_DIVIDE %s: <width=%u %s>\n",
ivl_lpm_basename(net), width,
ivl_lpm_signed(net)? "signed" : "unsigned");
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Q %u: %s\n", idx,
ivl_nexus_name(ivl_lpm_q(net, idx)));
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_data(net, idx);
fprintf(out, " Data A %u: %s\n", idx,
nex? ivl_nexus_name(nex) : "");
}
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_datab(net, idx);
fprintf(out, " Data B %u: %s\n", idx,
nex? ivl_nexus_name(nex) : "");
}
break;
}
case IVL_LPM_DIVIDE:
show_lpm_divide(net);
break;
case IVL_LPM_CMP_EEQ:
show_lpm_cmp_eeq(net);
@ -643,23 +667,10 @@ static void show_lpm(ivl_lpm_t net)
show_lpm_mux(net);
break;
case IVL_LPM_PART_VP: {
fprintf(out, " LPM_PART_VP %s: <width=%u, base=%u, signed=%d>\n",
ivl_lpm_basename(net),
width, ivl_lpm_base(net), ivl_lpm_signed(net));
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
fprintf(out, " I: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
break;
}
case IVL_LPM_PART_PV: {
fprintf(out, " LPM_PART_PV %s: <width=%u, base=%u, signed=%d>\n",
ivl_lpm_basename(net),
width, ivl_lpm_base(net), ivl_lpm_signed(net));
fprintf(out, " O: %s\n", ivl_nexus_name(ivl_lpm_q(net,0)));
fprintf(out, " I: %s\n", ivl_nexus_name(ivl_lpm_data(net,0)));
break;
}
case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
show_lpm_part(net);
break;
case IVL_LPM_REPEAT:
show_lpm_repeat(net);
@ -1111,6 +1122,9 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.111 2005/02/19 02:43:39 steve
* Support shifts and divide.
*
* Revision 1.110 2005/02/13 01:15:07 steve
* Replace supply nets with wires connected to pullup/down supply devices.
*