From d2a0ba0d135152ab6d1bc9eae1e1400fd641f975 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Wed, 8 Jul 2020 21:49:46 -0600 Subject: [PATCH] improved handling of number literals - elaborated literals larger than 32 bits are given an explicit size - constant folding no longer encodes illegal negative numbers --- src/Convert/DimensionQuery.hs | 2 +- src/Convert/Enum.hs | 2 +- src/Convert/Struct.hs | 5 +-- src/Language/SystemVerilog/AST/Expr.hs | 44 ++++++++++++++++---------- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/Convert/DimensionQuery.hs b/src/Convert/DimensionQuery.hs index 180765e..fffecd4 100644 --- a/src/Convert/DimensionQuery.hs +++ b/src/Convert/DimensionQuery.hs @@ -82,7 +82,7 @@ convertExpr (DimFn f (Left t) (Number str)) = else case f of FnLeft -> fst r FnRight -> snd r - FnIncrement -> endianCondExpr r (Number "1") (Number "-1") + FnIncrement -> endianCondExpr r (Number "1") (UniOp UniSub $ Number "1") FnLow -> endianCondExpr r (snd r) (fst r) FnHigh -> endianCondExpr r (fst r) (snd r) FnSize -> rangeSize r diff --git a/src/Convert/Enum.hs b/src/Convert/Enum.hs index f577e3a..4ad1131 100644 --- a/src/Convert/Enum.hs +++ b/src/Convert/Enum.hs @@ -89,7 +89,7 @@ makeEnumItems (itemType, l) = ++ show (zip keys vals) where keys = map fst l - vals = tail $ scanl step (Number "-1") (map snd l) + vals = tail $ scanl step (UniOp UniSub $ Number "1") (map snd l) noDuplicates = all (null . tail . flip elemIndices vals) vals step :: Expr -> Expr -> Expr step expr Nil = simplify $ BinOp Add expr (Number "1") diff --git a/src/Convert/Struct.hs b/src/Convert/Struct.hs index ae43b88..0eb128d 100644 --- a/src/Convert/Struct.hs +++ b/src/Convert/Struct.hs @@ -65,8 +65,9 @@ convertStruct' isStruct sg fields = else map simplify $ repeat (Number "0") fieldHis = if isStruct - then map simplify $ init $ scanr (BinOp Add) (Number "-1") fieldSizes - else map simplify $ map (BinOp Add (Number "-1")) fieldSizes + then map simplify $ init $ scanr (BinOp Add) minusOne fieldSizes + else map simplify $ map (BinOp Add minusOne) fieldSizes + minusOne = UniOp UniSub $ Number "1" -- create the mapping structure for the unstructured fields keys = map snd fields diff --git a/src/Language/SystemVerilog/AST/Expr.hs b/src/Language/SystemVerilog/AST/Expr.hs index e7a1aa9..238f4da 100644 --- a/src/Language/SystemVerilog/AST/Expr.hs +++ b/src/Language/SystemVerilog/AST/Expr.hs @@ -233,10 +233,6 @@ simplify :: Expr -> Expr simplify (UniOp LogNot (Number "1")) = Number "0" simplify (UniOp LogNot (Number "0")) = Number "1" simplify (UniOp LogNot (BinOp Eq a b)) = BinOp Ne a b -simplify (orig @ (UniOp UniSub (Number n))) = - case readNumber n of - Nothing -> orig - Just x -> Number $ show (-x) simplify (orig @ (Repeat (Number n) exprs)) = case readNumber n of Nothing -> orig @@ -252,7 +248,7 @@ simplify (Concat exprs) = simplify (orig @ (Call (Ident "$clog2") (Args [Number n] []))) = case readNumber n of Nothing -> orig - Just x -> Number $ show $ clog2 x + Just x -> toLiteral $ clog2 x simplify (Mux cc e1 e2) = case cc' of Number "1" -> e1' @@ -274,10 +270,14 @@ simplify (BinOp Add (Number n1) (BinOp Add (Number n2) e)) = simplify $ BinOp Add (BinOp Add (Number n1) (Number n2)) e simplify (BinOp Ge (BinOp Sub e (Number "1")) (Number "0")) = simplify $ BinOp Ge e (Number "1") +simplify (BinOp Add e1 (UniOp UniSub e2)) = + simplify $ BinOp Sub e1 e2 +simplify (BinOp Add (UniOp UniSub e2) e1) = + simplify $ BinOp Sub e1 e2 simplify (BinOp Add (BinOp Sub (Number n1) e) (Number n2)) = case (readNumber n1, readNumber n2) of (Just x, Just y) -> - simplify $ BinOp Sub (Number $ show (x + y)) e' + simplify $ BinOp Sub (toLiteral (x + y)) e' _ -> nochange where e' = simplify e @@ -295,33 +295,33 @@ simplify (BinOp op e1 e2) = (Add, e, BinOp Sub (Number "0") (Number "1")) -> BinOp Sub e (Number "1") (_ , Number a, Number b) -> case (op, readNumber a, readNumber b) of - (Add, Just x, Just y) -> Number $ show (x + y) - (Sub, Just x, Just y) -> Number $ show (x - y) - (Mul, Just x, Just y) -> Number $ show (x * y) + (Add, Just x, Just y) -> toLiteral (x + y) + (Sub, Just x, Just y) -> toLiteral (x - y) + (Mul, Just x, Just y) -> toLiteral (x * y) (Div, Just _, Just 0) -> Number "x" - (Div, Just x, Just y) -> Number $ show (x `quot` y) - (Mod, Just x, Just y) -> Number $ show (x `rem` y) - (Pow, Just x, Just y) -> Number $ show (x ^ y) + (Div, Just x, Just y) -> toLiteral (x `quot` y) + (Mod, Just x, Just y) -> toLiteral (x `rem` y) + (Pow, Just x, Just y) -> toLiteral (x ^ y) (Eq , Just x, Just y) -> bool $ x == y (Ne , Just x, Just y) -> bool $ x /= y (Gt , Just x, Just y) -> bool $ x > y (Ge , Just x, Just y) -> bool $ x >= y (Lt , Just x, Just y) -> bool $ x < y (Le , Just x, Just y) -> bool $ x <= y - (ShiftAL, Just x, Just y) -> Number $ show $ shiftL x (toInt y) - (ShiftAR, Just x, Just y) -> Number $ show $ shiftR x (toInt y) - (ShiftL , Just x, Just y) -> Number $ show $ shiftL x (toInt y) + (ShiftAL, Just x, Just y) -> toLiteral $ shiftL x (toInt y) + (ShiftAR, Just x, Just y) -> toLiteral $ shiftR x (toInt y) + (ShiftL , Just x, Just y) -> toLiteral $ shiftL x (toInt y) (ShiftR , Just x, Just y) -> if x < 0 && y > 0 then BinOp ShiftR (Number a) (Number b) - else Number $ show $ shiftR x (toInt y) + else toLiteral $ shiftR x (toInt y) _ -> BinOp op e1' e2' where toInt :: Integer -> Int toInt = fromIntegral (Add, BinOp Add e (Number a), Number b) -> case (readNumber a, readNumber b) of - (Just x, Just y) -> BinOp Add e $ Number $ show (x + y) + (Just x, Just y) -> BinOp Add e $ toLiteral (x + y) _ -> BinOp op e1' e2' (Sub, e, Number "-1") -> BinOp Add e (Number "1") _ -> BinOp op e1' e2' @@ -332,6 +332,16 @@ simplify (BinOp op e1 e2) = bool False = Number "0" simplify other = other +toLiteral :: Integer -> Expr +toLiteral n = + if n >= 4294967296 + then Number $ show (bits n) ++ "'d" ++ show n + else Number $ show n + +bits :: Integer -> Integer +bits 0 = 0 +bits n = 1 + bits (quot n 2) + rangeSize :: Range -> Expr rangeSize (s, e) = endianCondExpr (s, e) a b