Commit 9305c0f4 by Zachary Snow

PackedArray conversion supports complex shadowing

parent 9c1fc7d0
...@@ -21,106 +21,49 @@ module Convert.PackedArray (convert) where ...@@ -21,106 +21,49 @@ module Convert.PackedArray (convert) where
import Control.Monad.State import Control.Monad.State
import Data.Tuple (swap) import Data.Tuple (swap)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
type DimMap = Map.Map Identifier [Range] type DimMap = Map.Map Identifier [Range]
type IdentSet = Set.Set Identifier
data Info = Info data Info = Info
{ sTypeDims :: DimMap { sTypeDims :: DimMap
, sIdents :: IdentSet } deriving (Eq, Show)
} deriving Show
defaultInfo :: Info
defaultInfo = Info Map.empty Set.empty
convert :: AST -> AST convert :: AST -> AST
convert = traverseDescriptions convertDescription convert = traverseDescriptions convertDescription
convertDescription :: Description -> Description convertDescription :: Description -> Description
convertDescription (description @ (Part _ _ _ _ _ _)) = convertDescription (description @ (Part _ _ _ _ _ _)) =
traverseModuleItems (convertModuleItem info) description evalState
where (initialTraverse description >>= scopedTraverse)
collector = collectModuleItemsM $ collectDeclsM' ExcludeTFs collectDecl (Info Map.empty)
info = execState (collector description) defaultInfo where
initialTraverse = traverseModuleItemsM traverseMIDecl
scopedTraverse = traverseModuleItemsM $
traverseScopesM traverseDeclM traverseModuleItemM traverseStmtM
traverseMIDecl :: ModuleItem -> State Info ModuleItem
traverseMIDecl (MIDecl decl) =
traverseDeclM decl >>= return . MIDecl
traverseMIDecl other = return other
convertDescription description = description convertDescription description = description
-- collects packed-array dimension and variable existing info into the state -- collects and converts multi-dimensional packed-array declarations
collectDecl :: Decl -> State Info () traverseDeclM :: Decl -> State Info Decl
collectDecl (Variable _ t ident _ _) = do traverseDeclM (origDecl @ (Variable dir t ident a me)) = do
Info typeDims idents <- get Info typeDims <- get
let (_, rs) = typeRanges t let (tf, rs) = typeRanges t
let typeDims' = if length rs <= 1
if not (isImplicit t) && length rs > 1 then do
then Map.insert ident rs typeDims put $ Info $ Map.delete ident typeDims
else typeDims return origDecl
let idents' = else do
if not (isImplicit t) put $ Info $ Map.insert ident rs typeDims
then let r1 : r2 : rest = rs
if Set.member ident idents let rs' = (combineRanges r1 r2) : rest
then error $ "unsupported complex shadowing of " ++ show ident return $ Variable dir (tf rs') ident a me
else Set.insert ident idents traverseDeclM other = return other
else idents
put $ Info typeDims' idents'
where
isImplicit :: Type -> Bool
isImplicit (Implicit _ _) = True
isImplicit _ = False
collectDecl _ = return ()
-- shadows the latter info with the former
combineInfo :: Info -> Info -> Info
combineInfo local global =
Info typeDims idents
where
Info globalTypeDims globalIdents = global
Info localTypeDims localIdents = local
idents = Set.union globalIdents localIdents
typeDims = Map.union localTypeDims $
Map.withoutKeys globalTypeDims localIdents
-- Convert the multi-dimensional packed arrays within the given module item.
-- This function must ensure that function/task level shadowing is respected.
convertModuleItem :: Info -> ModuleItem -> ModuleItem
convertModuleItem globalInfo (orig @ (MIPackageItem (Function ml t x decls stmts))) =
rewrite info $
MIPackageItem $ Function ml t' x decls stmts
where
localInfo =
execState (collectDecl $ Variable Local t x [] Nothing) $
execState (collectDeclsM collectDecl orig) $
defaultInfo
info = combineInfo localInfo globalInfo
-- rewrite the return type of this function
Variable Local t' _ [] Nothing =
flattenDecl info $ Variable Local t x [] Nothing
convertModuleItem globalInfo (orig @ (MIPackageItem (Task ml x decls stmts))) =
rewrite info $
MIPackageItem $ Task ml x decls stmts
where
localInfo =
execState (collectDeclsM collectDecl orig) $
defaultInfo
info = combineInfo localInfo globalInfo
convertModuleItem info other =
rewrite info other
-- combine the leading two packed ranges of a declaration
flattenDecl :: Info -> Decl -> Decl
flattenDecl info (origDecl @ (Variable dir t ident a me)) =
if Map.notMember ident typeDims
then origDecl
else flatDecl
where
typeDims = sTypeDims info
(tf, rs) = typeRanges t
r1 : r2 : rest = rs
rs' = (combineRanges r1 r2) : rest
flatDecl = Variable dir (tf rs') ident a me
flattenDecl _ other = other
-- combines two ranges into one flattened range -- combines two ranges into one flattened range
combineRanges :: Range -> Range -> Range combineRanges :: Range -> Range -> Range
...@@ -144,13 +87,25 @@ combineRanges r1 r2 = r ...@@ -144,13 +87,25 @@ combineRanges r1 r2 = r
upper = BinOp Add (BinOp Mul size1 size2) upper = BinOp Add (BinOp Mul size1 size2)
(BinOp Sub lower (Number "1")) (BinOp Sub lower (Number "1"))
-- rewrite the declarations, expressions, and lvals in a module item to remove traverseModuleItemM :: ModuleItem -> State Info ModuleItem
-- the packed array dimensions captured in the given info traverseModuleItemM item =
rewrite :: Info -> ModuleItem -> ModuleItem traverseLHSsM traverseLHSM item >>=
rewrite info = traverseExprsM traverseExprM
traverseDecls (flattenDecl info) .
traverseLHSs (traverseNestedLHSs rewriteLHS ) . traverseStmtM :: Stmt -> State Info Stmt
traverseExprs (traverseNestedExprs rewriteExpr) traverseStmtM stmt =
traverseStmtLHSsM traverseLHSM stmt >>=
traverseStmtExprsM traverseExprM
traverseExprM :: Expr -> State Info Expr
traverseExprM = traverseNestedExprsM $ stately traverseExpr
traverseLHSM :: LHS -> State Info LHS
traverseLHSM = traverseNestedLHSsM $ stately traverseLHS
traverseExpr :: Info -> Expr -> Expr
traverseExpr info =
rewriteExpr
where where
typeDims = sTypeDims info typeDims = sTypeDims info
...@@ -249,9 +204,16 @@ rewrite info = ...@@ -249,9 +204,16 @@ rewrite info =
range' = (base, len) range' = (base, len)
rewriteExpr other = other rewriteExpr other = other
-- LHSs need to be converted too. Rather than duplicating the -- LHSs need to be converted too. Rather than duplicating the procedures, we
-- procedures, we turn the relevant LHSs into expressions temporarily -- turn the relevant LHSs into expressions temporarily and use the expression
-- and use the expression conversion written above. -- conversion written above.
traverseLHS :: Info -> LHS -> LHS
traverseLHS info =
rewriteLHS
where
typeDims = sTypeDims info
rewriteExpr = traverseExpr info
rewriteLHS :: LHS -> LHS rewriteLHS :: LHS -> LHS
rewriteLHS (LHSIdent x) = rewriteLHS (LHSIdent x) =
LHSIdent x' LHSIdent x'
......
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