2019-09-04 05:36:29 +02:00
|
|
|
{- sv2v
|
|
|
|
|
- Author: Zachary Snow <zach@zachjs.com>
|
|
|
|
|
-
|
|
|
|
|
- Conversion of streaming concatenations.
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
module Convert.Stream (convert) where
|
|
|
|
|
|
2020-08-16 19:12:06 +02:00
|
|
|
import Convert.Scoper
|
2019-09-04 05:36:29 +02:00
|
|
|
import Convert.Traverse
|
|
|
|
|
import Language.SystemVerilog.AST
|
|
|
|
|
|
|
|
|
|
convert :: [AST] -> [AST]
|
|
|
|
|
convert = map $ traverseDescriptions convertDescription
|
|
|
|
|
|
|
|
|
|
convertDescription :: Description -> Description
|
2020-08-16 19:12:06 +02:00
|
|
|
convertDescription = partScoper
|
|
|
|
|
traverseDeclM traverseModuleItemM return traverseStmtM
|
2019-09-04 05:36:29 +02:00
|
|
|
|
2020-08-16 19:12:06 +02:00
|
|
|
traverseDeclM :: Decl -> Scoper () Decl
|
|
|
|
|
traverseDeclM (Variable d t x [] (Stream StreamR _ exprs)) =
|
|
|
|
|
return $ Variable d t x [] expr'
|
|
|
|
|
where
|
|
|
|
|
expr = Concat exprs
|
|
|
|
|
expr' = resize exprSize lhsSize expr
|
|
|
|
|
lhsSize = DimsFn FnBits $ Left t
|
|
|
|
|
exprSize = sizeof expr
|
|
|
|
|
traverseDeclM (Variable d t x [] (expr @ (Stream StreamL chunk exprs))) = do
|
|
|
|
|
inProcedure <- withinProcedureM
|
|
|
|
|
if inProcedure
|
|
|
|
|
then return $ Variable d t x [] expr
|
|
|
|
|
else do
|
|
|
|
|
injectItem $ MIPackageItem func
|
|
|
|
|
return $ Variable d t x [] expr'
|
|
|
|
|
where
|
|
|
|
|
fnName = streamerFuncName x
|
|
|
|
|
func = streamerFunc fnName chunk (TypeOf $ Concat exprs) t
|
|
|
|
|
expr' = Call (Ident fnName) (Args [Concat exprs] [])
|
|
|
|
|
traverseDeclM decl = return decl
|
|
|
|
|
|
|
|
|
|
traverseModuleItemM :: ModuleItem -> Scoper () ModuleItem
|
|
|
|
|
traverseModuleItemM (Assign opt lhs (Stream StreamL chunk exprs)) =
|
|
|
|
|
injectItem (MIPackageItem func) >> return (Assign opt lhs expr')
|
|
|
|
|
where
|
|
|
|
|
fnName = streamerFuncName $ shortHash lhs
|
|
|
|
|
t = TypeOf $ lhsToExpr lhs
|
|
|
|
|
arg = Concat exprs
|
|
|
|
|
func = streamerFunc fnName chunk (TypeOf arg) t
|
|
|
|
|
expr' = Call (Ident fnName) (Args [arg] [])
|
|
|
|
|
traverseModuleItemM (Assign opt (LHSStream StreamL chunk lhss) expr) =
|
|
|
|
|
traverseModuleItemM $
|
|
|
|
|
Assign opt (LHSConcat lhss)
|
|
|
|
|
(Stream StreamL chunk [expr])
|
|
|
|
|
traverseModuleItemM (Assign opt lhs expr) =
|
|
|
|
|
return $ Assign opt lhs' expr'
|
|
|
|
|
where Asgn AsgnOpEq Nothing lhs' expr' =
|
|
|
|
|
traverseAsgn (lhs, expr) (Asgn AsgnOpEq Nothing)
|
|
|
|
|
traverseModuleItemM item = return item
|
|
|
|
|
|
|
|
|
|
traverseStmtM :: Stmt -> Scoper () Stmt
|
|
|
|
|
traverseStmtM (Asgn op mt lhs expr) =
|
|
|
|
|
return $ traverseAsgn (lhs, expr) (Asgn op mt)
|
|
|
|
|
traverseStmtM other = return other
|
|
|
|
|
|
|
|
|
|
-- produces a function used to capture an inline streaming concatenation
|
|
|
|
|
streamerFunc :: Identifier -> Expr -> Type -> Type -> PackageItem
|
|
|
|
|
streamerFunc fnName chunk rawInType rawOutType =
|
|
|
|
|
Function Automatic outType fnName [decl] [stmt]
|
|
|
|
|
where
|
|
|
|
|
decl = Variable Input inType "inp" [] Nil
|
|
|
|
|
lhs = LHSIdent fnName
|
|
|
|
|
expr = Stream StreamL chunk [Ident "inp"]
|
|
|
|
|
stmt = traverseAsgn (lhs, expr) (Asgn AsgnOpEq Nothing)
|
|
|
|
|
|
|
|
|
|
inType = sizedType rawInType
|
|
|
|
|
outType = sizedType rawOutType
|
|
|
|
|
sizedType :: Type -> Type
|
|
|
|
|
sizedType t = IntegerVector TLogic Unspecified [(hi, RawNum 0)]
|
|
|
|
|
where hi = BinOp Sub (DimsFn FnBits $ Left t) (RawNum 1)
|
|
|
|
|
|
|
|
|
|
streamerFuncName :: Identifier -> Identifier
|
|
|
|
|
streamerFuncName = (++) "_sv2v_strm_"
|
|
|
|
|
|
|
|
|
|
-- produces a block corresponding to the given leftward streaming concatenation
|
|
|
|
|
streamerBlock :: Expr -> Expr -> Expr -> (LHS -> Expr -> Stmt) -> LHS -> Expr -> Stmt
|
|
|
|
|
streamerBlock chunk inSize outSize asgn output input =
|
2019-10-01 05:03:55 +02:00
|
|
|
Block Seq ""
|
2020-06-14 21:56:09 +02:00
|
|
|
[ Variable Local t inp [] input
|
|
|
|
|
, Variable Local t out [] Nil
|
|
|
|
|
, Variable Local (IntegerAtom TInteger Unspecified) idx [] Nil
|
2019-09-04 05:36:29 +02:00
|
|
|
]
|
|
|
|
|
[ For inits cmp incr stmt
|
2020-05-06 00:42:45 +02:00
|
|
|
, If NoCheck cmp2 stmt2 Null
|
2020-08-16 19:12:06 +02:00
|
|
|
, asgn output result
|
2019-09-04 05:36:29 +02:00
|
|
|
]
|
|
|
|
|
where
|
2020-07-12 23:06:27 +02:00
|
|
|
lo = RawNum 0
|
2020-08-16 19:12:06 +02:00
|
|
|
hi = BinOp Sub inSize (RawNum 1)
|
2019-09-04 05:36:29 +02:00
|
|
|
t = IntegerVector TLogic Unspecified [(hi, lo)]
|
2020-08-16 19:12:06 +02:00
|
|
|
name = streamerBlockName chunk inSize
|
2019-09-04 05:36:29 +02:00
|
|
|
inp = name ++ "_inp"
|
|
|
|
|
out = name ++ "_out"
|
|
|
|
|
idx = name ++ "_idx"
|
|
|
|
|
-- main chunk loop
|
2019-10-01 05:03:55 +02:00
|
|
|
inits = Right [(LHSIdent idx, lo)]
|
2020-08-16 19:12:06 +02:00
|
|
|
cmp = BinOp Le (Ident idx) (BinOp Sub inSize chunk)
|
2019-09-04 05:36:29 +02:00
|
|
|
incr = [(LHSIdent idx, AsgnOp Add, chunk)]
|
|
|
|
|
lhs = LHSRange (LHSIdent out) IndexedMinus (BinOp Sub hi (Ident idx), chunk)
|
|
|
|
|
expr = Range (Ident inp) IndexedPlus (Ident idx, chunk)
|
2020-02-01 21:52:52 +01:00
|
|
|
stmt = Asgn AsgnOpEq Nothing lhs expr
|
2019-09-04 05:36:29 +02:00
|
|
|
-- final chunk loop
|
2020-08-16 19:12:06 +02:00
|
|
|
stub = BinOp Mod inSize chunk
|
|
|
|
|
lhs2 = LHSRange (LHSIdent out) IndexedPlus (RawNum 0, stub)
|
|
|
|
|
expr2 = Range (Ident inp) IndexedPlus (Ident idx, stub)
|
2020-02-01 21:52:52 +01:00
|
|
|
stmt2 = Asgn AsgnOpEq Nothing lhs2 expr2
|
2020-08-16 19:12:06 +02:00
|
|
|
cmp2 = BinOp Gt stub (RawNum 0)
|
|
|
|
|
-- size mismatch padding
|
|
|
|
|
result = resize inSize outSize (Ident out)
|
2019-09-04 05:36:29 +02:00
|
|
|
|
|
|
|
|
streamerBlockName :: Expr -> Expr -> Identifier
|
|
|
|
|
streamerBlockName chunk size =
|
2019-09-04 05:52:22 +02:00
|
|
|
"_sv2v_strm_" ++ shortHash (chunk, size)
|
2019-09-04 05:36:29 +02:00
|
|
|
|
2020-08-16 19:12:06 +02:00
|
|
|
-- pad or truncate the right side of an expression
|
|
|
|
|
resize :: Expr -> Expr -> Expr -> Expr
|
|
|
|
|
resize inSize outSize expr =
|
|
|
|
|
Mux
|
|
|
|
|
(BinOp Le inSize outSize)
|
|
|
|
|
(BinOp ShiftL expr (BinOp Sub outSize inSize))
|
|
|
|
|
(BinOp ShiftR expr (BinOp Sub inSize outSize))
|
2020-07-12 23:06:27 +02:00
|
|
|
|
2020-08-16 19:12:06 +02:00
|
|
|
-- rewrite a given assignment if it uses a streaming concatenation
|
2020-04-05 19:09:52 +02:00
|
|
|
traverseAsgn :: (LHS, Expr) -> (LHS -> Expr -> Stmt) -> Stmt
|
|
|
|
|
traverseAsgn (lhs, Stream StreamR _ exprs) constructor =
|
2020-08-16 19:12:06 +02:00
|
|
|
constructor lhs $ resize exprSize lhsSize expr
|
2019-09-04 05:36:29 +02:00
|
|
|
where
|
2020-08-16 19:12:06 +02:00
|
|
|
expr = Concat exprs
|
|
|
|
|
lhsSize = sizeof $ lhsToExpr lhs
|
|
|
|
|
exprSize = sizeof expr
|
2020-04-05 19:09:52 +02:00
|
|
|
traverseAsgn (LHSStream StreamR _ lhss, expr) constructor =
|
2020-08-16 19:12:06 +02:00
|
|
|
constructor lhs $ resize exprSize lhsSize expr
|
2019-09-04 05:36:29 +02:00
|
|
|
where
|
2020-08-16 19:12:06 +02:00
|
|
|
lhs = LHSConcat lhss
|
|
|
|
|
lhsSize = sizeof $ lhsToExpr lhs
|
|
|
|
|
exprSize = sizeof expr
|
|
|
|
|
traverseAsgn (lhs, Stream StreamL chunk exprs) constructor =
|
|
|
|
|
streamerBlock chunk exprSize lhsSize constructor lhs expr
|
|
|
|
|
where
|
|
|
|
|
expr = Concat exprs
|
|
|
|
|
lhsSize = sizeof $ lhsToExpr lhs
|
|
|
|
|
exprSize = sizeof expr
|
|
|
|
|
traverseAsgn (LHSStream StreamL chunk lhss, expr) constructor =
|
|
|
|
|
streamerBlock chunk exprSize lhsSize constructor lhs expr
|
2019-09-04 05:36:29 +02:00
|
|
|
where
|
|
|
|
|
lhs = LHSConcat lhss
|
2020-08-16 19:12:06 +02:00
|
|
|
lhsSize = sizeof $ lhsToExpr lhs
|
|
|
|
|
exprSize = sizeof expr
|
2020-04-05 19:09:52 +02:00
|
|
|
traverseAsgn (lhs, expr) constructor =
|
|
|
|
|
constructor lhs expr
|
2020-08-16 19:12:06 +02:00
|
|
|
|
|
|
|
|
sizeof :: Expr -> Expr
|
|
|
|
|
sizeof = DimsFn FnBits . Right
|