Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Module ports are really special PEIdent

 expressions, because a name can be used
 many places in the port list.
  • Loading branch information...
commit 3676d664083472c70a89b8f397e128320966164f 1 parent addedf7
steve authored
34 Module.cc
View
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
-#ident "$Id: Module.cc,v 1.11 2000/03/12 17:09:40 steve Exp $"
+#ident "$Id: Module.cc,v 1.12 2000/05/16 04:05:15 steve Exp $"
#endif
# include "Module.h"
@@ -28,28 +28,9 @@
Module::Module(const string&name, const svector<Module::port_t*>*pp)
: name_(name)
{
- if (pp) {
- // Save the list of ports, then scan the list to make
- // the implicit wires. Add those wires to the wire map.
+ if (pp)
ports_ = *pp;
- for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
- port_t*cur = ports_[idx];
- if (cur == 0)
- continue;
-
- // The port can actually be a list of wires, to
- // remember to scan the set. Also note the case
- // where a wire may be connected to multiple
- // ports, and reuse the link if that happens.
- for (unsigned jdx = 0; jdx < cur->wires.count(); jdx += 1) {
- PWire*tmp = add_wire(cur->wires[jdx]);
- if (tmp != cur->wires[jdx]) {
- delete cur->wires[jdx];
- cur->wires[jdx] = tmp;
- }
- }
- }
- }
+
}
void Module::add_gate(PGate*gate)
@@ -87,10 +68,10 @@ unsigned Module::port_count() const
return ports_.count();
}
-const svector<PWire*>& Module::get_port(unsigned idx) const
+const svector<PEIdent*>& Module::get_port(unsigned idx) const
{
assert(idx < ports_.count());
- return ports_[idx]->wires;
+ return ports_[idx]->expr;
}
unsigned Module::find_port(const string&name) const
@@ -144,6 +125,11 @@ const list<PProcess*>& Module::get_behaviors() const
/*
* $Log: Module.cc,v $
+ * Revision 1.12 2000/05/16 04:05:15 steve
+ * Module ports are really special PEIdent
+ * expressions, because a name can be used
+ * many places in the port list.
+ *
* Revision 1.11 2000/03/12 17:09:40 steve
* Support localparam.
*
14 Module.h
View
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
-#ident "$Id: Module.h,v 1.18 2000/05/02 16:27:38 steve Exp $"
+#ident "$Id: Module.h,v 1.19 2000/05/16 04:05:15 steve Exp $"
#endif
# include <list>
@@ -29,6 +29,7 @@
# include <string>
class PEvent;
class PExpr;
+class PEIdent;
class PGate;
class PTask;
class PFunction;
@@ -53,9 +54,7 @@ class Module {
public:
struct port_t {
string name;
- svector<PWire*>wires;
-
- port_t(int c=0) : wires(c) { }
+ svector<PEIdent*> expr;
};
public:
@@ -100,7 +99,7 @@ class Module {
void add_function(const string&name, PFunction*def);
unsigned port_count() const;
- const svector<PWire*>& get_port(unsigned idx) const;
+ const svector<PEIdent*>& get_port(unsigned idx) const;
unsigned find_port(const string&) const;
// Find a wire by name. This is used for connecting gates to
@@ -137,6 +136,11 @@ class Module {
/*
* $Log: Module.h,v $
+ * Revision 1.19 2000/05/16 04:05:15 steve
+ * Module ports are really special PEIdent
+ * expressions, because a name can be used
+ * many places in the port list.
+ *
* Revision 1.18 2000/05/02 16:27:38 steve
* Move signal elaboration to a seperate pass.
*
11 PExpr.h
View
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
-#ident "$Id: PExpr.h,v 1.37 2000/05/07 04:37:56 steve Exp $"
+#ident "$Id: PExpr.h,v 1.38 2000/05/16 04:05:15 steve Exp $"
#endif
# include <string>
@@ -171,6 +171,10 @@ class PEIdent : public PExpr {
virtual NetExpr*elaborate_expr(Design*des, NetScope*) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
+ // Elaborate the PEIdent as a port to a module. This method
+ // only applies to Ident expressions.
+ NetNet* elaborate_port(Design*des, NetScope*sc) const;
+
virtual bool is_constant(Module*) const;
verinum* eval_const(const Design*des, const string&path) const;
@@ -375,6 +379,11 @@ class PECallFunction : public PExpr {
/*
* $Log: PExpr.h,v $
+ * Revision 1.38 2000/05/16 04:05:15 steve
+ * Module ports are really special PEIdent
+ * expressions, because a name can be used
+ * many places in the port list.
+ *
* Revision 1.37 2000/05/07 04:37:56 steve
* Carry strength values from Verilog source to the
* pform and netlist for gates.
86 elab_net.cc
View
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
-#ident "$Id: elab_net.cc,v 1.36 2000/05/07 20:48:14 steve Exp $"
+#ident "$Id: elab_net.cc,v 1.37 2000/05/16 04:05:15 steve Exp $"
#endif
# include "PExpr.h"
@@ -1159,6 +1159,85 @@ NetNet* PEIdent::elaborate_lnet(Design*des, const string&path) const
}
/*
+ * This method is used to elaborate identifiers that are ports to a
+ * scope. The scope is presumed to be that of the module that has the
+ * port.
+ */
+NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
+{
+ const string path = scope->name();
+
+ NetNet*sig = des->find_signal(scope, text_);
+ if (sig == 0) {
+ cerr << get_line() << ": error: no wire/reg " << text_
+ << " in module " << scope->name() << "." << endl;
+ des->errors += 1;
+ 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(scope, des->local_symbol(path),
+ midx-lidx+1);
+ 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(scope, des->local_symbol(path),
+ lidx-midx+1);
+ 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(scope, des->local_symbol(path), 1);
+ connect(tmp->pin(0), sig->pin(idx));
+ sig = tmp;
+ }
+
+ return sig;
+}
+
+
+/*
* Elaborate a number as a NetConst object.
*/
NetNet* PENumber::elaborate_net(Design*des, const string&path,
@@ -1480,6 +1559,11 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path,
/*
* $Log: elab_net.cc,v $
+ * Revision 1.37 2000/05/16 04:05:15 steve
+ * Module ports are really special PEIdent
+ * expressions, because a name can be used
+ * many places in the port list.
+ *
* Revision 1.36 2000/05/07 20:48:14 steve
* Properly elaborate repeat concatenations.
*
20 elaborate.cc
View
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
-#ident "$Id: elaborate.cc,v 1.172 2000/05/11 23:37:27 steve Exp $"
+#ident "$Id: elaborate.cc,v 1.173 2000/05/16 04:05:16 steve Exp $"
#endif
/*
@@ -414,13 +414,20 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const
// Inside the module, the port is one or more signals,
// that were already elaborated. List all those signals,
// and I will connect them up later.
- svector<PWire*> mport = rmod->get_port(idx);
+ svector<PEIdent*> mport = rmod->get_port(idx);
svector<NetNet*>prts (mport.count());
unsigned prts_pin_count = 0;
for (unsigned ldx = 0 ; ldx < mport.count() ; ldx += 1) {
- PWire*pport = mport[ldx];
- prts[ldx] = des->find_signal(my_scope, pport->name());
+ PEIdent*pport = mport[ldx];
+ prts[ldx] = pport->elaborate_port(des, my_scope);
+ if (prts[ldx] == 0) {
+ cerr << pport->get_line() << ": internal error: "
+ << "Failed to elaborate port expr: "
+ << *pport << endl;
+ des->errors += 1;
+ continue;
+ }
assert(prts[ldx]);
prts_pin_count += prts[ldx]->pin_count();
}
@@ -2422,6 +2429,11 @@ Design* elaborate(const map<string,Module*>&modules,
/*
* $Log: elaborate.cc,v $
+ * Revision 1.173 2000/05/16 04:05:16 steve
+ * Module ports are really special PEIdent
+ * expressions, because a name can be used
+ * many places in the port list.
+ *
* Revision 1.172 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
95 parse.y
View
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
-#ident "$Id: parse.y,v 1.96 2000/05/11 23:37:27 steve Exp $"
+#ident "$Id: parse.y,v 1.97 2000/05/16 04:05:16 steve Exp $"
#endif
# include "parse_misc.h"
@@ -1478,9 +1478,10 @@ parameter_value_byname_list
}
;
+
/* The port (of a module) is a fairly complex item. Each port is
handled as a Module::port_t object. A simple port reference has a
- name and a PWire object, but more complex constructs are possible
+ name and a PExpr object, but more complex constructs are possible
where the name can be attached to a list of PWire objects.
The port_reference returns a Module::port_t, and so does the
@@ -1494,17 +1495,32 @@ parameter_value_byname_list
port
: port_reference
{ $$ = $1; }
+
+ /* This syntax attaches an external name to the port reference so
+ that the caller can bind by name to non-trivial port
+ references. The port_t object gets its PWire from the
+ port_reference, but its name from the PORTNAME. */
+
| PORTNAME '(' port_reference ')'
{ Module::port_t*tmp = $3;
tmp->name = $1;
delete $1;
$$ = tmp;
}
+
+ /* A port can also be a concatenation of port references. In this
+ case the port does not have a name available to the outside, only
+ positional parameter passing is possible here. */
+
| '{' port_reference_list '}'
{ Module::port_t*tmp = $2;
tmp->name = "";
$$ = tmp;
}
+
+ /* This attaches a name to a port reference contatenation list so
+ that parameter passing be name is possible. */
+
| PORTNAME '(' '{' port_reference_list '}' ')'
{ Module::port_t*tmp = $4;
tmp->name = $1;
@@ -1518,58 +1534,91 @@ port_opt
| { $$ = 0; }
;
+
+ /* A port reference is an internal (to the module) name of the port,
+ possibly with a part of bit select to attach it to specific bits
+ of a signal fully declared inside the module.
+
+ The parser creates a PEIdent for every port reference, even if the
+ signal is bound to different ports. The elaboration figures out
+ the mess that this creates. The port_reference (and the
+ port_reference_list below) puts the port reference PEIdent into the
+ port_t object to pass it up to the module declaration code. */
+
port_reference
+
: IDENTIFIER
- { Module::port_t*ptmp = new Module::port_t(1);
- PWire*wtmp = new PWire($1, NetNet::IMPLICIT,
- NetNet::PIMPLICIT);
- wtmp->set_file(@1.text);
- wtmp->set_lineno(@1.first_line);
+ { Module::port_t*ptmp = new Module::port_t;
+ PEIdent*tmp = new PEIdent($1);
+ tmp->set_file(@1.text);
+ tmp->set_lineno(@1.first_line);
ptmp->name = $1;
- ptmp->wires[0] = wtmp;
+ ptmp->expr = svector<PEIdent*>(1);
+ ptmp->expr[0] = tmp;
delete $1;
$$ = ptmp;
}
+
| IDENTIFIER '[' expression ':' expression ']'
- { PWire*wtmp = new PWire($1, NetNet::IMPLICIT,
- NetNet::PIMPLICIT);
+ { PEIdent*wtmp = new PEIdent($1);
wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line);
if (!pform_expression_is_constant($3)) {
- yyerror(@3, "error: msb expression of port bit select "
- "must be constant.");
+ yyerror(@3, "error: msb expression of "
+ "port part select must be constant.");
}
if (!pform_expression_is_constant($5)) {
- yyerror(@5, "error: lsb expression of port bit select "
- "must be constant.");
+ yyerror(@5, "error: lsb expression of "
+ "port part select must be constant.");
}
- wtmp->set_range($3, $5);
- Module::port_t*ptmp = new Module::port_t(1);
- ptmp->name = $1;
- ptmp->wires[0] = wtmp;
+ wtmp->msb_ = $3;
+ wtmp->lsb_ = $5;
+ Module::port_t*ptmp = new Module::port_t;
+ ptmp->name = "";
+ ptmp->expr = svector<PEIdent*>(1);
+ ptmp->expr[0] = wtmp;
+ delete $1;
+ $$ = ptmp;
+ }
+
+ | IDENTIFIER '[' expression ']'
+ { PEIdent*tmp = new PEIdent($1);
+ tmp->set_file(@1.text);
+ tmp->set_lineno(@1.first_line);
+ if (!pform_expression_is_constant($3)) {
+ yyerror(@3, "error: port bit select "
+ "must be constant.");
+ }
+ tmp->msb_ = $3;
+ Module::port_t*ptmp = new Module::port_t;
+ ptmp->name = "";
+ ptmp->expr = svector<PEIdent*>(1);
+ ptmp->expr[0] = tmp;
delete $1;
$$ = ptmp;
}
+
| IDENTIFIER '[' error ']'
{ yyerror(@1, "error: invalid port bit select");
- Module::port_t*ptmp = new Module::port_t(1);
- PWire*wtmp = new PWire($1, NetNet::IMPLICIT,
- NetNet::PIMPLICIT);
+ Module::port_t*ptmp = new Module::port_t;
+ PEIdent*wtmp = new PEIdent($1);
wtmp->set_file(@1.text);
wtmp->set_lineno(@1.first_line);
ptmp->name = $1;
- ptmp->wires[0] = wtmp;
+ ptmp->expr = svector<PEIdent*>(1);
+ ptmp->expr[0] = wtmp;
delete $1;
$$ = ptmp;
}
;
+
port_reference_list
: port_reference
{ $$ = $1; }
| port_reference_list ',' port_reference
{ Module::port_t*tmp = $1;
- tmp->wires = svector<PWire*>(tmp->wires, $3->wires);
+ tmp->expr = svector<PEIdent*>(tmp->expr, $3->expr);
delete $3;
$$ = tmp;
}
14 pform.cc
View
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
-#ident "$Id: pform.cc,v 1.59 2000/05/08 05:30:20 steve Exp $"
+#ident "$Id: pform.cc,v 1.60 2000/05/16 04:05:16 steve Exp $"
#endif
# include "compiler.h"
@@ -567,12 +567,13 @@ void pform_makewire(const vlltype&li, const list<string>*names,
}
-void pform_set_port_type(const string&name, NetNet::PortType pt)
+void pform_set_port_type(const string&nm, NetNet::PortType pt)
{
+ const string name = scoped_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) {
- VLerror("name is not a port.");
- return;
+ cur = new PWire(name, NetNet::IMPLICIT, pt);
+ pform_cur_module->add_wire(cur);
}
if (! cur->set_port_type(pt))
@@ -864,6 +865,11 @@ int pform_parse(const char*path, map<string,Module*>&modules,
/*
* $Log: pform.cc,v $
+ * Revision 1.60 2000/05/16 04:05:16 steve
+ * Module ports are really special PEIdent
+ * expressions, because a name can be used
+ * many places in the port list.
+ *
* Revision 1.59 2000/05/08 05:30:20 steve
* Deliver gate output strengths to the netlist.
*
36 pform_dump.cc
View
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
-#ident "$Id: pform_dump.cc,v 1.58 2000/05/11 23:37:27 steve Exp $"
+#ident "$Id: pform_dump.cc,v 1.59 2000/05/16 04:05:16 steve Exp $"
#endif
/*
@@ -211,9 +211,13 @@ void PWire::dump(ostream&out) const
break;
}
+ assert(msb_.count() == lsb_.count());
for (unsigned idx = 0 ; idx < msb_.count() ; idx += 1) {
- assert(lsb_[idx] && msb_[idx]);
- out << " [" << *msb_[idx] << ":" << *lsb_[idx] << "]";
+ assert(msb_[idx]);
+ if (lsb_[idx])
+ out << " [" << *msb_[idx] << ":" << *lsb_[idx] << "]";
+ else
+ out << " [" << *msb_[idx] << "]";
}
out << " " << name_;
@@ -634,24 +638,9 @@ void Module::dump(ostream&out) const
continue;
}
- switch (cur->wires[0]->get_port_type()) {
- case NetNet::PINPUT:
- out << " input ." << cur->name << "(";
- break;
- case NetNet::POUTPUT:
- out << " output ." << cur->name << "(";
- break;
- case NetNet::PINOUT:
- out << " inout ." << cur->name << "(";
- break;
- default:
- out << " XXXX ." << cur->name << "(";
- break;
- }
-
- out << cur->wires[0]->name();
- for (unsigned wdx = 1 ; wdx < cur->wires.count() ; wdx += 1) {
- out << ", " << cur->wires[wdx]->name();
+ out << " ." << cur->name << "(" << *cur->expr[0];
+ for (unsigned wdx = 1 ; wdx < cur->expr.count() ; wdx += 1) {
+ out << ", " << *cur->expr[wdx];
}
out << ")" << endl;
@@ -785,6 +774,11 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
+ * Revision 1.59 2000/05/16 04:05:16 steve
+ * Module ports are really special PEIdent
+ * expressions, because a name can be used
+ * many places in the port list.
+ *
* Revision 1.58 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
Please sign in to comment.
Something went wrong with that request. Please try again.