Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions hw/ip/otbn/doc/developing_otbn.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,5 @@ command-line use otherwise.
## Test the ISS

The ISS has a simple test suite, which runs various instructions and
makes sure they behave as expected. You can find the tests in
`dv/otbnsim/test` and can run them with `make -C dv/otbnsim test`.
makes sure they behave as expected.
See the [simulator page](../dv/otbnsim/README.md) for more details.
95 changes: 90 additions & 5 deletions hw/ip/otbn/doc/isa.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,98 @@ def logical_byte_shift(value: int, shift_type: int, shift_bytes: int) -> int:
shifted = value << shift_bits if shift_type == 0 else value >> shift_bits
return shifted & mask256

def extract_quarter_word(value: int, qwsel: int) -> int:
'''Extract a 64-bit quarter word from a 256-bit value.'''
def shift_vec_elem(value: int, size: int, shift_type: int, shift_bits: int) -> int:
'''Performs a logical bit shift on an unsigned integer confined to the given bit width.

With shift_type = 0, the value is shifted left by shift_bits; with shift_type = 1,
the value is shifted right by shift_bits.

The resulting shifted value is truncated to size bits.
'''
maskSize = (1 << size) - 1
assert 0 <= value <= maskSize
assert 0 <= shift_type <= 1
assert 0 <= shift_bits

if shift_type == 0:
result = (value << shift_bits) & maskSize
else:
result = (value >> shift_bits) & maskSize

return result

def extract_vec_elem(value: int, elem: int, size: int) -> int:
'''Returns the elem-th vector element from a 256-bit vector of size-bit elements interpreted as
unsigned integer.
'''
assert 0 <= value < (1 << 256)
assert 0 <= qwsel <= 3
return (value >> (qwsel * 64)) & ((1 << 64) - 1)
assert 0 <= elem < (256 // size)
return (value >> (elem * size)) & ((1 << size) - 1)

TODO Add new helpers for SIMD instructions once the simulator implementation exists.
def extract_quarter_word(value: int, qwsel: int) -> int:
'''Extracts a 64-bit quarter word from a 256-bit value.'''
assert 0 <= qwsel <= 3
return extract_vec_elem(value, qwsel, 64)

def lower_d_bits(value: int, d: int) -> int:
'''Extracts the lower d bits of the value.'''
assert 0 <= d
assert 0 <= value
return value & ((1 << d) - 1)

def upper_d_bits(value: int, d: int) -> int:
'''Extracts the upper d bits of the value and shifts them down by d.'''
assert 0 <= d
assert 0 <= value
return lower_d_bits(value >> d, d)

def element_length_in_bits(elen: int) -> int:
'''Returns the corresponding bit width for a given ELEN encoding.

Encoding | ELEN | Size in bits
0 | .8s | 32
1 | .4d | 64
2 | .2q | 128
'''
assert 0 <= elen <= 2
return 32 * (1 << elen)

def map_elems(op: Callable[[int, int], int], size: int, vec_a: int, vec_b: int) -> int:
'''Applies the operation op to each pair of elements for the given element size.

The vectors are expected to be 256-bit numbers where the elements are extracted from.
The op function takes two vector elements, performs the desired operation and is expected to
return a non-negative value.

The results are concatenated and returned as a 256-bit number.'''
result = 0
for elem in range(256 // size):
elem_a = extract_vec_elem(vec_a, elem, size)
elem_b = extract_vec_elem(vec_b, elem, size)

elem_c = op(elem_a, elem_b)
elem_c = elem_c & ((1 << size) - 1)
result |= elem_c << (elem * size)
return result

def montgomery_mul_no_cond_subtraction(a: int, b: int, q: int, mu: int, size: int) -> int:
'''Performs a Montgomery multiplication but without the final conditional subtraction.

The inputs a and b are in Montgomery space.
The result is also in Montgomery space.

Algorithm (where []_d are the lower d bits, []^d are the higher d bits):
r = [c + [[c]_d * mu]_d * q]^d
# Skipped conditional subtraction step:
# if r >= q:
# r -= q
return r
'''
reg_c = a * b
reg_tmp = lower_d_bits(reg_c, size)
reg_tmp = lower_d_bits(reg_tmp * mu, size)
r = upper_d_bits(reg_c + reg_tmp * q, size)
return r
```

# Errors
Expand Down
6 changes: 6 additions & 0 deletions hw/ip/otbn/dv/otbnsim/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ Trace entries from the simulated core (aka. from RTL) appear as a result of DPI
To check correct behaviour, the two separate logs generated by the model and the RTL are compared.
For more information about how OTBN RTL produces traces see the [Tracer README](../tracer/README.md).
To see the C++ program that compares both traces, check the method `otbn_trace_checker.cc` in `../model/otbn_trace_entry`.

## Testing the simulator
There is a simple test suite to check the simulator implementation.
It tests diverse instruction as defined by the tests in `./test/simple/` as well as some autogenerated tests for the bignum SIMD extension (see `generate_bn_simd_test.py`).

All test can be run with `make test` (which also generates the SIMD tests) and a single test can be run using `pytest -vv -k <testname>.s`.
Loading