summaryrefslogtreecommitdiffstats
path: root/verilog.tex
diff options
context:
space:
mode:
authorYann Herklotz <git@yannherklotz.com>2020-06-27 18:18:59 +0100
committerYann Herklotz <git@yannherklotz.com>2020-06-27 18:18:59 +0100
commit95c158d74989e13bade4c58ceb99d84e89f22159 (patch)
tree7756304613e86338a8202cc1b72911da59225857 /verilog.tex
parent1910e71c7184cd93a9e2f2dfadb0082d1164da85 (diff)
downloadoopsla21_fvhls-95c158d74989e13bade4c58ceb99d84e89f22159.tar.gz
oopsla21_fvhls-95c158d74989e13bade4c58ceb99d84e89f22159.zip
More changes to the semantics
Diffstat (limited to 'verilog.tex')
-rw-r--r--verilog.tex14
1 files changed, 12 insertions, 2 deletions
diff --git a/verilog.tex b/verilog.tex
index 17ccca4..8c1d6fa 100644
--- a/verilog.tex
+++ b/verilog.tex
@@ -28,9 +28,19 @@ The main addition to the Verilog syntax is the explicit declaration of inputs an
Existing operational semantics~\cite{loow19_verif_compil_verif_proces} were adapted for the semantics of the language that CoqUp eventually targets. These semantics are small-step operational semantics at the clock cycle level, as hardware typically does not terminate in any way, however, within each clock cycle the semantics are constructed in a big-step style semantics. This style of semantics matches the small-step operational semantics of CompCert's register transfer language (RTL) quite well.
-At the top-level, always blocks describe logic which is run every time some event occurs. The only event that is supported by these semantics is detecting the positive edge of the clock, so that we can implement synchronous logic. As soon as an event occurs, the hardware will be executed, meaning if there are multiple always blocks that get triggered by the event, these will run in parallel. However, as the semantics should be deterministic, we impose an order on the always blocks and execute them sequentially. However, to preserve the fact that the statements inside of the always block are executed in parallel, nonblocking assignments to variables need to be kept in a different association map compared to blocking assignments to variables. This preserves the behaviour that blocking assignments change the value of the variable inside of the clock cycle, whereas the nonblocking assignments only take place at the end of the clock cycle, and in parallel. We can denote these two association maps as $s = (\Gamma, \Delta)$, where $\Gamma$ is the current value of the registers, and $\Delta$ is the value of that variable when the clock cycle ends.
+At the top-level, always blocks describe logic which is run every time some event occurs. The only event that is supported by these semantics is detecting the positive edge of the clock, so that we can implement synchronous logic. As soon as an event occurs, the hardware will be executed, meaning if there are multiple always blocks that get triggered by the event, these will run in parallel. However, as the semantics should be deterministic, we impose an order on the always blocks and execute them sequentially. However, to preserve the fact that the statements inside of the always block are executed in parallel, nonblocking assignments to variables need to be kept in a different association map compared to blocking assignments to variables. This preserves the behaviour that blocking assignments change the value of the variable inside of the clock cycle, whereas the nonblocking assignments only take place at the end of the clock cycle, and in parallel. We can denote these two association maps as $s = (\Gamma_{r}, \Gamma_{a}, \Delta_{r}, \Delta_{a})$, where $\Gamma_{r}$ is the current value of the registers, $\Gamma_{a}$ is the current value of the array, and $\Delta_{r}$ and $\Delta_{a}$ are the values of the variables and arrays when the clock cycle ends.
-We can then define how one step in the semantics looks like.
+We can then define how one step in the semantics looks like. We therefore first need to define the structure of the main module which will contain the logic for the program. In general, functions that are translated to hardware will require basic handshaking signals so that the translated function can be used in hardware. Firstly, they require an input for the clock, so that all the sequential circuits are run at the right time. They then require a start and reset input, so that the hardware generated from the function can be reused multiple times. Finally, they need a finish and return signal, where finish will go high when the result is ready to be read. In addition to that, the function could take an arbitrary number of inputs which act as arguments to the function, so that the function can be called with different arguments. However, in addition to inputs and outputs to the module, we also need to keep track of some internal signals and properties about the module. Firstly, we need to keep track of the internal variables that contain the current state of the module, and the current contents of the stack. Finally, the module will contain the entry point of the module and the list of module items that declare all of the internal registers and contain the encoding of the state machine that behaves in the same way as the function. We can therefore declare it in the following way:
+
+\begin{align*}
+ \mathit{M} \quad ::= \quad \big\{\ &\mathtt{args} : \vec{r}\\
+ &\mathtt{body} : \vec{m}\\
+ &\mathtt{entrypoint} : n\\
+ &\mathtt{st, stk, finish, return, start, reset, clk} : r\\
+ &\mathtt{stacksize} : n\ \big\}
+\end{align*}
+
+The top level structure of a Verilog module consists of a list of module items $\vec{m}$. These are then executed sequentially while changing the associations of all the variables. We can define a function \textit{mis\_step}, which steps through all of the module items and executes them.
Definition of stmntrun.