From fb439c78b9071f306441e003b70e76f8e2e1df4f Mon Sep 17 00:00:00 2001 From: steve Date: Mon, 25 Jan 1999 05:45:56 +0000 Subject: [PATCH] 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. --- LineInfo.h | 60 +++++++++++++++++++++++++++++++++++ Module.h | 16 ++++++++-- PGate.h | 17 ++++++++-- Statement.cc | 18 ++++++++++- Statement.h | 21 ++++++++++-- elaborate.cc | 90 +++++++++++++++++++++++++++++++++++++++++++++++----- parse.y | 21 +++++++++--- pform.cc | 33 +++++++++++++++---- pform.h | 21 ++++++++++-- 9 files changed, 268 insertions(+), 29 deletions(-) create mode 100644 LineInfo.h 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. *