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
|
||||
- usages could be equivalently converted to range accesses with some added in
|
||||
- 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
|
||||
|
||||
import Control.Monad.State
|
||||
import Data.List (partition)
|
||||
import Data.Tuple (swap)
|
||||
import qualified Data.Set as Set
|
||||
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
|
||||
-- flattened, packed array
|
||||
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 $ MIDecl $ Variable Local t arrUnflat [(majorHi, majorLo)] Nothing
|
||||
, GenModuleItem $ Genvar index
|
||||
, GenModuleItem $ MIDecl $ Variable Local (IntegerAtom TInteger Unspecified) (arrUnflat ++ "_repeater_index") [] Nothing
|
||||
, GenFor
|
||||
(index, majorLo)
|
||||
(BinOp Le (Ident index) majorHi)
|
||||
(index, AsgnOp Add, Number "1")
|
||||
(ccExpr major
|
||||
(BinOp Le (Ident index) majorHi)
|
||||
(BinOp Ge (Ident index) majorHi))
|
||||
(index, AsgnOp Add, ccExpr major (Number "1") (Number "-1"))
|
||||
(Just $ prefix "unflatten_" ++ arr)
|
||||
[ localparam startBit
|
||||
(simplify $ BinOp Add majorLo
|
||||
(simplify $ BinOp Add (ccExpr major majorLo majorHi)
|
||||
(BinOp Mul (Ident index) size))
|
||||
, GenModuleItem $ (uncurry $ Assign Nothing) $
|
||||
if not writeToFlatVariant
|
||||
|
|
@ -209,13 +208,23 @@ unflattener writeToFlatVariant arr (t, (majorHi, majorLo)) =
|
|||
startBit = prefix "_tmp_start_" ++ arr
|
||||
arrUnflat = prefix arr
|
||||
index = prefix "_tmp_index_" ++ arr
|
||||
(minorHi, minorLo) = head $ snd $ typeRanges t
|
||||
size = rangeSize (minorHi, minorLo)
|
||||
minor = head $ snd $ typeRanges t
|
||||
size = rangeSize $ ccRange minor minor (swap minor)
|
||||
localparam :: Identifier -> Expr -> GenItem
|
||||
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")))
|
||||
, 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 (Implicit _ _) = True
|
||||
|
|
@ -232,13 +241,26 @@ flattenRanges rs =
|
|||
then rs'
|
||||
else error $ "flattenRanges on too small list: " ++ (show rs)
|
||||
where
|
||||
(s1, e1) = head rs
|
||||
(s2, e2) = head $ tail rs
|
||||
r1 = head 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)
|
||||
size2 = rangeSize (s2, e2)
|
||||
upper = BinOp Add (BinOp Mul size1 size2) (BinOp Sub e1 (Number "1"))
|
||||
r' = (simplify upper, e1)
|
||||
rs' = (tail $ tail rs) ++ [r']
|
||||
lower = BinOp Add e1 (BinOp Mul e2 size2)
|
||||
upper = BinOp Add (BinOp Mul size1 size2) (BinOp Sub lower (Number "1"))
|
||||
|
||||
rewriteModuleItem :: Info -> ModuleItem -> ModuleItem
|
||||
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
|
||||
-- common case of ranges like `[FOO-1:0]`
|
||||
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) =
|
||||
case (op, e1', e2') of
|
||||
(Add, Number "0", e) -> e
|
||||
|
|
@ -103,6 +119,10 @@ simplify (BinOp op e1 e2) =
|
|||
(Sub, Just x, Just y) -> Number $ show (x - y)
|
||||
(Mul, Just x, Just y) -> Number $ show (x * y)
|
||||
_ -> 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'
|
||||
where
|
||||
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
|
||||
NO_SEPARATE_TBS=1
|
||||
source ../lib/runner.sh
|
||||
|
|
|
|||
Loading…
Reference in New Issue