From 2cb9a2360cdfeea90668abe45f4c516e3020cee7 Mon Sep 17 00:00:00 2001 From: Prasad Joshi Date: Tue, 5 Jul 2011 18:11:56 +0100 Subject: [PATCH] Add support for SystemVerilog style time literals SystemVerilog has support for time literals. The time literal for example #10ns, adds a delay of 10ns no matter the time unit currently in effect. For more details please refer to http://iverilog.wikia.com/wiki/Projects#SystemVerilog_Style_Time_Literals Tested-by: Oswaldo Cadenas Signed-off-by: Prasad Joshi --- parse.y | 17 +++++++++++++++++ pform.cc | 43 +++++++++++++++++++++++++++++++++++++++++++ pform.h | 2 ++ 3 files changed, 62 insertions(+) diff --git a/parse.y b/parse.y index 7000f84dd..2f66e6075 100644 --- a/parse.y +++ b/parse.y @@ -975,6 +975,23 @@ delay_value_simple $$ = tmp; delete[]$1; } + | TIME_LITERAL + { + int unit; + + based_size = 0; + $$ = 0; + if ($1 == 0 || !get_time_unit($1, unit)) + yyerror(@1, "internal error: delay."); + else { + double p = pow(10, unit - pform_get_timeunit()); + double time = atof($1) * p; + + verireal *v = new verireal(time); + $$ = new PEFNumber(v); + FILE_NAME($$, @1); + } + } ; description diff --git a/pform.cc b/pform.cc index 5edddf785..05ddc3314 100644 --- a/pform.cc +++ b/pform.cc @@ -502,6 +502,44 @@ void pform_set_timescale(int unit, int prec, } } +bool get_time_unit(const char*cp, int &unit) +{ + const char *c; + bool rc = true; + + if (strchr(cp, '_')) { + VLerror(yylloc, "Invalid timeunit constant ('_' is not " + "supported)."); + return false; + } + + c = strpbrk(cp, "munpfs"); + if (!c) + return false; + + if (*c == 's') + unit = 0; + else if (!strncmp(c, "ms", 2)) + unit = -3; + else if (!strncmp(c, "us", 2)) + unit = -6; + else if (!strncmp(c, "ns", 2)) + unit = -9; + else if (!strncmp(c, "ps", 2)) + unit = -12; + else if (!strncmp(c, "fs", 2)) + unit = -15; + else { + rc = false; + + ostringstream msg; + msg << "Invalid timeunit scale '" << cp << "'."; + VLerror(msg.str().c_str()); + } + + return rc; +} + /* * Get a timeunit or timeprecision value from a string. This is * similar to the code in lexor.lex for the `timescale directive. @@ -611,6 +649,11 @@ void pform_set_timeunit(const char*txt, bool in_module, bool only_check) } } +int pform_get_timeunit() +{ + return pform_cur_module->time_unit; +} + void pform_set_timeprecision(const char*txt, bool in_module, bool only_check) { int val; diff --git a/pform.h b/pform.h index fff1d1b43..030e37105 100644 --- a/pform.h +++ b/pform.h @@ -434,6 +434,8 @@ extern void parm_to_defparam_list(const string¶m); /* * Tasks to set the timeunit or timeprecision for SystemVerilog. */ +extern bool get_time_unit(const char*cp, int &unit); +extern int pform_get_timeunit(); 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);