Add the synth functor to do generic synthesis
and add the LPM_FF device to handle rows of flip-flops.
This commit is contained in:
parent
f80c4a309e
commit
89881adece
|
|
@ -18,7 +18,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.25 1999/10/31 20:08:24 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.26 1999/11/01 02:07:40 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -66,7 +66,7 @@ distclean: clean
|
|||
rm -f Makefile
|
||||
|
||||
TT = t-null.o t-verilog.o t-vvm.o t-xnf.o
|
||||
FF = nobufz.o propinit.o sigfold.o xnfio.o xnfsyn.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 \
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: design_dump.cc,v 1.52 1999/10/31 20:08:24 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.53 1999/11/01 02:07:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -168,6 +168,13 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
|
|||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetFF::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_FF: " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetLogic::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "logic: ";
|
||||
|
|
@ -798,6 +805,11 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.53 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.52 1999/10/31 20:08:24 steve
|
||||
* Include subtraction in LPM_ADD_SUB device.
|
||||
*
|
||||
|
|
|
|||
12
emit.cc
12
emit.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: emit.cc,v 1.24 1999/10/10 01:59:54 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.25 1999/11/01 02:07:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -70,6 +70,11 @@ void NetConst::emit_node(ostream&o, struct target_t*tgt) const
|
|||
tgt->net_const(o, this);
|
||||
}
|
||||
|
||||
void NetFF::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_ff(o, this);
|
||||
}
|
||||
|
||||
void NetNEvent::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_event(o, this);
|
||||
|
|
@ -357,6 +362,11 @@ bool emit(ostream&o, const Design*des, const char*type)
|
|||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.25 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.24 1999/10/10 01:59:54 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
|
|
|
|||
31
functor.cc
31
functor.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: functor.cc,v 1.2 1999/07/18 05:52:46 steve Exp $"
|
||||
#ident "$Id: functor.cc,v 1.3 1999/11/01 02:07:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "functor.h"
|
||||
|
|
@ -35,6 +35,10 @@ void functor_t::process(class Design*, class NetProcTop*)
|
|||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_ff(class Design*, class NetFF*)
|
||||
{
|
||||
}
|
||||
|
||||
void Design::functor(functor_t*fun)
|
||||
{
|
||||
// apply to signals
|
||||
|
|
@ -53,10 +57,35 @@ void Design::functor(functor_t*fun)
|
|||
procs_idx_ = idx->next_;
|
||||
fun->process(this, idx);
|
||||
}
|
||||
|
||||
// apply to nodes
|
||||
if (nodes_) {
|
||||
NetNode*cur = nodes_->node_next_;
|
||||
do {
|
||||
NetNode*tmp = cur->node_next_;
|
||||
cur->functor_node(this, fun);
|
||||
cur = tmp;
|
||||
} while (cur != nodes_->node_next_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NetNode::functor_node(Design*, functor_t*)
|
||||
{
|
||||
}
|
||||
|
||||
void NetFF::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_ff(des, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.3 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.2 1999/07/18 05:52:46 steve
|
||||
* xnfsyn generates DFF objects for XNF output, and
|
||||
* properly rewrites the Design netlist in the process.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: functor.h,v 1.1 1999/07/17 22:01:13 steve Exp $"
|
||||
#ident "$Id: functor.h,v 1.2 1999/11/01 02:07:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -42,10 +42,17 @@ struct functor_t {
|
|||
/* This method is called for each process in the design. */
|
||||
virtual void process(class Design*des, class NetProcTop*);
|
||||
|
||||
/* This method is called for each FF in the design. */
|
||||
virtual void lpm_ff(class Design*des, class NetFF*);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.2 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.1 1999/07/17 22:01:13 steve
|
||||
* Add the functor interface for functor transforms.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
WHAT IS LPM
|
||||
|
||||
LPM (Library of Paramaterized Modules) is EIS-IS standard 103-A. It is
|
||||
a standard library of abstract devices that are designed to be close
|
||||
enough to the target hardware to be easily translated, yet abstract
|
||||
enough to support a variety of target technologies without excessive
|
||||
constraints. Icarus Verilog uses LPM internally to represent idealized
|
||||
hardware, especially when doing target neutral synthesis.
|
||||
|
||||
In general, the user does not even see the LPM that Icarus Verilog
|
||||
generates, because the LPM devices are translated into technology
|
||||
specific devices by the final code generator or target specific
|
||||
optimizers.
|
||||
|
||||
INTERNAL USES OF LPM
|
||||
|
||||
Internally, Icarus Verilog uses LPM devices to represent the design in
|
||||
abstract, especially when synthesizing such functions as addition,
|
||||
flip-flops, etc. The ``synth'' functor generates LPM modules when
|
||||
interpreting procedural constructs. The functor generates the LPM
|
||||
objects needed to replace a behavioral description, and uses
|
||||
attributes to tag the devices with LPM properties.
|
||||
|
||||
Code generators need to understand the supported LPM devices so that
|
||||
they can translate the devices into technology specific devices.
|
||||
9
main.cc
9
main.cc
|
|
@ -19,7 +19,7 @@ const char COPYRIGHT[] =
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: main.cc,v 1.23 1999/09/22 16:57:23 steve Exp $"
|
||||
#ident "$Id: main.cc,v 1.24 1999/11/01 02:07:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
const char NOTICE[] =
|
||||
|
|
@ -79,6 +79,7 @@ extern Design* elaborate(const map<string,Module*>&modules,
|
|||
extern void cprop(Design*des);
|
||||
extern void propinit(Design*des);
|
||||
extern void sigfold(Design*des);
|
||||
extern void synth(Design*des);
|
||||
extern void nobufz(Design*des);
|
||||
extern void xnfio(Design*des);
|
||||
extern void xnfsyn(Design*des);
|
||||
|
|
@ -92,6 +93,7 @@ static struct net_func_map {
|
|||
{ "nobufz", &nobufz },
|
||||
{ "propinit", &propinit },
|
||||
{ "sigfold", &sigfold },
|
||||
{ "synth", &synth },
|
||||
{ "xnfio", &xnfio },
|
||||
{ "xnfsyn", &xnfsyn },
|
||||
{ 0, 0 }
|
||||
|
|
@ -277,6 +279,11 @@ int main(int argc, char*argv[])
|
|||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.24 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.23 1999/09/22 16:57:23 steve
|
||||
* Catch parallel blocks in vvm emit.
|
||||
*
|
||||
|
|
|
|||
124
netlist.cc
124
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.78 1999/10/31 04:11:27 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.79 1999/11/01 02:07:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cassert>
|
||||
|
|
@ -376,7 +376,122 @@ const NetProc* NetProcTop::statement() const
|
|||
}
|
||||
|
||||
/*
|
||||
* The NetAddSub class represents an LPM ADD_SUB device. The pinout is
|
||||
* The NetFF class represents an LPM_FF device. The pinout is assigned
|
||||
* like so:
|
||||
* 0 -- Clock
|
||||
* 1 -- Enable
|
||||
* 2 -- Aload
|
||||
* 3 -- Aset
|
||||
* 4 -- Aclr
|
||||
* 5 -- Sload
|
||||
* 6 -- Sset
|
||||
* 7 -- Sclr
|
||||
*
|
||||
* 8 -- Data[0]
|
||||
* 9 -- Q[0]
|
||||
* ...
|
||||
*/
|
||||
|
||||
NetFF::NetFF(const string&n, unsigned wid)
|
||||
: NetNode(n, 8 + 2*wid)
|
||||
{
|
||||
pin_Clock().set_dir(Link::INPUT);
|
||||
pin_Clock().set_name("Clock", 0);
|
||||
pin_Enable().set_dir(Link::INPUT);
|
||||
pin_Enable().set_name("Enable", 0);
|
||||
pin_Aload().set_dir(Link::INPUT);
|
||||
pin_Aload().set_name("Aload", 0);
|
||||
pin_Aset().set_dir(Link::INPUT);
|
||||
pin_Aset().set_name("Aset", 0);
|
||||
pin_Aclr().set_dir(Link::INPUT);
|
||||
pin_Aclr().set_name("Aclr", 0);
|
||||
pin_Sload().set_dir(Link::INPUT);
|
||||
pin_Sload().set_name("Sload", 0);
|
||||
pin_Sset().set_dir(Link::INPUT);
|
||||
pin_Sset().set_name("Sset", 0);
|
||||
pin_Sclr().set_dir(Link::INPUT);
|
||||
pin_Sclr().set_name("Sclr", 0);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
pin_Data(idx).set_dir(Link::INPUT);
|
||||
pin_Data(idx).set_name("Data", idx);
|
||||
pin_Q(idx).set_dir(Link::OUTPUT);
|
||||
pin_Q(idx).set_name("Q", idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetFF::~NetFF()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetFF::width() const
|
||||
{
|
||||
return (pin_count() - 8) / 2;
|
||||
}
|
||||
|
||||
NetObj::Link& NetFF::pin_Clock()
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
NetObj::Link& NetFF::pin_Enable()
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
NetObj::Link& NetFF::pin_Aload()
|
||||
{
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
NetObj::Link& NetFF::pin_Aset()
|
||||
{
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
NetObj::Link& NetFF::pin_Aclr()
|
||||
{
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
NetObj::Link& NetFF::pin_Sload()
|
||||
{
|
||||
return pin(5);
|
||||
}
|
||||
|
||||
NetObj::Link& NetFF::pin_Sset()
|
||||
{
|
||||
return pin(6);
|
||||
}
|
||||
|
||||
NetObj::Link& NetFF::pin_Sclr()
|
||||
{
|
||||
return pin(7);
|
||||
}
|
||||
|
||||
NetObj::Link& NetFF::pin_Data(unsigned w)
|
||||
{
|
||||
unsigned pn = 8 + 2*w;
|
||||
assert(pn < pin_count());
|
||||
return pin(pn);
|
||||
}
|
||||
|
||||
NetObj::Link& NetFF::pin_Q(unsigned w)
|
||||
{
|
||||
unsigned pn = 9 + w*2;
|
||||
assert(pn < pin_count());
|
||||
return pin(pn);
|
||||
}
|
||||
|
||||
const NetObj::Link& NetFF::pin_Q(unsigned w) const
|
||||
{
|
||||
unsigned pn = 9 + w*2;
|
||||
assert(pn < pin_count());
|
||||
return pin(pn);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
|
||||
* assigned like so:
|
||||
* 0 -- Add_Sub
|
||||
* 1 -- Aclr
|
||||
|
|
@ -1878,6 +1993,11 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.78 1999/10/31 04:11:27 steve
|
||||
* Add to netlist links pin name and instance number,
|
||||
* and arrange in vvm for pin connections by name
|
||||
|
|
|
|||
40
netlist.h
40
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.81 1999/10/31 04:11:27 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.82 1999/11/01 02:07:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -211,6 +211,8 @@ class NetNode : public NetObj {
|
|||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
virtual void dump_node(ostream&, unsigned) const;
|
||||
|
||||
virtual void functor_node(Design*, functor_t*);
|
||||
|
||||
private:
|
||||
friend class Design;
|
||||
NetNode*node_next_, *node_prev_;
|
||||
|
|
@ -321,6 +323,37 @@ class NetAddSub : public NetNode {
|
|||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class represents an LPM_FF device. There is no literal gate
|
||||
* type in Verilog that maps, but gates of this type can be inferred.
|
||||
*/
|
||||
class NetFF : public NetNode {
|
||||
|
||||
public:
|
||||
NetFF(const string&n, unsigned width);
|
||||
~NetFF();
|
||||
|
||||
unsigned width() const;
|
||||
|
||||
NetObj::Link& pin_Clock();
|
||||
NetObj::Link& pin_Enable();
|
||||
NetObj::Link& pin_Aload();
|
||||
NetObj::Link& pin_Aset();
|
||||
NetObj::Link& pin_Aclr();
|
||||
NetObj::Link& pin_Sload();
|
||||
NetObj::Link& pin_Sset();
|
||||
NetObj::Link& pin_Sclr();
|
||||
|
||||
NetObj::Link& pin_Data(unsigned);
|
||||
NetObj::Link& pin_Q(unsigned);
|
||||
|
||||
const NetObj::Link& pin_Q(unsigned) const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual void emit_node(ostream&, struct target_t*) const;
|
||||
virtual void functor_node(Design*des, functor_t*fun);
|
||||
};
|
||||
|
||||
/*
|
||||
* This class represents the declared memory object. The parser
|
||||
* creates one of these for each declared memory in the elaborated
|
||||
|
|
@ -1749,6 +1782,11 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.81 1999/10/31 04:11:27 steve
|
||||
* Add to netlist links pin name and instance number,
|
||||
* and arrange in vvm for pin connections by name
|
||||
|
|
|
|||
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* 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: synth.cc,v 1.1 1999/11/01 02:07:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The synth function searches the behavioral description for
|
||||
* patterns that are known to represent LPM library components. This
|
||||
* is especially interesting for the sequential components such as
|
||||
* flip flops and latches. As threads are transformed into components,
|
||||
* the design is rewritten.
|
||||
*
|
||||
* Currently, this transform recognizes the following patterns:
|
||||
*
|
||||
* always @(posedge CLK) Q = D
|
||||
* always @(negedge CLK) Q = D
|
||||
*
|
||||
* always @(posedge CLK) if (CE) Q = D;
|
||||
* always @(negedge CLK) if (CE) Q = D;
|
||||
*
|
||||
* The r-value of the assignments must be identifiers (i.e. wires or
|
||||
* registers) and the CE must be single-bit identifiers. The generated
|
||||
* device will be wide enough to accomodate Q and D.
|
||||
*/
|
||||
# include "functor.h"
|
||||
# include "netlist.h"
|
||||
|
||||
class synth_f : public functor_t {
|
||||
|
||||
public:
|
||||
void process(class Design*, class NetProcTop*);
|
||||
|
||||
private:
|
||||
void proc_always_(class Design*);
|
||||
void proc_casn_(class Design*);
|
||||
void proc_ccon_(class Design*);
|
||||
|
||||
// The matcher does something like a recursive descent search
|
||||
// for the templates. These variables are filled in as the
|
||||
// searcher finds them.
|
||||
|
||||
class NetProcTop*top_;
|
||||
|
||||
class NetPEvent *pclk_;
|
||||
class NetNEvent *nclk_;
|
||||
|
||||
class NetCondit *con_;
|
||||
class NetAssign *asn_;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Look at a process, and divide the problem into always and initial
|
||||
* threads.
|
||||
*/
|
||||
void synth_f::process(class Design*des, class NetProcTop*top)
|
||||
{
|
||||
switch (top->type()) {
|
||||
case NetProcTop::KALWAYS:
|
||||
top_ = top;
|
||||
proc_always_(des);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* An "always ..." statement has been found.
|
||||
*/
|
||||
void synth_f::proc_always_(class Design*des)
|
||||
{
|
||||
// The statement must be a NetPEvent, ...
|
||||
pclk_ = dynamic_cast<class NetPEvent*>(top_->statement());
|
||||
if (pclk_ == 0)
|
||||
return;
|
||||
|
||||
// ... there must be a single event source, ...
|
||||
svector<class NetNEvent*>*neb = pclk_->back_list();
|
||||
if (neb == 0)
|
||||
return;
|
||||
if (neb->count() != 1) {
|
||||
delete neb;
|
||||
return;
|
||||
}
|
||||
nclk_ = (*neb)[0];
|
||||
delete neb;
|
||||
|
||||
// ... the event must be an edge, ...
|
||||
switch (nclk_->type()) {
|
||||
case NetNEvent::POSEDGE:
|
||||
case NetNEvent::NEGEDGE:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// Is this a clocked assignment?
|
||||
asn_ = dynamic_cast<NetAssign*>(pclk_->statement());
|
||||
if (asn_) {
|
||||
proc_casn_(des);
|
||||
return;
|
||||
}
|
||||
|
||||
con_ = dynamic_cast<NetCondit*>(pclk_->statement());
|
||||
if (con_) {
|
||||
proc_ccon_(des);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The process so far has been matched as:
|
||||
*
|
||||
* always @(posedge nclk_) asn_ = <r>;
|
||||
* always @(negedge nclk_) asn_ = <r>;
|
||||
*/
|
||||
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 ;
|
||||
}
|
||||
|
||||
// The signal and the assignment must be the same width...
|
||||
assert(asn_->pin_count() == sig->pin_count());
|
||||
|
||||
NetFF*ff = new NetFF(asn_->name(), asn_->pin_count());
|
||||
ff->attribute("LPM_FFType", "DFF");
|
||||
|
||||
for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) {
|
||||
connect(ff->pin_Data(idx), sig->pin(idx));
|
||||
connect(ff->pin_Q(idx), asn_->pin(idx));
|
||||
}
|
||||
|
||||
switch (nclk_->type()) {
|
||||
case NetNEvent::POSEDGE:
|
||||
connect(ff->pin_Clock(), nclk_->pin(0));
|
||||
break;
|
||||
|
||||
case NetNEvent::NEGEDGE:
|
||||
connect(ff->pin_Clock(), nclk_->pin(0));
|
||||
ff->attribute("Clock:LPM_Polarity", "INVERT");
|
||||
break;
|
||||
}
|
||||
|
||||
des->add_node(ff);
|
||||
|
||||
// This process is matched and replaced with a DFF. Get
|
||||
// rid of the now useless NetProcTop.
|
||||
des->delete_process(top_);
|
||||
}
|
||||
|
||||
/*
|
||||
* The process so far has been matched as:
|
||||
*
|
||||
* always @(posedge nclk_) if ...;
|
||||
* always @(negedge nclk_) if ...;
|
||||
*/
|
||||
void synth_f::proc_ccon_(class Design*des)
|
||||
{
|
||||
if (con_->else_clause())
|
||||
return;
|
||||
|
||||
asn_ = dynamic_cast<NetAssign*>(con_->if_clause());
|
||||
if (asn_ == 0)
|
||||
return;
|
||||
|
||||
NetESignal*sig = dynamic_cast<NetESignal*>(asn_->rval());
|
||||
if (sig == 0)
|
||||
return;
|
||||
|
||||
// The signal and the assignment must be the same width...
|
||||
assert(asn_->pin_count() == sig->pin_count());
|
||||
|
||||
NetESignal*ce = dynamic_cast<NetESignal*>(con_->expr());
|
||||
if (ce == 0)
|
||||
return;
|
||||
if (ce->pin_count() != 1)
|
||||
return;
|
||||
|
||||
NetFF*ff = new NetFF(asn_->name(), asn_->pin_count());
|
||||
ff->attribute("LPM_FFType", "DFF");
|
||||
|
||||
for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) {
|
||||
connect(ff->pin_Data(idx), sig->pin(idx));
|
||||
connect(ff->pin_Q(idx), asn_->pin(idx));
|
||||
}
|
||||
|
||||
switch (nclk_->type()) {
|
||||
case NetNEvent::POSEDGE:
|
||||
connect(ff->pin_Clock(), nclk_->pin(0));
|
||||
connect(ff->pin_Enable(), ce->pin(0));
|
||||
break;
|
||||
|
||||
case NetNEvent::NEGEDGE:
|
||||
connect(ff->pin_Clock(), nclk_->pin(0));
|
||||
connect(ff->pin_Enable(), ce->pin(0));
|
||||
ff->attribute("Clock:LPM_Polarity", "INVERT");
|
||||
break;
|
||||
}
|
||||
|
||||
des->add_node(ff);
|
||||
|
||||
|
||||
// This process is matched and replaced with a DFF. Get
|
||||
// rid of the now useless NetProcTop.
|
||||
des->delete_process(top_);
|
||||
}
|
||||
|
||||
void synth(Design*des)
|
||||
{
|
||||
synth_f synth_obj;
|
||||
des->functor(&synth_obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: synth.cc,v $
|
||||
* 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
|
||||
* flip-flops.
|
||||
*
|
||||
*/
|
||||
|
||||
23
t-vvm.cc
23
t-vvm.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: t-vvm.cc,v 1.70 1999/10/31 20:08:24 steve Exp $"
|
||||
#ident "$Id: t-vvm.cc,v 1.71 1999/11/01 02:07:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
|
|
@ -53,6 +53,7 @@ class target_vvm : public target_t {
|
|||
virtual void func_def(ostream&os, const NetFuncDef*);
|
||||
|
||||
virtual void lpm_add_sub(ostream&os, const NetAddSub*);
|
||||
virtual void lpm_ff(ostream&os, const NetFF*);
|
||||
|
||||
virtual void logic(ostream&os, const NetLogic*);
|
||||
virtual void bufz(ostream&os, const NetBUFZ*);
|
||||
|
|
@ -835,6 +836,21 @@ void target_vvm::lpm_add_sub(ostream&os, const NetAddSub*gate)
|
|||
}
|
||||
}
|
||||
|
||||
void target_vvm::lpm_ff(ostream&os, const NetFF*gate)
|
||||
{
|
||||
string mname = mangle(gate->name());
|
||||
os << "static vvm_ff<" << gate->width() << "> " << mname << ";"
|
||||
<< endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < gate->width() ; idx += 1) {
|
||||
unsigned pin = gate->pin_Q(idx).get_pin();
|
||||
string outfun = defn_gate_outputfun_(os, gate, pin);
|
||||
init_code << " " << mangle(gate->name()) <<
|
||||
".config_rout(" << idx << ", &" << outfun << ");" << endl;
|
||||
emit_gate_outputfun_(gate, pin);
|
||||
}
|
||||
}
|
||||
|
||||
void target_vvm::logic(ostream&os, const NetLogic*gate)
|
||||
{
|
||||
string outfun = defn_gate_outputfun_(os, gate, 0);
|
||||
|
|
@ -1802,6 +1818,11 @@ extern const struct target tgt_vvm = {
|
|||
};
|
||||
/*
|
||||
* $Log: t-vvm.cc,v $
|
||||
* Revision 1.71 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.70 1999/10/31 20:08:24 steve
|
||||
* Include subtraction in LPM_ADD_SUB device.
|
||||
*
|
||||
|
|
|
|||
13
target.cc
13
target.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: target.cc,v 1.21 1999/10/10 01:59:55 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.22 1999/11/01 02:07:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
|
|
@ -75,6 +75,12 @@ void target_t::lpm_add_sub(ostream&, const NetAddSub*)
|
|||
"Unhandled NetAddSub." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_ff(ostream&, const NetFF*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetFF." << endl;
|
||||
}
|
||||
|
||||
void target_t::net_assign(ostream&os, const NetAssign*)
|
||||
{
|
||||
}
|
||||
|
|
@ -275,6 +281,11 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
|||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.22 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.21 1999/10/10 01:59:55 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
|
|
|
|||
8
target.h
8
target.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: target.h,v 1.20 1999/10/10 01:59:55 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.21 1999/11/01 02:07:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -67,6 +67,7 @@ struct target_t {
|
|||
|
||||
/* LPM style components are handled here. */
|
||||
virtual void lpm_add_sub(ostream&os, const NetAddSub*);
|
||||
virtual void lpm_ff(ostream&os, const NetFF*);
|
||||
|
||||
/* Output a gate (called for each gate) */
|
||||
virtual void logic(ostream&os, const NetLogic*);
|
||||
|
|
@ -137,6 +138,11 @@ extern const struct target *target_table[];
|
|||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.21 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.20 1999/10/10 01:59:55 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
|
|
|
|||
10
vvm/vvm.h
10
vvm/vvm.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm.h,v 1.19 1999/10/31 04:11:28 steve Exp $"
|
||||
#ident "$Id: vvm.h,v 1.20 1999/11/01 02:07:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <vector>
|
||||
|
|
@ -98,6 +98,9 @@ inline vpip_bit_t not(vpip_bit_t l)
|
|||
}
|
||||
}
|
||||
|
||||
extern bool posedge(vpip_bit_t from, vpip_bit_t to);
|
||||
|
||||
|
||||
class vvm_bits_t {
|
||||
public:
|
||||
virtual ~vvm_bits_t() =0;
|
||||
|
|
@ -253,6 +256,11 @@ template <unsigned WIDTH> class vvm_signal_t : public __vpiSignal {
|
|||
|
||||
/*
|
||||
* $Log: vvm.h,v $
|
||||
* Revision 1.20 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.19 1999/10/31 04:11:28 steve
|
||||
* Add to netlist links pin name and instance number,
|
||||
* and arrange in vvm for pin connections by name
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_bit.cc,v 1.3 1999/10/28 00:47:25 steve Exp $"
|
||||
#ident "$Id: vvm_bit.cc,v 1.4 1999/11/01 02:07:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
|
|
@ -41,6 +41,20 @@ ostream& operator << (ostream&os, vpip_bit_t bit)
|
|||
return os;
|
||||
}
|
||||
|
||||
bool posedge(vpip_bit_t from, vpip_bit_t to)
|
||||
{
|
||||
switch (from) {
|
||||
case V1:
|
||||
return false;
|
||||
case V0:
|
||||
return from != to;
|
||||
case Vx:
|
||||
case Vz:
|
||||
return to == V1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&os, const vvm_bits_t&str)
|
||||
{
|
||||
os << str.get_width() << "b'";
|
||||
|
|
@ -100,6 +114,11 @@ vpip_bit_t add_with_carry(vpip_bit_t l, vpip_bit_t r, vpip_bit_t&carry)
|
|||
|
||||
/*
|
||||
* $Log: vvm_bit.cc,v $
|
||||
* Revision 1.4 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.3 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_gates.h,v 1.17 1999/10/31 20:08:24 steve Exp $"
|
||||
#ident "$Id: vvm_gates.h,v 1.18 1999/11/01 02:07:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
|
|
@ -152,6 +152,56 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_and {
|
|||
vvm_out_event::action_t output_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class simulates the LPM flip-flop device.
|
||||
* XXXX Inverted clock not yet supported.
|
||||
*/
|
||||
template <unsigned WIDTH> class vvm_ff {
|
||||
|
||||
public:
|
||||
explicit vvm_ff()
|
||||
{ clk_ = Vx;
|
||||
for (unsigned idx = 0 ; idx < WIDTH ; idx += 1)
|
||||
q_[idx] = Vx;
|
||||
}
|
||||
~vvm_ff() { }
|
||||
|
||||
void init_Data(unsigned idx, vpip_bit_t val) { d_[idx] = val; }
|
||||
void init_Clock(unsigned, vpip_bit_t val) { clk_ = val; }
|
||||
|
||||
void set_Clock(vvm_simulation*sim, unsigned, vpip_bit_t val)
|
||||
{ if (val == clk_) return;
|
||||
bool flag = posedge(clk_, val);
|
||||
clk_ = val;
|
||||
if (flag) latch_(sim);
|
||||
}
|
||||
|
||||
void set_Data(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
|
||||
{ d_[idx] = val;
|
||||
}
|
||||
|
||||
void config_rout(unsigned idx, vvm_out_event::action_t o)
|
||||
{ out_[idx] = o;
|
||||
}
|
||||
|
||||
private:
|
||||
vpip_bit_t d_[WIDTH];
|
||||
vpip_bit_t q_[WIDTH];
|
||||
vpip_bit_t clk_;
|
||||
|
||||
vvm_out_event::action_t out_[WIDTH];
|
||||
|
||||
void latch_(vvm_simulation*sim)
|
||||
{ q_ = d_;
|
||||
for (unsigned idx = 0 ; idx < WIDTH ; idx += 1)
|
||||
if (out_[idx]) {
|
||||
vvm_event*ev = new vvm_out_event(sim, q_[idx],
|
||||
out_[idx]);
|
||||
sim->active_event(ev);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned WIDTH, unsigned long DELAY> class vvm_or {
|
||||
|
||||
public:
|
||||
|
|
@ -599,6 +649,11 @@ template <unsigned WIDTH> class vvm_pevent {
|
|||
|
||||
/*
|
||||
* $Log: vvm_gates.h,v $
|
||||
* Revision 1.18 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
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.17 1999/10/31 20:08:24 steve
|
||||
* Include subtraction in LPM_ADD_SUB device.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue