From 22884f2e64ccf725260737e3a8979955e04e626a Mon Sep 17 00:00:00 2001 From: steve Date: Mon, 10 Jul 2006 00:21:49 +0000 Subject: [PATCH] Add support for full_case attribute. --- Statement.h | 10 ++++++-- attributes.txt | 8 +++++++ design_dump.cc | 16 ++++++++++++- elaborate.cc | 21 ++++++++++++++++- netlist.h | 8 +++++-- parse.y | 63 +++++++++++++++++++++++++++----------------------- pform.cc | 18 ++++++++++++++- pform.h | 7 +++++- pform_dump.cc | 20 +++++++++++++++- synth2.cc | 41 +++++++++++++++++++++++++++++--- 10 files changed, 171 insertions(+), 41 deletions(-) diff --git a/Statement.h b/Statement.h index 85b845add..2e1a8fa20 100644 --- a/Statement.h +++ b/Statement.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: Statement.h,v 1.40 2004/02/20 18:53:33 steve Exp $" +#ident "$Id: Statement.h,v 1.40.2.1 2006/07/10 00:21:49 steve Exp $" #endif # include @@ -71,12 +71,15 @@ class PProcess : public LineInfo { * fact, the Statement class is abstract and represents all the * possible kinds of statements that exist in Verilog. */ -class Statement : public LineInfo { +class Statement : public LineInfo, public Attrib { public: Statement() { } virtual ~Statement() =0; + map attributes; + + void dump_attributes(ostream&out, unsigned ind) const; virtual void dump(ostream&out, unsigned ind) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual void elaborate_scope(Design*des, NetScope*scope) const; @@ -456,6 +459,9 @@ class PWhile : public Statement { /* * $Log: Statement.h,v $ + * Revision 1.40.2.1 2006/07/10 00:21:49 steve + * Add support for full_case attribute. + * * Revision 1.40 2004/02/20 18:53:33 steve * Addtrbute keys are perm_strings. * diff --git a/attributes.txt b/attributes.txt index ed8280196..cefe62b8d 100644 --- a/attributes.txt +++ b/attributes.txt @@ -70,6 +70,14 @@ warning.) * Other Attributes +(* ivl_full_case *) + + This attribute only has meaning when attached to case statements, + and only when doing synthesis. The statement means to ignore the + possibility that some cases are not defined. Presume that the + device really is fully specified and do not emit any warnings + about missing guards. + [ none defined yet ] diff --git a/design_dump.cc b/design_dump.cc index 5edec26af..2ec02f253 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: design_dump.cc,v 1.149.2.5 2006/04/16 19:26:37 steve Exp $" +#ident "$Id: design_dump.cc,v 1.149.2.6 2006/07/10 00:21:50 steve Exp $" #endif # include "config.h" @@ -567,6 +567,8 @@ void NetCase::dump(ostream&o, unsigned ind) const break; } + dump_proc_attr(o, ind+2); + for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { o << setw(ind+2) << ""; if (items_[idx].guard) @@ -872,6 +874,15 @@ void NetProc::dump(ostream&o, unsigned ind) const o << setw(ind) << "" << "// " << typeid(*this).name() << endl; } +void NetProc::dump_proc_attr(ostream&o, unsigned ind) const +{ + unsigned idx; + for (idx = 0 ; idx < attr_cnt() ; idx += 1) { + o << setw(ind) << "" << "(* " << attr_key(idx) << " = " + << attr_value(idx) << " *)" << endl; + } +} + /* Dump an expression that no one wrote a dump method for. */ void NetExpr::dump(ostream&o) const { @@ -1119,6 +1130,9 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.149.2.6 2006/07/10 00:21:50 steve + * Add support for full_case attribute. + * * Revision 1.149.2.5 2006/04/16 19:26:37 steve * Fix handling of exploded memories with partial or missing resets. * diff --git a/elaborate.cc b/elaborate.cc index 2567bac47..e1eb3fe41 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: elaborate.cc,v 1.308.2.3 2006/06/12 00:16:51 steve Exp $" +#ident "$Id: elaborate.cc,v 1.308.2.4 2006/07/10 00:21:50 steve Exp $" #endif # include "config.h" @@ -67,6 +67,21 @@ void PGate::elaborate(Design*des, NetScope*scope) const typeid(*this).name() << endl; } +void process_attributes(Design*des, NetScope*scope, + Attrib*dest, const map&table) +{ + struct attrib_list_t*attrib_list = 0; + unsigned attrib_list_n = 0; + attrib_list = evaluate_attributes(table, attrib_list_n, + des, scope); + + for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1) + dest->attribute(attrib_list[adx].key, + attrib_list[adx].val); + + delete[]attrib_list; +} + /* * Elaborate the continuous assign. (This is *not* the procedural * assign.) Elaborate the lvalue and rvalue, and do the assignment. @@ -1391,6 +1406,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const NetCase*res = new NetCase(type_, expr, icount); res->set_line(*this); + process_attributes(des, scope, res, attributes); /* Iterate over all the case items (guard/statement pairs) elaborating them. If the guard has no expression, then this @@ -2785,6 +2801,9 @@ Design* elaborate(listroots) /* * $Log: elaborate.cc,v $ + * Revision 1.308.2.4 2006/07/10 00:21:50 steve + * Add support for full_case attribute. + * * Revision 1.308.2.3 2006/06/12 00:16:51 steve * Add support for -Wunused warnings. * diff --git a/netlist.h b/netlist.h index 4e6c840cc..6eff4a0ad 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.h,v 1.321.2.19 2006/06/23 03:49:46 steve Exp $" +#ident "$Id: netlist.h,v 1.321.2.20 2006/07/10 00:21:51 steve Exp $" #endif /* @@ -1438,7 +1438,7 @@ class NetUDP : public NetNode { * linked into the netlist. However, elaborating a process may cause * special nodes to be created to handle things like events. */ -class NetProc : public virtual LineInfo { +class NetProc : public virtual LineInfo, public Attrib { public: explicit NetProc(); @@ -1495,6 +1495,7 @@ class NetProc : public virtual LineInfo { const svector&events); virtual void dump(ostream&, unsigned ind) const; + void dump_proc_attr(ostream&, unsigned ind) const; private: friend class NetBlock; @@ -3536,6 +3537,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.321.2.20 2006/07/10 00:21:51 steve + * Add support for full_case attribute. + * * Revision 1.321.2.19 2006/06/23 03:49:46 steve * synthesis of NetCondit handles partial resets. * diff --git a/parse.y b/parse.y index 7e73901ad..a0cb18770 100644 --- a/parse.y +++ b/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: parse.y,v 1.201.2.3 2006/02/07 22:45:54 steve Exp $" +#ident "$Id: parse.y,v 1.201.2.4 2006/07/10 00:21:52 steve Exp $" #endif # include "config.h" @@ -308,17 +308,14 @@ attribute integers. This rule matches those declarations. The containing rule has presumably set up the scope. */ block_item_decl - : attribute_list_opt K_reg signed_opt range register_variable_list ';' - { pform_set_net_range($5, $4, $3); - if ($1) delete $1; + : K_reg signed_opt range register_variable_list ';' + { pform_set_net_range($4, $3, $2); } - | attribute_list_opt K_reg signed_opt register_variable_list ';' - { pform_set_net_range($4, 0, $3); - if ($1) delete $1; + | K_reg signed_opt register_variable_list ';' + { pform_set_net_range($3, 0, $2); } - | attribute_list_opt K_integer register_variable_list ';' - { pform_set_reg_integer($3); - if ($1) delete $1; + | K_integer register_variable_list ';' + { pform_set_reg_integer($2); } | K_time register_variable_list ';' { pform_set_reg_time($2); @@ -335,15 +332,13 @@ block_item_decl /* Recover from errors that happen within variable lists. Use the trailing semi-colon to resync the parser. */ - | attribute_list_opt K_reg error ';' - { yyerror(@2, "error: syntax error in reg variable list."); + | K_reg error ';' + { yyerror(@1, "error: syntax error in reg variable list."); yyerrok; - if ($1) delete $1; } - | attribute_list_opt K_integer error ';' - { yyerror(@2, "error: syntax error in integer variable list."); + | K_integer error ';' + { yyerror(@1, "error: syntax error in integer variable list."); yyerrok; - if ($1) delete $1; } | K_time error ';' { yyerror(@1, "error: syntax error in time variable list."); @@ -2548,9 +2543,9 @@ statement tmp->set_lineno(@1.first_line); $$ = tmp; } - | K_begin error K_end +/* | K_begin error K_end { yyerrok; } - +*/ /* fork-join blocks are very similar to begin-end blocks. In fact, from the parser's perspective there is no real difference. All we need to do is remember that this is a parallel block so that the @@ -2697,28 +2692,34 @@ statement tmp->set_lineno(@1.first_line); $$ = tmp; } - | event_control statement_opt + | event_control attribute_list_opt statement_opt { PEventStatement*tmp = $1; if (tmp == 0) { yyerror(@1, "error: Invalid event control."); $$ = 0; } else { - tmp->set_statement($2); + pform_attach_attributes($3, $2); + tmp->set_statement($3); $$ = tmp; } + if ($2) delete $2; } - | '@' '*' statement_opt + | '@' '*' attribute_list_opt statement_opt { PEventStatement*tmp = new PEventStatement; tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); - tmp->set_statement($3); + pform_attach_attributes($4, $3); + tmp->set_statement($4); + if ($3) delete $3; $$ = tmp; } - | '@' '(' '*' ')' statement_opt + | '@' '(' '*' ')' attribute_list_opt statement_opt { PEventStatement*tmp = new PEventStatement; tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); - tmp->set_statement($5); + pform_attach_attributes($6, $5); + tmp->set_statement($6); + if ($5) delete $5; $$ = tmp; } | lpvalue '=' expression ';' @@ -2827,14 +2828,18 @@ statement ; statement_list - : statement_list statement - { svector*tmp = new svector(*$1, $2); + : statement_list attribute_list_opt statement + { pform_attach_attributes($3, $2); + svector*tmp = new svector(*$1, $3); delete $1; + if ($2) delete $2; $$ = tmp; } - | statement - { svector*tmp = new svector(1); - (*tmp)[0] = $1; + | attribute_list_opt statement + { pform_attach_attributes($2, $1); + svector*tmp = new svector(1); + (*tmp)[0] = $2; + if ($1) delete $1; $$ = tmp; } ; diff --git a/pform.cc b/pform.cc index 0256243f4..fc5ca5b04 100644 --- a/pform.cc +++ b/pform.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.cc,v 1.129 2004/10/04 01:10:55 steve Exp $" +#ident "$Id: pform.cc,v 1.129.2.1 2006/07/10 00:21:53 steve Exp $" #endif # include "config.h" @@ -203,6 +203,19 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val, return res; } +void pform_attach_attributes(Statement*obj, svector*attr) +{ + if (obj == 0) + return; + if (attr == 0) + return; + + for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) { + named_pexpr_t*tmp = (*attr)[idx]; + obj->attributes[tmp->name] = tmp->parm; + } +} + void pform_startmodule(const char*name, const char*file, unsigned lineno, svector*attr) { @@ -1597,6 +1610,9 @@ int pform_parse(const char*path, FILE*file) /* * $Log: pform.cc,v $ + * Revision 1.129.2.1 2006/07/10 00:21:53 steve + * Add support for full_case attribute. + * * Revision 1.129 2004/10/04 01:10:55 steve * Clean up spurious trailing white space. * diff --git a/pform.h b/pform.h index ef97ff9ab..53e4d874b 100644 --- a/pform.h +++ b/pform.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform.h,v 1.81 2004/08/26 04:02:04 steve Exp $" +#ident "$Id: pform.h,v 1.81.2.1 2006/07/10 00:21:53 steve Exp $" #endif # include "netlist.h" @@ -219,6 +219,8 @@ extern void pform_set_attrib(perm_string name, perm_string key, extern void pform_set_type_attrib(perm_string name, const string&key, char*value); +extern void pform_attach_attributes(Statement*obj, svector*attr); + extern void pform_set_parameter(perm_string name, bool signed_flag, svector*range, @@ -298,6 +300,9 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.81.2.1 2006/07/10 00:21:53 steve + * Add support for full_case attribute. + * * Revision 1.81 2004/08/26 04:02:04 steve * Add support for localparam ranges. * diff --git a/pform_dump.cc b/pform_dump.cc index a70425cc9..ed35bb791 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: pform_dump.cc,v 1.88 2004/10/04 01:10:55 steve Exp $" +#ident "$Id: pform_dump.cc,v 1.88.2.1 2006/07/10 00:21:54 steve Exp $" #endif # include "config.h" @@ -418,6 +418,19 @@ void Statement::dump(ostream&out, unsigned ind) const out << setw(ind) << ""; out << "/* " << get_line() << ": " << typeid(*this).name() << " */ ;" << endl; + dump_attributes(out, ind+2); +} + +void Statement::dump_attributes(ostream&out, unsigned ind) const +{ + for (map::const_iterator idx = attributes.begin() + ; idx != attributes.end() + ; idx ++) { + out << setw(ind) << "" << "(* " << (*idx).first; + if ((*idx).second) + out << " = " << *(*idx).second; + out << " *)" << endl; + } } void PAssign::dump(ostream&out, unsigned ind) const @@ -487,6 +500,8 @@ void PCase::dump(ostream&out, unsigned ind) const } out << " (" << *expr_ << ") /* " << get_line() << " */" << endl; + dump_attributes(out, ind+2); + for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) { PCase::Item*cur = (*items_)[idx]; @@ -909,6 +924,9 @@ void PUdp::dump(ostream&out) const /* * $Log: pform_dump.cc,v $ + * Revision 1.88.2.1 2006/07/10 00:21:54 steve + * Add support for full_case attribute. + * * Revision 1.88 2004/10/04 01:10:55 steve * Clean up spurious trailing white space. * diff --git a/synth2.cc b/synth2.cc index 5e1e76046..c909ce3de 100644 --- a/synth2.cc +++ b/synth2.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: synth2.cc,v 1.39.2.38 2006/07/02 00:50:15 steve Exp $" +#ident "$Id: synth2.cc,v 1.39.2.39 2006/07/10 00:21:54 steve Exp $" #endif # include "config.h" @@ -444,6 +444,10 @@ bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag, NetNet*esig = expr_->synthesize(des); + bool full_case_flag = false; + if (attribute(perm_string::literal("ivl_full_case")).len() > 0) + full_case_flag = true; + /* Scan the select vector looking for constant bits. The constant bits will be elided from the select input connect, but we still need to keep track of them. */ @@ -632,7 +636,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag, default_sig = sig; } - if (statement_map[item] == 0 && !sync_flag) { + if (statement_map[item] == 0 && !sync_flag && !full_case_flag) { /* Missing case and no default; this could still be * synthesizable with synchronous logic, but not here. */ cerr << get_line() @@ -645,7 +649,35 @@ bool NetCase::synth_async(Design*des, NetScope*scope, bool sync_flag, continue; } - if (statement_map[item] == 0) { + if (statement_map[item] == 0 && !sync_flag) { + assert(full_case_flag); + + /* Cases that should never happen, we connect to + 0 bits. Hopefully, the target (or constant + propagation) will know how to optimize this + away. */ + NetConst*zero = new NetConst(scope, scope->local_symbol(), + verinum::V0); + zero->set_line(*this); + des->add_node(zero); + + NetNet*zsig = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, 1); + zsig->local_flag(true); + zsig->set_line(*this); + + connect(zsig->pin(0), zero->pin(0)); + + for (unsigned idx=0; idx < mux->width(); idx += 1) + connect(mux->pin_Data(idx,item), zsig->pin(0)); + + if (debug_synth) { + cerr << get_line() + << ": debug: Case item " << item << " is set to" + << " zero in combinational process." << endl; + } + + } else if (statement_map[item] == 0) { /* If this is an unspecified case, then get the input from the synchronous output. Note that we @@ -2179,6 +2211,9 @@ void synth2(Design*des) /* * $Log: synth2.cc,v $ + * Revision 1.39.2.39 2006/07/10 00:21:54 steve + * Add support for full_case attribute. + * * Revision 1.39.2.38 2006/07/02 00:50:15 steve * Properly synthesize casex statements. *