Add support for SVA "final" keyword
[yosys.git] / frontends / verilog / verilog_lexer.l
index 13b3e2bfc7012d3cc7470fe398606705ef1945b8..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)
 
@@ -116,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++;
@@ -128,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);
 }
@@ -138,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; }
@@ -161,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; }
@@ -181,14 +223,17 @@ YOSYS_NAMESPACE_END
 "genvar"  { return TOK_GENVAR; }
 "real"    { return TOK_REAL; }
 
+"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?[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_]+)? {
@@ -211,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') {
@@ -230,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;
 }
@@ -244,7 +297,7 @@ and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 {
 supply0 { return TOK_SUPPLY0; }
 supply1 { return TOK_SUPPLY1; }
 
-"$"(display|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) {
+"$"(display|write|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) {
        frontend_verilog_yylval.string = new std::string(yytext);
        return TOK_ID;
 }
@@ -257,6 +310,11 @@ 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]*"*/" {
        static bool printed_warning = false;
        if (!printed_warning) {
@@ -277,7 +335,7 @@ supply1 { return TOK_SUPPLY1; }
        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");
+                               "Yosys does support them but it is recommended to use Verilog `full_case' attributes instead!\n");
                printed_warning = true;
        }
        return TOK_SYNOPSYS_FULL_CASE;
@@ -286,7 +344,7 @@ supply1 { return TOK_SUPPLY1; }
        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");
+                               "Yosys does support them but it is recommended to use Verilog `parallel_case' attributes instead!\n");
                printed_warning = true;
        }
        return TOK_SYNOPSYS_PARALLEL_CASE;
@@ -347,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; }
 
@@ -359,10 +421,6 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
 \\[\r\n]               /* ignore continuation sequence */
 "//"[^\r\n]*           /* ignore one-line comments */
 
-"#"\ *[0-9][0-9_]*                     /* ignore simulation timings */
-"#"\ *[0-9][0-9_]*\.[0-9][0-9_]*       /* ignore simulation timings */
-"#"\ *[$a-zA-Z_\.][$a-zA-Z_0-9\.]*     /* ignore simulation timings */
-
 . { return *yytext; }
 
 %%