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:
parent
cb5fc54b5e
commit
2cce0ce238
|
|
@ -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>.
|
||||
|
|
|
|||
27
netlist.cc
27
netlist.cc
|
|
@ -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>.
|
||||
|
|
|
|||
17
netlist.h
17
netlist.h
|
|
@ -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
171
t-xnf.cc
|
|
@ -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>.
|
||||
|
|
|
|||
Loading…
Reference in New Issue