Commit 5cc4dce0 by Zachary Snow

refactor positional binding checking and resolution

parent ba270acb
......@@ -37,8 +37,8 @@ import qualified Convert.Package
import qualified Convert.ParamNoDefault
import qualified Convert.ParamType
import qualified Convert.RemoveComments
import qualified Convert.ResolveBindings
import qualified Convert.Simplify
import qualified Convert.StarPort
import qualified Convert.Stream
import qualified Convert.StringParam
import qualified Convert.Struct
......@@ -100,11 +100,11 @@ initialPhases selectExclude =
, Convert.Unique.convert
, Convert.LogOp.convert
, Convert.Foreach.convert
, Convert.StarPort.convert
, selectExclude Job.Assert Convert.Assertion.convert
, selectExclude Job.Always Convert.AlwaysKW.convert
, Convert.Package.convert
, Convert.ParamNoDefault.convert
, Convert.ResolveBindings.convert
]
convert :: [Job.Exclude] -> Phase
......
......@@ -96,15 +96,11 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
inlineInstance rs modportBindings partItems
part instanceName paramBindings portBindings
where
Instance part rawParamBindings instanceName rs rawPortBindings =
Instance part paramBindings instanceName rs portBindings =
instanceItem
maybePartInfo = Map.lookup part parts
Just partInfo = maybePartInfo
PartInfo partKind partPorts partItems = partInfo
partParams = parameterNames partItems
paramBindings = resolveBindings partParams rawParamBindings
portBindings = resolveBindings partPorts rawPortBindings
PartInfo partKind _ partItems = partInfo
modportInstances = extractModportInstances partInfo
getModportBindings modports = mapMaybe
......@@ -583,16 +579,6 @@ pattern InstArrKey expr = Dot (Bit expr (RawNum 0)) InstArrName
pattern InstArrEncoded :: Expr -> Expr -> ModuleItem
pattern InstArrEncoded l r = Modport InstArrName (InstArrVal l r)
-- given a list of module items, produces the parameter names in order
parameterNames :: [ModuleItem] -> [Identifier]
parameterNames =
execWriter . mapM (collectNestedModuleItemsM $ collectDeclsM collectDeclM)
where
collectDeclM :: Decl -> Writer [Identifier] ()
collectDeclM (Param Parameter _ x _) = tell [x]
collectDeclM (ParamType Parameter x _) = tell [x]
collectDeclM _ = return ()
-- determines the lower bound for the given slice
sliceLo :: PartSelectMode -> Range -> Expr
sliceLo NonIndexed (l, r) = endianCondExpr (l, r) r l
......
......@@ -450,8 +450,9 @@ resolveCSIdent className paramBindings scopeKeys itemName = do
"could not find class " ++ show className
let Just (classParams, classItems) = maybeClass
-- resolve the provided parameters
let resolveMsg = "parameters in class specialization of " ++ show className
let paramNames = mapMaybe extractParameterName classParams
let paramBindings' = resolveBindings paramNames paramBindings
let paramBindings' = resolveBindings resolveMsg paramNames paramBindings
-- generate a unique name for this synthetic package
let packageName = className ++ '_' : shortHash (scopeKeys, paramBindings')
-- process the synthetic package and inject the given parameters
......
......@@ -74,9 +74,8 @@ traverseModuleItem parts (orig @ (Instance part params name _ _)) =
where
maybePartInfo = Map.lookup part parts
Just partInfo = maybePartInfo
paramsResolved = resolveBindings (map fst partInfo) params
paramsWithNoDefault = map fst $ filter snd partInfo
missingParams = filter (needsDefault paramsResolved) paramsWithNoDefault
missingParams = filter (needsDefault params) paramsWithNoDefault
traverseModuleItem _ other = other
-- whether a given parameter is unspecified in the given parameter bindings
......
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for `.*` and unnamed bindings
-
- While positional bindings need not be converted, resolving them here
- simplifies downstream conversions.
-}
module Convert.ResolveBindings (convert) where
import Control.Monad.Writer.Strict
import qualified Data.Map.Strict as Map
import Convert.Traverse
import Language.SystemVerilog.AST
type Ports = Map.Map Identifier ([Identifier], [Identifier])
convert :: [AST] -> [AST]
convert =
traverseFiles
(collectDescriptionsM collectPortsM)
(traverseDescriptions . traverseModuleItems . mapInstance)
collectPortsM :: Description -> Writer Ports ()
collectPortsM (Part _ _ _ _ name ports items) =
tell $ Map.singleton name (params, ports)
where params = parameterNames items
collectPortsM _ = return ()
-- given a list of module items, produces the parameter names in order
parameterNames :: [ModuleItem] -> [Identifier]
parameterNames =
execWriter . mapM (collectNestedModuleItemsM $ collectDeclsM collectDeclM)
where
collectDeclM :: Decl -> Writer [Identifier] ()
collectDeclM (Param Parameter _ x _) = tell [x]
collectDeclM (ParamType Parameter x _) = tell [x]
collectDeclM _ = return ()
mapInstance :: Ports -> ModuleItem -> ModuleItem
mapInstance modulePorts (Instance m paramBindings x rs portBindings) =
-- if we can't find it, just skip :(
if maybeModuleInfo == Nothing
then Instance m paramBindings x rs portBindings
else Instance m paramBindings' x rs portBindings'
where
maybeModuleInfo = Map.lookup m modulePorts
Just (paramNames, portNames) = maybeModuleInfo
msg :: String -> String
msg = flip (++) $ " in instance " ++ show x ++ " of " ++ show m
paramBindings' = resolveBindings (msg "parameter overrides") paramNames
paramBindings
portBindings' = resolveBindings (msg "port connections") portNames
$ concatMap expandStar portBindings
expandStar :: PortBinding -> [PortBinding]
expandStar ("*", Nil) =
map (\port -> (port, Ident port)) $
filter (flip notElem alreadyBound) portNames
where alreadyBound = map fst portBindings
expandStar other = [other]
mapInstance _ other = other
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for `.*` in module instantiation
-}
module Convert.StarPort (convert) where
import Control.Monad.Writer.Strict
import qualified Data.Map.Strict as Map
import Convert.Traverse
import Language.SystemVerilog.AST
type Ports = Map.Map Identifier [Identifier]
convert :: [AST] -> [AST]
convert =
traverseFiles
(collectDescriptionsM collectPortsM)
(traverseDescriptions . traverseModuleItems . mapInstance)
collectPortsM :: Description -> Writer Ports ()
collectPortsM (Part _ _ _ _ name ports _) = tell $ Map.singleton name ports
collectPortsM _ = return ()
mapInstance :: Ports -> ModuleItem -> ModuleItem
mapInstance modulePorts (Instance m p x rs bindings) =
Instance m p x rs $ concatMap expandBinding bindings
where
alreadyBound :: [Identifier]
alreadyBound = map fst bindings
expandBinding :: PortBinding -> [PortBinding]
expandBinding ("*", Nil) =
case Map.lookup m modulePorts of
Just l ->
map (\port -> (port, Ident port)) $
filter (\s -> not $ elem s alreadyBound) $ l
-- if we can't find it, just skip :(
Nothing -> [("*", Nil)]
expandBinding other = [other]
mapInstance _ other = other
......@@ -1109,7 +1109,7 @@ traverseNestedModuleItemsM mapper = fullMapper
Nothing -> return $ GenIf (Number n) s1 s2
Just 0 -> genItemMapper s2
Just _ -> genItemMapper s1
genItemMapper (GenBlock "" [item]) = return item
genItemMapper (GenBlock "" [item]) = genItemMapper item
genItemMapper (GenBlock _ []) = return GenNull
genItemMapper other = return other
......
......@@ -88,13 +88,12 @@ shortHash x =
type Binding t = (Identifier, t)
-- give a set of bindings explicit names
resolveBindings :: Show t => [Identifier] -> [Binding t] -> [Binding t]
resolveBindings available bindings =
zipWith resolveBinding bindings [0..]
where
resolveBinding ("", e) idx =
if idx < length available
then (available !! idx, e)
else error $ "binding " ++ show e ++ " is out of range "
++ show available
resolveBinding other _ = other
resolveBindings :: String -> [Identifier] -> [Binding t] -> [Binding t]
resolveBindings _ _ [] = []
resolveBindings location available bindings =
if length available < length bindings then
error $ "too many bindings specified for " ++ location
else if null $ fst $ head bindings then
zip available $ map snd bindings
else
bindings
......@@ -87,9 +87,9 @@ executable sv2v
Convert.ParamNoDefault
Convert.ParamType
Convert.RemoveComments
Convert.ResolveBindings
Convert.Scoper
Convert.Simplify
Convert.StarPort
Convert.Stream
Convert.StringParam
Convert.Struct
......
// pattern: too many bindings specified for parameters in class specialization of "example"
class example #(
parameter P = 1,
parameter Q = 1
);
typedef logic [P * Q:0] T;
endclass
module top;
example#(1, 2, 3)::T x;
endmodule
// pattern: too many bindings specified for parameter overrides in instance "e" of "example"
module example;
parameter P = 1;
parameter Q = 1;
endmodule
module top;
example #(1, 2, 3) e();
endmodule
// pattern: too many bindings specified for port connections in instance "e" of "example"
module example(
input x, y
);
endmodule
module top;
example e(1'b1, 1'b0, 1'b0);
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