From 50d6faa9b07f1a67cc699b4dd24ec2e1565f8bfa Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 27 Jul 2020 18:50:26 -0600 Subject: [PATCH] yosys-compatible simple loop jump conversion --- src/Convert.hs | 2 +- src/Convert/Jump.hs | 46 +++++++++++++++++++++++++++++++++------------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/Convert.hs b/src/Convert.hs index 6493d7f..e8f8b3c 100644 --- a/src/Convert.hs +++ b/src/Convert.hs @@ -86,10 +86,10 @@ phases excludes = , Convert.Package.convert , Convert.Enum.convert , Convert.NestPI.convert + , Convert.ForDecl.convert , Convert.Jump.convert , Convert.Foreach.convert , selectExclude (Job.Interface, Convert.Interface.convert) - , Convert.ForDecl.convert , selectExclude (Job.Always , Convert.AlwaysKW.convert) , selectExclude (Job.Succinct , Convert.RemoveComments.convert) ] diff --git a/src/Convert/Jump.hs b/src/Convert/Jump.hs index beb4998..5812238 100644 --- a/src/Convert/Jump.hs +++ b/src/Convert/Jump.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE PatternSynonyms #-} {- sv2v - Author: Zachary Snow - @@ -116,6 +117,16 @@ convertStmts stmts = do return stmts' +pattern SimpleLoopInits :: Type -> Identifier -> Expr + -> Either [Decl] [(LHS, Expr)] +pattern SimpleLoopInits typ var expr = Left [Variable Local typ var [] expr] + +pattern SimpleLoopGuard :: BinOp -> Identifier -> Expr -> Expr +pattern SimpleLoopGuard cmp var bound = BinOp cmp (Ident var) bound + +pattern SimpleLoopIncrs :: Identifier -> AsgnOp -> Expr -> [(LHS, AsgnOp, Expr)] +pattern SimpleLoopIncrs var op step = [(LHSIdent var, op, step)] + -- rewrites the given statement, and returns the type of any unfinished jump convertStmt :: Stmt -> State Info Stmt @@ -166,13 +177,22 @@ convertStmt (Case unique kw expr cases) = do modify $ \s -> s { sHasJump = hasJump } return $ Case unique kw expr cases' +convertStmt (For + (inits @ (SimpleLoopInits _ var1 _)) + (comp @ (SimpleLoopGuard _ var2 _)) + (incr @ (SimpleLoopIncrs var3 _ _)) + stmt) = + if var1 /= var2 || var2 /= var3 + then convertLoop False loop comp stmt + else convertLoop True loop comp stmt + where loop c s = For inits c incr s convertStmt (For inits comp incr stmt) = - convertLoop loop comp stmt + convertLoop False loop comp stmt where loop c s = For inits c incr s convertStmt (While comp stmt) = - convertLoop While comp stmt + convertLoop False While comp stmt convertStmt (DoWhile comp stmt) = - convertLoop DoWhile comp stmt + convertLoop False DoWhile comp stmt convertStmt (Continue) = do loopDepth <- gets sLoopDepth @@ -236,8 +256,8 @@ convertSubStmt stmt = do put origState return (stmt', hasJump) -convertLoop :: (Expr -> Stmt -> Stmt) -> Expr -> Stmt -> State Info Stmt -convertLoop loop comp stmt = do +convertLoop :: Bool -> (Expr -> Stmt -> Stmt) -> Expr -> Stmt -> State Info Stmt +convertLoop local loop comp stmt = do -- save the loop state and increment loop depth Info { sLoopDepth = origLoopDepth, sHasJump = origHasJump } <- get assertMsg (not origHasJump) "has jump invariant failed" @@ -249,11 +269,13 @@ convertLoop loop comp stmt = do assertMsg (origLoopDepth + 1 == afterLoopDepth) "loop depth invariant failed" modify $ \s -> s { sLoopDepth = origLoopDepth } - let comp' = BinOp LogAnd comp $ BinOp Lt (Ident jumpState) jsBreak - let body = Block Seq "" [] - [ asgn jumpState jsNone - , stmt' - ] + let keepRunning = BinOp Lt (Ident jumpState) jsBreak + let comp' = if local then comp else BinOp LogAnd comp keepRunning + let body = Block Seq "" [] $ + [ asgn jumpState jsNone + , stmt' + ] + let body' = if local then If NoCheck keepRunning body Null else body let jsStackIdent = jumpState ++ "_" ++ show origLoopDepth let jsStackDecl = Variable Local jumpStateType jsStackIdent [] (Ident jumpState) @@ -271,13 +293,13 @@ convertLoop loop comp stmt = do loop comp stmt' else if origLoopDepth == 0 then Block Seq "" [] - [ loop comp' body + [ loop comp' body' , jsCheckReturn ] else Block Seq "" [ jsStackDecl ] - [ loop comp' body + [ loop comp' body' , jsStackRestore ]