Commit 2d3973e6 by Zachary Snow

synthesizable wildcard conversion

parent 51f2d2bb
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
- -
- `!=?` is simply converted as the logical negation of `==?`, which is - `!=?` is simply converted as the logical negation of `==?`, which is
- -
- TODO: For code using actual wildcard patterns, this conversion produces code
- which is not synthesizable.
-
- The conversion for `inside` produces wildcard equality comparisons as per the - The conversion for `inside` produces wildcard equality comparisons as per the
- SystemVerilog specification. However, many usages of `inside` don't depend on - SystemVerilog specification. However, many usages of `inside` don't depend on
- the wildcard behavior. To avoid generating needlessly complex output, this - the wildcard behavior. To avoid generating needlessly complex output, this
...@@ -28,57 +25,58 @@ ...@@ -28,57 +25,58 @@
module Convert.Wildcard (convert) where module Convert.Wildcard (convert) where
import Control.Monad.State import Data.Bits ((.|.))
import qualified Data.Map.Strict as Map
import Convert.Scoper
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
type Patterns = Map.Map Identifier Number
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert = map $ traverseDescriptions convertDescription convert = map $ traverseDescriptions convertDescription
convertDescription :: Description -> Description convertDescription :: Description -> Description
convertDescription = convertDescription =
scopedConversion traverseDeclM traverseModuleItemM traverseStmtM Map.empty partScoper traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM
traverseDeclM :: Decl -> State Patterns Decl traverseDeclM :: Decl -> Scoper Number Decl
traverseDeclM decl = do traverseDeclM decl = do
case decl of case decl of
Param Localparam _ x (Number n) -> modify $ Map.insert x n Param Localparam _ x (Number n) -> insertElem x n
_ -> return () _ -> return ()
let mi = MIPackageItem $ Decl decl let mi = MIPackageItem $ Decl decl
mi' <- traverseModuleItemM mi mi' <- traverseModuleItemM mi
let MIPackageItem (Decl decl') = mi' let MIPackageItem (Decl decl') = mi'
return decl' return decl'
traverseModuleItemM :: ModuleItem -> State Patterns ModuleItem traverseModuleItemM :: ModuleItem -> Scoper Number ModuleItem
traverseModuleItemM = traverseExprsM traverseExprM traverseModuleItemM = traverseExprsM traverseExprM
traverseStmtM :: Stmt -> State Patterns Stmt traverseGenItemM :: GenItem -> Scoper Number GenItem
traverseGenItemM = traverseGenItemExprsM traverseExprM
traverseStmtM :: Stmt -> Scoper Number Stmt
traverseStmtM = traverseStmtExprsM traverseExprM traverseStmtM = traverseStmtExprsM traverseExprM
traverseExprM :: Expr -> State Patterns Expr traverseExprM :: Expr -> Scoper Number Expr
traverseExprM = traverseNestedExprsM $ stately convertExpr traverseExprM = traverseNestedExprsM $ embedScopes convertExpr
isPlainPattern :: Patterns -> Expr -> Bool lookupPattern :: Scopes Number -> Expr -> Maybe Number
isPlainPattern _ (Number n) = lookupPattern _ (Number n) = Just n
numberToInteger n /= Nothing lookupPattern scopes e =
isPlainPattern patterns (Ident x) = case lookupExpr scopes e of
case Map.lookup x patterns of Nothing -> Nothing
Nothing -> False Just (_, _, n) -> Just n
Just n -> isPlainPattern patterns (Number n)
isPlainPattern _ _ = False
convertExpr :: Patterns -> Expr -> Expr convertExpr :: Scopes Number -> Expr -> Expr
convertExpr patterns (BinOp WEq l r) = convertExpr scopes (BinOp WEq l r) =
if isPlainPattern patterns r if maybePattern == Nothing then
then BinOp Eq l r
else
BinOp BitAnd couldMatch $ BinOp BitAnd couldMatch $
BinOp BitOr noExtraXZs $ BinOp BitOr noExtraXZs $
Number (Based 1 False Binary 0 1) Number (Based 1 False Binary 0 1)
else if numberToInteger pattern /= Nothing then
BinOp Eq l r
else
BinOp Eq (BinOp BitOr l mask) pattern'
where where
lxl = BinOp BitXor l l lxl = BinOp BitXor l l
rxr = BinOp BitXor r r rxr = BinOp BitXor r r
...@@ -89,8 +87,14 @@ convertExpr patterns (BinOp WEq l r) = ...@@ -89,8 +87,14 @@ convertExpr patterns (BinOp WEq l r) =
-- Step #2: extra X or Z -- Step #2: extra X or Z
noExtraXZs = BinOp TEq lxlxrxr rxr noExtraXZs = BinOp TEq lxlxrxr rxr
lxlxrxr = BinOp BitXor lxl rxr lxlxrxr = BinOp BitXor lxl rxr
convertExpr patterns (BinOp WNe l r) = -- For wildcard patterns we can find, use masking
maybePattern = lookupPattern scopes r
Just pattern = maybePattern
Based size signed base vals knds = pattern
mask = Number $ Based size signed base knds 0
pattern' = Number $ Based size signed base (vals .|. knds) 0
convertExpr scopes (BinOp WNe l r) =
UniOp LogNot $ UniOp LogNot $
convertExpr patterns $ convertExpr scopes $
BinOp WEq l r BinOp WEq l r
convertExpr _ other = other convertExpr _ other = other
...@@ -14,9 +14,14 @@ module top; ...@@ -14,9 +14,14 @@ module top;
initial $display("D", 3'bz11 inside {3'b1?1, 3'b011}); initial $display("D", 3'bz11 inside {3'b1?1, 3'b011});
initial $display("E", 3'bz11 inside {3'b?01, 3'b011}); initial $display("E", 3'bz11 inside {3'b?01, 3'b011});
generate
begin : patterns
localparam A = 3'b1?1;
end
endgenerate
function test1; function test1;
input logic [2:0] inp; input logic [2:0] inp;
return inp inside {3'b1?1}; return inp inside {patterns.A};
endfunction endfunction
initial begin initial begin
// should match // should match
......
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