riscv_hart_msu_vp.h 53KB

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