mirror of https://github.com/zachjs/sv2v.git
cleanup of Enum conversion; additional test
This commit is contained in:
parent
383754fa7a
commit
f9d46d548e
|
|
@ -3,17 +3,25 @@
|
|||
-
|
||||
- Conversion for `enum`
|
||||
-
|
||||
- TODO: We do not yet properly support enums which specify the value for some,
|
||||
- but not all items. My understanding is that they should continue in order
|
||||
- from the previous value.
|
||||
- This conversion replaces the enum items with localparams declared within any
|
||||
- modules in which that enum type appears. This is not necessarily foolproof,
|
||||
- as some tools do allow the use of an enum item even if the actual enum type
|
||||
- does not appear in that description.
|
||||
-
|
||||
- SystemVerilog allows for enums to have any number of the items' values
|
||||
- specified or unspecified. If the first one is unspecified, it is 0. All other
|
||||
- values take on the value of the previous item, plus 1.
|
||||
-
|
||||
- It is an error for multiple items of the same enum to take on the same value,
|
||||
- whether implicitly or explicitly. We catch try to catch "obvious" instances
|
||||
- of conflicts.
|
||||
-}
|
||||
|
||||
module Convert.Enum (convert) where
|
||||
|
||||
import Text.Read (readMaybe)
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Data.List (sortOn)
|
||||
import Control.Monad.Writer
|
||||
import Data.List (elemIndices, sortOn)
|
||||
import Data.Maybe (fromMaybe)
|
||||
import qualified Data.Set as Set
|
||||
|
||||
import Convert.Traverse
|
||||
|
|
@ -32,36 +40,45 @@ convertDescription :: Description -> Description
|
|||
convertDescription (description @ (Part _ _ _ _ _ _)) =
|
||||
Part extern kw lifetime name ports (enumItems ++ items)
|
||||
where
|
||||
enumPairs = sortOn snd $ concatMap (uncurry enumVals) $ Set.toList enums
|
||||
enumItems = map (\(x, v) -> MIDecl $ Localparam (Implicit Unspecified []) x v) enumPairs
|
||||
-- replace and collect the enum types in this description
|
||||
(Part extern kw lifetime name ports items, enums) =
|
||||
runWriter $ traverseModuleItemsM (traverseTypesM traverseType) $
|
||||
runWriter $
|
||||
traverseModuleItemsM (traverseTypesM traverseType) $
|
||||
traverseModuleItems (traverseExprs $ traverseNestedExprs traverseExpr) $
|
||||
description
|
||||
traverseType :: Type -> Writer Enums Type
|
||||
traverseType (Enum t v r) = do
|
||||
() <- tell $ Set.singleton (t, v)
|
||||
let baseType = fromMaybe defaultType t
|
||||
let (tf, rs) = typeRanges baseType
|
||||
return $ tf (rs ++ r)
|
||||
traverseType other = return other
|
||||
-- drop any enum type casts in favor of implicit conversion from the
|
||||
-- converted type
|
||||
traverseExpr :: Expr -> Expr
|
||||
traverseExpr (Cast (Left (Enum _ _ _)) e) = e
|
||||
traverseExpr other = other
|
||||
-- convert the collected enums into their corresponding localparams
|
||||
itemType = Implicit Unspecified []
|
||||
enumPairs = sortOn snd $ concatMap (enumVals . snd) $ Set.toList enums
|
||||
enumItems = map (\(x, v) -> MIDecl $ Localparam itemType x v) enumPairs
|
||||
convertDescription other = other
|
||||
|
||||
enumVals :: Maybe Type -> [(Identifier, Maybe Expr)] -> [(Identifier, Expr)]
|
||||
enumVals _ l = zip
|
||||
(map fst l)
|
||||
(tail $ scanl step (Number "-1") (map snd l))
|
||||
-- replace, but write down, enum types
|
||||
traverseType :: Type -> Writer Enums Type
|
||||
traverseType (Enum t v r) = do
|
||||
() <- tell $ Set.singleton (t, v)
|
||||
let baseType = fromMaybe defaultType t
|
||||
let (tf, rs) = typeRanges baseType
|
||||
return $ tf (rs ++ r)
|
||||
traverseType other = return other
|
||||
|
||||
-- drop any enum type casts in favor of implicit conversion from the
|
||||
-- converted type
|
||||
traverseExpr :: Expr -> Expr
|
||||
traverseExpr (Cast (Left (Enum _ _ _)) e) = e
|
||||
traverseExpr other = other
|
||||
|
||||
enumVals :: [(Identifier, Maybe Expr)] -> [(Identifier, Expr)]
|
||||
enumVals l =
|
||||
-- check for obviously duplicate values
|
||||
if noDuplicates
|
||||
then res
|
||||
else error $ "enum conversion has duplicate vals: " ++ show res
|
||||
where
|
||||
keys = map fst l
|
||||
vals = tail $ scanl step (Number "-1") (map snd l)
|
||||
res = zip keys vals
|
||||
noDuplicates = all (null . tail . flip elemIndices vals) vals
|
||||
step :: Expr -> Maybe Expr -> Expr
|
||||
step _ (Just expr) = expr
|
||||
step (Number n) Nothing =
|
||||
case (readMaybe n) :: Maybe Int of
|
||||
Just value -> Number (show $ value + 1)
|
||||
Nothing -> BinOp Add (Number n) (Number "1")
|
||||
step expr Nothing =
|
||||
BinOp Add expr (Number "1")
|
||||
simplify $ BinOp Add expr (Number "1")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
typedef enum {
|
||||
A_1, A_2, A_3
|
||||
} EnumA;
|
||||
|
||||
typedef enum {
|
||||
B_1 = 2, B_2 = 1, B_3 = 3
|
||||
} EnumB;
|
||||
|
||||
typedef enum {
|
||||
C_1 = 20, C_2 = 0, C_3 = 19
|
||||
} EnumC;
|
||||
|
||||
typedef enum {
|
||||
D_1 = 'h10, D_2, D_3
|
||||
} EnumD;
|
||||
|
||||
typedef enum {
|
||||
E_1, E_2 = 'h10, E_3, E_4, E_5 = 'b10, E_6
|
||||
} EnumE;
|
||||
|
||||
`define PRINT(val) $display("%02d", val);
|
||||
|
||||
module top;
|
||||
EnumA dummyA;
|
||||
EnumB dummyB;
|
||||
EnumC dummyC;
|
||||
EnumD dummyD;
|
||||
EnumE dummyE;
|
||||
|
||||
initial begin
|
||||
|
||||
`PRINT(A_1)
|
||||
`PRINT(A_2)
|
||||
`PRINT(A_3)
|
||||
|
||||
`PRINT(B_1)
|
||||
`PRINT(B_2)
|
||||
`PRINT(B_3)
|
||||
|
||||
`PRINT(C_1)
|
||||
`PRINT(C_2)
|
||||
`PRINT(C_3)
|
||||
|
||||
`PRINT(D_1)
|
||||
`PRINT(D_2)
|
||||
`PRINT(D_3)
|
||||
|
||||
`PRINT(E_1)
|
||||
`PRINT(E_2)
|
||||
`PRINT(E_3)
|
||||
`PRINT(E_4)
|
||||
`PRINT(E_5)
|
||||
`PRINT(E_6)
|
||||
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
`define PRINT(val) $display("%02d", val);
|
||||
|
||||
module top;
|
||||
initial begin
|
||||
|
||||
`PRINT(0)
|
||||
`PRINT(1)
|
||||
`PRINT(2)
|
||||
|
||||
`PRINT(2)
|
||||
`PRINT(1)
|
||||
`PRINT(3)
|
||||
|
||||
`PRINT(20)
|
||||
`PRINT(0)
|
||||
`PRINT(19)
|
||||
|
||||
`PRINT(16)
|
||||
`PRINT(17)
|
||||
`PRINT(18)
|
||||
|
||||
`PRINT(0)
|
||||
`PRINT(16)
|
||||
`PRINT(17)
|
||||
`PRINT(18)
|
||||
`PRINT(2)
|
||||
`PRINT(3)
|
||||
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
NO_SEPARATE_TBS=1
|
||||
source ../lib/runner.sh
|
||||
Loading…
Reference in New Issue