Add support for SVA "final" keyword
[yosys.git] / frontends / verilog / verilog_lexer.l
index 5e739842b1302fff9602186bafd4e32cbd8e7367..e9763266390b70a62a2e3f691b2a6f74a137417e 100644 (file)
@@ -2,11 +2,11 @@
  *  yosys -- Yosys Open SYnthesis Suite
  *
  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
- *  
+ *
  *  Permission to use, copy, modify, and/or distribute this software for any
  *  purpose with or without fee is hereby granted, provided that the above
  *  copyright notice and this permission notice appear in all copies.
- *  
+ *
  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@@ -40,9 +40,9 @@
 #endif
 
 #include "kernel/log.h"
-#include "verilog_frontend.h"
+#include "frontends/verilog/verilog_frontend.h"
 #include "frontends/ast/ast.h"
-#include "verilog_parser.tab.h"
+#include "verilog_parser.tab.hh"
 
 USING_YOSYS_NAMESPACE
 using namespace AST;
@@ -63,6 +63,10 @@ YOSYS_NAMESPACE_END
        frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); \
        return TOK_ID;
 
+#define NON_KEYWORD() \
+       frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); \
+       return TOK_ID;
+
 #define YY_INPUT(buf,result,max_size) \
        result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
 
@@ -85,6 +89,10 @@ YOSYS_NAMESPACE_END
        fn_stack.push_back(current_filename);
        ln_stack.push_back(frontend_verilog_yyget_lineno());
        current_filename = yytext+11;
+       if (!current_filename.empty() && current_filename.front() == '"')
+               current_filename = current_filename.substr(1);
+       if (!current_filename.empty() && current_filename.back() == '"')
+               current_filename = current_filename.substr(0, current_filename.size()-1);
        frontend_verilog_yyset_lineno(0);
 }
 
@@ -112,6 +120,9 @@ YOSYS_NAMESPACE_END
 
 "`timescale"[ \t]+[^ \t\r\n/]+[ \t]*"/"[ \t]*[^ \t\r\n]* /* ignore timescale directive */
 
+"`celldefine"[^\n]* /* ignore `celldefine */
+"`endcelldefine"[^\n]* /* ignore `endcelldefine */
+
 "`default_nettype"[ \t]+[^ \t\r\n/]+ {
        char *p = yytext;
        while (*p != 0 && *p != ' ' && *p != '\t') p++;
@@ -124,6 +135,9 @@ YOSYS_NAMESPACE_END
                frontend_verilog_yyerror("Unsupported default nettype: %s", p);
 }
 
+"`protect"[^\n]* /* ignore `protect*/
+"`endprotect"[^\n]* /* ignore `endprotect*/
+
 "`"[a-zA-Z_$][a-zA-Z0-9_$]* {
        frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext);
 }
@@ -134,6 +148,14 @@ YOSYS_NAMESPACE_END
 "endfunction"  { return TOK_ENDFUNCTION; }
 "task"         { return TOK_TASK; }
 "endtask"      { return TOK_ENDTASK; }
+"specify"      { return TOK_SPECIFY; }
+"endspecify"   { return TOK_ENDSPECIFY; }
+"specparam"    { return TOK_SPECPARAM; }
+"package"      { SV_KEYWORD(TOK_PACKAGE); }
+"endpackage"   { SV_KEYWORD(TOK_ENDPACKAGE); }
+"interface"    { SV_KEYWORD(TOK_INTERFACE); }
+"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); }
+"modport"      { SV_KEYWORD(TOK_MODPORT); }
 "parameter"    { return TOK_PARAMETER; }
 "localparam"   { return TOK_LOCALPARAM; }
 "defparam"     { return TOK_DEFPARAM; }
@@ -157,15 +179,39 @@ YOSYS_NAMESPACE_END
 "endgenerate"  { return TOK_ENDGENERATE; }
 "while"        { return TOK_WHILE; }
 "repeat"       { return TOK_REPEAT; }
+"automatic"    { return TOK_AUTOMATIC; }
+
+"unique"       { SV_KEYWORD(TOK_UNIQUE); }
+"unique0"      { SV_KEYWORD(TOK_UNIQUE); }
+"priority"     { SV_KEYWORD(TOK_PRIORITY); }
 
 "always_comb"  { SV_KEYWORD(TOK_ALWAYS); }
 "always_ff"    { SV_KEYWORD(TOK_ALWAYS); }
 "always_latch" { SV_KEYWORD(TOK_ALWAYS); }
 
-"assert"   { SV_KEYWORD(TOK_ASSERT); }
-"property" { SV_KEYWORD(TOK_PROPERTY); }
-"logic"    { SV_KEYWORD(TOK_REG); }
-"bit"      { SV_KEYWORD(TOK_REG); }
+ /* use special token for labels on assert, assume, cover, and restrict because it's insanley complex
+    to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some
+    global state.. its a mess) */
+[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] {
+       frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
+       return TOK_SVA_LABEL;
+}
+
+"assert"     { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
+"assume"     { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
+"cover"      { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
+"restrict"   { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); }
+"property"   { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); }
+"rand"       { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); }
+"const"      { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); }
+"checker"    { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); }
+"endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); }
+"final"      { SV_KEYWORD(TOK_FINAL); }
+"logic"      { SV_KEYWORD(TOK_LOGIC); }
+"bit"        { SV_KEYWORD(TOK_REG); }
+
+"eventually"   { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
+"s_eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
 
 "input"   { return TOK_INPUT; }
 "output"  { return TOK_OUTPUT; }
@@ -177,14 +223,17 @@ YOSYS_NAMESPACE_END
 "genvar"  { return TOK_GENVAR; }
 "real"    { return TOK_REAL; }
 
-[0-9]+ {
+"enum"    { SV_KEYWORD(TOK_ENUM); }
+"typedef" { SV_KEYWORD(TOK_TYPEDEF); }
+
+[0-9][0-9_]* {
        frontend_verilog_yylval.string = new std::string(yytext);
-       return TOK_CONST;
+       return TOK_CONSTVAL;
 }
 
-[0-9]*[ \t]*\'s?[bodh][ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
+[0-9]*[ \t]*\'s?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
        frontend_verilog_yylval.string = new std::string(yytext);
-       return TOK_CONST;
+       return TOK_CONSTVAL;
 }
 
 [0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)? {
@@ -207,10 +256,18 @@ YOSYS_NAMESPACE_END
        while (yystr[i]) {
                if (yystr[i] == '\\' && yystr[i + 1]) {
                        i++;
-                       if (yystr[i] == 'n')
+                       if (yystr[i] == 'a')
+                               yystr[i] = '\a';
+                       else if (yystr[i] == 'f')
+                               yystr[i] = '\f';
+                       else if (yystr[i] == 'n')
                                yystr[i] = '\n';
+                       else if (yystr[i] == 'r')
+                               yystr[i] = '\r';
                        else if (yystr[i] == 't')
                                yystr[i] = '\t';
+                       else if (yystr[i] == 'v')
+                               yystr[i] = '\v';
                        else if ('0' <= yystr[i] && yystr[i] <= '7') {
                                yystr[i] = yystr[i] - '0';
                                if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') {
@@ -226,7 +283,7 @@ YOSYS_NAMESPACE_END
                yystr[j++] = yystr[i++];
        }
        yystr[j] = 0;
-       frontend_verilog_yylval.string = new std::string(yystr);
+       frontend_verilog_yylval.string = new std::string(yystr, j);
        free(yystr);
        return TOK_STRING;
 }
@@ -240,7 +297,7 @@ and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 {
 supply0 { return TOK_SUPPLY0; }
 supply1 { return TOK_SUPPLY1; }
 
-"$"(display|time|stop|finish) {
+"$"(display|write|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) {
        frontend_verilog_yylval.string = new std::string(yytext);
        return TOK_ID;
 }
@@ -253,9 +310,18 @@ supply1 { return TOK_SUPPLY1; }
        return TOK_ID;
 }
 
+[a-zA-Z_$][a-zA-Z0-9_$\.]* {
+       frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
+       return TOK_ID;
+}
+
 "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
-       log_warning("Found one of those horrible `(synopsys|synthesis) translate_off' comments.\n"
-                       "It is strongly suggested to use `ifdef constructs instead!\n");
+       static bool printed_warning = false;
+       if (!printed_warning) {
+               log_warning("Found one of those horrible `(synopsys|synthesis) translate_off' comments.\n"
+                               "Yosys does support them but it is recommended to use `ifdef constructs instead!\n");
+               printed_warning = true;
+       }
        BEGIN(SYNOPSYS_TRANSLATE_OFF);
 }
 <SYNOPSYS_TRANSLATE_OFF>.    /* ignore synopsys translate_off body */
@@ -266,13 +332,21 @@ supply1 { return TOK_SUPPLY1; }
        BEGIN(SYNOPSYS_FLAGS);
 }
 <SYNOPSYS_FLAGS>full_case {
-       log_warning("Found one of those horrible `(synopsys|synthesis) full_case' comments.\n"
-                       "It is strongly suggested to use verilog x-values and default branches instead!\n");
+       static bool printed_warning = false;
+       if (!printed_warning) {
+               log_warning("Found one of those horrible `(synopsys|synthesis) full_case' comments.\n"
+                               "Yosys does support them but it is recommended to use Verilog `full_case' attributes instead!\n");
+               printed_warning = true;
+       }
        return TOK_SYNOPSYS_FULL_CASE;
 }
 <SYNOPSYS_FLAGS>parallel_case {
-       log_warning("Found one of those horrible `(synopsys|synthesis) parallel_case' comments.\n"
-                       "It is strongly suggested to use verilog `parallel_case' attributes instead!\n");
+       static bool printed_warning = false;
+       if (!printed_warning) {
+               log_warning("Found one of those horrible `(synopsys|synthesis) parallel_case' comments.\n"
+                               "Yosys does support them but it is recommended to use Verilog `parallel_case' attributes instead!\n");
+               printed_warning = true;
+       }
        return TOK_SYNOPSYS_PARALLEL_CASE;
 }
 <SYNOPSYS_FLAGS>. /* ignore everything else */
@@ -331,6 +405,10 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
 "<<<" { return OP_SSHL; }
 ">>>" { return OP_SSHR; }
 
+"::"  { return TOK_PACKAGESEP; }
+"++"  { return TOK_INCREMENT; }
+"--"  { return TOK_DECREMENT; }
+
 "+:" { return TOK_POS_INDEXED; }
 "-:" { return TOK_NEG_INDEXED; }
 
@@ -342,7 +420,6 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
 [ \t\r\n]              /* ignore whitespaces */
 \\[\r\n]               /* ignore continuation sequence */
 "//"[^\r\n]*           /* ignore one-line comments */
-"#"[$a-zA-Z_0-9\.]+    /* ignore simulation timings */
 
 . { return *yytext; }