Generic RISC-V ISS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1349 lines
52 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. /*******************************************************************************
  2. * Copyright (C) 2017, MINRES Technologies GmbH
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * 3. Neither the name of the copyright holder nor the names of its contributors
  16. * may be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  23. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. * POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * Contributors:
  32. * eyck@minres.com - initial implementation
  33. ******************************************************************************/
  34. #ifndef _RISCV_CORE_H_
  35. #define _RISCV_CORE_H_
  36. #include "iss/arch/traits.h"
  37. #include "iss/arch_if.h"
  38. #include "iss/log_categories.h"
  39. #include "iss/vm_if.h"
  40. #include "iss/instrumentation_if.h"
  41. #include <elfio/elfio.hpp>
  42. #include <iomanip>
  43. #include <sstream>
  44. #include <unordered_map>
  45. #include <util/ities.h>
  46. #include <util/sparse_array.h>
  47. #include <util/bit_field.h>
  48. #include <array>
  49. #include <type_traits>
  50. #define likely(x) __builtin_expect(!!(x), 1)
  51. #define unlikely(x) __builtin_expect(!!(x), 0)
  52. namespace iss {
  53. namespace arch {
  54. enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 };
  55. enum riscv_csr {
  56. /* user-level CSR */
  57. // User Trap Setup
  58. ustatus = 0x000,
  59. uie = 0x004,
  60. utvec = 0x005,
  61. // User Trap Handling
  62. uscratch = 0x040,
  63. uepc = 0x041,
  64. ucause = 0x042,
  65. utval = 0x043,
  66. uip = 0x044,
  67. // User Floating-Point CSRs
  68. fflags = 0x001,
  69. frm = 0x002,
  70. fcsr = 0x003,
  71. // User Counter/Timers
  72. cycle = 0xC00,
  73. time = 0xC01,
  74. instret = 0xC02,
  75. hpmcounter3 = 0xC03,
  76. hpmcounter4 = 0xC04,
  77. /*...*/
  78. hpmcounter31 = 0xC1F,
  79. cycleh = 0xC80,
  80. timeh = 0xC81,
  81. instreth = 0xC82,
  82. hpmcounter3h = 0xC83,
  83. hpmcounter4h = 0xC84,
  84. /*...*/
  85. hpmcounter31h = 0xC9F,
  86. /* supervisor-level CSR */
  87. // Supervisor Trap Setup
  88. sstatus = 0x100,
  89. sedeleg = 0x102,
  90. sideleg = 0x103,
  91. sie = 0x104,
  92. stvec = 0x105,
  93. scounteren = 0x106,
  94. // Supervisor Trap Handling
  95. sscratch = 0x140,
  96. sepc = 0x141,
  97. scause = 0x142,
  98. stval = 0x143,
  99. sip = 0x144,
  100. // Supervisor Protection and Translation
  101. satp = 0x180,
  102. /* machine-level CSR */
  103. // Machine Information Registers
  104. mvendorid = 0xF11,
  105. marchid = 0xF12,
  106. mimpid = 0xF13,
  107. mhartid = 0xF14,
  108. // Machine Trap Setup
  109. mstatus = 0x300,
  110. misa = 0x301,
  111. medeleg = 0x302,
  112. mideleg = 0x303,
  113. mie = 0x304,
  114. mtvec = 0x305,
  115. mcounteren = 0x306,
  116. // Machine Trap Handling
  117. mscratch = 0x340,
  118. mepc = 0x341,
  119. mcause = 0x342,
  120. mtval = 0x343,
  121. mip = 0x344,
  122. // Machine Protection and Translation
  123. pmpcfg0 = 0x3A0,
  124. pmpcfg1 = 0x3A1,
  125. pmpcfg2 = 0x3A2,
  126. pmpcfg3 = 0x3A3,
  127. pmpaddr0 = 0x3B0,
  128. pmpaddr1 = 0x3B1,
  129. /*...*/
  130. pmpaddr15 = 0x3BF,
  131. // Machine Counter/Timers
  132. mcycle = 0xB00,
  133. minstret = 0xB02,
  134. mhpmcounter3 = 0xB03,
  135. mhpmcounter4 = 0xB04,
  136. /*...*/
  137. mhpmcounter31 = 0xB1F,
  138. mcycleh = 0xB80,
  139. minstreth = 0xB82,
  140. mhpmcounter3h = 0xB83,
  141. mhpmcounter4h = 0xB84,
  142. /*...*/
  143. mhpmcounter31h = 0xB9F,
  144. // Machine Counter Setup
  145. mhpmevent3 = 0x323,
  146. mhpmevent4 = 0x324,
  147. /*...*/
  148. mhpmevent31 = 0x33F,
  149. // Debug/Trace Registers (shared with Debug Mode)
  150. tselect = 0x7A0,
  151. tdata1 = 0x7A1,
  152. tdata2 = 0x7A2,
  153. tdata3 = 0x7A3,
  154. // Debug Mode Registers
  155. dcsr = 0x7B0,
  156. dpc = 0x7B1,
  157. dscratch = 0x7B2
  158. };
  159. namespace {
  160. std::array<const char, 4> lvl = { { 'U', 'S', 'H', 'M' } };
  161. std::array<const char*, 16> trap_str = { { ""
  162. "Instruction address misaligned", //0
  163. "Instruction access fault", //1
  164. "Illegal instruction", //2
  165. "Breakpoint", //3
  166. "Load address misaligned", //4
  167. "Load access fault", //5
  168. "Store/AMO address misaligned", //6
  169. "Store/AMO access fault", //7
  170. "Environment call from U-mode", //8
  171. "Environment call from S-mode", //9
  172. "Reserved", //a
  173. "Environment call from M-mode", //b
  174. "Instruction page fault", //c
  175. "Load page fault", //d
  176. "Reserved", //e
  177. "Store/AMO page fault" } };
  178. std::array<const char*, 12> irq_str = { {
  179. "User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt",
  180. "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", "User external interrupt",
  181. "Supervisor external interrupt", "Reserved", "Machine external interrupt" } };
  182. enum {
  183. PGSHIFT = 12,
  184. PTE_PPN_SHIFT = 10,
  185. // page table entry (PTE) fields
  186. PTE_V = 0x001, // Valid
  187. PTE_R = 0x002, // Read
  188. PTE_W = 0x004, // Write
  189. PTE_X = 0x008, // Execute
  190. PTE_U = 0x010, // User
  191. PTE_G = 0x020, // Global
  192. PTE_A = 0x040, // Accessed
  193. PTE_D = 0x080, // Dirty
  194. PTE_SOFT = 0x300 // Reserved for Software
  195. };
  196. template <typename T> inline bool PTE_TABLE(T PTE) { return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); }
  197. enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3 };
  198. enum {
  199. ISA_A = 1,
  200. ISA_B = 1 << 1,
  201. ISA_C = 1 << 2,
  202. ISA_D = 1 << 3,
  203. ISA_E = 1 << 4,
  204. ISA_F = 1 << 5,
  205. ISA_G = 1 << 6,
  206. ISA_I = 1 << 8,
  207. ISA_M = 1 << 12,
  208. ISA_N = 1 << 13,
  209. ISA_Q = 1 << 16,
  210. ISA_S = 1 << 18,
  211. ISA_U = 1 << 20
  212. };
  213. struct vm_info {
  214. int levels;
  215. int idxbits;
  216. int ptesize;
  217. uint64_t ptbase;
  218. bool is_active() { return levels;}
  219. };
  220. class trap_load_access_fault : public trap_access {
  221. public:
  222. trap_load_access_fault(uint64_t badaddr)
  223. : trap_access(5 << 16, badaddr) {}
  224. };
  225. class illegal_instruction_fault : public trap_access {
  226. public:
  227. illegal_instruction_fault(uint64_t badaddr)
  228. : trap_access(2 << 16, badaddr) {}
  229. };
  230. class trap_instruction_page_fault : public trap_access {
  231. public:
  232. trap_instruction_page_fault(uint64_t badaddr)
  233. : trap_access(12 << 16, badaddr) {}
  234. };
  235. class trap_load_page_fault : public trap_access {
  236. public:
  237. trap_load_page_fault(uint64_t badaddr)
  238. : trap_access(13 << 16, badaddr) {}
  239. };
  240. class trap_store_page_fault : public trap_access {
  241. public:
  242. trap_store_page_fault(uint64_t badaddr)
  243. : trap_access(15 << 16, badaddr) {}
  244. };
  245. }
  246. template <typename BASE> class riscv_hart_msu_vp : public BASE {
  247. public:
  248. using super = BASE;
  249. using this_class = riscv_hart_msu_vp<BASE>;
  250. using virt_addr_t = typename super::virt_addr_t;
  251. using phys_addr_t = typename super::phys_addr_t;
  252. using reg_t = typename super::reg_t;
  253. using addr_t = typename super::addr_t;
  254. using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &);
  255. using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t);
  256. // primary template
  257. template<class T, class Enable = void> struct hart_state { };
  258. // specialization 32bit
  259. template <typename T>
  260. class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
  261. public:
  262. BEGIN_BF_DECL(mstatus_t, T);
  263. // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11)))
  264. BF_FIELD(SD, 31, 1);
  265. // Trap SRET
  266. BF_FIELD(TSR, 22, 1);
  267. // Timeout Wait
  268. BF_FIELD(TW, 21, 1);
  269. // Trap Virtual Memory
  270. BF_FIELD(TVM, 20, 1);
  271. // Make eXecutable Readable
  272. BF_FIELD(MXR, 19, 1);
  273. // permit Supervisor User Memory access
  274. BF_FIELD(SUM, 18, 1);
  275. // Modify PRiVilege
  276. BF_FIELD(MPRV, 17, 1);
  277. // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty
  278. BF_FIELD(XS, 15, 2);
  279. // floating-point unit status Off/Initial/Clean/Dirty
  280. BF_FIELD(FS, 13, 2);
  281. // machine previous privilege
  282. BF_FIELD(MPP, 11, 2);
  283. // supervisor previous privilege
  284. BF_FIELD(SPP, 8, 1);
  285. // previous machine interrupt-enable
  286. BF_FIELD(MPIE, 7, 1);
  287. // previous supervisor interrupt-enable
  288. BF_FIELD(SPIE, 5, 1);
  289. // previous user interrupt-enable
  290. BF_FIELD(UPIE, 4, 1);
  291. // machine interrupt-enable
  292. BF_FIELD(MIE, 3, 1);
  293. // supervisor interrupt-enable
  294. BF_FIELD(SIE, 1, 1);
  295. // user interrupt-enable
  296. BF_FIELD(UIE, 0, 1);
  297. END_BF_DECL();
  298. mstatus_t mstatus;
  299. static const reg_t mstatus_reset_val = 0;
  300. void write_mstatus(T val, unsigned priv_lvl){
  301. auto mask = get_mask(priv_lvl);
  302. auto new_val = (mstatus.st.value & ~mask) | (val & mask);
  303. mstatus=new_val;
  304. }
  305. T satp;
  306. static constexpr T get_misa() { return (1UL << 30) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; }
  307. static constexpr uint32_t get_mask(unsigned priv_lvl) {
  308. switch (priv_lvl) {
  309. case PRIV_U: return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001
  310. case PRIV_S: return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011
  311. default: return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011
  312. }
  313. }
  314. static inline vm_info decode_vm_info(uint32_t state, T sptbr) {
  315. if (state == PRIV_M) return {0, 0, 0, 0};
  316. if (state <= PRIV_S)
  317. switch (bit_sub<31, 1>(sptbr)) {
  318. case 0: return {0, 0, 0, 0}; // off
  319. case 1: return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32
  320. default: abort();
  321. }
  322. abort();
  323. return {0, 0, 0, 0}; // dummy
  324. }
  325. };
  326. // specialization 64bit
  327. template <typename T>
  328. class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
  329. public:
  330. BEGIN_BF_DECL(mstatus_t, T);
  331. // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11)))
  332. BF_FIELD(SD, 63, 1);
  333. // value of XLEN for S-mode
  334. BF_FIELD(SXL, 34, 2);
  335. // value of XLEN for U-mode
  336. BF_FIELD(UXL, 32, 2);
  337. // Trap SRET
  338. BF_FIELD(TSR, 22, 1);
  339. // Timeout Wait
  340. BF_FIELD(TW, 21, 1);
  341. // Trap Virtual Memory
  342. BF_FIELD(TVM, 20, 1);
  343. // Make eXecutable Readable
  344. BF_FIELD(MXR, 19, 1);
  345. // permit Supervisor User Memory access
  346. BF_FIELD(SUM, 18, 1);
  347. // Modify PRiVilege
  348. BF_FIELD(MPRV, 17, 1);
  349. // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty
  350. BF_FIELD(XS, 15, 2);
  351. // floating-point unit status Off/Initial/Clean/Dirty
  352. BF_FIELD(FS, 13, 2);
  353. // machine previous privilege
  354. BF_FIELD(MPP, 11, 2);
  355. // supervisor previous privilege
  356. BF_FIELD(SPP, 8, 1);
  357. // previous machine interrupt-enable
  358. BF_FIELD(MPIE, 7, 1);
  359. // previous supervisor interrupt-enable
  360. BF_FIELD(SPIE, 5, 1);
  361. // previous user interrupt-enable
  362. BF_FIELD(UPIE, 4, 1);
  363. // machine interrupt-enable
  364. BF_FIELD(MIE, 3, 1);
  365. // supervisor interrupt-enable
  366. BF_FIELD(SIE, 1, 1);
  367. // user interrupt-enable
  368. BF_FIELD(UIE, 0, 1);
  369. END_BF_DECL();
  370. mstatus_t mstatus;
  371. static const reg_t mstatus_reset_val = 0xa00000000;
  372. void write_mstatus(T val, unsigned priv_lvl){
  373. T old_val = mstatus;
  374. auto mask = get_mask(priv_lvl);
  375. auto new_val = (old_val & ~mask) | (val & mask);
  376. if((new_val&mstatus.SXL.Mask)==0){
  377. new_val |= old_val&mstatus.SXL.Mask;
  378. }
  379. if((new_val&mstatus.UXL.Mask)==0){
  380. new_val |= old_val&mstatus.UXL.Mask;
  381. }
  382. mstatus=new_val;
  383. }
  384. T satp;
  385. static constexpr T get_misa() { return (2ULL << 62) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; }
  386. static constexpr T get_mask(unsigned priv_lvl) {
  387. switch (priv_lvl) {
  388. case PRIV_U: return 0x8000000f00000011ULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
  389. case PRIV_S: return 0x8000000f000de133ULL; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011
  390. default: return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
  391. }
  392. }
  393. static inline vm_info decode_vm_info(uint32_t state, T sptbr) {
  394. if (state == PRIV_M) return {0, 0, 0, 0};
  395. if (state <= PRIV_S)
  396. switch (bit_sub<60, 4>(sptbr)) {
  397. case 0: return {0, 0, 0, 0}; // off
  398. case 8: return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV39
  399. case 9: return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV48
  400. case 10: return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV57
  401. case 11: return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV64
  402. default: abort();
  403. }
  404. abort();
  405. return {0, 0, 0, 0}; // dummy
  406. }
  407. };
  408. const typename super::reg_t PGSIZE = 1 << PGSHIFT;
  409. const typename super::reg_t PGMASK = PGSIZE - 1;
  410. constexpr reg_t get_irq_mask(size_t mode) {
  411. std::array<const reg_t,4> m = { {
  412. 0b000100010001,// U mode
  413. 0b001100110011,// S mode
  414. 0,
  415. 0b101110111011 // M mode
  416. }};
  417. return m[mode];
  418. }
  419. riscv_hart_msu_vp();
  420. virtual ~riscv_hart_msu_vp() = default;
  421. void reset(uint64_t address) override;
  422. std::pair<uint64_t,bool> load_file(std::string name, int type = -1) override;
  423. virtual phys_addr_t virt2phys(const iss::addr_t &addr) override;
  424. iss::status read(const iss::addr_t &addr, unsigned length, uint8_t *const data) override;
  425. iss::status write(const iss::addr_t &addr, unsigned length, const uint8_t *const data) override;
  426. virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data); }
  427. virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override;
  428. virtual uint64_t leave_trap(uint64_t flags) override;
  429. void wait_until(uint64_t flags) override;
  430. void disass_output(uint64_t pc, const std::string instr) override {
  431. std::stringstream s;
  432. s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0')
  433. << std::setw(sizeof(reg_t) * 2) << (reg_t)state.mstatus << std::dec << ";c:" << this->reg.icount << "]";
  434. CLOG(INFO, disass) << "0x"<<std::setw(16)<<std::setfill('0')<<std::hex<<pc<<"\t\t"<<instr<<"\t"<<s.str();
  435. };
  436. iss::instrumentation_if* get_instrumentation_if() override {return &instr_if;}
  437. protected:
  438. struct riscv_instrumentation_if : public iss::instrumentation_if{
  439. riscv_instrumentation_if(riscv_hart_msu_vp<BASE>& arch):arch(arch){}
  440. /**
  441. * get the name of this architecture
  442. *
  443. * @return the name of this architecture
  444. */
  445. const std::string core_type_name() const override {return traits<BASE>::core_type;}
  446. virtual uint64_t get_pc(){ return arch.get_pc(); };
  447. virtual uint64_t get_next_pc(){ return arch.get_next_pc(); };
  448. virtual void set_curr_instr_cycles(unsigned cycles){ arch.cycle_offset+=cycles-1; };
  449. riscv_hart_msu_vp<BASE>& arch;
  450. };
  451. friend struct riscv_instrumentation_if;
  452. addr_t get_pc(){return this->reg.PC;}
  453. addr_t get_next_pc(){return this->reg.NEXT_PC;}
  454. virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data);
  455. virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data);
  456. virtual iss::status read_csr(unsigned addr, reg_t &val);
  457. virtual iss::status write_csr(unsigned addr, reg_t val);
  458. hart_state<reg_t> state;
  459. uint64_t cycle_offset;
  460. reg_t fault_data;
  461. std::array<vm_info,2> vm;
  462. uint64_t tohost = tohost_dflt;
  463. uint64_t fromhost = fromhost_dflt;
  464. unsigned to_host_wr_cnt = 0;
  465. riscv_instrumentation_if instr_if;
  466. using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
  467. using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
  468. using csr_page_type = typename csr_type::page_type;
  469. mem_type mem;
  470. csr_type csr;
  471. void update_vm_info();
  472. std::stringstream uart_buf;
  473. std::unordered_map<reg_t, uint64_t> ptw;
  474. std::unordered_map<uint64_t, uint8_t> atomic_reservation;
  475. std::unordered_map<unsigned, rd_csr_f> csr_rd_cb;
  476. std::unordered_map<unsigned, wr_csr_f> csr_wr_cb;
  477. private:
  478. iss::status read_cycle(unsigned addr, reg_t &val);
  479. iss::status read_time(unsigned addr, reg_t &val);
  480. iss::status read_status(unsigned addr, reg_t &val);
  481. iss::status write_status(unsigned addr, reg_t val);
  482. iss::status read_ie(unsigned addr, reg_t &val);
  483. iss::status write_ie(unsigned addr, reg_t val);
  484. iss::status read_ip(unsigned addr, reg_t &val);
  485. iss::status write_ip(unsigned addr, reg_t val);
  486. iss::status read_satp(unsigned addr, reg_t &val);
  487. iss::status write_satp(unsigned addr, reg_t val);
  488. iss::status read_fcsr(unsigned addr, reg_t& val);
  489. iss::status write_fcsr(unsigned addr, reg_t val);
  490. protected:
  491. void check_interrupt();
  492. };
  493. template <typename BASE>
  494. riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp()
  495. : state(), cycle_offset(0), instr_if(*this) {
  496. csr[misa] = hart_state<reg_t>::get_misa();
  497. uart_buf.str("");
  498. // read-only registers
  499. csr_wr_cb[misa] = nullptr;
  500. for (unsigned addr = mcycle; addr <= hpmcounter31; ++addr) csr_wr_cb[addr] = nullptr;
  501. for (unsigned addr = mcycleh; addr <= hpmcounter31h; ++addr) csr_wr_cb[addr] = nullptr;
  502. // special handling
  503. csr_rd_cb[time] = &riscv_hart_msu_vp<BASE>::read_time;
  504. csr_wr_cb[time] = nullptr;
  505. csr_rd_cb[timeh] = &riscv_hart_msu_vp<BASE>::read_time;
  506. csr_wr_cb[timeh] = nullptr;
  507. csr_rd_cb[mcycle] = &riscv_hart_msu_vp<BASE>::read_cycle;
  508. csr_rd_cb[mcycleh] = &riscv_hart_msu_vp<BASE>::read_cycle;
  509. csr_rd_cb[minstret] = &riscv_hart_msu_vp<BASE>::read_cycle;
  510. csr_rd_cb[minstreth] = &riscv_hart_msu_vp<BASE>::read_cycle;
  511. csr_rd_cb[mstatus] = &riscv_hart_msu_vp<BASE>::read_status;
  512. csr_wr_cb[mstatus] = &riscv_hart_msu_vp<BASE>::write_status;
  513. csr_rd_cb[sstatus] = &riscv_hart_msu_vp<BASE>::read_status;
  514. csr_wr_cb[sstatus] = &riscv_hart_msu_vp<BASE>::write_status;
  515. csr_rd_cb[ustatus] = &riscv_hart_msu_vp<BASE>::read_status;
  516. csr_wr_cb[ustatus] = &riscv_hart_msu_vp<BASE>::write_status;
  517. csr_rd_cb[mip] = &riscv_hart_msu_vp<BASE>::read_ip;
  518. csr_wr_cb[mip] = &riscv_hart_msu_vp<BASE>::write_ip;
  519. csr_rd_cb[sip] = &riscv_hart_msu_vp<BASE>::read_ip;
  520. csr_wr_cb[sip] = &riscv_hart_msu_vp<BASE>::write_ip;
  521. csr_rd_cb[uip] = &riscv_hart_msu_vp<BASE>::read_ip;
  522. csr_wr_cb[uip] = &riscv_hart_msu_vp<BASE>::write_ip;
  523. csr_rd_cb[mie] = &riscv_hart_msu_vp<BASE>::read_ie;
  524. csr_wr_cb[mie] = &riscv_hart_msu_vp<BASE>::write_ie;
  525. csr_rd_cb[sie] = &riscv_hart_msu_vp<BASE>::read_ie;
  526. csr_wr_cb[sie] = &riscv_hart_msu_vp<BASE>::write_ie;
  527. csr_rd_cb[uie] = &riscv_hart_msu_vp<BASE>::read_ie;
  528. csr_wr_cb[uie] = &riscv_hart_msu_vp<BASE>::write_ie;
  529. csr_rd_cb[satp] = &riscv_hart_msu_vp<BASE>::read_satp;
  530. csr_wr_cb[satp] = &riscv_hart_msu_vp<BASE>::write_satp;
  531. csr_rd_cb[fcsr] = &riscv_hart_msu_vp<BASE>::read_fcsr;
  532. csr_wr_cb[fcsr] = &riscv_hart_msu_vp<BASE>::write_fcsr;
  533. csr_rd_cb[fflags] = &riscv_hart_msu_vp<BASE>::read_fcsr;
  534. csr_wr_cb[fflags] = &riscv_hart_msu_vp<BASE>::write_fcsr;
  535. csr_rd_cb[frm] = &riscv_hart_msu_vp<BASE>::read_fcsr;
  536. csr_wr_cb[frm] = &riscv_hart_msu_vp<BASE>::write_fcsr;
  537. }
  538. template <typename BASE> std::pair<uint64_t,bool> riscv_hart_msu_vp<BASE>::load_file(std::string name, int type) {
  539. FILE *fp = fopen(name.c_str(), "r");
  540. if (fp) {
  541. std::array<char, 5> buf;
  542. auto n = fread(buf.data(), 1, 4, fp);
  543. if (n != 4) throw std::runtime_error("input file has insufficient size");
  544. buf[4] = 0;
  545. if (strcmp(buf.data() + 1, "ELF") == 0) {
  546. fclose(fp);
  547. // Create elfio reader
  548. ELFIO::elfio reader;
  549. // Load ELF data
  550. if (!reader.load(name)) throw std::runtime_error("could not process elf file");
  551. // check elf properties
  552. if ( reader.get_class() != ELFCLASS32 )
  553. if(sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file");
  554. if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file");
  555. if ( reader.get_machine() != EM_RISCV ) throw std::runtime_error("wrong elf machine in file");
  556. for (const auto pseg : reader.segments) {
  557. const auto fsize = pseg->get_file_size(); // 0x42c/0x0
  558. const auto seg_data = pseg->get_data();
  559. if (fsize > 0) {
  560. auto res = this->write(
  561. phys_addr_t(iss::access_type::DEBUG_WRITE, traits<BASE>::MEM, pseg->get_physical_address()),
  562. fsize, reinterpret_cast<const uint8_t *const>(seg_data));
  563. if (res != iss::Ok)
  564. LOG(ERROR) << "problem writing " << fsize << "bytes to 0x" << std::hex
  565. << pseg->get_physical_address();
  566. }
  567. }
  568. for (const auto sec : reader.sections) {
  569. if (sec->get_name() == ".tohost") {
  570. tohost = sec->get_address();
  571. fromhost = tohost + 0x40;
  572. }
  573. }
  574. return std::make_pair(reader.get_entry(), true);
  575. }
  576. throw std::runtime_error("memory load file is not a valid elf file");
  577. }
  578. throw std::runtime_error("memory load file not found");
  579. }
  580. template <typename BASE>
  581. iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned length, uint8_t *const data) {
  582. #ifndef NDEBUG
  583. if (addr.access && iss::access_type::DEBUG) {
  584. LOG(DEBUG) << "debug read of " << length << " bytes @addr " << addr;
  585. } else {
  586. LOG(DEBUG) << "read of " << length << " bytes @addr " << addr;
  587. }
  588. #endif
  589. try {
  590. switch (addr.space) {
  591. case traits<BASE>::MEM: {
  592. if (unlikely((addr.access == iss::access_type::FETCH || addr.access == iss::access_type::DEBUG_FETCH) && (addr.val & 0x1) == 1)) {
  593. fault_data = addr.val;
  594. if (addr.access && iss::access_type::DEBUG) throw trap_access(0, addr.val);
  595. this->reg.trap_state = (1 << 31); // issue trap 0
  596. return iss::Err;
  597. }
  598. try {
  599. if (unlikely((addr.val & ~PGMASK) != ((addr.val + length - 1) & ~PGMASK))) { // we may cross a page boundary
  600. vm_info vm = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
  601. if (vm.levels != 0) { // VM is active
  602. auto split_addr = (addr.val + length) & ~PGMASK;
  603. auto len1 = split_addr - addr.val;
  604. auto res = read(addr, len1, data);
  605. if (res == iss::Ok)
  606. res = read(iss::addr_t{addr.access, addr.type, addr.space, split_addr}, length - len1, data + len1);
  607. return res;
  608. }
  609. }
  610. auto res = read_mem( BASE::v2p(addr), length, data);
  611. if (unlikely(res != iss::Ok)) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
  612. return res;
  613. } catch (trap_access &ta) {
  614. this->reg.trap_state = (1 << 31) | ta.id;
  615. return iss::Err;
  616. }
  617. } break;
  618. case traits<BASE>::CSR: {
  619. if (length != sizeof(reg_t)) return iss::Err;
  620. return read_csr(addr.val, *reinterpret_cast<reg_t *const>(data));
  621. } break;
  622. case traits<BASE>::FENCE: {
  623. if ((addr.val + length) > mem.size()) return iss::Err;
  624. switch (addr.val) {
  625. case 2: // SFENCE:VMA lower
  626. case 3: { // SFENCE:VMA upper
  627. auto tvm = state.mstatus.TVM;
  628. if (this->reg.machine_state == PRIV_S & tvm != 0) {
  629. this->reg.trap_state = (1 << 31) | (2 << 16);
  630. this->fault_data = this->reg.PC;
  631. return iss::Err;
  632. }
  633. return iss::Ok;
  634. }
  635. }
  636. } break;
  637. case traits<BASE>::RES: {
  638. auto it = atomic_reservation.find(addr.val);
  639. if (it != atomic_reservation.end() && (*it).second != 0) {
  640. memset(data, 0xff, length);
  641. atomic_reservation.erase(addr.val);
  642. } else
  643. memset(data, 0, length);
  644. } break;
  645. default:
  646. return iss::Err; // assert("Not supported");
  647. }
  648. return iss::Ok;
  649. } catch (trap_access &ta) {
  650. this->reg.trap_state = (1 << 31) | ta.id;
  651. return iss::Err;
  652. }
  653. }
  654. template <typename BASE>
  655. iss::status riscv_hart_msu_vp<BASE>::write(const iss::addr_t &addr, unsigned length, const uint8_t *const data) {
  656. #ifndef NDEBUG
  657. const char *prefix = (addr.access && iss::access_type::DEBUG)? "debug " : "";
  658. switch (length) {
  659. case 8:
  660. LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec
  661. << ") @addr " << addr;
  662. break;
  663. case 4:
  664. LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec
  665. << ") @addr " << addr;
  666. break;
  667. case 2:
  668. LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec
  669. << ") @addr " << addr;
  670. break;
  671. case 1:
  672. LOG(DEBUG) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec
  673. << ") @addr " << addr;
  674. break;
  675. default:
  676. LOG(DEBUG) << prefix << "write of " << length << " bytes @addr " << addr;
  677. }
  678. #endif
  679. try {
  680. switch (addr.space) {
  681. case traits<BASE>::MEM: {
  682. if (unlikely((addr.access && iss::access_type::FETCH) && (addr.val & 0x1) == 1)) {
  683. fault_data = addr.val;
  684. if (addr.access && iss::access_type::DEBUG) throw trap_access(0, addr.val);
  685. this->reg.trap_state = (1 << 31); // issue trap 0
  686. return iss::Err;
  687. }
  688. try {
  689. if (unlikely((addr.val & ~PGMASK) != ((addr.val + length - 1) & ~PGMASK))) { // we may cross a page boundary
  690. vm_info vm = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
  691. if (vm.levels != 0) { // VM is active
  692. auto split_addr = (addr.val + length) & ~PGMASK;
  693. auto len1 = split_addr - addr.val;
  694. auto res = write(addr, len1, data);
  695. if (res == iss::Ok)
  696. res = write(iss::addr_t{addr.access, addr.type, addr.space, split_addr}, length - len1, data + len1);
  697. return res;
  698. }
  699. }
  700. auto res = write_mem(BASE::v2p(addr), length, data);
  701. if (unlikely(res != iss::Ok)) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 7 (Store/AMO access fault)
  702. return res;
  703. } catch (trap_access &ta) {
  704. this->reg.trap_state = (1 << 31) | ta.id;
  705. return iss::Err;
  706. }
  707. phys_addr_t paddr = BASE::v2p(addr);
  708. if ((paddr.val + length) > mem.size()) return iss::Err;
  709. switch (paddr.val) {
  710. case 0x10013000: // UART0 base, TXFIFO reg
  711. case 0x10023000: // UART1 base, TXFIFO reg
  712. uart_buf << (char)data[0];
  713. if (((char)data[0]) == '\n' || data[0] == 0) {
  714. // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
  715. // '"<<uart_buf.str()<<"'";
  716. std::cout << uart_buf.str();
  717. uart_buf.str("");
  718. }
  719. return iss::Ok;
  720. case 0x10008000: { // HFROSC base, hfrosccfg reg
  721. auto &p = mem(paddr.val / mem.page_size);
  722. auto offs = paddr.val & mem.page_addr_mask;
  723. std::copy(data, data + length, p.data() + offs);
  724. auto &x = *(p.data() + offs + 3);
  725. if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1
  726. return iss::Ok;
  727. }
  728. case 0x10008008: { // HFROSC base, pllcfg reg
  729. auto &p = mem(paddr.val / mem.page_size);
  730. auto offs = paddr.val & mem.page_addr_mask;
  731. std::copy(data, data + length, p.data() + offs);
  732. auto &x = *(p.data() + offs + 3);
  733. x |= 0x80; // set pll lock upon writing
  734. return iss::Ok;
  735. } break;
  736. default: {}
  737. }
  738. } break;
  739. case traits<BASE>::CSR: {
  740. if (length != sizeof(reg_t)) return iss::Err;
  741. return write_csr(addr.val, *reinterpret_cast<const reg_t *>(data));
  742. } break;
  743. case traits<BASE>::FENCE: {
  744. if ((addr.val + length) > mem.size()) return iss::Err;
  745. switch (addr.val) {
  746. case 2:
  747. case 3: {
  748. ptw.clear();
  749. auto tvm = state.mstatus.TVM;
  750. if (this->reg.machine_state == PRIV_S & tvm != 0) {
  751. this->reg.trap_state = (1 << 31) | (2 << 16);
  752. this->fault_data = this->reg.PC;
  753. return iss::Err;
  754. }
  755. return iss::Ok;
  756. }
  757. }
  758. } break;
  759. case traits<BASE>::RES: {
  760. atomic_reservation[addr.val] = data[0];
  761. } break;
  762. default:
  763. return iss::Err;
  764. }
  765. return iss::Ok;
  766. } catch (trap_access &ta) {
  767. this->reg.trap_state = (1 << 31) | ta.id;
  768. return iss::Err;
  769. }
  770. }
  771. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned addr, reg_t &val) {
  772. if (addr >= csr.size()) return iss::Err;
  773. auto it = csr_rd_cb.find(addr);
  774. if (it == csr_rd_cb.end()) {
  775. val = csr[addr & csr.page_addr_mask];
  776. return iss::Ok;
  777. }
  778. rd_csr_f f = it->second;
  779. if (f == nullptr) throw illegal_instruction_fault(this->fault_data);
  780. return (this->*f)(addr, val);
  781. }
  782. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_csr(unsigned addr, reg_t val) {
  783. if (addr >= csr.size()) return iss::Err;
  784. auto it = csr_wr_cb.find(addr);
  785. if (it == csr_wr_cb.end()) {
  786. csr[addr & csr.page_addr_mask] = val;
  787. return iss::Ok;
  788. }
  789. wr_csr_f f = it->second;
  790. if (f == nullptr) throw illegal_instruction_fault(this->fault_data);
  791. return (this->*f)(addr, val);
  792. }
  793. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t &val) {
  794. auto cycle_val= this->reg.icount + cycle_offset;
  795. if (addr == mcycle) {
  796. val = static_cast<reg_t>(cycle_val);
  797. } else if (addr == mcycleh) {
  798. if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err;
  799. val = static_cast<reg_t>(cycle_val >> 32);
  800. }
  801. return iss::Ok;
  802. }
  803. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_time(unsigned addr, reg_t &val) {
  804. uint64_t time_val=(this->reg.icount + cycle_offset) / (100000000/32768-1); //-> ~3052;
  805. if (addr == time) {
  806. val = static_cast<reg_t>(time_val);
  807. } else if (addr == timeh) {
  808. if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err;
  809. val = static_cast<reg_t>(time_val >> 32);
  810. }
  811. return iss::Ok;
  812. }
  813. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_status(unsigned addr, reg_t &val) {
  814. auto req_priv_lvl = addr >> 8;
  815. if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
  816. val = state.mstatus & hart_state<reg_t>::get_mask(req_priv_lvl);
  817. return iss::Ok;
  818. }
  819. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_status(unsigned addr, reg_t val) {
  820. auto req_priv_lvl = addr >> 8;
  821. if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
  822. state.write_mstatus(val, req_priv_lvl);
  823. check_interrupt();
  824. update_vm_info();
  825. return iss::Ok;
  826. }
  827. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned addr, reg_t &val) {
  828. auto req_priv_lvl = addr >> 8;
  829. if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
  830. val = csr[mie];
  831. if (addr < mie) val &= csr[mideleg];
  832. if (addr < sie) val &= csr[sideleg];
  833. return iss::Ok;
  834. }
  835. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ie(unsigned addr, reg_t val) {
  836. auto req_priv_lvl = addr >> 8;
  837. if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
  838. auto mask = get_irq_mask(req_priv_lvl);
  839. csr[mie] = (csr[mie] & ~mask) | (val & mask);
  840. check_interrupt();
  841. return iss::Ok;
  842. }
  843. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ip(unsigned addr, reg_t &val) {
  844. auto req_priv_lvl = addr >> 8;
  845. if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
  846. val = csr[mip];
  847. if (addr < mip) val &= csr[mideleg];
  848. if (addr < sip) val &= csr[sideleg];
  849. return iss::Ok;
  850. }
  851. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ip(unsigned addr, reg_t val) {
  852. auto req_priv_lvl = addr >> 8;
  853. if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
  854. auto mask = get_irq_mask(req_priv_lvl);
  855. mask &= ~(1<<7); // MTIP is read only
  856. csr[mip] = (csr[mip] & ~mask) | (val & mask);
  857. check_interrupt();
  858. return iss::Ok;
  859. }
  860. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_satp(unsigned addr, reg_t &val) {
  861. reg_t tvm = state.mstatus.TVM;
  862. if (this->reg.machine_state == PRIV_S & tvm != 0) {
  863. this->reg.trap_state = (1 << 31) | (2 << 16);
  864. this->fault_data = this->reg.PC;
  865. return iss::Err;
  866. }
  867. val = state.satp;
  868. return iss::Ok;
  869. }
  870. template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_satp(unsigned addr, reg_t val) {
  871. reg_t tvm = state.mstatus.TVM;
  872. if (this->reg.machine_state == PRIV_S & tvm != 0) {
  873. this->reg.trap_state = (1 << 31) | (2 << 16);
  874. this->fault_data = this->reg.PC;
  875. return iss::Err;
  876. }
  877. state.satp = val;
  878. update_vm_info();
  879. return iss::Ok;
  880. }
  881. template<typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_fcsr(unsigned addr, reg_t& val) {
  882. switch(addr){
  883. case 1: //fflags, 4:0
  884. val = bit_sub<0, 5>(this->get_fcsr());
  885. break;
  886. case 2: // frm, 7:5
  887. val = bit_sub<5, 3>(this->get_fcsr());
  888. break;
  889. case 3: // fcsr
  890. val=this->get_fcsr();
  891. break;
  892. default:
  893. return iss::Err;
  894. }
  895. return iss::Ok;
  896. }
  897. template<typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigned addr, reg_t val) {
  898. switch(addr){
  899. case 1: //fflags, 4:0
  900. this->set_fcsr( (this->get_fcsr() & 0xffffffe0) | (val&0x1f));
  901. break;
  902. case 2: // frm, 7:5
  903. this->set_fcsr( (this->get_fcsr() & 0xffffff1f) | ((val&0x7)<<5));
  904. break;
  905. case 3: // fcsr
  906. this->set_fcsr(val&0xff);
  907. break;
  908. default:
  909. return iss::Err;
  910. }
  911. return iss::Ok;
  912. }
  913. template <typename BASE>
  914. iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
  915. if ((paddr.val + length) > mem.size()) return iss::Err;
  916. switch (paddr.val) {
  917. case 0x0200BFF8: { // CLINT base, mtime reg
  918. if(sizeof(reg_t)<length) return iss::Err;
  919. reg_t time_val;
  920. this->read_csr(time, time_val);
  921. std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data);
  922. } break;
  923. case 0x10008000: {
  924. const mem_type::page_type &p = mem(paddr.val / mem.page_size);
  925. uint64_t offs = paddr.val & mem.page_addr_mask;
  926. std::copy(p.data() + offs, p.data() + offs + length, data);
  927. if (this->reg.icount > 30000) data[3] |= 0x80;
  928. } break;
  929. default: {
  930. const auto &p = mem(paddr.val / mem.page_size);
  931. auto offs = paddr.val & mem.page_addr_mask;
  932. std::copy(p.data() + offs, p.data() + offs + length, data);
  933. }
  934. }
  935. return iss::Ok;
  936. }
  937. template <typename BASE>
  938. iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
  939. if ((paddr.val + length) > mem.size()) return iss::Err;
  940. switch (paddr.val) {
  941. case 0x10013000: // UART0 base, TXFIFO reg
  942. case 0x10023000: // UART1 base, TXFIFO reg
  943. uart_buf << (char)data[0];
  944. if (((char)data[0]) == '\n' || data[0] == 0) {
  945. // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
  946. // '"<<uart_buf.str()<<"'";
  947. std::cout << uart_buf.str();
  948. uart_buf.str("");
  949. }
  950. break;
  951. case 0x10008000: { // HFROSC base, hfrosccfg reg
  952. mem_type::page_type &p = mem(paddr.val / mem.page_size);
  953. size_t offs = paddr.val & mem.page_addr_mask;
  954. std::copy(data, data + length, p.data() + offs);
  955. uint8_t &x = *(p.data() + offs + 3);
  956. if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1
  957. } break;
  958. case 0x10008008: { // HFROSC base, pllcfg reg
  959. mem_type::page_type &p = mem(paddr.val / mem.page_size);
  960. size_t offs = paddr.val & mem.page_addr_mask;
  961. std::copy(data, data + length, p.data() + offs);
  962. uint8_t &x = *(p.data() + offs + 3);
  963. x |= 0x80; // set pll lock upon writing
  964. } break;
  965. default: {
  966. mem_type::page_type &p = mem(paddr.val / mem.page_size);
  967. std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask));
  968. // tohost handling in case of riscv-test
  969. if (paddr.access && iss::access_type::FUNC) {
  970. auto tohost_upper = (traits<BASE>::XLEN == 32 && paddr.val == (tohost + 4)) ||
  971. (traits<BASE>::XLEN == 64 && paddr.val == tohost);
  972. auto tohost_lower =
  973. (traits<BASE>::XLEN == 32 && paddr.val == tohost) || (traits<BASE>::XLEN == 64 && paddr.val == tohost);
  974. if (tohost_lower || tohost_upper) {
  975. uint64_t hostvar = *reinterpret_cast<uint64_t *>(p.data() + (tohost & mem.page_addr_mask));
  976. if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) {
  977. switch (hostvar >> 48) {
  978. case 0:
  979. if (hostvar != 0x1){
  980. LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
  981. << "), stopping simulation";
  982. }else{
  983. LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar
  984. << "), stopping simulation";
  985. }
  986. throw(iss::simulation_stopped(hostvar));
  987. case 0x0101: {
  988. char c = static_cast<char>(hostvar & 0xff);
  989. if (c == '\n' || c == 0) {
  990. LOG(INFO) << "tohost send '" << uart_buf.str() << "'";
  991. uart_buf.str("");
  992. } else
  993. uart_buf << c;
  994. to_host_wr_cnt = 0;
  995. } break;
  996. default:
  997. break;
  998. }
  999. } else if (tohost_lower)
  1000. to_host_wr_cnt++;
  1001. } else if ((traits<BASE>::XLEN == 32 && paddr.val == fromhost + 4) ||
  1002. (traits<BASE>::XLEN == 64 && paddr.val == fromhost)) {
  1003. uint64_t fhostvar = *reinterpret_cast<uint64_t *>(p.data() + (fromhost & mem.page_addr_mask));
  1004. *reinterpret_cast<uint64_t *>(p.data() + (tohost & mem.page_addr_mask)) = fhostvar;
  1005. }
  1006. }
  1007. }
  1008. }
  1009. return iss::Ok;
  1010. }
  1011. template<typename BASE>
  1012. inline void riscv_hart_msu_vp<BASE>::reset(uint64_t address) {
  1013. BASE::reset(address);
  1014. state.mstatus = hart_state<reg_t>::mstatus_reset_val;
  1015. update_vm_info();
  1016. }
  1017. template<typename BASE>
  1018. inline void riscv_hart_msu_vp<BASE>::update_vm_info() {
  1019. vm[1] = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
  1020. BASE::addr_mode[3]=BASE::addr_mode[2]=vm[1].is_active()?iss::address_type::VIRTUAL:iss::address_type::PHYSICAL;
  1021. if(state.mstatus.MPRV)
  1022. vm[0] = hart_state<reg_t>::decode_vm_info(state.mstatus.MPP, state.satp);
  1023. else
  1024. vm[0] = vm[1];
  1025. BASE::addr_mode[1]=BASE::addr_mode[0]=vm[0].is_active()?iss::address_type::VIRTUAL:iss::address_type::PHYSICAL;
  1026. ptw.clear();
  1027. }
  1028. template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
  1029. auto status = state.mstatus;
  1030. auto ip = csr[mip];
  1031. auto ie = csr[mie];
  1032. auto ideleg = csr[mideleg];
  1033. // Multiple simultaneous interrupts and traps at the same privilege level are
  1034. // handled in the following decreasing priority order:
  1035. // external interrupts, software interrupts, timer interrupts, then finally
  1036. // any synchronous traps.
  1037. auto ena_irq = ip & ie;
  1038. auto mie = state.mstatus.MIE;
  1039. auto m_enabled = this->reg.machine_state < PRIV_M || (this->reg.machine_state == PRIV_M && mie);
  1040. auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0;
  1041. if (enabled_interrupts == 0) {
  1042. auto sie = state.mstatus.SIE;
  1043. auto s_enabled = this->reg.machine_state < PRIV_S || (this->reg.machine_state == PRIV_S && sie);
  1044. enabled_interrupts = s_enabled ? ena_irq & ideleg : 0;
  1045. }
  1046. if (enabled_interrupts != 0) {
  1047. int res = 0;
  1048. while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++;
  1049. this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id
  1050. }
  1051. }
  1052. template <typename BASE>
  1053. typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys(const iss::addr_t &addr) {
  1054. const auto type = addr.access & iss::access_type::FUNC;
  1055. auto it = ptw.find(addr.val >> PGSHIFT);
  1056. if (it != ptw.end()) {
  1057. const reg_t pte = it->second;
  1058. const reg_t ad = PTE_A | (type == iss::access_type::WRITE) * PTE_D;
  1059. #ifdef RISCV_ENABLE_DIRTY
  1060. // set accessed and possibly dirty bits.
  1061. *(uint32_t *)ppte |= ad;
  1062. return {addr.getAccessType(), addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)};
  1063. #else
  1064. // take exception if access or possibly dirty bit is not set.
  1065. if ((pte & ad) == ad)
  1066. return {addr.access, addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)};
  1067. else
  1068. ptw.erase(it); // throw an exception
  1069. #endif
  1070. } else {
  1071. uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV
  1072. state.mstatus.MPP:
  1073. this->reg.machine_state;
  1074. const vm_info& vm = this->vm[static_cast<uint16_t>(type)/2];
  1075. const bool s_mode = mode == PRIV_S;
  1076. const bool sum = state.mstatus.SUM;
  1077. const bool mxr = state.mstatus.MXR;
  1078. // verify bits xlen-1:va_bits-1 are all equal
  1079. const int va_bits = PGSHIFT + vm.levels * vm.idxbits;
  1080. const reg_t mask = (reg_t(1) << (traits<BASE>::XLEN > -(va_bits - 1))) - 1;
  1081. const reg_t masked_msbs = (addr.val >> (va_bits - 1)) & mask;
  1082. const int levels = (masked_msbs != 0 && masked_msbs != mask) ? 0 : vm.levels;
  1083. reg_t base = vm.ptbase;
  1084. for (int i = levels - 1; i >= 0; i--) {
  1085. const int ptshift = i * vm.idxbits;
  1086. const reg_t idx = (addr.val >> (PGSHIFT + ptshift)) & ((1 << vm.idxbits) - 1);
  1087. // check that physical address of PTE is legal
  1088. reg_t pte = 0;
  1089. const uint8_t res =
  1090. this->read(phys_addr_t{addr.access, traits<BASE>::MEM, base + idx * vm.ptesize}, vm.ptesize, (uint8_t *)&pte);
  1091. if (res != 0) throw trap_load_access_fault(addr.val);
  1092. const reg_t ppn = pte >> PTE_PPN_SHIFT;
  1093. if (PTE_TABLE(pte)) { // next level of page table
  1094. base = ppn << PGSHIFT;
  1095. } else if ((pte & PTE_U) ? s_mode && (type == iss::access_type::FETCH || !sum) : !s_mode) {
  1096. break;
  1097. } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
  1098. break;
  1099. } else if (type == iss::access_type::FETCH ? !(pte & PTE_X)
  1100. : type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X))
  1101. : !((pte & PTE_R) && (pte & PTE_W))) {
  1102. break;
  1103. } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
  1104. break;
  1105. } else {
  1106. const reg_t ad = PTE_A | ((type == iss::access_type::WRITE) * PTE_D);
  1107. #ifdef RISCV_ENABLE_DIRTY
  1108. // set accessed and possibly dirty bits.
  1109. *(uint32_t *)ppte |= ad;
  1110. #else
  1111. // take exception if access or possibly dirty bit is not set.
  1112. if ((pte & ad) != ad) break;
  1113. #endif
  1114. // for superpage mappings, make a fake leaf PTE for the TLB's benefit.
  1115. const reg_t vpn = addr.val >> PGSHIFT;
  1116. const reg_t value = (ppn | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT;
  1117. const reg_t offset = addr.val & PGMASK;
  1118. ptw[vpn] = value | (pte & 0xff);
  1119. return {addr.access, addr.space, value | offset};
  1120. }
  1121. }
  1122. }
  1123. switch (type) {
  1124. case access_type::FETCH:
  1125. this->fault_data = addr.val;
  1126. throw trap_instruction_page_fault(addr.val);
  1127. case access_type::READ:
  1128. this->fault_data = addr.val;
  1129. throw trap_load_page_fault(addr.val);
  1130. case access_type::WRITE:
  1131. this->fault_data = addr.val;
  1132. throw trap_store_page_fault(addr.val);
  1133. default:
  1134. abort();
  1135. }
  1136. }
  1137. template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t flags, uint64_t addr) {
  1138. auto cur_priv = this->reg.machine_state;
  1139. // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
  1140. // calculate and write mcause val
  1141. auto trap_id = bit_sub<0, 16>(flags);
  1142. auto cause = bit_sub<16, 15>(flags);
  1143. if (trap_id == 0 && cause == 11) cause = 0x8 + cur_priv; // adjust environment call cause
  1144. // calculate effective privilege level
  1145. auto new_priv = PRIV_M;
  1146. if (trap_id == 0) { // exception
  1147. if (cur_priv != PRIV_M && ((csr[medeleg] >> cause) & 0x1) != 0)
  1148. new_priv = (csr[sedeleg] >> cause) & 0x1 ? PRIV_U : PRIV_S;
  1149. // store ret addr in xepc register
  1150. csr[uepc | (new_priv << 8)] = static_cast<reg_t>(addr); // store actual address instruction of exception
  1151. /*
  1152. * write mtval if new_priv=M_MODE, spec says:
  1153. * When a hardware breakpoint is triggered, or an instruction-fetch, load,
  1154. * or store address-misaligned,
  1155. * access, or page-fault exception occurs, mtval is written with the
  1156. * faulting effective address.
  1157. */
  1158. csr[utval | (new_priv << 8)] = fault_data;
  1159. fault_data = 0;
  1160. } else {
  1161. if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0)
  1162. new_priv = (csr[sideleg] >> cause) & 0x1 ? PRIV_U : PRIV_S;
  1163. csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt
  1164. this->reg.pending_trap = 0;
  1165. }
  1166. size_t adr=ucause | (new_priv << 8);
  1167. csr[adr] = (trap_id<<31)+cause;
  1168. // update mstatus
  1169. // xPP field of mstatus is written with the active privilege mode at the time
  1170. // of the trap; the x PIE field of mstatus
  1171. // is written with the value of the active interrupt-enable bit at the time of
  1172. // the trap; and the x IE field of mstatus
  1173. // is cleared
  1174. // store the actual privilege level in yPP and store interrupt enable flags
  1175. switch (new_priv) {
  1176. case PRIV_M:
  1177. state.mstatus.MPP=cur_priv;
  1178. state.mstatus.MPIE=state.mstatus.MIE;
  1179. break;
  1180. case PRIV_S:
  1181. state.mstatus.SPP = cur_priv;
  1182. state.mstatus.SPIE=state.mstatus.SIE;
  1183. break;
  1184. case PRIV_U:
  1185. state.mstatus.UPIE=state.mstatus.UIE;
  1186. break;
  1187. default:
  1188. break;
  1189. }
  1190. // get trap vector
  1191. auto ivec = csr[utvec | (new_priv << 8)];
  1192. // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE
  1193. // bits in mtvec
  1194. this->reg.NEXT_PC = ivec & ~0x1UL;
  1195. if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause;
  1196. // reset trap state
  1197. this->reg.machine_state = new_priv;
  1198. this->reg.trap_state = 0;
  1199. std::array<char, 32> buffer;
  1200. sprintf(buffer.data(), "0x%016lx", addr);
  1201. CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause])<<"' ("<<trap_id<<")"
  1202. << " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[cur_priv]
  1203. << " to " << lvl[new_priv];
  1204. update_vm_info();
  1205. return this->reg.NEXT_PC;
  1206. }
  1207. template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::leave_trap(uint64_t flags) {
  1208. auto cur_priv = this->reg.machine_state;
  1209. auto inst_priv = flags & 0x3;
  1210. auto status = state.mstatus;
  1211. auto tsr = state.mstatus.TSR;
  1212. if (cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) {
  1213. this->reg.trap_state = (1 << 31) | (2 << 16);
  1214. this->fault_data = this->reg.PC;
  1215. return this->reg.PC;
  1216. }
  1217. // pop the relevant lower-privilege interrupt enable and privilege mode stack
  1218. // clear respective yIE
  1219. switch (inst_priv) {
  1220. case PRIV_M:
  1221. this->reg.machine_state = state.mstatus.MPP;
  1222. state.mstatus.MPP=0; // clear mpp to U mode
  1223. state.mstatus.MIE=state.mstatus.MPIE;
  1224. break;
  1225. case PRIV_S:
  1226. this->reg.machine_state = state.mstatus.SPP;
  1227. state.mstatus.SPP= 0; // clear spp to U mode
  1228. state.mstatus.SIE=state.mstatus.SPIE;
  1229. break;
  1230. case PRIV_U:
  1231. this->reg.machine_state = 0;
  1232. state.mstatus.UIE=state.mstatus.UPIE;
  1233. break;
  1234. }
  1235. // sets the pc to the value stored in the x epc register.
  1236. this->reg.NEXT_PC = csr[uepc | inst_priv << 8];
  1237. CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.machine_state];
  1238. update_vm_info();
  1239. return this->reg.NEXT_PC;
  1240. }
  1241. template <typename BASE> void riscv_hart_msu_vp<BASE>::wait_until(uint64_t flags) {
  1242. auto status = state.mstatus;
  1243. auto tw = status.TW;
  1244. if (this->reg.machine_state == PRIV_S && tw != 0) {
  1245. this->reg.trap_state = (1 << 31) | (2 << 16);
  1246. this->fault_data = this->reg.PC;
  1247. }
  1248. }
  1249. }
  1250. }
  1251. #endif /* _RISCV_CORE_H_ */