mirror of https://github.com/zachjs/sv2v.git
PackedArray conversion supports arbitrary endianness
This commit is contained in:
parent
f47446653d
commit
011d88b544
|
|
@ -22,16 +22,13 @@
|
||||||
- Note: We don't count usages with an index in expressions as such, as those
|
- Note: We don't count usages with an index in expressions as such, as those
|
||||||
- usages could be equivalently converted to range accesses with some added in
|
- usages could be equivalently converted to range accesses with some added in
|
||||||
- multiplication.
|
- multiplication.
|
||||||
-
|
|
||||||
- TODO: This assumes that the first range index is the upper bound. We could
|
|
||||||
- probably get around this with some cleverness in the generate block. I don't
|
|
||||||
- think it's urgent to have support for "backwards" ranges.
|
|
||||||
-}
|
-}
|
||||||
|
|
||||||
module Convert.PackedArray (convert) where
|
module Convert.PackedArray (convert) where
|
||||||
|
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import Data.List (partition)
|
import Data.List (partition)
|
||||||
|
import Data.Tuple (swap)
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
|
|
||||||
|
|
@ -186,18 +183,20 @@ flattenModuleItem _ other = other
|
||||||
-- produces `generate` items for creating an unflattened copy of the given
|
-- produces `generate` items for creating an unflattened copy of the given
|
||||||
-- flattened, packed array
|
-- flattened, packed array
|
||||||
unflattener :: Bool -> Identifier -> (Type, Range) -> [GenItem]
|
unflattener :: Bool -> Identifier -> (Type, Range) -> [GenItem]
|
||||||
unflattener writeToFlatVariant arr (t, (majorHi, majorLo)) =
|
unflattener writeToFlatVariant arr (t, major @ (majorHi, majorLo)) =
|
||||||
[ GenModuleItem $ MIPackageItem $ Comment $ "sv2v packed-array-flatten unflattener for " ++ arr
|
[ GenModuleItem $ MIPackageItem $ Comment $ "sv2v packed-array-flatten unflattener for " ++ arr
|
||||||
, GenModuleItem $ MIDecl $ Variable Local t arrUnflat [(majorHi, majorLo)] Nothing
|
, GenModuleItem $ MIDecl $ Variable Local t arrUnflat [(majorHi, majorLo)] Nothing
|
||||||
, GenModuleItem $ Genvar index
|
, GenModuleItem $ Genvar index
|
||||||
, GenModuleItem $ MIDecl $ Variable Local (IntegerAtom TInteger Unspecified) (arrUnflat ++ "_repeater_index") [] Nothing
|
, GenModuleItem $ MIDecl $ Variable Local (IntegerAtom TInteger Unspecified) (arrUnflat ++ "_repeater_index") [] Nothing
|
||||||
, GenFor
|
, GenFor
|
||||||
(index, majorLo)
|
(index, majorLo)
|
||||||
|
(ccExpr major
|
||||||
(BinOp Le (Ident index) majorHi)
|
(BinOp Le (Ident index) majorHi)
|
||||||
(index, AsgnOp Add, Number "1")
|
(BinOp Ge (Ident index) majorHi))
|
||||||
|
(index, AsgnOp Add, ccExpr major (Number "1") (Number "-1"))
|
||||||
(Just $ prefix "unflatten_" ++ arr)
|
(Just $ prefix "unflatten_" ++ arr)
|
||||||
[ localparam startBit
|
[ localparam startBit
|
||||||
(simplify $ BinOp Add majorLo
|
(simplify $ BinOp Add (ccExpr major majorLo majorHi)
|
||||||
(BinOp Mul (Ident index) size))
|
(BinOp Mul (Ident index) size))
|
||||||
, GenModuleItem $ (uncurry $ Assign Nothing) $
|
, GenModuleItem $ (uncurry $ Assign Nothing) $
|
||||||
if not writeToFlatVariant
|
if not writeToFlatVariant
|
||||||
|
|
@ -209,13 +208,23 @@ unflattener writeToFlatVariant arr (t, (majorHi, majorLo)) =
|
||||||
startBit = prefix "_tmp_start_" ++ arr
|
startBit = prefix "_tmp_start_" ++ arr
|
||||||
arrUnflat = prefix arr
|
arrUnflat = prefix arr
|
||||||
index = prefix "_tmp_index_" ++ arr
|
index = prefix "_tmp_index_" ++ arr
|
||||||
(minorHi, minorLo) = head $ snd $ typeRanges t
|
minor = head $ snd $ typeRanges t
|
||||||
size = rangeSize (minorHi, minorLo)
|
size = rangeSize $ ccRange minor minor (swap minor)
|
||||||
localparam :: Identifier -> Expr -> GenItem
|
localparam :: Identifier -> Expr -> GenItem
|
||||||
localparam x v = GenModuleItem $ MIDecl $ Localparam (Implicit Unspecified []) x v
|
localparam x v = GenModuleItem $ MIDecl $ Localparam (Implicit Unspecified []) x v
|
||||||
origRange = ( (BinOp Add (Ident startBit)
|
origRangeAg = ( (BinOp Add (Ident startBit)
|
||||||
(BinOp Sub size (Number "1")))
|
(BinOp Sub size (Number "1")))
|
||||||
, Ident startBit )
|
, Ident startBit )
|
||||||
|
origRange = ccRange major origRangeAg (swap origRangeAg)
|
||||||
|
|
||||||
|
ccExpr :: Range -> Expr -> Expr -> Expr
|
||||||
|
ccExpr r e1 e2 = simplify $ Mux (uncurry (BinOp Ge) r) e1 e2
|
||||||
|
|
||||||
|
ccRange :: Range -> Range -> Range -> Range
|
||||||
|
ccRange r r1 r2 =
|
||||||
|
( ccExpr r (fst r1) (fst r2)
|
||||||
|
, ccExpr r (snd r1) (snd r2)
|
||||||
|
)
|
||||||
|
|
||||||
typeIsImplicit :: Type -> Bool
|
typeIsImplicit :: Type -> Bool
|
||||||
typeIsImplicit (Implicit _ _) = True
|
typeIsImplicit (Implicit _ _) = True
|
||||||
|
|
@ -232,13 +241,26 @@ flattenRanges rs =
|
||||||
then rs'
|
then rs'
|
||||||
else error $ "flattenRanges on too small list: " ++ (show rs)
|
else error $ "flattenRanges on too small list: " ++ (show rs)
|
||||||
where
|
where
|
||||||
(s1, e1) = head rs
|
r1 = head rs
|
||||||
(s2, e2) = head $ tail rs
|
r2 = head $ tail rs
|
||||||
|
rYY = flattenRangesHelp r1 r2
|
||||||
|
rYN = flattenRangesHelp r1 (swap r2)
|
||||||
|
rNY = flattenRangesHelp (swap r1) r2
|
||||||
|
rNN = flattenRangesHelp (swap r1) (swap r2)
|
||||||
|
rY = ccRange r2 rYY rYN
|
||||||
|
rN = ccRange r2 rNY rNN
|
||||||
|
rAg = ccRange r1 rY rN
|
||||||
|
r = ccRange r1 rAg (swap rAg)
|
||||||
|
rs' = (tail $ tail rs) ++ [r]
|
||||||
|
|
||||||
|
flattenRangesHelp :: Range -> Range -> Range
|
||||||
|
flattenRangesHelp (s1, e1) (s2, e2) =
|
||||||
|
(simplify upper, simplify lower)
|
||||||
|
where
|
||||||
size1 = rangeSize (s1, e1)
|
size1 = rangeSize (s1, e1)
|
||||||
size2 = rangeSize (s2, e2)
|
size2 = rangeSize (s2, e2)
|
||||||
upper = BinOp Add (BinOp Mul size1 size2) (BinOp Sub e1 (Number "1"))
|
lower = BinOp Add e1 (BinOp Mul e2 size2)
|
||||||
r' = (simplify upper, e1)
|
upper = BinOp Add (BinOp Mul size1 size2) (BinOp Sub lower (Number "1"))
|
||||||
rs' = (tail $ tail rs) ++ [r']
|
|
||||||
|
|
||||||
rewriteModuleItem :: Info -> ModuleItem -> ModuleItem
|
rewriteModuleItem :: Info -> ModuleItem -> ModuleItem
|
||||||
rewriteModuleItem info =
|
rewriteModuleItem info =
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,22 @@ showRange (h, l) = printf "[%s:%s]" (show h) (show l)
|
||||||
-- 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 (Mux (BinOp Ge c1 c2) e1 e2) =
|
||||||
|
case (c1', c2') of
|
||||||
|
(Number a, Number b) ->
|
||||||
|
case (readMaybe a :: Maybe Int, readMaybe b :: Maybe Int) of
|
||||||
|
(Just x, Just y) ->
|
||||||
|
if x >= y
|
||||||
|
then e1
|
||||||
|
else e2
|
||||||
|
_ -> nochange
|
||||||
|
_ -> nochange
|
||||||
|
where
|
||||||
|
c1' = simplify c1
|
||||||
|
c2' = simplify c2
|
||||||
|
e1' = simplify e1
|
||||||
|
e2' = simplify e2
|
||||||
|
nochange = Mux (BinOp Ge c1' c2') e1' e2'
|
||||||
simplify (BinOp op e1 e2) =
|
simplify (BinOp op e1 e2) =
|
||||||
case (op, e1', e2') of
|
case (op, e1', e2') of
|
||||||
(Add, Number "0", e) -> e
|
(Add, Number "0", e) -> e
|
||||||
|
|
@ -103,6 +119,10 @@ simplify (BinOp op e1 e2) =
|
||||||
(Sub, Just x, Just y) -> Number $ show (x - y)
|
(Sub, Just x, Just y) -> Number $ show (x - y)
|
||||||
(Mul, Just x, Just y) -> Number $ show (x * y)
|
(Mul, Just x, Just y) -> Number $ show (x * y)
|
||||||
_ -> BinOp op e1' e2'
|
_ -> BinOp op e1' e2'
|
||||||
|
(Add, BinOp Add e (Number a), Number b) ->
|
||||||
|
case (readMaybe a :: Maybe Int, readMaybe b :: Maybe Int) of
|
||||||
|
(Just x, Just y) -> BinOp Add e $ Number $ show (x + y)
|
||||||
|
_ -> BinOp op e1' e2'
|
||||||
_ -> BinOp op e1' e2'
|
_ -> BinOp op e1' e2'
|
||||||
where
|
where
|
||||||
e1' = simplify e1
|
e1' = simplify e1
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
// intentionally empty
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
`define CASE_A(name, dims) \
|
||||||
|
module name(clock, in, out); \
|
||||||
|
input wire clock, in; \
|
||||||
|
output logic dims out; \
|
||||||
|
initial out[0] = 0; \
|
||||||
|
initial out[1] = 0; \
|
||||||
|
initial out[2] = 0; \
|
||||||
|
always @(posedge clock) begin \
|
||||||
|
\
|
||||||
|
out[2][4] = out[2][3]; \
|
||||||
|
out[2][3] = out[2][2]; \
|
||||||
|
out[2][2] = out[2][1]; \
|
||||||
|
out[2][1] = out[2][0]; \
|
||||||
|
out[2][0] = out[1][4]; \
|
||||||
|
\
|
||||||
|
out[1][4] = out[1][3]; \
|
||||||
|
out[1][3] = out[1][2]; \
|
||||||
|
out[1][2] = out[1][1]; \
|
||||||
|
out[1][1] = out[1][0]; \
|
||||||
|
out[1][0] = out[0][4]; \
|
||||||
|
\
|
||||||
|
out[0][4] = out[0][3]; \
|
||||||
|
out[0][3] = out[0][2]; \
|
||||||
|
out[0][2] = out[0][1]; \
|
||||||
|
out[0][1] = out[0][0]; \
|
||||||
|
out[0][0] = in; \
|
||||||
|
\
|
||||||
|
end \
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`CASE_A(A1, [2:0][4:0])
|
||||||
|
`CASE_A(A2, [0:2][0:4])
|
||||||
|
`CASE_A(A3, [0:2][4:0])
|
||||||
|
`CASE_A(A4, [2:0][0:4])
|
||||||
|
|
||||||
|
`define CASE_B(name, dims) \
|
||||||
|
module name(clock, in, out); \
|
||||||
|
input wire clock, in; \
|
||||||
|
output logic dims out; \
|
||||||
|
initial out[1] = 0; \
|
||||||
|
initial out[2] = 0; \
|
||||||
|
initial out[3] = 0; \
|
||||||
|
always @(posedge clock) begin \
|
||||||
|
\
|
||||||
|
out[3][5] = out[3][4]; \
|
||||||
|
out[3][4] = out[3][3]; \
|
||||||
|
out[3][3] = out[3][2]; \
|
||||||
|
out[3][2] = out[3][1]; \
|
||||||
|
out[3][1] = out[2][5]; \
|
||||||
|
\
|
||||||
|
out[2][5] = out[2][4]; \
|
||||||
|
out[2][4] = out[2][3]; \
|
||||||
|
out[2][3] = out[2][2]; \
|
||||||
|
out[2][2] = out[2][1]; \
|
||||||
|
out[2][1] = out[1][5]; \
|
||||||
|
\
|
||||||
|
out[1][5] = out[1][4]; \
|
||||||
|
out[1][4] = out[1][3]; \
|
||||||
|
out[1][3] = out[1][2]; \
|
||||||
|
out[1][2] = out[1][1]; \
|
||||||
|
out[1][1] = in; \
|
||||||
|
\
|
||||||
|
end \
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`CASE_B(B1, [3:1][5:1])
|
||||||
|
`CASE_B(B2, [1:3][1:5])
|
||||||
|
`CASE_B(B3, [1:3][5:1])
|
||||||
|
`CASE_B(B4, [3:1][1:5])
|
||||||
|
|
||||||
|
`define CASE_C(name, dims) \
|
||||||
|
module name(clock, in, out); \
|
||||||
|
input wire clock, in; \
|
||||||
|
output logic dims out; \
|
||||||
|
initial out[2] = 0; \
|
||||||
|
initial out[3] = 0; \
|
||||||
|
initial out[4] = 0; \
|
||||||
|
always @(posedge clock) begin \
|
||||||
|
\
|
||||||
|
out[4][6] = out[4][5]; \
|
||||||
|
out[4][5] = out[4][4]; \
|
||||||
|
out[4][4] = out[4][3]; \
|
||||||
|
out[4][3] = out[4][2]; \
|
||||||
|
out[4][2] = out[3][6]; \
|
||||||
|
\
|
||||||
|
out[3][6] = out[3][5]; \
|
||||||
|
out[3][5] = out[3][4]; \
|
||||||
|
out[3][4] = out[3][3]; \
|
||||||
|
out[3][3] = out[3][2]; \
|
||||||
|
out[3][2] = out[2][6]; \
|
||||||
|
\
|
||||||
|
out[2][6] = out[2][5]; \
|
||||||
|
out[2][5] = out[2][4]; \
|
||||||
|
out[2][4] = out[2][3]; \
|
||||||
|
out[2][3] = out[2][2]; \
|
||||||
|
out[2][2] = in; \
|
||||||
|
\
|
||||||
|
end \
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`CASE_C(C1, [4:2][6:2])
|
||||||
|
`CASE_C(C2, [2:4][2:6])
|
||||||
|
`CASE_C(C3, [2:4][6:2])
|
||||||
|
`CASE_C(C4, [4:2][2:6])
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
// iverilog supports multi-dimensional packed arrays
|
||||||
|
`include "flatten.sv"
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
`define FOO(tag) \
|
||||||
|
wire [14:0] tag``one_out, tag``two_out, tag``thr_out, tag``fou_out; \
|
||||||
|
tag``1 tag``one(.clock(clock), .in(in), .out(tag``one_out)); \
|
||||||
|
tag``2 tag``two(.clock(clock), .in(in), .out(tag``two_out)); \
|
||||||
|
tag``3 tag``thr(.clock(clock), .in(in), .out(tag``thr_out)); \
|
||||||
|
tag``4 tag``fou(.clock(clock), .in(in), .out(tag``fou_out)); \
|
||||||
|
initial begin \
|
||||||
|
$monitor(`"tag", $time, ": %h %15b %15b %15b %15b", in, \
|
||||||
|
tag``one_out, tag``two_out, tag``thr_out, tag``fou_out); \
|
||||||
|
end
|
||||||
|
|
||||||
|
module top;
|
||||||
|
reg clock, in;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clock = 1;
|
||||||
|
forever #1 clock = ~clock;
|
||||||
|
end
|
||||||
|
|
||||||
|
integer i;
|
||||||
|
localparam [20:0] pattern = 20'b01101100001010101100;
|
||||||
|
initial begin
|
||||||
|
for (i = 0; i < 20; i++) begin
|
||||||
|
in = pattern[i];
|
||||||
|
#2;
|
||||||
|
end
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
`FOO(A)
|
||||||
|
`FOO(B)
|
||||||
|
`FOO(C)
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -1,3 +1,2 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
NO_SEPARATE_TBS=1
|
|
||||||
source ../lib/runner.sh
|
source ../lib/runner.sh
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue