System Verilog timeunit and timeprecision addition
This patch adds timeunit and timeprecision keywords.Use -gsystem-verilog generation flag to use this feature
This commit is contained in:
parent
e191cf7f55
commit
c2feeb03df
|
|
@ -134,6 +134,8 @@ extern bool gn_specify_blocks_flag;
|
|||
/* If this flag is true, then support/elaborate Verilog-AMS. */
|
||||
extern bool gn_verilog_ams_flag;
|
||||
|
||||
extern bool gn_system_verilog_flag;
|
||||
|
||||
/* If this flag is false a warning is printed when the port declaration
|
||||
is scalar and the net/register definition is vectored. */
|
||||
extern bool gn_io_range_error_flag;
|
||||
|
|
|
|||
21
lexor.lex
21
lexor.lex
|
|
@ -107,6 +107,8 @@ W [ \t\b\f\r]+
|
|||
|
||||
S [afpnumkKMGT]
|
||||
|
||||
TU [munpf]
|
||||
|
||||
%%
|
||||
|
||||
/* Recognize the various line directives. */
|
||||
|
|
@ -323,6 +325,25 @@ S [afpnumkKMGT]
|
|||
based_size = yylval.number->as_ulong();
|
||||
return DEC_NUMBER; }
|
||||
|
||||
[0-9]+{TU}?s {
|
||||
if(gn_system_verilog_flag)
|
||||
{
|
||||
yylval.text = strdupnew(yytext);
|
||||
return TIME_LITERAL;
|
||||
}
|
||||
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
|
||||
value is a number with a single letter scale factor. If
|
||||
verilog-ams is not enabled, then reject this rule. If it is
|
||||
|
|
|
|||
|
|
@ -162,6 +162,8 @@ tan, GN_KEYWORDS_VAMS_2_3, K_tan
|
|||
tanh, GN_KEYWORDS_VAMS_2_3, K_tanh
|
||||
task, GN_KEYWORDS_1364_1995, K_task
|
||||
time, GN_KEYWORDS_1364_1995, K_time
|
||||
timeprecision, GN_KEYWORDS_1800_2005, K_timeprecision
|
||||
timeunit, GN_KEYWORDS_1800_2005, K_timeunit
|
||||
tran, GN_KEYWORDS_1364_1995, K_tran
|
||||
tranif0, GN_KEYWORDS_1364_1995, K_tranif0
|
||||
tranif1, GN_KEYWORDS_1364_1995, K_tranif1
|
||||
|
|
|
|||
71
parse.y
71
parse.y
|
|
@ -218,7 +218,7 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
|||
list<index_component_t> *dimensions;
|
||||
};
|
||||
|
||||
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING
|
||||
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL
|
||||
%token <discipline> DISCIPLINE_IDENTIFIER
|
||||
%token <text> PATHPULSE_IDENTIFIER
|
||||
%token <number> BASED_NUMBER DEC_NUMBER
|
||||
|
|
@ -269,7 +269,8 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2)
|
|||
%token K_wone K_uwire
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
|
|
@ -728,6 +729,7 @@ description
|
|||
delete[] $3;
|
||||
delete[] $5;
|
||||
}
|
||||
| timeunits_declaration
|
||||
;
|
||||
|
||||
/* The discipline and nature declarations used to take no ';' after
|
||||
|
|
@ -736,6 +738,67 @@ description
|
|||
choose to make the ';' optional in this context. */
|
||||
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
|
||||
: K_discipline IDENTIFIER optional_semicolon
|
||||
{ pform_start_discipline($2); }
|
||||
|
|
@ -1986,6 +2049,7 @@ module : attribute_list_opt module_start IDENTIFIER
|
|||
module_port_list_opt
|
||||
module_attribute_foreign ';'
|
||||
{ pform_module_set_ports($6); }
|
||||
timeunits_declaration_opt
|
||||
module_item_list_opt
|
||||
K_endmodule
|
||||
{ Module::UCDriveType ucd;
|
||||
|
|
@ -2463,7 +2527,8 @@ module_item
|
|||
}
|
||||
| KK_attribute '(' error ')' ';'
|
||||
{ yyerror(@1, "error: Malformed $attribute parameter list."); }
|
||||
;
|
||||
| timeunits_declaration_check
|
||||
;
|
||||
|
||||
automatic_opt
|
||||
: K_automatic { $$ = true; }
|
||||
|
|
|
|||
168
pform.cc
168
pform.cc
|
|
@ -73,6 +73,19 @@ static NetNet::Type pform_default_nettype = NetNet::WIRE;
|
|||
static int pform_time_unit;
|
||||
static int pform_time_prec;
|
||||
|
||||
/* These two flags check the initial timeprecison and timeunit
|
||||
* declaration inside a module
|
||||
*/
|
||||
static bool tp_decl_flag = false;
|
||||
static bool tu_decl_flag = false;
|
||||
|
||||
/*
|
||||
* Flags used to set time_from_timescale based on timeunit and
|
||||
* timeprecision
|
||||
*/
|
||||
static bool tu_valid_flag = false;
|
||||
static bool tp_valid_flag = false;
|
||||
|
||||
static char*pform_timescale_file = 0;
|
||||
static unsigned pform_timescale_line;
|
||||
|
||||
|
|
@ -339,6 +352,156 @@ void pform_set_timescale(int unit, int prec,
|
|||
}
|
||||
}
|
||||
|
||||
void pform_set_timeunit(const char*txt,bool in_module,bool only_check)
|
||||
{
|
||||
unsigned num;
|
||||
const char*cp = txt + strspn(txt, " \t");
|
||||
char*tmp;
|
||||
const char*ctmp;
|
||||
|
||||
int val = 0;
|
||||
num = strtoul(cp, &tmp, 10);
|
||||
if (num == 0) {
|
||||
VLerror(yylloc, "Invalid timeunit string.");
|
||||
return;
|
||||
}
|
||||
|
||||
while (num >= 10) {
|
||||
val += 1;
|
||||
num /= 10;
|
||||
}
|
||||
if (num != 1) {
|
||||
VLerror(yylloc, "Invalid timeunit 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;
|
||||
|
||||
} else {
|
||||
VLerror(yylloc, "Invalid unit of measurement");
|
||||
return;
|
||||
}
|
||||
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)
|
||||
{
|
||||
unsigned num;
|
||||
const char*cp = txt + strspn(txt, " \t");
|
||||
char*tmp;
|
||||
const char*ctmp;
|
||||
|
||||
int val = 0;
|
||||
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;
|
||||
|
||||
} else {
|
||||
VLerror(yylloc, "Invalid unit of measurement");
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||
const char*file, unsigned lineno)
|
||||
|
|
@ -471,6 +634,7 @@ void pform_endmodule(const char*name, bool in_celldefine,
|
|||
Module::UCDriveType uc_drive)
|
||||
{
|
||||
assert(pform_cur_module);
|
||||
pform_cur_module->time_from_timescale = (tp_valid_flag && tu_valid_flag)|| pform_timescale_file != 0;
|
||||
perm_string mod_name = pform_cur_module->mod_name();
|
||||
assert(strcmp(name, mod_name) == 0);
|
||||
pform_cur_module->is_cell = in_celldefine;
|
||||
|
|
@ -495,6 +659,10 @@ void pform_endmodule(const char*name, bool in_celldefine,
|
|||
ivl_assert(*pform_cur_module, lexical_scope == 0);
|
||||
|
||||
pform_cur_module = 0;
|
||||
tp_decl_flag=false;
|
||||
tu_decl_flag=false;
|
||||
tu_valid_flag=false;
|
||||
tp_valid_flag=false;
|
||||
}
|
||||
|
||||
void pform_genvars(const struct vlltype&li, list<perm_string>*names)
|
||||
|
|
|
|||
6
pform.h
6
pform.h
|
|
@ -409,4 +409,10 @@ 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);
|
||||
/*
|
||||
* Timeunit and precision setting function
|
||||
*/
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue