Commit 0d095e6a by Zachary Snow

updated case inside representation

parent 2d7dc00b
......@@ -32,8 +32,6 @@ convertModuleItem item =
item
convertExpr :: Expr -> Expr
convertExpr (Inside Nil valueRanges) =
Inside Nil valueRanges
convertExpr (Inside expr valueRanges) =
if length checks == 1
then head checks
......@@ -50,31 +48,25 @@ convertExpr (Inside expr valueRanges) =
convertExpr other = other
convertStmt :: Stmt -> Stmt
convertStmt (Case u kw expr items) =
if not $ any isSpecialInside exprs then
Case u kw expr items
else if kw /= CaseN then
error $ "cannot use inside with " ++ show kw
else if hasSideEffects expr then
convertStmt (Case u CaseInside expr items) =
if hasSideEffects expr then
Block Seq "" [decl] [stmt]
else
foldr ($) defaultStmt $
map (uncurry $ If NoCheck) $
zip comps stmts
where
exprs = map fst items
-- evaluate expressions with side effects once
tmp = "sv2v_temp_" ++ shortHash expr
decl = Variable Local (TypeOf expr) tmp [] expr
stmt = convertStmt (Case u kw (Ident tmp) items)
stmt = convertStmt (Case u CaseInside (Ident tmp) items)
-- underlying inside case elaboration
itemsNonDefault = filter (not . null . fst) items
isSpecialInside :: [Expr] -> Bool
isSpecialInside [Inside Nil _] = True
isSpecialInside _ = False
makeComp :: [Expr] -> Expr
makeComp [Inside Nil ovr] = Inside expr ovr
makeComp _ = error "internal invariant violated"
makeComp = Inside expr . map unwrap
unwrap :: Expr -> ExprOrRange
unwrap (Range Nil NonIndexed r) = Right r
unwrap e = Left e
comps = map (makeComp . fst) itemsNonDefault
stmts = map snd itemsNonDefault
defaultStmt = fromMaybe Null (lookup [] items)
......
......@@ -28,7 +28,7 @@ import Text.Printf (printf)
import Language.SystemVerilog.AST.ShowHelp (commas, indent, unlines', showPad, showBlock)
import Language.SystemVerilog.AST.Attr (Attr)
import Language.SystemVerilog.AST.Decl (Decl)
import Language.SystemVerilog.AST.Expr (Expr(Inside, Nil), Args(..), showExprOrRange)
import Language.SystemVerilog.AST.Expr (Expr(Nil), Args(..))
import Language.SystemVerilog.AST.LHS (LHS)
import Language.SystemVerilog.AST.Op (AsgnOp(AsgnOpEq))
import Language.SystemVerilog.AST.Type (Identifier)
......@@ -65,8 +65,11 @@ instance Show Stmt where
header = if null name then "" else " : " ++ name
body = showBlock decls stmts
show (Case u kw e cs) =
printf "%s%s (%s)\n%s\nendcase" (showPad u) (show kw) (show e) bodyStr
where bodyStr = indent $ unlines' $ map showCase cs
printf "%s%s (%s)%s\n%s\nendcase" (showPad u) (show kw) (show e)
insideStr bodyStr
where
insideStr = if kw == CaseInside then " inside" else ""
bodyStr = indent $ unlines' $ map showCase cs
show (For inits cond assigns stmt) =
printf "for (%s; %s; %s)\n%s"
(showInits inits)
......@@ -140,19 +143,20 @@ showCase (a, b) = printf "%s:%s" exprStr (showShortBranch b)
where
exprStr = case a of
[] -> "default"
[Inside Nil c] -> commas $ map showExprOrRange c
_ -> commas $ map show a
data CaseKW
= CaseN
| CaseZ
| CaseX
| CaseInside
deriving Eq
instance Show CaseKW where
show CaseN = "case"
show CaseZ = "casez"
show CaseX = "casex"
show CaseInside = "case"
type Case = ([Expr], Stmt)
......
......@@ -1002,7 +1002,7 @@ StmtNonBlock :: { Stmt }
| Unique "if" "(" Expr ")" Stmt "else" Stmt { If $1 $4 $6 $8 }
| Unique "if" "(" Expr ")" Stmt %prec NoElse { If $1 $4 $6 Null }
| "for" "(" ForInit ForCond ForStep ")" Stmt { For $3 $4 $5 $7 }
| Unique CaseKW "(" Expr ")" Cases "endcase" { Case $1 $2 $4 $6 }
| CaseStmt { $1 }
| TimingControl Stmt { Timing $1 $2 }
| "return" ExprOrNil ";" { Return $2 }
| "break" ";" { Break }
......@@ -1018,6 +1018,10 @@ StmtNonBlock :: { Stmt }
| ProceduralAssertionStatement { Assertion $1 }
| "void" "'" "(" Expr CallArgs ")" ";" { Subroutine $4 $5 }
CaseStmt :: { Stmt }
: Unique CaseKW "(" Expr ")" Cases "endcase" { Case $1 $2 $4 $ validateCases $5 $6 }
| Unique CaseKW "(" Expr ")" "inside" InsideCases "endcase" { Case $1 (caseInsideKW $3 $2) $4 $ validateCases $5 $7 }
BlockKWPar :: { BlockKW }
: "fork" { Par }
BlockKWSeq :: { BlockKW }
......@@ -1127,12 +1131,16 @@ CaseKW :: { CaseKW }
| "casez" { CaseZ }
Cases :: { [Case] }
: opt("inside") InsideCases { validateCases $1 $2 }
InsideCases :: { [([ExprOrRange], Stmt)] }
: Case { [$1] }
| Case Cases { $1 : $2 }
Case :: { Case }
: Exprs ":" Stmt { ($1, $3) }
| "default" opt(":") Stmt { ([], $3) }
InsideCases :: { [Case] }
: InsideCase { [$1] }
| InsideCases InsideCase { $1 ++ [$2] }
InsideCase :: { ([ExprOrRange], Stmt) }
: OpenRangeList ":" Stmt { ($1, $3) }
| InsideCase InsideCases { $1 : $2 }
InsideCase :: { Case }
: OpenRangeList ":" Stmt { (map rangeAsExpr $1, $3) }
| "default" opt(":") Stmt { ([], $3) }
Real :: { String }
......@@ -1299,7 +1307,7 @@ GenItem :: { GenItem }
ConditionalGenerateConstruct :: { GenItem }
: "if" "(" Expr ")" GenItemOrNull "else" GenItemOrNull { GenIf $3 $5 $7 }
| "if" "(" Expr ")" GenItemOrNull %prec NoElse { GenIf $3 $5 GenNull }
| "case" "(" Expr ")" GenCases "endcase" { GenCase $3 $5 }
| "case" "(" Expr ")" GenCases "endcase" { GenCase $3 $ validateCases $4 $5 }
LoopGenerateConstruct :: { GenItem }
: "for" "(" GenvarInitialization ";" Expr ";" GenvarIteration ")" GenItem { $3 $5 $7 $9 }
......@@ -1308,7 +1316,7 @@ GenBlock :: { (Identifier, [GenItem]) }
GenCases :: { [GenCase] }
: GenCase { [$1] }
| GenCases GenCase { validateGenCases $ $1 ++ [$2] }
| GenCase GenCases { $1 : $2 }
GenCase :: { GenCase }
: Exprs ":" GenItemOrNull { ($1, $3) }
| "default" opt(":") GenItemOrNull { ([], $3) }
......@@ -1444,34 +1452,21 @@ fieldDecl t (x, rs2) =
(tf $ rs2 ++ rs1, x)
where (tf, rs1) = typeRanges t
validateCases :: Maybe Token -> [([ExprOrRange], Stmt)] -> [Case]
validateCases Nothing items =
if length (filter null exprs) <= 1
then zip exprs' stmts
else error $ "multiple default cases: " ++ show items
where
(exprs, stmts) = unzip items
exprs' = map (map unwrap) exprs
unwrap (Left expr) = expr
unwrap (Right range) =
error $ "illegal use of a range (" ++ show range
++ ") in a non-inside case"
validateCases (Just _) items =
if length (filter null sets) <= 1
then zip sets' stmts
else error $ "multiple default cases: " ++ show items
where
(sets, stmts) = unzip items
sets' = map unwrap sets
unwrap [] = []
unwrap ls = [Inside Nil ls]
validateGenCases :: [GenCase] -> [GenCase]
validateGenCases items =
if length (filter null exprs) <= 1
validateCases :: Token -> [([Expr], a)] -> [([Expr], a)]
validateCases tok items =
if length (filter (null . fst) items) <= 1
then items
else error $ "multiple default generate cases: " ++ show items
where
(exprs, _) = unzip items
else error $ show (tokenPosition tok)
++ ": Parse error: case has multiple defaults"
caseInsideKW :: Token -> CaseKW -> CaseKW
caseInsideKW _ CaseN = CaseInside
caseInsideKW tok kw =
error $ show (tokenPosition tok)
++ ": Parse error: cannot use inside with " ++ show kw
rangeAsExpr :: ExprOrRange -> Expr
rangeAsExpr (Left e) = e
rangeAsExpr (Right r) = Range Nil NonIndexed r
}
// pattern: case has multiple defaults
module top;
initial
case (0)
0: $display("FOO");
1: $display("BAR");
default: $display("A");
default: $display("B");
endcase
endmodule
// pattern: cannot use inside with casex
module top;
initial
casex (0) inside
0: $display("FOO");
1: $display("BAR");
endcase
endmodule
// pattern: cannot use inside with casez
module top;
initial
casez (0) inside
0: $display("FOO");
1: $display("BAR");
endcase
endmodule
// pattern: case has multiple defaults
module top;
case (0)
0: wire w;
1: wire x;
default: wire y;
default: wire z;
endcase
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