Parse more constant expressions.
This commit is contained in:
parent
df0c894cb0
commit
b2b9097488
51
lexor.lex
51
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.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
|
||||
|
||||
//# 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_octal(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_LAND; }
|
||||
|
||||
[;:\[\],()#=.@&!<|^~+*/-] { return yytext[0]; }
|
||||
[}{;:\[\],()#=.@&!<|^~+*/-] { return yytext[0]; }
|
||||
|
||||
\" { BEGIN(CSTRING); }
|
||||
<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);
|
||||
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_]* {
|
||||
/* Handle the special case of the unsized decimal number. */
|
||||
unsigned long value = 0;
|
||||
|
|
@ -298,18 +307,13 @@ static int check_identifier(const char*name)
|
|||
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');
|
||||
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
|
||||
unsigned idx = 0;
|
||||
char*eptr = ptr + strlen(ptr) - 1;
|
||||
const char*eptr = ptr + strlen(ptr) - 1;
|
||||
while ((eptr > ptr) && (idx < size)) {
|
||||
|
||||
if (*eptr == '_') {
|
||||
|
|
@ -336,7 +340,6 @@ static verinum*make_sized_binary(const char*txt)
|
|||
|
||||
eptr -= 1;
|
||||
}
|
||||
|
||||
// Zero-extend binary number, except that z or x is extended
|
||||
// if it is the highest supplied digit.
|
||||
while (idx < size) {
|
||||
|
|
@ -359,6 +362,24 @@ static verinum*make_sized_binary(const char*txt)
|
|||
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)
|
||||
{
|
||||
char*ptr;
|
||||
|
|
@ -410,6 +431,11 @@ static verinum*make_sized_octal(const char*txt)
|
|||
return new verinum(bits, size);
|
||||
}
|
||||
|
||||
static verinum*make_unsized_octal(const char*txt)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static verinum*make_sized_hex(const char*txt)
|
||||
{
|
||||
char*ptr;
|
||||
|
|
@ -479,6 +505,11 @@ static verinum*make_sized_hex(const char*txt)
|
|||
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
|
||||
* because there are no z or x values to worry about.
|
||||
|
|
|
|||
35
parse.y
35
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.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
|
||||
|
||||
# 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
|
||||
: NUMBER
|
||||
{ verinum*tmp = $1;
|
||||
|
|
@ -184,6 +188,23 @@ const_expression
|
|||
{ $$ = new PEString(*$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
|
||||
|
|
@ -277,6 +298,10 @@ expression
|
|||
{ $$ = $1; }
|
||||
| '(' expression ')'
|
||||
{ $$ = $2; }
|
||||
| '{' expression_list '}'
|
||||
{ yyerror(@1, "Sorry, concatenation operator not supported.");
|
||||
$$ = 0;
|
||||
}
|
||||
| '~' expression %prec UNARY_PREC
|
||||
{ $$ = 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
|
||||
: identifier { $$ = $1; }
|
||||
| identifier '[' expression ']'
|
||||
{ yyerror(@2, "Sorry, bit/memory selects "
|
||||
"not supported in lvalue.");
|
||||
$$ = $1;
|
||||
delete $3;
|
||||
}
|
||||
;
|
||||
|
||||
module
|
||||
|
|
|
|||
20
pform.cc
20
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.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
|
||||
|
||||
# include "pform.h"
|
||||
|
|
@ -426,8 +426,14 @@ static void pform_set_net_range(const string&name, list<PExpr*>*range)
|
|||
PExpr*msb = *idx;
|
||||
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.");
|
||||
}
|
||||
delete msb;
|
||||
delete lsb;
|
||||
}
|
||||
|
|
@ -438,6 +444,13 @@ void pform_set_parameter(const string&name, PExpr*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)
|
||||
{
|
||||
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 $
|
||||
* Revision 1.13 1999/05/06 04:09:28 steve
|
||||
* Parse more constant expressions.
|
||||
*
|
||||
* Revision 1.12 1999/05/02 23:25:32 steve
|
||||
* Enforce module instance names.
|
||||
*
|
||||
|
|
|
|||
6
pform.h
6
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.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
|
||||
|
||||
# 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,
|
||||
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<Statement*>*);
|
||||
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 $
|
||||
* Revision 1.10 1999/05/06 04:09:28 steve
|
||||
* Parse more constant expressions.
|
||||
*
|
||||
* Revision 1.9 1999/04/19 01:59:37 steve
|
||||
* Add memories to the parse and elaboration phases.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue