Fixed 64bit integer base instruction set
This commit is contained in:
@ -308,6 +308,14 @@ public:
|
||||
|
||||
mstatus_t mstatus;
|
||||
|
||||
static const reg_t mstatus_reset_val = 0;
|
||||
|
||||
void write_mstatus(T val, unsigned priv_lvl){
|
||||
auto mask = get_mask(priv_lvl);
|
||||
auto new_val = (mstatus & ~mask) | (val & mask);
|
||||
mstatus=new_val;
|
||||
}
|
||||
|
||||
T satp;
|
||||
|
||||
static constexpr T get_misa() { return (1UL << 30) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; }
|
||||
@ -379,14 +387,29 @@ public:
|
||||
|
||||
mstatus_t mstatus;
|
||||
|
||||
static const reg_t mstatus_reset_val = 0xa00000000;
|
||||
|
||||
void write_mstatus(T val, unsigned priv_lvl){
|
||||
T old_val = mstatus;
|
||||
auto mask = get_mask(priv_lvl);
|
||||
auto new_val = (old_val & ~mask) | (val & mask);
|
||||
if((new_val&mstatus.SXL.Mask)==0){
|
||||
new_val |= old_val&mstatus.SXL.Mask;
|
||||
}
|
||||
if((new_val&mstatus.UXL.Mask)==0){
|
||||
new_val |= old_val&mstatus.UXL.Mask;
|
||||
}
|
||||
mstatus=new_val;
|
||||
}
|
||||
|
||||
T satp;
|
||||
|
||||
static constexpr T get_misa() { return (2ULL << 62) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; }
|
||||
|
||||
static constexpr T get_mask(unsigned priv_lvl) {
|
||||
switch (priv_lvl) {
|
||||
case PRIV_U: return 0x8000000000000011ULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
|
||||
case PRIV_S: return 0x80000003000de133ULL; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011
|
||||
case PRIV_U: return 0x8000000f00000011ULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
|
||||
case PRIV_S: return 0x8000000f000de133ULL; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011
|
||||
default: return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011
|
||||
}
|
||||
}
|
||||
@ -423,6 +446,8 @@ public:
|
||||
riscv_hart_msu_vp();
|
||||
virtual ~riscv_hart_msu_vp() = default;
|
||||
|
||||
void reset(uint64_t address) override;
|
||||
|
||||
void load_file(std::string name, int type = -1) override;
|
||||
|
||||
virtual phys_addr_t v2p(const iss::addr_t &addr);
|
||||
@ -573,66 +598,71 @@ iss::status riscv_hart_msu_vp<BASE>::read(const iss::addr_t &addr, unsigned leng
|
||||
LOG(DEBUG) << "read of " << length << " bytes @addr " << addr;
|
||||
}
|
||||
#endif
|
||||
switch (addr.space) {
|
||||
case traits<BASE>::MEM: {
|
||||
if ((addr.type & (iss::ACCESS_TYPE - iss::DEBUG)) == iss::FETCH && (addr.val & 0x1) == 1) {
|
||||
fault_data = addr.val;
|
||||
if ((addr.type & iss::DEBUG)) throw trap_access(0, addr.val);
|
||||
this->reg.trap_state = (1 << 31); // issue trap 0
|
||||
return iss::Err;
|
||||
}
|
||||
try {
|
||||
if ((addr.val & ~PGMASK) != ((addr.val + length - 1) & ~PGMASK)) { // we may cross a page boundary
|
||||
vm_info vm = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
|
||||
if (vm.levels != 0) { // VM is active
|
||||
auto split_addr = (addr.val + length) & ~PGMASK;
|
||||
auto len1 = split_addr - addr.val;
|
||||
auto res = read(addr, len1, data);
|
||||
if (res == iss::Ok)
|
||||
res = read(iss::addr_t{addr.type, addr.space, split_addr}, length - len1, data + len1);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr);
|
||||
auto res = read_mem(paddr, length, data);
|
||||
if (res != iss::Ok) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||
return res;
|
||||
} catch (trap_access &ta) {
|
||||
this->reg.trap_state = (1 << 31) | ta.id;
|
||||
return iss::Err;
|
||||
}
|
||||
} break;
|
||||
case traits<BASE>::CSR: {
|
||||
if (length != sizeof(reg_t)) return iss::Err;
|
||||
return read_csr(addr.val, *reinterpret_cast<reg_t *const>(data));
|
||||
} break;
|
||||
case traits<BASE>::FENCE: {
|
||||
if ((addr.val + length) > mem.size()) return iss::Err;
|
||||
switch (addr.val) {
|
||||
case 2: // SFENCE:VMA lower
|
||||
case 3: { // SFENCE:VMA upper
|
||||
auto tvm = state.mstatus.TVM;
|
||||
if (this->reg.machine_state == PRIV_S & tvm != 0) {
|
||||
this->reg.trap_state = (1 << 31) | (2 << 16);
|
||||
this->fault_data = this->reg.PC;
|
||||
try {
|
||||
switch (addr.space) {
|
||||
case traits<BASE>::MEM: {
|
||||
if ((addr.type & (iss::ACCESS_TYPE - iss::DEBUG)) == iss::FETCH && (addr.val & 0x1) == 1) {
|
||||
fault_data = addr.val;
|
||||
if ((addr.type & iss::DEBUG)) throw trap_access(0, addr.val);
|
||||
this->reg.trap_state = (1 << 31); // issue trap 0
|
||||
return iss::Err;
|
||||
}
|
||||
return iss::Ok;
|
||||
try {
|
||||
if ((addr.val & ~PGMASK) != ((addr.val + length - 1) & ~PGMASK)) { // we may cross a page boundary
|
||||
vm_info vm = hart_state<reg_t>::decode_vm_info(this->reg.machine_state, state.satp);
|
||||
if (vm.levels != 0) { // VM is active
|
||||
auto split_addr = (addr.val + length) & ~PGMASK;
|
||||
auto len1 = split_addr - addr.val;
|
||||
auto res = read(addr, len1, data);
|
||||
if (res == iss::Ok)
|
||||
res = read(iss::addr_t{addr.type, addr.space, split_addr}, length - len1, data + len1);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr);
|
||||
auto res = read_mem(paddr, length, data);
|
||||
if (res != iss::Ok) this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault
|
||||
return res;
|
||||
} catch (trap_access &ta) {
|
||||
this->reg.trap_state = (1 << 31) | ta.id;
|
||||
return iss::Err;
|
||||
}
|
||||
} break;
|
||||
case traits<BASE>::CSR: {
|
||||
if (length != sizeof(reg_t)) return iss::Err;
|
||||
return read_csr(addr.val, *reinterpret_cast<reg_t *const>(data));
|
||||
} break;
|
||||
case traits<BASE>::FENCE: {
|
||||
if ((addr.val + length) > mem.size()) return iss::Err;
|
||||
switch (addr.val) {
|
||||
case 2: // SFENCE:VMA lower
|
||||
case 3: { // SFENCE:VMA upper
|
||||
auto tvm = state.mstatus.TVM;
|
||||
if (this->reg.machine_state == PRIV_S & tvm != 0) {
|
||||
this->reg.trap_state = (1 << 31) | (2 << 16);
|
||||
this->fault_data = this->reg.PC;
|
||||
return iss::Err;
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case traits<BASE>::RES: {
|
||||
auto it = atomic_reservation.find(addr.val);
|
||||
if (it != atomic_reservation.end() && (*it).second != 0) {
|
||||
memset(data, 0xff, length);
|
||||
atomic_reservation.erase(addr.val);
|
||||
} else
|
||||
memset(data, 0, length);
|
||||
} break;
|
||||
default:
|
||||
return iss::Err; // assert("Not supported");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case traits<BASE>::RES: {
|
||||
auto it = atomic_reservation.find(addr.val);
|
||||
if (it != atomic_reservation.end() && (*it).second != 0) {
|
||||
memset(data, 0xff, length);
|
||||
atomic_reservation.erase(addr.val);
|
||||
} else
|
||||
memset(data, 0, length);
|
||||
} break;
|
||||
default:
|
||||
return iss::Err; // assert("Not supported");
|
||||
return iss::Ok;
|
||||
} catch (trap_access &ta) {
|
||||
this->reg.trap_state = (1 << 31) | ta.id;
|
||||
return iss::Err;
|
||||
}
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
template <typename BASE>
|
||||
@ -810,10 +840,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_status(unsign
|
||||
template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_status(unsigned addr, reg_t val) {
|
||||
auto req_priv_lvl = addr >> 8;
|
||||
if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data);
|
||||
auto mask = hart_state<reg_t>::get_mask(req_priv_lvl);
|
||||
auto old_val = state.mstatus;
|
||||
auto new_val = (old_val & ~mask) | (val & mask);
|
||||
state.mstatus = new_val;
|
||||
state.write_mstatus(val, req_priv_lvl);
|
||||
check_interrupt();
|
||||
return iss::Ok;
|
||||
}
|
||||
@ -980,6 +1007,12 @@ inline void riscv_hart_msu_vp<BASE>::notify_phase(iss::arch_if::exec_phase phase
|
||||
BASE::notify_phase(phase);
|
||||
}
|
||||
|
||||
template<typename BASE>
|
||||
inline void riscv_hart_msu_vp<BASE>::reset(uint64_t address) {
|
||||
BASE::reset(address);
|
||||
state.mstatus = hart_state<reg_t>::mstatus_reset_val;
|
||||
}
|
||||
|
||||
template <typename BASE> void riscv_hart_msu_vp<BASE>::check_interrupt() {
|
||||
auto status = state.mstatus;
|
||||
auto ip = csr[mip];
|
||||
|
@ -28,7 +28,7 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Created on: Wed Oct 18 11:42:36 CEST 2017
|
||||
// Created on: Fri Nov 17 20:34:49 CET 2017
|
||||
// * rv32imac.h Author: <CoreDSL Generator>
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -126,7 +126,7 @@ struct rv32imac: public arch_if {
|
||||
using addr_t = typename traits<rv32imac>::addr_t;
|
||||
|
||||
rv32imac();
|
||||
~rv32imac() = default;
|
||||
~rv32imac();
|
||||
|
||||
void reset(uint64_t address=0) override;
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Created on: Wed Oct 18 11:42:36 CEST 2017
|
||||
// Created on: Fri Nov 17 20:34:49 CET 2017
|
||||
// * rv64ia.h Author: <CoreDSL Generator>
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
Reference in New Issue
Block a user