package Loop(for, forN, forBreak, forever) where import Vector import ActionSeq --@ \subsection{Loop} --@ --@ \index{Loop@\te{Loop} (package)} --@ The \te{Loop} package contains some functions to simplify the --@ construction of loops. All the constructs here take an --@ \te{ActionList} as the loop body. These action are then executed --@ in sequence a number of times, where the number depends on the --@ looping construct. --@ --@ \index{for@\te{for} (\te{Loop} function)} --@ The \te{for} function constructs a for loop where a register --@ will take on the specified values in sequence. --@ It is invoked as follows \qbs{for $var$ $low$ $high$ $body$}, --@ where $var$ is a register, $low$ is the lower bound, $high$ is --@ the upper bound, and $body$ is the action sequence that forms --@ the loop body. --@ \begin{verbatim} --@ module for#(Reg#(a) i, a lo, a hi, ActionList#(n) stmts)(ActionSeq) --@ provisos (Arith#(a), Ord#(a), Bits#(a, sa), --@ Add#(1, m, n), Add#(n, 1, n1), Log#(n1, l)); --@ \end{verbatim} for :: (IsModule mod cons, Arith a, Ord a, Bits a sa, Add 1 m n, Add n 1 n1, Log n1 l) => Reg a -> a -> a -> ActionList n -> mod ActionSeq for i lo hi stmts = liftModule $ module run :: Reg Bool <- mkReg False body :: ActionSeq <- actionSeq $ append (init stmts) (action { last stmts; run := i < hi; i := i + 1 } :> nil) interface start = if lo <= hi then action { run := True; i := lo; body.start } else action { } when not run done = not run checkDone = noAction when not run rules "for": when run ==> body.start --@ \index{forN@\te{forN} (\te{Loop} function)} --@ The function \te{forN} is like \te{for}, except that the loop --@ counts down from $high$ to zero (inclusive). --@ It is invoked as follows \qbs{forN $var$ $high$ $body$}. --@ \begin{verbatim} --@ module forN#(Reg#(a) i, a hi, ActionList#(n) stmts)(ActionSeq) --@ provisos (Arith#(a), Ord#(a), Bits#(a, sa), --@ Add#(1, m, n), Add#(n, 1, n1), Log#(n1, l)); --@ \end{verbatim} forN :: (IsModule mod cons, Arith a, Ord a, Bits a sa, Add 1 m n, Add n 1 n1, Log n1 l) => Reg a -> a -> ActionList n -> mod ActionSeq; forN i hi stmts = liftModule $ module run :: Reg Bool <- mkReg False body :: ActionSeq <- actionSeq $ append (init stmts) (action { last stmts; run := i > 0; i := i - 1 } :> nil) interface start = if hi >= 0 then action { run := True; i := hi; body.start } else action { } when not run done = not run checkDone = noAction when not run rules "for": when run ==> body.start --@ \index{forBreak@\te{forBreak} (\te{Loop} function)} --@ The function \te{forBreak} is like \te{for}, except that the loop --@ can be terminated early (just as with a \te{break} in C). --@ It is invoked as follows \qbs{for $var$ $low$ $high$ (\BSL break -> $body$ )} --@ \begin{verbatim} --@ module forBreak#(Reg#(a) i, a lo, a hi, --@ function ActionList#(n) stmts (Action br))(ActionSeq) --@ provisos (Arith#(a), Ord#(a), Bits#(a, sa), --@ Add#(n, 1, n1), Add#(n1, 1, n2), Log#(n2, l)); --@ \end{verbatim} forBreak :: (IsModule mod cons, Arith a, Ord a, Bits a sa, Add n 1 n1, Add n1 1 n2, Log n2 l) => Reg a -> a -> a -> (Action -> ActionList n) -> mod ActionSeq forBreak i lo hi stmts = liftModule $ module run :: Reg Bool <- mkReg False go :: Reg Bool <- mkRegU body :: ActionSeq <- actionSeqBreak $ \ brk -> append (stmts (action { go := False; brk })) (action { run := i < hi; i := i + 1 } :> nil) let rdy = not run || not go interface start = action { go := True; run := True; i := lo; body.start } when rdy done = rdy checkDone = noAction when rdy rules "forBreak": when run && go ==> body.start --@ \index{forever@\te{forever} (\te{Loop} function)} --@ The \te{forever} function constructs a loop that terminates when --@ the ``break'' function is called. --@ It is invoked as follows \qbs{forever (\BSL break -> $body$ )} --@ \begin{verbatim} --@ module forever#(function ActionList#(n) stmts (Action br))(ActionSeq); --@ \end{verbatim} forever :: (IsModule mod cons) => (Action -> ActionList n) -> mod ActionSeq forever stmts = liftModule $ module run :: Reg Bool <- mkReg False body :: ActionSeq <- actionSeqBreak $ \ brk -> stmts (action { run := False; brk }) interface start = action { run := True; body.start } when not run done = not run checkDone = noAction when not run rules "forever": when run ==> body.start