Commit af4711a8 by Zachary Snow

preliminary stream conversion

parent 73404643
...@@ -31,6 +31,7 @@ import qualified Convert.RemoveComments ...@@ -31,6 +31,7 @@ import qualified Convert.RemoveComments
import qualified Convert.Return import qualified Convert.Return
import qualified Convert.StarPort import qualified Convert.StarPort
import qualified Convert.StmtBlock import qualified Convert.StmtBlock
import qualified Convert.Stream
import qualified Convert.Struct import qualified Convert.Struct
import qualified Convert.Typedef import qualified Convert.Typedef
import qualified Convert.UnbasedUnsized import qualified Convert.UnbasedUnsized
...@@ -56,6 +57,7 @@ phases excludes = ...@@ -56,6 +57,7 @@ phases excludes =
, Convert.PackedArray.convert , Convert.PackedArray.convert
, Convert.StarPort.convert , Convert.StarPort.convert
, Convert.StmtBlock.convert , Convert.StmtBlock.convert
, Convert.Stream.convert
, Convert.Struct.convert , Convert.Struct.convert
, Convert.Typedef.convert , Convert.Typedef.convert
, Convert.UnbasedUnsized.convert , Convert.UnbasedUnsized.convert
......
...@@ -35,11 +35,3 @@ convertStmt (For inits cc asgns stmt) = ...@@ -35,11 +35,3 @@ convertStmt (For inits cc asgns stmt) =
convertStmt (AsgnBlk (AsgnOp op) lhs expr) = convertStmt (AsgnBlk (AsgnOp op) lhs expr) =
AsgnBlk AsgnOpEq lhs (BinOp op (lhsToExpr lhs) expr) AsgnBlk AsgnOpEq lhs (BinOp op (lhsToExpr lhs) expr)
convertStmt other = other 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 @@ ...@@ -17,6 +17,7 @@
module Convert.Bits (convert) where module Convert.Bits (convert) where
import Control.Monad.State import Control.Monad.State
import Data.List (elemIndex)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Convert.Traverse import Convert.Traverse
...@@ -37,7 +38,9 @@ traverseDeclM decl = do ...@@ -37,7 +38,9 @@ traverseDeclM decl = do
Variable _ t ident a _ -> modify $ Map.insert ident (t, a) Variable _ t ident a _ -> modify $ Map.insert ident (t, a)
Parameter t ident _ -> modify $ Map.insert ident (t, []) Parameter t ident _ -> modify $ Map.insert ident (t, [])
Localparam 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 :: ModuleItem -> State Info ModuleItem
traverseModuleItemM item = traverseExprsM traverseExprM item traverseModuleItemM item = traverseExprsM traverseExprM item
...@@ -46,7 +49,8 @@ traverseStmtM :: Stmt -> State Info Stmt ...@@ -46,7 +49,8 @@ traverseStmtM :: Stmt -> State Info Stmt
traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt
traverseExprM :: Expr -> State Info Expr 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 -- simplify a bits expression given scoped type information
convertExpr :: Info -> Expr -> Expr convertExpr :: Info -> Expr -> Expr
...@@ -83,6 +87,11 @@ convertExpr info (Bits (Right e)) = ...@@ -83,6 +87,11 @@ convertExpr info (Bits (Right e)) =
Just (t, rs) -> Just (t, rs) ->
convertExpr info $ Bits $ Left t' convertExpr info $ Bits $ Left t'
where t' = popRange t rs 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 _ -> Bits $ Right e
convertExpr _ other = other convertExpr _ other = other
......
{- 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 ...@@ -543,6 +543,7 @@ traverseExprsM' strat exprMapper = moduleItemMapper
expr' <- exprMapper expr expr' <- exprMapper expr
return $ Assign delay' lhs' expr' return $ Assign delay' lhs' expr'
moduleItemMapper (MIPackageItem (Function lifetime ret f decls stmts)) = do moduleItemMapper (MIPackageItem (Function lifetime ret f decls stmts)) = do
ret' <- typeMapper ret
decls' <- decls' <-
if strat == IncludeTFs if strat == IncludeTFs
then mapM declMapper decls then mapM declMapper decls
...@@ -551,7 +552,7 @@ traverseExprsM' strat exprMapper = moduleItemMapper ...@@ -551,7 +552,7 @@ traverseExprsM' strat exprMapper = moduleItemMapper
if strat == IncludeTFs if strat == IncludeTFs
then mapM stmtMapper stmts then mapM stmtMapper stmts
else return 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 moduleItemMapper (MIPackageItem (Task lifetime f decls stmts)) = do
decls' <- decls' <-
if strat == IncludeTFs if strat == IncludeTFs
......
...@@ -26,6 +26,7 @@ module Language.SystemVerilog.AST ...@@ -26,6 +26,7 @@ module Language.SystemVerilog.AST
, module Stmt , module Stmt
, module Type , module Type
, exprToLHS , exprToLHS
, lhsToExpr
) where ) where
import Language.SystemVerilog.AST.Attr as Attr import Language.SystemVerilog.AST.Attr as Attr
...@@ -59,3 +60,11 @@ exprToLHS (Stream o e ls) = do ...@@ -59,3 +60,11 @@ exprToLHS (Stream o e ls) = do
ls' <- mapM exprToLHS ls ls' <- mapM exprToLHS ls
Just $ LHSStream o e ls' Just $ LHSStream o e ls'
exprToLHS _ = Nothing 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 = ...@@ -123,6 +123,10 @@ readNumber n =
-- basic expression simplfication utility to help us generate nicer code in the -- basic expression simplfication utility to help us generate nicer code in the
-- common case of ranges like `[FOO-1:0]` -- common case of ranges like `[FOO-1:0]`
simplify :: Expr -> Expr 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)] []))) = simplify (orig @ (Call Nothing "$clog2" (Args [Just (Number n)] []))) =
case readNumber n of case readNumber n of
Nothing -> orig Nothing -> orig
......
...@@ -75,6 +75,7 @@ executable sv2v ...@@ -75,6 +75,7 @@ executable sv2v
Convert.Return Convert.Return
Convert.StarPort Convert.StarPort
Convert.StmtBlock Convert.StmtBlock
Convert.Stream
Convert.Struct Convert.Struct
Convert.Typedef Convert.Typedef
Convert.Traverse Convert.Traverse
......
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
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
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