Hi everyone,

I was recently trying to compiler few benchmarks from the
https://github.com/cornell-brg/xloops-bmarks using RISCV gcc compiler and
was trying to run them on gem5. There were few benchmarks in which gem5 was
showing unusual behaviour, reporting a page fault when there should be
none. I ran the riscv binary on spike and it worked fine. Then I tried
compiling the benchmark natively on x86 machine and ran it using valgrind
and didn’t find any issue. I was wondering is this a bug in the RISCV port
in gem5? I am compiling the following benchmark.

//========================================================================//
viterbi//========================================================================//
This application performs viterbi decoding on a frame of encoded data.
#include <cstring>#include <iostream>#include <iomanip>#include <vector>
//========================================================================//
viterbi 
dataset//========================================================================//
constraint length (number of memory registers)const int K = 7;//
number of symbol bits per input bitconst int rate = 2;// Dataset
parameters// size of data packetconst int framebits = 2048;//
generator polynomialsint polys[rate] = {121, 91};// size of bitpacked
data arraysconst int data_sz = framebits/8;unsigned char
data[((framebits + (K-1)) / 8) + 1];unsigned char
syms[rate*(framebits+(K-1))];unsigned char ref[(framebits+(K-1))/8+1];
namespace viterbi {namespace details {// constraint length (number of
memory registers)// implementation requires K <= 8const int K = 7;//
number of symbol bits per input bitconst int rate = 2;// number of
possible decoder statesconst int STATES (1 << (K-1));
}}
namespace viterbi {
  using namespace details;

  // Quickly generate a parity bit
  // see http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel

  //__attribute__ ((always_inline))
  int generate_symbol_bit_scalar(int x) {
    x ^= (x >> 16);
    x ^= (x >> 8);
    x ^= (x >> 4);
    x &= 0xf;
    return (0x6996 >> x) & 1;
  }

  // Viterbi Decoder: take encoded symbols and return the decoded msg
  void viterbi_scalar(unsigned char symbols[], unsigned char msg[],
                      int poly[], int framebits) {

    // Branch Table stores the state transitions, we only need to build
    // half thanks to trellace symmetry
    unsigned int branch_table[STATES/2 * rate];

    unsigned int* branch_table_ptr = &branch_table[0];
    //--------------------------------------------------------------------
    // Build Branch Lookup Table
    //--------------------------------------------------------------------

    for (int state = 0; state < STATES/2; state++) {
      for (int i = 0; i < rate; i ++) {
        int bit = generate_symbol_bit_scalar(2*state & poly[i]);
        branch_table[i*STATES/2 + state] = bit ? 255 : 0;
      }
    }

    // Two buffers to store the accumulated error for each state/path
    unsigned int error1[STATES];
    unsigned int error2[STATES];
    // Pointers to track which accumulated error buffer is most current,
    // pointer targets are swapped after each frame bit
    unsigned int * old_error = error1;
    unsigned int * new_error = error2;
    // Record the minimum error path entering each state for all framebits
    int traces[framebits+(K-1)][STATES];

    // Bias the accumulated error buffer towards the known start state
    error1[0] = 0;
    for(int i=1;i<STATES;i++)
      error1[i] = 63;

    //--------------------------------------------------------------------
    // Calculate Forward Paths
    //--------------------------------------------------------------------
    // For each frame bit, accumulate errors and determine path entering
    // states i & i+(STATES/2) (evaluate simultaneously using symmetry)

    for (int s = 0; s < framebits + (K-1); s++) {
      for (int i = 0; i < STATES/2; i++) {

        int decision0, decision1;
        unsigned int metric, m0, m1, m2, m3;
        metric = 0;

        // Compute the error metric for this state
        for (int j = 0; j < rate; j++)
          metric += branch_table_ptr[i+j*STATES/2] ^ symbols[s*rate+j];

        const unsigned int max = rate*(256 - 1);

        m0 = old_error[i] + metric;
        m1 = old_error[i+STATES/2] + (max - metric);
        m2 = old_error[i] + (max - metric);
        m3 = old_error[i+STATES/2] + metric;

        // Determine which transition is minimum
        decision0 = m0 > m1;
        decision1 = m2 > m3;

        // Save error for minimum transition
        new_error[2*i] =   decision0 ? m1 : m0;
        new_error[2*i+1] = decision1 ? m3 : m2;

        // Save transmission bit for minimum transition
        traces[s][2*i]   = decision0;
        traces[s][2*i+1] = decision1;
      }

      // Swap targets of old and new error buffers
      unsigned int * temp = old_error;
      old_error = new_error;
      new_error = temp;
    }

    //--------------------------------------------------------------------
    // Path Traceback
    //--------------------------------------------------------------------
    // Traceback through the path with the lowest error and generate
    // the decoded message based on the observed state transitions

    // Assume final state is 0
    unsigned int endstate = 0;
    unsigned int nbits = framebits;

    // Offset to only access the last framebits bits (ignore flush bits)
    int (* trace_ptr)[STATES] = traces+(K-1);

    // Traceback loop, densely pack the message bits
    while (nbits-- !=0) {
      int k = trace_ptr[nbits][endstate];
      endstate = (endstate >> 1) | (k << (K-2));
      msg[nbits>>3] >>= 1;
      msg[nbits>>3] |= (k << 7);
    }
  }

}
int main( int argc, char* argv[] )
{
    for ( int i = 0; i < ((framebits + (K-1)) / 8) + 1; i++ )
      data[i] = i;

    for ( int i = 0; i < rate*(framebits+(K-1)); i++ )
      syms[i] = i;

    for ( int i = 0; i < (framebits+(K-1))/8+1; i++ )
      ref[i] = i;

    unsigned char msg[(framebits + (K-1))/8 + 1] = {0};
    viterbi::viterbi_scalar(syms, msg, polys, framebits);
    return 0;
}

And running it using

% riscv64-unknown-elf-g++ viterbi.cc -o viterbi
% ./build/RISCV/gem5.debug --verbose  ./configs/example/se.py -c  ./viterbi

This gives me the following error and stack trace

0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000
info: Entering event queue @ 0.  Starting simulation...
**** REAL SIMULATION ****
panic: Page table fault when accessing virtual address 0x7ffffffffff7f400
Memory Usage: 793264 KBytes
Program aborted at tick 28870000
--- BEGIN LIBC BACKTRACE ---
./build/RISCV/gem5.debug(_Z15print_backtracev+0x1f)[0x14e4046]
./build/RISCV/gem5.debug(_Z12abortHandleri+0x5c)[0x14ef70b]
/lib64/libpthread.so.0(+0xf370)[0x7f69aacc7370]
/lib64/libc.so.6(gsignal+0x37)[0x7f69a98e61d7]
/lib64/libc.so.6(abort+0x148)[0x7f69a98e78c8]
./build/RISCV/gem5.debug(_ZN21GenericPageTableFault6invokeEP13ThreadContextRK14RefCountingPtrI10StaticInstE+0xa0)[0x15099c6]
./build/RISCV/gem5.debug(_ZN13BaseSimpleCPU9advancePCERKSt10shared_ptrI9FaultBaseE+0x139)[0x1306fab]
./build/RISCV/gem5.debug(_ZN15AtomicSimpleCPU4tickEv+0x925)[0x12f6b07]
./build/RISCV/gem5.debug[0x12f3d8d]
./build/RISCV/gem5.debug[0x12f6eb9]
./build/RISCV/gem5.debug(_ZNKSt8functionIFvvEEclEv+0x32)[0x12e80a0]
./build/RISCV/gem5.debug(_ZN20EventFunctionWrapper7processEv+0x1c)[0x12e705e]
./build/RISCV/gem5.debug(_ZN10EventQueue10serviceOneEv+0xda)[0x14ecfb2]
./build/RISCV/gem5.debug(_Z9doSimLoopP10EventQueue+0x1ef)[0x14f4e96]
./build/RISCV/gem5.debug(_Z8simulatem+0x2dc)[0x14f4b11]
./build/RISCV/gem5.debug(_ZN8pybind116detail15argument_loaderIJmEE9call_implIP22GlobalSimLoopExitEventRPFS5_mEJLm0EEEET_OT0_NS0_14index_sequenceIJXspT1_EEEE+0x3c)[0x1736d7c]
./build/RISCV/gem5.debug(_ZN8pybind116detail15argument_loaderIJmEE4callIP22GlobalSimLoopExitEventRPFS5_mEEENSt9enable_ifIXntsrSt7is_voidIT_E5valueESB_E4typeEOT0_+0x34)[0x1734c96]
./build/RISCV/gem5.debug(_ZZN8pybind1112cpp_function10initializeIRPFP22GlobalSimLoopExitEventmES3_JmEJNS_4nameENS_5scopeENS_7siblingENS_5arg_vEEEEvOT_PFT0_DpT1_EDpRKT2_ENKUlRNS_6detail13function_callEE1_clESO_+0x94)[0x1730c08]
./build/RISCV/gem5.debug(_ZZN8pybind1112cpp_function10initializeIRPFP22GlobalSimLoopExitEventmES3_JmEJNS_4nameENS_5scopeENS_7siblingENS_5arg_vEEEEvOT_PFT0_DpT1_EDpRKT2_ENUlRNS_6detail13function_callEE1_4_FUNESO_+0x1d)[0x1730c5b]
./build/RISCV/gem5.debug(_ZN8pybind1112cpp_function10dispatcherEP7_objectS2_S2_+0x9a3)[0x16d7466]
./build/RISCV/gem5.debug(PyEval_EvalFrameEx+0x7d42)[0x205dd52]
./build/RISCV/gem5.debug(PyEval_EvalCodeEx+0x89c)[0x205f5ec]
./build/RISCV/gem5.debug(PyEval_EvalFrameEx+0x7131)[0x205d141]
./build/RISCV/gem5.debug(PyEval_EvalFrameEx+0x7245)[0x205d255]
./build/RISCV/gem5.debug(PyEval_EvalFrameEx+0x7245)[0x205d255]
./build/RISCV/gem5.debug(PyEval_EvalCodeEx+0x89c)[0x205f5ec]
./build/RISCV/gem5.debug(PyEval_EvalFrameEx+0x5f2a)[0x205bf3a]
./build/RISCV/gem5.debug(PyEval_EvalCodeEx+0x89c)[0x205f5ec]
./build/RISCV/gem5.debug(PyEval_EvalFrameEx+0x7131)[0x205d141]
./build/RISCV/gem5.debug(PyEval_EvalCodeEx+0x89c)[0x205f5ec]
./build/RISCV/gem5.debug(PyEval_EvalCode+0x19)[0x205f6d9]
./build/RISCV/gem5.debug(PyRun_StringFlags+0xf5)[0x2087c25]
--- END LIBC BACKTRACE ---

Thanks,

Best Regards,
Nitish

‌
​
_______________________________________________
gem5-users mailing list
[email protected]
http://m5sim.org/cgi-bin/mailman/listinfo/gem5-users

Reply via email to