From e6263d6caa63a9398f1a8bb148c9843aace916a0 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 26 Apr 2021 18:02:41 -0400 Subject: [PATCH] support function calls within type parameters --- src/Convert/ParamType.hs | 42 ++++++++++++++++++++++++---------------- test/basic/paramtype.sv | 11 +++++++++++ test/basic/paramtype.v | 6 ++++++ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/Convert/ParamType.hs b/src/Convert/ParamType.hs index e03256d..1be75f4 100644 --- a/src/Convert/ParamType.hs +++ b/src/Convert/ParamType.hs @@ -289,19 +289,22 @@ typeIsUnresolved = collectUnresolvedExprM Dot {} = tell $ Any True collectUnresolvedExprM _ = return () -prepareTypeIdents :: Identifier -> Type -> (Type, IdentSet) -prepareTypeIdents prefix = +prepareTypeExprs :: Identifier -> Identifier -> Type -> (Type, (IdentSet, [Decl])) +prepareTypeExprs instanceName paramName = runWriter . traverseNestedTypesM - (traverseTypeExprsM $ traverseNestedExprsM prepareExprIdents) + (traverseTypeExprsM $ traverseNestedExprsM prepareExpr) where - prepareExprIdents :: Expr -> Writer IdentSet Expr - prepareExprIdents (e @ (Ident "$unsigned")) = return e - prepareExprIdents (e @ (Ident "$signed" )) = return e - prepareExprIdents (e @ (Ident "$clog2" )) = return e - prepareExprIdents (Ident x) = do - tell $ Set.singleton x - return $ Ident $ prefix ++ '_' : x - prepareExprIdents other = return other + prepareExpr :: Expr -> Writer (IdentSet, [Decl]) Expr + prepareExpr (e @ Call{}) = do + tell (Set.empty, [decl]) + prepareExpr $ Ident x + where + decl = Param Localparam (TypeOf e) x e + x = instanceName ++ "_sv2v_pfunc_" ++ shortHash e + prepareExpr (Ident x) = do + tell (Set.singleton x, []) + return $ Ident $ paramName ++ '_' : x + prepareExpr other = return other addedParamName :: Identifier -> Identifier -> Identifier addedParamName paramName var = paramName ++ '_' : var @@ -328,7 +331,9 @@ convertModuleItemM info (orig @ (Instance m bindings x r p)) = else do tell $ Set.singleton (m, resolvedTypes) let m' = moduleInstanceName m resolvedTypes - return $ Instance m' (additionalBindings ++ bindings') x r p + return $ Generate $ map GenModuleItem $ + map (MIPackageItem . Decl) addedDecls ++ + [Instance m' (additionalBindings ++ bindings') x r p] where (paramNames, maybeTypeMap) = info Map.! m -- attach names to unnamed parameters @@ -341,20 +346,23 @@ convertModuleItemM info (orig @ (Instance m bindings x r p)) = else bindings -- determine the types corresponding to each type parameter bindingsMap = Map.fromList bindingsNamed - resolvedTypes = Map.mapWithKey resolveType maybeTypeMap - resolveType :: Identifier -> Maybe Type -> (Type, IdentSet) + resolvedTypesWithDecls = Map.mapWithKey resolveType maybeTypeMap + resolvedTypes = Map.map (\(a, (b, _)) -> (a, b)) resolvedTypesWithDecls + addedDecls = concatMap (snd . snd . snd) $ + Map.toList resolvedTypesWithDecls + resolveType :: Identifier -> Maybe Type -> (Type, (IdentSet, [Decl])) resolveType paramName defaultType = case (Map.lookup paramName bindingsMap, defaultType) of - (Nothing, Just t) -> (t, Set.empty) + (Nothing, Just t) -> (t, (Set.empty, [])) (Nothing, Nothing) -> error $ "instantiation " ++ show orig ++ " is missing a type parameter: " ++ paramName - (Just (Left t), _) -> prepareTypeIdents paramName t + (Just (Left t), _) -> prepareTypeExprs x paramName t (Just (Right e), _) -> -- Some types are parsed as expressions because of the -- ambiguities of defined type names. case exprToType e of - Just t -> prepareTypeIdents paramName t + Just t -> prepareTypeExprs x paramName t Nothing -> error $ "instantiation " ++ show orig ++ " has expr " ++ show e diff --git a/test/basic/paramtype.sv b/test/basic/paramtype.sv index 4f183b3..892c319 100644 --- a/test/basic/paramtype.sv +++ b/test/basic/paramtype.sv @@ -109,9 +109,20 @@ module f_2; o_nodef #(.T(logic [1:0]), .U(logic), .b(1), .a(0)) x(); endmodule module f_3; o_nodef #(0, logic [1:0], logic [2:0], 1) x(); endmodule module f_4; o_nodef #(.T(logic [1:0]), .U(logic), .b(0), .a(1)) x(); endmodule +function automatic integer square; + input integer inp; + return inp ** 2; +endfunction + +localparam type SomeT = logic [square(integer'(3)):0] ; +localparam type OtherT = enum SomeT { A, B, C, D }; + module p_1; p #(logic [1:0], logic [2:0]) x(); endmodule module p_2; p x(); endmodule module p_3; localparam W = 2; p #(logic [W:0], logic [W:0]) x(); endmodule module p_4; parameter W = 2; p #(logic [$clog2(W):0], logic [$clog2(W):0]) x(); endmodule module p_5; parameter W = 2; p #(logic [$unsigned(W):0], logic [$unsigned(W):0]) x(); endmodule module p_6; parameter W = 2; p #(logic [$signed(W):0], logic [$signed(W):0]) x(); endmodule +module p_7; parameter W = 2; p #(logic [square(W):0], logic [square(W):0]) x(); endmodule +module p_8; p #(OtherT) x(); endmodule +module p_9; p #(SomeT, OtherT) x(); endmodule diff --git a/test/basic/paramtype.v b/test/basic/paramtype.v index 7035aeb..14f138c 100644 --- a/test/basic/paramtype.v +++ b/test/basic/paramtype.v @@ -48,5 +48,11 @@ module top; $display("p 001 00000000000000000000000000000010 3"); $display("p 000 00000000000000000000000000000001 3"); $display("p 001 00000000000000000000000000000010 3"); + $display("p 00000 00000000000000000000000000000001 5"); + $display("p 00001 00000000000000000000000000000010 5"); + $display("p 0000000000 00000000000000000000000000000001 10"); + $display("p 1 00000000000000000000000000000010 1"); + $display("p 0000000000 00000000000000000000000000000001 10"); + $display("p 0000000001 00000000000000000000000000000010 10"); end endmodule