mirror of https://github.com/zachjs/sv2v.git
added conversion for packed unions
This commit is contained in:
parent
8a67a91166
commit
81f5fb500f
|
|
@ -1,7 +1,7 @@
|
||||||
{- sv2v
|
{- sv2v
|
||||||
- Author: Zachary Snow <zach@zachjs.com>
|
- Author: Zachary Snow <zach@zachjs.com>
|
||||||
-
|
-
|
||||||
- Conversion for `struct packed`
|
- Conversion for `struct packed` and `union packed`
|
||||||
-}
|
-}
|
||||||
|
|
||||||
module Convert.Struct (convert) where
|
module Convert.Struct (convert) where
|
||||||
|
|
@ -70,10 +70,19 @@ convertDescription other = other
|
||||||
|
|
||||||
-- write down unstructured versions of packed struct types
|
-- write down unstructured versions of packed struct types
|
||||||
collectStructM :: Type -> Writer Structs ()
|
collectStructM :: Type -> Writer Structs ()
|
||||||
collectStructM (Struct (Packed sg) fields _) = do
|
collectStructM (Struct (Packed sg) fields _) =
|
||||||
|
collectStructM' Struct True sg fields
|
||||||
|
collectStructM (Union (Packed sg) fields _) =
|
||||||
|
collectStructM' Union False sg fields
|
||||||
|
collectStructM _ = return ()
|
||||||
|
|
||||||
|
collectStructM'
|
||||||
|
:: (Packing -> [Field] -> [Range] -> Type)
|
||||||
|
-> Bool -> Signing -> [Field] -> Writer Structs ()
|
||||||
|
collectStructM' constructor isStruct sg fields = do
|
||||||
if canUnstructure
|
if canUnstructure
|
||||||
then tell $ Map.singleton
|
then tell $ Map.singleton
|
||||||
(Struct (Packed sg) fields)
|
(constructor (Packed sg) fields)
|
||||||
(unstructType, unstructFields)
|
(unstructType, unstructFields)
|
||||||
else return ()
|
else return ()
|
||||||
where
|
where
|
||||||
|
|
@ -90,8 +99,14 @@ collectStructM (Struct (Packed sg) fields _) = do
|
||||||
|
|
||||||
-- layout the fields into the unstructured type; note that `scanr` is
|
-- layout the fields into the unstructured type; note that `scanr` is
|
||||||
-- used here because SystemVerilog structs are laid out backwards
|
-- used here because SystemVerilog structs are laid out backwards
|
||||||
fieldLos = map simplify $ tail $ scanr (BinOp Add) (Number "0") fieldSizes
|
fieldLos =
|
||||||
fieldHis = map simplify $ init $ scanr (BinOp Add) (Number "-1") fieldSizes
|
if isStruct
|
||||||
|
then map simplify $ tail $ scanr (BinOp Add) (Number "0") fieldSizes
|
||||||
|
else map simplify $ repeat (Number "0")
|
||||||
|
fieldHis =
|
||||||
|
if isStruct
|
||||||
|
then map simplify $ init $ scanr (BinOp Add) (Number "-1") fieldSizes
|
||||||
|
else map simplify $ map (BinOp Add (Number "-1")) fieldSizes
|
||||||
|
|
||||||
-- create the mapping structure for the unstructured fields
|
-- create the mapping structure for the unstructured fields
|
||||||
unstructOffsets = map simplify $ map snd fieldRanges
|
unstructOffsets = map simplify $ map snd fieldRanges
|
||||||
|
|
@ -102,7 +117,10 @@ collectStructM (Struct (Packed sg) fields _) = do
|
||||||
|
|
||||||
-- create the unstructured type; result type takes on the signing of the
|
-- create the unstructured type; result type takes on the signing of the
|
||||||
-- struct itself to preserve behavior of operations on the whole struct
|
-- struct itself to preserve behavior of operations on the whole struct
|
||||||
structSize = foldl1 (BinOp Add) fieldSizes
|
structSize =
|
||||||
|
if isStruct
|
||||||
|
then foldl1 (BinOp Add) fieldSizes
|
||||||
|
else head fieldSizes
|
||||||
packedRange = (simplify $ BinOp Sub structSize (Number "1"), zero)
|
packedRange = (simplify $ BinOp Sub structSize (Number "1"), zero)
|
||||||
unstructType = IntegerVector TLogic sg [packedRange]
|
unstructType = IntegerVector TLogic sg [packedRange]
|
||||||
|
|
||||||
|
|
@ -114,7 +132,6 @@ collectStructM (Struct (Packed sg) fields _) = do
|
||||||
isIntVec _ = False
|
isIntVec _ = False
|
||||||
canUnstructure = all isIntVec fieldTypes
|
canUnstructure = all isIntVec fieldTypes
|
||||||
|
|
||||||
collectStructM _ = return ()
|
|
||||||
|
|
||||||
-- convert a struct type to its unstructured equivalent
|
-- convert a struct type to its unstructured equivalent
|
||||||
convertType :: Structs -> Type -> Type
|
convertType :: Structs -> Type -> Type
|
||||||
|
|
@ -252,7 +269,13 @@ convertAsgn structs types (lhs, expr) =
|
||||||
convertLHS (LHSDot l x ) =
|
convertLHS (LHSDot l x ) =
|
||||||
case t of
|
case t of
|
||||||
InterfaceT _ _ _ -> (Implicit Unspecified [], LHSDot l' x)
|
InterfaceT _ _ _ -> (Implicit Unspecified [], LHSDot l' x)
|
||||||
Struct _ _ _ -> case Map.lookup structTf structs of
|
Struct p fields [] -> undot (Struct p fields) fields
|
||||||
|
Union p fields [] -> undot (Union p fields) fields
|
||||||
|
Implicit sg _ -> (Implicit sg [], LHSDot l' x)
|
||||||
|
_ -> error $ "convertLHS encountered dot for bad type: " ++ show (t, l, x)
|
||||||
|
where
|
||||||
|
(t, l') = convertLHS l
|
||||||
|
undot structTf fields = case Map.lookup structTf structs of
|
||||||
Nothing -> (fieldType, LHSDot l' x)
|
Nothing -> (fieldType, LHSDot l' x)
|
||||||
Just (structT, m) -> (tf [tr], LHSRange l' NonIndexed r)
|
Just (structT, m) -> (tf [tr], LHSRange l' NonIndexed r)
|
||||||
where
|
where
|
||||||
|
|
@ -261,13 +284,8 @@ convertAsgn structs types (lhs, expr) =
|
||||||
hi' = BinOp Add base $ BinOp Sub hi lo
|
hi' = BinOp Add base $ BinOp Sub hi lo
|
||||||
lo' = base
|
lo' = base
|
||||||
tr = (simplify hi', simplify lo')
|
tr = (simplify hi', simplify lo')
|
||||||
Implicit sg _ -> (Implicit sg [], LHSDot l' x)
|
where
|
||||||
_ -> error $ "convertLHS encountered dot for bad type: " ++ show (t, l, x)
|
fieldType = lookupFieldType fields x
|
||||||
where
|
|
||||||
(t, l') = convertLHS l
|
|
||||||
Struct p fields [] = t
|
|
||||||
structTf = Struct p fields
|
|
||||||
fieldType = lookupFieldType fields x
|
|
||||||
convertLHS (LHSConcat lhss) =
|
convertLHS (LHSConcat lhss) =
|
||||||
(Implicit Unspecified [], LHSConcat $ map (snd . convertLHS) lhss)
|
(Implicit Unspecified [], LHSConcat $ map (snd . convertLHS) lhss)
|
||||||
|
|
||||||
|
|
@ -330,17 +348,18 @@ convertAsgn structs types (lhs, expr) =
|
||||||
Just t -> (t, Ident x)
|
Just t -> (t, Ident x)
|
||||||
convertSubExpr (Dot e x) =
|
convertSubExpr (Dot e x) =
|
||||||
case subExprType of
|
case subExprType of
|
||||||
Struct _ _ _ ->
|
Struct p fields [] -> undot (Struct p fields) fields
|
||||||
if Map.notMember structTf structs
|
Union p fields [] -> undot (Union p fields) fields
|
||||||
then (fieldType, Dot e' x)
|
|
||||||
else (fieldType, Range e' NonIndexed r)
|
|
||||||
_ -> (Implicit Unspecified [], Dot e' x)
|
_ -> (Implicit Unspecified [], Dot e' x)
|
||||||
where
|
where
|
||||||
(subExprType, e') = convertSubExpr e
|
(subExprType, e') = convertSubExpr e
|
||||||
Struct p fields [] = subExprType
|
undot structTf fields =
|
||||||
structTf = Struct p fields
|
if Map.notMember structTf structs
|
||||||
fieldType = lookupFieldType fields x
|
then (fieldType, Dot e' x)
|
||||||
r = lookupUnstructRange structTf x
|
else (fieldType, Range e' NonIndexed r)
|
||||||
|
where
|
||||||
|
fieldType = lookupFieldType fields x
|
||||||
|
r = lookupUnstructRange structTf x
|
||||||
convertSubExpr (Range eOuter NonIndexed (rOuter @ (hiO, loO))) =
|
convertSubExpr (Range eOuter NonIndexed (rOuter @ (hiO, loO))) =
|
||||||
-- VCS doesn't allow ranges to be cascaded, so we need to combine
|
-- VCS doesn't allow ranges to be cascaded, so we need to combine
|
||||||
-- nested Ranges into a single range. My understanding of the
|
-- nested Ranges into a single range. My understanding of the
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
module Language.SystemVerilog.AST.Type
|
module Language.SystemVerilog.AST.Type
|
||||||
( Identifier
|
( Identifier
|
||||||
|
, Field
|
||||||
, Type (..)
|
, Type (..)
|
||||||
, Signing (..)
|
, Signing (..)
|
||||||
, Packing (..)
|
, Packing (..)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
typedef union packed {
|
||||||
|
logic [4:0] x;
|
||||||
|
logic [4:0] y;
|
||||||
|
} A;
|
||||||
|
|
||||||
|
typedef union packed {
|
||||||
|
logic [4:0] x;
|
||||||
|
logic [0:4] y;
|
||||||
|
} B;
|
||||||
|
|
||||||
|
typedef union packed {
|
||||||
|
logic [4:0] x;
|
||||||
|
logic [1:5] y;
|
||||||
|
} C;
|
||||||
|
|
||||||
|
typedef union packed {
|
||||||
|
logic [4:0] x;
|
||||||
|
struct packed {
|
||||||
|
logic [2:0] a;
|
||||||
|
logic [1:0] b;
|
||||||
|
} y;
|
||||||
|
struct packed {
|
||||||
|
logic [1:0] a;
|
||||||
|
logic [0:2] b;
|
||||||
|
} z;
|
||||||
|
} D;
|
||||||
|
|
||||||
|
module wrap;
|
||||||
|
|
||||||
|
A a;
|
||||||
|
B b;
|
||||||
|
C c;
|
||||||
|
D d;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
|
||||||
|
$monitor($time, " %b %b", a.x, a.y);
|
||||||
|
a.x = 5'b01101; #10;
|
||||||
|
a.y = 5'b11101; #10;
|
||||||
|
|
||||||
|
$monitor($time, " %b %b", b.x, b.y);
|
||||||
|
b.x = 5'b01101; #10;
|
||||||
|
b.y = 5'b11101; #10;
|
||||||
|
|
||||||
|
$monitor($time, " %b %b", c.x, c.y);
|
||||||
|
c.x = 5'b01101; #10;
|
||||||
|
c.y = 5'b11101; #10;
|
||||||
|
|
||||||
|
$monitor($time, " %b %b {%b %b} %b {%b %b}", d.x, d.y, d.y.a, d.y.b,
|
||||||
|
d.z, d.z.a, d.z.b);
|
||||||
|
d.x = 5'b01101; #10;
|
||||||
|
d.y = '{ a: 3'b110, b: 2'b01 }; #10;
|
||||||
|
d.z = '{ b: 3'b110, a: 2'b01 }; #10;
|
||||||
|
d.y.a = 3'b010; #10;
|
||||||
|
d.y.b = 2'b10; #10;
|
||||||
|
d.z.a = 2'b11; #10;
|
||||||
|
d.z.b = 3'b101; #10;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
module wrap;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
|
||||||
|
// This was generated by running the original through VCS.
|
||||||
|
|
||||||
|
$display(" 0 01101 01101");
|
||||||
|
$display(" 10 11101 11101");
|
||||||
|
|
||||||
|
$display(" 20 01101 01101");
|
||||||
|
$display(" 30 11101 11101");
|
||||||
|
|
||||||
|
$display(" 40 01101 01101");
|
||||||
|
$display(" 50 11101 11101");
|
||||||
|
|
||||||
|
$display(" 60 01101 01101 {011 01} 01101 {01 101}");
|
||||||
|
$display(" 70 11001 11001 {110 01} 11001 {11 001}");
|
||||||
|
$display(" 80 01110 01110 {011 10} 01110 {01 110}");
|
||||||
|
$display(" 90 01010 01010 {010 10} 01010 {01 010}");
|
||||||
|
$display(" 110 11010 11010 {110 10} 11010 {11 010}");
|
||||||
|
$display(" 120 11101 11101 {111 01} 11101 {11 101}");
|
||||||
|
|
||||||
|
#130;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
module top;
|
||||||
|
wrap wrap();
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue