difftest.h 7.4 KB
Newer Older
L
Lemover 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/***************************************************************************************
* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
*
* XiangShan is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*          http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*
* See the Mulan PSL v2 for more details.
***************************************************************************************/

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#ifndef __DIFFTEST_H__
#define __DIFFTEST_H__

#include "common.h"

#include "nemuproxy.h"
#define DIFF_PROXY NemuProxy

#define DIFFTEST_CORE_NUMBER  EMU_CORES
#define DIFFTEST_COMMIT_WIDTH 6
#define DIFFTEST_STORE_WIDTH  2
#define DIFFTEST_LOAD_WIDTH   6

#define DIFFTEST_STORE_COMMIT



// Difftest structures
// trap events: self-defined traps
typedef struct {
  uint8_t  valid = 0;
  uint8_t  code;
  uint64_t pc;
39 40
  uint64_t cycleCnt = 0;
  uint64_t instrCnt = 0;
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
} trap_event_t;

// architectural events: interrupts and exceptions
// whose priority should be higher than normal commits
typedef struct {
  uint32_t interrupt = 0;
  uint32_t exception = 0;
  uint64_t exceptionPC = 0;
} arch_event_t;

typedef struct {
  uint8_t  valid = 0;
  uint64_t pc;
  uint32_t inst;
  uint8_t  skip;
  uint8_t  isRVC;
  uint8_t  scFailed;
  uint8_t  wen;
  uint8_t  wdest;
  uint64_t wdata;
} instr_commit_t;

typedef struct {
  uint64_t gpr[32];
  uint64_t fpr[32];
} arch_reg_state_t;

typedef struct __attribute__((packed)) {
  uint64_t this_pc;
  uint64_t mstatus;
  uint64_t mcause;
  uint64_t mepc;
  uint64_t sstatus;
  uint64_t scause;
  uint64_t sepc;
  uint64_t satp;
  uint64_t mip;
  uint64_t mie;
  uint64_t mscratch;
  uint64_t sscratch;
  uint64_t mideleg;
  uint64_t medeleg;
  uint64_t mtval;
  uint64_t stval;
  uint64_t mtvec;
  uint64_t stvec;
  uint64_t priviledgeMode;
} arch_csr_state_t;

const int DIFFTEST_NR_REG = (sizeof(arch_reg_state_t) + sizeof(arch_csr_state_t)) / sizeof(uint64_t);

typedef struct {
  uint8_t  resp = 0;
  uint64_t addr;
  uint8_t  data[64];
  uint64_t mask;
} sbuffer_state_t;

typedef struct {
  uint8_t  valid = 0;
  uint64_t addr;
  uint64_t data;
  uint8_t  mask;
} store_event_t;

typedef struct {
  uint8_t  valid = 0;
  uint64_t paddr;
  uint8_t  fuType;
  uint8_t  opType;
} load_event_t;

typedef struct {
  uint8_t  resp = 0;
  uint64_t addr;
  uint64_t data;
  uint8_t  mask;
  uint8_t  fuop;
  uint64_t out;
} atomic_event_t;

typedef struct {
  uint8_t  resp = 0;
  uint64_t addr;
  uint64_t data[4];
} ptw_event_t;

typedef struct {
  trap_event_t     trap;
  arch_event_t     event;
  instr_commit_t   commit[DIFFTEST_COMMIT_WIDTH];
  arch_reg_state_t regs;
  arch_csr_state_t csr;
  sbuffer_state_t  sbuffer;
  store_event_t    store[DIFFTEST_STORE_WIDTH];
  load_event_t     load[DIFFTEST_LOAD_WIDTH];
  atomic_event_t   atomic;
  ptw_event_t      ptw;
} difftest_core_state_t;

enum retire_inst_type {
  RET_NORMAL=0,
  RET_INT,
  RET_EXC
};

class DiffState {
public:
  DiffState(int history_length = 32);
  void record_group(uint64_t pc, uint64_t count) {
    retire_group_pc_queue [retire_group_pointer] = pc;
    retire_group_cnt_queue[retire_group_pointer] = count;
    retire_group_pointer = (retire_group_pointer + 1) % DEBUG_GROUP_TRACE_SIZE;
  };
155
  void record_inst(uint64_t pc, uint32_t inst, uint8_t en, uint8_t dest, uint64_t data) {
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
    retire_inst_pc_queue   [retire_inst_pointer] = pc;
    retire_inst_inst_queue [retire_inst_pointer] = inst;
    retire_inst_wen_queue  [retire_inst_pointer] = en;
    retire_inst_wdst_queue [retire_inst_pointer] = dest;
    retire_inst_wdata_queue[retire_inst_pointer] = data;
    retire_inst_type_queue[retire_inst_pointer] = RET_NORMAL;
    retire_inst_pointer = (retire_inst_pointer + 1) % DEBUG_INST_TRACE_SIZE;
  };
  void record_abnormal_inst(uint64_t pc, uint32_t inst, uint32_t abnormal_type, uint64_t cause) {
    retire_inst_pc_queue   [retire_inst_pointer] = pc;
    retire_inst_inst_queue [retire_inst_pointer] = inst;
    retire_inst_wdata_queue[retire_inst_pointer] = cause; // write cause to data queue to save space
    retire_inst_type_queue[retire_inst_pointer] = abnormal_type;
    retire_inst_pointer = (retire_inst_pointer + 1) % DEBUG_INST_TRACE_SIZE;
  };
W
wakafa 已提交
171
  void display(int coreid);
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195

private:
  const static size_t DEBUG_GROUP_TRACE_SIZE = 16;
  const static size_t DEBUG_INST_TRACE_SIZE = 16;

  int retire_group_pointer = 0;
  uint64_t retire_group_pc_queue[DEBUG_GROUP_TRACE_SIZE] = {0};
  uint32_t retire_group_cnt_queue[DEBUG_GROUP_TRACE_SIZE] = {0};

  int retire_inst_pointer = 0;
  uint64_t retire_inst_pc_queue[DEBUG_INST_TRACE_SIZE] = {0};
  uint32_t retire_inst_inst_queue[DEBUG_INST_TRACE_SIZE] = {0};
  uint64_t retire_inst_wen_queue[DEBUG_INST_TRACE_SIZE] = {0};
  uint32_t retire_inst_wdst_queue[DEBUG_INST_TRACE_SIZE] = {0};
  uint64_t retire_inst_wdata_queue[DEBUG_INST_TRACE_SIZE] = {0};
  uint32_t retire_inst_type_queue[DEBUG_INST_TRACE_SIZE] = {0};
};

class Difftest {
public:
  // Difftest public APIs for testbench
  // Its backend should be cross-platform (NEMU, Spike, ...)
  // Initialize difftest environments
  Difftest(int coreid);
W
wakafa 已提交
196
  DIFF_PROXY *proxy;
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
  uint32_t num_commit = 0; // # of commits if made progress
  // Trigger a difftest checking procdure
  int step();
  inline bool get_trap_valid() {
    return dut.trap.valid;
  }
  inline int get_trap_code() {
    return dut.trap.code;
  }
  void display();

  // Difftest public APIs for dut: called from DPI-C functions (or testbench)
  // These functions generally do nothing but copy the information to core_state.
  inline trap_event_t *get_trap_event() {
    return &(dut.trap);
  }
  inline arch_event_t *get_arch_event() {
    return &(dut.event);
  }
  inline instr_commit_t *get_instr_commit(uint8_t index) {
    return &(dut.commit[index]);
  }
  inline arch_csr_state_t *get_csr_state() {
    return &(dut.csr);
  }
  inline arch_reg_state_t *get_arch_reg_state() {
    return &(dut.regs);
  }
  inline sbuffer_state_t *get_sbuffer_state() {
    return &(dut.sbuffer);
  }
  inline store_event_t *get_store_event(uint8_t index) {
    return &(dut.store[index]);
  }
  inline load_event_t *get_load_event(uint8_t index) {
    return &(dut.load[index]);
  }
  inline atomic_event_t *get_atomic_event() {
    return &(dut.atomic);
  }
  inline ptw_event_t *get_ptw_event() {
    return &(dut.ptw);
  }

private:
  const uint64_t firstCommit_limit = 5000;
  const uint64_t stuck_limit = 5000;

  int id;
  difftest_core_state_t dut;
  difftest_core_state_t ref;
  uint64_t *ref_regs_ptr = (uint64_t*)&ref.regs;
  uint64_t *dut_regs_ptr = (uint64_t*)&dut.regs;

  bool progress = false;
  bool has_commit = false;
  uint64_t ticks = 0;
  uint64_t last_commit = 0;


  uint64_t nemu_this_pc;
  DiffState *state;

  int check_timeout();
  void do_first_instr_commit();
  void do_interrupt();
  void do_exception();
  void do_instr_commit(int index);
  int do_store_check();
W
wakafa 已提交
266
  int do_golden_memory_update();
267 268 269 270 271 272 273 274 275 276 277 278 279
  // inline uint64_t *ref_regs_ptr() { return (uint64_t*)&ref.regs; }
  // inline uint64_t *dut_regs_ptr() { return (uint64_t*)&dut.regs; }

  void raise_trap(int trapCode);
  void clear_step();
};

extern Difftest **difftest;
int difftest_init();
int difftest_step();
int difftest_state();

#endif