From b354cf68b80806a6a3a1d57edaaffa4730f03743 Mon Sep 17 00:00:00 2001 From: steve Date: Wed, 16 Feb 2000 03:58:27 +0000 Subject: [PATCH] Fix up width matching in structural bitwise operators. --- PExpr.h | 12 ++- elab_net.cc | 207 ++++++++++++++++++++++++++++++------------------ netmisc.h | 7 +- pad_to_width.cc | 25 +++++- 4 files changed, 167 insertions(+), 84 deletions(-) diff --git a/PExpr.h b/PExpr.h index bb96e81c0..347589a89 100644 --- a/PExpr.h +++ b/PExpr.h @@ -1,7 +1,7 @@ #ifndef __PExpr_H #define __PExpr_H /* - * Copyright (c) 1998-1999 Stephen Williams + * Copyright (c) 1998-2000 Stephen Williams * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: PExpr.h,v 1.27 2000/01/13 03:35:35 steve Exp $" +#ident "$Id: PExpr.h,v 1.28 2000/02/16 03:58:27 steve Exp $" #endif # include @@ -254,6 +254,11 @@ class PEBinary : public PExpr { unsigned long rise, unsigned long fall, unsigned long decay) const; + NetNet* elaborate_net_bit_(Design*des, const string&path, + unsigned lwidth, + unsigned long rise, + unsigned long fall, + unsigned long decay) const; NetNet* elaborate_net_cmp_(Design*des, const string&path, unsigned lwidth, unsigned long rise, @@ -323,6 +328,9 @@ class PECallFunction : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.28 2000/02/16 03:58:27 steve + * Fix up width matching in structural bitwise operators. + * * Revision 1.27 2000/01/13 03:35:35 steve * Multiplication all the way to simulation. * diff --git a/elab_net.cc b/elab_net.cc index 0bad2de34..73f0543fd 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -17,11 +17,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: elab_net.cc,v 1.21 2000/02/14 06:04:52 steve Exp $" +#ident "$Id: elab_net.cc,v 1.22 2000/02/16 03:58:27 steve Exp $" #endif # include "PExpr.h" # include "netlist.h" +# include "netmisc.h" /* * Elaborating binary operations generally involves elaborating the @@ -42,6 +43,11 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path, case '+': case '-': return elaborate_net_add_(des, path, width, rise, fall, decay); + case '|': // Bitwise OR + case '&': + case '^': + case 'X': // Exclusing NOR + return elaborate_net_bit_(des, path, width, rise, fall, decay); case 'E': case 'e': case 'n': @@ -79,87 +85,10 @@ NetNet* PEBinary::elaborate_net(Design*des, const string&path, switch (op_) { case '^': // XOR - assert(lsig->pin_count() == rsig->pin_count()); - osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE, - lsig->pin_count()); - osig->local_flag(true); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { - gate = new NetLogic(des->local_symbol(path), 3, - NetLogic::XOR); - connect(gate->pin(1), lsig->pin(idx)); - connect(gate->pin(2), rsig->pin(idx)); - connect(gate->pin(0), osig->pin(idx)); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - } - des->add_signal(osig); - break; - case 'X': // XNOR - assert(lsig->pin_count() == rsig->pin_count()); - osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE, - lsig->pin_count()); - osig->local_flag(true); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { - gate = new NetLogic(des->local_symbol(path), 3, - NetLogic::XNOR); - connect(gate->pin(1), lsig->pin(idx)); - connect(gate->pin(2), rsig->pin(idx)); - connect(gate->pin(0), osig->pin(idx)); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - } - des->add_signal(osig); - break; - case '&': // AND - if (lsig->pin_count() != rsig->pin_count()) { - cerr << get_line() << ": internal error: lsig pin count (" - << lsig->pin_count() << ") != rsig pin count (" - << rsig->pin_count() << ")." << endl; - des->errors += 1; - return 0; - } - - assert(lsig->pin_count() == rsig->pin_count()); - osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE, - lsig->pin_count()); - osig->local_flag(true); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { - gate = new NetLogic(des->local_symbol(path), 3, - NetLogic::AND); - connect(gate->pin(1), lsig->pin(idx)); - connect(gate->pin(2), rsig->pin(idx)); - connect(gate->pin(0), osig->pin(idx)); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - } - des->add_signal(osig); - break; - case '|': // Bitwise OR - assert(lsig->pin_count() == rsig->pin_count()); - osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE, - lsig->pin_count()); - osig->local_flag(true); - for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { - gate = new NetLogic(des->local_symbol(path), 3, - NetLogic::OR); - connect(gate->pin(1), lsig->pin(idx)); - connect(gate->pin(2), rsig->pin(idx)); - connect(gate->pin(0), osig->pin(idx)); - gate->rise_time(rise); - gate->fall_time(fall); - gate->decay_time(decay); - des->add_node(gate); - } - des->add_signal(osig); + assert(0); break; case 'E': // === (Case equals) @@ -276,6 +205,123 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, const string&path, return osig; } +/* + * Elaborate various bitwise logic operators. These are all similar in + * that they take operants of equal width, and each bit does not + * affect any other bits. Also common about all this is how bit widths + * of the operands are handled, when they do not match. + */ +NetNet* PEBinary::elaborate_net_bit_(Design*des, const string&path, + unsigned width, + unsigned long rise, + unsigned long fall, + unsigned long decay) const +{ + NetNet*lsig = left_->elaborate_net(des, path, width, 0, 0, 0), + *rsig = right_->elaborate_net(des, path, width, 0, 0, 0); + if (lsig == 0) { + cerr << get_line() << ": error: Cannot elaborate "; + left_->dump(cerr); + cerr << endl; + return 0; + } + if (rsig == 0) { + cerr << get_line() << ": error: Cannot elaborate "; + right_->dump(cerr); + cerr << endl; + return 0; + } + + if (lsig->pin_count() < rsig->pin_count()) + lsig = pad_to_width(des, path, lsig, rsig->pin_count()); + if (rsig->pin_count() < lsig->pin_count()) + rsig = pad_to_width(des, path, rsig, lsig->pin_count()); + + if (lsig->pin_count() != rsig->pin_count()) { + cerr << get_line() << ": internal error: lsig pin count (" + << lsig->pin_count() << ") != rsig pin count (" + << rsig->pin_count() << ")." << endl; + des->errors += 1; + return 0; + } + + assert(lsig->pin_count() == rsig->pin_count()); + + NetNet*osig = new NetNet(0, des->local_symbol(path), NetNet::WIRE, + lsig->pin_count()); + osig->local_flag(true); + + switch (op_) { + case '^': // XOR + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + NetLogic*gate = new NetLogic(des->local_symbol(path), 3, + NetLogic::XOR); + connect(gate->pin(1), lsig->pin(idx)); + connect(gate->pin(2), rsig->pin(idx)); + connect(gate->pin(0), osig->pin(idx)); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + } + break; + + case 'X': // XNOR + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + NetLogic*gate = new NetLogic(des->local_symbol(path), 3, + NetLogic::XNOR); + connect(gate->pin(1), lsig->pin(idx)); + connect(gate->pin(2), rsig->pin(idx)); + connect(gate->pin(0), osig->pin(idx)); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + } + break; + + case '&': // AND + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + NetLogic*gate = new NetLogic(des->local_symbol(path), 3, + NetLogic::AND); + connect(gate->pin(1), lsig->pin(idx)); + connect(gate->pin(2), rsig->pin(idx)); + connect(gate->pin(0), osig->pin(idx)); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + } + break; + + case '|': // Bitwise OR + for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) { + NetLogic*gate = new NetLogic(des->local_symbol(path), + 3, NetLogic::OR); + connect(gate->pin(1), lsig->pin(idx)); + connect(gate->pin(2), rsig->pin(idx)); + connect(gate->pin(0), osig->pin(idx)); + gate->rise_time(rise); + gate->fall_time(fall); + gate->decay_time(decay); + des->add_node(gate); + } + break; + + default: + assert(0); + } + + des->add_signal(osig); + + if (NetTmp*tmp = dynamic_cast(lsig)) + delete tmp; + if (NetTmp*tmp = dynamic_cast(rsig)) + delete tmp; + + return osig; +} + /* * Elaborate the various binary comparison operators. The comparison * operators return a single bit result, no matter what, so the left @@ -1290,6 +1336,9 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path, /* * $Log: elab_net.cc,v $ + * Revision 1.22 2000/02/16 03:58:27 steve + * Fix up width matching in structural bitwise operators. + * * Revision 1.21 2000/02/14 06:04:52 steve * Unary reduction operators do not set their operand width * diff --git a/netmisc.h b/netmisc.h index 89eb272b6..861139e0a 100644 --- a/netmisc.h +++ b/netmisc.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: netmisc.h,v 1.1 1999/09/29 00:42:51 steve Exp $" +#ident "$Id: netmisc.h,v 1.2 2000/02/16 03:58:27 steve Exp $" #endif # include "netlist.h" @@ -31,10 +31,13 @@ * enough. */ extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid); - +extern NetNet*pad_to_width(Design*des, const string&p, NetNet*n, unsigned w); /* * $Log: netmisc.h,v $ + * Revision 1.2 2000/02/16 03:58:27 steve + * Fix up width matching in structural bitwise operators. + * * Revision 1.1 1999/09/29 00:42:51 steve * Allow expanding of additive operators. * diff --git a/pad_to_width.cc b/pad_to_width.cc index b077297d0..18fb968ea 100644 --- a/pad_to_width.cc +++ b/pad_to_width.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pad_to_width.cc,v 1.2 2000/01/01 06:17:25 steve Exp $" +#ident "$Id: pad_to_width.cc,v 1.3 2000/02/16 03:58:27 steve Exp $" #endif # include "netlist.h" @@ -45,9 +45,32 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid) return expr; } +NetNet*pad_to_width(Design*des, const string&path, NetNet*net, unsigned wid) +{ + if (net->pin_count() >= wid) + return net; + + verinum pad(verinum::V0, wid - net->pin_count()); + NetConst*con = new NetConst(des->local_symbol(path), pad); + des->add_node(con); + + NetNet*tmp = new NetNet(0, des->local_symbol(path), NetNet::WIRE, wid); + tmp->local_flag(true); + des->add_signal(tmp); + + for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) + connect(tmp->pin(idx), net->pin(idx)); + for (unsigned idx = net->pin_count() ; idx < wid ; idx += 1) + connect(tmp->pin(idx), con->pin(idx-net->pin_count())); + + return tmp; +} /* * $Log: pad_to_width.cc,v $ + * Revision 1.3 2000/02/16 03:58:27 steve + * Fix up width matching in structural bitwise operators. + * * Revision 1.2 2000/01/01 06:17:25 steve * Propogate line number information when expanding expressions. *