mirror of https://github.com/zachjs/sv2v.git
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
This commit is contained in:
parent
737c66a6c9
commit
d88c516d33
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -0,0 +1,199 @@
|
|||
{-# 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
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
{-# 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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,298 @@
|
|||
{- sv2v
|
||||
- Author: Zachary Snow <zach@zachjs.com>
|
||||
-
|
||||
- SystemVerilog number literals
|
||||
-}
|
||||
|
||||
module Language.SystemVerilog.AST.Number
|
||||
( Number (..)
|
||||
, Base (..)
|
||||
, parseNumber
|
||||
, numberBitLength
|
||||
, numberIsSigned
|
||||
, numberIsSized
|
||||
, numberToInteger
|
||||
) where
|
||||
|
||||
import Data.Char (digitToInt, intToDigit, toLower)
|
||||
import Data.List (elemIndex)
|
||||
import Text.Read (readMaybe)
|
||||
|
||||
-- normalize the number first, making everything lowercase and removing
|
||||
-- visual niceties like spaces and underscores
|
||||
parseNumber :: String -> Number
|
||||
parseNumber = parseNumber' . map toLower . filter (not . isPad)
|
||||
where isPad ch = ch == '_' || ch == ' '
|
||||
|
||||
parseNumber' :: String -> Number
|
||||
parseNumber' ['\'', ch] = UnbasedUnsized ch
|
||||
parseNumber' str =
|
||||
-- simple decimal number
|
||||
if maybeIdx == Nothing then
|
||||
let n = readDecimal str
|
||||
in Decimal (negate $ decimalSize True n) True n
|
||||
-- non-decimal based integral number
|
||||
else if maybeBase /= Nothing then
|
||||
let (values, kinds) = parseBasedDigits (baseSize base) digitsExtended
|
||||
in Based size signed base values kinds
|
||||
-- decimal X or Z literal
|
||||
else if numDigits == 1 && elem leadDigit xzDigits then
|
||||
let (vals, knds) = parseBasedDigits 2 $ replicate (abs size) leadDigit
|
||||
in Based size signed Binary vals knds
|
||||
-- explicitly-based decimal number
|
||||
else
|
||||
let num = readDecimal digits
|
||||
in if rawSize == 0
|
||||
then Decimal (negate $ decimalSize signed num) signed num
|
||||
else Decimal size signed num
|
||||
where
|
||||
-- pull out the components of the literals
|
||||
maybeIdx = elemIndex '\'' str
|
||||
Just idx = maybeIdx
|
||||
signBasedAndDigits = drop (idx + 1) str
|
||||
(signed, baseAndDigits) = takeSign signBasedAndDigits
|
||||
(maybeBase, digits) = takeBase baseAndDigits
|
||||
|
||||
-- high-order X or Z is extended up to the size of the literal
|
||||
leadDigit = head digits
|
||||
numDigits = length digits
|
||||
digitsExtended =
|
||||
if elem leadDigit xzDigits
|
||||
then replicate (sizeDigits - numDigits) leadDigit ++ digits
|
||||
else digits
|
||||
|
||||
-- determine the number of digits needed based on the size
|
||||
sizeDigits = ((abs size) `div` bitsPerDigit) + sizeExtraDigit
|
||||
sizeExtraDigit =
|
||||
if (abs size) `mod` bitsPerDigit == 0
|
||||
then 0
|
||||
else 1
|
||||
|
||||
-- determine the explicit size of the literal in bites
|
||||
Just base = maybeBase
|
||||
rawSize =
|
||||
if idx == 0
|
||||
then 0
|
||||
else readDecimal $ take idx str
|
||||
size =
|
||||
if rawSize /= 0 then
|
||||
rawSize
|
||||
else if maybeBase /= Nothing then
|
||||
negate $ max 32 (bitsPerDigit * numDigits)
|
||||
else
|
||||
-32
|
||||
bitsPerDigit = bits $ baseSize base - 1
|
||||
|
||||
-- read a simple unsigned decimal number
|
||||
readDecimal :: Read a => String -> a
|
||||
readDecimal str =
|
||||
case readMaybe str of
|
||||
Nothing -> error $ "could not parse decimal " ++ show str
|
||||
Just n -> n
|
||||
|
||||
-- returns the number of bits necessary to represent a number; it gives an extra
|
||||
-- bit for signed numbers so that the literal doesn't sign extend unnecessarily
|
||||
decimalSize :: Bool -> Integer -> Int
|
||||
decimalSize True = max 32 . fromIntegral . bits . (* 2)
|
||||
decimalSize False = max 32 . fromIntegral . bits
|
||||
|
||||
-- remove the leading sign specified, if it is present
|
||||
takeSign :: String -> (Bool, String)
|
||||
takeSign ('s' : rest) = (True, rest)
|
||||
takeSign rest = (False, rest)
|
||||
|
||||
-- pop the leading base specified from a based coda
|
||||
takeBase :: String -> (Maybe Base, String)
|
||||
takeBase ('d' : rest) = (Nothing, rest)
|
||||
takeBase ('b' : rest) = (Just Binary, rest)
|
||||
takeBase ('o' : rest) = (Just Octal, rest)
|
||||
takeBase ('h' : rest) = (Just Hex, rest)
|
||||
takeBase rest = error $ "cannot parse based coda " ++ show rest
|
||||
|
||||
-- convert the digits of a based number to its corresponding value and kind bits
|
||||
parseBasedDigits :: Integer -> String -> (Integer, Integer)
|
||||
parseBasedDigits base str =
|
||||
(values, kinds)
|
||||
where
|
||||
values = parseDigits parseValueDigit str
|
||||
kinds = parseDigits parseKindDigit str
|
||||
|
||||
parseDigits :: (Char -> Integer) -> String -> Integer
|
||||
parseDigits f = foldl sumStep 0 . map f
|
||||
sumStep :: Integer -> Integer -> Integer
|
||||
sumStep total digit = total * base + digit
|
||||
|
||||
parseValueDigit :: Char -> Integer
|
||||
parseValueDigit x =
|
||||
if elem x xDigits then
|
||||
0
|
||||
else if elem x zDigits then
|
||||
base - 1
|
||||
else
|
||||
fromIntegral $ digitToInt x
|
||||
|
||||
parseKindDigit :: Char -> Integer
|
||||
parseKindDigit x =
|
||||
if elem x xzDigits
|
||||
then base - 1
|
||||
else 0
|
||||
|
||||
xDigits :: [Char]
|
||||
xDigits = ['x']
|
||||
zDigits :: [Char]
|
||||
zDigits = ['z', '?']
|
||||
xzDigits :: [Char]
|
||||
xzDigits = xDigits ++ zDigits
|
||||
|
||||
data Base
|
||||
= Binary
|
||||
| Octal
|
||||
| Hex
|
||||
deriving (Eq, Ord)
|
||||
|
||||
instance Show Base where
|
||||
show Binary = "b"
|
||||
show Octal = "o"
|
||||
show Hex = "h"
|
||||
|
||||
data Number
|
||||
= UnbasedUnsized Char
|
||||
| Decimal Int Bool Integer
|
||||
| Based Int Bool Base Integer Integer
|
||||
deriving (Eq, Ord)
|
||||
|
||||
baseSize :: Integral a => Base -> a
|
||||
baseSize Binary = 2
|
||||
baseSize Octal = 8
|
||||
baseSize Hex = 16
|
||||
|
||||
-- get the number of bits in a number
|
||||
numberBitLength :: Number -> Integer
|
||||
numberBitLength UnbasedUnsized{} = 32
|
||||
numberBitLength (Decimal size _ _) = fromIntegral $ abs size
|
||||
numberBitLength (Based size _ _ _ _) = fromIntegral $ abs size
|
||||
|
||||
-- get whether or not a number is signed
|
||||
numberIsSized :: Number -> Bool
|
||||
numberIsSized UnbasedUnsized{} = False
|
||||
numberIsSized (Decimal size _ _) = size > 0
|
||||
numberIsSized (Based size _ _ _ _) = size > 0
|
||||
|
||||
-- get whether or not a number is signed
|
||||
numberIsSigned :: Number -> Bool
|
||||
numberIsSigned UnbasedUnsized{} = False
|
||||
numberIsSigned (Decimal _ signed _) = signed
|
||||
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{} = Nothing
|
||||
numberToInteger (Decimal _ _ num) = Just num
|
||||
numberToInteger (Based _ _ _ num 0) = Just num
|
||||
numberToInteger Based{} = Nothing
|
||||
|
||||
-- return the number of bits in a number (i.e. ilog2)
|
||||
bits :: Integral a => a -> a
|
||||
bits 0 = 0
|
||||
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 (Decimal (-32) True value) =
|
||||
if value < 0
|
||||
then error $ "illegal decimal: " ++ show value
|
||||
else show value
|
||||
show (Decimal size signed value) =
|
||||
if size == 0
|
||||
then error $ "illegal decimal literal: "
|
||||
++ show (size, signed, value)
|
||||
else sizeStr ++ '\'' : signedStr ++ 'd' : valueStr
|
||||
where
|
||||
sizeStr = if size > 0 then show size else ""
|
||||
signedStr = if signed then "s" else ""
|
||||
valueStr = show value
|
||||
show (Based size signed base value kinds) =
|
||||
if size == 0 || value < 0 || kinds < 0
|
||||
then error $ "illegal based literal: "
|
||||
++ show (size, signed, base, value, kinds)
|
||||
else sizeStr ++ '\'' : signedStr ++ baseCh : valueStr
|
||||
where
|
||||
sizeStr = if size > 0 then show size else ""
|
||||
signedStr = if signed then "s" else ""
|
||||
[baseCh] = show base
|
||||
valueStr = showBasedDigits (baseSize base) size value kinds
|
||||
|
||||
showBasedDigits :: Int -> Int -> Integer -> Integer -> String
|
||||
showBasedDigits base size values kinds =
|
||||
if numDigits > sizeDigits then
|
||||
error $ "invalid based literal digits: "
|
||||
++ show (base, size, values, kinds, numDigits, sizeDigits)
|
||||
else if size < -32 then
|
||||
padList '0' sizeDigits digits
|
||||
else if leadingXZ && size < 0 then
|
||||
removeExtraPadding digits
|
||||
else if leadingXZ then
|
||||
padList '0' sizeDigits digits
|
||||
else
|
||||
digits
|
||||
where
|
||||
valChunks = chunk (fromIntegral base) values
|
||||
kndChunks = chunk (fromIntegral base) kinds
|
||||
numDigits = max (length valChunks) (length kndChunks)
|
||||
|
||||
digits = zipWith combineChunks
|
||||
(padList 0 numDigits valChunks)
|
||||
(padList 0 numDigits kndChunks)
|
||||
leadingXZ = elem (head digits) xzDigits
|
||||
|
||||
removeExtraPadding :: String -> String
|
||||
removeExtraPadding ('x' : 'x' : chs) = removeExtraPadding ('x' : chs)
|
||||
removeExtraPadding ('z' : 'z' : chs) = removeExtraPadding ('z' : chs)
|
||||
removeExtraPadding chs = chs
|
||||
|
||||
-- determine the number of digits needed based on the explicit size
|
||||
sizeDigits = ((abs size) `div` bitsPerDigit) + sizeExtraDigit
|
||||
sizeExtraDigit =
|
||||
if (abs size) `mod` bitsPerDigit == 0
|
||||
then 0
|
||||
else 1
|
||||
bitsPerDigit = bits $ base - 1
|
||||
|
||||
-- combine a value and kind digit into their corresponding character
|
||||
combineChunks :: Int -> Int -> Char
|
||||
combineChunks value kind =
|
||||
if kind == 0 then
|
||||
intToDigit value
|
||||
else if kind /= base - 1 then
|
||||
invalid
|
||||
else if value == 0 then
|
||||
'x'
|
||||
else if value == base - 1 then
|
||||
'z'
|
||||
else
|
||||
invalid
|
||||
where
|
||||
invalid = error $ "based bits inconsistent: "
|
||||
++ show (base, values, kinds, value, kind)
|
||||
|
||||
-- pad the left side of a list with `padding` to be at least `size` elements
|
||||
padList :: a -> Int -> [a] -> [a]
|
||||
padList padding size values =
|
||||
replicate (size - length values) padding ++ values
|
||||
|
||||
-- split an integer into chunks of `base` bits
|
||||
chunk :: Integer -> Integer -> [Int]
|
||||
chunk base n0 =
|
||||
reverse $ chunkStep (quotRem n0 base)
|
||||
where
|
||||
chunkStep (n, d) =
|
||||
case n of
|
||||
0 -> [d']
|
||||
_ -> d' : chunkStep (quotRem n base)
|
||||
where d' = fromIntegral d
|
||||
|
|
@ -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] }
|
||||
|
|
@ -929,7 +930,7 @@ LHS :: { LHS }
|
|||
| 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 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 }
|
||||
|
|
@ -1185,7 +1190,7 @@ Expr :: { Expr }
|
|||
| 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 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);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
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
|
||||
|
|
@ -0,0 +1 @@
|
|||
`include "div.sv"
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
`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
|
||||
|
|
@ -0,0 +1 @@
|
|||
`include "number.sv"
|
||||
Loading…
Reference in New Issue