Commit 546657d2 by Zachary Snow

added (very hacky) PackedArrayFlatten conversion; convert logics in generate

parent 0c08b9ae
...@@ -11,6 +11,7 @@ import Language.SystemVerilog.AST ...@@ -11,6 +11,7 @@ import Language.SystemVerilog.AST
import qualified Convert.AlwaysKW import qualified Convert.AlwaysKW
import qualified Convert.Logic import qualified Convert.Logic
import qualified Convert.Typedef import qualified Convert.Typedef
import qualified Convert.PackedArrayFlatten
import qualified Convert.StarPort import qualified Convert.StarPort
type Phase = AST -> AST type Phase = AST -> AST
...@@ -20,6 +21,7 @@ phases = ...@@ -20,6 +21,7 @@ phases =
[ Convert.AlwaysKW.convert [ Convert.AlwaysKW.convert
, Convert.Logic.convert , Convert.Logic.convert
, Convert.Typedef.convert , Convert.Typedef.convert
, Convert.PackedArrayFlatten.convert
, Convert.StarPort.convert , Convert.StarPort.convert
] ]
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
module Convert.Logic (convert) where module Convert.Logic (convert) where
import Data.Maybe (fromJust)
import qualified Data.Set as Set import qualified Data.Set as Set
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
...@@ -59,4 +60,22 @@ convertModuleItem idents (LocalNet (Logic mr) ident val) = ...@@ -59,4 +60,22 @@ convertModuleItem idents (LocalNet (Logic mr) ident val) =
LocalNet (t mr) ident val LocalNet (t mr) ident val
where where
t = if Set.member ident idents then Reg else Wire t = if Set.member ident idents then Reg else Wire
convertModuleItem idents (Generate items) = Generate $ map (convertGenItem $ convertModuleItem idents) items
convertModuleItem _ other = other convertModuleItem _ other = other
convertGenItem :: (ModuleItem -> ModuleItem) -> GenItem -> GenItem
convertGenItem f item = convertGenItem' item
where
convertGenItem' :: GenItem -> GenItem
convertGenItem' (GenBlock x items) = GenBlock x $ map convertGenItem' items
convertGenItem' (GenFor a b c d items) = GenFor a b c d $ map convertGenItem' items
convertGenItem' (GenIf e i1 i2) = GenIf e (convertGenItem' i1) (convertGenItem' i2)
convertGenItem' (GenNull) = GenNull
convertGenItem' (GenModuleItem moduleItem) = GenModuleItem $ f moduleItem
convertGenItem' (GenCase e cases def) = GenCase e cases' def'
where
cases' = zip (map fst cases) (map (convertGenItem' . snd) cases)
def' = if def == Nothing
then Nothing
else Just $ convertGenItem' $ fromJust def
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for flattening multi-dimensional packed arrays
-
- To simplify the code, this only removes one dimension per identifier at a
- time. Because the conversions are repeatedly applied until convergence, this
- will eventually remove all the extra packed dimensions.
-
- TODO FIXME XXX: We don't actually have support for more than 2 dimensions
- right now. I don't think the parser can even handle that. This isn't
- something that should be too common, so maybe we can hold off on that for
- now.
-
- TODO FIXME XXX: This does not yet identify and flatten candidates that are
- themselves contained inside of generate blocks.
-
- TODO FIXME XXX: This actually assumes that the first range index is the upper
- bound. We could get arround this with a generate block.
-}
module Convert.PackedArrayFlatten (convert) where
-- Note that, for now, only wire/reg/logic/alias can have multiple packed
-- dimensions. This means all such transformations are for module items, though
-- we must of course change uses of these items in non-constant expressions,
-- which we, unfortunately, do not distinguish from constant expressions in the
-- AST.
import Data.Maybe
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import Language.SystemVerilog.AST
type DimMap = Map.Map Identifier (Type, Range)
convert :: AST -> AST
convert = map convertDescription
convertDescription :: Description -> Description
convertDescription (Module name ports items) =
Module name ports $ items' ++ unflatteners
where
toFlatten = mapMaybe getExtraDims items
dimMap = Map.fromList toFlatten
items' = map (convertModuleItem dimMap) items
unflatteners = concat $ map (unflattener outputs) toFlatten
outputs = Set.fromList $ mapMaybe getOutput items
getOutput :: ModuleItem -> Maybe Identifier
getOutput (PortDecl Output _ ident) = Just ident
getOutput _ = Nothing
getExtraDims :: ModuleItem -> Maybe (Identifier, (Type, Range))
getExtraDims (LocalNet t ident _) =
if length rs > 1
then Just (ident, (tf $ tail rs, head rs))
else Nothing
where (tf, rs) = typeDims t
getExtraDims _ = Nothing
convertDescription other = other
unflattener :: Set.Set Identifier -> (Identifier, (Type, Range)) -> [ModuleItem]
unflattener outputs (arr, (t, (a, b))) =
[ Comment $ "sv2v packed-array-flatten unflattener for " ++ arr
, LocalNet t arrUnflat (Left [(a, b)])
, Generate
[ GenModuleItem $ Genvar index
, GenModuleItem $ MIIntegerV $ IntegerV (arrUnflat ++ "_repeater_index") (Right Nothing)
, localparam hi a
, localparam lo b
, localparam size
(BinOp Add (BinOp Sub bigHi bigLo) (Number "1"))
, GenFor
(index, Ident lo)
(BinOp Le (Ident index) (Ident hi))
(index, BinOp Add (Ident index) (Number "1"))
(prefix "unflatten")
[ localparam startBit
(BinOp Add (Ident lo)
(BinOp Mul (Ident index) (Ident size)))
, GenModuleItem $ (uncurry Assign) $
if Set.notMember arr outputs
then (LHSBit arrUnflat $ Ident index, IdentRange arr origRange)
else (LHSRange arr origRange, IdentBit arrUnflat $ Ident index)
]
]
]
where
startBit = prefix "__START_BIT"
size = prefix "__SIZE"
arrUnflat = prefix arr
index = prefix "__index"
hi = prefix "__hi"
lo = prefix "__lo"
(bigHi, bigLo) = head $ snd $ typeDims t
localparam :: Identifier -> Expr -> GenItem
localparam x v = GenModuleItem $ MILocalparam $ Localparam Nothing x v
origRange = ( (BinOp Add (Ident startBit)
(BinOp Sub (Ident size) (Number "1")))
, Ident startBit )
typeDims :: Type -> ([Range] -> Type, [Range])
typeDims (Reg r) = (Reg , r)
typeDims (Wire r) = (Wire , r)
typeDims (Logic r) = (Logic , r)
typeDims (Alias t r) = (Alias t, r)
prefix :: Identifier -> Identifier
prefix ident = "__sv2v_PAF_" ++ ident
rewriteRangesOrAssignment :: DimMap -> RangesOrAssignment -> RangesOrAssignment
rewriteRangesOrAssignment dimMap (Right (Just e)) =
Right $ Just $ rewriteExpr dimMap e
rewriteRangesOrAssignment _ other = other
rewriteRange :: DimMap -> Range -> Range
rewriteRange dimMap (a, b) = (r a, r b)
where r = rewriteExpr dimMap
rewriteIdentifier :: DimMap -> Identifier -> Identifier
rewriteIdentifier dimMap x =
if Map.member x dimMap
then prefix x
else x
rewriteExpr :: DimMap -> Expr -> Expr
rewriteExpr dimMap = rewriteExpr'
where
ri :: Identifier -> Identifier
ri = rewriteIdentifier dimMap
re = rewriteExpr'
rewriteExpr' :: Expr -> Expr
rewriteExpr' (String s) = String s
rewriteExpr' (Number s) = Number s
rewriteExpr' (ConstBool b) = ConstBool b
rewriteExpr' (Ident i ) = Ident (ri i)
rewriteExpr' (IdentRange i (r @ (s, e))) =
case Map.lookup i dimMap of
Nothing -> IdentRange (ri i) (rewriteRange dimMap r)
Just (t, _) ->
IdentRange i (s', e')
where
(a, b) = head $ snd $ typeDims t
size = BinOp Add (BinOp Sub a b) (Number "1")
s' = BinOp Sub (BinOp Mul size (BinOp Add s (Number "1"))) (Number "1")
e' = BinOp Mul size e
rewriteExpr' (IdentBit i e) = IdentBit (ri i) (re e)
rewriteExpr' (Repeat e l) = Repeat (re e) (map re l)
rewriteExpr' (Concat l ) = Concat (map re l)
rewriteExpr' (Call f l) = Call f (map re l)
rewriteExpr' (UniOp o e) = UniOp o (re e)
rewriteExpr' (BinOp o e1 e2) = BinOp o (re e1) (re e2)
rewriteExpr' (Mux e1 e2 e3) = Mux (re e1) (re e2) (re e3)
rewriteExpr' (Bit e n) = Bit (re e) n
flattenRanges :: [Range] -> [Range]
flattenRanges rs =
if length rs >= 2
then rs'
else error $ "flattenRanges on too small list: " ++ (show rs)
where
(s1, e1) = head rs
(s2, e2) = head $ tail rs
size1 = BinOp Add (BinOp Sub s1 e1) (Number "1")
size2 = BinOp Add (BinOp Sub s2 e2) (Number "1")
upper = BinOp Add (BinOp Mul size1 size2) (BinOp Sub e1 (Number "1"))
r' = (upper, e1)
rs' = (tail $ tail rs) ++ [r']
rewriteLHS :: DimMap -> LHS -> LHS
rewriteLHS dimMap (LHS x ) = LHS (rewriteIdentifier dimMap x)
rewriteLHS dimMap (LHSBit x e) = LHSBit (rewriteIdentifier dimMap x) (rewriteExpr dimMap e)
rewriteLHS dimMap (LHSRange x r) = LHSRange (rewriteIdentifier dimMap x) (rewriteRange dimMap r)
rewriteLHS dimMap (LHSConcat ls) = LHSConcat $ map (rewriteLHS dimMap) ls
rewriteStmt :: DimMap -> Stmt -> Stmt
rewriteStmt dimMap orig = rs orig
where
rs :: Stmt -> Stmt
rs (Block decls stmts) = Block decls (map rs stmts)
rs (Case e cases def) = Case e' cases' def'
where
re :: Expr -> Expr
re = rewriteExpr dimMap
rc :: Case -> Case
rc (exprs, stmt) = (map re exprs, rs stmt)
e' = re e
cases' = map rc cases
def' =
case def of
Nothing -> Nothing
Just stmt -> Just $ rs stmt
rs (BlockingAssignment lhs expr) = convertAssignment BlockingAssignment lhs expr
rs (NonBlockingAssignment lhs expr) = convertAssignment NonBlockingAssignment lhs expr
rs (For (x1, e1) cc (x2, e2) stmt) = For (x1, e1') cc' (x2, e2') (rs stmt)
where
e1' = rewriteExpr dimMap e1
e2' = rewriteExpr dimMap e2
cc' = rewriteExpr dimMap cc
rs (If cc s1 s2) = If (rewriteExpr dimMap cc) (rs s1) (rs s2)
rs (Timing sense stmt) = Timing sense (rs stmt)
rs (Null) = Null
convertAssignment :: (LHS -> Expr -> Stmt) -> LHS -> Expr -> Stmt
convertAssignment constructor (lhs @ (LHS ident)) (expr @ (Repeat _ exprs)) =
case Map.lookup ident dimMap of
Nothing -> constructor (rewriteLHS dimMap lhs) (rewriteExpr dimMap expr)
Just (_, (a, b)) ->
For inir chkr incr assign
where
index = prefix $ ident ++ "_repeater_index"
assign = constructor
(LHSBit (prefix ident) (Ident index))
(Concat exprs)
inir = (index, b)
chkr = BinOp Le (Ident index) a
incr = (index, BinOp Add (Ident index) (Number "1"))
convertAssignment constructor lhs expr =
constructor (rewriteLHS dimMap lhs) (rewriteExpr dimMap expr)
convertModuleItem :: DimMap -> ModuleItem -> ModuleItem
convertModuleItem dimMap (LocalNet t x val) =
if Map.member x dimMap
then LocalNet t' x val'
else LocalNet t x val'
where
(tf, rs) = typeDims t
t' = tf $ flattenRanges rs
val' = rewriteRangesOrAssignment dimMap val
convertModuleItem dimMap (PortDecl dir rs x) =
if Map.member x dimMap
then PortDecl dir (flattenRanges rs) x
else PortDecl dir rs x
convertModuleItem dimMap (Generate items) =
Generate $ map (convertGenItem dimMap) items
convertModuleItem dimMap (Assign lhs expr) =
Assign (rewriteLHS dimMap lhs) (rewriteExpr dimMap expr)
convertModuleItem dimMap (AlwaysC kw stmt) =
AlwaysC kw (rewriteStmt dimMap stmt)
convertModuleItem dimMap (Function ret f decls stmt) =
Function ret f decls (rewriteStmt dimMap stmt)
convertModuleItem _ (Instance m params x Nothing) =
Instance m params x Nothing
convertModuleItem dimMap (Instance m params x (Just l)) =
Instance m params x $ Just $ map convertPortBinding l
where
convertPortBinding :: PortBinding -> PortBinding
convertPortBinding (p, Nothing) = (p, Nothing)
convertPortBinding (p, Just e) = (p, Just $ rewriteExpr dimMap e)
convertModuleItem _ (Comment x) = Comment x
convertModuleItem _ (Genvar x) = Genvar x
convertModuleItem _ (MIParameter x) = MIParameter x
convertModuleItem _ (MILocalparam x) = MILocalparam x
convertModuleItem _ (MIIntegerV x) = MIIntegerV x
convertGenItem :: DimMap -> GenItem -> GenItem
convertGenItem dimMap item = convertGenItem' item
where
f :: ModuleItem -> ModuleItem
f = convertModuleItem dimMap
convertGenItem' :: GenItem -> GenItem
convertGenItem' (GenBlock x items) = GenBlock x $ map convertGenItem' items
convertGenItem' (GenFor a b c d items) = GenFor a b c d $ map convertGenItem' items
convertGenItem' (GenIf e i1 i2) = GenIf e (convertGenItem' i1) (convertGenItem' i2)
convertGenItem' (GenNull) = GenNull
convertGenItem' (GenModuleItem moduleItem) = GenModuleItem $ f moduleItem
convertGenItem' (GenCase e cases def) = GenCase e cases' def'
where
cases' = zip (map fst cases) (map (convertGenItem' . snd) cases)
def' = if def == Nothing
then Nothing
else Just $ convertGenItem' $ fromJust def
...@@ -21,6 +21,7 @@ module Language.SystemVerilog.AST ...@@ -21,6 +21,7 @@ module Language.SystemVerilog.AST
, Case , Case
, Range , Range
, GenCase , GenCase
, RangesOrAssignment
) where ) where
import Data.List import Data.List
...@@ -322,7 +323,7 @@ commas = intercalate ", " ...@@ -322,7 +323,7 @@ commas = intercalate ", "
instance Show Stmt where instance Show Stmt where
show (Block Nothing b ) = printf "begin\n%s\nend" $ indent $ unlines' $ map show b show (Block Nothing b ) = printf "begin\n%s\nend" $ indent $ unlines' $ map show b
show (Block (Just (a, i)) b ) = printf "begin : %s\n%s%s\nend" a $ indent $ unlines' $ (map show i ++ map show b) show (Block (Just (a, i)) b ) = printf "begin : %s\n%s\nend" a $ indent $ unlines' $ (map show i ++ map show b)
show (Case a b Nothing ) = printf "case (%s)\n%s\nendcase" (show a) (indent $ unlines' $ map showCase b) show (Case a b Nothing ) = printf "case (%s)\n%s\nendcase" (show a) (indent $ unlines' $ map showCase b)
show (Case a b (Just c) ) = printf "case (%s)\n%s\n\tdefault:\n%s\nendcase" (show a) (indent $ unlines' $ map showCase b) (indent $ indent $ show c) show (Case a b (Just c) ) = printf "case (%s)\n%s\n\tdefault:\n%s\nendcase" (show a) (indent $ unlines' $ map showCase b) (indent $ indent $ show c)
show (BlockingAssignment a b ) = printf "%s = %s;" (show a) (show b) show (BlockingAssignment a b ) = printf "%s = %s;" (show a) (show b)
...@@ -335,7 +336,7 @@ instance Show Stmt where ...@@ -335,7 +336,7 @@ instance Show Stmt where
data BlockItemDeclaration data BlockItemDeclaration
-- TODO: Maybe BIDReg should use [Range] for the first arg as well, but it's -- TODO: Maybe BIDReg should use [Range] for the first arg as well, but it's
-- really not clear to me what useful purpose this would have. -- really not clear to me what *useful* purpose this would have.
= BIDReg (Maybe Range) Identifier [Range] = BIDReg (Maybe Range) Identifier [Range]
| BIDParameter Parameter | BIDParameter Parameter
| BIDLocalparam Localparam | BIDLocalparam Localparam
......
...@@ -62,6 +62,7 @@ executable sv2v ...@@ -62,6 +62,7 @@ executable sv2v
Convert Convert
Convert.AlwaysKW Convert.AlwaysKW
Convert.Logic Convert.Logic
Convert.PackedArrayFlatten
Convert.StarPort Convert.StarPort
Convert.Typedef Convert.Typedef
Convert.Template.ModuleItem Convert.Template.ModuleItem
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment