Support memories in continuous assignments.
This commit is contained in:
parent
fae40cf380
commit
a81dcd7955
11
PExpr.h
11
PExpr.h
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
257
elab_net.cc
257
elab_net.cc
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
217
elaborate.cc
217
elaborate.cc
|
|
@ -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
10
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.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.
|
||||
*
|
||||
|
|
|
|||
119
netlist.cc
119
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.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.
|
||||
*
|
||||
|
|
|
|||
49
netlist.h
49
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.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.
|
||||
*
|
||||
|
|
|
|||
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.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
|
||||
|
|
|
|||
31
t-vvm.cc
31
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.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.
|
||||
*
|
||||
|
|
|
|||
11
target.cc
11
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.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.
|
||||
*
|
||||
|
|
|
|||
6
target.h
6
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.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.
|
||||
*
|
||||
|
|
|
|||
32
vvm/vvm.h
32
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.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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue