mirror of https://github.com/zachjs/sv2v.git
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
This commit is contained in:
parent
db4c396389
commit
976f582287
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
// The reference output for this test should match that of the
|
||||
// struct_part_select test.
|
||||
`include "struct_part_select.v"
|
||||
Loading…
Reference in New Issue