From 50a6966a4f470eff66b908e0bf498d911287a978 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Sun, 9 Aug 2020 10:31:04 -0600 Subject: [PATCH] fix three typeof conversion issues - type of strings are left implicit - type of implicitly-typed params uses the type of the default value - prevent exponential blowup for large ternary expressions --- src/Convert/TypeOf.hs | 42 +++++++++++++-------- test/basic/large_mux.sv | 10 +++++ test/basic/large_mux.v | 10 +++++ test/basic/large_mux.vh | 81 +++++++++++++++++++++++++++++++++++++++++ test/basic/string.sv | 6 +++ test/basic/string.v | 5 +++ test/basic/typeof.sv | 11 ++++++ test/basic/typeof.v | 13 +++++++ 8 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 test/basic/large_mux.sv create mode 100644 test/basic/large_mux.v create mode 100644 test/basic/large_mux.vh create mode 100644 test/basic/string.sv create mode 100644 test/basic/string.v diff --git a/src/Convert/TypeOf.hs b/src/Convert/TypeOf.hs index a60ae05..88f707e 100644 --- a/src/Convert/TypeOf.hs +++ b/src/Convert/TypeOf.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE PatternSynonyms #-} {- sv2v - Author: Zachary Snow - @@ -9,6 +10,7 @@ module Convert.TypeOf (convert) where import Data.Tuple (swap) import qualified Data.Map.Strict as Map +import Convert.ExprUtils (simplify) import Convert.Scoper import Convert.Traverse import Language.SystemVerilog.AST @@ -17,21 +19,28 @@ convert :: [AST] -> [AST] convert = map $ traverseDescriptions $ partScoper traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM +pattern UnknownType :: Type +pattern UnknownType = Implicit Unspecified [] + traverseDeclM :: Decl -> Scoper Type Decl traverseDeclM decl = do item <- traverseModuleItemM (MIPackageItem $ Decl decl) let MIPackageItem (Decl decl') = item case decl' of + Variable Local UnknownType ident [] Nil -> do + -- functions with no return type implicitly return a single bit + insertElem ident $ IntegerVector TLogic Unspecified [] + return decl' Variable d t ident a e -> do let t' = injectRanges t a insertElem ident t' return $ case t' of UnpackedType t'' a' -> Variable d t'' ident a' e _ -> Variable d t' ident [] e - Param _ t ident _ -> do - let t' = if t == Implicit Unspecified [] - then IntegerAtom TInteger Unspecified - else t + Param _ t ident e -> do + t' <- if t == UnknownType + then typeof e + else return t insertElem ident t' return decl' ParamType{} -> return decl' @@ -63,9 +72,6 @@ lookupTypeOf expr = do details <- lookupElemM expr case details of Nothing -> return $ TypeOf expr - -- functions with no return type implicitly return a single bit - Just (_, _, Implicit Unspecified []) -> - return $ IntegerVector TLogic Unspecified [] Just (_, replacements, typ) -> return $ if Map.null replacements then typ @@ -144,24 +150,30 @@ typeof (Mux _ a b) = return $ largerSizeType a b typeof (Concat exprs) = return $ typeOfSize $ concatSize exprs typeof (Repeat reps exprs) = return $ typeOfSize size where size = BinOp Mul reps (concatSize exprs) +typeof String{} = return UnknownType typeof other = lookupTypeOf other -- produces a type large enough to hold either expression largerSizeType :: Expr -> Expr -> Type -largerSizeType a b = - typeOfSize larger - where - sizeof = DimsFn FnBits . Right - cond = BinOp Ge (sizeof a) (sizeof b) - larger = Mux cond (sizeof a) (sizeof b) +largerSizeType a b = typeOfSize $ largerSizeOf a b -- returns the total size of concatenated list of expressions concatSize :: [Expr] -> Expr concatSize exprs = foldl (BinOp Add) (RawNum 0) $ map sizeof exprs - where - sizeof = DimsFn FnBits . Right + +-- returns the size of an expression, with the short-circuiting +sizeof :: Expr -> Expr +sizeof (Number n) = RawNum $ numberBitLength n +sizeof (Mux _ a b) = largerSizeOf a b +sizeof expr = DimsFn FnBits $ Left $ TypeOf expr + +-- returns the maximum size of the two given expressions +largerSizeOf :: Expr -> Expr -> Expr +largerSizeOf a b = + simplify $ Mux cond (sizeof a) (sizeof b) + where cond = BinOp Ge (sizeof a) (sizeof b) -- produces a generic type of the given size typeOfSize :: Expr -> Type diff --git a/test/basic/large_mux.sv b/test/basic/large_mux.sv new file mode 100644 index 0000000..4effe1c --- /dev/null +++ b/test/basic/large_mux.sv @@ -0,0 +1,10 @@ +module top; + parameter SVO_MODE = "768x576"; + `include "large_mux.vh" + type(SVO_HOR_PIXELS) DOUBLE_SVO_HOR_PIXELS = 2 * SVO_HOR_PIXELS; + initial begin + $display("%s", SVO_MODE); + $display("%d", SVO_HOR_PIXELS); + $display("%d", DOUBLE_SVO_HOR_PIXELS); + end +endmodule diff --git a/test/basic/large_mux.v b/test/basic/large_mux.v new file mode 100644 index 0000000..51579bd --- /dev/null +++ b/test/basic/large_mux.v @@ -0,0 +1,10 @@ +module top; + parameter SVO_MODE = "768x576"; + `include "large_mux.vh" + wire [31:0] DOUBLE_SVO_HOR_PIXELS = 2 * SVO_HOR_PIXELS; + initial begin + $display("%s", SVO_MODE); + $display("%d", SVO_HOR_PIXELS); + $display("%d", DOUBLE_SVO_HOR_PIXELS); + end +endmodule diff --git a/test/basic/large_mux.vh b/test/basic/large_mux.vh new file mode 100644 index 0000000..cf28385 --- /dev/null +++ b/test/basic/large_mux.vh @@ -0,0 +1,81 @@ + localparam SVO_HOR_PIXELS = + SVO_MODE == "768x576" ? 768 : + SVO_MODE == "1280x854R" ? 1280 : + SVO_MODE == "2560x2048R" ? 2560 : + SVO_MODE == "1920x1200" ? 1920 : + SVO_MODE == "480x320R" ? 480 : + SVO_MODE == "1280x768R" ? 1280 : + SVO_MODE == "2560x1440R" ? 2560 : + SVO_MODE == "2048x1536" ? 2048 : + SVO_MODE == "1024x576" ? 1024 : + SVO_MODE == "320x200" ? 320 : + SVO_MODE == "384x288R" ? 384 : + SVO_MODE == "1280x1024R" ? 1280 : + SVO_MODE == "768x576R" ? 768 : + SVO_MODE == "2048x1536R" ? 2048 : + SVO_MODE == "1024x576R" ? 1024 : + SVO_MODE == "1680x1050R" ? 1680 : + SVO_MODE == "1280x854" ? 1280 : + SVO_MODE == "2560x2048" ? 2560 : + SVO_MODE == "1440x900R" ? 1440 : + SVO_MODE == "2048x1080" ? 2048 : + SVO_MODE == "1152x768R" ? 1152 : + SVO_MODE == "4096x2160" ? 4096 : + SVO_MODE == "4096x2160R" ? 4096 : + SVO_MODE == "800x480" ? 800 : + SVO_MODE == "2560x1080R" ? 2560 : + SVO_MODE == "1440x1080R" ? 1440 : + SVO_MODE == "854x480" ? 854 : + SVO_MODE == "640x480" ? 640 : + SVO_MODE == "480x320" ? 480 : + SVO_MODE == "1920x1200R" ? 1920 : + SVO_MODE == "3840x2160" ? 3840 : + SVO_MODE == "1400x1050" ? 1400 : + SVO_MODE == "854x480R" ? 854 : + SVO_MODE == "1680x1050" ? 1680 : + SVO_MODE == "320x200R" ? 320 : + SVO_MODE == "1920x1080R" ? 1920 : + SVO_MODE == "1920x1080" ? 1920 : + SVO_MODE == "2560x1440" ? 2560 : + SVO_MODE == "1440x900" ? 1440 : + SVO_MODE == "1024x600" ? 1024 : + SVO_MODE == "1400x1050R" ? 1400 : + SVO_MODE == "1366x768" ? 1366 : + SVO_MODE == "1440x1080" ? 1440 : + SVO_MODE == "1600x900" ? 1600 : + SVO_MODE == "64x48T" ? 64 : + SVO_MODE == "640x480R" ? 640 : + SVO_MODE == "352x288R" ? 352 : + SVO_MODE == "1024x768" ? 1024 : + SVO_MODE == "800x600" ? 800 : + SVO_MODE == "1280x960" ? 1280 : + SVO_MODE == "1024x768R" ? 1024 : + SVO_MODE == "1280x960R" ? 1280 : + SVO_MODE == "1600x900R" ? 1600 : + SVO_MODE == "800x600R" ? 800 : + SVO_MODE == "1280x800" ? 1280 : + SVO_MODE == "384x288" ? 384 : + SVO_MODE == "352x288" ? 352 : + SVO_MODE == "800x480R" ? 800 : + SVO_MODE == "1440x960" ? 1440 : + SVO_MODE == "3840x2160R" ? 3840 : + SVO_MODE == "2048x1080R" ? 2048 : + SVO_MODE == "1280x800R" ? 1280 : + SVO_MODE == "1366x768R" ? 1366 : + SVO_MODE == "1600x1200R" ? 1600 : + SVO_MODE == "2560x1600" ? 2560 : + SVO_MODE == "1600x1200" ? 1600 : + SVO_MODE == "320x240" ? 320 : + SVO_MODE == "1152x864" ? 1152 : + SVO_MODE == "1440x960R" ? 1440 : + SVO_MODE == "2560x1080" ? 2560 : + SVO_MODE == "1152x768" ? 1152 : + SVO_MODE == "1280x720" ? 1280 : + SVO_MODE == "1152x864R" ? 1152 : + SVO_MODE == "1024x600R" ? 1024 : + SVO_MODE == "1280x1024" ? 1280 : + SVO_MODE == "1280x768" ? 1280 : + SVO_MODE == "1280x720R" ? 1280 : + SVO_MODE == "2560x1600R" ? 2560 : + SVO_MODE == "320x240R" ? 320 : + 'bx; diff --git a/test/basic/string.sv b/test/basic/string.sv new file mode 100644 index 0000000..09eddda --- /dev/null +++ b/test/basic/string.sv @@ -0,0 +1,6 @@ +module top; + parameter FOO = "some useful string"; + localparam type T = type(FOO); + localparam T BAR = "some other useful string"; + initial $display("'%s' '%s'", FOO, BAR); +endmodule diff --git a/test/basic/string.v b/test/basic/string.v new file mode 100644 index 0000000..10fd93f --- /dev/null +++ b/test/basic/string.v @@ -0,0 +1,5 @@ +module top; + parameter FOO = "some useful string"; + localparam BAR = "some other useful string"; + initial $display("'%s' '%s'", FOO, BAR); +endmodule diff --git a/test/basic/typeof.sv b/test/basic/typeof.sv index 4f08359..0defacb 100644 --- a/test/basic/typeof.sv +++ b/test/basic/typeof.sv @@ -70,4 +70,15 @@ module top; $display("%b %d %d %d", i, i, $left(i), $right(i)); $display("%b %d %d %d", a, a, $left(a), $right(a)); end + + localparam X = 5'b10110; + localparam Y = X + 6'b00001; + initial begin + type(X) tX = X; + type(Y) tY = Y; + $display("%b %d %d %d", X, X, $left(X), $right(X)); + $display("%b %d %d %d", Y, Y, $left(Y), $right(Y)); + $display("%b %d %d %d", tX, tX, $left(tX), $right(tX)); + $display("%b %d %d %d", tY, tY, $left(tY), $right(tY)); + end endmodule diff --git a/test/basic/typeof.v b/test/basic/typeof.v index af83a81..277a672 100644 --- a/test/basic/typeof.v +++ b/test/basic/typeof.v @@ -85,4 +85,17 @@ module top; $display("%b %d %d %d", a, a, 31, 0); end endgenerate + + localparam X = 5'b10110; + localparam Y = X + 6'b00001; + initial begin : block5 + reg [4:0] tX; + reg [5:0] tY; + tX = X; + tY = Y; + $display("%b %d %d %d", X, X, 4, 0); + $display("%b %d %d %d", Y, Y, 5, 0); + $display("%b %d %d %d", tX, tX, 4, 0); + $display("%b %d %d %d", tY, tY, 5, 0); + end endmodule