mirror of https://github.com/zachjs/sv2v.git
initial work towards fleshing out package conversion
This commit is contained in:
parent
91dd144137
commit
d2c06b58bc
|
|
@ -49,7 +49,7 @@ traverseDescriptionM (orig @ (Part extern kw lifetime name ports items)) = do
|
|||
existingPIs
|
||||
let newItems = map MIPackageItem $ Map.elems $
|
||||
Map.restrictKeys tfs neededPIs
|
||||
return $ Part extern kw lifetime name ports (items ++ newItems)
|
||||
return $ Part extern kw lifetime name ports (newItems ++ items)
|
||||
where
|
||||
existingPIs = execWriter $ collectModuleItemsM collectPIsM orig
|
||||
runner f = execWriter $ collectModuleItemsM f orig
|
||||
|
|
@ -97,4 +97,5 @@ piName (Decl (Variable _ _ ident _ _)) = Just ident
|
|||
piName (Decl (Parameter _ ident _)) = Just ident
|
||||
piName (Decl (Localparam _ ident _)) = Just ident
|
||||
piName (Import x y) = Just $ show $ Import x y
|
||||
piName (Export _) = Nothing
|
||||
piName (Comment _) = Nothing
|
||||
|
|
|
|||
|
|
@ -1,7 +1,32 @@
|
|||
{- sv2v
|
||||
- Author: Zachary Snow <zach@zachjs.com>
|
||||
-
|
||||
- Conversion for packages and imports
|
||||
- Conversion for packages, exports, and imports
|
||||
-
|
||||
- TODO: We do not yet handle exports.
|
||||
- TODO: The scoping rules are not being entirely followed yet.
|
||||
- TODO: Explicit imports may introduce name conflicts because of carried items.
|
||||
-
|
||||
- The SystemVerilog scoping rules for exports and imports are not entirely
|
||||
- trivial. We do not explicitly handle the "error" scenarios detailed Table
|
||||
- 26-1 of Section 26-3 of IEEE 1800-2017. Users generally shouldn't be relying
|
||||
- on this tool to catch and report such wild naming conflicts that are outlined
|
||||
- there.
|
||||
-
|
||||
- Summary:
|
||||
- * In scopes which have a local declaration of an identifier, that identifier
|
||||
- refers to that local declaration.
|
||||
- * If there is no local declaration, the identifier refers to the imported
|
||||
- declaration.
|
||||
- * If there is an explicit import of that identifier, the identifier refers to
|
||||
- the imported declaration.
|
||||
- * Usages of conflicting wildcard imports are not allowed.
|
||||
-
|
||||
- If a package cannot be found within a file that references it (including
|
||||
- through files it imports), we fall back to an arbitrary package with the
|
||||
- given name, if it exists. While this isn't foolproof, some projects do rely
|
||||
- on their toolchain to locate their packages in other files, much like modules
|
||||
- or interfaces.
|
||||
-}
|
||||
|
||||
module Convert.Package (convert) where
|
||||
|
|
@ -29,13 +54,23 @@ convert asts =
|
|||
where
|
||||
packages = execWriter $
|
||||
collectDescriptionsM collectDescriptionM $ concat curr
|
||||
globalItems = map PackageItem $
|
||||
concatMap (uncurry globalPackageItems) $ Map.toList packages
|
||||
next = map ((++) globalItems) $ map (filter shouldntRemove) $ map
|
||||
(traverseDescriptions $ traverseDescription packages) curr
|
||||
shouldntRemove :: Description -> Bool
|
||||
shouldntRemove (Package _ name _) = Map.notMember name packages
|
||||
shouldntRemove _ = True
|
||||
next = map (convertFile packages) curr
|
||||
|
||||
convertFile :: Packages -> AST -> AST
|
||||
convertFile globalPackages ast =
|
||||
(++) globalItems $
|
||||
filter (not . isCollected) $
|
||||
traverseDescriptions (traverseDescription packages) $
|
||||
ast
|
||||
where
|
||||
globalItems = map PackageItem $
|
||||
concatMap (uncurry globalPackageItems) $ Map.toList packages
|
||||
localPackages = execWriter $
|
||||
collectDescriptionsM collectDescriptionM ast
|
||||
packages = Map.union localPackages globalPackages
|
||||
isCollected :: Description -> Bool
|
||||
isCollected (Package _ name _) = Map.member name localPackages
|
||||
isCollected _ = False
|
||||
|
||||
globalPackageItems :: Identifier -> PackageItems -> [PackageItem]
|
||||
globalPackageItems name items =
|
||||
|
|
@ -86,20 +121,30 @@ collectDescriptionM _ = return ()
|
|||
|
||||
traverseDescription :: Packages -> Description -> Description
|
||||
traverseDescription packages description =
|
||||
traverseModuleItems (traverseModuleItem packages) description
|
||||
traverseModuleItems (traverseModuleItem existingItemNames packages)
|
||||
description
|
||||
where
|
||||
existingItemNames = execWriter $
|
||||
collectModuleItemsM writePIName description
|
||||
writePIName :: ModuleItem -> Writer Idents ()
|
||||
writePIName (MIPackageItem item) =
|
||||
case piName item of
|
||||
Nothing -> return ()
|
||||
Just x -> tell $ Set.singleton x
|
||||
writePIName _ = return ()
|
||||
|
||||
traverseModuleItem :: Packages -> ModuleItem -> ModuleItem
|
||||
traverseModuleItem packages (MIPackageItem (Import x y)) =
|
||||
traverseModuleItem :: Idents -> Packages -> ModuleItem -> ModuleItem
|
||||
traverseModuleItem existingItemNames packages (MIPackageItem (Import x y)) =
|
||||
if Map.member x packages
|
||||
then Generate $ map (GenModuleItem . MIPackageItem) items
|
||||
else MIPackageItem $ Import x y
|
||||
where
|
||||
packageItems = packages Map.! x
|
||||
filterer = case y of
|
||||
Nothing -> \_ -> True
|
||||
Just ident -> (==) ident
|
||||
filterer itemName = case y of
|
||||
Nothing -> Set.notMember itemName existingItemNames
|
||||
Just ident -> ident == itemName
|
||||
items = map snd $ filter (filterer . fst) $ Map.toList packageItems
|
||||
traverseModuleItem _ item =
|
||||
traverseModuleItem _ _ item =
|
||||
(traverseExprs $ traverseNestedExprs traverseExpr) $
|
||||
(traverseStmts traverseStmt) $
|
||||
(traverseTypes traverseType) $
|
||||
|
|
@ -131,4 +176,5 @@ piName (Decl (Variable _ _ ident _ _)) = Just ident
|
|||
piName (Decl (Parameter _ ident _)) = Just ident
|
||||
piName (Decl (Localparam _ ident _)) = Just ident
|
||||
piName (Import _ _) = Nothing
|
||||
piName (Export _) = Nothing
|
||||
piName (Comment _) = Nothing
|
||||
|
|
|
|||
|
|
@ -564,6 +564,8 @@ traverseExprsM' strat exprMapper = moduleItemMapper
|
|||
return $ MIPackageItem $ Comment c
|
||||
moduleItemMapper (MIPackageItem (Import x y)) =
|
||||
return $ MIPackageItem $ Import x y
|
||||
moduleItemMapper (MIPackageItem (Export x)) =
|
||||
return $ MIPackageItem $ Export x
|
||||
moduleItemMapper (AssertionItem (mx, a)) = do
|
||||
a' <- traverseAssertionStmtsM stmtMapper a
|
||||
a'' <- traverseAssertionExprsM exprMapper a'
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ data PackageItem
|
|||
| Function (Maybe Lifetime) Type Identifier [Decl] [Stmt]
|
||||
| Task (Maybe Lifetime) Identifier [Decl] [Stmt]
|
||||
| Import Identifier (Maybe Identifier)
|
||||
| Export (Maybe (Identifier, Maybe Identifier))
|
||||
| Decl Decl
|
||||
| Comment String
|
||||
deriving Eq
|
||||
|
|
@ -72,6 +73,8 @@ instance Show PackageItem where
|
|||
(showLifetime ml) x (indent $ show i)
|
||||
(indent $ unlines' $ map show b)
|
||||
show (Import x y) = printf "import %s::%s;" x (fromMaybe "*" y)
|
||||
show (Export Nothing) = "export *::*";
|
||||
show (Export (Just (x, y))) = printf "export %s::%s;" x (fromMaybe "*" y)
|
||||
show (Decl decl) = show decl
|
||||
show (Comment c) =
|
||||
if elem '\n' c
|
||||
|
|
|
|||
|
|
@ -578,6 +578,8 @@ NonDeclPackageItem :: { [PackageItem] }
|
|||
| "function" opt(Lifetime) FuncRetAndName TFItems DeclsAndStmts "endfunction" opt(Tag) { [Function $2 (fst $3) (snd $3) (map defaultFuncInput $ (map makeInput $4) ++ fst $5) (snd $5)] }
|
||||
| "task" opt(Lifetime) Identifier TFItems DeclsAndStmts "endtask" opt(Tag) { [Task $2 $3 (map defaultFuncInput $ $4 ++ fst $5) (snd $5)] }
|
||||
| "import" PackageImportItems ";" { map (uncurry Import) $2 }
|
||||
| "export" PackageImportItems ";" { map (Export . Just) $2 }
|
||||
| "export" "*" "::" "*" ";" { [Export Nothing] } -- "Nothing" being no restrictions
|
||||
|
||||
PackageImportItems :: { [(Identifier, Maybe Identifier)] }
|
||||
: PackageImportItem { [$1] }
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ package D;
|
|||
endpackage
|
||||
package E;
|
||||
import D::*;
|
||||
export D::*;
|
||||
endpackage
|
||||
package F;
|
||||
localparam MAGIC = -42;
|
||||
localparam PIZZAZZ = -5;
|
||||
endpackage
|
||||
module top;
|
||||
import A::FOO;
|
||||
|
|
@ -33,4 +38,28 @@ module top;
|
|||
$display("%d", E::pack(0));
|
||||
$display("%d", E::pack(1));
|
||||
end
|
||||
import F::*;
|
||||
initial begin
|
||||
$display("imported MAGIC %d", MAGIC);
|
||||
$display("imported MAGIC %d", F::MAGIC);
|
||||
begin
|
||||
localparam MAGIC = 42;
|
||||
$display("local MAGIC %d", MAGIC);
|
||||
$display("imported MAGIC %d", F::MAGIC);
|
||||
end
|
||||
$display("imported MAGIC %d", MAGIC);
|
||||
$display("imported MAGIC %d", F::MAGIC);
|
||||
end
|
||||
localparam PIZZAZZ = -6;
|
||||
initial begin
|
||||
$display("local PIZZAZZ %d", PIZZAZZ);
|
||||
$display("imported PIZZAZZ %d", F::PIZZAZZ);
|
||||
begin
|
||||
localparam PIZZAZZ = -7;
|
||||
$display("shadowed local PIZZAZZ %d", PIZZAZZ);
|
||||
$display("imported PIZZAZZ %d", F::PIZZAZZ);
|
||||
end
|
||||
$display("local PIZZAZZ %d", PIZZAZZ);
|
||||
$display("imported PIZZAZZ %d", F::PIZZAZZ);
|
||||
end
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -25,4 +25,20 @@ module top;
|
|||
$display("%d", E_pack(0));
|
||||
$display("%d", E_pack(1));
|
||||
end
|
||||
initial begin
|
||||
$display("imported MAGIC %d", -42);
|
||||
$display("imported MAGIC %d", -42);
|
||||
$display("local MAGIC %d", +42);
|
||||
$display("imported MAGIC %d", -42);
|
||||
$display("imported MAGIC %d", -42);
|
||||
$display("imported MAGIC %d", -42);
|
||||
end
|
||||
initial begin
|
||||
$display("local PIZZAZZ %d", -6);
|
||||
$display("imported PIZZAZZ %d", -5);
|
||||
$display("shadowed local PIZZAZZ %d", -7);
|
||||
$display("imported PIZZAZZ %d", -5);
|
||||
$display("local PIZZAZZ %d", -6);
|
||||
$display("imported PIZZAZZ %d", -5);
|
||||
end
|
||||
endmodule
|
||||
|
|
|
|||
Loading…
Reference in New Issue