2019-12-08 23:36:25 +01:00
|
|
|
{- sv2v
|
|
|
|
|
- Author: Zachary Snow <zach@zachjs.com>
|
|
|
|
|
-
|
2019-12-22 01:31:56 +01:00
|
|
|
- Conversion for `inside` expressions and cases
|
2019-12-08 23:36:25 +01:00
|
|
|
-
|
2020-06-17 01:40:46 +02:00
|
|
|
- The expressions are compared to each candidate using `==?`, the wildcard
|
|
|
|
|
- comparison. As required by the specification, the result of each comparison
|
|
|
|
|
- is combined using an OR reduction.
|
2019-12-08 23:36:25 +01:00
|
|
|
-
|
2019-12-22 01:31:56 +01:00
|
|
|
- `case ... inside` statements are converted to an equivalent if-else cascade.
|
|
|
|
|
-
|
2019-12-08 23:36:25 +01:00
|
|
|
- TODO: Add support for array value ranges.
|
2019-12-22 01:31:56 +01:00
|
|
|
- TODO: This conversion may cause an expression with side effects to be
|
|
|
|
|
- evaluated more than once.
|
2019-12-08 23:36:25 +01:00
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
module Convert.Inside (convert) where
|
|
|
|
|
|
|
|
|
|
import Convert.Traverse
|
|
|
|
|
import Language.SystemVerilog.AST
|
|
|
|
|
|
2020-11-27 22:09:16 +01:00
|
|
|
import Control.Monad.Writer
|
2019-12-22 01:31:56 +01:00
|
|
|
import Data.Maybe (fromMaybe)
|
|
|
|
|
|
2019-12-08 23:36:25 +01:00
|
|
|
convert :: [AST] -> [AST]
|
2019-12-22 01:31:56 +01:00
|
|
|
convert = map $ traverseDescriptions $ traverseModuleItems convertModuleItem
|
|
|
|
|
|
|
|
|
|
convertModuleItem :: ModuleItem -> ModuleItem
|
|
|
|
|
convertModuleItem item =
|
|
|
|
|
traverseExprs (traverseNestedExprs convertExpr) $
|
2021-07-16 00:05:47 +02:00
|
|
|
traverseStmts (traverseNestedStmts convertStmt) $
|
2019-12-22 01:31:56 +01:00
|
|
|
item
|
2019-12-08 23:36:25 +01:00
|
|
|
|
|
|
|
|
convertExpr :: Expr -> Expr
|
|
|
|
|
convertExpr (Inside expr valueRanges) =
|
|
|
|
|
if length checks == 1
|
|
|
|
|
then head checks
|
|
|
|
|
else UniOp RedOr $ Concat checks
|
|
|
|
|
where
|
|
|
|
|
checks = map toCheck valueRanges
|
2021-02-17 22:57:15 +01:00
|
|
|
toCheck :: Expr -> Expr
|
|
|
|
|
toCheck (Range Nil NonIndexed (lo, hi)) =
|
2019-12-08 23:36:25 +01:00
|
|
|
BinOp LogAnd
|
|
|
|
|
(BinOp Le lo expr)
|
|
|
|
|
(BinOp Ge hi expr)
|
2021-02-17 22:57:15 +01:00
|
|
|
toCheck pattern =
|
|
|
|
|
BinOp WEq expr pattern
|
2019-12-08 23:36:25 +01:00
|
|
|
convertExpr other = other
|
2019-12-22 01:31:56 +01:00
|
|
|
|
|
|
|
|
convertStmt :: Stmt -> Stmt
|
2021-02-17 19:26:13 +01:00
|
|
|
convertStmt (Case u CaseInside expr items) =
|
|
|
|
|
if hasSideEffects expr then
|
2020-11-27 22:09:16 +01:00
|
|
|
Block Seq "" [decl] [stmt]
|
2019-12-22 01:31:56 +01:00
|
|
|
else
|
|
|
|
|
foldr ($) defaultStmt $
|
|
|
|
|
map (uncurry $ If NoCheck) $
|
|
|
|
|
zip comps stmts
|
|
|
|
|
where
|
2020-11-27 22:09:16 +01:00
|
|
|
-- evaluate expressions with side effects once
|
|
|
|
|
tmp = "sv2v_temp_" ++ shortHash expr
|
|
|
|
|
decl = Variable Local (TypeOf expr) tmp [] expr
|
2021-02-17 19:26:13 +01:00
|
|
|
stmt = convertStmt (Case u CaseInside (Ident tmp) items)
|
2020-11-27 22:09:16 +01:00
|
|
|
-- underlying inside case elaboration
|
2019-12-22 01:31:56 +01:00
|
|
|
itemsNonDefault = filter (not . null . fst) items
|
2021-02-17 22:57:15 +01:00
|
|
|
comps = map (Inside expr . fst) itemsNonDefault
|
2019-12-22 01:31:56 +01:00
|
|
|
stmts = map snd itemsNonDefault
|
|
|
|
|
defaultStmt = fromMaybe Null (lookup [] items)
|
|
|
|
|
convertStmt other = other
|
2020-11-27 22:09:16 +01:00
|
|
|
|
|
|
|
|
hasSideEffects :: Expr -> Bool
|
|
|
|
|
hasSideEffects expr =
|
|
|
|
|
getAny $ execWriter $ collectNestedExprsM write expr
|
|
|
|
|
where
|
|
|
|
|
write :: Expr -> Writer Any ()
|
|
|
|
|
write Call{} = tell $ Any True
|
|
|
|
|
write _ = return ()
|