Patch to synthesize LPM_ADD_SUB from expressions,

Thanks to Larry Doolittle. Also handle constants
 in expressions.

 Synthesize adders in XNF, based on a patch from
 Larry. Accept synthesis of constants from Larry
 as is.
This commit is contained in:
steve 1999-11-05 04:40:40 +00:00
parent cb5fc54b5e
commit 2cce0ce238
4 changed files with 274 additions and 6 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: expr_synth.cc,v 1.2 1999/11/04 03:53:26 steve Exp $"
#ident "$Id: expr_synth.cc,v 1.3 1999/11/05 04:40:40 steve Exp $"
#endif
# include "netlist.h"
@ -31,6 +31,44 @@ NetNet* NetExpr::synthesize(Design*des)
return 0;
}
/*
* Make an LPM_ADD_SUB device from addition operators.
*/
NetNet* NetEBAdd::synthesize(Design*des)
{
assert((op()=='+') || (op()=='-'));
string path = des->local_symbol("SYNTH");
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
assert(lsig->pin_count() == rsig->pin_count());
unsigned width=lsig->pin_count();
NetNet*osig = new NetNet(path, NetNet::IMPLICIT, width);
string oname = des->local_symbol(path);
NetAddSub *adder = new NetAddSub(oname, width);
for (unsigned idx = 0 ; idx < width; idx += 1) {
connect(lsig->pin(idx), adder->pin_DataA(idx));
connect(rsig->pin(idx), adder->pin_DataB(idx));
connect(osig->pin(idx), adder->pin_Result(idx));
}
des->add_node(adder);
des->add_signal(osig);
switch (op()) {
case '+':
adder->attribute("LPM_Direction", "ADD");
break;
case '-':
adder->attribute("LPM_Direction", "SUB");
break;
}
return osig;
}
/*
* The bitwise logic operators are turned into discrete gates pretty
* easily. Synthesize the left and right sub-expressions to get
@ -81,6 +119,22 @@ NetNet* NetEBBits::synthesize(Design*des)
return osig;
}
NetNet* NetEConst::synthesize(Design*des)
{
string path = des->local_symbol("SYNTH");
unsigned width=expr_width();
NetNet*osig = new NetNet(path, NetNet::IMPLICIT, width);
for (unsigned idx = 0 ; idx < width; idx += 1) {
string oname = des->local_symbol(path);
NetConst *c = new NetConst(oname, value().get(idx));
connect(osig->pin(idx), c->pin(0));
des->add_node(c);
}
des->add_signal(osig);
return osig;
}
/*
* The bitwise unary logic operator (there is only one) is turned
* into discrete gates just as easily as the binary ones above.
@ -150,6 +204,15 @@ NetNet* NetESignal::synthesize(Design*des)
/*
* $Log: expr_synth.cc,v $
* Revision 1.3 1999/11/05 04:40:40 steve
* Patch to synthesize LPM_ADD_SUB from expressions,
* Thanks to Larry Doolittle. Also handle constants
* in expressions.
*
* Synthesize adders in XNF, based on a patch from
* Larry. Accept synthesis of constants from Larry
* as is.
*
* Revision 1.2 1999/11/04 03:53:26 steve
* Patch to synthesize unary ~ and the ternary operator.
* Thanks to Larry Doolittle <LRDoolittle@lbl.gov>.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: netlist.cc,v 1.82 1999/11/04 03:53:26 steve Exp $"
#ident "$Id: netlist.cc,v 1.83 1999/11/05 04:40:40 steve Exp $"
#endif
# include <cassert>
@ -555,6 +555,13 @@ NetObj::Link& NetAddSub::pin_DataA(unsigned idx)
return pin(idx);
}
const NetObj::Link& NetAddSub::pin_DataA(unsigned idx) const
{
idx = 6 + idx*3;
assert(idx < pin_count());
return pin(idx);
}
NetObj::Link& NetAddSub::pin_DataB(unsigned idx)
{
idx = 7 + idx*3;
@ -562,6 +569,13 @@ NetObj::Link& NetAddSub::pin_DataB(unsigned idx)
return pin(idx);
}
const NetObj::Link& NetAddSub::pin_DataB(unsigned idx) const
{
idx = 7 + idx*3;
assert(idx < pin_count());
return pin(idx);
}
NetObj::Link& NetAddSub::pin_Result(unsigned idx)
{
idx = 8 + idx*3;
@ -602,7 +616,7 @@ NetMux::NetMux(const string&n, unsigned wi, unsigned si, unsigned sw)
}
for (unsigned idx = 0 ; idx < swidth_ ; idx += 1) {
pin_Sel(idx).set_dir(Link::OUTPUT);
pin_Sel(idx).set_dir(Link::INPUT);
pin_Sel(idx).set_name("Sel", idx);
}
}
@ -2090,6 +2104,15 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/*
* $Log: netlist.cc,v $
* Revision 1.83 1999/11/05 04:40:40 steve
* Patch to synthesize LPM_ADD_SUB from expressions,
* Thanks to Larry Doolittle. Also handle constants
* in expressions.
*
* Synthesize adders in XNF, based on a patch from
* Larry. Accept synthesis of constants from Larry
* as is.
*
* Revision 1.82 1999/11/04 03:53:26 steve
* Patch to synthesize unary ~ and the ternary operator.
* Thanks to Larry Doolittle <LRDoolittle@lbl.gov>.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: netlist.h,v 1.85 1999/11/04 03:53:26 steve Exp $"
#ident "$Id: netlist.h,v 1.86 1999/11/05 04:40:40 steve Exp $"
#endif
/*
@ -317,6 +317,8 @@ class NetAddSub : public NetNode {
NetObj::Link& pin_DataB(unsigned idx);
NetObj::Link& pin_Result(unsigned idx);
const NetObj::Link& pin_DataA(unsigned idx) const;
const NetObj::Link& pin_DataB(unsigned idx) const;
const NetObj::Link& pin_Result(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
@ -493,7 +495,7 @@ class NetExpr : public LineInfo {
/*
* The expression constant is slightly special, and is sometimes
* retured from other classes that can be evaluated at compile
* returned from other classes that can be evaluated at compile
* time. This class represents constant values in expressions.
*/
class NetEConst : public NetExpr {
@ -509,6 +511,7 @@ class NetEConst : public NetExpr {
virtual void dump(ostream&) const;
virtual NetEConst* dup_expr() const;
virtual NetNet*synthesize(Design*);
private:
verinum value_;
@ -1339,6 +1342,7 @@ class NetEBAdd : public NetEBinary {
virtual bool set_width(unsigned w);
virtual NetEBAdd* dup_expr() const;
virtual NetEConst* eval_tree();
virtual NetNet* synthesize(Design*);
};
/*
@ -1854,6 +1858,15 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.86 1999/11/05 04:40:40 steve
* Patch to synthesize LPM_ADD_SUB from expressions,
* Thanks to Larry Doolittle. Also handle constants
* in expressions.
*
* Synthesize adders in XNF, based on a patch from
* Larry. Accept synthesis of constants from Larry
* as is.
*
* Revision 1.85 1999/11/04 03:53:26 steve
* Patch to synthesize unary ~ and the ternary operator.
* Thanks to Larry Doolittle <LRDoolittle@lbl.gov>.

171
t-xnf.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: t-xnf.cc,v 1.11 1999/11/04 03:53:26 steve Exp $"
#ident "$Id: t-xnf.cc,v 1.12 1999/11/05 04:40:40 steve Exp $"
#endif
/* XNF BACKEND
@ -71,9 +71,11 @@ class target_xnf : public target_t {
void end_design(ostream&os, const Design*);
void signal(ostream&os, const NetNet*);
void lpm_add_sub(ostream&os, const NetAddSub*);
void lpm_ff(ostream&os, const NetFF*);
void lpm_mux(ostream&os, const NetMux*);
void net_const(ostream&os, const NetConst*);
void logic(ostream&os, const NetLogic*);
void bufz(ostream&os, const NetBUFZ*);
void udp(ostream&os, const NetUDP*);
@ -259,6 +261,142 @@ void target_xnf::signal(ostream&os, const NetNet*net)
<< ", " << num << endl;
}
/*
* This function makes an adder out of carry logic symbols. It makes
* as many 2 bit adders as are possible, then the top bit is made into
* a 1-bit adder (with carry in) in the F unit. The low carry is
* initialized with the FORCE-0 configuration of a carry unit below
* the 0 bit. This takes up the carry logic of the CLB below, but not
* the G function.
*
* References:
* XNF 6.1 Specification
* Application note XAPP 013
*/
void target_xnf::lpm_add_sub(ostream&os, const NetAddSub*gate)
{
// Keep people from thinking this really works.
//assert(0);
unsigned width = gate->width();
string name = mangle(gate->name());
/* Make the force-0 cary mode object to initialize the bottom
bits of the carry chain. Label this with the width instead
of the bit position so that symbols dont clash. */
os << "SYM, " << name << name << "<" << width << ">, CY4, "
"LIBVER=2.0.0" << endl;
os << " PIN, COUT, O, " << name << "/COUT<0>" << endl;
for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
os << " PIN, C" << cn << ", I, " << name << "/C"
<< cn << "<" << width << ">" << endl;
}
os << "END" << endl;
os << "SYM, " << name << "/C<" << width << ">, CY4_37, "
"CYMODE=FORCE-0" << endl;
for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
os << " PIN, C" << cn << ", O, " << name << "/C"
<< cn << "<" << width << ">" << endl;
}
os << "END" << endl;
/* Now make the 2 bit adders that chain from the cin
initializer and up. Safe the tail bit (if there is one) for
later. */
for (unsigned idx = 0 ; idx < (width&~1) ; idx += 2) {
os << "SYM, " << name << "<" << idx << ">, CY4, "
"LIBVER=2.0.0" << endl;
draw_pin(os, "A0", gate->pin_DataA(idx+0));
draw_pin(os, "B0", gate->pin_DataB(idx+0));
draw_pin(os, "A1", gate->pin_DataA(idx+1));
draw_pin(os, "B1", gate->pin_DataB(idx+1));
// Connect the Cout to the next Cin
if ((idx+2) < width)
os << " PIN, COUT, O, " << name << "/COUT<" <<
(idx+1) << ">" << endl;
// Connect the Cin to the previous Cout
if (idx > 0)
os << " PIN, CIN, I, " << name << "/COUT<" <<
(idx-1) << ">" << endl;
else
os << " PIN, CIN, I, " << name << "/COUT<" <<
(width) << ">" << endl;
for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
os << " PIN, C" << cn << ", I, " << name << "/C"
<< cn << "<" << idx << ">" << endl;
}
os << "END" << endl;
os << "SYM, " << name << "/C<" << idx << ">, ";
os << "CY4_02, CYMODE=ADD-FG-CI" << endl;
for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
os << " PIN, C" << cn << ", O, " << name << "/C"
<< cn << "<" << idx << ">" << endl;
}
os << "END" << endl;
}
/* If there is a tail bit, draw it as a single bit adder that
takes its carry in from the previously drawn adder. */
if (width%2) {
os << "SYM, " << name << "<" << (width-1) << ">, CY4, "
"LIBVER=2.0.0" << endl;
draw_pin(os, "A0", gate->pin_DataA(width-1));
draw_pin(os, "B0", gate->pin_DataB(width-1));
if (width > 2)
os << " PIN, CIN, I, " << name << "/COUT<" <<
(width-2) << ">" << endl;
for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
os << " PIN, C" << cn << ", I, " << name << "/C"
<< cn << "<" << (width-1) << ">" << endl;
}
os << "END" << endl;
os << "SYM, " << name << "/C<" << (width-1) << ">, ";
os << "CY4_01, CYMODE=ADD-F-CI" << endl;
for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
os << " PIN, C" << cn << ", O, " << name << "/C"
<< cn << "<" << (width-1) << ">" << endl;
}
os << "END" << endl;
}
#if 0
for (unsigned idx = 0 ; idx < width ; idx += 1) {
os << "SYM, " << name << "/C<" << idx << ">, CY4, LIBVER=2.0.0" << endl;
draw_pin(os, "A0", gate->pin_DataA(idx));
draw_pin(os, "B0", gate->pin_DataB(idx));
// if (idx==0) draw_pin(os, "CIN", gate->pin_Cin());
os << " PIN, CIN, I, " << name << "/CY<" << idx << ">" << endl;
// if (idx+1==width) draw_pin(os, "COUT", gate->pin_Cout());
os << " PIN, COUT, I, " << name << "/CY<" << idx+1 << ">" << endl;
os << "END" << endl;
os << "SYM, " << name << "/X<" << idx << ">, XOR, LIBVER=2.0.0" << endl;
draw_pin(os, "O", gate->pin_Result(idx));
draw_pin(os, "I0", gate->pin_DataA(idx));
draw_pin(os, "I1", gate->pin_DataB(idx));
// if (idx==0) draw_pin(os, "CIN", gate->pin_Cin());
os << " PIN, I2, I, " << name << "/CY<" << idx << ">" << endl;
os << "END" << endl;
}
os << "PWR, 0, " << name << "/CY<0>" << endl;
#endif
}
void target_xnf::lpm_ff(ostream&os, const NetFF*net)
{
string type = net->attribute("LPM_FFType");
@ -315,6 +453,28 @@ void target_xnf::lpm_mux(ostream&os, const NetMux*net)
}
void target_xnf::net_const(ostream&os, const NetConst*c)
{
verinum::V v=c->value();
assert(v==verinum::V0 || v==verinum::V1);
const NetObj::Link& lnk = c->pin(0);
// Code parallels draw_pin above, some smart c++ guru should
// find a way to make a method out of this.
unsigned cpin;
const NetObj*cur;
for (lnk.next_link(cur, cpin)
; cur->pin(cpin) != lnk
; cur->pin(cpin).next_link(cur, cpin)) {
const NetNet*sig = dynamic_cast<const NetNet*>(cur);
if (sig) {
os << "PWR, " << v << ", " << mangle(sig->name());
if (sig->pin_count() > 1)
os << "<" << cpin << ">";
os << endl;
}
}
}
/*
* The logic gates I know so far can be translated directly into XNF
@ -411,6 +571,15 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
/*
* $Log: t-xnf.cc,v $
* Revision 1.12 1999/11/05 04:40:40 steve
* Patch to synthesize LPM_ADD_SUB from expressions,
* Thanks to Larry Doolittle. Also handle constants
* in expressions.
*
* Synthesize adders in XNF, based on a patch from
* Larry. Accept synthesis of constants from Larry
* as is.
*
* Revision 1.11 1999/11/04 03:53:26 steve
* Patch to synthesize unary ~ and the ternary operator.
* Thanks to Larry Doolittle <LRDoolittle@lbl.gov>.