From b0dcb3b60e3074636341b838c83b7985574d28be Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 25 Oct 2017 22:05:31 +0200 Subject: [PATCH] Fixed handling of compressed ISA --- dbt-core | 2 +- riscv.sc/src/sysc/core_complex.cpp | 19 +- riscv/gen_input/RV32C.core_desc | 104 ++++----- riscv/incl/iss/arch/riscv_hart_msu_vp.h | 28 ++- riscv/src/internal/vm_riscv.in.cpp | 5 +- riscv/src/internal/vm_rv32imac.cpp | 277 +++++++++++------------- sc-components | 2 +- 7 files changed, 219 insertions(+), 218 deletions(-) diff --git a/dbt-core b/dbt-core index 55b281a..29a6988 160000 --- a/dbt-core +++ b/dbt-core @@ -1 +1 @@ -Subproject commit 55b281a010a7cedc7ba23c3856a551a9ee314eb4 +Subproject commit 29a69884d2fcfb29f7a5f5a927e93e35f05fdd7e diff --git a/riscv.sc/src/sysc/core_complex.cpp b/riscv.sc/src/sysc/core_complex.cpp index f28448b..fc57487 100644 --- a/riscv.sc/src/sysc/core_complex.cpp +++ b/riscv.sc/src/sysc/core_complex.cpp @@ -97,14 +97,14 @@ public: void notify_phase(iss::arch_if::exec_phase phase); void disass_output(uint64_t pc, const std::string instr) override { -#ifndef WITH_SCV - std::stringstream s; - s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0') - << std::setw(sizeof(reg_t) * 2) << (reg_t)state.mstatus << std::dec << ";c:" << this->reg.icount << "]"; - CLOG(INFO, disass) << "0x"<>::reporting_level() && logging::Output2FILE::stream()){ + std::stringstream s; + s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0') + << std::setw(sizeof(reg_t) * 2) << (reg_t)state.mstatus << std::dec << ";c:" << this->reg.icount << "]"; + scc::Log>().get(logging::INFO, "disass") + << "0x"<disass_output(pc,instr); -#endif }; iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) { @@ -221,7 +221,7 @@ void core_complex::start_of_simulation() { quantum_keeper.reset(); if (elf_file.value.size() > 0) cpu->load_file(elf_file.value); #ifdef WITH_SCV - if (stream_handle == NULL) { + if (m_db!=nullptr && stream_handle == nullptr) { string basename(this->name()); stream_handle = new scv_tr_stream((basename + ".instr").c_str(), "TRANSACTOR", m_db); instr_tr_handle = new scv_tr_generator<>("execute", *stream_handle); @@ -232,6 +232,7 @@ void core_complex::start_of_simulation() { void core_complex::disass_output(uint64_t pc, const std::string instr_str) { #ifdef WITH_SCV + if (m_db==nullptr) return; if(tr_handle.is_active()) tr_handle.end_transaction(); tr_handle = instr_tr_handle->begin_transaction(); tr_handle.record_attribute("PC", pc); @@ -270,7 +271,7 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, gp.set_streaming_width(4); auto delay{quantum_keeper.get_local_time()}; #ifdef WITH_SCV - if(tr_handle.is_valid()){ + if(m_db!=nullptr && tr_handle.is_valid()){ if(is_fetch && tr_handle.is_active()) tr_handle.end_transaction(); auto preExt = new scv4tlm::tlm_recording_extension(tr_handle, this); gp.set_extension(preExt); diff --git a/riscv/gen_input/RV32C.core_desc b/riscv/gen_input/RV32C.core_desc index 43d584e..6b453b8 100644 --- a/riscv/gen_input/RV32C.core_desc +++ b/riscv/gen_input/RV32C.core_desc @@ -12,42 +12,37 @@ InsructionSet RV32CI { PC[XLEN](is_pc) } instructions{ - C.ADDI4SPN { //(RES, nzuimm=0) - encoding: b000 | nzuimm[5:4] | nzuimm[9:6] | nzuimm[2:2] | nzuimm[3:3] | rd[2:0] | b00; - args_disass: "x%rd$d, 0x%nzuimm$05x"; - if(nzuimm == 0) - raise(0, 2); + C.ADDI4SPN { //(RES, imm=0) + encoding: b000 | imm[5:4] | imm[9:6] | imm[2:2] | imm[3:3] | rd[2:0] | b00; + args_disass: "x%rd$d, 0x%imm$05x"; + if(imm == 0) raise(0, 2); val rd_idx[5] <= rd+8; val x2_idx[5] <= 2; - X[rd_idx] <= X[x2_idx] + nzuimm; + X[rd_idx] <= X[x2_idx] + imm; } C.LW { // (RV32) encoding: b010 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00; args_disass: "x(8+%rd$d), x(8+%rs1$d), 0x%uimm$05x"; val rs1_idx[5] <= rs1+8; - val adr[XLEN] <= X[rs1_idx]+uimm; val rd_idx[5] <= rd+8; - X[rd_idx] <= MEM[adr]{32}; + val offs[XLEN] <= X[rs1_idx]+uimm; + X[rd_idx] <= MEM[offs]{32}; } C.SW {//(RV32) encoding: b110 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00; args_disass: "x(8+%rs1$d), x(8+%rs2$d), 0x%uimm$05x"; val rs1_idx[5] <= rs1+8; - val adr[XLEN] <= X[rs1_idx]+uimm; val rs2_idx[5] <= rs2+8; - MEM[adr]{32} <= X[rs2_idx]; - } - C.NOP {//(RV32) - encoding: b000 | b0 | b00000 | b00000 | b01; //TODO - args_disass: ""; + val offs[XLEN] <= X[rs1_idx]+uimm; + MEM[offs]{32} <= X[rs2_idx]; } C.ADDI {//(RV32) - encoding:b000 | nzimm[5:5]s | rs1[4:0] | nzimm[4:0]s | b01; - args_disass: "x%rs1$d, 0x%nzimm$05x"; - if(nzimm == 0) - raise(0, 2); - X[rs1] <= X[rs1] + nzimm; - + encoding:b000 | imm[5:5]s | rs1[4:0] | imm[4:0]s | b01; + args_disass: "x%rs1$d, 0x%imm$05x"; + X[rs1] <= X[rs1] + imm; + } + C.NOP { + encoding:b000 | b0 | b00000 | b00000 | b01; } // C.JAL will be overwritten by C.ADDIW for RV64/128 C.JAL(no_cont) {//(RV32) @@ -60,35 +55,32 @@ InsructionSet RV32CI { C.LI {//(RV32) encoding:b010 | imm[5:5]s | rd[4:0] | imm[4:0]s | b01; args_disass: "x%rd$d, 0x%imm$05x"; - if(rd == 0) raise(0, 2); + if(rd == 0) raise(0, 2); //TODO: should it be handled as trap? X[rd] <= imm; } // order matters here as C.ADDI16SP overwrites C.LUI vor rd==2 C.LUI {//(RV32) - encoding:b011 | nzimm[17:17]s | rd[4:0] | nzimm[16:12]s | b01; - args_disass: "x%rd$d, 0x%nzimm$05x"; - if(rd == 0) raise(0, 2); - if(rd == 2) raise(0, 2); - if(nzimm == 0) raise(0, 2); - X[rd] <= nzimm; + encoding:b011 | imm[17:17]s | rd[4:0] | imm[16:12]s | b01; + args_disass: "x%rd$d, 0x%imm$05x"; + if(rd == 0) raise(0, 2); //TODO: should it be handled as trap? + if(imm == 0) raise(0, 2); //TODO: should it be handled as trap? + X[rd] <= imm; } C.ADDI16SP {//(RV32) - encoding:b011 | nzimm[9:9]s | b00010 | nzimm[4:4]s |nzimm[6:6]s | nzimm[8:7]s | nzimm[5:5]s | b01; - args_disass: "0x%nzimm$05x"; + encoding:b011 | imm[9:9]s | b00010 | imm[4:4]s | imm[6:6]s | imm[8:7]s | imm[5:5]s | b01; + args_disass: "0x%imm$05x"; val x2_idx[5] <= 2; - X[x2_idx] <= X[x2_idx]s + nzimm; + X[x2_idx] <= X[x2_idx]s + imm; } C.SRLI {//(RV32 nse) - encoding:b100 | shamt[5:5] | b00 | rs1[2:0] | shamt[4:0] | b01; + encoding:b100 | b0 | b00 | rs1[2:0] | shamt[4:0] | b01; args_disass: "x(8+%rs1$d), %shamt$d"; - if(shamt > 31) raise(0, 2); val rs1_idx[5] <= rs1+8; X[rs1_idx] <= shrl(X[rs1_idx], shamt); } C.SRAI {//(RV32) - encoding:b100 | shamt[5:5] | b01 | rs1[2:0] | shamt[4:0] | b01; + encoding:b100 | b0 | b01 | rs1[2:0] | shamt[4:0] | b01; args_disass: "x(8+%rs1$d), %shamt$d"; - if(shamt > 31) raise(0, 2); val rs1_idx[5] <= rs1+8; X[rs1_idx] <= shra(X[rs1_idx], shamt); } @@ -132,27 +124,23 @@ InsructionSet RV32CI { PC<=PC+imm; } C.BEQZ(no_cont) {//(RV32) - encoding:b110 | imm[8:8]s | imm[4:3]s | rs1d[2:0] | imm[7:6]s |imm[2:1]s | imm[5:5]s | b01; - args_disass: "x(8+%rs1d$d), 0x%imm$05x"; - val rs1[5] <= rs1d+8; - PC<=choose(X[rs1]==0, PC+imm, PC+2); + encoding:b110 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s |imm[2:1]s | imm[5:5]s | b01; + args_disass: "x(8+%rs1$d), 0x%imm$05x"; + val rs1_idx[5] <= rs1+8; + PC<=choose(X[rs1_idx]==0, PC+imm, PC+2); } C.BNEZ(no_cont) {//(RV32) - encoding:b111 | imm[8:8] | imm[4:3] | rs1d[2:0] | imm[7:6] | imm[2:1] | imm[5:5] | b01; - args_disass: "x(8+%rs1d$d),, 0x%imm$05x"; - val rs1[5] <= rs1d+8; - PC<=choose(X[rs1]!=0, PC+imm, PC+2); + encoding:b111 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s | imm[2:1]s | imm[5:5]s | b01; + args_disass: "x(8+%rs1$d), 0x%imm$05x"; + val rs1_idx[5] <= rs1+8; + PC<=choose(X[rs1_idx]!=0, PC+imm, PC+2); } C.SLLI {//(RV32) - encoding:b000 | shamt[5:5] | rs1[4:0] | shamt[4:0] | b10; + encoding:b000 | b0 | rs1[4:0] | shamt[4:0] | b10; args_disass: "x%rs1$d, %shamt$d"; if(rs1 == 0) raise(0, 2); - if(shamt > 31) raise(0, 2); X[rs1] <= shll(X[rs1], shamt); } - C.LQSP {//(RV128) - encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:4] | uimm[9:6] | b10; - } C.LWSP {// encoding:b010 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10; args_disass: "x%rd$d, sp, 0x%uimm$05x"; @@ -160,7 +148,7 @@ InsructionSet RV32CI { val offs[XLEN] <= X[x2_idx] + uimm; X[rd] <= MEM[offs]{32}; } - // order matters as C.JR is a special case of C.JR + // order matters as C.JR is a special case of C.MV C.MV {//(RV32) encoding:b100 | b0 | rd[4:0] | rs2[4:0] | b10; args_disass: "x%rd$d, x%rs2$d"; @@ -171,23 +159,23 @@ InsructionSet RV32CI { args_disass: "x%rs1$d"; PC <= X[rs1]; } - C.EBREAK(no_cont) {//(RV32) - encoding:b100 | b1 | b00000 | b00000 | b10; - raise(0, 3); - } - // order matters as C.JALR is a special case of C.ADD + // order matters as C.EBREAK is a special case of C.JALR which is a special case of C.ADD C.ADD {//(RV32) encoding:b100 | b1 | rd[4:0] | rs2[4:0] | b10; args_disass: "x%rd$d, x%rs2$d"; - X[rd] <= X[rd] + X[rs2]; + X[rd] <= X[rd] + X[rs2]; } C.JALR(no_cont) {//(RV32) encoding:b100 | b1 | rs1[4:0] | b00000 | b10; args_disass: "x%rs1$d"; - val rd[5] <= 1; - X[rd] <= PC+2; + val r_idx[5] <= 1; + X[r_idx] <= PC+2; PC<=X[rs1]; } + C.EBREAK(no_cont) {//(RV32) + encoding:b100 | b1 | b00000 | b00000 | b10; + raise(0, 3); + } C.SWSP {// encoding:b110 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10; args_disass: "x2+0x%uimm$05x, x%rs2$d"; @@ -195,6 +183,10 @@ InsructionSet RV32CI { val offs[XLEN] <= X[x2_idx] + uimm; MEM[offs]{32} <= X[rs2]; } + DII { + encoding:b000 | b0 | b00000 | b00000 | b00; + raise(0, 2); + } } } diff --git a/riscv/incl/iss/arch/riscv_hart_msu_vp.h b/riscv/incl/iss/arch/riscv_hart_msu_vp.h index 1f6ae7d..6a77273 100644 --- a/riscv/incl/iss/arch/riscv_hart_msu_vp.h +++ b/riscv/incl/iss/arch/riscv_hart_msu_vp.h @@ -435,6 +435,8 @@ public: virtual uint64_t leave_trap(uint64_t flags) override; void wait_until(uint64_t flags) override; + void notify_phase(iss::arch_if::exec_phase phase); + void disass_output(uint64_t pc, const std::string instr) override { std::stringstream s; s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0') @@ -468,6 +470,7 @@ protected: private: iss::status read_cycle(unsigned addr, reg_t &val); + iss::status read_time(unsigned addr, reg_t &val); iss::status read_status(unsigned addr, reg_t &val); iss::status write_status(unsigned addr, reg_t val); iss::status read_ie(unsigned addr, reg_t &val); @@ -489,6 +492,10 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() for (unsigned addr = mcycle; addr <= hpmcounter31; ++addr) csr_wr_cb[addr] = nullptr; for (unsigned addr = mcycleh; addr <= hpmcounter31h; ++addr) csr_wr_cb[addr] = nullptr; // special handling + csr_rd_cb[time] = &riscv_hart_msu_vp::read_time; + csr_wr_cb[time] = nullptr; + csr_rd_cb[timeh] = &riscv_hart_msu_vp::read_time; + csr_wr_cb[timeh] = nullptr; csr_rd_cb[mcycle] = &riscv_hart_msu_vp::read_cycle; csr_rd_cb[mcycleh] = &riscv_hart_msu_vp::read_cycle; csr_rd_cb[minstret] = &riscv_hart_msu_vp::read_cycle; @@ -781,6 +788,17 @@ template iss::status riscv_hart_msu_vp::read_cycle(unsigne return iss::Ok; } +template iss::status riscv_hart_msu_vp::read_time(unsigned addr, reg_t &val) { + uint64_t time_val=this->reg.icount>>12; + if (addr == time) { + val = static_cast(time_val); + } else if (addr == timeh) { + if (sizeof(typename traits::reg_t) != 4) return iss::Err; + val = static_cast(time_val >> 32); + } + return iss::Ok; +} + template iss::status riscv_hart_msu_vp::read_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); @@ -862,8 +880,9 @@ iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length if ((paddr.val + length) > mem.size()) return iss::Err; switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg - uint64_t mtime = this->reg.icount >> 12 /*12*/; - std::copy((uint8_t *)&mtime, ((uint8_t *)&mtime) + length, data); + if(sizeof(reg_t)csr[time]; + std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + length, data); } break; case 0x10008000: { const mem_type::page_type &p = mem(paddr.val / mem.page_size); @@ -954,6 +973,11 @@ iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned lengt return iss::Ok; } +template +inline void riscv_hart_msu_vp::notify_phase(iss::arch_if::exec_phase phase) { + BASE::notify_phase(phase); +} + template void riscv_hart_msu_vp::check_interrupt() { auto status = state.mstatus; auto ip = csr[mip]; diff --git a/riscv/src/internal/vm_riscv.in.cpp b/riscv/src/internal/vm_riscv.in.cpp index fa7bfac..2d37da0 100644 --- a/riscv/src/internal/vm_riscv.in.cpp +++ b/riscv/src/internal/vm_riscv.in.cpp @@ -148,7 +148,8 @@ protected: } // some compile time constants - enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; + // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; + enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; @@ -281,7 +282,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, } catch (trap_access &ta) { throw trap_access(ta.id, pc.val); } - if (insn == 0x0000006f) throw simulation_stopped(0); + if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack typename vm_impl::processing_pc_entry addr(*this, pc, paddr); ++inst_cnt; diff --git a/riscv/src/internal/vm_rv32imac.cpp b/riscv/src/internal/vm_rv32imac.cpp index 7549ccf..805b407 100644 --- a/riscv/src/internal/vm_rv32imac.cpp +++ b/riscv/src/internal/vm_rv32imac.cpp @@ -148,7 +148,8 @@ protected: } // some compile time constants - enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; + // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; + enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; @@ -364,10 +365,10 @@ private: {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, /* instruction C.SW */ {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.NOP */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, /* instruction C.ADDI */ {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, + /* instruction C.NOP */ + {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, /* instruction C.JAL */ {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, /* instruction C.LI */ @@ -377,9 +378,9 @@ private: /* instruction C.ADDI16SP */ {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, /* instruction C.SRLI */ - {16, 0b1000000000000001, 0b1110110000000011, &this_class::__c_srli}, + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1110110000000011, &this_class::__c_srai}, + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, /* instruction C.ANDI */ {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, /* instruction C.SUB */ @@ -397,23 +398,23 @@ private: /* instruction C.BNEZ */ {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, /* instruction C.SLLI */ - {16, 0b0000000000000010, 0b1110000000000011, &this_class::__c_slli}, - /* instruction C.LQSP */ - {16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_lqsp}, + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, /* instruction C.LWSP */ {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, /* instruction C.MV */ {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, /* instruction C.JR */ {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.EBREAK */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, /* instruction C.ADD */ {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, /* instruction C.JALR */ {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, + /* instruction C.EBREAK */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, /* instruction C.SWSP */ {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, + /* instruction DII */ + {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, }; // instruction LUI std::tuple __lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ @@ -3353,11 +3354,11 @@ private: this->gen_sync(iss::PRE_SYNC); uint8_t fld_rd_val = 0 | (bit_sub<2,3>(instr)); - uint16_t fld_nzuimm_val = 0 | (bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4); + uint16_t fld_imm_val = 0 | (bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4); if(this->disass_enabled){ /* generate console output when executing the command */ boost::format ins_fmter("C.ADDI4SPN x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_nzuimm_val; + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_imm_val; std::vector args { this->core_ptr, this->gen_const(64, pc.val), @@ -3367,14 +3368,14 @@ private: } pc=pc+2; - if(fld_nzuimm_val == 0){ + if(fld_imm_val == 0){ this->gen_raise_trap(0, 2); } uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t x2_idx_val = 2; Value* X_rd_idx_val = this->builder->CreateAdd( this->gen_reg_load(x2_idx_val, 0), - this->gen_const(32U, fld_nzuimm_val)); + this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ @@ -3406,11 +3407,11 @@ private: pc=pc+2; uint8_t rs1_idx_val = (fld_rs1_val + 8); - Value* adr_val = this->builder->CreateAdd( + uint8_t rd_idx_val = (fld_rd_val + 8); + Value* offs_val = this->builder->CreateAdd( this->gen_reg_load(rs1_idx_val, 0), this->gen_const(32U, fld_uimm_val)); - uint8_t rd_idx_val = (fld_rd_val + 8); - Value* X_rd_idx_val = this->gen_read_mem(traits::MEM, adr_val, 32/8); + Value* X_rd_idx_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); this->builder->CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ @@ -3442,15 +3443,47 @@ private: pc=pc+2; uint8_t rs1_idx_val = (fld_rs1_val + 8); - Value* adr_val = this->builder->CreateAdd( + uint8_t rs2_idx_val = (fld_rs2_val + 8); + Value* offs_val = this->builder->CreateAdd( this->gen_reg_load(rs1_idx_val, 0), this->gen_const(32U, fld_uimm_val)); - uint8_t rs2_idx_val = (fld_rs2_val + 8); - Value* MEM_adr_val = this->gen_reg_load(rs2_idx_val, 0); + Value* MEM_offs_val = this->gen_reg_load(rs2_idx_val, 0); this->gen_write_mem( traits::MEM, - adr_val, - this->builder->CreateZExtOrTrunc(MEM_adr_val,this->get_type(32))); + offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + // instruction C.ADDI + std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.ADDI"); + + this->gen_sync(iss::PRE_SYNC); + + int8_t fld_imm_val = 0 | (bit_sub<2,5>(instr)) | (signed_bit_sub<12,1>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.ADDI x%1$d, 0x%2$05x"); + ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder->CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder->CreateCall(this->mod->getFunction("print_disass"), args); + } + pc=pc+2; + + Value* X_rs1_val = this->builder->CreateAdd( + this->gen_reg_load(fld_rs1_val, 0), + this->gen_const(32U, fld_imm_val)); + this->builder->CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3467,12 +3500,10 @@ private: ; if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("C.NOP "); - ins_fmter ; std::vector args { this->core_ptr, this->gen_const(64, pc.val), - this->builder->CreateGlobalStringPtr(ins_fmter.str()), + this->builder->CreateGlobalStringPtr("C.NOP"), }; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3486,41 +3517,6 @@ private: return std::make_tuple(vm::CONT, bb); } - // instruction C.ADDI - std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.ADDI"); - - this->gen_sync(iss::PRE_SYNC); - - int8_t fld_nzimm_val = 0 | (bit_sub<2,5>(instr)) | (signed_bit_sub<12,1>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("C.ADDI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_nzimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder->CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - pc=pc+2; - - if(fld_nzimm_val == 0){ - this->gen_raise_trap(0, 2); - } - Value* X_rs1_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_nzimm_val)); - this->builder->CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - // instruction C.JAL std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ bb->setName("C.JAL"); @@ -3594,12 +3590,12 @@ private: this->gen_sync(iss::PRE_SYNC); - int32_t fld_nzimm_val = 0 | (bit_sub<2,5>(instr) << 12) | (signed_bit_sub<12,1>(instr) << 17); + int32_t fld_imm_val = 0 | (bit_sub<2,5>(instr) << 12) | (signed_bit_sub<12,1>(instr) << 17); uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); if(this->disass_enabled){ /* generate console output when executing the command */ boost::format ins_fmter("C.LUI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_nzimm_val; + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; std::vector args { this->core_ptr, this->gen_const(64, pc.val), @@ -3612,13 +3608,10 @@ private: if(fld_rd_val == 0){ this->gen_raise_trap(0, 2); } - if(fld_rd_val == 2){ + if(fld_imm_val == 0){ this->gen_raise_trap(0, 2); } - if(fld_nzimm_val == 0){ - this->gen_raise_trap(0, 2); - } - Value* X_rd_val = this->gen_const(32U, fld_nzimm_val); + Value* X_rd_val = this->gen_const(32U, fld_imm_val); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ @@ -3633,11 +3626,11 @@ private: this->gen_sync(iss::PRE_SYNC); - int16_t fld_nzimm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (signed_bit_sub<12,1>(instr) << 9); + int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (signed_bit_sub<12,1>(instr) << 9); if(this->disass_enabled){ /* generate console output when executing the command */ boost::format ins_fmter("C.ADDI16SP 0x%1$05x"); - ins_fmter % (int64_t)fld_nzimm_val; + ins_fmter % (int64_t)fld_imm_val; std::vector args { this->core_ptr, this->gen_const(64, pc.val), @@ -3652,7 +3645,7 @@ private: this->gen_ext( this->gen_reg_load(x2_idx_val, 0), 32, true), - this->gen_const(32U, fld_nzimm_val)); + this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(X_x2_idx_val, get_reg_ptr(x2_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ @@ -3667,7 +3660,7 @@ private: this->gen_sync(iss::PRE_SYNC); - uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5); + uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)); uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3682,9 +3675,6 @@ private: } pc=pc+2; - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 2); - } uint8_t rs1_idx_val = (fld_rs1_val + 8); Value* X_rs1_idx_val = this->builder->CreateLShr( this->gen_reg_load(rs1_idx_val, 0), @@ -3703,7 +3693,7 @@ private: this->gen_sync(iss::PRE_SYNC); - uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5); + uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)); uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3718,9 +3708,6 @@ private: } pc=pc+2; - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 2); - } uint8_t rs1_idx_val = (fld_rs1_val + 8); Value* X_rs1_idx_val = this->builder->CreateAShr( this->gen_reg_load(rs1_idx_val, 0), @@ -3938,11 +3925,11 @@ private: this->gen_sync(iss::PRE_SYNC); int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (signed_bit_sub<12,1>(instr) << 8); - uint8_t fld_rs1d_val = 0 | (bit_sub<7,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); if(this->disass_enabled){ /* generate console output when executing the command */ boost::format ins_fmter("C.BEQZ x(8+%1$d), 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1d_val % (int64_t)fld_imm_val; + ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; std::vector args { this->core_ptr, this->gen_const(64, pc.val), @@ -3952,11 +3939,11 @@ private: } pc=pc+2; - uint8_t rs1_val = (fld_rs1d_val + 8); + uint8_t rs1_idx_val = (fld_rs1_val + 8); Value* PC_val = this->gen_choose( this->builder->CreateICmp( ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1_val, 0), + this->gen_reg_load(rs1_idx_val, 0), this->gen_const(32U, 0)), this->builder->CreateAdd( this->gen_reg_load(traits::PC, 0), @@ -3977,12 +3964,12 @@ private: this->gen_sync(iss::PRE_SYNC); - uint16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8); - uint8_t fld_rs1d_val = 0 | (bit_sub<7,3>(instr)); + int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (signed_bit_sub<12,1>(instr) << 8); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("C.BNEZ x(8+%1$d),, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1d_val % (uint64_t)fld_imm_val; + boost::format ins_fmter("C.BNEZ x(8+%1$d), 0x%2$05x"); + ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; std::vector args { this->core_ptr, this->gen_const(64, pc.val), @@ -3992,11 +3979,11 @@ private: } pc=pc+2; - uint8_t rs1_val = (fld_rs1d_val + 8); + uint8_t rs1_idx_val = (fld_rs1_val + 8); Value* PC_val = this->gen_choose( this->builder->CreateICmp( ICmpInst::ICMP_NE, - this->gen_reg_load(rs1_val, 0), + this->gen_reg_load(rs1_idx_val, 0), this->gen_const(32U, 0)), this->builder->CreateAdd( this->gen_reg_load(traits::PC, 0), @@ -4017,7 +4004,7 @@ private: this->gen_sync(iss::PRE_SYNC); - uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5); + uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)); uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -4035,9 +4022,6 @@ private: if(fld_rs1_val == 0){ this->gen_raise_trap(0, 2); } - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 2); - } Value* X_rs1_val = this->builder->CreateShl( this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_shamt_val)); @@ -4049,33 +4033,6 @@ private: return std::make_tuple(vm::CONT, bb); } - // instruction C.LQSP - std::tuple __c_lqsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.LQSP"); - - this->gen_sync(iss::PRE_SYNC); - - uint16_t fld_uimm_val = 0 | (bit_sub<2,4>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 5); - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder->CreateGlobalStringPtr("C.LQSP"), - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - pc=pc+2; - - /* TODO: describe operations for C.LQSP ! */ - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - // instruction C.LWSP std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ bb->setName("C.LWSP"); @@ -4167,30 +4124,6 @@ private: return std::make_tuple(iss::vm::BRANCH, nullptr); } - // instruction C.EBREAK - std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.EBREAK"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder->CreateGlobalStringPtr("C.EBREAK"), - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - pc=pc+2; - - this->gen_raise_trap(0, 3); - this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - // instruction C.ADD std::tuple __c_add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ bb->setName("C.ADD"); @@ -4243,11 +4176,11 @@ private: } pc=pc+2; - uint8_t rd_val = 1; - Value* X_rd_val = this->builder->CreateAdd( + uint8_t r_idx_val = 1; + Value* X_r_idx_val = this->builder->CreateAdd( this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 2)); - this->builder->CreateStore(X_rd_val, get_reg_ptr(rd_val), false); + this->builder->CreateStore(X_r_idx_val, get_reg_ptr(r_idx_val), false); Value* PC_val = this->gen_reg_load(fld_rs1_val, 0); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ @@ -4255,6 +4188,30 @@ private: return std::make_tuple(iss::vm::BRANCH, nullptr); } + // instruction C.EBREAK + std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.EBREAK"); + + this->gen_sync(iss::PRE_SYNC); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder->CreateGlobalStringPtr("C.EBREAK"), + }; + this->builder->CreateCall(this->mod->getFunction("print_disass"), args); + } + pc=pc+2; + + this->gen_raise_trap(0, 3); + this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + // instruction C.SWSP std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ bb->setName("C.SWSP"); @@ -4292,6 +4249,32 @@ private: return std::make_tuple(vm::CONT, bb); } + // instruction DII + std::tuple __dii(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("DII"); + + this->gen_sync(iss::PRE_SYNC); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder->CreateGlobalStringPtr("DII"), + }; + this->builder->CreateCall(this->mod->getFunction("print_disass"), args); + } + pc=pc+2; + + this->gen_raise_trap(0, 2); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + /* end generated code */ /**************************************************************************** * end opcode definitions @@ -4358,7 +4341,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, } catch (trap_access &ta) { throw trap_access(ta.id, pc.val); } - if (insn == 0x0000006f) throw simulation_stopped(0); + if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack typename vm_impl::processing_pc_entry addr(*this, pc, paddr); ++inst_cnt; diff --git a/sc-components b/sc-components index fbd3247..ba65d9f 160000 --- a/sc-components +++ b/sc-components @@ -1 +1 @@ -Subproject commit fbd3247649d3b12d0e752c92a5d856572641445c +Subproject commit ba65d9f172246d6735a40fd6259ec13467e43419