diff --git a/src/cartesi-machine.lua b/src/cartesi-machine.lua index a8cec69b..67811080 100755 --- a/src/cartesi-machine.lua +++ b/src/cartesi-machine.lua @@ -1609,7 +1609,7 @@ for _, a in ipairs(arg) do end local function print_root_hash(machine, print) - (print or stderr)("%u: %s\n", machine:read_mcycle(), util.hexhash(machine:get_root_hash())) + (print or stderr)("%u: %s\n", machine:read_reg("mcycle"), util.hexhash(machine:get_root_hash())) end local function dump_value_proofs(machine, desired_proofs, config) @@ -1906,7 +1906,7 @@ local function get_and_print_yield(machine, htif) reason_str = cmio_yield_manual_reason[reason] or reason_str end stderr("\n%s yield %s (%d) (0x%06x data)\n", cmd_str, reason_str, reason, #data) - stderr("Cycles: %u\n", machine:read_mcycle()) + stderr("Cycles: %u\n", machine:read_reg("mcycle")) return cmd, reason, data end @@ -2068,7 +2068,7 @@ local backup_closer = setmetatable({}, { -- once all inputs for advance state have been consumed, we check if the user selected cmio inspect state -- if so, we feed the query, reset iflags_Y, and resume the machine -- the machine can now continue processing and may yield automatic to produce reports we save -while math.ult(machine:read_mcycle(), max_mcycle) do +while math.ult(machine:read_reg("mcycle"), max_mcycle) do local next_mcycle = math.min(next_hash_mcycle, max_mcycle) if gdb_stub and gdb_stub:is_connected() then gdb_stub:run(next_mcycle) @@ -2076,17 +2076,17 @@ while math.ult(machine:read_mcycle(), max_mcycle) do machine:run(next_mcycle) end -- deal with halt - if machine:read_iflags_H() then + if machine:read_reg("iflags_H") ~= 0 then exit_code = machine:read_reg("htif_tohost_data") >> 1 if exit_code ~= 0 then stderr("\nHalted with payload: %u\n", exit_code) else stderr("\nHalted\n") end - stderr("Cycles: %u\n", machine:read_mcycle()) + stderr("Cycles: %u\n", machine:read_reg("mcycle")) break -- deal with yield manual - elseif machine:read_iflags_Y() then + elseif machine:read_reg("iflags_Y") ~= 0 then local _, reason, data = get_and_print_yield(machine, config.htif) -- there was an exception if reason == cartesi.CMIO_YIELD_MANUAL_REASON_TX_EXCEPTION then @@ -2150,7 +2150,7 @@ while math.ult(machine:read_mcycle(), max_mcycle) do end end -- deal with yield automatic - elseif machine:read_iflags_X() then + elseif machine:read_reg("iflags_X") ~= 0 then local _, reason, data = get_and_print_yield(machine, config.htif) -- we have fed an advance state input if cmio_advance and cmio_advance.next_input_index > cmio_advance.input_index_begin then @@ -2172,12 +2172,12 @@ while math.ult(machine:read_mcycle(), max_mcycle) do end -- otherwise ignore end - if machine:read_iflags_Y() then + if machine:read_reg("iflags_Y") ~= 0 then -- commit any pending snapshot do_commit() break end - if machine:read_mcycle() == next_hash_mcycle then + if machine:read_reg("mcycle") == next_hash_mcycle then print_root_hash(machine) next_hash_mcycle = next_hash_mcycle + periodic_hashes_period end @@ -2192,16 +2192,16 @@ end -- Advance micro cycles if max_uarch_cycle > 0 then -- Save halt flag before micro cycles - local previously_halted = machine:read_iflags_H() + local previously_halted = machine:read_reg("iflags_H") ~= 0 if machine:run_uarch(max_uarch_cycle) == cartesi.UARCH_BREAK_REASON_UARCH_HALTED then -- Microarchitecture halted. This means that one "macro" instruction was totally executed -- The mcycle counter was incremented, unless the machine was already halted - if machine:read_iflags_H() and not previously_halted then stderr("Halted\n") end - stderr("Cycles: %u\n", machine:read_mcycle()) + if machine:read_reg("iflags_H") ~= 0 and not previously_halted then stderr("Halted\n") end + stderr("Cycles: %u\n", machine:read_reg("mcycle")) if auto_reset_uarch then machine:reset_uarch() else - stderr("uCycles: %u\n", machine:read_uarch_cycle()) + stderr("uCycles: %u\n", machine:read_reg("uarch_cycle")) end end end diff --git a/src/cartesi/gdbstub.lua b/src/cartesi/gdbstub.lua index 59d27037..fd8614e0 100644 --- a/src/cartesi/gdbstub.lua +++ b/src/cartesi/gdbstub.lua @@ -189,16 +189,16 @@ function GDBStub:_handle_query(_, query) elseif query:find("^qRcmd,") then -- custom command local payload = hex2str(query:sub(7)) if payload:find("^stepc %d+$") then -- step a fixed number of cycles - self.mcycle_limit = self.machine:read_mcycle() + tonumber(payload:match("^stepc (%d+)$")) + self.mcycle_limit = self.machine:read_reg("mcycle") + tonumber(payload:match("^stepc (%d+)$")) return self:_send_ok() elseif payload:find("^stepu %d+$") then -- step until a cycle number - self.mcycle_limit = math.max(self.machine:read_mcycle(), tonumber(payload:match("^stepu (%d+)$"))) + self.mcycle_limit = math.max(self.machine:read_reg("mcycle"), tonumber(payload:match("^stepu (%d+)$"))) return self:_send_ok() elseif payload == "stepc_clear" then -- remove stepping breakpoint self.mcycle_limit = nil return self:_send_ok() elseif payload == "cycles" then -- print current cycle - self:_send_rcmd_reply(string.format("%u\n", self.machine:read_mcycle())) + self:_send_rcmd_reply(string.format("%u\n", self.machine:read_reg("mcycle"))) return self:_send_ok() elseif payload:find("^reg [%w_]+$") then -- read machine registers local reg_name = payload:match("^reg ([%w_]+)$") @@ -244,7 +244,7 @@ function GDBStub:_handle_query(_, query) self.performed_first_hash = true end local hash = self.machine:get_root_hash() - self:_send_rcmd_reply(string.format("%u: %s\n", self.machine:read_mcycle(), str2hex(hash))) + self:_send_rcmd_reply(string.format("%u: %s\n", self.machine:read_reg("mcycle"), str2hex(hash))) return self:_send_ok() elseif payload:find("^store .*$") then -- store the machine state local store_dir = payload:match("^store (.*)$") @@ -393,7 +393,7 @@ end -- GDB is asking to let the machine continue. function GDBStub:_handle_continue() local machine = self.machine - local mcycle = machine:read_mcycle() + local mcycle = machine:read_reg("mcycle") local mcycle_end = self.max_mcycle local ult = math.ult -- localized to speed up Lua loop if self.mcycle_limit and ult(self.mcycle_limit, self.max_mcycle) then @@ -407,22 +407,22 @@ function GDBStub:_handle_continue() machine:run(mcycle + 1) if breakpoints[machine:read_reg("pc")] then -- breakpoint reached return self:_send_signal(signals.SIGTRAP) - elseif machine:read_iflags_H() then -- machined halted + elseif machine:read_reg("iflags_H") ~= 0 then -- machined halted return self:_send_signal(signals.SIGTERM) - elseif machine:read_iflags_Y() or machine:read_iflags_X() then -- machine yielded + elseif machine:read_reg("iflags_Y") ~= 0 or machine:read_reg("iflags_X") ~= 0 then -- machine yielded self.yielded = true return true -- a reply will be sent to GDB in the next run loop end - mcycle = machine:read_mcycle() + mcycle = machine:read_reg("mcycle") end else -- no breakpoint set, we can run through the fast path machine:run(mcycle_end) end - if machine:read_iflags_H() then -- machine halted + if machine:read_reg("iflags_H") ~= 0 then -- machine halted return self:_send_signal(signals.SIGTERM) - elseif machine:read_mcycle() == self.max_mcycle then -- reached max cycles + elseif machine:read_reg("mcycle") == self.max_mcycle then -- reached max cycles return self:_send_signal(signals.SIGQUIT) - elseif machine:read_iflags_Y() or machine:read_iflags_X() then -- machine yielded + elseif machine:read_reg("iflags_Y") ~= 0 or machine:read_reg("iflags_X") ~= 0 then -- machine yielded self.yielded = true return true -- a reply will be sent to GDB in the next run loop else -- reached step cycles limit diff --git a/src/clua-i-virtual-machine.cpp b/src/clua-i-virtual-machine.cpp index 549056ef..8ffbb30b 100644 --- a/src/clua-i-virtual-machine.cpp +++ b/src/clua-i-virtual-machine.cpp @@ -149,11 +149,10 @@ cm_reg clua_check_cm_proc_reg(lua_State *L, int idx) try { {"scounteren", CM_REG_SCOUNTEREN}, {"senvcfg", CM_REG_SENVCFG}, {"ilrsc", CM_REG_ILRSC}, - {"iflags", CM_REG_IFLAGS}, - {"iflags_prv", CM_REG_IFLAGS_PRV}, - {"iflags_x", CM_REG_IFLAGS_X}, - {"iflags_y", CM_REG_IFLAGS_Y}, - {"iflags_h", CM_REG_IFLAGS_H}, + {"iprv", CM_REG_IPRV}, + {"iflags_X", CM_REG_IFLAGS_X}, + {"iflags_Y", CM_REG_IFLAGS_Y}, + {"iflags_H", CM_REG_IFLAGS_H}, {"iunrep", CM_REG_IUNREP}, {"clint_mtimecmp", CM_REG_CLINT_MTIMECMP}, {"plic_girqpend", CM_REG_PLIC_GIRQPEND}, @@ -577,26 +576,6 @@ static int machine_obj_index_get_root_hash(lua_State *L) { return 1; } -static int machine_obj_index_read_mcycle(lua_State *L) { - auto &m = clua_check>(L, 1); - uint64_t val{}; - if (cm_read_mcycle(m.get(), &val) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - lua_pushinteger(L, static_cast(val)); - return 1; -} - -static int machine_obj_index_read_uarch_cycle(lua_State *L) { - auto &m = clua_check>(L, 1); - uint64_t val{}; - if (cm_read_uarch_cycle(m.get(), &val) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - lua_pushinteger(L, static_cast(val)); - return 1; -} - /// \brief This is the machine:read_reg() method implementation. /// \param L Lua state. static int machine_obj_index_read_reg(lua_State *L) { @@ -609,62 +588,6 @@ static int machine_obj_index_read_reg(lua_State *L) { return 1; } -/// \brief This is the machine:read_iflags_H() method implementation. -/// \param L Lua state. -static int machine_obj_index_read_iflags_H(lua_State *L) { - auto &m = clua_check>(L, 1); - bool val{}; - if (cm_read_iflags_H(m.get(), &val) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - lua_pushboolean(L, static_cast(val)); - return 1; -} - -/// \brief This is the machine:read_iflags_Y() method implementation. -/// \param L Lua state. -static int machine_obj_index_read_iflags_Y(lua_State *L) { - auto &m = clua_check>(L, 1); - bool val{}; - if (cm_read_iflags_Y(m.get(), &val) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - lua_pushboolean(L, static_cast(val)); - return 1; -} - -/// \brief This is the machine:read_iflags_X() method implementation. -/// \param L Lua state. -static int machine_obj_index_read_iflags_X(lua_State *L) { - auto &m = clua_check>(L, 1); - bool val{}; - if (cm_read_iflags_X(m.get(), &val) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - lua_pushboolean(L, static_cast(val)); - return 1; -} - -/// \brief This is the machine:set_iflags_Y() method implementation. -/// \param L Lua state. -static int machine_obj_index_set_iflags_Y(lua_State *L) { - auto &m = clua_check>(L, 1); - if (cm_set_iflags_Y(m.get()) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - return 0; -} - -/// \brief This is the machine:reset_iflags_Y() method implementation. -/// \param L Lua state. -static int machine_obj_index_reset_iflags_Y(lua_State *L) { - auto &m = clua_check>(L, 1); - if (cm_reset_iflags_Y(m.get()) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - return 0; -} - /// \brief This is the machine:read_memory() method implementation. /// \param L Lua state. static int machine_obj_index_read_memory(lua_State *L) { @@ -746,28 +669,6 @@ static int machine_obj_index_log_step(lua_State *L) { return 1; } -/// \brief This is the machine:read_uarch_halt_flag() method implementation. -/// \param L Lua state. -static int machine_obj_index_read_uarch_halt_flag(lua_State *L) { - auto &m = clua_check>(L, 1); - bool val{}; - if (cm_read_uarch_halt_flag(m.get(), &val) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - lua_pushboolean(L, static_cast(val)); - return 1; -} - -/// \brief This is the machine:set_uarch_halt_flag() method implementation. -/// \param L Lua state. -static int machine_obj_index_set_uarch_halt_flag(lua_State *L) { - auto &m = clua_check>(L, 1); - if (cm_set_uarch_halt_flag(m.get()) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - return 0; -} - /// \brief This is the machine:reset_uarch() method implementation. /// \param L Lua state. static int machine_obj_index_reset_uarch(lua_State *L) { @@ -1141,53 +1042,44 @@ static int machine_obj_index_swap(lua_State *L) { /// \brief Contents of the machine object metatable __index table. static const auto machine_obj_index = cartesi::clua_make_luaL_Reg_array({ - {"is_empty", machine_obj_index_is_empty}, {"create", machine_obj_index_create}, - {"load", machine_obj_index_load}, - {"get_proof", machine_obj_index_get_proof}, + {"destroy", machine_obj_index_destroy}, + {"get_default_config", machine_obj_index_get_default_config}, {"get_initial_config", machine_obj_index_get_initial_config}, - {"get_runtime_config", machine_obj_index_get_runtime_config}, - {"set_runtime_config", machine_obj_index_set_runtime_config}, + {"get_memory_ranges", machine_obj_index_get_memory_ranges}, + {"get_proof", machine_obj_index_get_proof}, + {"get_reg_address", machine_obj_index_get_reg_address}, {"get_root_hash", machine_obj_index_get_root_hash}, - {"read_reg", machine_obj_index_read_reg}, - {"read_uarch_cycle", machine_obj_index_read_uarch_cycle}, - {"read_iflags_H", machine_obj_index_read_iflags_H}, - {"read_iflags_Y", machine_obj_index_read_iflags_Y}, - {"read_iflags_X", machine_obj_index_read_iflags_X}, - {"set_iflags_Y", machine_obj_index_set_iflags_Y}, - {"reset_iflags_Y", machine_obj_index_reset_iflags_Y}, - {"read_mcycle", machine_obj_index_read_mcycle}, + {"get_runtime_config", machine_obj_index_get_runtime_config}, + {"is_empty", machine_obj_index_is_empty}, + {"load", machine_obj_index_load}, + {"log_reset_uarch", machine_obj_index_log_reset_uarch}, + {"log_send_cmio_response", machine_obj_index_log_send_cmio_response}, + {"log_step", machine_obj_index_log_step}, + {"log_step_uarch", machine_obj_index_log_step_uarch}, {"read_memory", machine_obj_index_read_memory}, + {"read_reg", machine_obj_index_read_reg}, {"read_virtual_memory", machine_obj_index_read_virtual_memory}, {"read_word", machine_obj_index_read_word}, + {"receive_cmio_request", machine_obj_index_receive_cmio_request}, + {"replace_memory_range", machine_obj_index_replace_memory_range}, + {"reset_uarch", machine_obj_index_reset_uarch}, {"run", machine_obj_index_run}, - {"log_step", machine_obj_index_log_step}, {"run_uarch", machine_obj_index_run_uarch}, - {"log_step_uarch", machine_obj_index_log_step_uarch}, + {"send_cmio_response", machine_obj_index_send_cmio_response}, + {"set_runtime_config", machine_obj_index_set_runtime_config}, {"store", machine_obj_index_store}, + {"swap", machine_obj_index_swap}, + {"translate_virtual_address", machine_obj_index_translate_virtual_address}, {"verify_dirty_page_maps", machine_obj_index_verify_dirty_page_maps}, {"verify_merkle_tree", machine_obj_index_verify_merkle_tree}, - {"write_reg", machine_obj_index_write_reg}, - {"write_memory", machine_obj_index_write_memory}, - {"write_virtual_memory", machine_obj_index_write_virtual_memory}, - {"translate_virtual_address", machine_obj_index_translate_virtual_address}, - {"replace_memory_range", machine_obj_index_replace_memory_range}, - {"destroy", machine_obj_index_destroy}, - {"read_uarch_halt_flag", machine_obj_index_read_uarch_halt_flag}, - {"set_uarch_halt_flag", machine_obj_index_set_uarch_halt_flag}, - {"get_memory_ranges", machine_obj_index_get_memory_ranges}, - {"reset_uarch", machine_obj_index_reset_uarch}, - {"log_reset_uarch", machine_obj_index_log_reset_uarch}, - {"receive_cmio_request", machine_obj_index_receive_cmio_request}, - {"send_cmio_response", machine_obj_index_send_cmio_response}, - {"log_send_cmio_response", machine_obj_index_log_send_cmio_response}, - {"get_default_config", machine_obj_index_get_default_config}, - {"get_reg_address", machine_obj_index_get_reg_address}, - {"verify_step", machine_obj_index_verify_step}, - {"verify_step_uarch", machine_obj_index_verify_step_uarch}, {"verify_reset_uarch", machine_obj_index_verify_reset_uarch}, {"verify_send_cmio_response", machine_obj_index_verify_send_cmio_response}, - {"swap", machine_obj_index_swap}, + {"verify_step", machine_obj_index_verify_step}, + {"verify_step_uarch", machine_obj_index_verify_step_uarch}, + {"write_memory", machine_obj_index_write_memory}, + {"write_reg", machine_obj_index_write_reg}, + {"write_virtual_memory", machine_obj_index_write_virtual_memory}, }); /// \brief This is the class() constructor implementation. diff --git a/src/device-state-access.h b/src/device-state-access.h index 51d5633a..fd810ab9 100644 --- a/src/device-state-access.h +++ b/src/device-state-access.h @@ -75,16 +75,16 @@ class device_state_access : public i_device_state_access { return m_mcycle; } - void do_set_iflags_H() override { - m_a.set_iflags_H(); + void do_write_iflags_H(uint64_t val) override { + m_a.write_iflags_H(val); } - void do_set_iflags_Y() override { - m_a.set_iflags_Y(); + void do_write_iflags_Y(uint64_t val) override { + m_a.write_iflags_Y(val); } - void do_set_iflags_X() override { - m_a.set_iflags_X(); + void do_write_iflags_X(uint64_t val) override { + m_a.write_iflags_X(val); } uint64_t do_read_clint_mtimecmp() override { diff --git a/src/htif.cpp b/src/htif.cpp index 2cf8331a..24358d6d 100644 --- a/src/htif.cpp +++ b/src/htif.cpp @@ -63,7 +63,7 @@ static bool htif_read(void * /*context*/, i_device_state_access *a, uint64_t off static execute_status htif_halt(i_device_state_access *a, uint64_t cmd, uint64_t data) { if (cmd == HTIF_HALT_CMD_HALT && ((data & 1) != 0)) { - a->set_iflags_H(); + a->write_iflags_H(1); return execute_status::success_and_halt; } //??D Write acknowledgement to fromhost??? @@ -76,11 +76,11 @@ static execute_status htif_yield(i_device_state_access *a, uint64_t cmd, uint64_ // If yield command is enabled, yield and acknowledge if (cmd < 64 && (((a->read_htif_iyield() >> cmd) & 1) != 0)) { if (cmd == HTIF_YIELD_CMD_MANUAL) { - a->set_iflags_Y(); + a->write_iflags_Y(1); status = execute_status::success_and_yield; a->write_htif_fromhost(HTIF_BUILD(HTIF_DEV_YIELD, cmd, 0, 0)); } else if (cmd == HTIF_YIELD_CMD_AUTOMATIC) { - a->set_iflags_X(); + a->write_iflags_X(1); status = execute_status::success_and_yield; a->write_htif_fromhost(HTIF_BUILD(HTIF_DEV_YIELD, cmd, 0, 0)); } diff --git a/src/i-device-state-access.h b/src/i-device-state-access.h index 075d2bc4..184edda4 100644 --- a/src/i-device-state-access.h +++ b/src/i-device-state-access.h @@ -73,21 +73,24 @@ class i_device_state_access { } /// \brief Sets the iflags_H flag. + /// \param val New register value. /// \details This is Cartesi-specific. - void set_iflags_H() { - do_set_iflags_H(); + void write_iflags_H(uint64_t val) { + do_write_iflags_H(val); } /// \brief Sets the iflags_Y flag. + /// \param val New register value. /// \details This is Cartesi-specific. - void set_iflags_Y() { - do_set_iflags_Y(); + void write_iflags_Y(uint64_t val) { + do_write_iflags_Y(val); } /// \brief Sets the iflags_X flag. + /// \param val New register value. /// \details This is Cartesi-specific. - void set_iflags_X() { - do_set_iflags_X(); + void write_iflags_X(uint64_t val) { + do_write_iflags_X(val); } /// \brief Reads CLINT's mtimecmp. @@ -207,9 +210,9 @@ class i_device_state_access { virtual void do_reset_mip(uint64_t mask) = 0; virtual uint64_t do_read_mip() = 0; virtual uint64_t do_read_mcycle() = 0; - virtual void do_set_iflags_H() = 0; - virtual void do_set_iflags_Y() = 0; - virtual void do_set_iflags_X() = 0; + virtual void do_write_iflags_H(uint64_t val) = 0; + virtual void do_write_iflags_Y(uint64_t val) = 0; + virtual void do_write_iflags_X(uint64_t val) = 0; virtual uint64_t do_read_clint_mtimecmp() = 0; virtual void do_write_clint_mtimecmp(uint64_t val) = 0; virtual uint64_t do_read_plic_girqpend() = 0; diff --git a/src/i-state-access.h b/src/i-state-access.h index d692b32c..6fbeb0de 100644 --- a/src/i-state-access.h +++ b/src/i-state-access.h @@ -326,16 +326,52 @@ class i_state_access { // CRTP return derived().do_write_mideleg(val); } - /// \brief Reads CSR iflags. + /// \brief Reads CSR iprv. /// \returns Register value. - auto read_iflags() { - return derived().do_read_iflags(); + uint64_t read_iprv() { + return derived().do_read_iprv(); } - /// \brief Writes CSR iflags. + /// \brief Writes CSR iprv. /// \param val New register value. - auto write_iflags(uint64_t val) { - return derived().do_write_iflags(val); + void write_iprv(uint64_t val) { + return derived().do_write_iprv(val); + } + + /// \brief Reads CSR iflags_X. + /// \returns Register value. + uint64_t read_iflags_X() { + return derived().do_read_iflags_X(); + } + + /// \brief Writes CSR iflags_X. + /// \param val New register value. + void write_iflags_X(uint64_t val) { + return derived().do_write_iflags_X(val); + } + + /// \brief Reads CSR iflags_Y. + /// \returns Register value. + uint64_t read_iflags_Y() { + return derived().do_read_iflags_Y(); + } + + /// \brief Writes CSR iflags_Y. + /// \param val New register value. + void write_iflags_Y(uint64_t val) { + return derived().do_write_iflags_Y(val); + } + + /// \brief Reads CSR iflags_H. + /// \returns Register value. + uint64_t read_iflags_H() { + return derived().do_read_iflags_H(); + } + + /// \brief Writes CSR iflags_H. + /// \param val New register value. + void write_iflags_H(uint64_t val) { + return derived().do_write_iflags_H(val); } /// \brief Reads CSR mcounteren. @@ -460,70 +496,6 @@ class i_state_access { // CRTP return derived().do_write_ilrsc(val); } - /// \brief Sets the iflags_H flag. - /// \details This is Cartesi-specific. - void set_iflags_H() { - return derived().do_set_iflags_H(); - } - - /// \brief Reads the iflags_H flag. - /// \returns The flag value. - /// \details This is Cartesi-specific. - bool read_iflags_H() { - return derived().do_read_iflags_H(); - } - - /// \brief Sets the iflags_Y flag. - /// \details This is Cartesi-specific. - void set_iflags_Y() { - return derived().do_set_iflags_Y(); - } - - /// \brief Sets the iflags_X flag. - /// \details This is Cartesi-specific. - void set_iflags_X() { - return derived().do_set_iflags_X(); - } - - /// \brief Resets the iflags_Y flag. - /// \details This is Cartesi-specific. - void reset_iflags_Y() { - return derived().do_reset_iflags_Y(); - } - - /// \brief Resets the iflags_X flag. - /// \details This is Cartesi-specific. - void reset_iflags_X() { - return derived().do_reset_iflags_X(); - } - - /// \brief Reads the iflags_Y flag. - /// \returns The flag value. - /// \details This is Cartesi-specific. - bool read_iflags_Y() { - return derived().do_read_iflags_Y(); - } - - /// \brief Reads the iflags_X flag. - /// \returns The flag value. - /// \details This is Cartesi-specific. - bool read_iflags_X() { - return derived().do_read_iflags_X(); - } - - /// \brief Reads the current privilege mode from iflags_PRV. - /// \details This is Cartesi-specific. - /// \returns Current privilege mode. - uint8_t read_iflags_PRV() { - return derived().do_read_iflags_PRV(); - } - - /// \brief Changes the privilege mode in iflags_PRV. - /// \details This is Cartesi-specific. - void write_iflags_PRV(uint8_t val) { - return derived().do_write_iflags_PRV(val); - } - /// \brief Reads CSR iunrep. /// \returns Register value. /// \details This is Cartesi-specific. diff --git a/src/interpret.cpp b/src/interpret.cpp index 572d317e..72d66d73 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -257,7 +257,7 @@ static void dump_exception_or_interrupt(uint64_t cause, STATE &s) { #ifdef DUMP_REGS template static void dump_regs(const STATE &s) { - const std::array priv_str{"USHM"}; + const std::array prv_str{"USHM"}; int cols = 256 / XLEN; std::ignore = fprintf(stderr, "pc = "); print_uint64_t(s.pc); @@ -280,7 +280,7 @@ static void dump_regs(const STATE &s) { std::ignore = fprintf(stderr, " "); } } - std::ignore = fprintf(stderr, "priv=%c", priv_str[s.iflags.PRV]); + std::ignore = fprintf(stderr, "prv=%c", prv_str[s.iprv]); std::ignore = fprintf(stderr, " mstatus="); print_uint64_t(s.mstatus); std::ignore = fprintf(stderr, " cycles=%" PRId64, s.mcycle); @@ -308,7 +308,7 @@ static inline bool csr_is_read_only(CSR_address csraddr) { /// \brief Extract privilege level from CSR address. /// \param csr Address of CSR in file. /// \returns Privilege level. -static inline uint32_t csr_priv(CSR_address csr) { +static inline uint32_t csr_prv(CSR_address csr) { return (to_underlying(csr) >> 8) & 3; } @@ -318,14 +318,14 @@ static inline uint32_t csr_priv(CSR_address csr) { /// \param new_prv New privilege level. /// \details This function is outlined to minimize host CPU code cache pressure. template -static NO_INLINE void set_priv(STATE_ACCESS &a, int new_prv) { - INC_COUNTER(a.get_statistics(), priv_level[new_prv]); - a.write_iflags_PRV(new_prv); +static NO_INLINE void set_prv(STATE_ACCESS &a, uint64_t new_prv) { + INC_COUNTER(a.get_statistics(), prv_level[new_prv]); + a.write_iprv(new_prv); // Invalidate all TLB entries a.flush_all_tlb(); INC_COUNTER(a.get_statistics(), tlb_flush_all); - INC_COUNTER(a.get_statistics(), tlb_flush_set_priv); - //??D new priv 1.11 draft says invalidation should + INC_COUNTER(a.get_statistics(), tlb_flush_set_prv); + //??D new privileged 1.11 draft says invalidation should // happen within a trap handler, although it could // also happen in xRET insn. a.write_ilrsc(-1); // invalidate reserved address @@ -380,8 +380,8 @@ static NO_INLINE uint64_t raise_exception(STATE_ACCESS &a, uint64_t pc, uint64_t // For each interrupt or exception number, there is a bit at mideleg // or medeleg saying if it should be delegated bool deleg = false; - auto priv = a.read_iflags_PRV(); - if (priv <= PRV_S) { + auto prv = a.read_iprv(); + if (prv <= PRV_S) { if (cause & MCAUSE_INTERRUPT_FLAG) { // Clear the MCAUSE_INTERRUPT_FLAG bit before shifting deleg = (a.read_mideleg() >> (cause & (XLEN - 1))) & 1; @@ -400,11 +400,11 @@ static NO_INLINE uint64_t raise_exception(STATE_ACCESS &a, uint64_t pc, uint64_t a.write_stval(tval); uint64_t mstatus = a.read_mstatus(); mstatus = (mstatus & ~MSTATUS_SPIE_MASK) | (((mstatus >> MSTATUS_SIE_SHIFT) & 1) << MSTATUS_SPIE_SHIFT); - mstatus = (mstatus & ~MSTATUS_SPP_MASK) | (priv << MSTATUS_SPP_SHIFT); + mstatus = (mstatus & ~MSTATUS_SPP_MASK) | (prv << MSTATUS_SPP_SHIFT); mstatus &= ~MSTATUS_SIE_MASK; a.write_mstatus(mstatus); - if (priv != PRV_S) { - set_priv(a, PRV_S); + if (prv != PRV_S) { + set_prv(a, PRV_S); } new_pc = a.read_stvec(); #ifdef DUMP_COUNTERS @@ -420,11 +420,11 @@ static NO_INLINE uint64_t raise_exception(STATE_ACCESS &a, uint64_t pc, uint64_t a.write_mtval(tval); uint64_t mstatus = a.read_mstatus(); mstatus = (mstatus & ~MSTATUS_MPIE_MASK) | (((mstatus >> MSTATUS_MIE_SHIFT) & 1) << MSTATUS_MPIE_SHIFT); - mstatus = (mstatus & ~MSTATUS_MPP_MASK) | (priv << MSTATUS_MPP_SHIFT); + mstatus = (mstatus & ~MSTATUS_MPP_MASK) | (prv << MSTATUS_MPP_SHIFT); mstatus &= ~MSTATUS_MIE_MASK; a.write_mstatus(mstatus); - if (priv != PRV_M) { - set_priv(a, PRV_M); + if (prv != PRV_M) { + set_prv(a, PRV_M); } new_pc = a.read_mtvec(); #ifdef DUMP_COUNTERS @@ -453,8 +453,8 @@ static inline uint32_t get_pending_irq_mask(STATE_ACCESS &a) { } uint32_t enabled_ints = 0; - auto priv = a.read_iflags_PRV(); - switch (priv) { + auto prv = a.read_iprv(); + switch (prv) { // interrupt trap condition 1a: the current privilege mode is M case PRV_M: { const uint64_t mstatus = a.read_mstatus(); @@ -1484,10 +1484,10 @@ static inline uint64_t read_csr_success(uint64_t val, bool *status) { template static inline bool rdcounteren(STATE_ACCESS &a, uint64_t mask) { uint64_t counteren = MCOUNTEREN_R_MASK; - auto priv = a.read_iflags_PRV(); - if (priv <= PRV_S) { + auto prv = a.read_iprv(); + if (prv <= PRV_S) { counteren &= a.read_mcounteren(); - if (priv < PRV_S) { + if (prv < PRV_S) { counteren &= a.read_scounteren(); } } @@ -1579,10 +1579,10 @@ static inline uint64_t read_csr_sip(STATE_ACCESS &a, bool *status) { template static inline uint64_t read_csr_satp(STATE_ACCESS &a, bool *status) { const uint64_t mstatus = a.read_mstatus(); - auto priv = a.read_iflags_PRV(); + auto prv = a.read_iprv(); // When TVM=1, attempts to read or write the satp CSR // while executing in S-mode will raise an illegal instruction exception - if (unlikely(priv == PRV_S && (mstatus & MSTATUS_TVM_MASK))) { + if (unlikely(prv == PRV_S && (mstatus & MSTATUS_TVM_MASK))) { return read_csr_fail(status); } return read_csr_success(a.read_satp(), status); @@ -1716,7 +1716,7 @@ static inline uint64_t read_csr_fcsr(STATE_ACCESS &a, bool *status) { /// \details This function is outlined to minimize host CPU code cache pressure. template static NO_INLINE uint64_t read_csr(STATE_ACCESS &a, uint64_t mcycle, CSR_address csraddr, bool *status) { - if (unlikely(csr_priv(csraddr) > a.read_iflags_PRV())) { + if (unlikely(csr_prv(csraddr) > a.read_iprv())) { return read_csr_fail(status); } @@ -1945,11 +1945,11 @@ static execute_status write_csr_sip(STATE_ACCESS &a, uint64_t val) { template static NO_INLINE execute_status write_csr_satp(STATE_ACCESS &a, uint64_t val) { const uint64_t mstatus = a.read_mstatus(); - auto priv = a.read_iflags_PRV(); + auto prv = a.read_iprv(); // When TVM=1, attempts to read or write the satp CSR // while executing in S-mode will raise an illegal instruction exception - if (unlikely(priv == PRV_S && (mstatus & MSTATUS_TVM_MASK))) { + if (unlikely(prv == PRV_S && (mstatus & MSTATUS_TVM_MASK))) { return execute_status::failure; } @@ -2222,7 +2222,7 @@ static NO_INLINE execute_status write_csr(STATE_ACCESS &a, uint64_t mcycle, CSR_ if (unlikely(csr_is_read_only(csraddr))) { return execute_status::failure; } - if (unlikely(csr_priv(csraddr) > a.read_iflags_PRV())) { + if (unlikely(csr_prv(csraddr) > a.read_iprv())) { return execute_status::failure; } @@ -2511,8 +2511,8 @@ static FORCE_INLINE execute_status execute_CSRRCI(STATE_ACCESS &a, uint64_t &pc, template static FORCE_INLINE execute_status execute_ECALL(STATE_ACCESS &a, uint64_t &pc, uint32_t insn) { dump_insn(a, pc, insn, "ecall"); - auto priv = a.read_iflags_PRV(); - pc = raise_exception(a, pc, MCAUSE_ECALL_BASE + priv, 0); + auto prv = a.read_iprv(); + pc = raise_exception(a, pc, MCAUSE_ECALL_BASE + prv, 0); return execute_status::failure; } @@ -2528,9 +2528,9 @@ static FORCE_INLINE execute_status execute_EBREAK(STATE_ACCESS &a, uint64_t &pc, template static FORCE_INLINE execute_status execute_SRET(STATE_ACCESS &a, uint64_t &pc, uint32_t insn) { dump_insn(a, pc, insn, "sret"); - auto priv = a.read_iflags_PRV(); + auto prv = a.read_iprv(); uint64_t mstatus = a.read_mstatus(); - if (unlikely(priv < PRV_S || (priv == PRV_S && (mstatus & MSTATUS_TSR_MASK)))) { + if (unlikely(prv < PRV_S || (prv == PRV_S && (mstatus & MSTATUS_TSR_MASK)))) { return raise_illegal_insn_exception(a, pc, insn); } auto spp = (mstatus & MSTATUS_SPP_MASK) >> MSTATUS_SPP_SHIFT; @@ -2547,8 +2547,8 @@ static FORCE_INLINE execute_status execute_SRET(STATE_ACCESS &a, uint64_t &pc, u mstatus &= ~MSTATUS_MPRV_MASK; } a.write_mstatus(mstatus); - if (priv != spp) { - set_priv(a, spp); + if (prv != spp) { + set_prv(a, spp); } pc = a.read_sepc(); return execute_status::success_and_serve_interrupts; @@ -2558,8 +2558,8 @@ static FORCE_INLINE execute_status execute_SRET(STATE_ACCESS &a, uint64_t &pc, u template static FORCE_INLINE execute_status execute_MRET(STATE_ACCESS &a, uint64_t &pc, uint32_t insn) { dump_insn(a, pc, insn, "mret"); - auto priv = a.read_iflags_PRV(); - if (unlikely(priv < PRV_M)) { + auto prv = a.read_iprv(); + if (unlikely(prv < PRV_M)) { return raise_illegal_insn_exception(a, pc, insn); } uint64_t mstatus = a.read_mstatus(); @@ -2578,8 +2578,8 @@ static FORCE_INLINE execute_status execute_MRET(STATE_ACCESS &a, uint64_t &pc, u mstatus &= ~MSTATUS_MPRV_MASK; } a.write_mstatus(mstatus); - if (priv != mpp) { - set_priv(a, mpp); + if (prv != mpp) { + set_prv(a, mpp); } pc = a.read_mepc(); return execute_status::success_and_serve_interrupts; @@ -2591,10 +2591,10 @@ template static FORCE_INLINE execute_status execute_WFI(STATE_ACCESS &a, uint64_t &pc, uint64_t &mcycle, uint32_t insn) { dump_insn(a, pc, insn, "wfi"); // Check privileges and do nothing else - auto priv = a.read_iflags_PRV(); + auto prv = a.read_iprv(); const uint64_t mstatus = a.read_mstatus(); // WFI can always causes an illegal instruction exception in less-privileged modes when TW=1 - if (unlikely(priv == PRV_U || (priv < PRV_M && (mstatus & MSTATUS_TW_MASK)))) { + if (unlikely(prv == PRV_U || (prv < PRV_M && (mstatus & MSTATUS_TW_MASK)))) { return raise_illegal_insn_exception(a, pc, insn); } // We wait for interrupts until the next timer interrupt. @@ -3203,12 +3203,12 @@ static FORCE_INLINE execute_status execute_SFENCE_VMA(STATE_ACCESS &a, uint64_t } INC_COUNTER(a.get_statistics(), fence_vma); dump_insn(a, pc, insn, "sfence.vma"); - auto priv = a.read_iflags_PRV(); + auto prv = a.read_iprv(); const uint64_t mstatus = a.read_mstatus(); // When TVM=1, attempts to execute an SFENCE.VMA while executing in S-mode // will raise an illegal instruction exception. - if (unlikely(priv == PRV_U || (priv == PRV_S && (mstatus & MSTATUS_TVM_MASK)))) { + if (unlikely(prv == PRV_U || (prv == PRV_S && (mstatus & MSTATUS_TVM_MASK)))) { return raise_illegal_insn_exception(a, pc, insn); } const uint32_t rs1 = insn_get_rs1(insn); @@ -5620,20 +5620,20 @@ interpreter_break_reason interpret(STATE_ACCESS &a, uint64_t mcycle_end) { } // Just reset the automatic yield flag and continue - a.reset_iflags_X(); + a.write_iflags_X(0); // Run the interpreter loop, // the loop is outlined in a dedicated function so the compiler can optimize it better const execute_status status = interpret_loop(a, mcycle_end, mcycle); // Detect and return the reason for stopping the interpreter loop - if (a.read_iflags_H()) { + if (a.read_iflags_H() != 0) { return interpreter_break_reason::halted; } - if (a.read_iflags_Y()) { + if (a.read_iflags_Y() != 0) { return interpreter_break_reason::yielded_manually; } - if (a.read_iflags_X()) { + if (a.read_iflags_X() != 0) { return interpreter_break_reason::yielded_automatically; } if (status == execute_status::success_and_yield) { diff --git a/src/json-util.cpp b/src/json-util.cpp index 4469bbef..2d41a789 100644 --- a/src/json-util.cpp +++ b/src/json-util.cpp @@ -166,11 +166,10 @@ static auto reg_from_name(const std::string &name) { {"scounteren", reg::scounteren}, {"senvcfg", reg::senvcfg}, {"ilrsc", reg::ilrsc}, - {"iflags", reg::iflags}, - {"iflags_prv", reg::iflags_prv}, - {"iflags_x", reg::iflags_x}, - {"iflags_y", reg::iflags_y}, - {"iflags_h", reg::iflags_h}, + {"iprv", reg::iprv}, + {"iflags_X", reg::iflags_X}, + {"iflags_Y", reg::iflags_Y}, + {"iflags_H", reg::iflags_H}, {"iunrep", reg::iunrep}, {"clint_mtimecmp", reg::clint_mtimecmp}, {"plic_girqpend", reg::plic_girqpend}, @@ -420,16 +419,14 @@ static auto reg_to_name(machine::reg r) { return "senvcfg"; case reg::ilrsc: return "ilrsc"; - case reg::iflags: - return "iflags"; - case reg::iflags_prv: - return "iflags_prv"; - case reg::iflags_x: - return "iflags_x"; - case reg::iflags_y: - return "iflags_y"; - case reg::iflags_h: - return "iflags_h"; + case reg::iprv: + return "iprv"; + case reg::iflags_X: + return "iflags_X"; + case reg::iflags_Y: + return "iflags_Y"; + case reg::iflags_H: + return "iflags_H"; case reg::iunrep: return "iunrep"; case reg::clint_mtimecmp: @@ -1261,7 +1258,10 @@ void ju_get_opt_field(const nlohmann::json &j, const K &key, processor_config &v ju_get_opt_field(jconfig, "scounteren"s, value.scounteren, new_path); ju_get_opt_field(jconfig, "senvcfg"s, value.senvcfg, new_path); ju_get_opt_field(jconfig, "ilrsc"s, value.ilrsc, new_path); - ju_get_opt_field(jconfig, "iflags"s, value.iflags, new_path); + ju_get_opt_field(jconfig, "iprv"s, value.iprv, new_path); + ju_get_opt_field(jconfig, "iflags_X"s, value.iflags_X, new_path); + ju_get_opt_field(jconfig, "iflags_Y"s, value.iflags_Y, new_path); + ju_get_opt_field(jconfig, "iflags_H"s, value.iflags_H, new_path); ju_get_opt_field(jconfig, "iunrep"s, value.iunrep, new_path); } @@ -1803,7 +1803,8 @@ void to_json(nlohmann::json &j, const processor_config &config) { {"medeleg", config.medeleg}, {"mideleg", config.mideleg}, {"mcounteren", config.mcounteren}, {"menvcfg", config.menvcfg}, {"stvec", config.stvec}, {"sscratch", config.sscratch}, {"sepc", config.sepc}, {"scause", config.scause}, {"stval", config.stval}, {"satp", config.satp}, {"scounteren", config.scounteren}, - {"senvcfg", config.senvcfg}, {"ilrsc", config.ilrsc}, {"iflags", config.iflags}, {"iunrep", config.iunrep}}; + {"senvcfg", config.senvcfg}, {"ilrsc", config.ilrsc}, {"iprv", config.iprv}, {"iflags_X", config.iflags_X}, + {"iflags_Y", config.iflags_Y}, {"iflags_H", config.iflags_H}, {"iunrep", config.iunrep}}; } void to_json(nlohmann::json &j, const flash_drive_configs &fs) { diff --git a/src/jsonrpc-discover.json b/src/jsonrpc-discover.json index 2f8a2cba..05b4e9fd 100644 --- a/src/jsonrpc-discover.json +++ b/src/jsonrpc-discover.json @@ -1283,7 +1283,16 @@ "ilrsc": { "$ref": "#/components/schemas/UnsignedInteger" }, - "iflags": { + "iprv": { + "$ref": "#/components/schemas/UnsignedInteger" + }, + "iflags_X": { + "$ref": "#/components/schemas/UnsignedInteger" + }, + "iflags_Y": { + "$ref": "#/components/schemas/UnsignedInteger" + }, + "iflags_H": { "$ref": "#/components/schemas/UnsignedInteger" }, "iunrep": { diff --git a/src/machine-c-api.cpp b/src/machine-c-api.cpp index 1a3735b0..e6c92315 100644 --- a/src/machine-c-api.cpp +++ b/src/machine-c-api.cpp @@ -315,8 +315,14 @@ static cartesi::machine_reg convert_from_c(cm_reg r) { return reg::senvcfg; case CM_REG_ILRSC: return reg::ilrsc; - case CM_REG_IFLAGS: - return reg::iflags; + case CM_REG_IPRV: + return reg::iprv; + case CM_REG_IFLAGS_X: + return reg::iflags_X; + case CM_REG_IFLAGS_Y: + return reg::iflags_Y; + case CM_REG_IFLAGS_H: + return reg::iflags_H; case CM_REG_IUNREP: return reg::iunrep; case CM_REG_CLINT_MTIMECMP: @@ -405,14 +411,6 @@ static cartesi::machine_reg convert_from_c(cm_reg r) { return reg::uarch_cycle; case CM_REG_UARCH_HALT_FLAG: return reg::uarch_halt_flag; - case CM_REG_IFLAGS_PRV: - return reg::iflags_prv; - case CM_REG_IFLAGS_X: - return reg::iflags_x; - case CM_REG_IFLAGS_Y: - return reg::iflags_y; - case CM_REG_IFLAGS_H: - return reg::iflags_h; case CM_REG_HTIF_TOHOST_DEV: return reg::htif_tohost_dev; case CM_REG_HTIF_TOHOST_CMD: @@ -915,64 +913,6 @@ cm_error cm_read_uarch_cycle(const cm_machine *m, uint64_t *val) try { return cm_result_failure(); } -cm_error cm_read_iflags_Y(const cm_machine *m, bool *val) try { - if (val == nullptr) { - throw std::invalid_argument("invalid val output"); - } - const auto *cpp_m = convert_from_c(m); - *val = static_cast(cpp_m->read_reg(cartesi::machine::reg::iflags_y)); - return cm_result_success(); -} catch (...) { - if (val != nullptr) { - *val = false; - } - return cm_result_failure(); -} - -cm_error cm_reset_iflags_Y(cm_machine *m) try { - auto *cpp_m = convert_from_c(m); - cpp_m->write_reg(cartesi::machine::reg::iflags_y, 0); - return cm_result_success(); -} catch (...) { - return cm_result_failure(); -} - -cm_error cm_set_iflags_Y(cm_machine *m) try { - auto *cpp_m = convert_from_c(m); - cpp_m->write_reg(cartesi::machine::reg::iflags_y, 1); - return cm_result_success(); -} catch (...) { - return cm_result_failure(); -} - -cm_error cm_read_iflags_X(const cm_machine *m, bool *val) try { - if (val == nullptr) { - throw std::invalid_argument("invalid val output"); - } - const auto *cpp_m = convert_from_c(m); - *val = static_cast(cpp_m->read_reg(cartesi::machine::reg::iflags_x)); - return cm_result_success(); -} catch (...) { - if (val != nullptr) { - *val = false; - } - return cm_result_failure(); -} - -cm_error cm_read_iflags_H(const cm_machine *m, bool *val) try { - if (val == nullptr) { - throw std::invalid_argument("invalid val output"); - } - const auto *cpp_m = convert_from_c(m); - *val = static_cast(cpp_m->read_reg(cartesi::machine::reg::iflags_h)); - return cm_result_success(); -} catch (...) { - if (val != nullptr) { - *val = false; - } - return cm_result_failure(); -} - cm_error cm_verify_dirty_page_maps(cm_machine *m, bool *result) try { if (result == nullptr) { throw std::invalid_argument("invalid result output"); @@ -1101,8 +1041,8 @@ cm_error cm_receive_cmio_request(const cm_machine *m, uint8_t *cmd, uint16_t *re const auto *cpp_m = convert_from_c(m); // NOTE(edubart): This can be implemented on top of other APIs, // implementing in the C++ machine class would add lot of boilerplate code in all interfaces. - if ((cpp_m->read_reg(cartesi::machine::reg::iflags_x) == 0) && - (cpp_m->read_reg(cartesi::machine::reg::iflags_y) == 0)) { + if ((cpp_m->read_reg(cartesi::machine::reg::iflags_X) == 0) && + (cpp_m->read_reg(cartesi::machine::reg::iflags_Y) == 0)) { throw std::runtime_error{"machine is not yielded"}; } const uint64_t tohost = cpp_m->read_reg(cartesi::machine::reg::htif_tohost); diff --git a/src/machine-c-api.h b/src/machine-c-api.h index d0d5770b..a3e904d9 100644 --- a/src/machine-c-api.h +++ b/src/machine-c-api.h @@ -226,7 +226,10 @@ typedef enum cm_reg { CM_REG_SCOUNTEREN, CM_REG_SENVCFG, CM_REG_ILRSC, - CM_REG_IFLAGS, + CM_REG_IPRV, + CM_REG_IFLAGS_X, + CM_REG_IFLAGS_Y, + CM_REG_IFLAGS_H, CM_REG_IUNREP, // Device registers CM_REG_CLINT_MTIMECMP, @@ -274,10 +277,6 @@ typedef enum cm_reg { CM_REG_UARCH_CYCLE, CM_REG_UARCH_HALT_FLAG, // Views of registers - CM_REG_IFLAGS_PRV, - CM_REG_IFLAGS_X, - CM_REG_IFLAGS_Y, - CM_REG_IFLAGS_H, CM_REG_HTIF_TOHOST_DEV, CM_REG_HTIF_TOHOST_CMD, CM_REG_HTIF_TOHOST_REASON, @@ -568,57 +567,6 @@ CM_API cm_error cm_write_virtual_memory(cm_machine *m, uint64_t address, const u /// \detail The translation is based on the current mapping, as defined in CM_REG_SATP. CM_API cm_error cm_translate_virtual_address(cm_machine *m, uint64_t vaddr, uint64_t *paddr); -/// \brief Reads the value of the CM_REG_MCYCLE. -/// \param m Pointer to a non-empty machine object (holds a machine instance). -/// \param val Receives the value. -/// \returns 0 for success, non zero code for error. -CM_API cm_error cm_read_mcycle(const cm_machine *m, uint64_t *val); - -/// \brief Reads the value of the X flag in CM_REG_IFLAGS. -/// \param m Pointer to a non-empty machine object (holds a machine instance). -/// \param val Receives the value. -/// \returns 0 for success, non zero code for error. -CM_API cm_error cm_read_iflags_X(const cm_machine *m, bool *val); - -/// \brief Reads the value of the Y flag in CM_REG_IFLAGS. -/// \param m Pointer to a non-empty machine object (holds a machine instance). -/// \param val Receives the value. -/// \returns 0 for success, non zero code for error. -CM_API cm_error cm_read_iflags_Y(const cm_machine *m, bool *val); - -/// \brief Resets the value of the Y flag in CM_REG_IFLAGS. -/// \param m Pointer to a non-empty machine object (holds a machine instance). -/// \returns 0 for success, non zero code for error. -CM_API cm_error cm_reset_iflags_Y(cm_machine *m); - -/// \brief Sets the Y flag in CM_REG_IFLAGS. -/// \param m Pointer to a non-empty machine object (holds a machine instance). -/// \returns 0 for success, non zero code for error. -CM_API cm_error cm_set_iflags_Y(cm_machine *m); - -/// \brief Reads the value of the H flag in CM_REG_IFLAGS. -/// \param m Pointer to a non-empty machine object (holds a machine instance). -/// \param val Receives the value. -/// \returns 0 for success, non zero code for error. -CM_API cm_error cm_read_iflags_H(const cm_machine *m, bool *val); - -/// \brief Reads the value of CM_REG_UARCH_CYCLE. -/// \param m Pointer to a non-empty machine object (holds a machine instance). -/// \param val Receives the value. -/// \returns 0 for success, non zero code for error. -CM_API cm_error cm_read_uarch_cycle(const cm_machine *m, uint64_t *val); - -/// \brief Reads the value of CM_REG_UARCH_HALT_FLAG. -/// \param m Pointer to a non-empty machine object (holds a machine instance). -/// \param val Receives the value. -/// \returns 0 for success, non zero code for error. -CM_API cm_error cm_read_uarch_halt_flag(const cm_machine *m, bool *val); - -/// \brief Sets the value of CM_REG_UARCH_HALT_FLAG. -/// \param m Pointer to a non-empty machine object (holds a machine instance). -/// \returns 0 for success, non zero code for error. -CM_API cm_error cm_set_uarch_halt_flag(cm_machine *m); - // ------------------------------------ // Running // ------------------------------------ diff --git a/src/machine-config.h b/src/machine-config.h index d37813fd..30beab49 100644 --- a/src/machine-config.h +++ b/src/machine-config.h @@ -72,7 +72,10 @@ struct processor_config final { uint64_t scounteren{SCOUNTEREN_INIT}; ///< Value of scounteren CSR uint64_t senvcfg{SENVCFG_INIT}; ///< Value of senvcfg CSR uint64_t ilrsc{ILRSC_INIT}; ///< Value of ilrsc CSR - uint64_t iflags{IFLAGS_INIT}; ///< Value of iflags CSR + uint64_t iprv{IPRV_INIT}; ///< Value of iprv CSR + uint64_t iflags_X{IFLAGS_X_INIT}; ///< Value of iflags_X CSR + uint64_t iflags_Y{IFLAGS_Y_INIT}; ///< Value of iflags_Y CSR + uint64_t iflags_H{IFLAGS_H_INIT}; ///< Value of iflags_H CSR uint64_t iunrep{IUNREP_INIT}; ///< Value of iunrep CSR }; diff --git a/src/machine-reg.h b/src/machine-reg.h index 0adafed9..c5a95ae5 100644 --- a/src/machine-reg.h +++ b/src/machine-reg.h @@ -122,7 +122,10 @@ enum class machine_reg : uint64_t { scounteren = PMA_SHADOW_STATE_START + offsetof(shadow_state, scounteren), senvcfg = PMA_SHADOW_STATE_START + offsetof(shadow_state, senvcfg), ilrsc = PMA_SHADOW_STATE_START + offsetof(shadow_state, ilrsc), - iflags = PMA_SHADOW_STATE_START + offsetof(shadow_state, iflags), + iprv = PMA_SHADOW_STATE_START + offsetof(shadow_state, iprv), + iflags_X = PMA_SHADOW_STATE_START + offsetof(shadow_state, iflags_X), + iflags_Y = PMA_SHADOW_STATE_START + offsetof(shadow_state, iflags_Y), + iflags_H = PMA_SHADOW_STATE_START + offsetof(shadow_state, iflags_H), iunrep = PMA_SHADOW_STATE_START + offsetof(shadow_state, iunrep), clint_mtimecmp = PMA_SHADOW_STATE_START + offsetof(shadow_state, clint_mtimecmp), plic_girqpend = PMA_SHADOW_STATE_START + offsetof(shadow_state, plic_girqpend), @@ -174,10 +177,6 @@ enum class machine_reg : uint64_t { uarch_last_ = uarch_x31, // Views of registers - iflags_prv, - iflags_x, - iflags_y, - iflags_h, htif_tohost_dev, htif_tohost_cmd, htif_tohost_reason, diff --git a/src/machine-state.h b/src/machine-state.h index 915b9c8b..0d71b3bb 100644 --- a/src/machine-state.h +++ b/src/machine-state.h @@ -36,14 +36,6 @@ namespace cartesi { -/// \brief Cartesi-specific unpacked CSR iflags. -struct unpacked_iflags { - uint8_t PRV; ///< Privilege level. - bool X; ///< CPU has yielded with automatic reset. - bool Y; ///< CPU has yielded with manual reset. - bool H; ///< CPU has been permanently halted. -}; - /// \brief Machine state. /// \details The machine_state structure contains the entire /// state of a Cartesi machine. @@ -92,10 +84,14 @@ struct machine_state { uint64_t senvcfg{}; ///< CSR senvcfg. // Cartesi-specific state - uint64_t ilrsc{}; ///< Cartesi-specific CSR ilrsc (For LR/SC instructions). - uint64_t iunrep{}; ///< Cartesi-specific CSR iunrep - - unpacked_iflags iflags{}; ///< Cartesi-specific unpacked CSR iflags. + uint64_t ilrsc{}; ///< For LR/SC instructions (Cartesi-specific). + uint64_t iprv{}; ///< Privilege level (Cartesi-specific). + struct { + uint64_t X{}; ///< CPU has yielded with automatic reset (Cartesi-specific). + uint64_t Y{}; ///< CPU has yielded with manual reset (Cartesi-specific). + uint64_t H{}; ///< CPU has been permanently halted (Cartesi-specific). + } iflags; + uint64_t iunrep{}; ///< Unreproducible mode (Cartesi-specific). /// \brief CLINT state struct { @@ -137,32 +133,6 @@ struct machine_state { #ifdef DUMP_HIST std::unordered_map insn_hist; #endif - - /// \brief Reads the value of the iflags register. - /// \returns The value of the register. - uint64_t read_iflags() const { - return packed_iflags(iflags.PRV, static_cast(iflags.X), static_cast(iflags.Y), - static_cast(iflags.H)); - } - - /// \brief Reads the value of the iflags register. - /// \param val New register value. - void write_iflags(uint64_t val) { - iflags.H = (((val >> IFLAGS_H_SHIFT) & 1) != 0); - iflags.Y = (((val >> IFLAGS_Y_SHIFT) & 1) != 0); - iflags.X = (((val >> IFLAGS_X_SHIFT) & 1) != 0); - iflags.PRV = (val >> IFLAGS_PRV_SHIFT) & 3; - } - - /// \brief Packs iflags into the CSR value - /// \param PRV privilege level - /// \param I Waiting for interrupts flag - /// \param Y Yielded flag - /// \param H Halted flag - /// \returns Packed iflags - static uint64_t packed_iflags(int PRV, int X, int Y, int H) { - return (PRV << IFLAGS_PRV_SHIFT) | (X << IFLAGS_X_SHIFT) | (Y << IFLAGS_Y_SHIFT) | (H << IFLAGS_H_SHIFT); - } }; } // namespace cartesi diff --git a/src/machine-statistics.h b/src/machine-statistics.h index a6aeb439..e0221d68 100644 --- a/src/machine-statistics.h +++ b/src/machine-statistics.h @@ -23,20 +23,20 @@ namespace cartesi { /// \brief Machine statistics struct machine_statistics { - uint64_t inner_loop; ///< Counts executions of inner loop - uint64_t outer_loop; ///< Counts executions of outer loop - uint64_t sv_int; ///< Counts supervisor interrupts - uint64_t sv_ex; ///< Counts supervisor exceptions (except ECALL) - uint64_t m_int; ///< Counts machine interrupts - uint64_t m_ex; ///< Counts machine exceptions (except ECALL) - uint64_t atomic_mop; ///< Counts atomic memory operations - uint64_t flush_all; ///< Counts flush all calls - uint64_t flush_va; ///< Counts flush virtual address calls - uint64_t fence; ///< Counts fence calls - uint64_t fence_i; ///< Counts fence.i calls - uint64_t fence_vma; ///< Counts fence.vma calls - uint64_t max_asid; ///< Counts the maximum number of used ASIDs (only relevant when ASIDLEN > 0) - uint64_t priv_level[4]; ///< Counts changes to privilege levels + uint64_t inner_loop; ///< Counts executions of inner loop + uint64_t outer_loop; ///< Counts executions of outer loop + uint64_t sv_int; ///< Counts supervisor interrupts + uint64_t sv_ex; ///< Counts supervisor exceptions (except ECALL) + uint64_t m_int; ///< Counts machine interrupts + uint64_t m_ex; ///< Counts machine exceptions (except ECALL) + uint64_t atomic_mop; ///< Counts atomic memory operations + uint64_t flush_all; ///< Counts flush all calls + uint64_t flush_va; ///< Counts flush virtual address calls + uint64_t fence; ///< Counts fence calls + uint64_t fence_i; ///< Counts fence.i calls + uint64_t fence_vma; ///< Counts fence.vma calls + uint64_t max_asid; ///< Counts the maximum number of used ASIDs (only relevant when ASIDLEN > 0) + uint64_t prv_level[4]; ///< Counts changes to prvilege levels // TLB uint64_t tlb_chit; ///< Counts TLB code access hits @@ -51,7 +51,7 @@ struct machine_statistics { uint64_t tlb_flush_write; ///< Counts write TLB flush calls uint64_t tlb_flush_satp; ///< Counts TLB flush originated from satp changes uint64_t tlb_flush_mstatus; ///< Counts TLB flush originated from mstatus changes - uint64_t tlb_flush_set_priv; ///< Counts TLB flush originated from set_priv changes + uint64_t tlb_flush_set_prv; ///< Counts TLB flush originated from set_prv changes uint64_t tlb_flush_fence_vma_all; ///< Counts TLB flush originated from SFENCE.VMA (all) uint64_t tlb_flush_fence_vma_asid; ///< Counts TLB flush originated from SFENCE.VMA (asid) uint64_t tlb_flush_fence_vma_vaddr; ///< Counts TLB flush originated from SFENCE.VMA (vaddr) diff --git a/src/machine.cpp b/src/machine.cpp index 8525836b..6c6eca5b 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -341,7 +341,10 @@ machine::machine(const machine_config &c, const machine_runtime_config &r) : m_c write_reg(reg::scounteren, m_c.processor.scounteren); write_reg(reg::senvcfg, m_c.processor.senvcfg); write_reg(reg::ilrsc, m_c.processor.ilrsc); - write_reg(reg::iflags, m_c.processor.iflags); + write_reg(reg::iprv, m_c.processor.iprv); + write_reg(reg::iflags_X, m_c.processor.iflags_X); + write_reg(reg::iflags_Y, m_c.processor.iflags_Y); + write_reg(reg::iflags_H, m_c.processor.iflags_H); write_reg(reg::iunrep, m_c.processor.iunrep); // Register RAM @@ -668,7 +671,10 @@ machine_config machine::get_serialization_config() const { c.processor.scounteren = read_reg(reg::scounteren); c.processor.senvcfg = read_reg(reg::senvcfg); c.processor.ilrsc = read_reg(reg::ilrsc); - c.processor.iflags = read_reg(reg::iflags); + c.processor.iprv = read_reg(reg::iprv); + c.processor.iflags_X = read_reg(reg::iflags_X); + c.processor.iflags_Y = read_reg(reg::iflags_Y); + c.processor.iflags_H = read_reg(reg::iflags_H); c.processor.iunrep = read_reg(reg::iunrep); // Copy current CLINT state to config c.clint.mtimecmp = read_reg(reg::clint_mtimecmp); @@ -854,9 +860,9 @@ machine::~machine() { std::ignore = fprintf(stderr, "fence.i: %" PRIu64 "\n", m_s.stats.fence_i); std::ignore = fprintf(stderr, "fence.vma: %" PRIu64 "\n", m_s.stats.fence_vma); std::ignore = fprintf(stderr, "max asid: %" PRIu64 "\n", m_s.stats.max_asid); - std::ignore = fprintf(stderr, "User mode: %" PRIu64 "\n", m_s.stats.priv_level[PRV_U]); - std::ignore = fprintf(stderr, "Supervisor mode: %" PRIu64 "\n", m_s.stats.priv_level[PRV_S]); - std::ignore = fprintf(stderr, "Machine mode: %" PRIu64 "\n", m_s.stats.priv_level[PRV_M]); + std::ignore = fprintf(stderr, "User mode: %" PRIu64 "\n", m_s.stats.prv_level[PRV_U]); + std::ignore = fprintf(stderr, "Supervisor mode: %" PRIu64 "\n", m_s.stats.prv_level[PRV_S]); + std::ignore = fprintf(stderr, "Machine mode: %" PRIu64 "\n", m_s.stats.prv_level[PRV_M]); std::ignore = fprintf(stderr, "tlb code hit ratio: %.4f\n", TLB_HIT_RATIO(m_s, tlb_cmiss, tlb_chit)); std::ignore = fprintf(stderr, "tlb read hit ratio: %.4f\n", TLB_HIT_RATIO(m_s, tlb_rmiss, tlb_rhit)); @@ -873,7 +879,7 @@ machine::~machine() { std::ignore = fprintf(stderr, "tlb_flush_vaddr: %" PRIu64 "\n", m_s.stats.tlb_flush_vaddr); std::ignore = fprintf(stderr, "tlb_flush_satp: %" PRIu64 "\n", m_s.stats.tlb_flush_satp); std::ignore = fprintf(stderr, "tlb_flush_mstatus: %" PRIu64 "\n", m_s.stats.tlb_flush_mstatus); - std::ignore = fprintf(stderr, "tlb_flush_set_priv: %" PRIu64 "\n", m_s.stats.tlb_flush_set_priv); + std::ignore = fprintf(stderr, "tlb_flush_set_prv: %" PRIu64 "\n", m_s.stats.tlb_flush_set_prv); std::ignore = fprintf(stderr, "tlb_flush_fence_vma_all: %" PRIu64 "\n", m_s.stats.tlb_flush_fence_vma_all); std::ignore = fprintf(stderr, "tlb_flush_fence_vma_asid: %" PRIu64 "\n", m_s.stats.tlb_flush_fence_vma_asid); std::ignore = fprintf(stderr, "tlb_flush_fence_vma_vaddr: %" PRIu64 "\n", m_s.stats.tlb_flush_fence_vma_vaddr); @@ -1070,8 +1076,14 @@ uint64_t machine::read_reg(reg r) const { return m_s.senvcfg; case reg::ilrsc: return m_s.ilrsc; - case reg::iflags: - return m_s.read_iflags(); + case reg::iprv: + return m_s.iprv; + case reg::iflags_X: + return m_s.iflags.X; + case reg::iflags_Y: + return m_s.iflags.Y; + case reg::iflags_H: + return m_s.iflags.H; case reg::iunrep: return m_s.iunrep; case reg::clint_mtimecmp: @@ -1160,14 +1172,6 @@ uint64_t machine::read_reg(reg r) const { return m_uarch.get_state().cycle; case reg::uarch_halt_flag: return static_cast(m_uarch.get_state().halt_flag); - case reg::iflags_prv: - return m_s.iflags.PRV; - case reg::iflags_x: - return static_cast(m_s.iflags.X); - case reg::iflags_y: - return static_cast(m_s.iflags.Y); - case reg::iflags_h: - return static_cast(m_s.iflags.H); case reg::htif_tohost_dev: return HTIF_DEV_FIELD(m_s.htif.tohost); case reg::htif_tohost_cmd: @@ -1467,8 +1471,17 @@ void machine::write_reg(reg w, uint64_t value) { case reg::ilrsc: m_s.ilrsc = value; break; - case reg::iflags: - m_s.write_iflags(value); + case reg::iprv: + m_s.iprv = value; + break; + case reg::iflags_X: + m_s.iflags.X = value; + break; + case reg::iflags_Y: + m_s.iflags.Y = value; + break; + case reg::iflags_H: + m_s.iflags.H = value; break; case reg::iunrep: m_s.iunrep = value; @@ -1601,18 +1614,6 @@ void machine::write_reg(reg w, uint64_t value) { case reg::uarch_halt_flag: m_uarch.get_state().halt_flag = static_cast(value); break; - case reg::iflags_prv: - m_s.iflags.PRV = static_cast(value); - break; - case reg::iflags_x: - m_s.iflags.X = static_cast(value); - break; - case reg::iflags_y: - m_s.iflags.Y = static_cast(value); - break; - case reg::iflags_h: - m_s.iflags.H = static_cast(value); - break; case reg::htif_tohost_dev: m_s.htif.tohost = HTIF_REPLACE_DEV(m_s.htif.tohost, value); break; diff --git a/src/record-state-access.h b/src/record-state-access.h index f7e7a480..7df3b90b 100644 --- a/src/record-state-access.h +++ b/src/record-state-access.h @@ -199,18 +199,13 @@ class record_state_access : public i_state_accesspush_bracket(type, text); } - void do_reset_iflags_Y() { - auto new_iflags = machine_state::packed_iflags(m_m.get_state().iflags.PRV, - static_cast(m_m.get_state().iflags.X), 0 /* Y */, static_cast(m_m.get_state().iflags.H)); - const uint64_t iflags_addr = machine_reg_address(machine_reg::iflags); - log_read(iflags_addr, "iflags.Y"); - log_before_write(iflags_addr, new_iflags, "iflags.Y"); - m_m.get_state().iflags.Y = false; - update_after_write(iflags_addr); + void do_write_iflags_Y(uint64_t val) { + log_before_write_write_and_update(machine_reg_address(machine_reg::iflags_Y), m_m.get_state().iflags.Y, val, + "iflags.Y"); } - bool do_read_iflags_Y() const { - log_read(machine_reg_address(machine_reg::iflags), "iflags.Y"); + uint64_t do_read_iflags_Y() const { + log_read(machine_reg_address(machine_reg::iflags_Y), "iflags.Y"); return m_m.get_state().iflags.Y; } diff --git a/src/record-step-state-access.h b/src/record-step-state-access.h index c247ef2c..cdfe8586 100644 --- a/src/record-step-state-access.h +++ b/src/record-step-state-access.h @@ -467,54 +467,44 @@ class record_step_state_access : public i_state_accessread(pma.get_device_noexcept().get_context(), &da, offset, pval, diff --git a/src/replay-state-access.h b/src/replay-state-access.h index 2a06427f..43c28cb3 100644 --- a/src/replay-state-access.h +++ b/src/replay-state-access.h @@ -263,15 +263,12 @@ class replay_state_access : public i_state_access(machine_reg_address(machine_reg::iflags)); + uint64_t do_read_iprv() { + return raw_read_memory(machine_reg_address(machine_reg::iprv)); } - void do_write_iflags(uint64_t val) { - raw_write_memory(machine_reg_address(machine_reg::iflags), val); + void do_write_iprv(uint64_t val) { + raw_write_memory(machine_reg_address(machine_reg::iprv), val); } - void do_set_iflags_H() { - auto old_iflags = read_iflags(); - auto new_iflags = old_iflags | IFLAGS_H_MASK; - write_iflags(new_iflags); + uint64_t do_read_iflags_X() { + return raw_read_memory(machine_reg_address(machine_reg::iflags_X)); } - bool do_read_iflags_H() { - auto iflags = read_iflags(); - return (iflags & IFLAGS_H_MASK) != 0; + void do_write_iflags_X(uint64_t val) { + raw_write_memory(machine_reg_address(machine_reg::iflags_X), val); } - void do_set_iflags_X() { - auto old_iflags = read_iflags(); - auto new_iflags = old_iflags | IFLAGS_X_MASK; - write_iflags(new_iflags); + uint64_t do_read_iflags_Y() { + return raw_read_memory(machine_reg_address(machine_reg::iflags_Y)); } - void do_reset_iflags_X() { - auto old_iflags = read_iflags(); - auto new_iflags = old_iflags & (~IFLAGS_X_MASK); - write_iflags(new_iflags); + void do_write_iflags_Y(uint64_t val) { + raw_write_memory(machine_reg_address(machine_reg::iflags_Y), val); } - bool do_read_iflags_X() { - auto iflags = read_iflags(); - return (iflags & IFLAGS_X_MASK) != 0; + uint64_t do_read_iflags_H() { + return raw_read_memory(machine_reg_address(machine_reg::iflags_H)); } - void do_set_iflags_Y() { - auto old_iflags = read_iflags(); - auto new_iflags = old_iflags | IFLAGS_Y_MASK; - write_iflags(new_iflags); - } - - void do_reset_iflags_Y() { - auto old_iflags = read_iflags(); - auto new_iflags = old_iflags & (~IFLAGS_Y_MASK); - write_iflags(new_iflags); - } - - bool do_read_iflags_Y() { - auto iflags = read_iflags(); - return (iflags & IFLAGS_Y_MASK) != 0; - } - - uint8_t do_read_iflags_PRV() { - auto iflags = read_iflags(); - return (iflags & IFLAGS_PRV_MASK) >> IFLAGS_PRV_SHIFT; - } - - void do_write_iflags_PRV(uint8_t val) { - auto old_iflags = read_iflags(); - auto new_iflags = - (old_iflags & (~IFLAGS_PRV_MASK)) | ((static_cast(val) << IFLAGS_PRV_SHIFT) & IFLAGS_PRV_MASK); - write_iflags(new_iflags); + void do_write_iflags_H(uint64_t val) { + raw_write_memory(machine_reg_address(machine_reg::iflags_H), val); } uint64_t do_read_iunrep() { diff --git a/src/riscv-constants.h b/src/riscv-constants.h index 15f3f0ce..5f5edcfb 100644 --- a/src/riscv-constants.h +++ b/src/riscv-constants.h @@ -111,7 +111,7 @@ enum MEDELEG_RW_masks : uint64_t { }; /// \brief Privilege modes -enum PRV_constants : uint8_t { +enum PRV_constants : uint64_t { PRV_U = 0, ///< User mode PRV_S = 1, ///< Supervisor mode PRV_HS = 2, ///< Hypervisor-extended supervisor mode @@ -421,16 +421,6 @@ enum COUNTEREN_rw_masks : uint64_t { SCOUNTEREN_RW_MASK = MCOUNTEREN_RW_MASK }; -/// \brief Cartesi-specific iflags shifts -enum IFLAGS_shifts { IFLAGS_H_SHIFT = 0, IFLAGS_Y_SHIFT = 1, IFLAGS_X_SHIFT = 2, IFLAGS_PRV_SHIFT = 3 }; - -enum IFLAGS_masks : uint64_t { - IFLAGS_H_MASK = UINT64_C(1) << IFLAGS_H_SHIFT, - IFLAGS_Y_MASK = UINT64_C(1) << IFLAGS_Y_SHIFT, - IFLAGS_X_MASK = UINT64_C(1) << IFLAGS_X_SHIFT, - IFLAGS_PRV_MASK = UINT64_C(3) << IFLAGS_PRV_SHIFT -}; - /// \brief Initial values for Cartesi machines enum CARTESI_init : uint64_t { // The machines starts executing instructions from RAM start by default, @@ -451,31 +441,34 @@ enum CARTESI_init : uint64_t { MTVAL_INIT = UINT64_C(0), ///< Initial value for mtval MISA_INIT = (MISA_MXL_VALUE << MISA_MXL_SHIFT) | MISA_EXT_S_MASK | MISA_EXT_U_MASK | MISA_EXT_I_MASK | MISA_EXT_M_MASK | MISA_EXT_A_MASK | MISA_EXT_F_MASK | MISA_EXT_D_MASK | - MISA_EXT_C_MASK, ///< Initial value for misa - MIE_INIT = UINT64_C(0), ///< Initial value for mie - MIP_INIT = UINT64_C(0), ///< Initial value for mip - MEDELEG_INIT = UINT64_C(0), ///< Initial value for medeleg - MIDELEG_INIT = UINT64_C(0), ///< Initial value for mideleg - MCOUNTEREN_INIT = UINT64_C(0), ///< Initial value for mcounteren - STVEC_INIT = UINT64_C(0), ///< Initial value for stvec - SSCRATCH_INIT = UINT64_C(0), ///< Initial value for sscratch - SEPC_INIT = UINT64_C(0), ///< Initial value for sepc - SCAUSE_INIT = UINT64_C(0), ///< Initial value for scause - STVAL_INIT = UINT64_C(0), ///< Initial value for stval - SATP_INIT = UINT64_C(0), ///< Initial value for satp - SCOUNTEREN_INIT = UINT64_C(0), ///< Initial value for scounteren - ILRSC_INIT = UINT64_C(-1), ///< Initial value for ilrsc - IFLAGS_INIT = static_cast(PRV_M) << IFLAGS_PRV_SHIFT, ///< Initial value for iflags - IUNREP_INIT = UINT64_C(0), ///< Initial value for iunrep - MTIMECMP_INIT = UINT64_C(0), ///< Initial value for mtimecmp - GIRQPEND_INIT = UINT64_C(0), ///< Initial value for girqpend - GIRQSRVD_INIT = UINT64_C(0), ///< Initial value for girqsrvd - FROMHOST_INIT = UINT64_C(0), ///< Initial value for fromhost - TOHOST_INIT = UINT64_C(0), ///< Initial value for tohost - MENVCFG_INIT = UINT64_C(0), ///< Initial value for menvcfg - SENVCFG_INIT = UINT64_C(0), ///< Initial value for senvcfg - UARCH_HALT_FLAG_INIT = UINT64_C(0), ///< Initial value for microarchitecture halt flag - UARCH_X_INIT = UINT64_C(0), ///< Initial value for microarchitecture general purpose register x + MISA_EXT_C_MASK, ///< Initial value for misa + MIE_INIT = UINT64_C(0), ///< Initial value for mie + MIP_INIT = UINT64_C(0), ///< Initial value for mip + MEDELEG_INIT = UINT64_C(0), ///< Initial value for medeleg + MIDELEG_INIT = UINT64_C(0), ///< Initial value for mideleg + MCOUNTEREN_INIT = UINT64_C(0), ///< Initial value for mcounteren + STVEC_INIT = UINT64_C(0), ///< Initial value for stvec + SSCRATCH_INIT = UINT64_C(0), ///< Initial value for sscratch + SEPC_INIT = UINT64_C(0), ///< Initial value for sepc + SCAUSE_INIT = UINT64_C(0), ///< Initial value for scause + STVAL_INIT = UINT64_C(0), ///< Initial value for stval + SATP_INIT = UINT64_C(0), ///< Initial value for satp + SCOUNTEREN_INIT = UINT64_C(0), ///< Initial value for scounteren + ILRSC_INIT = UINT64_C(-1), ///< Initial value for ilrsc + IPRV_INIT = PRV_M, ///< Initial value for iprv + IFLAGS_X_INIT = UINT64_C(0), ///< Initial value for iflags_X + IFLAGS_Y_INIT = UINT64_C(0), ///< Initial value for iflags_Y + IFLAGS_H_INIT = UINT64_C(0), ///< Initial value for iflags_H + IUNREP_INIT = UINT64_C(0), ///< Initial value for iunrep + MTIMECMP_INIT = UINT64_C(0), ///< Initial value for mtimecmp + GIRQPEND_INIT = UINT64_C(0), ///< Initial value for girqpend + GIRQSRVD_INIT = UINT64_C(0), ///< Initial value for girqsrvd + FROMHOST_INIT = UINT64_C(0), ///< Initial value for fromhost + TOHOST_INIT = UINT64_C(0), ///< Initial value for tohost + MENVCFG_INIT = UINT64_C(0), ///< Initial value for menvcfg + SENVCFG_INIT = UINT64_C(0), ///< Initial value for senvcfg + UARCH_HALT_FLAG_INIT = UINT64_C(0), ///< Initial value for microarchitecture halt flag + UARCH_X_INIT = UINT64_C(0), ///< Initial value for microarchitecture general purpose register x UARCH_PC_INIT = EXPAND_UINT64_C(PMA_UARCH_RAM_START_DEF), ///< Initial value for microarchitecture pc UARCH_CYCLE_INIT = UINT64_C(0), ///< Initial value for microarchitecture cycle MHARTID_INIT = UINT64_C(0), ///< Initial mhartid diff --git a/src/send-cmio-response.cpp b/src/send-cmio-response.cpp index e9430441..48567e92 100644 --- a/src/send-cmio-response.cpp +++ b/src/send-cmio-response.cpp @@ -57,7 +57,7 @@ void send_cmio_response(STATE_ACCESS &a, uint16 reason, bytes data, uint32 dataL uint64 yieldData = uint64ShiftLeft((uint64(reason) & mask16), 32) | (uint64(dataLength) & mask32); writeHtifFromhost(a, yieldData); // Reset iflags.Y - resetIflagsY(a); + writeIflagsY(a, 0); } // Explicit instantiation for state_access diff --git a/src/shadow-state-factory.cpp b/src/shadow-state-factory.cpp index 9470eefe..48d147ad 100644 --- a/src/shadow-state-factory.cpp +++ b/src/shadow-state-factory.cpp @@ -84,7 +84,10 @@ static bool shadow_state_peek(const pma_entry & /*pma*/, const machine &m, uint6 s->scounteren = m.read_reg(machine_reg::scounteren); s->senvcfg = m.read_reg(machine_reg::senvcfg); s->ilrsc = m.read_reg(machine_reg::ilrsc); - s->iflags = m.read_reg(machine_reg::iflags); + s->iprv = m.read_reg(machine_reg::iprv); + s->iflags_X = m.read_reg(machine_reg::iflags_X); + s->iflags_Y = m.read_reg(machine_reg::iflags_Y); + s->iflags_H = m.read_reg(machine_reg::iflags_H); s->iunrep = m.read_reg(machine_reg::iunrep); s->clint_mtimecmp = m.read_reg(machine_reg::clint_mtimecmp); s->plic_girqpend = m.read_reg(machine_reg::plic_girqpend); diff --git a/src/shadow-state.h b/src/shadow-state.h index 30abf2f3..fd35759f 100644 --- a/src/shadow-state.h +++ b/src/shadow-state.h @@ -63,7 +63,10 @@ struct PACKED shadow_state { uint64_t scounteren; uint64_t senvcfg; uint64_t ilrsc; - uint64_t iflags; + uint64_t iprv; + uint64_t iflags_X; + uint64_t iflags_Y; + uint64_t iflags_H; uint64_t iunrep; uint64_t clint_mtimecmp; uint64_t plic_girqpend; diff --git a/src/state-access.h b/src/state-access.h index 71a48a15..c7fc808c 100644 --- a/src/state-access.h +++ b/src/state-access.h @@ -328,44 +328,36 @@ class state_access : public i_state_access { m_m.get_state().ilrsc = val; } - void do_set_iflags_H() { - m_m.get_state().iflags.H = true; + uint64_t do_read_iprv() const { + return m_m.get_state().iprv; } - bool do_read_iflags_H() const { - return m_m.get_state().iflags.H; - } - - void do_set_iflags_X() { - m_m.get_state().iflags.X = true; + void do_write_iprv(uint64_t val) { + m_m.get_state().iprv = val; } - void do_reset_iflags_X() { - m_m.get_state().iflags.X = false; - } - - bool do_read_iflags_X() const { + uint64_t do_read_iflags_X() const { return m_m.get_state().iflags.X; } - void do_set_iflags_Y() { - m_m.get_state().iflags.Y = true; + void do_write_iflags_X(uint64_t val) { + m_m.get_state().iflags.X = val; } - void do_reset_iflags_Y() { - m_m.get_state().iflags.Y = false; + uint64_t do_read_iflags_Y() const { + return m_m.get_state().iflags.Y; } - bool do_read_iflags_Y() const { - return m_m.get_state().iflags.Y; + void do_write_iflags_Y(uint64_t val) { + m_m.get_state().iflags.Y = val; } - uint8_t do_read_iflags_PRV() const { - return m_m.get_state().iflags.PRV; + uint64_t do_read_iflags_H() const { + return m_m.get_state().iflags.H; } - void do_write_iflags_PRV(uint8_t val) { - m_m.get_state().iflags.PRV = val; + void do_write_iflags_H(uint64_t val) { + m_m.get_state().iflags.H = val; } uint64_t do_read_iunrep() const { @@ -554,14 +546,6 @@ class state_access : public i_state_access { return pmas[index]; } - uint64_t do_read_iflags() { - return m_m.get_state().read_iflags(); - } - - void do_write_iflags(uint64_t val) { - m_m.get_state().write_iflags(val); - } - bool do_read_device(pma_entry &pma, uint64_t mcycle, uint64_t offset, uint64_t *pval, int log2_size) { device_state_access da(*this, mcycle); return pma.get_device_noexcept().get_driver()->read(pma.get_device_noexcept().get_context(), &da, offset, pval, diff --git a/src/translate-virtual-address.h b/src/translate-virtual-address.h index 5044fdfd..fe0811dc 100644 --- a/src/translate-virtual-address.h +++ b/src/translate-virtual-address.h @@ -103,19 +103,19 @@ static inline bool read_ram_uint64(STATE_ACCESS &a, uint64_t paddr, uint64_t *pv /// \returns True if succeeded, false otherwise. template static NO_INLINE bool translate_virtual_address(STATE_ACCESS &a, uint64_t *ppaddr, uint64_t vaddr, int xwr_shift) { - auto priv = a.read_iflags_PRV(); + auto prv = a.read_iprv(); const uint64_t mstatus = a.read_mstatus(); // When MPRV is set, data loads and stores use privilege in MPP // instead of the current privilege level (code access is unaffected) if (xwr_shift != PTE_XWR_X_SHIFT && (mstatus & MSTATUS_MPRV_MASK)) { - priv = (mstatus & MSTATUS_MPP_MASK) >> MSTATUS_MPP_SHIFT; + prv = (mstatus & MSTATUS_MPP_MASK) >> MSTATUS_MPP_SHIFT; } // The satp register is considered active when the effective privilege mode is S-mode or U-mode. // Executions of the address-translation algorithm may only begin using a given value of satp when // satp is active. - if (unlikely(priv > PRV_S)) { + if (unlikely(prv > PRV_S)) { // We are in M-mode (or in HS-mode if Hypervisor extension is active) *ppaddr = vaddr; return true; @@ -196,7 +196,7 @@ static NO_INLINE bool translate_virtual_address(STATE_ACCESS &a, uint64_t *ppadd return false; } // (We know we are not PRV_M if we reached here) - if (priv == PRV_S) { + if (prv == PRV_S) { if ((pte & PTE_U_MASK)) { // S-mode can never execute instructions from user pages, regardless of the state of SUM if (unlikely(xwr_shift == PTE_XWR_X_SHIFT)) { diff --git a/src/uarch-bridge.h b/src/uarch-bridge.h index b4862fe4..b09ea5a3 100644 --- a/src/uarch-bridge.h +++ b/src/uarch-bridge.h @@ -316,8 +316,17 @@ class uarch_bridge { case reg::ilrsc: s.ilrsc = data; return; - case reg::iflags: - s.write_iflags(data); + case reg::iprv: + s.iprv = data; + return; + case reg::iflags_X: + s.iflags.X = data; + return; + case reg::iflags_Y: + s.iflags.Y = data; + return; + case reg::iflags_H: + s.iflags.H = data; return; case reg::clint_mtimecmp: s.clint.mtimecmp = data; @@ -539,8 +548,14 @@ class uarch_bridge { return s.senvcfg; case reg::ilrsc: return s.ilrsc; - case reg::iflags: - return s.read_iflags(); + case reg::iprv: + return s.iprv; + case reg::iflags_X: + return s.iflags.X; + case reg::iflags_Y: + return s.iflags.Y; + case reg::iflags_H: + return s.iflags.H; case reg::clint_mtimecmp: return s.clint.mtimecmp; case reg::plic_girqpend: @@ -762,8 +777,14 @@ class uarch_bridge { return "senvcfg"; case reg::ilrsc: return "ilrsc"; - case reg::iflags: - return "iflags"; + case reg::iprv: + return "iprv"; + case reg::iflags_X: + return "iflags.X"; + case reg::iflags_Y: + return "iflags.Y"; + case reg::iflags_H: + return "iflags.H"; case reg::clint_mtimecmp: return "clint.mtimecmp"; case reg::plic_girqpend: diff --git a/src/uarch-solidity-compat.h b/src/uarch-solidity-compat.h index e86aee33..fc31d052 100644 --- a/src/uarch-solidity-compat.h +++ b/src/uarch-solidity-compat.h @@ -101,13 +101,13 @@ static inline void resetState(UarchState &a) { } template -static inline bool readIflagsY(UarchState &a) { +static inline uint64 readIflagsY(UarchState &a) { return a.read_iflags_Y(); } template -static inline void resetIflagsY(UarchState &a) { - a.reset_iflags_Y(); +static inline void writeIflagsY(UarchState &a, uint64 val) { + a.write_iflags_Y(val); } template diff --git a/tests/lua/cartesi-machine-tests.lua b/tests/lua/cartesi-machine-tests.lua index 7f7df660..7478d3bf 100755 --- a/tests/lua/cartesi-machine-tests.lua +++ b/tests/lua/cartesi-machine-tests.lua @@ -578,11 +578,11 @@ end local function run_machine(machine, ctx, max_mcycle, advance_machine_fn) advance_machine_fn = advance_machine_fn or advance_machine - local mcycle = machine:read_mcycle() + local mcycle = machine:read_reg("mcycle") while math.ult(mcycle, max_mcycle) do advance_machine_fn(machine, max_mcycle) - mcycle = machine:read_mcycle() - if machine:read_iflags_H() then + mcycle = machine:read_reg("mcycle") + if machine:read_reg("iflags_H") ~= 0 then break end end @@ -664,7 +664,7 @@ local function check_and_print_result(machine, ctx) fatal("%s: failed. returned halt payload %d, expected %d\n", ctx.ram_image, halt_payload, expected_halt_payload) end - local cycles = machine:read_mcycle() + local cycles = machine:read_reg("mcycle") local expected_cycles = ctx.expected_cycles or 0 if cycles ~= expected_cycles then fatal("%s: failed. terminated with mcycle = %d, expected %d\n", ctx.ram_image, cycles, expected_cycles) @@ -685,8 +685,8 @@ local function hash(tests) local machine = build_machine(ram_image) local total_cycles = 0 local max_mcycle = 2 * expected_cycles - while math.ult(machine:read_mcycle(), max_mcycle) do - local initial_cycle = machine:read_uarch_cycle() + while math.ult(machine:read_reg("mcycle"), max_mcycle) do + local initial_cycle = machine:read_reg("uarch_cycle") local next_action_cycle = math.maxinteger if periodic_action then next_action_cycle = periodic_action_start @@ -699,29 +699,36 @@ local function hash(tests) end end local status = machine:run_uarch(initial_cycle + (next_action_cycle - total_cycles)) - local final_cycle = machine:read_uarch_cycle() + local final_cycle = machine:read_reg("uarch_cycle") total_cycles = total_cycles + (final_cycle - initial_cycle) if not periodic_action or total_cycles == next_action_cycle then - out:write(machine:read_mcycle(), " ", final_cycle, " ", util.hexhash(machine:get_root_hash()), "\n") + out:write( + machine:read_reg("mcycle"), + " ", + final_cycle, + " ", + util.hexhash(machine:get_root_hash()), + "\n" + ) total_cycles = total_cycles + 1 end if status == cartesi.UARCH_BREAK_REASON_UARCH_HALTED then machine:reset_uarch() - if machine:read_iflags_H() then + if machine:read_reg("iflags_H") ~= 0 then break end end end if machine:read_reg("htif_tohost_data") >> 1 ~= expected_payload - or machine:read_mcycle() ~= expected_cycles + or machine:read_reg("mcycle") ~= expected_cycles then os.exit(1, true) end out:write( - machine:read_mcycle(), + machine:read_reg("mcycle"), " ", - machine:read_uarch_cycle(), + machine:read_reg("uarch_cycle"), " ", util.hexhash(machine:get_root_hash()), "\n" @@ -760,7 +767,7 @@ local function step(tests) local total_logged_steps = 0 local total_uarch_cycles = 0 local max_mcycle = 2 * expected_cycles - while math.ult(machine:read_mcycle(), max_mcycle) do + while math.ult(machine:read_reg("mcycle"), max_mcycle) do local uarch_cycle_increment = 0 local next_action_uarch_cycle if periodic_action then @@ -774,31 +781,31 @@ local function step(tests) end uarch_cycle_increment = next_action_uarch_cycle - total_uarch_cycles end - local init_uarch_cycle = machine:read_uarch_cycle() - machine:run_uarch(machine:read_uarch_cycle() + uarch_cycle_increment) - local final_uarch_cycle = machine:read_uarch_cycle() + local init_uarch_cycle = machine:read_reg("uarch_cycle") + machine:run_uarch(machine:read_reg("uarch_cycle") + uarch_cycle_increment) + local final_uarch_cycle = machine:read_reg("uarch_cycle") total_uarch_cycles = total_uarch_cycles + (final_uarch_cycle - init_uarch_cycle) - if machine:read_uarch_halt_flag() then + if machine:read_reg("uarch_halt_flag") then machine:reset_uarch() - if machine:read_iflags_H() then + if machine:read_reg("iflags_H") ~= 0 then break end end if not periodic_action or total_uarch_cycles == next_action_uarch_cycle then - local init_mcycle = machine:read_mcycle() - init_uarch_cycle = machine:read_uarch_cycle() + local init_mcycle = machine:read_reg("mcycle") + init_uarch_cycle = machine:read_reg("uarch_cycle") local log = machine:log_step_uarch(log_type) - local final_mcycle = machine:read_mcycle() - final_uarch_cycle = machine:read_uarch_cycle() + local final_mcycle = machine:read_reg("mcycle") + final_uarch_cycle = machine:read_reg("uarch_cycle") if total_logged_steps > 0 then out:write(",\n") end util.dump_json_log(log, init_mcycle, init_uarch_cycle, final_mcycle, final_uarch_cycle, out, 3) total_uarch_cycles = total_uarch_cycles + 1 total_logged_steps = total_logged_steps + 1 - if machine:read_uarch_halt_flag() then + if machine:read_reg("uarch_halt_flag") then machine:reset_uarch() - if machine:read_iflags_H() then + if machine:read_reg("iflags_H") ~= 0 then break end end @@ -812,7 +819,7 @@ local function step(tests) end if machine:read_reg("htif_tohost_data") >> 1 ~= expected_payload - or machine:read_mcycle() ~= expected_cycles + or machine:read_reg("mcycle") ~= expected_cycles then os.exit(1, true) end @@ -869,8 +876,8 @@ for _, test in ipairs(riscv_tests) do end local function run_host_and_uarch_machines(host_machine, uarch_machine, ctx, max_mcycle) - local host_cycles = host_machine:read_mcycle() - local uarch_cycles = uarch_machine:read_mcycle() + local host_cycles = host_machine:read_reg("mcycle") + local uarch_cycles = uarch_machine:read_reg("mcycle") assert(host_cycles == uarch_cycles) if host_cycles ~= uarch_cycles then fatal("%s: host_cycles ~= uarch_cycles: %d ~= %d", ctx.ram_image, host_cycles, uarch_cycles) @@ -889,13 +896,13 @@ local function run_host_and_uarch_machines(host_machine, uarch_machine, ctx, max end host_machine:run(1 + host_cycles) advance_machine_with_uarch(uarch_machine) - host_cycles = host_machine:read_mcycle() - uarch_cycles = uarch_machine:read_mcycle() + host_cycles = host_machine:read_reg("mcycle") + uarch_cycles = uarch_machine:read_reg("mcycle") if host_cycles ~= uarch_cycles then fatal("%s: host_cycles ~= uarch_cycles: %d ~= %d", ctx.ram_image, host_cycles, uarch_cycles) end - local host_iflags_H = host_machine:read_iflags_H() - local uarch_iflags_H = uarch_machine:read_iflags_H() + local host_iflags_H = host_machine:read_reg("iflags_H") ~= 0 + local uarch_iflags_H = uarch_machine:read_reg("iflags_H") ~= 0 if host_iflags_H ~= uarch_iflags_H then fatal( "%s: host_iflags_H ~= uarch_iflags_H: %s ~= %s", diff --git a/tests/lua/cmio-test.lua b/tests/lua/cmio-test.lua index 213a1314..399f4181 100755 --- a/tests/lua/cmio-test.lua +++ b/tests/lua/cmio-test.lua @@ -143,12 +143,12 @@ local function setup_inspect(machine, data) end local function get_exit_code(machine) - assert(machine:read_iflags_H()) + assert(machine:read_reg("iflags_H") ~= 0) return machine:read_reg("htif_tohost_data") >> 1 end local function check_output(machine, expected) - assert(machine:read_iflags_X()) + assert(machine:read_reg("iflags_X") ~= 0) local cmd, reason, output = machine:receive_cmio_request() assert(cmd == cartesi.CMIO_YIELD_COMMAND_AUTOMATIC) assert(reason == cartesi.CMIO_YIELD_AUTOMATIC_REASON_TX_OUTPUT) @@ -164,7 +164,7 @@ local function check_output(machine, expected) end local function check_report(machine, expected) - assert(machine:read_iflags_X()) + assert(machine:read_reg("iflags_X") ~= 0) local cmd, reason, output = machine:receive_cmio_request() assert(cmd == cartesi.CMIO_YIELD_COMMAND_AUTOMATIC) assert(reason == cartesi.CMIO_YIELD_AUTOMATIC_REASON_TX_REPORT) @@ -172,7 +172,7 @@ local function check_report(machine, expected) end local function check_exception(machine, expected) - assert(machine:read_iflags_Y()) + assert(machine:read_reg("iflags_Y") ~= 0) local cmd, reason, output = machine:receive_cmio_request() assert(cmd == cartesi.CMIO_YIELD_COMMAND_MANUAL) assert(reason == cartesi.CMIO_YIELD_MANUAL_REASON_TX_EXCEPTION) @@ -210,7 +210,7 @@ end local function check_finish(machine, output_hashes, expected_reason) local cmd, reason, output = machine:receive_cmio_request() - assert(machine:read_iflags_Y()) + assert(machine:read_reg("iflags_Y") ~= 0) assert(cmd == cartesi.CMIO_YIELD_COMMAND_MANUAL) assert(reason == expected_reason) diff --git a/tests/lua/htif-cmio.lua b/tests/lua/htif-cmio.lua index d8dd3582..60d0ae85 100755 --- a/tests/lua/htif-cmio.lua +++ b/tests/lua/htif-cmio.lua @@ -50,9 +50,9 @@ local function test(config) local tx_length = 1 << cartesi.PMA_CMIO_TX_BUFFER_LOG2_SIZE assert(string.rep(pattern, tx_length / 8) == machine:read_memory(cartesi.PMA_CMIO_TX_BUFFER_START, tx_length)) - assert(machine:read_iflags_H()) + assert(machine:read_reg("iflags_H") ~= 0) - local mcycle = machine:read_mcycle() + local mcycle = machine:read_reg("mcycle") assert(mcycle == final_mcycle, "[mcycle] expected:" .. final_mcycle .. " got: " .. mcycle) local exit = machine:read_reg("htif_tohost_data") >> 1 diff --git a/tests/lua/htif-console.lua b/tests/lua/htif-console.lua index de1b69bf..746a0cbb 100755 --- a/tests/lua/htif-console.lua +++ b/tests/lua/htif-console.lua @@ -45,7 +45,7 @@ local function test(config, console_getchar_enable) machine:run(math.maxinteger) -- should be halted - assert(machine:read_iflags_H(), "expected iflags_H set") + assert(machine:read_reg("iflags_H") ~= 0, "expected iflags_H set") -- with the expected payload local exit_payload = machine:read_reg("htif_tohost_data") >> 1 @@ -55,7 +55,7 @@ local function test(config, console_getchar_enable) ) -- at the expected mcycle - local final_mcycle = machine:read_mcycle() + local final_mcycle = machine:read_reg("mcycle") assert( final_mcycle == expected_final_mcycle, string.format("mcycle: expected, %u got %u", expected_final_mcycle, final_mcycle) diff --git a/tests/lua/htif-yield.lua b/tests/lua/htif-yield.lua index 3bc58501..1ea0d4a2 100755 --- a/tests/lua/htif-yield.lua +++ b/tests/lua/htif-yield.lua @@ -163,15 +163,15 @@ local function run_machine_with_uarch(machine) local ubr = machine:run_uarch() if ubr == cartesi.UARCH_BREAK_REASON_UARCH_HALTED then machine:reset_uarch() - if machine:read_iflags_H() then + if machine:read_reg("iflags_H") ~= 0 then -- iflags.H was set during the last mcycle return cartesi.BREAK_REASON_HALTED end - if machine:read_iflags_Y() then + if machine:read_reg("iflags_Y") ~= 0 then -- iflags.Y was set during the last mcycle return cartesi.BREAK_REASON_YIELDED_MANUALLY end - if machine:read_iflags_X() then + if machine:read_reg("iflags_X") ~= 0 then -- machine was yielded with automatic reset. iflags.X will be cleared on the next mcycle return cartesi.BREAK_REASON_YIELDED_AUTOMATICALLY end @@ -214,7 +214,7 @@ local function test(machine_config, yield_automatic_enable, yield_manual_enable) local break_reason = run_machine(machine) -- mcycle should be as expected - local mcycle = machine:read_mcycle() + local mcycle = machine:read_reg("mcycle") assert(mcycle == v.mcycle, string.format("mcycle: expected %d, got %d", v.mcycle, mcycle)) if yield_automatic_enable and v.cmd == YIELD_AUTOMATIC then @@ -222,12 +222,12 @@ local function test(machine_config, yield_automatic_enable, yield_manual_enable) break_reason == cartesi.BREAK_REASON_YIELDED_AUTOMATICALLY, "expected break reason yielded automatically" ) - assert(machine:read_iflags_X(), "expected iflags_X set") - assert(not machine:read_iflags_Y(), "expected iflags_Y not set") + assert(machine:read_reg("iflags_X") ~= 0, "expected iflags_X set") + assert(machine:read_reg("iflags_Y") == 0, "expected iflags_Y not set") elseif yield_manual_enable and v.cmd == YIELD_MANUAL then assert(break_reason == cartesi.BREAK_REASON_YIELDED_MANUALLY, "expected break reason yielded manually") - assert(machine:read_iflags_Y(), "expected iflags_Y set") - assert(not machine:read_iflags_X(), "expected iflags_X not set") + assert(machine:read_reg("iflags_Y") ~= 0, "expected iflags_Y set") + assert(machine:read_reg("iflags_X") == 0, "expected iflags_X not set") else assert(false) end @@ -240,24 +240,24 @@ local function test(machine_config, yield_automatic_enable, yield_manual_enable) -- cmd should be as expected assert(machine:read_reg("htif_tohost_cmd") == v.cmd) -- trying to run it without resetting iflags.Y should not advance - if machine:read_iflags_Y() then + if machine:read_reg("iflags_Y") ~= 0 then run_machine(machine) - assert(mcycle == machine:read_mcycle()) - assert(machine:read_iflags_Y()) + assert(mcycle == machine:read_reg("mcycle")) + assert(machine:read_reg("iflags_Y") ~= 0) end -- now reset it so the machine can be advanced - machine:reset_iflags_Y() + machine:write_reg("iflags_Y", 0) end end -- finally run to completion local break_reason = run_machine(machine) -- should be halted assert(break_reason == cartesi.BREAK_REASON_HALTED) - assert(machine:read_iflags_H(), "expected iflags_H set") + assert(machine:read_reg("iflags_H") ~= 0, "expected iflags_H set") -- at the expected mcycle assert( - machine:read_mcycle() == final_mcycle, - string.format("mcycle: expected, %u got %u", final_mcycle, machine:read_mcycle()) + machine:read_reg("mcycle") == final_mcycle, + string.format("mcycle: expected, %u got %u", final_mcycle, machine:read_reg("mcycle")) ) -- with the expected payload assert( diff --git a/tests/lua/machine-bind.lua b/tests/lua/machine-bind.lua index 8547b905..a8c9d87c 100755 --- a/tests/lua/machine-bind.lua +++ b/tests/lua/machine-bind.lua @@ -177,16 +177,19 @@ local cpu_reg_addr = { scounteren = 720, senvcfg = 728, ilrsc = 736, - iflags = 744, - iunrep = 752, - clint_mtimecmp = 760, - plic_girqpend = 768, - plic_girqsrvd = 776, - htif_tohost = 784, - htif_fromhost = 792, - htif_ihalt = 800, - htif_iconsole = 808, - htif_iyield = 816, + iprv = 744, + iflags_X = 752, + iflags_Y = 760, + iflags_H = 768, + iunrep = 776, + clint_mtimecmp = 784, + plic_girqpend = 792, + plic_girqsrvd = 800, + htif_tohost = 808, + htif_fromhost = 816, + htif_ihalt = 824, + htif_iconsole = 832, + htif_iyield = 840, } for i = 0, 31 do cpu_reg_addr["x" .. i] = i * 8 @@ -299,9 +302,9 @@ print("Testing machine bindings for type " .. machine_type) print("\n\ntesting machine initial flags") do_test("machine should not have halt and yield initial flags set", function(machine) -- Check machine is not halted - assert(not machine:read_iflags_H(), "machine shouldn't be halted") + assert(machine:read_reg("iflags_H") == 0, "machine shouldn't be halted") -- Check machine is not yielded - assert(not machine:read_iflags_Y(), "machine shouldn't be yielded") + assert(machine:read_reg("iflags_Y") == 0, "machine shouldn't be yielded") end) print("\n\ntesting machine register initial flag values ") @@ -469,7 +472,10 @@ do_test("should return expected values", function(machine) -- Check register read local to_ignore = { - iflags = true, + iflags_X = true, + iflags_Y = true, + iflags_H = true, + iprv = true, clint_mtimecmp = true, plic_girqpend = true, plic_girqsrvd = true, @@ -540,71 +546,71 @@ end) do_test("should error if target mcycle is smaller than current mcycle", function(machine) machine:write_reg("mcycle", MAX_MCYCLE) - assert(machine:read_mcycle() == MAX_MCYCLE) + assert(machine:read_reg("mcycle") == MAX_MCYCLE) local success, err = pcall(function() machine:run(MAX_MCYCLE - 1) end) assert(success == false) assert(err and err:match("mcycle is past")) - assert(machine:read_mcycle() == MAX_MCYCLE) + assert(machine:read_reg("mcycle") == MAX_MCYCLE) end) do_test("should error if target uarch_cycle is smaller than current uarch_cycle", function(machine) machine:write_reg("uarch_cycle", MAX_UARCH_CYCLE) - assert(machine:read_uarch_cycle() == MAX_UARCH_CYCLE) + assert(machine:read_reg("uarch_cycle") == MAX_UARCH_CYCLE) local success, err = pcall(function() machine:run_uarch(MAX_UARCH_CYCLE - 1) end) assert(success == false) assert(err and err:match("uarch_cycle is past")) - assert(machine:read_uarch_cycle() == MAX_UARCH_CYCLE) + assert(machine:read_reg("uarch_cycle") == MAX_UARCH_CYCLE) end) print("\n\n run_uarch tests") do_test("advance one micro cycle without halting", function(machine) - assert(machine:read_uarch_cycle() == 0, "uarch cycle should be 0") - assert(machine:read_uarch_halt_flag() == false, "uarch halt flag should be cleared") - assert(machine:read_iflags_Y() == false, "iflags.Y should be cleared") - assert(machine:read_iflags_H() == false, "iflags.H should be cleared") + assert(machine:read_reg("uarch_cycle") == 0, "uarch cycle should be 0") + assert(machine:read_reg("uarch_halt_flag") == 0, "uarch halt flag should be cleared") + assert(machine:read_reg("iflags_Y") == 0, "iflags.Y should be cleared") + assert(machine:read_reg("iflags_H") == 0, "iflags.H should be cleared") local status = machine:run_uarch(1) assert(status == cartesi.UARCH_BREAK_REASON_REACHED_TARGET_CYCLE) - assert(machine:read_uarch_cycle() == 1, "uarch cycle should be 1") - assert(machine:read_uarch_halt_flag() == false, "uarch should not be halted") + assert(machine:read_reg("uarch_cycle") == 1, "uarch cycle should be 1") + assert(machine:read_reg("uarch_halt_flag") == 0, "uarch should not be halted") end) do_test("do not advance micro cycle if uarch is halted", function(machine) - machine:set_uarch_halt_flag() - assert(machine:read_uarch_cycle() == 0, "uarch cycle should be 0") - assert(machine:read_uarch_halt_flag() == true, "uarch halt flag should be set") - assert(machine:read_iflags_Y() == false, "iflags.Y should be cleared") - assert(machine:read_iflags_H() == false, "iflags.H should be cleared") + machine:write_reg("uarch_halt_flag", 1) + assert(machine:read_reg("uarch_cycle") == 0, "uarch cycle should be 0") + assert(machine:read_reg("uarch_halt_flag") ~= 0, "uarch halt flag should be set") + assert(machine:read_reg("iflags_Y") == 0, "iflags.Y should be cleared") + assert(machine:read_reg("iflags_H") == 0, "iflags.H should be cleared") local status = machine:run_uarch(1) assert(status == cartesi.UARCH_BREAK_REASON_UARCH_HALTED, "run_uarch should return UARCH_BREAK_REASON_UARCH_HALTED") - assert(machine:read_uarch_cycle() == 0, "uarch cycle should still be 0") + assert(machine:read_reg("uarch_cycle") == 0, "uarch cycle should still be 0") end) do_test("advance micro cycles until halt", function(machine) - assert(machine:read_uarch_cycle() == 0, "uarch cycle should be 0") - assert(machine:read_uarch_halt_flag() == false, "machine should not be halted") + assert(machine:read_reg("uarch_cycle") == 0, "uarch cycle should be 0") + assert(machine:read_reg("uarch_halt_flag") == 0, "machine should not be halted") local status = machine:run_uarch() assert(status == cartesi.UARCH_BREAK_REASON_UARCH_HALTED) - assert(machine:read_uarch_cycle() == 3, "uarch cycle should be 4") - assert(machine:read_uarch_halt_flag() == true, "uarch should be halted") + assert(machine:read_reg("uarch_cycle") == 3, "uarch cycle should be 4") + assert(machine:read_reg("uarch_halt_flag") ~= 0, "uarch should be halted") end) print("\n\n run machine to 1000 mcycle") do_test("mcycle value should be 1000 after execution", function(machine) -- Run machine machine:write_reg("mcycle", 0) - assert(machine:read_mcycle() == 0) + assert(machine:read_reg("mcycle") == 0) - local test = machine:read_mcycle() + local test = machine:read_reg("mcycle") while test < 1000 do machine:run(1000) - test = machine:read_mcycle() + test = machine:read_reg("mcycle") end - assert(machine:read_mcycle() == 1000) + assert(machine:read_reg("mcycle") == 1000) end) print("\n\n check reading and writing htif registers") @@ -700,10 +706,10 @@ end) do_test("step when uarch cycle is max", function(machine) machine:write_reg("uarch_cycle", MAX_UARCH_CYCLE) - assert(machine:read_uarch_cycle() == MAX_UARCH_CYCLE) + assert(machine:read_reg("uarch_cycle") == MAX_UARCH_CYCLE) local initial_hash = machine:get_root_hash() local log = machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) - assert(machine:read_uarch_cycle() == MAX_UARCH_CYCLE) + assert(machine:read_reg("uarch_cycle") == MAX_UARCH_CYCLE) local final_hash = machine:get_root_hash() assert(final_hash == initial_hash) machine:verify_step_uarch(initial_hash, log, final_hash) @@ -771,14 +777,14 @@ end) test_util.make_do_test(build_machine, machine_type, { processor = { mcycle = 1 }, uarch = {} })( "It should use the embedded uarch-ram.bin when the uarch config is not provided", function(machine) - assert(machine:read_mcycle() == 1) + assert(machine:read_reg("mcycle") == 1) -- Advance one mcycle by running the "big interpreter" compiled to the microarchitecture that is embedded -- in the emulator executable. Note that the config used to create the machine has an empty uarch key; -- therefore, the embedded uarch image is used. machine:run_uarch() - assert(machine:read_mcycle() == 2) + assert(machine:read_reg("mcycle") == 2) end ) @@ -824,8 +830,8 @@ end local function test_reset_uarch(machine, with_log, with_annotations) -- assert initial fixture state - assert(machine:read_uarch_halt_flag() == true) - assert(machine:read_uarch_cycle() == 1) + assert(machine:read_reg("uarch_halt_flag") ~= 0) + assert(machine:read_reg("uarch_cycle") == 1) assert(machine:read_reg("uarch_pc") == 0) for i = 1, 31 do assert(machine:read_reg("uarch_x" .. i) == test_reset_uarch_config.processor["x" .. i]) @@ -854,8 +860,8 @@ local function test_reset_uarch(machine, with_log, with_annotations) machine:reset_uarch() end --- assert registers are reset to pristine values - assert(machine:read_uarch_halt_flag() == false) - assert(machine:read_uarch_cycle() == 0) + assert(machine:read_reg("uarch_halt_flag") == 0) + assert(machine:read_reg("uarch_cycle") == 0) assert(machine:read_reg("uarch_pc") == cartesi.UARCH_RAM_START_ADDRESS) for i = 1, 31 do assert(machine:read_reg("uarch_x" .. i) == 0) @@ -1138,8 +1144,8 @@ print("\n\ntesting send cmio response ") do_test("send_cmio_response fails if iflags.Y is not set", function(machine) local reason = 1 local data = string.rep("a", 1 << cartesi.PMA_CMIO_RX_BUFFER_LOG2_SIZE) - machine:reset_iflags_Y() - assert(machine:read_iflags_Y() == false) + machine:write_reg("iflags_Y", 0) + assert(machine:read_reg("iflags_Y") == 0) test_util.assert_error("iflags.Y is not set", function() machine:send_cmio_response(reason, data) end) @@ -1151,7 +1157,7 @@ end) do_test("send_cmio_response fails if data is too big", function(machine) local reason = 1 local data_too_big = string.rep("a", 1 + (1 << cartesi.PMA_CMIO_RX_BUFFER_LOG2_SIZE)) - machine:set_iflags_Y() + machine:write_reg("iflags_Y", 1) test_util.assert_error("CMIO response data is too large", function() machine:send_cmio_response(reason, data_too_big) end) @@ -1178,7 +1184,7 @@ local function test_send_cmio_input_with_different_arguments() local all_zeros_hash = test_util.merkle_hash(all_zeros, 0, cartesi.PMA_CMIO_RX_BUFFER_LOG2_SIZE) -- prepares and asserts the state before send_cmio_response is called local function assert_before_cmio_response_sent(machine) - machine:set_iflags_Y() + machine:write_reg("iflags_Y", 1) -- initial rx buffer should be all zeros assert(machine:read_memory(cartesi.PMA_CMIO_RX_BUFFER_START, max_rx_buffer_len) == all_zeros) end @@ -1187,7 +1193,7 @@ local function test_send_cmio_input_with_different_arguments() -- rx buffer should now contain the data assert(machine:read_memory(cartesi.PMA_CMIO_RX_BUFFER_START, max_rx_buffer_len) == data) -- iflags.Y should be cleared - assert(machine:read_iflags_Y() == false) + assert(machine:read_reg("iflags_Y") == 0) -- fromhost should reflect the reason and data length local expected_fromhost = ((reason & 0xffff) << 32) | (#data & 0xffffffff) assert(machine:read_reg("htif_fromhost") == expected_fromhost) @@ -1215,10 +1221,10 @@ local function test_send_cmio_input_with_different_arguments() local root_hash_after = machine:get_root_hash() -- check log local accesses = log.accesses - assert(#accesses == 5) + assert(#accesses == 4) assert_access(accesses, 1, { type = "read", - address = machine:get_reg_address("iflags"), + address = machine:get_reg_address("iflags_Y"), log2_size = 3, }) assert_access(accesses, 2, { @@ -1236,13 +1242,8 @@ local function test_send_cmio_input_with_different_arguments() log2_size = 3, }) assert_access(accesses, 4, { - type = "read", - address = machine:get_reg_address("iflags"), - log2_size = 3, - }) - assert_access(accesses, 5, { type = "write", - address = machine:get_reg_address("iflags"), + address = machine:get_reg_address("iflags_Y"), log2_size = 3, }) -- ask machine to verify state transitions @@ -1251,20 +1252,20 @@ local function test_send_cmio_input_with_different_arguments() ) end end + test_send_cmio_input_with_different_arguments() do_test("Dump of log produced by send_cmio_response should match", function(machine) - machine:set_iflags_Y() + machine:write_reg("iflags_Y", 1) local data = "0123456789" local reason = 7 local log = machine:log_send_cmio_response(reason, data, cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) -- luacheck: push no max line length local expected_dump = "begin send cmio response\n" - .. " 1: read iflags.Y@0x2e8(744): 0x1a(26)\n" + .. " 1: read iflags.Y@0x2f8(760): 0x1(1)\n" .. ' 2: write cmio rx buffer@0x60000000(1610612736): hash:"290decd9"(2^5 bytes) -> hash:"555b1f6d"(2^5 bytes)\n' - .. " 3: write htif.fromhost@0x318(792): 0x0(0) -> 0x70000000a(30064771082)\n" - .. " 4: read iflags.Y@0x2e8(744): 0x1a(26)\n" - .. " 5: write iflags.Y@0x2e8(744): 0x1a(26) -> 0x18(24)\n" + .. " 3: write htif.fromhost@0x330(816): 0x0(0) -> 0x70000000a(30064771082)\n" + .. " 4: write iflags.Y@0x2f8(760): 0x1(1) -> 0x0(0)\n" .. "end send cmio response\n" -- luacheck: pop local temp_file = test_util.new_temp_file() @@ -1307,10 +1308,10 @@ do_test("send_cmio_response with different data sizes", function(machine) machine:write_memory(cartesi.PMA_CMIO_RX_BUFFER_START, initial_rx_buffer) assert(machine:read_memory(cartesi.PMA_CMIO_RX_BUFFER_START, rx_buffer_size) == initial_rx_buffer) local data = string.rep("a", case.data_len) - machine:set_iflags_Y() + machine:write_reg("iflags_Y", 1) if logging then local log = machine:log_send_cmio_response(reason, data) - assert(#log.accesses == 5, string.format("log should have 5 accesses, but it has %s", #log.accesses)) + assert(#log.accesses == 4, string.format("log should have 4 accesses, but it has %s", #log.accesses)) assert(log.accesses[2].type == "write", "access 2 should be a write") assert(1 << log.accesses[2].log2_size == case.write_len, "log2_size of write access does not match") else @@ -1338,18 +1339,19 @@ do_test("send_cmio_response of zero bytes", function(machine) local initial_rx_buffer = string.rep("x", rx_buffer_size) machine:write_memory(cartesi.PMA_CMIO_RX_BUFFER_START, initial_rx_buffer) assert(machine:read_memory(cartesi.PMA_CMIO_RX_BUFFER_START, rx_buffer_size) == initial_rx_buffer) - machine:set_iflags_Y() + machine:write_reg("iflags_Y", 1) local reason = 1 local data = "" machine:send_cmio_response(reason, data) local new_rx_buffer = machine:read_memory(cartesi.PMA_CMIO_RX_BUFFER_START, rx_buffer_size) assert(new_rx_buffer == initial_rx_buffer, "rx_buffer should not have been modified") - assert(machine:read_iflags_Y() == false, "iflags.Y should be cleared") + assert(machine:read_reg("iflags_Y") == 0, "iflags.Y should be cleared") -- log and verify - machine:set_iflags_Y() + machine:write_reg("iflags_Y", 1) local hash_before = machine:get_root_hash() local log = machine:log_send_cmio_response(reason, data) - assert(#log.accesses == 4, "log should have 4 accesses") + util.dump_log(log, io.stderr) + assert(#log.accesses == 3, "log should have 3 accesses") local hash_after = machine:get_root_hash() machine:verify_send_cmio_response(reason, data, hash_before, log, hash_after) end) @@ -1560,7 +1562,7 @@ test_util.make_do_test(build_machine, machine_type, { uarch = {} })("log_step sa }) machine:write_reg("mcycle", 0) - assert(machine:read_mcycle() == 0) + assert(machine:read_reg("mcycle") == 0) -- log_step should fail because the temp file already exists success, err = pcall(function() machine:log_step(1, filename1) @@ -1569,13 +1571,13 @@ test_util.make_do_test(build_machine, machine_type, { uarch = {} })("log_step sa assert(err:match("file already exists")) -- delete file and confirm that machine is on same mcycle os.remove(filename1) - assert(machine:read_mcycle() == 0) + assert(machine:read_reg("mcycle") == 0) -- get current root hash and log step local root_hash_before = machine:get_root_hash() local mcycle_count = 10 local status = machine:log_step(mcycle_count, filename1) assert(status == cartesi.BREAK_REASON_REACHED_TARGET_MCYCLE) - assert(machine:read_mcycle() == mcycle_count) + assert(machine:read_reg("mcycle") == mcycle_count) local root_hash_after = machine:get_root_hash() assert(root_hash_before ~= root_hash_after) -- verify step should pass diff --git a/tests/lua/machine-test.lua b/tests/lua/machine-test.lua index bdf5a277..dde12021 100755 --- a/tests/lua/machine-test.lua +++ b/tests/lua/machine-test.lua @@ -158,9 +158,9 @@ do_test("machine halt and yield flags and config matches", function(machine) assert(initial_config["processor"]["pc"] == cartesi.PMA_RAM_START, "pc value does not match") assert(initial_config["ram"]["length"] == 1048576, "ram length value does not match") -- Check machine is not halted - assert(not machine:read_iflags_H(), "machine shouldn't be halted") + assert(machine:read_reg("iflags_H") == 0, "machine shouldn't be halted") -- Check machine is not yielded - assert(not machine:read_iflags_Y(), "machine shouldn't be yielded") + assert(machine:read_reg("iflags_Y") == 0, "machine shouldn't be yielded") end) print("\n\ntesting if machine initial hash is correct") @@ -221,13 +221,13 @@ end) print("\n\nrun machine to 1000 mcycle and check for mcycle and root hash") do_test("mcycle and root hash should match", function(machine) -- Run to 1000 cycle tics - local current_mcycle = machine:read_mcycle() + local current_mcycle = machine:read_reg("mcycle") while current_mcycle < 1000 do machine:run(1000) - current_mcycle = machine:read_mcycle() + current_mcycle = machine:read_reg("mcycle") end - assert(machine:read_mcycle() == 1000, "machine mcycle should be 1000") + assert(machine:read_reg("mcycle") == 1000, "machine mcycle should be 1000") local root_hash = machine:get_root_hash() @@ -248,9 +248,9 @@ do_test("mcycle and root hash should match", function(machine) machine:run(MAX_MCYCLE) -- Check machine is halted - assert(machine:read_iflags_H(), "machine should be halted") + assert(machine:read_reg("iflags_H") ~= 0, "machine should be halted") -- Check for end mcycle - local end_mcycle = machine:read_mcycle() + local end_mcycle = machine:read_reg("mcycle") assert(end_mcycle == 3, "machine mcycle should be 3") local root_hash = machine:get_root_hash() @@ -278,10 +278,10 @@ if machine_type == "local" then assert(machine:run(1000) == cartesi.BREAK_REASON_YIELDED_SOFTLY) -- Check machine state - assert(machine:read_mcycle() == 1, "machine mcycle should be 1") - assert(not machine:read_iflags_H()) - assert(not machine:read_iflags_Y()) - assert(not machine:read_iflags_X()) + assert(machine:read_reg("mcycle") == 1, "machine mcycle should be 1") + assert(machine:read_reg("iflags_H") == 0) + assert(machine:read_reg("iflags_Y") == 0) + assert(machine:read_reg("iflags_X") == 0) -- Check if previous instruction match local prev_insn = string.unpack("> 1 == 0, "invalid return code") - assert(machine:read_mcycle() == EXPECTED_MCYCLE, "invalid mcycle") + assert(machine:read_reg("mcycle") == EXPECTED_MCYCLE, "invalid mcycle") end print("testing mtime interrupt") @@ -50,7 +50,7 @@ print("testing mtime interrupt") do_test("machine:run should interrupt for mtime", function(machine) for _ = 1, EXPECTED_MCYCLE do machine:run(-1) - if machine:read_iflags_H() then + if machine:read_reg("iflags_H") ~= 0 then break end end @@ -61,7 +61,7 @@ end) do_test("machine:log_step_uarch should interrupt for mtime", function(machine) for _ = 1, EXPECTED_MCYCLE do machine:log_step_uarch() - if machine:read_iflags_H() then + if machine:read_reg("iflags_H") ~= 0 then break end end diff --git a/tests/lua/uarch-riscv-tests.lua b/tests/lua/uarch-riscv-tests.lua index e3859739..5a471384 100755 --- a/tests/lua/uarch-riscv-tests.lua +++ b/tests/lua/uarch-riscv-tests.lua @@ -271,7 +271,7 @@ local function read_all(path) end local function check_test_result(machine, ctx) - local actual_cycle = machine:read_uarch_cycle() + local actual_cycle = machine:read_reg("uarch_cycle") if ctx.uarch_run_success then if ctx.expected_error_pattern then fatal( @@ -477,10 +477,10 @@ local function run_machine_writing_json_logs(machine, ctx) local indent = 0 util.indentout(out, indent, '{ "steps":[\n') local step_count = 0 - while math.ult(machine:read_uarch_cycle(), max_cycle) do + while math.ult(machine:read_reg("uarch_cycle"), max_cycle) do local log = machine:log_step_uarch() step_count = step_count + 1 - local halted = machine:read_uarch_halt_flag() + local halted = machine:read_reg("uarch_halt_flag") ~= 0 write_log_to_file(log, out, indent + 1, halted) if halted then break @@ -495,7 +495,7 @@ end local function create_json_reset_log() local machine = build_machine() local test_name = "reset-uarch" - machine:set_uarch_halt_flag() + machine:write_reg("uarch_halt_flag", 1) local initial_root_hash = machine:get_root_hash() local log = machine:log_reset_uarch() local out = create_json_log_file(test_name .. "-steps") @@ -519,7 +519,7 @@ local function create_json_send_cmio_response_log() local test_name = "send-cmio-response" local response_data = "This is a test cmio response" local reason = 1 - machine:set_iflags_Y() + machine:write_reg("iflags_Y", 1) local initial_root_hash = machine:get_root_hash() local log = machine:log_send_cmio_response(reason, response_data) local out = create_json_log_file(test_name .. "-steps") diff --git a/tests/misc/test-machine-c-api.cpp b/tests/misc/test-machine-c-api.cpp index 3fdfedc6..ca22964c 100644 --- a/tests/misc/test-machine-c-api.cpp +++ b/tests/misc/test-machine-c-api.cpp @@ -715,64 +715,6 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(read_write_virtual_memory_massive_test, ordinary_ BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_INVALID_ARGUMENT); \ } -// clang-format off -CHECK_READER_FAILS_ON_nullptr_MACHINE(uint64_t, mcycle) -CHECK_READER_FAILS_ON_nullptr_MACHINE(uint64_t, uarch_cycle) -CHECK_READER_FAILS_ON_nullptr_MACHINE(bool, iflags_Y) -CHECK_READER_FAILS_ON_nullptr_MACHINE(bool, iflags_X) -CHECK_READER_FAILS_ON_nullptr_MACHINE(bool, iflags_H) - // clang-format on - - BOOST_AUTO_TEST_CASE_NOLINT(set_iflags_y_null_machine_test) { - cm_error error_code = cm_set_iflags_Y(nullptr); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_INVALID_ARGUMENT); -} - -BOOST_AUTO_TEST_CASE_NOLINT(reset_iflags_y_null_machine_test) { - cm_error error_code = cm_reset_iflags_Y(nullptr); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_INVALID_ARGUMENT); -} - -BOOST_FIXTURE_TEST_CASE_NOLINT(iflags_read_write_complex_test, ordinary_machine_fixture) { - uint64_t read_value = 0; - - cm_error error_code = cm_read_reg(_machine, CM_REG_IFLAGS, &read_value); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); - BOOST_CHECK_EQUAL(read_value, static_cast(0x18)); - - bool yflag{}; - bool xflag{}; - bool hflag{}; - error_code = cm_read_iflags_Y(_machine, &yflag); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); - BOOST_CHECK(!yflag); - error_code = cm_read_iflags_X(_machine, &xflag); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); - BOOST_CHECK(!xflag); - error_code = cm_read_iflags_H(_machine, &hflag); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); - BOOST_CHECK(!hflag); - - error_code = cm_set_iflags_Y(_machine); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); - error_code = cm_read_reg(_machine, CM_REG_IFLAGS, &read_value); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); - BOOST_CHECK_EQUAL(read_value, static_cast(0x1a)); - - error_code = cm_reset_iflags_Y(_machine); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); - error_code = cm_read_reg(_machine, CM_REG_IFLAGS, &read_value); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); - BOOST_CHECK_EQUAL(read_value, static_cast(0x18)); -} BOOST_FIXTURE_TEST_CASE_NOLINT(ids_read_test, ordinary_machine_fixture) { uint64_t vendorid{}; uint64_t archid{}; @@ -1213,7 +1155,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(log_step_uarch_until_halt, access_log_machine_fix uint64_t halt{1}; // at micro cycle 0 - error_code = cm_read_uarch_cycle(_machine, &cycle); + error_code = cm_read_reg(_machine, CM_REG_UARCH_CYCLE, &cycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(cycle, 0); @@ -1266,7 +1208,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(log_step_uarch_until_halt, access_log_machine_fix BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); // at micro cycle 4 - error_code = cm_read_uarch_cycle(_machine, &cycle); + error_code = cm_read_reg(_machine, CM_REG_UARCH_CYCLE, &cycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(cycle, 3); @@ -1325,7 +1267,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_run_1000_cycle_test, ordinary_machine_fix BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); uint64_t read_mcycle{}; - error_code = cm_read_mcycle(_machine, &read_mcycle); + error_code = cm_read_reg(_machine, CM_REG_MCYCLE, &read_mcycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); BOOST_CHECK_EQUAL(read_mcycle, static_cast(1000)); @@ -1348,7 +1290,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_run_to_past_test, ordinary_machine_fixtur BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); uint64_t read_mcycle{}; - error_code = cm_read_mcycle(_machine, &read_mcycle); + error_code = cm_read_reg(_machine, CM_REG_MCYCLE, &read_mcycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); BOOST_CHECK_EQUAL(read_mcycle, cycle_num); @@ -1367,7 +1309,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_run_long_cycle_test, ordinary_machine_fix BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); uint64_t read_mcycle{}; - error_code = cm_read_mcycle(_machine, &read_mcycle); + error_code = cm_read_reg(_machine, CM_REG_MCYCLE, &read_mcycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); BOOST_CHECK_EQUAL(read_mcycle, static_cast(600000)); @@ -1391,7 +1333,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_run_uarch_advance_one_cycle, access_log_m // ensure that uarch cycle is 0 uint64_t cycle{}; - cm_error error_code = cm_read_uarch_cycle(_machine, &cycle); + cm_error error_code = cm_read_reg(_machine, CM_REG_UARCH_CYCLE, &cycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); BOOST_REQUIRE_EQUAL(cycle, 0); @@ -1404,7 +1346,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_run_uarch_advance_one_cycle, access_log_m BOOST_REQUIRE_EQUAL(status, CM_UARCH_BREAK_REASON_REACHED_TARGET_CYCLE); // confirm uarch cycle was incremented - error_code = cm_read_uarch_cycle(_machine, &cycle); + error_code = cm_read_reg(_machine, CM_REG_UARCH_CYCLE, &cycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); BOOST_REQUIRE_EQUAL(cycle, 1); @@ -1413,7 +1355,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_run_uarch_advance_one_cycle, access_log_m BOOST_FIXTURE_TEST_CASE_NOLINT(machine_run_uarch_advance_until_halt, access_log_machine_fixture) { // ensure that uarch cycle is 0 uint64_t cycle{}; - cm_error error_code = cm_read_uarch_cycle(_machine, &cycle); + cm_error error_code = cm_read_reg(_machine, CM_REG_UARCH_CYCLE, &cycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); BOOST_REQUIRE_EQUAL(cycle, 0); @@ -1437,7 +1379,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_run_uarch_advance_until_halt, access_log_ BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); BOOST_REQUIRE_EQUAL(status, CM_UARCH_BREAK_REASON_REACHED_TARGET_CYCLE); - error_code = cm_read_uarch_cycle(_machine, &cycle); + error_code = cm_read_reg(_machine, CM_REG_UARCH_CYCLE, &cycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(cycle, 1); @@ -1455,7 +1397,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_run_uarch_advance_until_halt, access_log_ BOOST_REQUIRE_EQUAL(status, CM_UARCH_BREAK_REASON_UARCH_HALTED); // confirm uarch cycle advanced - error_code = cm_read_uarch_cycle(_machine, &cycle); + error_code = cm_read_reg(_machine, CM_REG_UARCH_CYCLE, &cycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); BOOST_REQUIRE_EQUAL(cycle, 3); @@ -1471,7 +1413,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_reset_uarch, ordinary_machine_fixture) { // ensure that uarch cycle is 0 uint64_t halt_cycle{}; uint64_t cycle{}; - cm_error error_code = cm_read_uarch_cycle(_machine, &cycle); + cm_error error_code = cm_read_reg(_machine, CM_REG_UARCH_CYCLE, &cycle); BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); @@ -1505,7 +1447,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_reset_uarch, ordinary_machine_fixture) { BOOST_REQUIRE_EQUAL(halt, 1); // save halt cycle - error_code = cm_read_uarch_cycle(_machine, &halt_cycle); + error_code = cm_read_reg(_machine, CM_REG_UARCH_CYCLE, &halt_cycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE(halt_cycle > 0); @@ -1515,7 +1457,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(machine_reset_uarch, ordinary_machine_fixture) { BOOST_REQUIRE_EQUAL(status, CM_UARCH_BREAK_REASON_UARCH_HALTED); // should stay at halt cycle - error_code = cm_read_uarch_cycle(_machine, &cycle); + error_code = cm_read_reg(_machine, CM_REG_UARCH_CYCLE, &cycle); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(cycle, halt_cycle); diff --git a/uarch/uarch-machine-state-access.h b/uarch/uarch-machine-state-access.h index f9b33cdf..1b945509 100644 --- a/uarch/uarch-machine-state-access.h +++ b/uarch/uarch-machine-state-access.h @@ -405,69 +405,36 @@ class uarch_machine_state_access : public i_state_access(machine_reg_address(machine_reg::iflags)); + uint64_t do_read_iprv() { + return raw_read_memory(machine_reg_address(machine_reg::iprv)); } - void do_write_iflags(uint64_t val) { - raw_write_memory(machine_reg_address(machine_reg::iflags), val); + void do_write_iprv(uint64_t val) { + raw_write_memory(machine_reg_address(machine_reg::iprv), val); } - void do_set_iflags_H() { - auto old_iflags = read_iflags(); - auto new_iflags = old_iflags | IFLAGS_H_MASK; - write_iflags(new_iflags); + uint64_t do_read_iflags_X() { + return raw_read_memory(machine_reg_address(machine_reg::iflags_X)); } - bool do_read_iflags_H() { - auto iflags = read_iflags(); - return (iflags & IFLAGS_H_MASK) != 0; + void do_write_iflags_X(uint64_t val) { + raw_write_memory(machine_reg_address(machine_reg::iflags_X), val); } - void do_set_iflags_X() { - auto old_iflags = read_iflags(); - auto new_iflags = old_iflags | IFLAGS_X_MASK; - write_iflags(new_iflags); + uint64_t do_read_iflags_Y() { + return raw_read_memory(machine_reg_address(machine_reg::iflags_Y)); } - void do_reset_iflags_X() { - auto old_iflags = read_iflags(); - auto new_iflags = old_iflags & (~IFLAGS_X_MASK); - write_iflags(new_iflags); + void do_write_iflags_Y(uint64_t val) { + raw_write_memory(machine_reg_address(machine_reg::iflags_Y), val); } - bool do_read_iflags_X() { - auto iflags = read_iflags(); - return (iflags & IFLAGS_X_MASK) != 0; + uint64_t do_read_iflags_H() { + return raw_read_memory(machine_reg_address(machine_reg::iflags_H)); } - void do_set_iflags_Y() { - auto old_iflags = read_iflags(); - auto new_iflags = old_iflags | IFLAGS_Y_MASK; - write_iflags(new_iflags); - } - - void do_reset_iflags_Y() { - auto old_iflags = read_iflags(); - auto new_iflags = old_iflags & (~IFLAGS_Y_MASK); - write_iflags(new_iflags); - } - - bool do_read_iflags_Y() { - auto iflags = read_iflags(); - return (iflags & IFLAGS_Y_MASK) != 0; - } - - uint8_t do_read_iflags_PRV() { - auto iflags = read_iflags(); - return (iflags & IFLAGS_PRV_MASK) >> IFLAGS_PRV_SHIFT; - } - - void do_write_iflags_PRV(uint8_t val) { - auto old_iflags = read_iflags(); - auto new_iflags = - (old_iflags & (~IFLAGS_PRV_MASK)) | ((static_cast(val) << IFLAGS_PRV_SHIFT) & IFLAGS_PRV_MASK); - write_iflags(new_iflags); + void do_write_iflags_H(uint64_t val) { + raw_write_memory(machine_reg_address(machine_reg::iflags_H), val); } uint64_t do_read_iunrep() {