Commit 81f5fb50 by Zachary Snow

added conversion for packed unions

parent 8a67a911
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for `struct packed`
- Conversion for `struct packed` and `union packed`
-}
module Convert.Struct (convert) where
......@@ -70,10 +70,19 @@ convertDescription other = other
-- write down unstructured versions of packed struct types
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
then tell $ Map.singleton
(Struct (Packed sg) fields)
(constructor (Packed sg) fields)
(unstructType, unstructFields)
else return ()
where
......@@ -90,8 +99,14 @@ collectStructM (Struct (Packed sg) fields _) = do
-- layout the fields into the unstructured type; note that `scanr` is
-- used here because SystemVerilog structs are laid out backwards
fieldLos = map simplify $ tail $ scanr (BinOp Add) (Number "0") fieldSizes
fieldHis = map simplify $ init $ scanr (BinOp Add) (Number "-1") fieldSizes
fieldLos =
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
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
-- 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)
unstructType = IntegerVector TLogic sg [packedRange]
......@@ -114,7 +132,6 @@ collectStructM (Struct (Packed sg) fields _) = do
isIntVec _ = False
canUnstructure = all isIntVec fieldTypes
collectStructM _ = return ()
-- convert a struct type to its unstructured equivalent
convertType :: Structs -> Type -> Type
......@@ -252,7 +269,13 @@ convertAsgn structs types (lhs, expr) =
convertLHS (LHSDot l x ) =
case t of
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)
Just (structT, m) -> (tf [tr], LHSRange l' NonIndexed r)
where
......@@ -261,13 +284,8 @@ convertAsgn structs types (lhs, expr) =
hi' = BinOp Add base $ BinOp Sub hi lo
lo' = base
tr = (simplify hi', simplify lo')
Implicit sg _ -> (Implicit sg [], LHSDot l' x)
_ -> error $ "convertLHS encountered dot for bad type: " ++ show (t, l, x)
where
(t, l') = convertLHS l
Struct p fields [] = t
structTf = Struct p fields
fieldType = lookupFieldType fields x
where
fieldType = lookupFieldType fields x
convertLHS (LHSConcat lhss) =
(Implicit Unspecified [], LHSConcat $ map (snd . convertLHS) lhss)
......@@ -330,17 +348,18 @@ convertAsgn structs types (lhs, expr) =
Just t -> (t, Ident x)
convertSubExpr (Dot e x) =
case subExprType of
Struct _ _ _ ->
if Map.notMember structTf structs
then (fieldType, Dot e' x)
else (fieldType, Range e' NonIndexed r)
Struct p fields [] -> undot (Struct p fields) fields
Union p fields [] -> undot (Union p fields) fields
_ -> (Implicit Unspecified [], Dot e' x)
where
(subExprType, e') = convertSubExpr e
Struct p fields [] = subExprType
structTf = Struct p fields
fieldType = lookupFieldType fields x
r = lookupUnstructRange structTf x
undot structTf fields =
if Map.notMember structTf structs
then (fieldType, Dot e' x)
else (fieldType, Range e' NonIndexed r)
where
fieldType = lookupFieldType fields x
r = lookupUnstructRange structTf x
convertSubExpr (Range eOuter NonIndexed (rOuter @ (hiO, loO))) =
-- VCS doesn't allow ranges to be cascaded, so we need to combine
-- nested Ranges into a single range. My understanding of the
......
......@@ -8,6 +8,7 @@
module Language.SystemVerilog.AST.Type
( Identifier
, Field
, Type (..)
, Signing (..)
, Packing (..)
......
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
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
module top;
wrap wrap();
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