mirror of https://github.com/zachjs/sv2v.git
refactor positional binding checking and resolution
This commit is contained in:
parent
ba270acb0e
commit
5cc4dce01f
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue