Fix up original SV timeunit/timeprecision patch.
This patch modifies the original SystemVerilog timeunit/timeprecision patch in the following way: Removed trailing space. Reworked some code to use standard spacing rules. Added some comments. Combined some code. Major rework of local/global timeunit/timeprecision logic. Major rework of timeunit/timeprecision declaration/check code. This was needed to remove the shift/reduce warnings. Add a number of checks for invalid combinations.
This commit is contained in:
parent
c2feeb03df
commit
9dce6496fb
|
|
@ -134,6 +134,7 @@ extern bool gn_specify_blocks_flag;
|
||||||
/* If this flag is true, then support/elaborate Verilog-AMS. */
|
/* If this flag is true, then support/elaborate Verilog-AMS. */
|
||||||
extern bool gn_verilog_ams_flag;
|
extern bool gn_verilog_ams_flag;
|
||||||
|
|
||||||
|
/* If this flag is true, then support/elaborate SystemVerilog. */
|
||||||
extern bool gn_system_verilog_flag;
|
extern bool gn_system_verilog_flag;
|
||||||
|
|
||||||
/* If this flag is false a warning is printed when the port declaration
|
/* If this flag is false a warning is printed when the port declaration
|
||||||
|
|
|
||||||
35
lexor.lex
35
lexor.lex
|
|
@ -108,7 +108,7 @@ W [ \t\b\f\r]+
|
||||||
S [afpnumkKMGT]
|
S [afpnumkKMGT]
|
||||||
|
|
||||||
TU [munpf]
|
TU [munpf]
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
/* Recognize the various line directives. */
|
/* Recognize the various line directives. */
|
||||||
|
|
@ -250,6 +250,15 @@ TU [munpf]
|
||||||
in_UDP = false;
|
in_UDP = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Translate these to checks if we already have or are
|
||||||
|
* outside the declaration region. */
|
||||||
|
case K_timeunit:
|
||||||
|
if (have_timeunit_decl) rc = K_timeunit_check;
|
||||||
|
break;
|
||||||
|
case K_timeprecision:
|
||||||
|
if (have_timeprec_decl) rc = K_timeprecision_check;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
yylval.text = 0;
|
yylval.text = 0;
|
||||||
break;
|
break;
|
||||||
|
|
@ -325,25 +334,13 @@ TU [munpf]
|
||||||
based_size = yylval.number->as_ulong();
|
based_size = yylval.number->as_ulong();
|
||||||
return DEC_NUMBER; }
|
return DEC_NUMBER; }
|
||||||
|
|
||||||
[0-9]+{TU}?s {
|
/* This rule handles scaled time values for SystemVerilog. */
|
||||||
if(gn_system_verilog_flag)
|
[0-9][0-9_]*(\.[0-9][0-9_]*)?{TU}?s {
|
||||||
{
|
if(gn_system_verilog_flag) {
|
||||||
yylval.text = strdupnew(yytext);
|
yylval.text = strdupnew(yytext);
|
||||||
return TIME_LITERAL;
|
return TIME_LITERAL;
|
||||||
}
|
} else REJECT; }
|
||||||
else
|
|
||||||
REJECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
[0-9]*\.[0-9]+{TU}?s {
|
|
||||||
if(gn_system_verilog_flag)
|
|
||||||
{
|
|
||||||
yylval.text = strdupnew(yytext);
|
|
||||||
return TIME_LITERAL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
REJECT;
|
|
||||||
}
|
|
||||||
/* These rules handle the scaled real literals from Verilog-AMS. The
|
/* These rules handle the scaled real literals from Verilog-AMS. The
|
||||||
value is a number with a single letter scale factor. If
|
value is a number with a single letter scale factor. If
|
||||||
verilog-ams is not enabled, then reject this rule. If it is
|
verilog-ams is not enabled, then reject this rule. If it is
|
||||||
|
|
|
||||||
|
|
@ -162,8 +162,8 @@ tan, GN_KEYWORDS_VAMS_2_3, K_tan
|
||||||
tanh, GN_KEYWORDS_VAMS_2_3, K_tanh
|
tanh, GN_KEYWORDS_VAMS_2_3, K_tanh
|
||||||
task, GN_KEYWORDS_1364_1995, K_task
|
task, GN_KEYWORDS_1364_1995, K_task
|
||||||
time, GN_KEYWORDS_1364_1995, K_time
|
time, GN_KEYWORDS_1364_1995, K_time
|
||||||
timeprecision, GN_KEYWORDS_1800_2005, K_timeprecision
|
timeprecision, GN_KEYWORDS_1364_1995, K_timeprecision
|
||||||
timeunit, GN_KEYWORDS_1800_2005, K_timeunit
|
timeunit, GN_KEYWORDS_1364_1995, K_timeunit
|
||||||
tran, GN_KEYWORDS_1364_1995, K_tran
|
tran, GN_KEYWORDS_1364_1995, K_tran
|
||||||
tranif0, GN_KEYWORDS_1364_1995, K_tranif0
|
tranif0, GN_KEYWORDS_1364_1995, K_tranif0
|
||||||
tranif1, GN_KEYWORDS_1364_1995, K_tranif1
|
tranif1, GN_KEYWORDS_1364_1995, K_tranif1
|
||||||
|
|
|
||||||
111
parse.y
111
parse.y
|
|
@ -35,6 +35,9 @@ class PSpecPath;
|
||||||
extern void lex_start_table();
|
extern void lex_start_table();
|
||||||
extern void lex_end_table();
|
extern void lex_end_table();
|
||||||
|
|
||||||
|
bool have_timeunit_decl = false;
|
||||||
|
bool have_timeprec_decl = false;
|
||||||
|
|
||||||
static svector<PExpr*>* param_active_range = 0;
|
static svector<PExpr*>* param_active_range = 0;
|
||||||
static bool param_active_signed = false;
|
static bool param_active_signed = false;
|
||||||
static ivl_variable_type_t param_active_type = IVL_VT_LOGIC;
|
static ivl_variable_type_t param_active_type = IVL_VT_LOGIC;
|
||||||
|
|
@ -270,7 +273,9 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
||||||
|
|
||||||
/* The new tokens from 1800-2005. */
|
/* The new tokens from 1800-2005. */
|
||||||
%token K_always_comb K_always_ff K_always_latch K_assert
|
%token K_always_comb K_always_ff K_always_latch K_assert
|
||||||
%token K_timeprecision K_timeunit
|
%token K_timeprecision K_timeunit
|
||||||
|
/* Fake tokens that are passed once we have an initial token. */
|
||||||
|
%token K_timeprecision_check K_timeunit_check
|
||||||
|
|
||||||
/* The new tokens for Verilog-AMS 2.3. */
|
/* The new tokens for Verilog-AMS 2.3. */
|
||||||
%token K_abs K_abstol K_access K_acos K_acosh K_analog K_asin K_asinh
|
%token K_abs K_abstol K_access K_acos K_acosh K_analog K_asin K_asinh
|
||||||
|
|
@ -729,7 +734,10 @@ description
|
||||||
delete[] $3;
|
delete[] $3;
|
||||||
delete[] $5;
|
delete[] $5;
|
||||||
}
|
}
|
||||||
| timeunits_declaration
|
| K_timeunit TIME_LITERAL ';'
|
||||||
|
{ pform_set_timeunit($2, false, false); }
|
||||||
|
| K_timeprecision TIME_LITERAL ';'
|
||||||
|
{ pform_set_timeprecision($2, false, false); }
|
||||||
;
|
;
|
||||||
|
|
||||||
/* The discipline and nature declarations used to take no ';' after
|
/* The discipline and nature declarations used to take no ';' after
|
||||||
|
|
@ -738,67 +746,6 @@ description
|
||||||
choose to make the ';' optional in this context. */
|
choose to make the ';' optional in this context. */
|
||||||
optional_semicolon : ';' | ;
|
optional_semicolon : ';' | ;
|
||||||
|
|
||||||
timeunits_declaration_opt
|
|
||||||
:local_timeunits_declaration
|
|
||||||
|
|
|
||||||
;
|
|
||||||
|
|
||||||
timeunits_declaration
|
|
||||||
: K_timeprecision TIME_LITERAL ';'
|
|
||||||
K_timeunit TIME_LITERAL ';'
|
|
||||||
{
|
|
||||||
pform_set_timeprecision($2,false,false);
|
|
||||||
pform_set_timeunit($5,false,false);
|
|
||||||
}
|
|
||||||
| K_timeunit TIME_LITERAL ';'
|
|
||||||
K_timeprecision TIME_LITERAL ';'
|
|
||||||
{
|
|
||||||
pform_set_timeunit($2,false,false);
|
|
||||||
pform_set_timeprecision($5,false,false);
|
|
||||||
}
|
|
||||||
| K_timeunit TIME_LITERAL ';'
|
|
||||||
{
|
|
||||||
pform_set_timeunit($2,false,false);
|
|
||||||
}
|
|
||||||
| K_timeprecision TIME_LITERAL ';'
|
|
||||||
{
|
|
||||||
pform_set_timeprecision($2,false,false);
|
|
||||||
}
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
local_timeunits_declaration
|
|
||||||
: K_timeprecision TIME_LITERAL ';'
|
|
||||||
K_timeunit TIME_LITERAL ';'
|
|
||||||
{
|
|
||||||
pform_set_timeprecision($2,true,false);
|
|
||||||
pform_set_timeunit($5,true,false);
|
|
||||||
}
|
|
||||||
| K_timeunit TIME_LITERAL ';'
|
|
||||||
K_timeprecision TIME_LITERAL ';'
|
|
||||||
{
|
|
||||||
pform_set_timeunit($2,true,false);
|
|
||||||
pform_set_timeprecision($5,true,false);
|
|
||||||
}
|
|
||||||
| K_timeunit TIME_LITERAL ';'
|
|
||||||
{
|
|
||||||
pform_set_timeunit($2,true,false);
|
|
||||||
}
|
|
||||||
| K_timeprecision TIME_LITERAL ';'
|
|
||||||
{
|
|
||||||
pform_set_timeprecision($2,true,false);
|
|
||||||
}
|
|
||||||
|
|
||||||
timeunits_declaration_check
|
|
||||||
: K_timeunit TIME_LITERAL ';'
|
|
||||||
{
|
|
||||||
pform_set_timeunit($2,true,true);
|
|
||||||
}
|
|
||||||
| K_timeprecision TIME_LITERAL ';'
|
|
||||||
{
|
|
||||||
pform_set_timeprecision($2,true,true);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
discipline_declaration
|
discipline_declaration
|
||||||
: K_discipline IDENTIFIER optional_semicolon
|
: K_discipline IDENTIFIER optional_semicolon
|
||||||
{ pform_start_discipline($2); }
|
{ pform_start_discipline($2); }
|
||||||
|
|
@ -2038,6 +1985,25 @@ cont_assign_list
|
||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* We allow zero, one or two unique declarations. */
|
||||||
|
local_timeunit_prec_decl_opt
|
||||||
|
: /* Empty */
|
||||||
|
| local_timeunit_prec_decl
|
||||||
|
| local_timeunit_prec_decl local_timeunit_prec_decl
|
||||||
|
;
|
||||||
|
|
||||||
|
/* By setting the appropriate have_time???_decl we allow only
|
||||||
|
one declaration of each type in this module. */
|
||||||
|
local_timeunit_prec_decl
|
||||||
|
: K_timeunit TIME_LITERAL ';'
|
||||||
|
{ pform_set_timeunit($2, true, false);
|
||||||
|
have_timeunit_decl = true;
|
||||||
|
}
|
||||||
|
| K_timeprecision TIME_LITERAL ';'
|
||||||
|
{ pform_set_timeprecision($2, true, false);
|
||||||
|
have_timeprec_decl = true;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
/* This is the global structure of a module. A module in a start
|
/* This is the global structure of a module. A module in a start
|
||||||
section, with optional ports, then an optional list of module
|
section, with optional ports, then an optional list of module
|
||||||
|
|
@ -2049,8 +2015,12 @@ module : attribute_list_opt module_start IDENTIFIER
|
||||||
module_port_list_opt
|
module_port_list_opt
|
||||||
module_attribute_foreign ';'
|
module_attribute_foreign ';'
|
||||||
{ pform_module_set_ports($6); }
|
{ pform_module_set_ports($6); }
|
||||||
timeunits_declaration_opt
|
local_timeunit_prec_decl_opt
|
||||||
module_item_list_opt
|
{ have_timeunit_decl = true; // Every thing past here is
|
||||||
|
have_timeprec_decl = true; // a check!
|
||||||
|
pform_check_timeunit_prec();
|
||||||
|
}
|
||||||
|
module_item_list_opt
|
||||||
K_endmodule
|
K_endmodule
|
||||||
{ Module::UCDriveType ucd;
|
{ Module::UCDriveType ucd;
|
||||||
switch (uc_drive) {
|
switch (uc_drive) {
|
||||||
|
|
@ -2067,8 +2037,9 @@ module : attribute_list_opt module_start IDENTIFIER
|
||||||
}
|
}
|
||||||
pform_endmodule($3, in_celldefine, ucd);
|
pform_endmodule($3, in_celldefine, ucd);
|
||||||
delete[]$3;
|
delete[]$3;
|
||||||
|
have_timeunit_decl = false; // We will allow decls again.
|
||||||
|
have_timeprec_decl = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
module_start : K_module | K_macromodule ;
|
module_start : K_module | K_macromodule ;
|
||||||
|
|
@ -2527,8 +2498,12 @@ module_item
|
||||||
}
|
}
|
||||||
| KK_attribute '(' error ')' ';'
|
| KK_attribute '(' error ')' ';'
|
||||||
{ yyerror(@1, "error: Malformed $attribute parameter list."); }
|
{ yyerror(@1, "error: Malformed $attribute parameter list."); }
|
||||||
| timeunits_declaration_check
|
|
||||||
;
|
| K_timeunit_check TIME_LITERAL ';'
|
||||||
|
{ pform_set_timeunit($2, true, true); }
|
||||||
|
| K_timeprecision_check TIME_LITERAL ';'
|
||||||
|
{ pform_set_timeprecision($2, true, true); }
|
||||||
|
;
|
||||||
|
|
||||||
automatic_opt
|
automatic_opt
|
||||||
: K_automatic { $$ = true; }
|
: K_automatic { $$ = true; }
|
||||||
|
|
|
||||||
|
|
@ -70,5 +70,11 @@ extern unsigned long based_size;
|
||||||
extern bool in_celldefine;
|
extern bool in_celldefine;
|
||||||
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
|
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
|
||||||
extern UCDriveType uc_drive;
|
extern UCDriveType uc_drive;
|
||||||
|
/*
|
||||||
|
* Flags to control if we are declaring or checking a timeunit or
|
||||||
|
* timeprecision statement.
|
||||||
|
*/
|
||||||
|
extern bool have_timeunit_decl;
|
||||||
|
extern bool have_timeprec_decl;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
292
pform.cc
292
pform.cc
|
|
@ -73,18 +73,20 @@ static NetNet::Type pform_default_nettype = NetNet::WIRE;
|
||||||
static int pform_time_unit;
|
static int pform_time_unit;
|
||||||
static int pform_time_prec;
|
static int pform_time_prec;
|
||||||
|
|
||||||
/* These two flags check the initial timeprecison and timeunit
|
/* These two flags check the initial timeprecision and timeunit
|
||||||
* declaration inside a module
|
* declaration inside a module.
|
||||||
*/
|
*/
|
||||||
static bool tp_decl_flag = false;
|
static bool tp_decl_flag = false;
|
||||||
static bool tu_decl_flag = false;
|
static bool tu_decl_flag = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags used to set time_from_timescale based on timeunit and
|
* Flags used to set time_from_timescale based on timeunit and
|
||||||
* timeprecision
|
* timeprecision.
|
||||||
*/
|
*/
|
||||||
static bool tu_valid_flag = false;
|
static bool tu_global_flag = false;
|
||||||
static bool tp_valid_flag = false;
|
static bool tp_global_flag = false;
|
||||||
|
static bool tu_local_flag = false;
|
||||||
|
static bool tp_local_flag = false;
|
||||||
|
|
||||||
static char*pform_timescale_file = 0;
|
static char*pform_timescale_file = 0;
|
||||||
static unsigned pform_timescale_line;
|
static unsigned pform_timescale_line;
|
||||||
|
|
@ -305,6 +307,9 @@ void pform_set_timescale(int unit, int prec,
|
||||||
assert(unit >= prec);
|
assert(unit >= prec);
|
||||||
pform_time_unit = unit;
|
pform_time_unit = unit;
|
||||||
pform_time_prec = prec;
|
pform_time_prec = prec;
|
||||||
|
/* A `timescale clears the timeunit/timeprecision state. */
|
||||||
|
tu_global_flag = false;
|
||||||
|
tp_global_flag = false;
|
||||||
|
|
||||||
if (pform_timescale_file) {
|
if (pform_timescale_file) {
|
||||||
free(pform_timescale_file);
|
free(pform_timescale_file);
|
||||||
|
|
@ -352,154 +357,137 @@ void pform_set_timescale(int unit, int prec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_set_timeunit(const char*txt,bool in_module,bool only_check)
|
/*
|
||||||
|
* Get a timeunit or timeprecision value from a string. This is
|
||||||
|
* similar to the code in lexor.lex for the `timescale directive.
|
||||||
|
*/
|
||||||
|
static bool get_time_unit_prec(const char*cp, int &res, bool is_unit)
|
||||||
{
|
{
|
||||||
unsigned num;
|
/* We do not support a '_' in these time constants. */
|
||||||
const char*cp = txt + strspn(txt, " \t");
|
if (strchr(cp, '_')) {
|
||||||
char*tmp;
|
if (is_unit) {
|
||||||
const char*ctmp;
|
VLerror(yylloc, "Invalid timeunit constant ('_' is not "
|
||||||
|
"supported).");
|
||||||
int val = 0;
|
} else {
|
||||||
num = strtoul(cp, &tmp, 10);
|
VLerror(yylloc, "Invalid timeprecision constant ('_' is not "
|
||||||
if (num == 0) {
|
"supported).");
|
||||||
VLerror(yylloc, "Invalid timeunit string.");
|
}
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (num >= 10) {
|
/* Check for the 1 digit. */
|
||||||
val += 1;
|
if (*cp != '1') {
|
||||||
num /= 10;
|
if (is_unit) {
|
||||||
|
VLerror(yylloc, "Invalid timeunit constant (1st digit).");
|
||||||
|
} else {
|
||||||
|
VLerror(yylloc, "Invalid timeprecision constant (1st digit).");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (num != 1) {
|
cp += 1;
|
||||||
VLerror(yylloc, "Invalid timeunit number.");
|
|
||||||
return;
|
/* Check the number of zeros after the 1. */
|
||||||
|
res = strspn(cp, "0");
|
||||||
|
if (res > 2) {
|
||||||
|
if (is_unit) {
|
||||||
|
VLerror(yylloc, "Invalid timeunit constant (number of "
|
||||||
|
"zeros).");
|
||||||
|
} else {
|
||||||
|
VLerror(yylloc, "Invalid timeprecision constant (number of "
|
||||||
|
"zeros).");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cp += res;
|
||||||
|
|
||||||
|
/* Now process the scaling string. */
|
||||||
|
if (strncmp("s", cp, 1) == 0) {
|
||||||
|
res -= 0;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strncmp("ms", cp, 2) == 0) {
|
||||||
|
res -= 3;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strncmp("us", cp, 2) == 0) {
|
||||||
|
res -= 6;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strncmp("ns", cp, 2) == 0) {
|
||||||
|
res -= 9;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strncmp("ps", cp, 2) == 0) {
|
||||||
|
res -= 12;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strncmp("fs", cp, 2) == 0) {
|
||||||
|
res -= 15;
|
||||||
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cp = tmp;
|
ostringstream msg;
|
||||||
cp += strspn(cp, " \t");
|
msg << "Invalid ";
|
||||||
ctmp = cp + strcspn(cp, " \t/");
|
if (is_unit) msg << "timeunit";
|
||||||
|
else msg << "timeprecision";
|
||||||
|
msg << " scale '" << cp << "'.";
|
||||||
|
VLerror(msg.str().c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (strncmp("s", cp, ctmp-cp) == 0) {
|
void pform_set_timeunit(const char*txt, bool in_module, bool only_check)
|
||||||
val -= 0;
|
{
|
||||||
|
int val;
|
||||||
|
|
||||||
} else if (strncmp("ms", cp, ctmp-cp) == 0) {
|
if (get_time_unit_prec(txt, val, true)) return;
|
||||||
val -= 3;
|
|
||||||
|
|
||||||
} else if (strncmp("us", cp, ctmp-cp) == 0) {
|
if (in_module) {
|
||||||
val -= 6;
|
if (!only_check) {
|
||||||
|
pform_cur_module->time_unit = val;
|
||||||
} else if (strncmp("ns", cp, ctmp-cp) == 0) {
|
tu_decl_flag = true;
|
||||||
val -= 9;
|
tu_local_flag = true;
|
||||||
|
} else if (!tu_decl_flag) {
|
||||||
} else if (strncmp("ps", cp, ctmp-cp) == 0) {
|
VLerror(yylloc, "error: repeat timeunit found and the "
|
||||||
val -= 12;
|
"initial module timeunit is missing.");
|
||||||
|
return;
|
||||||
} else if (strncmp("fs", cp, ctmp-cp) == 0) {
|
} else if (pform_cur_module->time_unit != val) {
|
||||||
val -= 15;
|
VLerror(yylloc, "error: repeat timeunit does not match "
|
||||||
|
"the initial module timeunit "
|
||||||
|
"declaration.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
VLerror(yylloc, "Invalid unit of measurement");
|
tu_global_flag = true;
|
||||||
return;
|
pform_time_unit = val;
|
||||||
}
|
|
||||||
if(in_module )
|
|
||||||
{
|
|
||||||
if(!only_check)
|
|
||||||
{
|
|
||||||
pform_cur_module->time_unit = val;
|
|
||||||
tu_decl_flag=true;
|
|
||||||
tu_valid_flag=true;
|
|
||||||
}
|
|
||||||
else if (!tu_decl_flag)
|
|
||||||
{
|
|
||||||
VLerror(yylloc, "Timeunit declaration not found after module declaration");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(pform_cur_module->time_unit!= val)
|
|
||||||
{
|
|
||||||
VLerror(yylloc, "Timeliteral do not match the initial timeunit declaration");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tu_valid_flag=true;
|
|
||||||
pform_time_unit = val;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_set_timeprecision(const char*txt,bool in_module,bool only_check)
|
void pform_set_timeprecision(const char*txt, bool in_module, bool only_check)
|
||||||
{
|
{
|
||||||
unsigned num;
|
int val;
|
||||||
const char*cp = txt + strspn(txt, " \t");
|
|
||||||
char*tmp;
|
|
||||||
const char*ctmp;
|
|
||||||
|
|
||||||
int val = 0;
|
if (get_time_unit_prec(txt, val, false)) return;
|
||||||
num = strtoul(cp, &tmp, 10);
|
|
||||||
if (num == 0) {
|
|
||||||
VLerror(yylloc, "Invalid timeprecision string.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (num >= 10) {
|
|
||||||
val += 1;
|
|
||||||
num /= 10;
|
|
||||||
}
|
|
||||||
if (num != 1) {
|
|
||||||
VLerror(yylloc, "Invalid timeprecision number.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cp = tmp;
|
|
||||||
cp += strspn(cp, " \t");
|
|
||||||
ctmp = cp + strcspn(cp, " \t/");
|
|
||||||
|
|
||||||
if (strncmp("s", cp, ctmp-cp) == 0) {
|
|
||||||
val -= 0;
|
|
||||||
|
|
||||||
} else if (strncmp("ms", cp, ctmp-cp) == 0) {
|
|
||||||
val -= 3;
|
|
||||||
|
|
||||||
} else if (strncmp("us", cp, ctmp-cp) == 0) {
|
|
||||||
val -= 6;
|
|
||||||
|
|
||||||
} else if (strncmp("ns", cp, ctmp-cp) == 0) {
|
|
||||||
val -= 9;
|
|
||||||
|
|
||||||
} else if (strncmp("ps", cp, ctmp-cp) == 0) {
|
|
||||||
val -= 12;
|
|
||||||
|
|
||||||
} else if (strncmp("fs", cp, ctmp-cp) == 0) {
|
|
||||||
val -= 15;
|
|
||||||
|
|
||||||
|
if (in_module) {
|
||||||
|
if (!only_check) {
|
||||||
|
pform_cur_module->time_precision = val;
|
||||||
|
tp_decl_flag = true;
|
||||||
|
tp_local_flag = true;
|
||||||
|
} else if (!tp_decl_flag) {
|
||||||
|
VLerror(yylloc, "error: repeat timeprecision found and the "
|
||||||
|
"initial module timeprecision is missing.");
|
||||||
|
return;
|
||||||
|
} else if (pform_cur_module->time_precision != val) {
|
||||||
|
VLerror(yylloc, "error: repeat timeprecision does not match "
|
||||||
|
"the initial module timeprecision "
|
||||||
|
"declaration.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
VLerror(yylloc, "Invalid unit of measurement");
|
pform_time_prec = val;
|
||||||
return;
|
tp_global_flag=true;
|
||||||
}
|
|
||||||
if(in_module)
|
|
||||||
{
|
|
||||||
if(!only_check)
|
|
||||||
{
|
|
||||||
pform_cur_module->time_precision = val;
|
|
||||||
tp_decl_flag=true;
|
|
||||||
tp_valid_flag=true;
|
|
||||||
}
|
|
||||||
else if (!tp_decl_flag)
|
|
||||||
{
|
|
||||||
VLerror(yylloc, "Timeprecision declaration not found after module declaration");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(pform_cur_module->time_precision!= val)
|
|
||||||
{
|
|
||||||
VLerror(yylloc, "Timeliteral do not match the initial timeprecision declaration");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pform_time_prec = val;
|
|
||||||
tp_valid_flag=true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -560,8 +548,12 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||||
|
|
||||||
perm_string lex_name = lex_strings.make(name);
|
perm_string lex_name = lex_strings.make(name);
|
||||||
pform_cur_module = new Module(lex_name);
|
pform_cur_module = new Module(lex_name);
|
||||||
|
/* Set the local time unit/precision to the global value. */
|
||||||
pform_cur_module->time_unit = pform_time_unit;
|
pform_cur_module->time_unit = pform_time_unit;
|
||||||
pform_cur_module->time_precision = pform_time_prec;
|
pform_cur_module->time_precision = pform_time_prec;
|
||||||
|
tu_local_flag = tu_global_flag;
|
||||||
|
tp_local_flag = tp_global_flag;
|
||||||
|
|
||||||
/* If we have a timescale file then the time information is from
|
/* If we have a timescale file then the time information is from
|
||||||
* a timescale directive. */
|
* a timescale directive. */
|
||||||
pform_cur_module->time_from_timescale = pform_timescale_file != 0;
|
pform_cur_module->time_from_timescale = pform_timescale_file != 0;
|
||||||
|
|
@ -594,6 +586,22 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In SystemVerilog we can have separate timeunit and timeprecision
|
||||||
|
* declarations. We need to have the values worked out by time this
|
||||||
|
* task is called.
|
||||||
|
*/
|
||||||
|
void pform_check_timeunit_prec()
|
||||||
|
{
|
||||||
|
assert(pform_cur_module);
|
||||||
|
if (gn_system_verilog_flag && (pform_cur_module->time_unit <
|
||||||
|
pform_cur_module->time_precision)) {
|
||||||
|
VLerror("error: a timeprecision is missing or is too "
|
||||||
|
"large!");
|
||||||
|
} else assert(pform_cur_module->time_unit >=
|
||||||
|
pform_cur_module->time_precision);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is called by the parser to make a simple port
|
* This function is called by the parser to make a simple port
|
||||||
* reference. This is a name without a .X(...), so the internal name
|
* reference. This is a name without a .X(...), so the internal name
|
||||||
|
|
@ -634,7 +642,9 @@ void pform_endmodule(const char*name, bool in_celldefine,
|
||||||
Module::UCDriveType uc_drive)
|
Module::UCDriveType uc_drive)
|
||||||
{
|
{
|
||||||
assert(pform_cur_module);
|
assert(pform_cur_module);
|
||||||
pform_cur_module->time_from_timescale = (tp_valid_flag && tu_valid_flag)|| pform_timescale_file != 0;
|
pform_cur_module->time_from_timescale = (tu_local_flag &&
|
||||||
|
tp_local_flag) ||
|
||||||
|
(pform_timescale_file != 0);
|
||||||
perm_string mod_name = pform_cur_module->mod_name();
|
perm_string mod_name = pform_cur_module->mod_name();
|
||||||
assert(strcmp(name, mod_name) == 0);
|
assert(strcmp(name, mod_name) == 0);
|
||||||
pform_cur_module->is_cell = in_celldefine;
|
pform_cur_module->is_cell = in_celldefine;
|
||||||
|
|
@ -659,10 +669,10 @@ void pform_endmodule(const char*name, bool in_celldefine,
|
||||||
ivl_assert(*pform_cur_module, lexical_scope == 0);
|
ivl_assert(*pform_cur_module, lexical_scope == 0);
|
||||||
|
|
||||||
pform_cur_module = 0;
|
pform_cur_module = 0;
|
||||||
tp_decl_flag=false;
|
tp_decl_flag = false;
|
||||||
tu_decl_flag=false;
|
tu_decl_flag = false;
|
||||||
tu_valid_flag=false;
|
tu_local_flag = false;
|
||||||
tp_valid_flag=false;
|
tp_local_flag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pform_genvars(const struct vlltype&li, list<perm_string>*names)
|
void pform_genvars(const struct vlltype&li, list<perm_string>*names)
|
||||||
|
|
|
||||||
8
pform.h
8
pform.h
|
|
@ -143,6 +143,7 @@ extern PWire* pform_get_wire_in_scope(perm_string name);
|
||||||
*/
|
*/
|
||||||
extern void pform_startmodule(const char*, const char*file, unsigned lineno,
|
extern void pform_startmodule(const char*, const char*file, unsigned lineno,
|
||||||
svector<named_pexpr_t*>*attr);
|
svector<named_pexpr_t*>*attr);
|
||||||
|
extern void pform_check_timeunit_prec();
|
||||||
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
||||||
|
|
||||||
/* This function is used to support the port definition in a
|
/* This function is used to support the port definition in a
|
||||||
|
|
@ -410,9 +411,10 @@ extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
|
||||||
extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
|
extern PExpr* pform_make_branch_probe_expression(const struct vlltype&loc,
|
||||||
char*name, char*branch);
|
char*name, char*branch);
|
||||||
/*
|
/*
|
||||||
* Timeunit and precision setting function
|
* Tasks to set the timeunit or timeprecision for SystemVerilog.
|
||||||
*/
|
*/
|
||||||
extern void pform_set_timeunit(const char*txt,bool in_module,bool only_check);
|
extern void pform_set_timeunit(const char*txt, bool in_module, bool only_check);
|
||||||
extern void pform_set_timeprecision(const char*txt,bool in_module,bool only_check);
|
extern void pform_set_timeprecision(const char*txt, bool in_module,
|
||||||
|
bool only_check);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue