2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * The Verilog frontend.
22 * This frontend is using the AST frontend library (see frontends/ast/).
23 * Thus this frontend does not generate RTLIL code directly but creates an
24 * AST directly from the Verilog parse tree and then passes this AST to
25 * the AST frontend library.
29 * A simple lexer for Verilog code. Non-preprocessor compiler directives are
30 * handled here. The preprocessor stuff is handled in preproc.cc. Everything
31 * else is left to the bison parser (see parser.y).
38 // bison generates code using the 'register' storage class specifier
39 #pragma clang diagnostic ignored "-Wdeprecated-register"
42 #include "kernel/log.h"
43 #include "frontends/verilog/verilog_frontend.h"
44 #include "frontends/ast/ast.h"
45 #include "verilog_parser.tab.hh"
49 using namespace VERILOG_FRONTEND;
52 namespace VERILOG_FRONTEND {
53 std::vector<std::string> fn_stack;
54 std::vector<int> ln_stack;
58 #define SV_KEYWORD(_tok) \
59 if (sv_mode) return _tok; \
60 log("Lexer warning: The SystemVerilog keyword `%s' (at %s:%d) is not "\
61 "recognized unless read_verilog is called with -sv!\n", yytext, \
62 AST::current_filename.c_str(), frontend_verilog_yyget_lineno()); \
63 frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); \
66 #define NON_KEYWORD() \
67 frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); \
70 #define YY_INPUT(buf,result,max_size) \
71 result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
78 %option prefix="frontend_verilog_yy"
82 %x SYNOPSYS_TRANSLATE_OFF
88 <INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_push "[^\n]* {
89 fn_stack.push_back(current_filename);
90 ln_stack.push_back(frontend_verilog_yyget_lineno());
91 current_filename = yytext+11;
92 if (!current_filename.empty() && current_filename.front() == '"')
93 current_filename = current_filename.substr(1);
94 if (!current_filename.empty() && current_filename.back() == '"')
95 current_filename = current_filename.substr(0, current_filename.size()-1);
96 frontend_verilog_yyset_lineno(0);
99 <INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_pop"[^\n]*\n {
100 current_filename = fn_stack.back();
102 frontend_verilog_yyset_lineno(ln_stack.back());
106 <INITIAL,SYNOPSYS_TRANSLATE_OFF>"`line"[ \t]+[^ \t\r\n]+[ \t]+\"[^ \r\n]+\"[^\r\n]*\n {
107 char *p = yytext + 5;
108 while (*p == ' ' || *p == '\t') p++;
109 frontend_verilog_yyset_lineno(atoi(p));
110 while (*p && *p != ' ' && *p != '\t') p++;
111 while (*p == ' ' || *p == '\t') p++;
112 char *q = *p ? p + 1 : p;
113 while (*q && *q != '"') q++;
114 current_filename = std::string(p).substr(1, q-p-1);
117 "`file_notfound "[^\n]* {
118 log_error("Can't open include file `%s'!\n", yytext + 15);
121 "`timescale"[ \t]+[^ \t\r\n/]+[ \t]*"/"[ \t]*[^ \t\r\n]* /* ignore timescale directive */
123 "`celldefine"[^\n]* /* ignore `celldefine */
124 "`endcelldefine"[^\n]* /* ignore `endcelldefine */
126 "`default_nettype"[ \t]+[^ \t\r\n/]+ {
128 while (*p != 0 && *p != ' ' && *p != '\t') p++;
129 while (*p == ' ' || *p == '\t') p++;
130 if (!strcmp(p, "none"))
131 VERILOG_FRONTEND::default_nettype_wire = false;
132 else if (!strcmp(p, "wire"))
133 VERILOG_FRONTEND::default_nettype_wire = true;
135 frontend_verilog_yyerror("Unsupported default nettype: %s", p);
138 "`protect"[^\n]* /* ignore `protect*/
139 "`endprotect"[^\n]* /* ignore `endprotect*/
141 "`"[a-zA-Z_$][a-zA-Z0-9_$]* {
142 frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext);
145 "module" { return TOK_MODULE; }
146 "endmodule" { return TOK_ENDMODULE; }
147 "function" { return TOK_FUNCTION; }
148 "endfunction" { return TOK_ENDFUNCTION; }
149 "task" { return TOK_TASK; }
150 "endtask" { return TOK_ENDTASK; }
151 "specify" { return TOK_SPECIFY; }
152 "endspecify" { return TOK_ENDSPECIFY; }
153 "specparam" { return TOK_SPECPARAM; }
154 "package" { SV_KEYWORD(TOK_PACKAGE); }
155 "endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); }
156 "interface" { SV_KEYWORD(TOK_INTERFACE); }
157 "endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); }
158 "modport" { SV_KEYWORD(TOK_MODPORT); }
159 "parameter" { return TOK_PARAMETER; }
160 "localparam" { return TOK_LOCALPARAM; }
161 "defparam" { return TOK_DEFPARAM; }
162 "assign" { return TOK_ASSIGN; }
163 "always" { return TOK_ALWAYS; }
164 "initial" { return TOK_INITIAL; }
165 "begin" { return TOK_BEGIN; }
166 "end" { return TOK_END; }
167 "if" { return TOK_IF; }
168 "else" { return TOK_ELSE; }
169 "for" { return TOK_FOR; }
170 "posedge" { return TOK_POSEDGE; }
171 "negedge" { return TOK_NEGEDGE; }
172 "or" { return TOK_OR; }
173 "case" { return TOK_CASE; }
174 "casex" { return TOK_CASEX; }
175 "casez" { return TOK_CASEZ; }
176 "endcase" { return TOK_ENDCASE; }
177 "default" { return TOK_DEFAULT; }
178 "generate" { return TOK_GENERATE; }
179 "endgenerate" { return TOK_ENDGENERATE; }
180 "while" { return TOK_WHILE; }
181 "repeat" { return TOK_REPEAT; }
182 "automatic" { return TOK_AUTOMATIC; }
184 "unique" { SV_KEYWORD(TOK_UNIQUE); }
185 "unique0" { SV_KEYWORD(TOK_UNIQUE); }
186 "priority" { SV_KEYWORD(TOK_PRIORITY); }
188 "always_comb" { SV_KEYWORD(TOK_ALWAYS); }
189 "always_ff" { SV_KEYWORD(TOK_ALWAYS); }
190 "always_latch" { SV_KEYWORD(TOK_ALWAYS); }
192 /* parse labels on assert, assume, cover, and restrict right here because it's insanley complex
193 to do it in the parser (because we force the parser too early to reduce when parsing cells..) */
194 ([a-zA-Z_$][a-zA-Z0-9_$]*[ \t\r\n]*:[ \t\r\n]*)?(assert|assume|cover|restrict)/[^a-zA-Z0-9_$\.] {
195 frontend_verilog_yylval.string = new std::string(yytext);
196 auto &str = *frontend_verilog_yylval.string;
201 if (cursor == GetSize(str)) {
203 delete frontend_verilog_yylval.string;
204 frontend_verilog_yylval.string = nullptr;
205 goto sva_without_label;
207 char c = str[cursor];
208 if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') {
213 keyword = str.substr(cursor);
214 str = "\\" + str.substr(0, cursor);
220 log_assert(cursor < GetSize(keyword));
221 char c = keyword[cursor];
222 if (c != ' ' && c != '\t' && c != '\r' && c != '\n' && c != ':') {
223 keyword = keyword.substr(cursor);
229 if (keyword == "assert") { return TOK_ASSERT; }
230 else if (keyword == "assume") { return TOK_ASSUME; }
231 else if (keyword == "cover") { return TOK_COVER; }
232 else if (keyword == "restrict") { return TOK_RESTRICT; }
236 if (keyword == "assert") { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
237 else if (keyword == "assume") { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
238 else if (keyword == "cover") { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
239 else if (keyword == "restrict") { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); }
243 "property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); }
244 "rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); }
245 "const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); }
246 "checker" { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); }
247 "endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); }
248 "logic" { SV_KEYWORD(TOK_LOGIC); }
249 "bit" { SV_KEYWORD(TOK_REG); }
251 "eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
252 "s_eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
254 "input" { return TOK_INPUT; }
255 "output" { return TOK_OUTPUT; }
256 "inout" { return TOK_INOUT; }
257 "wire" { return TOK_WIRE; }
258 "reg" { return TOK_REG; }
259 "integer" { return TOK_INTEGER; }
260 "signed" { return TOK_SIGNED; }
261 "genvar" { return TOK_GENVAR; }
262 "real" { return TOK_REAL; }
264 "enum" { SV_KEYWORD(TOK_ENUM); }
265 "typedef" { SV_KEYWORD(TOK_TYPEDEF); }
268 frontend_verilog_yylval.string = new std::string(yytext);
272 [0-9]*[ \t]*\'s?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
273 frontend_verilog_yylval.string = new std::string(yytext);
277 [0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)? {
278 frontend_verilog_yylval.string = new std::string(yytext);
282 [0-9][0-9_]*[eE][-+]?[0-9_]+ {
283 frontend_verilog_yylval.string = new std::string(yytext);
287 \" { BEGIN(STRING); }
288 <STRING>\\. { yymore(); }
291 char *yystr = strdup(yytext);
292 yystr[strlen(yytext) - 1] = 0;
295 if (yystr[i] == '\\' && yystr[i + 1]) {
299 else if (yystr[i] == 'f')
301 else if (yystr[i] == 'n')
303 else if (yystr[i] == 'r')
305 else if (yystr[i] == 't')
307 else if (yystr[i] == 'v')
309 else if ('0' <= yystr[i] && yystr[i] <= '7') {
310 yystr[i] = yystr[i] - '0';
311 if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') {
312 yystr[i + 1] = yystr[i] * 8 + yystr[i + 1] - '0';
315 if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') {
316 yystr[i + 1] = yystr[i] * 8 + yystr[i + 1] - '0';
321 yystr[j++] = yystr[i++];
324 frontend_verilog_yylval.string = new std::string(yystr, j);
328 <STRING>. { yymore(); }
330 and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 {
331 frontend_verilog_yylval.string = new std::string(yytext);
332 return TOK_PRIMITIVE;
335 supply0 { return TOK_SUPPLY0; }
336 supply1 { return TOK_SUPPLY1; }
338 "$"(display|write|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) {
339 frontend_verilog_yylval.string = new std::string(yytext);
343 "$signed" { return TOK_TO_SIGNED; }
344 "$unsigned" { return TOK_TO_UNSIGNED; }
346 [a-zA-Z_$][a-zA-Z0-9_$]* {
347 frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
351 [a-zA-Z_$][a-zA-Z0-9_$\.]* {
352 frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
356 "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
357 static bool printed_warning = false;
358 if (!printed_warning) {
359 log_warning("Found one of those horrible `(synopsys|synthesis) translate_off' comments.\n"
360 "Yosys does support them but it is recommended to use `ifdef constructs instead!\n");
361 printed_warning = true;
363 BEGIN(SYNOPSYS_TRANSLATE_OFF);
365 <SYNOPSYS_TRANSLATE_OFF>. /* ignore synopsys translate_off body */
366 <SYNOPSYS_TRANSLATE_OFF>\n /* ignore synopsys translate_off body */
367 <SYNOPSYS_TRANSLATE_OFF>"/*"[ \t]*(synopsys|synthesis)[ \t]*"translate_on"[ \t]*"*/" { BEGIN(0); }
369 "/*"[ \t]*(synopsys|synthesis)[ \t]+ {
370 BEGIN(SYNOPSYS_FLAGS);
372 <SYNOPSYS_FLAGS>full_case {
373 static bool printed_warning = false;
374 if (!printed_warning) {
375 log_warning("Found one of those horrible `(synopsys|synthesis) full_case' comments.\n"
376 "Yosys does support them but it is recommended to use Verilog `full_case' attributes instead!\n");
377 printed_warning = true;
379 return TOK_SYNOPSYS_FULL_CASE;
381 <SYNOPSYS_FLAGS>parallel_case {
382 static bool printed_warning = false;
383 if (!printed_warning) {
384 log_warning("Found one of those horrible `(synopsys|synthesis) parallel_case' comments.\n"
385 "Yosys does support them but it is recommended to use Verilog `parallel_case' attributes instead!\n");
386 printed_warning = true;
388 return TOK_SYNOPSYS_PARALLEL_CASE;
390 <SYNOPSYS_FLAGS>. /* ignore everything else */
391 <SYNOPSYS_FLAGS>"*/" { BEGIN(0); }
393 import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
395 return TOK_DPI_FUNCTION;
398 <IMPORT_DPI>[a-zA-Z_$][a-zA-Z0-9_$]* {
399 frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
403 <IMPORT_DPI>[ \t\r\n] /* ignore whitespaces */
415 frontend_verilog_yylval.string = new std::string(yytext);
419 "(*" { return ATTR_BEGIN; }
420 "*)" { return ATTR_END; }
422 "{*" { return DEFATTR_BEGIN; }
423 "*}" { return DEFATTR_END; }
425 "**" { return OP_POW; }
426 "||" { return OP_LOR; }
427 "&&" { return OP_LAND; }
428 "==" { return OP_EQ; }
429 "!=" { return OP_NE; }
430 "<=" { return OP_LE; }
431 ">=" { return OP_GE; }
433 "===" { return OP_EQX; }
434 "!==" { return OP_NEX; }
436 "~&" { return OP_NAND; }
437 "~|" { return OP_NOR; }
438 "~^" { return OP_XNOR; }
439 "^~" { return OP_XNOR; }
441 "<<" { return OP_SHL; }
442 ">>" { return OP_SHR; }
443 "<<<" { return OP_SSHL; }
444 ">>>" { return OP_SSHR; }
446 "::" { return TOK_PACKAGESEP; }
447 "++" { return TOK_INCREMENT; }
448 "--" { return TOK_DECREMENT; }
450 "+:" { return TOK_POS_INDEXED; }
451 "-:" { return TOK_NEG_INDEXED; }
453 "/*" { BEGIN(COMMENT); }
454 <COMMENT>. /* ignore comment body */
455 <COMMENT>\n /* ignore comment body */
456 <COMMENT>"*/" { BEGIN(0); }
458 [ \t\r\n] /* ignore whitespaces */
459 \\[\r\n] /* ignore continuation sequence */
460 "//"[^\r\n]* /* ignore one-line comments */
462 . { return *yytext; }
466 // this is a hack to avoid the 'yyinput defined but not used' error msgs
467 void *frontend_verilog_avoid_input_warnings() {
468 return (void*)&yyinput;