mirror of https://github.com/zachjs/sv2v.git
preliminary stream conversion
This commit is contained in:
parent
7340464364
commit
af4711a8cf
|
|
@ -31,6 +31,7 @@ import qualified Convert.RemoveComments
|
|||
import qualified Convert.Return
|
||||
import qualified Convert.StarPort
|
||||
import qualified Convert.StmtBlock
|
||||
import qualified Convert.Stream
|
||||
import qualified Convert.Struct
|
||||
import qualified Convert.Typedef
|
||||
import qualified Convert.UnbasedUnsized
|
||||
|
|
@ -56,6 +57,7 @@ phases excludes =
|
|||
, Convert.PackedArray.convert
|
||||
, Convert.StarPort.convert
|
||||
, Convert.StmtBlock.convert
|
||||
, Convert.Stream.convert
|
||||
, Convert.Struct.convert
|
||||
, Convert.Typedef.convert
|
||||
, Convert.UnbasedUnsized.convert
|
||||
|
|
|
|||
|
|
@ -35,11 +35,3 @@ convertStmt (For inits cc asgns stmt) =
|
|||
convertStmt (AsgnBlk (AsgnOp op) lhs expr) =
|
||||
AsgnBlk AsgnOpEq lhs (BinOp op (lhsToExpr lhs) expr)
|
||||
convertStmt other = other
|
||||
|
||||
lhsToExpr :: LHS -> Expr
|
||||
lhsToExpr (LHSIdent x ) = Ident x
|
||||
lhsToExpr (LHSBit l e ) = Bit (lhsToExpr l) e
|
||||
lhsToExpr (LHSRange l m r ) = Range (lhsToExpr l) m r
|
||||
lhsToExpr (LHSDot l x ) = Dot (lhsToExpr l) x
|
||||
lhsToExpr (LHSConcat ls) = Concat $ map lhsToExpr ls
|
||||
lhsToExpr (LHSStream o e ls) = Stream o e $ map lhsToExpr ls
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
module Convert.Bits (convert) where
|
||||
|
||||
import Control.Monad.State
|
||||
import Data.List (elemIndex)
|
||||
import qualified Data.Map.Strict as Map
|
||||
|
||||
import Convert.Traverse
|
||||
|
|
@ -37,7 +38,9 @@ traverseDeclM decl = do
|
|||
Variable _ t ident a _ -> modify $ Map.insert ident (t, a)
|
||||
Parameter t ident _ -> modify $ Map.insert ident (t, [])
|
||||
Localparam t ident _ -> modify $ Map.insert ident (t, [])
|
||||
return decl
|
||||
item <- traverseModuleItemM (MIPackageItem $ Decl decl)
|
||||
let MIPackageItem (Decl decl') = item
|
||||
return decl'
|
||||
|
||||
traverseModuleItemM :: ModuleItem -> State Info ModuleItem
|
||||
traverseModuleItemM item = traverseExprsM traverseExprM item
|
||||
|
|
@ -46,7 +49,8 @@ traverseStmtM :: Stmt -> State Info Stmt
|
|||
traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt
|
||||
|
||||
traverseExprM :: Expr -> State Info Expr
|
||||
traverseExprM = traverseNestedExprsM $ stately convertExpr
|
||||
traverseExprM = traverseNestedExprsM $ stately converter
|
||||
where converter a b = simplify $ (traverseNestedExprs (convertExpr a) b)
|
||||
|
||||
-- simplify a bits expression given scoped type information
|
||||
convertExpr :: Info -> Expr -> Expr
|
||||
|
|
@ -83,6 +87,11 @@ convertExpr info (Bits (Right e)) =
|
|||
Just (t, rs) ->
|
||||
convertExpr info $ Bits $ Left t'
|
||||
where t' = popRange t rs
|
||||
Stream _ _ exprs -> convertExpr info $ Bits $ Right $ Concat exprs
|
||||
Number n ->
|
||||
case elemIndex '\'' n of
|
||||
Nothing -> Bits $ Right $ Number n
|
||||
Just idx -> Number $ take idx n
|
||||
_ -> Bits $ Right e
|
||||
convertExpr _ other = other
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
{- sv2v
|
||||
- Author: Zachary Snow <zach@zachjs.com>
|
||||
-
|
||||
- Conversion of streaming concatenations.
|
||||
-}
|
||||
|
||||
module Convert.Stream (convert) where
|
||||
|
||||
import Control.Monad.Writer
|
||||
import Data.Hashable (hash)
|
||||
|
||||
import Convert.Traverse
|
||||
import Language.SystemVerilog.AST
|
||||
|
||||
type Funcs = [ModuleItem]
|
||||
|
||||
convert :: [AST] -> [AST]
|
||||
convert = map $ traverseDescriptions convertDescription
|
||||
|
||||
convertDescription :: Description -> Description
|
||||
convertDescription (description @ (Part _ _ _ _ _ _)) =
|
||||
Part extern kw lifetime name ports (items ++ funcs)
|
||||
where
|
||||
(description', funcSet) =
|
||||
runWriter $ traverseModuleItemsM (traverseStmtsM traverseStmtM) description
|
||||
Part extern kw lifetime name ports items = description'
|
||||
funcs = reverse $ uniq [] funcSet
|
||||
uniq curr [] = curr
|
||||
uniq curr (x : xs) =
|
||||
if elem x curr
|
||||
then uniq curr xs
|
||||
else uniq (x : curr) xs
|
||||
convertDescription other = other
|
||||
|
||||
streamerBlock :: Expr -> Expr -> (LHS -> Expr -> Stmt) -> LHS -> Expr -> Stmt
|
||||
streamerBlock chunk size asgn output input =
|
||||
Block Nothing
|
||||
[ Variable Local t inp [] $ Just input
|
||||
, Variable Local t out [] Nothing
|
||||
, Variable Local (IntegerAtom TInteger Unspecified) idx [] Nothing
|
||||
, Variable Local (IntegerAtom TInteger Unspecified) bas [] Nothing
|
||||
]
|
||||
[ For inits cmp incr stmt
|
||||
, AsgnBlk AsgnOpEq (LHSIdent bas) (Ident idx)
|
||||
, For inits cmp2 incr2 stmt2
|
||||
, asgn output (Ident out)
|
||||
]
|
||||
where
|
||||
lo = Number "0"
|
||||
hi = BinOp Sub size (Number "1")
|
||||
t = IntegerVector TLogic Unspecified [(hi, lo)]
|
||||
name = streamerBlockName chunk size
|
||||
inp = name ++ "_inp"
|
||||
out = name ++ "_out"
|
||||
idx = name ++ "_idx"
|
||||
bas = name ++ "_bas"
|
||||
-- main chunk loop
|
||||
inits = [Right (LHSIdent idx, lo)]
|
||||
cmp = Just $ BinOp Le (Ident idx) (BinOp Sub hi chunk)
|
||||
incr = [(LHSIdent idx, AsgnOp Add, chunk)]
|
||||
lhs = LHSRange (LHSIdent out) IndexedMinus (BinOp Sub hi (Ident idx), chunk)
|
||||
expr = Range (Ident inp) IndexedPlus (Ident idx, chunk)
|
||||
stmt = AsgnBlk AsgnOpEq lhs expr
|
||||
-- final chunk loop
|
||||
cmp2 = Just $ BinOp Lt (Ident idx) (BinOp Sub size (Ident bas))
|
||||
incr2 = [(LHSIdent idx, AsgnOp Add, Number "1")]
|
||||
lhs2 = LHSBit (LHSIdent out) (Ident idx)
|
||||
expr2 = Bit (Ident inp) (BinOp Add (Ident idx) (Ident bas))
|
||||
stmt2 = AsgnBlk AsgnOpEq lhs2 expr2
|
||||
|
||||
streamerBlockName :: Expr -> Expr -> Identifier
|
||||
streamerBlockName chunk size =
|
||||
"_sv2v_strm_" ++ take 5 str
|
||||
where
|
||||
val = hash $ show (chunk, size)
|
||||
str = tail $ show val
|
||||
|
||||
traverseStmtM :: Stmt -> Writer Funcs Stmt
|
||||
traverseStmtM (AsgnBlk op lhs expr) =
|
||||
traverseAsgnM (lhs, expr) (AsgnBlk op)
|
||||
traverseStmtM (Asgn mt lhs expr) =
|
||||
traverseAsgnM (lhs, expr) (Asgn mt)
|
||||
traverseStmtM other = return other
|
||||
|
||||
traverseAsgnM :: (LHS, Expr) -> (LHS -> Expr -> Stmt) -> Writer Funcs Stmt
|
||||
traverseAsgnM (lhs, Stream StreamR _ exprs) constructor =
|
||||
return $ constructor lhs expr
|
||||
where
|
||||
expr = Concat $ exprs ++ [Repeat delta [Number "1'b0"]]
|
||||
size = Bits $ Right $ lhsToExpr lhs
|
||||
exprSize = Bits $ Right (Concat exprs)
|
||||
delta = BinOp Sub size exprSize
|
||||
traverseAsgnM (LHSStream StreamR _ lhss, expr) constructor =
|
||||
return $ constructor (LHSConcat lhss) expr
|
||||
traverseAsgnM (lhs, Stream StreamL chunk exprs) constructor = do
|
||||
return $ streamerBlock chunk size constructor lhs expr
|
||||
where
|
||||
expr = Concat $ Repeat delta [Number "1'b0"] : exprs
|
||||
size = Bits $ Right $ lhsToExpr lhs
|
||||
exprSize = Bits $ Right (Concat exprs)
|
||||
delta = BinOp Sub size exprSize
|
||||
traverseAsgnM (LHSStream StreamL chunk lhss, expr) constructor = do
|
||||
return $ streamerBlock chunk size constructor lhs expr
|
||||
where
|
||||
lhs = LHSConcat lhss
|
||||
size = Bits $ Right expr
|
||||
traverseAsgnM (lhs, expr) constructor =
|
||||
return $ constructor lhs expr
|
||||
|
|
@ -543,6 +543,7 @@ traverseExprsM' strat exprMapper = moduleItemMapper
|
|||
expr' <- exprMapper expr
|
||||
return $ Assign delay' lhs' expr'
|
||||
moduleItemMapper (MIPackageItem (Function lifetime ret f decls stmts)) = do
|
||||
ret' <- typeMapper ret
|
||||
decls' <-
|
||||
if strat == IncludeTFs
|
||||
then mapM declMapper decls
|
||||
|
|
@ -551,7 +552,7 @@ traverseExprsM' strat exprMapper = moduleItemMapper
|
|||
if strat == IncludeTFs
|
||||
then mapM stmtMapper stmts
|
||||
else return stmts
|
||||
return $ MIPackageItem $ Function lifetime ret f decls' stmts'
|
||||
return $ MIPackageItem $ Function lifetime ret' f decls' stmts'
|
||||
moduleItemMapper (MIPackageItem (Task lifetime f decls stmts)) = do
|
||||
decls' <-
|
||||
if strat == IncludeTFs
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ module Language.SystemVerilog.AST
|
|||
, module Stmt
|
||||
, module Type
|
||||
, exprToLHS
|
||||
, lhsToExpr
|
||||
) where
|
||||
|
||||
import Language.SystemVerilog.AST.Attr as Attr
|
||||
|
|
@ -59,3 +60,11 @@ exprToLHS (Stream o e ls) = do
|
|||
ls' <- mapM exprToLHS ls
|
||||
Just $ LHSStream o e ls'
|
||||
exprToLHS _ = Nothing
|
||||
|
||||
lhsToExpr :: LHS -> Expr
|
||||
lhsToExpr (LHSIdent x ) = Ident x
|
||||
lhsToExpr (LHSBit l e ) = Bit (lhsToExpr l) e
|
||||
lhsToExpr (LHSRange l m r ) = Range (lhsToExpr l) m r
|
||||
lhsToExpr (LHSDot l x ) = Dot (lhsToExpr l) x
|
||||
lhsToExpr (LHSConcat ls) = Concat $ map lhsToExpr ls
|
||||
lhsToExpr (LHSStream o e ls) = Stream o e $ map lhsToExpr ls
|
||||
|
|
|
|||
|
|
@ -123,6 +123,10 @@ readNumber n =
|
|||
-- basic expression simplfication utility to help us generate nicer code in the
|
||||
-- common case of ranges like `[FOO-1:0]`
|
||||
simplify :: Expr -> Expr
|
||||
simplify (Repeat (Number "0") _) = Concat []
|
||||
simplify (Concat [expr]) = expr
|
||||
simplify (Concat exprs) =
|
||||
Concat $ filter (/= Concat []) exprs
|
||||
simplify (orig @ (Call Nothing "$clog2" (Args [Just (Number n)] []))) =
|
||||
case readNumber n of
|
||||
Nothing -> orig
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ executable sv2v
|
|||
Convert.Return
|
||||
Convert.StarPort
|
||||
Convert.StmtBlock
|
||||
Convert.Stream
|
||||
Convert.Struct
|
||||
Convert.Typedef
|
||||
Convert.Traverse
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
module top;
|
||||
|
||||
// Derived from: https://www.amiq.com/consulting/2017/05/29/how-to-pack-data-using-systemverilog-streaming-operators/
|
||||
typedef struct packed {
|
||||
logic [3:0] addr;
|
||||
logic [3:0] data;
|
||||
} packet_t;
|
||||
initial begin
|
||||
// TODO: Add support for implicitly sized arrays.
|
||||
logic [1:0] array[4] = '{ 2'b10, 2'b01, 2'b11, 2'b00 };
|
||||
packet_t packet = {<<4{ {<<2{array}} }};
|
||||
$display("packet addr = %b", packet.addr);
|
||||
$display("packet data = %b", packet.data);
|
||||
end
|
||||
|
||||
initial begin
|
||||
logic [23:0] temp;
|
||||
|
||||
temp = {>>byte{24'h060708}};
|
||||
$display("%h", temp);
|
||||
temp = {<<byte{24'h060708}};
|
||||
$display("%h", temp);
|
||||
|
||||
temp = {>>bit{24'h060708}};
|
||||
$display("%h", temp);
|
||||
temp = {<<bit{24'h060708}};
|
||||
$display("%h", temp);
|
||||
|
||||
temp = {>>7{24'h060708}};
|
||||
$display("%h", temp);
|
||||
temp = {<<7{24'h060708}};
|
||||
$display("%h", temp);
|
||||
|
||||
temp = {>>7{20'h60708}};
|
||||
$display("%h", temp);
|
||||
// TODO: Handle this edge case.
|
||||
//temp = {<<7{20'h60708}};
|
||||
//$display("%h", temp);
|
||||
|
||||
temp = {>>7{16'h0708}};
|
||||
$display("%h", temp);
|
||||
temp = {<<7{16'h0708}};
|
||||
$display("%h", temp);
|
||||
end
|
||||
|
||||
task test_unpack;
|
||||
input logic [23:0] in;
|
||||
logic [0:0] i;
|
||||
logic [1:0] j;
|
||||
logic [2:0] k;
|
||||
logic [5:0] l;
|
||||
logic [11:0] m;
|
||||
{>>byte{i, j, k, l, m}} = in;
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
{<<byte{i, j, k, l, m}} = in;
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
{>>bit{i, j, k, l, m}} = in;
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
{<<bit{i, j, k, l, m}} = in;
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
{>>7{i, j, k, l, m}} = in;
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
{<<7{i, j, k, l, m}} = in;
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
endtask
|
||||
initial begin
|
||||
test_unpack(24'h060708);
|
||||
test_unpack(24'hC02375);
|
||||
test_unpack(24'h12E3B8);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
module top;
|
||||
|
||||
initial begin
|
||||
$display("packet addr = %b", {2'b01, 2'b10});
|
||||
$display("packet data = %b", {2'b00, 2'b11});
|
||||
end
|
||||
|
||||
function automatic [23:0] pack_r_8_24;
|
||||
input [23:0] in;
|
||||
integer i;
|
||||
for (i = 0; i < 24; i = i + 8) begin
|
||||
pack_r_8_24[i+:8] = in[i+:8];
|
||||
end
|
||||
endfunction
|
||||
function automatic [23:0] pack_l_8_24;
|
||||
input [23:0] in;
|
||||
integer i;
|
||||
for (i = 0; i < 24; i = i + 8) begin
|
||||
pack_l_8_24[i+:8] = in[23-i-:8];
|
||||
end
|
||||
endfunction
|
||||
function automatic [23:0] pack_r_1_24;
|
||||
input [23:0] in;
|
||||
integer i;
|
||||
for (i = 0; i < 24; i = i + 1) begin
|
||||
pack_r_1_24[i] = in[i];
|
||||
end
|
||||
endfunction
|
||||
function automatic [23:0] pack_l_1_24;
|
||||
input [23:0] in;
|
||||
integer i;
|
||||
for (i = 0; i < 24; i = i + 1) begin
|
||||
pack_l_1_24[i] = in[23-i];
|
||||
end
|
||||
endfunction
|
||||
function automatic [23:0] pack_r_7_24;
|
||||
input [23:0] in;
|
||||
integer i;
|
||||
begin
|
||||
for (i = 0; i < 24; i = i + 7) begin
|
||||
pack_r_7_24[i+:7] = in[i+:7];
|
||||
end
|
||||
for (i = 0; i < 24; i = i + 7) begin
|
||||
pack_r_7_24[i+:7] = in[i+:7];
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
function automatic [23:0] pack_l_7_24;
|
||||
input [23:0] in;
|
||||
integer i;
|
||||
integer e;
|
||||
begin
|
||||
for (i = 0; i < 24; i = i + 7) begin
|
||||
pack_l_7_24[23-i-:7] = in[i+:7];
|
||||
end
|
||||
e = i - 7;
|
||||
for (i = 0; i < 24-e; i = i + 1) begin
|
||||
pack_l_7_24[i] = in[i+e];
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
initial begin
|
||||
$display("%h", pack_r_8_24(24'h060708));
|
||||
$display("%h", pack_l_8_24(24'h060708));
|
||||
|
||||
$display("%h", pack_r_1_24(24'h060708));
|
||||
$display("%h", pack_l_1_24(24'h060708));
|
||||
|
||||
$display("%h", pack_r_7_24(24'h060708));
|
||||
$display("%h", pack_l_7_24(24'h060708));
|
||||
|
||||
$display("%h", pack_r_7_24(24'h607080));
|
||||
//$display("%h", pack_l_7_24(24'h0c0708));
|
||||
|
||||
$display("%h", pack_r_7_24(24'h070800));
|
||||
$display("%h", pack_l_7_24(24'h000708));
|
||||
end
|
||||
|
||||
task test_unpack;
|
||||
input [23:0] in;
|
||||
reg [0:0] i;
|
||||
reg [1:0] j;
|
||||
reg [2:0] k;
|
||||
reg [5:0] l;
|
||||
reg [11:0] m;
|
||||
begin
|
||||
{i, j, k, l, m} = in;
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
{i, j, k, l, m} = pack_l_8_24(in);
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
{i, j, k, l, m} = in;
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
{i, j, k, l, m} = pack_l_1_24(in);
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
{i, j, k, l, m} = in;
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
{i, j, k, l, m} = pack_l_7_24(in);
|
||||
$display("%b %b %b %b %b", i, j, k, l, m);
|
||||
end
|
||||
endtask
|
||||
initial begin
|
||||
test_unpack(24'h060708);
|
||||
test_unpack(24'hC02375);
|
||||
test_unpack(24'h12E3B8);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
// 060708
|
||||
// 080706
|
||||
// 060708
|
||||
// 10e060
|
||||
// 060708
|
||||
// 1038c0
|
||||
//
|
||||
|
||||
// 1 11 010 110001 100000000110
|
||||
// 0 00 110 111000 010001100000
|
||||
//
|
||||
// 00 001 100000 011100001000
|
||||
// 0 00 010 000000 011100000110
|
||||
// 0 00 001 100000 011100001000
|
||||
// 0 00 100 001110 000001100000
|
||||
// 0 00 001 100000 011100001000
|
||||
// 0 00 110 000100 000010000011
|
||||
// 1 10 000 000010 001101110101
|
||||
// 0 11 101 010010 001111000000
|
||||
// 1 10 000 000010 001101110101
|
||||
// 1 01 011 101100 010000000011
|
||||
// 1 10 000 000010 001101110101
|
||||
// 0 00 110 111000 010001100000
|
||||
// 0 00 100 101110 001110111000
|
||||
// 1 01 110 001110 001100010010
|
||||
// 0 00 100 101110 001110111000
|
||||
// 0 00 111 011100 011101001000
|
||||
// 0 00 100 101110 001110111000
|
||||
// 0 00 111 011101 110000001001
|
||||
|
||||
|
||||
// 0 00 001 100000 011100001000
|
||||
// 0 00 010 000000 011100000110
|
||||
// 0 00 001 100000 011100001000
|
||||
// 0 00 100 001110 000001100000
|
||||
// 0 00 001 100000 011100001000
|
||||
// 0 00 100 000011 100011000000
|
||||
// 1 10 000 000010 001101110101
|
||||
// 0 11 101 010010 001111000000
|
||||
// 1 10 000 000010 001101110101
|
||||
// 1 01 011 101100 010000000011
|
||||
// 1 10 000 000010 001101110101
|
||||
// 1 11 010 110001 100000000110
|
||||
// 0 00 100 101110 001110111000
|
||||
// 1 01 110 001110 001100010010
|
||||
// 0 00 100 101110 001110111000
|
||||
// 0 00 111 011100 011101001000
|
||||
// 0 00 100 101110 001110111000
|
||||
// 0 11 100 010001 111001011000
|
||||
Loading…
Reference in New Issue