mirror of https://github.com/zachjs/sv2v.git
initial parameter type conversion
This commit is contained in:
parent
73e961d7c2
commit
4de585ec0f
|
|
@ -27,6 +27,7 @@ import qualified Convert.NamedBlock
|
|||
import qualified Convert.NestPI
|
||||
import qualified Convert.Package
|
||||
import qualified Convert.PackedArray
|
||||
import qualified Convert.ParamType
|
||||
import qualified Convert.RemoveComments
|
||||
import qualified Convert.Return
|
||||
import qualified Convert.StarPort
|
||||
|
|
@ -54,6 +55,7 @@ phases excludes =
|
|||
, Convert.KWArgs.convert
|
||||
, Convert.Mux.convert
|
||||
, Convert.PackedArray.convert
|
||||
, Convert.ParamType.convert
|
||||
, Convert.StarPort.convert
|
||||
, Convert.StmtBlock.convert
|
||||
, Convert.Stream.convert
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
{- sv2v
|
||||
- Author: Zachary Snow <zach@zachjs.com>
|
||||
-
|
||||
- Conversion for `parameter type` in module instantiations
|
||||
-}
|
||||
|
||||
module Convert.ParamType (convert) where
|
||||
|
||||
import Control.Monad.Writer
|
||||
import Data.Either (isLeft)
|
||||
import Data.Maybe (isJust, isNothing, fromJust)
|
||||
import qualified Data.Map.Strict as Map
|
||||
|
||||
import Convert.Traverse
|
||||
import Language.SystemVerilog.AST
|
||||
|
||||
type MaybeTypeMap = Map.Map Identifier (Maybe Type)
|
||||
type Info = Map.Map Identifier ([Identifier], MaybeTypeMap)
|
||||
|
||||
type Instance = Map.Map Identifier Type
|
||||
type Instances = [(Identifier, Instance)]
|
||||
|
||||
convert :: [AST] -> [AST]
|
||||
convert files =
|
||||
concatMap (map explodeDescription) files'
|
||||
where
|
||||
info = execWriter $
|
||||
mapM (collectDescriptionsM collectDescriptionM) files
|
||||
(files', instancesRaw) = runWriter $ mapM
|
||||
(mapM $ traverseModuleItemsM $ mapInstance info) files
|
||||
instances = reverse $ uniq [] instancesRaw
|
||||
-- TODO: use the unique package
|
||||
uniq curr [] = curr
|
||||
uniq curr (x : xs) =
|
||||
if elem x curr
|
||||
then uniq curr xs
|
||||
else uniq (x : curr) xs
|
||||
|
||||
explodeDescription :: Description -> [Description]
|
||||
explodeDescription (part @ (Part _ _ _ name _ _)) =
|
||||
if null theseInstances
|
||||
then [part]
|
||||
else map (rewriteModule part) theseInstances
|
||||
where theseInstances = map snd $ filter ((== name) . fst) instances
|
||||
explodeDescription other = [other]
|
||||
|
||||
-- TODO FIXME: Need to keep around the default instance and not perform
|
||||
-- substitutions in it.
|
||||
|
||||
-- substitute in a particular instance's paramter types
|
||||
rewriteModule :: Description -> Instance -> Description
|
||||
rewriteModule part typeMap =
|
||||
Part extern kw ml m' p items'
|
||||
where
|
||||
Part extern kw ml m p items = part
|
||||
m' = renameModule info m typeMap
|
||||
items' = map rewriteDecl items
|
||||
rewriteDecl :: ModuleItem -> ModuleItem
|
||||
rewriteDecl (MIPackageItem (Decl (ParamType Parameter x _))) =
|
||||
MIPackageItem $ Typedef (typeMap Map.! x) x
|
||||
rewriteDecl other = other
|
||||
-- TODO FIXME: Typedef conversion must be made to handle
|
||||
-- ParamTypes!
|
||||
-----items' = map (traverseDecls rewriteDecl) items
|
||||
-----rewriteDecl :: Decl -> Decl
|
||||
-----rewriteDecl (ParamType Parameter x _) =
|
||||
----- ParamType Localparam x (Just $ typeMap Map.! x)
|
||||
-----rewriteDecl other = other
|
||||
|
||||
|
||||
-- write down module parameter names and type parameters
|
||||
collectDescriptionM :: Description -> Writer Info ()
|
||||
collectDescriptionM (part @ (Part _ _ _ name _ _)) =
|
||||
tell $ Map.singleton name (paramNames, maybeTypeMap)
|
||||
where
|
||||
params = execWriter $
|
||||
collectModuleItemsM (collectDeclsM collectDeclM) part
|
||||
paramNames = map fst params
|
||||
maybeTypeMap = Map.fromList $
|
||||
map (\(x, y) -> (x, fromJust y)) $
|
||||
filter (isJust . snd) params
|
||||
collectDeclM :: Decl -> Writer [(Identifier, Maybe (Maybe Type))] ()
|
||||
collectDeclM (Param Parameter _ x _) = tell [(x, Nothing)]
|
||||
collectDeclM (ParamType Parameter x v) = tell [(x, Just v )]
|
||||
collectDeclM _ = return ()
|
||||
collectDescriptionM _ = return ()
|
||||
|
||||
-- produces the default type mapping of a module, if there is one
|
||||
defaultInstance :: MaybeTypeMap -> Maybe Instance
|
||||
defaultInstance maybeTypeMap =
|
||||
if any isNothing maybeTypeMap
|
||||
then Nothing
|
||||
else Just $ Map.map fromJust maybeTypeMap
|
||||
|
||||
-- generate a "unique" name for a particular module type instance
|
||||
renameModule :: Info -> Identifier -> Instance -> Identifier
|
||||
renameModule info m inst =
|
||||
if defaultInstance maybeTypeMap == Just inst
|
||||
then m -- default instances keep the original module name
|
||||
else m ++ "_" ++ shortHash (m, inst)
|
||||
where maybeTypeMap = snd $ info Map.! m
|
||||
|
||||
|
||||
mapInstance :: Info -> ModuleItem -> Writer Instances ModuleItem
|
||||
mapInstance info (orig @ (Instance m bindings x r p)) =
|
||||
if Map.notMember m info then
|
||||
return orig
|
||||
else if any (isLeft . snd) bindings' then
|
||||
error $ "param type resolution left type params: " ++ show orig
|
||||
++ " converted to: " ++ show bindings'
|
||||
else do
|
||||
tell [(m, resolvedTypes)]
|
||||
let m' = renameModule info m resolvedTypes
|
||||
return $ Instance m' bindings' x r p
|
||||
where
|
||||
(paramNames, maybeTypeMap) = info Map.! m
|
||||
-- attach names to unnamed parameters
|
||||
bindingsNamed =
|
||||
if all (== "") (map fst bindings) then
|
||||
zip paramNames (map snd bindings)
|
||||
else if any (== "") (map fst bindings) then
|
||||
error $ "instance has a mix of named and unnamed params: "
|
||||
++ show orig
|
||||
else bindings
|
||||
-- determine the types corresponding to each type parameter
|
||||
bindingsMap = Map.fromList bindingsNamed
|
||||
resolvedTypes = Map.mapWithKey resolveType maybeTypeMap
|
||||
resolveType :: Identifier -> Maybe Type -> Type
|
||||
resolveType paramName defaultType =
|
||||
case (Map.lookup paramName bindingsMap, defaultType) of
|
||||
(Nothing, Just t) -> t
|
||||
(Nothing, Nothing) ->
|
||||
error $ "instantiation " ++ show orig ++
|
||||
" is missing a type parameter: " ++ paramName
|
||||
(Just (Left t), _) -> t
|
||||
(Just (Right e), _) ->
|
||||
-- TODO: Some types could have been parsed as an expression
|
||||
-- (i.e. aliases). Ideally we should have any such aliases
|
||||
-- resolved before applying this conversion.
|
||||
error $ "instantiation " ++ show orig ++ " has expr "
|
||||
++ show e ++ " for type param: " ++ paramName
|
||||
-- leave only the normal expression params behind
|
||||
isParamType = flip Map.member maybeTypeMap
|
||||
bindings' = filter (not . isParamType . fst) bindingsNamed
|
||||
mapInstance _ other = return other
|
||||
|
|
@ -71,6 +71,7 @@ executable sv2v
|
|||
Convert.NestPI
|
||||
Convert.Package
|
||||
Convert.PackedArray
|
||||
Convert.ParamType
|
||||
Convert.RemoveComments
|
||||
Convert.Return
|
||||
Convert.StarPort
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
module m_def #(
|
||||
parameter type T = logic
|
||||
);
|
||||
T x = 0;
|
||||
initial begin
|
||||
$display("m_def %b %b %d", x, x+1, $bits(T));
|
||||
end
|
||||
endmodule
|
||||
|
||||
module m_nodef #(
|
||||
parameter type T
|
||||
);
|
||||
T x = 0;
|
||||
initial begin
|
||||
$display("m_nodef %b %b %d", x, x+1, $bits(T));
|
||||
end
|
||||
endmodule
|
||||
|
||||
module n_nodef #(
|
||||
parameter type T,
|
||||
parameter type U
|
||||
);
|
||||
T x = 0;
|
||||
U y = 1;
|
||||
initial begin
|
||||
$display("n_nodef %b %b %d", x, x+1, $bits(T));
|
||||
$display("n_nodef %b %b %d", y, y+1, $bits(U));
|
||||
end
|
||||
endmodule
|
||||
|
||||
module n_def #(
|
||||
parameter type T = logic,
|
||||
parameter type U = logic
|
||||
);
|
||||
T x = 0;
|
||||
U y = 1;
|
||||
initial begin
|
||||
$display("n_def %b %b %d", x, x+1, $bits(T));
|
||||
$display("n_def %b %b %d", y, y+1, $bits(U));
|
||||
end
|
||||
endmodule
|
||||
|
||||
module n_tdef #(
|
||||
parameter type T,
|
||||
parameter type U = logic
|
||||
);
|
||||
T x = 0;
|
||||
U y = 1;
|
||||
initial begin
|
||||
$display("n_tdef %b %b %d", x, x+1, $bits(T));
|
||||
$display("n_tdef %b %b %d", y, y+1, $bits(U));
|
||||
end
|
||||
endmodule
|
||||
|
||||
// TODO Add support for parameters without default values.
|
||||
module o_nodef #(
|
||||
parameter a = 0,
|
||||
parameter type T,
|
||||
parameter type U,
|
||||
parameter b = 0
|
||||
);
|
||||
T x = a;
|
||||
U y = b;
|
||||
initial begin
|
||||
$display("n_nodef a=%d %b %b %d", a, x, x+1, $bits(T));
|
||||
$display("n_nodef b=%d %b %b %d", b, y, y+1, $bits(U));
|
||||
end
|
||||
endmodule
|
||||
|
||||
module top; endmodule
|
||||
|
||||
// Top level modules appear to be generally instantiated in lexicographic order,
|
||||
// but instances within a module do not. This silliness helps produce more
|
||||
// consistent output.
|
||||
|
||||
module a_1; m_def x(); endmodule
|
||||
module a_2; m_def #(logic [1:0]) x(); endmodule
|
||||
module a_3; m_def #(.T(logic [1:0])) x(); endmodule
|
||||
|
||||
module b_1; m_nodef #(logic [1:0]) x(); endmodule
|
||||
module b_2; m_nodef #(.T(logic [1:0])) x(); endmodule
|
||||
|
||||
module c_1; n_nodef #(logic [1:0], logic [2:0]) x(); endmodule
|
||||
module c_2; n_nodef #(.T(logic [1:0]), .U(logic)) x(); endmodule
|
||||
module c_3; n_nodef #(.U(logic), .T(logic [1:0])) x(); endmodule
|
||||
|
||||
module d_1; n_def #(logic [1:0], logic [2:0]) x(); endmodule
|
||||
module d_2; n_def #(.T(logic [1:0])) x(); endmodule
|
||||
module d_3; n_def #(.U(logic [1:0])) x(); endmodule
|
||||
module d_4; n_def #(.U(logic), .T(logic [1:0])) x(); endmodule
|
||||
|
||||
module e_1; n_tdef #(logic [1:0], logic [2:0]) x(); endmodule
|
||||
module e_2; n_tdef #(.T(logic [1:0]), .U(logic)) x(); endmodule
|
||||
module e_3; n_tdef #(.U(logic), .T(logic [1:0])) x(); endmodule
|
||||
|
||||
module f_1; o_nodef #(1, logic [1:0], logic [2:0], 0) x(); endmodule
|
||||
module f_2; o_nodef #(.T(logic [1:0]), .U(logic), .b(1), .a(0)) x(); endmodule
|
||||
module f_3; o_nodef #(0, logic [1:0], logic [2:0], 1) x(); endmodule
|
||||
module f_4; o_nodef #(.T(logic [1:0]), .U(logic), .b(0), .a(1)) x(); endmodule
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
module top;
|
||||
initial begin
|
||||
// generated by running a commercial simulator
|
||||
$display("m_def 0 00000000000000000000000000000001 1");
|
||||
$display("m_def 00 00000000000000000000000000000001 2");
|
||||
$display("m_def 00 00000000000000000000000000000001 2");
|
||||
$display("m_nodef 00 00000000000000000000000000000001 2");
|
||||
$display("m_nodef 00 00000000000000000000000000000001 2");
|
||||
$display("n_nodef 00 00000000000000000000000000000001 2");
|
||||
$display("n_nodef 001 00000000000000000000000000000010 3");
|
||||
$display("n_nodef 00 00000000000000000000000000000001 2");
|
||||
$display("n_nodef 1 00000000000000000000000000000010 1");
|
||||
$display("n_nodef 00 00000000000000000000000000000001 2");
|
||||
$display("n_nodef 1 00000000000000000000000000000010 1");
|
||||
$display("n_def 00 00000000000000000000000000000001 2");
|
||||
$display("n_def 001 00000000000000000000000000000010 3");
|
||||
$display("n_def 00 00000000000000000000000000000001 2");
|
||||
$display("n_def 1 00000000000000000000000000000010 1");
|
||||
$display("n_def 0 00000000000000000000000000000001 1");
|
||||
$display("n_def 01 00000000000000000000000000000010 2");
|
||||
$display("n_def 00 00000000000000000000000000000001 2");
|
||||
$display("n_def 1 00000000000000000000000000000010 1");
|
||||
$display("n_tdef 00 00000000000000000000000000000001 2");
|
||||
$display("n_tdef 001 00000000000000000000000000000010 3");
|
||||
$display("n_tdef 00 00000000000000000000000000000001 2");
|
||||
$display("n_tdef 1 00000000000000000000000000000010 1");
|
||||
$display("n_tdef 00 00000000000000000000000000000001 2");
|
||||
$display("n_tdef 1 00000000000000000000000000000010 1");
|
||||
$display("n_nodef a= 1 01 00000000000000000000000000000010 2");
|
||||
$display("n_nodef b= 0 000 00000000000000000000000000000001 3");
|
||||
$display("n_nodef a= 0 00 00000000000000000000000000000001 2");
|
||||
$display("n_nodef b= 1 1 00000000000000000000000000000010 1");
|
||||
$display("n_nodef a= 0 00 00000000000000000000000000000001 2");
|
||||
$display("n_nodef b= 1 001 00000000000000000000000000000010 3");
|
||||
$display("n_nodef a= 1 01 00000000000000000000000000000010 2");
|
||||
$display("n_nodef b= 0 0 00000000000000000000000000000001 1");
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue