Commit af4711a8 by Zachary Snow

preliminary stream conversion

parent 73404643
......@@ -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
......
{- 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
......
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