summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/examples/exn.sail20
-rw-r--r--doc/examples/list.sail1
-rw-r--r--doc/examples/my_replicate_bits.sail3
-rw-r--r--doc/examples/regref.sail17
-rw-r--r--doc/manual.tex7
-rw-r--r--doc/riscv.tex15
-rw-r--r--doc/tutorial.tex260
-rw-r--r--doc/types.tex2
-rw-r--r--doc/usage.tex44
9 files changed, 327 insertions, 42 deletions
diff --git a/doc/examples/exn.sail b/doc/examples/exn.sail
new file mode 100644
index 00000000..de97e3f9
--- /dev/null
+++ b/doc/examples/exn.sail
@@ -0,0 +1,20 @@
+val print = {ocaml: "print_endline"} : string -> unit
+
+scattered union exception
+
+union clause exception = Epair : (range(0, 255), range(0, 255))
+
+union clause exception = Eunknown : string
+
+function main() : unit -> unit = {
+ try {
+ throw(Eunknown("foo"))
+ } catch {
+ Eunknown(msg) => print(msg),
+ _ => exit()
+ }
+}
+
+union clause exception = Eint : int
+
+end exception
diff --git a/doc/examples/list.sail b/doc/examples/list.sail
new file mode 100644
index 00000000..4eaeb67a
--- /dev/null
+++ b/doc/examples/list.sail
@@ -0,0 +1 @@
+let l : list(int) = 1 :: 2 :: 3 :: [||] \ No newline at end of file
diff --git a/doc/examples/my_replicate_bits.sail b/doc/examples/my_replicate_bits.sail
index bd45a32d..c9972cd6 100644
--- a/doc/examples/my_replicate_bits.sail
+++ b/doc/examples/my_replicate_bits.sail
@@ -11,7 +11,8 @@ val "shiftl" : forall 'm. (bits('m), int) -> bits('m)
val operator >> = {
ocaml: "shiftr_ocaml",
c: "shiftr_c",
- lem: "shiftr_lem"
+ lem: "shiftr_lem",
+ _: "shiftr"
} : forall 'm. (bits('m), int) -> bits('m)
val "or_vec" : forall 'n. (bits('n), bits('n)) -> bits('n)
diff --git a/doc/examples/regref.sail b/doc/examples/regref.sail
new file mode 100644
index 00000000..268af295
--- /dev/null
+++ b/doc/examples/regref.sail
@@ -0,0 +1,17 @@
+default Order dec
+$include <prelude.sail>
+
+register X0 : bits(8)
+register X1 : bits(8)
+register X2 : bits(8)
+
+let X : vector(3, dec, register(bits(8))) = [ref X2, ref X1, ref X0]
+
+function main() : unit -> unit = {
+ X0 = 0xFF;
+ assert(X0 == 0xFF);
+ (*X[0]) = 0x11;
+ assert(X0 == 0x11);
+ (*ref X0) = 0x00;
+ assert(X0 == 0x00)
+} \ No newline at end of file
diff --git a/doc/manual.tex b/doc/manual.tex
index a52600a5..3b75b26a 100644
--- a/doc/manual.tex
+++ b/doc/manual.tex
@@ -25,7 +25,7 @@
\lstdefinelanguage{sail}
{ morekeywords={val,function,cast,type,forall,overload,operator,enum,union,undefined,exit,and,assert,sizeof,
scattered,register,inc,dec,if,then,else,effect,let,as,@,in,end,Type,Int,Order,match,clause,struct,
- foreach,from,to,by,infix,infixl,infixr,bitfield,default},
+ foreach,from,to,by,infix,infixl,infixr,bitfield,default,try,catch,throw},
keywordstyle={\bf\ttfamily\color{blue}},
morestring=[b]",
stringstyle={\ttfamily\color{red}},
@@ -64,8 +64,9 @@
\title{The Sail instruction-set semantics specification language}
-\author{Kathryn E. Gray \and Peter Sewell \and Christopher Pulte \and
- Shaked Flur \and Robert Norton-Wright \and Alasdair Armstrong}
+\author{Alasdair Armstrong \and Thomas Bauereiss \and Brian Campbell \and
+ Shaked Flur \and Kathryn E. Gray \and Robert Norton-Wright \and Christopher Pulte \and
+ Peter Sewell}
\maketitle
diff --git a/doc/riscv.tex b/doc/riscv.tex
index e2aa3025..1e50c90c 100644
--- a/doc/riscv.tex
+++ b/doc/riscv.tex
@@ -63,14 +63,13 @@ register Xs : vector(32, dec, xlen_t)
\sailX
We also give a function \ll{MEMr} for reading memory, this function
-just points at a builtin we have defined elsewhere \TODO{Section where
- we talk about preludes, built-in type environment etc}. Note that functions in sail are
-annotated with effects. This effect system is quite basic, but
-indicates whether or not functions read or write registers (rreg and
-wreg), read and write memory (rmem and wmem), as well as a host of
-other concurrency model related effects. They also indicate whether a
-function throws exceptions or has other non-local control flow (the
-escape effect).
+just points at a builtin we have defined elsewhere. Note that
+functions in sail are annotated with effects. This effect system is
+quite basic, but indicates whether or not functions read or write
+registers (rreg and wreg), read and write memory (rmem and wmem), as
+well as a host of other concurrency model related effects. They also
+indicate whether a function throws exceptions or has other non-local
+control flow (the escape effect).
\sailMEMr
\sailfnMEMr
diff --git a/doc/tutorial.tex b/doc/tutorial.tex
index 98a06710..34046e2b 100644
--- a/doc/tutorial.tex
+++ b/doc/tutorial.tex
@@ -60,6 +60,31 @@ does not make any distinction between expressions and statements, so
since there is only a single line of code within the foreach block, we
can drop it and simply write: \mrbfnmyreplicatebitsthree
+\subsection{External Bindings}
+
+Rather than defining functions within Sail itself, they can be mapped
+onto functions definition within the various backend targets supported
+by Sail. This is primarily used to setup the primitive functions
+defined in the Sail library. These declarations work like much FFI
+bindings in many programming languages---in Sail we provide the
+\ll{val} declaration, except rather than giving a function body we
+supply a string used to identify the external operator in each
+backend. For example, we could link the \ll{>>} operator with the
+\verb|shiftl| primitive as \mrbzeightoperatorzzerozIzIznine If the
+external function has the same name as the sail function, such as
+\ll{shiftl = "shiftl"}, then we can use the shorthand syntax
+\mrbshiftl
+
+We can map onto differently-named operations for different targets by
+using a JSON-like \ll{key: "value"} notation, for example:
+\mrbzeightoperatorzzerozKzKznine We can also omit backends---in which
+case those targets will expect a definition written in Sail. Note that
+no checking is done to ensure that the definition in the target
+matches the type of the Sail function. Finally, the \ll{_} key used
+above is a wildcard that will be used for any backend not otherwise
+included. If we use the wildcard key, then we cannot omit specific
+backends to force them to use a definition in Sail.
+
\subsection{Numeric Types}
\label{sec:numeric}
@@ -95,7 +120,9 @@ Note that \ll{bit} isn't a numeric type (i.e. it's not
\ll{range(0,1)}. This is intentional, as otherwise it would be
possible to write expressions like \ll{(1 : bit) + 5} which would end
up being equal to \ll{6 : range(5, 6)}. This kind of implicit casting
-from bits to other numeric types would be highly undesirable.
+from bits to other numeric types would be highly undesirable. The
+\ll{bit} type itself is a two-element type with members \ll{bitzero} and
+\ll{bitone}.
\subsection{Vector Type}
\label{sec:vec}
@@ -236,6 +263,12 @@ Pattern matching can be used to destructure lists, see Section~\ref{sec:pat}
\subsection{Other Types}
+Sail also has a \ll{string} type, and a \ll{real} type. The \ll{real}
+type is used to model arbitrary real numbers, so floating point
+instructions could be specified by saying that they are equivalent to
+mapping the floating point inputs to real numbers, performing the
+arithmetic operation on the real numbers, and then mapping back to a
+floating point value of the appropriate precision.
\subsection{Pattern Matching}
\label{sec:pat}
@@ -307,6 +340,17 @@ somewhat ambiguous. This is the primary reason why we have the basic,
but incomplete, pattern exhaustiveness check mentioned above---it can
warn you if removing an enum constructor breaks a pattern match.
+\paragraph{Matching on tuples}
+
+We use match to destructure tuple types, for example:
+\begin{lstlisting}
+let x : (int, int) = (2, 3) in
+match x {
+ (y, z) => print("y = 2 and z = 3")
+}
+
+\end{lstlisting}
+
\paragraph{Matching on unions}
Match can also be used to destructure union constructors, for example
@@ -443,10 +487,10 @@ assignment operator within a block.
}
\end{lstlisting}
The assignment operator is the equality symbol, as in C and other
-programming languages. Sail supports a rich language of
-\emph{l-expression} forms, which can appear on the left of an
-assignment. These will be described in Subsection~\ref{sec:lexp}. Note
-that we could have written
+programming languages. Sail supports a rich language of \emph{l-value}
+forms, which can appear on the left of an assignment. These will be
+described in Subsection~\ref{sec:lexp}. Note that we could have
+written
\begin{lstlisting}
{
x = 3;
@@ -473,23 +517,130 @@ the variable \ll{x}, so
would allow \ll{x} to be either 2 or 3, but not any other value. The
\lstinline+{|2, 3|}+ syntax is equivalent to \lstinline+{'n, 'n in {2, 3}. int('n)}+.
-\subsubsection{l-expressions}
+\subsubsection{Assignment and l-values}
\label{sec:lexp}
-Sail allows for setter functions to be declared in a very simple way:
-\ll{f(x) = y} is sugar for \ll{f(x, y)}. This feature is commonly used
-when setting
+It is common in ISA specifications to assign to complex l-values,
+e.g.~to a subvector or named field of a bitvector register, or to an
+l-value computed with some auxiliary function, e.g.~to select the
+appropriate register for the current execution model.
+
+We have l-values that allow us to write to individual elements of a
+vector:
+\begin{lstlisting}
+{
+ v : bits(8) = 0xFF;
+ v[0] = bitzero;
+ assert(v == 0xFE)
+}
+\end{lstlisting}
+as well as sub ranges of a vector:
+\begin{lstlisting}
+{
+ v : bits(8) = 0xFF;
+ v[4 .. 0] = 0x0; // assume default Order dec
+ assert(v == 0xF0)
+}
+\end{lstlisting}
+We also have vector concatenation l-values, which work much like
+vector concatenation patterns
+\begin{lstlisting}
+{
+ v1 : bits(4) = 0xF;
+ v2 : bits(4) = 0xF;
+ v1 @ v2 = 0xAB;
+ assert(v1 == 0xA & v2 == 0xB)
+}
+\end{lstlisting}
+For structs we can write to an individual struct field as
+\begin{lstlisting}
+{
+ s : S = struct { field = 0xFF }
+ s.field = 0x00
+}
+\end{lstlisting}
+assume we have a struct type \ll{S}, with a field simply called
+\ll{field}. We can do multiple assignment using tuples, e.g.
+\begin{lstlisting}
+{
+ (x, y) = (2, 3);
+ assert(x == 2 & x == 3)
+}
+\end{lstlisting}
+
+Finally, we allow functions to appear in l-values. This is a very
+simple way to declare `setter' functions that look like custom
+l-values, for example:
+\begin{lstlisting}
+{
+ memory(addr) = 0x0F
+}
+\end{lstlisting}
+This works because \ll{f(x) = y} is sugar for \ll{f(x, y)}. This
+feature is commonly used when setting registers or memory that has
+additional semantics for when they are read or written. We commonly
+use the overloading feature to declare what appear to be getter/setter
+pairs, so the above example we could implement a \ll{read_memory}
+function and a \ll{write_memory} function and overload them both as
+\ll{memory} to allow us to write memory using \ll{memory(addr) = data}
+and read memory as \ll{data = memory(addr)}, as so:
+\begin{lstlisting}
+val read_memory : bits(64) -> bits(8)
+val write_memory : (bits(64), bits(8)) -> unit
+
+overload memory = {read_memory, write_memory}
+\end{lstlisting}
+For more details on operator and function overloading see
+Section~\ref{sec:overload}.
+
+\subsection{Registers}
+
+Registers can be declared with a top level
+\begin{center}
+ \ll{register} \textit{name} \ll{:} \textit{type}
+\end{center}
+declaration. Registers are essentially top-level global variables and
+can be set with the previously discussed l-expression forms. There is
+currently no restriction on the type of a register in
+Sail.\footnote{We may at some point want to enforce that they can be
+ mapped to bitvectors.}
+
+Registers differ from ordinary mutable variables as we can pass around
+references to them by name. A reference to a register \ll{R} is
+created as \ll{ref R}. If the register \ll{R} has the type \ll{A},
+then the type of \ll{ref R} will be \ll{register(A)}. There is a
+dereferencing l-value operator \ll{*} for assigning to a register
+reference. One use for register references is to create a list of
+general purpose registers, so they can be indexed using numeric
+variables. For example:
+\lstinputlisting{examples/regref.sail}
+
+We can dereference register references using the \ll{"reg_deref"}
+builtin (see Section~\ref{sec:prelude}), which is set up like so:
+\begin{lstlisting}
+val "reg_deref" : forall ('a : Type). register('a) -> 'a effect {rreg}
+\end{lstlisting}
+Currently there is no built-in syntactic sugar for dereferencing
+registers in expressions.
+
+Unlike previous versions of Sail, referencing and de-referencing
+registers is done explicitly, although we can use an automatic cast to
+implictly dereference registers if that semantics is desired for a
+specific specification that makes heavy use of register references,
+like so:
+\begin{lstlisting}
+val cast auto_reg_deref = "reg_deref" : forall ('a : Type). register('a) -> a effect {rreg}
+\end{lstlisting}
-\fbox{TODO}
\subsection{Type declarations}
\subsubsection{Enumerations}
-Enumerations can be defined in either a Haskell-like syntax
-(useful for smaller enums) or a more traditional C-like syntax, which
-is often more readable for enumerations with more members. There are
-no lexical constraints on the identifiers that can be part of an
+Enumerations can be defined in either a Haskell-like syntax (useful
+for smaller enums) or a more traditional C-like syntax, which is often
+more readable for enumerations with more members. There are no lexical
+constraints on the identifiers that can be part of an
enumeration. There are also no restrictions on the name of a
enumeration type, other than it must be a valid identifier. For
example, the following shows two ways to define the enumeration
@@ -658,6 +809,7 @@ vector slicing. Operators used in types always share precedence with
identically named operators at the expression level.
\subsection{Ad-hoc Overloading}
+\label{sec:overload}
Sail has a flexible overloading mechanism using the \ll{overload}
keyword
@@ -736,14 +888,14 @@ so we can use this to define functions with optional arguments, e.g.
\ll{sizeof}, see Section~\ref{sec:sizeof}) or we can provide it
ourselves as an explicit argument.
-\subsection{Getters and Setters}
-\label{sec:getset}
+%% \subsection{Getters and Setters}
+%% \label{sec:getset}
-We have already seen some examples of getters and setters in
-Subsection~\ref{sec:bitfield}, but they can be used in many other
-contexts.
+%% We have already seen some examples of getters and setters in
+%% Subsection~\ref{sec:bitfield}, but they can be used in many other
+%% contexts.
-\fbox{TODO}
+%% \fbox{TODO}
\subsection{Sizeof and Constraint}
\label{sec:sizeof}
@@ -793,8 +945,73 @@ otherwise not accessible at runtime, and so can be used to implement
implicit arguments, as was seen for \ll{replicate_bits} in
Section~\ref{sec:functions}.
+\subsection{Scattered Definitions}
+\label{sec:scattered}
+In a Sail specification, sometimes it is desirable to collect together
+the definitions relating to each machine instruction (or group
+thereof), e.g.~grouping the clauses of an AST type with the associated
+clauses of decode and execute functions, as in
+Section~\ref{sec:riscv}. Sail permits this with syntactic sugar for
+`scattered' definitions. Either functions or union types can be
+scattered.
+
+One begins a scattered definition by declaring the name and kind
+(either function or union) of the scattered definition, e.g.
+\begin{lstlisting}
+scattered function foo
+
+scattered union bar
+\end{lstlisting}
+This is then followed by a list of clauses for either the union or the
+function, which can be freely interleaved with other definitions (such
+as \ll{E} in the below code)
+\begin{lstlisting}[mathescape]
+union clause bar : Baz(int, int)
+
+function clause foo(Baz(x, y)) = $\ldots$
+
+enum E = A | B | C
+
+union clause bar : Quux(string)
+
+function clause foo(Quux(str)) = print(str)
+\end{lstlisting}
+Finally the scattered definition is ended with the \ll{end} keyword, like so:
+\begin{lstlisting}
+end foo
+
+end bar
+\end{lstlisting}
+
+Semantically, scattered definitions of union types appear at the start
+of their definition, and scattered definitions of functions appear at
+the end. A scattered function definition can be recursive, but
+mutually recursive scattered function definitions should be avoided.
+
+\subsection{Exceptions}
+\label{sec:exn}
+
+Perhaps suprisingly for a specification language, Sail has exception
+support. This is because exceptions as a language feature do sometimes
+appear in vendor ISA pseudocode, and such code would be very difficult
+to translate into Sail if Sail did not itself support exceptions. We
+already translate Sail to monadic theorem prover code, so working with
+a monad that supports exceptions there is fairly natural.
+
+For exceptions we have two language features: \ll{throw} statements
+and \ll{try}-\ll{catch} blocks. The throw keyword takes a value of
+type \ll{exception} as an argument, which can be any user defined type
+with that name. There is no builtin exception type, so to use
+exceptions one must be set up on a per-project basis. Usually the
+exception type will be a union, often a scattered union, which allows
+for the exceptions to be declared throughout the specification as they
+would be in OCaml, for example: \lstinputlisting{examples/exn.sail}
+Note how the use of the scattered type allows additional exceptions to
+be declared even after they are used.
+
\subsection{Preludes and Default Environment}
\label{sec:prelude}
+
By default Sail has almost no built-in types or functions, except for
the primitive types described in this Chapter. This is because
different vendor-pseudocode's have varying naming conventions and
@@ -834,4 +1051,7 @@ operations. These are listed below:
the default order (which must be set before including this file).
\item[smt.sail] Defines operators allowing div, mod, and abs
to be used in types by exposing them to the Z3 SMT solver.
+ \item[exception\_basic.sail] Defines a trivial exception type, for
+ situations where you don't want to declare your own (see
+ Section~\ref{sec:exn}).
\end{description}
diff --git a/doc/types.tex b/doc/types.tex
index 11037c91..a74cdea9 100644
--- a/doc/types.tex
+++ b/doc/types.tex
@@ -1,6 +1,8 @@
\section{Type System}
\label{sec:types}
+(This section is still a work in progress)
+
\newcommand{\tcheck}[3]{#1 \vdash #2 \Leftarrow #3}
\newcommand{\tinfer}[3]{#1 \vdash #2 \Rightarrow #3}
\newcommand{\msail}[1]{\text{\lstinline[mathescape]+#1+}}
diff --git a/doc/usage.tex b/doc/usage.tex
index 12095822..3b8eed5f 100644
--- a/doc/usage.tex
+++ b/doc/usage.tex
@@ -21,7 +21,7 @@ definitions used in the rest of the specification and then
specification.
For more complex projects, once can use \ll{$include} statments in
-Sail source, for example: \TODO{use \# like C}
+Sail source, for example:
\begin{lstlisting}
$include <library.sail>
$include "file.sail"
@@ -38,7 +38,7 @@ AST is parsed~\footnote{This can affect precedence declarations for custom user
\subsection{OCaml compilation}
-To compile a sail specification into OCaml, one calls Sail as
+To compile a Sail specification into OCaml, one calls Sail as
\begin{verbatim}
sail -ocaml FILES
\end{verbatim}
@@ -76,25 +76,46 @@ specification. In particular \verb+elf.sail+ defines a function
correct location. ELF loading is done by the linksem
library\footnote{\url{https://github.com/rems-project/linksem}}.
-There is also an \verb+-ocaml_trace+ option which instruments the
-generated OCaml code with tracing information this option implies \verb+-ocaml+.
+There is also an \verb+-ocaml_trace+ option which is the same as
+\verb+-ocaml+ except it instruments the generated OCaml code with
+tracing information.
-\subsection{C compilation}
+%% \subsection{C compilation}
-WIP but basically like OCaml
+%% WIP but basically like OCaml
-\subsection{Lem embedding}
+\subsection{Lem and Isabelle}
-\TODO{Document generating lem}
+We have a separate document detailing how to generate Isabelle
+theories from Sail models, and how to work with those models in
+Isabelle, see:
+\begin{center}
+\url{https://github.com/rems-project/sail/raw/sail2/snapshots/isabelle/Manual.pdf}
+\end{center}
+Currently there are generated Isabelle snapshots for some of our
+models in \verb+snapshots/isabelle+ in the Sail repository. These
+snapshots are provided for convenience, and are not guaranteed to be
+up-to-date.
+
+In order to open a theory of one of the specifications in Isabelle,
+use the -l Sail command-line flag to load the session containing the
+Sail library. Snapshots of the Sail and Lem libraries are in the
+\verb+lib/sail+ and \verb+lib/lem+ directories, respectively. You can
+tell Isabelle where to find them using the -d flag, as in
+\begin{verbatim}
+isabelle jedit -l Sail -d lib/lem -d lib/sail riscv/Riscv.thy
+\end{verbatim}
+When run from the \verb+snapshots/isabelle+ directory this will open
+the RISC-V specification.
\subsection{Interactive mode}
-Compiling sail with
+Compiling Sail with
\begin{verbatim}
make isail
\end{verbatim}
builds it with a GHCi-style interactive interpreter. This can be used
-by starting Sail with \verb+sail -i+. If sail is not compiled with
+by starting Sail with \verb+sail -i+. If Sail is not compiled with
interactive support the \verb+-i+ flag does nothing. Sail will still
handle any other command line arguments as per usual, including
compiling to OCaml or Lem. One can also pass a list of commands to the
@@ -127,6 +148,9 @@ indicated by starting with the letter d.
improve typechecking times if you are repeatedly typechecking the
same specification while developing it.
+\item \verb+-no_lexp_bounds_check+ Turn off bounds checking in the left
+ hand side of assignments.
+
\item \verb+-no_effects+ Turn off effect checking. May break some
backends that assume effects are properly checked.