Commit ea56f51d by Zachary Snow

support for parameters without defaults

parent e94c0346
...@@ -33,6 +33,7 @@ import qualified Convert.MultiplePacked ...@@ -33,6 +33,7 @@ import qualified Convert.MultiplePacked
import qualified Convert.NamedBlock import qualified Convert.NamedBlock
import qualified Convert.NestPI import qualified Convert.NestPI
import qualified Convert.Package import qualified Convert.Package
import qualified Convert.ParamNoDefault
import qualified Convert.ParamType import qualified Convert.ParamType
import qualified Convert.RemoveComments import qualified Convert.RemoveComments
import qualified Convert.SignCast import qualified Convert.SignCast
...@@ -109,7 +110,9 @@ run excludes = foldr (.) id $ phases excludes ...@@ -109,7 +110,9 @@ run excludes = foldr (.) id $ phases excludes
convert :: [Job.Exclude] -> Phase convert :: [Job.Exclude] -> Phase
convert excludes = convert excludes =
convert' . Convert.NestPI.reorder convert'
. Convert.NestPI.reorder
. Convert.ParamNoDefault.convert
where where
convert' :: Phase convert' :: Phase
convert' descriptions = convert' descriptions =
......
...@@ -588,19 +588,6 @@ pattern InstArrKey expr = Dot (Bit expr (RawNum 0)) InstArrName ...@@ -588,19 +588,6 @@ pattern InstArrKey expr = Dot (Bit expr (RawNum 0)) InstArrName
pattern InstArrEncoded :: Expr -> Expr -> ModuleItem pattern InstArrEncoded :: Expr -> Expr -> ModuleItem
pattern InstArrEncoded l r = Modport InstArrName (InstArrVal l r) pattern InstArrEncoded l r = Modport InstArrName (InstArrVal l r)
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
-- given a list of module items, produces the parameter names in order -- given a list of module items, produces the parameter names in order
parameterNames :: [ModuleItem] -> [Identifier] parameterNames :: [ModuleItem] -> [Identifier]
parameterNames = parameterNames =
......
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for parameters without default values
-
- This conversion ensures that any parameters which don't have a default value
- are always given an explicit value wherever that module or interface is used.
-
- Parameters are given a fake default value if they do not have one so that the
- given source for that module can be consumed by downstream tools. This is not
- done for type parameters, as those modules are rewritten by a separate
- conversion. Localparams without defaults are expressly caught and forbidden.
-}
module Convert.ParamNoDefault (convert) where
import Control.Monad.Writer.Strict
import Data.List (intercalate)
import qualified Data.Map.Strict as Map
import Convert.Traverse
import Language.SystemVerilog.AST
type Parts = Map.Map Identifier [(Identifier, Bool)]
convert :: [AST] -> [AST]
convert files =
map convertFile files'
where
(files', parts) = runWriter $
mapM (traverseDescriptionsM traverseDescriptionM) files
convertFile = traverseDescriptions $ traverseModuleItems $
traverseModuleItem parts
traverseDescriptionM :: Description -> Writer Parts Description
traverseDescriptionM (Part attrs extern kw lifetime name ports items) = do
let (items', params) = runWriter $ mapM traverseModuleItemM items
tell $ Map.singleton name params
return $ Part attrs extern kw lifetime name ports items'
traverseDescriptionM other = return other
traverseModuleItemM :: ModuleItem -> Writer [(Identifier, Bool)] ModuleItem
traverseModuleItemM (MIAttr attr item) =
traverseModuleItemM item >>= return . MIAttr attr
traverseModuleItemM (MIPackageItem (Decl decl)) =
traverseDeclM decl >>= return . MIPackageItem . Decl
traverseModuleItemM other = return other
-- writes down the parameters for a part
traverseDeclM :: Decl -> Writer [(Identifier, Bool)] Decl
traverseDeclM (Param Localparam _ x Nil) =
error $ "localparam " ++ show x ++ " has no default value"
traverseDeclM (Param Parameter t x e) = do
tell [(x, e == Nil)]
return $ if e == Nil
then Param Parameter t x $ RawNum 0
else Param Parameter t x e
traverseDeclM (ParamType Localparam x Nothing) =
error $ "localparam type " ++ show x ++ " has no default value"
traverseDeclM (ParamType Parameter x mt) = do
-- parameter types are rewritten separately, so no fake default here
tell [(x, mt == Nothing)]
return $ ParamType Parameter x mt
traverseDeclM other = return other
-- check for instances missing values for parameters without defaults
traverseModuleItem :: Parts -> ModuleItem -> ModuleItem
traverseModuleItem parts (orig @ (Instance part params name _ _)) =
if maybePartInfo == Nothing || null missingParams
then orig
else error $ "instance " ++ show name ++ " of " ++ show part
++ " is missing values for parameters without defaults: "
++ (intercalate " " $ map show missingParams)
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
traverseModuleItem _ other = other
-- whether a given parameter is unspecified in the given parameter bindings
needsDefault :: [(Identifier, TypeOrExpr)] -> Identifier -> Bool
needsDefault instanceParams param =
case lookup param instanceParams of
Nothing -> True
Just (Right Nil) -> True
Just _ -> False
...@@ -29,6 +29,7 @@ module Language.SystemVerilog.AST ...@@ -29,6 +29,7 @@ module Language.SystemVerilog.AST
, exprToLHS , exprToLHS
, lhsToExpr , lhsToExpr
, shortHash , shortHash
, resolveBindings
) where ) where
import Text.Printf (printf) import Text.Printf (printf)
...@@ -84,3 +85,16 @@ shortHash :: (Show a) => a -> String ...@@ -84,3 +85,16 @@ shortHash :: (Show a) => a -> String
shortHash x = shortHash x =
take 5 $ printf "%05X" val take 5 $ printf "%05X" val
where val = hash $ show x where val = hash $ show 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
...@@ -28,7 +28,7 @@ data Decl ...@@ -28,7 +28,7 @@ data Decl
instance Show Decl where instance Show Decl where
showList l _ = unlines' $ map show l showList l _ = unlines' $ map show l
show (Param s t x e) = printf "%s %s%s = %s;" (show s) (showPad t) x (show e) show (Param s t x e) = printf "%s %s%s%s;" (show s) (showPad t) x (showAssignment e)
show (ParamType s x mt) = printf "%s type %s%s;" (show s) x tStr show (ParamType s x mt) = printf "%s type %s%s;" (show s) x tStr
where tStr = maybe "" ((" = " ++) . show) mt where tStr = maybe "" ((" = " ++) . show) mt
show (Variable d t x a e) = printf "%s%s%s%s%s;" (showPad d) (showPad t) x (showRanges a) (showAssignment e) show (Variable d t x a e) = printf "%s%s%s%s%s;" (showPad d) (showPad t) x (showRanges a) (showAssignment e)
......
...@@ -921,8 +921,10 @@ DeclAsgns :: { [(Identifier, Expr, [Range])] } ...@@ -921,8 +921,10 @@ DeclAsgns :: { [(Identifier, Expr, [Range])] }
: DeclAsgn { [$1] } : DeclAsgn { [$1] }
| DeclAsgns "," DeclAsgn { $1 ++ [$3] } | DeclAsgns "," DeclAsgn { $1 ++ [$3] }
DeclAsgn :: { (Identifier, Expr, [Range]) } DeclAsgn :: { (Identifier, Expr, [Range]) }
: Identifier "=" Expr { ($1, $3, []) } : Identifier "=" Expr { ($1, $3, []) }
| Identifier DimensionsNonEmpty "=" Expr { ($1, $4, $2) } | Identifier DimensionsNonEmpty "=" Expr { ($1, $4, $2) }
| Identifier { ($1, Nil, []) }
| Identifier DimensionsNonEmpty { ($1, Nil, $2) }
Range :: { Range } Range :: { Range }
: "[" Expr ":" Expr "]" { ($2, $4) } : "[" Expr ":" Expr "]" { ($2, $4) }
......
...@@ -83,6 +83,7 @@ executable sv2v ...@@ -83,6 +83,7 @@ executable sv2v
Convert.NamedBlock Convert.NamedBlock
Convert.NestPI Convert.NestPI
Convert.Package Convert.Package
Convert.ParamNoDefault
Convert.ParamType Convert.ParamType
Convert.RemoveComments Convert.RemoveComments
Convert.Scoper Convert.Scoper
......
`define DUMP(name) initial $display(`"name W=%b $bits(X)=%0d Y=%b $bits(Z)=%0d", W, $bits(X), Y, $bits(Z));
interface InterfaceA #(
parameter W,
parameter type X,
parameter byte Y,
parameter type Z
);
`DUMP(InterfaceA)
endinterface
interface InterfaceB;
parameter W;
parameter type X;
parameter byte Y;
parameter type Z;
`DUMP(InterfaceB)
endinterface
module ModuleA #(
parameter W,
parameter type X,
parameter byte Y,
parameter type Z
);
`DUMP(ModuleA)
endmodule
module ModuleB;
parameter W;
parameter type X;
parameter byte Y;
parameter type Z;
`DUMP(ModuleB)
endmodule
module top;
`define PARAMS_A #(.Y(6), .X(logic [4:0]), .Z(logic [6:0]), .W(4))
`define PARAMS_B #(0, logic, 2, logic [2:0])
InterfaceA `PARAMS_A ia1();
InterfaceA `PARAMS_B ia2();
InterfaceB `PARAMS_A ib1();
InterfaceB `PARAMS_B ib2();
ModuleA `PARAMS_A ma1();
ModuleA `PARAMS_B ma2();
ModuleB `PARAMS_A mb1();
ModuleB `PARAMS_B mb2();
endmodule
`define DUMP(name) initial $display(`"name W=%b $bits(X)=%0d Y=%b $bits(Z)=%0d`", W, X, Y, Z);
module InterfaceA #(
parameter W = 9,
parameter X = 9,
parameter [7:0] Y = 9,
parameter Z = 9
);
`DUMP(InterfaceA)
endmodule
module InterfaceB;
parameter W = 9;
parameter X = 9;
parameter [7:0] Y = 9;
parameter Z = 9;
`DUMP(InterfaceB)
endmodule
module ModuleA #(
parameter W = 9,
parameter X = 9,
parameter [7:0] Y = 9,
parameter Z = 9
);
`DUMP(ModuleA)
endmodule
module ModuleB;
parameter W = 9;
parameter X = 9;
parameter [7:0] Y = 9;
parameter Z = 9;
`DUMP(ModuleB)
endmodule
module top;
`define PARAMS_A #(.Y(6), .X(5), .Z(7), .W(4))
`define PARAMS_B #(0, 1, 2, 3)
InterfaceA `PARAMS_A ia1();
InterfaceA `PARAMS_B ia2();
InterfaceB `PARAMS_A ib1();
InterfaceB `PARAMS_B ib2();
ModuleA `PARAMS_A ma1();
ModuleA `PARAMS_B ma2();
ModuleB `PARAMS_A mb1();
ModuleB `PARAMS_B mb2();
endmodule
// pattern: localparam "X" has no default value
module top;
localparam X;
endmodule
// pattern: localparam type "X" has no default value
module top;
localparam type X;
endmodule
// pattern: instance "e" of "Example" is missing values for parameters without defaults: "X"
module Example;
parameter type X;
endmodule
module top;
Example e();
endmodule
// pattern: instance "bad" of "Example" is missing values for parameters without defaults: "Y"
module Example;
parameter X = 1;
parameter Y;
endmodule
module top;
Example #(.Y(1)) good();
Example #(1) bad();
endmodule
// pattern: instance "bad" of "Example" is missing values for parameters without defaults: "Y"
interface Example;
parameter X = 1;
parameter Y;
endinterface
module top;
Example #(.Y(1)) good();
Example #(.Y()) bad();
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