diff --git a/Module.cc b/Module.cc index 714790f69..7e1cff7f3 100644 --- a/Module.cc +++ b/Module.cc @@ -17,12 +17,25 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: Module.cc,v 1.4 1999/07/31 19:14:47 steve Exp $" +#ident "$Id: Module.cc,v 1.5 1999/08/03 04:14:49 steve Exp $" #endif # include "Module.h" # include "PWire.h" +Module::Module(const string&name, const svector*pp) +: name_(name) +{ + if (pp) { + ports_ = *pp; + for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) { + port_t*cur = ports_[idx]; + for (unsigned jdx = 0 ; jdx < cur->wires.count() ; jdx += 1) + add_wire(cur->wires[jdx]); + } + } +} + void Module::add_gate(PGate*gate) { gates_.push_back(gate); @@ -48,6 +61,29 @@ void Module::add_behavior(PProcess*b) behaviors_.push_back(b); } +unsigned Module::port_count() const +{ + return ports_.count(); +} + +const PWire* Module::get_port(unsigned idx) const +{ + assert(idx < ports_.count()); + assert(ports_[idx]->wires.count() == 1); + return ports_[idx]->wires[0]; +} + +unsigned Module::find_port(const string&name) const +{ + assert(name != ""); + for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) + if (ports_[idx]->name == name) + return idx; + + return ports_.count(); +} + + PWire* Module::get_wire(const string&name) { for (list::iterator cur = wires_.begin() @@ -64,6 +100,10 @@ PWire* Module::get_wire(const string&name) /* * $Log: Module.cc,v $ + * Revision 1.5 1999/08/03 04:14:49 steve + * Parse into pform arbitrarily complex module + * port declarations. + * * Revision 1.4 1999/07/31 19:14:47 steve * Add functions up to elaboration (Ed Carter) * diff --git a/Module.h b/Module.h index 60a549397..699ce6982 100644 --- a/Module.h +++ b/Module.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: Module.h,v 1.6 1999/07/31 19:14:47 steve Exp $" +#ident "$Id: Module.h,v 1.7 1999/08/03 04:14:49 steve Exp $" #endif # include @@ -41,11 +41,23 @@ class Design; */ class Module { - public: - explicit Module(const string&name, unsigned nports) - : ports(nports), name_(name) { } - svector ports; + /* The module ports are in general a vector of port_t + objects. Each port has a name and an ordered list of + wires. The name is the means that the outside uses to + access the port, the wires are the internal connections to + the port. */ + public: + struct port_t { + string name; + svectorwires; + + port_t(int c=0) : wires(c) { } + }; + + public: + explicit Module(const string&name, const svector*); + /* The module has parameters that are evaluated when the module is elaborated. During parsing, I put the parameters @@ -60,6 +72,10 @@ class Module { void add_task(const string&name, PTask*def); void add_function(const string&name, PFunction*def); + unsigned port_count() const; + const PWire* get_port(unsigned idx) const; + unsigned find_port(const string&) const; + // Find a wire by name. This is used for connecting gates to // existing wires, etc. PWire* get_wire(const string&name); @@ -74,6 +90,7 @@ class Module { private: const string name_; + svector ports_; list wires_; list gates_; list behaviors_; @@ -88,6 +105,10 @@ class Module { /* * $Log: Module.h,v $ + * Revision 1.7 1999/08/03 04:14:49 steve + * Parse into pform arbitrarily complex module + * port declarations. + * * Revision 1.6 1999/07/31 19:14:47 steve * Add functions up to elaboration (Ed Carter) * diff --git a/elaborate.cc b/elaborate.cc index 21c6d9fa6..dd945f974 100644 --- a/elaborate.cc +++ b/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.65 1999/08/01 21:48:11 steve Exp $" +#ident "$Id: elaborate.cc,v 1.66 1999/08/03 04:14:49 steve Exp $" #endif /* @@ -34,8 +34,6 @@ string Design::local_symbol(const string&path) { - string result = "_L"; - strstream res; res << "_L" << (lcounter_++) << ends; return path + "." + res.str(); @@ -395,11 +393,8 @@ void PGBuiltin::elaborate(Design*des, const string&path) const */ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const { - string my_name; - if (get_name() == "") - my_name = des->local_symbol(path); - else - my_name = path + "." + get_name(); + assert(get_name() != ""); + const string my_name = path + "." + get_name(); const svector*pins; @@ -408,7 +403,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const // ports. If this is simply positional binding in the first // place, then get the binding from the base class. if (pins_) { - unsigned nexp = rmod->ports.count(); + unsigned nexp = rmod->port_count(); svector*exp = new svector(nexp); // Scan the bindings, matching them with port names. @@ -416,14 +411,11 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const // Given a binding, look at the module port names // for the position that matches the binding name. - unsigned pidx = 0; - while (pidx < nexp) { - if (pins_[idx].name == rmod->ports[pidx]->name()) - break; - - pidx += 1; - } + unsigned pidx = rmod->find_port(pins_[idx].name); + // If the port name doesn't exist, the find_port + // method will return the port count. Detect that + // as an error. if (pidx == nexp) { cerr << get_line() << ": port ``" << pins_[idx].name << "'' is not a port of " @@ -432,6 +424,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const continue; } + // If I already bound something to this port, then + // the (*exp) array will already have a pointer + // value where I want to place this expression. if ((*exp)[pidx]) { cerr << get_line() << ": port ``" << pins_[idx].name << "'' already bound." << @@ -440,7 +435,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const continue; } - // OK, od the binding by placing the expression in + // OK, do the binding by placing the expression in // the right place. (*exp)[pidx] = pins_[idx].parm; } @@ -449,9 +444,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const } else { - if (pin_count() != rmod->ports.count()) { + if (pin_count() != rmod->port_count()) { cerr << get_line() << ": Wrong number " - "of parameters. Expecting " << rmod->ports.count() << + "of parameters. Expecting " << rmod->port_count() << ", got " << pin_count() << "." << endl; des->errors += 1; @@ -460,7 +455,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const // No named bindings, just use the positional list I // already have. - assert(pin_count() == rmod->ports.count()); + assert(pin_count() == rmod->port_count()); pins = get_pins(); } @@ -486,14 +481,15 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const } assert(sig); - NetNet*prt = des->find_signal(my_name, rmod->ports[idx]->name()); + const PWire*pport = rmod->get_port(idx); + NetNet*prt = des->find_signal(my_name, pport->name()); assert(prt); // Check that the parts have matching pin counts. If // not, they are different widths. if (prt->pin_count() != sig->pin_count()) { cerr << get_line() << ": Port " << - rmod->ports[idx]->name() << " of " << type_ << + pport->name() << " of " << type_ << " expects " << prt->pin_count() << " pins, got " << sig->pin_count() << " from " << sig->name() << endl; des->errors += 1; @@ -2045,6 +2041,10 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.66 1999/08/03 04:14:49 steve + * Parse into pform arbitrarily complex module + * port declarations. + * * Revision 1.65 1999/08/01 21:48:11 steve * set width of procedural r-values when then * l-value is a memory word. diff --git a/main.cc b/main.cc index c4129cad5..60f40cdb6 100644 --- a/main.cc +++ b/main.cc @@ -19,7 +19,7 @@ const char COPYRIGHT[] = * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: main.cc,v 1.21 1999/07/18 05:52:46 steve Exp $" +#ident "$Id: main.cc,v 1.22 1999/08/03 04:14:49 steve Exp $" #endif const char NOTICE[] = @@ -209,7 +209,7 @@ int main(int argc, char*argv[]) ; mod != modules.end() ; mod ++ ) { Module*cur = (*mod).second; - if (cur->ports.count() == 0) + if (cur->port_count() == 0) if (start_module == "") { start_module = cur->get_name(); } else { @@ -272,6 +272,10 @@ int main(int argc, char*argv[]) /* * $Log: main.cc,v $ + * Revision 1.22 1999/08/03 04:14:49 steve + * Parse into pform arbitrarily complex module + * port declarations. + * * Revision 1.21 1999/07/18 05:52:46 steve * xnfsyn generates DFF objects for XNF output, and * properly rewrites the Design netlist in the process. diff --git a/parse.y b/parse.y index 860d2d744..c90bfdda1 100644 --- a/parse.y +++ b/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: parse.y,v 1.56 1999/08/01 23:25:51 steve Exp $" +#ident "$Id: parse.y,v 1.57 1999/08/03 04:14:49 steve Exp $" #endif # include "parse_misc.h" @@ -40,6 +40,9 @@ extern void lex_end_table(); lgate*gate; svector*gates; + Module::port_t *mport; + svector*mports; + portname_t*portname; svector*portnames; @@ -106,8 +109,9 @@ extern void lex_end_table(); %type net_decl_assign %type net_decl_assigns -%type port -%type list_of_ports list_of_ports_opt +%type port port_reference port_reference_list +%type list_of_ports list_of_ports_opt + %type task_item task_item_list task_item_list_opt %type function_item function_item_list @@ -801,12 +805,14 @@ identifier list_of_ports : port - { svector*tmp = new svector(1); + { svector*tmp + = new svector(1); (*tmp)[0] = $1; $$ = tmp; } | list_of_ports ',' port - { svector*tmp = new svector(*$1, $3); + { svector*tmp + = new svector(*$1, $3); delete $1; $$ = tmp; } @@ -1118,39 +1124,100 @@ parameter_assign_list | parameter_assign_list ',' parameter_assign ; + /* The port (of a module) is a fairle 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 + where the name can be attached to a list of PWire objects. + + The port_reference returns a Module::port_t, and so does the + port_reference_list. The port_reference_list may have built up a + list of PWires in the port_t object, but it is still a single + Module::port_t object. + + The port rule below takes the built up Module::port_t object and + tweaks its name as needed. */ + port + : port_reference + { $$ = $1; } + | PORTNAME '(' port_reference ')' + { Module::port_t*tmp = $3; + tmp->name = $1; + $$ = tmp; + } + | '{' port_reference_list '}' + { Module::port_t*tmp = $2; + tmp->name = ""; + $$ = tmp; + } + | PORTNAME '(' '{' port_reference_list '}' ')' + { Module::port_t*tmp = $4; + tmp->name = $1; + $$ = tmp; + } + ; + +port_reference : IDENTIFIER - { $$ = new PWire($1, NetNet::IMPLICIT, NetNet::PIMPLICIT); - $$->set_file(@1.text); - $$->set_lineno(@1.first_line); + { 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); + ptmp->name = $1; + ptmp->wires[0] = wtmp; delete $1; + $$ = ptmp; } | IDENTIFIER '[' expression ':' expression ']' - { PWire*tmp = new PWire($1, NetNet::IMPLICIT, - NetNet::PIMPLICIT); - tmp->set_file(@1.text); - tmp->set_lineno(@1.first_line); + { PWire*wtmp = new PWire($1, NetNet::IMPLICIT, + NetNet::PIMPLICIT); + wtmp->set_file(@1.text); + wtmp->set_lineno(@1.first_line); if (!pform_expression_is_constant($3)) { yyerror(@3, "msb expression of port bit select " "must be constant."); } if (!pform_expression_is_constant($5)) { - yyerror(@3, "lsb expression of port bit select " + yyerror(@5, "lsb expression of port bit select " "must be constant."); } - tmp->set_range($3, $5); + wtmp->set_range($3, $5); + Module::port_t*ptmp = new Module::port_t(1); + ptmp->name = $1; + ptmp->wires[0] = wtmp; delete $1; - $$ = tmp; + $$ = ptmp; } | IDENTIFIER '[' error ']' { yyerror(@1, "invalid port bit select"); - $$ = new PWire($1, NetNet::IMPLICIT, NetNet::PIMPLICIT); - $$->set_file(@1.text); - $$->set_lineno(@1.first_line); + 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); + ptmp->name = $1; + ptmp->wires[0] = wtmp; delete $1; + $$ = ptmp; } ; +port_reference_list + : port_reference + { $$ = $1; } + | port_reference_list ',' port_reference + { Module::port_t*tmp = $1; + tmp->wires = svector(tmp->wires, $3->wires); + delete $3; + $$ = tmp; + } + ; + + /* The port_name rule is used with a module is being *instantiated*, + and not when it is being declared. See the port rule if you are + looking for the ports of a module declaration. */ + port_name : PORTNAME '(' expression ')' { portname_t*tmp = new portname_t; diff --git a/pform.cc b/pform.cc index e3855cb36..b73460ff1 100644 --- a/pform.cc +++ b/pform.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform.cc,v 1.36 1999/08/01 16:34:50 steve Exp $" +#ident "$Id: pform.cc,v 1.37 1999/08/03 04:14:49 steve Exp $" #endif # include "compiler.h" @@ -94,18 +94,11 @@ static unsigned long evaluate_delay(PExpr*delay) return pp->value().as_ulong(); } -void pform_startmodule(const string&name, svector*ports) +void pform_startmodule(const string&name, svector*ports) { assert( pform_cur_module == 0 ); - pform_cur_module = new Module(name, ports? ports->count() : 0); - - if (ports) { - for (unsigned idx = 0 ; idx < ports->count() ; idx += 1) { - pform_cur_module->add_wire((*ports)[idx]); - pform_cur_module->ports[idx] = (*ports)[idx]; - } - delete ports; - } + pform_cur_module = new Module(name, ports); + delete ports; } void pform_endmodule(const string&name) @@ -662,6 +655,10 @@ int pform_parse(const char*path, map&modules, /* * $Log: pform.cc,v $ + * Revision 1.37 1999/08/03 04:14:49 steve + * Parse into pform arbitrarily complex module + * port declarations. + * * Revision 1.36 1999/08/01 16:34:50 steve * Parse and elaborate rise/fall/decay times * for gates, and handle the rules for partial diff --git a/pform.h b/pform.h index ed1e548de..fe7ec40d6 100644 --- a/pform.h +++ b/pform.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform.h,v 1.26 1999/08/01 16:34:50 steve Exp $" +#ident "$Id: pform.h,v 1.27 1999/08/03 04:14:49 steve Exp $" #endif # include "netlist.h" @@ -95,7 +95,7 @@ struct lgate { * are to apply to the scope of that module. The endmodule causes the * pform to close up and finish the named module. */ -extern void pform_startmodule(const string&, svector*ports); +extern void pform_startmodule(const string&, svector*); extern void pform_endmodule(const string&); extern void pform_make_udp(const char*name, list*parms, @@ -167,6 +167,10 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.27 1999/08/03 04:14:49 steve + * Parse into pform arbitrarily complex module + * port declarations. + * * Revision 1.26 1999/08/01 16:34:50 steve * Parse and elaborate rise/fall/decay times * for gates, and handle the rules for partial diff --git a/pform_dump.cc b/pform_dump.cc index c4f224540..2584d10c0 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform_dump.cc,v 1.32 1999/08/01 16:34:50 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.33 1999/08/03 04:14:49 steve Exp $" #endif /* @@ -494,6 +494,31 @@ void Module::dump(ostream&out) const { out << "module " << name_ << ";" << endl; + for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) { + port_t*cur = ports_[idx]; + switch (cur->wires[0]->get_port_type()) { + case NetNet::PINPUT: + out << " input ." << cur->name << "("; + break; + case NetNet::POUTPUT: + out << " input ." << cur->name << "("; + break; + case NetNet::PINOUT: + out << " input ." << 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 << ")" << endl; + } + typedef map::const_iterator parm_iter_t; for (parm_iter_t cur = parameters.begin() ; cur != parameters.end() ; cur ++) { @@ -594,6 +619,10 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.33 1999/08/03 04:14:49 steve + * Parse into pform arbitrarily complex module + * port declarations. + * * Revision 1.32 1999/08/01 16:34:50 steve * Parse and elaborate rise/fall/decay times * for gates, and handle the rules for partial