Commit 7ea5b60d by Zachary Snow

support for inside case statements

parent ba79b17b
{- sv2v
- 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
- 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
- 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: This conversion may cause an expression with side effects to be
- evaluated more than once.
-}
module Convert.Inside (convert) where
......@@ -16,13 +20,20 @@ module Convert.Inside (convert) where
import Convert.Traverse
import Language.SystemVerilog.AST
import Data.Maybe (fromMaybe)
convert :: [AST] -> [AST]
convert =
map $
traverseDescriptions $ traverseModuleItems $
traverseExprs $ traverseNestedExprs convertExpr
convert = map $ traverseDescriptions $ traverseModuleItems convertModuleItem
convertModuleItem :: ModuleItem -> ModuleItem
convertModuleItem item =
traverseExprs (traverseNestedExprs convertExpr) $
traverseStmts convertStmt $
item
convertExpr :: Expr -> Expr
convertExpr (Inside Nil valueRanges) =
Inside Nil valueRanges
convertExpr (Inside expr valueRanges) =
if length checks == 1
then head checks
......@@ -44,3 +55,27 @@ convertExpr (Inside expr valueRanges) =
(BinOp Le lo expr)
(BinOp Ge hi expr)
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
, DimFn (..)
, showAssignment
, showRanges
, showExprOrRange
, simplify
, rangeSize
, endianCondExpr
......@@ -85,9 +86,6 @@ instance Show Expr where
show (Inside e l ) = printf "(%s inside { %s })" (show e) (intercalate ", " strs)
where
strs = map showExprOrRange l
showExprOrRange :: ExprOrRange -> String
showExprOrRange (Left x) = show x
showExprOrRange (Right x) = show x
show (Pattern l ) =
printf "'{\n%s\n}" (indent $ intercalate ",\n" $ map showPatternItem l)
where
......@@ -159,6 +157,10 @@ showRanges l = " " ++ (concatMap showRange l)
showRange :: Range -> String
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 p n = if p >= n then 0 else 1 + clog2Help (p*2) n
clog2 :: Int -> Int
......
......@@ -28,7 +28,7 @@ import Text.Printf (printf)
import Language.SystemVerilog.AST.ShowHelp (commas, indent, unlines', showPad)
import Language.SystemVerilog.AST.Attr (Attr)
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.Op (AsgnOp(AsgnOpEq))
import Language.SystemVerilog.AST.Type (Identifier)
......@@ -132,7 +132,11 @@ showShortBranch stmt = showBranch stmt
showCase :: Case -> String
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
= CaseN
......
......@@ -1046,17 +1046,13 @@ CaseKW :: { CaseKW }
| "casez" { CaseZ }
Cases :: { [Case] }
: {- empty -} { [] }
| Case Cases { $1 : $2 }
| CaseDefault CasesNoDefault { ([], $1) : $2 }
CasesNoDefault :: { [Case] }
: {- empty -} { [] }
| CasesNoDefault Case { $1 ++ [$2] }
Case :: { Case }
: Exprs ":" Stmt { ($1, $3) }
CaseDefault :: { Stmt }
: "default" opt(":") Stmt { $3 }
: opt("inside") InsideCases { validateCases $1 $2 }
InsideCases :: { [([ExprOrRange], Stmt)] }
: InsideCase { [$1] }
| InsideCases InsideCase { $1 ++ [$2] }
InsideCase :: { ([ExprOrRange], Stmt) }
: OpenRangeList ":" Stmt { ($1, $3) }
| "default" opt(":") Stmt { ([], $3) }
Number :: { String }
: number { tokenString $1 }
......@@ -1223,17 +1219,11 @@ GenBlock :: { (Identifier, [GenItem]) }
: "begin" StrTag GenItems "end" StrTag { (combineTags $2 $5, $3) }
GenCases :: { [GenCase] }
: {- empty -} { [] }
| GenCase GenCases { $1 : $2 }
| GenCaseDefault GenCasesNoDefault { ([], $1) : $2 }
GenCasesNoDefault :: { [GenCase] }
: {- empty -} { [] }
| GenCasesNoDefault GenCase { $1 ++ [$2] }
: GenCase { [$1] }
| GenCases GenCase { validateGenCases $ $1 ++ [$2] }
GenCase :: { GenCase }
: Exprs ":" GenItemOrNull { ($1, $3) }
GenCaseDefault :: { GenItem }
: "default" opt(":") GenItemOrNull { $3 }
: Exprs ":" GenItemOrNull { ($1, $3) }
| "default" opt(":") GenItemOrNull { ([], $3) }
GenvarInitialization :: { (Bool, Identifier, Expr) }
: "genvar" Identifier "=" Expr { (True , $2, $4) }
......@@ -1335,4 +1325,34 @@ 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
then items
else error $ "multiple default generate cases: " ++ show items
where
(exprs, _) = unzip items
}
......@@ -46,4 +46,18 @@ module top;
$display("test2(%02d) = %b", i, test2(i));
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
......@@ -51,4 +51,19 @@ module top;
$display("test2(%02d) = %b", i, test2(i));
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
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