Add the synthesize method to NetExpr to handle

synthesis of expressions, and use that method
 to improve r-value handling of LPM_FF synthesis.

 Modify the XNF target to handle LPM_FF objects.
This commit is contained in:
steve 1999-11-02 04:55:34 +00:00
parent 73753f1337
commit b66e7b1713
8 changed files with 240 additions and 62 deletions

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.26 1999/11/01 02:07:40 steve Exp $"
#ident "$Id: Makefile.in,v 1.27 1999/11/02 04:55:34 steve Exp $"
#
#
SHELL = /bin/sh
@ -69,7 +69,7 @@ TT = t-null.o t-verilog.o t-vvm.o t-xnf.o
FF = nobufz.o propinit.o sigfold.o synth.o xnfio.o xnfsyn.o
O = main.o cprop.o design_dump.o elaborate.o elab_expr.o elab_net.o \
emit.o eval.o eval_tree.o functor.o \
emit.o eval.o eval_tree.o expr_synth.o functor.o \
lexor.o lexor_keyword.o mangle.o netlist.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o \
set_width.o \

103
expr_synth.cc Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: expr_synth.cc,v 1.1 1999/11/02 04:55:34 steve Exp $"
#endif
# include "netlist.h"
NetNet* NetExpr::synthesize(Design*des)
{
cerr << get_line() << ": internal error: cannot synthesize expression: "
<< *this << endl;
des->errors += 1;
return 0;
}
/*
* The bitwise logic operators are turned into discrete gates pretty
* easily. Synthesize the left and right sub-expressions to get
* signals, then just connect a single gate to each bit of the vector
* of the expression.
*/
NetNet* NetEBBits::synthesize(Design*des)
{
string path = des->local_symbol("SYNTH");
NetNet*lsig = left_->synthesize(des);
NetNet*rsig = right_->synthesize(des);
assert(lsig->pin_count() == rsig->pin_count());
NetNet*osig = new NetNet(path, NetNet::IMPLICIT, lsig->pin_count());
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
string oname = des->local_symbol(path);
NetLogic*gate;
switch (op()) {
case '&':
gate = new NetLogic(oname, 3, NetLogic::AND);
break;
case '|':
gate = new NetLogic(oname, 3, NetLogic::OR);
break;
case '^':
gate = new NetLogic(oname, 3, NetLogic::XOR);
break;
case 'O':
gate = new NetLogic(oname, 3, NetLogic::NOR);
break;
case 'X':
gate = new NetLogic(oname, 3, NetLogic::XNOR);
break;
default:
assert(0);
}
connect(osig->pin(idx), gate->pin(0));
connect(lsig->pin(idx), gate->pin(1));
connect(rsig->pin(idx), gate->pin(2));
des->add_node(gate);
}
des->add_signal(osig);
return osig;
}
NetNet* NetESignal::synthesize(Design*des)
{
NetNet*sig = new NetNet(name(), NetNet::WIRE, pin_count());
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1)
connect(sig->pin(idx), pin(idx));
des->add_signal(sig);
return sig;
}
/*
* $Log: expr_synth.cc,v $
* Revision 1.1 1999/11/02 04:55:34 steve
* Add the synthesize method to NetExpr to handle
* synthesis of expressions, and use that method
* to improve r-value handling of LPM_FF synthesis.
*
* Modify the XNF target to handle LPM_FF objects.
*
*/

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.79 1999/11/01 02:07:40 steve Exp $"
#ident "$Id: netlist.cc,v 1.80 1999/11/02 04:55:34 steve Exp $"
#endif
# include <cassert>
@ -433,11 +433,21 @@ NetObj::Link& NetFF::pin_Clock()
return pin(0);
}
const NetObj::Link& NetFF::pin_Clock() const
{
return pin(0);
}
NetObj::Link& NetFF::pin_Enable()
{
return pin(1);
}
const NetObj::Link& NetFF::pin_Enable() const
{
return pin(1);
}
NetObj::Link& NetFF::pin_Aload()
{
return pin(2);
@ -475,6 +485,13 @@ NetObj::Link& NetFF::pin_Data(unsigned w)
return pin(pn);
}
const NetObj::Link& NetFF::pin_Data(unsigned w) const
{
unsigned pn = 8 + 2*w;
assert(pn < pin_count());
return pin(pn);
}
NetObj::Link& NetFF::pin_Q(unsigned w)
{
unsigned pn = 9 + w*2;
@ -687,47 +704,6 @@ NetAssignMemNB::~NetAssignMemNB()
{
}
#if 0
/*
* This method looks at the objects connected to me, and searches for
* a signal that I am fully connected to. Return that signal, and the
* range of bits that I use.
*/
void NetAssign::find_lval_range(const NetNet*&net, unsigned&msb,
unsigned&lsb) const
{
const NetObj*cur;
unsigned cpin;
for (pin(0).next_link(cur,cpin) ; pin(0) != cur->pin(cpin)
; cur->pin(cpin).next_link(cur, cpin)) {
const NetNet*s = dynamic_cast<const NetNet*>(cur);
if (s == 0)
continue;
if (!connected(*this, *s))
continue;
unsigned idx;
for (idx = 1 ; idx < pin_count() ; idx += 1) {
if (idx+cpin > s->pin_count())
break;
if (! connected(pin(idx), s->pin(idx+cpin)))
break;
}
if (idx < pin_count())
continue;
net = s;
lsb = cpin;
msb = cpin+pin_count()-1;
return;
}
assert(0); // No suitable signals??
}
#endif
NetBlock::~NetBlock()
{
@ -1993,6 +1969,13 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/*
* $Log: netlist.cc,v $
* Revision 1.80 1999/11/02 04:55:34 steve
* Add the synthesize method to NetExpr to handle
* synthesis of expressions, and use that method
* to improve r-value handling of LPM_FF synthesis.
*
* Modify the XNF target to handle LPM_FF objects.
*
* Revision 1.79 1999/11/01 02:07:40 steve
* Add the synth functor to do generic synthesis
* and add the LPM_FF device to handle rows of

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.82 1999/11/01 02:07:40 steve Exp $"
#ident "$Id: netlist.h,v 1.83 1999/11/02 04:55:34 steve Exp $"
#endif
/*
@ -347,6 +347,9 @@ class NetFF : public NetNode {
NetObj::Link& pin_Data(unsigned);
NetObj::Link& pin_Q(unsigned);
const NetObj::Link& pin_Clock() const;
const NetObj::Link& pin_Enable() const;
const NetObj::Link& pin_Data(unsigned) const;
const NetObj::Link& pin_Q(unsigned) const;
virtual void dump_node(ostream&, unsigned ind) const;
@ -428,6 +431,11 @@ class NetExpr : public LineInfo {
// any. This is a deep copy operation.
virtual NetExpr*dup_expr() const =0;
// Return a version of myself that is structural. This is used
// for converting expressions to gates.
virtual NetNet*synthesize(Design*);
protected:
void expr_width(unsigned w) { width_ = w; }
@ -1306,6 +1314,8 @@ class NetEBBits : public NetEBinary {
virtual bool set_width(unsigned w);
virtual NetEBBits* dup_expr() const;
virtual NetNet* synthesize(Design*);
};
/*
@ -1600,6 +1610,8 @@ class NetESignal : public NetExpr, public NetNode {
virtual NetESignal* dup_expr() const;
NetNet* synthesize(Design*des);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void emit_node(ostream&, struct target_t*) const;
virtual void dump(ostream&) const;
@ -1782,6 +1794,13 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.83 1999/11/02 04:55:34 steve
* Add the synthesize method to NetExpr to handle
* synthesis of expressions, and use that method
* to improve r-value handling of LPM_FF synthesis.
*
* Modify the XNF target to handle LPM_FF objects.
*
* Revision 1.82 1999/11/01 02:07:40 steve
* Add the synth functor to do generic synthesis
* and add the LPM_FF device to handle rows of

View File

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ident "$Id: netlist.txt,v 1.4 1999/09/29 00:03:27 steve Exp $"
#ident "$Id: netlist.txt,v 1.5 1999/11/02 04:55:34 steve Exp $"
Note that the netlist.h header contains detailed descriptions of how
@ -57,6 +57,31 @@ destructors for nets and nodes automatically arrange for pins to be
disconnected when the item is deleted, so that the netlist can be
changed during processing.
STRUCTURAL LINKS
The NetNode and NetNet classes contain arrays of Link objects, one
object per pin. Each pin is a single bit. The Link objects link
circularly to all the NetNode and NetNet objects' links that are
connected together in the design. This way, code that examines a node
of the design can discover what is connected to each pin.
See the NetObj::Link class definition for a description of the link
methods.
Currently, a link has 3 possible direction properties:
PASSIVE -- These pins are sampled by the object that holds the
pin based on some external event. These are used,
for example, by NetESignal objects that read a
point for a procedural expression.
INPUT -- These pins potentially react to the setting of its
input.
OUTPUT -- These pins potentially drive the node. (They may be
three-state.)
BEHAVIORAL ITEMS: NetProcTop, NetProc and derived classes
Behavioral items are not in general linked to the netlist. Instead,
@ -189,6 +214,13 @@ some task calls. C++ programmers recognize this as inlining a task.)
$Log: netlist.txt,v $
Revision 1.5 1999/11/02 04:55:34 steve
Add the synthesize method to NetExpr to handle
synthesis of expressions, and use that method
to improve r-value handling of LPM_FF synthesis.
Modify the XNF target to handle LPM_FF objects.
Revision 1.4 1999/09/29 00:03:27 steve
Spelling fixes from Larry.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: synth.cc,v 1.1 1999/11/01 02:07:41 steve Exp $"
#ident "$Id: synth.cc,v 1.2 1999/11/02 04:55:34 steve Exp $"
#endif
/*
@ -132,14 +132,9 @@ void synth_f::proc_always_(class Design*des)
*/
void synth_f::proc_casn_(class Design*des)
{
// ... and the rval must be a simple signal.
NetESignal*sig = dynamic_cast<NetESignal*>(asn_->rval());
if (sig == 0) {
cerr << "Noted complex rval in DFF, name " << asn_->name() <<
", not yet implemented" << endl;
return ;
}
// Turn the r-value into gates.
NetNet*sig = asn_->rval()->synthesize(des);
assert(sig);
// The signal and the assignment must be the same width...
assert(asn_->pin_count() == sig->pin_count());
@ -185,9 +180,8 @@ void synth_f::proc_ccon_(class Design*des)
if (asn_ == 0)
return;
NetESignal*sig = dynamic_cast<NetESignal*>(asn_->rval());
if (sig == 0)
return;
NetNet*sig = asn_->rval()->synthesize(des);
assert(sig);
// The signal and the assignment must be the same width...
assert(asn_->pin_count() == sig->pin_count());
@ -235,6 +229,13 @@ void synth(Design*des)
/*
* $Log: synth.cc,v $
* Revision 1.2 1999/11/02 04:55:34 steve
* Add the synthesize method to NetExpr to handle
* synthesis of expressions, and use that method
* to improve r-value handling of LPM_FF synthesis.
*
* Modify the XNF target to handle LPM_FF objects.
*
* Revision 1.1 1999/11/01 02:07:41 steve
* Add the synth functor to do generic synthesis
* and add the LPM_FF device to handle rows of

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.9 1999/08/25 22:22:08 steve Exp $"
#ident "$Id: t-xnf.cc,v 1.10 1999/11/02 04:55:34 steve Exp $"
#endif
/* XNF BACKEND
@ -70,6 +70,9 @@ class target_xnf : public target_t {
void start_design(ostream&os, const Design*);
void end_design(ostream&os, const Design*);
void signal(ostream&os, const NetNet*);
void lpm_ff(ostream&os, const NetFF*);
void logic(ostream&os, const NetLogic*);
void bufz(ostream&os, const NetBUFZ*);
void udp(ostream&os, const NetUDP*);
@ -176,8 +179,9 @@ void target_xnf::draw_sym_with_lcaname(ostream&os, string lca,
void target_xnf::start_design(ostream&os, const Design*des)
{
os << "LCANET,6" << endl;
os << "PROG,verilog,0.0,\"Icarus Verilog\"" << endl;
os << "PART," << des->get_flag("part") << endl;
os << "PROG,verilog,0.2PRE,\"Icarus Verilog\"" << endl;
if (des->get_flag("part") != "")
os << "PART," << des->get_flag("part") << endl;
}
void target_xnf::end_design(ostream&os, const Design*)
@ -254,6 +258,35 @@ void target_xnf::signal(ostream&os, const NetNet*net)
<< ", " << num << endl;
}
void target_xnf::lpm_ff(ostream&os, const NetFF*net)
{
string type = net->attribute("LPM_FFType");
if (type == "") type = "DFF";
// XXXX For now, only support DFF
assert(type == "DFF");
// XXXX For now, I do not now how to deal with XNF-LCA attributes.
assert(net->attribute("XNF-LCA") == "");
for (unsigned idx = 0 ; idx < net->width() ; idx += 1) {
os << "SYM, " << mangle(net->name()) << "<" << idx
<< ">, DFF, LIBVER=2.0.0" << endl;
draw_pin(os, "Q", net->pin_Q(idx));
draw_pin(os, "D", net->pin_Data(idx));
if (net->attribute("Clock:LPM_Polarity") == "INVERT")
draw_pin(os, "~C", net->pin_Clock());
else
draw_pin(os, "C", net->pin_Clock());
if (count_outputs(net->pin_Enable()) > 0)
draw_pin(os, "CE", net->pin_Enable());
os << "END" << endl;
}
}
/*
* The logic gates I know so far can be translated directly into XNF
* standard symbol types. This is a fairly obvious transformation.
@ -349,6 +382,13 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
/*
* $Log: t-xnf.cc,v $
* Revision 1.10 1999/11/02 04:55:34 steve
* Add the synthesize method to NetExpr to handle
* synthesis of expressions, and use that method
* to improve r-value handling of LPM_FF synthesis.
*
* Modify the XNF target to handle LPM_FF objects.
*
* Revision 1.9 1999/08/25 22:22:08 steve
* handle bufz in XNF backend.
*

View File

@ -78,7 +78,7 @@ fi
case "$target" in
vvm) targetSuffix="" ;;
xnf) targetSuffix=".xnf"
functors="-Fxnfsyn -Fsigfold -Fxnfio" ;;
functors="-Fsynth -Fsigfold -Fxnfio" ;;
*) targetSuffix=".$target" ;;
esac