mirror of https://github.com/zachjs/sv2v.git
added input port default conversion
This commit is contained in:
parent
8cc828c77f
commit
5d5723f65d
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
### New Features
|
||||
|
||||
* Added support for module and interface input ports with default values
|
||||
* Added conversion of severity system tasks and elaboration system tasks (e.g.,
|
||||
`$info`) into `$display` tasks that include source file and scope information;
|
||||
pass `-E SeverityTask` to disable this new conversion
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import qualified Convert.Package
|
|||
import qualified Convert.ParamNoDefault
|
||||
import qualified Convert.ParamType
|
||||
import qualified Convert.PortDecl
|
||||
import qualified Convert.PortDefault
|
||||
import qualified Convert.RemoveComments
|
||||
import qualified Convert.ResolveBindings
|
||||
import qualified Convert.SeverityTask
|
||||
|
|
@ -75,6 +76,7 @@ finalPhases _ =
|
|||
, Convert.FuncRet.convert
|
||||
, Convert.TFBlock.convert
|
||||
, Convert.Unsigned.convert
|
||||
, Convert.PortDefault.convert
|
||||
, Convert.StringType.convert
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -631,10 +631,14 @@ inlineInstance global ranges modportBindings items partName
|
|||
|
||||
removeDeclDir :: Decl -> Decl
|
||||
removeDeclDir (Variable _ t x a e) =
|
||||
Variable Local t' x a e
|
||||
where t' = case t of
|
||||
Variable Local t' x a e'
|
||||
where
|
||||
t' = case t of
|
||||
Implicit sg rs -> IntegerVector TLogic sg rs
|
||||
_ -> t
|
||||
e' = if isNothing (lookup x instancePorts)
|
||||
then e
|
||||
else Nil
|
||||
removeDeclDir decl@Net{} =
|
||||
traverseNetAsVar removeDeclDir decl
|
||||
removeDeclDir other = other
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
{- sv2v
|
||||
- Author: Zachary Snow <zach@zachjs.com>
|
||||
-
|
||||
- Conversion for input ports with default values
|
||||
-
|
||||
- The default values are permitted to depend on complex constants declared
|
||||
- within the instantiated module. The relevant constants are copied into the
|
||||
- site of the instantiation.
|
||||
-}
|
||||
|
||||
module Convert.PortDefault (convert) where
|
||||
|
||||
import Control.Monad.Writer.Strict
|
||||
import Data.Functor ((<&>))
|
||||
import qualified Data.Map.Strict as Map
|
||||
import Data.Maybe (isNothing)
|
||||
|
||||
import Convert.Traverse
|
||||
import Convert.UnbasedUnsized (inlineConstants)
|
||||
import Language.SystemVerilog.AST
|
||||
|
||||
type Part = ([ModuleItem], [PortDefault])
|
||||
type Parts = Map.Map Identifier Part
|
||||
type PortDefault = (Identifier, Decl)
|
||||
|
||||
convert :: [AST] -> [AST]
|
||||
convert files =
|
||||
map (traverseDescriptions convertDescription) files'
|
||||
where
|
||||
(files', parts) = runWriter $
|
||||
mapM (traverseDescriptionsM preparePart) files
|
||||
convertDescription = traverseModuleItems $ convertModuleItem parts
|
||||
|
||||
-- remove and record input ports with defaults
|
||||
preparePart :: Description -> Writer Parts Description
|
||||
preparePart description@(Part att ext kw lif name ports items) =
|
||||
if null portDefaults
|
||||
then return description
|
||||
else do
|
||||
tell $ Map.singleton name (items, portDefaults)
|
||||
return $ Part att ext kw lif name ports items'
|
||||
where
|
||||
(items', portDefaults) = runWriter $
|
||||
mapM (traverseNestedModuleItemsM prepareModuleItem) items
|
||||
preparePart other = return other
|
||||
|
||||
prepareModuleItem :: ModuleItem -> Writer [PortDefault] ModuleItem
|
||||
prepareModuleItem (MIPackageItem (Decl decl)) =
|
||||
prepareDecl decl <&> MIPackageItem . Decl
|
||||
prepareModuleItem other = return other
|
||||
|
||||
prepareDecl :: Decl -> Writer [PortDefault] Decl
|
||||
prepareDecl (Variable Input t x [] e) | e /= Nil =
|
||||
preparePortDefault t x e >> return (Variable Input t x [] Nil)
|
||||
prepareDecl (Net Input n s t x [] e) | e /= Nil =
|
||||
preparePortDefault t x e >> return (Net Input n s t x [] Nil)
|
||||
prepareDecl other = return other
|
||||
|
||||
preparePortDefault :: Type -> Identifier -> Expr -> Writer [PortDefault] ()
|
||||
preparePortDefault t x e = tell [(x, decl)]
|
||||
where
|
||||
decl = Param Localparam t' x e
|
||||
t' = case t of
|
||||
Implicit sg [] -> Implicit sg [(RawNum 0, RawNum 0)]
|
||||
_ -> t
|
||||
|
||||
-- add default port bindings to module instances that need them
|
||||
convertModuleItem :: Parts -> ModuleItem -> ModuleItem
|
||||
convertModuleItem parts (Instance moduleName params instanceName ds bindings) =
|
||||
if isNothing maybePart || null neededDecls
|
||||
then instanceBase bindings
|
||||
else Generate $ map GenModuleItem $
|
||||
stubItems ++ [instanceBase $ neededBindings ++ bindings]
|
||||
where
|
||||
instanceBase = Instance moduleName params instanceName ds
|
||||
maybePart = Map.lookup moduleName parts
|
||||
Just (moduleItems, portDefaults) = maybePart
|
||||
|
||||
-- determine which defaulted ports are unbound
|
||||
(neededBindings, neededDecls) = unzip
|
||||
[ ( (port, Ident $ blockName ++ '_' : port)
|
||||
, MIPackageItem $ Decl decl
|
||||
)
|
||||
| (port, decl) <- portDefaults
|
||||
, isNothing (lookup port bindings)
|
||||
]
|
||||
|
||||
-- inline and prefix the declarations used by the defaults
|
||||
stubItems = inlineConstants blockName params moduleItems neededDecls
|
||||
blockName = "sv2v_pd_" ++ instanceName
|
||||
|
||||
convertModuleItem _ other = other
|
||||
|
|
@ -14,7 +14,10 @@
|
|||
- creating hierarchical or generate-scoped references.
|
||||
-}
|
||||
|
||||
module Convert.UnbasedUnsized (convert) where
|
||||
module Convert.UnbasedUnsized
|
||||
( convert
|
||||
, inlineConstants
|
||||
) where
|
||||
|
||||
import Control.Monad.Writer.Strict
|
||||
import Data.Either (isLeft)
|
||||
|
|
@ -62,7 +65,7 @@ convertModuleItem parts (Instance moduleName params instanceName ds bindings) =
|
|||
|
||||
-- checking whether we're ready to inline
|
||||
hasTypeParams = any (isLeft . snd) params
|
||||
moduleIsResolved = isEntirelyResolved selectedStubItems
|
||||
moduleIsResolved = isEntirelyResolved stubItems
|
||||
|
||||
-- transform the existing bindings to reference extension declarations
|
||||
(bindings', extensionDeclLists) = unzip $
|
||||
|
|
@ -71,13 +74,18 @@ convertModuleItem parts (Instance moduleName params instanceName ds bindings) =
|
|||
|
||||
-- inline the necessary portions of the module alongside the selected
|
||||
-- extension declarations
|
||||
stubItems =
|
||||
map (traverseDecls overrideParam) $
|
||||
prefixItems blockName selectedStubItems
|
||||
selectedStubItems = inject rawStubItems extensionDecls
|
||||
rawStubItems = createModuleStub moduleItems
|
||||
stubItems = inlineConstants blockName params moduleItems extensionDecls
|
||||
blockName = "sv2v_uu_" ++ instanceName
|
||||
|
||||
convertModuleItem _ other = convertModuleItem' other
|
||||
|
||||
inlineConstants :: Identifier -> [ParamBinding] -> [ModuleItem] -> [ModuleItem]
|
||||
-> [ModuleItem]
|
||||
inlineConstants blockName params moduleItems =
|
||||
map (traverseDecls overrideParam) .
|
||||
prefixItems blockName .
|
||||
inject (createModuleStub moduleItems)
|
||||
where
|
||||
-- override a parameter value in the stub
|
||||
overrideParam :: Decl -> Decl
|
||||
overrideParam (Param Parameter t x e) =
|
||||
|
|
@ -89,8 +97,6 @@ convertModuleItem parts (Instance moduleName params instanceName ds bindings) =
|
|||
where xOrig = drop (length blockName + 1) x
|
||||
overrideParam decl = decl
|
||||
|
||||
convertModuleItem _ other = convertModuleItem' other
|
||||
|
||||
-- convert a port binding and produce a list of needed extension decls
|
||||
convertBinding :: Identifier -> PortBinding -> (PortBinding, [Decl])
|
||||
convertBinding blockName (portName, expr) =
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ executable sv2v
|
|||
Convert.ParamNoDefault
|
||||
Convert.ParamType
|
||||
Convert.PortDecl
|
||||
Convert.PortDefault
|
||||
Convert.RemoveComments
|
||||
Convert.ResolveBindings
|
||||
Convert.Scoper
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
module M(x, y);
|
||||
parameter P = 0;
|
||||
localparam L = 10;
|
||||
function automatic integer F;
|
||||
input integer inp;
|
||||
return inp + L;
|
||||
endfunction
|
||||
input wire integer x = F(P); // defining a default here is non-standard
|
||||
input wire integer y;
|
||||
initial #1 $display("M %0d %0d", x, y);
|
||||
endmodule
|
||||
|
||||
module N #(
|
||||
parameter type P,
|
||||
parameter type Q = integer,
|
||||
localparam L = 10
|
||||
) (
|
||||
input wire P x = $bits(P) + L,
|
||||
input wire Q y = $bits(Q) + L
|
||||
);
|
||||
initial #1 $display("N %b %b", x, y);
|
||||
endmodule
|
||||
|
||||
interface I #(
|
||||
parameter type P,
|
||||
parameter type Q = integer,
|
||||
localparam L = 10
|
||||
) (
|
||||
input wire P x = $bits(P) + L,
|
||||
input wire Q y = $bits(Q) + L
|
||||
);
|
||||
initial #2 $display("I %b %b", x, y);
|
||||
endinterface
|
||||
|
||||
module top;
|
||||
M m0(0, 0);
|
||||
M m1(.y(1));
|
||||
M#(1) m2(.y(2));
|
||||
|
||||
N#(logic) n0();
|
||||
N#(logic) n1(1'b0);
|
||||
N#(logic) n2(.y(2));
|
||||
N#(byte) n3();
|
||||
N#(byte, shortint) n4();
|
||||
|
||||
I#(logic) i0();
|
||||
I#(logic) i1(0);
|
||||
I#(logic) i2(.y(2));
|
||||
I#(byte) i3();
|
||||
I#(byte, shortint) i4();
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
module top;
|
||||
initial #2 begin
|
||||
$display("M %0d %0d", 0, 0);
|
||||
$display("M %0d %0d", 10, 1);
|
||||
$display("M %0d %0d", 11, 2);
|
||||
|
||||
$display("N %b %b", 1'b1, 32'd42);
|
||||
$display("N %b %b", 1'b0, 32'd42);
|
||||
$display("N %b %b", 1'b1, 32'd2);
|
||||
$display("N %b %b", 8'd18, 32'd42);
|
||||
$display("N %b %b", 8'd18, 16'd26);
|
||||
|
||||
$display("I %b %b", 1'b1, 32'd42);
|
||||
$display("I %b %b", 1'b0, 32'd42);
|
||||
$display("I %b %b", 1'b1, 32'd2);
|
||||
$display("I %b %b", 8'd18, 32'd42);
|
||||
$display("I %b %b", 8'd18, 16'd26);
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue