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 ...@@ -27,7 +27,7 @@ module Convert.MultiplePacked (convert) where
import Control.Monad.State import Control.Monad.State
import Data.Tuple (swap) import Data.Tuple (swap)
import Data.Maybe (isJust, fromJust) import Data.Maybe (isJust)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Convert.Traverse import Convert.Traverse
...@@ -118,7 +118,10 @@ traverseLHSM :: LHS -> State Info LHS ...@@ -118,7 +118,10 @@ traverseLHSM :: LHS -> State Info LHS
traverseLHSM lhs = do traverseLHSM lhs = do
let expr = lhsToExpr lhs let expr = lhsToExpr lhs
expr' <- traverseExprM expr 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 :: Info -> Expr -> Expr
traverseExpr typeMap = traverseExpr typeMap =
...@@ -220,46 +223,45 @@ traverseExpr typeMap = ...@@ -220,46 +223,45 @@ traverseExpr typeMap =
range' = (simplify base, simplify len) range' = (simplify base, simplify len)
rewriteExpr (orig @ (Range (Bit expr idxInner) NonIndexed rangeOuter)) = rewriteExpr (orig @ (Range (Bit expr idxInner) NonIndexed rangeOuter)) =
if isJust maybeDims && expr == rewriteExpr expr if isJust maybeDims && expr == rewriteExpr expr
then endianCondExpr rangeOuter then rewriteExpr $ Range exprOuter IndexedMinus range
(rewriteExpr $ Range exprOuter IndexedMinus range)
(rewriteExpr $ Range exprOuter IndexedPlus range)
else orig else orig
where where
maybeDims = dims expr maybeDims = dims expr
exprOuter = Bit expr idxInner 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 len = rangeSize rangeOuter
range = (base, len) range = (base, len)
rewriteExpr (orig @ (Range (Bit expr idxInner) modeOuter rangeOuter)) = rewriteExpr (orig @ (Range (Bit expr idxInner) modeOuter rangeOuter)) =
if isJust maybeDims && expr == rewriteExpr expr if isJust maybeDims && expr == rewriteExpr expr
then endianCondExpr dimOuter then Range expr' modeOuter range'
(Range expr' modeDec range')
(Range expr' modeInc range')
else orig else orig
where where
maybeDims = dims expr maybeDims = dims expr
Just (dimInner, dimOuter, expr') = maybeDims Just (dimInner, dimOuter, expr') = maybeDims
idxInner' = orientIdx dimInner idxInner idxInner' = orientIdx dimInner idxInner
(modeDec, modeInc) =
case modeOuter of
IndexedPlus -> (IndexedPlus , IndexedMinus)
IndexedMinus -> (IndexedMinus, IndexedPlus )
NonIndexed -> error "invariant violated"
(baseOuter, lenOuter) = rangeOuter (baseOuter, lenOuter) = rangeOuter
baseOuter' = orientIdx dimOuter baseOuter baseOuter' = orientIdx dimOuter baseOuter
start = BinOp Mul idxInner' (rangeSize dimOuter) 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 len = lenOuter
range' = (base, len) range' = (base, len)
one = Number "1"
rewriteExpr (orig @ (Range expr NonIndexed range)) = rewriteExpr (orig @ (Range expr NonIndexed range)) =
if isJust maybeDims && expr == rewriteExpr expr if isJust maybeDims && expr == rewriteExpr expr
then endianCondExpr range then rewriteExpr $ Range expr IndexedMinus range'
(rewriteExpr $ Range expr IndexedMinus range')
(rewriteExpr $ Range expr IndexedPlus range')
else orig else orig
where where
maybeDims = dims expr 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 len = rangeSize range
range' = (base, len) range' = (base, len)
rewriteExpr (orig @ (Range expr mode range)) = rewriteExpr (orig @ (Range expr mode range)) =
......
...@@ -250,11 +250,13 @@ convertAsgn structs types (lhs, expr) = ...@@ -250,11 +250,13 @@ convertAsgn structs types (lhs, expr) =
-- converting LHSs by looking at the innermost types first -- converting LHSs by looking at the innermost types first
convertLHS :: LHS -> (Type, LHS) convertLHS :: LHS -> (Type, LHS)
convertLHS l = 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 where
e = lhsToExpr l e = lhsToExpr l
(t, e') = convertSubExpr e (t, e') = convertSubExpr e
Just l' = exprToLHS e'
specialTag = ':' specialTag = ':'
defaultKey = specialTag : "default" defaultKey = specialTag : "default"
...@@ -395,13 +397,12 @@ convertAsgn structs types (lhs, expr) = ...@@ -395,13 +397,12 @@ convertAsgn structs types (lhs, expr) =
maybeFields = getFields subExprType maybeFields = getFields subExprType
Just (structTf, fields) = maybeFields Just (structTf, fields) = maybeFields
(fieldType, bounds, dims) = lookupFieldInfo structTf fields x (fieldType, bounds, dims) = lookupFieldInfo structTf fields x
base = fst bounds
len = rangeSize bounds len = rangeSize bounds
[dim] = dims [dim] = dims
undotted = if null dims || rangeSize dim == Number "1" undotted = if null dims || rangeSize dim == Number "1"
then Bit e' (fst bounds) then Bit e' (fst bounds)
else endianCondExpr dim else Range e' IndexedMinus (base, len)
(Range e' IndexedMinus (fst bounds, len))
(Range e' IndexedPlus (snd bounds, len))
convertSubExpr (Range (Dot e x) NonIndexed rOuter) = convertSubExpr (Range (Dot e x) NonIndexed rOuter) =
if maybeFields == Nothing if maybeFields == Nothing
then (Implicit Unspecified [], orig') then (Implicit Unspecified [], orig')
...@@ -438,12 +439,14 @@ convertAsgn structs types (lhs, expr) = ...@@ -438,12 +439,14 @@ convertAsgn structs types (lhs, expr) =
[dim] = dims [dim] = dims
baseLeft = BinOp Sub (fst bounds) $ BinOp Sub (fst dim) baseO baseLeft = BinOp Sub (fst bounds) $ BinOp Sub (fst dim) baseO
baseRight = BinOp Add (snd bounds) $ BinOp Sub (snd dim) baseO baseRight = BinOp Add (snd bounds) $ BinOp Sub (snd dim) baseO
undotted = endianCondExpr dim baseDec = baseLeft
(Range e' mode (baseLeft , lenO)) baseInc = case mode of
(Range e' otherMode (baseRight, lenO)) IndexedPlus -> BinOp Add (BinOp Sub baseRight lenO) one
otherMode = if mode == IndexedPlus IndexedMinus -> BinOp Sub (BinOp Add baseRight lenO) one
then IndexedMinus NonIndexed -> error "invariant violated"
else IndexedPlus base = endianCondExpr dim baseDec baseInc
undotted = Range e' mode (base, lenO)
one = Number "1"
convertSubExpr (Range e mode r) = convertSubExpr (Range e mode r) =
(t', Range e' mode r) (t', Range e' mode r)
where 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