Commit 5fd21ebf by Zachary Snow

improved parsing in declaration contexts

- support for additional assignment statements in loop initializations
- greatly improved error messaging in these contexts
- decl parser takes in the ending token; significant related refactoring
- pass through elaboration system tasks
- removed non-blocking assignment operator precedence hack
- preliminary nosim test suite for features unsupported by iverilog
parent 6ee558b6
...@@ -625,6 +625,11 @@ traverseNodesM exprMapper declMapper typeMapper lhsMapper stmtMapper = ...@@ -625,6 +625,11 @@ traverseNodesM exprMapper declMapper typeMapper lhsMapper stmtMapper =
a' <- traverseAssertionStmtsM stmtMapper a a' <- traverseAssertionStmtsM stmtMapper a
a'' <- traverseAssertionExprsM exprMapper a' a'' <- traverseAssertionExprsM exprMapper a'
return $ AssertionItem (mx, a'') return $ AssertionItem (mx, a'')
moduleItemMapper (ElabTask severity (Args pnArgs kwArgs)) = do
pnArgs' <- mapM exprMapper pnArgs
kwArgs' <- fmap (zip kwNames) $ mapM exprMapper kwExprs
return $ ElabTask severity $ Args pnArgs' kwArgs'
where (kwNames, kwExprs) = unzip kwArgs
genItemMapper = traverseGenItemExprsM exprMapper genItemMapper = traverseGenItemExprsM exprMapper
......
...@@ -14,6 +14,7 @@ module Language.SystemVerilog.AST.ModuleItem ...@@ -14,6 +14,7 @@ module Language.SystemVerilog.AST.ModuleItem
, NInputGateKW (..) , NInputGateKW (..)
, NOutputGateKW (..) , NOutputGateKW (..)
, AssignOption (..) , AssignOption (..)
, Severity (..)
) where ) where
import Data.List (intercalate) import Data.List (intercalate)
...@@ -24,7 +25,7 @@ import Language.SystemVerilog.AST.ShowHelp ...@@ -24,7 +25,7 @@ import Language.SystemVerilog.AST.ShowHelp
import Language.SystemVerilog.AST.Attr (Attr) import Language.SystemVerilog.AST.Attr (Attr)
import Language.SystemVerilog.AST.Decl (Direction) import Language.SystemVerilog.AST.Decl (Direction)
import Language.SystemVerilog.AST.Description (PackageItem) import Language.SystemVerilog.AST.Description (PackageItem)
import Language.SystemVerilog.AST.Expr (Expr(Nil), pattern Ident, Range, showRanges, ParamBinding, showParams) import Language.SystemVerilog.AST.Expr (Expr(Nil), pattern Ident, Range, showRanges, ParamBinding, showParams, Args)
import Language.SystemVerilog.AST.GenItem (GenItem) import Language.SystemVerilog.AST.GenItem (GenItem)
import Language.SystemVerilog.AST.LHS (LHS) import Language.SystemVerilog.AST.LHS (LHS)
import Language.SystemVerilog.AST.Stmt (Stmt, AssertionItem, Timing(Delay)) import Language.SystemVerilog.AST.Stmt (Stmt, AssertionItem, Timing(Delay))
...@@ -41,6 +42,7 @@ data ModuleItem ...@@ -41,6 +42,7 @@ data ModuleItem
| Modport Identifier [ModportDecl] | Modport Identifier [ModportDecl]
| Initial Stmt | Initial Stmt
| Final Stmt | Final Stmt
| ElabTask Severity Args
| MIPackageItem PackageItem | MIPackageItem PackageItem
| NInputGate NInputGateKW Expr Identifier LHS [Expr] | NInputGate NInputGateKW Expr Identifier LHS [Expr]
| NOutputGate NOutputGateKW Expr Identifier [LHS] Expr | NOutputGate NOutputGateKW Expr Identifier [LHS] Expr
...@@ -58,6 +60,7 @@ instance Show ModuleItem where ...@@ -58,6 +60,7 @@ instance Show ModuleItem where
show (Modport x l) = printf "modport %s(\n%s\n);" x (indent $ intercalate ",\n" $ map showModportDecl l) show (Modport x l) = printf "modport %s(\n%s\n);" x (indent $ intercalate ",\n" $ map showModportDecl l)
show (Initial s ) = printf "initial %s" (show s) show (Initial s ) = printf "initial %s" (show s)
show (Final s ) = printf "final %s" (show s) show (Final s ) = printf "final %s" (show s)
show (ElabTask s a) = printf "%s%s;" (show s) (show a)
show (NInputGate kw d x lhs exprs) = show (NInputGate kw d x lhs exprs) =
showGate kw d x $ show lhs : map show exprs showGate kw d x $ show lhs : map show exprs
show (NOutputGate kw d x lhss expr) = show (NOutputGate kw d x lhss expr) =
...@@ -148,3 +151,16 @@ instance Show AssignOption where ...@@ -148,3 +151,16 @@ instance Show AssignOption where
show AssignOptionNone = "" show AssignOptionNone = ""
show (AssignOptionDelay de) = printf "#(%s)" (show de) show (AssignOptionDelay de) = printf "#(%s)" (show de)
show (AssignOptionDrive s0 s1) = printf "(%s, %s)" (show s0) (show s1) show (AssignOptionDrive s0 s1) = printf "(%s, %s)" (show s0) (show s1)
data Severity
= SeverityInfo
| SeverityWarning
| SeverityError
| SeverityFatal
deriving Eq
instance Show Severity where
show SeverityInfo = "$info"
show SeverityWarning = "$warning"
show SeverityError = "$error"
show SeverityFatal = "$fatal"
...@@ -401,7 +401,6 @@ time { Token Lit_time _ _ } ...@@ -401,7 +401,6 @@ time { Token Lit_time _ _ }
-- operator precedences, from *lowest* to *highest* -- operator precedences, from *lowest* to *highest*
%nonassoc DefaultStrength %nonassoc DefaultStrength
%nonassoc DriveStrength ChargeStrength %nonassoc DriveStrength ChargeStrength
%nonassoc Asgn
%nonassoc NoElse %nonassoc NoElse
%nonassoc "else" %nonassoc "else"
%right "|->" "|=>" "#-#" "#=#" %right "|->" "|=>" "#-#" "#=#"
...@@ -630,17 +629,17 @@ Strength :: { Strength } ...@@ -630,17 +629,17 @@ Strength :: { Strength }
DeclTokens(delim) :: { [DeclToken] } DeclTokens(delim) :: { [DeclToken] }
: DeclTokensBase(DeclTokens(delim), delim) { $1 } : DeclTokensBase(DeclTokens(delim), delim) { $1 }
DeclTokensBase(repeat, delim) :: { [DeclToken] } DeclTokensBase(repeat, delim) :: { [DeclToken] }
: DeclToken delim { [$1] } : DeclToken DTDelim(delim) { [$1, $2] }
| DeclToken repeat { [$1] ++ $2 } | DeclToken repeat { [$1] ++ $2 }
| IdentifierP ParamBindings repeat { [uncurry DTIdent $1, DTParams (fst $1) $2] ++ $3 } | IdentifierP ParamBindings repeat { [uncurry DTIdent $1, DTParams (fst $1) $2] ++ $3 }
| DeclTokenAsgn "," repeat { [$1, DTComma (tokenPosition $2)] ++ $3 } | DeclTokenAsgn "," repeat { [$1, DTComma (tokenPosition $2)] ++ $3 }
| DeclTokenAsgn delim { [$1] } | DeclTokenAsgn DTDelim(delim) { [$1, $2] }
DeclToken :: { DeclToken } DeclToken :: { DeclToken }
: "," { DTComma $ tokenPosition $1 } : "," { DTComma $ tokenPosition $1 }
| "[" "]" { DTAutoDim $ tokenPosition $1 } | "[" "]" { DTAutoDim $ tokenPosition $1 }
| "const" { DTConst $ tokenPosition $1 } | "const" { DTConst $ tokenPosition $1 }
| "var" { DTVar $ tokenPosition $1 } | "var" { DTVar $ tokenPosition $1 }
| PartSelectP { uncurry DTRange $1 } | PartSelectP { uncurry (DTRange $ fst $1) (snd $1) }
| IdentifierP { uncurry DTIdent $1 } | IdentifierP { uncurry DTIdent $1 }
| DirectionP { uncurry DTDir $1 } | DirectionP { uncurry DTDir $1 }
| LHSConcatP { uncurry DTConcat $1 } | LHSConcatP { uncurry DTConcat $1 }
...@@ -655,21 +654,23 @@ DeclToken :: { DeclToken } ...@@ -655,21 +654,23 @@ DeclToken :: { DeclToken }
| "{" StreamOp Concat "}" { DTStream (tokenPosition $1) $2 (RawNum 1) (map toLHS $3) } | "{" StreamOp Concat "}" { DTStream (tokenPosition $1) $2 (RawNum 1) (map toLHS $3) }
| "type" "(" Expr ")" { uncurry DTType $ makeTypeOf $1 $3 } | "type" "(" Expr ")" { uncurry DTType $ makeTypeOf $1 $3 }
| IncOrDecOperatorP { DTAsgn (fst $1) (AsgnOp $ snd $1) Nothing (RawNum 1) } | IncOrDecOperatorP { DTAsgn (fst $1) (AsgnOp $ snd $1) Nothing (RawNum 1) }
| "<=" opt(DelayOrEvent) Expr %prec Asgn { DTAsgn (tokenPosition $1) AsgnOpNonBlocking $2 $3 }
| IdentifierP "::" Identifier { uncurry DTPSIdent $1 $3 } | IdentifierP "::" Identifier { uncurry DTPSIdent $1 $3 }
| IdentifierP ParamBindings "::" Identifier { uncurry DTCSIdent $1 $2 $4 } | IdentifierP ParamBindings "::" Identifier { uncurry DTCSIdent $1 $2 $4 }
DTDelim(delim) :: { DeclToken }
: delim { DTEnd (tokenPosition $1) (head $ tokenString $1) }
DeclTokenAsgn :: { DeclToken } DeclTokenAsgn :: { DeclToken }
: "=" opt(DelayOrEvent) Expr { DTAsgn (tokenPosition $1) AsgnOpEq $2 $3 } : "=" opt(DelayOrEvent) Expr { DTAsgn (tokenPosition $1) AsgnOpEq $2 $3 }
| AsgnBinOpP Expr { uncurry DTAsgn $1 Nothing $2 } | AsgnBinOpP Expr { uncurry DTAsgn $1 Nothing $2 }
| "<=" opt(DelayOrEvent) Expr { DTAsgn (tokenPosition $1) AsgnOpNonBlocking $2 $3 }
PortDeclTokens(delim) :: { [DeclToken] } PortDeclTokens(delim) :: { [DeclToken] }
: DeclTokensBase(PortDeclTokens(delim), delim) { $1 } : DeclTokensBase(PortDeclTokens(delim), delim) { $1 }
| GenericInterfaceDecl PortDeclTokens(delim) { $1 ++ $2} | GenericInterfaceDecl PortDeclTokens(delim) { $1 ++ $2}
| GenericInterfaceDecl delim { $1 } | GenericInterfaceDecl DTDelim(delim) { $1 ++ [$2] }
| AttributeInstanceP PortDeclTokens(delim) { uncurry DTAttr $1 : $2 } | AttributeInstanceP PortDeclTokens(delim) { uncurry DTAttr $1 : $2 }
ModuleDeclTokens(delim) :: { [DeclToken] } ModuleDeclTokens(delim) :: { [DeclToken] }
: DeclTokensBase(ModuleDeclTokens(delim), delim) { $1 } : DeclTokensBase(ModuleDeclTokens(delim), delim) { $1 }
| GenericInterfaceDecl ModuleDeclTokens(delim) { $1 ++ $2} | GenericInterfaceDecl ModuleDeclTokens(delim) { $1 ++ $2}
| GenericInterfaceDecl delim { $1 } | GenericInterfaceDecl DTDelim(delim) { $1 ++ [$2] }
GenericInterfaceDecl :: { [DeclToken] } GenericInterfaceDecl :: { [DeclToken] }
: "interface" IdentifierP { [DTType (tokenPosition $1) (\Unspecified -> InterfaceT "" ""), uncurry DTIdent $2] } : "interface" IdentifierP { [DTType (tokenPosition $1) (\Unspecified -> InterfaceT "" ""), uncurry DTIdent $2] }
......
module top;
if (1 == 0)
wire foo;
else
$info("foo");
endmodule
module top;
initial begin
integer x, y;
x = 0;
y = 3;
for (x += 1; x < y; x++)
$display("A x = %0d", x);
end
initial begin
integer x, y;
x = 0;
for (x += 1, y = 3; x < y; x++)
$display("B x = %0d", x);
end
initial begin
integer x, y;
x = 0;
for (y = 3, x += 1; x < y; x++)
$display("C x = %0d", x);
end
initial
for (integer x = 0, y = 3; x < y; x++)
$display("D x = %0d", x);
initial
for (integer x = 0, byte y = 3; x < y; x++)
$display("E x = %0d", x);
initial begin
integer x, y;
x = 0;
for (x++, y = 3; x < y; x++)
$display("F x = %0d", x);
end
initial begin
integer x, y;
x = 0;
for (y = 3, x++; x < y; x++)
$display("G x = %0d", x);
end
initial begin
integer x, y;
x = 0;
for (--x, y = 3; x < y; x++)
$display("H x = %0d", x);
end
initial begin
integer x, y;
x = 0;
for (y = 3, --x; x < y; x++)
$display("I x = %0d", x);
end
initial begin
integer x, y;
x = 0;
y = 2;
for (--y, ++y, y++, ++x, --x, --x; x < y; x++)
$display("J x = %0d", x);
end
endmodule
module top;
`define LOOP(ID, START) \
x = 0; \
for (x = START; x < 3; x = x + 1) \
$display(`"ID x = %0d`", x);
initial begin : blk
integer x;
`LOOP(A, 1)
`LOOP(B, 1)
`LOOP(C, 1)
`LOOP(D, 0)
`LOOP(E, 0)
`LOOP(F, 1)
`LOOP(G, 1)
`LOOP(H, -1)
`LOOP(I, -1)
`LOOP(J, -1)
end
endmodule
// pattern: auto_dim_int\.sv:3:15: Parse error: expected comma or end of declarations
module top;
integer x [] = 1;
endmodule
// pattern: block_start_1\.sv:4:9: Parse error: expected primary token or type
module top;
initial begin
,;
end
endmodule
// pattern: block_start_2\.sv:4:9: Parse error: expected primary token or type
module top;
initial begin
= 1;
end
endmodule
// pattern: block_start_3\.sv:4:9: Parse error: expected primary token or type
module top;
initial begin
P::Q = 1;
end
endmodule
// pattern: block_start_4\.sv:4:11: Parse error: unexpected statement token
module top;
initial begin
a , ;
end
endmodule
// pattern: decl_bare\.sv:3:5: Parse error: declaration missing type information
module top; module top;
a;
endmodule endmodule
// pattern: decl_missing_comma\.sv:3:15: Parse error: expected comma or end of declarations
module top;
integer a b;
endmodule
// pattern: decl_trailing_comma\.sv:3:16: Parse error: unexpected token in declaration
module top;
integer a, ;
endmodule
// pattern: elab_task_stray_after_args\.sv:3:12: Parse error: unexpected token after elaboration system task
module top;
$info(), ;
endmodule
// pattern: elab_task_stray_before_args\.sv:3:11: Parse error: unexpected token after elaboration system task
module top;
$info , ();
endmodule
// pattern: elab_task_stray_no_args\.sv:3:11: Parse error: unexpected token after elaboration system task
module top;
$info , ;
endmodule
// pattern: for loop declaration missing initialization // pattern: for_loop_decl_no_init\.sv:4:14: Parse error: for loop declaration of "x" is missing initialization
module top; module top;
initial initial
for (integer x; x < 3; x = x + 1) for (integer x; x < 3; x = x + 1)
......
// pattern: for_loop_init_bare\.sv:3:19: Parse error: expected assignment operator
module top;
initial for (a,; 1; a++) ;
endmodule
// pattern: for_loop_init_delay\.sv:4:20: Parse error: unexpected timing modifier in for loop initialization
module top;
integer x;
initial for (x = #1 1; 1; x++) ;
endmodule
// pattern: for_loop_init_nblk\.sv:4:20: Parse error: unexpected non-blocking assignment in for loop initialization
module top;
integer x;
initial for (x <= 1; 1; x++) ;
endmodule
// pattern: for_loop_init_stray\.sv:3:22: Parse error: expected ',' or ';'
module top;
initial for (a++ b++; 1; a++) ;
endmodule
// pattern: instantiation_extra_comma\.sv:3:18: Parse error: expected instantiation before delimiter // pattern: instantiation_extra_comma\.sv:3:18: Parse error: expected instantiation before ','
module top; module top;
example a(), , b(); example a(), , b();
endmodule endmodule
// pattern: instantiation_missing_ports\.sv:3:14: Parse error: expected port connections before delimiter // pattern: instantiation_missing_ports\.sv:3:14: Parse error: expected port connections before ','
module top; module top;
example a, c(); example a, c();
endmodule endmodule
// pattern: instantiation_trailing_comma\.sv:3:16: Parse error: unexpected end of instantiation list // pattern: instantiation_trailing_comma\.sv:3:18: Parse error: expected instantiation before ';'
module top; module top;
example a(), ; example a(), ;
endmodule endmodule
// pattern: port_list_incomplete\.sv:2:17: Parse error: expected identifier
module top(input);
endmodule
// pattern: run_on_decl_item.sv:3:16: Parse error: unexpected comma-separated declarations // pattern: run_on_decl_item\.sv:3:16: Parse error: unexpected token in declaration
module top; module top;
integer x, byte y; integer x, byte y;
endmodule endmodule
// pattern: run_on_decl_stmt.sv:4:20: Parse error: unexpected comma-separated declarations // pattern: run_on_decl_stmt\.sv:4:20: Parse error: unexpected token in declaration
module top; module top;
initial begin initial begin
integer x, byte y; integer x, byte y;
......
module top;
$info;
$info("%b", 1);
$warning;
$warning("%b", 2);
$error;
$error("%b", 3);
$fatal;
$fatal("%b", 4);
endmodule
#!/bin/bash
addTest() {
test=$1
eval "test_$test() { assertConverts $test.sv; }"
suite_addTest test_$test
}
source ../lib/functions.sh
source ../lib/discover.sh
. shunit2
module top;
trireg (small) x;
trireg (medium) y;
trireg (large) z;
endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment