From 399c978c0944d2a568cdcb3dc73d6a9f9779ee50 Mon Sep 17 00:00:00 2001 From: bLueriVerLHR Date: Sun, 14 May 2023 17:46:12 +0800 Subject: [PATCH] [Add] full funtion except execeptions and cache/TLB added --- CMakeLists.txt | 30 +- include/devaddr.h | 10 +- lasim/la32r.cc | 721 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 612 insertions(+), 149 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4974c54..2cad6e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,24 +51,24 @@ set(LAOS laos) # ----- ----- 构建 Verilator 项目 ----- ----- -set(LACPU lacpu) -set(LAVSIM lavsim) -set(LA_VSIM_TARGET ${PROJECT_NAME}-vsim) +# set(LACPU lacpu) +# set(LAVSIM lavsim) +# set(LA_VSIM_TARGET ${PROJECT_NAME}-vsim) -find_package(verilator HINTS $ENV{VERILATOR_ROOT} ${VERILATOR_ROOT}) +# find_package(verilator HINTS $ENV{VERILATOR_ROOT} ${VERILATOR_ROOT}) -if (NOT verilator_FOUND) - message(FATAL_ERROR "Verilator was not found.") -endif() +# if (NOT verilator_FOUND) +# message(FATAL_ERROR "Verilator was not found.") +# endif() -# set default top module as top file -set(VSRC ${CMAKE_SOURCE_DIR}/${LACPU}/top.v) +# # set default top module as top file +# set(VSRC ${CMAKE_SOURCE_DIR}/${LACPU}/rtl/soc_lite_top.v) -# get all cxx source files from lavsim folder -file(GLOB_RECURSE LAVSIM_SRC ${CMAKE_SOURCE_DIR}/${LAVSIM}/*.cc) +# # get all cxx source files from lavsim folder +# file(GLOB_RECURSE LAVSIM_SRC ${CMAKE_SOURCE_DIR}/${LAVSIM}/*.cc) -add_executable(${LA_VSIM_TARGET} ${LAVSIM_SRC}) +# add_executable(${LA_VSIM_TARGET} ${LAVSIM_SRC}) -verilate(${LA_VSIM_TARGET} - INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/${LACPU} ${VERILATOR_ROOT}/include - SOURCES ${VSRC}) \ No newline at end of file +# verilate(${LA_VSIM_TARGET} +# INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/${LACPU}/rtl/cpu ${VERILATOR_ROOT}/include +# SOURCES ${VSRC}) \ No newline at end of file diff --git a/include/devaddr.h b/include/devaddr.h index 7251a85..2c91e75 100644 --- a/include/devaddr.h +++ b/include/devaddr.h @@ -4,11 +4,15 @@ #define DEVADDR_H__ #define RAM_ADDR 0x0000'0000 -#define IMG_ADDR 0x0001'04d8 -#define STK_ADDR 0x2000'0000 +#define RST_ADDR 0x1c00'0000 + +#define HEAP_ADDR 0x2000'0000 +#define HEAP_SIZE 0x0020'0000 +#define STAK_SIZE 0x0002'0000 +#define STAK_ADDR (HEAP_ADDR + HEAP_SIZE + STAK_SIZE) #define DEVICE_BASE 0xa0000000 -#define MMIO_BASE 0xa0000000 +#define MMIO_BASE 0xa0000000 #define SERIAL_PORT (DEVICE_BASE + 0x00003f8) #define KBD_ADDR (DEVICE_BASE + 0x0000060) diff --git a/lasim/la32r.cc b/lasim/la32r.cc index b02bcdf..6c0e3a6 100644 --- a/lasim/la32r.cc +++ b/lasim/la32r.cc @@ -1,15 +1,24 @@ +#include + #include #include #include namespace { + +// +// ----- ----- new type defines ----- ----- +// + using u64 = uint64_t; using i64 = int64_t; using u32 = uint32_t; using i32 = int32_t; -SystemBus *sysbus; +// +// ----- ----- enum defines ----- ----- +// enum regenum { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, @@ -18,60 +27,174 @@ enum regenum { R30, R31, PC }; +enum CSRADDR { + CRMD = 0x000, /* 当前模式信息 */ + PRMD = 0x001, /* 例外前模式信息 */ + EUEN = 0x002, /* 拓展部件使能 */ + ECFG = 0x004, /* 例外配置 */ + ESTAT = 0x005, /* 例外状态 */ + ERA = 0x006, /* 例外返回地址 */ + BADV = 0x007, /* 出错虚地址 */ + EENTRY = 0x00c, /* 例外地址入口 */ + TLBIDX = 0x010, /* TLB 索引 */ + TLBEHI = 0x011, /* TLB 表项高位 */ + TLBELO0 = 0x012, /* TLB 表项低位 0 */ + TLBELO1 = 0x013, /* TLB 表项低位 1 */ + ASID = 0x018, /* 地址空间标识符 */ + PGDL = 0x019, /* 低半地址空间全局目录基址 */ + PGDH = 0x01a, /* 高半地址空间全局目录基址 */ + PGD = 0x01b, /* 全局目录基址 */ + CPUID = 0x020, /* 处理器编号 */ + SAVE0 = 0x030, /* 数据保存 0*/ + SAVE1 = 0x031, /* 数据保存 1*/ + SAVE2 = 0x032, /* 数据保存 2 */ + SAVE3 = 0x033, /* 数据保存 3 */ + TID = 0x040, /* 定时器编号 */ + TCFG = 0x041, /* 定时器配置 */ + TVAL = 0x042, /* 定时器值 */ + TICLR = 0x044, /* 定时中断清除 */ + LLBCTL = 0x060, /* LLBit 控制 */ + TLBRENTRY = 0x088, /* TLB 重填例外入口 */ + CTAG = 0x098, /* 高速缓存标签 */ + DMW0 = 0x180, /* 直接映射配置窗口 0 */ + DMW1 = 0x181, /* 直接映射配置窗口 1 */ +}; + +enum CSRRDATTR { + CSR_RW, /* 软件可读写 */ + CSR_R, /* 软件只读 */ + CSR_R0, /* 软件只 `读 0` */ + CSR_W1, /* 软件读无意义,只 `写 1` */ +}; + enum PLV { - PLV0, - // PLV1, - // PLV2, - PLV3, -} PrivilegeLevel ; + PLV0 = 0, + // PLV1, + // PLV2, + PLV3 = 3, +}; + +enum SCOP { + SC_RDHI, + SC_RDLO, + SC_RDID, +}; + +enum TLBOP { + TLB_SRCH, + TLB_RD, + TLB_WR, + TLB_FILL, +}; + +enum DATAKIND { + BYTE, + HWORD, + WORD, + DWORD, +}; + +// +// ----- ----- customize constant defines ----- ----- +// + +constexpr u32 RSTVEC = 0x1c00'0000; +constexpr u32 IDXLEN = 16; +constexpr u32 PALEN = 36; +constexpr u32 TVALLEN = 31; + +static_assert(IDXLEN <= 16); // TLB idx 宽度 +static_assert(36 >= PALEN && 13 <= PALEN); // 页表物理页号长度 +static_assert(TVALLEN <= 32); // 计时器计数宽度 + +const char *regnames[] = { + [R0] = "zero", + [R1] = "ra", + [R2] = "tp", + [R3] = "sp", + [R4] = "a0", [R5] = "a1", + [R6] = "a2", [R7] = "a3", [R8] = "a4", [R9] = "a5", [R10] = "a6", [R11] = "a7", + [R12] = "t0", [R13] = "t1", [R14] = "t2", [R15] = "t3", [R16] = "t4", [R17] = "t5", [R18] = "t6", [R19] = "t7", [R20] = "t8", + [R21] = "r21", + [R22] = "fp/s9", + [R23] = "s0", [R24] = "s1", [R25] = "s2", [R26] = "s3", [R27] = "s4", [R28] = "s5", [R29] = "s6", [R30] = "s7", [R31] = "s8", +}; + +// +// ----- ----- struct defines ----- ----- +// + +struct CSRBaseInfo { + u32 data = 0x0; + u32 wmask = 0xffff'ffff; + u32 w1mask = 0x0; +}; + +// +// ----- ----- class defines ----- ----- +// class Registers { private: - u32 regs_[32] = {0}; + u32 regs_[31] = {0}; u32 pc_ = 0; + u32 _; public: Registers() = default; - u32 get(u32 idx) { + void operator >> (u32 addr) { + pc_ = addr; + } + + const u32 &operator()(u32 idx) { panicifnot((0 <= idx && 32 >= idx) || idx == PC); + if (idx == 0) { + return 0; + } + if (idx == PC) { return pc_; } - if (0 <= idx && 32 >= idx) { - return regs_[idx]; + if (1 <= idx && 32 >= idx) { + return regs_[idx - 1]; } panic("Unexpected register access"); } - void set(u32 idx, u32 data) { - panicifnot((0 <= idx && 32 >= idx) || idx == PC); - if (idx == PC) { - pc_ = data; - } - - if (0 <= idx && 32 >= idx) { - regs_[idx] = data; - } - - panic("Unexpected register access"); - - } - u32 &operator[](u32 idx) { - if (idx == PC) { - return pc_; + panicifnot(0 <= idx && 32 >= idx); + if (idx == 0) { + return _; } - if (0 <= idx && 32 >= idx) { - return regs_[idx]; + if (1 <= idx && 32 >= idx) { + return regs_[idx - 1]; } panic("Unexpected register access"); } -} Regs ; +}; + +// +// ----- ----- static values ----- ----- +// + +PLV PrivilegeLevel; + +Registers Regs; + +std::unordered_map CSRs; + +u64 stblcnt[4] = {0}; + +SystemBus *sysbus; + +// +// ----- ----- binary operations ----- ----- +// constexpr u32 gb(u32 hi, u32 lo, u32 data) { panicifnot(hi >= lo); @@ -82,12 +205,328 @@ constexpr u32 gb(u32 hi, u32 lo, u32 data) { return data & mask; } +constexpr u32 msk(u32 hi, u32 lo) { + panicifnot(hi >= lo); + + u32 width = hi - lo + 1; + u32 mask = (u32)(~0) >> (32 - width); + return mask << lo; +} + +constexpr u32 msk(u32 pos) { + return 0x1 << pos; +} + constexpr u32 sext(u32 data, u32 width) { u32 upper = 32 - width; u32 result = (i32)(data << upper) >> upper; return result; } +constexpr u32 sll(u32 data, u32 sa) { + if (sa == 0) + return data; + + return data << sa; +} + +constexpr u32 srl(u32 data, u32 sa) { + if (sa == 0) + return data; + + return data >> sa; +} + +constexpr u32 sra(u32 data, u32 sa) { + if (sa == 0) + return data; + + return (i32)data >> sa; +} + +constexpr u32 sb(u32 hi, u32 lo, u32 &data, u32 wdata) { + auto &&mask = msk(hi, lo); + auto &&rem = data & ~mask; + auto &&wr = (wdata << lo) & mask; + data = rem | wdata; + return data; +} + +constexpr u32 sb(u32 pos, u32 &data, u32 wdata) { + auto &&mask = msk(pos); + auto &&rem = data & ~mask; + auto &&wr = (wdata << pos) & mask; + data = rem | wdata; + return data; +} + +constexpr u32 rounddown(u32 data, u32 agn = 2) { + return (data >> agn) << agn; +} + +constexpr u32 roundfup(u32 data, u32 agn = 2) { + auto &&upper = gb(31, agn, data); + return (upper + 1) << agn; +} + +constexpr u32 roundup(u32 data, u32 agn = 2) { + auto &&upper = gb(31, agn, data); + auto &&lower = agn ? gb(agn - 1, 0, data) : 0; + return lower ? (upper + 1) << agn : upper << agn; +} + + +// +// ----- ----- unit test ----- ----- +// + +static_assert(gb(15, 0, 0xdead'beef) == 0x0000'beef); +static_assert(gb(31, 16, 0xdead'beef) == 0x0000'dead); + +static_assert(msk( 0, 0) == 0x0000'0001); +static_assert(msk(31, 0) == 0xffff'ffff); +static_assert(msk( 3, 0) == 0x0000'000f); +static_assert(msk(23, 12) == 0x00ff'f000); +static_assert(msk(31, 31) == 0x8000'0000); + +static_assert(msk( 0) == 0x0000'0001); +static_assert(msk( 1) == 0x0000'0002); +static_assert(msk( 2) == 0x0000'0004); +static_assert(msk(30) == 0x4000'0000); +static_assert(msk(31) == 0x8000'0000); + +static_assert(sext(0x0000'0001, 1) == 0xffff'ffff); +static_assert(sext(0x0000'0fff, 16) == 0x0000'0fff); +static_assert(sext(0x0000'dead, 16) == 0xffff'dead); +static_assert(sext(0x000f'dead, 20) == 0xffff'dead); + +static_assert(sll(0x1, 0) == 0x1); +static_assert(sll(0x1, 1) == 0x2); +static_assert(sll(0x1, 31) == 0x8000'0000); + +static_assert(srl(0x8000'0000, 0) == 0x8000'0000); +static_assert(srl(0x8000'0000, 1) == 0x4000'0000); +static_assert(srl(0x8000'0000, 31) == 0x1); + +static_assert(srl(0x8000'0000, 0) == 0x8000'0000); +static_assert(sra(0x8000'0000, 1) == 0xc000'0000); +static_assert(sra(0x8000'0000, 31) == 0xffff'ffff); + +// +// ----- ----- CSR Control ----- ----- +// + +#define CRMD_PLV 1, 0 +#define CRMD_IE 2 +#define CRMD_DA 3 +#define CRMD_PG 4 +#define CRMD_DATF 6, 5 +#define CRMD_DATM 8, 7 + +#define EUEN_FPE 0 + +#define ECFG_LIE_09_00 9, 0 +#define ECFG_LIE_12_11 12,11 + +#define ESTAT_IS_01_00 1, 0 +// #define ESTAT_IS_09_02 9, 2 +// #define ESTAT_IS_11 11 +// #define ESTAT_IS_12 12 +// #define ESTAT_Ecode 21,16 +// #define ESTAT_EsubCode 30,22 + +#define TCFG_En 0 +#define TCFG_Periodic 1 +#define TCFG_InitVal (TVALLEN - 1),2 + +#define LLBCTL_WCLLB 1 +#define LLBCTL_KLO 2 + +#define DMW_PLV0 0 +#define DMW_PLV3 3 +#define DMW_MAT 5, 4 +#define DMW_PSEG 27,25 +#define DMW_VSEG 31,29 + + + +// +// ----- ----- control logic functions ----- ----- +// + +void init_csr() { + CSRs.emplace(CRMD , CSRBaseInfo{ + .wmask = msk(8, 7) | msk(6, 5) | msk(4) | msk(3) | msk(2) | msk(1, 0), + }); + CSRs.emplace(PRMD , CSRBaseInfo{ + .wmask = msk(2) | msk(1, 0), + }); + CSRs.emplace(EUEN , CSRBaseInfo{ + .wmask = msk(0), + }); + CSRs.emplace(ECFG , CSRBaseInfo{ + .wmask = msk(12, 11) | msk(9, 0), + }); + CSRs.emplace(ESTAT , CSRBaseInfo{ + .wmask = msk(1, 0), + }); + CSRs.emplace(ERA , CSRBaseInfo{ + .wmask = msk(31, 0), + }); + CSRs.emplace(BADV , CSRBaseInfo{ + .wmask = msk(31, 0), + }); + CSRs.emplace(EENTRY , CSRBaseInfo{ + .wmask = msk(31, 6), + }); + CSRs.emplace(TLBIDX , CSRBaseInfo{ + .wmask = msk(31) | msk(29, 24) | msk(IDXLEN - 1, 0), + }); + CSRs.emplace(TLBEHI , CSRBaseInfo{ + .wmask = msk(31, 13), + }); + CSRs.emplace(TLBELO0 , CSRBaseInfo{ + .wmask = msk(31, 13), + }); + CSRs.emplace(TLBELO1 , CSRBaseInfo{ + .wmask = msk(PALEN - 5, 8) | msk(6) | msk(5, 4) | msk(3, 2) | msk(1) | msk(0), + }); + CSRs.emplace(ASID , CSRBaseInfo{ + .wmask = msk(9, 0), + }); + CSRs.emplace(PGDL , CSRBaseInfo{ + .wmask = msk(31, 12), + }); + CSRs.emplace(PGDH , CSRBaseInfo{ + .wmask = msk(31, 12), + }); + CSRs.emplace(PGD , CSRBaseInfo{ + .wmask = 0, + }); + CSRs.emplace(CPUID , CSRBaseInfo{ + .wmask = 0, + }); + CSRs.emplace(SAVE0 , CSRBaseInfo{ + .wmask = msk(31, 0), + }); + CSRs.emplace(SAVE1 , CSRBaseInfo{ + .wmask = msk(31, 0), + }); + CSRs.emplace(SAVE2 , CSRBaseInfo{ + .wmask = msk(31, 0), + }); + CSRs.emplace(SAVE3 , CSRBaseInfo{ + .wmask = msk(31, 0), + }); + CSRs.emplace(TID , CSRBaseInfo{ + .wmask = msk(31, 0), + }); + CSRs.emplace(TCFG , CSRBaseInfo{ + .wmask = msk(TVALLEN - 1, 2) | msk(1) | msk(0), + }); + CSRs.emplace(TVAL , CSRBaseInfo{ + .wmask = 0, + }); + CSRs.emplace(TICLR , CSRBaseInfo{ + .w1mask = msk(0), + }); + CSRs.emplace(LLBCTL , CSRBaseInfo{ + .wmask = msk(2), + .w1mask = msk(1), + }); + CSRs.emplace(TLBRENTRY , CSRBaseInfo{ + .wmask = msk(31, 6), + }); + CSRs.emplace(CTAG , CSRBaseInfo{ + .wmask = 0, + }); + CSRs.emplace(DMW0 , CSRBaseInfo{ + .wmask = msk(31, 29) | msk(27, 25) | msk(5, 4) | msk(3) | msk(0), + }); + CSRs.emplace(DMW1 , CSRBaseInfo{ + .wmask = msk(31, 29) | msk(27, 25) | msk(5, 4) | msk(3) | msk(0), + }); +} + +/** + * @brief 始终返回旧值 +*/ +u32 csr_wr(bool wen, u32 data, u32 addr) { + auto &&csr = CSRs.at(addr); + auto old = csr.data; + if (wen) { + auto &&wdata = data & (csr.wmask & ~csr.w1mask); + auto &&must1 = data & csr.w1mask ; + csr.data = wdata | must1; + } + return old; +} + +u32 stable_counter(bool rhi) { + auto &&tid = csr_wr(false, 0x0, TID); + return rhi ? stblcnt[tid] >> 32 : stblcnt[tid]; +} + +void exception_enter(u32 code) { + panic("Not implemented yet"); +} + +void exception_return() { + panic("Not implemented yet"); +} + +void exception_break(u32 code) { + panic("Not implemented yet"); +} + +void exception_syscall(u32 code) { + panic("Not implemented yet"); +} + +void cache_ctrl(u32 code, u32 addr) { + panic("Not implemented yet"); +} + +void tlb_ctrl(TLBOP opcode) { + panic("Not implemented yet"); +} + +void invtbl(u32 op, u32 asid, u32 vaddr) { + panic("Not implemented yet"); +} + +void idle_wait() { + panic("Not implemented yet"); +} + +u32 ll(u32 addr) { + panic("Not implemented yet"); +} + +u32 sc(u32 addr) { + panic("Not implemented yet"); +} + +u32 cache_visit(DATAKIND datakind, bool wen, u32 wdata, u32 addr) { + + if (wen) { + + } + panic("Not implemented yet"); +} + +u32 cache_prefetch(u32 hint, u32 addr) { + panic("Not implemented yet"); +} + +void inst_barrier(u32 hint) {} + +void data_barrier(u32 hint) {} + +// +// ----- ----- decode and execute ----- ----- +// + bool check(const char *instfmt, u32 inst) { size_t len = strlen(instfmt); panicifnot(len >= 32); @@ -120,38 +559,19 @@ bool check(const char *instfmt, u32 inst) { return hit == 32; } -u32 SLL(u32 data, u32 sa) { - if (sa == 0) - return data; - - return data << sa; -} - -u32 SRL(u32 data, u32 sa) { - if (sa == 0) - return data; - - return data >> sa; -} - -u32 SRA(u32 data, u32 sa) { - if (sa == 0) - return data; - - return (i32)data >> sa; -} - #define BEGIN_CHECK() if (false) {} -#define INST(str, instname, extracond, ...) \ -else if (check((str), (inst)) && (extracond)) { \ - curinst = #instname; \ - __VA_ARGS__; \ +#define INST(str, instname, extracond, ...) \ +else if (check((str), (inst)) && (extracond)) { \ + curinst = #instname; \ + __VA_ARGS__; \ } -void decode_and_exec(u32 inst) { +u32 decode_and_exec(u32 inst, u32 curpc) { + u32 nxtpc = curpc + 4; + // These decode is fixed u32 rd = gb( 4, 0, inst); u32 rj = gb( 9, 5, inst); @@ -165,13 +585,17 @@ void decode_and_exec(u32 inst) { u32 si14 = sext(gb(23, 10, inst), 14); u32 si20 = sext(gb(24, 5, inst), 20); - u32 csr = gb(23, 10, inst); + u32 csraddr = gb(23, 10, inst); u32 offs_15_00 = gb(25, 10, inst); u32 offs_20_16 = gb( 4, 0, inst); u32 offs_25_16 = gb( 9, 0, inst); - u32 code = rd << 0 | rj << 5 | rk << 10; + u32 offs16 = offs_15_00; + u32 offs21 = offs_20_16 << 16 | offs_15_00; + u32 offs26 = offs_25_16 << 16 | offs_15_00; + + u32 code = rk << 10 | rj << 5 | rd << 0; u32 level = code; u32 hint = code; @@ -182,108 +606,143 @@ void decode_and_exec(u32 inst) { const char *curinst = nullptr; BEGIN_CHECK() - INST("00000000000000000'1100'0'xxxxx'00000", RDCNTID.W, gb(4, 0, inst) == 0) - INST("00000000000000000'1100'0'00000'xxxxx", RDCNTVL.W, gb(9, 5, inst) == 0) - INST("00000000000000000'1100'1'00000'xxxxx", RDCNTVH.W, gb(9, 5, inst) == 0) + INST("00000000000000000'1100'0'xxxxx'00000", RDCNTID.W, gb(4, 0, inst) == 0, Regs[rj] = csr_wr(false, 0x0, TID)) + INST("00000000000000000'1100'0'00000'xxxxx", RDCNTVL.W, gb(9, 5, inst) == 0, Regs[rd] = stable_counter(false)) + INST("00000000000000000'1100'1'00000'xxxxx", RDCNTVH.W, gb(9, 5, inst) == 0, Regs[rd] = stable_counter(true )) - INST("00000000000'100000'xxxxx'xxxxx'xxxxx", ADD.W, true, Regs[rd] = Regs[rj] + Regs[rk]) - INST("00000000000'100010'xxxxx'xxxxx'xxxxx", SUB.W, true, Regs[rd] = Regs[rj] - Regs[rk]) - INST("00000000000'100100'xxxxx'xxxxx'xxxxx", SLT, true, Regs[rd] = (i32)Regs[rj] < (i32)Regs[rk]) - INST("00000000000'100101'xxxxx'xxxxx'xxxxx", SLTU, true, Regs[rd] = Regs[rj] < Regs[rk]) - INST("00000000000'101000'xxxxx'xxxxx'xxxxx", NOR, true, Regs[rd] = ~(Regs[rj] | Regs[rk])) - INST("00000000000'101001'xxxxx'xxxxx'xxxxx", AND, true, Regs[rd] = Regs[rj] & Regs[rk]) - INST("00000000000'101010'xxxxx'xxxxx'xxxxx", OR, true, Regs[rd] = Regs[rj] | Regs[rk]) - INST("00000000000'101011'xxxxx'xxxxx'xxxxx", XOR, true, Regs[rd] = Regs[rj] ^ Regs[rk]) - INST("00000000000'101110'xxxxx'xxxxx'xxxxx", SLL.W, true, Regs[rd] = SLL(Regs[rj], gb(4, 0, Regs[rk]))) - INST("00000000000'101111'xxxxx'xxxxx'xxxxx", SRL.W, true, Regs[rd] = SRL(Regs[rj], gb(4, 0, Regs[rk]))) - INST("00000000000'110000'xxxxx'xxxxx'xxxxx", SRA.W, true, Regs[rd] = SRA(Regs[rj], gb(4, 0, Regs[rk]))) - INST("00000000000'111000'xxxxx'xxxxx'xxxxx", MUL.W, true, Regs[rd] = Regs[rj] * Regs[rk]) - INST("00000000000'111001'xxxxx'xxxxx'xxxxx", MULH.W, true, Regs[rd] = (u32)(((i64)(i32)Regs[rj] * (i64)(i32)Regs[rk]) >> 32)) - INST("00000000000'111010'xxxxx'xxxxx'xxxxx", MULH.WU, true, Regs[rd] = (u32)(((u64)Regs[rj] * (u64)Regs[rk]) >> 32)) - INST("0000000000'1000000'xxxxx'xxxxx'xxxxx", DIV.W, true, Regs[rd] = (i32)Regs[rj] / (i32)Regs[rk]) - INST("0000000000'1000001'xxxxx'xxxxx'xxxxx", MOD.W, true, Regs[rd] = (i32)Regs[rj] % (i32)Regs[rk]) - INST("0000000000'1000010'xxxxx'xxxxx'xxxxx", DIV.WU, true, Regs[rd] = Regs[rj] / Regs[rk]) - INST("0000000000'1000011'xxxxx'xxxxx'xxxxx", MOD.WU, true, Regs[rd] = Regs[rj] % Regs[rk]) + INST("00000000000'100000'xxxxx'xxxxx'xxxxx", ADD.W, true, Regs[rd] = Regs(rj) + Regs(rk)) + INST("00000000000'100010'xxxxx'xxxxx'xxxxx", SUB.W, true, Regs[rd] = Regs(rj) - Regs(rk)) + INST("00000000000'100100'xxxxx'xxxxx'xxxxx", SLT, true, Regs[rd] = (i32)Regs(rj) < (i32)Regs(rk)) + INST("00000000000'100101'xxxxx'xxxxx'xxxxx", SLTU, true, Regs[rd] = Regs(rj) < Regs(rk)) + INST("00000000000'101000'xxxxx'xxxxx'xxxxx", NOR, true, Regs[rd] = ~(Regs(rj) | Regs(rk))) + INST("00000000000'101001'xxxxx'xxxxx'xxxxx", AND, true, Regs[rd] = Regs(rj) & Regs(rk)) + INST("00000000000'101010'xxxxx'xxxxx'xxxxx", OR, true, Regs[rd] = Regs(rj) | Regs(rk)) + INST("00000000000'101011'xxxxx'xxxxx'xxxxx", XOR, true, Regs[rd] = Regs(rj) ^ Regs(rk)) + INST("00000000000'101110'xxxxx'xxxxx'xxxxx", sll.W, true, Regs[rd] = sll(Regs(rj), gb(4, 0, Regs(rk)))) + INST("00000000000'101111'xxxxx'xxxxx'xxxxx", srl.W, true, Regs[rd] = srl(Regs(rj), gb(4, 0, Regs(rk)))) + INST("00000000000'110000'xxxxx'xxxxx'xxxxx", sra.W, true, Regs[rd] = sra(Regs(rj), gb(4, 0, Regs(rk)))) + INST("00000000000'111000'xxxxx'xxxxx'xxxxx", MUL.W, true, Regs[rd] = Regs(rj) * Regs(rk)) + INST("00000000000'111001'xxxxx'xxxxx'xxxxx", MULH.W, true, Regs[rd] = (u32)(((i64)(i32)Regs(rj) * (i64)(i32)Regs(rk)) >> 32)) + INST("00000000000'111010'xxxxx'xxxxx'xxxxx", MULH.WU, true, Regs[rd] = (u32)(((u64)Regs(rj) * (u64)Regs(rk)) >> 32)) + INST("0000000000'1000000'xxxxx'xxxxx'xxxxx", DIV.W, true, Regs[rd] = (i32)Regs(rj) / (i32)Regs(rk)) + INST("0000000000'1000001'xxxxx'xxxxx'xxxxx", MOD.W, true, Regs[rd] = (i32)Regs(rj) % (i32)Regs(rk)) + INST("0000000000'1000010'xxxxx'xxxxx'xxxxx", DIV.WU, true, Regs[rd] = Regs(rj) / Regs(rk)) + INST("0000000000'1000011'xxxxx'xxxxx'xxxxx", MOD.WU, true, Regs[rd] = Regs(rj) % Regs(rk)) - INST("0000000000'1010100'xxxxx xxxxx xxxxx", BREAK, true, ) - INST("0000000000'1010110'xxxxx xxxxx xxxxx", SYSCALL, true, ) + INST("0000000000'1010100'xxxxx xxxxx xxxxx", BREAK, true, exception_break (code)) + INST("0000000000'1010110'xxxxx xxxxx xxxxx", SYSCALL, true, exception_syscall(code)) - INST("000000000'10000'000'xxxxx'xxxxx'xxxxx", SLLI.W, true, Regs[rd] = SLL(Regs[rj], ui5)) - INST("000000000'10000'001'xxxxx'xxxxx'xxxxx", SRLI.W, true, Regs[rd] = SRL(Regs[rj], ui5)) - INST("000000000'10000'010'xxxxx'xxxxx'xxxxx", SRAI.W, true, Regs[rd] = SRA(Regs[rj], ui5)) + INST("000000000'10000'000'xxxxx'xxxxx'xxxxx", SLLI.W, true, Regs[rd] = sll(Regs(rj), ui5)) + INST("000000000'10000'001'xxxxx'xxxxx'xxxxx", SRLI.W, true, Regs[rd] = srl(Regs(rj), ui5)) + INST("000000000'10000'010'xxxxx'xxxxx'xxxxx", SRAI.W, true, Regs[rd] = sra(Regs(rj), ui5)) - INST("000000'1000'xxxxxxx xxxxx'xxxxx'xxxxx", SLTI, true, Regs[rd] = (i32)Regs[rj] < (i32)si12) - INST("000000'1001'xxxxxxx xxxxx'xxxxx'xxxxx", SLTUI, true, Regs[rd] = Regs[rj] < si12) - INST("000000'1010'xxxxxxx xxxxx'xxxxx'xxxxx", ADDI.W, true, Regs[rd] = Regs[rj] + si12) - INST("000000'1101'xxxxxxx xxxxx'xxxxx'xxxxx", ANDI, true, Regs[rd] = Regs[rj] & ui12) - INST("000000'1110'xxxxxxx xxxxx'xxxxx'xxxxx", ORI, true, Regs[rd] = Regs[rj] | ui12) - INST("000000'1111'xxxxxxx xxxxx'xxxxx'xxxxx", XORI, true, Regs[rd] = Regs[rj] ^ ui12) + INST("000000'1000'xxxxxxx xxxxx'xxxxx'xxxxx", SLTI, true, Regs[rd] = (i32)Regs(rj) < (i32)si12) + INST("000000'1001'xxxxxxx xxxxx'xxxxx'xxxxx", SLTUI, true, Regs[rd] = Regs(rj) < si12) + INST("000000'1010'xxxxxxx xxxxx'xxxxx'xxxxx", ADDI.W, true, Regs[rd] = Regs(rj) + si12) + INST("000000'1101'xxxxxxx xxxxx'xxxxx'xxxxx", ANDI, true, Regs[rd] = Regs(rj) & ui12) + INST("000000'1110'xxxxxxx xxxxx'xxxxx'xxxxx", ORI, true, Regs[rd] = Regs(rj) | ui12) + INST("000000'1111'xxxxxxx xxxxx'xxxxx'xxxxx", XORI, true, Regs[rd] = Regs(rj) ^ ui12) - INST("00000'100'xxxxxxxxxxxxxx'00000'xxxxx", CSRRD, gb(9, 5, inst) == 0, ) - INST("00000'100'xxxxxxxxxxxxxx'00001'xxxxx", CSRWR, gb(9, 5, inst) == 1, ) - INST("00000'100'xxxxxxxxxxxxxx'xxxxx'xxxxx", CSRXCHG, gb(9, 5, inst) > 1, ) + INST("00000'100'xxxxxxxxxxxxxx'00000'xxxxx", CSRRD, gb(9, 5, inst) == 0, Regs[rd] = csr_wr(false, 0x0, csraddr)) + INST("00000'100'xxxxxxxxxxxxxx'00001'xxxxx", CSRWR, gb(9, 5, inst) == 1, Regs[rd] = csr_wr(true, Regs(rd), csraddr)) + INST("00000'100'xxxxxxxxxxxxxx'xxxxx'xxxxx", CSRXCHG, gb(9, 5, inst) > 1, Regs[rd] = csr_wr(true, Regs(rd) & Regs(rj), csraddr)) - INST("00000'11000'xxxxxxxxxxxx'xxxxx'xxxxx", CACOP, true, ) + INST("00000'11000'xxxxxxxxxxxx'xxxxx'xxxxx", CACOP, true, cache_ctrl(code5, si12 + Regs[rj])) - INST("00000'1100'1001000001'010'00000'00000", TLBSRCH, true, ) - INST("00000'1100'1001000001'011'00000'00000", TLBRD, true, ) - INST("00000'1100'1001000001'100'00000'00000", TLBWR, true, ) - INST("00000'1100'1001000001'101'00000'00000", TLBFILL, true, ) - INST("00000'1100'1001000001'110'00000'00000", ERTN, true, ) + INST("00000'1100'1001000001'010'00000'00000", TLBSRCH, true, tlb_ctrl(TLB_SRCH)) + INST("00000'1100'1001000001'011'00000'00000", TLBRD, true, tlb_ctrl(TLB_RD )) + INST("00000'1100'1001000001'100'00000'00000", TLBWR, true, tlb_ctrl(TLB_WR )) + INST("00000'1100'1001000001'101'00000'00000", TLBFILL, true, tlb_ctrl(TLB_FILL)) + INST("00000'1100'1001000001'110'00000'00000", ERTN, true, exception_return()) - INST("00000'1100'1001'0001'xxxxx xxxxx xxxxx", IDLE, true, ) - INST("00000'1100'1001'0011'xxxxx'xxxxx'xxxxx", INVTLB, true, ) + INST("00000'1100'1001'0001'xxxxx xxxxx xxxxx", IDLE, true, idle_wait()) + INST("00000'1100'1001'0011'xxxxx'xxxxx'xxxxx", INVTLB, true, invtbl(op, Regs(rj), Regs(rk))) - INST("000'1010'xxxxxxxxxxxxxxxxxxxx'xxxxx", LU12I.W, true, ) - INST("000'1110'xxxxxxxxxxxxxxxxxxxx'xxxxx", PCADDU12I, true, ) + INST("000'1010'xxxxxxxxxxxxxxxxxxxx'xxxxx", LU12I.W, true, Regs[rd] = si20 << 12) + INST("000'1110'xxxxxxxxxxxxxxxxxxxx'xxxxx", PCADDU12I, true, Regs[rd] = si20 << 12 + curpc) - INST("00'100000'xxxxxxxxxxxxxx'xxxxx'xxxxx", LL.W, true, ) - INST("00'100001'xxxxxxxxxxxxxx'xxxxx'xxxxx", SC.W, true, ) + INST("00'100000'xxxxxxxxxxxxxx'xxxxx'xxxxx", LL.W, true, Regs[rd] = ll((si14 << 2) + Regs[rj])) + INST("00'100001'xxxxxxxxxxxxxx'xxxxx'xxxxx", SC.W, true, Regs[rd] = sc((si14 << 2) + Regs[rj])) - INST("00'10100000'xxxxxxxxxxxx'xxxxx'xxxxx", LD.B, true, ) - INST("00'10100001'xxxxxxxxxxxx'xxxxx'xxxxx", LD.H, true, ) - INST("00'10100010'xxxxxxxxxxxx'xxxxx'xxxxx", LD.W, true, ) - INST("00'10100100'xxxxxxxxxxxx'xxxxx'xxxxx", ST.B, true, ) - INST("00'10100101'xxxxxxxxxxxx'xxxxx'xxxxx", ST.H, true, ) - INST("00'10100110'xxxxxxxxxxxx'xxxxx'xxxxx", ST.W, true, ) - INST("00'10101000'xxxxxxxxxxxx'xxxxx'xxxxx", LD.BU, true, ) - INST("00'10101001'xxxxxxxxxxxx'xxxxx'xxxxx", LD.HU, true, ) - INST("00'10101011'xxxxxxxxxxxx'xxxxx'xxxxx", PRELD, true, ) + INST("00'10100000'xxxxxxxxxxxx'xxxxx'xxxxx", LD.B, true, Regs[rd] = sext(cache_visit(BYTE, false, 0x0, si12 + Regs[rj]), 8)) + INST("00'10100001'xxxxxxxxxxxx'xxxxx'xxxxx", LD.H, true, Regs[rd] = sext(cache_visit(BYTE, false, 0x0, si12 + Regs[rj]), 16)) + INST("00'10100010'xxxxxxxxxxxx'xxxxx'xxxxx", LD.W, true, Regs[rd] = cache_visit(BYTE, false, 0x0, si12 + Regs[rj]) ) + INST("00'10100100'xxxxxxxxxxxx'xxxxx'xxxxx", ST.B, true, cache_visit(BYTE, true, Regs[rd], si12 + Regs[rj])) + INST("00'10100101'xxxxxxxxxxxx'xxxxx'xxxxx", ST.H, true, cache_visit(BYTE, true, Regs[rd], si12 + Regs[rj])) + INST("00'10100110'xxxxxxxxxxxx'xxxxx'xxxxx", ST.W, true, cache_visit(BYTE, true, Regs[rd], si12 + Regs[rj])) + INST("00'10101000'xxxxxxxxxxxx'xxxxx'xxxxx", LD.BU, true, Regs[rd] = cache_visit(BYTE, false, 0x0, si12 + Regs[rj])) + INST("00'10101001'xxxxxxxxxxxx'xxxxx'xxxxx", LD.HU, true, Regs[rd] = cache_visit(BYTE, false, 0x0, si12 + Regs[rj])) + INST("00'10101011'xxxxxxxxxxxx'xxxxx'xxxxx", PRELD, true, cache_prefetch(hint5, si12 + Regs[rj])) - INST("00'111000011100100'xxxxx xxxxx xxxxx", DBAR, true, ) - INST("00'111000011100101'xxxxx xxxxx xxxxx", IBAR, true, ) + INST("00'111000011100100'xxxxx xxxxx xxxxx", DBAR, true, data_barrier(hint)) + INST("00'111000011100101'xxxxx xxxxx xxxxx", IBAR, true, inst_barrier(hint)) - INST("0'10010'xxxxxxxxxxxxxxxx'00xxx'xxxxx", BCEQZ, gb(9, 8, inst) == 0, ) - INST("0'10010'xxxxxxxxxxxxxxxx'01xxx'xxxxx", BCNEZ, gb(9, 8, inst) == 1, ) - INST("0'10011'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", JIRL, true, ) - INST("0'10100'xxxxxxxxxxxxxxxx'xxxxx xxxxx", B, true, ) - INST("0'10101'xxxxxxxxxxxxxxxx'xxxxx xxxxx", BL, true, ) - INST("0'10110'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BEQ, true, ) - INST("0'10111'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BNE, true, ) - INST("0'11000'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BLT, true, ) - INST("0'11001'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BGE, true, ) - INST("0'11010'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BLTU, true, ) - INST("0'11011'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BGEU, true, ) + INST("0'10011'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", JIRL, true, Regs[rd] = curpc + 4; nxtpc = Regs[rj] + sext(offs16 << 2, 18)) + INST("0'10100'xxxxxxxxxxxxxxxx'xxxxx xxxxx", B, true, nxtpc = curpc + sext(offs26 << 2, 28)) + INST("0'10101'xxxxxxxxxxxxxxxx'xxxxx xxxxx", BL, true, Regs[R1] = curpc + 4; nxtpc = curpc + sext(offs26 << 2, 28)) + INST("0'10110'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BEQ, true, nxtpc = Regs(rj) == Regs(rd) ? curpc + sext(offs16 << 2, 18) : nxtpc) + INST("0'10111'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BNE, true, nxtpc = Regs(rj) != Regs(rd) ? curpc + sext(offs16 << 2, 18) : nxtpc) + INST("0'11000'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BLT, true, nxtpc = (i32)Regs(rj) < (i32)Regs(rd) ? curpc + sext(offs16 << 2, 18) : nxtpc) + INST("0'11001'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BGE, true, nxtpc = (i32)Regs(rj) >= (i32)Regs(rd) ? curpc + sext(offs16 << 2, 18) : nxtpc) + INST("0'11010'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BLTU, true, nxtpc = Regs(rj) < Regs(rd) ? curpc + sext(offs16 << 2, 18) : nxtpc) + INST("0'11011'xxxxxxxxxxxxxxxx'xxxxx'xxxxx", BGEU, true, nxtpc = Regs(rj) >= Regs(rd) ? curpc + sext(offs16 << 2, 18) : nxtpc) printf("%08x: %s\n", inst, curinst); + + return nxtpc; } u32 fetch() { u32 inst; - sysbus->read32(inst, Regs[PC]); + sysbus->read32(inst, Regs(PC)); return inst; } +void reset() { + + auto &&crmd = CSRs.at(CRMD).data; + sb( CRMD_PLV, crmd, 0); + sb( CRMD_IE, crmd, 0); + sb( CRMD_DA, crmd, 1); + sb( CRMD_PG, crmd, 0); + sb(CRMD_DATF, crmd, 0); + sb(CRMD_DATM, crmd, 0); + + auto &&euen = CSRs.at(EUEN).data; + sb(EUEN_FPE, euen, 0); + + auto &&ecfg = CSRs.at(ECFG).data; + sb(ECFG_LIE_09_00, ecfg, 0); + sb(ECFG_LIE_12_11, ecfg, 0); + + auto &&estat = CSRs.at(ESTAT).data; + sb(ESTAT_IS_01_00, estat, 0); + + auto &&tcfg = CSRs.at(TCFG).data; + sb(TCFG_En, tcfg, 0); + + auto &&llbctl = CSRs.at(LLBCTL).data; + sb(LLBCTL_KLO, llbctl, 0); + + auto &&dmw0 = CSRs.at(DMW0).data; + sb(DMW_PLV0, dmw0, 0); + sb(DMW_PLV3, dmw0, 0); + + auto &&dmw1 = CSRs.at(DMW0).data; + sb(DMW_PLV0, dmw1, 0); + sb(DMW_PLV3, dmw1, 0); +} + } LA32R::LA32R(SystemBus *bus) { sysbus = bus; - - Regs[PC] = IMG_ADDR; + init_csr(); + Regs >> RSTVEC; } void LA32R::Step(unsigned in) { u32 inst = fetch(); - decode_and_exec(inst); - Regs[PC] += 4; + auto &&nxtpc = decode_and_exec(inst, Regs(PC)); + Regs >> nxtpc; } \ No newline at end of file