Spellcheck
authorlekernel <sebastien.bourdeauducq@lekernel.net>
Sat, 15 May 2010 20:57:38 +0000 (22:57 +0200)
committerlekernel <sebastien.bourdeauducq@lekernel.net>
Sat, 15 May 2010 20:57:38 +0000 (22:57 +0200)
doc/thesis.tex

index 1cb064f..be37f68 100644 (file)
@@ -1,5 +1,4 @@
 % http://www.idt.mdh.se/phd/thesis/kthesis-1.0/
-% TODO: spellcheck
 \documentclass[a4paper,11pt]{kthesis}
 \usepackage[T1]{fontenc}
 \usepackage[normalem]{ulem}
@@ -44,9 +43,9 @@ First, I would like to express my gratitude to Professor Mats Brorsson, my super
 
 I would also like to thank Lattice Semiconductor for opening the source code of their LatticeMico32 processor core.
 
-Special thanks go to all the people who are indirectly involved with this Master's thesis project: Henry de Beauchesne (Xilinx) for getting me started with high-end FPGA tools, Shawn Tan (Aeste Works (M) Sdn Bhd) for his help with understanding the WISHBONE bus, Gregory Taylor (NASA's Jet Propulsion Laboratory) for letting me know that they were using parts of my code in the development of a communications system to be put onboard the international space station, Takeshi Matsuya (Keio University) for his work on the port of Linux to the system-on-chip described herein, Michael Walle for developing support of the system-on-chip in the QEMU emulator and Wolfgang Spraul (Sharism at Work Ltd.) for proposing me an agreement for manufacturing devices using the system-on-chip design.
+Special thanks go to all the people who are indirectly involved with this Master's thesis project: Henry de Beauchesne (Xilinx) for getting me started with high-end FPGA tools, Shawn Tan (Aeste Works (M) Sdn Bhd) for his help with understanding the WISHBONE bus, Gregory Taylor (NASA's Jet Propulsion Laboratory) for letting me know that they were using parts of my code in the development of a communications system to be put on board the international space station, Takeshi Matsuya (Keio University) for his work on the port of Linux to the system-on-chip described herein, Michael Walle for developing support of the system-on-chip in the QEMU emulator and Wolfgang Spraul (Sharism at Work Ltd.) for proposing me an agreement for manufacturing devices using the system-on-chip design.
 
-Thanks to the Eid\^olon music band (Reims, France), for whom I wrote my first PC-based video synthesis program in 2005, which has been a source of inspiration for this project.
+Thanks to the Eid\^olon music band (Rheims, France), for whom I wrote my first PC-based video synthesis program in 2005, which has been a source of inspiration for this project.
 
 Finally, I would like to thank all the researchers who have retained their copyright on their papers (or have put them in the public domain) and distribute them online for everybody to download freely (incidentally in accordance with the principle of free exchange of information from the KTH ethics policy). This in spite of the default agreement of many publishers such as the IEEE, which asks authors to assign their copyrights to the publishers so the latter have the exclusive permission to sell the download of documents that they did not write, without giving back to the authors, at a price supposedly meant to cover publishing expenses but which is not justified by today's low costs of network bandwidth and servers.
 
@@ -93,7 +92,7 @@ Meeting the performance constraints while still using cheap and relatively small
 \chapter{Background}
 \section{Video synthesis}
 \subsection{Overview}
-MilkDrop~\cite{milkdrop} (figure~\ref{fig:milkdrop}) is a popular open source video synthesis framework that was originally made to develop visualization plugins for the Winamp audio player. People have since then ported MilkDrop to many different platforms~\cite{wpmilkdrop} and made it react to live events, such as captured audio and video~\cite{visikord} (figure~\ref{fig:visikord}) or movements of a Wiimote remote control~\cite{wiimodemd}.
+MilkDrop~\cite{milkdrop} (figure~\ref{fig:milkdrop}) is a popular open source video synthesis framework that was originally made to develop visualization plug-ins for the Winamp audio player. People have since then ported MilkDrop to many different platforms~\cite{wpmilkdrop} and made it react to live events, such as captured audio and video~\cite{visikord} (figure~\ref{fig:visikord}) or movements of a Wiimote remote control~\cite{wiimodemd}.
 
 The idea behind the Milkymist project is to implement an embedded video synthesis platform on a custom open source system-on-chip, that is based on the same rendering principle of MilkDrop but with more control interfaces and features. The device built around the system-on-chip should be stand-alone, which means that a graphical user interface for configuring the visual effects should be implemented (figure~\ref{fig:flickernoise}).
 
@@ -149,7 +148,7 @@ This process is done on an internal frame buffer whose horizontal and vertical d
 \end{itemize}
 It must be noted that this two-step process increases the computation time and the consumption of memory bandwidth.
 
-All the steps of the rendering are heavily parametrizable by the user, using a coded format called a \textit{patch} or \textit{preset} which defines the aspect and the interaction forms of a particular visual effect. The listing of a sample patch is given by figure~\ref{fig:samplepatch} and the meaning of the language is explained below.
+All the steps of the rendering are heavily parameterizable by the user, using a coded format called a \textit{patch} or \textit{preset} which defines the aspect and the interaction forms of a particular visual effect. The listing of a sample patch is given by figure~\ref{fig:samplepatch} and the meaning of the language is explained below.
 
 \begin{figure}
 \centering
@@ -218,7 +217,7 @@ Indeed, as explained further in section~\ref{sec:tm}, the distortion works by us
 
 Per-vertex equations are thus evaluated at each vertex (whose position can be retrieved through the \verb!x! and \verb!y! variables), and alter the position of that vertex. In the example patch (figure~\ref{fig:samplepatch}), the image is locally scaled horizontally and vertically by factors depending on the position of the vertex and on the time, resulting in a twisted visual effect.
 
-As discussed in chapter~\ref{ch:tmu}, the floating point computations for each vertex are intensive and required the use of a dedicated coprocessor.
+As discussed in chapter~\ref{ch:tmu}, the floating point computations for each vertex are intensive and required the use of a dedicated co-processor.
 
 \section{Open source SoC platforms}
 There is an existing effort to build open source system-on-chips. It is interesting to review these projects in order to look forward to building upon them --- possibly adding hardware accelerators or performing other modifications in order to improve performance.
@@ -241,7 +240,7 @@ Implemented on a FPGA, this processor is extremely resource-intensive. A cut-dow
 As it turns out, the OpenSPARC architecture is a very complex design which implements a huge number of techniques which increase the software execution speed (instructions per clock cycle). While this is a wise choice for a software-centric processor implemented on a fully custom semiconductor chip, with a FPGA process it is more appealing to keep the software processor simple in order to save resources and make room for custom hardware accelerators, taking advantage of the FPGA flexibility.
 
 \subsubsection{GRLIB}
-GRLIB~\cite{grlib} is a very professional and standard-compliant library of SoC cores. The library features a comprehensive set of cores: AMBA AHB/APB bus control elements, the LEON3 SPARC processor, a 32-bit PC133 SDRAM controller, a 32-bit PCI bridge with DMA, a 10/100/1000 Mbit Ethernet MAC,  16/32/64-bit DDR SDRAM/DDR2 SDRAM controllers and more.
+GRLIB~\cite{grlib} is a very professional and standard-compliant library of SoC cores. The library features a comprehensive set of cores: AMBA AHB/APB bus control elements, the LEON3 SPARC processor, a 32-bit PC133 SDRAM controller, a 32-bit PCI bridge with DMA, a 10/100/1000 Mb/s Ethernet MAC, 16/32/64-bit DDR SDRAM/DDR2 SDRAM controllers and more.
 
 However, its drawbacks are:
 \begin{itemize}
@@ -256,7 +255,7 @@ Because of these reasons, GRLIB was not retained.
 \subsubsection{ORPSoC (OpenRISC)}
 ORPSoC is based on the OpenRISC~\cite{openrisc} processor core, which is the flagship product of OpenCores, a community of developers of open source system-on-chips. ORPSoC is essentially maintained by ORSoC AB.
 
-ORPSoC notably features the OpenRISC OR1200 processor core, the Wishbone~\cite{wishbone} bus, comprehensive debugging facilities, a 16550-compatible RS232 UART, a 10/100Mbps Ethernet MAC and a SDRAM controller.
+ORPSoC notably features the OpenRISC OR1200 processor core, the Wishbone~\cite{wishbone} bus, comprehensive debugging facilities, a 16550-compatible RS232 UART, a 10/100 Mb/s Ethernet MAC and a SDRAM controller.
 
 Unfortunately, ORPSoC is resource-inefficient and buggy. The OpenRISC implementation is not well optimized for synthesis. We carried out tests on the August 17, 2009 OpenRISC release. Still using the XC4VLX25 FPGA as target, synthesis with Xst and Xilinx ISE 11.4 yields an utilization of 5077 LUTs for the CPU core only (using the default FPGA configuration: no caches, no MMU, multiplier, and with the implementation of the RAMs using the RAMB16 elements of the FPGA selected), running at approximately 100MHz. A similar resource usage is reported in~\cite{softcorecomp}. The synthesis report shows asynchronous control signals where there should not be (such as on the output of the program counter), which can be an indication of poor quality of the design. Other IP cores comprising ORPSoC have similar issues (we tested the 16550 UART and the Ethernet MAC). Finally, the provided SDRAM controller only supports the low-bandwidth 16-bit single data rate option, has a high latency due to the extensive use of clock domain transfer FIFOs, does not support pipelined transfers and has a poorly written code.
 
@@ -278,7 +277,7 @@ This microprocessor core has been retained for use in Milkymist, as described in
 \subsubsection{Microblaze and Nios II}
 Even though we are not interested in proprietary designs, we still give a brief overview of the resource usage of Microblaze and Nios II systems as a comparison.
 
-\paragraph{Microblaze.} In~\cite{softcorecomp}, the Microblaze core is reported to use approximately 2400 LUTs, like LatticeMico32. The platform builder GUI in Xilinx ISE 12.1 also limits the frequency of Microblaze systems to 100MHz when targetting the Virtex-4 family. Thus, Microblaze is close to LatticeMico32 regarding area and frequency.
+\paragraph{Microblaze.} In~\cite{softcorecomp}, the Microblaze core is reported to use approximately 2400 LUTs, like LatticeMico32. The platform builder GUI in Xilinx ISE 12.1 also limits the frequency of Microblaze systems to 100MHz when targeting the Virtex-4 family. Thus, Microblaze is close to LatticeMico32 regarding area and frequency.
 
 \paragraph{Nios II.} According to an Altera report~\cite{niosbench}, Nios II/f uses 1600 Cyclone II LEs. A LE is mainly comprised of a 4-LUT and a register, which is comparable to the Virtex-4 architecture on which LatticeMico32 was tested. Thus, it seems that the Nios II core would be approximately two thirds of the area of LatticeMico32.
 
@@ -394,7 +393,7 @@ According to this background, we can derive the following project guidelines:
 \begin{itemize}
 \item develop a fast, resource-efficient and FPGA-optimized system-on-chip
 \item develop an efficient memory subsystem
-\item reuse a light-weight softcore CPU
+\item reuse a light-weight soft-core CPU
 \item partition carefully the tasks between hardware and software
 \item develop custom hardware accelerators
 \end{itemize}
@@ -448,15 +447,15 @@ High-end processors for servers and workstations have a good ability to cope wit
 Some SDRAM controllers do a lot to optimize bandwidth but have little focus on latency. Bandwidth-optimizing techniques include:
 \begin{itemize}
 \item reordering memory transactions to maximize the page mode hit rate.
-\item grouping reads and writes together to reduce write recovery times. Along with the above technique, this has a detrimental impact on latency because of the delays incurred by the additional logic in the address datapath.
+\item grouping reads and writes together to reduce write recovery times. Along with the above technique, this has a detrimental impact on latency because of the delays incurred by the additional logic in the address data path.
 \item running the system and the SDRAM in asynchronous clock domains in order to be able to run the SDRAM at its maximum allowable clock frequency. This requires the use of synchronizers or FIFOs, which have a high latency.
-\item configuring the SDRAM at high CAS latencies in order to increase its maximum allowable clock frequency. This trend is best illustrated by the advent of DDR2 and DDR3 memories whose key innovation is to run their internal DRAM core at a submultiple of the I/O frequency with a wide data bus which is then serialized on the I/O pins. Since the internal DRAM core has a latency comparable to that of the earlier SDR and DDR technologies, the number of CAS latency cycles relative to the I/O clock is also multiplied.
+\item configuring the SDRAM at high CAS latencies in order to increase its maximum allowable clock frequency. This trend is best illustrated by the advent of DDR2 and DDR3 memories whose key innovation is to run their internal DRAM core at a sub-multiple of the I/O frequency with a wide data bus which is then serialized on the I/O pins. Since the internal DRAM core has a latency comparable to that of the earlier SDR and DDR technologies, the number of CAS latency cycles relative to the I/O clock is also multiplied.
 \end{itemize}
 
 An extreme example of these memory controller bandwidth optimizations is the MemMax\textregistered ~DRAM scheduler~\cite{memmax}. This unit sits on top of an already existing memory controller (which already has its own latency), adding seven stages of complex and high-latency pipelining that produces a good - but compute-intensive - DRAM schedule. The actual efficiency of this system has been questioned~\cite{dramqos} because of that significant increase in latency.
 
 \section{Another approach}
-The out-of-order execution and hardware multithreading processor optimizations discussed above that cope with high memory latency are complex and impractical in the context of small and cheap embedded systems, especially those targetted at FPGA implementations. For example, FPGA implementations of the OpenSPARC~\cite{opensparc} processor, which employs such optimizations, typically require an expensive high-end Xilinx XUPV5 board whose Virtex-5 FPGA alone costs roughly 13000 SEK.
+The out-of-order execution and hardware multi-threading processor optimizations discussed above that cope with high memory latency are complex and impractical in the context of small and cheap embedded systems, especially those targeted at FPGA implementations. For example, FPGA implementations of the OpenSPARC~\cite{opensparc} processor, which employs such optimizations, typically require an expensive high-end Xilinx XUPV5 board whose Virtex-5 FPGA alone costs roughly 13000 SEK.
 
 Milkymist therefore uses simple in-order execution schemes in its CPU and in its accelerators, and strives to improve performance by focusing on reducing the memory latency.
 
@@ -520,7 +519,7 @@ The memory bus of Milkymist~\cite{fml} is pipelined. During the transfer of the
 \hline
 \end{tabular}
 
-Together with burst access, this helps acheiving high performance: the memory controller can hide DRAM latencies and row switch delays by issuing the requests to the DRAM in advance, while the previous transaction is still transferring data.
+Together with burst access, this helps achieving high performance: the memory controller can hide DRAM latencies and row switch delays by issuing the requests to the DRAM in advance, while the previous transaction is still transferring data.
 
 \section{Practical implementation}
 \label{sec:memimpl}
@@ -532,27 +531,27 @@ The Milkymist SoC uses 32-bit DDR SDRAM, configured to its maximum burst length
 \hline
 \textbf{Task} & \textbf{Required bandwidth} \\
 \hline
-VGA frame buffer, 1024x768, 75Hz, 16bpp & 950Mbps \\
+VGA frame buffer, 1024x768, 75Hz, 16bpp & 950Mb/s \\
 \hline
-Distortion: texture mapping, 512x512 to 512x512, 30fps, 16bpp & 250Mbps \\
+Distortion: texture mapping, 512x512 to 512x512, 30fps, 16bpp & 250Mb/s \\
 \hline
-Live video: texture mapping, 720x576 to 512x512 with transparency, 30fps, 16bpp & 300Mbps \\
+Live video: texture mapping, 720x576 to 512x512 with transparency, 30fps, 16bpp & 300Mb/s \\
 \hline
-Scaling: texture mapping, 512x512 to 1024x768, 30fps, 16bpp & 500Mbps \\
+Scaling: texture mapping, 512x512 to 1024x768, 30fps, 16bpp & 500Mb/s \\
 \hline
-Video echo: texture mapping, 512x512 to 1024x768 with transparency, 30fps, 16bpp & 900Mbps \\
+Video echo: texture mapping, 512x512 to 1024x768 with transparency, 30fps, 16bpp & 900Mb/s \\
 \hline
-NTSC input, 720x576, 30fps, 16bpp & 200Mbps \\
+NTSC input, 720x576, 30fps, 16bpp & 200Mb/s \\
 \hline
-Software and misc. & 200Mbps \\
+Software and misc. & 200Mb/s \\
 \hline
-\textbf{Total} & \textbf{3.3Gbps} \\
+\textbf{Total} & \textbf{3.3Gb/s} \\
 \hline
 \end{tabularx}
 \caption{Estimate of the memory bandwidth consumption.}\label{tab:membw}
 \end{table}
 
-The memory is run at 100MHz, yielding a peak theoretical bandwidth of 6.4Gbps, which is more than enough for the intended video synthesis application (table~\ref{tab:membw}). This bandwidth is however never attained: events such as switching DRAM rows which takes significant time and, to a lesser extent, DRAM refreshes introduce dead times on the data bus. We will see in section~\ref{sec:memperf} that such an oversizing of the off-chip memory is needed if we want to keep the memory system simple.
+The memory is run at 100MHz, yielding a peak theoretical bandwidth of 6.4Gb/s, which is more than enough for the intended video synthesis application (table~\ref{tab:membw}). This bandwidth is however never attained: events such as switching DRAM rows which takes significant time and, to a lesser extent, DRAM refreshes introduce dead times on the data bus. We will see in section~\ref{sec:memperf} that such an oversizing of the off-chip memory is needed if we want to keep the memory system simple.
 
 \begin{figure}[H]
 \centering
@@ -572,11 +571,11 @@ Finally, the bus interface is a piece of glue logic that connects the SoC pipeli
 
 HPDMC has been implemented in Verilog HDL, tested and debugged in RTL simulation using a DDR SDRAM Verilog model from Micron, integrated into the SoC, synthesized into FPGA technology, and eventually calibrated and tested by software routines running on the actual hardware.
 
-This design of memory controller, specifically crafted for the Milkymist project and released under the GNU GPL license on the internet, has been picked up by the NASA for a software defined radio project and may be put up onboard the international space station in 2011. Gregory Taylor, Electronics Engineer at the NASA Jet Propulsion Laboratory, wrote:
+This design of memory controller, specifically crafted for the Milkymist project and released under the GNU GPL license on the internet, has been picked up by the NASA for a software defined radio project and may be put up on board the international space station in 2011. Gregory Taylor, Electronics Engineer at the NASA Jet Propulsion Laboratory, wrote:
 
-\textit{While searching for a suitable SDRAM controller for the Jet Propulsion Laboratory's Software-Defined Radio onboard NASA's CoNNeCT experiment, I found S\'ebastien's HPDMC SDRAM controller on OpenCores.org. We needed a controller that was both high performance and well documented. Though the original HPDMC controller was designed for DDR SDRAM with a 32-bit bus, S\'ebastien clearly explained the modifications necessary to adapt the controller to our Single Data Rate, 40-bit wide SDRAM chip. I found the code to be well documented and easy to follow. The performance has met our requirements and the FPGA size requirement is small.}
+\textit{While searching for a suitable SDRAM controller for the Jet Propulsion Laboratory's Software-Defined Radio on board NASA's CoNNeCT experiment, I found S\'ebastien's HPDMC SDRAM controller on OpenCores.org. We needed a controller that was both high performance and well documented. Though the original HPDMC controller was designed for DDR SDRAM with a 32-bit bus, S\'ebastien clearly explained the modifications necessary to adapt the controller to our Single Data Rate, 40-bit wide SDRAM chip. I found the code to be well documented and easy to follow. The performance has met our requirements and the FPGA size requirement is small.}
 
-\textit{The Communication Navigation and Networking Reconfigurable Testbed (CoNNeCT) experiment to be installed onboard the ISS is designed for the next generation of SDRs conforming to the Space Telecommunications Radio Systems (STRS) open architecture standard. The HPDMC controller will likely find its way into one or more loadable waveform payloads in the JPL SDR, and perhaps be used in other NASA projects as well. It may eventually find its way into deep space.}
+\textit{The Communication Navigation and Networking Reconfigurable Testbed (CoNNeCT) experiment to be installed on board the ISS is designed for the next generation of SDRs conforming to the Space Telecommunications Radio Systems (STRS) open architecture standard. The HPDMC controller will likely find its way into one or more loadable waveform payloads in the JPL SDR, and perhaps be used in other NASA projects as well. It may eventually find its way into deep space.}
 
 \section{Performance measurement}
 \label{sec:memperf}
@@ -595,7 +594,7 @@ That logic core exploits properties of the FastMemoryLink signaling in order to
 \item the \textbf{bus occupancy} which is the percentage of time during which the link was busy and therefore unavailable for a new request.
 \end{itemize}
 
-Every FastMemoryLink transaction begins with the assertion of the strobe signal. Then, after one or more wait cycles, the memory controller asserts the acknowledgement signal together with the first word of data being transferred. The next cycle, the strobe signal is deasserted (unless a new transaction begins) while the next word in the burst is being transferred. A new transaction can start with the assertion of the strobe signal even if a burst is already going on (pipelining). See figure~\ref{fig:fmltransactions} for an example.
+Every FastMemoryLink transaction begins with the assertion of the strobe signal. Then, after one or more wait cycles, the memory controller asserts the acknowledgement signal together with the first word of data being transferred. The next cycle, the strobe signal is de-asserted (unless a new transaction begins) while the next word in the burst is being transferred. A new transaction can start with the assertion of the strobe signal even if a burst is already going on (pipelining). See figure~\ref{fig:fmltransactions} for an example.
 
 \begin{figure}
 \centering
@@ -629,7 +628,7 @@ In the equations that follow, these symbols are used:
 \caption{Maximum utilization of a FML bus.} \label{fig:fmlmax}
 \end{figure}
 
-The average memory access time can be used to derive an upper bound on the maximum bandwidth that the memory system can handle. Indeed, FML is a pipelined bus which supports only one outstanding (waiting) transaction, so the case that uses the most bandwidth for a given memory access time is when the strobe signal is always asserted (figure~\ref{fig:fmlmax}) so that a new transaction begins as soon as the first word of the previous trasaction is transferred.
+The average memory access time can be used to derive an upper bound on the maximum bandwidth that the memory system can handle. Indeed, FML is a pipelined bus which supports only one outstanding (waiting) transaction, so the case that uses the most bandwidth for a given memory access time is when the strobe signal is always asserted (figure~\ref{fig:fmlmax}) so that a new transaction begins as soon as the first word of the previous transaction is transferred.
 
 Therefore, only a fraction $\alpha$ of the peak bandwidth $f \cdot w$ can be used at most, and we have:
 \begin{equation}
@@ -670,14 +669,14 @@ Illusion \& Rovastar - Snowflake Delight & 1399 & 39 \% & 6.28 & 55 \% & 3516 \\
 Rovastar \& Idiot24-7 - Balk Acid & 1427 & 41 \% & 6.38 & 54 \% & 3469 \\
 \hline
 \end{tabular}
-\caption{Memory performance in different conditions (Milkymist 0.5.1). Bandwidths are in Mbps.}\label{tab:memperformance}
+\caption{Memory performance in different conditions (Milkymist 0.5.1). Bandwidths are in Mb/s.}\label{tab:memperformance}
 \end{table}
 
 It is difficult to compare these results to those of other memory controllers as they are usually not published (or not measured at all).
 
 However, two conclusions can be drawn:
 \begin{itemize}
-\item there are enough occupancy and bandwidth margins for the system to operate at higher resolutions and/or color depths than 640x480 and 16 bits per pixel. The 3.3 Gbps bandwidth requirement that was estimated in section~\ref{sec:memimpl} seems attainable, although challenging.
+\item there are enough occupancy and bandwidth margins for the system to operate at higher resolutions and/or color depths than 640x480 and 16 bits per pixel. The 3.3 Gb/s bandwidth requirement that was estimated in section~\ref{sec:memimpl} seems attainable, although challenging.
 \item to go further, an ``out-of-order'' memory controller can be envisioned. Such a controller would have a split transaction bus (allowing a larger number of outstanding transactions, thus minimizing the impact that latency has on bandwidth) and would be able to reorder pending memory transactions to maximize the page hit rate.
 \end{itemize}
 
@@ -694,7 +693,7 @@ Wishbone is a synchronous sequential bus with support for variable latency (wait
 
 Wishbone is used around the SoC's LatticeMico32 CPU core and for simple DMA masters which have modest requirements of bandwidth and of volume of transferred data. As explained in Section~\ref{sec:fmlbrg}, connecting DMA masters that transfer small amounts of data (which can fit in the L2 cache) to the same bus as the CPU simplifies dealing with cache coherency issues.
 
-The data width used for the Wishbone bus is 32, yielding a peak bandwidth of 3.2Gbps when the system is running at 100MHz.
+The data width used for the Wishbone bus is 32, yielding a peak bandwidth of 3.2Gb/s when the system is running at 100MHz.
 
 \section{Configuration and Status Registers: the CSR bus}
 Milkymist uses memory-mapped I/O through configuration and status registers.
@@ -720,7 +719,7 @@ SDRAM latency varies a lot depending on the state of the SDRAM at the time the r
 \subsection{Burst only}
 SDRAM is best accessed in burst mode (see subsection~\ref{subsec:fmlburst}).
 
-However, enabling or configuring burst mode is a relatively lengthy and complex operation, requiring a reload of the SDRAM mode register which takes several cycles. Furthermode, supporting multiple burst lengths makes the scheduling of the transfers more complex to avoid ``overlapping'' transfers that would create conflicts at the data pins.
+However, enabling or configuring burst mode is a relatively lengthy and complex operation, requiring a reload of the SDRAM mode register which takes several cycles. Furthermore, supporting multiple burst lengths makes the scheduling of the transfers more complex to avoid ``overlapping'' transfers that would create conflicts at the data pins.
 
 Therefore, in order to greatly simplify the memory controller, all transfers on FML are made using a fixed and pre-defined burst length.
 
@@ -733,13 +732,13 @@ The benefits of this feature have already been discussed in subsection~\ref{subs
 Pipelined requests may come from the same core that issued the initial transfer, or from another core. The FML arbiter would then pipeline the request coming from the other core.
 
 \subsection{Usage}
-The data width used for the FML bus is 64, yielding a peak bandwidth of 6.4Gbps when the system is running at 100MHz. This is twice the peak bandwidth of the Wishbone bus. Furthermore, this bus provides a short path to the memory controller, reducing latency and therefore potentially further increasing effective bandwidth, as discussed in Section~\ref{sec:memorywall}.
+The data width used for the FML bus is 64, yielding a peak bandwidth of 6.4Gb/s when the system is running at 100MHz. This is twice the peak bandwidth of the Wishbone bus. Furthermore, this bus provides a short path to the memory controller, reducing latency and therefore potentially further increasing effective bandwidth, as discussed in Section~\ref{sec:memorywall}.
 
 Peripherals directly connected to FML are typically those which transfer large amounts of data (that would exceed the capacity of the L2 cache presented in section~\ref{sec:fmlbrg}) and which have high bandwidth requirements (and therefore can take advantage of the bandwidth and latency improvement compared to Wishbone).
 
 In the Milkymist SoC, they are comprised of:
 \begin{itemize}
-\item the VGA output controller, which needs to continously scan a frame buffer up to several megabytes in size to generate the video signal.
+\item the VGA output controller, which needs to continuously scan a frame buffer up to several megabytes in size to generate the video signal.
 \item the (planned) video input, which writes, every second, dozens of digitized video frames weighting hundreds of kilobytes each.
 \item the texture mapping unit (chapter~\ref{ch:tmu}), which needs to deal with large textures at high speed.
 \end{itemize}
@@ -758,10 +757,10 @@ A traditional write-back cache with a line length equal to the FML burst length
 The LatticeMico32 CPU (section~\ref{sec:mico32}) uses a write-through cache without hardware coherency. Thus, the following operations must be done by the software to ensure cache coherency:
 \begin{itemize}
 \item Before reading DMA data from a peripheral using shared memory, the L1 cache should be cleared as it may hold an outdated copy of the data.
-\item When writing DMA data to a peripheral using shared memory on the Wishbone bus, no precaution should be taken. The CPU writes go directly to the bus, and end up in the L2 cache or the SDRAM where the peripheral will correctly retreive them.
+\item When writing DMA data to a peripheral using shared memory on the Wishbone bus, no precaution should be taken. The CPU writes go directly to the bus, and end up in the L2 cache or the SDRAM where the peripheral will correctly retrieve them.
 \end{itemize}
 
-It is noteworthy that the CSR address space is non-cacheable, therefore no cache-related precaution should be taken when reading or writing CSRs.
+It is noteworthy that the CSR address space is non-cache-able, therefore no cache-related precaution should be taken when reading or writing CSRs.
 
 \subsection{Coherency issues around the Wishbone-FML (L2) cache}
 The Wishbone-FML bridge provides very limited support for cache coherency. Cache coherency issues arise because of the masters directly connected to the FML bus:
@@ -862,8 +861,8 @@ The instructions that affect $e$ between two consecutive values of $x$ are $e \l
 
 After the first instruction:
 \begin{itemize}
-\item if $e$ was negative or zero, we have $-\frac{Dx}{2} \leq e < Dx < \frac{3 \cdot Dx}{2} $ (because $0 \leq R < Dx$ and the recursion hypothese).
-\item if $e$ was positive, it was inferior or equal to $\frac{Dx}{2}$ (because of the recursion hypothese), therefore we have $0 < e < \frac{3 \cdot Dx}{2} $.
+\item if $e$ was negative or zero, we have $-\frac{Dx}{2} \leq e < Dx < \frac{3 \cdot Dx}{2} $ (because $0 \leq R < Dx$ and the recursion hypothesis).
+\item if $e$ was positive, it was inferior or equal to $\frac{Dx}{2}$ (because of the recursion hypothesis), therefore we have $0 < e < \frac{3 \cdot Dx}{2} $.
 \end{itemize}
 After the second instruction, if we had $e > \frac{Dx}{2}$, we'll have $e < \frac{3 \cdot Dx}{2} - Dx$. Therefore, $e \leq \frac{Dx}{2}$. $\Box$
 
@@ -1005,11 +1004,11 @@ Vertical interpolation & 503808 & 5 ms \\
 \hline
 Horizontal interpolation & 8060928 & 81 ms \\
 \hline
-Framebuffer reads & 2097152 & 21 ms \\
+Frame buffer reads & 2097152 & 21 ms \\
 \hline
 Bilinear filtering & 19660800 & 197 ms \\
 \hline
-Framebuffer writes & 524288 & 5 ms \\
+Frame buffer writes & 524288 & 5 ms \\
 \hline
 \textbf{Total} & 30846976 & 308 ms \\
 \hline
@@ -1028,7 +1027,7 @@ It is expected that the memory latency for reading the frame buffer would be a p
 
 With a direct-mapped texel cache having a hit rate of 90\%, a hit time of 1 cycle and a miss penalty of 9 cycles, the average memory access times is 1.8 cycles. With a 100MHz system clock, such a cache has a throughput of 55 megapixels per second, well above the optimistic estimate made in subsection~\ref{subsec:perfcontext}.\footnote{This is a quick estimate assuming a normal cache that does not support bilinear filtering. To implement bilinear filtering, the situation is more complex as the cache needs to look up 4 pixels at once. This is discussed in subsection~\ref{subsec:texelcache}.}
 
-To make sure that the memory access time is the only limiting factor, it was chosen that the rest of the system should be designed to support a throughput of approximately one output pixel per clock cycle. This heuristic was influenced by the fact that it corresponds to a spatial implementation of the algorithm (i.e. with little or no time-based resource sharing of the hardware components) but does not require resource-intensive duplication of large hardware units either. A spatial implementation requires more area than a time-shared one, but it is simpler to understand, and needs fewer multiplexers and is less prone to routing congestions, making it easier to achieve timing closure in FPGAs.
+To make sure that the memory access time is the only limiting factor, it was chosen that the rest of the system should be designed to support a throughput of approximately one output pixel per clock cycle. This heuristic was influenced by the fact that it corresponds to a spatial implementation of the algorithm (i.e. with little or no time-based resource sharing of the hardware components) but does not require resource-intensive duplication of large hardware units either. A spatial implementation requires more area than a time-shared one, but it is simpler to understand, and needs fewer multiplexers and is less prone to routing congestion, making it easier to achieve timing closure in FPGAs.
 
 A deeply pipelined implementation of the texture mapping algorithm was thus chosen, whose block diagram is depicted in figure~\ref{fig:tmublock}. Many of the stages have internal pipeline sub-stages, and they are detailed below.
 
@@ -1042,7 +1041,7 @@ A deeply pipelined implementation of the texture mapping algorithm was thus chos
 \subsection{Vertex fetch engine}
 There is not much to say about this stage, which is a straightforward finite state machine-based Wishbone bus master that fetches the texture coordinates of each vertex from the system memory, and sends them down the pipeline to the vertical interpolator.
 
-The vertex fetch engine is connected to the lower-bandwidth Wishbone bus because this saves resources compared to FML (which has a wider datapath) and makes it easier to handle cache coherency issues (section~\ref{sec:coherency}).
+The vertex fetch engine is connected to the lower-bandwidth Wishbone bus because this saves resources compared to FML (which has a wider data path) and makes it easier to handle cache coherency issues (section~\ref{sec:coherency}).
 
 \subsection{Interpolators}
 The horizontal and vertical interpolators are both implemented in the same way. They are vector interpolators, which contain two scalar interpolators (figure~\ref{fig:vectinter}, one for each texture coordinate). Each scalar interpolator contains additional internal pipeline sub-stages, as described in figure~\ref{fig:pipeinter}.
@@ -1064,9 +1063,9 @@ The vertical interpolator contains two vector interpolators, one for each vertic
 \end{figure}
 
 \subsubsection{Stages of the scalar interpolator}
-\paragraph{Stage A: Dx and Dy computation.} This stage computes the two differences $y_{1} - y_{0}$ and $x_{1} - x_{0}$. It is based on simple registered arithemetic combinatorial functions, which compute the two differences in one clock cycle.
+\paragraph{Stage A: Dx and Dy computation.} This stage computes the two differences $y_{1} - y_{0}$ and $x_{1} - x_{0}$. It is based on simple registered arithmetic combinatorial functions, which compute the two differences in one clock cycle.
 
-\paragraph{Stage B: Q and R computation.} The next operation is to perform the Euclidian division of Dy by Dx. The hardware does so by using the restoring division method~\cite{restdiv}, which takes as many cycles as there are quotient digits (our implementation has 18).
+\paragraph{Stage B: Q and R computation.} The next operation is to perform the Euclidean division of Dy by Dx. The hardware does so by using the restoring division method~\cite{restdiv}, which takes as many cycles as there are quotient digits (our implementation has 18).
 
 In order to keep the resource usage low, the divider is not pipelined. After operands are sent to it, it stalls transmissions from the upstream stage for several cycles until the division is complete.
 
@@ -1332,7 +1331,7 @@ We must now determine an optimal size for the texel cache. The size must represe
 
 To study the impact of the cache size on the hit rate, we simulated the complete Verilog code of texture mapping unit with different cache sizes. The CSR interface of the texture mapping unit (subsection~\ref{subsec:tmucsr}) supports eight registers that measure, for each channel, the number of requests\footnote{As outlined above, channels are only active (i.e. issue a cache request) when needed (i.e. when the interpolated texture coordinates are not integer). Channel 1 is always active and therefore makes as many accesses as there are pixels in the output picture. Its accesses are however still counted as a means to check that the texture mapping unit is operating correctly.} and how many of those requests hit the cache. Those registers are still present after logic synthesis, and can be used to validate the performance of the texel cache in the real system.\footnote{The reason why we performed the tests using Verilog simulations instead of the real FPGA-based system is because logic synthesis --- needed for each tested cache size --- takes a long time, and some cache configurations may cause resource shortages, timing problems or even Xst synthesizer bugs that would need to be manually addressed.}
 
-The source and destination images have a resolution of 512x512 pixels, and are tesselated with 16x16 rectangles forming a 32x32 mesh --- which matches the configuration used for distortions by the renderer program. Different sets of texture coordinates were used at each vertex, according to table~\ref{tab:tcsets}. Texture coordinates are multiplied by 64 to perform the conversion of integers into the fixed point format used throughout the linear interpolation process (see subsection~\ref{subsec:bilfpformat}). $x$ and $y$ refer to the indices of the vertex in the mesh. Texture wrapping was enabled, as it puts more load on the cache than texture clamping.
+The source and destination images have a resolution of 512x512 pixels, and are tessellated with 16x16 rectangles forming a 32x32 mesh --- which matches the configuration used for distortions by the renderer program. Different sets of texture coordinates were used at each vertex, according to table~\ref{tab:tcsets}. Texture coordinates are multiplied by 64 to perform the conversion of integers into the fixed point format used throughout the linear interpolation process (see subsection~\ref{subsec:bilfpformat}). $x$ and $y$ refer to the indices of the vertex in the mesh. Texture wrapping was enabled, as it puts more load on the cache than texture clamping.
 
 The sets were chosen for the following reasons:
 \begin{itemize}
@@ -1450,19 +1449,19 @@ Results are reported in table~\ref{tab:tcresults} and figure~\ref{fig:tcresultsg
 \hline
 \textbf{Cache size} & \textbf{copy} & \textbf{zoomin} & \textbf{zoomout} & \textbf{rotozoom} \\
 \hline
-2KB & 93.75 \% & 98.08 \% & 83.33 \% & 73.06 \% \\
+2kB & 93.75 \% & 98.08 \% & 83.33 \% & 73.06 \% \\
 \hline
-4KB & 93.75 \% & 98.08 \% & 83.33 \% & 82.94 \% \\
+4kB & 93.75 \% & 98.08 \% & 83.33 \% & 82.94 \% \\
 \hline
-8KB & 93.75 \% & 98.62 \% & 83.33 \% & 93.73 \% \\
+8kB & 93.75 \% & 98.62 \% & 83.33 \% & 93.73 \% \\
 \hline
-16KB & 93.75 \% & 99.27 \% & 86.94 \% & 95.74 \% \\
+16kB & 93.75 \% & 99.27 \% & 86.94 \% & 95.74 \% \\
 \hline
-32KB & 93.75 \% & 99.27 \% & 91.44 \% & 96.02 \% \\
+32kB & 93.75 \% & 99.27 \% & 91.44 \% & 96.02 \% \\
 \hline
-64KB & 93.75 \% & 99.27 \% & 94.14 \% & 96.02 \% \\
+64kB & 93.75 \% & 99.27 \% & 94.14 \% & 96.02 \% \\
 \hline
-128KB & 93.75 \% & 99.27 \% & 94.14 \% & 96.15 \% \\
+128kB & 93.75 \% & 99.27 \% & 94.14 \% & 96.15 \% \\
 \hline
 \end{tabular}
 \caption{Hit rates for each set of texture coordinates and different cache sizes.}\label{tab:tcresults}
@@ -1479,11 +1478,11 @@ Before we go on choosing a texel cache size, a few comments on these results can
 
 First, for the ``copy'' set, the hit rate remains at a constant 93.75 \%. This is expected and supports the validity of the results. Indeed, the texture mapping unit is copying rectangles whose horizontal size is the length in pixels of a cache line (4 words of 64-bit each yields 16 pixels of 16 bits each). In our tests, the texture frame buffer was aligned to the beginning of a cache line and 512 (the horizontal texture size) is a multiple of the cache line length in pixels, therefore each horizontal line in a rectangle corresponds to a cache line. Each texture pixel is read exactly once (channels 2, 3 and 4 are idle as the interpolated texture coordinates are always integer). What happens is that, for each horizontal line in each rectangle, the first texel is read and misses the cache. Then, the next 15 texels in the line are immediately read and hit the cache. This indeed yields a cache hit rate of $\frac{15}{16} = 0.9375$.
 
-A result more surprising at first sight is that for the ``zoomout'' set, which is supposed to be the worst case, the cache hit rate is low --- as expected --- and increases, until it slightly exceeds the hit rate for the ``copy'' set for cache sizes of 64KB and above.
+A result more surprising at first sight is that for the ``zoomout'' set, which is supposed to be the worst case, the cache hit rate is low --- as expected --- and increases, until it slightly exceeds the hit rate for the ``copy'' set for cache sizes of 64kB and above.
 
-This has to do with the fact that the texture mapping unit draws the rectangles in the same order as frame buffers are scanned (from left to right and top to bottom). When the cache reaches 64KB, it is able to memorize a full band of texels that is more than 48 pixels high ($512\cdot48\cdot2 = 49152 < 65536$) which contains more than all the texels needed to draw a full line of rectangles (16 pixels high) in the output picture. Since the output picture repeats the texture, the repetition generates cache hits that are not present with the ``copy'' set.
+This has to do with the fact that the texture mapping unit draws the rectangles in the same order as frame buffers are scanned (from left to right and top to bottom). When the cache reaches 64kB, it is able to memorize a full band of texels that is more than 48 pixels high ($512\cdot48\cdot2 = 49152 < 65536$) which contains more than all the texels needed to draw a full line of rectangles (16 pixels high) in the output picture. Since the output picture repeats the texture, the repetition generates cache hits that are not present with the ``copy'' set.
 
-As for choosing a texel cache size, we went for a 32KB cache. There is no significant performance improvement with using a larger cache except for the ``zoomout'' set for which there is a slight increase in the hit rate between 32KB and 64KB. Since the ``zoomout'' set is a worst-case scenario seldom found in practice (MilkDrop usually zooms out by factors much less than the one we used, resulting in fewer cache misses), we felt it was not worth doubling the cache size to improve its performance.
+As for choosing a texel cache size, we went for a 32kB cache. There is no significant performance improvement with using a larger cache except for the ``zoomout'' set for which there is a slight increase in the hit rate between 32kB and 64kB. Since the ``zoomout'' set is a worst-case scenario seldom found in practice (MilkDrop usually zooms out by factors much less than the one we used, resulting in fewer cache misses), we felt it was not worth doubling the cache size to improve its performance.
 
 We also need to check that this cache size cannot cause inter-channel cache conflicts (ICCCs). The cache line size is 32 bytes, thus, the cache line length in 16bpp pixels is $N_{l} = 16$ and the cache holds $\frac{N_{c}}{N_{l}}=1024$ lines. The texture mapping unit is operated with 512x512 textures and texture wrapping is enabled.
 
@@ -1494,11 +1493,11 @@ Fortunately, there is a cheaper solution. What we actually need to verify is thi
 \left\lfloor \frac{a_{A}}{N_{l}} \right\rfloor \not \equiv \left\lfloor \frac{a_{A}+H \cdot V-1}{N_{l}} \right\rfloor \pmod{\frac{N_{c}}{N_{l}}}
 \end{equation}
 
-We \textit{add} the hypothese that the frame buffer address is a multiple of the cache line length, which we can easily achieve by imposing alignment requirements to the software toolchain. Without loss of generality, we suppose that $a_{A}$ is the address of channel 4, which is equal to the address of the frame buffer in the case creating the problem (figure~\ref{fig:chdisphvwrap}). $\frac{a_{A}}{N_{l}}$ is therefore integer, and the only condition that implies the absence of conflict between channels 1 and 4 becomes:
+We \textit{add} the hypothesis that the frame buffer address is a multiple of the cache line length, which we can easily achieve by imposing alignment requirements to the software tool chain. Without loss of generality, we suppose that $a_{A}$ is the address of channel 4, which is equal to the address of the frame buffer in the case creating the problem (figure~\ref{fig:chdisphvwrap}). $\frac{a_{A}}{N_{l}}$ is therefore integer, and the only condition that implies the absence of conflict between channels 1 and 4 becomes:
 \begin{equation}
 \left\lfloor \frac{H \cdot V-1}{N_{l}} \right\rfloor \not \equiv 0 \pmod{\frac{N_{c}}{N_{l}}}
 \end{equation}
-This condition is verified. So, ICCCs will always be avoided with a 32KB texel cache if we make sure that the 512x512 texture is aligned to a 32-byte boundary.
+This condition is verified. So, ICCCs will always be avoided with a 32kB texel cache if we make sure that the 512x512 texture is aligned to a 32-byte boundary.
 
 \subsection{Bilinear filter}
 The bilinear filter is a straightforward arithmetic circuit that implements the equation~\ref{eq:bfilter} with five pipeline sub-stages.
@@ -1554,11 +1553,11 @@ Beyond this basic principle of operation, the texture mapping unit supports seve
 \end{itemize}
 
 \section{Implementation results}
-We were unable to implement the planned 32KB texel cache in the XC4VLX25 FPGA of our ML401 development board, because the complete SoC with such a cache exceeds the on-chip SRAM capacity of the FPGA. Therefore, for these experiments, we had to use a 16KB cache instead. This issue should be resolved easily in the future, as our final board (chapter~\ref{ch:conclusion}) will have an FPGA with much more on-chip memory.
+We were unable to implement the planned 32kB texel cache in the XC4VLX25 FPGA of our ML401 development board, because the complete SoC with such a cache exceeds the on-chip SRAM capacity of the FPGA. Therefore, for these experiments, we had to use a 16kB cache instead. This issue should be resolved easily in the future, as our final board (chapter~\ref{ch:conclusion}) will have an FPGA with much more on-chip memory.
 
 We wanted to validate the performance of our texture mapping unit (TMU) design, measured in megapixels per second at the output (also called \textit{fill rate}). Since it is a memory-bound process (subsection~\ref{subsec:tmustrategy}), it is relevant to examine its performance for different values of the texel cache hit rate.
 
-To do so, we varied the texel cache hit rate by making the TMU zoom a picture at different levels. We proceeded with a texture size of 512x512 and an output picture of 640x480. The vertex mesh had a resolution of 32x32, and, to implement the different zoom levels, the vertex coordinates were $(z \cdot x, z \cdot y)$ with $z$ varying between 0 and 2047. Each measurement was done twice to reduce the risk of errors and transients (CPU interrupts, DRAM refreshes, etc.), yielding 4096 points which are plotted in figure~\ref{fig:tmuresult}. The measurements were done programmatically by a software routine running on the system-on-chip itself. The video output was enabled during the process (and showing the result of the texture mapping), running in the standard VGA mode of 640x480 at 60Hz and putting a background load of approximately 300 Mbit/s on the memory system for scanning the frame buffer.
+To do so, we varied the texel cache hit rate by making the TMU zoom a picture at different levels. We proceeded with a texture size of 512x512 and an output picture of 640x480. The vertex mesh had a resolution of 32x32, and, to implement the different zoom levels, the vertex coordinates were $(z \cdot x, z \cdot y)$ with $z$ varying between 0 and 2047. Each measurement was done twice to reduce the risk of errors and transients (CPU interrupts, DRAM refreshes, etc.), yielding 4096 points which are plotted in figure~\ref{fig:tmuresult}. The measurements were done programmatically by a software routine running on the system-on-chip itself. The video output was enabled during the process (and showing the result of the texture mapping), running in the standard VGA mode of 640x480 at 60Hz and putting a background load of approximately 300 Mb/s on the memory system for scanning the frame buffer.
 
 \begin{figure}[htp]
 \centering
@@ -1572,13 +1571,13 @@ The plot underlines the importance of the memory subsystem in a performance-driv
 However, our design still appears suitable for the application of rendering MilkDrop-like patches with all the options enabled (i.e. in the worst case) at VGA resolution (640x480). Indeed, this would involve:
 \begin{enumerate}
 \item Distortion of a 512x512 texture to a 512x512 texture. This is represented by the ``rotozoom'' set of vertex coordinates (table~\ref{tab:tcsets}) whose resulting cache hit rate is 95.74 \% (table~\ref{tab:tcresults}). The fill rate is therefore approximately 30 megapixels per second (figure~\ref{fig:tmuresult}). The time taken by this process is thus $\frac{512 \cdot 512}{30 \cdot 10^{6}}=8.7\unit{ms}$.
-\item Inclusion of a live video frame into the texture.\footnote{We are --- very optimistically --- neglecting the time it takes to read the output picture when alpha blending is enabled.} We assume the input video frame to be 720x288 (we are using \textit{bob deinterlacing}, i.e. line doubling of the interlaced video frames) and the target rectangle in the texture to be 360x288. This is represented by the ``zoomout'' set with a cache hit rate of 86.94 \% yielding a fill rate of very approximately 15 megapixels per second. The time taken by this process is $\frac{360 \cdot 288}{15 \cdot 10^{6}}=6.9\unit{ms}$.
+\item Inclusion of a live video frame into the texture.\footnote{We are --- very optimistically --- neglecting the time it takes to read the output picture when alpha blending is enabled.} We assume the input video frame to be 720x288 (we are using \textit{bob de-interlacing}, i.e. line doubling of the interlaced video frames) and the target rectangle in the texture to be 360x288. This is represented by the ``zoomout'' set with a cache hit rate of 86.94 \% yielding a fill rate of very approximately 15 megapixels per second. The time taken by this process is $\frac{360 \cdot 288}{15 \cdot 10^{6}}=6.9\unit{ms}$.
 \item Zooming of the 512x512 texture to 640x480 resolution, done twice (once for the normal picture and once for video echo\footnote{Again neglecting the extra delay due to alpha blending.}). This is represented by the ``zoomin'' set of vertex coordinates. The texel hit rate is estimated at 99.27\%, and the fill rate at 55 megapixels per second. The time taken is estimated to be $2 \cdot \frac{640 \cdot 480}{55 \cdot 10^{6}}=11.2\unit{ms}$.
 \end{enumerate}
 
 The total time is $26.8\unit{ms}$, which corresponds to 37 frames per second. This is more than enough to achieve a smooth video animation.
 
-\chapter{Floating point coprocessor}
+\chapter{Floating point co-processor}
 \label{ch:pfpu}
 \section{Purpose}
 \label{sec:pfpupurpose}
@@ -1588,7 +1587,7 @@ We would like to be able to generate a mesh of up to 64x64 vertices at 30 frames
 
 This rules out any software-based implementation. Even assuming a favorable case where patches are compiled (not interpreted) and the LatticeMico32 ISA (section~\ref{sec:mico32}) equipped with a traditional floating point unit, each basic floating point operation would take approximately 5 cycles at least.\footnote{FPGAs are unlikely to compute the totality of a floating point operation in less than 50ns, which is 5 cycles at 100MHz. Since LatticeMico32 uses a fixed-length in-order pipeline, the CPU would need to be stalled during those cycles.} Even at 100\% CPU utilization, a software implementation would be 3 times too slow!
 
-We have therefore designed and implemented a coprocessor for those computations, called PFPU (Programmable Floating Point Unit).
+We have therefore designed and implemented a co-processor for those computations, called PFPU (Programmable Floating Point Unit).
 
 \section{Forms of parallelism}
 We need a parallel implementation to solve the problem of performance. Two approaches can be thought of: \textit{vertex-level parallelism} and \textit{instruction-level parallelism}.
@@ -1610,12 +1609,12 @@ A fully software-based extraction of instruction-level parallelism was chosen fo
 \item A software-based instruction scheduler can have a large instruction window, and thus extract more parallelism than an hardware solution could.
 \end{itemize}
 
-This static scheduling technique makes the floating point coprocessor close to a VLIW (Very Long Instruction Word) processor --- even though its instruction words are, in fact, not particularly long, as the design is very simple (only one operation is issued per instruction, and jumps are not supported). The architecture we designed is outlined in figure~\ref{fig:pfpuarch}.
+This static scheduling technique makes the floating point co-processor close to a VLIW (Very Long Instruction Word) processor --- even though its instruction words are, in fact, not particularly long, as the design is very simple (only one operation is issued per instruction, and jumps are not supported). The architecture we designed is outlined in figure~\ref{fig:pfpuarch}.
 
 \begin{figure}[htp]
 \centering
 \includegraphics[height=100mm]{pfpu_architecture.eps}
-\caption{Hardware architecture of the floating point coprocessor.}
+\caption{Hardware architecture of the floating point co-processor.}
 \label{fig:pfpuarch}
 \end{figure}
 
@@ -1646,7 +1645,7 @@ A special instruction is used to write the final result to the memory. It writes
 The instruction RAM belongs on-chip for two simple reasons:
 \begin{itemize}
 \item it is small: it must only contain hundreds of instructions (the program for one vertex), so its capacity is only a few kilobytes.
-\item it transfers a large amount of data: one 25-bit instruction on each clock cycle at 100MHz yields a bandwidth of 2.5Gbps.
+\item it transfers a large amount of data: one 25-bit instruction on each clock cycle at 100MHz yields a bandwidth of 2.5Gb/s.
 \end{itemize}
 There are no jumps or loop structures (for each vertex, the program is always executed linearly), so it does not make sense to replace it with a DRAM-backed cache.
 
@@ -1743,7 +1742,7 @@ If an instruction is found, the FPVM registers of its operands are translated to
 
 It can be noted that the handling of WAW and WAR hazards is zealous, as some hazards detected by the algorithm may actually not be present because of the pipeline delays. Since those hazards are infrequent, this approach does not have a large impact on the performance but simplifies the algorithm.
 
-Several instructions can sometimes meet the conditions to be schedulable at the same cycle. In this case, the algorithm chooses the first one to appear in the FPVM instruction flow. This \textit{greedy} approach can certainly be optimized, though no effort has been made in this direction.
+Several instructions can sometimes meet the conditions to be potentially scheduled at the same cycle. In this case, the algorithm chooses the first one to appear in the FPVM instruction flow. This \textit{greedy} approach can certainly be optimized, though no effort has been made in this direction.
 
 \subsection{Constants and user variables}
 \label{subsec:constparam}
@@ -1840,7 +1839,7 @@ Division & 15 \\
 \label{ch:sw}
 \section{LatticeMico32}
 \label{sec:mico32}
-The heart of the software execution capabilities of the SoC is the LatticeMico32 microprocessor core~\cite{mico32}. It is a classic 6-stage in-order pipelined RISC processor (figure~\ref{fig:lm32arch}) with a custom instruction set supported by the GNU (GCC-based) compiler toolchain. It supports separate instruction and data caches with up to two ways. There are an optional barrel shifter, pipelined multiplier and multi-cycle divider.
+The heart of the software execution capabilities of the SoC is the LatticeMico32 microprocessor core~\cite{mico32}. It is a classic 6-stage in-order pipelined RISC processor (figure~\ref{fig:lm32arch}) with a custom instruction set supported by the GNU (GCC-based) compiler tool chain. It supports separate instruction and data caches with up to two ways. There are an optional barrel shifter, pipelined multiplier and multi-cycle divider.
 
 \begin{figure}[htp]
 \centering
@@ -1849,7 +1848,7 @@ The heart of the software execution capabilities of the SoC is the LatticeMico32
 \label{fig:lm32arch}
 \end{figure}
 
-The Milkymist system-on-chip uses LatticeMico32 with 2-way caches of 16KB each, and all the optional features enabled.
+The Milkymist system-on-chip uses LatticeMico32 with 2-way caches of 16kB each, and all the optional features enabled.
 
 At the time this thesis is written, LatticeMico32 is the only hardware component that we have not developed specifically for the Milkymist project.
 
@@ -1864,7 +1863,7 @@ The ``nommu'' version of Linux has been ported to the Milkymist SoC (figure~\ref
 \end{figure}
 
 \section{Benchmarking}
-The performance of the Milkymist SoC was compared to Microblaze~\cite{microblaze}, the proprietary Xilinx softcore SoC platform.
+The performance of the Milkymist SoC was compared to Microblaze~\cite{microblaze}, the proprietary Xilinx soft-core SoC platform.
 
 The benchmark used was the ``consumer'' MiBench~\cite{mibench} suite. By contrast to traditional benchmarks such as SPEC, MiBench is tailored to typical workloads of embedded systems. Only two benchmarks are missing from the ``consumer'' set: \verb!tiff2rgba! (it tried to use too much contiguous memory for the nommu Milkymist/Linux allocator to handle) and \verb!lame! (it crashed on Microblaze).
 
@@ -1880,9 +1879,9 @@ All tests were run on a Xilinx ML401 (XC4VLX25 FPGA, see figure~\ref{fig:ml401})
 For Milkymist, the configuration used was the default one of the port to the ML401 board:
 \begin{itemize}
 \item Processor with hardware multiplier, divider and barrel shifter
-\item 16KB L1 instruction and data (write-through) cache (2-way set-associative)
+\item 16kB L1 instruction and data (write-through) cache (2-way set-associative)
 \item No memory management unit (LatticeMico32 does not have one)
-\item 16KB FML bridge write-back L2 cache (direct mapped)
+\item 16kB FML bridge write-back L2 cache (direct mapped)
 \item HPDMC DDR SDRAM controller, 32-bit SDRAM bus width
 \item 100MHz DDR SDRAM clock
 \item Video output running at standard VGA resolution, consuming approximately 300MBps of memory bandwidth
@@ -1892,7 +1891,7 @@ For Milkymist, the configuration used was the default one of the port to the ML4
 For Microblaze, the configuration is as follows:
 \begin{itemize}
 \item Processor with hardware multiplier, divider and barrel shifter
-\item 16KB L1 instruction and data (write-through) cache (direct mapped, multi-way caches are not supported)
+\item 16kB L1 instruction and data (write-through) cache (direct mapped, multi-way caches are not supported)
 \item Full memory management unit
 \item No L2 cache (not supported)
 \item MPMC DDR SDRAM controller, 32-bit SDRAM bus width
@@ -1999,7 +1998,7 @@ The system-on-chip provides limited support for cache coherency (section~\ref{se
 \subsubsection{Cache coherency within the analysis loop}
 The only precaution that should be taken is to invalidate the L1 cache after each received buffer from the AC97 audio controller.
 
-There is no need to invalidate the any cache after evaluation of the per-frame equations, as the outputs are read directly from the PFPU register file which is mapped in the non-cacheable CSR address space.
+There is no need to invalidate the any cache after evaluation of the per-frame equations, as the outputs are read directly from the PFPU register file which is mapped in the non-cache-able CSR address space.
 
 The output the per-vertex equations is sent directly to the rendering loop.
 
@@ -2023,7 +2022,7 @@ To solve these issues with a minimal number of cache invalidations, we make sure
 Our implementation is \textit{event-driven}. Instead of being fully sequential, the software waits for and acts upon events (for example, the texture mapping unit finishing processing, or a new audio buffer being ready). After an event is received, the CPU can either process the data itself (for example, run the FIR filters after a new audio buffer is ready) or run another hardware unit (for example, run the TMU after the PFPU has evaluated the per-vertex equations). This approach improves performance by letting the three main processing units of the system (the CPU, the PFPU and the TMU) operate in parallel.
 
 \subsection{Results}
-Our system is able to render successfully many original MilkDrop presets at 30 frames per seconds in 640x480 resolution. However, it is often operating near its limit, and sometimes above it, as some presets exhibit a lower frame rate. This is often due to the fact that drawing the waves and the borders take a long time on the CPU, especially when many semi-transparent pixels need to be drawn. This precludes the possibility of supporting presets that employ complex custom waves and shapes (that would be drawn by the CPU), unless further acceleration techniques are devloped.
+Our system is able to render successfully many original MilkDrop presets at 30 frames per seconds in 640x480 resolution. However, it is often operating near its limit, and sometimes above it, as some presets exhibit a lower frame rate. This is often due to the fact that drawing the waves and the borders take a long time on the CPU, especially when many semi-transparent pixels need to be drawn. This precludes the possibility of supporting presets that employ complex custom waves and shapes (that would be drawn by the CPU), unless further acceleration techniques are developed.
 
 \chapter{Conclusion and future works}
 \label{ch:conclusion}
@@ -2053,7 +2052,7 @@ We hope that this open hardware platform will be successful --- used not only fo
 \begin{figure}[htp]
 \centering
 \includegraphics[width=\textwidth]{mm1.eps}
-\caption{Printed circuit board floorplan of the Milkymist One.}
+\caption{Printed circuit board floor plan of the Milkymist One.}
 \label{fig:mm1}
 \end{figure}