Commit de581eca by Zachary Snow

initial support for types in struct patterns

parent 3979d294
...@@ -8,8 +8,7 @@ module Convert.Struct (convert) where ...@@ -8,8 +8,7 @@ module Convert.Struct (convert) where
import Control.Monad.State import Control.Monad.State
import Control.Monad.Writer import Control.Monad.Writer
import Data.List (elemIndex, sortOn) import Data.List (partition)
import Data.Maybe (fromJust, isJust)
import Data.Tuple (swap) import Data.Tuple (swap)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import qualified Data.Set as Set import qualified Data.Set as Set
...@@ -299,67 +298,86 @@ convertAsgn structs types (lhs, expr) = ...@@ -299,67 +298,86 @@ convertAsgn structs types (lhs, expr) =
convertLHS (LHSStream o e lhss) = convertLHS (LHSStream o e lhss) =
(Implicit Unspecified [], LHSStream o e $ map (snd . convertLHS) lhss) (Implicit Unspecified [], LHSStream o e $ map (snd . convertLHS) lhss)
defaultKey = Just "default" specialTag = ':'
defaultKey = specialTag : "default"
-- try expression conversion by looking at the *outermost* type first -- try expression conversion by looking at the *outermost* type first
convertExpr :: Type -> Expr -> Expr convertExpr :: Type -> Expr -> Expr
-- TODO: This is really a conversion for using default patterns to -- TODO: This is really a conversion for using default patterns to
-- populate arrays. Maybe this should be somewhere else? -- populate arrays. Maybe this should be somewhere else?
convertExpr (IntegerVector t sg (r:rs)) (Pattern [(Just "default", e)]) = convertExpr (IntegerVector t sg (r:rs)) (Pattern [(":default", e)]) =
Repeat (rangeSize r) [e'] Repeat (rangeSize r) [e']
where e' = convertExpr (IntegerVector t sg rs) e where e' = convertExpr (IntegerVector t sg rs) e
convertExpr (Struct (Packed sg) fields (_:rs)) (Concat exprs) = convertExpr (Struct (Packed sg) fields (_:rs)) (Concat exprs) =
Concat $ map (convertExpr (Struct (Packed sg) fields rs)) exprs Concat $ map (convertExpr (Struct (Packed sg) fields rs)) exprs
convertExpr (Struct (Packed sg) fields (_:rs)) (Bit e _) = convertExpr (Struct (Packed sg) fields (_:rs)) (Bit e _) =
convertExpr (Struct (Packed sg) fields rs) e convertExpr (Struct (Packed sg) fields rs) e
convertExpr (Struct (Packed sg) fields rs) (Pattern [(Just "default", e)]) =
if Map.notMember structTf structs then
Pattern [(defaultKey, e)]
else if null rs then
expanded
else
Repeat (dimensionsSize rs) [expanded]
where
structTf = Struct (Packed sg) fields
expanded = convertExpr (structTf []) $ Pattern $
take (length fields) (repeat (Nothing, e))
convertExpr (Struct (Packed sg) fields []) (Pattern itemsOrig) = convertExpr (Struct (Packed sg) fields []) (Pattern itemsOrig) =
if length items /= length fields then if extraNames /= Set.empty then
error $ "struct pattern " ++ show items ++ error $ "pattern " ++ show (Pattern itemsOrig) ++
" doesn't have the same # of items as " ++ show structTf " has extra named fields: " ++
else if itemsFieldNames /= fieldNames then show (Set.toList extraNames) ++ " that are not in " ++
error $ "struct pattern " ++ show items ++ " has fields " ++ show structTf
show itemsFieldNames ++ ", but struct type has fields " ++ else if Map.member structTf structs then
show fieldNames Call Nothing
else if Map.notMember structTf structs then (packerFnName structTf)
Pattern items (Args (map (Just . snd) items) [])
else else
Call Nothing fnName $ Args (map (Just . snd) items) [] Pattern items
where where
subMap = \(Just ident, subExpr) ->
(Just ident, convertExpr (lookupFieldType fields ident) subExpr)
structTf = Struct (Packed sg) fields structTf = Struct (Packed sg) fields
fieldNames = map snd fields
fieldTypeMap = Map.fromList $ map swap fields
itemsNamed = itemsNamed =
-- patterns either use positions based or name/type/default
if all ((/= "") . fst) itemsOrig then
itemsOrig
-- position-based patterns should cover every field
else if length itemsOrig /= length fields then
error $ "struct pattern " ++ show items ++
" doesn't have the same # of items as " ++
show structTf
-- if the pattern does not use identifiers, use the -- if the pattern does not use identifiers, use the
-- identifiers from the struct type definition in order -- identifiers from the struct type definition in order
if not (all (isJust . fst) itemsOrig) then
zip (map (Just. snd) fields) (map snd itemsOrig)
-- if the pattern has a default value, use that for any
-- missing fields
else if any ((== defaultKey) . fst) itemsOrig then
let origValueMap = Map.fromList itemsOrig
origValues = Map.delete defaultKey origValueMap
defaultValue = origValueMap Map.! defaultKey
defaultValues = Map.fromList $
zip (map Just fieldNames) (repeat defaultValue)
in Map.toList $ Map.union origValues defaultValues
else else
itemsOrig zip fieldNames (map snd itemsOrig)
items = sortOn itemPosition $ map subMap itemsNamed (specialItems, namedItems) =
fieldNames = map snd fields partition ((== specialTag) . head . fst) itemsNamed
itemsFieldNames = map (fromJust . fst) items namedItemMap = Map.fromList namedItems
itemPosition = \(Just x, _) -> fromJust $ elemIndex x fieldNames specialItemMap = Map.fromList specialItems
fnName = packerFnName structTf
extraNames = Set.difference
(Set.fromList $ map fst namedItems)
(Map.keysSet fieldTypeMap)
items = zip fieldNames $ map resolveField fieldNames
resolveField :: Identifier -> Expr
resolveField fieldName =
convertExpr fieldType $
-- look up by name
if Map.member fieldName namedItemMap then
namedItemMap Map.! fieldName
-- look up by field type
else if Map.member fieldTypeName specialItemMap then
specialItemMap Map.! fieldTypeName
-- fall back on the default value
else if Map.member defaultKey specialItemMap then
specialItemMap Map.! defaultKey
else
error $ "couldn't find field " ++ fieldName ++
" from struct definition " ++ show structTf ++
" in struct pattern " ++ show itemsOrig
where
fieldType = fieldTypeMap Map.! fieldName
fieldTypeName =
specialTag : (show $ fst $ typeRanges fieldType)
convertExpr (Struct (Packed sg) fields (r : rs)) subExpr =
Repeat (rangeSize r) [subExpr']
where
structTf = Struct (Packed sg) fields
subExpr' = convertExpr (structTf rs) subExpr
convertExpr _ other = other convertExpr _ other = other
-- try expression conversion by looking at the *innermost* type first -- try expression conversion by looking at the *innermost* type first
...@@ -470,7 +488,7 @@ convertAsgn structs types (lhs, expr) = ...@@ -470,7 +488,7 @@ convertAsgn structs types (lhs, expr) =
tore' = convertTypeOrExpr tore tore' = convertTypeOrExpr tore
e' = snd $ convertSubExpr e e' = snd $ convertSubExpr e
convertSubExpr (Pattern items) = convertSubExpr (Pattern items) =
if all (== Nothing) $ map fst items' if all (== "") $ map fst items'
then (Implicit Unspecified [], Concat $ map snd items') then (Implicit Unspecified [], Concat $ map snd items')
else (Implicit Unspecified [], Pattern items') else (Implicit Unspecified [], Pattern items')
where where
......
...@@ -54,7 +54,7 @@ data Expr ...@@ -54,7 +54,7 @@ data Expr
| DimsFn DimsFn TypeOrExpr | DimsFn DimsFn TypeOrExpr
| DimFn DimFn TypeOrExpr Expr | DimFn DimFn TypeOrExpr Expr
| Dot Expr Identifier | Dot Expr Identifier
| Pattern [(Maybe Identifier, Expr)] | Pattern [(Identifier, Expr)]
| MinTypMax Expr Expr Expr | MinTypMax Expr Expr Expr
| Nil | Nil
deriving (Eq, Ord) deriving (Eq, Ord)
...@@ -82,9 +82,10 @@ instance Show Expr where ...@@ -82,9 +82,10 @@ instance Show Expr where
show (Pattern l ) = show (Pattern l ) =
printf "'{\n%s\n}" (indent $ intercalate ",\n" $ map showPatternItem l) printf "'{\n%s\n}" (indent $ intercalate ",\n" $ map showPatternItem l)
where where
showPatternItem :: (Maybe Identifier, Expr) -> String showPatternItem :: (Identifier, Expr) -> String
showPatternItem (Nothing, e) = show e showPatternItem ("" , e) = show e
showPatternItem (Just n , e) = printf "%s: %s" n (show e) showPatternItem (':' : n, e) = showPatternItem (n, e)
showPatternItem (n , e) = printf "%s: %s" n (show e)
show (MinTypMax a b c) = printf "(%s : %s : %s)" (show a) (show b) (show c) show (MinTypMax a b c) = printf "(%s : %s : %s)" (show a) (show b) (show c)
data Args data Args
......
...@@ -1162,15 +1162,16 @@ Expr :: { Expr } ...@@ -1162,15 +1162,16 @@ Expr :: { Expr }
| "~^" Expr %prec REDUCE_OP { UniOp RedXnor $2 } | "~^" Expr %prec REDUCE_OP { UniOp RedXnor $2 }
| "^~" Expr %prec REDUCE_OP { UniOp RedXnor $2 } | "^~" Expr %prec REDUCE_OP { UniOp RedXnor $2 }
PatternItems :: { [(Maybe Identifier, Expr)] } PatternItems :: { [(Identifier, Expr)] }
: PatternNamedItems { map (\(x,e) -> (Just x, e)) $1 } : PatternNamedItems { $1 }
| PatternUnnamedItems { zip (repeat Nothing) $1 } | PatternUnnamedItems { zip (repeat "") $1 }
PatternNamedItems :: { [(Identifier, Expr)] } PatternNamedItems :: { [(Identifier, Expr)] }
: PatternNamedItem { [$1] } : PatternNamedItem { [$1] }
| PatternNamedItems "," PatternNamedItem { $1 ++ [$3] } | PatternNamedItems "," PatternNamedItem { $1 ++ [$3] }
PatternNamedItem :: { (Identifier, Expr) } PatternNamedItem :: { (Identifier, Expr) }
: Identifier ":" Expr { ($1, $3) } : Identifier ":" Expr { ($1 , $3) }
| "default" ":" Expr { (tokenString $1, $3) } | PartialType ":" Expr { (':' : show $1 , $3) }
| "default" ":" Expr { (':' : "default", $3) }
PatternUnnamedItems :: { [Expr] } PatternUnnamedItems :: { [Expr] }
: PatternUnnamedItem { [$1] } : PatternUnnamedItem { [$1] }
| PatternUnnamedItems "," PatternUnnamedItem { $1 ++ [$3] } | PatternUnnamedItems "," PatternUnnamedItem { $1 ++ [$3] }
......
module test;
typedef struct packed {
int w, x;
byte y;
logic z;
} struct_a;
struct_a a;
initial begin
$monitor("%2d: %b %b %b %b %b", $time, a, a.w, a.x, a.y, a.z);
#1 a.w = 0;
#1 a.x = 0;
#1 a.y = 0;
#1 a.z = 0;
#1 a = '{default: 1};
#1 a = '{default: 2};
#1 a = '{default: 3};
#1 a = '{default: 0};
#1 a = '{default: -1};
#1 a = '{default: -2};
#1 a = '{int: 0, default: 1};
#1 a = '{byte: 0, default: 1};
#1 a = '{logic: 0, default: 1};
#1 a = '{logic: 1, int: 2, byte: 3};
#1 a = '{logic: 1, int: 2, byte: 3, default: -1};
#1 a = '{int: 3, byte: 2, default: 0};
#1 a = '{w: 8, int: 0, default: 1};
#1 a = '{w: 8, byte: 0, default: 1};
#1 a = '{w: 8, logic: 0, default: 1};
#1 a = '{w: 8, logic: 1, int: 2, byte: 3};
#1 a = '{w: 8, logic: 1, int: 2, byte: 3, default: -1};
#1 a = '{w: 8, int: 3, byte: 2, default: 0};
end
endmodule
module top; endmodule
module test;
reg [31:0] a_w, a_x;
reg [7:0] a_y;
reg a_z;
reg [72:0] a;
always @* a = {a_w, a_x, a_y, a_z};
initial begin
$monitor("%2d: %b %b %b %b %b", $time, a, a_w, a_x, a_y, a_z);
#1 a_w = 0;
#1 a_x = 0;
#1 a_y = 0;
#1 a_z = 0;
#1 begin
a_w = 1;
a_x = 1;
a_y = 1;
a_z = 1;
end
#1 begin
a_w = 2;
a_x = 2;
a_y = 2;
a_z = 2;
end
#1 begin
a_w = 3;
a_x = 3;
a_y = 3;
a_z = 3;
end
#1 begin
a_w = 0;
a_x = 0;
a_y = 0;
a_z = 0;
end
#1 begin
a_w = -1;
a_x = -1;
a_y = -1;
a_z = -1;
end
#1 begin
a_w = -2;
a_x = -2;
a_y = -2;
a_z = -2;
end
#1 begin
a_w = 0;
a_x = 0;
a_y = 1;
a_z = 1;
end
#1 begin
a_w = 1;
a_x = 1;
a_y = 0;
a_z = 1;
end
#1 begin
a_w = 1;
a_x = 1;
a_y = 1;
a_z = 0;
end
#1 begin
a_w = 2;
a_x = 2;
a_y = 3;
a_z = 1;
end
#1;
#1 begin
a_w = 3;
a_x = 3;
a_y = 2;
a_z = 0;
end
#1 begin
a_w = 8;
a_x = 0;
a_y = 1;
a_z = 1;
end
#1 begin
a_w = 8;
a_x = 1;
a_y = 0;
a_z = 1;
end
#1 begin
a_w = 8;
a_x = 1;
a_y = 1;
a_z = 0;
end
#1 begin
a_w = 8;
a_x = 2;
a_y = 3;
a_z = 1;
end
#1;
#1 begin
a_w = 8;
a_x = 3;
a_y = 2;
a_z = 0;
end
end
endmodule
module top; 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