mirror of https://github.com/zachjs/sv2v.git
173 lines
5.7 KiB
Haskell
173 lines
5.7 KiB
Haskell
{- sv2v
|
|
- Author: Zachary Snow <zach@zachjs.com>
|
|
-
|
|
- Conversion of size casts on non-constant expressions.
|
|
-}
|
|
|
|
module Convert.SizeCast (convert) where
|
|
|
|
import Control.Monad.State
|
|
import Control.Monad.Writer
|
|
import qualified Data.Map.Strict as Map
|
|
import qualified Data.Set as Set
|
|
|
|
import Convert.Traverse
|
|
import Language.SystemVerilog.AST
|
|
|
|
type TypeMap = Map.Map Identifier Type
|
|
type CastSet = Set.Set (Expr, Signing)
|
|
|
|
type ST = StateT TypeMap (Writer CastSet)
|
|
|
|
convert :: [AST] -> [AST]
|
|
convert = map convertFile
|
|
|
|
convertFile :: AST -> AST
|
|
convertFile descriptions =
|
|
descriptions' ++ map (uncurry castFn) funcs
|
|
where
|
|
results = map convertDescription descriptions
|
|
descriptions' = map fst results
|
|
funcs = Set.toList $ Set.unions $ map snd results
|
|
|
|
convertDescription :: Description -> (Description, CastSet)
|
|
convertDescription description =
|
|
(description', info)
|
|
where
|
|
(description', info) =
|
|
runWriter $
|
|
scopedConversionM traverseDeclM traverseModuleItemM traverseStmtM
|
|
Map.empty description
|
|
|
|
traverseDeclM :: Decl -> ST Decl
|
|
traverseDeclM decl = do
|
|
case decl of
|
|
Variable _ t x _ _ -> modify $ Map.insert x t
|
|
Param _ t x _ -> modify $ Map.insert x t
|
|
ParamType _ _ _ -> return ()
|
|
CommentDecl _ -> return ()
|
|
return decl
|
|
|
|
traverseModuleItemM :: ModuleItem -> ST ModuleItem
|
|
traverseModuleItemM item = traverseExprsM traverseExprM item
|
|
|
|
traverseStmtM :: Stmt -> ST Stmt
|
|
traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt
|
|
|
|
traverseExprM :: Expr -> ST Expr
|
|
traverseExprM =
|
|
traverseNestedExprsM convertExprM
|
|
where
|
|
convertExprM :: Expr -> ST Expr
|
|
convertExprM (Cast (Right (Number s)) (Number n)) =
|
|
case (readNumber s, readNumber n) of
|
|
(Just s', Just n') ->
|
|
return $ Number str
|
|
where
|
|
str = (show size) ++ "'d" ++ (show num)
|
|
size = s'
|
|
num = if size == 32
|
|
then n'
|
|
else n' `mod` (2 ^ s')
|
|
_ -> convertCastM (Number s) (Number n)
|
|
convertExprM (orig @ (Cast (Right DimsFn{}) _)) =
|
|
return orig
|
|
convertExprM (Cast (Right (Ident x)) e) = do
|
|
typeMap <- get
|
|
-- can't convert this cast yet because x could be a typename
|
|
if Map.notMember x typeMap
|
|
then return $ Cast (Right $ Ident x) e
|
|
else convertCastM (Ident x) e
|
|
convertExprM (Cast (Right s) e) =
|
|
convertCastM s e
|
|
convertExprM (Cast (Left (IntegerVector _ Signed rs)) e) =
|
|
convertCastWithSigningM (dimensionsSize rs) e Signed
|
|
convertExprM (Cast (Left (IntegerVector _ _ rs)) e) =
|
|
convertExprM $ Cast (Right $ dimensionsSize rs) e
|
|
convertExprM other = return other
|
|
|
|
convertCastM :: Expr -> Expr -> ST Expr
|
|
convertCastM s e = do
|
|
typeMap <- get
|
|
case exprSigning typeMap e of
|
|
Just sg -> convertCastWithSigningM s e sg
|
|
_ -> return $ Cast (Right s) e
|
|
|
|
convertCastWithSigningM :: Expr -> Expr -> Signing -> ST Expr
|
|
convertCastWithSigningM s e sg = do
|
|
lift $ tell $ Set.singleton (s, sg)
|
|
let f = castFnName s sg
|
|
let args = Args [e] []
|
|
return $ Call (Ident f) args
|
|
|
|
castFn :: Expr -> Signing -> Description
|
|
castFn e sg =
|
|
PackageItem $
|
|
Function Automatic t fnName [decl] [Return $ Ident inp]
|
|
where
|
|
inp = "inp"
|
|
r = (simplify $ BinOp Sub e (Number "1"), Number "0")
|
|
t = IntegerVector TLogic sg [r]
|
|
fnName = castFnName e sg
|
|
decl = Variable Input t inp [] Nil
|
|
|
|
castFnName :: Expr -> Signing -> String
|
|
castFnName e sg =
|
|
if sg == Unspecified
|
|
then init name
|
|
else name
|
|
where
|
|
sizeStr = case e of
|
|
Number n ->
|
|
case readNumber n of
|
|
Just v -> show v
|
|
_ -> shortHash e
|
|
_ -> shortHash e
|
|
name = "sv2v_cast_" ++ sizeStr ++ "_" ++ show sg
|
|
|
|
exprSigning :: TypeMap -> Expr -> Maybe Signing
|
|
exprSigning typeMap (Ident x) =
|
|
case Map.lookup x typeMap of
|
|
Just t -> typeSigning t
|
|
Nothing -> Just Unspecified
|
|
exprSigning typeMap (BinOp op e1 e2) =
|
|
combiner sg1 sg2
|
|
where
|
|
sg1 = exprSigning typeMap e1
|
|
sg2 = exprSigning typeMap e2
|
|
combiner = case op of
|
|
BitAnd -> combineSigning
|
|
BitXor -> combineSigning
|
|
BitXnor -> combineSigning
|
|
BitOr -> combineSigning
|
|
Mul -> combineSigning
|
|
Div -> combineSigning
|
|
Add -> combineSigning
|
|
Sub -> combineSigning
|
|
Mod -> curry fst
|
|
Pow -> curry fst
|
|
ShiftAL -> curry fst
|
|
ShiftAR -> curry fst
|
|
_ -> \_ _ -> Just Unspecified
|
|
exprSigning _ _ = Just Unspecified
|
|
|
|
combineSigning :: Maybe Signing -> Maybe Signing -> Maybe Signing
|
|
combineSigning Nothing _ = Nothing
|
|
combineSigning _ Nothing = Nothing
|
|
combineSigning (Just Unspecified) msg = msg
|
|
combineSigning msg (Just Unspecified) = msg
|
|
combineSigning (Just Signed) _ = Just Signed
|
|
combineSigning _ (Just Signed) = Just Signed
|
|
combineSigning (Just Unsigned) _ = Just Unsigned
|
|
|
|
typeSigning :: Type -> Maybe Signing
|
|
typeSigning (Net _ sg _) = Just sg
|
|
typeSigning (Implicit sg _) = Just sg
|
|
typeSigning (IntegerVector _ sg _) = Just sg
|
|
typeSigning (IntegerAtom t sg ) =
|
|
Just $ case (sg, t) of
|
|
(Unspecified, TTime) -> Unsigned
|
|
(Unspecified, _ ) -> Signed
|
|
(_ , _ ) -> sg
|
|
typeSigning _ = Nothing
|