refactor positional binding checking and resolution

This commit is contained in:
Zachary Snow 2021-04-30 13:42:36 -04:00
parent ba270acb0e
commit 5cc4dce01f
12 changed files with 111 additions and 75 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,67 @@
{- 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

View File

@ -1,42 +0,0 @@
{- 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,10 @@
// 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

View File

@ -0,0 +1,8 @@
// 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

View File

@ -0,0 +1,8 @@
// 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