Commit d88c516d by Zachary Snow

enhanced handling of number literals

- number literals are parsed rather than stored as strings
- fix array query functions used on non-trivial number literals
- more efficient expression simplification recursion
- expanded constant folding scenarios
parent 737c66a6
......@@ -19,8 +19,7 @@
module Convert.DimensionQuery (convert) where
import Data.List (elemIndex)
import Convert.ExprUtils
import Convert.Traverse
import Language.SystemVerilog.AST
......@@ -37,9 +36,9 @@ elaborateType (IntegerAtom t sg) =
IntegerVector TLogic sg [(hi, lo)]
where
size = atomSize t
hi = Number $ show (size - 1)
lo = Number "0"
atomSize :: IntegerAtomType -> Int
hi = RawNum $ size - 1
lo = RawNum 0
atomSize :: IntegerAtomType -> Integer
atomSize TByte = 8
atomSize TShortint = 16
atomSize TInt = 32
......@@ -59,32 +58,32 @@ convertExpr (DimFn fn (Right e) d) =
DimFn fn (Left $ TypeOf e) d
convertExpr (orig @ (DimsFn FnUnpackedDimensions (Left t))) =
case t of
UnpackedType _ rs -> Number $ show $ length rs
UnpackedType _ rs -> RawNum $ fromIntegral $ length rs
TypeOf{} -> orig
_ -> Number "0"
_ -> RawNum 0
convertExpr (orig @ (DimsFn FnDimensions (Left t))) =
case t of
IntegerAtom{} -> Number "1"
IntegerAtom{} -> RawNum 1
Alias{} -> orig
PSAlias{} -> orig
CSAlias{} -> orig
TypeOf{} -> orig
UnpackedType t' rs ->
BinOp Add
(Number $ show $ length rs)
(RawNum $ fromIntegral $ length rs)
(DimsFn FnDimensions $ Left t')
_ -> Number $ show $ length $ snd $ typeRanges t
_ -> RawNum $ fromIntegral $ length $ snd $ typeRanges t
-- conversion for array dimension functions on types
convertExpr (DimFn f (Left t) (Number str)) =
if dm == Nothing || isUnresolved t then
DimFn f (Left t) (Number str)
else if d <= 0 || fromIntegral d > length rs then
Number "'x"
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'
else case f of
FnLeft -> fst r
FnRight -> snd r
FnIncrement -> endianCondExpr r (Number "1") (UniOp UniSub $ Number "1")
FnIncrement -> endianCondExpr r (RawNum 1) (UniOp UniSub $ RawNum 1)
FnLow -> endianCondExpr r (snd r) (fst r)
FnHigh -> endianCondExpr r (fst r) (snd r)
FnSize -> rangeSize r
......@@ -93,9 +92,10 @@ convertExpr (DimFn f (Left t) (Number str)) =
UnpackedType tInner rsOuter ->
rsOuter ++ (snd $ typeRanges $ elaborateType tInner)
_ -> snd $ typeRanges $ elaborateType t
dm = readNumber str
Just d = dm
r = rs !! (fromIntegral $ d - 1)
d = case numberToInteger n of
Just value -> fromIntegral value
Nothing -> 0
r = rs !! (d - 1)
isUnresolved :: Type -> Bool
isUnresolved Alias{} = True
isUnresolved PSAlias{} = True
......@@ -117,7 +117,7 @@ convertBits (Left t) =
Struct _ fields rs ->
BinOp Mul
(dimensionsSize rs)
(foldl (BinOp Add) (Number "0") fieldSizes)
(foldl (BinOp Add) (RawNum 0) fieldSizes)
where fieldSizes = map (DimsFn FnBits . Left . fst) fields
UnpackedType t' rs ->
BinOp Mul
......@@ -127,17 +127,13 @@ convertBits (Left t) =
convertBits (Right e) =
case e of
Concat exprs ->
foldl (BinOp Add) (Number "0") $
foldl (BinOp Add) (RawNum 0) $
map (convertBits . Right) $
exprs
Stream _ _ exprs -> convertBits $ Right $ Concat exprs
Number n ->
case elemIndex '\'' n of
Nothing -> Number "32"
Just 0 -> Number "32"
Just idx -> Number $ take idx n
Number n -> RawNum $ numberBitLength n
Range expr mode range ->
BinOp Mul size $ convertBits $ Right $ Bit expr (Number "0")
BinOp Mul size $ convertBits $ Right $ Bit expr (RawNum 0)
where
size = case mode of
NonIndexed -> rangeSize range
......
......@@ -49,6 +49,6 @@ convertExpr :: Idents -> Expr -> Expr
convertExpr functions (Call (Ident func) (Args [] [])) =
Call (Ident func) (Args args [])
where args = if Set.member func functions
then [Number "0"]
then [RawNum 0]
else []
convertExpr _ other = other
......@@ -23,6 +23,7 @@ import Control.Monad.Writer
import Data.List (elemIndices)
import qualified Data.Set as Set
import Convert.ExprUtils
import Convert.Traverse
import Language.SystemVerilog.AST
......@@ -72,12 +73,12 @@ traverseType (Enum (Implicit sg rl) v rs) =
-- default to a 32 bit logic
t' = IntegerVector TLogic sg rl'
rl' = if null rl
then [(Number "31", Number "0")]
then [(RawNum 31, RawNum 0)]
else rl
traverseType (Enum t v rs) = do
let (tf, rl) = typeRanges t
rlParam <- case rl of
[ ] -> return [(Number "0", Number "0")]
[ ] -> return [(RawNum 0, RawNum 0)]
[_] -> return rl
_ -> error $ "unexpected multi-dim enum type: " ++ show (Enum t v rs)
tell $ Set.singleton (tf rlParam, v) -- type of localparams
......@@ -93,10 +94,10 @@ makeEnumItems (itemType, l) =
++ show (zip keys vals)
where
keys = map fst l
vals = tail $ scanl step (UniOp UniSub $ Number "1") (map snd l)
vals = tail $ scanl step (UniOp UniSub $ RawNum 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")
step expr Nil = simplify $ BinOp Add expr (RawNum 1)
step _ expr = expr
toPackageItem :: Identifier -> Expr -> PackageItem
toPackageItem x v =
......
{-# LANGUAGE PatternSynonyms #-}
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Utilities for expressions and ranges
-}
module Convert.ExprUtils
( simplify
, simplifyStep
, rangeSize
, rangeSizeHiLo
, endianCondExpr
, endianCondRange
, dimensionsSize
) where
import Data.Bits (shiftL, shiftR)
import Convert.Traverse
import Language.SystemVerilog.AST
simplify :: Expr -> Expr
simplify = simplifyStep . traverseSinglyNestedExprs simplify . simplifyStep
simplifyStep :: Expr -> Expr
simplifyStep (UniOp LogNot (Number n)) =
case numberToInteger n of
Just 0 -> bool True
Just _ -> bool False
Nothing -> UniOp LogNot $ Number n
simplifyStep (UniOp LogNot (BinOp Eq a b)) = BinOp Ne a b
simplifyStep (UniOp LogNot (BinOp Ne a b)) = BinOp Eq a b
simplifyStep (UniOp UniSub (UniOp UniSub e)) = e
simplifyStep (UniOp UniSub (BinOp Sub e1 e2)) = BinOp Sub e2 e1
simplifyStep (Concat [e]) = e
simplifyStep (Concat es) = Concat $ filter (/= Concat []) es
simplifyStep (Repeat (Dec 0) _) = Concat []
simplifyStep (Repeat (Dec 1) es) = Concat es
simplifyStep (Mux (Number n) e1 e2) =
case numberToInteger n of
Just 0 -> e2
Just _ -> e1
Nothing -> Mux (Number n) e1 e2
simplifyStep (Call (Ident "$clog2") (Args [Dec k] [])) =
toDec $ clog2 k
where
clog2Help :: Integer -> Integer -> Integer
clog2Help p n = if p >= n then 0 else 1 + clog2Help (p*2) n
clog2 :: Integer -> Integer
clog2 n = if n < 2 then 0 else clog2Help 1 n
simplifyStep (BinOp op e1 e2) = simplifyBinOp op e1 e2
simplifyStep other = other
simplifyBinOp :: BinOp -> Expr -> Expr -> Expr
simplifyBinOp Add (Dec 0) e = e
simplifyBinOp Add e (Dec 0) = e
simplifyBinOp Sub e (Dec 0) = e
simplifyBinOp Sub (Dec 0) e = UniOp UniSub e
simplifyBinOp Mul (Dec 0) _ = toDec 0
simplifyBinOp Mul (Dec 1) e = e
simplifyBinOp Mul _ (Dec 0) = toDec 0
simplifyBinOp Mul e (Dec 1) = e
simplifyBinOp Add e1 (UniOp UniSub e2) = BinOp Sub e1 e2
simplifyBinOp Add (UniOp UniSub e1) e2 = BinOp Sub e2 e1
simplifyBinOp Sub e1 (UniOp UniSub e2) = BinOp Add e1 e2
simplifyBinOp Sub (UniOp UniSub e1) e2 = UniOp UniSub $ BinOp Add e1 e2
simplifyBinOp Sub (n1 @ Number{}) (BinOp Sub (n2 @ Number{}) e) =
BinOp Add (BinOp Sub n1 n2) e
simplifyBinOp Sub (n1 @ Number{}) (BinOp Sub e (n2 @ Number{})) =
BinOp Sub (BinOp Add n1 n2) e
simplifyBinOp Sub (BinOp Add e (n1 @ Number{})) (n2 @ Number{}) =
BinOp Add e (BinOp Sub n1 n2)
simplifyBinOp Add (n1 @ Number{}) (BinOp Add (n2 @ Number{}) e) =
BinOp Add (BinOp Add n1 n2) e
simplifyBinOp Add (n1 @ Number{}) (BinOp Sub e (n2 @ Number{})) =
BinOp Add e (BinOp Sub n1 n2)
simplifyBinOp Sub (BinOp Sub e (n1 @ Number{})) (n2 @ Number{}) =
BinOp Sub e (BinOp Add n1 n2)
simplifyBinOp Add (BinOp Sub e (n1 @ Number{})) (n2 @ Number{}) =
BinOp Sub e (BinOp Sub n1 n2)
simplifyBinOp Add (BinOp Sub (n1 @ Number{}) e) (n2 @ Number{}) =
BinOp Sub (BinOp Add n1 n2) e
simplifyBinOp Ge (BinOp Sub e (Dec 1)) (Dec 0) = BinOp Ge e (toDec 1)
simplifyBinOp ShiftAL (Dec x) (Dec y) = toDec $ shiftL x (fromIntegral y)
simplifyBinOp ShiftAR (Dec x) (Dec y) = toDec $ shiftR x (fromIntegral y)
simplifyBinOp ShiftL (Dec x) (Dec y) = toDec $ shiftL x (fromIntegral y)
simplifyBinOp ShiftR (Dec x) (Dec y) = toDec $ shiftR x (fromIntegral y)
simplifyBinOp op e1 e2 =
case (e1, e2) of
(Dec x, Dec y) -> constantFold orig op x y
(SizDec x, Dec y) -> constantFold orig op x y
(Dec x, SizDec y) -> constantFold orig op x y
(Bas x, Dec y) -> constantFold orig op x y
(Dec x, Bas y) -> constantFold orig op x y
(Bas x, Bas y) -> constantFold orig op x y
(NegDec x, Dec y) -> constantFold orig op (-x) y
(Dec x, NegDec y) -> constantFold orig op x (-y)
(NegDec x, NegDec y) -> constantFold orig op (-x) (-y)
_ -> orig
where orig = BinOp op e1 e2
-- attempt to constant fold a binary operation on integers
constantFold :: Expr -> BinOp -> Integer -> Integer -> Expr
constantFold _ Add x y = toDec (x + y)
constantFold _ Sub x y = toDec (x - y)
constantFold _ Mul x y = toDec (x * y)
constantFold _ Div _ 0 = Number $ Based (-32) True Hex 0 bits
where bits = 2 ^ (32 :: Integer) - 1
constantFold _ Div x y = toDec (x `quot` y)
constantFold _ Mod x y = toDec (x `rem` y)
constantFold _ Pow x y = toDec (x ^ y)
constantFold _ Eq x y = bool $ x == y
constantFold _ Ne x y = bool $ x /= y
constantFold _ Gt x y = bool $ x > y
constantFold _ Ge x y = bool $ x >= y
constantFold _ Lt x y = bool $ x < y
constantFold _ Le x y = bool $ x <= y
constantFold fallback _ _ _ = fallback
bool :: Bool -> Expr
bool True = Number $ Decimal 1 False 1
bool False = Number $ Decimal 1 False 0
toDec :: Integer -> Expr
toDec n =
if n < 0 then
UniOp UniSub $ toDec (-n)
else if n >= 4294967296 `div` 2 then
let size = fromIntegral $ bits $ n * 2
in Number $ Decimal (negate size) True n
else
RawNum n
where
bits :: Integer -> Integer
bits 0 = 0
bits v = 1 + bits (quot v 2)
pattern Dec :: Integer -> Expr
pattern Dec n <- Number (Decimal (-32) _ n)
pattern SizDec :: Integer -> Expr
pattern SizDec n <- Number (Decimal 32 _ n)
pattern NegDec :: Integer -> Expr
pattern NegDec n <- UniOp UniSub (Dec n)
pattern Bas :: Integer -> Expr
pattern Bas n <- Number (Based _ _ _ n 0)
-- returns the size of a range
rangeSize :: Range -> Expr
rangeSize (s, e) =
endianCondExpr (s, e) a b
where
a = rangeSizeHiLo (s, e)
b = rangeSizeHiLo (e, s)
-- returns the size of a range known to be ordered
rangeSizeHiLo :: Range -> Expr
rangeSizeHiLo (hi, lo) =
simplify $ BinOp Add (BinOp Sub hi lo) (RawNum 1)
-- chooses one or the other expression based on the endianness of the given
-- range; [hi:lo] chooses the first expression
endianCondExpr :: Range -> Expr -> Expr -> Expr
endianCondExpr r e1 e2 = simplify $ Mux (uncurry (BinOp Ge) r) e1 e2
-- chooses one or the other range based on the endianness of the given range,
-- but in such a way that the result is itself also usable as a range even if
-- the endianness cannot be resolved during conversion, i.e. if it's dependent
-- on a parameter value; [hi:lo] chooses the first range
endianCondRange :: Range -> Range -> Range -> Range
endianCondRange r r1 r2 =
( endianCondExpr r (fst r1) (fst r2)
, endianCondExpr r (snd r1) (snd r2)
)
-- returns the total size of a set of dimensions
dimensionsSize :: [Range] -> Expr
dimensionsSize ranges =
simplify $
foldl (BinOp Mul) (RawNum 1) $
map rangeSize $
ranges
......@@ -23,7 +23,7 @@ convertStmt (For (Left []) cc asgns stmt) =
convertStmt $ For (Right []) cc asgns stmt
convertStmt (For (Right []) cc asgns stmt) =
convertStmt $ For inits cc asgns stmt
where inits = Left [dummyDecl $ Number "0"]
where inits = Left [dummyDecl $ RawNum 0]
convertStmt (orig @ (For (Right [_]) _ _ _)) = orig
convertStmt (For (Left inits) cc asgns stmt) =
......
......@@ -22,16 +22,16 @@ convertStmt :: Stmt -> Stmt
convertStmt (Foreach x idxs stmt) =
(foldl (.) id $ map toLoop $ zip [1..] idxs) stmt
where
toLoop :: (Int, Identifier) -> (Stmt -> Stmt)
toLoop :: (Integer, Identifier) -> (Stmt -> Stmt)
toLoop (_, "") = id
toLoop (d, i) =
For (Left [idxDecl]) cmp [incr]
where
queryFn f = DimFn f (Right $ Ident x) (Number $ show d)
queryFn f = DimFn f (Right $ Ident x) (RawNum d)
idxDecl = Variable Local (IntegerAtom TInteger Unspecified) i []
(queryFn FnLeft)
cmp =
Mux (BinOp Eq (queryFn FnIncrement) (Number "1"))
Mux (BinOp Eq (queryFn FnIncrement) (RawNum 1))
(BinOp Ge (Ident i) (queryFn FnRight))
(BinOp Le (Ident i) (queryFn FnRight))
incr = (LHSIdent i, AsgnOp Sub, queryFn FnIncrement)
......
......@@ -276,23 +276,26 @@ convertLoop loop comp stmt = do
]
jumpStateType :: Type
jumpStateType = IntegerVector TBit Unspecified [(Number "0", Number "1")]
jumpStateType = IntegerVector TBit Unspecified [(RawNum 0, RawNum 1)]
jumpState :: String
jumpState = "_sv2v_jump"
jsVal :: Integer -> Expr
jsVal n = Number $ Based 2 False Binary n 0
-- keep running the loop/function normally
jsNone :: Expr
jsNone = Number "2'b00"
jsNone = jsVal 0
-- skip to the next iteration of the loop (continue)
jsContinue :: Expr
jsContinue = Number "2'b01"
jsContinue = jsVal 1
-- stop running the loop immediately (break)
jsBreak :: Expr
jsBreak = Number "2'b10"
jsBreak = jsVal 2
-- stop running the function immediately (return)
jsReturn :: Expr
jsReturn = Number "2'b11"
jsReturn = jsVal 3
assertMsg :: Bool -> String -> State Info ()
......
......@@ -134,7 +134,7 @@ traverseModuleItem ports scopes =
tmp = "sv2v_tmp_" ++ instanceName ++ "_" ++ portName
tmpExpr = Ident tmp
t = Net (NetType TWire) Unspecified
[(DimsFn FnBits $ Right expr, Number "1")]
[(DimsFn FnBits $ Right expr, RawNum 1)]
items =
[ MIPackageItem $ Decl $ Variable Local t tmp [] Nil
, AlwaysC AlwaysComb $ Asgn AsgnOpEq Nothing lhs tmpExpr]
......@@ -182,7 +182,7 @@ rewriteDeclM (Variable d t x a e) = do
return $ Variable d' t' x a e
rewriteDeclM (Param s (IntegerVector _ sg []) x e) =
return $ Param s (Implicit sg [(zero, zero)]) x e
where zero = Number "0"
where zero = RawNum 0
rewriteDeclM (Param s (IntegerVector _ sg rs) x e) =
return $ Param s (Implicit sg rs) x e
rewriteDeclM decl = return decl
......
......@@ -26,6 +26,7 @@
module Convert.MultiplePacked (convert) where
import Convert.ExprUtils
import Control.Monad ((>=>))
import Data.Tuple (swap)
import Data.Maybe (isJust)
......@@ -110,7 +111,7 @@ combineRanges r1 r2 = r
size2 = rangeSizeHiLo (s2, e2)
lower = BinOp Add e2 (BinOp Mul e1 size2)
upper = BinOp Add (BinOp Mul size1 size2)
(BinOp Sub lower (Number "1"))
(BinOp Sub lower (RawNum 1))
traverseStmtM :: Stmt -> Scoper TypeInfo Stmt
traverseStmtM =
......@@ -254,7 +255,7 @@ convertExpr scopes =
maybeDims = dims expr
exprOuter = Bit expr idxInner
baseDec = fst rangeOuter
baseInc = BinOp Sub (BinOp Add baseDec len) (Number "1")
baseInc = BinOp Sub (BinOp Add baseDec len) (RawNum 1)
base = endianCondExpr rangeOuter baseDec baseInc
len = rangeSize rangeOuter
range = (base, len)
......@@ -277,7 +278,7 @@ convertExpr scopes =
base = endianCondExpr dimOuter baseDec baseInc
len = lenOuter
range' = (base, len)
one = Number "1"
one = RawNum 1
rewriteExpr (orig @ (Range expr NonIndexed range)) =
if isJust maybeDims && expr == rewriteExpr expr
then rewriteExpr $ Range expr IndexedMinus range'
......@@ -285,7 +286,7 @@ convertExpr scopes =
where
maybeDims = dims expr
baseDec = fst range
baseInc = BinOp Sub (BinOp Add baseDec len) (Number "1")
baseInc = BinOp Sub (BinOp Add baseDec len) (RawNum 1)
base = endianCondExpr range baseDec baseInc
len = rangeSize range
range' = (base, len)
......@@ -299,7 +300,7 @@ convertExpr scopes =
sizeOuter = rangeSize dimOuter
offsetOuter = uncurry (endianCondExpr dimOuter) $ swap dimOuter
(baseOrig, lenOrig) = range
lenOrigMinusOne = BinOp Sub lenOrig (Number "1")
lenOrigMinusOne = BinOp Sub lenOrig (RawNum 1)
baseSwapped =
orientIdx dimInner $
case mode of
......
......@@ -13,6 +13,7 @@ import Data.Maybe (isJust, isNothing, fromJust)
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import Convert.ExprUtils
import Convert.Traverse
import Language.SystemVerilog.AST
......@@ -164,7 +165,7 @@ convert files =
idents = Set.toList identSet
toParam :: Identifier -> Decl
toParam ident =
Param Parameter typ name (Number "0")
Param Parameter typ name (RawNum 0)
where
typ = Alias (addedParamTypeName paramName ident) []
name = addedParamName paramName ident
......@@ -225,7 +226,7 @@ exprToType (Bit e i) =
Just t -> Just $ tf (rs ++ [r])
where
(tf, rs) = typeRanges t
r = (simplify $ BinOp Sub i (Number "1"), Number "0")
r = (simplify $ BinOp Sub i (RawNum 1), RawNum 0)
exprToType _ = Nothing
-- checks where a type is sufficiently resolved to be substituted
......
......@@ -19,6 +19,7 @@ module Convert.Simplify (convert) where
import Control.Monad.State
import qualified Data.Map.Strict as Map
import Convert.ExprUtils
import Convert.Traverse
import Language.SystemVerilog.AST
......@@ -66,44 +67,56 @@ traverseStmtM :: Stmt -> State Info Stmt
traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt
traverseExprM :: Expr -> State Info Expr
traverseExprM = traverseNestedExprsM $ stately convertExpr
traverseExprM = stately convertExpr
substituteExprM :: Expr -> State Info Expr
substituteExprM = traverseNestedExprsM $ stately substitute
substituteExprM = stately substitute
convertExpr :: Info -> Expr -> Expr
convertExpr info (Cast (Right c) e) =
Cast (Right c') e
Cast (Right c') e'
where
c' = simplify $ substitute info c
c' = convertExpr info $ substitute info c
e' = convertExpr info e
convertExpr info (DimFn f v e) =
DimFn f v e'
where
e' = simplify $ substitute info e
where e' = convertExpr info $ substitute info e
convertExpr info (Call (Ident "$clog2") (Args [e] [])) =
if clog2' == clog2
then clog2
else clog2'
if val' == val
then val
else val'
where
e' = simplify $ substitute info e
clog2 = Call (Ident "$clog2") (Args [e'] [])
clog2' = simplify clog2
e' = convertExpr info $ substitute info e
val = Call (Ident "$clog2") (Args [e'] [])
val' = simplifyStep val
convertExpr info (Mux cc aa bb) =
if before == after
then simplify $ Mux cc aa bb
else simplify $ Mux after aa bb
then simplifyStep $ Mux cc' aa' bb'
else simplifyStep $ Mux after aa' bb'
where
before = substitute info cc
after = simplify before
convertExpr _ (other @ Repeat{}) = traverseNestedExprs simplify other
convertExpr _ (other @ Concat{}) = simplify other
convertExpr _ (other @ BinOp{}) = simplify other
convertExpr _ (other @ UniOp{}) = simplify other
convertExpr _ other = other
before = substitute info cc'
after = convertExpr info before
aa' = convertExpr info aa
bb' = convertExpr info bb
cc' = convertExpr info cc
convertExpr info (BinOp op e1 e2) =
simplifyStep $ BinOp op
(convertExpr info e1)
(convertExpr info e2)
convertExpr info (UniOp op expr) =
simplifyStep $ UniOp op $ convertExpr info expr
convertExpr info (Repeat expr exprs) =
simplifyStep $ Repeat
(convertExpr info expr)
(map (convertExpr info) exprs)
convertExpr info (Concat exprs) =
simplifyStep $ Concat (map (convertExpr info) exprs)
convertExpr info expr =
traverseSinglyNestedExprs (convertExpr info) expr
substitute :: Info -> Expr -> Expr
substitute info expr =
traverseNestedExprs substitute' $ simplify expr
traverseNestedExprs substitute' expr
where
substitute' :: Expr -> Expr
substitute' (Ident x) =
......
......@@ -12,6 +12,7 @@ import Control.Monad.Writer
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import Convert.ExprUtils
import Convert.Traverse
import Language.SystemVerilog.AST
......@@ -55,8 +56,8 @@ traverseModuleItemM item = traverseExprsM traverseExprM item
traverseStmtM :: Stmt -> ST Stmt
traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt
pattern ConvertedUU :: Char -> Expr
pattern ConvertedUU ch = Number ['1', '\'', 's', 'b', ch]
pattern ConvertedUU :: Integer -> Integer -> Expr
pattern ConvertedUU a b = Number (Based 1 True Binary a b)
traverseExprM :: Expr -> ST Expr
traverseExprM =
......@@ -64,16 +65,25 @@ traverseExprM =
where
convertExprM :: Expr -> ST Expr
convertExprM (Cast (Right (Number s)) (Number n)) =
if elem '\'' n && s == takeWhile (/= '\'') n
then return $ Number n
else case (readNumber s, readNumber n) of
(Just s', Just n') ->
return $ Number str
case n of
UnbasedUnsized{} -> fallback
Decimal (-32) True val ->
num $ Decimal (fromIntegral size) False val'
where
str = (show size) ++ "'d" ++ (show num)
size = s'
num = n' `mod` (2 ^ s')
_ -> convertCastM (Number s) (Number n)
Just size = numberToInteger s
val' = val `mod` (2 ^ size)
Decimal size signed val ->
if sizesMatch
then num $ Decimal (abs size) signed val
else fallback
Based size signed base vals knds ->
if sizesMatch
then num $ Based (abs size) signed base vals knds
else fallback
where
sizesMatch = numberToInteger s == Just (numberBitLength n)
fallback = convertCastM (Number s) (Number n)
num = return . Number
convertExprM (orig @ (Cast (Right DimsFn{}) _)) =
return orig
convertExprM (Cast (Right (Ident x)) e) = do
......@@ -91,13 +101,13 @@ traverseExprM =
convertExprM other = return other
convertCastM :: Expr -> Expr -> ST Expr
convertCastM (s @ (Number str)) (e @ (ConvertedUU ch)) = do
typeMap <- get
case (exprSigning typeMap e, readNumber str) of
(Just Unspecified, Just n) -> return $ Number $
show n ++ "'b" ++ take (fromIntegral n) (repeat ch)
(Just sg, _) -> convertCastWithSigningM s e sg
_ -> return $ Cast (Right s) e
convertCastM (RawNum n) (ConvertedUU a b) =
return $ Number $ Based (fromIntegral n) False Binary
(extend a) (extend b)
where
extend 0 = 0
extend 1 = (2 ^ n) - 1
extend _ = error "not possible"
convertCastM s e = do
typeMap <- get
case exprSigning typeMap e of
......@@ -117,7 +127,7 @@ castFn e sg =
Function Automatic t fnName [decl] [Return $ Ident inp]
where
inp = "inp"
r = (simplify $ BinOp Sub e (Number "1"), Number "0")
r = (simplify $ BinOp Sub e (RawNum 1), RawNum 0)
t = IntegerVector TLogic sg [r]
fnName = castFnName e sg
decl = Variable Input t inp [] Nil
......@@ -130,7 +140,7 @@ castFnName e sg =
where
sizeStr = case e of
Number n ->
case readNumber n of
case numberToInteger n of
Just v -> show v
_ -> shortHash e
_ -> shortHash e
......
......@@ -29,8 +29,8 @@ streamerBlock chunk size asgn output input =
, asgn output (Ident out)
]
where
lo = Number "0"
hi = BinOp Sub size (Number "1")
lo = RawNum 0
hi = BinOp Sub size (RawNum 1)
t = IntegerVector TLogic Unspecified [(hi, lo)]
name = streamerBlockName chunk size
inp = name ++ "_inp"
......@@ -49,7 +49,7 @@ streamerBlock chunk size asgn output input =
lhs2 = LHSRange (LHSIdent out) IndexedMinus (BinOp Sub hi base, left)
expr2 = Range (Ident inp) IndexedPlus (base, left)
stmt2 = Asgn AsgnOpEq Nothing lhs2 expr2
cmp2 = BinOp Gt left (Number "0")
cmp2 = BinOp Gt left (RawNum 0)
streamerBlockName :: Expr -> Expr -> Identifier
streamerBlockName chunk size =
......@@ -60,11 +60,14 @@ traverseStmt (Asgn op mt lhs expr) =
traverseAsgn (lhs, expr) (Asgn op mt)
traverseStmt other = other
zeroBit :: Expr
zeroBit = Number $ Based 1 False Binary 0 0
traverseAsgn :: (LHS, Expr) -> (LHS -> Expr -> Stmt) -> Stmt
traverseAsgn (lhs, Stream StreamR _ exprs) constructor =
constructor lhs expr
where
expr = Concat $ exprs ++ [Repeat delta [Number "1'b0"]]
expr = Concat $ exprs ++ [Repeat delta [zeroBit]]
size = DimsFn FnBits $ Right $ lhsToExpr lhs
exprSize = DimsFn FnBits $ Right (Concat exprs)
delta = BinOp Sub size exprSize
......@@ -73,7 +76,7 @@ traverseAsgn (LHSStream StreamR _ lhss, expr) constructor =
traverseAsgn (lhs, Stream StreamL chunk exprs) constructor = do
streamerBlock chunk size constructor lhs expr
where
expr = Concat $ Repeat delta [Number "1'b0"] : exprs
expr = Concat $ Repeat delta [zeroBit] : exprs
size = DimsFn FnBits $ Right $ lhsToExpr lhs
exprSize = DimsFn FnBits $ Right (Concat exprs)
delta = BinOp Sub size exprSize
......
......@@ -12,6 +12,7 @@ import Data.Tuple (swap)
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import Convert.ExprUtils
import Convert.Scoper
import Convert.Traverse
import Language.SystemVerilog.AST
......@@ -43,7 +44,7 @@ convertStruct' isStruct sg fields =
then Just (unstructType, unstructFields)
else Nothing
where
zero = Number "0"
zero = RawNum 0
typeRange :: Type -> Range
typeRange t =
case ranges of
......@@ -61,13 +62,13 @@ convertStruct' isStruct sg fields =
-- used here because SystemVerilog structs are laid out backwards
fieldLos =
if isStruct
then map simplify $ tail $ scanr (BinOp Add) (Number "0") fieldSizes
else map simplify $ repeat (Number "0")
then map simplify $ tail $ scanr (BinOp Add) (RawNum 0) fieldSizes
else map simplify $ repeat (RawNum 0)
fieldHis =
if isStruct
then map simplify $ init $ scanr (BinOp Add) minusOne fieldSizes
else map simplify $ map (BinOp Add minusOne) fieldSizes
minusOne = UniOp UniSub $ Number "1"
minusOne = UniOp UniSub $ RawNum 1
-- create the mapping structure for the unstructured fields
keys = map snd fields
......@@ -80,7 +81,7 @@ convertStruct' isStruct sg fields =
if isStruct
then foldl1 (BinOp Add) fieldSizes
else head fieldSizes
packedRange = (simplify $ BinOp Sub structSize (Number "1"), zero)
packedRange = (simplify $ BinOp Sub structSize (RawNum 1), zero)
unstructType = IntegerVector TLogic sg [packedRange]
-- check if this struct can be packed into an integer vector; we only
......@@ -208,20 +209,20 @@ convertExpr (t @ IntegerVector{}) (Concat exprs) =
caster = Cast (Left $ dropInnerTypeRange t)
exprs' = map caster exprs
isUnsizedNumber :: Expr -> Bool
isUnsizedNumber (Number n) = not $ elem '\'' n
isUnsizedNumber (Number n) = not $ numberIsSized n
isUnsizedNumber (UniOp UniSub e) = isUnsizedNumber e
isUnsizedNumber _ = False
convertExpr (Struct packing fields (_:rs)) (Concat exprs) =
Concat $ map (convertExpr (Struct packing fields rs)) exprs
convertExpr (Struct packing fields (_:rs)) (Bit e _) =
convertExpr (Struct packing fields rs) e
convertExpr (Struct packing fields []) (Pattern [("", Repeat (Number nStr) exprs)]) =
case fmap fromIntegral (readNumber nStr) of
Just n -> convertExpr (Struct packing fields []) $ Pattern $
zip (repeat "") (concat $ take n $ repeat exprs)
convertExpr (Struct packing fields []) (Pattern [("", Repeat (Number n) exprs)]) =
case fmap fromIntegral (numberToInteger n) of
Just val -> convertExpr (Struct packing fields []) $ Pattern $
zip (repeat "") (concat $ replicate val exprs)
Nothing ->
error $ "unable to handle repeat in pattern: " ++
(show $ Repeat (Number nStr) exprs)
(show $ Repeat (Number n) exprs)
convertExpr (struct @ (Struct _ fields [])) (Pattern itemsOrig) =
if extraNames /= Set.empty then
error $ "pattern " ++ show (Pattern itemsOrig) ++
......@@ -332,7 +333,7 @@ convertSubExpr scopes (Dot e x) =
(fieldType, bounds, dims) = lookupFieldInfo subExprType x
base = fst bounds
len = rangeSize bounds
undotted = if null dims || rangeSize (head dims) == Number "1"
undotted = if null dims || rangeSize (head dims) == RawNum 1
then Bit e' (fst bounds)
else Range e' IndexedMinus (base, len)
convertSubExpr scopes (Range (Dot e x) NonIndexed rOuter) =
......@@ -374,7 +375,7 @@ convertSubExpr scopes (Range (Dot e x) mode (baseO, lenO)) =
NonIndexed -> error "invariant violated"
base = endianCondExpr dim baseDec baseInc
undotted = Range e' mode (base, lenO)
one = Number "1"
one = RawNum 1
convertSubExpr scopes (Range e mode r) =
(dropInnerTypeRange t, Range e' mode r)
where (t, e') = convertSubExpr scopes e
......
......@@ -78,6 +78,9 @@ module Convert.Traverse
, traverseNestedExprsM
, traverseNestedExprs
, collectNestedExprsM
, traverseSinglyNestedExprsM
, traverseSinglyNestedExprs
, collectSinglyNestedExprsM
, traverseNestedLHSsM
, traverseNestedLHSs
, collectNestedLHSsM
......@@ -211,8 +214,13 @@ traverseSinglyNestedStmtsM fullMapper = cs
cs (DoWhile e stmt) = fullMapper stmt >>= return . DoWhile e
cs (Forever stmt) = fullMapper stmt >>= return . Forever
cs (Foreach x vars stmt) = fullMapper stmt >>= return . Foreach x vars
cs (If NoCheck (Number "1") s _) = fullMapper s
cs (If NoCheck (Number "0") _ s) = fullMapper s
cs (If NoCheck (Number n) s1 s2) = do
s1' <- fullMapper s1
s2' <- fullMapper s2
return $ case numberToInteger n of
Nothing -> If NoCheck (Number n) s1' s2'
Just 0 -> s2'
Just _ -> s1'
cs (If u e s1 s2) = do
s1' <- fullMapper s1
s2' <- fullMapper s2
......@@ -379,8 +387,16 @@ collectStmtLHSsM = collectify traverseStmtLHSsM
traverseNestedExprsM :: Monad m => MapperM m Expr -> MapperM m Expr
traverseNestedExprsM mapper = exprMapper
where exprMapper = mapper >=> traverseSinglyNestedExprsM exprMapper
traverseNestedExprs :: Mapper Expr -> Mapper Expr
traverseNestedExprs = unmonad traverseNestedExprsM
collectNestedExprsM :: Monad m => CollectorM m Expr -> CollectorM m Expr
collectNestedExprsM = collectify traverseNestedExprsM
traverseSinglyNestedExprsM :: Monad m => MapperM m Expr -> MapperM m Expr
traverseSinglyNestedExprsM exprMapper = em
where
exprMapper = mapper >=> em
(_, _, _, typeMapper, _) = exprMapperHelpers exprMapper
typeOrExprMapper (Left t) =
typeMapper t >>= return . Left
......@@ -393,7 +409,8 @@ traverseNestedExprsM mapper = exprMapper
e2' <- exprMapper e2
return $ Right (e1', e2')
em (String s) = return $ String s
em (Number s) = return $ Number s
em (Real s) = return $ Real s
em (Number n) = return $ Number n
em (Time s) = return $ Time s
em (Ident i) = return $ Ident i
em (PSIdent x y) = return $ PSIdent x y
......@@ -466,6 +483,11 @@ traverseNestedExprsM mapper = exprMapper
return $ MinTypMax e1' e2' e3'
em (Nil) = return Nil
traverseSinglyNestedExprs :: Mapper Expr -> Mapper Expr
traverseSinglyNestedExprs = unmonad traverseSinglyNestedExprsM
collectSinglyNestedExprsM :: Monad m => CollectorM m Expr -> CollectorM m Expr
collectSinglyNestedExprsM = collectify traverseSinglyNestedExprsM
exprMapperHelpers :: Monad m => MapperM m Expr ->
( MapperM m Range
, MapperM m Decl
......@@ -1033,8 +1055,11 @@ traverseNestedModuleItemsM mapper = fullMapper
Generate subItems -> GenBlock "" subItems
_ -> GenModuleItem moduleItem'
genItemMapper (GenIf _ GenNull GenNull) = return GenNull
genItemMapper (GenIf (Number "1") s _) = return s
genItemMapper (GenIf (Number "0") _ s) = return s
genItemMapper (GenIf (Number n) s1 s2) = do
case numberToInteger n of
Nothing -> return $ GenIf (Number n) s1 s2
Just 0 -> genItemMapper s2
Just _ -> genItemMapper s1
genItemMapper (GenBlock "" [item]) = return item
genItemMapper (GenBlock _ []) = return GenNull
genItemMapper other = return other
......@@ -1049,11 +1074,6 @@ traverseNestedStmts = unmonad traverseNestedStmtsM
collectNestedStmtsM :: Monad m => CollectorM m Stmt -> CollectorM m Stmt
collectNestedStmtsM = collectify traverseNestedStmtsM
traverseNestedExprs :: Mapper Expr -> Mapper Expr
traverseNestedExprs = unmonad traverseNestedExprsM
collectNestedExprsM :: Monad m => CollectorM m Expr -> CollectorM m Expr
collectNestedExprsM = collectify traverseNestedExprsM
-- Traverse all the declaration scopes within a ModuleItem. Note that Functions,
-- Tasks, Always/Initial/Final blocks are all NOT passed through ModuleItem
-- mapper, and Decl ModuleItems are NOT passed through the Decl mapper. The
......
......@@ -6,7 +6,6 @@
module Convert.TypeOf (convert) where
import Data.List (elemIndex)
import Data.Tuple (swap)
import qualified Data.Map.Strict as Map
......@@ -76,8 +75,9 @@ typeof :: Expr -> Scoper Type Type
typeof (Number n) =
return $ IntegerVector TLogic sg [r]
where
(size, sg) = parseNumber n
r = (Number $ show (size - 1), Number "0")
r = (RawNum $ size - 1, RawNum 0)
size = numberBitLength n
sg = if numberIsSigned n then Signed else Unspecified
typeof (Call (Ident x) _) =
typeof $ Ident x
typeof (orig @ (Bit e _)) = do
......@@ -94,8 +94,8 @@ typeof (orig @ (Range e mode r)) = do
lo = fst r
hi = case mode of
NonIndexed -> snd r
IndexedPlus -> BinOp Sub (uncurry (BinOp Add) r) (Number "1")
IndexedMinus -> BinOp Add (uncurry (BinOp Sub) r) (Number "1")
IndexedPlus -> BinOp Sub (uncurry (BinOp Add) r) (RawNum 1)
IndexedMinus -> BinOp Add (uncurry (BinOp Sub) r) (RawNum 1)
typeof (orig @ (Dot e x)) = do
t <- typeof e
case t of
......@@ -133,19 +133,6 @@ typeof (Repeat reps exprs) = return $ typeOfSize size
where size = BinOp Mul reps (concatSize exprs)
typeof other = lookupTypeOf other
-- determines the size and sign of a number literal
parseNumber :: String -> (Integer, Signing)
parseNumber s =
case elemIndex '\'' s of
Nothing -> (32, Signed)
Just 0 -> parseNumber $ '3' : '2' : s
Just idx -> (size, signing)
where
Just size = readNumber $ take idx s
signing = case drop (idx + 1) s of
's' : _ -> Signed
_ -> Unsigned
-- produces a type large enough to hold either expression
largerSizeType :: Expr -> Expr -> Type
largerSizeType a b =
......@@ -158,7 +145,7 @@ largerSizeType a b =
-- returns the total size of concatenated list of expressions
concatSize :: [Expr] -> Expr
concatSize exprs =
foldl (BinOp Add) (Number "0") $
foldl (BinOp Add) (RawNum 0) $
map sizeof exprs
where
sizeof = DimsFn FnBits . Right
......@@ -166,10 +153,10 @@ concatSize exprs =
-- produces a generic type of the given size
typeOfSize :: Expr -> Type
typeOfSize size =
IntegerVector TLogic sg [(hi, Number "0")]
IntegerVector TLogic sg [(hi, RawNum 0)]
where
sg = Unspecified -- suitable for now
hi = BinOp Sub size (Number "1")
hi = BinOp Sub size (RawNum 1)
-- combines a type with unpacked ranges
injectRanges :: Type -> [Range] -> Type
......
......@@ -76,7 +76,7 @@ bindItem ports bind =
where
portName = lookupPort ports (bPort bind)
size = DimsFn FnBits $ Right $ Ident portName
rng = (BinOp Sub size (Number "1"), Number "0")
rng = (BinOp Sub size (RawNum 1), RawNum 0)
typ = Implicit Unspecified [rng]
name = bindName bind
expr = literalFor $ bBit bind
......@@ -102,8 +102,8 @@ convertModuleItemM (Instance moduleName params instanceName [] bindings) = do
expr'' <- traverseNestedExprsM (replaceBindingExpr port) expr'
return (portName, expr'')
replaceBindingExpr :: Port -> Expr -> Writer Binds Expr
replaceBindingExpr port (orig @ (Cast Right{} (Number num))) = do
let ch = last num
replaceBindingExpr port (orig @ (Cast Right{} (ConvertedUU a b))) = do
let ch = charForBit a b
if orig == sizedLiteralFor tag ch
then do
let bind = Bind moduleName ch port
......@@ -120,14 +120,24 @@ convertModuleItem =
traverseTypes (traverseNestedTypes convertType) .
traverseAsgns convertAsgn
digits :: [Char]
digits = ['0', '1', 'x', 'z', 'X', 'Z']
literalFor :: Char -> Expr
literalFor ch =
if elem ch digits
then Number ("1'sb" ++ [ch])
else error $ "unexpected unbased-unsized digit: " ++ [ch]
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]
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"
sizedLiteralFor :: Expr -> Char -> Expr
sizedLiteralFor expr ch =
......@@ -206,7 +216,7 @@ convertExpr (ContextDetermined expr) (UU ch) =
convertExpr _ other = other
pattern UU :: Char -> Expr
pattern UU ch = Number ['\'', ch]
pattern UU ch = Number (UnbasedUnsized ch)
convertType :: Type -> Type
convertType (TypeOf e) = TypeOf $ convertExpr SelfDetermined e
......
......@@ -34,7 +34,7 @@ import qualified Data.Map.Strict as Map
import Convert.Traverse
import Language.SystemVerilog.AST
type Patterns = Map.Map Identifier String
type Patterns = Map.Map Identifier Number
convert :: [AST] -> [AST]
convert = map $ traverseDescriptions convertDescription
......@@ -64,10 +64,7 @@ traverseExprM = traverseNestedExprsM $ stately convertExpr
isPlainPattern :: Patterns -> Expr -> Bool
isPlainPattern _ (Number n) =
not $ any isWildcardChar n
where
isWildcardChar :: Char -> Bool
isWildcardChar = flip elem "xzXZ?"
numberToInteger n /= Nothing
isPlainPattern patterns (Ident x) =
case Map.lookup x patterns of
Nothing -> False
......@@ -81,7 +78,7 @@ convertExpr patterns (BinOp WEq l r) =
else
BinOp BitAnd couldMatch $
BinOp BitOr noExtraXZs $
Number "1'bx"
Number (Based 1 False Binary 0 1)
where
lxl = BinOp BitXor l l
rxr = BinOp BitXor r r
......
......@@ -22,6 +22,7 @@ module Language.SystemVerilog.AST
, module GenItem
, module LHS
, module ModuleItem
, module Number
, module Op
, module Stmt
, module Type
......@@ -40,6 +41,7 @@ import Language.SystemVerilog.AST.Expr as Expr
import Language.SystemVerilog.AST.GenItem as GenItem
import Language.SystemVerilog.AST.LHS as LHS
import Language.SystemVerilog.AST.ModuleItem as ModuleItem
import Language.SystemVerilog.AST.Number as Number
import Language.SystemVerilog.AST.Op as Op
import Language.SystemVerilog.AST.Stmt as Stmt
import Language.SystemVerilog.AST.Type as Type
......
{-# LANGUAGE PatternSynonyms #-}
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
- Initial Verilog AST Author: Tom Hawkins <tomahawkins@gmail.com>
......@@ -17,23 +18,15 @@ module Language.SystemVerilog.AST.Expr
, showAssignment
, showRanges
, showExprOrRange
, simplify
, rangeSize
, rangeSizeHiLo
, endianCondExpr
, endianCondRange
, dimensionsSize
, readNumber
, ParamBinding
, showParams
, pattern RawNum
) where
import Data.Bits (shiftL, shiftR)
import Data.List (intercalate)
import Numeric (readHex)
import Text.Printf (printf)
import Text.Read (readMaybe)
import Language.SystemVerilog.AST.Number (Number(..))
import Language.SystemVerilog.AST.Op
import Language.SystemVerilog.AST.ShowHelp
import {-# SOURCE #-} Language.SystemVerilog.AST.Type
......@@ -43,9 +36,13 @@ type Range = (Expr, Expr)
type TypeOrExpr = Either Type Expr
type ExprOrRange = Either Expr Range
pattern RawNum :: Integer -> Expr
pattern RawNum n = Number (Decimal (-32) True n)
data Expr
= String String
| Number String
| Real String
| Number Number
| Time String
| Ident Identifier
| PSIdent Identifier Identifier
......@@ -71,9 +68,10 @@ data Expr
instance Show Expr where
show (Nil ) = ""
show (Number str ) = str
show (Time str ) = str
show (Ident str ) = str
show (Real str ) = str
show (Number n ) = show n
show (PSIdent x y ) = printf "%s::%s" x y
show (CSIdent x p y) = printf "%s#%s::%s" x (showParams p) y
show (String str ) = printf "\"%s\"" str
......@@ -193,24 +191,6 @@ showExprOrRange :: ExprOrRange -> String
showExprOrRange (Left x) = show x
showExprOrRange (Right x) = show x
clog2Help :: Integer -> Integer -> Integer
clog2Help p n = if p >= n then 0 else 1 + clog2Help (p*2) n
clog2 :: Integer -> Integer
clog2 n = if n < 2 then 0 else clog2Help 1 n
readNumber :: String -> Maybe Integer
readNumber ('3' : '2' : '\'' : 'd' : rest) = readMaybe rest
readNumber ( '\'' : 'd' : rest) = readMaybe rest
readNumber ('3' : '2' : '\'' : 'h' : rest) =
case readHex rest of
[(v, _)] -> Just v
_ -> Nothing
readNumber ('\'' : 'h' : rest) =
case readHex rest of
[(v, _)] -> Just v
_ -> Nothing
readNumber n = readMaybe n
showUniOpPrec :: Expr -> ShowS
showUniOpPrec (e @ UniOp{}) = (showParen True . shows) e
showUniOpPrec (e @ BinOp{}) = (showParen True . shows) e
......@@ -220,154 +200,6 @@ showBinOpPrec :: Expr -> ShowS
showBinOpPrec (e @ BinOp{}) = (showParen True . shows) e
showBinOpPrec e = shows e
-- basic expression simplfication utility to help us generate nicer code in the
-- common case of ranges like `[FOO-1:0]`
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 @ (Repeat (Number n) exprs)) =
case readNumber n of
Nothing -> orig
Just 0 -> Concat []
Just 1 -> Concat exprs
Just x ->
if x < 0
then error $ "negative repeat count: " ++ show orig
else orig
simplify (Concat [expr]) = expr
simplify (Concat exprs) =
Concat $ filter (/= Concat []) exprs
simplify (orig @ (Call (Ident "$clog2") (Args [Number n] []))) =
case readNumber n of
Nothing -> orig
Just x -> toLiteral $ clog2 x
simplify (Mux cc e1 e2) =
case cc' of
Number "1" -> e1'
Number "0" -> e2'
_ -> Mux cc' e1' e2'
where
cc' = simplify cc
e1' = simplify e1
e2' = simplify e2
simplify (Range e NonIndexed r) = Range e NonIndexed r
simplify (Range e _ (i, Number "0")) = Bit e i
simplify (BinOp Sub (Number n1) (BinOp Sub (Number n2) e)) =
simplify $ BinOp Add (BinOp Sub (Number n1) (Number n2)) e
simplify (BinOp Sub (Number n1) (BinOp Sub e (Number n2))) =
simplify $ BinOp Sub (BinOp Add (Number n1) (Number n2)) e
simplify (BinOp Sub (BinOp Add e (Number n1)) (Number n2)) =
simplify $ BinOp Add e (BinOp Sub (Number n1) (Number n2))
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 (toLiteral (x + y)) e'
_ -> nochange
where
e' = simplify e
nochange = BinOp Add (BinOp Sub (Number n1) e') (Number n2)
simplify (BinOp op e1 e2) =
case (op, e1', e2') of
(Add, Number "0", e) -> e
(Add, e, Number "0") -> e
(Mul, _, Number "0") -> Number "0"
(Mul, Number "0", _) -> Number "0"
(Mul, e, Number "1") -> e
(Mul, Number "1", e) -> e
(Sub, e, Number "0") -> e
(Add, BinOp Sub e (Number "1"), Number "1") -> e
(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) -> 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) -> 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) -> 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 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 $ toLiteral (x + y)
_ -> BinOp op e1' e2'
(Sub, e, Number "-1") -> BinOp Add e (Number "1")
_ -> BinOp op e1' e2'
where
e1' = simplify e1
e2' = simplify e2
bool True = Number "1"
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
where
a = rangeSizeHiLo (s, e)
b = rangeSizeHiLo (e, s)
rangeSizeHiLo :: Range -> Expr
rangeSizeHiLo (hi, lo) =
simplify $ BinOp Add (BinOp Sub hi lo) (Number "1")
-- chooses one or the other expression based on the endianness of the given
-- range; [hi:lo] chooses the first expression
endianCondExpr :: Range -> Expr -> Expr -> Expr
endianCondExpr r e1 e2 = simplify $ Mux (uncurry (BinOp Ge) r) e1 e2
-- chooses one or the other range based on the endianness of the given range,
-- but in such a way that the result is itself also usable as a range even if
-- the endianness cannot be resolved during conversion, i.e. if it's dependent
-- on a parameter value; [hi:lo] chooses the first range
endianCondRange :: Range -> Range -> Range -> Range
endianCondRange r r1 r2 =
( endianCondExpr r (fst r1) (fst r2)
, endianCondExpr r (snd r1) (snd r2)
)
dimensionsSize :: [Range] -> Expr
dimensionsSize ranges =
simplify $
foldl (BinOp Mul) (Number "1") $
map rangeSize $
ranges
type ParamBinding = (Identifier, TypeOrExpr)
showParams :: [ParamBinding] -> String
......
......@@ -112,10 +112,10 @@ typeRanges (UnpackedType t rs) = (UnpackedType t, rs)
nullRange :: Type -> ([Range] -> Type)
nullRange t [] = t
nullRange t [(Number "0", Number "0")] = t
nullRange t [(RawNum 0, RawNum 0)] = t
nullRange (IntegerAtom TInteger sg) rs =
-- integer arrays are allowed in SystemVerilog but not in Verilog
IntegerVector TBit sg (rs ++ [(Number "31", Number "0")])
IntegerVector TBit sg (rs ++ [(RawNum 31, RawNum 0)])
nullRange t rs1 =
if t == t'
then error $ "non-vector type " ++ show t ++
......@@ -136,9 +136,9 @@ elaborateIntegerAtom other = other
-- size; if not unspecified, the first signing overrides the second
baseIntType :: Signing -> Signing -> Int -> Type
baseIntType sgOverride sgBase size =
IntegerVector TReg sg [(Number hi, Number "0")]
IntegerVector TReg sg [(RawNum hi, RawNum 0)]
where
hi = show (size - 1)
hi = fromIntegral $ size - 1
sg = if sgOverride /= Unspecified
then sgOverride
else sgBase
......
......@@ -74,9 +74,6 @@ import Language.SystemVerilog.Parser.Tokens
| @binaryNumber
| @hexNumber
| @unbasedUnsizedLiteral
@number
= @integralNumber
| @realNumber
-- Strings
......@@ -366,7 +363,8 @@ tokens :-
@escapedIdentifier { tok Id_escaped }
@systemIdentifier { tok Id_system }
@number { tok Lit_number }
@realNumber { tok Lit_real }
@integralNumber { tok Lit_number }
@string { tok Lit_string }
@time { tok Lit_time }
......
......@@ -295,6 +295,7 @@ import Language.SystemVerilog.Parser.Tokens
simpleIdentifier { Token Id_simple _ _ }
escapedIdentifier { Token Id_escaped _ _ }
systemIdentifier { Token Id_system _ _ }
real { Token Lit_real _ _ }
number { Token Lit_number _ _ }
string { Token Lit_string _ _ }
time { Token Lit_time _ _ }
......@@ -630,10 +631,10 @@ DeclToken :: { DeclToken }
| ExplicitLifetime {% posInject \p -> DTLifetime p $1 }
| "const" PartialType {% posInject \p -> DTType p $2 }
| "{" StreamOp StreamSize Concat "}" {% posInject \p -> DTStream p $2 $3 (map toLHS $4) }
| "{" StreamOp Concat "}" {% posInject \p -> DTStream p $2 (Number "1") (map toLHS $3) }
| "{" StreamOp Concat "}" {% posInject \p -> DTStream p $2 (RawNum 1) (map toLHS $3) }
| opt("var") "type" "(" Expr ")" {% posInject \p -> DTType p (\Unspecified -> \[] -> TypeOf $4) }
| "<=" opt(DelayOrEvent) Expr {% posInject \p -> DTAsgn p AsgnOpNonBlocking $2 $3 }
| IncOrDecOperator {% posInject \p -> DTAsgn p (AsgnOp $1) Nothing (Number "1") }
| IncOrDecOperator {% posInject \p -> DTAsgn p (AsgnOp $1) Nothing (RawNum 1) }
| Identifier "::" Identifier {% posInject \p -> DTPSIdent p $1 $3 }
| Identifier ParamBindings "::" Identifier {% posInject \p -> DTCSIdent p $1 $2 $4 }
DeclTokenAsgn :: { DeclToken }
......@@ -905,7 +906,7 @@ DimensionsNonEmpty :: { [Range] }
| DimensionsNonEmpty Dimension { $1 ++ [$2] }
Dimension :: { Range }
: Range { $1 }
| "[" Expr "]" { (Number "0", BinOp Sub $2 (Number "1")) }
| "[" Expr "]" { (RawNum 0, BinOp Sub $2 (RawNum 1)) }
DeclAsgns :: { [(Identifier, Expr, [Range])] }
: DeclAsgn { [$1] }
......@@ -928,8 +929,8 @@ LHS :: { LHS }
| LHS "[" Expr "]" { LHSBit $1 $3 }
| LHS "." Identifier { LHSDot $1 $3 }
| LHSConcat { LHSConcat $1 }
| "{" StreamOp StreamSize Concat "}" { LHSStream $2 $3 (map toLHS $4) }
| "{" StreamOp Concat "}" { LHSStream $2 (Number "1") (map toLHS $3) }
| "{" StreamOp StreamSize Concat "}" { LHSStream $2 $3 (map toLHS $4) }
| "{" StreamOp Concat "}" { LHSStream $2 (RawNum 1) (map toLHS $3) }
LHSConcat :: { [LHS] }
: "{" LHSs "}" { $2 }
......@@ -972,8 +973,8 @@ StmtAsgn :: { Stmt }
: LHS "=" opt(DelayOrEvent) Expr ";" { Asgn AsgnOpEq $3 $1 $4 }
| LHS "<=" opt(DelayOrEvent) Expr ";" { Asgn AsgnOpNonBlocking $3 $1 $4 }
| LHS AsgnBinOp Expr ";" { Asgn $2 Nothing $1 $3 }
| LHS IncOrDecOperator ";" { Asgn (AsgnOp $2) Nothing $1 (Number "1") }
| IncOrDecOperator LHS ";" { Asgn (AsgnOp $1) Nothing $2 (Number "1") }
| LHS IncOrDecOperator ";" { Asgn (AsgnOp $2) Nothing $1 (RawNum 1) }
| IncOrDecOperator LHS ";" { Asgn (AsgnOp $1) Nothing $2 (RawNum 1) }
| LHS ";" { Subroutine (lhsToExpr $1) (Args [] []) }
| LHS CallArgs ";" { Subroutine (lhsToExpr $1) $2 }
StmtNonAsgn :: { Stmt }
......@@ -1021,7 +1022,7 @@ ForInit :: { Either [Decl] [(LHS, Expr)] }
| DeclTokens(";") { parseDTsAsDeclsOrAsgns $1 }
ForCond :: { Expr }
: ";" { Number "1" }
: ";" { RawNum 1 }
| Expr ";" { $1 }
ForStep :: { [(LHS, AsgnOp, Expr)] }
......@@ -1032,8 +1033,8 @@ ForStepNonEmpty :: { [(LHS, AsgnOp, Expr)] }
| ForStepNonEmpty "," ForStepAssignment { $1 ++ [$3] }
ForStepAssignment :: { (LHS, AsgnOp, Expr) }
: LHS AsgnOp Expr { ($1, $2, $3) }
| IncOrDecOperator LHS { ($2, AsgnOp $1, Number "1") }
| LHS IncOrDecOperator { ($1, AsgnOp $2, Number "1") }
| IncOrDecOperator LHS { ($2, AsgnOp $1, RawNum 1) }
| LHS IncOrDecOperator { ($1, AsgnOp $2, RawNum 1) }
IdxVars :: { [Identifier] }
: "[" IdxVarsInside "]" { $2 }
......@@ -1122,8 +1123,11 @@ InsideCase :: { ([ExprOrRange], Stmt) }
: OpenRangeList ":" Stmt { ($1, $3) }
| "default" opt(":") Stmt { ([], $3) }
Number :: { String }
: number { tokenString $1 }
Real :: { String }
: real { tokenString $1 }
Number :: { Number }
: number { parseNumber $ tokenString $1 }
String :: { String }
: string { tail $ init $ tokenString $1 }
......@@ -1169,11 +1173,12 @@ ValueRange :: { ExprOrRange }
Expr :: { Expr }
: "(" Expr ")" { $2 }
| String { String $1 }
| Real { Real $1 }
| Number { Number $1 }
| Time { Time $1 }
| Expr CallArgs { Call $1 $2 }
| DimsFn "(" TypeOrExpr ")" { DimsFn $1 $3 }
| DimFn "(" TypeOrExpr ")" { DimFn $1 $3 (Number "1") }
| DimFn "(" TypeOrExpr ")" { DimFn $1 $3 (RawNum 1) }
| DimFn "(" TypeOrExpr "," Expr ")" { DimFn $1 $3 $5 }
| Expr PartSelect { Range $1 (fst $2) (snd $2) }
| Expr "[" Expr "]" { Bit $1 $3 }
......@@ -1184,8 +1189,8 @@ Expr :: { Expr }
| "'" "{" PatternItems "}" { Pattern $3 }
| CastingType "'" "(" Expr ")" { Cast (Left $1) $4 }
| Expr "'" "(" Expr ")" { Cast (Right $1) $4 }
| "{" StreamOp StreamSize Concat "}" { Stream $2 $3 $4 }
| "{" StreamOp Concat "}" { Stream $2 (Number "1") $3 }
| "{" StreamOp StreamSize Concat "}" { Stream $2 $3 $4 }
| "{" StreamOp Concat "}" { Stream $2 (RawNum 1) $3 }
| Expr "inside" "{" OpenRangeList "}" { Inside $1 $4 }
| "(" Expr ":" Expr ":" Expr ")" { MinTypMax $2 $4 $6 }
| Identifier %prec REDUCE_OP {- defer -} { Ident $1 }
......@@ -1302,8 +1307,8 @@ GenvarInitialization :: { Expr -> (Identifier, AsgnOp, Expr) -> GenItem -> GenIt
GenvarIteration :: { (Identifier, AsgnOp, Expr) }
: Identifier AsgnOp Expr { ($1, $2, $3) }
| IncOrDecOperator Identifier { ($2, AsgnOp $1, Number "1") }
| Identifier IncOrDecOperator { ($1, AsgnOp $2, Number "1") }
| IncOrDecOperator Identifier { ($2, AsgnOp $1, RawNum 1) }
| Identifier IncOrDecOperator { ($1, AsgnOp $2, RawNum 1) }
AsgnOp :: { AsgnOp }
: "=" { AsgnOpEq }
......
......@@ -183,7 +183,7 @@ parseDTsAsIntantiations (DTIdent _ name : tokens) =
follow = if null toks' then [] else step (tail toks')
asRange :: DeclToken -> Range
asRange (DTRange _ (NonIndexed, s)) = s
asRange (DTBit _ s) = (Number "0", BinOp Sub s (Number "1"))
asRange (DTBit _ s) = (RawNum 0, BinOp Sub s (RawNum 1))
asRange _ = failure
failure = error $ "unrecognized instantiation of " ++ name
++ ": " ++ show inst
......@@ -439,14 +439,14 @@ takeRanges (token : tokens) =
_ -> ([] , token : tokens)
where
(rs, rest) = takeRanges tokens
asRange s = (Number "0", BinOp Sub s (Number "1"))
asRange s = (RawNum 0, BinOp Sub s (RawNum 1))
autoDim :: [a] -> ([Range], [DeclToken])
autoDim l =
((lo, hi) : rs, rest)
where
n = length l
lo = Number "0"
hi = Number $ show (n - 1)
lo = RawNum 0
hi = RawNum $ fromIntegral $ n - 1
-- Matching `AsgnOpEq` and `AsgnOpNonBlocking` here allows tripLookahead to work
-- both for standard declarations and in `parseDTsAsDeclOrStmt`, where we're
......
......@@ -302,6 +302,7 @@ data TokenName
| Id_simple
| Id_escaped
| Id_system
| Lit_real
| Lit_number
| Lit_string
| Lit_time
......
......@@ -43,6 +43,7 @@ executable sv2v
Language.SystemVerilog.AST.GenItem
Language.SystemVerilog.AST.LHS
Language.SystemVerilog.AST.ModuleItem
Language.SystemVerilog.AST.Number
Language.SystemVerilog.AST.Op
Language.SystemVerilog.AST.ShowHelp
Language.SystemVerilog.AST.Stmt
......@@ -64,6 +65,7 @@ executable sv2v
Convert.DuplicateGenvar
Convert.EmptyArgs
Convert.Enum
Convert.ExprUtils
Convert.ForDecl
Convert.Foreach
Convert.FuncRet
......
......@@ -25,6 +25,14 @@ module top;
$display($size(Ram[0]));
$display($bits(foo));
$display("args %b", $size(RamPair, 1));
$display("args %b", $size(RamPair, 1'b1));
$display("args %b", $size(RamPair, '1));
$display("args %b", $size(RamPair, 'o1));
$display("args %b", $size(RamPair, 1'h1));
$display("args %b", $size(RamPair, 1'd1));
$display("args %b", $size(RamPair, 1'dx));
`EXHAUST(Ram);
`EXHAUST(Ram[0+:2]);
`EXHAUST(Ram[1+:2]);
......
......@@ -5,6 +5,14 @@ module top;
$display(16);
$display(3);
$display("args %b", 2);
$display("args %b", 2);
$display("args %b", 2);
$display("args %b", 2);
$display("args %b", 2);
$display("args %b", 2);
$display("args %b", 1'bx);
$display(10, 10, 16);
$display(0, 0, 16);
$display(9, 9, 1);
......
module top;
localparam X = 1 / 0;
localparam Y = 'dx;
localparam Z = 40'dx____;
initial $display("%b", X);
initial $display("%b", Y);
initial $display("%b", Z);
endmodule
`include "div.sv"
`define TEST(N) \
$display(`"N -> %0d %b`", N, N); \
$display(`"$bits(N) -> %0d`", $bits(N));
module top;
initial begin
`TEST(0) `TEST(1) `TEST(2)
`TEST(-0) `TEST(-1) `TEST(-2)
`TEST('d0) `TEST('d1) `TEST('d2)
`TEST('sd0) `TEST('sd1) `TEST('sd2)
`TEST('b0) `TEST('b1) `TEST('b10)
`TEST('sd0) `TEST('sd1) `TEST('sd2)
`TEST(1'sox) `TEST(2'sox) `TEST(3'sox) `TEST(7'sox) `TEST(8'sox) `TEST(9'sox) `TEST(9'soxx) `TEST(10'soxx)
`TEST(1'soz) `TEST(2'soz) `TEST(3'soz) `TEST(7'soz) `TEST(8'soz) `TEST(9'soz) `TEST(9'sozz) `TEST(10'sozz)
`TEST(1'SOZ) `TEST(2'SOZ) `TEST(3'SOZ) `TEST(7'SOZ) `TEST(8'SOZ) `TEST(9'SOZ) `TEST(9'SOZZ) `TEST(10'SOZZ)
`TEST(1234_5678) `TEST('h1234_5678) `TEST('o1234_5677) `TEST('b0101_1100)
`TEST('d4294967295) `TEST('d4294967296) `TEST('d4294967297) `TEST('d4294967298) `TEST('d4294967299)
`TEST('d004294967295) `TEST('d004294967296) `TEST('d004294967297) `TEST('d004294967298) `TEST('d004294967299)
`TEST(4294967295) `TEST(4294967296) `TEST(4294967297) `TEST(4294967298) `TEST(4294967299)
`TEST(-4294967295) `TEST(-4294967297) `TEST(-4294967298) `TEST(-4294967299)
`TEST(-8589934593) `TEST(8589934592) `TEST(8589934593)
// iverlog does weird things with these: `TEST(-4294967296) `TEST(-8589934592)
`TEST(659) `TEST('h 837FF) `TEST('o7460)
`TEST(4'b1001) `TEST(5 'D 3) `TEST(3'b01x) `TEST(12'hx) `TEST(16'hz)
`TEST(-8 'd 6) `TEST(4 'shf) `TEST(-4 'sd15) `TEST(16'sd?)
`TEST('bx) `TEST('bz) `TEST('bzx) `TEST('bxz)
`TEST(3'bx) `TEST(3'b1x) `TEST(3'bx1) `TEST('b1x) `TEST('bx1) `TEST(3'b0x1) `TEST(3'b0z1)
`TEST('hf & 10'hf) `TEST(7'hf & 10'hf)
`TEST('b01xz01xz01xz01xz01xz01xz01xz01xz01xz) `TEST('b101xz01xz01xz01xz01xz01xz01xz01xz01xz)
`TEST(36'b01xz01xz01xz01xz01xz01xz01xz01xz01xz) `TEST(37'b01xz01xz01xz01xz01xz01xz01xz01xz01xz)
`TEST(36'sb01xz01xz01xz01xz01xz01xz01xz01xz01xz) `TEST(37'sb01xz01xz01xz01xz01xz01xz01xz01xz01xz)
`TEST('h01xz01xz) `TEST('h101xz01xz)
`TEST(36'h01xz01xz) `TEST(37'h01xz01xz)
`TEST(36'hb01xz01xz) `TEST(37'hb01xz01xz)
end
endmodule
`include "number.sv"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment