From 8bdd381cdf7e9a6f32c7b7340991cc7a86bc0809 Mon Sep 17 00:00:00 2001 From: steve Date: Wed, 3 Feb 1999 04:20:11 +0000 Subject: [PATCH] Parse and elaborate the Verilog CASE statement. --- Statement.cc | 32 +++++++++++++++++++++++++++++++- Statement.h | 30 +++++++++++++++++++++++++++++- design_dump.cc | 27 ++++++++++++++++++++++++++- elaborate.cc | 27 +++++++++++++++++++++++++-- netlist.cc | 33 ++++++++++++++++++++++++++++++++- netlist.h | 33 ++++++++++++++++++++++++++++++++- parse.y | 48 +++++++++++++++++++++++++++++++++++++++++++++++- pform_dump.cc | 27 ++++++++++++++++++++++++++- 8 files changed, 248 insertions(+), 9 deletions(-) diff --git a/Statement.cc b/Statement.cc index 390945175..80296b586 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.4 1999/01/25 05:45:56 steve Exp $" +#ident "$Id: Statement.cc,v 1.5 1999/02/03 04:20:11 steve Exp $" #endif # include "Statement.h" @@ -57,6 +57,33 @@ PCallTask::PCallTask(const string&n, const list&p) } +PCase::PCase(PExpr*ex, list*l) +: expr_(ex) +{ + nitems_ = l->size(); + items_ = new Item[nitems_]; + + list::const_iterator cur; + unsigned idx; + for (cur = l->begin(), idx = 0 ; cur != l->end() ; cur ++, idx += 1) { + items_[idx] = *(*cur); + delete (*cur); + } + + delete l; +} + +PCase::~PCase() +{ + delete expr_; + for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + if (items_[idx].expr) delete items_[idx].expr; + if (items_[idx].stat) delete items_[idx].stat; + } + + delete[]items_; +} + PCondit::~PCondit() { delete expr_; @@ -77,6 +104,9 @@ PWhile::~PWhile() /* * $Log: Statement.cc,v $ + * Revision 1.5 1999/02/03 04:20:11 steve + * Parse and elaborate the Verilog CASE statement. + * * 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. diff --git a/Statement.h b/Statement.h index cb680aaf4..144bc5648 100644 --- a/Statement.h +++ b/Statement.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: Statement.h,v 1.5 1999/01/25 05:45:56 steve Exp $" +#ident "$Id: Statement.h,v 1.6 1999/02/03 04:20:11 steve Exp $" #endif # include @@ -149,6 +149,31 @@ class PCallTask : public Statement { PExpr**const parms_; }; +class PCase : public Statement { + + public: + struct Item { + PExpr*expr; + Statement*stat; + }; + + PCase(PExpr*ex, list*); + ~PCase(); + + virtual NetProc* elaborate(Design*des, const string&path) const; + virtual void dump(ostream&out, unsigned ind) const; + + private: + PExpr*expr_; + + Item*items_; + unsigned nitems_; + + private: // not implemented + PCase(const PCase&); + PCase& operator= (const PCase&); +}; + class PCondit : public Statement { public: @@ -248,6 +273,9 @@ class PWhile : public Statement { /* * $Log: Statement.h,v $ + * Revision 1.6 1999/02/03 04:20:11 steve + * Parse and elaborate the Verilog CASE statement. + * * 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. diff --git a/design_dump.cc b/design_dump.cc index 729d22427..52b85a249 100644 --- a/design_dump.cc +++ b/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.10 1999/02/01 00:26:48 steve Exp $" +#ident "$Id: design_dump.cc,v 1.11 1999/02/03 04:20:11 steve Exp $" #endif /* @@ -303,6 +303,28 @@ void NetBlock::dump(ostream&o, unsigned ind) const o << setw(ind) << "" << "end" << endl; } +void NetCase::dump(ostream&o, unsigned ind) const +{ + o << setw(ind) << "" << "case (" << *expr_ << ")" << endl; + + for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + o << setw(ind+2) << ""; + if (items_[idx].guard) + o << *items_[idx].guard << ":"; + else + o << "default:"; + + if (items_[idx].statement) { + o << endl; + items_[idx].statement->dump(o, ind+6); + } else { + o << " ;" << endl; + } + } + + o << setw(ind) << "" << "endcase" << endl; +} + void NetCondit::dump(ostream&o, unsigned ind) const { o << setw(ind) << "" << "if ("; @@ -468,6 +490,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.11 1999/02/03 04:20:11 steve + * Parse and elaborate the Verilog CASE statement. + * * Revision 1.10 1999/02/01 00:26:48 steve * Carry some line info to the netlist, * Dump line numbers for processes. diff --git a/elaborate.cc b/elaborate.cc index e2057ce9b..936499a4d 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.12 1999/02/01 00:26:49 steve Exp $" +#ident "$Id: elaborate.cc,v 1.13 1999/02/03 04:20:11 steve Exp $" #endif /* @@ -650,11 +650,31 @@ NetProc* PBlock::elaborate(Design*des, const string&path) const return cur; } +NetProc* PCase::elaborate(Design*des, const string&path) const +{ + NetExpr*expr = expr_->elaborate_expr(des, path); + NetCase*res = new NetCase(expr, nitems_); + + for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + NetExpr*gu = 0; + NetProc*st = 0; + if (items_[idx].expr) + gu = items_[idx].expr->elaborate_expr(des, path); + + if (items_[idx].stat) + st = items_[idx].stat->elaborate(des, path); + + res->set_case(idx, gu, st); + } + + return res; +} + NetProc* PCondit::elaborate(Design*des, const string&path) const { NetExpr*expr = expr_->elaborate_expr(des, path); NetProc*i = if_->elaborate(des, path); - NetProc*e = else_->elaborate(des, path); + NetProc*e = else_? else_->elaborate(des, path) : 0; NetCondit*res = new NetCondit(expr, i, e); return res; @@ -851,6 +871,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.13 1999/02/03 04:20:11 steve + * Parse and elaborate the Verilog CASE statement. + * * Revision 1.12 1999/02/01 00:26:49 steve * Carry some line info to the netlist, * Dump line numbers for processes. diff --git a/netlist.cc b/netlist.cc index 1b273ee30..671618f23 100644 --- a/netlist.cc +++ b/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.14 1998/12/18 05:16:25 steve Exp $" +#ident "$Id: netlist.cc,v 1.15 1999/02/03 04:20:11 steve Exp $" #endif # include @@ -320,6 +320,34 @@ void NetBlock::append(NetProc*cur) } } +NetCase::NetCase(NetExpr*ex, unsigned cnt) +: expr_(ex), nitems_(cnt) +{ + assert(expr_); + items_ = new Item[nitems_]; + for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + items_[idx].guard = 0; + items_[idx].statement = 0; + } +} + +NetCase::~NetCase() +{ + delete expr_; + for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + if (items_[idx].guard) delete items_[idx].guard; + if (items_[idx].statement) delete items_[idx].statement; + } + delete[]items_; +} + +void NetCase::set_case(unsigned idx, NetExpr*e, NetProc*p) +{ + assert(idx < nitems_); + items_[idx].guard = e; + items_[idx].statement = p; +} + NetTask::~NetTask() { delete[]parms_; @@ -845,6 +873,9 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.15 1999/02/03 04:20:11 steve + * Parse and elaborate the Verilog CASE statement. + * * Revision 1.14 1998/12/18 05:16:25 steve * Parse more UDP input edge descriptions. * diff --git a/netlist.h b/netlist.h index d7b9f0da5..f817b1939 100644 --- a/netlist.h +++ b/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.16 1999/02/01 00:26:49 steve Exp $" +#ident "$Id: netlist.h,v 1.17 1999/02/03 04:20:11 steve Exp $" #endif /* @@ -531,6 +531,34 @@ class NetBlock : public NetProc { NetProc*last_; }; +/* A CASE statement in the verilog source leads, eventually, to one of + these. This is different from a simple conditional because of the + way the comparisons are performed. Also, it is likely that the + target may be able to optimize differently. */ +class NetCase : public NetProc { + + public: + NetCase(NetExpr*ex, unsigned cnt); + ~NetCase(); + + void set_case(unsigned idx, NetExpr*ex, NetProc*st); + + //virtual void emit_proc(ostream&, struct target_t*) const; + virtual void dump(ostream&, unsigned ind) const; + + private: + + struct Item { + NetExpr*guard; + NetProc*statement; + }; + + NetExpr*expr_; + unsigned nitems_; + Item*items_; +}; + + /* A condit represents a conditional. It has an expression to test, and a pair of statements to select from. */ class NetCondit : public NetProc { @@ -925,6 +953,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.17 1999/02/03 04:20:11 steve + * Parse and elaborate the Verilog CASE statement. + * * Revision 1.16 1999/02/01 00:26:49 steve * Carry some line info to the netlist, * Dump line numbers for processes. diff --git a/parse.y b/parse.y index 9ac54dda9..b181a92b7 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.11 1999/01/25 05:45:56 steve Exp $" +#ident "$Id: parse.y,v 1.12 1999/02/03 04:20:11 steve Exp $" #endif # include "parse_misc.h" @@ -34,6 +34,9 @@ extern void lex_end_table(); string*text; list*strings; + PCase::Item*citem; + list*citems; + lgate*gate; list*gates; @@ -89,6 +92,9 @@ extern void lex_end_table(); %type port %type list_of_ports list_of_ports_opt +%type case_item +%type case_items + %type gate_instance %type gate_instance_list @@ -123,6 +129,40 @@ bitsel { $$ = $2; } ; +case_item + : expression ':' statement_opt + { PCase::Item*tmp = new PCase::Item; + tmp->expr = $1; + tmp->stat = $3; + $$ = tmp; + } + | K_default ':' statement_opt + { PCase::Item*tmp = new PCase::Item; + tmp->expr = 0; + tmp->stat = $3; + $$ = tmp; + } + | K_default statement_opt + { PCase::Item*tmp = new PCase::Item; + tmp->expr = 0; + tmp->stat = $2; + $$ = tmp; + } + ; + +case_items + : case_items case_item + { list*tmp = $1; + tmp->push_back($2); + $$ = tmp; + } + | case_item + { list*tmp = new list; + tmp->push_back($1); + $$ = tmp; + } + ; + const_expression : NUMBER { $$ = new PENumber($1); @@ -546,6 +586,12 @@ statement { $$ = pform_make_block(PBlock::BL_SEQ, 0); } | K_fork K_join { $$ = pform_make_block(PBlock::BL_PAR, 0); } + | K_case '(' expression ')' case_items K_endcase + { PCase*tmp = new PCase($3, $5); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); + $$ = tmp; + } | K_if '(' expression ')' statement_opt { PCondit*tmp = new PCondit($3, $5, 0); $$ = tmp; diff --git a/pform_dump.cc b/pform_dump.cc index 16b5a3d3b..d103376a3 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.8 1999/02/01 00:26:49 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.9 1999/02/03 04:20:11 steve Exp $" #endif /* @@ -224,6 +224,28 @@ void PCallTask::dump(ostream&out, unsigned ind) const out << ";" << endl; } +void PCase::dump(ostream&out, unsigned ind) const +{ + out << setw(ind) << "" << "case (" << *expr_ << ") /* " << + get_line() << " */" << endl; + + for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + if (items_[idx].expr) + out << setw(ind+2) << "" << *items_[idx].expr << ":"; + else + out << setw(ind+2) << "" << "default:"; + + if (items_[idx].stat) { + out << endl; + items_[idx].stat->dump(out, ind+6); + } else { + out << " ;" << endl; + } + } + + out << setw(ind) << "" << "endcase" << endl; +} + void PCondit::dump(ostream&out, unsigned ind) const { out << setw(ind) << "" << "if (" << *expr_ << ")" << endl; @@ -373,6 +395,9 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.9 1999/02/03 04:20:11 steve + * Parse and elaborate the Verilog CASE statement. + * * Revision 1.8 1999/02/01 00:26:49 steve * Carry some line info to the netlist, * Dump line numbers for processes.