2020-01-11 22:22:07 +01:00
|
|
|
{- sv2v
|
|
|
|
|
- Author: Zachary Snow <zach@zachjs.com>
|
|
|
|
|
-
|
|
|
|
|
- Conversion for the `type` operator
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
module Convert.TypeOf (convert) where
|
|
|
|
|
|
2020-06-21 04:39:13 +02:00
|
|
|
import Data.Tuple (swap)
|
2020-01-11 22:22:07 +01:00
|
|
|
import qualified Data.Map.Strict as Map
|
|
|
|
|
|
2020-07-03 02:50:26 +02:00
|
|
|
import Convert.Scoper
|
2020-01-11 22:22:07 +01:00
|
|
|
import Convert.Traverse
|
|
|
|
|
import Language.SystemVerilog.AST
|
|
|
|
|
|
|
|
|
|
convert :: [AST] -> [AST]
|
2020-07-03 02:50:26 +02:00
|
|
|
convert = map $ traverseDescriptions $ partScoper
|
|
|
|
|
traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM
|
2020-01-11 22:22:07 +01:00
|
|
|
|
2020-07-03 02:50:26 +02:00
|
|
|
traverseDeclM :: Decl -> Scoper Type Decl
|
2020-01-11 22:22:07 +01:00
|
|
|
traverseDeclM decl = do
|
|
|
|
|
item <- traverseModuleItemM (MIPackageItem $ Decl decl)
|
|
|
|
|
let MIPackageItem (Decl decl') = item
|
2020-01-12 02:35:51 +01:00
|
|
|
case decl' of
|
2020-06-14 21:56:09 +02:00
|
|
|
Variable d t ident a e -> do
|
2020-01-12 02:35:51 +01:00
|
|
|
let t' = injectRanges t a
|
2020-07-03 02:50:26 +02:00
|
|
|
insertElem ident t'
|
2020-01-12 02:35:51 +01:00
|
|
|
return $ case t' of
|
2020-06-14 21:56:09 +02:00
|
|
|
UnpackedType t'' a' -> Variable d t'' ident a' e
|
|
|
|
|
_ -> Variable d t' ident [] e
|
2020-01-12 02:35:51 +01:00
|
|
|
Param _ t ident _ -> do
|
2020-02-09 23:05:58 +01:00
|
|
|
let t' = if t == Implicit Unspecified []
|
|
|
|
|
then IntegerAtom TInteger Unspecified
|
|
|
|
|
else t
|
2020-07-03 02:50:26 +02:00
|
|
|
insertElem ident t'
|
2020-01-12 02:35:51 +01:00
|
|
|
return decl'
|
2020-01-31 04:17:17 +01:00
|
|
|
ParamType{} -> return decl'
|
|
|
|
|
CommentDecl{} -> return decl'
|
2020-01-11 22:22:07 +01:00
|
|
|
|
2020-07-03 02:50:26 +02:00
|
|
|
traverseModuleItemM :: ModuleItem -> Scoper Type ModuleItem
|
2020-07-16 02:44:57 +02:00
|
|
|
traverseModuleItemM = traverseTypesM $ traverseNestedTypesM traverseTypeM
|
2020-01-11 22:22:07 +01:00
|
|
|
|
2020-07-03 02:50:26 +02:00
|
|
|
traverseGenItemM :: GenItem -> Scoper Type GenItem
|
|
|
|
|
traverseGenItemM = traverseGenItemExprsM traverseExprM
|
2020-01-11 22:22:07 +01:00
|
|
|
|
2020-07-03 02:50:26 +02:00
|
|
|
traverseStmtM :: Stmt -> Scoper Type Stmt
|
|
|
|
|
traverseStmtM = traverseStmtExprsM traverseExprM
|
|
|
|
|
|
|
|
|
|
traverseExprM :: Expr -> Scoper Type Expr
|
2020-07-16 02:44:57 +02:00
|
|
|
traverseExprM = traverseNestedExprsM $ traverseExprTypesM $
|
|
|
|
|
traverseNestedTypesM traverseTypeM
|
2020-07-03 02:50:26 +02:00
|
|
|
|
|
|
|
|
traverseTypeM :: Type -> Scoper Type Type
|
2020-01-11 22:22:07 +01:00
|
|
|
traverseTypeM (TypeOf expr) = typeof expr
|
|
|
|
|
traverseTypeM other = return other
|
|
|
|
|
|
2020-07-03 02:50:26 +02:00
|
|
|
lookupTypeOf :: Expr -> Scoper Type Type
|
|
|
|
|
lookupTypeOf expr = do
|
2020-07-15 06:22:41 +02:00
|
|
|
details <- lookupElemM expr
|
2020-07-03 02:50:26 +02:00
|
|
|
case details of
|
|
|
|
|
Nothing -> return $ TypeOf expr
|
|
|
|
|
-- functions with no return type implicitly return a single bit
|
|
|
|
|
Just (_, _, Implicit Unspecified []) ->
|
|
|
|
|
return $ IntegerVector TLogic Unspecified []
|
|
|
|
|
Just (_, replacements, typ) ->
|
2020-07-16 02:44:57 +02:00
|
|
|
return $ if Map.null replacements
|
|
|
|
|
then typ
|
|
|
|
|
else rewriteType typ
|
2020-07-03 02:50:26 +02:00
|
|
|
where
|
|
|
|
|
rewriteType = traverseNestedTypes $ traverseTypeExprs $
|
|
|
|
|
traverseNestedExprs replace
|
|
|
|
|
replace :: Expr -> Expr
|
|
|
|
|
replace (Ident x) =
|
|
|
|
|
Map.findWithDefault (Ident x) x replacements
|
|
|
|
|
replace other = other
|
|
|
|
|
|
|
|
|
|
typeof :: Expr -> Scoper Type Type
|
2020-06-07 18:47:35 +02:00
|
|
|
typeof (Number n) =
|
|
|
|
|
return $ IntegerVector TLogic sg [r]
|
|
|
|
|
where
|
2020-07-12 23:06:27 +02:00
|
|
|
r = (RawNum $ size - 1, RawNum 0)
|
|
|
|
|
size = numberBitLength n
|
|
|
|
|
sg = if numberIsSigned n then Signed else Unspecified
|
2020-07-18 03:18:48 +02:00
|
|
|
typeof (Call (Ident "$unsigned") (Args [e] [])) =
|
|
|
|
|
typeof e
|
|
|
|
|
typeof (Call (Ident "$signed") (Args [e] [])) =
|
|
|
|
|
typeof e
|
2020-07-03 02:50:26 +02:00
|
|
|
typeof (Call (Ident x) _) =
|
|
|
|
|
typeof $ Ident x
|
2020-01-12 04:52:12 +01:00
|
|
|
typeof (orig @ (Bit e _)) = do
|
|
|
|
|
t <- typeof e
|
2020-07-03 02:50:26 +02:00
|
|
|
case t of
|
|
|
|
|
TypeOf _ -> lookupTypeOf orig
|
|
|
|
|
_ -> return $ popRange t
|
2020-01-12 04:52:12 +01:00
|
|
|
typeof (orig @ (Range e mode r)) = do
|
|
|
|
|
t <- typeof e
|
|
|
|
|
return $ case t of
|
|
|
|
|
TypeOf _ -> TypeOf orig
|
|
|
|
|
_ -> replaceRange (lo, hi) t
|
|
|
|
|
where
|
|
|
|
|
lo = fst r
|
|
|
|
|
hi = case mode of
|
|
|
|
|
NonIndexed -> snd r
|
2020-07-12 23:06:27 +02:00
|
|
|
IndexedPlus -> BinOp Sub (uncurry (BinOp Add) r) (RawNum 1)
|
|
|
|
|
IndexedMinus -> BinOp Add (uncurry (BinOp Sub) r) (RawNum 1)
|
2020-06-21 04:39:13 +02:00
|
|
|
typeof (orig @ (Dot e x)) = do
|
|
|
|
|
t <- typeof e
|
2020-07-03 02:50:26 +02:00
|
|
|
case t of
|
2020-06-21 04:39:13 +02:00
|
|
|
Struct _ fields [] ->
|
2020-07-03 02:50:26 +02:00
|
|
|
return $ fieldsType fields
|
|
|
|
|
Union _ fields [] ->
|
|
|
|
|
return $ fieldsType fields
|
|
|
|
|
_ -> lookupTypeOf orig
|
|
|
|
|
where
|
|
|
|
|
fieldsType :: [Field] -> Type
|
|
|
|
|
fieldsType fields =
|
2020-06-21 04:39:13 +02:00
|
|
|
case lookup x $ map swap fields of
|
|
|
|
|
Just typ -> typ
|
|
|
|
|
Nothing -> TypeOf orig
|
2020-06-07 18:47:35 +02:00
|
|
|
typeof (Cast (Right s) _) = return $ typeOfSize s
|
2020-06-15 03:43:32 +02:00
|
|
|
typeof (UniOp UniSub e ) = typeof e
|
2020-06-07 18:47:35 +02:00
|
|
|
typeof (UniOp BitNot e ) = typeof e
|
|
|
|
|
typeof (BinOp Pow e _) = typeof e
|
|
|
|
|
typeof (BinOp ShiftL e _) = typeof e
|
|
|
|
|
typeof (BinOp ShiftR e _) = typeof e
|
|
|
|
|
typeof (BinOp ShiftAL e _) = typeof e
|
|
|
|
|
typeof (BinOp ShiftAR e _) = typeof e
|
|
|
|
|
typeof (BinOp Add a b) = return $ largerSizeType a b
|
|
|
|
|
typeof (BinOp Sub a b) = return $ largerSizeType a b
|
|
|
|
|
typeof (BinOp Mul a b) = return $ largerSizeType a b
|
|
|
|
|
typeof (BinOp Div a b) = return $ largerSizeType a b
|
|
|
|
|
typeof (BinOp Mod a b) = return $ largerSizeType a b
|
|
|
|
|
typeof (BinOp BitAnd a b) = return $ largerSizeType a b
|
|
|
|
|
typeof (BinOp BitXor a b) = return $ largerSizeType a b
|
|
|
|
|
typeof (BinOp BitXnor a b) = return $ largerSizeType a b
|
|
|
|
|
typeof (BinOp BitOr a b) = return $ largerSizeType a b
|
|
|
|
|
typeof (Mux _ a b) = return $ largerSizeType a b
|
|
|
|
|
typeof (Concat exprs) = return $ typeOfSize $ concatSize exprs
|
|
|
|
|
typeof (Repeat reps exprs) = return $ typeOfSize size
|
|
|
|
|
where size = BinOp Mul reps (concatSize exprs)
|
2020-07-03 02:50:26 +02:00
|
|
|
typeof other = lookupTypeOf other
|
2020-01-11 22:22:07 +01:00
|
|
|
|
2020-06-07 18:47:35 +02:00
|
|
|
-- produces a type large enough to hold either expression
|
|
|
|
|
largerSizeType :: Expr -> Expr -> Type
|
|
|
|
|
largerSizeType a b =
|
|
|
|
|
typeOfSize larger
|
|
|
|
|
where
|
|
|
|
|
sizeof = DimsFn FnBits . Right
|
|
|
|
|
cond = BinOp Ge (sizeof a) (sizeof b)
|
|
|
|
|
larger = Mux cond (sizeof a) (sizeof b)
|
|
|
|
|
|
|
|
|
|
-- returns the total size of concatenated list of expressions
|
|
|
|
|
concatSize :: [Expr] -> Expr
|
|
|
|
|
concatSize exprs =
|
2020-07-12 23:06:27 +02:00
|
|
|
foldl (BinOp Add) (RawNum 0) $
|
2020-06-07 18:47:35 +02:00
|
|
|
map sizeof exprs
|
|
|
|
|
where
|
|
|
|
|
sizeof = DimsFn FnBits . Right
|
|
|
|
|
|
|
|
|
|
-- produces a generic type of the given size
|
|
|
|
|
typeOfSize :: Expr -> Type
|
|
|
|
|
typeOfSize size =
|
2020-07-12 23:06:27 +02:00
|
|
|
IntegerVector TLogic sg [(hi, RawNum 0)]
|
2020-06-07 18:47:35 +02:00
|
|
|
where
|
|
|
|
|
sg = Unspecified -- suitable for now
|
2020-07-12 23:06:27 +02:00
|
|
|
hi = BinOp Sub size (RawNum 1)
|
2020-06-07 18:47:35 +02:00
|
|
|
|
2020-01-11 22:22:07 +01:00
|
|
|
-- combines a type with unpacked ranges
|
2020-01-12 02:35:51 +01:00
|
|
|
injectRanges :: Type -> [Range] -> Type
|
|
|
|
|
injectRanges t [] = t
|
|
|
|
|
injectRanges (UnpackedType t rs) unpacked = UnpackedType t $ unpacked ++ rs
|
|
|
|
|
injectRanges t unpacked = UnpackedType t unpacked
|
|
|
|
|
|
2020-01-12 04:52:12 +01:00
|
|
|
-- removes the most significant range of the given type
|
2020-01-12 02:35:51 +01:00
|
|
|
popRange :: Type -> Type
|
2020-01-12 04:52:12 +01:00
|
|
|
popRange (UnpackedType t [_]) = t
|
2020-02-17 05:39:48 +01:00
|
|
|
popRange (IntegerAtom TInteger sg) =
|
|
|
|
|
IntegerVector TLogic sg []
|
2020-01-12 02:35:51 +01:00
|
|
|
popRange t =
|
2020-02-17 05:39:48 +01:00
|
|
|
tf rs
|
|
|
|
|
where (tf, _ : rs) = typeRanges t
|
2020-01-12 04:52:12 +01:00
|
|
|
|
|
|
|
|
-- replaces the most significant range of the given type
|
|
|
|
|
replaceRange :: Range -> Type -> Type
|
|
|
|
|
replaceRange r (UnpackedType t (_ : rs)) =
|
|
|
|
|
UnpackedType t (r : rs)
|
2020-02-17 05:39:48 +01:00
|
|
|
replaceRange r (IntegerAtom TInteger sg) =
|
|
|
|
|
IntegerVector TLogic sg [r]
|
2020-01-12 04:52:12 +01:00
|
|
|
replaceRange r t =
|
2020-02-17 05:39:48 +01:00
|
|
|
tf (r : rs)
|
|
|
|
|
where (tf, _ : rs) = typeRanges t
|