From 183580632c884b44261f9df600bdefebca869e24 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Fri, 9 Jul 2021 12:21:46 -0400 Subject: [PATCH] restrict unbased unsized bit representation --- src/Convert/Cast.hs | 13 +++---- src/Convert/DimensionQuery.hs | 2 +- src/Convert/TypeOf.hs | 4 +- src/Convert/UnbasedUnsized.hs | 43 +++++++++------------ src/Language/SystemVerilog/AST/Number.hs | 49 ++++++++++++++++-------- 5 files changed, 60 insertions(+), 51 deletions(-) diff --git a/src/Convert/Cast.hs b/src/Convert/Cast.hs index b793516..4e86386 100644 --- a/src/Convert/Cast.hs +++ b/src/Convert/Cast.hs @@ -116,16 +116,15 @@ convertCastM (RawNum size) (Number (Based 1 True Binary a b)) signed = return $ Number $ Based (fromIntegral size) signed Binary (val * a) (val * b) where val = (2 ^ size) - 1 -convertCastM (RawNum size) (Number (UnbasedUnsized ch)) signed = +convertCastM (RawNum size) (Number (UnbasedUnsized bit)) signed = convertCastM (RawNum size) (Number num) signed where num = Based 1 True Binary a b - (a, b) = case ch of - '0' -> (0, 0) - '1' -> (1, 0) - 'x' -> (0, 1) - 'z' -> (1, 1) - _ -> error $ "unexpected unbased-unsized digit: " ++ [ch] + (a, b) = case bit of + Bit0 -> (0, 0) + Bit1 -> (1, 0) + BitX -> (0, 1) + BitZ -> (1, 1) convertCastM size value signed = do value' <- traverseExprM value useFn <- embedScopes canUseCastFn size diff --git a/src/Convert/DimensionQuery.hs b/src/Convert/DimensionQuery.hs index d3df635..ed9bf53 100644 --- a/src/Convert/DimensionQuery.hs +++ b/src/Convert/DimensionQuery.hs @@ -79,7 +79,7 @@ convertExpr (DimFn f (Left t) (Number n)) = if isUnresolved t then DimFn f (Left t) (Number n) else if d <= 0 || d > length rs then - Number $ UnbasedUnsized 'x' + Number $ UnbasedUnsized BitX else case f of FnLeft -> fst r FnRight -> snd r diff --git a/src/Convert/TypeOf.hs b/src/Convert/TypeOf.hs index 30d6fc1..2bd5ab6 100644 --- a/src/Convert/TypeOf.hs +++ b/src/Convert/TypeOf.hs @@ -96,9 +96,9 @@ traverseExprM (Cast (Left (Implicit sg [])) expr) = -- and `$unsigned` system functions present in Verilog-2005 traverseExprM $ Call (Ident fn) $ Args [expr] [] where fn = if sg == Signed then "$signed" else "$unsigned" -traverseExprM (Cast (Left t) (Number (UnbasedUnsized ch))) = +traverseExprM (Cast (Left t) (Number (UnbasedUnsized bit))) = -- defer until this expression becomes explicit - return $ Cast (Left t) (Number (UnbasedUnsized ch)) + return $ Cast (Left t) (Number (UnbasedUnsized bit)) traverseExprM (Cast (Left (t @ (IntegerAtom TInteger _))) expr) = -- convert to cast to an integer vector type traverseExprM $ Cast (Left t') expr diff --git a/src/Convert/UnbasedUnsized.hs b/src/Convert/UnbasedUnsized.hs index 84163eb..37decda 100644 --- a/src/Convert/UnbasedUnsized.hs +++ b/src/Convert/UnbasedUnsized.hs @@ -68,11 +68,11 @@ convertModuleItem parts (Instance moduleName params instanceName [] bindings) = convertExpr (ContextDetermined tag) expr replaceBindingExpr :: Identifier -> Int -> Expr -> Expr replaceBindingExpr portName idx (orig @ (Repeat _ [ConvertedUU a b])) = - if orig == sizedLiteralFor tag ch + if orig == sizedLiteralFor tag bit then Repeat portSize [ConvertedUU a b] else orig where - ch = charForBit a b + bit = bitForBased a b portName' = if null portName then lookupBindingName portNames idx @@ -159,28 +159,21 @@ convertModuleItem' = traverseTypes (traverseNestedTypes convertType) . traverseAsgns convertAsgn -literalFor :: Char -> Expr -literalFor 'Z' = literalFor 'z' -literalFor 'X' = literalFor 'x' -literalFor '0' = Number $ Based 1 True Binary 0 0 -literalFor '1' = Number $ Based 1 True Binary 1 0 -literalFor 'x' = Number $ Based 1 True Binary 0 1 -literalFor 'z' = Number $ Based 1 True Binary 1 1 -literalFor ch = error $ "unexpected unbased-unsized digit: " ++ [ch] +literalFor :: Bit -> Expr +literalFor = Number . (uncurry $ Based 1 True Binary) . bitToVK pattern ConvertedUU :: Integer -> Integer -> Expr pattern ConvertedUU a b = Number (Based 1 True Binary a b) -charForBit :: Integer -> Integer -> Char -charForBit 0 0 = '0' -charForBit 1 0 = '1' -charForBit 0 1 = 'x' -charForBit 1 1 = 'z' -charForBit _ _ = error "charForBit invariant violated" +bitForBased :: Integer -> Integer -> Bit +bitForBased 0 0 = Bit0 +bitForBased 1 0 = Bit1 +bitForBased 0 1 = BitX +bitForBased _ _ = BitZ -sizedLiteralFor :: Expr -> Char -> Expr -sizedLiteralFor expr ch = - Repeat size [literalFor ch] +sizedLiteralFor :: Expr -> Bit -> Expr +sizedLiteralFor expr bit = + Repeat size [literalFor bit] where size = DimsFn FnBits $ Right expr convertAsgn :: (LHS, Expr) -> (LHS, Expr) @@ -251,14 +244,14 @@ convertExpr context (UniOp op expr) = if isSizedUniOp op then UniOp op (convertExpr context expr) else UniOp op (convertExpr SelfDetermined expr) -convertExpr SelfDetermined (UU ch) = - literalFor ch -convertExpr (ContextDetermined expr) (UU ch) = - sizedLiteralFor expr ch +convertExpr SelfDetermined (UU bit) = + literalFor bit +convertExpr (ContextDetermined expr) (UU bit) = + sizedLiteralFor expr bit convertExpr _ other = other -pattern UU :: Char -> Expr -pattern UU ch = Number (UnbasedUnsized ch) +pattern UU :: Bit -> Expr +pattern UU bit = Number (UnbasedUnsized bit) convertType :: Type -> Type convertType (TypeOf e) = TypeOf $ convertExpr SelfDetermined e diff --git a/src/Language/SystemVerilog/AST/Number.hs b/src/Language/SystemVerilog/AST/Number.hs index 3289c45..f21a4ba 100644 --- a/src/Language/SystemVerilog/AST/Number.hs +++ b/src/Language/SystemVerilog/AST/Number.hs @@ -7,11 +7,13 @@ module Language.SystemVerilog.AST.Number ( Number (..) , Base (..) + , Bit (..) , parseNumber , numberBitLength , numberIsSigned , numberIsSized , numberToInteger + , bitToVK ) where import Data.Bits (shiftL) @@ -26,7 +28,10 @@ parseNumber = parseNumber' . map toLower . filter (not . isPad) where isPad = flip elem "_ \n\t" parseNumber' :: String -> Number -parseNumber' ['\'', ch] = UnbasedUnsized ch +parseNumber' "'0" = UnbasedUnsized Bit0 +parseNumber' "'1" = UnbasedUnsized Bit1 +parseNumber' "'x" = UnbasedUnsized BitX +parseNumber' "'z" = UnbasedUnsized BitZ parseNumber' str = -- simple decimal number if maybeIdx == Nothing then @@ -145,6 +150,26 @@ zDigits = ['z', '?'] xzDigits :: [Char] xzDigits = xDigits ++ zDigits +data Bit + = Bit0 + | Bit1 + | BitX + | BitZ + deriving (Eq, Ord) + +instance Show Bit where + show Bit0 = "0" + show Bit1 = "1" + show BitX = "x" + show BitZ = "z" + +-- convet an unbased unsized bit to its (values, kinds) pair +bitToVK :: Bit -> (Integer, Integer) +bitToVK Bit0 = (0, 0) +bitToVK Bit1 = (1, 0) +bitToVK BitX = (0, 1) +bitToVK BitZ = (1, 1) + data Base = Binary | Octal @@ -157,7 +182,7 @@ instance Show Base where show Hex = "h" data Number - = UnbasedUnsized Char + = UnbasedUnsized Bit | Decimal Int Bool Integer | Based Int Bool Base Integer Integer deriving (Eq, Ord) @@ -191,8 +216,8 @@ numberIsSigned (Based _ signed _ _ _) = signed -- get the integer value of a number, provided it has not X or Z bits numberToInteger :: Number -> Maybe Integer -numberToInteger (UnbasedUnsized '1') = Just 1 -numberToInteger (UnbasedUnsized '0') = Just 0 +numberToInteger (UnbasedUnsized Bit1) = Just 1 +numberToInteger (UnbasedUnsized Bit0) = Just 0 numberToInteger UnbasedUnsized{} = Nothing numberToInteger (Decimal _ _ num) = Just num numberToInteger (Based _ _ _ num 0) = Just num @@ -205,10 +230,8 @@ bits n = 1 + bits (quot n 2) -- number to string conversion instance Show Number where - show (UnbasedUnsized ch) = - if elem ch "01xzXZ" - then ['\'', ch] - else error $ "illegal unbased-unsized char: " ++ show ch + show (UnbasedUnsized bit) = + '\'' : show bit show (Decimal (-32) True value) = if value < 0 then error $ "illegal decimal: " ++ show value @@ -326,11 +349,5 @@ instance Semigroup Number where toBased (n @ Based{}) = n toBased (Decimal size signed num) = Based size signed Hex num 0 - toBased (UnbasedUnsized ch) = - case ch of - '0' -> based 0 0 - '1' -> based 1 0 - 'x' -> based 0 1 - 'z' -> based 1 1 - _ -> error $ "invalid unbased unsized char: " ++ show ch - where based = Based 1 False Binary + toBased (UnbasedUnsized bit) = + uncurry (Based 1 False Binary) (bitToVK bit)