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:
steve 1999-11-01 02:07:40 +00:00
parent f80c4a309e
commit 89881adece
16 changed files with 629 additions and 16 deletions

View File

@ -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 \

View File

@ -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
View File

@ -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.
*

View File

@ -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.

View File

@ -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.
*

26
lpm.txt Normal file
View File

@ -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.

View File

@ -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.
*

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.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

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.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

244
synth.cc Normal file
View File

@ -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.
*
*/

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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

View File

@ -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

View File

@ -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.
*