From 10ffaeda9049d75a1a9c0d2ba87b95b1bba6da98 Mon Sep 17 00:00:00 2001 From: steve Date: Sun, 16 May 1999 05:08:42 +0000 Subject: [PATCH] Redo constant expression detection to happen after parsing. Parse more operators and expressions. --- PExpr.cc | 34 ++++++++++- PExpr.h | 19 +++++- elaborate.cc | 14 ++++- lexor.lex | 6 +- netlist.cc | 13 +++- netlist.h | 19 +++++- parse.y | 170 ++++++++++++++++++++++++++++++--------------------- pform.cc | 20 +++--- pform.h | 11 +++- 9 files changed, 216 insertions(+), 90 deletions(-) diff --git a/PExpr.cc b/PExpr.cc index f5b8f94ea..688840f1d 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -17,10 +17,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: PExpr.cc,v 1.2 1998/11/11 00:01:51 steve Exp $" +#ident "$Id: PExpr.cc,v 1.3 1999/05/16 05:08:42 steve Exp $" #endif # include "PExpr.h" +# include "Module.h" # include PExpr::~PExpr() @@ -32,6 +33,21 @@ bool PExpr::is_the_same(const PExpr*that) const return typeid(this) == typeid(that); } +bool PExpr::is_constant(Module*) const +{ + return false; +} + +/* + * An identifier can be in a constant expresion if (and only if) it is + * a parameter. + */ +bool PEIdent::is_constant(Module*mod) const +{ + map::const_iterator cur = mod->parameters.find(text_); + return cur != mod->parameters.end(); +} + bool PENumber::is_the_same(const PExpr*that) const { const PENumber*obj = dynamic_cast(that); @@ -41,8 +57,24 @@ bool PENumber::is_the_same(const PExpr*that) const return *value_ == *obj->value_; } +bool PENumber::is_constant(Module*) const +{ + return true; +} + +bool PEString::is_constant(Module*) const +{ + return true; +} + /* * $Log: PExpr.cc,v $ + * Revision 1.3 1999/05/16 05:08:42 steve + * Redo constant expression detection to happen + * after parsing. + * + * Parse more operators and expressions. + * * Revision 1.2 1998/11/11 00:01:51 steve * Check net ranges in declarations. * diff --git a/PExpr.h b/PExpr.h index 148ec5d9f..3d051992c 100644 --- a/PExpr.h +++ b/PExpr.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: PExpr.h,v 1.8 1999/05/10 00:16:57 steve Exp $" +#ident "$Id: PExpr.h,v 1.9 1999/05/16 05:08:42 steve Exp $" #endif # include @@ -28,6 +28,7 @@ # include "LineInfo.h" class Design; +class Module; class NetNet; class NetExpr; @@ -57,6 +58,12 @@ class PExpr : public LineInfo { // this expression. This method is used for comparing // expressions that must be structurally "identical". virtual bool is_the_same(const PExpr*that) const; + + // Return true if this expression is a valid constant + // expression. the Module pointer is needed to find parameter + // identifiers and any other module specific interpretations + // of expresions. + virtual bool is_constant(Module*) const; }; ostream& operator << (ostream&, const PExpr&); @@ -99,6 +106,7 @@ class PEIdent : public PExpr { virtual void dump(ostream&) const; virtual NetNet* elaborate_net(Design*des, const string&path) const; virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual bool is_constant(Module*) const; verinum* eval_const(const Design*des, const string&path) const; // XXXX @@ -132,6 +140,7 @@ class PENumber : public PExpr { virtual verinum* eval_const(const Design*des, const string&path) const; virtual bool is_the_same(const PExpr*that) const; + virtual bool is_constant(Module*) const; private: verinum*const value_; @@ -147,6 +156,8 @@ class PEString : public PExpr { virtual void dump(ostream&) const; virtual NetExpr*elaborate_expr(Design*des, const string&path) const; + virtual bool is_constant(Module*) const; + private: const string text_; }; @@ -185,6 +196,12 @@ class PEBinary : public PExpr { /* * $Log: PExpr.h,v $ + * Revision 1.9 1999/05/16 05:08:42 steve + * Redo constant expression detection to happen + * after parsing. + * + * Parse more operators and expressions. + * * Revision 1.8 1999/05/10 00:16:57 steve * Parse and elaborate the concatenate operator * in structural contexts, Replace vector diff --git a/elaborate.cc b/elaborate.cc index 833c51870..aec09646e 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.25 1999/05/10 00:16:58 steve Exp $" +#ident "$Id: elaborate.cc,v 1.26 1999/05/16 05:08:42 steve Exp $" #endif /* @@ -724,7 +724,9 @@ NetExpr* PEBinary::elaborate_expr(Design*des, const string&path) const NetExpr* PENumber::elaborate_expr(Design*des, const string&path) const { assert(value_); - return new NetEConst(*value_); + NetEConst*tmp = new NetEConst(*value_); + tmp->set_line(*this); + return tmp; } NetExpr* PEString::elaborate_expr(Design*des, const string&path) const @@ -789,7 +791,7 @@ NetExpr*PEIdent::elaborate_expr(Design*des, const string&path) const NetExpr* PExpr::elaborate_expr(Design*des, const string&path) const { cerr << "Cannot elaborate expression: " << *this << endl; - return new NetEConst(verinum()); + return 0; } NetExpr* PEUnary::elaborate_expr(Design*des, const string&path) const @@ -1148,6 +1150,12 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.26 1999/05/16 05:08:42 steve + * Redo constant expression detection to happen + * after parsing. + * + * Parse more operators and expressions. + * * Revision 1.25 1999/05/10 00:16:58 steve * Parse and elaborate the concatenate operator * in structural contexts, Replace vector diff --git a/lexor.lex b/lexor.lex index 07a58463d..9060e4a8f 100644 --- a/lexor.lex +++ b/lexor.lex @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: lexor.lex,v 1.14 1999/05/13 04:02:09 steve Exp $" +#ident "$Id: lexor.lex,v 1.15 1999/05/16 05:08:42 steve Exp $" #endif //# define YYSTYPE lexval @@ -68,6 +68,8 @@ static verinum*make_unsized_hex(const char*txt); \n { yylloc.first_line += 1; yymore(); } "*/" { BEGIN(0); } +"<<" { return K_LS; } +">>" { return K_RS; } "<=" { return K_LE; } ">=" { return K_GE; } "==" { return K_EQ; } @@ -77,7 +79,7 @@ static verinum*make_unsized_hex(const char*txt); "||" { return K_LOR; } "&&" { return K_LAND; } -[}{;:\[\],()#=.@&!<|^~+*/-] { return yytext[0]; } +[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; } \" { BEGIN(CSTRING); } \\\" { yymore(); } diff --git a/netlist.cc b/netlist.cc index ac87d8b43..12b3b16ff 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.25 1999/05/13 04:02:09 steve Exp $" +#ident "$Id: netlist.cc,v 1.26 1999/05/16 05:08:42 steve Exp $" #endif # include @@ -507,6 +507,11 @@ NetEConst::~NetEConst() void NetEConst::set_width(unsigned w) { + if (w > value_.len()) { + cerr << get_line() << ": Cannot expand " << *this + << " to " << w << " bits." << endl; + assert(0); + } assert(w <= value_.len()); value_ = verinum(value_, w); expr_width(w); @@ -1054,6 +1059,12 @@ NetNet* Design::find_signal(bool (*func)(const NetNet*)) /* * $Log: netlist.cc,v $ + * Revision 1.26 1999/05/16 05:08:42 steve + * Redo constant expression detection to happen + * after parsing. + * + * Parse more operators and expressions. + * * Revision 1.25 1999/05/13 04:02:09 steve * More precise handling of verinum bit lengths. * diff --git a/netlist.h b/netlist.h index dc0979e79..fd15363a8 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.30 1999/05/12 04:03:19 steve Exp $" +#ident "$Id: netlist.h,v 1.31 1999/05/16 05:08:42 steve Exp $" #endif /* @@ -327,7 +327,7 @@ class NetMemory { * being referenced, so can handle garbage collection. Also, this * trick can be used to replace subexpressions. */ -class NetExpr { +class NetExpr : public LineInfo { public: explicit NetExpr(unsigned w =0) : width_(w), reflist_(0) { } virtual ~NetExpr() =0; @@ -881,15 +881,22 @@ class NetProcTop : public LineInfo { * * ^ -- Bit-wise exclusive OR * + -- Arithmetic add - * - -- Arighmetic minus + * - -- Arithmetic minus + * * -- Arithmetic multiply + * / -- Arithmetic divide + * % -- Arithmetic modulus * & -- Bit-wise AND * | -- Bit-wise OR * e -- Logical equality (==) * E -- Case equality (===) + * L -- Less or equal + * G -- Greater or equal * n -- Logical inequality (!=) * N -- Case inequality (!==) * a -- Logical AND (&&) * o -- Logical OR (||) + * l -- Left shift (<<) + * r -- Right shift (>>) */ class NetEBinary : public NetExpr { @@ -1178,6 +1185,12 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.31 1999/05/16 05:08:42 steve + * Redo constant expression detection to happen + * after parsing. + * + * Parse more operators and expressions. + * * Revision 1.30 1999/05/12 04:03:19 steve * emit NetAssignMem objects in vvm target. * diff --git a/parse.y b/parse.y index 3dd785a7a..b53503340 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.25 1999/05/10 00:16:58 steve Exp $" +#ident "$Id: parse.y,v 1.26 1999/05/16 05:08:42 steve Exp $" #endif # include "parse_misc.h" @@ -61,7 +61,7 @@ extern void lex_end_table(); %token IDENTIFIER PORTNAME SYSTEM_IDENTIFIER STRING %token NUMBER -%token K_LE K_GE K_EQ K_NE K_CEQ K_CNE +%token K_LE K_GE K_EQ K_NE K_CEQ K_CNE K_LS K_RS %token K_LOR K_LAND %token K_always K_and K_assign K_begin K_buf K_bufif0 K_bufif1 K_case %token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable @@ -101,7 +101,7 @@ extern void lex_end_table(); %type gate_instance %type gate_instance_list -%type bitsel delay delay_opt expression expr_primary const_expression +%type delay delay_opt expression expr_primary %type lavalue lpvalue %type expression_list @@ -122,7 +122,9 @@ extern void lex_end_table(); %left '&' %left K_EQ K_NE K_CEQ K_CNE %left K_GE K_LE '<' '>' +%left K_LS K_RS %left '+' '-' +%left '*' '/' '%' %left UNARY_PREC %% @@ -132,11 +134,6 @@ source_file | source_file description ; -bitsel - : '[' const_expression ']' - { $$ = $2; } - ; - case_item : expression ':' statement_opt { PCase::Item*tmp = new PCase::Item; @@ -171,52 +168,6 @@ case_items } ; - /* const_expressions are restricted expressions that have guaranteed - known values at compile time. I treat them differently at parse - time so that I can tack correctness checking onto the parse - process. */ -const_expression - : NUMBER - { verinum*tmp = $1; - if (tmp == 0) { - yyerror(@1, "XXXX internal error: const_expression."); - $$ = 0; - } else { - PENumber*tmp = new PENumber($1); - tmp->set_file(@1.text); - tmp->set_lineno(@1.first_line); - $$ = tmp; - } - } - | STRING - { PEString*tmp = new PEString(*$1); - tmp->set_file(@2.text); - tmp->set_lineno(@2.first_line); - delete $1; - $$ = tmp; - } - | IDENTIFIER - { if (!pform_is_parameter(*$1)) { - yyerror(@1, "Identifier in constant expression" - " must be a parameter name."); - delete $1; - $$ = 0; - } else { - PEIdent*tmp = new PEIdent(*$1); - tmp->set_file(@1.text); - tmp->set_lineno(@1.first_line); - $$ = tmp; - delete $1; - } - } - | const_expression '-' const_expression - { PEBinary*tmp = new PEBinary('-', $1, $3); - tmp->set_file(@2.text); - tmp->set_lineno(@2.first_line); - $$ = tmp; - } - ; - delay : '#' NUMBER { verinum*tmp = $2; @@ -332,6 +283,15 @@ expression | expression '^' expression { $$ = new PEBinary('^', $1, $3); } + | expression '*' expression + { $$ = new PEBinary('*', $1, $3); + } + | expression '/' expression + { $$ = new PEBinary('/', $1, $3); + } + | expression '%' expression + { $$ = new PEBinary('%', $1, $3); + } | expression '+' expression { $$ = new PEBinary('+', $1, $3); } @@ -350,12 +310,24 @@ expression | expression '>' expression { $$ = new PEBinary('>', $1, $3); } + | expression K_LS expression + { $$ = new PEBinary('l', $1, $3); + } + | expression K_RS expression + { $$ = new PEBinary('r', $1, $3); + } | expression K_EQ expression { $$ = new PEBinary('e', $1, $3); } | expression K_CEQ expression { $$ = new PEBinary('E', $1, $3); } + | expression K_LE expression + { $$ = new PEBinary('L', $1, $3); + } + | expression K_GE expression + { $$ = new PEBinary('G', $1, $3); + } | expression K_NE expression { $$ = new PEBinary('n', $1, $3); } @@ -396,7 +368,10 @@ expr_primary yyerror(@1, "XXXX No number value in primary?"); $$ = 0; } else { - $$ = new PENumber($1); + PENumber*tmp = new PENumber($1); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); + $$ = tmp; } } | STRING @@ -579,9 +554,16 @@ lavalue delete $1; $$ = tmp; } - | IDENTIFIER bitsel + | IDENTIFIER '[' expression ']' { PEIdent*tmp = new PEIdent(*$1); - tmp->msb_ = $2; + PExpr*sel = $3; + if (! pform_expression_is_constant(sel)) { + yyerror(@2, "Bit select in lvalue must " + "contain a constant expression."); + delete sel; + } else { + tmp->msb_ = sel; + } tmp->set_file(@1.text); tmp->set_lineno(@1.first_line); delete $1; @@ -623,6 +605,14 @@ lpvalue $$ = tmp; } + | identifier '[' expression ':' expression ']' + { yyerror(@1, "Sorry, part selects" + " not supported in lvalue."); + $$ = 0; + delete $1; + delete $3; + delete $5; + } | '{' expression_list '}' { yyerror(@1, "Sorry, concatenation expressions" " not supported in lvalue."); @@ -721,14 +711,25 @@ net_type ; parameter_assign - : IDENTIFIER '=' const_expression - { pform_set_parameter(*$1, $3); + : IDENTIFIER '=' expression + { PExpr*tmp = $3; + if (!pform_expression_is_constant(tmp)) { + yyerror(@3, "parameter value must be constant."); + delete tmp; + tmp = 0; + } + pform_set_parameter(*$1, tmp); delete $1; } ; parameter_assign_list : parameter_assign + | range parameter_assign + { yyerror(@1, "Ranges in parameter definition " + "are not supported."); + delete $1; + } | parameter_assign_list ',' parameter_assign ; @@ -738,12 +739,25 @@ port $$->port_type = NetNet::PIMPLICIT; delete $1; } - | IDENTIFIER '[' const_expression ':' const_expression ']' - { $$ = new PWire(*$1, NetNet::IMPLICIT); - $$->port_type = NetNet::PIMPLICIT; - $$->msb = $3; - $$->lsb = $5; + | IDENTIFIER '[' expression ':' expression ']' + { PWire*tmp = new PWire(*$1, NetNet::IMPLICIT); + tmp->port_type = NetNet::PIMPLICIT; + if (!pform_expression_is_constant($3)) { + yyerror(@3, "msb expression of port bit select " + "must be constant."); + delete $3; + } else { + tmp->msb = $3; + } + if (!pform_expression_is_constant($5)) { + yyerror(@3, "lsb expression of port bit select " + "must be constant."); + delete $5; + } else { + tmp->msb = $5; + } delete $1; + $$ = tmp; } | IDENTIFIER '[' error ']' { yyerror(@1, "invalid port bit select"); @@ -754,10 +768,14 @@ port ; port_name - : PORTNAME '(' IDENTIFIER ')' + : PORTNAME '(' expression ')' { delete $1; delete $3; } + | PORTNAME '(' error ')' + { yyerror(@3, "invalid port connection expression."); + delete $1; + } | PORTNAME '(' ')' { delete $1; } @@ -775,10 +793,20 @@ port_type ; range - : '[' const_expression ':' const_expression ']' + : '[' expression ':' expression ']' { svector*tmp = new svector (2); - (*tmp)[0] = $2; - (*tmp)[1] = $4; + if (!pform_expression_is_constant($2)) { + yyerror(@2, "msb of range must be constant."); + delete $2; + } else { + (*tmp)[0] = $2; + } + if (!pform_expression_is_constant($4)) { + yyerror(@4, "msb of range must be constant."); + delete $4; + } else { + (*tmp)[1] = $4; + } $$ = tmp; } ; @@ -798,8 +826,12 @@ register_variable { pform_makewire(*$1, NetNet::REG); $$ = $1; } - | IDENTIFIER '[' const_expression ':' const_expression ']' + | IDENTIFIER '[' expression ':' expression ']' { pform_makewire(*$1, NetNet::REG); + if (! pform_expression_is_constant($3)) + yyerror(@3, "msb of register range must be constant."); + if (! pform_expression_is_constant($5)) + yyerror(@3, "lsb of register range must be constant."); pform_set_reg_idx(*$1, $3, $5); $$ = $1; } diff --git a/pform.cc b/pform.cc index 0497d97e0..4ec479929 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.17 1999/05/10 00:16:58 steve Exp $" +#ident "$Id: pform.cc,v 1.18 1999/05/16 05:08:42 steve Exp $" #endif # include "pform.h" @@ -82,6 +82,11 @@ void pform_endmodule(const string&name) cur_module = 0; } +bool pform_expression_is_constant(const PExpr*ex) +{ + return ex->is_constant(cur_module); +} + void pform_make_udp(string*name, list*parms, list*decl, list*table, Statement*init_expr) @@ -421,13 +426,6 @@ void pform_set_parameter(const string&name, PExpr*expr) cur_module->parameters[name] = expr; } -bool pform_is_parameter(const string&name) -{ - map::const_iterator cur = - cur_module->parameters.find(name); - return cur != cur_module->parameters.end(); -} - void pform_set_port_type(list*names, NetNet::PortType pt) { for (list::const_iterator cur = names->begin() @@ -518,6 +516,12 @@ int pform_parse(const char*path, map&modules, /* * $Log: pform.cc,v $ + * Revision 1.18 1999/05/16 05:08:42 steve + * Redo constant expression detection to happen + * after parsing. + * + * Parse more operators and expressions. + * * Revision 1.17 1999/05/10 00:16:58 steve * Parse and elaborate the concatenate operator * in structural contexts, Replace vector diff --git a/pform.h b/pform.h index b97b4c8b5..79ae5b224 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.13 1999/05/10 00:16:58 steve Exp $" +#ident "$Id: pform.h,v 1.14 1999/05/16 05:08:42 steve Exp $" #endif # include "netlist.h" @@ -107,13 +107,14 @@ extern void pform_set_attrib(const string&name, const string&key, extern void pform_set_type_attrib(const string&name, const string&key, const string&value); extern void pform_set_parameter(const string&name, PExpr*expr); -extern bool pform_is_parameter(const string&name); extern PProcess* pform_make_behavior(PProcess::Type, Statement*); extern Statement* pform_make_block(PBlock::BL_TYPE, list*); extern Statement* pform_make_calltask(string*t, svector* =0); extern list* pform_make_udp_input_ports(list*); +extern bool pform_expression_is_constant(const PExpr*); + /* * The makegate function creates a new gate (which need not have a * name) and connects it to the specified wires. @@ -139,6 +140,12 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.14 1999/05/16 05:08:42 steve + * Redo constant expression detection to happen + * after parsing. + * + * Parse more operators and expressions. + * * Revision 1.13 1999/05/10 00:16:58 steve * Parse and elaborate the concatenate operator * in structural contexts, Replace vector