diff --git a/LineInfo.h b/LineInfo.h new file mode 100644 index 000000000..81c07b834 --- /dev/null +++ b/LineInfo.h @@ -0,0 +1,60 @@ +#ifndef __LineInfo_H +#define __LineInfo_H +/* + * Copyright (c) 1999 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(WINNT) +#ident "$Id: LineInfo.h,v 1.1 1999/01/25 05:45:56 steve Exp $" +#endif + +# include + +class LineInfo { + public: + LineInfo() : lineno_(0) { } + + string get_line() const + { char buf[8]; + sprintf(buf, "%u", lineno_); + return file_ + ":" + buf; + } + + void set_file(const string&f) { file_ = f; } + void set_lineno(unsigned n) { lineno_ = n; } + + private: + string file_; + unsigned lineno_; +}; + +/* + * $Log: LineInfo.h,v $ + * Revision 1.1 1999/01/25 05:45:56 steve + * Add the LineInfo class to carry the source file + * location of things. PGate, Statement and PProcess. + * + * elaborate handles module parameter mismatches, + * missing or incorrect lvalues for procedural + * assignment, and errors are propogated to the + * top of the elaboration call tree. + * + * Attach line numbers to processes, gates and + * assignment statements. + * + */ +#endif diff --git a/Module.h b/Module.h index fb45f56dc..92372226d 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.1 1998/11/03 23:28:52 steve Exp $" +#ident "$Id: Module.h,v 1.2 1999/01/25 05:45:56 steve Exp $" #endif # include @@ -57,7 +57,7 @@ class Module { const list& get_gates() const { return gates_; } const list& get_behaviors() const { return behaviors_; } - void elaborate(Design*, const string&path) const; + bool elaborate(Design*, const string&path) const; private: const string name_; @@ -74,6 +74,18 @@ class Module { /* * $Log: Module.h,v $ + * Revision 1.2 1999/01/25 05:45:56 steve + * Add the LineInfo class to carry the source file + * location of things. PGate, Statement and PProcess. + * + * elaborate handles module parameter mismatches, + * missing or incorrect lvalues for procedural + * assignment, and errors are propogated to the + * top of the elaboration call tree. + * + * Attach line numbers to processes, gates and + * assignment statements. + * * Revision 1.1 1998/11/03 23:28:52 steve * Introduce verilog to CVS. * diff --git a/PGate.h b/PGate.h index 0ea434929..c292daf40 100644 --- a/PGate.h +++ b/PGate.h @@ -19,10 +19,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: PGate.h,v 1.2 1998/12/01 00:42:13 steve Exp $" +#ident "$Id: PGate.h,v 1.3 1999/01/25 05:45:56 steve Exp $" #endif # include +# include "LineInfo.h" class PExpr; class PUdp; class Design; @@ -36,7 +37,7 @@ class Design; * step will need to convert expressions to a network of gates in * order to elaborate expression inputs, but that can easily be done. */ -class PGate { +class PGate : public LineInfo { public: explicit PGate(const string&name, const vector&pins, long del) @@ -135,6 +136,18 @@ class PGModule : public PGate { /* * $Log: PGate.h,v $ + * Revision 1.3 1999/01/25 05:45:56 steve + * Add the LineInfo class to carry the source file + * location of things. PGate, Statement and PProcess. + * + * elaborate handles module parameter mismatches, + * missing or incorrect lvalues for procedural + * assignment, and errors are propogated to the + * top of the elaboration call tree. + * + * Attach line numbers to processes, gates and + * assignment statements. + * * Revision 1.2 1998/12/01 00:42:13 steve * Elaborate UDP devices, * Support UDP type attributes, and diff --git a/Statement.cc b/Statement.cc index 3ff826326..390945175 100644 --- a/Statement.cc +++ b/Statement.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: Statement.cc,v 1.3 1998/11/11 03:13:04 steve Exp $" +#ident "$Id: Statement.cc,v 1.4 1999/01/25 05:45:56 steve Exp $" #endif # include "Statement.h" @@ -64,6 +64,10 @@ PCondit::~PCondit() delete else_; } +PProcess::~PProcess() +{ + delete statement_; +} PWhile::~PWhile() { @@ -73,6 +77,18 @@ PWhile::~PWhile() /* * $Log: Statement.cc,v $ + * Revision 1.4 1999/01/25 05:45:56 steve + * Add the LineInfo class to carry the source file + * location of things. PGate, Statement and PProcess. + * + * elaborate handles module parameter mismatches, + * missing or incorrect lvalues for procedural + * assignment, and errors are propogated to the + * top of the elaboration call tree. + * + * Attach line numbers to processes, gates and + * assignment statements. + * * Revision 1.3 1998/11/11 03:13:04 steve * Handle while loops. * diff --git a/Statement.h b/Statement.h index eb9b79656..cb680aaf4 100644 --- a/Statement.h +++ b/Statement.h @@ -19,12 +19,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: Statement.h,v 1.4 1998/11/11 03:13:04 steve Exp $" +#ident "$Id: Statement.h,v 1.5 1999/01/25 05:45:56 steve Exp $" #endif # include # include # include "netlist.h" +# include "LineInfo.h" class PExpr; class Statement; @@ -34,7 +35,7 @@ class Statement; * pointer to the single statement that is the process. A module may * have several concurrent processes. */ -class PProcess { +class PProcess : public LineInfo { public: enum Type { PR_INITIAL, PR_ALWAYS }; @@ -42,6 +43,8 @@ class PProcess { PProcess(Type t, Statement*st) : type_(t), statement_(st) { } + virtual ~PProcess(); + Type type() const { return type_; } Statement*statement() { return statement_; } @@ -57,7 +60,7 @@ class PProcess { * fact, the Statement class is abstract and represents all the * possible kinds of statements that exist in Verilog. */ -class Statement { +class Statement : public LineInfo { public: Statement() { } @@ -245,6 +248,18 @@ class PWhile : public Statement { /* * $Log: Statement.h,v $ + * Revision 1.5 1999/01/25 05:45:56 steve + * Add the LineInfo class to carry the source file + * location of things. PGate, Statement and PProcess. + * + * elaborate handles module parameter mismatches, + * missing or incorrect lvalues for procedural + * assignment, and errors are propogated to the + * top of the elaboration call tree. + * + * Attach line numbers to processes, gates and + * assignment statements. + * * Revision 1.4 1998/11/11 03:13:04 steve * Handle while loops. * diff --git a/elaborate.cc b/elaborate.cc index 3916fc643..631fea71c 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.10 1998/12/14 02:01:34 steve Exp $" +#ident "$Id: elaborate.cc,v 1.11 1999/01/25 05:45:56 steve Exp $" #endif /* @@ -221,6 +221,14 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const // Now connect the ports of the newly elaborated designs to // the expressions that are the instantiation parameters. + if (pin_count() != rmod->ports.size()) { + cerr << get_line() << ": Wrong number " + "of parameters. Expecting " << rmod->ports.size() << + ", got " << pin_count() << "." + << endl; + return; + } + assert(pin_count() == rmod->ports.size()); for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) { @@ -240,12 +248,22 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, const string&path) const assert(prt->pin_count() == sig->pin_count()); switch (prt->port_type()) { + // INPUT and OUTPUT ports are directional. Handle + // them like assignments. case NetNet::PINPUT: do_assign(des, path, prt, sig); break; case NetNet::POUTPUT: do_assign(des, path, sig, prt); break; + + // INOUT ports are like terminal posts. Just + // connect the inside and the outside nets + // together. + case NetNet::PINOUT: + for (unsigned p = 0 ; p < sig->pin_count() ; p += 1) + connect(prt->pin(p), sig->pin(p)); + break; default: assert(0); } @@ -569,10 +587,17 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const { NetNet*reg = des->find_signal(path+"."+lval()); if (reg == 0) { - cerr << "Could not match signal: " << lval() << endl; - return new NetProc; + cerr << get_line() << ": Could not match signal: " << + lval() << endl; + return 0; } assert(reg); + + if (reg->type() != NetNet::REG) { + cerr << get_line() << ": " << lval() << " is not a register." + << endl; + return 0; + } assert(reg->type() == NetNet::REG); assert(expr_); @@ -585,11 +610,29 @@ NetProc* PAssign::elaborate(Design*des, const string&path) const return cur; } +/* + * This is the elaboration method for a begin-end block. Try to + * elaborate the entire block, even if it fails somewhere. This way I + * get all the error messages out of it. Then, if I detected a failure + * then pass the failure up. + */ NetProc* PBlock::elaborate(Design*des, const string&path) const { NetBlock*cur = new NetBlock(NetBlock::SEQU); + bool fail_flag = false; + for (unsigned idx = 0 ; idx < size() ; idx += 1) { - cur->append(stat(idx)->elaborate(des, path)); + NetProc*tmp = stat(idx)->elaborate(des, path); + if (tmp == 0) { + fail_flag = true; + continue; + } + cur->append(tmp); + } + + if (fail_flag) { + delete cur; + cur = 0; } return cur; @@ -635,14 +678,18 @@ NetProc* PDelayStatement::elaborate(Design*des, const string&path) const NetProc* PEventStatement::elaborate(Design*des, const string&path) const { NetProc*enet = statement_->elaborate(des, path); + if (enet == 0) + return 0; + NetPEvent*ev = new NetPEvent(des->local_symbol(path), type_, enet); NetNet*expr = expr_->elaborate_net(des, path); if (expr == 0) { - cerr << "Failed to elaborate expression: "; + cerr << get_line() << ": Failed to elaborate expression: "; expr_->dump(cerr); cerr << endl; - exit(1); + delete ev; + return 0; } assert(expr); connect(ev->pin(0), expr->pin(0)); @@ -695,8 +742,10 @@ NetProc* PWhile::elaborate(Design*des, const string&path) const return loop; } -void Module::elaborate(Design*des, const string&path) const +bool Module::elaborate(Design*des, const string&path) const { + bool result_flag = true; + // Get all the explicitly declared wires of the module and // start the signals list with them. const list&wl = get_wires(); @@ -728,6 +777,13 @@ void Module::elaborate(Design*des, const string&path) const ; st ++ ) { NetProc*cur = (*st)->statement()->elaborate(des, path); + if (cur == 0) { + cerr << (*st)->get_line() << ": Elaboration " + "failed for this process." << endl; + result_flag = false; + continue; + } + NetProcTop*top; switch ((*st)->type()) { case PProcess::PR_INITIAL: @@ -740,6 +796,8 @@ void Module::elaborate(Design*des, const string&path) const des->add_process(top); } + + return result_flag; } Design* elaborate(const map&modules, @@ -759,16 +817,32 @@ Design* elaborate(const map&modules, modlist = &modules; udplist = &primitives; - rmod->elaborate(des, root); + bool rc = rmod->elaborate(des, root); modlist = 0; udplist = 0; + if (rc == false) { + delete des; + des = 0; + } return des; } /* * $Log: elaborate.cc,v $ + * Revision 1.11 1999/01/25 05:45:56 steve + * Add the LineInfo class to carry the source file + * location of things. PGate, Statement and PProcess. + * + * elaborate handles module parameter mismatches, + * missing or incorrect lvalues for procedural + * assignment, and errors are propogated to the + * top of the elaboration call tree. + * + * Attach line numbers to processes, gates and + * assignment statements. + * * Revision 1.10 1998/12/14 02:01:34 steve * Fully elaborate Sequential UDP behavior. * diff --git a/parse.y b/parse.y index a06f53c4d..9ac54dda9 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.10 1998/12/18 05:16:25 steve Exp $" +#ident "$Id: parse.y,v 1.11 1999/01/25 05:45:56 steve Exp $" #endif # include "parse_misc.h" @@ -271,6 +271,8 @@ gate_instance { lgate*tmp = new lgate; tmp->name = *$1; tmp->parms = $3; + tmp->file = @1.text; + tmp->lineno = @1.first_line; delete $1; $$ = tmp; } @@ -278,6 +280,8 @@ gate_instance { lgate*tmp = new lgate; tmp->name = ""; tmp->parms = $2; + tmp->file = @1.text; + tmp->lineno = @1.first_line; $$ = tmp; } ; @@ -446,10 +450,14 @@ module_item delete $3; } | K_always statement - { pform_make_behavior(PProcess::PR_ALWAYS, $2); + { PProcess*tmp = pform_make_behavior(PProcess::PR_ALWAYS, $2); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); } | K_initial statement - { pform_make_behavior(PProcess::PR_INITIAL, $2); + { PProcess*tmp = pform_make_behavior(PProcess::PR_INITIAL, $2); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); } | KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')' ';' { pform_set_attrib(*$3, *$5, *$7); @@ -592,7 +600,10 @@ statement $$ = tmp; } | lvalue '=' expression ';' - { $$ = pform_make_assignment($1, $3); + { Statement*tmp = pform_make_assignment($1, $3); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); + $$ = tmp; } | lvalue K_LE expression ';' { $$ = pform_make_assignment($1, $3); @@ -699,6 +710,8 @@ udp_initial : K_initial IDENTIFIER '=' NUMBER ';' { PExpr*etmp = new PENumber($4); PAssign*atmp = new PAssign(*$2, etmp); + atmp->set_file(@2.text); + atmp->set_lineno(@2.first_line); delete $2; $$ = atmp; } diff --git a/pform.cc b/pform.cc index 07c4c8a31..1893cf76f 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.7 1998/12/09 04:02:47 steve Exp $" +#ident "$Id: pform.cc,v 1.8 1999/01/25 05:45:56 steve Exp $" #endif # include "pform.h" @@ -27,6 +27,7 @@ # include # include # include +# include /* * The lexor accesses the vl_* variables. @@ -261,9 +262,12 @@ void pform_makegates(PGBuiltin::Type type, void pform_make_modgate(const string&type, const string&name, - const vector&wires) + const vector&wires, + const string&fn, unsigned ln) { PGate*cur = new PGModule(type, name, wires); + cur->set_file(fn); + cur->set_lineno(ln); cur_module->add_gate(cur); } @@ -281,7 +285,7 @@ void pform_make_modgates(const string&type, list*gates) wires[idx] = ep; } - pform_make_modgate(type, cur.name, wires); + pform_make_modgate(type, cur.name, wires, cur.file, cur.lineno); } delete gates; @@ -311,9 +315,11 @@ void pform_makewire(const string&name, NetNet::Type type) { PWire*cur = cur_module->get_wire(name); if (cur) { - if (cur->type != NetNet::IMPLICIT) - VLerror("Extra definition of wire."); - + if (cur->type != NetNet::IMPLICIT) { + strstream msg; + msg << "Duplicate definition of " << name << "."; + VLerror(msg.str()); + } cur->type = type; return; } @@ -433,10 +439,11 @@ list* pform_make_udp_input_ports(list*names) return out; } -void pform_make_behavior(PProcess::Type type, Statement*st) +PProcess* pform_make_behavior(PProcess::Type type, Statement*st) { PProcess*pp = new PProcess(type, st); cur_module->add_behavior(pp); + return pp; } Statement* pform_make_block(PBlock::BL_TYPE type, list*sl) @@ -493,6 +500,18 @@ int pform_parse(const char*path, map&modules, /* * $Log: pform.cc,v $ + * Revision 1.8 1999/01/25 05:45:56 steve + * Add the LineInfo class to carry the source file + * location of things. PGate, Statement and PProcess. + * + * elaborate handles module parameter mismatches, + * missing or incorrect lvalues for procedural + * assignment, and errors are propogated to the + * top of the elaboration call tree. + * + * Attach line numbers to processes, gates and + * assignment statements. + * * Revision 1.7 1998/12/09 04:02:47 steve * Support the include directive. * diff --git a/pform.h b/pform.h index d83337e0a..3906ea516 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.5 1998/12/09 04:02:47 steve Exp $" +#ident "$Id: pform.h,v 1.6 1999/01/25 05:45:56 steve Exp $" #endif # include "netlist.h" @@ -63,8 +63,13 @@ class PExpr; */ struct lgate { + lgate() : parms(0), lineno(0) { } + string name; list*parms; + + string file; + unsigned lineno; }; @@ -94,7 +99,7 @@ extern void pform_set_attrib(const string&name, const string&key, const string&value); extern void pform_set_type_attrib(const string&name, const string&key, const string&value); -extern void pform_make_behavior(PProcess::Type, Statement*); +extern PProcess* pform_make_behavior(PProcess::Type, Statement*); extern Statement* pform_make_block(PBlock::BL_TYPE, list*); extern Statement* pform_make_assignment(string*t, PExpr*e); extern Statement* pform_make_calltask(string*t, list* =0); @@ -132,6 +137,18 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.6 1999/01/25 05:45:56 steve + * Add the LineInfo class to carry the source file + * location of things. PGate, Statement and PProcess. + * + * elaborate handles module parameter mismatches, + * missing or incorrect lvalues for procedural + * assignment, and errors are propogated to the + * top of the elaboration call tree. + * + * Attach line numbers to processes, gates and + * assignment statements. + * * Revision 1.5 1998/12/09 04:02:47 steve * Support the include directive. *