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