Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Support memories in continuous assignments.

  • Loading branch information...
commit a81dcd79559bdd0ed03395f60152f9267baca6e6 1 parent fae40cf
steve authored
View
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.
*
View
13 design_dump.cc
@@ -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
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.
*
View
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
View
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.
*
View
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.
*
View
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.
*
View
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
View
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.
*
View
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.
*
View
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.
*
View
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.
*
View
13 vvm/vvm_bit.cc
@@ -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
61 vvm/vvm_gates.h
@@ -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.
*
Please sign in to comment.
Something went wrong with that request. Please try again.