Commit d2c06b58 by Zachary Snow

initial work towards fleshing out package conversion

parent 91dd1441
......@@ -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
{- 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment