[libre-riscv-dev] spike-sv non-default element widths

lkcl lkcl at libre-riscv.org
Thu Oct 11 09:49:34 BST 2018

On Thu, Oct 11, 2018 at 8:30 AM Jacob Lifshay <programmerjake at gmail.com> wrote:
> On Thu, Oct 11, 2018 at 12:09 AM lkcl <lkcl at libre-riscv.org> wrote:

> > https://git.libre-riscv.org/?p=riscv-isa-sim.git;a=blob;f=operators/operators.t.cc;h=b5ac0185adba82ad8424401a50807f63ecb383ea;hb=c3d43aa1e221c74936adac7673f1923cbec5fdd0
> >
> >  ok so for all possible int8_t values 0-255 on +-*/% >> << when first
> > typecast to uint8_t into a uint16_t, a uint16_t answer is correct
> >
> >             int8_t x=0, y=0;
> >             int16_t x1, y1;
> >             int8_t z = x op y;
> >             x1 = (uint8_t)x;
> >             y1 = (uint8_t)y;
> >             uint16_t z1 = x1 op y1;
> >
> > all answers match.
> >
> Actually, it doesn't work.

 there's no failures, and that's what i'm looking for.  all three of
the following produce success:

 #define operator_check( op ) { \
            uint64_t z = (int8_t)(x op y);                    \
            x1 = (uint8_t)x;                                  \
            y1 = (uint8_t)y;                                  \

#define operator_check( op ) { \
            int8_t z = (int8_t)(x op y);                       \
            x1 = (uint8_t)x;                                  \
            y1 = (uint8_t)y;                                  \
            uint16_t z1 = x1 op y1;                           \

#define operator_check( op ) { \
            auto z = (int8_t)(x op y);                       \
            x1 = (uint8_t)x;                                  \
            y1 = (uint8_t)y;                                  \
            uint16_t z1 = x1 op y1;                           \

all of those never produce the word "FAILED" for all x in range 0-255
for all y in range 0-255 for all operands plus, minus, mul, div,
remainder (modulo), shiftleft and shiftright.

> The reason is that C/C++ specifies everything
> smaller than int is promoted to int before the arithmetic is done, so to
> check properly you would need to cast the result of each operation to the
> type the operation was supposed to be done in. Like:
> int8_t x, y;
> auto z = (int8_t)(x * y);
> Since Rust doesn't cast between integer types unless you explicitly tell it
> to, it may be a more appropriate language for testing out
> arithmetical/logical operations.

 the goal is to fool spike into doing the correct arithmetic operation
yet still have all integer operands stored in uint64_t, and to not
have to modify the riscv/insns/*.h files - at all - in the process of
getting the *exact* same *.h files to produce the correct answers - at
runtime - on dynamic changing of bitwidths.

 hence, if the c++ upcasts to an int, internally, it genuinely doesn't
matter *as long as the answer is correct*.

 so, making absolutely sure that the c++ compiler is generating the
right answers to test is clearly absolutely essential.

 can you see anything wrong with the test code, that it might be
producing the wrong answers at line 19?


> I tried to translate what I think you intended in your code snippet to rust
> which you can view the output generated on Compiler Explorer:
> https://rust.godbolt.org/z/ydX-JH

 appreciated... however taking that route would ultimately mean having
an external call-out from spike (c++) to a rust math library, as the
code, once tested (in rust) would then need to be used... in spike.

 unless completely rewriting a new simulator entirely from scratch in
rust.  at 16,000 lines of code i'm not keen on doing that, as it would
require abandoning the hugely-tested spike codebase.


More information about the libre-riscv-dev mailing list