Commit 4cbfd8fa by Zachary Snow

enum conversion explicitly sizes generated params and supports partial types

parent 093a4d4d
...@@ -6,7 +6,8 @@ ...@@ -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 ...@@ -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 _ _ _ _ _ _)) = ...@@ -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 ...@@ -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 } ...@@ -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 { ...@@ -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; ...@@ -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, 2)
`PRINT(B, 3)
`PRINT(C, 1)
`PRINT(C, 2)
`PRINT(C, 3)
`PRINT(B_1) `PRINT(D, 1)
`PRINT(B_2) `PRINT(D, 2)
`PRINT(B_3) `PRINT(D, 3)
`PRINT(C_1) `PRINT(E, 1)
`PRINT(C_2) `PRINT(E, 2)
`PRINT(C_3) `PRINT(E, 3)
`PRINT(E, 4)
`PRINT(E, 5)
`PRINT(E, 6)
`PRINT(D_1) `PRINT(F, 1)
`PRINT(D_2) `PRINT(F, 2)
`PRINT(D_3)
`PRINT(E_1) `PRINT(G, 1)
`PRINT(E_2) `PRINT(G, 2)
`PRINT(E_3)
`PRINT(E_4)
`PRINT(E_5)
`PRINT(E_6)
end end
endmodule endmodule
`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(A, 0)
`PRINT(A, 1)
`PRINT(A, 2)
`PRINT(2) `PRINT(B, 2)
`PRINT(1) `PRINT(B, 1)
`PRINT(3) `PRINT(B, 3)
`PRINT(20) `PRINT(C, 20)
`PRINT(0) `PRINT(C, 0)
`PRINT(19) `PRINT(C, 19)
`PRINT(16) `PRINT(D, 16)
`PRINT(17) `PRINT(D, 17)
`PRINT(18) `PRINT(D, 18)
`PRINT(0) `PRINT(E, 0)
`PRINT(16) `PRINT(E, 16)
`PRINT(17) `PRINT(E, 17)
`PRINT(18) `PRINT(E, 18)
`PRINT(2) `PRINT(E, 2)
`PRINT(3) `PRINT(E, 3)
`PRINT(F, 0)
`PRINT(F, 1)
`PRINT(G, 0)
`PRINT(G, 1)
end end
endmodule endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment