1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
\chapter{RVWMO Memory Consistency Model, Version 2.0}
\label{ch:memorymodel}
This chapter defines the RISC-V memory consistency model.
A memory consistency model is a set of rules specifying the values that can be returned by loads of memory.
RISC-V uses a memory model called ``RVWMO'' (RISC-V Weak Memory Ordering) which is designed to provide flexibility for architects to build high-performance scalable designs while simultaneously supporting a tractable programming model.
Under RVWMO, code running on a single hart appears to execute in order from the perspective of other memory instructions in the same hart, but memory instructions from another hart may observe the memory instructions from the first hart being executed in a different order.
Therefore, multithreaded code may require explicit synchronization to guarantee ordering between memory instructions from different harts.
The base RISC-V ISA provides a FENCE instruction for this purpose, described in Section~\ref{sec:fence}, while the atomics extension ``A'' additionally defines load-reserved/store-conditional and atomic read-modify-write instructions.
The standard ISA extension for misaligned atomics ``Zam'' (Chapter~\ref{sec:zam}) and the standard ISA extension for total store ordering ``Ztso'' (Chapter~\ref{sec:ztso}) augment RVWMO with additional rules specific to those extensions.
The appendices to this specification provide both axiomatic and operational formalizations of the memory consistency model as well as additional explanatory material.
\begin{commentary}
This chapter defines the memory model for regular main memory operations. The interaction of the memory model with I/O memory, instruction fetches, FENCE.I, page table walks, and SFENCE.VMA is not (yet) formalized. Some or all of the above may be formalized in a future revision of this specification. The RV128 base ISA and future ISA extensions such as the ``V'' vector and ``J'' JIT extensions will need to be incorporated into a future revision as well.
Memory consistency models supporting overlapping memory accesses of different widths simultaneously remain an active area of academic research and are not yet fully understood. The specifics of how memory accesses of different sizes interact under RVWMO are specified to the best of our current abilities, but they are subject to revision should new issues be uncovered.
\end{commentary}
\section{Definition of the RVWMO Memory Model}
\label{sec:rvwmo}
The RVWMO memory model is defined in terms of the {\em global memory order}, a total ordering of the memory operations produced by all harts.
In general, a multithreaded program has many different possible executions, with each execution having its own corresponding global memory order.
The global memory order is defined over the primitive load and store operations generated by memory instructions.
It is then subject to the constraints defined in the rest of this chapter.
Any execution satisfying all of the memory model constraints is a legal execution (as far as the memory model is concerned).
\subsection*{Memory Model Primitives}
\label{sec:rvwmo:primitives}
The {\em program order} over memory operations reflects the order in which the instructions that generate each load and store are logically laid out in that hart's dynamic instruction stream; i.e., the order in which a simple in-order processor would execute the instructions of that hart.
Memory-accessing instructions give rise to {\em memory operations}.
A memory operation can be either a {\em load operation}, a {\em store operation}, or both simultaneously.
All memory operations are single-copy atomic: they can never be observed in a partially complete state.
Among instructions in RV32GC and RV64GC, each aligned memory instruction gives rise to exactly one memory operation, with two exceptions.
First, an unsuccessful SC instruction does not give rise to any memory operations.
Second, FLD and FSD instructions may each give rise to multiple memory operations if XLEN$<$64, as stated in Section~\ref{fld_fsd} and clarified below.
An aligned AMO gives rise to a single memory operation that is both a load operation and a store operation simultaneously.
\begin{commentary}
Instructions in the RV128 base instruction set and in future ISA extensions such as V (vector) and P (SIMD) may give rise to multiple memory operations. However, the memory model for these extensions has not yet been formalized.
\end{commentary}
A misaligned load or store instruction may be decomposed into a set of component memory operations of any granularity.
An FLD or FSD instruction for which XLEN$<$64 may also be decomposed into a set of component memory operations of any granularity.
The memory operations generated by such instructions are not ordered with respect to each other in program order, but they are ordered normally with respect to the memory operations generated by preceding and subsequent instructions in program order.
The atomics extension ``A'' does not require execution environments to support misaligned atomic instructions at all; however, if misaligned atomics are supported via the ``Zam'' extension, LRs, SCs, and AMOs may be decomposed subject to the constraints of the atomicity axiom for misaligned atomics, which is defined in Chapter~\ref{sec:zam}.
\begin{commentary}
The decomposition of misaligned memory operations down to byte granularity facilitates emulation on implementations that do not natively support misaligned accesses.
Such implementations might, for example, simply iterate over the bytes of a misaligned access one by one.
\end{commentary}
An LR instruction and an SC instruction are said to be {\em paired} if the LR precedes the SC in program order and if there are no other LR or SC instructions in between; the corresponding memory operations are said to be paired as well (except in case of a failed SC, where no store operation is generated).
The complete list of conditions determining whether an SC must succeed, may succeed, or must fail is defined in Section~\ref{sec:lrsc}.
Load and store operations may also carry one or more ordering annotations from the following set: ``acquire-RCpc'', ``acquire-RCsc'', ``release-RCpc'', and ``release-RCsc''.
An AMO or LR instruction with {\em aq} set has an ``acquire-RCsc'' annotation.
An AMO or SC instruction with {\em rl} set has a ``release-RCsc'' annotation.
An AMO, LR, or SC instruction with both {\em aq} and {\em rl} set has both ``acquire-RCsc'' and ``release-RCsc'' annotations.
For convenience, we use the term ``acquire annotation'' to refer to an acquire-RCpc annotation or an acquire-RCsc annotation.
Likewise, a ``release annotation'' refers to a release-RCpc annotation or a release-RCsc annotation.
An ``RCpc annotation'' refers to an acquire-RCpc annotation or a release-RCpc annotation.
An ``RCsc annotation'' refers to an acquire-RCsc annotation or a release-RCsc annotation.
\begin{commentary}
In the memory model literature, the term ``RCpc'' stands for release consistency with processor-consistent synchronization operations, and the term ``RCsc'' stands for release consistency with sequentially consistent synchronization operations~\cite{Gharachorloo90memoryconsistency}.
While there are many different definitions for acquire and release annotations in the literature, in the context of RVWMO these terms are concisely and completely defined by Preserved Program Order rules \ref{ppo:acquire}--\ref{ppo:rcsc}.
``RCpc'' annotations are currently only used when implicitly assigned to every memory access per the standard extension ``Ztso'' (Chapter~\ref{sec:ztso}). Furthermore, although the ISA does not currently contain native load-acquire or store-release instructions, nor RCpc variants thereof, the RVWMO model itself is designed to be forwards-compatible with the potential addition of any or all of the above into the ISA in a future extension.
\end{commentary}
\subsection*{Syntactic Dependencies}
\label{sec:memorymodel:dependencies}
The definition of the RVWMO memory model depends in part on the notion of a syntactic dependency, defined as follows.
In the context of defining dependencies, a ``register'' refers either to an entire general-purpose register, some portion of a CSR, or an entire CSR. The granularity at which dependencies are tracked through CSRs is specific to each CSR and is defined in Section~\ref{sec:csr-granularity}.
Syntactic dependencies are defined in terms of instructions' {\em source registers}, instructions' {\em destination registers}, and the way instructions {\em carry a dependency} from their source registers to their destination registers.
This section provides a general definition of all of these terms; however, Section~\ref{sec:source-dest-regs} provides a complete listing of the specifics for each instruction.
In general, a register $r$ other than {\tt x0} is a {\em source register} for an instruction $i$ if any of the following hold:
\begin{itemize}
\item In the opcode of $i$, {\em rs1}, {\em rs2}, or {\em rs3} is set to $r$
\item $i$ is a CSR instruction, and in the opcode of $i$, {\em csr} is set to $r$, unless $i$ is CSRRW or CSRRWI and {\em rd} is set to {\tt x0}
\item $r$ is a CSR and an implicit source register for $i$, as defined in Section~\ref{sec:source-dest-regs}
\item $r$ is a CSR that aliases with another source register for $i$
\end{itemize}
Memory instructions also further specify which source registers are {\em address source registers} and which are {\em data source registers}.
In general, a register $r$ other than {\tt x0} is a {\em destination register} for an instruction $i$ if any of the following hold:
\begin{itemize}
\item In the opcode of $i$, {\em rd} is set to $r$
\item $i$ is a CSR instruction, and in the opcode of $i$, {\em csr} is set to $r$, unless $i$ is CSRRS or CSRRC and {\em rs1} is set to {\tt x0} or $i$ is CSRRSI or CSRRCI and uimm[4:0] is set to zero.
\item $r$ is a CSR and an implicit destination register for $i$, as defined in Section~\ref{sec:source-dest-regs}
\item $r$ is a CSR that aliases with another destination register for $i$
\end{itemize}
Most non-memory instructions {\em carry a dependency} from each of their source registers to each of their destination registers.
However, there are exceptions to this rule; see Section~\ref{sec:source-dest-regs}
Instruction $j$ has a {\em syntactic dependency} on instruction $i$ via destination register $s$ of $i$ and source register $r$ of $j$ if either of the following hold:
\begin{itemize}
\item $s$ is the same as $r$, and no instruction program-ordered between $i$ and $j$ has $r$ as a destination register
\item There is an instruction $m$ program-ordered between $i$ and $j$ such that all of the following hold:
\begin{enumerate}
\item $j$ has a syntactic dependency on $m$ via destination register $q$ and source register $r$
\item $m$ has a syntactic dependency on $i$ via destination register $s$ and source register $p$
\item $m$ carries a dependency from $p$ to $q$
\end{enumerate}
\end{itemize}
Finally, in the definitions that follow, let $a$ and $b$ be two memory operations, and let $i$ and $j$ be the instructions that generate $a$ and $b$, respectively.
$b$ has a {\em syntactic address dependency} on $a$ if $r$ is an address source register for $j$ and $j$ has a syntactic dependency on $i$ via source register $r$
$b$ has a {\em syntactic data dependency} on $a$ if $b$ is a store operation, $r$ is a data source register for $j$, and $j$ has a syntactic dependency on $i$ via source register $r$
$b$ has a {\em syntactic control dependency} on $a$ if there is an instruction $m$ program-ordered between $i$ and $j$ such that $m$ is a branch or indirect jump and $m$ has a syntactic dependency on $i$.
\begin{commentary}
Generally speaking, non-AMO load instructions do not have data source registers, and unconditional non-AMO store instructions do not have destination registers. However, a successful SC instruction is considered to have the register specified in {\em rd} as a destination register, and hence it is possible for an instruction to have a syntactic dependency on a successful SC instruction that precedes it in program order.
\end{commentary}
\subsection*{Preserved Program Order}
The global memory order for any given execution of a program respects some but not all of each hart's program order.
The subset of program order that must be respected by the global memory order is known as {\em preserved program order}.
\newcommand{\ppost}{$b$ is a store, and $a$ and $b$ access overlapping memory addresses}
\newcommand{\ppofence}{There is a FENCE instruction that orders $a$ before $b$}
\newcommand{\ppoacquire}{$a$ has an acquire annotation}
\newcommand{\pporelease}{$b$ has a release annotation}
\newcommand{\pporcsc}{$a$ and $b$ both have RCsc annotations}
\newcommand{\ppoamoforward}{$a$ is generated by an AMO or SC instruction, $b$ is a load, and $b$ returns a value written by $a$}
\newcommand{\ppoaddr}{$b$ has a syntactic address dependency on $a$}
\newcommand{\ppodata}{$b$ has a syntactic data dependency on $a$}
\newcommand{\ppoctrl}{$b$ is a store, and $b$ has a syntactic control dependency on $a$}
\newcommand{\ppopair}{$a$ is paired with $b$}
\newcommand{\ppordw}{$a$ and $b$ are loads, $x$ is a byte read by both $a$ and $b$, there is no store to $x$ between $a$ and $b$ in program order, and $a$ and $b$ return values for $x$ written by different memory operations}
\newcommand{\ppoaddrdatarfi}{$b$ is a load, and there exists some store $m$ between $a$ and $b$ in program order such that $m$ has an address or data dependency on $a$, and $b$ returns a value written by $m$}
\newcommand{\ppoaddrpo}{$b$ is a store, and there exists some instruction $m$ between $a$ and $b$ in program order such that $m$ has an address dependency on $a$}
%\newcommand{\ppoctrlcfence}{$a$ and $b$ are loads, $b$ has a syntactic control dependency on $a$, and there exists a {\tt fence.i} between the branch used to form the control dependency and $b$ in program order}
%\newcommand{\ppoaddrpocfence}{$a$ is a load, there exists an instruction $m$ which has a syntactic address dependency on $a$, and there exists a {\tt fence.i} between $m$ and $b$ in program order}
The complete definition of preserved program order is as follows (and note that AMOs are simultaneously both loads and stores):
memory operation $a$ precedes memory operation $b$ in preserved program order (and hence also in the global memory order) if $a$ precedes $b$ in program order, $a$ and $b$ both access regular main memory (rather than I/O regions), and any of the following hold:
\begin{itemize}
\item Overlapping-Address Orderings:
\begin{enumerate}
\item\label{ppo:->st} \ppost
\item\label{ppo:rdw} \ppordw
\item\label{ppo:amoforward} \ppoamoforward
\end{enumerate}
\item Explicit Synchronization
\begin{enumerate}[resume]
\item\label{ppo:fence} \ppofence
\item\label{ppo:acquire} \ppoacquire
\item\label{ppo:release} \pporelease
\item\label{ppo:rcsc} \pporcsc
\item\label{ppo:pair} \ppopair
\end{enumerate}
\item Syntactic Dependencies
\begin{enumerate}[resume]
\item\label{ppo:addr} \ppoaddr
\item\label{ppo:data} \ppodata
\item\label{ppo:ctrl} \ppoctrl
\end{enumerate}
\item Pipeline Dependencies
\begin{enumerate}[resume]
\item\label{ppo:addrdatarfi} \ppoaddrdatarfi
\item\label{ppo:addrpo} \ppoaddrpo
%\item\label{ppo:ctrlcfence} \ppoctrlcfence
%\item\label{ppo:addrpocfence} \ppoaddrpocfence
\end{enumerate}
\end{itemize}
\subsection*{Memory Model Axioms}
An execution of a RISC-V program obeys the RVWMO memory consistency model only if there exists a global memory order conforming to preserved program order and satisfying the {\em load value axiom}, the {\em atomicity axiom}, and the {\em progress axiom}.
\newcommand{\loadvalueaxiom}{
Each byte of each load $i$ returns the value written to that byte by the store that is the latest in global memory order among the following stores:
\begin{enumerate}
\item Stores that write that byte and that precede $i$ in the global memory order
\item Stores that write that byte and that precede $i$ in program order
\end{enumerate}
}
\newcommand{\atomicityaxiom}{If $r$ and $w$ are paired load and store operations generated by aligned LR and SC instructions in a hart $h$, $s$ is a store to byte $x$, and $r$ returns a value written by $s$, then $s$ must precede $w$ in the global memory order, and there can be no store from a hart other than $h$ to byte $x$ following $s$ and preceding $w$ in the global memory order.}
\newcommand{\progressaxiom}{No memory operation may be preceded in the global memory order by an infinite sequence of other memory operations.}
\paragraph{Load Value Axiom}
\label{rvwmo:ax:load}
\loadvalueaxiom
\paragraph{Atomicity Axiom}
\label{rvwmo:ax:atom}
\atomicityaxiom
\begin{commentary}
The \nameref{rvwmo:ax:atom} theoretically supports LR/SC pairs of different widths and to mismatched addresses, since implementations are permitted to allow SC operations to succeed in such cases. However, in practice, we expect such patterns to be rare, and their use is discouraged.
\end{commentary}
\paragraph{Progress Axiom}
\label{rvwmo:ax:prog}
\progressaxiom
\input{dep-table}
|