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:
parent
73753f1337
commit
b66e7b1713
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
67
netlist.cc
67
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.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
|
||||
|
|
|
|||
21
netlist.h
21
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.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
|
||||
|
|
|
|||
34
netlist.txt
34
netlist.txt
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
25
synth.cc
25
synth.cc
|
|
@ -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
|
||||
|
|
|
|||
46
t-xnf.cc
46
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.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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ fi
|
|||
case "$target" in
|
||||
vvm) targetSuffix="" ;;
|
||||
xnf) targetSuffix=".xnf"
|
||||
functors="-Fxnfsyn -Fsigfold -Fxnfio" ;;
|
||||
functors="-Fsynth -Fsigfold -Fxnfio" ;;
|
||||
*) targetSuffix=".$target" ;;
|
||||
esac
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue