sv2v/Convert/CaseKW.hs

61 lines
1.9 KiB
Haskell

{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for `casez` and `casex`
-
- Note that this conversion does not completely replicate the behavior of
- `casex` and `casez` in cases where that case expression itself (rather than
- just the case item patterns) contains wildcard values. This is apparently
- rarely ever intentially done.
-}
module Convert.CaseKW (convert) where
import Convert.Template.Stmt (stmtConverter)
import Language.SystemVerilog.AST
convert :: AST -> AST
convert = stmtConverter convertStmt
-- Conversions:
-- `casez` -> `case` with wildcards (?, z) expanded
-- `casex` -> `case` with wildcards (?, z, x) expanded
-- to be either 0 or 1
wildcards :: CaseKW -> [Char]
wildcards CaseN = [] -- CaseN == `case`
wildcards CaseZ = ['?', 'z', 'Z']
wildcards CaseX = ['?', 'z', 'Z', 'x', 'X']
possibilities :: [Char]
possibilities = ['0', '1']
explodeBy :: [Char] -> String -> [String]
explodeBy _ "" = [""]
explodeBy wilds (x : xs) =
if elem x wilds
then concat $ map (\c -> map (c :) prev) possibilities
else map (x :) prev
where prev = explodeBy wilds xs
expandExpr :: [Char] -> Expr -> [Expr]
expandExpr wilds (Number s) = map Number $ explodeBy wilds s
expandExpr [] other = [other]
-- TODO: Hopefully they only give us constant expressions...
expandExpr _ other = error $ "CaseKW conversione encountered case that was not a number, which is dubious..." ++ (show other)
-- Note that we don't have to convert the statements within the cases, as the
-- conversion template takes care of that for us.
convertStmt :: Stmt -> Stmt
convertStmt (Case kw expr cases def) =
Case CaseN expr cases' def
where
wilds = wildcards kw
cases' = map convertCase cases
convertCase :: Case -> Case
convertCase (exprs, stmt) = (exprs', stmt)
where exprs' = concat $ map (expandExpr wilds) exprs
convertStmt other = other