mirror of https://github.com/zachjs/sv2v.git
several major fixes surrounding packed arrays
- entirely new PackedArray conversion (always flattens) - typedef and struct correctly order packed ranges when combining types - Stmt LHS traversal no longer traverses nested statements to avoid double conversion - Logic conversion applies to `initial` blocks` - new and modified tests to cover these cases
This commit is contained in:
parent
fb3d68e339
commit
9a38225b1d
|
|
@ -57,7 +57,7 @@ convertDescription orig =
|
||||||
|
|
||||||
regIdents :: ModuleItem -> Writer RegIdents ()
|
regIdents :: ModuleItem -> Writer RegIdents ()
|
||||||
regIdents (AlwaysC _ stmt) =
|
regIdents (AlwaysC _ stmt) =
|
||||||
collectStmtLHSsM (collectNestedLHSsM idents) $
|
collectNestedStmtsM (collectStmtLHSsM (collectNestedLHSsM idents)) $
|
||||||
traverseNestedStmts removeTimings stmt
|
traverseNestedStmts removeTimings stmt
|
||||||
where
|
where
|
||||||
idents :: LHS -> Writer RegIdents ()
|
idents :: LHS -> Writer RegIdents ()
|
||||||
|
|
@ -66,4 +66,6 @@ regIdents (AlwaysC _ stmt) =
|
||||||
removeTimings :: Stmt -> Stmt
|
removeTimings :: Stmt -> Stmt
|
||||||
removeTimings (Timing _ s) = s
|
removeTimings (Timing _ s) = s
|
||||||
removeTimings other = other
|
removeTimings other = other
|
||||||
|
regIdents (Initial stmt) =
|
||||||
|
regIdents $ AlwaysC Always stmt
|
||||||
regIdents _ = return ()
|
regIdents _ = return ()
|
||||||
|
|
|
||||||
|
|
@ -6,83 +6,57 @@
|
||||||
- This removes one dimension per identifier at a time. This works fine because
|
- This removes one dimension per identifier at a time. This works fine because
|
||||||
- the conversions are repeatedly applied.
|
- the conversions are repeatedly applied.
|
||||||
-
|
-
|
||||||
- Packed arrays can be used in any of the following ways: A) as a whole,
|
- We previously had a very complex conversion which used `generate` to make
|
||||||
- including as a port; B) with an index (`foo[0]`); or C) with a range
|
- flattened and unflattened versions of the array as necessary. This has now
|
||||||
- (`foo[10:0]`). The rules for this conversion are:
|
- been "simplified" to always flatten the array, and then rewrite all usages of
|
||||||
- 1. If used with an index, then we must have an unflattened/unpacked
|
- the array as appropriate.
|
||||||
- version of that array after the conversion, so that we may get at the
|
|
||||||
- packed sub-arrays.
|
|
||||||
- 2. If used as a whole or with a range, then we must have a flattened
|
|
||||||
- version of that array after the conversion, so that we may get at a
|
|
||||||
- contiguous sequence of elements.
|
|
||||||
- 3. If both 1 and 2 apply, then we will make a fancy generate block to
|
|
||||||
- derive one from the other. The derivation direction is decided based on
|
|
||||||
- which version, if any, is exposed directly as a port.
|
|
||||||
-
|
-
|
||||||
- Note: We don't count usages with an index in expressions as such, as those
|
- Note that the ranges being combined may not be of the form [hi:lo], and need
|
||||||
- usages could be equivalently converted to range accesses with some added in
|
- not even be the same direction! Because of this, we have to flip arround
|
||||||
- multiplication.
|
- the indices of certain accesses.
|
||||||
|
-
|
||||||
|
- TODO: Name conflicts between functions/tasks and the description that
|
||||||
|
- contains them likely breaks this conversion.
|
||||||
-}
|
-}
|
||||||
|
|
||||||
module Convert.PackedArray (convert) where
|
module Convert.PackedArray (convert) where
|
||||||
|
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import Data.List (partition)
|
|
||||||
import Data.Tuple (swap)
|
import Data.Tuple (swap)
|
||||||
import qualified Data.Set as Set
|
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
|
|
||||||
import Convert.Traverse
|
import Convert.Traverse
|
||||||
import Language.SystemVerilog.AST
|
import Language.SystemVerilog.AST
|
||||||
|
|
||||||
type DirMap = Map.Map Identifier Direction
|
|
||||||
type DimMap = Map.Map Identifier (Type, Range)
|
type DimMap = Map.Map Identifier (Type, Range)
|
||||||
type IdentSet = Set.Set Identifier
|
|
||||||
|
|
||||||
data Info = Info
|
data Info = Info
|
||||||
{ sTypeDims :: DimMap
|
{ sTypeDims :: DimMap
|
||||||
, sPortDirs :: DirMap
|
} deriving Show
|
||||||
, sIdxUses :: IdentSet
|
|
||||||
, sSeqUses :: IdentSet }
|
|
||||||
deriving Show
|
|
||||||
|
|
||||||
convert :: AST -> AST
|
convert :: AST -> AST
|
||||||
convert = traverseDescriptions convertDescription
|
convert = traverseDescriptions convertDescription
|
||||||
|
|
||||||
convertDescription :: Description -> Description
|
convertDescription :: Description -> Description
|
||||||
convertDescription (description @ (Part _ _ _ _ _ _)) =
|
convertDescription (description @ (Part _ _ _ _ _ _)) =
|
||||||
hoistPortDecls $
|
|
||||||
traverseModuleItems (flattenModuleItem info . rewriteModuleItem info) description
|
traverseModuleItems (flattenModuleItem info . rewriteModuleItem info) description
|
||||||
where
|
where
|
||||||
-- collect all possible information info our Info structure
|
-- collect all possible information info our Info structure
|
||||||
rawInfo =
|
info =
|
||||||
execState (collectModuleItemsM (collectLHSsM collectLHS) description) $
|
|
||||||
execState (collectModuleItemsM (collectExprsM collectExpr) description) $
|
|
||||||
execState (collectModuleItemsM collectDecl description) $
|
execState (collectModuleItemsM collectDecl description) $
|
||||||
execState (collectModuleItemsM collectTF description) $
|
execState (collectModuleItemsM collectTF description) $
|
||||||
(Info Map.empty Map.empty Set.empty Set.empty)
|
(Info Map.empty)
|
||||||
relevantIdents = Map.keysSet $ sTypeDims rawInfo
|
|
||||||
-- restrict the sets/maps to only contain keys which need transformation
|
|
||||||
info = rawInfo
|
|
||||||
{ sPortDirs = Map.restrictKeys (sPortDirs rawInfo) relevantIdents
|
|
||||||
, sIdxUses = Set.intersection (sIdxUses rawInfo) relevantIdents
|
|
||||||
, sSeqUses = Set.intersection (sSeqUses rawInfo) relevantIdents }
|
|
||||||
convertDescription description = description
|
convertDescription description = description
|
||||||
|
|
||||||
-- collects port direction and packed-array dimension info into the state
|
-- collects port direction and packed-array dimension info into the state
|
||||||
collectDecl :: ModuleItem -> State Info ()
|
collectDecl :: ModuleItem -> State Info ()
|
||||||
collectDecl (MIDecl (Variable dir t ident _ _)) = do
|
collectDecl (MIDecl (Variable _ t ident _ _)) = do
|
||||||
let (tf, rs) = typeRanges t
|
let (tf, rs) = typeRanges t
|
||||||
if not (typeIsImplicit t) && length rs > 1
|
if not (typeIsImplicit t) && length rs > 1
|
||||||
then
|
then
|
||||||
let dets = (tf $ tail rs, head rs) in
|
let dets = (tf $ tail rs, head rs) in
|
||||||
modify $ \s -> s { sTypeDims = Map.insert ident dets (sTypeDims s) }
|
modify $ \s -> s { sTypeDims = Map.insert ident dets (sTypeDims s) }
|
||||||
else return ()
|
else return ()
|
||||||
if dir /= Local
|
|
||||||
then do
|
|
||||||
() <- recordSeqUsage ident
|
|
||||||
modify $ \s -> s { sPortDirs = Map.insert ident dir (sPortDirs s) }
|
|
||||||
else return ()
|
|
||||||
collectDecl _ = return ()
|
collectDecl _ = return ()
|
||||||
|
|
||||||
-- collects task and function info into the state
|
-- collects task and function info into the state
|
||||||
|
|
@ -96,47 +70,6 @@ collectTF (MIPackageItem (Task _ _ decls _)) = do
|
||||||
return ()
|
return ()
|
||||||
collectTF _ = return ()
|
collectTF _ = return ()
|
||||||
|
|
||||||
-- collectors for identifier usage information
|
|
||||||
recordSeqUsage :: Identifier -> State Info ()
|
|
||||||
recordSeqUsage i = modify $ \s -> s { sSeqUses = Set.insert i $ sSeqUses s }
|
|
||||||
recordIdxUsage :: Identifier -> State Info ()
|
|
||||||
recordIdxUsage i = modify $ \s -> s { sIdxUses = Set.insert i $ sIdxUses s }
|
|
||||||
collectExpr :: Expr -> State Info ()
|
|
||||||
collectExpr (Ident i) = recordSeqUsage i
|
|
||||||
collectExpr other = collectNestedExprsM collectNestedExpr other
|
|
||||||
collectNestedExpr :: Expr -> State Info ()
|
|
||||||
collectNestedExpr (Range (Ident i) _ _) = recordSeqUsage i
|
|
||||||
collectNestedExpr _ = return ()
|
|
||||||
collectLHS :: LHS -> State Info ()
|
|
||||||
collectLHS (LHSIdent i) = recordSeqUsage i
|
|
||||||
collectLHS other = collectNestedLHSsM collectNestedLHS other
|
|
||||||
collectNestedLHS :: LHS -> State Info ()
|
|
||||||
collectNestedLHS (LHSRange (LHSIdent i) _ _) = recordSeqUsage i
|
|
||||||
collectNestedLHS (LHSBit (LHSIdent i) _) = recordIdxUsage i
|
|
||||||
collectNestedLHS _ = return ()
|
|
||||||
|
|
||||||
-- VCS doesn't like port declarations inside of `generate` blocks, so we hoist
|
|
||||||
-- them out with this function. This obviously isn't ideal, but it's a
|
|
||||||
-- relatively straightforward transformation, and testing in VCS is important.
|
|
||||||
hoistPortDecls :: Description -> Description
|
|
||||||
hoistPortDecls (Part extern kw lifetime name ports items) =
|
|
||||||
Part extern kw lifetime name ports (concat $ map explode items)
|
|
||||||
where
|
|
||||||
explode :: ModuleItem -> [ModuleItem]
|
|
||||||
explode (Generate genItems) =
|
|
||||||
if null rest
|
|
||||||
then portDecls
|
|
||||||
else portDecls ++ [Generate rest]
|
|
||||||
where
|
|
||||||
(wrappedPortDecls, rest) = partition isPortDecl genItems
|
|
||||||
portDecls = map (\(GenModuleItem item) -> item) wrappedPortDecls
|
|
||||||
isPortDecl :: GenItem -> Bool
|
|
||||||
isPortDecl (GenModuleItem (MIDecl (Variable dir _ _ _ _))) =
|
|
||||||
dir /= Local
|
|
||||||
isPortDecl _ = False
|
|
||||||
explode other = [other]
|
|
||||||
hoistPortDecls other = other
|
|
||||||
|
|
||||||
-- rewrite a module item if it contains a declaration to flatten
|
-- rewrite a module item if it contains a declaration to flatten
|
||||||
flattenModuleItem :: Info -> ModuleItem -> ModuleItem
|
flattenModuleItem :: Info -> ModuleItem -> ModuleItem
|
||||||
flattenModuleItem info (MIPackageItem (Function ml t x decls stmts)) =
|
flattenModuleItem info (MIPackageItem (Function ml t x decls stmts)) =
|
||||||
|
|
@ -154,77 +87,19 @@ flattenModuleItem info (MIPackageItem (Task ml x decls stmts)) =
|
||||||
mapDecl decl = decl'
|
mapDecl decl = decl'
|
||||||
where MIDecl decl' = flattenModuleItem info $ MIDecl decl
|
where MIDecl decl' = flattenModuleItem info $ MIDecl decl
|
||||||
flattenModuleItem info (origDecl @ (MIDecl (Variable dir t ident a me))) =
|
flattenModuleItem info (origDecl @ (MIDecl (Variable dir t ident a me))) =
|
||||||
-- if it doesn't need any mapping, then skip it
|
if Map.notMember ident typeDims
|
||||||
if Map.notMember ident typeDims then origDecl
|
then origDecl
|
||||||
-- if it is never used as a sequence (whole or range), then move the packed
|
else flatDecl
|
||||||
-- dimension to the unpacked side
|
|
||||||
else if Set.notMember ident seqUses then flipDecl
|
|
||||||
-- if it is used as a sequence, but never indexed-into (sub-array), then
|
|
||||||
-- flatten (combine) the ranges, leaving them packed
|
|
||||||
else if Set.notMember ident duoUses then flatDecl
|
|
||||||
-- if it is both used as a sequence and is indexed-into
|
|
||||||
else
|
|
||||||
-- if this is not the fully-typed declaration of this item, then flatten
|
|
||||||
-- it, but don't make the `generate` block this time to avoid duplicates
|
|
||||||
if typeIsImplicit t then flatDecl
|
|
||||||
-- otherwise, flatten it, and also create an unflattened copy
|
|
||||||
else Generate $ (GenModuleItem flatDecl) : genItems
|
|
||||||
where
|
where
|
||||||
Info typeDims portDirs idxUses seqUses = info
|
Info typeDims = info
|
||||||
duoUses = Set.intersection idxUses seqUses
|
|
||||||
portDir = Map.lookup ident portDirs
|
|
||||||
writeToFlatVariant = portDir == Just Output || portDir == Nothing
|
|
||||||
genItems = unflattener writeToFlatVariant ident (typeDims Map.! ident)
|
|
||||||
(tf, rs) = typeRanges t
|
(tf, rs) = typeRanges t
|
||||||
flipDecl = MIDecl $ Variable dir (tf $ tail rs) ident (a ++ [head rs]) me
|
flatDecl = MIDecl $ Variable dir (tf $ flattenRanges rs) ident a me
|
||||||
flatDecl = MIDecl $ Variable dir (tf $ flattenRanges rs) ident a me
|
|
||||||
flattenModuleItem _ other = other
|
flattenModuleItem _ other = other
|
||||||
|
|
||||||
-- produces `generate` items for creating an unflattened copy of the given
|
|
||||||
-- flattened, packed array
|
|
||||||
unflattener :: Bool -> Identifier -> (Type, Range) -> [GenItem]
|
|
||||||
unflattener writeToFlatVariant arr (t, major @ (majorHi, majorLo)) =
|
|
||||||
[ GenModuleItem $ MIPackageItem $ Comment $ "sv2v packed-array-flatten unflattener for " ++ arr
|
|
||||||
, GenModuleItem $ MIDecl $ Variable Local t arrUnflat [(majorHi, majorLo)] Nothing
|
|
||||||
, GenModuleItem $ Genvar index
|
|
||||||
, GenModuleItem $ MIDecl $ Variable Local (IntegerAtom TInteger Unspecified) (arrUnflat ++ "_repeater_index") [] Nothing
|
|
||||||
, GenFor
|
|
||||||
(index, majorLo)
|
|
||||||
(endianCondExpr major
|
|
||||||
(BinOp Le (Ident index) majorHi)
|
|
||||||
(BinOp Ge (Ident index) majorHi))
|
|
||||||
(index, AsgnOp Add, endianCondExpr major (Number "1") (Number "-1"))
|
|
||||||
(Just $ prefix "unflatten_" ++ arr)
|
|
||||||
[ localparam startBit
|
|
||||||
(simplify $ BinOp Add (endianCondExpr major majorLo majorHi)
|
|
||||||
(BinOp Mul (Ident index) size))
|
|
||||||
, GenModuleItem $ (uncurry $ Assign Nothing) $
|
|
||||||
if not writeToFlatVariant
|
|
||||||
then (LHSBit (LHSIdent arrUnflat) $ Ident index, Range (Ident arr) NonIndexed origRange)
|
|
||||||
else (LHSRange (LHSIdent arr) NonIndexed origRange, Bit (Ident arrUnflat) (Ident index))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
where
|
|
||||||
startBit = prefix "_tmp_start_" ++ arr
|
|
||||||
arrUnflat = prefix arr
|
|
||||||
index = prefix "_tmp_index_" ++ arr
|
|
||||||
minor = head $ snd $ typeRanges t
|
|
||||||
size = rangeSize $ endianCondRange minor minor (swap minor)
|
|
||||||
localparam :: Identifier -> Expr -> GenItem
|
|
||||||
localparam x v = GenModuleItem $ MIDecl $ Localparam (Implicit Unspecified []) x v
|
|
||||||
origRangeAg = ( (BinOp Add (Ident startBit)
|
|
||||||
(BinOp Sub size (Number "1")))
|
|
||||||
, Ident startBit )
|
|
||||||
origRange = endianCondRange major origRangeAg (swap origRangeAg)
|
|
||||||
|
|
||||||
typeIsImplicit :: Type -> Bool
|
typeIsImplicit :: Type -> Bool
|
||||||
typeIsImplicit (Implicit _ _) = True
|
typeIsImplicit (Implicit _ _) = True
|
||||||
typeIsImplicit _ = False
|
typeIsImplicit _ = False
|
||||||
|
|
||||||
-- prefix a string with a namespace of sorts
|
|
||||||
prefix :: Identifier -> Identifier
|
|
||||||
prefix ident = "_sv2v_" ++ ident
|
|
||||||
|
|
||||||
-- combines (flattens) the bottom two ranges in the given list of ranges
|
-- combines (flattens) the bottom two ranges in the given list of ranges
|
||||||
flattenRanges :: [Range] -> [Range]
|
flattenRanges :: [Range] -> [Range]
|
||||||
flattenRanges rs =
|
flattenRanges rs =
|
||||||
|
|
@ -240,8 +115,7 @@ flattenRanges rs =
|
||||||
rNN = flattenRangesHelp (swap r1) (swap r2)
|
rNN = flattenRangesHelp (swap r1) (swap r2)
|
||||||
rY = endianCondRange r2 rYY rYN
|
rY = endianCondRange r2 rYY rYN
|
||||||
rN = endianCondRange r2 rNY rNN
|
rN = endianCondRange r2 rNY rNN
|
||||||
rAg = endianCondRange r1 rY rN
|
r = endianCondRange r1 rY rN
|
||||||
r = endianCondRange r1 rAg (swap rAg)
|
|
||||||
rs' = (tail $ tail rs) ++ [r]
|
rs' = (tail $ tail rs) ++ [r]
|
||||||
|
|
||||||
flattenRangesHelp :: Range -> Range -> Range
|
flattenRangesHelp :: Range -> Range -> Range
|
||||||
|
|
@ -250,79 +124,119 @@ flattenRangesHelp (s1, e1) (s2, e2) =
|
||||||
where
|
where
|
||||||
size1 = rangeSize (s1, e1)
|
size1 = rangeSize (s1, e1)
|
||||||
size2 = rangeSize (s2, e2)
|
size2 = rangeSize (s2, e2)
|
||||||
lower = BinOp Add e1 (BinOp Mul e2 size2)
|
lower = BinOp Add e2 (BinOp Mul e1 size2)
|
||||||
upper = BinOp Add (BinOp Mul size1 size2) (BinOp Sub lower (Number "1"))
|
upper = BinOp Add (BinOp Mul size1 size2) (BinOp Sub lower (Number "1"))
|
||||||
|
|
||||||
rewriteModuleItem :: Info -> ModuleItem -> ModuleItem
|
rewriteModuleItem :: Info -> ModuleItem -> ModuleItem
|
||||||
rewriteModuleItem info =
|
rewriteModuleItem info =
|
||||||
traverseStmts rewriteStmt .
|
traverseLHSs (traverseNestedLHSs rewriteLHS ) .
|
||||||
traverseExprs (traverseNestedExprs rewriteExpr)
|
traverseExprs (traverseNestedExprs rewriteExpr)
|
||||||
where
|
where
|
||||||
Info typeDims _ idxUses seqUses = info
|
Info typeDims = info
|
||||||
duoUses = Set.intersection idxUses seqUses
|
|
||||||
|
|
||||||
rewriteIdent :: Bool -> Identifier -> Identifier
|
dims :: Identifier -> (Range, Range)
|
||||||
rewriteIdent isSeqUsage x =
|
dims x =
|
||||||
if Set.member x duoUses
|
(dimInner, dimOuter)
|
||||||
then
|
where
|
||||||
-- if an array is used both ways, then the original name is
|
(t, r) = typeDims Map.! x
|
||||||
-- the flattened version
|
dimInner = r
|
||||||
if isSeqUsage
|
dimOuter = head $ snd $ typeRanges t
|
||||||
then x
|
|
||||||
else prefix x
|
orientIdx :: Range -> Expr -> Expr
|
||||||
else x
|
orientIdx r e =
|
||||||
rewriteSeqIdent = rewriteIdent True
|
endianCondExpr r e eSwapped
|
||||||
rewriteIdxIdent = rewriteIdent False
|
where
|
||||||
|
eSwapped = BinOp Sub (snd r) (BinOp Sub e (fst r))
|
||||||
|
|
||||||
rewriteExpr :: Expr -> Expr
|
rewriteExpr :: Expr -> Expr
|
||||||
rewriteExpr (Ident i) = Ident $ rewriteSeqIdent i
|
rewriteExpr (Ident x) =
|
||||||
rewriteExpr (Bit (Ident i) e) =
|
if head x == ':'
|
||||||
if Map.member i typeDims && Set.member i seqUses && Set.notMember i idxUses
|
then Ident $ tail x
|
||||||
then Range (Ident $ rewriteSeqIdent i) NonIndexed (hi, lo)
|
else Ident x
|
||||||
else Bit (Ident $ rewriteIdxIdent i) e
|
rewriteExpr (orig @ (Bit (Bit (Ident x) idxInner) idxOuter)) =
|
||||||
|
if Map.member x typeDims
|
||||||
|
then Bit (Ident x') idx'
|
||||||
|
else orig
|
||||||
where
|
where
|
||||||
r = head $ snd $ typeRanges $ fst $ typeDims Map.! i
|
(dimInner, dimOuter) = dims x
|
||||||
size = rangeSize r
|
x' = ':' : x
|
||||||
lo = simplify $ BinOp Mul e size
|
idxInner' = orientIdx dimInner idxInner
|
||||||
hi = simplify $ BinOp Add lo (BinOp Sub size (Number "1"))
|
idxOuter' = orientIdx dimOuter idxOuter
|
||||||
rewriteExpr (Range (Ident i) m (r @ (s, e))) =
|
base = BinOp Mul idxInner' (rangeSize dimOuter)
|
||||||
if Map.member i typeDims
|
idx' = simplify $ BinOp Add base idxOuter'
|
||||||
then Range (Ident i) m r'
|
rewriteExpr (orig @ (Bit (Ident x) idx)) =
|
||||||
else Range (Ident i) m r
|
if Map.member x typeDims
|
||||||
|
then Range (Ident x') mode' range'
|
||||||
|
else orig
|
||||||
where
|
where
|
||||||
(a, b) = head $ snd $ typeRanges $ fst $ typeDims Map.! i
|
(dimInner, dimOuter) = dims x
|
||||||
size = rangeSize (a, b)
|
x' = ':' : x
|
||||||
s' = BinOp Sub (BinOp Mul size (BinOp Add s (Number "1"))) (Number "1")
|
mode' = IndexedPlus
|
||||||
e' = BinOp Mul size e
|
idx' = orientIdx dimInner idx
|
||||||
r' = (simplify s', simplify e')
|
len = rangeSize dimOuter
|
||||||
|
base = BinOp Add (endianCondExpr dimOuter (snd dimOuter) (fst dimOuter)) (BinOp Mul idx' len)
|
||||||
|
range' = (simplify base, simplify len)
|
||||||
|
rewriteExpr (orig @ (Range (Ident x) mode range)) =
|
||||||
|
if Map.member x typeDims
|
||||||
|
then Range (Ident x') mode' range'
|
||||||
|
else orig
|
||||||
|
where
|
||||||
|
(_, dimOuter) = dims x
|
||||||
|
x' = ':' : x
|
||||||
|
mode' = mode
|
||||||
|
size = rangeSize dimOuter
|
||||||
|
range' =
|
||||||
|
case mode of
|
||||||
|
NonIndexed ->
|
||||||
|
(simplify hi, simplify lo)
|
||||||
|
where
|
||||||
|
lo = BinOp Mul size (snd range)
|
||||||
|
hi = BinOp Sub (BinOp Add lo (BinOp Mul (rangeSize range) size)) (Number "1")
|
||||||
|
IndexedPlus -> (BinOp Mul size (fst range), BinOp Mul size (snd range))
|
||||||
|
IndexedMinus -> (BinOp Mul size (fst range), BinOp Mul size (snd range))
|
||||||
|
---- TODO: I'm not sure how these should be handled yet.
|
||||||
|
----rewriteExpr (orig @ (Range (Bit (Ident x) idxInner) modeOuter rangeOuter)) =
|
||||||
|
---- if Map.member x typeDims
|
||||||
|
---- then Range (Ident x') mode' range'
|
||||||
|
---- else orig
|
||||||
|
---- where
|
||||||
|
---- (dimInner, dimOuter) = dims x
|
||||||
|
---- x' = ':' : x
|
||||||
|
---- mode' =
|
||||||
|
---- range' =
|
||||||
rewriteExpr other = other
|
rewriteExpr other = other
|
||||||
|
|
||||||
rewriteLHS :: LHS -> LHS
|
rewriteLHS :: LHS -> LHS
|
||||||
rewriteLHS (LHSIdent x ) = LHSIdent (rewriteSeqIdent x)
|
rewriteLHS (LHSIdent x) =
|
||||||
rewriteLHS (LHSBit (LHSIdent x) e) =
|
LHSIdent x'
|
||||||
LHSBit (LHSIdent $ rewriteIdxIdent x) e
|
where Ident x' = rewriteExpr (Ident x)
|
||||||
rewriteLHS (LHSBit l e ) = LHSBit (rewriteLHS l) e
|
rewriteLHS (orig @ (LHSBit (LHSBit (LHSIdent x) idxInner) idxOuter)) =
|
||||||
rewriteLHS (LHSRange l m r) = LHSRange (rewriteLHS l) m r
|
if Map.member x typeDims
|
||||||
rewriteLHS (LHSDot l x ) = LHSDot (rewriteLHS l) x
|
then LHSBit (LHSIdent x') idx'
|
||||||
rewriteLHS (LHSConcat ls ) = LHSConcat $ map rewriteLHS ls
|
else orig
|
||||||
|
where Bit (Ident x') idx' =
|
||||||
rewriteStmt :: Stmt -> Stmt
|
rewriteExpr (Bit (Bit (Ident x) idxInner) idxOuter)
|
||||||
rewriteStmt (AsgnBlk op lhs expr) = convertAssignment (AsgnBlk op) lhs expr
|
rewriteLHS (orig @ (LHSBit (LHSRange (LHSIdent x) modeInner rangeInner) idxOuter)) =
|
||||||
rewriteStmt (Asgn mt lhs expr) = convertAssignment (Asgn mt) lhs expr
|
if Map.member x typeDims
|
||||||
rewriteStmt other = other
|
then LHSRange (LHSIdent x') mode' range'
|
||||||
convertAssignment :: (LHS -> Expr -> Stmt) -> LHS -> Expr -> Stmt
|
else orig
|
||||||
convertAssignment constructor (lhs @ (LHSIdent ident)) (expr @ (Repeat _ exprs)) =
|
where Range (Ident x') mode' range' =
|
||||||
if Map.member ident typeDims
|
rewriteExpr (Bit (Range (Ident x) modeInner rangeInner) idxOuter)
|
||||||
then For inir chkr incr assign
|
rewriteLHS (orig @ (LHSBit (LHSIdent x) idx)) =
|
||||||
else constructor (rewriteLHS lhs) expr
|
if Map.member x typeDims
|
||||||
where
|
then LHSRange (LHSIdent x') mode' range'
|
||||||
(_, (a, b)) = typeDims Map.! ident
|
else orig
|
||||||
index = prefix $ ident ++ "_repeater_index"
|
where Range (Ident x') mode' range' = rewriteExpr (Bit (Ident x) idx)
|
||||||
assign = constructor
|
rewriteLHS (orig @ (LHSRange (LHSIdent x) mode range)) =
|
||||||
(LHSBit (LHSIdent $ prefix ident) (Ident index))
|
if Map.member x typeDims
|
||||||
(Concat exprs)
|
then LHSRange (LHSIdent x') mode' range'
|
||||||
inir = [Right (LHSIdent index, b)]
|
else orig
|
||||||
chkr = Just $ BinOp Le (Ident index) a
|
where Range (Ident x') mode' range' =
|
||||||
incr = [(LHSIdent index, AsgnOp Add, Number "1")]
|
rewriteExpr (Range (Ident x) mode range)
|
||||||
convertAssignment constructor lhs expr =
|
rewriteLHS (orig @ (LHSRange (LHSBit (LHSIdent x) idxInner) modeOuter rangeOuter)) =
|
||||||
constructor (rewriteLHS lhs) expr
|
if Map.member x typeDims
|
||||||
|
then LHSRange (LHSIdent x') mode' range'
|
||||||
|
else orig
|
||||||
|
where Range (Ident x') mode' range' =
|
||||||
|
rewriteExpr (Range (Bit (Ident x) idxInner) modeOuter rangeOuter)
|
||||||
|
rewriteLHS other = other
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ convertType :: Structs -> Type -> Type
|
||||||
convertType structs t1 =
|
convertType structs t1 =
|
||||||
case Map.lookup tf1 structs of
|
case Map.lookup tf1 structs of
|
||||||
Nothing -> t1
|
Nothing -> t1
|
||||||
Just (t2, _) -> tf2 (rs2 ++ rs1)
|
Just (t2, _) -> tf2 (rs1 ++ rs2)
|
||||||
where (tf2, rs2) = typeRanges t2
|
where (tf2, rs2) = typeRanges t2
|
||||||
where (tf1, rs1) = typeRanges t1
|
where (tf1, rs1) = typeRanges t1
|
||||||
|
|
||||||
|
|
@ -141,30 +141,46 @@ convertAsgn structs types (lhs, expr) =
|
||||||
Nothing -> (Implicit Unspecified [], LHSIdent x)
|
Nothing -> (Implicit Unspecified [], LHSIdent x)
|
||||||
Just t -> (t, LHSIdent x)
|
Just t -> (t, LHSIdent x)
|
||||||
convertLHS (LHSBit l e) =
|
convertLHS (LHSBit l e) =
|
||||||
if null rs
|
|
||||||
then (Implicit Unspecified [], LHSBit l' e')
|
|
||||||
else (tf $ tail rs, LHSBit l' e')
|
|
||||||
where
|
|
||||||
(t, l') = convertLHS l
|
|
||||||
(tf, rs) = typeRanges t
|
|
||||||
e' = snd $ convertSubExpr e
|
|
||||||
convertLHS (LHSRange l m rOuterOrig) =
|
|
||||||
case l' of
|
case l' of
|
||||||
LHSRange lInner NonIndexed (_, loI) ->
|
LHSRange lInner NonIndexed (_, loI) ->
|
||||||
(t, LHSRange lInner m (simplify hi, simplify lo))
|
(t', LHSBit lInner (simplify $ BinOp Add loI e'))
|
||||||
|
LHSRange lInner IndexedPlus (baseI, _) ->
|
||||||
|
(t', LHSBit lInner (simplify $ BinOp Add baseI e'))
|
||||||
|
_ -> (t', LHSBit l' e')
|
||||||
|
where
|
||||||
|
(t, l') = convertLHS l
|
||||||
|
t' = case typeRanges t of
|
||||||
|
(_, []) -> Implicit Unspecified []
|
||||||
|
(tf, rs) -> tf $ tail rs
|
||||||
|
e' = snd $ convertSubExpr e
|
||||||
|
convertLHS (LHSRange lOuter NonIndexed rOuterOrig) =
|
||||||
|
case lOuter' of
|
||||||
|
LHSRange lInner NonIndexed (_, loI) ->
|
||||||
|
(t, LHSRange lInner NonIndexed (simplify hi, simplify lo))
|
||||||
where
|
where
|
||||||
lo = BinOp Add loI loO
|
lo = BinOp Add loI loO
|
||||||
hi = BinOp Add loI hiO
|
hi = BinOp Add loI hiO
|
||||||
_ -> if null rs
|
LHSRange lInner IndexedPlus (baseI, _) ->
|
||||||
then (Implicit Unspecified [], LHSRange l' m rOuter)
|
(t, LHSRange lInner IndexedPlus (simplify base, simplify len))
|
||||||
else (tf rs', LHSRange l' m rOuter)
|
where
|
||||||
|
base = BinOp Add baseI loO
|
||||||
|
len = rangeSize rOuter
|
||||||
|
_ -> (t, LHSRange lOuter' NonIndexed rOuter)
|
||||||
where
|
where
|
||||||
(t, l') = convertLHS l
|
|
||||||
(tf, rs) = typeRanges t
|
|
||||||
hiO = snd $ convertSubExpr $ fst rOuterOrig
|
hiO = snd $ convertSubExpr $ fst rOuterOrig
|
||||||
loO = snd $ convertSubExpr $ snd rOuterOrig
|
loO = snd $ convertSubExpr $ snd rOuterOrig
|
||||||
rOuter = (hiO, loO)
|
rOuter = (hiO, loO)
|
||||||
rs' = rOuter : tail rs
|
(t, lOuter') = convertLHS lOuter
|
||||||
|
convertLHS (LHSRange l m r) =
|
||||||
|
(t', LHSRange l' m r')
|
||||||
|
where
|
||||||
|
hi = snd $ convertSubExpr $ fst r
|
||||||
|
lo = snd $ convertSubExpr $ snd r
|
||||||
|
r' = (hi, lo)
|
||||||
|
(t, l') = convertLHS l
|
||||||
|
t' = case typeRanges t of
|
||||||
|
(_, []) -> Implicit Unspecified []
|
||||||
|
(tf, rs) -> tf $ tail rs
|
||||||
convertLHS (LHSDot l x ) =
|
convertLHS (LHSDot l x ) =
|
||||||
case t of
|
case t of
|
||||||
InterfaceT _ _ _ -> (Implicit Unspecified [], LHSDot l' x)
|
InterfaceT _ _ _ -> (Implicit Unspecified [], LHSDot l' x)
|
||||||
|
|
@ -236,18 +252,30 @@ convertAsgn structs types (lhs, expr) =
|
||||||
structTf = Struct p fields
|
structTf = Struct p fields
|
||||||
fieldType = lookupFieldType fields x
|
fieldType = lookupFieldType fields x
|
||||||
r = lookupUnstructRange structTf x
|
r = lookupUnstructRange structTf x
|
||||||
convertSubExpr (Range eOuter m (rOuter @ (hiO, loO))) =
|
convertSubExpr (Range eOuter NonIndexed (rOuter @ (hiO, loO))) =
|
||||||
-- VCS doesn't allow ranges to be cascaded, so we need to combine
|
-- VCS doesn't allow ranges to be cascaded, so we need to combine
|
||||||
-- nested Ranges into a single range. My understanding of the
|
-- nested Ranges into a single range. My understanding of the
|
||||||
-- semantics are that a range returns a new, zero-indexed sub-range.
|
-- semantics are that a range returns a new, zero-indexed sub-range.
|
||||||
case eOuter' of
|
case eOuter' of
|
||||||
Range eInner NonIndexed (_, loI) ->
|
Range eInner NonIndexed (_, loI) ->
|
||||||
(t, Range eInner m (simplify hi, simplify lo))
|
(t, Range eInner NonIndexed (simplify hi, simplify lo))
|
||||||
where
|
where
|
||||||
lo = BinOp Add loI loO
|
lo = BinOp Add loI loO
|
||||||
hi = BinOp Add loI hiO
|
hi = BinOp Add loI hiO
|
||||||
_ -> (t, Range eOuter' m rOuter)
|
Range eInner IndexedPlus (baseI, _) ->
|
||||||
|
(t, Range eInner IndexedPlus (simplify base, simplify len))
|
||||||
|
where
|
||||||
|
base = BinOp Add baseI loO
|
||||||
|
len = rangeSize rOuter
|
||||||
|
_ -> (t, Range eOuter' NonIndexed rOuter)
|
||||||
where (t, eOuter') = convertSubExpr eOuter
|
where (t, eOuter') = convertSubExpr eOuter
|
||||||
|
convertSubExpr (Range e m r) =
|
||||||
|
(t', Range e' m r)
|
||||||
|
where
|
||||||
|
(t, e') = convertSubExpr e
|
||||||
|
t' = case typeRanges t of
|
||||||
|
(_, []) -> Implicit Unspecified []
|
||||||
|
(tf, rs) -> tf $ tail rs
|
||||||
convertSubExpr (Concat exprs) =
|
convertSubExpr (Concat exprs) =
|
||||||
(Implicit Unspecified [], Concat $ map (snd . convertSubExpr) exprs)
|
(Implicit Unspecified [], Concat $ map (snd . convertSubExpr) exprs)
|
||||||
convertSubExpr (BinOp op e1 e2) =
|
convertSubExpr (BinOp op e1 e2) =
|
||||||
|
|
@ -259,6 +287,8 @@ convertAsgn structs types (lhs, expr) =
|
||||||
case e' of
|
case e' of
|
||||||
Range eInner NonIndexed (_, loI) ->
|
Range eInner NonIndexed (_, loI) ->
|
||||||
(t', Bit eInner (simplify $ BinOp Add loI i'))
|
(t', Bit eInner (simplify $ BinOp Add loI i'))
|
||||||
|
Range eInner IndexedPlus (baseI, _) ->
|
||||||
|
(t', Bit eInner (simplify $ BinOp Add baseI i'))
|
||||||
_ -> (t', Bit e' i')
|
_ -> (t', Bit e' i')
|
||||||
where
|
where
|
||||||
(t, e') = convertSubExpr e
|
(t, e') = convertSubExpr e
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ module Convert.Traverse
|
||||||
, traverseNestedModuleItems
|
, traverseNestedModuleItems
|
||||||
, collectNestedModuleItemsM
|
, collectNestedModuleItemsM
|
||||||
, traverseNestedStmts
|
, traverseNestedStmts
|
||||||
|
, collectNestedStmtsM
|
||||||
, traverseNestedExprs
|
, traverseNestedExprs
|
||||||
, collectNestedExprsM
|
, collectNestedExprsM
|
||||||
, traverseNestedLHSsM
|
, traverseNestedLHSsM
|
||||||
|
|
@ -303,7 +304,7 @@ traverseAssertionExprsM mapper = assertionMapper
|
||||||
return $ Cover e' stmt
|
return $ Cover e' stmt
|
||||||
|
|
||||||
traverseStmtLHSsM :: Monad m => MapperM m LHS -> MapperM m Stmt
|
traverseStmtLHSsM :: Monad m => MapperM m LHS -> MapperM m Stmt
|
||||||
traverseStmtLHSsM mapper = traverseNestedStmtsM stmtMapper
|
traverseStmtLHSsM mapper = stmtMapper
|
||||||
where
|
where
|
||||||
fullMapper = mapper
|
fullMapper = mapper
|
||||||
stmtMapper (Timing (Event sense) stmt) = do
|
stmtMapper (Timing (Event sense) stmt) = do
|
||||||
|
|
@ -591,7 +592,7 @@ traverseLHSsM' strat mapper item =
|
||||||
lhs' <- mapper lhs
|
lhs' <- mapper lhs
|
||||||
return $ NInputGate kw x lhs' exprs
|
return $ NInputGate kw x lhs' exprs
|
||||||
traverseModuleItemLHSsM (AssertionItem (mx, a)) = do
|
traverseModuleItemLHSsM (AssertionItem (mx, a)) = do
|
||||||
Assertion a' <- traverseStmtLHSsM mapper (Assertion a)
|
Assertion a' <- traverseNestedStmtsM (traverseStmtLHSsM mapper) (Assertion a)
|
||||||
return $ AssertionItem (mx, a')
|
return $ AssertionItem (mx, a')
|
||||||
traverseModuleItemLHSsM other = return other
|
traverseModuleItemLHSsM other = return other
|
||||||
|
|
||||||
|
|
@ -610,7 +611,7 @@ collectLHSsM = collectLHSsM' IncludeTFs
|
||||||
traverseNestedLHSsM :: Monad m => MapperM m LHS -> MapperM m LHS
|
traverseNestedLHSsM :: Monad m => MapperM m LHS -> MapperM m LHS
|
||||||
traverseNestedLHSsM mapper = fullMapper
|
traverseNestedLHSsM mapper = fullMapper
|
||||||
where
|
where
|
||||||
fullMapper lhs = tl lhs >>= mapper
|
fullMapper lhs = mapper lhs >>= tl
|
||||||
tl (LHSIdent x ) = return $ LHSIdent x
|
tl (LHSIdent x ) = return $ LHSIdent x
|
||||||
tl (LHSBit l e ) = fullMapper l >>= \l' -> return $ LHSBit l' e
|
tl (LHSBit l e ) = fullMapper l >>= \l' -> return $ LHSBit l' e
|
||||||
tl (LHSRange l m r) = fullMapper l >>= \l' -> return $ LHSRange l' m r
|
tl (LHSRange l m r) = fullMapper l >>= \l' -> return $ LHSRange l' m r
|
||||||
|
|
@ -792,6 +793,8 @@ collectNestedModuleItemsM = collectify traverseNestedModuleItemsM
|
||||||
|
|
||||||
traverseNestedStmts :: Mapper Stmt -> Mapper Stmt
|
traverseNestedStmts :: Mapper Stmt -> Mapper Stmt
|
||||||
traverseNestedStmts = unmonad traverseNestedStmtsM
|
traverseNestedStmts = unmonad traverseNestedStmtsM
|
||||||
|
collectNestedStmtsM :: Monad m => CollectorM m Stmt -> CollectorM m Stmt
|
||||||
|
collectNestedStmtsM = collectify traverseNestedStmtsM
|
||||||
|
|
||||||
traverseNestedExprs :: Mapper Expr -> Mapper Expr
|
traverseNestedExprs :: Mapper Expr -> Mapper Expr
|
||||||
traverseNestedExprs = unmonad traverseNestedExprsM
|
traverseNestedExprs = unmonad traverseNestedExprsM
|
||||||
|
|
|
||||||
|
|
@ -72,12 +72,12 @@ resolveType types (Alias st rs1) =
|
||||||
if Map.notMember st types
|
if Map.notMember st types
|
||||||
then InterfaceT st Nothing rs1
|
then InterfaceT st Nothing rs1
|
||||||
else case resolveType types $ types Map.! st of
|
else case resolveType types $ types Map.! st of
|
||||||
(Net kw rs2) -> Net kw $ rs2 ++ rs1
|
(Net kw rs2) -> Net kw $ rs1 ++ rs2
|
||||||
(Implicit sg rs2) -> Implicit sg $ rs2 ++ rs1
|
(Implicit sg rs2) -> Implicit sg $ rs1 ++ rs2
|
||||||
(IntegerVector kw sg rs2) -> IntegerVector kw sg $ rs2 ++ rs1
|
(IntegerVector kw sg rs2) -> IntegerVector kw sg $ rs1 ++ rs2
|
||||||
(Enum t v rs2) -> Enum t v $ rs2 ++ rs1
|
(Enum t v rs2) -> Enum t v $ rs1 ++ rs2
|
||||||
(Struct p l rs2) -> Struct p l $ rs2 ++ rs1
|
(Struct p l rs2) -> Struct p l $ rs1 ++ rs2
|
||||||
(InterfaceT x my rs2) -> InterfaceT x my $ rs2 ++ rs1
|
(InterfaceT x my rs2) -> InterfaceT x my $ rs1 ++ rs2
|
||||||
(IntegerAtom kw _ ) -> error $ "resolveType encountered packed `" ++ (show kw) ++ "` on " ++ st
|
(IntegerAtom kw _ ) -> error $ "resolveType encountered packed `" ++ (show kw) ++ "` on " ++ st
|
||||||
(NonInteger kw ) -> error $ "resolveType encountered packed `" ++ (show kw) ++ "` on " ++ st
|
(NonInteger kw ) -> error $ "resolveType encountered packed `" ++ (show kw) ++ "` on " ++ st
|
||||||
(Alias _ _) -> error $ "resolveType invariant failed on " ++ st
|
(Alias _ _) -> error $ "resolveType invariant failed on " ++ st
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,10 @@ simplify other = other
|
||||||
|
|
||||||
rangeSize :: Range -> Expr
|
rangeSize :: Range -> Expr
|
||||||
rangeSize (s, e) =
|
rangeSize (s, e) =
|
||||||
simplify $ BinOp Add (BinOp Sub s e) (Number "1")
|
endianCondExpr (s, e) a b
|
||||||
|
where
|
||||||
|
a = simplify $ BinOp Add (BinOp Sub s e) (Number "1")
|
||||||
|
b = simplify $ BinOp Add (BinOp Sub e s) (Number "1")
|
||||||
|
|
||||||
-- chooses one or the other expression based on the endianness of the given
|
-- chooses one or the other expression based on the endianness of the given
|
||||||
-- range; [hi:lo] chooses the first expression
|
-- range; [hi:lo] chooses the first expression
|
||||||
|
|
|
||||||
|
|
@ -1,104 +1,55 @@
|
||||||
`define CASE_A(name, dims) \
|
`define CASE(name, dims, a, b) \
|
||||||
module name(clock, in, out); \
|
module name(clock, in, out); \
|
||||||
input wire clock, in; \
|
input wire clock, in; \
|
||||||
output logic dims out; \
|
output logic dims out; \
|
||||||
initial out[0] = 0; \
|
initial out[0+a] = 0; \
|
||||||
initial out[1] = 0; \
|
initial out[1+a] = 0; \
|
||||||
initial out[2] = 0; \
|
initial out[2+a] = 0; \
|
||||||
always @(posedge clock) begin \
|
always @(posedge clock) begin \
|
||||||
|
/*$display($time, `" name ", out[0+a][1+b+:1]);*/ \
|
||||||
|
/*$display($time, `" name ", out[0+a][1+b+:1]);*/ \
|
||||||
|
/*$display($time, `" name ", out[1+a][1+b+:1]);*/ \
|
||||||
|
/*$display($time, `" name ", out[1+a][1+b+:1]);*/ \
|
||||||
|
/*$display($time, `" name ", out[2+a][1+b+:1]);*/ \
|
||||||
|
/*$display($time, `" name ", out[2+a][1+b+:1]);*/ \
|
||||||
\
|
\
|
||||||
out[2][4] = out[2][3]; \
|
out[2+a][4+b] = out[2+a][3+b]; \
|
||||||
out[2][3] = out[2][2]; \
|
out[2+a][3+b] = out[2+a][2+b]; \
|
||||||
out[2][2] = out[2][1]; \
|
out[2+a][2+b] = out[2+a][1+b]; \
|
||||||
out[2][1] = out[2][0]; \
|
out[2+a][1+b] = out[2+a][0+b]; \
|
||||||
out[2][0] = out[1][4]; \
|
out[2+a][0+b] = out[1+a][4+b]; \
|
||||||
\
|
\
|
||||||
out[1][4] = out[1][3]; \
|
out[1+a][4+b] = out[1+a][3+b]; \
|
||||||
out[1][3] = out[1][2]; \
|
out[1+a][3+b] = out[1+a][2+b]; \
|
||||||
out[1][2] = out[1][1]; \
|
out[1+a][2+b] = out[1+a][1+b]; \
|
||||||
out[1][1] = out[1][0]; \
|
out[1+a][1+b] = out[1+a][0+b]; \
|
||||||
out[1][0] = out[0][4]; \
|
out[1+a][0+b] = out[0+a][4+b]; \
|
||||||
\
|
\
|
||||||
out[0][4] = out[0][3]; \
|
out[0+a][4+b] = out[0+a][3+b]; \
|
||||||
out[0][3] = out[0][2]; \
|
out[0+a][3+b] = out[0+a][2+b]; \
|
||||||
out[0][2] = out[0][1]; \
|
out[0+a][2+b] = out[0+a][1+b]; \
|
||||||
out[0][1] = out[0][0]; \
|
out[0+a][1+b] = out[0+a][0+b]; \
|
||||||
out[0][0] = in; \
|
out[0+a][0+b] = in; \
|
||||||
\
|
\
|
||||||
end \
|
end \
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
`CASE_A(A1, [2:0][4:0])
|
`CASE(A1, [2:0][4:0], 0, 0)
|
||||||
`CASE_A(A2, [0:2][0:4])
|
`CASE(A2, [0:2][0:4], 0, 0)
|
||||||
`CASE_A(A3, [0:2][4:0])
|
`CASE(A3, [0:2][4:0], 0, 0)
|
||||||
`CASE_A(A4, [2:0][0:4])
|
`CASE(A4, [2:0][0:4], 0, 0)
|
||||||
|
|
||||||
`define CASE_B(name, dims) \
|
`CASE(B1, [3:1][5:1], 1, 1)
|
||||||
module name(clock, in, out); \
|
`CASE(B2, [1:3][1:5], 1, 1)
|
||||||
input wire clock, in; \
|
`CASE(B3, [1:3][5:1], 1, 1)
|
||||||
output logic dims out; \
|
`CASE(B4, [3:1][1:5], 1, 1)
|
||||||
initial out[1] = 0; \
|
|
||||||
initial out[2] = 0; \
|
|
||||||
initial out[3] = 0; \
|
|
||||||
always @(posedge clock) begin \
|
|
||||||
\
|
|
||||||
out[3][5] = out[3][4]; \
|
|
||||||
out[3][4] = out[3][3]; \
|
|
||||||
out[3][3] = out[3][2]; \
|
|
||||||
out[3][2] = out[3][1]; \
|
|
||||||
out[3][1] = out[2][5]; \
|
|
||||||
\
|
|
||||||
out[2][5] = out[2][4]; \
|
|
||||||
out[2][4] = out[2][3]; \
|
|
||||||
out[2][3] = out[2][2]; \
|
|
||||||
out[2][2] = out[2][1]; \
|
|
||||||
out[2][1] = out[1][5]; \
|
|
||||||
\
|
|
||||||
out[1][5] = out[1][4]; \
|
|
||||||
out[1][4] = out[1][3]; \
|
|
||||||
out[1][3] = out[1][2]; \
|
|
||||||
out[1][2] = out[1][1]; \
|
|
||||||
out[1][1] = in; \
|
|
||||||
\
|
|
||||||
end \
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
`CASE_B(B1, [3:1][5:1])
|
`CASE(C1, [4:2][6:2], 2, 2)
|
||||||
`CASE_B(B2, [1:3][1:5])
|
`CASE(C2, [2:4][2:6], 2, 2)
|
||||||
`CASE_B(B3, [1:3][5:1])
|
`CASE(C3, [2:4][6:2], 2, 2)
|
||||||
`CASE_B(B4, [3:1][1:5])
|
`CASE(C4, [4:2][2:6], 2, 2)
|
||||||
|
|
||||||
`define CASE_C(name, dims) \
|
`CASE(D1, [5:3][6:2], 3, 2)
|
||||||
module name(clock, in, out); \
|
`CASE(D2, [3:5][2:6], 3, 2)
|
||||||
input wire clock, in; \
|
`CASE(D3, [3:5][6:2], 3, 2)
|
||||||
output logic dims out; \
|
`CASE(D4, [5:3][2:6], 3, 2)
|
||||||
initial out[2] = 0; \
|
|
||||||
initial out[3] = 0; \
|
|
||||||
initial out[4] = 0; \
|
|
||||||
always @(posedge clock) begin \
|
|
||||||
\
|
|
||||||
out[4][6] = out[4][5]; \
|
|
||||||
out[4][5] = out[4][4]; \
|
|
||||||
out[4][4] = out[4][3]; \
|
|
||||||
out[4][3] = out[4][2]; \
|
|
||||||
out[4][2] = out[3][6]; \
|
|
||||||
\
|
|
||||||
out[3][6] = out[3][5]; \
|
|
||||||
out[3][5] = out[3][4]; \
|
|
||||||
out[3][4] = out[3][3]; \
|
|
||||||
out[3][3] = out[3][2]; \
|
|
||||||
out[3][2] = out[2][6]; \
|
|
||||||
\
|
|
||||||
out[2][6] = out[2][5]; \
|
|
||||||
out[2][5] = out[2][4]; \
|
|
||||||
out[2][4] = out[2][3]; \
|
|
||||||
out[2][3] = out[2][2]; \
|
|
||||||
out[2][2] = in; \
|
|
||||||
\
|
|
||||||
end \
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
`CASE_C(C1, [4:2][6:2])
|
|
||||||
`CASE_C(C2, [2:4][2:6])
|
|
||||||
`CASE_C(C3, [2:4][6:2])
|
|
||||||
`CASE_C(C4, [4:2][2:6])
|
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,13 @@
|
||||||
tag``2 tag``two(.clock(clock), .in(in), .out(tag``two_out)); \
|
tag``2 tag``two(.clock(clock), .in(in), .out(tag``two_out)); \
|
||||||
tag``3 tag``thr(.clock(clock), .in(in), .out(tag``thr_out)); \
|
tag``3 tag``thr(.clock(clock), .in(in), .out(tag``thr_out)); \
|
||||||
tag``4 tag``fou(.clock(clock), .in(in), .out(tag``fou_out)); \
|
tag``4 tag``fou(.clock(clock), .in(in), .out(tag``fou_out)); \
|
||||||
|
integer tag``i; \
|
||||||
initial begin \
|
initial begin \
|
||||||
$monitor(`"tag", $time, ": %h %15b %15b %15b %15b", in, \
|
for (tag``i = 0; tag``i < 20; tag``i++) begin \
|
||||||
tag``one_out, tag``two_out, tag``thr_out, tag``fou_out); \
|
#2; \
|
||||||
|
$display(`"tag", $time, ": %h %15b %15b %15b %15b", in, \
|
||||||
|
tag``one_out, tag``two_out, tag``thr_out, tag``fou_out); \
|
||||||
|
end \
|
||||||
end
|
end
|
||||||
|
|
||||||
module top;
|
module top;
|
||||||
|
|
@ -30,5 +34,6 @@ module top;
|
||||||
`FOO(A)
|
`FOO(A)
|
||||||
`FOO(B)
|
`FOO(B)
|
||||||
`FOO(C)
|
`FOO(C)
|
||||||
|
`FOO(D)
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
`define PRINT(arr, a, b) \
|
||||||
|
$display(arr[0+a][0+b]); \
|
||||||
|
$display(arr[0+a][1+b]); \
|
||||||
|
$display(arr[0+a][2+b]); \
|
||||||
|
$display(arr[1+a][0+b]); \
|
||||||
|
$display(arr[1+a][1+b]); \
|
||||||
|
$display(arr[1+a][2+b]); \
|
||||||
|
$display(arr[2+a][0+b]); \
|
||||||
|
$display(arr[2+a][1+b]); \
|
||||||
|
$display(arr[2+a][2+b]); \
|
||||||
|
$display(arr[3+a][0+b]); \
|
||||||
|
$display(arr[3+a][1+b]); \
|
||||||
|
$display(arr[3+a][2+b]); \
|
||||||
|
$display(arr[4+a][0+b]); \
|
||||||
|
$display(arr[4+a][1+b]); \
|
||||||
|
$display(arr[4+a][2+b]);
|
||||||
|
|
||||||
|
module Example;
|
||||||
|
|
||||||
|
typedef logic [2:0] Pack;
|
||||||
|
Pack [4:0] arr1;
|
||||||
|
Pack [4:0] arr2;
|
||||||
|
Pack [4:0] arr3;
|
||||||
|
initial begin
|
||||||
|
arr1 = 'b100101010100100;
|
||||||
|
arr1[0][1] = ~arr1[0][1];
|
||||||
|
arr1[4][2] = ~arr1[4][2];
|
||||||
|
`PRINT(arr1, 0, 0)
|
||||||
|
arr2 = 'b100101000110101;
|
||||||
|
`PRINT(arr2, 0, 0)
|
||||||
|
arr3 = 'b100100111101010;
|
||||||
|
arr3[1] = arr3[2];
|
||||||
|
`PRINT(arr3, 0, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
Pack [5:1] arr4;
|
||||||
|
Pack [5:1] arr5;
|
||||||
|
Pack [5:1] arr6;
|
||||||
|
initial begin
|
||||||
|
arr4 = 'b100101010100100;
|
||||||
|
arr4[1][1] = ~arr4[1][1];
|
||||||
|
arr4[5][2] = ~arr4[5][2];
|
||||||
|
`PRINT(arr4, 1, 0)
|
||||||
|
arr5 = 'b100101000110101;
|
||||||
|
`PRINT(arr5, 1, 0)
|
||||||
|
arr6 = 'b100100111101010;
|
||||||
|
arr6[2] = arr6[3];
|
||||||
|
`PRINT(arr6, 1, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
Pack [1:5] arr7;
|
||||||
|
Pack [1:5] arr8;
|
||||||
|
Pack [1:5] arr9;
|
||||||
|
initial begin
|
||||||
|
arr7 = 'b100101010100100;
|
||||||
|
arr7[1][1] = ~arr7[1][1];
|
||||||
|
arr7[5][2] = ~arr7[5][2];
|
||||||
|
`PRINT(arr7, 1, 0)
|
||||||
|
arr8 = 'b100101000110101;
|
||||||
|
`PRINT(arr8, 1, 0)
|
||||||
|
arr9 = 'b100100111101010;
|
||||||
|
arr9[2] = arr9[3];
|
||||||
|
`PRINT(arr9, 1, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
`define PRINT(arr, a, b) \
|
||||||
|
$display(arr[0+a][0+b]); \
|
||||||
|
$display(arr[0+a][1+b]); \
|
||||||
|
$display(arr[0+a][2+b]); \
|
||||||
|
$display(arr[1+a][0+b]); \
|
||||||
|
$display(arr[1+a][1+b]); \
|
||||||
|
$display(arr[1+a][2+b]); \
|
||||||
|
$display(arr[2+a][0+b]); \
|
||||||
|
$display(arr[2+a][1+b]); \
|
||||||
|
$display(arr[2+a][2+b]); \
|
||||||
|
$display(arr[3+a][0+b]); \
|
||||||
|
$display(arr[3+a][1+b]); \
|
||||||
|
$display(arr[3+a][2+b]); \
|
||||||
|
$display(arr[4+a][0+b]); \
|
||||||
|
$display(arr[4+a][1+b]); \
|
||||||
|
$display(arr[4+a][2+b]);
|
||||||
|
|
||||||
|
module Example;
|
||||||
|
|
||||||
|
reg [4:0][2:0] arr1;
|
||||||
|
reg [4:0][2:0] arr2;
|
||||||
|
reg [4:0][2:0] arr3;
|
||||||
|
initial begin
|
||||||
|
arr1 = 'b100101010100100;
|
||||||
|
arr1[0][1] = ~arr1[0][1];
|
||||||
|
arr1[4][2] = ~arr1[4][2];
|
||||||
|
`PRINT(arr1, 0, 0)
|
||||||
|
arr2 = 'b100101000110101;
|
||||||
|
`PRINT(arr2, 0, 0)
|
||||||
|
arr3 = 'b100100111101010;
|
||||||
|
arr3[1] = arr3[2];
|
||||||
|
`PRINT(arr3, 0, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
reg [5:1][2:0] arr4;
|
||||||
|
reg [5:1][2:0] arr5;
|
||||||
|
reg [5:1][2:0] arr6;
|
||||||
|
initial begin
|
||||||
|
arr4 = 'b100101010100100;
|
||||||
|
arr4[1][1] = ~arr4[1][1];
|
||||||
|
arr4[5][2] = ~arr4[5][2];
|
||||||
|
`PRINT(arr4, 1, 0)
|
||||||
|
arr5 = 'b100101000110101;
|
||||||
|
`PRINT(arr5, 1, 0)
|
||||||
|
arr6 = 'b100100111101010;
|
||||||
|
arr6[2] = arr6[3];
|
||||||
|
`PRINT(arr6, 1, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
reg [1:5][2:0] arr7;
|
||||||
|
reg [1:5][2:0] arr8;
|
||||||
|
reg [1:5][2:0] arr9;
|
||||||
|
initial begin
|
||||||
|
arr7 = 'b100101010100100;
|
||||||
|
arr7[1][1] = ~arr7[1][1];
|
||||||
|
arr7[5][2] = ~arr7[5][2];
|
||||||
|
`PRINT(arr7, 1, 0)
|
||||||
|
arr8 = 'b100101000110101;
|
||||||
|
`PRINT(arr8, 1, 0)
|
||||||
|
arr9 = 'b100100111101010;
|
||||||
|
arr9[2] = arr9[3];
|
||||||
|
`PRINT(arr9, 1, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
module top;
|
||||||
|
Example example();
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
typedef struct packed {
|
||||||
|
logic x;
|
||||||
|
logic [3:0] y;
|
||||||
|
logic [1:0] z;
|
||||||
|
} Struct_t;
|
||||||
|
|
||||||
|
module Unpacker(in, select, a, b, c);
|
||||||
|
parameter WIDTH = 8;
|
||||||
|
input Struct_t [WIDTH-1:0] in;
|
||||||
|
input logic [$clog2(WIDTH)-1:0] select;
|
||||||
|
output logic a;
|
||||||
|
output logic [3:0] b;
|
||||||
|
output logic [1:0] c;
|
||||||
|
assign a = in[select].x;
|
||||||
|
assign b = in[select].y;
|
||||||
|
assign c = in[select].z;
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
module Unpacker(in, select, a, b, c);
|
||||||
|
parameter WIDTH = 8;
|
||||||
|
input wire [WIDTH-1:0][6:0] in;
|
||||||
|
input wire [$clog2(WIDTH)-1:0] select;
|
||||||
|
output wire a;
|
||||||
|
output wire [3:0] b;
|
||||||
|
output wire [1:0] c;
|
||||||
|
wire [6:0] p;
|
||||||
|
assign p = in[select];
|
||||||
|
assign a = p[6:6];
|
||||||
|
assign b = p[5:2];
|
||||||
|
assign c = p[1:0];
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
module top;
|
||||||
|
reg [56-1:0] in;
|
||||||
|
reg [2:0] select;
|
||||||
|
|
||||||
|
wire a;
|
||||||
|
wire [3:0] b;
|
||||||
|
wire [1:0] c;
|
||||||
|
|
||||||
|
Unpacker unpacker(in, select, a, b, c);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$monitor("%d: %01b %04b %02b", select, a, b, c);
|
||||||
|
in = 'b01111011011011101111100111110111001010001011100110101000;
|
||||||
|
select = 0; #1;
|
||||||
|
select = 1; #1;
|
||||||
|
select = 2; #1;
|
||||||
|
select = 3; #1;
|
||||||
|
select = 4; #1;
|
||||||
|
select = 5; #1;
|
||||||
|
select = 6; #1;
|
||||||
|
select = 7; #1;
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
// 0 1010 00
|
||||||
|
// 1 1100 11
|
||||||
|
// 0 1000 10
|
||||||
|
// 0 1110 01
|
||||||
|
// 0 0111 11
|
||||||
|
// 1 0111 11
|
||||||
|
// 1 0110 11
|
||||||
|
// 0 1111 01
|
||||||
|
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue