Commit fb3d68e3 by Zachary Snow

propper support for indexed part select addressing

parent 011d88b5
......@@ -37,8 +37,8 @@ convertStmt (AsgnBlk (AsgnOp op) lhs expr) =
convertStmt other = other
lhsToExpr :: LHS -> Expr
lhsToExpr (LHSIdent x) = Ident x
lhsToExpr (LHSBit l e) = Bit (lhsToExpr l) e
lhsToExpr (LHSRange l r) = Range (lhsToExpr l) r
lhsToExpr (LHSDot l x) = Dot (lhsToExpr l) x
lhsToExpr (LHSConcat ls) = Concat $ map lhsToExpr ls
lhsToExpr (LHSIdent x ) = Ident x
lhsToExpr (LHSBit l e ) = Bit (lhsToExpr l) e
lhsToExpr (LHSRange l m r) = Range (lhsToExpr l) m r
lhsToExpr (LHSDot l x ) = Dot (lhsToExpr l) x
lhsToExpr (LHSConcat ls ) = Concat $ map lhsToExpr ls
......@@ -167,8 +167,8 @@ convertDescription interfaces modules (Part extern Module lifetime name ports it
else orig
convertLHS its mps (LHSBit l e) =
LHSBit l (traverseNestedExprs (convertExpr its mps) e)
convertLHS its mps (LHSRange l (e1, e2)) =
LHSRange l (traverseNestedExprs (convertExpr its mps) e1, traverseNestedExprs (convertExpr its mps) e2)
convertLHS its mps (LHSRange l m (e1, e2)) =
LHSRange l m (traverseNestedExprs (convertExpr its mps) e1, traverseNestedExprs (convertExpr its mps) e2)
convertLHS _ _ other = other
convertPort :: Identifier -> [Identifier]
convertPort ident =
......
......@@ -105,14 +105,14 @@ collectExpr :: Expr -> State Info ()
collectExpr (Ident i) = recordSeqUsage i
collectExpr other = collectNestedExprsM collectNestedExpr other
collectNestedExpr :: Expr -> State Info ()
collectNestedExpr (Range (Ident i) _) = recordSeqUsage i
collectNestedExpr (Range (Ident i) _ _) = recordSeqUsage i
collectNestedExpr _ = return ()
collectLHS :: LHS -> State Info ()
collectLHS (LHSIdent i) = recordSeqUsage i
collectLHS other = collectNestedLHSsM collectNestedLHS other
collectNestedLHS :: LHS -> State Info ()
collectNestedLHS (LHSRange (LHSIdent i) _) = recordSeqUsage i
collectNestedLHS (LHSBit (LHSIdent i) _) = recordIdxUsage i
collectNestedLHS (LHSRange (LHSIdent i) _ _) = recordSeqUsage i
collectNestedLHS (LHSBit (LHSIdent i) _) = recordIdxUsage i
collectNestedLHS _ = return ()
-- VCS doesn't like port declarations inside of `generate` blocks, so we hoist
......@@ -190,18 +190,18 @@ unflattener writeToFlatVariant arr (t, major @ (majorHi, majorLo)) =
, GenModuleItem $ MIDecl $ Variable Local (IntegerAtom TInteger Unspecified) (arrUnflat ++ "_repeater_index") [] Nothing
, GenFor
(index, majorLo)
(ccExpr major
(endianCondExpr major
(BinOp Le (Ident index) majorHi)
(BinOp Ge (Ident index) majorHi))
(index, AsgnOp Add, ccExpr major (Number "1") (Number "-1"))
(index, AsgnOp Add, endianCondExpr major (Number "1") (Number "-1"))
(Just $ prefix "unflatten_" ++ arr)
[ localparam startBit
(simplify $ BinOp Add (ccExpr major majorLo majorHi)
(simplify $ BinOp Add (endianCondExpr major majorLo majorHi)
(BinOp Mul (Ident index) size))
, GenModuleItem $ (uncurry $ Assign Nothing) $
if not writeToFlatVariant
then (LHSBit (LHSIdent arrUnflat) $ Ident index, Range (Ident arr) origRange)
else (LHSRange (LHSIdent arr) origRange, Bit (Ident arrUnflat) (Ident index))
then (LHSBit (LHSIdent arrUnflat) $ Ident index, Range (Ident arr) NonIndexed origRange)
else (LHSRange (LHSIdent arr) NonIndexed origRange, Bit (Ident arrUnflat) (Ident index))
]
]
where
......@@ -209,22 +209,13 @@ unflattener writeToFlatVariant arr (t, major @ (majorHi, majorLo)) =
arrUnflat = prefix arr
index = prefix "_tmp_index_" ++ arr
minor = head $ snd $ typeRanges t
size = rangeSize $ ccRange minor minor (swap minor)
size = rangeSize $ endianCondRange minor minor (swap minor)
localparam :: Identifier -> Expr -> GenItem
localparam x v = GenModuleItem $ MIDecl $ Localparam (Implicit Unspecified []) x v
origRangeAg = ( (BinOp Add (Ident startBit)
(BinOp Sub size (Number "1")))
, 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)
)
origRange = endianCondRange major origRangeAg (swap origRangeAg)
typeIsImplicit :: Type -> Bool
typeIsImplicit (Implicit _ _) = True
......@@ -247,10 +238,10 @@ flattenRanges rs =
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)
rY = endianCondRange r2 rYY rYN
rN = endianCondRange r2 rNY rNN
rAg = endianCondRange r1 rY rN
r = endianCondRange r1 rAg (swap rAg)
rs' = (tail $ tail rs) ++ [r]
flattenRangesHelp :: Range -> Range -> Range
......@@ -287,17 +278,17 @@ rewriteModuleItem info =
rewriteExpr (Ident i) = Ident $ rewriteSeqIdent i
rewriteExpr (Bit (Ident i) e) =
if Map.member i typeDims && Set.member i seqUses && Set.notMember i idxUses
then Range (Ident $ rewriteSeqIdent i) (hi, lo)
then Range (Ident $ rewriteSeqIdent i) NonIndexed (hi, lo)
else Bit (Ident $ rewriteIdxIdent i) e
where
r = head $ snd $ typeRanges $ fst $ typeDims Map.! i
size = rangeSize r
lo = simplify $ BinOp Mul e size
hi = simplify $ BinOp Add lo (BinOp Sub size (Number "1"))
rewriteExpr (Range (Ident i) (r @ (s, e))) =
rewriteExpr (Range (Ident i) m (r @ (s, e))) =
if Map.member i typeDims
then Range (Ident i) r'
else Range (Ident i) r
then Range (Ident i) m r'
else Range (Ident i) m r
where
(a, b) = head $ snd $ typeRanges $ fst $ typeDims Map.! i
size = rangeSize (a, b)
......@@ -307,13 +298,13 @@ rewriteModuleItem info =
rewriteExpr other = other
rewriteLHS :: LHS -> LHS
rewriteLHS (LHSIdent x ) = LHSIdent (rewriteSeqIdent x)
rewriteLHS (LHSIdent x ) = LHSIdent (rewriteSeqIdent x)
rewriteLHS (LHSBit (LHSIdent x) e) =
LHSBit (LHSIdent $ rewriteIdxIdent x) e
rewriteLHS (LHSBit l e) = LHSBit (rewriteLHS l) e
rewriteLHS (LHSRange l r) = LHSRange (rewriteLHS l) r
rewriteLHS (LHSDot l x) = LHSDot (rewriteLHS l) x
rewriteLHS (LHSConcat ls) = LHSConcat $ map rewriteLHS ls
rewriteLHS (LHSBit l e ) = LHSBit (rewriteLHS l) e
rewriteLHS (LHSRange l m r) = LHSRange (rewriteLHS l) m r
rewriteLHS (LHSDot l x ) = LHSDot (rewriteLHS l) x
rewriteLHS (LHSConcat ls ) = LHSConcat $ map rewriteLHS ls
rewriteStmt :: Stmt -> Stmt
rewriteStmt (AsgnBlk op lhs expr) = convertAssignment (AsgnBlk op) lhs expr
......
......@@ -148,16 +148,16 @@ convertAsgn structs types (lhs, expr) =
(t, l') = convertLHS l
(tf, rs) = typeRanges t
e' = snd $ convertSubExpr e
convertLHS (LHSRange l rOuterOrig) =
convertLHS (LHSRange l m rOuterOrig) =
case l' of
LHSRange lInner (_, loI) ->
(t, LHSRange lInner (simplify hi, simplify lo))
LHSRange lInner NonIndexed (_, loI) ->
(t, LHSRange lInner m (simplify hi, simplify lo))
where
lo = BinOp Add loI loO
hi = BinOp Add loI hiO
_ -> if null rs
then (Implicit Unspecified [], LHSRange l' rOuter)
else (tf rs', LHSRange l' rOuter)
then (Implicit Unspecified [], LHSRange l' m rOuter)
else (tf rs', LHSRange l' m rOuter)
where
(t, l') = convertLHS l
(tf, rs) = typeRanges t
......@@ -170,7 +170,7 @@ convertAsgn structs types (lhs, expr) =
InterfaceT _ _ _ -> (Implicit Unspecified [], LHSDot l' x)
Struct _ _ _ -> case Map.lookup structTf structs of
Nothing -> (fieldType, LHSDot l' x)
Just (structT, m) -> (tf [tr], LHSRange l' r)
Just (structT, m) -> (tf [tr], LHSRange l' NonIndexed r)
where
(tf, _) = typeRanges structT
(r @ (hi, lo), base) = m Map.! x
......@@ -228,7 +228,7 @@ convertAsgn structs types (lhs, expr) =
Struct _ _ _ ->
if Map.notMember structTf structs
then (fieldType, Dot e' x)
else (fieldType, Range e' r)
else (fieldType, Range e' NonIndexed r)
_ -> (Implicit Unspecified [], Dot e' x)
where
(subExprType, e') = convertSubExpr e
......@@ -236,17 +236,17 @@ convertAsgn structs types (lhs, expr) =
structTf = Struct p fields
fieldType = lookupFieldType fields x
r = lookupUnstructRange structTf x
convertSubExpr (Range eOuter (rOuter @ (hiO, loO))) =
convertSubExpr (Range eOuter m (rOuter @ (hiO, loO))) =
-- VCS doesn't allow ranges to be cascaded, so we need to combine
-- nested Ranges into a single range. My understanding of the
-- semantics are that a range returns a new, zero-indexed sub-range.
case eOuter' of
Range eInner (_, loI) ->
(t, Range eInner (simplify hi, simplify lo))
Range eInner NonIndexed (_, loI) ->
(t, Range eInner m (simplify hi, simplify lo))
where
lo = BinOp Add loI loO
hi = BinOp Add loI hiO
_ -> (t, Range eOuter' rOuter)
_ -> (t, Range eOuter' m rOuter)
where (t, eOuter') = convertSubExpr eOuter
convertSubExpr (Concat exprs) =
(Implicit Unspecified [], Concat $ map (snd . convertSubExpr) exprs)
......@@ -257,7 +257,7 @@ convertAsgn structs types (lhs, expr) =
(_, e2') = convertSubExpr e2
convertSubExpr (Bit e i) =
case e' of
Range eInner (_, loI) ->
Range eInner NonIndexed (_, loI) ->
(t', Bit eInner (simplify $ BinOp Add loI i'))
_ -> (t', Bit e' i')
where
......
......@@ -355,11 +355,11 @@ traverseNestedExprsM mapper = exprMapper
em (String s) = return $ String s
em (Number s) = return $ Number s
em (Ident i) = return $ Ident i
em (Range e (e1, e2)) = do
em (Range e m (e1, e2)) = do
e' <- exprMapper e
e1' <- exprMapper e1
e2' <- exprMapper e2
return $ Range e' (e1', e2')
return $ Range e' m (e1', e2')
em (Bit e1 e2) = do
e1' <- exprMapper e1
e2' <- exprMapper e2
......@@ -611,11 +611,11 @@ traverseNestedLHSsM :: Monad m => MapperM m LHS -> MapperM m LHS
traverseNestedLHSsM mapper = fullMapper
where
fullMapper lhs = tl lhs >>= mapper
tl (LHSIdent x ) = return $ LHSIdent x
tl (LHSBit l e ) = fullMapper l >>= \l' -> return $ LHSBit l' e
tl (LHSRange l r ) = fullMapper l >>= \l' -> return $ LHSRange l' r
tl (LHSDot l x ) = fullMapper l >>= \l' -> return $ LHSDot l' x
tl (LHSConcat lhss) = mapM fullMapper lhss >>= return . LHSConcat
tl (LHSIdent x ) = return $ LHSIdent x
tl (LHSBit l e ) = fullMapper l >>= \l' -> return $ LHSBit l' e
tl (LHSRange l m r) = fullMapper l >>= \l' -> return $ LHSRange l' m r
tl (LHSDot l x ) = fullMapper l >>= \l' -> return $ LHSDot l' x
tl (LHSConcat lhss ) = mapM fullMapper lhss >>= return . LHSConcat
traverseNestedLHSs :: Mapper LHS -> Mapper LHS
traverseNestedLHSs = unmonad traverseNestedLHSsM
......
......@@ -9,10 +9,13 @@ module Language.SystemVerilog.AST.Expr
( Expr (..)
, Range
, Args (..)
, PartSelectMode (..)
, showAssignment
, showRanges
, simplify
, rangeSize
, endianCondExpr
, endianCondRange
) where
import Data.List (intercalate)
......@@ -29,7 +32,7 @@ data Expr
= String String
| Number String
| Ident Identifier
| Range Expr Range
| Range Expr PartSelectMode Range
| Bit Expr Expr
| Repeat Expr [Expr]
| Concat [Expr]
......@@ -48,7 +51,7 @@ instance Show Expr where
show (Ident str ) = str
show (String str ) = printf "\"%s\"" str
show (Bit e b ) = printf "%s[%s]" (show e) (show b)
show (Range e r ) = printf "%s%s" (show e) (showRange r)
show (Range e m r) = printf "%s[%s%s%s]" (show e) (show $ fst r) (show m) (show $ snd r)
show (Repeat e l ) = printf "{%s {%s}}" (show e) (commas $ map show l)
show (Concat l ) = printf "{%s}" (commas $ map show l)
show (UniOp a b ) = printf "(%s %s)" (show a) (show b)
......@@ -76,6 +79,17 @@ instance Show Args where
showPnArg = maybe "" show
showKwArg (x, me) = printf ".%s(%s)" x (showPnArg me)
data PartSelectMode
= NonIndexed
| IndexedPlus
| IndexedMinus
deriving (Eq, Ord)
instance Show PartSelectMode where
show NonIndexed = ":"
show IndexedPlus = "+:"
show IndexedMinus = "-:"
showAssignment :: Maybe Expr -> String
showAssignment Nothing = ""
showAssignment (Just val) = " = " ++ show val
......@@ -132,3 +146,18 @@ simplify other = other
rangeSize :: Range -> Expr
rangeSize (s, e) =
simplify $ BinOp Add (BinOp Sub s e) (Number "1")
-- chooses one or the other expression based on the endianness of the given
-- range; [hi:lo] chooses the first expression
endianCondExpr :: Range -> Expr -> Expr -> Expr
endianCondExpr r e1 e2 = simplify $ Mux (uncurry (BinOp Ge) r) e1 e2
-- chooses one or the other range based on the endianness of the given range,
-- but in such a way that the result is itself also usable as a range even if
-- the endianness cannot be resolved during conversion, i.e. if it's dependent
-- on a parameter value; [hi:lo] chooses the first range
endianCondRange :: Range -> Range -> Range -> Range
endianCondRange r r1 r2 =
( endianCondExpr r (fst r1) (fst r2)
, endianCondExpr r (snd r1) (snd r2)
)
......@@ -13,19 +13,19 @@ import Text.Printf (printf)
import Language.SystemVerilog.AST.ShowHelp (commas)
import Language.SystemVerilog.AST.Type (Identifier)
import Language.SystemVerilog.AST.Expr (Expr, Range)
import Language.SystemVerilog.AST.Expr (Expr, PartSelectMode, Range)
data LHS
= LHSIdent Identifier
| LHSBit LHS Expr
| LHSRange LHS Range
| LHSRange LHS PartSelectMode Range
| LHSDot LHS Identifier
| LHSConcat [LHS]
deriving Eq
instance Show LHS where
show (LHSIdent x ) = x
show (LHSBit l e ) = printf "%s[%s]" (show l) (show e)
show (LHSRange l (a, b)) = printf "%s[%s:%s]" (show l) (show a) (show b)
show (LHSDot l x ) = printf "%s.%s" (show l) x
show (LHSConcat lhss ) = printf "{%s}" (commas $ map show lhss)
show (LHSIdent x ) = x
show (LHSBit l e ) = printf "%s[%s]" (show l) (show e)
show (LHSRange l m (a, b)) = printf "%s[%s%s%s]" (show l) (show a) (show m) (show b)
show (LHSDot l x ) = printf "%s.%s" (show l) x
show (LHSConcat lhss ) = printf "{%s}" (commas $ map show lhss)
......@@ -601,13 +601,15 @@ DeclAsgn :: { (Identifier, Expr) }
Range :: { Range }
: "[" Expr ":" Expr "]" { ($2, $4) }
-- TODO: This assumes the ranges are always [hi:lo]; See section 11.5.1!
| "[" Expr "+:" Expr "]" { (BinOp Sub (BinOp Add $2 $4) (Number "1"), $2) }
| "[" Expr "-:" Expr "]" { ($2, BinOp Add (BinOp Sub $2 $4) (Number "1")) }
PartSelect :: { (PartSelectMode, Range) }
: "[" Expr ":" Expr "]" { (NonIndexed , ($2, $4)) }
| "[" Expr "+:" Expr "]" { (IndexedPlus , ($2, $4)) }
| "[" Expr "-:" Expr "]" { (IndexedMinus, ($2, $4)) }
LHS :: { LHS }
: Identifier { LHSIdent $1 }
| LHS Range { LHSRange $1 $2 }
| LHS PartSelect { LHSRange $1 (fst $2) (snd $2) }
| LHS "[" Expr "]" { LHSBit $1 $3 }
| LHS "." Identifier { LHSDot $1 $3 }
| "{" LHSs "}" { LHSConcat $2 }
......@@ -782,7 +784,7 @@ Expr :: { Expr }
| Identifier "(" CallArgs ")" { Call $1 $3 }
| "$bits" "(" BitsArg ")" { Bits $3 }
| Identifier { Ident $1 }
| Expr Range { Range $1 $2 }
| Expr PartSelect { Range $1 (fst $2) (snd $2) }
| Expr "[" Expr "]" { Bit $1 $3 }
| "{" Expr "{" Exprs "}" "}" { Repeat $2 $4 }
| "{" Exprs "}" { Concat $2 }
......@@ -934,12 +936,11 @@ combineTags Nothing other = other
combineTags other _ = other
exprToLHS :: Expr -> LHS
exprToLHS (Ident x) = LHSIdent x
exprToLHS (Bit e b) = LHSBit (exprToLHS e) b
exprToLHS (Range e r) = LHSRange (exprToLHS e) r
exprToLHS (Dot e x) = LHSDot (exprToLHS e) x
exprToLHS (Concat es) = LHSConcat (map exprToLHS es)
exprToLHS (Ident x ) = LHSIdent x
exprToLHS (Bit e b ) = LHSBit (exprToLHS e) b
exprToLHS (Range e m r) = LHSRange (exprToLHS e) m r
exprToLHS (Dot e x ) = LHSDot (exprToLHS e) x
exprToLHS (Concat es ) = LHSConcat (map exprToLHS es)
exprToLHS other =
error $ "Parse error: cannot convert expression to LHS: " ++ show other
}
......@@ -235,7 +235,7 @@ takeLHSStep :: Maybe LHS -> DeclToken -> Maybe LHS
takeLHSStep (Nothing ) (DTConcat lhss) = Just $ LHSConcat lhss
takeLHSStep (Nothing ) (DTIdent x ) = Just $ LHSIdent x
takeLHSStep (Just curr) (DTBit e ) = Just $ LHSBit curr e
takeLHSStep (Just curr) (DTRange r ) = Just $ LHSRange curr r
takeLHSStep (Just curr) (DTRange r ) = Just $ LHSRange curr NonIndexed r
takeLHSStep (Just curr) (DTDot x ) = Just $ LHSDot curr x
takeLHSStep (maybeCurr) token =
error $ "unexpected token in LHS: " ++ show (maybeCurr, token)
......
module top;
wire [31:0] a;
wire [0:31] b;
assign a = 'h64ded943;
assign b = 'hb7151d17;
initial begin
$display(a[0+:8]);
$display(a[15-:8]);
$display(b[0+:8]);
$display(b[15-:8]);
end
endmodule
module top;
wire [31:0] a;
wire [0:31] b;
assign a = 'h64ded943;
assign b = 'hb7151d17;
initial begin
$display(a[7:0]);
$display(a[15:8]);
$display(b[0:7]);
$display(b[8:15]);
end
endmodule
// intentionally empty
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