diff --git a/src/Convert/PackedArray.hs b/src/Convert/PackedArray.hs index a0b189b..6f4e1ad 100644 --- a/src/Convert/PackedArray.hs +++ b/src/Convert/PackedArray.hs @@ -21,106 +21,49 @@ module Convert.PackedArray (convert) where import Control.Monad.State import Data.Tuple (swap) import qualified Data.Map.Strict as Map -import qualified Data.Set as Set import Convert.Traverse import Language.SystemVerilog.AST type DimMap = Map.Map Identifier [Range] -type IdentSet = Set.Set Identifier data Info = Info { sTypeDims :: DimMap - , sIdents :: IdentSet - } deriving Show - -defaultInfo :: Info -defaultInfo = Info Map.empty Set.empty + } deriving (Eq, Show) convert :: AST -> AST convert = traverseDescriptions convertDescription convertDescription :: Description -> Description convertDescription (description @ (Part _ _ _ _ _ _)) = - traverseModuleItems (convertModuleItem info) description + evalState + (initialTraverse description >>= scopedTraverse) + (Info Map.empty) where - collector = collectModuleItemsM $ collectDeclsM' ExcludeTFs collectDecl - info = execState (collector description) defaultInfo + 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 --- collects packed-array dimension and variable existing info into the state -collectDecl :: Decl -> State Info () -collectDecl (Variable _ t ident _ _) = do - Info typeDims idents <- get - let (_, rs) = typeRanges t - let typeDims' = - if not (isImplicit t) && length rs > 1 - then Map.insert ident rs typeDims - else typeDims - let idents' = - if not (isImplicit t) - then - if Set.member ident idents - then error $ "unsupported complex shadowing of " ++ show ident - else Set.insert ident idents - 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 +-- collects and converts multi-dimensional packed-array declarations +traverseDeclM :: Decl -> State Info Decl +traverseDeclM (origDecl @ (Variable dir t ident a me)) = do + Info typeDims <- get + let (tf, rs) = typeRanges t + if length rs <= 1 + then do + put $ Info $ Map.delete ident typeDims + return origDecl + else do + put $ Info $ Map.insert ident rs typeDims + let r1 : r2 : rest = rs + let rs' = (combineRanges r1 r2) : rest + return $ Variable dir (tf rs') ident a me +traverseDeclM other = return other -- combines two ranges into one flattened range combineRanges :: Range -> Range -> Range @@ -144,13 +87,25 @@ combineRanges r1 r2 = r upper = BinOp Add (BinOp Mul size1 size2) (BinOp Sub lower (Number "1")) --- rewrite the declarations, expressions, and lvals in a module item to remove --- the packed array dimensions captured in the given info -rewrite :: Info -> ModuleItem -> ModuleItem -rewrite info = - traverseDecls (flattenDecl info) . - traverseLHSs (traverseNestedLHSs rewriteLHS ) . - traverseExprs (traverseNestedExprs rewriteExpr) +traverseModuleItemM :: ModuleItem -> State Info ModuleItem +traverseModuleItemM item = + traverseLHSsM traverseLHSM item >>= + traverseExprsM traverseExprM + +traverseStmtM :: Stmt -> State Info Stmt +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 typeDims = sTypeDims info @@ -249,9 +204,16 @@ rewrite info = range' = (base, len) rewriteExpr other = other - -- LHSs need to be converted too. Rather than duplicating the - -- procedures, we turn the relevant LHSs into expressions temporarily - -- and use the expression conversion written above. +-- LHSs need to be converted too. Rather than duplicating the procedures, we +-- turn the relevant LHSs into expressions temporarily and use the expression +-- conversion written above. +traverseLHS :: Info -> LHS -> LHS +traverseLHS info = + rewriteLHS + where + typeDims = sTypeDims info + rewriteExpr = traverseExpr info + rewriteLHS :: LHS -> LHS rewriteLHS (LHSIdent x) = LHSIdent x' diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index 84b85f7..1ffc802 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -32,6 +32,9 @@ module Convert.Traverse , traverseExprsM' , traverseExprs' , collectExprsM' +, traverseStmtExprsM +, traverseStmtExprs +, collectStmtExprsM , traverseLHSsM , traverseLHSs , collectLHSsM @@ -61,11 +64,14 @@ module Convert.Traverse , collectNestedModuleItemsM , traverseNestedStmts , collectNestedStmtsM +, traverseNestedExprsM , traverseNestedExprs , collectNestedExprsM , traverseNestedLHSsM , traverseNestedLHSs , collectNestedLHSsM +, traverseScopesM +, stately ) where import Control.Monad.State @@ -188,7 +194,12 @@ collectStmtsM = collectStmtsM' IncludeTFs traverseNestedStmtsM :: Monad m => MapperM m Stmt -> MapperM m Stmt traverseNestedStmtsM mapper = fullMapper where - fullMapper stmt = mapper stmt >>= cs + fullMapper stmt = mapper stmt >>= traverseSinglyNestedStmtsM fullMapper + +-- variant of the above which only traverse one level down +traverseSinglyNestedStmtsM :: Monad m => MapperM m Stmt -> MapperM m Stmt +traverseSinglyNestedStmtsM fullMapper = cs + where cs (StmtAttr a stmt) = fullMapper stmt >>= return . StmtAttr a cs (Block name decls stmts) = mapM fullMapper stmts >>= return . Block name decls @@ -430,9 +441,10 @@ traverseNestedExprsM mapper = exprMapper exprs <- mapM exprMapper $ map snd l return $ Pattern $ zip names exprs - -traverseExprsM' :: Monad m => TFStrategy -> MapperM m Expr -> MapperM m ModuleItem -traverseExprsM' strat mapper = moduleItemMapper +exprMapperHelpers :: Monad m => MapperM m Expr -> + (MapperM m Range, MapperM m (Maybe Expr), MapperM m Decl) +exprMapperHelpers exprMapper = + (rangeMapper, maybeExprMapper, declMapper) where rangeMapper (a, b) = do @@ -453,59 +465,14 @@ traverseExprsM' strat mapper = moduleItemMapper me' <- maybeExprMapper me return $ Variable d t x a' me' - exprMapper = mapper +traverseExprsM' :: Monad m => TFStrategy -> MapperM m Expr -> MapperM m ModuleItem +traverseExprsM' strat exprMapper = moduleItemMapper + where - caseMapper (exprs, stmt) = do - exprs' <- mapM exprMapper exprs - return (exprs', stmt) - stmtMapper = traverseNestedStmtsM flatStmtMapper - flatStmtMapper (StmtAttr attr stmt) = - -- note: we exclude expressions in attributes from conversion - return $ StmtAttr attr stmt - flatStmtMapper (Block name decls stmts) = do - decls' <- mapM declMapper decls - return $ Block name decls' stmts - flatStmtMapper (Case u kw e cases def) = do - e' <- exprMapper e - cases' <- mapM caseMapper cases - return $ Case u kw e' cases' def - flatStmtMapper (AsgnBlk op lhs expr) = - exprMapper expr >>= return . AsgnBlk op lhs - flatStmtMapper (Asgn mt lhs expr) = - exprMapper expr >>= return . Asgn mt lhs - flatStmtMapper (For inits cc asgns stmt) = do - inits' <- mapM initMapper inits - cc' <- maybeExprMapper cc - asgns' <- mapM asgnMapper asgns - return $ For inits' cc' asgns' stmt - flatStmtMapper (While e stmt) = - exprMapper e >>= \e' -> return $ While e' stmt - flatStmtMapper (RepeatL e stmt) = - exprMapper e >>= \e' -> return $ RepeatL e' stmt - flatStmtMapper (DoWhile e stmt) = - exprMapper e >>= \e' -> return $ DoWhile e' stmt - flatStmtMapper (Forever stmt) = return $ Forever stmt - flatStmtMapper (If u cc s1 s2) = - exprMapper cc >>= \cc' -> return $ If u cc' s1 s2 - flatStmtMapper (Timing event stmt) = return $ Timing event stmt - flatStmtMapper (Subroutine f (Args l p)) = do - l' <- mapM maybeExprMapper l - pes <- mapM maybeExprMapper $ map snd p - let p' = zip (map fst p) pes - return $ Subroutine f (Args l' p') - flatStmtMapper (Return expr) = - exprMapper expr >>= return . Return - flatStmtMapper (Trigger x) = return $ Trigger x - flatStmtMapper (Assertion a) = do - a' <- traverseAssertionStmtsM stmtMapper a - a'' <- traverseAssertionExprsM exprMapper a' - return $ Assertion a'' - flatStmtMapper (Null) = return Null + (rangeMapper, maybeExprMapper, declMapper) + = exprMapperHelpers exprMapper - initMapper (Left decl) = declMapper decl >>= return . Left - initMapper (Right (l, e)) = exprMapper e >>= \e' -> return $ Right (l, e') - - asgnMapper (l, op, e) = exprMapper e >>= \e' -> return $ (l, op, e') + stmtMapper = traverseNestedStmtsM (traverseStmtExprsM exprMapper) portBindingMapper (p, me) = maybeExprMapper me >>= \me' -> return (p, me') @@ -602,6 +569,70 @@ traverseExprs = traverseExprs' IncludeTFs collectExprsM :: Monad m => CollectorM m Expr -> CollectorM m ModuleItem collectExprsM = collectExprsM' IncludeTFs +traverseStmtExprsM :: Monad m => MapperM m Expr -> MapperM m Stmt +traverseStmtExprsM exprMapper = flatStmtMapper + where + + (_, maybeExprMapper, declMapper) + = exprMapperHelpers exprMapper + + caseMapper (exprs, stmt) = do + exprs' <- mapM exprMapper exprs + return (exprs', stmt) + stmtMapper = traverseNestedStmtsM flatStmtMapper + flatStmtMapper (StmtAttr attr stmt) = + -- note: we exclude expressions in attributes from conversion + return $ StmtAttr attr stmt + flatStmtMapper (Block name decls stmts) = do + decls' <- mapM declMapper decls + return $ Block name decls' stmts + flatStmtMapper (Case u kw e cases def) = do + e' <- exprMapper e + cases' <- mapM caseMapper cases + return $ Case u kw e' cases' def + flatStmtMapper (AsgnBlk op lhs expr) = + exprMapper expr >>= return . AsgnBlk op lhs + flatStmtMapper (Asgn mt lhs expr) = + exprMapper expr >>= return . Asgn mt lhs + flatStmtMapper (For inits cc asgns stmt) = do + inits' <- mapM initMapper inits + cc' <- maybeExprMapper cc + asgns' <- mapM asgnMapper asgns + return $ For inits' cc' asgns' stmt + flatStmtMapper (While e stmt) = + exprMapper e >>= \e' -> return $ While e' stmt + flatStmtMapper (RepeatL e stmt) = + exprMapper e >>= \e' -> return $ RepeatL e' stmt + flatStmtMapper (DoWhile e stmt) = + exprMapper e >>= \e' -> return $ DoWhile e' stmt + flatStmtMapper (Forever stmt) = return $ Forever stmt + flatStmtMapper (If u cc s1 s2) = + exprMapper cc >>= \cc' -> return $ If u cc' s1 s2 + flatStmtMapper (Timing event stmt) = return $ Timing event stmt + flatStmtMapper (Subroutine f (Args l p)) = do + l' <- mapM maybeExprMapper l + pes <- mapM maybeExprMapper $ map snd p + let p' = zip (map fst p) pes + return $ Subroutine f (Args l' p') + flatStmtMapper (Return expr) = + exprMapper expr >>= return . Return + flatStmtMapper (Trigger x) = return $ Trigger x + flatStmtMapper (Assertion a) = do + a' <- traverseAssertionStmtsM stmtMapper a + a'' <- traverseAssertionExprsM exprMapper a' + return $ Assertion a'' + flatStmtMapper (Null) = return Null + + initMapper (Left decl) = declMapper decl >>= return . Left + initMapper (Right (l, e)) = exprMapper e >>= \e' -> return $ Right (l, e') + + asgnMapper (l, op, e) = exprMapper e >>= \e' -> return $ (l, op, e') + +traverseStmtExprs :: Mapper Expr -> Mapper Stmt +traverseStmtExprs = unmonad traverseStmtExprsM +collectStmtExprsM :: Monad m => CollectorM m Expr -> CollectorM m Stmt +collectStmtExprsM = collectify traverseStmtExprsM + traverseLHSsM' :: Monad m => TFStrategy -> MapperM m LHS -> MapperM m ModuleItem traverseLHSsM' strat mapper item = traverseStmtsM' strat (traverseStmtLHSsM mapper) item >>= traverseModuleItemLHSsM @@ -837,3 +868,68 @@ traverseNestedExprs :: Mapper Expr -> Mapper Expr traverseNestedExprs = unmonad traverseNestedExprsM collectNestedExprsM :: Monad m => CollectorM m Expr -> CollectorM m Expr collectNestedExprsM = collectify traverseNestedExprsM + +-- Traverse all the declaration scopes within a ModuleItem. Note that Functions, +-- Tasks, Always and Initial blocks are all NOT passed through ModuleItem +-- mapper, and MIDecl ModuleItems are NOT passed through the Decl mapper. The +-- state is restored to its previous value after each scope is exited. Only the +-- Decl mapper may modify the state, as we maintain the invariant that all other +-- functions restore the state on exit. The Stmt mapper must not traverse +-- statements recursively, as we add a recursive wrapper here. +traverseScopesM + :: (Eq s, Show s) + => MapperM (State s) Decl + -> MapperM (State s) ModuleItem + -> MapperM (State s) Stmt + -> MapperM (State s) ModuleItem +traverseScopesM declMapper moduleItemMapper stmtMapper = + fullModuleItemMapper + where + + fullStmtMapper stmt = stmtMapper stmt >>= traverseSinglyNestedStmtsM cs + cs (Block name decls stmts) = do + prevState <- get + decls' <- mapM declMapper decls + block <- fullStmtMapper $ Block name decls' stmts + put prevState + return block + cs other = fullStmtMapper other + + redirectModuleItem (MIPackageItem (Function ml t x decls stmts)) = do + prevState <- get + t' <- do + res <- declMapper $ Variable Local t x [] Nothing + case res of + Variable Local newType _ [] Nothing -> return newType + _ -> error $ "redirected func ret traverse failed: " ++ show res + decls' <- mapM declMapper decls + stmts' <- mapM fullStmtMapper stmts + put prevState + return $ MIPackageItem $ Function ml t' x decls' stmts' + redirectModuleItem (MIPackageItem (Task ml x decls stmts)) = do + prevState <- get + decls' <- mapM declMapper decls + stmts' <- mapM fullStmtMapper stmts + put prevState + return $ MIPackageItem $ Task ml x decls' stmts' + redirectModuleItem (AlwaysC kw stmt) = + fullStmtMapper stmt >>= return . AlwaysC kw + redirectModuleItem (Initial stmt) = + fullStmtMapper stmt >>= return . Initial + redirectModuleItem item = + moduleItemMapper item + + fullModuleItemMapper item = do + prevState <- get + item' <- redirectModuleItem item + currState <- get + if prevState == currState + then return item' + else error $ "illegal scope state modification: " + ++ show (prevState, item, currState, item') + +-- convert a basic mapper with an initial argument to a stateful mapper +stately :: (Eq s, Show s) => (s -> Mapper a) -> MapperM (State s) a +stately mapper thing = do + s <- get + return $ mapper s thing diff --git a/test/basic/packed_array_shadow.sv b/test/basic/packed_array_shadow.sv index 6f1b668..8d4d99c 100644 --- a/test/basic/packed_array_shadow.sv +++ b/test/basic/packed_array_shadow.sv @@ -94,21 +94,180 @@ module top; end + initial begin + begin : lol_block + logic [1:0][1:0] arr; + arr = 4'b1001; + $display("LOL: $bits(arr): ", $bits(arr )); + $display("LOL: $bits(arr[0]): ", $bits(arr[0] )); + $display("LOL: $bits(arr[0][0]): ", $bits(arr[0][0])); + $display("LOL: arr[0]: ", arr[0]); + $display("LOL: arr[1]: ", arr[1]); + $display("LOL: arr[0][1]: ", arr[0][1]); + $display("LOL: arr[1][0]: ", arr[1][0]); + $display("LOL: arr[1][1]: ", arr[1][1]); + end + end + + task magic; begin - begin : magic_block + begin : magic_block1 logic [1:0][1:0] magic_arr; magic_arr = 4'b1001; - $display("$bits(magic_arr): ", $bits(magic_arr )); - $display("$bits(magic_arr[0]): ", $bits(magic_arr[0] )); - $display("$bits(magic_arr[0][0]): ", $bits(magic_arr[0][0])); - $display("magic_arr[0][0]: ", magic_arr[0][0]); - $display("magic_arr[0][1]: ", magic_arr[0][1]); - $display("magic_arr[1][0]: ", magic_arr[1][0]); - $display("magic_arr[1][1]: ", magic_arr[1][1]); + $display("MB1: $bits(magic_arr): ", $bits(magic_arr )); + $display("MB1: $bits(magic_arr[0]): ", $bits(magic_arr[0] )); + $display("MB1: $bits(magic_arr[0][0]): ", $bits(magic_arr[0][0])); + $display("MB1: magic_arr[0]: ", magic_arr[0]); + $display("MB1: magic_arr[1]: ", magic_arr[1]); + $display("MB1: magic_arr[0][1]: ", magic_arr[0][1]); + $display("MB1: magic_arr[1][0]: ", magic_arr[1][0]); + $display("MB1: magic_arr[1][1]: ", magic_arr[1][1]); + end + begin : magic_block2 + logic [3:0] magic_arr; + magic_arr = 4'b1001; + $display("MB2: $bits(magic_arr): ", $bits(magic_arr )); + $display("MB2: $bits(magic_arr[0]): ", $bits(magic_arr[0] )); + $display("MB2: magic_arr[0]: ", magic_arr[0]); + $display("MB2: magic_arr[1]: ", magic_arr[1]); + $display("MB2: magic_arr[2]: ", magic_arr[2]); + $display("MB2: magic_arr[3]: ", magic_arr[3]); + end + begin : magic_block3 + logic [1:0][1:0][1:0] magic_arr; + magic_arr = 4'b1001; + $display("MB3: $bits(magic_arr): ", $bits(magic_arr )); + $display("MB3: $bits(magic_arr[0]): ", $bits(magic_arr[0] )); + $display("MB3: $bits(magic_arr[0][0]): ", $bits(magic_arr[0][0] )); + $display("MB3: $bits(magic_arr[0][0][0]): ", $bits(magic_arr[0][0][0])); + $display("MB3: magic_arr[0]: ", magic_arr[0]); + $display("MB3: magic_arr[1]: ", magic_arr[1]); + $display("MB3: magic_arr[0][0]: ", magic_arr[0][0]); + $display("MB3: magic_arr[0][1]: ", magic_arr[0][1]); + $display("MB3: magic_arr[1][0]: ", magic_arr[1][0]); + $display("MB3: magic_arr[1][1]: ", magic_arr[1][1]); + $display("MB3: magic_arr[0][0][0]: ", magic_arr[0][0][0]); + $display("MB3: magic_arr[0][0][1]: ", magic_arr[0][0][1]); + $display("MB3: magic_arr[0][1][0]: ", magic_arr[0][1][0]); + $display("MB3: magic_arr[0][1][1]: ", magic_arr[0][1][1]); + $display("MB3: magic_arr[1][0][1]: ", magic_arr[1][0][1]); + $display("MB3: magic_arr[1][0][0]: ", magic_arr[1][0][0]); + $display("MB3: magic_arr[1][1][1]: ", magic_arr[1][1][1]); + $display("MB3: magic_arr[1][1][0]: ", magic_arr[1][1][0]); + begin : magic_block4 + logic [1:0][1:0] magic_arr; + magic_arr = 4'b1001; + $display("MB4: $bits(magic_arr): ", $bits(magic_arr )); + $display("MB4: $bits(magic_arr[0]): ", $bits(magic_arr[0] )); + $display("MB4: $bits(magic_arr[0][0]): ", $bits(magic_arr[0][0])); + $display("MB4: magic_arr[0]: ", magic_arr[0]); + $display("MB4: magic_arr[1]: ", magic_arr[1]); + $display("MB4: magic_arr[0][1]: ", magic_arr[0][1]); + $display("MB4: magic_arr[1][0]: ", magic_arr[1][0]); + $display("MB4: magic_arr[1][1]: ", magic_arr[1][1]); + end + magic_arr = 4'b1001; + $display("MB3: $bits(magic_arr): ", $bits(magic_arr )); + $display("MB3: $bits(magic_arr[0]): ", $bits(magic_arr[0] )); + $display("MB3: $bits(magic_arr[0][0]): ", $bits(magic_arr[0][0] )); + $display("MB3: $bits(magic_arr[0][0][0]): ", $bits(magic_arr[0][0][0])); + $display("MB3: magic_arr[0]: ", magic_arr[0]); + $display("MB3: magic_arr[1]: ", magic_arr[1]); + $display("MB3: magic_arr[0][0]: ", magic_arr[0][0]); + $display("MB3: magic_arr[0][1]: ", magic_arr[0][1]); + $display("MB3: magic_arr[1][0]: ", magic_arr[1][0]); + $display("MB3: magic_arr[1][1]: ", magic_arr[1][1]); + $display("MB3: magic_arr[0][0][0]: ", magic_arr[0][0][0]); + $display("MB3: magic_arr[0][0][1]: ", magic_arr[0][0][1]); + $display("MB3: magic_arr[0][1][0]: ", magic_arr[0][1][0]); + $display("MB3: magic_arr[0][1][1]: ", magic_arr[0][1][1]); + $display("MB3: magic_arr[1][0][1]: ", magic_arr[1][0][1]); + $display("MB3: magic_arr[1][0][0]: ", magic_arr[1][0][0]); + $display("MB3: magic_arr[1][1][1]: ", magic_arr[1][1][1]); + $display("MB3: magic_arr[1][1][0]: ", magic_arr[1][1][0]); end end endtask initial magic(); + + initial begin + begin : ntf_magic_block1 + logic [1:0][1:0] ntf_magic_arr; + ntf_magic_arr = 4'b1001; + $display("NTFMB1: $bits(ntf_magic_arr): ", $bits(ntf_magic_arr )); + $display("NTFMB1: $bits(ntf_magic_arr[0]): ", $bits(ntf_magic_arr[0] )); + $display("NTFMB1: $bits(ntf_magic_arr[0][0]): ", $bits(ntf_magic_arr[0][0])); + $display("NTFMB1: ntf_magic_arr[0]: ", ntf_magic_arr[0]); + $display("NTFMB1: ntf_magic_arr[1]: ", ntf_magic_arr[1]); + $display("NTFMB1: ntf_magic_arr[0][1]: ", ntf_magic_arr[0][1]); + $display("NTFMB1: ntf_magic_arr[1][0]: ", ntf_magic_arr[1][0]); + $display("NTFMB1: ntf_magic_arr[1][1]: ", ntf_magic_arr[1][1]); + end + begin : ntf_magic_block2 + logic [3:0] ntf_magic_arr; + ntf_magic_arr = 4'b1001; + $display("NTFMB2: $bits(ntf_magic_arr): ", $bits(ntf_magic_arr )); + $display("NTFMB2: $bits(ntf_magic_arr[0]): ", $bits(ntf_magic_arr[0] )); + $display("NTFMB2: ntf_magic_arr[0]: ", ntf_magic_arr[0]); + $display("NTFMB2: ntf_magic_arr[1]: ", ntf_magic_arr[1]); + $display("NTFMB2: ntf_magic_arr[2]: ", ntf_magic_arr[2]); + $display("NTFMB2: ntf_magic_arr[3]: ", ntf_magic_arr[3]); + end + begin : ntf_magic_block3 + logic [1:0][1:0][1:0] ntf_magic_arr; + ntf_magic_arr = 4'b1001; + $display("NTFMB3: $bits(ntf_magic_arr): ", $bits(ntf_magic_arr )); + $display("NTFMB3: $bits(ntf_magic_arr[0]): ", $bits(ntf_magic_arr[0] )); + $display("NTFMB3: $bits(ntf_magic_arr[0][0]): ", $bits(ntf_magic_arr[0][0] )); + $display("NTFMB3: $bits(ntf_magic_arr[0][0][0]): ", $bits(ntf_magic_arr[0][0][0])); + $display("NTFMB3: ntf_magic_arr[0]: ", ntf_magic_arr[0]); + $display("NTFMB3: ntf_magic_arr[1]: ", ntf_magic_arr[1]); + $display("NTFMB3: ntf_magic_arr[0][0]: ", ntf_magic_arr[0][0]); + $display("NTFMB3: ntf_magic_arr[0][1]: ", ntf_magic_arr[0][1]); + $display("NTFMB3: ntf_magic_arr[1][0]: ", ntf_magic_arr[1][0]); + $display("NTFMB3: ntf_magic_arr[1][1]: ", ntf_magic_arr[1][1]); + $display("NTFMB3: ntf_magic_arr[0][0][0]: ", ntf_magic_arr[0][0][0]); + $display("NTFMB3: ntf_magic_arr[0][0][1]: ", ntf_magic_arr[0][0][1]); + $display("NTFMB3: ntf_magic_arr[0][1][0]: ", ntf_magic_arr[0][1][0]); + $display("NTFMB3: ntf_magic_arr[0][1][1]: ", ntf_magic_arr[0][1][1]); + $display("NTFMB3: ntf_magic_arr[1][0][1]: ", ntf_magic_arr[1][0][1]); + $display("NTFMB3: ntf_magic_arr[1][0][0]: ", ntf_magic_arr[1][0][0]); + $display("NTFMB3: ntf_magic_arr[1][1][1]: ", ntf_magic_arr[1][1][1]); + $display("NTFMB3: ntf_magic_arr[1][1][0]: ", ntf_magic_arr[1][1][0]); + begin : ntf_magic_block4 + logic [1:0][1:0] ntf_magic_arr; + ntf_magic_arr = 4'b1001; + $display("NTFMB4: $bits(ntf_magic_arr): ", $bits(ntf_magic_arr )); + $display("NTFMB4: $bits(ntf_magic_arr[0]): ", $bits(ntf_magic_arr[0] )); + $display("NTFMB4: $bits(ntf_magic_arr[0][0]): ", $bits(ntf_magic_arr[0][0])); + $display("NTFMB4: ntf_magic_arr[0]: ", ntf_magic_arr[0]); + $display("NTFMB4: ntf_magic_arr[1]: ", ntf_magic_arr[1]); + $display("NTFMB4: ntf_magic_arr[0][1]: ", ntf_magic_arr[0][1]); + $display("NTFMB4: ntf_magic_arr[1][0]: ", ntf_magic_arr[1][0]); + $display("NTFMB4: ntf_magic_arr[1][1]: ", ntf_magic_arr[1][1]); + end + ntf_magic_arr = 4'b1001; + $display("NTFMB3: $bits(ntf_magic_arr): ", $bits(ntf_magic_arr )); + $display("NTFMB3: $bits(ntf_magic_arr[0]): ", $bits(ntf_magic_arr[0] )); + $display("NTFMB3: $bits(ntf_magic_arr[0][0]): ", $bits(ntf_magic_arr[0][0] )); + $display("NTFMB3: $bits(ntf_magic_arr[0][0][0]): ", $bits(ntf_magic_arr[0][0][0])); + $display("NTFMB3: ntf_magic_arr[0]: ", ntf_magic_arr[0]); + $display("NTFMB3: ntf_magic_arr[1]: ", ntf_magic_arr[1]); + $display("NTFMB3: ntf_magic_arr[0][0]: ", ntf_magic_arr[0][0]); + $display("NTFMB3: ntf_magic_arr[0][1]: ", ntf_magic_arr[0][1]); + $display("NTFMB3: ntf_magic_arr[1][0]: ", ntf_magic_arr[1][0]); + $display("NTFMB3: ntf_magic_arr[1][1]: ", ntf_magic_arr[1][1]); + $display("NTFMB3: ntf_magic_arr[0][0][0]: ", ntf_magic_arr[0][0][0]); + $display("NTFMB3: ntf_magic_arr[0][0][1]: ", ntf_magic_arr[0][0][1]); + $display("NTFMB3: ntf_magic_arr[0][1][0]: ", ntf_magic_arr[0][1][0]); + $display("NTFMB3: ntf_magic_arr[0][1][1]: ", ntf_magic_arr[0][1][1]); + $display("NTFMB3: ntf_magic_arr[1][0][1]: ", ntf_magic_arr[1][0][1]); + $display("NTFMB3: ntf_magic_arr[1][0][0]: ", ntf_magic_arr[1][0][0]); + $display("NTFMB3: ntf_magic_arr[1][1][1]: ", ntf_magic_arr[1][1][1]); + $display("NTFMB3: ntf_magic_arr[1][1][0]: ", ntf_magic_arr[1][1][0]); + end + end + endmodule