diff --git a/src/Convert/Enum.hs b/src/Convert/Enum.hs index a817cd3..68f6cb6 100644 --- a/src/Convert/Enum.hs +++ b/src/Convert/Enum.hs @@ -28,12 +28,12 @@ defaultType :: Type defaultType = IntegerVector TLogic Unspecified [(Number "31", Number "0")] convertDescription :: Description -> Description -convertDescription (description @ (Part _ _ _ _)) = - Part kw name ports (enumItems ++ items) +convertDescription (description @ (Part _ _ _ _ _ _)) = + Part extern kw lifetime name ports (enumItems ++ items) where enumPairs = concat $ map (uncurry enumVals) $ Set.toList enums enumItems = map (\(x, v) -> MIDecl $ Localparam (Implicit Unspecified []) x v) enumPairs - (Part kw name ports items, enums) = + (Part extern kw lifetime name ports items, enums) = runWriter $ traverseModuleItemsM (traverseTypesM traverseType) $ traverseModuleItems (traverseExprs $ traverseNestedExprs traverseExpr) $ description diff --git a/src/Convert/Interface.hs b/src/Convert/Interface.hs index f951f92..f3f091c 100644 --- a/src/Convert/Interface.hs +++ b/src/Convert/Interface.hs @@ -25,17 +25,18 @@ convert descriptions = descriptions where interfaces = execWriter $ collectDescriptionsM collectDesc descriptions + -- we can only collect/map non-extern interfaces collectDesc :: Description -> Writer Interfaces () - collectDesc (Part Interface name ports items) = + collectDesc (Part False Interface _ name ports items) = tell $ Map.singleton name (ports, items) collectDesc _ = return () isInterface :: Description -> Bool - isInterface (Part Interface _ _ _) = True + isInterface (Part False Interface _ _ _ _) = True isInterface _ = False convertDescription :: Interfaces -> Description -> Description -convertDescription interfaces (Part Module name ports items) = - Part Module name ports' items' +convertDescription interfaces (Part extern Module lifetime name ports items) = + Part extern Module lifetime name ports' items' where items' = map (traverseNestedModuleItems $ traverseExprs (traverseNestedExprs convertExpr)) $ diff --git a/src/Convert/Logic.hs b/src/Convert/Logic.hs index e5dd22a..0e81cf3 100644 --- a/src/Convert/Logic.hs +++ b/src/Convert/Logic.hs @@ -25,7 +25,7 @@ convert :: AST -> AST convert = traverseDescriptions convertDescription convertDescription :: Description -> Description -convertDescription (orig @ (Part Module _ _ _)) = +convertDescription (orig @ (Part _ Module _ _ _ _)) = traverseModuleItems (traverseDecls convertDecl . convertModuleItem) orig where idents = execWriter (collectModuleItemsM regIdents orig) diff --git a/src/Convert/PackedArray.hs b/src/Convert/PackedArray.hs index 41ebab9..38de442 100644 --- a/src/Convert/PackedArray.hs +++ b/src/Convert/PackedArray.hs @@ -49,7 +49,7 @@ convert :: AST -> AST convert = traverseDescriptions convertDescription convertDescription :: Description -> Description -convertDescription (description @ (Part _ _ ports _)) = +convertDescription (description @ (Part _ _ _ _ ports _)) = hoistPortDecls $ traverseModuleItems (flattenModuleItem info . rewriteModuleItem info) description where @@ -105,8 +105,8 @@ collectNestedLHS _ = return () -- them out with this function. This obviously isn't ideal, but it's a -- relatively straightforward transformation, and testing in VCS is important. hoistPortDecls :: Description -> Description -hoistPortDecls (Part kw name ports items) = - Part kw name ports (concat $ map explode items) +hoistPortDecls (Part extern kw lifetime name ports items) = + Part extern kw lifetime name ports (concat $ map explode items) where explode :: ModuleItem -> [ModuleItem] explode (Generate genItems) = diff --git a/src/Convert/StarPort.hs b/src/Convert/StarPort.hs index f264dd8..3cce8bc 100644 --- a/src/Convert/StarPort.hs +++ b/src/Convert/StarPort.hs @@ -18,7 +18,7 @@ convert descriptions = where modulePorts = execWriter $ collectDescriptionsM getPorts descriptions getPorts :: Description -> Writer (Map.Map Identifier [Identifier]) () - getPorts (Part _ name ports _) = tell $ Map.singleton name ports + getPorts (Part _ _ _ name ports _) = tell $ Map.singleton name ports getPorts _ = return () mapInstance :: ModuleItem -> ModuleItem diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index 9c3fb84..96300e7 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -80,8 +80,8 @@ maybeDo _ Nothing = return Nothing maybeDo fun (Just val) = fun val >>= return . Just traverseModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m Description -traverseModuleItemsM mapper (Part kw name ports items) = - mapM fullMapper items >>= return . Part kw name ports +traverseModuleItemsM mapper (Part extern kw lifetime name ports items) = + mapM fullMapper items >>= return . Part extern kw lifetime name ports where fullMapper (Generate genItems) = mapM fullGenItemMapper genItems >>= mapper . Generate @@ -95,8 +95,8 @@ traverseModuleItemsM mapper (Part kw name ports items) = genItemMapper other = return other traverseModuleItemsM mapper (PackageItem packageItem) = do let item = MIPackageItem packageItem - Part Module "DNE" [] [item'] <- - traverseModuleItemsM mapper (Part Module "DNE" [] [item]) + Part False Module Nothing "DNE" [] [item'] <- + traverseModuleItemsM mapper (Part False Module Nothing "DNE" [] [item]) return $ case item' of MIPackageItem packageItem' -> PackageItem packageItem' other -> error $ "encountered bad package module item: " ++ show other @@ -529,8 +529,8 @@ collectAsgnsM = collectify traverseAsgnsM traverseNestedModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m ModuleItem traverseNestedModuleItemsM mapper item = do - Part Module "DNE" [] [item'] <- - traverseModuleItemsM mapper (Part Module "DNE" [] [item]) + Part False Module Nothing "DNE" [] [item'] <- + traverseModuleItemsM mapper (Part False Module Nothing "DNE" [] [item]) return item' traverseNestedModuleItems :: Mapper ModuleItem -> Mapper ModuleItem diff --git a/src/Language/SystemVerilog/AST.hs b/src/Language/SystemVerilog/AST.hs index 0a6bbcf..195aaa2 100644 --- a/src/Language/SystemVerilog/AST.hs +++ b/src/Language/SystemVerilog/AST.hs @@ -82,22 +82,26 @@ instance Show PackageItem where show (Comment c) = "// " ++ c data Description - = Part PartKW Identifier [Identifier] [ModuleItem] + = Part Bool PartKW (Maybe Lifetime) Identifier [Identifier] [ModuleItem] | PackageItem PackageItem | Directive String deriving Eq instance Show Description where showList descriptions _ = intercalate "\n" $ map show descriptions - show (Part kw name ports items) = unlines - [ (show kw) ++ " " ++ name ++ portsStr ++ ";" - , indent $ unlines' $ map show items - , "end" ++ (show kw) ] + show (Part True kw lifetime name _ items) = + printf "extern %s %s%s %s;" + (show kw) (showLifetime lifetime) name (indentedParenList itemStrs) + where itemStrs = map (\(MIDecl a) -> init $ show a) items + show (Part False kw lifetime name ports items) = + printf "%s %s%s%s;\n%s\nend%s" + (show kw) (showLifetime lifetime) name portsStr bodyStr (show kw) where portsStr = if null ports then "" - else indentedParenList ports + else " " ++ indentedParenList ports + bodyStr = indent $ unlines' $ map show items show (PackageItem i) = show i show (Directive str) = str diff --git a/src/Language/SystemVerilog/Parser/Lex.x b/src/Language/SystemVerilog/Parser/Lex.x index 3753ebf..5b89945 100644 --- a/src/Language/SystemVerilog/Parser/Lex.x +++ b/src/Language/SystemVerilog/Parser/Lex.x @@ -98,6 +98,7 @@ tokens :- "endmodule" { tok KW_endmodule } "endtask" { tok KW_endtask } "enum" { tok KW_enum } + "extern" { tok KW_extern } "for" { tok KW_for } "forever" { tok KW_forever } "function" { tok KW_function } diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index d44defe..476f013 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -43,6 +43,7 @@ import Language.SystemVerilog.Parser.Tokens "endmodule" { Token KW_endmodule _ _ } "endtask" { Token KW_endtask _ _ } "enum" { Token KW_enum _ _ } +"extern" { Token KW_extern _ _ } "for" { Token KW_for _ _ } "forever" { Token KW_forever _ _ } "function" { Token KW_function _ _ } @@ -223,7 +224,8 @@ Descriptions :: { [Description] } | Descriptions Description { $1 ++ [$2] } Description :: { Description } - : Part { $1 } + : Part(ModuleKW , "endmodule" ) { $1 } + | Part(InterfaceKW, "endinterface") { $1 } | PackageItem { PackageItem $1 } | Directive { Directive $1 } @@ -296,9 +298,14 @@ Packing :: { Packing } | "packed" { Packed Unspecified } | {- empty -} { Unpacked } -Part :: { Description } - : "module" Identifier Params PortDecls ";" ModuleItems "endmodule" opt(Tag) { Part Module $2 (fst $4) ($3 ++ (snd $4) ++ $6) } - | "interface" Identifier Params PortDecls ";" ModuleItems "endinterface" opt(Tag) { Part Interface $2 (fst $4) ($3 ++ (snd $4) ++ $6) } +Part(begin, end) :: { Description } + : begin opt(Lifetime) Identifier Params PortDecls ";" ModuleItems end opt(Tag) { Part False $1 $2 $3 (fst $5) ($4 ++ (snd $5) ++ $7) } + | "extern" begin opt(Lifetime) Identifier Params PortDecls ";" { Part True $2 $3 $4 (fst $6) ($5 ++ (snd $6) ) } + +ModuleKW :: { PartKW } + : "module" { Module } +InterfaceKW :: { PartKW } + : "interface" { Interface } Tag :: { Identifier } : ":" Identifier { $2 }