Stream.hs 3.69 KB
Newer Older
1 2 3 4 5 6 7 8 9
{- sv2v
 - Author: Zachary Snow <zach@zachjs.com>
 -
 - Conversion of streaming concatenations.
 -}

module Convert.Stream (convert) where

import Control.Monad.Writer
10
import Data.List.Unique (complex)
11 12 13 14 15 16 17 18 19 20

import Convert.Traverse
import Language.SystemVerilog.AST

type Funcs = [ModuleItem]

convert :: [AST] -> [AST]
convert = map $ traverseDescriptions convertDescription

convertDescription :: Description -> Description
21 22
convertDescription (description @ Part{}) =
    Part attrs extern kw lifetime name ports (items ++ funcs)
23 24 25
    where
        (description', funcSet) =
            runWriter $ traverseModuleItemsM (traverseStmtsM traverseStmtM) description
26
        Part attrs extern kw lifetime name ports items = description'
27
        (funcs, _, _) = complex funcSet
28 29 30 31
convertDescription other = other

streamerBlock :: Expr -> Expr -> (LHS -> Expr -> Stmt) -> LHS -> Expr -> Stmt
streamerBlock chunk size asgn output input =
32
    Block Seq ""
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
    [ Variable Local t inp [] $ Just input
    , Variable Local t out [] Nothing
    , Variable Local (IntegerAtom TInteger Unspecified) idx [] Nothing
    , Variable Local (IntegerAtom TInteger Unspecified) bas [] Nothing
    ]
    [ For inits cmp incr stmt
    , AsgnBlk AsgnOpEq (LHSIdent bas) (Ident idx)
    , For inits cmp2 incr2 stmt2
    , asgn output (Ident out)
    ]
    where
        lo = Number "0"
        hi = BinOp Sub size (Number "1")
        t = IntegerVector TLogic Unspecified [(hi, lo)]
        name = streamerBlockName chunk size
        inp = name ++ "_inp"
        out = name ++ "_out"
        idx = name ++ "_idx"
        bas = name ++ "_bas"
        -- main chunk loop
53 54
        inits = Right [(LHSIdent idx, lo)]
        cmp = BinOp Le (Ident idx) (BinOp Sub hi chunk)
55 56 57 58 59
        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)
        stmt = AsgnBlk AsgnOpEq lhs expr
        -- final chunk loop
60
        cmp2 = BinOp Lt (Ident idx) (BinOp Sub size (Ident bas))
61 62 63 64 65 66 67
        incr2 = [(LHSIdent idx, AsgnOp Add, Number "1")]
        lhs2 = LHSBit (LHSIdent out) (Ident idx)
        expr2 = Bit (Ident inp) (BinOp Add (Ident idx) (Ident bas))
        stmt2 = AsgnBlk AsgnOpEq lhs2 expr2

streamerBlockName :: Expr -> Expr -> Identifier
streamerBlockName chunk size =
68
    "_sv2v_strm_" ++ shortHash (chunk, size)
69 70 71 72 73 74 75 76 77 78 79 80 81

traverseStmtM :: Stmt -> Writer Funcs Stmt
traverseStmtM (AsgnBlk op lhs expr) =
    traverseAsgnM (lhs, expr) (AsgnBlk op)
traverseStmtM (Asgn mt lhs expr) =
    traverseAsgnM (lhs, expr) (Asgn mt)
traverseStmtM other = return other

traverseAsgnM :: (LHS, Expr) -> (LHS -> Expr -> Stmt) -> Writer Funcs Stmt
traverseAsgnM (lhs, Stream StreamR _ exprs) constructor =
    return $ constructor lhs expr
    where
        expr = Concat $ exprs ++ [Repeat delta [Number "1'b0"]]
82 83
        size = DimsFn FnBits $ Right $ lhsToExpr lhs
        exprSize = DimsFn FnBits $ Right (Concat exprs)
84 85 86 87 88 89 90
        delta = BinOp Sub size exprSize
traverseAsgnM (LHSStream StreamR _ lhss, expr) constructor =
    return $ constructor (LHSConcat lhss) expr
traverseAsgnM (lhs, Stream StreamL chunk exprs) constructor = do
    return $ streamerBlock chunk size constructor lhs expr
    where
        expr = Concat $ Repeat delta [Number "1'b0"] : exprs
91 92
        size = DimsFn FnBits $ Right $ lhsToExpr lhs
        exprSize = DimsFn FnBits $ Right (Concat exprs)
93 94 95 96 97
        delta = BinOp Sub size exprSize
traverseAsgnM (LHSStream StreamL chunk lhss, expr) constructor = do
    return $ streamerBlock chunk size constructor lhs expr
    where
        lhs = LHSConcat lhss
98
        size = DimsFn FnBits $ Right expr
99 100
traverseAsgnM (lhs, expr) constructor =
    return $ constructor lhs expr