Wildcard.hs 3.41 KB
Newer Older
1 2 3 4 5 6
{- sv2v
 - Author: Zachary Snow <zach@zachjs.com>
 -
 - Conversion for `==?` and `!=?`
 -
 - `a ==? b` is defined as the bitwise comparison of `a` and `b`, where X and Z
7 8 9 10 11 12 13 14 15
 - values in `b` (but not those in `a`) are used as wildcards. This conversion
 - relies on the fact that works because any value xor'ed with X or Z becomes X.
 -
 - Procedure for `A ==? B`:
 - 1. If there is any bit in A that doesn't match a non-wildcarded bit in B,
 -    then the result is always `1'b0`.
 - 2. If there is any X or Z in A that is not wildcarded in B, then the result
 -    is `1'bx`.
 - 3. Otherwise, the result is `1'b1`.
16 17
 -
 - `!=?` is simply converted as the logical negation of `==?`, which is
18 19 20 21 22 23
 -
 - The conversion for `inside` produces wildcard equality comparisons as per the
 - SystemVerilog specification. However, many usages of `inside` don't depend on
 - the wildcard behavior. To avoid generating needlessly complex output, this
 - conversion use the standard equality operator if the pattern obviously
 - contains no wildcard bits.
24 25 26 27
 -}

module Convert.Wildcard (convert) where

28
import Data.Bits ((.|.))
29

30
import Convert.Scoper
31 32 33 34
import Convert.Traverse
import Language.SystemVerilog.AST

convert :: [AST] -> [AST]
35 36 37 38
convert = map $ traverseDescriptions convertDescription

convertDescription :: Description -> Description
convertDescription =
39
    partScoper traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM
40

41
traverseDeclM :: Decl -> Scoper Number Decl
42 43
traverseDeclM decl = do
    case decl of
44
        Param Localparam _ x (Number n) -> insertElem x n
45 46 47 48 49 50
        _ -> return ()
    let mi = MIPackageItem $ Decl decl
    mi' <- traverseModuleItemM mi
    let MIPackageItem (Decl decl') = mi'
    return decl'

51
traverseModuleItemM :: ModuleItem -> Scoper Number ModuleItem
52 53
traverseModuleItemM = traverseExprsM traverseExprM

54 55 56 57
traverseGenItemM :: GenItem -> Scoper Number GenItem
traverseGenItemM = traverseGenItemExprsM traverseExprM

traverseStmtM :: Stmt -> Scoper Number Stmt
58 59
traverseStmtM = traverseStmtExprsM traverseExprM

60 61
traverseExprM :: Expr -> Scoper Number Expr
traverseExprM = traverseNestedExprsM $ embedScopes convertExpr
62

63 64 65
lookupPattern :: Scopes Number -> Expr -> Maybe Number
lookupPattern _ (Number n) = Just n
lookupPattern scopes e =
66
    case lookupElem scopes e of
67 68
        Nothing -> Nothing
        Just (_, _, n) -> Just n
69

70 71 72 73 74 75 76 77 78 79
convertExpr :: Scopes Number -> Expr -> Expr
convertExpr scopes (BinOp WEq l r) =
    if maybePattern == Nothing then
        BinOp BitAnd couldMatch $
        BinOp BitOr  noExtraXZs $
        Number (Based 1 False Binary 0 1)
    else if numberToInteger pattern /= Nothing then
        BinOp Eq l r
    else
        BinOp Eq (BinOp BitOr l mask) pattern'
80 81 82 83
    where
        lxl = BinOp BitXor l l
        rxr = BinOp BitXor r r
        -- Step #1: definitive mismatch
84
        couldMatch = BinOp TEq rxlxl lxrxr
85 86 87
        rxlxl = BinOp BitXor r lxl
        lxrxr = BinOp BitXor l rxr
        -- Step #2: extra X or Z
88
        noExtraXZs = BinOp TEq lxlxrxr rxr
89
        lxlxrxr = BinOp BitXor lxl rxr
90 91 92 93 94 95 96
        -- For wildcard patterns we can find, use masking
        maybePattern = lookupPattern scopes r
        Just pattern = maybePattern
        Based size signed base vals knds = pattern
        mask = Number $ Based size signed base knds 0
        pattern' = Number $ Based size signed base (vals .|. knds) 0
convertExpr scopes (BinOp WNe l r) =
97
    UniOp LogNot $
98
    convertExpr scopes $
99
    BinOp WEq l r
100
convertExpr _ other = other