2019-09-27 04:47:36 +02:00
|
|
|
{- sv2v
|
|
|
|
|
- Author: Zachary Snow <zach@zachjs.com>
|
|
|
|
|
-
|
|
|
|
|
- Conversion for any unpacked array which must be packed because it is: A) a
|
2020-02-14 05:59:01 +01:00
|
|
|
- port; B) is bound to a port; C) is assigned a value in a single assignment;
|
2020-06-06 19:42:30 +02:00
|
|
|
- or D) is assigned to an unpacked array which itself must be packed.
|
2019-09-27 04:47:36 +02:00
|
|
|
-
|
|
|
|
|
- The scoped nature of declarations makes this challenging. While scoping is
|
2020-06-06 19:42:30 +02:00
|
|
|
- obeyed in general, if any of a set of *equivalent* declarations within a
|
|
|
|
|
- module is packed, all of the declarations are packed. This is because we only
|
|
|
|
|
- record the declaration that needs to be packed when a relevant usage is
|
|
|
|
|
- encountered.
|
2019-09-27 04:47:36 +02:00
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
module Convert.UnpackedArray (convert) where
|
|
|
|
|
|
|
|
|
|
import Control.Monad.State
|
|
|
|
|
import qualified Data.Set as Set
|
|
|
|
|
|
2020-07-15 06:22:41 +02:00
|
|
|
import Convert.Scoper
|
2019-09-27 04:47:36 +02:00
|
|
|
import Convert.Traverse
|
|
|
|
|
import Language.SystemVerilog.AST
|
|
|
|
|
|
2020-07-15 06:22:41 +02:00
|
|
|
type Location = [Identifier]
|
|
|
|
|
type Locations = Set.Set Location
|
|
|
|
|
type ST = ScoperT Decl (State Locations)
|
2019-09-27 04:47:36 +02:00
|
|
|
|
|
|
|
|
convert :: [AST] -> [AST]
|
|
|
|
|
convert = map $ traverseDescriptions convertDescription
|
|
|
|
|
|
|
|
|
|
convertDescription :: Description -> Description
|
2020-07-15 06:22:41 +02:00
|
|
|
convertDescription (description @ (Part _ _ Module _ _ _ _)) =
|
|
|
|
|
evalState (operation description) Set.empty
|
2019-09-27 04:47:36 +02:00
|
|
|
where
|
2020-07-15 06:22:41 +02:00
|
|
|
operation =
|
|
|
|
|
partScoperT traverseDeclM traverseModuleItemM noop traverseStmtM >=>
|
|
|
|
|
partScoperT rewriteDeclM noop noop noop
|
|
|
|
|
noop = return
|
|
|
|
|
convertDescription other = other
|
2019-09-27 04:47:36 +02:00
|
|
|
|
2020-07-15 06:22:41 +02:00
|
|
|
-- tracks multi-dimensional unpacked array declarations
|
2019-09-27 04:47:36 +02:00
|
|
|
traverseDeclM :: Decl -> ST Decl
|
2020-07-15 06:22:41 +02:00
|
|
|
traverseDeclM (decl @ (Variable _ _ _ [] _)) = return decl
|
|
|
|
|
traverseDeclM (decl @ (Variable dir _ x _ e)) = do
|
|
|
|
|
insertElem x decl
|
|
|
|
|
if dir /= Local || e /= Nil
|
|
|
|
|
then flatUsageM x
|
2019-09-27 04:47:36 +02:00
|
|
|
else return ()
|
2020-07-15 06:22:41 +02:00
|
|
|
return decl
|
2020-01-31 04:17:17 +01:00
|
|
|
traverseDeclM other = return other
|
2019-09-27 04:47:36 +02:00
|
|
|
|
2020-07-15 06:22:41 +02:00
|
|
|
-- pack decls marked for packing
|
|
|
|
|
rewriteDeclM :: Decl -> ST Decl
|
|
|
|
|
rewriteDeclM (decl @ (Variable _ _ _ [] _)) = return decl
|
|
|
|
|
rewriteDeclM (decl @ (Variable d t x a e)) = do
|
|
|
|
|
insertElem x decl
|
|
|
|
|
details <- lookupElemM x
|
|
|
|
|
let Just (accesses, _, _) = details
|
|
|
|
|
let location = map accessName accesses
|
|
|
|
|
usedAsPacked <- lift $ gets $ Set.member location
|
|
|
|
|
if usedAsPacked
|
2019-09-27 04:47:36 +02:00
|
|
|
then do
|
|
|
|
|
let (tf, rs) = typeRanges t
|
|
|
|
|
let t' = tf $ a ++ rs
|
2020-07-15 06:22:41 +02:00
|
|
|
return $ Variable d t' x [] e
|
|
|
|
|
else return decl
|
|
|
|
|
rewriteDeclM other = return other
|
2019-09-27 04:47:36 +02:00
|
|
|
|
|
|
|
|
traverseModuleItemM :: ModuleItem -> ST ModuleItem
|
2020-06-20 22:41:13 +02:00
|
|
|
traverseModuleItemM =
|
|
|
|
|
traverseModuleItemM'
|
|
|
|
|
>=> traverseLHSsM traverseLHSM
|
|
|
|
|
>=> traverseExprsM traverseExprM
|
|
|
|
|
>=> traverseAsgnsM traverseAsgnM
|
2019-09-27 04:47:36 +02:00
|
|
|
|
|
|
|
|
traverseModuleItemM' :: ModuleItem -> ST ModuleItem
|
|
|
|
|
traverseModuleItemM' (Instance a b c d bindings) = do
|
|
|
|
|
bindings' <- mapM collectBinding bindings
|
|
|
|
|
return $ Instance a b c d bindings'
|
|
|
|
|
where
|
|
|
|
|
collectBinding :: PortBinding -> ST PortBinding
|
2020-07-15 06:22:41 +02:00
|
|
|
collectBinding (y, x) = do
|
2019-09-27 04:47:36 +02:00
|
|
|
flatUsageM x
|
2020-07-15 06:22:41 +02:00
|
|
|
return (y, x)
|
2019-09-27 04:47:36 +02:00
|
|
|
traverseModuleItemM' other = return other
|
|
|
|
|
|
|
|
|
|
traverseStmtM :: Stmt -> ST Stmt
|
2020-06-20 22:41:13 +02:00
|
|
|
traverseStmtM =
|
|
|
|
|
traverseStmtLHSsM traverseLHSM >=>
|
|
|
|
|
traverseStmtExprsM traverseExprM >=>
|
2020-02-14 05:59:01 +01:00
|
|
|
traverseStmtAsgnsM traverseAsgnM
|
2019-09-27 04:47:36 +02:00
|
|
|
|
|
|
|
|
traverseExprM :: Expr -> ST Expr
|
2020-07-15 06:22:41 +02:00
|
|
|
traverseExprM (Range x mode i) =
|
|
|
|
|
flatUsageM x >> return (Range x mode i)
|
2020-03-19 04:39:40 +01:00
|
|
|
traverseExprM other = return other
|
2019-09-27 04:47:36 +02:00
|
|
|
|
|
|
|
|
traverseLHSM :: LHS -> ST LHS
|
2020-07-15 06:22:41 +02:00
|
|
|
traverseLHSM x = flatUsageM x >> return x
|
2019-09-27 04:47:36 +02:00
|
|
|
|
2020-02-14 05:59:01 +01:00
|
|
|
traverseAsgnM :: (LHS, Expr) -> ST (LHS, Expr)
|
2020-07-15 06:22:41 +02:00
|
|
|
traverseAsgnM (x, Mux cond y z) = do
|
2020-06-06 19:42:30 +02:00
|
|
|
flatUsageM x
|
|
|
|
|
flatUsageM y
|
|
|
|
|
flatUsageM z
|
2020-07-15 06:22:41 +02:00
|
|
|
return (x, Mux cond y z)
|
|
|
|
|
traverseAsgnM (x, y) = do
|
2020-02-14 05:59:01 +01:00
|
|
|
flatUsageM x
|
|
|
|
|
flatUsageM y
|
2020-07-15 06:22:41 +02:00
|
|
|
return (x, y)
|
2020-02-14 05:59:01 +01:00
|
|
|
|
2020-07-15 06:22:41 +02:00
|
|
|
flatUsageM :: ScopeKey e => e -> ST ()
|
2019-09-27 04:47:36 +02:00
|
|
|
flatUsageM x = do
|
2020-07-15 06:22:41 +02:00
|
|
|
details <- lookupElemM x
|
|
|
|
|
case details of
|
|
|
|
|
Just (accesses, _, _) -> do
|
|
|
|
|
let location = map accessName accesses
|
|
|
|
|
lift $ modify $ Set.insert location
|
2019-09-27 04:47:36 +02:00
|
|
|
Nothing -> return ()
|