From 4cf65dd4e2f1706d8905b4a4e99c00242b9b82c5 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Sun, 9 Feb 2020 17:05:58 -0500 Subject: [PATCH] support for struct type parameters - param type conversion properly supports deferred param type resolution - fixed struct conversion incomplete Subroutine traversal - struct conversion excludes param types from conversion - parameters are defaulted to have integer type --- src/Convert/ParamType.hs | 4 +++- src/Convert/Struct.hs | 9 ++++++--- src/Convert/Traverse.hs | 28 +++++++++++++++++++++++----- src/Convert/TypeOf.hs | 5 ++++- test/basic/struct_param.sv | 30 ++++++++++++++++++++++++++++++ test/basic/struct_param.v | 28 ++++++++++++++++++++++++++++ 6 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 test/basic/struct_param.sv create mode 100644 test/basic/struct_param.v diff --git a/src/Convert/ParamType.hs b/src/Convert/ParamType.hs index c265c20..0542081 100644 --- a/src/Convert/ParamType.hs +++ b/src/Convert/ParamType.hs @@ -220,6 +220,8 @@ isSimpleType (IntegerVector _ _ _) = True isSimpleType (IntegerAtom _ _ ) = True isSimpleType (NonInteger _ ) = True isSimpleType (Net _ _ _) = True +isSimpleType (Struct _ fields _) = all (isSimpleType . fst) fields +isSimpleType (Union _ fields _) = all (isSimpleType . fst) fields isSimpleType _ = False -- attempt to rewrite instantiations with type parameters @@ -235,7 +237,7 @@ convertModuleItemM info (orig @ (Instance m bindings x r p)) = else if any (not . isSimpleType) resolvedTypes then do let defaults = Map.map Left resolvedTypes let bindingsDefaulted = Map.toList $ Map.union bindingsMap defaults - if isDefaultName m + if isDefaultName m || bindingsDefaulted /= Map.toList bindingsMap then return $ Instance m bindingsNamed x r p else return $ Instance (moduleDefaultName m) bindingsDefaulted x r p else do diff --git a/src/Convert/Struct.hs b/src/Convert/Struct.hs index 275339c..883f3cd 100644 --- a/src/Convert/Struct.hs +++ b/src/Convert/Struct.hs @@ -27,7 +27,7 @@ convert = map $ traverseDescriptions convertDescription convertDescription :: Description -> Description convertDescription (description @ Part{}) = - traverseModuleItems (traverseTypes $ convertType structs) $ + traverseModuleItems (traverseTypes' ExcludeParamTypes $ convertType structs) $ Part attrs extern kw lifetime name ports (items ++ funcs) where description' @ (Part attrs extern kw lifetime name ports items) = @@ -53,8 +53,11 @@ convertDescription (description @ Part{}) = traverseStmtM :: Stmt -> State Types Stmt traverseStmtM (Subroutine expr args) = do stateTypes <- get - return $ Subroutine expr $ - convertCall structs stateTypes expr args + let stmt' = Subroutine expr $ convertCall + structs stateTypes expr args + traverseStmtLHSsM traverseLHSM stmt' >>= + traverseStmtExprsM traverseExprM >>= + traverseStmtAsgnsM traverseAsgnM traverseStmtM stmt = traverseStmtLHSsM traverseLHSM stmt >>= traverseStmtExprsM traverseExprM >>= diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index 40c675f..0010fe9 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -9,6 +9,7 @@ module Convert.Traverse , Mapper , CollectorM , TFStrategy (..) +, TypeStrategy (..) , unmonad , collectify , traverseDescriptionsM @@ -53,6 +54,9 @@ module Convert.Traverse , traverseExprTypesM , traverseExprTypes , collectExprTypesM +, traverseTypesM' +, traverseTypes' +, collectTypesM' , traverseTypesM , traverseTypes , collectTypesM @@ -101,6 +105,11 @@ data TFStrategy | ExcludeTFs deriving Eq +data TypeStrategy + = IncludeParamTypes + | ExcludeParamTypes + deriving Eq + unmonad :: (MapperM (State ()) a -> MapperM (State ()) b) -> Mapper a -> Mapper b unmonad traverser mapper thing = evalState (traverser (return . mapper) thing) () @@ -910,8 +919,8 @@ traverseExprTypes = unmonad traverseExprTypesM collectExprTypesM :: Monad m => CollectorM m Type -> CollectorM m Expr collectExprTypesM = collectify traverseExprTypesM -traverseTypesM :: Monad m => MapperM m Type -> MapperM m ModuleItem -traverseTypesM mapper item = +traverseTypesM' :: Monad m => TypeStrategy -> MapperM m Type -> MapperM m ModuleItem +traverseTypesM' strategy mapper item = miMapper item >>= traverseDeclsM declMapper >>= traverseExprsM (traverseNestedExprsM exprMapper) @@ -938,14 +947,23 @@ traverseTypesM mapper item = return $ Instance m params' x r p where mapParam (i, Left t) = - fullMapper t >>= \t' -> return (i, Left t') + if strategy == IncludeParamTypes + then fullMapper t >>= \t' -> return (i, Left t') + else return (i, Left t) mapParam (i, Right e) = return $ (i, Right e) miMapper other = return other +traverseTypes' :: TypeStrategy -> Mapper Type -> Mapper ModuleItem +traverseTypes' strategy = unmonad $ traverseTypesM' strategy +collectTypesM' :: Monad m => TypeStrategy -> CollectorM m Type -> CollectorM m ModuleItem +collectTypesM' strategy = collectify $ traverseTypesM' strategy + +traverseTypesM :: Monad m => MapperM m Type -> MapperM m ModuleItem +traverseTypesM = traverseTypesM' IncludeParamTypes traverseTypes :: Mapper Type -> Mapper ModuleItem -traverseTypes = unmonad traverseTypesM +traverseTypes = traverseTypes' IncludeParamTypes collectTypesM :: Monad m => CollectorM m Type -> CollectorM m ModuleItem -collectTypesM = collectify traverseTypesM +collectTypesM = collectTypesM' IncludeParamTypes traverseGenItemsM :: Monad m => MapperM m GenItem -> MapperM m ModuleItem traverseGenItemsM mapper = moduleItemMapper diff --git a/src/Convert/TypeOf.hs b/src/Convert/TypeOf.hs index 5743480..8f1dee3 100644 --- a/src/Convert/TypeOf.hs +++ b/src/Convert/TypeOf.hs @@ -51,7 +51,10 @@ traverseDeclM decl = do UnpackedType t'' a' -> Variable d t'' ident a' me _ -> Variable d t' ident [] me Param _ t ident _ -> do - modify $ Map.insert ident t + let t' = if t == Implicit Unspecified [] + then IntegerAtom TInteger Unspecified + else t + modify $ Map.insert ident t' return decl' ParamType{} -> return decl' CommentDecl{} -> return decl' diff --git a/test/basic/struct_param.sv b/test/basic/struct_param.sv new file mode 100644 index 0000000..ff55a2b --- /dev/null +++ b/test/basic/struct_param.sv @@ -0,0 +1,30 @@ +// TODO Add support for parameters without default values. +module Module #(parameter type T, parameter N = 1); + T t; + type(t.a) x; + type(t.b) y; + initial begin + $display("$bits(T)=", $bits(T)); + $display("$bits(t)=", $bits(t)); + $display("$bits(t.a)=", $bits(t.a)); + $display("$bits(t.b)=", $bits(t.b)); + $display("$bits(x)=", $bits(x)); + $display("$bits(y)=", $bits(y)); + $display("$bits(N)=", $bits(N)); + $display("N=", N); + end +endmodule +module top; + typedef struct packed { + logic a; + logic [2] b; + } Struct1; + typedef struct packed { + logic [5] a; + Struct1 b; + logic [2] c; + logic d; + } Struct2; + Module #(Struct1, $bits(Struct1)) m1(); + Module #(Struct2, $bits(Struct2)) m2(); +endmodule diff --git a/test/basic/struct_param.v b/test/basic/struct_param.v new file mode 100644 index 0000000..f4fb879 --- /dev/null +++ b/test/basic/struct_param.v @@ -0,0 +1,28 @@ +module Module1 #(parameter N = 1); + initial begin + $display("$bits(T)=", 3); + $display("$bits(t)=", 3); + $display("$bits(t.a)=", 1); + $display("$bits(t.b)=", 2); + $display("$bits(x)=", 1); + $display("$bits(y)=", 2); + $display("$bits(N)=", 32); + $display("N=", N); + end +endmodule +module Module2 #(parameter N = 1); + initial begin + $display("$bits(T)=", 11); + $display("$bits(t)=", 11); + $display("$bits(t.a)=", 5); + $display("$bits(t.b)=", 3); + $display("$bits(x)=", 5); + $display("$bits(y)=", 3); + $display("$bits(N)=", 32); + $display("N=", N); + end +endmodule +module top; + Module1 #(3) m1(); + Module2 #(11) m2(); +endmodule