Commit 011d88b5 by Zachary Snow

PackedArray conversion supports arbitrary endianness

parent f4744665
...@@ -22,16 +22,13 @@ ...@@ -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 ...@@ -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)) = ...@@ -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 = ...@@ -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) ...@@ -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) = ...@@ -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
......
// intentionally empty
`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])
// iverilog supports multi-dimensional packed arrays
`include "flatten.sv"
`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
#!/bin/sh #!/bin/sh
NO_SEPARATE_TBS=1
source ../lib/runner.sh source ../lib/runner.sh
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