Commit 7ea5b60d by Zachary Snow

support for inside case statements

parent ba79b17b
{- sv2v {- sv2v
- Author: Zachary Snow <zach@zachjs.com> - Author: Zachary Snow <zach@zachjs.com>
- -
- Conversion for `inside` expressions - Conversion for `inside` expressions and cases
- -
- The expressions are compared to each candidate using the wildcard comparison - The expressions are compared to each candidate using the wildcard comparison
- operator. Note that if expression has any Xs or Zs that are not wildcarded in - operator. Note that if expression has any Xs or Zs that are not wildcarded in
- the candidate, the results is `1'bx`. As required by the specification, the - the candidate, the results is `1'bx`. As required by the specification, the
- result of each comparison is combined using an OR reduction. - result of each comparison is combined using an OR reduction.
- -
- `case ... inside` statements are converted to an equivalent if-else cascade.
-
- TODO: Add support for array value ranges. - TODO: Add support for array value ranges.
- TODO: This conversion may cause an expression with side effects to be
- evaluated more than once.
-} -}
module Convert.Inside (convert) where module Convert.Inside (convert) where
...@@ -16,13 +20,20 @@ module Convert.Inside (convert) where ...@@ -16,13 +20,20 @@ module Convert.Inside (convert) where
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
import Data.Maybe (fromMaybe)
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert = convert = map $ traverseDescriptions $ traverseModuleItems convertModuleItem
map $
traverseDescriptions $ traverseModuleItems $ convertModuleItem :: ModuleItem -> ModuleItem
traverseExprs $ traverseNestedExprs convertExpr convertModuleItem item =
traverseExprs (traverseNestedExprs convertExpr) $
traverseStmts convertStmt $
item
convertExpr :: Expr -> Expr convertExpr :: Expr -> Expr
convertExpr (Inside Nil valueRanges) =
Inside Nil valueRanges
convertExpr (Inside expr valueRanges) = convertExpr (Inside expr valueRanges) =
if length checks == 1 if length checks == 1
then head checks then head checks
...@@ -44,3 +55,27 @@ convertExpr (Inside expr valueRanges) = ...@@ -44,3 +55,27 @@ convertExpr (Inside expr valueRanges) =
(BinOp Le lo expr) (BinOp Le lo expr)
(BinOp Ge hi expr) (BinOp Ge hi expr)
convertExpr other = other 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
foldr ($) defaultStmt $
map (uncurry $ If NoCheck) $
zip comps stmts
where
exprs = map fst items
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"
comps = map (makeComp . fst) itemsNonDefault
stmts = map snd itemsNonDefault
defaultStmt = fromMaybe Null (lookup [] items)
convertStmt other = other
...@@ -16,6 +16,7 @@ module Language.SystemVerilog.AST.Expr ...@@ -16,6 +16,7 @@ module Language.SystemVerilog.AST.Expr
, DimFn (..) , DimFn (..)
, showAssignment , showAssignment
, showRanges , showRanges
, showExprOrRange
, simplify , simplify
, rangeSize , rangeSize
, endianCondExpr , endianCondExpr
...@@ -85,9 +86,6 @@ instance Show Expr where ...@@ -85,9 +86,6 @@ instance Show Expr where
show (Inside e l ) = printf "(%s inside { %s })" (show e) (intercalate ", " strs) show (Inside e l ) = printf "(%s inside { %s })" (show e) (intercalate ", " strs)
where where
strs = map showExprOrRange l strs = map showExprOrRange l
showExprOrRange :: ExprOrRange -> String
showExprOrRange (Left x) = show x
showExprOrRange (Right x) = show x
show (Pattern l ) = show (Pattern l ) =
printf "'{\n%s\n}" (indent $ intercalate ",\n" $ map showPatternItem l) printf "'{\n%s\n}" (indent $ intercalate ",\n" $ map showPatternItem l)
where where
...@@ -159,6 +157,10 @@ showRanges l = " " ++ (concatMap showRange l) ...@@ -159,6 +157,10 @@ showRanges l = " " ++ (concatMap showRange l)
showRange :: Range -> String showRange :: Range -> String
showRange (h, l) = printf "[%s:%s]" (show h) (show l) showRange (h, l) = printf "[%s:%s]" (show h) (show l)
showExprOrRange :: ExprOrRange -> String
showExprOrRange (Left x) = show x
showExprOrRange (Right x) = show x
clog2Help :: Int -> Int -> Int clog2Help :: Int -> Int -> Int
clog2Help p n = if p >= n then 0 else 1 + clog2Help (p*2) n clog2Help p n = if p >= n then 0 else 1 + clog2Help (p*2) n
clog2 :: Int -> Int clog2 :: Int -> Int
......
...@@ -28,7 +28,7 @@ import Text.Printf (printf) ...@@ -28,7 +28,7 @@ import Text.Printf (printf)
import Language.SystemVerilog.AST.ShowHelp (commas, indent, unlines', showPad) import Language.SystemVerilog.AST.ShowHelp (commas, indent, unlines', showPad)
import Language.SystemVerilog.AST.Attr (Attr) import Language.SystemVerilog.AST.Attr (Attr)
import Language.SystemVerilog.AST.Decl (Decl) import Language.SystemVerilog.AST.Decl (Decl)
import Language.SystemVerilog.AST.Expr (Expr, Args(..)) import Language.SystemVerilog.AST.Expr (Expr(Inside, Nil), Args(..), showExprOrRange)
import Language.SystemVerilog.AST.LHS (LHS) import Language.SystemVerilog.AST.LHS (LHS)
import Language.SystemVerilog.AST.Op (AsgnOp(AsgnOpEq)) import Language.SystemVerilog.AST.Op (AsgnOp(AsgnOpEq))
import Language.SystemVerilog.AST.Type (Identifier) import Language.SystemVerilog.AST.Type (Identifier)
...@@ -132,7 +132,11 @@ showShortBranch stmt = showBranch stmt ...@@ -132,7 +132,11 @@ showShortBranch stmt = showBranch stmt
showCase :: Case -> String showCase :: Case -> String
showCase (a, b) = printf "%s:%s" exprStr (showShortBranch b) showCase (a, b) = printf "%s:%s" exprStr (showShortBranch b)
where exprStr = if null a then "default" else commas $ map show a where
exprStr = case a of
[] -> "default"
[Inside Nil c] -> commas $ map showExprOrRange c
_ -> commas $ map show a
data CaseKW data CaseKW
= CaseN = CaseN
......
...@@ -1046,17 +1046,13 @@ CaseKW :: { CaseKW } ...@@ -1046,17 +1046,13 @@ CaseKW :: { CaseKW }
| "casez" { CaseZ } | "casez" { CaseZ }
Cases :: { [Case] } Cases :: { [Case] }
: {- empty -} { [] } : opt("inside") InsideCases { validateCases $1 $2 }
| Case Cases { $1 : $2 } InsideCases :: { [([ExprOrRange], Stmt)] }
| CaseDefault CasesNoDefault { ([], $1) : $2 } : InsideCase { [$1] }
CasesNoDefault :: { [Case] } | InsideCases InsideCase { $1 ++ [$2] }
: {- empty -} { [] } InsideCase :: { ([ExprOrRange], Stmt) }
| CasesNoDefault Case { $1 ++ [$2] } : OpenRangeList ":" Stmt { ($1, $3) }
| "default" opt(":") Stmt { ([], $3) }
Case :: { Case }
: Exprs ":" Stmt { ($1, $3) }
CaseDefault :: { Stmt }
: "default" opt(":") Stmt { $3 }
Number :: { String } Number :: { String }
: number { tokenString $1 } : number { tokenString $1 }
...@@ -1223,17 +1219,11 @@ GenBlock :: { (Identifier, [GenItem]) } ...@@ -1223,17 +1219,11 @@ GenBlock :: { (Identifier, [GenItem]) }
: "begin" StrTag GenItems "end" StrTag { (combineTags $2 $5, $3) } : "begin" StrTag GenItems "end" StrTag { (combineTags $2 $5, $3) }
GenCases :: { [GenCase] } GenCases :: { [GenCase] }
: {- empty -} { [] } : GenCase { [$1] }
| GenCase GenCases { $1 : $2 } | GenCases GenCase { validateGenCases $ $1 ++ [$2] }
| GenCaseDefault GenCasesNoDefault { ([], $1) : $2 }
GenCasesNoDefault :: { [GenCase] }
: {- empty -} { [] }
| GenCasesNoDefault GenCase { $1 ++ [$2] }
GenCase :: { GenCase } GenCase :: { GenCase }
: Exprs ":" GenItemOrNull { ($1, $3) } : Exprs ":" GenItemOrNull { ($1, $3) }
GenCaseDefault :: { GenItem } | "default" opt(":") GenItemOrNull { ([], $3) }
: "default" opt(":") GenItemOrNull { $3 }
GenvarInitialization :: { (Bool, Identifier, Expr) } GenvarInitialization :: { (Bool, Identifier, Expr) }
: "genvar" Identifier "=" Expr { (True , $2, $4) } : "genvar" Identifier "=" Expr { (True , $2, $4) }
...@@ -1335,4 +1325,34 @@ fieldDecl t (x, rs2) = ...@@ -1335,4 +1325,34 @@ fieldDecl t (x, rs2) =
(tf $ rs2 ++ rs1, x) (tf $ rs2 ++ rs1, x)
where (tf, rs1) = typeRanges t 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
then items
else error $ "multiple default generate cases: " ++ show items
where
(exprs, _) = unzip items
} }
...@@ -46,4 +46,18 @@ module top; ...@@ -46,4 +46,18 @@ module top;
$display("test2(%02d) = %b", i, test2(i)); $display("test2(%02d) = %b", i, test2(i));
end end
function integer test3;
input integer inp;
case (inp) inside
[16:23]: return 1;
[32:47]: return 2;
default: return 0;
0, [60:61], 4: return 3;
endcase
endfunction
initial begin
for (integer i = 0; i < 64; ++i)
$display("test3(%02d) = %b", i, test3(i));
end
endmodule endmodule
...@@ -51,4 +51,19 @@ module top; ...@@ -51,4 +51,19 @@ module top;
$display("test2(%02d) = %b", i, test2(i)); $display("test2(%02d) = %b", i, test2(i));
end end
function [0:31] test3;
input integer inp;
begin
if (16 <= inp && inp <= 23) test3 = 1;
else if (32 <= inp && inp <= 47) test3 = 2;
else if (inp == 0 || (60 <= inp && inp <= 61) || inp == 4) test3 = 3;
else test3 = 0;
end
endfunction
initial begin : block3
integer i;
for (i = 0; i < 64; ++i)
$display("test3(%02d) = %b", i, test3(i));
end
endmodule 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