mirror of https://github.com/zachjs/sv2v.git
conversion for implicitly variably sized parameters
This commit is contained in:
parent
e4135bb896
commit
e80db12422
|
|
@ -39,6 +39,7 @@ import qualified Convert.Simplify
|
||||||
import qualified Convert.SizeCast
|
import qualified Convert.SizeCast
|
||||||
import qualified Convert.StarPort
|
import qualified Convert.StarPort
|
||||||
import qualified Convert.Stream
|
import qualified Convert.Stream
|
||||||
|
import qualified Convert.StringParam
|
||||||
import qualified Convert.Struct
|
import qualified Convert.Struct
|
||||||
import qualified Convert.TFBlock
|
import qualified Convert.TFBlock
|
||||||
import qualified Convert.Typedef
|
import qualified Convert.Typedef
|
||||||
|
|
@ -89,6 +90,7 @@ phases excludes =
|
||||||
, Convert.ForDecl.convert
|
, Convert.ForDecl.convert
|
||||||
, Convert.Jump.convert
|
, Convert.Jump.convert
|
||||||
, Convert.Foreach.convert
|
, Convert.Foreach.convert
|
||||||
|
, Convert.StringParam.convert
|
||||||
, selectExclude (Job.Interface, Convert.Interface.convert)
|
, selectExclude (Job.Interface, Convert.Interface.convert)
|
||||||
, selectExclude (Job.Always , Convert.AlwaysKW.convert)
|
, selectExclude (Job.Always , Convert.AlwaysKW.convert)
|
||||||
, selectExclude (Job.Succinct , Convert.RemoveComments.convert)
|
, selectExclude (Job.Succinct , Convert.RemoveComments.convert)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
{-# LANGUAGE PatternSynonyms #-}
|
||||||
|
{- sv2v
|
||||||
|
- Author: Zachary Snow <zach@zachjs.com>
|
||||||
|
-
|
||||||
|
- Conversion for variable-length string parameters
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Convert.StringParam (convert) where
|
||||||
|
|
||||||
|
import Control.Monad.Writer.Strict
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
|
||||||
|
import Convert.Traverse
|
||||||
|
import Language.SystemVerilog.AST
|
||||||
|
|
||||||
|
type PartStringParams = Map.Map Identifier [(Identifier, Int)]
|
||||||
|
|
||||||
|
convert :: [AST] -> [AST]
|
||||||
|
convert files =
|
||||||
|
if Map.null partStringParams
|
||||||
|
then files
|
||||||
|
else map traverseModuleItem files'
|
||||||
|
where
|
||||||
|
(files', partStringParams) = runWriter $
|
||||||
|
mapM (traverseDescriptionsM traverseDescriptionM) files
|
||||||
|
traverseModuleItem = traverseDescriptions $ traverseModuleItems $
|
||||||
|
mapInstance partStringParams
|
||||||
|
|
||||||
|
-- adds automatic width parameters for string parameters
|
||||||
|
traverseDescriptionM :: Description -> Writer PartStringParams Description
|
||||||
|
traverseDescriptionM (Part attrs extern kw lifetime name ports items) =
|
||||||
|
if null stringParamNames
|
||||||
|
then return $ Part attrs extern kw lifetime name ports items
|
||||||
|
else do
|
||||||
|
tell $ Map.singleton name stringParamIds
|
||||||
|
return $ Part attrs extern kw lifetime name ports items'
|
||||||
|
where
|
||||||
|
(items', stringParamNames) = runWriter $
|
||||||
|
mapM (traverseNestedModuleItemsM traverseModuleItemM) items
|
||||||
|
allParamNames = parameterNames items
|
||||||
|
stringParamIds = filter (flip elem stringParamNames . fst) $
|
||||||
|
zip allParamNames [0..]
|
||||||
|
traverseDescriptionM other = return other
|
||||||
|
|
||||||
|
-- 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 ()
|
||||||
|
|
||||||
|
pattern UnknownType :: Type
|
||||||
|
pattern UnknownType = Implicit Unspecified []
|
||||||
|
|
||||||
|
-- rewrite an existing string parameter
|
||||||
|
traverseModuleItemM :: ModuleItem -> Writer [Identifier] ModuleItem
|
||||||
|
traverseModuleItemM (orig @ (MIPackageItem (Decl (Param Parameter t x e)))) =
|
||||||
|
case (t, e) of
|
||||||
|
(UnknownType, String str) -> do
|
||||||
|
tell [x]
|
||||||
|
return $ Generate $ map wrap [width str, param str]
|
||||||
|
where wrap = GenModuleItem . MIPackageItem . Decl
|
||||||
|
_ -> return orig
|
||||||
|
where
|
||||||
|
w = widthName x
|
||||||
|
r = (BinOp Sub (Ident w) (RawNum 1), RawNum 0)
|
||||||
|
t' = IntegerVector TBit Unspecified [r]
|
||||||
|
defaultWidth str = DimsFn FnBits $ Right $ String str
|
||||||
|
width str = Param Parameter UnknownType w (defaultWidth str)
|
||||||
|
param str = Param Parameter t' x (String str)
|
||||||
|
traverseModuleItemM other = return other
|
||||||
|
|
||||||
|
widthName :: Identifier -> Identifier
|
||||||
|
widthName paramName = "_sv2v_width_" ++ paramName
|
||||||
|
|
||||||
|
-- convert isntances which use the converted string parameters
|
||||||
|
mapInstance :: PartStringParams -> ModuleItem -> ModuleItem
|
||||||
|
mapInstance partStringParams (Instance m params x rs ports) =
|
||||||
|
case Map.lookup m partStringParams of
|
||||||
|
Nothing -> Instance m params x rs ports
|
||||||
|
Just stringParams -> Instance m params' x rs ports
|
||||||
|
where params' = concat $ zipWith (expand stringParams) params [0..]
|
||||||
|
where
|
||||||
|
expand :: [(Identifier, Int)] -> ParamBinding -> Int -> [ParamBinding]
|
||||||
|
expand _ (paramName, Left t) _ = [(paramName, Left t)]
|
||||||
|
expand stringParams (orig @ ("", Right expr)) idx =
|
||||||
|
if elem idx $ map snd stringParams
|
||||||
|
then [("", Right width), orig]
|
||||||
|
else [orig]
|
||||||
|
where width = DimsFn FnBits $ Right expr
|
||||||
|
expand stringParams (orig @ (paramName, Right expr)) _ =
|
||||||
|
if elem paramName $ map fst stringParams
|
||||||
|
then [(widthName paramName, Right width), orig]
|
||||||
|
else [orig]
|
||||||
|
where width = DimsFn FnBits $ Right expr
|
||||||
|
mapInstance _ other = other
|
||||||
|
|
@ -37,12 +37,12 @@ traverseDeclM decl = do
|
||||||
return $ case t' of
|
return $ case t' of
|
||||||
UnpackedType t'' a' -> Variable d t'' ident a' e
|
UnpackedType t'' a' -> Variable d t'' ident a' e
|
||||||
_ -> Variable d t' ident [] e
|
_ -> Variable d t' ident [] e
|
||||||
Param _ t ident e -> do
|
Param _ UnknownType ident String{} ->
|
||||||
t' <- if t == UnknownType
|
insertElem ident UnknownType >> return decl'
|
||||||
then typeof e
|
Param _ UnknownType ident e ->
|
||||||
else return t
|
typeof e >>= insertElem ident >> return decl'
|
||||||
insertElem ident t'
|
Param _ t ident _ ->
|
||||||
return decl'
|
insertElem ident t >> return decl'
|
||||||
ParamType{} -> return decl'
|
ParamType{} -> return decl'
|
||||||
CommentDecl{} -> return decl'
|
CommentDecl{} -> return decl'
|
||||||
|
|
||||||
|
|
@ -137,25 +137,39 @@ typeof (BinOp ShiftL e _) = typeof e
|
||||||
typeof (BinOp ShiftR e _) = typeof e
|
typeof (BinOp ShiftR e _) = typeof e
|
||||||
typeof (BinOp ShiftAL e _) = typeof e
|
typeof (BinOp ShiftAL e _) = typeof e
|
||||||
typeof (BinOp ShiftAR e _) = typeof e
|
typeof (BinOp ShiftAR e _) = typeof e
|
||||||
typeof (BinOp Add a b) = return $ largerSizeType a b
|
typeof (BinOp Add a b) = largerSizeType a b
|
||||||
typeof (BinOp Sub a b) = return $ largerSizeType a b
|
typeof (BinOp Sub a b) = largerSizeType a b
|
||||||
typeof (BinOp Mul a b) = return $ largerSizeType a b
|
typeof (BinOp Mul a b) = largerSizeType a b
|
||||||
typeof (BinOp Div a b) = return $ largerSizeType a b
|
typeof (BinOp Div a b) = largerSizeType a b
|
||||||
typeof (BinOp Mod a b) = return $ largerSizeType a b
|
typeof (BinOp Mod a b) = largerSizeType a b
|
||||||
typeof (BinOp BitAnd a b) = return $ largerSizeType a b
|
typeof (BinOp BitAnd a b) = largerSizeType a b
|
||||||
typeof (BinOp BitXor a b) = return $ largerSizeType a b
|
typeof (BinOp BitXor a b) = largerSizeType a b
|
||||||
typeof (BinOp BitXnor a b) = return $ largerSizeType a b
|
typeof (BinOp BitXnor a b) = largerSizeType a b
|
||||||
typeof (BinOp BitOr a b) = return $ largerSizeType a b
|
typeof (BinOp BitOr a b) = largerSizeType a b
|
||||||
typeof (Mux _ a b) = return $ largerSizeType a b
|
typeof (Mux _ a b) = largerSizeType a b
|
||||||
typeof (Concat exprs) = return $ typeOfSize $ concatSize exprs
|
typeof (Concat exprs) = return $ typeOfSize $ concatSize exprs
|
||||||
typeof (Repeat reps exprs) = return $ typeOfSize size
|
typeof (Repeat reps exprs) = return $ typeOfSize size
|
||||||
where size = BinOp Mul reps (concatSize exprs)
|
where size = BinOp Mul reps (concatSize exprs)
|
||||||
typeof String{} = return UnknownType
|
typeof (String str) =
|
||||||
|
return $ IntegerVector TBit Unspecified [r]
|
||||||
|
where
|
||||||
|
r = (RawNum $ len - 1, RawNum 0)
|
||||||
|
len = if null str then 1 else 8 * unescapedLength str
|
||||||
|
unescapedLength :: String -> Integer
|
||||||
|
unescapedLength [] = 0
|
||||||
|
unescapedLength ('\\' : _ : rest) = 1 + unescapedLength rest
|
||||||
|
unescapedLength (_ : rest) = 1 + unescapedLength rest
|
||||||
typeof other = lookupTypeOf other
|
typeof other = lookupTypeOf other
|
||||||
|
|
||||||
-- produces a type large enough to hold either expression
|
-- produces a type large enough to hold either expression
|
||||||
largerSizeType :: Expr -> Expr -> Type
|
largerSizeType :: Expr -> Expr -> Scoper Type Type
|
||||||
largerSizeType a b = typeOfSize $ largerSizeOf a b
|
largerSizeType a (Number (Based 1 _ _ _ _)) = typeof a
|
||||||
|
largerSizeType a b = do
|
||||||
|
t <- typeof a
|
||||||
|
u <- typeof b
|
||||||
|
return $ if t == u
|
||||||
|
then t
|
||||||
|
else typeOfSize $ largerSizeOf a b
|
||||||
|
|
||||||
-- returns the total size of concatenated list of expressions
|
-- returns the total size of concatenated list of expressions
|
||||||
concatSize :: [Expr] -> Expr
|
concatSize :: [Expr] -> Expr
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ executable sv2v
|
||||||
Convert.SizeCast
|
Convert.SizeCast
|
||||||
Convert.StarPort
|
Convert.StarPort
|
||||||
Convert.Stream
|
Convert.Stream
|
||||||
|
Convert.StringParam
|
||||||
Convert.Struct
|
Convert.Struct
|
||||||
Convert.TFBlock
|
Convert.TFBlock
|
||||||
Convert.Traverse
|
Convert.Traverse
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
module top;
|
module top;
|
||||||
parameter FOO = "some useful string";
|
localparam FOO = "some useful string";
|
||||||
localparam type T = type(FOO);
|
localparam type T = type(FOO);
|
||||||
localparam T BAR = "some other useful string";
|
localparam T BAR = "some other useful string";
|
||||||
initial $display("'%s' '%s'", FOO, BAR);
|
initial $display("'%s' '%s'", FOO, BAR);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
module top;
|
module top;
|
||||||
parameter FOO = "some useful string";
|
localparam FOO = "some useful string";
|
||||||
localparam BAR = "some other useful string";
|
localparam BAR = "some other useful string";
|
||||||
initial $display("'%s' '%s'", FOO, BAR);
|
initial $display("'%s' '%s'", FOO, BAR);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
`include "string_param.vh"
|
||||||
|
|
||||||
|
module Example(inp, out);
|
||||||
|
parameter PATTERN = "whatever";
|
||||||
|
parameter UNUSED = 0;
|
||||||
|
localparam IN_WIDTH = $bits(PATTERN);
|
||||||
|
localparam OUT_WIDTH = `COUNT_ONES(PATTERN);
|
||||||
|
|
||||||
|
input [IN_WIDTH - 1:0] inp;
|
||||||
|
output [OUT_WIDTH - 1:0] out;
|
||||||
|
if (PATTERN[0])
|
||||||
|
assign out[0] = inp[0];
|
||||||
|
for (genvar j = 1; j < IN_WIDTH; ++j)
|
||||||
|
if (PATTERN[j])
|
||||||
|
assign out[`COUNT_ONES(PATTERN[j - 1:0])] = inp[j];
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
`include "string_param.vh"
|
||||||
|
|
||||||
|
module Example(inp, out);
|
||||||
|
parameter PATTERN = "whatever";
|
||||||
|
parameter IN_WIDTH = $bits(PATTERN);
|
||||||
|
localparam OUT_WIDTH = `COUNT_ONES(PATTERN);
|
||||||
|
|
||||||
|
input wire [IN_WIDTH - 1:0] inp;
|
||||||
|
output wire [OUT_WIDTH - 1:0] out;
|
||||||
|
if (PATTERN[0])
|
||||||
|
assign out[0] = inp[0];
|
||||||
|
genvar j;
|
||||||
|
for (j = 1; j < IN_WIDTH; j = j + 1)
|
||||||
|
if (PATTERN[j])
|
||||||
|
assign out[`COUNT_ONES(PATTERN[j - 1:0])] = inp[j];
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
`define COUNT_ONES(expr) (0 \
|
||||||
|
+ ((expr) >> 0 & 1'b1) + ((expr) >> 1 & 1'b1) + ((expr) >> 2 & 1'b1) + ((expr) >> 3 & 1'b1) \
|
||||||
|
+ ((expr) >> 4 & 1'b1) + ((expr) >> 5 & 1'b1) + ((expr) >> 6 & 1'b1) + ((expr) >> 7 & 1'b1) \
|
||||||
|
+ ((expr) >> 8 & 1'b1) + ((expr) >> 9 & 1'b1) + ((expr) >> 10 & 1'b1) + ((expr) >> 11 & 1'b1) \
|
||||||
|
+ ((expr) >> 12 & 1'b1) + ((expr) >> 13 & 1'b1) + ((expr) >> 14 & 1'b1) + ((expr) >> 15 & 1'b1) \
|
||||||
|
+ ((expr) >> 16 & 1'b1) + ((expr) >> 17 & 1'b1) + ((expr) >> 18 & 1'b1) + ((expr) >> 19 & 1'b1) \
|
||||||
|
+ ((expr) >> 20 & 1'b1) + ((expr) >> 21 & 1'b1) + ((expr) >> 22 & 1'b1) + ((expr) >> 23 & 1'b1) \
|
||||||
|
+ ((expr) >> 24 & 1'b1) + ((expr) >> 25 & 1'b1) + ((expr) >> 26 & 1'b1) + ((expr) >> 27 & 1'b1) \
|
||||||
|
+ ((expr) >> 28 & 1'b1) + ((expr) >> 29 & 1'b1) + ((expr) >> 30 & 1'b1) + ((expr) >> 31 & 1'b1) \
|
||||||
|
)
|
||||||
|
|
||||||
|
module top;
|
||||||
|
reg [31:0] data;
|
||||||
|
|
||||||
|
`define TEST(idx, pattern, in_width, out_width) \
|
||||||
|
localparam p``idx = pattern; \
|
||||||
|
wire [in_width - 1:0] i``idx; \
|
||||||
|
wire [out_width - 1:0] o``idx; \
|
||||||
|
assign i``idx = data[0+:in_width]; \
|
||||||
|
Example #(p``idx, in_width) e``idx(i``idx, o``idx);
|
||||||
|
|
||||||
|
`TEST(1, 5'b10101, 5, 3)
|
||||||
|
`TEST(2, 10'b1110001111, 10, 7)
|
||||||
|
|
||||||
|
integer i;
|
||||||
|
initial begin
|
||||||
|
data = 0;
|
||||||
|
for (i = 0; i < 100; i = i + 1) begin
|
||||||
|
data = 1664525 * data + 1013904223;
|
||||||
|
#1 $display("%b %b %b", data, o1, o2);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue