mirror of https://github.com/zachjs/sv2v.git
enum conversion explicitly sizes generated params and supports partial types
This commit is contained in:
parent
093a4d4dd9
commit
4cbfd8fa1a
|
|
@ -6,7 +6,8 @@
|
||||||
- This conversion replaces the enum items with localparams declared within any
|
- This conversion replaces the enum items with localparams declared within any
|
||||||
- modules in which that enum type appears. This is not necessarily foolproof,
|
- 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
|
- as some tools do allow the use of an enum item even if the actual enum type
|
||||||
- does not appear in that description.
|
- does not appear in that description. The localparams are explicitly sized to
|
||||||
|
- match the size of the converted enum type.
|
||||||
-
|
-
|
||||||
- SystemVerilog allows for enums to have any number of the items' values
|
- 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
|
- specified or unspecified. If the first one is unspecified, it is 0. All other
|
||||||
|
|
@ -21,13 +22,12 @@ module Convert.Enum (convert) where
|
||||||
|
|
||||||
import Control.Monad.Writer
|
import Control.Monad.Writer
|
||||||
import Data.List (elemIndices, sortOn)
|
import Data.List (elemIndices, sortOn)
|
||||||
import Data.Maybe (fromMaybe)
|
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
import Convert.Traverse
|
import Convert.Traverse
|
||||||
import Language.SystemVerilog.AST
|
import Language.SystemVerilog.AST
|
||||||
|
|
||||||
type EnumInfo = (Maybe Type, [(Identifier, Maybe Expr)])
|
type EnumInfo = ([Range], [(Identifier, Maybe Expr)])
|
||||||
type Enums = Set.Set EnumInfo
|
type Enums = Set.Set EnumInfo
|
||||||
|
|
||||||
convert :: AST -> AST
|
convert :: AST -> AST
|
||||||
|
|
@ -47,18 +47,28 @@ convertDescription (description @ (Part _ _ _ _ _ _)) =
|
||||||
traverseModuleItems (traverseExprs $ traverseNestedExprs traverseExpr) $
|
traverseModuleItems (traverseExprs $ traverseNestedExprs traverseExpr) $
|
||||||
description
|
description
|
||||||
-- convert the collected enums into their corresponding localparams
|
-- convert the collected enums into their corresponding localparams
|
||||||
itemType = Implicit Unspecified []
|
itemType = Implicit Unspecified
|
||||||
enumPairs = sortOn snd $ concatMap (enumVals . snd) $ Set.toList enums
|
enumPairs = sortOn snd $ concatMap enumVals $ Set.toList enums
|
||||||
enumItems = map (\(x, v) -> MIDecl $ Localparam itemType x v) enumPairs
|
enumItems = map (\((r, x), v) -> MIDecl $ Localparam (itemType r) x v) enumPairs
|
||||||
convertDescription other = other
|
convertDescription other = other
|
||||||
|
|
||||||
|
toBaseType :: Maybe Type -> Type
|
||||||
|
toBaseType Nothing = defaultType
|
||||||
|
toBaseType (Just (Implicit _ rs)) =
|
||||||
|
fst (typeRanges defaultType) rs
|
||||||
|
toBaseType (Just t) =
|
||||||
|
if null rs
|
||||||
|
then tf [(Number "0", Number "0")]
|
||||||
|
else t
|
||||||
|
where (tf, rs) = typeRanges t
|
||||||
|
|
||||||
-- replace, but write down, enum types
|
-- replace, but write down, enum types
|
||||||
traverseType :: Type -> Writer Enums Type
|
traverseType :: Type -> Writer Enums Type
|
||||||
traverseType (Enum t v r) = do
|
traverseType (Enum t v rs) = do
|
||||||
() <- tell $ Set.singleton (t, v)
|
let baseType = toBaseType t
|
||||||
let baseType = fromMaybe defaultType t
|
let (tf, r) = typeRanges baseType
|
||||||
let (tf, rs) = typeRanges baseType
|
() <- tell $ Set.singleton (r, v)
|
||||||
return $ tf (rs ++ r)
|
return $ tf (r ++ rs)
|
||||||
traverseType other = return other
|
traverseType other = return other
|
||||||
|
|
||||||
-- drop any enum type casts in favor of implicit conversion from the
|
-- drop any enum type casts in favor of implicit conversion from the
|
||||||
|
|
@ -67,16 +77,17 @@ traverseExpr :: Expr -> Expr
|
||||||
traverseExpr (Cast (Left (Enum _ _ _)) e) = e
|
traverseExpr (Cast (Left (Enum _ _ _)) e) = e
|
||||||
traverseExpr other = other
|
traverseExpr other = other
|
||||||
|
|
||||||
enumVals :: [(Identifier, Maybe Expr)] -> [(Identifier, Expr)]
|
enumVals :: ([Range], [(Identifier, Maybe Expr)]) -> [(([Range], Identifier), Expr)]
|
||||||
enumVals l =
|
enumVals (r, l) =
|
||||||
-- check for obviously duplicate values
|
-- check for obviously duplicate values
|
||||||
if noDuplicates
|
if noDuplicates
|
||||||
then res
|
then res
|
||||||
else error $ "enum conversion has duplicate vals: " ++ show res
|
else error $ "enum conversion has duplicate vals: "
|
||||||
|
++ show (zip keys vals)
|
||||||
where
|
where
|
||||||
keys = map fst l
|
keys = map fst l
|
||||||
vals = tail $ scanl step (Number "-1") (map snd l)
|
vals = tail $ scanl step (Number "-1") (map snd l)
|
||||||
res = zip keys vals
|
res = zip (zip (repeat r) keys) vals
|
||||||
noDuplicates = all (null . tail . flip elemIndices vals) vals
|
noDuplicates = all (null . tail . flip elemIndices vals) vals
|
||||||
step :: Expr -> Maybe Expr -> Expr
|
step :: Expr -> Maybe Expr -> Expr
|
||||||
step _ (Just expr) = expr
|
step _ (Just expr) = expr
|
||||||
|
|
|
||||||
|
|
@ -269,13 +269,16 @@ PartialType :: { Signing -> [Range] -> Type }
|
||||||
| IntegerVectorType { IntegerVector $1 }
|
| IntegerVectorType { IntegerVector $1 }
|
||||||
| IntegerAtomType { \sg -> \[] -> IntegerAtom $1 sg }
|
| IntegerAtomType { \sg -> \[] -> IntegerAtom $1 sg }
|
||||||
| NonIntegerType { \Unspecified -> \[] -> NonInteger $1 }
|
| NonIntegerType { \Unspecified -> \[] -> NonInteger $1 }
|
||||||
| "enum" opt(Type) "{" EnumItems "}" { \Unspecified -> Enum $2 $4 }
|
| "enum" EnumBaseType "{" EnumItems "}" { \Unspecified -> Enum $2 $4 }
|
||||||
| "struct" Packing "{" StructItems "}" { \Unspecified -> Struct $2 $4 }
|
| "struct" Packing "{" StructItems "}" { \Unspecified -> Struct $2 $4 }
|
||||||
CastingType :: { Type }
|
CastingType :: { Type }
|
||||||
: IntegerVectorType { IntegerVector $1 Unspecified [] }
|
: IntegerVectorType { IntegerVector $1 Unspecified [] }
|
||||||
| IntegerAtomType { IntegerAtom $1 Unspecified }
|
| IntegerAtomType { IntegerAtom $1 Unspecified }
|
||||||
| NonIntegerType { NonInteger $1 }
|
| NonIntegerType { NonInteger $1 }
|
||||||
| Signing { Implicit $1 [] }
|
| Signing { Implicit $1 [] }
|
||||||
|
EnumBaseType :: { Maybe Type }
|
||||||
|
: opt(Type) { $1 }
|
||||||
|
| DimensionsNonEmpty { Just $ Implicit Unspecified $1 }
|
||||||
|
|
||||||
Signing :: { Signing }
|
Signing :: { Signing }
|
||||||
: "signed" { Signed }
|
: "signed" { Signed }
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,18 @@ typedef enum {
|
||||||
E_1, E_2 = 'h10, E_3, E_4, E_5 = 'b10, E_6
|
E_1, E_2 = 'h10, E_3, E_4, E_5 = 'b10, E_6
|
||||||
} EnumE;
|
} EnumE;
|
||||||
|
|
||||||
`define PRINT(val) $display("%02d", val);
|
typedef enum logic {
|
||||||
|
F_1, F_2
|
||||||
|
} EnumF;
|
||||||
|
|
||||||
|
typedef enum [0:0] {
|
||||||
|
G_1, G_2
|
||||||
|
} EnumG;
|
||||||
|
|
||||||
|
`define PRINT(name, val) \
|
||||||
|
dummy``name = name``_``val; \
|
||||||
|
$display("%010x %010x %02d %02d", \
|
||||||
|
name``_``val, dummy``name, $bits(name``_``val), $bits(dummy``name));
|
||||||
|
|
||||||
module top;
|
module top;
|
||||||
EnumA dummyA;
|
EnumA dummyA;
|
||||||
|
|
@ -26,31 +37,39 @@ module top;
|
||||||
EnumC dummyC;
|
EnumC dummyC;
|
||||||
EnumD dummyD;
|
EnumD dummyD;
|
||||||
EnumE dummyE;
|
EnumE dummyE;
|
||||||
|
EnumF dummyF;
|
||||||
|
EnumG dummyG;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
|
||||||
`PRINT(A_1)
|
`PRINT(A, 1)
|
||||||
`PRINT(A_2)
|
`PRINT(A, 2)
|
||||||
`PRINT(A_3)
|
`PRINT(A, 3)
|
||||||
|
|
||||||
`PRINT(B_1)
|
`PRINT(B, 1)
|
||||||
`PRINT(B_2)
|
`PRINT(B, 2)
|
||||||
`PRINT(B_3)
|
`PRINT(B, 3)
|
||||||
|
|
||||||
`PRINT(C_1)
|
`PRINT(C, 1)
|
||||||
`PRINT(C_2)
|
`PRINT(C, 2)
|
||||||
`PRINT(C_3)
|
`PRINT(C, 3)
|
||||||
|
|
||||||
`PRINT(D_1)
|
`PRINT(D, 1)
|
||||||
`PRINT(D_2)
|
`PRINT(D, 2)
|
||||||
`PRINT(D_3)
|
`PRINT(D, 3)
|
||||||
|
|
||||||
`PRINT(E_1)
|
`PRINT(E, 1)
|
||||||
`PRINT(E_2)
|
`PRINT(E, 2)
|
||||||
`PRINT(E_3)
|
`PRINT(E, 3)
|
||||||
`PRINT(E_4)
|
`PRINT(E, 4)
|
||||||
`PRINT(E_5)
|
`PRINT(E, 5)
|
||||||
`PRINT(E_6)
|
`PRINT(E, 6)
|
||||||
|
|
||||||
|
`PRINT(F, 1)
|
||||||
|
`PRINT(F, 2)
|
||||||
|
|
||||||
|
`PRINT(G, 1)
|
||||||
|
`PRINT(G, 2)
|
||||||
|
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,56 @@
|
||||||
`define PRINT(val) $display("%02d", val);
|
`define PRINT(name, val) \
|
||||||
|
$display("%010x %010x %02d %02d", \
|
||||||
|
val, val, $bits(dummy``name), $bits(dummy``name));
|
||||||
|
|
||||||
module top;
|
module top;
|
||||||
|
|
||||||
|
reg [31:0] dummyA;
|
||||||
|
reg [31:0] dummyB;
|
||||||
|
reg [31:0] dummyC;
|
||||||
|
reg [31:0] dummyD;
|
||||||
|
reg [31:0] dummyE;
|
||||||
|
reg dummyF;
|
||||||
|
reg [0:0] dummyG;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
|
||||||
`PRINT(0)
|
dummyA = 'b10;
|
||||||
`PRINT(1)
|
dummyB = 'b11;
|
||||||
`PRINT(2)
|
dummyC = 'b10011;
|
||||||
|
dummyD = 'b10010;
|
||||||
|
dummyE = 'b11;
|
||||||
|
dummyF = 'b1;
|
||||||
|
dummyG = 'b1;
|
||||||
|
|
||||||
`PRINT(2)
|
`PRINT(A, 0)
|
||||||
`PRINT(1)
|
`PRINT(A, 1)
|
||||||
`PRINT(3)
|
`PRINT(A, 2)
|
||||||
|
|
||||||
`PRINT(20)
|
`PRINT(B, 2)
|
||||||
`PRINT(0)
|
`PRINT(B, 1)
|
||||||
`PRINT(19)
|
`PRINT(B, 3)
|
||||||
|
|
||||||
`PRINT(16)
|
`PRINT(C, 20)
|
||||||
`PRINT(17)
|
`PRINT(C, 0)
|
||||||
`PRINT(18)
|
`PRINT(C, 19)
|
||||||
|
|
||||||
`PRINT(0)
|
`PRINT(D, 16)
|
||||||
`PRINT(16)
|
`PRINT(D, 17)
|
||||||
`PRINT(17)
|
`PRINT(D, 18)
|
||||||
`PRINT(18)
|
|
||||||
`PRINT(2)
|
`PRINT(E, 0)
|
||||||
`PRINT(3)
|
`PRINT(E, 16)
|
||||||
|
`PRINT(E, 17)
|
||||||
|
`PRINT(E, 18)
|
||||||
|
`PRINT(E, 2)
|
||||||
|
`PRINT(E, 3)
|
||||||
|
|
||||||
|
`PRINT(F, 0)
|
||||||
|
`PRINT(F, 1)
|
||||||
|
|
||||||
|
`PRINT(G, 0)
|
||||||
|
`PRINT(G, 1)
|
||||||
|
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue