Commit 4cbfd8fa by Zachary Snow

enum conversion explicitly sizes generated params and supports partial types

parent 093a4d4d
......@@ -6,7 +6,8 @@
- 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.
- 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
- 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 Data.List (elemIndices, sortOn)
import Data.Maybe (fromMaybe)
import qualified Data.Set as Set
import Convert.Traverse
import Language.SystemVerilog.AST
type EnumInfo = (Maybe Type, [(Identifier, Maybe Expr)])
type EnumInfo = ([Range], [(Identifier, Maybe Expr)])
type Enums = Set.Set EnumInfo
convert :: AST -> AST
......@@ -47,18 +47,28 @@ convertDescription (description @ (Part _ _ _ _ _ _)) =
traverseModuleItems (traverseExprs $ traverseNestedExprs traverseExpr) $
description
-- 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
itemType = Implicit Unspecified
enumPairs = sortOn snd $ concatMap enumVals $ Set.toList enums
enumItems = map (\((r, x), v) -> MIDecl $ Localparam (itemType r) x v) enumPairs
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
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 (Enum t v rs) = do
let baseType = toBaseType t
let (tf, r) = typeRanges baseType
() <- tell $ Set.singleton (r, v)
return $ tf (r ++ rs)
traverseType other = return other
-- 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 other = other
enumVals :: [(Identifier, Maybe Expr)] -> [(Identifier, Expr)]
enumVals l =
enumVals :: ([Range], [(Identifier, Maybe Expr)]) -> [(([Range], Identifier), Expr)]
enumVals (r, l) =
-- check for obviously duplicate values
if noDuplicates
then res
else error $ "enum conversion has duplicate vals: " ++ show res
else error $ "enum conversion has duplicate vals: "
++ show (zip keys vals)
where
keys = map fst 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
step :: Expr -> Maybe Expr -> Expr
step _ (Just expr) = expr
......
......@@ -269,13 +269,16 @@ PartialType :: { Signing -> [Range] -> Type }
| IntegerVectorType { IntegerVector $1 }
| IntegerAtomType { \sg -> \[] -> IntegerAtom $1 sg }
| NonIntegerType { \Unspecified -> \[] -> NonInteger $1 }
| "enum" opt(Type) "{" EnumItems "}" { \Unspecified -> Enum $2 $4 }
| "struct" Packing "{" StructItems "}" { \Unspecified -> Struct $2 $4 }
| "enum" EnumBaseType "{" EnumItems "}" { \Unspecified -> Enum $2 $4 }
| "struct" Packing "{" StructItems "}" { \Unspecified -> Struct $2 $4 }
CastingType :: { Type }
: IntegerVectorType { IntegerVector $1 Unspecified [] }
| IntegerAtomType { IntegerAtom $1 Unspecified }
| NonIntegerType { NonInteger $1 }
| Signing { Implicit $1 [] }
EnumBaseType :: { Maybe Type }
: opt(Type) { $1 }
| DimensionsNonEmpty { Just $ Implicit Unspecified $1 }
Signing :: { Signing }
: "signed" { Signed }
......
......@@ -18,7 +18,18 @@ typedef enum {
E_1, E_2 = 'h10, E_3, E_4, E_5 = 'b10, E_6
} 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;
EnumA dummyA;
......@@ -26,31 +37,39 @@ module top;
EnumC dummyC;
EnumD dummyD;
EnumE dummyE;
EnumF dummyF;
EnumG dummyG;
initial begin
`PRINT(A_1)
`PRINT(A_2)
`PRINT(A_3)
`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(B_1)
`PRINT(B_2)
`PRINT(B_3)
`PRINT(D, 1)
`PRINT(D, 2)
`PRINT(D, 3)
`PRINT(C_1)
`PRINT(C_2)
`PRINT(C_3)
`PRINT(E, 1)
`PRINT(E, 2)
`PRINT(E, 3)
`PRINT(E, 4)
`PRINT(E, 5)
`PRINT(E, 6)
`PRINT(D_1)
`PRINT(D_2)
`PRINT(D_3)
`PRINT(F, 1)
`PRINT(F, 2)
`PRINT(E_1)
`PRINT(E_2)
`PRINT(E_3)
`PRINT(E_4)
`PRINT(E_5)
`PRINT(E_6)
`PRINT(G, 1)
`PRINT(G, 2)
end
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;
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
`PRINT(0)
`PRINT(1)
`PRINT(2)
dummyA = 'b10;
dummyB = 'b11;
dummyC = 'b10011;
dummyD = 'b10010;
dummyE = 'b11;
dummyF = 'b1;
dummyG = 'b1;
`PRINT(A, 0)
`PRINT(A, 1)
`PRINT(A, 2)
`PRINT(2)
`PRINT(1)
`PRINT(3)
`PRINT(B, 2)
`PRINT(B, 1)
`PRINT(B, 3)
`PRINT(20)
`PRINT(0)
`PRINT(19)
`PRINT(C, 20)
`PRINT(C, 0)
`PRINT(C, 19)
`PRINT(16)
`PRINT(17)
`PRINT(18)
`PRINT(D, 16)
`PRINT(D, 17)
`PRINT(D, 18)
`PRINT(0)
`PRINT(16)
`PRINT(17)
`PRINT(18)
`PRINT(2)
`PRINT(3)
`PRINT(E, 0)
`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
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