From fb3d68e339d49494b77a46456077f9a8999b61a3 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Fri, 5 Apr 2019 13:53:52 -0400 Subject: [PATCH] propper support for indexed part select addressing --- src/Convert/AsgnOp.hs | 10 ++-- src/Convert/Interface.hs | 4 +- src/Convert/PackedArray.hs | 55 ++++++++----------- src/Convert/Struct.hs | 24 ++++---- src/Convert/Traverse.hs | 14 ++--- src/Language/SystemVerilog/AST/Expr.hs | 33 ++++++++++- src/Language/SystemVerilog/AST/LHS.hs | 14 ++--- src/Language/SystemVerilog/Parser/Parse.y | 23 ++++---- .../SystemVerilog/Parser/ParseDecl.hs | 2 +- test/basic/part_select.sv | 12 ++++ test/basic/part_select.v | 12 ++++ test/basic/part_select_tb.v | 1 + 12 files changed, 125 insertions(+), 79 deletions(-) create mode 100644 test/basic/part_select.sv create mode 100644 test/basic/part_select.v create mode 100644 test/basic/part_select_tb.v diff --git a/src/Convert/AsgnOp.hs b/src/Convert/AsgnOp.hs index ef3727b..0bf31ad 100644 --- a/src/Convert/AsgnOp.hs +++ b/src/Convert/AsgnOp.hs @@ -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 diff --git a/src/Convert/Interface.hs b/src/Convert/Interface.hs index a8911ea..86165cf 100644 --- a/src/Convert/Interface.hs +++ b/src/Convert/Interface.hs @@ -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 = diff --git a/src/Convert/PackedArray.hs b/src/Convert/PackedArray.hs index 5033f81..3cce69e 100644 --- a/src/Convert/PackedArray.hs +++ b/src/Convert/PackedArray.hs @@ -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 diff --git a/src/Convert/Struct.hs b/src/Convert/Struct.hs index 15f9d2b..2fed5a6 100644 --- a/src/Convert/Struct.hs +++ b/src/Convert/Struct.hs @@ -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 diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index 5d9a18e..868073b 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -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 diff --git a/src/Language/SystemVerilog/AST/Expr.hs b/src/Language/SystemVerilog/AST/Expr.hs index 92bb868..f5d81db 100644 --- a/src/Language/SystemVerilog/AST/Expr.hs +++ b/src/Language/SystemVerilog/AST/Expr.hs @@ -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) + ) diff --git a/src/Language/SystemVerilog/AST/LHS.hs b/src/Language/SystemVerilog/AST/LHS.hs index 7c4e3bc..7fde305 100644 --- a/src/Language/SystemVerilog/AST/LHS.hs +++ b/src/Language/SystemVerilog/AST/LHS.hs @@ -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) diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index 744f97d..ae934df 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -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 - } diff --git a/src/Language/SystemVerilog/Parser/ParseDecl.hs b/src/Language/SystemVerilog/Parser/ParseDecl.hs index c34c450..df7b832 100644 --- a/src/Language/SystemVerilog/Parser/ParseDecl.hs +++ b/src/Language/SystemVerilog/Parser/ParseDecl.hs @@ -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) diff --git a/test/basic/part_select.sv b/test/basic/part_select.sv new file mode 100644 index 0000000..2e0ca5b --- /dev/null +++ b/test/basic/part_select.sv @@ -0,0 +1,12 @@ +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 diff --git a/test/basic/part_select.v b/test/basic/part_select.v new file mode 100644 index 0000000..1ae32a5 --- /dev/null +++ b/test/basic/part_select.v @@ -0,0 +1,12 @@ +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 diff --git a/test/basic/part_select_tb.v b/test/basic/part_select_tb.v new file mode 100644 index 0000000..d11c69f --- /dev/null +++ b/test/basic/part_select_tb.v @@ -0,0 +1 @@ +// intentionally empty