Commit ea56f51d by Zachary Snow

support for parameters without defaults

parent e94c0346
......@@ -33,6 +33,7 @@ import qualified Convert.MultiplePacked
import qualified Convert.NamedBlock
import qualified Convert.NestPI
import qualified Convert.Package
import qualified Convert.ParamNoDefault
import qualified Convert.ParamType
import qualified Convert.RemoveComments
import qualified Convert.SignCast
......@@ -109,7 +110,9 @@ run excludes = foldr (.) id $ phases excludes
convert :: [Job.Exclude] -> Phase
convert excludes =
convert' . Convert.NestPI.reorder
convert'
. Convert.NestPI.reorder
. Convert.ParamNoDefault.convert
where
convert' :: Phase
convert' descriptions =
......
......@@ -588,19 +588,6 @@ pattern InstArrKey expr = Dot (Bit expr (RawNum 0)) InstArrName
pattern InstArrEncoded :: Expr -> Expr -> ModuleItem
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
parameterNames :: [ModuleItem] -> [Identifier]
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
, exprToLHS
, lhsToExpr
, shortHash
, resolveBindings
) where
import Text.Printf (printf)
......@@ -84,3 +85,16 @@ shortHash :: (Show a) => a -> String
shortHash x =
take 5 $ printf "%05X" val
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
instance Show Decl where
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
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)
......
......@@ -923,6 +923,8 @@ DeclAsgns :: { [(Identifier, Expr, [Range])] }
DeclAsgn :: { (Identifier, Expr, [Range]) }
: Identifier "=" Expr { ($1, $3, []) }
| Identifier DimensionsNonEmpty "=" Expr { ($1, $4, $2) }
| Identifier { ($1, Nil, []) }
| Identifier DimensionsNonEmpty { ($1, Nil, $2) }
Range :: { Range }
: "[" Expr ":" Expr "]" { ($2, $4) }
......
......@@ -83,6 +83,7 @@ executable sv2v
Convert.NamedBlock
Convert.NestPI
Convert.Package
Convert.ParamNoDefault
Convert.ParamType
Convert.RemoveComments
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