Skip to content

Commit 23339d9

Browse files
README text
1 parent d7b9025 commit 23339d9

File tree

1 file changed

+19
-19
lines changed

1 file changed

+19
-19
lines changed

testable-simd-models/README.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ The structure of this crate is based on [rust-lang/stdarch/crates/core_arch](htt
66

77
## Code Structure
88
Within the `core_arch` folder in this crate, there is a different
9-
folder for each architecture for which we have wrtten models.
9+
folder for each architecture for which we have written models.
1010
In particular, it contains folders for `x86` and `arm_shared`.
1111
Each such folder has 2 sub-folders: `models` and `tests`.
1212

@@ -18,18 +18,18 @@ abstractions implemented in `abstractions`, especially those in
1818
resemble their implementations within the Rust core itself.
1919

2020
The `tests` folder contains the tests of these models, and is
21-
structured the same way as `models`. Each file additionally contains
21+
structured the same way as `models`. Each file additionally includes
2222
the definition of a macro that makes writing these tests easier. The
2323
tests work by testing the models against the intrinsics in the Rust
2424
core, trying out random inputs (generally 1000), and comparing their
2525
outputs.
2626

27-
All tests can run by executing `cargo test` and we expect this to be
27+
All tests can be run by executing `cargo test`, and we expect this to be
2828
run as part of CI.
2929

3030
## Modeling a SIMD Intrinsic
3131

32-
There are three kinds of SIMD intrinsics we find in `core::arch`.
32+
There are three kinds of SIMD intrinsics in `core::arch`.
3333

3434
The first kind are builtin Rust compiler intrinsics, some of which are
3535
in the [`intrinsics/simd.rs` file](https://github.com/model-checking/verify-rust-std/blob/main/library/core/src/intrinsics/simd.rs)
@@ -42,7 +42,7 @@ of `extern` intrinsics used in the Intel x86 AVX2 library.
4242
These extern intrinsics are typically platform-specific functions that map to low-level instructions.
4343

4444
The third kind are `defined` intrinsics that are given proper definitions in Rust, and their code may
45-
depend on the builtin intrinsics or the extern intrinsics. There defined intrinsics represent higher-level
45+
depend on the builtin intrinsics or the extern intrinsics. These defined intrinsics represent higher-level
4646
operations that are wrappers around one or more assembly instructions.
4747

4848
### Modeling builtin intrinsics manually
@@ -70,7 +70,7 @@ pub fn simd_add<const N: u64, T: MachineInteger + Copy>(
7070
```
7171

7272
Notably, we model a strongly typed version of `simd_add`, in contrast to the compiler
73-
intrinsic which is too generic and unimplementable in safe Rust:
73+
intrinsic, which is too generic and unimplementable in safe Rust:
7474

7575
```rust
7676
/// Adds two simd vectors elementwise.
@@ -81,8 +81,8 @@ intrinsic which is too generic and unimplementable in safe Rust:
8181
pub unsafe fn simd_add<T>(x: T, y: T) -> T;
8282
```
8383

84-
The main rules for writing these models is that they should be simple and self-contained,
85-
relying only on the libraries in `abstractions` or on builtin Rust language features or on
84+
The main rules for writing these models are that they should be simple and self-contained,
85+
relying only on the libraries in `abstractions`, on builtin Rust language features, or
8686
other testable models. In particular, they should not themselves directly call Rust libraries
8787
or external crates, without going through the abstractions API.
8888

@@ -98,7 +98,7 @@ the extern intrinsics used in `avx2.rs` can be found in `avx2_handwritten.rs`.
9898
Modeling extern intrinsics is similar to modeling the builtin ones,
9999
in that the models are written by hand and treat the SIMD vectors
100100
as arrays of machine integers. The main difference is that these intrinsics
101-
are platform specific and so their modeling requires looking at the Intel or ARM
101+
are platform-specific and so their modeling requires looking at the Intel or ARM
102102
documentation for the underlying operation.
103103

104104
For example, the extern intrinsic `phaddw` used in `avx2` corresponds to an
@@ -125,8 +125,8 @@ pub fn phaddw(a: i16x16, b: i16x16) -> i16x16 {
125125

126126
### Modeling defined intrinsics semi-automatically
127127

128-
To model the third category of intrinsics, we copy the Rust code of
129-
the intrinsic and adapt it to use our underlying abstractions. The
128+
To model a defined intrinsic, we essentially copy the Rust code of
129+
the intrinsic from `core::arch` and adapt it to use our underlying abstractions. The
130130
changes needed to the code are sometimes scriptable, and indeed most
131131
of our models were generated from a script, but some changes are still
132132
needed by hand.
@@ -175,12 +175,12 @@ pub fn _mm256_bsrli_epi128<const IMM8: i32>(a: __m256i) -> __m256i {
175175
}
176176
```
177177

178-
Thus, we then go to to `core_arch/x86/models/avx2.rs`, and add this implementation.
178+
Thus, we then go to `core_arch/x86/models/avx2.rs`, and add this implementation.
179179
The only change it requires here is that the `simd_shuffle` macro is a function in our model,
180180
and we discard all the function attributes.
181181

182-
For other intrinsics, sometimes we need to make more changes. Since our model of the builtin intrinsics
183-
are more precise with respect to the type of their arguments compared to their Rust counterparts, we
182+
For other intrinsics, we sometimes need to make more changes. Since our model of the builtin intrinsics
183+
is more precise concerning the type of their arguments compared to their Rust counterparts, we
184184
sometimes need to add more type annotations in our defined models. We also remove all `unsafe` guards,
185185
since our models are always in safe Rust. Otherwise, our code for the defined intrinsics looks very
186186
similar to the upstream code in `core::arch`.
@@ -192,26 +192,26 @@ similar to the upstream code in `core::arch`.
192192
mk!([100]_mm256_bsrli_epi128{<0>,<1>,<2>,<3>,...,<255>}(a: BitVec));
193193
```
194194
The macro invocation has four parts.
195-
1. `mk!([100]...`: By default the macro tests for a thousand randomly generated inputs. If needed, this can be modified, such as here, where the `[100]` is used so that
195+
1. `mk!([100]...`: By default, the macro tests for a thousand randomly generated inputs. If needed, this can be modified, such as here, where the `[100]` is used so that
196196
only 100 inputs are generated.
197197
2. `_mm256_bsrli_epi128`: This is the name of the intrinsic being tested, and is necessary in all cases.
198198
3. `{<0>,<1>,<2>,<3>,...,<255>}`: This part only appears when the intrinsic has a const generic argument, like the `IMM8` in this intrinsic.
199199
As the name indicates, this constant argument is supposed to be at most 8 bits wide.
200-
We can confirm this by looking at the implementation, and spotting the `static_assert_uimm_bits!(IMM8, 8);`
200+
We can confirm this by looking at the implementation and spotting the `static_assert_uimm_bits!(IMM8, 8);`
201201
line, which asserts that constant argument is positive and fits in 8 bits. Thus, we add `{<0>,<1>,<2>,<3>,...,<255>}` to test for each possible constant
202202
value of the constant argument.
203203
4. `(a: BitVec)`: This part contains all the arguments of the intrinsic and their types.
204204

205-
This surmises the steps needed to use the `mk!` macro to generate a test. There is a caveat however. In the case that the output of an intrinsic is _not_
206-
a bit-vector (and is instead say, an integer like `i32`), then the macro will not work, and a manual test has to be written. You can see examples in the test files.
205+
This summarizes the steps needed to use the `mk!` macro to generate a test. There is a caveat: in the case that the output of an intrinsic is _not_
206+
a bit-vector (and is instead, say, an integer like `i32`), then the macro will not work, and a manual test has to be written. You can see examples in the test files.
207207

208208

209209

210210
## Contributing Models
211211

212212
To contribute new models of intrinsics, we expect the author to follow
213213
the above steps and provide comprehensive tests. It is important that
214-
the model author look carefully at both the Intel/ARM specification
214+
the model author looks carefully at both the Intel/ARM specifications
215215
and the Rust `stdarch` implementation, because they may look quite different
216216
from each other.
217217

0 commit comments

Comments
 (0)