Commit 04337988 by Zachary Snow

standardized handling of resolution across source files

parent d2c06b58
...@@ -21,14 +21,12 @@ type Modports = Map.Map Identifier [ModportDecl] ...@@ -21,14 +21,12 @@ type Modports = Map.Map Identifier [ModportDecl]
type Modules = Map.Map (Identifier, Identifier) Type type Modules = Map.Map (Identifier, Identifier) Type
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert descriptions = convert =
map ( traverseFiles (collectDescriptionsM collectDesc) converter
filter (not . isInterface) .
traverseDescriptions (convertDescription interfaces modules)
) descriptions
where where
(interfaces, modules) = converter (interfaces, modules) =
execWriter $ collectDescriptionsM collectDesc $ concat descriptions filter (not . isInterface) .
map (convertDescription interfaces modules)
-- we can only collect/map non-extern interfaces -- we can only collect/map non-extern interfaces
collectDesc :: Description -> Writer (Interfaces, Modules) () collectDesc :: Description -> Writer (Interfaces, Modules) ()
collectDesc (orig @ (Part False kw _ name ports items)) = do collectDesc (orig @ (Part False kw _ name ports items)) = do
......
...@@ -36,10 +36,11 @@ type Idents = Set.Set Identifier ...@@ -36,10 +36,11 @@ type Idents = Set.Set Identifier
type Ports = Map.Map (Identifier, Identifier) Direction type Ports = Map.Map (Identifier, Identifier) Direction
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert asts = convert =
map (traverseDescriptions $ convertDescription ports) asts traverseFiles
(collectDescriptionsM collectPortsM)
(traverseDescriptions . convertDescription)
where where
ports = execWriter $ collectDescriptionsM collectPortsM $ concat asts
collectPortsM :: Description -> Writer Ports () collectPortsM :: Description -> Writer Ports ()
collectPortsM (orig @ (Part _ _ _ name portNames _)) = collectPortsM (orig @ (Part _ _ _ name portNames _)) =
collectModuleItemsM collectPortDirsM orig collectModuleItemsM collectPortDirsM orig
......
...@@ -21,12 +21,6 @@ ...@@ -21,12 +21,6 @@
- * If there is an explicit import of that identifier, the identifier refers to - * If there is an explicit import of that identifier, the identifier refers to
- the imported declaration. - the imported declaration.
- * Usages of conflicting wildcard imports are not allowed. - * 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 module Convert.Package (convert) where
...@@ -43,8 +37,7 @@ type PackageItems = Map.Map Identifier PackageItem ...@@ -43,8 +37,7 @@ type PackageItems = Map.Map Identifier PackageItem
type Idents = Set.Set Identifier type Idents = Set.Set Identifier
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert asts = convert = step
step asts
where where
step :: [AST] -> [AST] step :: [AST] -> [AST]
step curr = step curr =
...@@ -52,12 +45,12 @@ convert asts = ...@@ -52,12 +45,12 @@ convert asts =
then curr then curr
else step next else step next
where where
packages = execWriter $ next = traverseFiles
collectDescriptionsM collectDescriptionM $ concat curr (collectDescriptionsM collectDescriptionM)
next = map (convertFile packages) curr convertFile curr
convertFile :: Packages -> AST -> AST convertFile :: Packages -> AST -> AST
convertFile globalPackages ast = convertFile packages ast =
(++) globalItems $ (++) globalItems $
filter (not . isCollected) $ filter (not . isCollected) $
traverseDescriptions (traverseDescription packages) $ traverseDescriptions (traverseDescription packages) $
...@@ -65,11 +58,8 @@ convertFile globalPackages ast = ...@@ -65,11 +58,8 @@ convertFile globalPackages ast =
where where
globalItems = map PackageItem $ globalItems = map PackageItem $
concatMap (uncurry globalPackageItems) $ Map.toList packages concatMap (uncurry globalPackageItems) $ Map.toList packages
localPackages = execWriter $
collectDescriptionsM collectDescriptionM ast
packages = Map.union localPackages globalPackages
isCollected :: Description -> Bool isCollected :: Description -> Bool
isCollected (Package _ name _) = Map.member name localPackages isCollected (Package _ name _) = Map.member name packages
isCollected _ = False isCollected _ = False
globalPackageItems :: Identifier -> PackageItems -> [PackageItem] globalPackageItems :: Identifier -> PackageItems -> [PackageItem]
......
...@@ -12,28 +12,31 @@ import qualified Data.Map.Strict as Map ...@@ -12,28 +12,31 @@ import qualified Data.Map.Strict as Map
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
type Ports = Map.Map Identifier [Identifier]
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert asts = convert =
map (traverseDescriptions $ traverseModuleItems mapInstance) asts traverseFiles
where (collectDescriptionsM collectPortsM)
modulePorts = execWriter $ collectDescriptionsM getPorts $ concat asts (traverseDescriptions . traverseModuleItems . mapInstance)
getPorts :: Description -> Writer (Map.Map Identifier [Identifier]) ()
getPorts (Part _ _ _ name ports _) = tell $ Map.singleton name ports
getPorts _ = return ()
mapInstance :: ModuleItem -> ModuleItem collectPortsM :: Description -> Writer Ports ()
mapInstance (Instance m p x r bindings) = collectPortsM (Part _ _ _ name ports _) = tell $ Map.singleton name ports
Instance m p x r $ concatMap expandBinding bindings collectPortsM _ = return ()
where
alreadyBound :: [Identifier] mapInstance :: Ports -> ModuleItem -> ModuleItem
alreadyBound = map fst bindings mapInstance modulePorts (Instance m p x r bindings) =
expandBinding :: PortBinding -> [PortBinding] Instance m p x r $ concatMap expandBinding bindings
expandBinding ("*", Nothing) = where
case Map.lookup m modulePorts of alreadyBound :: [Identifier]
Just l -> alreadyBound = map fst bindings
map (\port -> (port, Just $ Ident port)) $ expandBinding :: PortBinding -> [PortBinding]
filter (\s -> not $ elem s alreadyBound) $ l expandBinding ("*", Nothing) =
-- if we can't find it, just skip :( case Map.lookup m modulePorts of
Nothing -> [("*", Nothing)] Just l ->
expandBinding other = [other] map (\port -> (port, Just $ Ident port)) $
mapInstance other = other filter (\s -> not $ elem s alreadyBound) $ l
-- if we can't find it, just skip :(
Nothing -> [("*", Nothing)]
expandBinding other = [other]
mapInstance _ other = other
...@@ -76,9 +76,11 @@ module Convert.Traverse ...@@ -76,9 +76,11 @@ module Convert.Traverse
, traverseScopesM , traverseScopesM
, scopedConversion , scopedConversion
, stately , stately
, traverseFiles
) where ) where
import Control.Monad.State import Control.Monad.State
import Control.Monad.Writer
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
type MapperM m t = t -> m t type MapperM m t = t -> m t
...@@ -1009,3 +1011,27 @@ stately :: (Eq s, Show s) => (s -> Mapper a) -> MapperM (State s) a ...@@ -1009,3 +1011,27 @@ stately :: (Eq s, Show s) => (s -> Mapper a) -> MapperM (State s) a
stately mapper thing = do stately mapper thing = do
s <- get s <- get
return $ mapper s thing return $ mapper s thing
-- In many conversions, we want to resolve items locally first, and then fall
-- back to looking at other source files, if necessary. This helper captures
-- this behavior, allowing a conversion to fall back to arbitrary global
-- collected item, if one exists. While this isn't foolproof (we could
-- inadvertently resolve a name that doesn't exist in the given file), many
-- projects rely on their toolchain to locate their modules, interfaces,
-- packages, or typenames in other files. Global resolution of modules and
-- interfaces is more commonly expected than global resolution of typenames and
-- packages.
traverseFiles
:: Monoid w
=> CollectorM (Writer w) AST
-> (w -> Mapper AST)
-> Mapper [AST]
traverseFiles fileCollectorM fileMapper files =
map traverseFile files
where
globalNotes = execWriter $ mapM fileCollectorM files
traverseFile file =
fileMapper notes file
where
localNotes = execWriter $ fileCollectorM file
notes = localNotes <> globalNotes
...@@ -18,15 +18,11 @@ import Language.SystemVerilog.AST ...@@ -18,15 +18,11 @@ import Language.SystemVerilog.AST
type Types = Map.Map Identifier Type type Types = Map.Map Identifier Type
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert = map convertFile convert =
traverseFiles
convertFile :: AST -> AST (collectDescriptionsM getTypedef)
convertFile descriptions = (\a -> traverseDescriptions $ removeTypedef . convertDescription a)
traverseDescriptions removeTypedef $
traverseDescriptions (convertDescription types) $
descriptions
where where
types = execWriter $ collectDescriptionsM getTypedef descriptions
getTypedef :: Description -> Writer Types () getTypedef :: Description -> Writer Types ()
getTypedef (PackageItem (Typedef a b)) = tell $ Map.singleton b a getTypedef (PackageItem (Typedef a b)) = tell $ Map.singleton b a
getTypedef _ = return () getTypedef _ = return ()
......
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