2020-01-11 22:22:07 +01:00
|
|
|
{- sv2v
|
|
|
|
|
- Author: Zachary Snow <zach@zachjs.com>
|
|
|
|
|
-
|
|
|
|
|
- Conversion for the `type` operator
|
|
|
|
|
-
|
|
|
|
|
- TODO: This conversion only supports the most basic expressions so far. We can
|
|
|
|
|
- add support for range and bit accesses, struct fields, and perhaps even
|
|
|
|
|
- arithmetic operations. Bits and pieces of similar logic exist in other
|
|
|
|
|
- conversion.
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
module Convert.TypeOf (convert) where
|
|
|
|
|
|
|
|
|
|
import Control.Monad.State
|
2020-06-07 18:47:35 +02:00
|
|
|
import Data.List (elemIndex)
|
2020-01-12 02:35:51 +01:00
|
|
|
import Data.Maybe (fromMaybe, mapMaybe)
|
2020-06-07 18:47:35 +02:00
|
|
|
import Data.Int (Int32)
|
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
|
|
|
|
|
|
|
|
|
|
import Convert.Traverse
|
|
|
|
|
import Language.SystemVerilog.AST
|
|
|
|
|
|
2020-01-12 02:35:51 +01:00
|
|
|
type Info = Map.Map Identifier Type
|
2020-01-11 22:22:07 +01:00
|
|
|
|
|
|
|
|
convert :: [AST] -> [AST]
|
|
|
|
|
convert = map $ traverseDescriptions convertDescription
|
|
|
|
|
|
|
|
|
|
convertDescription :: Description -> Description
|
|
|
|
|
convertDescription (description @ Part{}) =
|
|
|
|
|
scopedConversion traverseDeclM traverseModuleItemM traverseStmtM
|
|
|
|
|
initialState description
|
|
|
|
|
where
|
|
|
|
|
Part _ _ _ _ _ _ items = description
|
|
|
|
|
initialState = Map.fromList $ mapMaybe returnType items
|
2020-01-12 02:35:51 +01:00
|
|
|
returnType :: ModuleItem -> Maybe (Identifier, Type)
|
2020-01-11 22:22:07 +01:00
|
|
|
returnType (MIPackageItem (Function _ t f _ _)) =
|
2020-01-12 02:35:51 +01:00
|
|
|
if t == Implicit Unspecified []
|
|
|
|
|
-- functions with no return type implicitly return a single bit
|
|
|
|
|
then Just (f, IntegerVector TLogic Unspecified [])
|
|
|
|
|
else Just (f, t)
|
2020-01-11 22:22:07 +01:00
|
|
|
returnType _ = Nothing
|
|
|
|
|
convertDescription other = other
|
|
|
|
|
|
|
|
|
|
traverseDeclM :: Decl -> State Info Decl
|
|
|
|
|
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
|
|
|
|
|
modify $ Map.insert ident t'
|
|
|
|
|
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
|
|
|
|
|
modify $ Map.insert 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
|
|
|
|
|
|
|
|
traverseModuleItemM :: ModuleItem -> State Info ModuleItem
|
|
|
|
|
traverseModuleItemM item = traverseTypesM traverseTypeM item
|
|
|
|
|
|
|
|
|
|
traverseStmtM :: Stmt -> State Info Stmt
|
2020-01-12 02:35:51 +01:00
|
|
|
traverseStmtM =
|
|
|
|
|
traverseStmtExprsM $ traverseNestedExprsM $ traverseExprTypesM traverseTypeM
|
2020-01-11 22:22:07 +01:00
|
|
|
|
|
|
|
|
traverseTypeM :: Type -> State Info Type
|
|
|
|
|
traverseTypeM (TypeOf expr) = typeof expr
|
|
|
|
|
traverseTypeM other = return other
|
|
|
|
|
|
|
|
|
|
typeof :: Expr -> State Info Type
|
2020-06-07 18:47:35 +02:00
|
|
|
typeof (Number n) =
|
|
|
|
|
return $ IntegerVector TLogic sg [r]
|
|
|
|
|
where
|
|
|
|
|
(size, sg) = parseNumber n
|
|
|
|
|
r = (Number $ show (size - 1), Number "0")
|
2020-01-11 22:22:07 +01:00
|
|
|
typeof (orig @ (Ident x)) = do
|
|
|
|
|
res <- gets $ Map.lookup x
|
2020-01-12 02:35:51 +01:00
|
|
|
return $ fromMaybe (TypeOf orig) res
|
2020-01-11 22:22:07 +01:00
|
|
|
typeof (orig @ (Call (Ident x) _)) = do
|
|
|
|
|
res <- gets $ Map.lookup x
|
2020-01-12 02:35:51 +01:00
|
|
|
return $ fromMaybe (TypeOf orig) res
|
2020-01-12 04:52:12 +01:00
|
|
|
typeof (orig @ (Bit e _)) = do
|
|
|
|
|
t <- typeof e
|
|
|
|
|
return $ case t of
|
|
|
|
|
TypeOf _ -> TypeOf orig
|
|
|
|
|
_ -> popRange t
|
|
|
|
|
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
|
|
|
|
|
IndexedPlus -> BinOp Sub (uncurry (BinOp Add) r) (Number "1")
|
|
|
|
|
IndexedMinus -> BinOp Add (uncurry (BinOp Sub) r) (Number "1")
|
2020-06-21 04:39:13 +02:00
|
|
|
typeof (orig @ (Dot e x)) = do
|
|
|
|
|
t <- typeof e
|
|
|
|
|
return $ case t of
|
|
|
|
|
Struct _ fields [] ->
|
|
|
|
|
case lookup x $ map swap fields of
|
|
|
|
|
Just typ -> typ
|
|
|
|
|
Nothing -> TypeOf orig
|
|
|
|
|
_ -> TypeOf orig
|
2020-06-07 18:47:35 +02:00
|
|
|
typeof (orig @ (Cast (Right (Ident x)) _)) = do
|
|
|
|
|
typeMap <- get
|
|
|
|
|
if Map.member x typeMap
|
|
|
|
|
then return $ typeOfSize (Ident x)
|
|
|
|
|
else return $ TypeOf orig
|
|
|
|
|
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-01-11 22:22:07 +01:00
|
|
|
typeof other = return $ TypeOf other
|
|
|
|
|
|
2020-06-07 18:47:35 +02:00
|
|
|
-- determines the size and sign of a number literal
|
|
|
|
|
parseNumber :: String -> (Int32, Signing)
|
|
|
|
|
parseNumber s =
|
|
|
|
|
case elemIndex '\'' s of
|
|
|
|
|
Nothing -> (32, Signed)
|
|
|
|
|
Just 0 -> parseNumber $ '3' : '2' : s
|
|
|
|
|
Just idx -> (size, signing)
|
|
|
|
|
where
|
|
|
|
|
Just size = readNumber $ take idx s
|
|
|
|
|
signing = case drop (idx + 1) s of
|
|
|
|
|
's' : _ -> Signed
|
|
|
|
|
_ -> Unsigned
|
|
|
|
|
|
|
|
|
|
-- produces a type large enough to hold either expression
|
|
|
|
|
largerSizeType :: Expr -> Expr -> Type
|
|
|
|
|
largerSizeType a b =
|
|
|
|
|
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 =
|
|
|
|
|
foldl (BinOp Add) (Number "0") $
|
|
|
|
|
map sizeof exprs
|
|
|
|
|
where
|
|
|
|
|
sizeof = DimsFn FnBits . Right
|
|
|
|
|
|
|
|
|
|
-- produces a generic type of the given size
|
|
|
|
|
typeOfSize :: Expr -> Type
|
|
|
|
|
typeOfSize size =
|
|
|
|
|
IntegerVector TLogic sg [(hi, Number "0")]
|
|
|
|
|
where
|
|
|
|
|
sg = Unspecified -- suitable for now
|
|
|
|
|
hi = BinOp Sub size (Number "1")
|
|
|
|
|
|
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
|