Commit e80db124 by Zachary Snow

conversion for implicitly variably sized parameters

parent e4135bb8
...@@ -39,6 +39,7 @@ import qualified Convert.Simplify ...@@ -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 = ...@@ -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)
......
{-# 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 ...@@ -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 ...@@ -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 ...@@ -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
......
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);
......
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
`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
`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
`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
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