Support memories in continuous assignments.

This commit is contained in:
steve 1999-11-21 00:13:08 +00:00
parent fae40cf380
commit a81dcd7955
14 changed files with 633 additions and 231 deletions

11
PExpr.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: PExpr.h,v 1.24 1999/11/14 20:24:28 steve Exp $"
#ident "$Id: PExpr.h,v 1.25 1999/11/21 00:13:08 steve Exp $"
#endif
# include <string>
@ -159,6 +159,12 @@ class PEIdent : public PExpr {
// If this is a reference to a memory, this is the index
// expression.
PExpr*idx_;
NetNet* elaborate_net_ram_(Design*des, const string&path,
NetMemory*mem, unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
};
class PENumber : public PExpr {
@ -307,6 +313,9 @@ class PECallFunction : public PExpr {
/*
* $Log: PExpr.h,v $
* Revision 1.25 1999/11/21 00:13:08 steve
* Support memories in continuous assignments.
*
* Revision 1.24 1999/11/14 20:24:28 steve
* Add support for the LPM_CLSHIFT device.
*

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.57 1999/11/14 23:43:45 steve Exp $"
#ident "$Id: design_dump.cc,v 1.58 1999/11/21 00:13:08 steve Exp $"
#endif
/*
@ -241,6 +241,14 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetRamDq::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
<< name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetTaskDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "task " << name_ << ";" << endl;
@ -834,6 +842,9 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.58 1999/11/21 00:13:08 steve
* Support memories in continuous assignments.
*
* Revision 1.57 1999/11/14 23:43:45 steve
* Support combinatorial comparators.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: elab_net.cc,v 1.6 1999/11/14 23:43:45 steve Exp $"
#ident "$Id: elab_net.cc,v 1.7 1999/11/21 00:13:08 steve Exp $"
#endif
# include "PExpr.h"
@ -493,6 +493,258 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, const string&path,
return osig;
}
NetNet* PEIdent::elaborate_net(Design*des, const string&path,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const
{
NetNet*sig = des->find_signal(path, text_);
if (sig == 0) {
/* If the identifier is a memory instead of a signal,
then handle it elsewhere. Create a RAM. */
if (NetMemory*mem = des->find_memory(path+"."+text_))
return elaborate_net_ram_(des, path, mem, lwidth,
rise, fall, decay);
if (const NetExpr*pe = des->find_parameter(path, text_)) {
const NetEConst*pc = dynamic_cast<const NetEConst*>(pe);
assert(pc);
verinum pvalue = pc->value();
sig = new NetNet(path+"."+text_, NetNet::IMPLICIT,
pc->expr_width());
for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) {
NetConst*cp = new NetConst(des->local_symbol(path),
pvalue[idx]);
connect(sig->pin(idx), cp->pin(0));
des->add_node(cp);
}
} else {
sig = new NetNet(path+"."+text_, NetNet::IMPLICIT, 1);
des->add_signal(sig);
cerr << get_line() << ": warning: Implicitly defining "
"wire " << path << "." << text_ << "." << endl;
}
}
assert(sig);
if (msb_ && lsb_) {
verinum*mval = msb_->eval_const(des, path);
if (mval == 0) {
cerr << msb_->get_line() << ": error: unable to "
"evaluate constant expression: " << *msb_ <<
endl;
des->errors += 1;
return 0;
}
verinum*lval = lsb_->eval_const(des, path);
if (lval == 0) {
cerr << lsb_->get_line() << ": error: unable to "
"evaluate constant expression: " << *lsb_ <<
endl;
delete mval;
des->errors += 1;
return 0;
}
assert(mval);
assert(lval);
unsigned midx = sig->sb_to_idx(mval->as_long());
unsigned lidx = sig->sb_to_idx(lval->as_long());
if (midx >= lidx) {
NetTmp*tmp = new NetTmp(des->local_symbol(path),
midx-lidx+1);
des->add_signal(tmp);
if (tmp->pin_count() > sig->pin_count()) {
cerr << get_line() << ": bit select out of "
<< "range for " << sig->name() << endl;
return sig;
}
for (unsigned idx = lidx ; idx <= midx ; idx += 1)
connect(tmp->pin(idx-lidx), sig->pin(idx));
sig = tmp;
} else {
NetTmp*tmp = new NetTmp(des->local_symbol(path),
lidx-midx+1);
des->add_signal(tmp);
assert(tmp->pin_count() <= sig->pin_count());
for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
connect(tmp->pin(idx-midx), sig->pin(idx));
sig = tmp;
}
} else if (msb_) {
verinum*mval = msb_->eval_const(des, path);
if (mval == 0) {
cerr << get_line() << ": index of " << text_ <<
" needs to be constant in this context." <<
endl;
des->errors += 1;
return 0;
}
assert(mval);
unsigned idx = sig->sb_to_idx(mval->as_long());
if (idx >= sig->pin_count()) {
cerr << get_line() << "; index " << sig->name() <<
"[" << mval->as_long() << "] out of range." << endl;
des->errors += 1;
idx = 0;
}
NetTmp*tmp = new NetTmp(des->local_symbol(path), 1);
des->add_signal(tmp);
connect(tmp->pin(0), sig->pin(idx));
sig = tmp;
}
return sig;
}
/*
* When I run into an identifier in an expression that referrs to a
* memory, create a RAM port object.
*/
NetNet* PEIdent::elaborate_net_ram_(Design*des, const string&path,
NetMemory*mem, unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const
{
if (msb_ == 0) {
cerr << get_line() << ": error: memory reference without"
" the required index expression." << endl;
des->errors += 1;
return 0;
}
NetNet*adr = msb_->elaborate_net(des, path, 0, 0, 0, 0);
if (adr == 0)
return 0;
NetRamDq*ram = new NetRamDq(des->local_symbol(mem->name()),
mem, adr->pin_count());
des->add_node(ram);
for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1)
connect(ram->pin_Address(idx), adr->pin(idx));
NetNet*osig = new NetTmp(des->local_symbol(mem->name()), ram->width());
des->add_signal(osig);
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
connect(ram->pin_Q(idx), osig->pin(idx));
return osig;
}
/*
* Identifiers in continuous assignment l-values are limited to wires
* and that ilk. Detect registers and memories here and report errors.
*/
NetNet* PEIdent::elaborate_lnet(Design*des, const string&path) const
{
NetNet*sig = des->find_signal(path, text_);
if (sig == 0) {
/* Don't allow memories here. Is it a memory? */
if (des->find_memory(path+"."+text_)) {
cerr << get_line() << ": error: memories (" << text_
<< ") cannot be l-values in continuous "
<< "assignments." << endl;
return 0;
}
/* Fine, create an implicit wire as an l-value. */
sig = new NetNet(path+"."+text_, NetNet::IMPLICIT, 1);
des->add_signal(sig);
cerr << get_line() << ": warning: Implicitly defining "
"wire " << path << "." << text_ << "." << endl;
}
assert(sig);
/* Don't allow registers as assign l-values. */
if (sig->type() == NetNet::REG) {
cerr << get_line() << ": error: registers (" << sig->name()
<< ") cannot be l-values in continuous"
<< " assignments." << endl;
return 0;
}
if (msb_ && lsb_) {
/* Detect a part select. Evaluate the bits and elaborate
the l-value by creating a sub-net that links to just
the right pins. */
verinum*mval = msb_->eval_const(des, path);
assert(mval);
verinum*lval = lsb_->eval_const(des, path);
assert(lval);
unsigned midx = sig->sb_to_idx(mval->as_long());
unsigned lidx = sig->sb_to_idx(lval->as_long());
if (midx >= lidx) {
NetTmp*tmp = new NetTmp(des->local_symbol(path),
midx-lidx+1);
des->add_signal(tmp);
if (tmp->pin_count() > sig->pin_count()) {
cerr << get_line() << ": bit select out of "
<< "range for " << sig->name() << endl;
return sig;
}
for (unsigned idx = lidx ; idx <= midx ; idx += 1)
connect(tmp->pin(idx-lidx), sig->pin(idx));
sig = tmp;
} else {
NetTmp*tmp = new NetTmp(des->local_symbol(path),
lidx-midx+1);
des->add_signal(tmp);
assert(tmp->pin_count() <= sig->pin_count());
for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
connect(tmp->pin(idx-midx), sig->pin(idx));
sig = tmp;
}
} else if (msb_) {
verinum*mval = msb_->eval_const(des, path);
if (mval == 0) {
cerr << get_line() << ": index of " << text_ <<
" needs to be constant in this context." <<
endl;
des->errors += 1;
return 0;
}
assert(mval);
unsigned idx = sig->sb_to_idx(mval->as_long());
if (idx >= sig->pin_count()) {
cerr << get_line() << "; index " << sig->name() <<
"[" << mval->as_long() << "] out of range." << endl;
des->errors += 1;
idx = 0;
}
NetTmp*tmp = new NetTmp(des->local_symbol(path), 1);
des->add_signal(tmp);
connect(tmp->pin(0), sig->pin(idx));
sig = tmp;
}
return sig;
}
/*
* Elaborate a number as a NetConst object.
*/
@ -564,6 +816,9 @@ NetNet* PETernary::elaborate_net(Design*des, const string&path,
/*
* $Log: elab_net.cc,v $
* Revision 1.7 1999/11/21 00:13:08 steve
* Support memories in continuous assignments.
*
* Revision 1.6 1999/11/14 23:43:45 steve
* Support combinatorial comparators.
*

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: elaborate.cc,v 1.124 1999/11/18 03:52:19 steve Exp $"
#ident "$Id: elaborate.cc,v 1.125 1999/11/21 00:13:08 steve Exp $"
#endif
/*
@ -706,218 +706,6 @@ NetNet* PEConcat::elaborate_lnet(Design*des, const string&path) const
return osig;
}
NetNet* PEIdent::elaborate_net(Design*des, const string&path,
unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const
{
NetNet*sig = des->find_signal(path, text_);
if (sig == 0) {
if (des->find_memory(path+"."+text_)) {
cerr << get_line() << ": sorry: memories not supported"
" in this context." << endl;
return 0;
}
if (const NetExpr*pe = des->find_parameter(path, text_)) {
const NetEConst*pc = dynamic_cast<const NetEConst*>(pe);
assert(pc);
verinum pvalue = pc->value();
sig = new NetNet(path+"."+text_, NetNet::IMPLICIT,
pc->expr_width());
for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) {
NetConst*cp = new NetConst(des->local_symbol(path),
pvalue[idx]);
connect(sig->pin(idx), cp->pin(0));
des->add_node(cp);
}
} else {
sig = new NetNet(path+"."+text_, NetNet::IMPLICIT, 1);
des->add_signal(sig);
cerr << get_line() << ": warning: Implicitly defining "
"wire " << path << "." << text_ << "." << endl;
}
}
assert(sig);
if (msb_ && lsb_) {
verinum*mval = msb_->eval_const(des, path);
if (mval == 0) {
cerr << msb_->get_line() << ": error: unable to "
"evaluate constant expression: " << *msb_ <<
endl;
des->errors += 1;
return 0;
}
verinum*lval = lsb_->eval_const(des, path);
if (lval == 0) {
cerr << lsb_->get_line() << ": error: unable to "
"evaluate constant expression: " << *lsb_ <<
endl;
delete mval;
des->errors += 1;
return 0;
}
assert(mval);
assert(lval);
unsigned midx = sig->sb_to_idx(mval->as_long());
unsigned lidx = sig->sb_to_idx(lval->as_long());
if (midx >= lidx) {
NetTmp*tmp = new NetTmp(des->local_symbol(path),
midx-lidx+1);
des->add_signal(tmp);
if (tmp->pin_count() > sig->pin_count()) {
cerr << get_line() << ": bit select out of "
<< "range for " << sig->name() << endl;
return sig;
}
for (unsigned idx = lidx ; idx <= midx ; idx += 1)
connect(tmp->pin(idx-lidx), sig->pin(idx));
sig = tmp;
} else {
NetTmp*tmp = new NetTmp(des->local_symbol(path),
lidx-midx+1);
des->add_signal(tmp);
assert(tmp->pin_count() <= sig->pin_count());
for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
connect(tmp->pin(idx-midx), sig->pin(idx));
sig = tmp;
}
} else if (msb_) {
verinum*mval = msb_->eval_const(des, path);
if (mval == 0) {
cerr << get_line() << ": index of " << text_ <<
" needs to be constant in this context." <<
endl;
des->errors += 1;
return 0;
}
assert(mval);
unsigned idx = sig->sb_to_idx(mval->as_long());
if (idx >= sig->pin_count()) {
cerr << get_line() << "; index " << sig->name() <<
"[" << mval->as_long() << "] out of range." << endl;
des->errors += 1;
idx = 0;
}
NetTmp*tmp = new NetTmp(des->local_symbol(path), 1);
des->add_signal(tmp);
connect(tmp->pin(0), sig->pin(idx));
sig = tmp;
}
return sig;
}
/*
* Identifiers in continuous assignment l-values are limited to wires
* and that ilk. Detect registers and memories here and report errors.
*/
NetNet* PEIdent::elaborate_lnet(Design*des, const string&path) const
{
NetNet*sig = des->find_signal(path, text_);
if (sig == 0) {
/* Don't allow memories here. Is it a memory? */
if (des->find_memory(path+"."+text_)) {
cerr << get_line() << ": error: memories (" << text_
<< ") cannot be l-values in continuous "
<< "assignments." << endl;
return 0;
}
/* Fine, create an implicit wire as an l-value. */
sig = new NetNet(path+"."+text_, NetNet::IMPLICIT, 1);
des->add_signal(sig);
cerr << get_line() << ": warning: Implicitly defining "
"wire " << path << "." << text_ << "." << endl;
}
assert(sig);
/* Don't allow registers as assign l-values. */
if (sig->type() == NetNet::REG) {
cerr << get_line() << ": error: registers (" << sig->name()
<< ") cannot be l-values in continuous"
<< " assignments." << endl;
return 0;
}
if (msb_ && lsb_) {
/* Detect a part select. Evaluate the bits and elaborate
the l-value by creating a sub-net that links to just
the right pins. */
verinum*mval = msb_->eval_const(des, path);
assert(mval);
verinum*lval = lsb_->eval_const(des, path);
assert(lval);
unsigned midx = sig->sb_to_idx(mval->as_long());
unsigned lidx = sig->sb_to_idx(lval->as_long());
if (midx >= lidx) {
NetTmp*tmp = new NetTmp(des->local_symbol(path),
midx-lidx+1);
des->add_signal(tmp);
if (tmp->pin_count() > sig->pin_count()) {
cerr << get_line() << ": bit select out of "
<< "range for " << sig->name() << endl;
return sig;
}
for (unsigned idx = lidx ; idx <= midx ; idx += 1)
connect(tmp->pin(idx-lidx), sig->pin(idx));
sig = tmp;
} else {
NetTmp*tmp = new NetTmp(des->local_symbol(path),
lidx-midx+1);
des->add_signal(tmp);
assert(tmp->pin_count() <= sig->pin_count());
for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
connect(tmp->pin(idx-midx), sig->pin(idx));
sig = tmp;
}
} else if (msb_) {
verinum*mval = msb_->eval_const(des, path);
if (mval == 0) {
cerr << get_line() << ": index of " << text_ <<
" needs to be constant in this context." <<
endl;
des->errors += 1;
return 0;
}
assert(mval);
unsigned idx = sig->sb_to_idx(mval->as_long());
if (idx >= sig->pin_count()) {
cerr << get_line() << "; index " << sig->name() <<
"[" << mval->as_long() << "] out of range." << endl;
des->errors += 1;
idx = 0;
}
NetTmp*tmp = new NetTmp(des->local_symbol(path), 1);
des->add_signal(tmp);
connect(tmp->pin(0), sig->pin(idx));
sig = tmp;
}
return sig;
}
NetNet* PEUnary::elaborate_net(Design*des, const string&path,
unsigned width,
unsigned long rise,
@ -2345,6 +2133,9 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $Log: elaborate.cc,v $
* Revision 1.125 1999/11/21 00:13:08 steve
* Support memories in continuous assignments.
*
* Revision 1.124 1999/11/18 03:52:19 steve
* Turn NetTmp objects into normal local NetNet objects,
* and add the nodangle functor to clean up the local

10
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.28 1999/11/14 23:43:45 steve Exp $"
#ident "$Id: emit.cc,v 1.29 1999/11/21 00:13:08 steve Exp $"
#endif
/*
@ -90,6 +90,11 @@ void NetMux::emit_node(ostream&o, struct target_t*tgt) const
tgt->lpm_mux(o, this);
}
void NetRamDq::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->lpm_ram_dq(o, this);
}
void NetNEvent::emit_node(ostream&o, struct target_t*tgt) const
{
tgt->net_event(o, this);
@ -377,6 +382,9 @@ bool emit(ostream&o, const Design*des, const char*type)
/*
* $Log: emit.cc,v $
* Revision 1.29 1999/11/21 00:13:08 steve
* Support memories in continuous assignments.
*
* Revision 1.28 1999/11/14 23:43:45 steve
* Support combinatorial comparators.
*

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.89 1999/11/19 05:02:37 steve Exp $"
#ident "$Id: netlist.cc,v 1.90 1999/11/21 00:13:08 steve Exp $"
#endif
# include <cassert>
@ -998,6 +998,120 @@ const NetObj::Link& NetMux::pin_Data(unsigned w, unsigned s) const
return pin(2+width_+swidth_+s*width_+w);
}
NetRamDq::NetRamDq(const string&n, NetMemory*mem, unsigned awid)
: NetNode(n, 3+2*mem->width()+awid), mem_(mem), awidth_(awid)
{
pin(0).set_dir(NetObj::Link::INPUT); pin(0).set_name("InClock", 0);
pin(1).set_dir(NetObj::Link::INPUT); pin(1).set_name("OutClock", 0);
pin(2).set_dir(NetObj::Link::INPUT); pin(2).set_name("WE", 0);
for (unsigned idx = 0 ; idx < awidth_ ; idx += 1) {
pin(3+idx).set_dir(NetObj::Link::INPUT);
pin(3+idx).set_name("Address", idx);
}
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
pin(3+awidth_+idx).set_dir(NetObj::Link::INPUT);
pin(3+awidth_+idx).set_name("Data", idx);
}
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
pin(3+awidth_+width()+idx).set_dir(NetObj::Link::OUTPUT);
pin(3+awidth_+width()+idx).set_name("Q", idx);
}
}
NetRamDq::~NetRamDq()
{
}
unsigned NetRamDq::width() const
{
return mem_->width();
}
unsigned NetRamDq::awidth() const
{
return awidth_;
}
unsigned NetRamDq::size() const
{
return mem_->count();
}
const NetMemory* NetRamDq::mem() const
{
return mem_;
}
NetObj::Link& NetRamDq::pin_InClock()
{
return pin(0);
}
const NetObj::Link& NetRamDq::pin_InClock() const
{
return pin(0);
}
NetObj::Link& NetRamDq::pin_OutClock()
{
return pin(1);
}
const NetObj::Link& NetRamDq::pin_OutClock() const
{
return pin(1);
}
NetObj::Link& NetRamDq::pin_WE()
{
return pin(2);
}
const NetObj::Link& NetRamDq::pin_WE() const
{
return pin(2);
}
NetObj::Link& NetRamDq::pin_Address(unsigned idx)
{
assert(idx < awidth_);
return pin(3+idx);
}
const NetObj::Link& NetRamDq::pin_Address(unsigned idx) const
{
assert(idx < awidth_);
return pin(3+idx);
}
NetObj::Link& NetRamDq::pin_Data(unsigned idx)
{
assert(idx < width());
return pin(3+awidth_+idx);
}
const NetObj::Link& NetRamDq::pin_Data(unsigned idx) const
{
assert(idx < width());
return pin(3+awidth_+idx);
}
NetObj::Link& NetRamDq::pin_Q(unsigned idx)
{
assert(idx < width());
return pin(3+awidth_+width()+idx);
}
const NetObj::Link& NetRamDq::pin_Q(unsigned idx) const
{
assert(idx < width());
return pin(3+awidth_+width()+idx);
}
/*
* NetAssign
*/
@ -2404,6 +2518,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*))
/*
* $Log: netlist.cc,v $
* Revision 1.90 1999/11/21 00:13:08 steve
* Support memories in continuous assignments.
*
* Revision 1.89 1999/11/19 05:02:37 steve
* handle duplicate connect to a nexus.
*

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.91 1999/11/19 05:02:37 steve Exp $"
#ident "$Id: netlist.h,v 1.92 1999/11/21 00:13:09 steve Exp $"
#endif
/*
@ -514,6 +514,50 @@ class NetMux : public NetNode {
unsigned swidth_;
};
/*
* This device represents an LPM_RAM_DQ device. The actual content is
* represented by a NetMemory object allocated elsewhere, but that
* object fixes the width and size of the device. The pin count of the
* address input is given in the constructor.
*/
class NetRamDq : public NetNode {
public:
NetRamDq(const string&name, NetMemory*mem, unsigned awid);
~NetRamDq();
unsigned width() const;
unsigned awidth() const;
unsigned size() const;
const NetMemory*mem() const;
NetObj::Link& pin_InClock();
NetObj::Link& pin_OutClock();
NetObj::Link& pin_WE();
NetObj::Link& pin_Address(unsigned idx);
NetObj::Link& pin_Data(unsigned idx);
NetObj::Link& pin_Q(unsigned idx);
const NetObj::Link& pin_InClock() const;
const NetObj::Link& pin_OutClock() const;
const NetObj::Link& pin_WE() const;
const NetObj::Link& pin_Address(unsigned idx) const;
const NetObj::Link& pin_Data(unsigned idx) const;
const NetObj::Link& pin_Q(unsigned idx) const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual void emit_node(ostream&, struct target_t*) const;
private:
friend class NetMemory;
NetMemory*mem_;
NetRamDq*next_;
unsigned awidth_;
};
/* =========
* There are cases where expressions need to be represented. The
* NetExpr class is the root of a heirarchy that serves that purpose.
@ -1933,6 +1977,9 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.92 1999/11/21 00:13:09 steve
* Support memories in continuous assignments.
*
* Revision 1.91 1999/11/19 05:02:37 steve
* handle duplicate connect to a nexus.
*

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.5 1999/11/02 04:55:34 steve Exp $"
#ident "$Id: netlist.txt,v 1.6 1999/11/21 00:13:09 steve Exp $"
Note that the netlist.h header contains detailed descriptions of how
@ -114,6 +114,35 @@ and a NetProc. The NetAssign_ node has pins that represent the l-value
of the statement, and carries behavioral expressions that represent
the r-value of the assignment.
MEMORIES
The netlist form includes the NetMemory type to hold the content of a
memory. Instances of this type represent the declaration of a memory,
and occur once for each memory. References to the memory are managed
by the NetEMemory and NetAssignMem_ classes.
An instance of the NetEMemory class is created whenever a procedural
expression references a memory element. The operand is the index to
use to address (and read) the memory.
An instance of the NetAssignMem_ class is created when there is a
procedural assignment to the memory. The NetAssignMem_ object
represents the l-value reference (a write) to the memory. As with the
NetEMemory class, this is a procedural reference only.
When a memory reference appears in structural context (i.e. continuous
assignments) elaboration creates a NetRamDq. This is a LPM_RAM_DQ
device. Elaboration leaves the write control and data input pins
unconnected for now, because memories cannot appear is l-values of
continuous assignments. However, the synthesis functor may connect
signals to the write control lines to get a fully operational RAM.
By the time elaboration completes, there may be many NetAssignMem_,
NetEMemory and NetRamDq objects referencing the same NetMemory
object. Each represents a port into the memory. It is up to the
synthesis steps (and the target code) to figure out what to do with
these ports.
EXPRESSIONS
Expressions are represented as a tree of NetExpr nodes. The NetExpr
@ -214,6 +243,9 @@ some task calls. C++ programmers recognize this as inlining a task.)
$Log: netlist.txt,v $
Revision 1.6 1999/11/21 00:13:09 steve
Support memories in continuous assignments.
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

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.76 1999/11/14 23:43:45 steve Exp $"
#ident "$Id: t-vvm.cc,v 1.77 1999/11/21 00:13:09 steve Exp $"
#endif
# include <iostream>
@ -64,6 +64,7 @@ class target_vvm : public target_t {
virtual void lpm_compare(ostream&os, const NetCompare*);
virtual void lpm_ff(ostream&os, const NetFF*);
virtual void lpm_mux(ostream&os, const NetMux*);
virtual void lpm_ram_dq(ostream&os, const NetRamDq*);
virtual void logic(ostream&os, const NetLogic*);
virtual void bufz(ostream&os, const NetBUFZ*);
@ -937,6 +938,22 @@ void target_vvm::lpm_mux(ostream&os, const NetMux*mux)
}
}
void target_vvm::lpm_ram_dq(ostream&os, const NetRamDq*ram)
{
string mname = mangle(ram->name());
os << "static vvm_ram_dq<" << ram->width() << "," <<
ram->awidth() << "," << ram->size() << "> " << mname <<
"(&" << mangle(ram->mem()->name()) << ");" << endl;
for (unsigned idx = 0 ; idx < ram->width() ; idx += 1) {
unsigned pin = ram->pin_Q(idx).get_pin();
string outfun = defn_gate_outputfun_(os, ram, pin);
init_code << " " << mangle(ram->name()) <<
".config_rout(" << idx << ", &" << outfun << ");" << endl;
emit_gate_outputfun_(ram, pin);
}
}
void target_vvm::logic(ostream&os, const NetLogic*gate)
{
string outfun = defn_gate_outputfun_(os, gate, 0);
@ -1417,8 +1434,9 @@ void target_vvm::proc_assign_mem(ostream&os, const NetAssignMem*amem)
defn << " /* " << amem->get_line() << " */" << endl;
if (mem->width() == amem->rval()->expr_width()) {
defn << " " << mangle(mem->name()) << ".set_word(" <<
index << ".as_unsigned(), " << rval << ");" << endl;
defn << " " << mangle(mem->name()) <<
".set_word(sim_, " << index << ".as_unsigned(), " <<
rval << ");" << endl;
} else {
assert(mem->width() <= amem->rval()->expr_width());
@ -1429,8 +1447,8 @@ void target_vvm::proc_assign_mem(ostream&os, const NetAssignMem*amem)
defn << " " << tmp << "[" << idx << "] = " <<
rval << "[" << idx << "];" << endl;
defn << " " << mangle(mem->name()) << ".set_word(" <<
index << ".as_unsigned(), " << tmp << ");" << endl;
defn << " " << mangle(mem->name()) << ".set_word(sim_, "
<< index << ".as_unsigned(), " << tmp << ");" << endl;
}
}
@ -1902,6 +1920,9 @@ extern const struct target tgt_vvm = {
};
/*
* $Log: t-vvm.cc,v $
* Revision 1.77 1999/11/21 00:13:09 steve
* Support memories in continuous assignments.
*
* Revision 1.76 1999/11/14 23:43:45 steve
* Support combinatorial comparators.
*

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.25 1999/11/14 23:43:45 steve Exp $"
#ident "$Id: target.cc,v 1.26 1999/11/21 00:13:09 steve Exp $"
#endif
# include "target.h"
@ -99,6 +99,12 @@ void target_t::lpm_mux(ostream&, const NetMux*)
"Unhandled NetMux." << endl;
}
void target_t::lpm_ram_dq(ostream&, const NetRamDq*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetRamDq." << endl;
}
void target_t::net_assign(ostream&os, const NetAssign*)
{
}
@ -299,6 +305,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/*
* $Log: target.cc,v $
* Revision 1.26 1999/11/21 00:13:09 steve
* Support memories in continuous assignments.
*
* Revision 1.25 1999/11/14 23:43:45 steve
* Support combinatorial comparators.
*

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.24 1999/11/14 23:43:46 steve Exp $"
#ident "$Id: target.h,v 1.25 1999/11/21 00:13:09 steve Exp $"
#endif
# include "netlist.h"
@ -71,6 +71,7 @@ struct target_t {
virtual void lpm_compare(ostream&os, const NetCompare*);
virtual void lpm_ff(ostream&os, const NetFF*);
virtual void lpm_mux(ostream&os, const NetMux*);
virtual void lpm_ram_dq(ostream&os, const NetRamDq*);
/* Output a gate (called for each gate) */
virtual void logic(ostream&os, const NetLogic*);
@ -141,6 +142,9 @@ extern const struct target *target_table[];
/*
* $Log: target.h,v $
* Revision 1.25 1999/11/21 00:13:09 steve
* Support memories in continuous assignments.
*
* Revision 1.24 1999/11/14 23:43:46 steve
* Support combinatorial comparators.
*

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.21 1999/11/10 02:52:24 steve Exp $"
#ident "$Id: vvm.h,v 1.22 1999/11/21 00:13:09 steve Exp $"
#endif
# include <vector>
@ -254,14 +254,27 @@ template <unsigned WIDTH> class vvm_signal_t : public __vpiSignal {
}
};
struct vvm_ram_callback {
vvm_ram_callback();
virtual ~vvm_ram_callback();
virtual void handle_write(vvm_simulation*sim, unsigned idx) =0;
vvm_ram_callback*next_;
};
template <unsigned WIDTH, unsigned SIZE>
class vvm_memory_t : public __vpiMemory {
public:
void set_word(unsigned addr, const vvm_bitset_t<WIDTH>&val)
vvm_memory_t()
{ cb_list_ = 0;
}
void set_word(vvm_simulation*sim, unsigned addr,
const vvm_bitset_t<WIDTH>&val)
{ unsigned base = WIDTH * addr;
for (unsigned idx = 0 ; idx < WIDTH ; idx += 1)
bits[base+idx] = val[idx];
call_list_(sim, addr);
}
vvm_bitset_t<WIDTH> get_word(unsigned addr) const
@ -271,10 +284,25 @@ class vvm_memory_t : public __vpiMemory {
val[idx] = bits[base+idx];
return val;
}
void set_callback(vvm_ram_callback*ram)
{ ram->next_ = cb_list_;
cb_list_ = ram;
}
private:
vvm_ram_callback*cb_list_;
void call_list_(vvm_simulation*sim, unsigned idx)
{ for (vvm_ram_callback*cur = cb_list_; cur; cur = cur->next_)
cur->handle_write(sim, idx);
}
};
/*
* $Log: vvm.h,v $
* Revision 1.22 1999/11/21 00:13:09 steve
* Support memories in continuous assignments.
*
* Revision 1.21 1999/11/10 02:52:24 steve
* Create the vpiMemory handle type.
*

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.4 1999/11/01 02:07:41 steve Exp $"
#ident "$Id: vvm_bit.cc,v 1.5 1999/11/21 00:13:09 steve Exp $"
#endif
# include "vvm.h"
@ -68,6 +68,14 @@ vvm_bits_t::~vvm_bits_t()
{
}
vvm_ram_callback::vvm_ram_callback()
{
}
vvm_ram_callback::~vvm_ram_callback()
{
}
vpip_bit_t add_with_carry(vpip_bit_t l, vpip_bit_t r, vpip_bit_t&carry)
{
unsigned li, ri, ci;
@ -114,6 +122,9 @@ 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.5 1999/11/21 00:13:09 steve
* Support memories in continuous assignments.
*
* 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

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.23 1999/11/15 00:42:31 steve Exp $"
#ident "$Id: vvm_gates.h,v 1.24 1999/11/21 00:13:09 steve Exp $"
#endif
# include "vvm.h"
@ -553,6 +553,62 @@ template <unsigned WIDTH, unsigned long DELAY> class vvm_nor {
vvm_out_event::action_t output_;
};
template <unsigned WIDTH, unsigned AWIDTH, unsigned SIZE>
class vvm_ram_dq : protected vvm_ram_callback {
public:
vvm_ram_dq(vvm_memory_t<WIDTH,SIZE>*mem)
: mem_(mem)
{ mem->set_callback(this);
for (unsigned idx = 0 ; idx < WIDTH ; idx += 1)
out_[idx] = 0;
for (unsigned idx = 0 ; idx < AWIDTH ; idx += 1)
addr_[idx] = Vx;
}
void init_Address(unsigned idx, vpip_bit_t val)
{ addr_[idx] = val; }
void set_Address(vvm_simulation*sim, unsigned idx, vpip_bit_t val)
{ if (addr_[idx] == val) return;
addr_[idx] = val;
compute_();
send_out_(sim);
}
void handle_write(vvm_simulation*sim, unsigned idx)
{ if (idx == addr_val_) send_out_(sim); }
void config_rout(unsigned idx, vvm_out_event::action_t o)
{ out_[idx] = o; }
private:
vvm_memory_t<WIDTH,SIZE>*mem_;
vpip_bit_t addr_[AWIDTH];
vvm_out_event::action_t out_[WIDTH];
unsigned long addr_val_;
void compute_()
{ unsigned bit;
unsigned mask;
addr_val_ = 0;
for (bit = 0, mask = 1 ; bit < AWIDTH ; bit += 1, mask <<= 1)
if (addr_[bit] == V1) addr_val_ |= mask;
}
void send_out_(vvm_simulation*sim)
{ vvm_bitset_t<WIDTH>ov = mem_->get_word(addr_val_);
for (unsigned bit = 0 ; bit < WIDTH ; bit += 1)
if (out_[bit]) {
vvm_event*ev = new vvm_out_event(sim,
ov[bit],
out_[bit]);
sim->active_event(ev);
}
}
};
template <unsigned long DELAY> class vvm_bufif1 {
public:
@ -931,6 +987,9 @@ template <unsigned WIDTH> class vvm_pevent {
/*
* $Log: vvm_gates.h,v $
* Revision 1.24 1999/11/21 00:13:09 steve
* Support memories in continuous assignments.
*
* Revision 1.23 1999/11/15 00:42:31 steve
* Fixup to include right shift support.
*