Parse more constant expressions.

This commit is contained in:
steve
1999-05-06 04:09:28 +00:00
parent df0c894cb0
commit b2b9097488
4 changed files with 98 additions and 14 deletions
+41 -10
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: lexor.lex,v 1.11 1999/03/16 04:44:45 steve Exp $" #ident "$Id: lexor.lex,v 1.12 1999/05/06 04:09:28 steve Exp $"
#endif #endif
//# define YYSTYPE lexval //# define YYSTYPE lexval
@@ -44,6 +44,10 @@ static verinum*make_sized_binary(const char*txt);
static verinum*make_sized_dec(const char*txt); static verinum*make_sized_dec(const char*txt);
static verinum*make_sized_octal(const char*txt); static verinum*make_sized_octal(const char*txt);
static verinum*make_sized_hex(const char*txt); static verinum*make_sized_hex(const char*txt);
static verinum*make_unsized_binary(const char*txt);
static verinum*make_unsized_dec(const char*txt);
static verinum*make_unsized_octal(const char*txt);
static verinum*make_unsized_hex(const char*txt);
%} %}
@@ -73,7 +77,7 @@ static verinum*make_sized_hex(const char*txt);
"||" { return K_LOR; } "||" { return K_LOR; }
"&&" { return K_LAND; } "&&" { return K_LAND; }
[;:\[\],()#=.@&!<|^~+*/-] { return yytext[0]; } [}{;:\[\],()#=.@&!<|^~+*/-] { return yytext[0]; }
\" { BEGIN(CSTRING); } \" { BEGIN(CSTRING); }
<CSTRING>\\\" { yymore(); } <CSTRING>\\\" { yymore(); }
@@ -130,6 +134,11 @@ static verinum*make_sized_hex(const char*txt);
[0-9][0-9_]*\'[hH][0-9a-fA-Fxz_]+ { yylval.number = make_sized_hex(yytext); [0-9][0-9_]*\'[hH][0-9a-fA-Fxz_]+ { yylval.number = make_sized_hex(yytext);
return NUMBER; } return NUMBER; }
\'[bB][0-1xz_]+ { yylval.number = make_unsized_binary(yytext); return NUMBER; }
\'[oO][0-7xz_]+ { yylval.number = make_unsized_octal(yytext); return NUMBER; }
\'[hH][0-9a-fA-Fxz_]+ { yylval.number = make_unsized_hex(yytext);
return NUMBER; }
[0-9][0-9_]* { [0-9][0-9_]* {
/* Handle the special case of the unsized decimal number. */ /* Handle the special case of the unsized decimal number. */
unsigned long value = 0; unsigned long value = 0;
@@ -298,18 +307,13 @@ static int check_identifier(const char*name)
return IDENTIFIER; return IDENTIFIER;
} }
static verinum*make_sized_binary(const char*txt) static verinum*make_binary_with_size(unsigned size, const char*ptr)
{ {
char*ptr;
unsigned size = strtoul(txt,&ptr,10);
assert(*ptr == '\'');
ptr += 1;
assert(tolower(*ptr) == 'b'); assert(tolower(*ptr) == 'b');
verinum::V*bits = new verinum::V[size]; verinum::V*bits = new verinum::V[size];
unsigned idx = 0; unsigned idx = 0;
char*eptr = ptr + strlen(ptr) - 1; const char*eptr = ptr + strlen(ptr) - 1;
while ((eptr > ptr) && (idx < size)) { while ((eptr > ptr) && (idx < size)) {
if (*eptr == '_') { if (*eptr == '_') {
@@ -336,7 +340,6 @@ static verinum*make_sized_binary(const char*txt)
eptr -= 1; eptr -= 1;
} }
// Zero-extend binary number, except that z or x is extended // Zero-extend binary number, except that z or x is extended
// if it is the highest supplied digit. // if it is the highest supplied digit.
while (idx < size) { while (idx < size) {
@@ -359,6 +362,24 @@ static verinum*make_sized_binary(const char*txt)
return new verinum(bits, size); return new verinum(bits, size);
} }
static verinum*make_sized_binary(const char*txt)
{
char*ptr;
unsigned size = strtoul(txt,&ptr,10);
assert(*ptr == '\'');
ptr += 1;
assert(tolower(*ptr) == 'b');
return make_binary_with_size(size, ptr);
}
static verinum*make_unsized_binary(const char*txt)
{
assert(*txt == '\'');
txt += 1;
return make_binary_with_size(64, txt);
}
static verinum*make_sized_octal(const char*txt) static verinum*make_sized_octal(const char*txt)
{ {
char*ptr; char*ptr;
@@ -410,6 +431,11 @@ static verinum*make_sized_octal(const char*txt)
return new verinum(bits, size); return new verinum(bits, size);
} }
static verinum*make_unsized_octal(const char*txt)
{
assert(0);
}
static verinum*make_sized_hex(const char*txt) static verinum*make_sized_hex(const char*txt)
{ {
char*ptr; char*ptr;
@@ -479,6 +505,11 @@ static verinum*make_sized_hex(const char*txt)
return new verinum(bits, size); return new verinum(bits, size);
} }
static verinum*make_unsized_hex(const char*txt)
{
assert(0);
}
/* /*
* Making a deciman number is much easier then the other base numbers * Making a deciman number is much easier then the other base numbers
* because there are no z or x values to worry about. * because there are no z or x values to worry about.
+34 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: parse.y,v 1.20 1999/05/05 03:27:15 steve Exp $" #ident "$Id: parse.y,v 1.21 1999/05/06 04:09:28 steve Exp $"
#endif #endif
# include "parse_misc.h" # include "parse_misc.h"
@@ -170,6 +170,10 @@ 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 const_expression
: NUMBER : NUMBER
{ verinum*tmp = $1; { verinum*tmp = $1;
@@ -184,6 +188,23 @@ const_expression
{ $$ = new PEString(*$1); { $$ = new PEString(*$1);
delete $1; delete $1;
} }
| 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
{ $$ = new PEBinary('-', $1, $3);
}
; ;
delay delay
@@ -277,6 +298,10 @@ expression
{ $$ = $1; } { $$ = $1; }
| '(' expression ')' | '(' expression ')'
{ $$ = $2; } { $$ = $2; }
| '{' expression_list '}'
{ yyerror(@1, "Sorry, concatenation operator not supported.");
$$ = 0;
}
| '~' expression %prec UNARY_PREC | '~' expression %prec UNARY_PREC
{ $$ = new PEUnary('~', $2); { $$ = new PEUnary('~', $2);
} }
@@ -507,8 +532,16 @@ list_of_variables
} }
; ;
/* An lvalue is the expression that can go on the left side of an
assignment. This rule handles only procedural assignments. */
lvalue lvalue
: identifier { $$ = $1; } : identifier { $$ = $1; }
| identifier '[' expression ']'
{ yyerror(@2, "Sorry, bit/memory selects "
"not supported in lvalue.");
$$ = $1;
delete $3;
}
; ;
module module
+18 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: pform.cc,v 1.12 1999/05/02 23:25:32 steve Exp $" #ident "$Id: pform.cc,v 1.13 1999/05/06 04:09:28 steve Exp $"
#endif #endif
# include "pform.h" # include "pform.h"
@@ -426,8 +426,14 @@ static void pform_set_net_range(const string&name, list<PExpr*>*range)
PExpr*msb = *idx; PExpr*msb = *idx;
idx ++; idx ++;
PExpr*lsb = *idx; PExpr*lsb = *idx;
if (! (cur->msb->is_the_same(msb) && cur->lsb->is_the_same(lsb))) if (msb == 0) {
VLerror(yylloc, "failed to parse msb of range.");
} else if (lsb == 0) {
VLerror(yylloc, "failed to parse lsb of range.");
} else if (! (cur->msb->is_the_same(msb) &&
cur->lsb->is_the_same(lsb))) {
VLerror(yylloc, "net ranges are not identical."); VLerror(yylloc, "net ranges are not identical.");
}
delete msb; delete msb;
delete lsb; delete lsb;
} }
@@ -438,6 +444,13 @@ void pform_set_parameter(const string&name, PExpr*expr)
cur_module->parameters[name] = expr; cur_module->parameters[name] = expr;
} }
bool pform_is_parameter(const string&name)
{
map<string,PExpr*>::const_iterator cur =
cur_module->parameters.find(name);
return cur != cur_module->parameters.end();
}
void pform_set_port_type(list<string>*names, NetNet::PortType pt) void pform_set_port_type(list<string>*names, NetNet::PortType pt)
{ {
for (list<string>::const_iterator cur = names->begin() for (list<string>::const_iterator cur = names->begin()
@@ -535,6 +548,9 @@ int pform_parse(const char*path, map<string,Module*>&modules,
/* /*
* $Log: pform.cc,v $ * $Log: pform.cc,v $
* Revision 1.13 1999/05/06 04:09:28 steve
* Parse more constant expressions.
*
* Revision 1.12 1999/05/02 23:25:32 steve * Revision 1.12 1999/05/02 23:25:32 steve
* Enforce module instance names. * Enforce module instance names.
* *
+5 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#if !defined(WINNT) #if !defined(WINNT)
#ident "$Id: pform.h,v 1.9 1999/04/19 01:59:37 steve Exp $" #ident "$Id: pform.h,v 1.10 1999/05/06 04:09:28 steve Exp $"
#endif #endif
# include "netlist.h" # include "netlist.h"
@@ -107,6 +107,7 @@ extern void pform_set_attrib(const string&name, const string&key,
extern void pform_set_type_attrib(const string&name, const string&key, extern void pform_set_type_attrib(const string&name, const string&key,
const string&value); const string&value);
extern void pform_set_parameter(const string&name, PExpr*expr); 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 PProcess* pform_make_behavior(PProcess::Type, Statement*);
extern Statement* pform_make_block(PBlock::BL_TYPE, list<Statement*>*); extern Statement* pform_make_block(PBlock::BL_TYPE, list<Statement*>*);
extern Statement* pform_make_assignment(string*t, PExpr*e); extern Statement* pform_make_assignment(string*t, PExpr*e);
@@ -140,6 +141,9 @@ extern void pform_dump(ostream&out, Module*mod);
/* /*
* $Log: pform.h,v $ * $Log: pform.h,v $
* Revision 1.10 1999/05/06 04:09:28 steve
* Parse more constant expressions.
*
* Revision 1.9 1999/04/19 01:59:37 steve * Revision 1.9 1999/04/19 01:59:37 steve
* Add memories to the parse and elaboration phases. * Add memories to the parse and elaboration phases.
* *