diff --git a/src/Convert.hs b/src/Convert.hs index 83ab3ed..333cd2c 100644 --- a/src/Convert.hs +++ b/src/Convert.hs @@ -21,6 +21,7 @@ import qualified Convert.ForDecl import qualified Convert.Foreach import qualified Convert.FuncRet import qualified Convert.FuncRoutine +import qualified Convert.ImplicitNet import qualified Convert.Inside import qualified Convert.Interface import qualified Convert.IntTypes @@ -63,6 +64,7 @@ phases excludes = , Convert.FuncRet.convert , Convert.FuncRoutine.convert , Convert.EmptyArgs.convert + , Convert.ImplicitNet.convert , Convert.Inside.convert , Convert.IntTypes.convert , Convert.KWArgs.convert diff --git a/src/Convert/ImplicitNet.hs b/src/Convert/ImplicitNet.hs new file mode 100644 index 0000000..c71c250 --- /dev/null +++ b/src/Convert/ImplicitNet.hs @@ -0,0 +1,107 @@ +{-# LANGUAGE PatternSynonyms #-} +{- sv2v + - Author: Zachary Snow <zach@zachjs.com> + - + - Create declarations for implicit nets + -} + +module Convert.ImplicitNet (convert) where + +import Control.Monad (when) +import Data.List (isPrefixOf, mapAccumL) + +import Convert.Scoper +import Language.SystemVerilog.AST + +type DefaultNetType = Maybe NetType + +convert :: [AST] -> [AST] +convert = + snd . mapAccumL + (mapAccumL traverseDescription) + (Just TWire) + +traverseDescription :: DefaultNetType -> Description + -> (DefaultNetType, Description) +traverseDescription defaultNetType (PackageItem (Directive str)) = + (defaultNetType', PackageItem $ Directive str) + where + prefix = "`default_nettype " + defaultNetType' = + if isPrefixOf prefix str + then parseDefaultNetType $ drop (length prefix) str + else defaultNetType +traverseDescription defaultNetType (part @ Part{}) = + (defaultNetType, partScoper traverseDeclM + (traverseModuleItemM defaultNetType) + return return part) +traverseDescription defaultNetType other = (defaultNetType, other) + +traverseDeclM :: Decl -> Scoper () Decl +traverseDeclM decl = do + case decl of + Variable _ t x _ _ -> when (t /= unknownType) $ insertElem x () + Param _ _ x _ -> insertElem x () + ParamType{} -> return () + CommentDecl{} -> return () + return decl + where unknownType = Implicit Unspecified [] + +traverseModuleItemM :: DefaultNetType -> ModuleItem -> Scoper () ModuleItem +traverseModuleItemM _ (Genvar x) = + insertElem x () >> return (Genvar x) +traverseModuleItemM defaultNetType (orig @ (Assign _ x _)) = do + needsLHS defaultNetType x + return orig +traverseModuleItemM defaultNetType (orig @ (NInputGate _ _ x lhs exprs)) = do + insertElem x () + needsLHS defaultNetType lhs + _ <- mapM (needsExpr defaultNetType) exprs + return orig +traverseModuleItemM defaultNetType (orig @ (NOutputGate _ _ x lhss expr)) = do + insertElem x () + _ <- mapM (needsLHS defaultNetType) lhss + needsExpr defaultNetType expr + return orig +traverseModuleItemM defaultNetType (orig @ (Instance _ _ _ _ ports)) = do + _ <- mapM (needsExpr defaultNetType . snd) ports + return orig +traverseModuleItemM _ item = return item + +needsExpr :: DefaultNetType -> Expr -> Scoper () () +needsExpr defaultNetType (Ident x) = needsIdent defaultNetType x +needsExpr _ _ = return () + +needsLHS :: DefaultNetType -> LHS -> Scoper () () +needsLHS defaultNetType (LHSIdent x) = needsIdent defaultNetType x +needsLHS _ _ = return () + +needsIdent :: DefaultNetType -> Identifier -> Scoper () () +needsIdent defaultNetType x = do + details <- lookupElemM x + when (details == Nothing) $ do + insertElem x () + injectItem decl + where + t = impliedNetType x defaultNetType Unspecified [] + decl = MIPackageItem $ Decl $ Variable Local t x [] Nil + +impliedNetType :: String -> DefaultNetType -> Signing -> [Range] -> Type +impliedNetType var Nothing = + error $ "implicit declaration of " ++ + show var ++ " but default_nettype is none" +impliedNetType _ (Just netType) = Net (NetType netType) + +parseDefaultNetType :: String -> DefaultNetType +parseDefaultNetType "tri" = Just TTri +parseDefaultNetType "triand" = Just TTriand +parseDefaultNetType "trior" = Just TTrior +parseDefaultNetType "trireg" = Just TTrireg +parseDefaultNetType "tri0" = Just TTri0 +parseDefaultNetType "tri1" = Just TTri1 +parseDefaultNetType "uwire" = Just TUwire +parseDefaultNetType "wire" = Just TWire +parseDefaultNetType "wand" = Just TWand +parseDefaultNetType "wor" = Just TWor +parseDefaultNetType "none" = Nothing +parseDefaultNetType str = error $ "bad default_nettype: " ++ show str diff --git a/sv2v.cabal b/sv2v.cabal index 24dbc5f..d7df4ce 100644 --- a/sv2v.cabal +++ b/sv2v.cabal @@ -70,6 +70,7 @@ executable sv2v Convert.Foreach Convert.FuncRet Convert.FuncRoutine + Convert.ImplicitNet Convert.Inside Convert.Interface Convert.IntTypes diff --git a/test/basic/implicit_net.sv b/test/basic/implicit_net.sv new file mode 100644 index 0000000..c8cdef9 --- /dev/null +++ b/test/basic/implicit_net.sv @@ -0,0 +1,39 @@ +`define DISPLAY(expr) \ + $display(`"expr = %b; $bits(expr) = %0d`", expr, $bits(expr)); + +`default_nettype wor + +module Example(a, b, c); + input a, b, c; + initial begin + `DISPLAY(a) + `DISPLAY(b) + `DISPLAY(c) + end +endmodule + +module top; + assign foo = 0; + type(foo) bar; + assign bar = 1; + + and (o1, foo, bar); + not (o2, o3, foo); + not (u1, u2, u3); + + Example e (a, b, c); + + initial begin + `DISPLAY(foo) + `DISPLAY(bar) + `DISPLAY(o1) + `DISPLAY(o2) + `DISPLAY(o3) + `DISPLAY(u1) + `DISPLAY(u2) + `DISPLAY(u3) + `DISPLAY(a) + `DISPLAY(b) + `DISPLAY(c) + end +endmodule diff --git a/test/basic/implicit_net.v b/test/basic/implicit_net.v new file mode 100644 index 0000000..e0590b0 --- /dev/null +++ b/test/basic/implicit_net.v @@ -0,0 +1,43 @@ +`define DISPLAY(expr) \ + $display(`"expr = %b; $bits(expr) = %0d`", expr, $bits(expr)); + +`default_nettype wor + +module Example(a, b, c); + input a, b, c; + initial begin + `DISPLAY(a) + `DISPLAY(b) + `DISPLAY(c) + end +endmodule + +module top; + wor foo; + assign foo = 0; + wor bar; + assign bar = 1; + + wor o1, o2, o3; + wor u1, u2, u3; + and (o1, foo, bar); + not (o2, o3, foo); + not (u1, u2, u3); + + wor a, b, c; + Example e (a, b, c); + + initial begin + `DISPLAY(foo) + `DISPLAY(bar) + `DISPLAY(o1) + `DISPLAY(o2) + `DISPLAY(o3) + `DISPLAY(u1) + `DISPLAY(u2) + `DISPLAY(u3) + `DISPLAY(a) + `DISPLAY(b) + `DISPLAY(c) + end +endmodule