Commit 976f5822 by Zachary Snow

push struct and multi-packed ternaries into ranges

- the ternary expressions were previously used to decide the direction
  of generated part selects
- this fixes an issue where ternaries were generated for LHSs
parent db4c3963
......@@ -27,7 +27,7 @@ module Convert.MultiplePacked (convert) where
import Control.Monad.State
import Data.Tuple (swap)
import Data.Maybe (isJust, fromJust)
import Data.Maybe (isJust)
import qualified Data.Map.Strict as Map
import Convert.Traverse
......@@ -118,7 +118,10 @@ traverseLHSM :: LHS -> State Info LHS
traverseLHSM lhs = do
let expr = lhsToExpr lhs
expr' <- traverseExprM expr
return $ fromJust $ exprToLHS expr'
case exprToLHS expr' of
Just lhs' -> return lhs'
Nothing -> error $ "multi-packed conversion created non-LHS from "
++ (show expr) ++ " to " ++ (show expr')
traverseExpr :: Info -> Expr -> Expr
traverseExpr typeMap =
......@@ -220,46 +223,45 @@ traverseExpr typeMap =
range' = (simplify base, simplify len)
rewriteExpr (orig @ (Range (Bit expr idxInner) NonIndexed rangeOuter)) =
if isJust maybeDims && expr == rewriteExpr expr
then endianCondExpr rangeOuter
(rewriteExpr $ Range exprOuter IndexedMinus range)
(rewriteExpr $ Range exprOuter IndexedPlus range)
then rewriteExpr $ Range exprOuter IndexedMinus range
else orig
where
maybeDims = dims expr
exprOuter = Bit expr idxInner
base = fst rangeOuter
baseDec = fst rangeOuter
baseInc = BinOp Sub (BinOp Add baseDec len) (Number "1")
base = endianCondExpr rangeOuter baseDec baseInc
len = rangeSize rangeOuter
range = (base, len)
rewriteExpr (orig @ (Range (Bit expr idxInner) modeOuter rangeOuter)) =
if isJust maybeDims && expr == rewriteExpr expr
then endianCondExpr dimOuter
(Range expr' modeDec range')
(Range expr' modeInc range')
then Range expr' modeOuter range'
else orig
where
maybeDims = dims expr
Just (dimInner, dimOuter, expr') = maybeDims
idxInner' = orientIdx dimInner idxInner
(modeDec, modeInc) =
case modeOuter of
IndexedPlus -> (IndexedPlus , IndexedMinus)
IndexedMinus -> (IndexedMinus, IndexedPlus )
NonIndexed -> error "invariant violated"
(baseOuter, lenOuter) = rangeOuter
baseOuter' = orientIdx dimOuter baseOuter
start = BinOp Mul idxInner' (rangeSize dimOuter)
base = simplify $ BinOp Add start baseOuter'
baseDec = BinOp Add start baseOuter'
baseInc = case modeOuter of
IndexedPlus -> BinOp Add (BinOp Sub baseDec len) one
IndexedMinus -> BinOp Sub (BinOp Add baseDec len) one
NonIndexed -> error "invariant violated"
base = endianCondExpr dimOuter baseDec baseInc
len = lenOuter
range' = (base, len)
one = Number "1"
rewriteExpr (orig @ (Range expr NonIndexed range)) =
if isJust maybeDims && expr == rewriteExpr expr
then endianCondExpr range
(rewriteExpr $ Range expr IndexedMinus range')
(rewriteExpr $ Range expr IndexedPlus range')
then rewriteExpr $ Range expr IndexedMinus range'
else orig
where
maybeDims = dims expr
base = fst range
baseDec = fst range
baseInc = BinOp Sub (BinOp Add baseDec len) (Number "1")
base = endianCondExpr range baseDec baseInc
len = rangeSize range
range' = (base, len)
rewriteExpr (orig @ (Range expr mode range)) =
......
......@@ -250,11 +250,13 @@ convertAsgn structs types (lhs, expr) =
-- converting LHSs by looking at the innermost types first
convertLHS :: LHS -> (Type, LHS)
convertLHS l =
(t, l')
case exprToLHS e' of
Just l' -> (t, l')
Nothing -> error $ "struct conversion created non-LHS from "
++ (show e) ++ " to " ++ (show e')
where
e = lhsToExpr l
(t, e') = convertSubExpr e
Just l' = exprToLHS e'
specialTag = ':'
defaultKey = specialTag : "default"
......@@ -395,13 +397,12 @@ convertAsgn structs types (lhs, expr) =
maybeFields = getFields subExprType
Just (structTf, fields) = maybeFields
(fieldType, bounds, dims) = lookupFieldInfo structTf fields x
base = fst bounds
len = rangeSize bounds
[dim] = dims
undotted = if null dims || rangeSize dim == Number "1"
then Bit e' (fst bounds)
else endianCondExpr dim
(Range e' IndexedMinus (fst bounds, len))
(Range e' IndexedPlus (snd bounds, len))
else Range e' IndexedMinus (base, len)
convertSubExpr (Range (Dot e x) NonIndexed rOuter) =
if maybeFields == Nothing
then (Implicit Unspecified [], orig')
......@@ -438,12 +439,14 @@ convertAsgn structs types (lhs, expr) =
[dim] = dims
baseLeft = BinOp Sub (fst bounds) $ BinOp Sub (fst dim) baseO
baseRight = BinOp Add (snd bounds) $ BinOp Sub (snd dim) baseO
undotted = endianCondExpr dim
(Range e' mode (baseLeft , lenO))
(Range e' otherMode (baseRight, lenO))
otherMode = if mode == IndexedPlus
then IndexedMinus
else IndexedPlus
baseDec = baseLeft
baseInc = case mode of
IndexedPlus -> BinOp Add (BinOp Sub baseRight lenO) one
IndexedMinus -> BinOp Sub (BinOp Add baseRight lenO) one
NonIndexed -> error "invariant violated"
base = endianCondExpr dim baseDec baseInc
undotted = Range e' mode (base, lenO)
one = Number "1"
convertSubExpr (Range e mode r) =
(t', Range e' mode r)
where
......
module Example;
// The test is equivalent to the struct_part_select test, except that all of
// the dimensions and indices have been replaced with parameters. This
// ensures sv2v can generate reasonable output even when nothing can be
// simplified down at the time of conversion.
parameter ONE = 1;
parameter TWO = 2;
parameter THREE = 3;
parameter FOUR = 4;
parameter FIVE = 5;
parameter SIX = 6;
parameter SEVEN = 7;
parameter EIGHT = 8;
parameter NINE = 9;
parameter TEN = 10;
typedef struct packed {
logic [TEN:FOUR] a;
logic [ONE:THREE] bx;
logic [THREE:ONE] by;
logic [THREE:FOUR][FIVE:SEVEN] cw;
logic [FOUR:THREE][FIVE:SEVEN] cx;
logic [THREE:FOUR][SEVEN:FIVE] cy;
logic [FOUR:THREE][SEVEN:FIVE] cz;
} T;
T t;
initial begin
$monitor("%2d %b %b %b %b %b %b %b %b %b %b %b %b %b %b %b %b", $time,
t, t.a, t.bx, t.by,
t.cw, t.cw[THREE], t.cw[FOUR],
t.cx, t.cx[THREE], t.cx[FOUR],
t.cy, t.cy[THREE], t.cy[FOUR],
t.cz, t.cz[THREE], t.cz[FOUR]
);
#1 t.a = 1;
#1 t.a[FIVE+:TWO] = '1;
#1 t.a[EIGHT-:THREE] = '1;
#1 t.a[TEN] = 1;
#1 t.a[SEVEN] = 0;
#1 t.bx[ONE+:ONE] = 1;
#1 t.bx[ONE:TWO] = 1;
#1 t.bx[THREE] = 0;
#1 t.bx[THREE-:TWO] = 1;
#1 t.bx[TWO] = 0;
#1 t.by[ONE+:ONE] = 1;
#1 t.by[TWO:ONE] = 1;
#1 t.by[THREE] = 0;
#1 t.by[THREE-:TWO] = 1;
#1 t.by[TWO] = 0;
#1 t.cw[THREE][SIX+:ONE] = 1;
#1 t.cw[THREE][SEVEN-:TWO] = 1;
#1 t.cw[THREE][FIVE+:TWO] = 0;
#1 t.cw[THREE][SIX:SEVEN] = 2'b10;
#1 t.cw[THREE][SIX:SEVEN] = 2'b01;
#1 t.cw[THREE:FOUR] = '1;
#1 t.cw[FOUR][FIVE] = 0;
#1 t.cw[FOUR][SIX:SEVEN] = 0;
#1 t.cw[THREE+:TWO] = 6'b010011;
#1 t.cw[FOUR-:TWO] = 6'b101011;
#1 t.cx[THREE][SIX+:ONE] = 1;
#1 t.cx[THREE][SEVEN-:TWO] = 1;
#1 t.cx[THREE][FIVE+:TWO] = 0;
#1 t.cx[THREE][SIX:SEVEN] = 2'b10;
#1 t.cx[THREE][SIX:SEVEN] = 2'b01;
#1 t.cx[FOUR:THREE] = '1;
#1 t.cx[FOUR][FIVE] = 0;
#1 t.cx[FOUR][SIX:SEVEN] = 0;
#1 t.cx[THREE+:TWO] = 6'b010011;
#1 t.cx[FOUR-:TWO] = 6'b101011;
#1 t.cy[THREE][SIX+:ONE] = 1;
#1 t.cy[THREE][SEVEN-:TWO] = 1;
#1 t.cy[THREE][FIVE+:TWO] = 0;
#1 t.cy[THREE][SEVEN:SIX] = 2'b10;
#1 t.cy[THREE][SEVEN:SIX] = 2'b01;
#1 t.cy[THREE:FOUR] = '1;
#1 t.cy[FOUR][FIVE] = 0;
#1 t.cy[FOUR][SEVEN:SIX] = 0;
#1 t.cy[THREE+:TWO] = 6'b010011;
#1 t.cy[FOUR-:TWO] = 6'b101011;
#1 t.cz[THREE][SIX+:ONE] = 1;
#1 t.cz[THREE][SEVEN-:TWO] = 1;
#1 t.cz[THREE][FIVE+:TWO] = 0;
#1 t.cz[THREE][SEVEN:SIX] = 2'b10;
#1 t.cz[THREE][SEVEN:SIX] = 2'b01;
#1 t.cz[FOUR:THREE] = '1;
#1 t.cz[FOUR][FIVE] = 0;
#1 t.cz[FOUR][SEVEN:SIX] = 0;
#1 t.cz[THREE+:TWO] = 6'b010011;
#1 t.cz[FOUR-:TWO] = 6'b101011;
end
endmodule
module top;
endmodule
// The reference output for this test should match that of the
// struct_part_select test.
`include "struct_part_select.v"
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