diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index aba82f222..ccf4937b6 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -374,6 +374,7 @@ void V3ParseImp::lexToken() { || token == yGLOBAL__LEX // || token == yLOCAL__LEX // || token == yNEW__LEX // + || token == ySTATIC__LEX // || token == yVIRTUAL__LEX // || token == yWITH__LEX // // Never put yID_* here; below symbol table resolution would break @@ -420,6 +421,12 @@ void V3ParseImp::lexToken() { } else { token = yNEW__ETC; } + } else if (token == ySTATIC__LEX) { + if (nexttok == yCONSTRAINT) { + token = ySTATIC__CONSTRAINT; + } else { + token = ySTATIC__ETC; + } } else if (token == yVIRTUAL__LEX) { if (nexttok == yCLASS) { token = yVIRTUAL__CLASS; diff --git a/src/verilog.l b/src/verilog.l index 9e7bfe74d..cebe62569 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -294,6 +294,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "always" { FL; return yALWAYS; } "and" { FL; return yAND; } "assign" { FL; return yASSIGN; } + "before" { FL; return yBEFORE; } "begin" { FL; return yBEGIN; } "buf" { FL; return yBUF; } "bufif0" { FL; return yBUFIF0; } @@ -478,14 +479,14 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "class" { FL; return yCLASS; } "clocking" { FL; return yCLOCKING; } "const" { FL; return yCONST__LEX; } - "constraint" { ERROR_RSVD_WORD("SystemVerilog 2005"); } + "constraint" { FL; return yCONSTRAINT; } "context" { FL; return yCONTEXT; } "continue" { FL; return yCONTINUE; } "cover" { FL; return yCOVER; } "covergroup" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "coverpoint" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "cross" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "dist" { ERROR_RSVD_WORD("SystemVerilog 2005"); } + "dist" { FL; return yDIST; } "do" { FL; return yDO; } "endclass" { FL; return yENDCLASS; } "endclocking" { FL; return yENDCLOCKING; } @@ -538,8 +539,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "sequence" { ERROR_RSVD_WORD("SystemVerilog 2005"); } "shortint" { FL; return ySHORTINT; } "shortreal" { FL; return ySHORTREAL; } - "solve" { ERROR_RSVD_WORD("SystemVerilog 2005"); } - "static" { FL; return ySTATIC__ETC; } + "solve" { FL; return ySOLVE; } + "static" { FL; return ySTATIC__LEX; } "string" { FL; return ySTRING; } "struct" { FL; return ySTRUCT; } "super" { FL; return ySUPER; } @@ -594,7 +595,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "implements" { FL; return yIMPLEMENTS; } "interconnect" { ERROR_RSVD_WORD("SystemVerilog 2012"); } "nettype" { ERROR_RSVD_WORD("SystemVerilog 2012"); } - "soft" { ERROR_RSVD_WORD("SystemVerilog 2012"); } + "soft" { FL; return ySOFT; } } /* System Verilog 2017 */ diff --git a/src/verilog.y b/src/verilog.y index 816664c5e..721d60942 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -421,7 +421,7 @@ class AstSenTree; %token yASSIGN "assign" %token yASSUME "assume" %token yAUTOMATIC "automatic" -//UNSUP %token yBEFORE "before" +%token yBEFORE "before" %token yBEGIN "begin" %token yBIND "bind" //UNSUP %token yBINS "bins" @@ -441,7 +441,7 @@ class AstSenTree; //UNSUP %token yCLOCK "clock" %token yCLOCKING "clocking" %token yCMOS "cmos" -//UNSUP %token yCONSTRAINT "constraint" +%token yCONSTRAINT "constraint" %token yCONST__ETC "const" %token yCONST__LEX "const-in-lex" //UNSUP %token yCONST__LOCAL "const-then-local" @@ -456,7 +456,7 @@ class AstSenTree; %token yDEFAULT "default" %token yDEFPARAM "defparam" %token yDISABLE "disable" -//UNSUP %token yDIST "dist" +%token yDIST "dist" %token yDO "do" %token yEDGE "edge" %token yELSE "else" @@ -584,13 +584,13 @@ class AstSenTree; %token ySHORTINT "shortint" %token ySHORTREAL "shortreal" %token ySIGNED "signed" -//UNSUP %token ySOFT "soft" -//UNSUP %token ySOLVE "solve" +%token ySOFT "soft" +%token ySOLVE "solve" %token ySPECIFY "specify" %token ySPECPARAM "specparam" -//UNSUP %token ySTATIC__CONSTRAINT "static-then-constraint" +%token ySTATIC__CONSTRAINT "static-then-constraint" %token ySTATIC__ETC "static" -//UNSUP %token ySTATIC__LEX "static-in-lex" +%token ySTATIC__LEX "static-in-lex" %token ySTRING "string" //UNSUP %token ySTRONG "strong" %token ySTRUCT "struct" @@ -910,8 +910,7 @@ class AstSenTree; %left '^' yP_XNOR %left '&' yP_NAND %left yP_EQUAL yP_NOTEQUAL yP_CASEEQUAL yP_CASENOTEQUAL yP_WILDEQUAL yP_WILDNOTEQUAL -%left '>' '<' yP_GTE yP_LTE yP_LTE__IGNORE yINSIDE -//UNSUP yDIST in above +%left '>' '<' yP_GTE yP_LTE yP_LTE__IGNORE yINSIDE yDIST %left yP_SLEFT yP_SRIGHT yP_SSRIGHT %left '+' '-' %left '*' '/' '%' @@ -3403,9 +3402,8 @@ function_subroutine_callNoMethod: // IEEE: function_subroutine_call (as f // // IEEE: randomize_call // // We implement randomize as a normal funcRef, since randomize isn't a keyword // // Note yNULL is already part of expressions, so they come for free - //UNSUP funcRef yWITH__CUR constraint_block { $$ = $1; BBUNSUP($2, "Unsupported: randomize() 'with'"); } - //UNSUP remove the next line, temporary until have constraint_block (but enough for UVM parsing) - | funcRef yWITH__CUR '{' '}' { $$ = $1; BBUNSUP($2, "Unsupported: randomize() 'with'"); } + | funcRef yWITH__CUR constraint_block { $$ = $1; BBUNSUP($2, "Unsupported: randomize() 'with'"); } + | funcRef yWITH__CUR '{' '}' { $$ = $1; BBUNSUP($2, "Unsupported: randomize() 'with'"); } ; system_t_call: // IEEE: system_tf_call (as task) @@ -4094,7 +4092,7 @@ expr: // IEEE: part of expression/constant_expression/primary // // // IEEE: expression_or_dist - here to avoid reduce problems // // "expr yDIST '{' dist_list '}'" - //UNSUP ~l~expr yDIST '{' dist_list '}' { UNSUP } + | ~l~expr yDIST '{' dist_list '}' { $$ = $1; BBUNSUP($2, "Unsupported: dist"); } ; fexpr: // For use as first part of statement (disambiguates <=) @@ -5880,7 +5878,7 @@ class_itemList: class_item: // ==IEEE: class_item class_property { $$ = $1; } | class_method { $$ = $1; } - //UNSUP class_constraint { $$ = $1; } + | class_constraint { $$ = $1; } // | class_declaration { $$ = NULL; BBUNSUP($1, "Unsupported: class within class"); } | timeunits_declaration { $$ = $1; } @@ -5943,86 +5941,86 @@ memberQualOne: // IEEE: property_qualifier + method_qualifier //********************************************************************** // Constraints -//UNSUPclass_constraint: // ==IEEE: class_constraint -//UNSUP // // IEEE: constraint_declaration -//UNSUP constraintStaticE yCONSTRAINT idAny constraint_block { } -//UNSUP // // IEEE: constraint_prototype + constraint_prototype_qualifier -//UNSUP | constraintStaticE yCONSTRAINT idAny ';' { } -//UNSUP | yEXTERN constraintStaticE yCONSTRAINT idAny ';' { } -//UNSUP | yPURE constraintStaticE yCONSTRAINT idAny ';' { } -//UNSUP ; +class_constraint: // ==IEEE: class_constraint + // // IEEE: constraint_declaration + constraintStaticE yCONSTRAINT idAny constraint_block { $$ = NULL; BBUNSUP($2, "Unsupported: constraint"); /*and audit all rules below for UNSUP*/ } + // // IEEE: constraint_prototype + constraint_prototype_qualifier + | constraintStaticE yCONSTRAINT idAny ';' { $$ = NULL; } + | yEXTERN constraintStaticE yCONSTRAINT idAny ';' { $$ = NULL; BBUNSUP($1, "Unsupported: extern constraint"); } + | yPURE constraintStaticE yCONSTRAINT idAny ';' { $$ = NULL; BBUNSUP($1, "Unsupported: pure constraint"); } + ; -//UNSUPconstraint_block: // ==IEEE: constraint_block -//UNSUP '{' constraint_block_itemList '}' { $$ = $1; } -//UNSUP ; +constraint_block: // ==IEEE: constraint_block + '{' constraint_block_itemList '}' { $$ = $2; } + ; -//UNSUPconstraint_block_itemList: // IEEE: { constraint_block_item } -//UNSUP constraint_block_item { $$ = $1; } -//UNSUP | constraint_block_itemList constraint_block_item { $$ = AstNode::addNextNull($1, $2); } -//UNSUP ; +constraint_block_itemList: // IEEE: { constraint_block_item } + constraint_block_item { $$ = $1; } + | constraint_block_itemList constraint_block_item { $$ = AstNode::addNextNull($1, $2); } + ; -//UNSUPconstraint_block_item: // ==IEEE: constraint_block_item -//UNSUP ySOLVE solve_before_list yBEFORE solve_before_list ';' { } -//UNSUP | constraint_expression { $$ = $1; } -//UNSUP ; +constraint_block_item: // ==IEEE: constraint_block_item + constraint_expression { $$ = $1; } + | ySOLVE solve_before_list yBEFORE solve_before_list ';' { $$ = NULL; BBUNSUP($2, "Unsupported: solve before"); } + ; -//UNSUPsolve_before_list: // ==IEEE: solve_before_list -//UNSUP constraint_primary { $$ = $1; } -//UNSUP | solve_before_list ',' constraint_primary { } -//UNSUP ; +solve_before_list: // ==IEEE: solve_before_list + constraint_primary { $$ = $1; } + | solve_before_list ',' constraint_primary { $$ = AstNode::addNextNull($1, $3); } + ; -//UNSUPconstraint_primary: // ==IEEE: constraint_primary -//UNSUP // // exprScope more general than: [ implicit_class_handle '.' | class_scope ] hierarchical_identifier select -//UNSUP exprScope { $$ = $1; } -//UNSUP ; +constraint_primary: // ==IEEE: constraint_primary + // // exprScope more general than: [ implicit_class_handle '.' | class_scope ] hierarchical_identifier select + exprScope { $$ = $1; } + ; -//UNSUPconstraint_expressionList: // ==IEEE: { constraint_expression } -//UNSUP constraint_expression { $$ = $1; } -//UNSUP | constraint_expressionList constraint_expression { $$ = AstNode::addNextNull($1, $2); } -//UNSUP ; +constraint_expressionList: // ==IEEE: { constraint_expression } + constraint_expression { $$ = $1; } + | constraint_expressionList constraint_expression { $$ = AstNode::addNextNull($1, $2); } + ; -//UNSUPconstraint_expression: // ==IEEE: constraint_expression -//UNSUP expr/*expression_or_dist*/ ';' { $$ = $1; } -//UNSUP // // 1800-2012: -//UNSUP | ySOFT expr/*expression_or_dist*/ ';' { } -//UNSUP // // 1800-2012: -//UNSUP // // IEEE: uniqueness_constraint ';' -//UNSUP | yUNIQUE '{' open_range_list '}' { } -//UNSUP // // IEEE: expr yP_MINUSGT constraint_set -//UNSUP // // Conflicts with expr:"expr yP_MINUSGT expr"; rule moved there -//UNSUP // -//UNSUP | yIF '(' expr ')' constraint_set %prec prLOWER_THAN_ELSE { } -//UNSUP | yIF '(' expr ')' constraint_set yELSE constraint_set { } -//UNSUP // // IEEE says array_identifier here, but dotted accepted in VMM + 1800-2009 -//UNSUP | yFOREACH '(' idClassForeach/*array_id[loop_variables]*/ ')' constraint_set { } -//UNSUP // // soft is 1800-2012 -//UNSUP | yDISABLE ySOFT expr/*constraint_primary*/ ';' { } -//UNSUP ; +constraint_expression: // ==IEEE: constraint_expression + expr/*expression_or_dist*/ ';' { $$ = $1; } + // // 1800-2012: + | ySOFT expr/*expression_or_dist*/ ';' { $$ = NULL; /*UNSUP*/ } + // // 1800-2012: + // // IEEE: uniqueness_constraint ';' + | yUNIQUE '{' open_range_list '}' { $$ = NULL; /*UNSUP*/ } + // // IEEE: expr yP_MINUSGT constraint_set + // // Conflicts with expr:"expr yP_MINUSGT expr"; rule moved there + // + | yIF '(' expr ')' constraint_set %prec prLOWER_THAN_ELSE { $$ = NULL; /*UNSUP*/ } + | yIF '(' expr ')' constraint_set yELSE constraint_set { $$ = NULL; /*UNSUP*/ } + // // IEEE says array_identifier here, but dotted accepted in VMM + 1800-2009 + | yFOREACH '(' idClassForeach '[' loop_variables ']' ')' constraint_set { $$ = NULL; /*UNSUP*/ } + // // soft is 1800-2012 + | yDISABLE ySOFT expr/*constraint_primary*/ ';' { $$ = NULL; /*UNSUP*/ } + ; -//UNSUPconstraint_set: // ==IEEE: constraint_set -//UNSUP constraint_expression { $$ = $1; } -//UNSUP | '{' constraint_expressionList '}' { $$ = $2; } -//UNSUP ; +constraint_set: // ==IEEE: constraint_set + constraint_expression { $$ = $1; } + | '{' constraint_expressionList '}' { $$ = $2; } + ; -//UNSUPdist_list: // ==IEEE: dist_list -//UNSUP dist_item { $$ = $1; } -//UNSUP | dist_list ',' dist_item { $$ = AstNode::addNextNull($1, $3); } -//UNSUP ; +dist_list: // ==IEEE: dist_list + dist_item { $$ = $1; } + | dist_list ',' dist_item { $$ = AstNode::addNextNull($1, $3); } + ; -//UNSUPdist_item: // ==IEEE: dist_item + dist_weight -//UNSUP value_range { $$ = $1; } -//UNSUP | value_range yP_COLONEQ expr { } -//UNSUP | value_range yP_COLONDIV expr { } -//UNSUP ; +dist_item: // ==IEEE: dist_item + dist_weight + value_range { $$ = $1; } + | value_range yP_COLONEQ expr { $$ = $1; BBUNSUP($1, "Unsupported: dist :="); } + | value_range yP_COLONDIV expr { $$ = $1; BBUNSUP($1, "Unsupported: dist :/"); } + ; //UNSUPextern_constraint_declaration: // ==IEEE: extern_constraint_declaration //UNSUP constraintStaticE yCONSTRAINT class_scope_id constraint_block { } //UNSUP ; -//UNSUPconstraintStaticE: // IEEE: part of extern_constraint_declaration -//UNSUP /* empty */ { $$ = false; } -//UNSUP | ySTATIC__CONSTRAINT { $$ = true; } -//UNSUP ; +constraintStaticE: // IEEE: part of extern_constraint_declaration + /* empty */ { $$ = false; } + | ySTATIC__CONSTRAINT { $$ = true; } + ; //********************************************************************** // Constants diff --git a/test_regress/t/t_randomize.out b/test_regress/t/t_randomize.out index 2a5c996f7..3b00607a8 100644 --- a/test_regress/t/t_randomize.out +++ b/test_regress/t/t_randomize.out @@ -1,4 +1,40 @@ -%Error: t/t_randomize.v:25:25: Unsupported: randomize() 'with' - 25 | v = p.randomize() with {}; +%Error: t/t_randomize.v:11:4: Unsupported: extern constraint + 11 | extern constraint ex; + | ^~~~~~ +%Error: t/t_randomize.v:13:4: Unsupported: constraint + 13 | constraint a { header > 0 && header < 1000; } + | ^~~~~~~~~~ +%Error: t/t_randomize.v:14:4: Unsupported: constraint + 14 | constraint b { + | ^~~~~~~~~~ +%Error: t/t_randomize.v:19:4: Unsupported: constraint + 19 | constraint b { + | ^~~~~~~~~~ +%Error: t/t_randomize.v:23:4: Unsupported: constraint + 23 | constraint c { + | ^~~~~~~~~~ +%Error: t/t_randomize.v:29:29: Unsupported: solve before + 29 | constraint order { solve length before header; } + | ^~~~~~ +%Error: t/t_randomize.v:29:4: Unsupported: constraint + 29 | constraint order { solve length before header; } + | ^~~~~~~~~~ +%Error: t/t_randomize.v:32:16: Unsupported: dist :/ + 32 | x dist { [100:102] :/ 1, 200 := 2, 300 := 5}; + | ^ +%Error: t/t_randomize.v:32:32: Unsupported: dist := + 32 | x dist { [100:102] :/ 1, 200 := 2, 300 := 5}; + | ^~~ +%Error: t/t_randomize.v:32:42: Unsupported: dist := + 32 | x dist { [100:102] :/ 1, 200 := 2, 300 := 5}; + | ^~~ +%Error: t/t_randomize.v:32:9: Unsupported: dist + 32 | x dist { [100:102] :/ 1, 200 := 2, 300 := 5}; + | ^~~~ +%Error: t/t_randomize.v:30:4: Unsupported: constraint + 30 | constraint dis { + | ^~~~~~~~~~ +%Error: t/t_randomize.v:50:25: Unsupported: randomize() 'with' + 50 | v = p.randomize() with {}; | ^~~~ %Error: Exiting due to diff --git a/test_regress/t/t_randomize.v b/test_regress/t/t_randomize.v index e5842cb22..adc5bfcca 100644 --- a/test_regress/t/t_randomize.v +++ b/test_regress/t/t_randomize.v @@ -7,6 +7,31 @@ class Packet; rand int header; rand int length; + + extern constraint ex; + + constraint a { header > 0 && header < 1000; } + constraint b { + if (64 > header) { + header < (64'h1 << length); + } + } + constraint b { + header >= length - 10; + header <= length; + } + constraint c { + foreach (in_use[i]) { + !(start_offset <= in_use[i].Xend_offsetX && + start_offset + len - 1 >= in_use[i].Xstart_offsetX); + } + } + constraint order { solve length before header; } + constraint dis { + disable soft x; + x dist { [100:102] :/ 1, 200 := 2, 300 := 5}; + } + endclass module t (/*AUTOARG*/); diff --git a/test_regress/t/t_randomize_bbox.pl b/test_regress/t/t_randomize_bbox.pl new file mode 100755 index 000000000..2f89e3fb1 --- /dev/null +++ b/test_regress/t/t_randomize_bbox.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +top_filename("t/t_randomize.v"); + +lint( + verilator_flags => ["--bbox-unsup"], + fails => 1, + ); + +ok(1); +1;