sv2v/src/Convert/DimensionQuery.hs

143 lines
4.8 KiB
Haskell
Raw Normal View History

{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Elaboration of the "expression size system function" ($bits) and the "array
- query functions" ($dimensions, $unpacked_dimensions, $left, $right, $low,
- $high, $increment, and $size).
-
- Some tools support $bits and some of the other functions in Verilog, but it
- is not part of the specification, so we have to convert them ourselves.
-
- Functions on types are trivially elaborated based on the dimensions of that
- type, so long as it has been resolved to a primitive type.
-
2020-01-12 02:35:51 +01:00
- Functions on expressions relies on the `type` operator and the `TypeOf`
- conversion to determine the underlying type of expression. The conversion of
- `$bits` on expressions recursively breaks the expression into its subtypes
- and finds their sizes.
-}
module Convert.DimensionQuery (convert) where
import Data.List (elemIndex)
import Convert.Traverse
import Language.SystemVerilog.AST
convert :: [AST] -> [AST]
convert = map $ traverseDescriptions convertDescription
convertDescription :: Description -> Description
convertDescription =
2020-01-12 02:35:51 +01:00
traverseModuleItems $ traverseExprs $ traverseNestedExprs convertExpr
-- elaborate integer atom types to have explicit dimensions
elaborateType :: Type -> Type
elaborateType (IntegerAtom t sg) =
IntegerVector TLogic sg [(hi, lo)]
where
size = atomSize t
hi = Number $ show (size - 1)
lo = Number "0"
atomSize :: IntegerAtomType -> Int
atomSize TByte = 8
atomSize TShortint = 16
atomSize TInt = 32
atomSize TLongint = 64
atomSize TInteger = 32
atomSize TTime = 64
elaborateType other = other
2020-01-12 02:35:51 +01:00
convertExpr :: Expr -> Expr
-- conversion for array dimensions functions
2020-01-12 02:35:51 +01:00
convertExpr (DimsFn FnBits v) =
convertBits v
convertExpr (DimsFn fn (Right e)) =
DimsFn fn $ Left $ TypeOf e
convertExpr (DimFn fn (Right e) d) =
DimFn fn (Left $ TypeOf e) d
convertExpr (orig @ (DimsFn FnUnpackedDimensions (Left t))) =
case t of
2020-01-12 02:35:51 +01:00
UnpackedType _ rs -> Number $ show $ length rs
TypeOf{} -> orig
_ -> Number "0"
convertExpr (orig @ (DimsFn FnDimensions (Left t))) =
case t of
IntegerAtom{} -> Number "1"
CSAlias{} -> orig
2020-01-12 02:35:51 +01:00
TypeOf{} -> orig
UnpackedType t' rs ->
BinOp Add
(Number $ show $ length rs)
(DimsFn FnDimensions $ Left t')
_ -> Number $ show $ length $ snd $ typeRanges t
-- conversion for array dimension functions on types
2020-01-12 02:35:51 +01:00
convertExpr (DimFn f (Left t) (Number str)) =
if dm == Nothing || isUnresolved t then
DimFn f (Left t) (Number str)
2020-06-07 04:45:08 +02:00
else if d <= 0 || fromIntegral d > length rs then
Number "'x"
else case f of
FnLeft -> fst r
FnRight -> snd r
FnIncrement -> endianCondExpr r (Number "1") (UniOp UniSub $ Number "1")
FnLow -> endianCondExpr r (snd r) (fst r)
FnHigh -> endianCondExpr r (fst r) (snd r)
FnSize -> rangeSize r
where
2020-01-12 02:35:51 +01:00
rs = case elaborateType t of
UnpackedType tInner rsOuter ->
rsOuter ++ (snd $ typeRanges $ elaborateType tInner)
_ -> snd $ typeRanges $ elaborateType t
dm = readNumber str
Just d = dm
2020-06-07 04:45:08 +02:00
r = rs !! (fromIntegral $ d - 1)
2020-01-12 02:35:51 +01:00
isUnresolved :: Type -> Bool
isUnresolved (CSAlias{}) = True
2020-01-12 02:35:51 +01:00
isUnresolved (TypeOf{}) = True
isUnresolved _ = False
convertExpr (DimFn f (Left t) d) =
DimFn f (Left t) d
2020-01-12 02:35:51 +01:00
convertExpr other = other
2020-01-12 02:35:51 +01:00
-- simplify a bits expression
convertBits :: TypeOrExpr -> Expr
convertBits (Left t) =
case elaborateType t of
IntegerVector _ _ rs -> dimensionsSize rs
Implicit _ rs -> dimensionsSize rs
Net _ _ rs -> dimensionsSize rs
2020-02-10 01:07:12 +01:00
Struct _ fields rs ->
BinOp Mul
(dimensionsSize rs)
(foldl (BinOp Add) (Number "0") fieldSizes)
where fieldSizes = map (DimsFn FnBits . Left . fst) fields
2020-01-12 02:35:51 +01:00
UnpackedType t' rs ->
BinOp Mul
(dimensionsSize rs)
(DimsFn FnBits $ Left t')
_ -> DimsFn FnBits $ Left t
2020-01-12 02:35:51 +01:00
convertBits (Right e) =
case e of
Concat exprs ->
foldl (BinOp Add) (Number "0") $
2020-01-12 02:35:51 +01:00
map (convertBits . Right) $
exprs
2020-01-12 02:35:51 +01:00
Stream _ _ exprs -> convertBits $ Right $ Concat exprs
Number n ->
case elemIndex '\'' n of
Nothing -> Number "32"
Just 0 -> Number "32"
Just idx -> Number $ take idx n
2020-06-07 03:28:37 +02:00
Range expr mode range ->
BinOp Mul size $ convertBits $ Right $ Bit expr (Number "0")
where
size = case mode of
NonIndexed -> rangeSize range
IndexedPlus -> snd range
IndexedMinus -> snd range
2020-01-12 02:35:51 +01:00
_ -> DimsFn FnBits $ Left $ TypeOf e