diff --git a/src/Convert/MultiplePacked.hs b/src/Convert/MultiplePacked.hs index f328b6b..5a38a44 100644 --- a/src/Convert/MultiplePacked.hs +++ b/src/Convert/MultiplePacked.hs @@ -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)) = diff --git a/src/Convert/Struct.hs b/src/Convert/Struct.hs index 6621e30..d92e31f 100644 --- a/src/Convert/Struct.hs +++ b/src/Convert/Struct.hs @@ -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 diff --git a/test/basic/struct_part_select_param.sv b/test/basic/struct_part_select_param.sv new file mode 100644 index 0000000..8c0c259 --- /dev/null +++ b/test/basic/struct_part_select_param.sv @@ -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 diff --git a/test/basic/struct_part_select_param.v b/test/basic/struct_part_select_param.v new file mode 100644 index 0000000..6beeb9c --- /dev/null +++ b/test/basic/struct_part_select_param.v @@ -0,0 +1,3 @@ +// The reference output for this test should match that of the +// struct_part_select test. +`include "struct_part_select.v"