Commit 9694799a by Zachary Snow

more consistent procedural assignment support

parent 610d9aba
......@@ -32,6 +32,6 @@ convertStmt (For inits cc asgns stmt) =
convertAsgn (lhs, AsgnOp op, expr) =
(lhs, AsgnOpEq, BinOp op (lhsToExpr lhs) expr)
convertAsgn other = other
convertStmt (AsgnBlk (AsgnOp op) lhs expr) =
AsgnBlk AsgnOpEq lhs (BinOp op (lhsToExpr lhs) expr)
convertStmt (Asgn (AsgnOp op) mt lhs expr) =
Asgn AsgnOpEq mt lhs (BinOp op (lhsToExpr lhs) expr)
convertStmt other = other
......@@ -47,4 +47,4 @@ splitDecl (Variable d t ident a (Just e)) =
splitDecl other = (other, Nothing)
asgnStmt :: (LHS, Expr) -> Stmt
asgnStmt = uncurry $ AsgnBlk AsgnOpEq
asgnStmt = uncurry $ Asgn AsgnOpEq Nothing
......@@ -80,7 +80,7 @@ splitDecl other =
error $ "invalid for loop decl: " ++ show other
asgnStmt :: (LHS, Expr) -> Stmt
asgnStmt = uncurry $ AsgnBlk AsgnOpEq
asgnStmt = uncurry $ Asgn AsgnOpEq Nothing
dummyDecl :: Maybe Expr -> Decl
dummyDecl = Variable Local (IntegerAtom TInteger Unspecified) "_sv2v_dummy" []
......@@ -101,7 +101,7 @@ addJumpStateDeclStmt stmt =
where (decls, [stmt']) = addJumpStateDeclTF [] [stmt]
removeJumpState :: Stmt -> Stmt
removeJumpState (orig @ (AsgnBlk _ (LHSIdent ident) _)) =
removeJumpState (orig @ (Asgn _ _ (LHSIdent ident) _)) =
if ident == jumpState
then Null
else orig
......@@ -298,4 +298,4 @@ assertMsg True _ = return ()
assertMsg False msg = error msg
asgn :: Identifier -> Expr -> Stmt
asgn x e = AsgnBlk AsgnOpEq (LHSIdent x) e
asgn x e = Asgn AsgnOpEq Nothing (LHSIdent x) e
......@@ -80,7 +80,7 @@ convertDescription ports orig =
fixModuleItem (Assign Nothing lhs expr) =
if Set.disjoint usedIdents origIdents
then Assign Nothing lhs expr
else AlwaysC AlwaysComb $ AsgnBlk AsgnOpEq lhs expr
else AlwaysC AlwaysComb $ Asgn AsgnOpEq Nothing lhs expr
where
usedIdents = execWriter $ collectNestedLHSsM lhsIdents lhs
-- rewrite port bindings to use temporary nets where necessary
......@@ -109,7 +109,7 @@ convertDescription ports orig =
t = Net TWire Unspecified [(DimsFn FnBits $ Right expr, Number "1")]
items =
[ MIPackageItem $ Decl $ Variable Local t tmp [] Nothing
, AlwaysC AlwaysComb $ AsgnBlk AsgnOpEq lhs tmpExpr]
, AlwaysC AlwaysComb $ Asgn AsgnOpEq Nothing lhs tmpExpr]
lhs = case exprToLHS expr of
Just l -> l
Nothing ->
......
......@@ -36,7 +36,7 @@ streamerBlock chunk size asgn output input =
, Variable Local (IntegerAtom TInteger Unspecified) bas [] Nothing
]
[ For inits cmp incr stmt
, AsgnBlk AsgnOpEq (LHSIdent bas) (Ident idx)
, Asgn AsgnOpEq Nothing (LHSIdent bas) (Ident idx)
, For inits cmp2 incr2 stmt2
, asgn output (Ident out)
]
......@@ -55,23 +55,21 @@ streamerBlock chunk size asgn output input =
incr = [(LHSIdent idx, AsgnOp Add, chunk)]
lhs = LHSRange (LHSIdent out) IndexedMinus (BinOp Sub hi (Ident idx), chunk)
expr = Range (Ident inp) IndexedPlus (Ident idx, chunk)
stmt = AsgnBlk AsgnOpEq lhs expr
stmt = Asgn AsgnOpEq Nothing lhs expr
-- final chunk loop
cmp2 = BinOp Lt (Ident idx) (BinOp Sub size (Ident bas))
incr2 = [(LHSIdent idx, AsgnOp Add, Number "1")]
lhs2 = LHSBit (LHSIdent out) (Ident idx)
expr2 = Bit (Ident inp) (BinOp Add (Ident idx) (Ident bas))
stmt2 = AsgnBlk AsgnOpEq lhs2 expr2
stmt2 = Asgn AsgnOpEq Nothing lhs2 expr2
streamerBlockName :: Expr -> Expr -> Identifier
streamerBlockName chunk size =
"_sv2v_strm_" ++ shortHash (chunk, size)
traverseStmtM :: Stmt -> Writer Funcs Stmt
traverseStmtM (AsgnBlk op lhs expr) =
traverseAsgnM (lhs, expr) (AsgnBlk op)
traverseStmtM (Asgn mt lhs expr) =
traverseAsgnM (lhs, expr) (Asgn mt)
traverseStmtM (Asgn op mt lhs expr) =
traverseAsgnM (lhs, expr) (Asgn op mt)
traverseStmtM other = return other
traverseAsgnM :: (LHS, Expr) -> (LHS -> Expr -> Stmt) -> Writer Funcs Stmt
......
......@@ -244,8 +244,7 @@ traverseSinglyNestedStmtsM fullMapper = cs
caseStmts <- mapM fullMapper $ map snd cases
let cases' = zip (map fst cases) caseStmts
return $ Case u kw expr cases'
cs (AsgnBlk op lhs expr) = return $ AsgnBlk op lhs expr
cs (Asgn mt lhs expr) = return $ Asgn mt lhs expr
cs (Asgn op mt lhs expr) = return $ Asgn op mt lhs expr
cs (For a b c stmt) = fullMapper stmt >>= return . For a b c
cs (While e stmt) = fullMapper stmt >>= return . While e
cs (RepeatL e stmt) = fullMapper stmt >>= return . RepeatL e
......@@ -375,12 +374,12 @@ traverseStmtLHSsM mapper = stmtMapper
stmtMapper (Timing (Event sense) stmt) = do
sense' <- senseMapper sense
return $ Timing (Event sense') stmt
stmtMapper (Asgn (Just (Event sense)) lhs expr) = do
stmtMapper (Asgn op (Just (Event sense)) lhs expr) = do
lhs' <- fullMapper lhs
sense' <- senseMapper sense
return $ Asgn (Just $ Event sense') lhs' expr
stmtMapper (AsgnBlk op lhs expr) = fullMapper lhs >>= \lhs' -> return $ AsgnBlk op lhs' expr
stmtMapper (Asgn mt lhs expr) = fullMapper lhs >>= \lhs' -> return $ Asgn mt lhs' expr
return $ Asgn op (Just $ Event sense') lhs' expr
stmtMapper (Asgn op mt lhs expr) =
fullMapper lhs >>= \lhs' -> return $ Asgn op mt lhs' expr
stmtMapper (For inits me incrs stmt) = do
inits' <- mapInits inits
let (lhss, asgnOps, exprs) = unzip3 incrs
......@@ -708,14 +707,10 @@ traverseStmtExprsM exprMapper = flatStmtMapper
e' <- exprMapper e
cases' <- mapM caseMapper cases
return $ Case u kw e' cases'
flatStmtMapper (AsgnBlk op lhs expr) = do
flatStmtMapper (Asgn op mt lhs expr) = do
lhs' <- lhsMapper lhs
expr' <- exprMapper expr
return $ AsgnBlk op lhs' expr'
flatStmtMapper (Asgn mt lhs expr) = do
lhs' <- lhsMapper lhs
expr' <- exprMapper expr
return $ Asgn mt lhs' expr'
return $ Asgn op mt lhs' expr'
flatStmtMapper (For inits cc asgns stmt) = do
inits' <- initsMapper inits
cc' <- exprMapper cc
......@@ -1028,12 +1023,9 @@ collectAsgnsM = collectAsgnsM' IncludeTFs
traverseStmtAsgnsM :: Monad m => MapperM m (LHS, Expr) -> MapperM m Stmt
traverseStmtAsgnsM mapper = stmtMapper
where
stmtMapper (AsgnBlk op lhs expr) = do
(lhs', expr') <- mapper (lhs, expr)
return $ AsgnBlk op lhs' expr'
stmtMapper (Asgn mt lhs expr) = do
stmtMapper (Asgn op mt lhs expr) = do
(lhs', expr') <- mapper (lhs, expr)
return $ Asgn mt lhs' expr'
return $ Asgn op mt lhs' expr'
stmtMapper other = return other
traverseStmtAsgns :: Mapper (LHS, Expr) -> Mapper Stmt
......
......@@ -100,11 +100,13 @@ instance Show BinOp where
data AsgnOp
= AsgnOpEq
| AsgnOpNonBlocking
| AsgnOp BinOp
deriving (Eq, Ord)
instance Show AsgnOp where
show AsgnOpEq = "="
show AsgnOpNonBlocking = "<="
show (AsgnOp op) = (show op) ++ "="
data StreamOp
......
......@@ -38,8 +38,7 @@ data Stmt
| Block BlockKW Identifier [Decl] [Stmt]
| Case ViolationCheck CaseKW Expr [Case]
| For (Either [Decl] [(LHS, Expr)]) Expr [(LHS, AsgnOp, Expr)] Stmt
| AsgnBlk AsgnOp LHS Expr
| Asgn (Maybe Timing) LHS Expr
| Asgn AsgnOp (Maybe Timing) LHS Expr
| While Expr Stmt
| RepeatL Expr Stmt
| DoWhile Expr Stmt
......@@ -83,8 +82,7 @@ instance Show Stmt where
showAssign (l, op, e) = printf "%s %s %s" (show l) (show op) (show e)
show (Subroutine e a) = printf "%s%s;" (show e) aStr
where aStr = if a == Args [] [] then "" else show a
show (AsgnBlk o v e) = printf "%s %s %s;" (show v) (show o) (show e)
show (Asgn t v e) = printf "%s <= %s%s;" (show v) (maybe "" showPad t) (show e)
show (Asgn o t v e) = printf "%s %s %s%s;" (show v) (show o) (maybe "" showPad t) (show e)
show (While e s) = printf "while (%s) %s" (show e) (show s)
show (RepeatL e s) = printf "repeat (%s) %s" (show e) (show s)
show (DoWhile e s) = printf "do %s while (%s);" (show s) (show e)
......@@ -134,7 +132,6 @@ showElseBranch (stmt @ If{}) = ' ' : show stmt
showElseBranch stmt = showBranch stmt
showShortBranch :: Stmt -> String
showShortBranch (stmt @ AsgnBlk{}) = ' ' : show stmt
showShortBranch (stmt @ Asgn{}) = ' ' : show stmt
showShortBranch stmt = showBranch stmt
......
......@@ -593,8 +593,8 @@ DeclTokens(delim) :: { [DeclToken] }
: DeclToken delim { [$1] }
| DeclToken DeclTokens(delim) { [$1] ++ $2 }
| Identifier ParamBindings DeclTokens(delim) {% posInject \p -> [DTIdent p $1, DTParams p $2] ++ $3 }
| AsgnOp Expr "," DeclTokens(delim) {% posInject \p -> [DTAsgn p $1 $2, DTComma p] ++ $4 }
| AsgnOp Expr delim {% posInject \p -> [DTAsgn p $1 $2] }
| DeclTokenAsgn "," DeclTokens(delim) {% posInject \p -> [$1, DTComma p] ++ $3 }
| DeclTokenAsgn delim {% posInject \p -> [$1] }
DeclToken :: { DeclToken }
: "," {% posInject \p -> DTComma p }
| "[" "]" {% posInject \p -> DTAutoDim p }
......@@ -613,8 +613,11 @@ DeclToken :: { DeclToken }
| "{" StreamOp StreamSize Concat "}" {% posInject \p -> DTStream p $2 $3 (map toLHS $4) }
| "{" StreamOp Concat "}" {% posInject \p -> DTStream p $2 (Number "1") (map toLHS $3) }
| opt("var") "type" "(" Expr ")" {% posInject \p -> DTType p (\Unspecified -> \[] -> TypeOf $4) }
| "<=" opt(DelayOrEventControl) Expr {% posInject \p -> DTAsgnNBlk p $2 $3 }
| IncOrDecOperator {% posInject \p -> DTAsgn p (AsgnOp $1) (Number "1") }
| "<=" opt(DelayOrEvent) Expr {% posInject \p -> DTAsgn p AsgnOpNonBlocking $2 $3 }
| IncOrDecOperator {% posInject \p -> DTAsgn p (AsgnOp $1) Nothing (Number "1") }
DeclTokenAsgn :: { DeclToken }
: "=" opt(DelayOrEvent) Expr {% posInject \p -> DTAsgn p AsgnOpEq $2 $3 }
| AsgnBinOp Expr {% posInject \p -> DTAsgn p $1 Nothing $2 }
VariablePortIdentifiers :: { [(Identifier, Maybe Expr)] }
: VariablePortIdentifier { [$1] }
......@@ -902,10 +905,11 @@ Stmt :: { Stmt }
| StmtTrace StmtNonAsgn { $2 }
StmtAsgn :: { Stmt }
: LHS AsgnOp Expr ";" { AsgnBlk $2 $1 $3 }
| LHS IncOrDecOperator ";" { AsgnBlk (AsgnOp $2) $1 (Number "1") }
| IncOrDecOperator LHS ";" { AsgnBlk (AsgnOp $1) $2 (Number "1") }
| LHS "<=" opt(DelayOrEventControl) Expr ";" { Asgn $3 $1 $4 }
: LHS "=" opt(DelayOrEvent) Expr ";" { Asgn AsgnOpEq $3 $1 $4 }
| LHS "<=" opt(DelayOrEvent) Expr ";" { Asgn AsgnOpNonBlocking $3 $1 $4 }
| LHS AsgnBinOp Expr ";" { Asgn $2 Nothing $1 $3 }
| LHS IncOrDecOperator ";" { Asgn (AsgnOp $2) Nothing $1 (Number "1") }
| IncOrDecOperator LHS ";" { Asgn (AsgnOp $1) Nothing $2 (Number "1") }
| LHS ";" { Subroutine (lhsToExpr $1) (Args [] []) }
| LHS CallArgs ";" { Subroutine (lhsToExpr $1) $2 }
StmtNonAsgn :: { Stmt }
......@@ -1007,9 +1011,9 @@ ClockingEvent :: { Sense }
: "@" "(" Senses ")" { $3 }
TimingControl :: { Timing }
: DelayOrEventControl { $1 }
: DelayOrEvent { $1 }
| CycleDelay { Cycle $1 }
DelayOrEventControl :: { Timing }
DelayOrEvent :: { Timing }
: DelayControl { Delay $1 }
| EventControl { Event $1 }
DelayControl :: { Expr }
......@@ -1237,7 +1241,9 @@ GenvarIteration :: { (Identifier, AsgnOp, Expr) }
AsgnOp :: { AsgnOp }
: "=" { AsgnOpEq }
| "+=" { AsgnOp Add }
| AsgnBinOp { $1 }
AsgnBinOp :: { AsgnOp }
: "+=" { AsgnOp Add }
| "-=" { AsgnOp Sub }
| "*=" { AsgnOp Mul }
| "/=" { AsgnOp Div }
......
......@@ -55,8 +55,7 @@ import Language.SystemVerilog.Parser.Tokens (Position(..))
data DeclToken
= DTComma Position
| DTAutoDim Position
| DTAsgn Position AsgnOp Expr
| DTAsgnNBlk Position (Maybe Timing) Expr
| DTAsgn Position AsgnOp (Maybe Timing) Expr
| DTRange Position (PartSelectMode, Range)
| DTIdent Position Identifier
| DTPSIdent Position Identifier Identifier
......@@ -73,9 +72,9 @@ data DeclToken
deriving (Show, Eq)
-- entrypoints besides `parseDTsAsDeclOrStmt` use this to disallow `DTAsgnNBlk`
-- and `DTAsgn` with a binary assignment operator because we don't expect to see
-- those assignment operators in declarations
-- entrypoints besides `parseDTsAsDeclOrStmt` use this to disallow `DTAsgn` with
-- a non-blocking operator, binary assignment operator, or a timing control
-- because we don't expect to see those assignment operators in declarations
forbidNonEqAsgn :: [DeclToken] -> a -> a
forbidNonEqAsgn tokens =
if any isNonEqAsgn tokens
......@@ -83,8 +82,8 @@ forbidNonEqAsgn tokens =
else id
where
isNonEqAsgn :: DeclToken -> Bool
isNonEqAsgn (DTAsgnNBlk _ _ _) = True
isNonEqAsgn (DTAsgn _ (AsgnOp _) _) = True
isNonEqAsgn (DTAsgn _ op mt _) =
op /= AsgnOpEq || mt /= Nothing
isNonEqAsgn _ = False
......@@ -211,8 +210,8 @@ parseDTsAsDecl tokens =
parseDTsAsDeclOrStmt :: [DeclToken] -> ([Decl], [Stmt])
parseDTsAsDeclOrStmt [DTIdent pos f] = ([], [traceStmt pos, Subroutine (Ident f) (Args [] [])])
parseDTsAsDeclOrStmt [DTPSIdent pos p f] = ([], [traceStmt pos, Subroutine (PSIdent p f) (Args [] [])])
parseDTsAsDeclOrStmt (DTAsgn pos (AsgnOp op) e : tok : toks) =
parseDTsAsDeclOrStmt $ (tok : toks) ++ [DTAsgn pos (AsgnOp op) e]
parseDTsAsDeclOrStmt (DTAsgn pos (AsgnOp op) mt e : tok : toks) =
parseDTsAsDeclOrStmt $ (tok : toks) ++ [DTAsgn pos (AsgnOp op) mt e]
parseDTsAsDeclOrStmt tokens =
if (isStmt (last tokens) || tripLookahead tokens) && maybeLhs /= Nothing
then ([], [traceStmt pos, stmt])
......@@ -220,14 +219,12 @@ parseDTsAsDeclOrStmt tokens =
where
pos = tokPos $ last tokens
stmt = case last tokens of
DTAsgn _ op e -> AsgnBlk op lhs e
DTAsgnNBlk _ mt e -> Asgn mt lhs e
DTAsgn _ op mt e -> Asgn op mt lhs e
DTInstance _ args -> Subroutine (lhsToExpr lhs) (instanceToArgs args)
_ -> error $ "invalid block item decl or stmt: " ++ (show tokens)
maybeLhs = takeLHS $ init tokens
Just lhs = maybeLhs
isStmt :: DeclToken -> Bool
isStmt (DTAsgnNBlk{}) = True
isStmt (DTAsgn{}) = True
isStmt (DTInstance{}) = True
isStmt _ = False
......@@ -272,20 +269,19 @@ parseDTsAsAsgns tokens =
lhs = case takeLHS lhsToks of
Nothing -> error $ "could not parse as LHS: " ++ show lhsToks
Just l -> l
DTAsgn _ AsgnOpEq expr : l1 = l0
DTAsgn _ AsgnOpEq Nothing expr : l1 = l0
asgn = (lhs, expr)
isDTAsgn :: DeclToken -> Bool
isDTAsgn (DTAsgn{}) = True
isDTAsgn (DTAsgn _ _ Nothing _) = True
isDTAsgn _ = False
isAsgnToken :: DeclToken -> Bool
isAsgnToken (DTBit _ _) = True
isAsgnToken (DTConcat _ _) = True
isAsgnToken (DTStream _ _ _ _) = True
isAsgnToken (DTDot _ _) = True
isAsgnToken (DTAsgnNBlk _ _ _) = True
isAsgnToken (DTAsgn _ (AsgnOp _) _) = True
isAsgnToken (DTBit{} ) = True
isAsgnToken (DTConcat{}) = True
isAsgnToken (DTStream{}) = True
isAsgnToken (DTDot{} ) = True
isAsgnToken (DTAsgn _ op _ _) = op /= AsgnOpEq
isAsgnToken _ = False
takeLHS :: [DeclToken] -> Maybe LHS
......@@ -415,8 +411,8 @@ takeRanges (token : tokens) =
DTBit _ s -> (asRange s : rs, rest )
DTAutoDim _ ->
case rest of
(DTAsgn _ AsgnOpEq (Pattern l) : _) -> autoDim l
(DTAsgn _ AsgnOpEq (Concat l) : _) -> autoDim l
(DTAsgn _ AsgnOpEq Nothing (Pattern l) : _) -> autoDim l
(DTAsgn _ AsgnOpEq Nothing (Concat l) : _) -> autoDim l
_ -> ([] , token : tokens)
_ -> ([] , token : tokens)
where
......@@ -430,13 +426,15 @@ takeRanges (token : tokens) =
lo = Number "0"
hi = Number $ show (n - 1)
-- Matching DTAsgnNBlk here allows tripLookahead to work both for standard
-- declarations and in `parseDTsAsDeclOrStmt`, where we're checking for an
-- assignment statement. The other entry points disallow `DTAsgnNBlk`, so this
-- doesn't liberalize the parser.
-- Matching `AsgnOpEq` and `AsgnOpNonBlocking` here allows tripLookahead to work
-- both for standard declarations and in `parseDTsAsDeclOrStmt`, where we're
-- checking for an assignment statement. The other entry points disallow
-- `AsgnOpNonBlocking`, so this doesn't liberalize the parser.
takeAsgn :: [DeclToken] -> (Maybe Expr, [DeclToken])
takeAsgn (DTAsgn _ AsgnOpEq e : rest) = (Just e , rest)
takeAsgn (DTAsgnNBlk _ _ e : rest) = (Just e , rest)
takeAsgn (DTAsgn _ op Nothing e : rest) =
if op == AsgnOpEq || op == AsgnOpNonBlocking
then (Just e , rest)
else (Nothing, rest)
takeAsgn rest = (Nothing, rest)
takeComma :: [DeclToken] -> (Bool, [DeclToken])
......@@ -460,8 +458,7 @@ isComma _ = False
tokPos :: DeclToken -> Position
tokPos (DTComma p) = p
tokPos (DTAutoDim p) = p
tokPos (DTAsgn p _ _) = p
tokPos (DTAsgnNBlk p _ _) = p
tokPos (DTAsgn p _ _ _) = p
tokPos (DTRange p _) = p
tokPos (DTIdent p _) = p
tokPos (DTPSIdent p _ _) = p
......
module top;
logic [4] a, b;
always b = #5 a;
initial begin
a = #1 1;
$monitor("%2d %b %b", $time, a, b);
#1; a = 0;
#1; a = 'he;
#1;
#10; a = 'h5;
#10;
$finish;
end
endmodule
module top;
reg [0:3] a, b;
always b = #5 a;
initial begin
a = #1 1;
$monitor("%2d %b %b", $time, a, b);
#1; a = 0;
#1; a = 'he;
#1;
#10; a = 'h5;
#10;
$finish;
end
endmodule
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