Line 229... |
Line 229... |
\section{Interrupt handling}
|
\section{Interrupt handling}
|
\label{sec:interrupthandling}
|
\label{sec:interrupthandling}
|
|
|
\subsection{Control register}
|
\subsection{Control register}
|
|
|
\lxp{} supports 8 interrupts with hardwired priority levels (interrupts with lower vector numbers have higher priority). Interrupts vectors (pointers to interrupt handlers) are stored in the \code{iv0}--\code{iv7} registers. Interrupt handling is controlled by the \code{cr} register (Table \ref{tab:cr}).
|
\lxp{} supports 8 interrupts with hardwired priority levels (interrupts with lower vector numbers have higher priority). Interrupt vectors (pointers to interrupt handlers) are stored in the \code{iv0}--\code{iv7} registers. Interrupt handling is controlled by the \code{cr} register (Table \ref{tab:cr}).
|
|
|
\begin{table}[htbp]
|
\begin{table}[htbp]
|
\caption{Control register}
|
\caption{Control register}
|
\label{tab:cr}
|
\label{tab:cr}
|
\begin{tabularx}{\textwidth}{lL}
|
\begin{tabularx}{\textwidth}{lL}
|
\toprule
|
\toprule
|
Bit & Description \\
|
Bit & Description \\
|
\midrule
|
\midrule
|
0 & Enable interrupt 0 \\
|
0 & Enable interrupt 0 \\
|
1 & Enable interrupt 1 \\
|
|
& \ldots \\
|
& \ldots \\
|
7 & Enable interrupt 7 \\
|
7 & Enable interrupt 7 \\
|
8 & Temporarily block interrupt 0 \\
|
8 & Interrupt 0 wake-up flag \\
|
9 & Temporarily block interrupt 1 \\
|
|
& \ldots \\
|
& \ldots \\
|
15 & Temporarily block interrupt 7 \\
|
15 & Interrupt 7 wake-up flag \\
|
31--16 & \emph{Reserved} \\
|
31--16 & \emph{Reserved} \\
|
\bottomrule
|
\bottomrule
|
\end{tabularx}
|
\end{tabularx}
|
\end{table}
|
\end{table}
|
|
|
Disabled interrupts are ignored altogether: if the CPU receives an interrupt request signal while the corresponding interrupt is disabled, the interrupt handler will not be called even if the interrupt is enabled later. Conversely, temporarily blocked interrupts are still registered, but their handlers are not called until they are unblocked.
|
Disabled interrupts are ignored altogether: if the CPU receives an interrupt request signal while the corresponding interrupt is disabled, the interrupt will not be processed even if it is enabled later.
|
|
|
|
Wake-up flag marks the interrupt as a \emph{wake-up interrupt} (see below).
|
|
|
Like other registers, \code{cr} is zero-initialized during the CPU reset, meaning that no interrupts are initially enabled.
|
Like other registers, \code{cr} is zero-initialized during the CPU reset, meaning that no interrupts are initially enabled.
|
|
|
\subsection{Invoking interrupt handlers}
|
\subsection{Invoking interrupt handlers}
|
|
|
Interrupt handlers are invoked by the CPU similarly to procedures (Section \ref{sec:callingprocedures}), the difference being that in this case return address is stored in the \code{irp} register (as opposed to \code{rp}), and the least significant bit of the register (\code{IRF} -- \emph{Interrupt Return Flag}) is set.
|
Interrupt handlers are invoked by the CPU similarly to procedures (Section \ref{sec:callingprocedures}), the difference being that in this case return address is stored in the \code{irp} register (as opposed to \code{rp}), and the least significant bit of the register (\code{IRF} -- \emph{Interrupt Return Flag}) is set.
|
|
|
An interrupt handler returns using the \code{\instr{jmp} irp} instruction which also has an \instr{iret} alias. Until the interrupt handler returns, the CPU will defer further interrupt processing (although incoming interrupt requests will still be registered). This also means that the \code{irp} register value will not be unexpectedly overwritten. When executing the \code{\instr{jmp} irp} instruction, the CPU will recognize the \code{IRF} flag and resume interrupt processing as usual. It is also possible to perform a conditional return from the interrupt handler, similarly to the technique described in Section \ref{sec:callingprocedures} for conditional procedure returns.
|
An interrupt handler returns using the \code{\instr{jmp} irp} instruction which also has an \instr{iret} alias. Until the interrupt handler returns, the CPU will defer further interrupt processing (although incoming interrupt requests will still be registered). This also means that the \code{irp} register value will not be unexpectedly overwritten. When executing the \code{\instr{jmp} irp} instruction, the CPU will recognize the \code{IRF} flag and resume interrupt processing as usual. It is also possible to perform a conditional return from the interrupt handler, similarly to the technique described in Section \ref{sec:callingprocedures} for conditional procedure returns.
|
|
|
|
\subsection{Wake-up interrupts}
|
|
|
|
When a wake-up interrupt is received, the interrupt handler is not called, but the CPU still resumes execution if halted by the \instr{hlt} instruction. The effect is similar to invoking an interrupt with an empty handler (containing only \instr{iret}), but without the overhead of interrupt processing. Wake-up interrupts do not affect the CPU when it is not halted.
|
|
|
|
Unlike normal interrupts, wake-up interrupts are processed even when the CPU executes an interrupt handler for another interrupt.
|
|
|
\subsection{Non-returnable interrupts}
|
\subsection{Non-returnable interrupts}
|
|
|
If an interrupt vector has the least significant bit (\code{IRF}) set, the CPU will resume interrupt processing immediately. One should not try to invoke \instr{iret} from such a handler since the \code{irp} register could have been overwritten by another interrupt. This technique can be useful when the CPU's only task is to process external events:
|
If an interrupt vector has the least significant bit (\code{IRF}) set, the CPU will resume interrupt processing immediately. One should not try to invoke \instr{iret} from such a handler since the \code{irp} register could have been overwritten by another interrupt. This technique can be useful when the CPU's only task is to process external events:
|
|
|
\begin{codeparbreakable}
|
\begin{codeparbreakable}
|
Line 492... |
Line 498... |
\caption{Typical WISHBONE data bus WRITE and READ cycles}
|
\caption{Typical WISHBONE data bus WRITE and READ cycles}
|
\label{fig:dbustiming}
|
\label{fig:dbustiming}
|
\end{figure}
|
\end{figure}
|
|
|
\section{Interrupts}
|
\section{Interrupts}
|
|
\label{sec:interrupts}
|
|
|
\lxp{} registers an interrupt condition when the corresponding request signal goes from \code{0} to \code{1}. Transitions from \code{1} to \code{0} are ignored. All interrupt request signals must be synchronous with the system clock (\signal{clk\_i}); if coming from an asynchronous source, they must be synchronized using a sequence of at least two flip-flops clocked by \signal{clk\_i}. These flip-flops are not included in the \lxp{} core in order not to increase interrupt processing delay for interrupt sources that are inherently synchronous. Failure to properly synchronize interrupt request signals will cause timing violations that will manifest itself as intermittent, hard to debug faults.
|
\lxp{} registers an interrupt condition when the corresponding request signal goes from \code{0} to \code{1}. Transitions from \code{1} to \code{0} are ignored. All interrupt request signals must be synchronous with the system clock (\signal{clk\_i}); if coming from an asynchronous source, they must be synchronized using a sequence of at least two flip-flops clocked by \signal{clk\_i}. These flip-flops are not included in the \lxp{} core in order not to increase interrupt processing delay for interrupt sources that are inherently synchronous. Failure to properly synchronize interrupt request signals will cause timing violations that will manifest itself as intermittent, hard to debug faults.
|
|
|
\section{Synthesis and optimization}
|
\section{Synthesis and optimization}
|
\label{sec:synthesis}
|
\label{sec:synthesis}
|
Line 1103... |
Line 1110... |
The result is rounded towards zero and is undefined if RD2 is zero. If the CPU was configured without a divider, this instruction returns \code{0}.
|
The result is rounded towards zero and is undefined if RD2 is zero. If the CPU was configured without a divider, this instruction returns \code{0}.
|
|
|
\subsection{\instr{hlt} -- Halt}
|
\subsection{\instr{hlt} -- Halt}
|
\label{subsec:instr:hlt}
|
\label{subsec:instr:hlt}
|
|
|
Wait for an interrupt.
|
Halt the CPU until an enabled interrupt is received.
|
|
|
\subsubsection{Syntax}
|
\subsubsection{Syntax}
|
|
|
\code{\instr{hlt}}
|
\code{\instr{hlt}}
|
|
|
Line 1826... |
Line 1833... |
\bottomrule
|
\bottomrule
|
\end{ctabular}
|
\end{ctabular}
|
|
|
\chapter{List of changes}
|
\chapter{List of changes}
|
|
|
|
\section*{Version 1.3 (2022-08-28)}
|
|
|
|
This release removes support for temporarily blocked interrupts (interrupts can still be disabled) and introduces wake-up interrupts.
|
|
|
\section*{Version 1.2 (2021-10-21)}
|
\section*{Version 1.2 (2021-10-21)}
|
|
|
This release introduces a few non-breaking changes to the software and testbench. The CPU RTL description hasn't been changed from the previous release.
|
This release introduces a few non-breaking changes to the software and testbench. The CPU RTL description hasn't been changed from the previous release.
|
|
|
\begin{itemize}
|
\begin{itemize}
|