From d42d67b9918266b2abcaeaa9838216400b5131d4 Mon Sep 17 00:00:00 2001 From: mariusmonton Date: Thu, 28 Mar 2019 22:52:36 +0100 Subject: [PATCH] DMI access added (if available) --- inc/BusCtrl.h | 3 + inc/CPU.h | 5 + src/BusCtrl.cpp | 11 + src/CPU.cpp | 950 ++++++++++++++++++++++++---------------------- src/Memory.cpp | 13 +- src/Simulator.cpp | 6 +- 6 files changed, 516 insertions(+), 472 deletions(-) diff --git a/inc/BusCtrl.h b/inc/BusCtrl.h index b700f32..2634bf4 100644 --- a/inc/BusCtrl.h +++ b/inc/BusCtrl.h @@ -86,6 +86,9 @@ public: private: Log *log; + + bool instr_direct_mem_ptr(tlm::tlm_generic_payload&, tlm::tlm_dmi& dmi_data); + void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end); }; #endif diff --git a/inc/CPU.h b/inc/CPU.h index ac7b387..f48fe31 100644 --- a/inc/CPU.h +++ b/inc/CPU.h @@ -70,6 +70,9 @@ private: bool interrupt; uint32_t int_cause; bool irq_already_down; + + bool dmi_ptr_valid; + /** * * @brief Process and triggers IRQ if all conditions met @@ -100,6 +103,8 @@ private: * When called it triggers an IRQ */ void call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay); + + void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end); }; #endif diff --git a/src/BusCtrl.cpp b/src/BusCtrl.cpp index 84bb894..de6d7ef 100644 --- a/src/BusCtrl.cpp +++ b/src/BusCtrl.cpp @@ -10,6 +10,8 @@ BusCtrl::BusCtrl(sc_module_name name): sc_module(name) cpu_instr_socket.register_b_transport(this, &BusCtrl::b_transport); cpu_data_socket.register_b_transport(this, &BusCtrl::b_transport); log = Log::getInstance(); + cpu_instr_socket.register_get_direct_mem_ptr(this, &BusCtrl::instr_direct_mem_ptr); + memory_socket.register_invalidate_direct_mem_ptr( this, &BusCtrl::invalidate_direct_mem_ptr); } @@ -42,3 +44,12 @@ void BusCtrl::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) { trans.set_response_status( tlm::TLM_OK_RESPONSE ); } + +bool BusCtrl::instr_direct_mem_ptr(tlm::tlm_generic_payload& gp, tlm::tlm_dmi& dmi_data) { + return memory_socket->get_direct_mem_ptr(gp, dmi_data); +} + +void BusCtrl::invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) { + cpu_instr_socket->invalidate_direct_mem_ptr(start, end); +} + diff --git a/src/CPU.cpp b/src/CPU.cpp index 3e3ea46..d5ce378 100644 --- a/src/CPU.cpp +++ b/src/CPU.cpp @@ -1,446 +1,449 @@ #include "CPU.h" SC_HAS_PROCESS(CPU); -CPU::CPU(sc_module_name name, uint32_t PC): sc_module(name) -, instr_bus("instr_bus") -{ - register_bank = new Registers(); - exec = new Execute("Execute", register_bank); - perf = Performance::getInstance(); - log = Log::getInstance(); +CPU::CPU(sc_module_name name, uint32_t PC) : + sc_module(name), instr_bus("instr_bus") { + register_bank = new Registers(); + exec = new Execute("Execute", register_bank); + perf = Performance::getInstance(); + log = Log::getInstance(); - register_bank->setPC(PC); + register_bank->setPC(PC); - //register_bank->setValue(Registers::sp, (0xD0000 / 4) - 1); - register_bank->setValue(Registers::sp, (0x10000000 / 4) - 1); + //register_bank->setValue(Registers::sp, (0xD0000 / 4) - 1); + register_bank->setValue(Registers::sp, (0x10000000 / 4) - 1); - irq_line_socket.register_b_transport(this, &CPU::call_interrupt); - interrupt = false; + irq_line_socket.register_b_transport(this, &CPU::call_interrupt); + interrupt = false; - int_cause = 0; - irq_already_down = false; + int_cause = 0; + irq_already_down = false; - SC_THREAD(CPU_thread); + dmi_ptr_valid = false; + instr_bus.register_invalidate_direct_mem_ptr( this, &CPU::invalidate_direct_mem_ptr); + + SC_THREAD(CPU_thread); } CPU::~CPU() { - cout << "*********************************************" << endl; - register_bank->dump(); - cout << "end time: " << sc_time_stamp() << endl; - perf->dump(); - cout << "*********************************************" << endl; + cout << "*********************************************" << endl; + register_bank->dump(); + cout << "end time: " << sc_time_stamp() << endl; + perf->dump(); + cout << "*********************************************" << endl; } bool CPU::cpu_process_IRQ() { - uint32_t csr_temp; - uint32_t new_pc, old_pc; - bool ret_value = false; + uint32_t csr_temp; + uint32_t new_pc, old_pc; + bool ret_value = false; - if (interrupt == true) { - csr_temp = register_bank->getCSR(CSR_MSTATUS); - if (csr_temp & MSTATUS_MIE) { - } else { - log->SC_log(Log::DEBUG) << "interrupt delayed" << endl; - return ret_value; - } + if (interrupt == true) { + csr_temp = register_bank->getCSR(CSR_MSTATUS); + if (csr_temp & MSTATUS_MIE) { + } else { + log->SC_log(Log::DEBUG) << "interrupt delayed" << endl; + return ret_value; + } - csr_temp = register_bank->getCSR(CSR_MIP); - - if ( (csr_temp & MIP_MEIP ) == 0 ) { - csr_temp |= MIP_MEIP; // MEIP bit in MIP register (11th bit) - register_bank->setCSR(CSR_MIP, csr_temp); - log->SC_log(Log::DEBUG) << "Interrupt!" << endl; - - /* updated MEPC register */ - old_pc = register_bank->getPC(); - register_bank->setCSR(CSR_MEPC, old_pc); - log->SC_log(Log::INFO) << "Old PC Value 0x" << hex << old_pc << endl; - - /* update MCAUSE register */ - register_bank->setCSR(CSR_MCAUSE, 0x80000000); - - /* set new PC address */ - new_pc = register_bank->getCSR(CSR_MTVEC); - //new_pc = new_pc & 0xFFFFFFFC; // last two bits always to 0 - log->SC_log(Log::DEBUG) << "NEW PC Value 0x" << hex << new_pc << endl; - register_bank->setPC(new_pc); - - ret_value = true; - interrupt = false; - irq_already_down = false; - } - } else { - if (irq_already_down == false) { csr_temp = register_bank->getCSR(CSR_MIP); - csr_temp &= ~MIP_MEIP; - register_bank->setCSR(CSR_MIP, csr_temp); - irq_already_down = true; - } - } - return ret_value; + if ((csr_temp & MIP_MEIP) == 0) { + csr_temp |= MIP_MEIP; // MEIP bit in MIP register (11th bit) + register_bank->setCSR(CSR_MIP, csr_temp); + log->SC_log(Log::DEBUG) << "Interrupt!" << endl; + + /* updated MEPC register */ + old_pc = register_bank->getPC(); + register_bank->setCSR(CSR_MEPC, old_pc); + log->SC_log(Log::INFO) << "Old PC Value 0x" << hex << old_pc + << endl; + + /* update MCAUSE register */ + register_bank->setCSR(CSR_MCAUSE, 0x80000000); + + /* set new PC address */ + new_pc = register_bank->getCSR(CSR_MTVEC); + //new_pc = new_pc & 0xFFFFFFFC; // last two bits always to 0 + log->SC_log(Log::DEBUG) << "NEW PC Value 0x" << hex << new_pc + << endl; + register_bank->setPC(new_pc); + + ret_value = true; + interrupt = false; + irq_already_down = false; + } + } else { + if (irq_already_down == false) { + csr_temp = register_bank->getCSR(CSR_MIP); + csr_temp &= ~MIP_MEIP; + register_bank->setCSR(CSR_MIP, csr_temp); + irq_already_down = true; + } + } + + return ret_value; } bool CPU::process_c_instruction(Instruction &inst) { - bool PC_not_affected = true; + bool PC_not_affected = true; - C_Instruction c_inst(inst.getInstr()); + C_Instruction c_inst(inst.getInstr()); - switch(c_inst.decode()) { - case OP_C_ADDI4SPN: - PC_not_affected = exec->C_ADDI4SPN(inst); - break; - case OP_C_LW: - exec->LW(inst, true); - break; - case OP_C_SW: - exec->SW(inst, true); - break; - case OP_C_ADDI: - exec->ADDI(inst, true); - break; - case OP_C_JAL: - exec->JAL(inst, true, 1); - PC_not_affected = false; - break; - case OP_C_J: - exec->JAL(inst, true, 0); - PC_not_affected = false; - break; - case OP_C_LI: - exec->C_LI(inst); - break; - case OP_C_SLLI: - exec->C_SLLI(inst); - break; - case OP_C_LWSP: - exec->C_LWSP(inst); - break; - case OP_C_JR: - exec->C_JR(inst); - PC_not_affected = false; - break; - case OP_C_MV: - exec->C_MV(inst); - break; - case OP_C_JALR: - exec->JALR(inst, true); - PC_not_affected = false; - break; - case OP_C_ADD: - exec->C_ADD(inst); - break; - case OP_C_SWSP: - exec->C_SWSP(inst); - break; - case OP_C_ADDI16SP: - exec->C_ADDI16SP(inst); - break; - case OP_C_BEQZ: - exec->C_BEQZ(inst); - PC_not_affected = false; - break; - case OP_C_BNEZ: - exec->C_BNEZ(inst); - PC_not_affected = false; - break; - case OP_C_SRLI: - exec->C_SRLI(inst); - break; - case OP_C_SRAI: - exec->C_SRAI(inst); - break; - case OP_C_ANDI: - exec->C_ANDI(inst); - break; - case OP_C_SUB: - exec->C_SUB(inst); - break; - case OP_C_XOR: - exec->C_XOR(inst); - break; - case OP_C_OR: - exec->C_OR(inst); - break; - case OP_C_AND: - exec->C_AND(inst); - break; - default: - std::cout << "C instruction not implemented yet" << endl; - inst.dump(); - exec->NOP(inst); - //sc_stop(); - break; + switch (c_inst.decode()) { + case OP_C_ADDI4SPN: + PC_not_affected = exec->C_ADDI4SPN(inst); + break; + case OP_C_LW: + exec->LW(inst, true); + break; + case OP_C_SW: + exec->SW(inst, true); + break; + case OP_C_ADDI: + exec->ADDI(inst, true); + break; + case OP_C_JAL: + exec->JAL(inst, true, 1); + PC_not_affected = false; + break; + case OP_C_J: + exec->JAL(inst, true, 0); + PC_not_affected = false; + break; + case OP_C_LI: + exec->C_LI(inst); + break; + case OP_C_SLLI: + exec->C_SLLI(inst); + break; + case OP_C_LWSP: + exec->C_LWSP(inst); + break; + case OP_C_JR: + exec->C_JR(inst); + PC_not_affected = false; + break; + case OP_C_MV: + exec->C_MV(inst); + break; + case OP_C_JALR: + exec->JALR(inst, true); + PC_not_affected = false; + break; + case OP_C_ADD: + exec->C_ADD(inst); + break; + case OP_C_SWSP: + exec->C_SWSP(inst); + break; + case OP_C_ADDI16SP: + exec->C_ADDI16SP(inst); + break; + case OP_C_BEQZ: + exec->C_BEQZ(inst); + PC_not_affected = false; + break; + case OP_C_BNEZ: + exec->C_BNEZ(inst); + PC_not_affected = false; + break; + case OP_C_SRLI: + exec->C_SRLI(inst); + break; + case OP_C_SRAI: + exec->C_SRAI(inst); + break; + case OP_C_ANDI: + exec->C_ANDI(inst); + break; + case OP_C_SUB: + exec->C_SUB(inst); + break; + case OP_C_XOR: + exec->C_XOR(inst); + break; + case OP_C_OR: + exec->C_OR(inst); + break; + case OP_C_AND: + exec->C_AND(inst); + break; + default: + std::cout << "C instruction not implemented yet" << endl; + inst.dump(); + exec->NOP(inst); + //sc_stop(); + break; - } + } - return PC_not_affected; + return PC_not_affected; } bool CPU::process_m_instruction(Instruction &inst) { - bool PC_not_affected = true; + bool PC_not_affected = true; - M_Instruction m_inst(inst.getInstr()); + M_Instruction m_inst(inst.getInstr()); - switch(m_inst.decode()) { - case OP_M_MUL: - exec->M_MUL(inst); - break; - case OP_M_MULH: - exec->M_MULH(inst); - break; - case OP_M_MULHSU: - exec->M_MULHSU(inst); - break; - case OP_M_MULHU: - exec->M_MULHU(inst); - break; - case OP_M_DIV: - exec->M_DIV(inst); - break; - case OP_M_DIVU: - exec->M_DIVU(inst); - break; - case OP_M_REM: - exec->M_REM(inst); - break; - case OP_M_REMU: - exec->M_REMU(inst); - break; - default: - std::cout << "M instruction not implemented yet" << endl; - inst.dump(); - exec->NOP(inst); - break; - } + switch (m_inst.decode()) { + case OP_M_MUL: + exec->M_MUL(inst); + break; + case OP_M_MULH: + exec->M_MULH(inst); + break; + case OP_M_MULHSU: + exec->M_MULHSU(inst); + break; + case OP_M_MULHU: + exec->M_MULHU(inst); + break; + case OP_M_DIV: + exec->M_DIV(inst); + break; + case OP_M_DIVU: + exec->M_DIVU(inst); + break; + case OP_M_REM: + exec->M_REM(inst); + break; + case OP_M_REMU: + exec->M_REMU(inst); + break; + default: + std::cout << "M instruction not implemented yet" << endl; + inst.dump(); + exec->NOP(inst); + break; + } - return PC_not_affected; + return PC_not_affected; } - bool CPU::process_a_instruction(Instruction inst) { - bool PC_not_affected = true; + bool PC_not_affected = true; - A_Instruction a_inst(inst.getInstr()); + A_Instruction a_inst(inst.getInstr()); - switch(a_inst.decode()) { - case OP_A_LR: - exec->A_LR(inst); - break; - case OP_A_SC: - exec->A_SC(inst); - break; - case OP_A_AMOSWAP: - exec->A_AMOSWAP(inst); - break; - case OP_A_AMOADD: - exec->A_AMOADD(inst); - break; - case OP_A_AMOXOR: - exec->A_AMOXOR(inst); - break; - case OP_A_AMOAND: - exec->A_AMOAND(inst); - break; - case OP_A_AMOOR: - exec->A_AMOOR(inst); - break; - case OP_A_AMOMIN: - exec->A_AMOMIN(inst); - break; - case OP_A_AMOMAX: - exec->A_AMOMAX(inst); - break; - case OP_A_AMOMINU: - exec->A_AMOMINU(inst); - break; - case OP_A_AMOMAXU: - exec->A_AMOMAXU(inst); - break; - default: - std::cout << "A instruction not implemented yet" << endl; - inst.dump(); - exec->NOP(inst); - break; - } + switch (a_inst.decode()) { + case OP_A_LR: + exec->A_LR(inst); + break; + case OP_A_SC: + exec->A_SC(inst); + break; + case OP_A_AMOSWAP: + exec->A_AMOSWAP(inst); + break; + case OP_A_AMOADD: + exec->A_AMOADD(inst); + break; + case OP_A_AMOXOR: + exec->A_AMOXOR(inst); + break; + case OP_A_AMOAND: + exec->A_AMOAND(inst); + break; + case OP_A_AMOOR: + exec->A_AMOOR(inst); + break; + case OP_A_AMOMIN: + exec->A_AMOMIN(inst); + break; + case OP_A_AMOMAX: + exec->A_AMOMAX(inst); + break; + case OP_A_AMOMINU: + exec->A_AMOMINU(inst); + break; + case OP_A_AMOMAXU: + exec->A_AMOMAXU(inst); + break; + default: + std::cout << "A instruction not implemented yet" << endl; + inst.dump(); + exec->NOP(inst); + break; + } - return PC_not_affected; + return PC_not_affected; } bool CPU::process_base_instruction(Instruction &inst) { - bool PC_not_affected = true; + bool PC_not_affected = true; - switch(inst.decode()) { - case OP_LUI: - exec->LUI(inst); - break; - case OP_AUIPC: - exec->AUIPC(inst); - break; - case OP_JAL: - exec->JAL(inst); - PC_not_affected = false; - break; - case OP_JALR: - exec->JALR(inst); - PC_not_affected = false; - break; - case OP_BEQ: - exec->BEQ(inst); - PC_not_affected = false; - break; - case OP_BNE: - exec->BNE(inst); - PC_not_affected = false; - break; - case OP_BLT: - exec->BLT(inst); - PC_not_affected = false; - break; - case OP_BGE: - exec->BGE(inst); - PC_not_affected = false; - break; - case OP_BLTU: - exec->BLTU(inst); - PC_not_affected = false; - break; - case OP_BGEU: - exec->BGEU(inst); - PC_not_affected = false; - break; - case OP_LB: - exec->LB(inst); - break; - case OP_LH: - exec->LH(inst); - break; - case OP_LW: - exec->LW(inst); - break; - case OP_LBU: - exec->LBU(inst); - break; - case OP_LHU: - exec->LHU(inst); - break; - case OP_SB: - exec->SB(inst); - break; - case OP_SH: - exec->SH(inst); - break; - case OP_SW: - exec->SW(inst); - break; - case OP_ADDI: - exec->ADDI(inst); - break; - case OP_SLTI: - exec->SLTI(inst); - break; - case OP_SLTIU: - exec->SLTIU(inst); - break; - case OP_XORI: - exec->XORI(inst); - break; - case OP_ORI: - exec->ORI(inst); - break; - case OP_ANDI: - exec->ANDI(inst); - break; - case OP_SLLI: - PC_not_affected = exec->SLLI(inst); - break; - case OP_SRLI: - exec->SRLI(inst); - break; - case OP_SRAI: - exec->SRAI(inst); - break; - case OP_ADD: - exec->ADD(inst); - break; - case OP_SUB: - exec->SUB(inst); - break; - case OP_SLL: - exec->SLL(inst); - break; - case OP_SLT: - exec->SLT(inst); - break; - case OP_SLTU: - exec->SLTU(inst); - break; - case OP_XOR: - exec->XOR(inst); - break; - case OP_SRL: - exec->SRL(inst); - break; - case OP_SRA: - exec->SRA(inst); - break; - case OP_OR: - exec->OR(inst); - break; - case OP_AND: - exec->AND(inst); - break; - case OP_FENCE: - exec->FENCE(inst); - break; - case OP_ECALL: - exec->ECALL(inst); - break; - case OP_EBREAK: - exec->EBREAK(inst); - break; - case OP_CSRRW: - exec->CSRRW(inst); - break; - case OP_CSRRS: - exec->CSRRS(inst); - break; - case OP_CSRRC: - exec->CSRRC(inst); - break; - case OP_CSRRWI: - exec->CSRRWI(inst); - break; - case OP_CSRRSI: - exec->CSRRSI(inst); - break; - case OP_CSRRCI: - exec->CSRRCI(inst); - break; + switch (inst.decode()) { + case OP_LUI: + exec->LUI(inst); + break; + case OP_AUIPC: + exec->AUIPC(inst); + break; + case OP_JAL: + exec->JAL(inst); + PC_not_affected = false; + break; + case OP_JALR: + exec->JALR(inst); + PC_not_affected = false; + break; + case OP_BEQ: + exec->BEQ(inst); + PC_not_affected = false; + break; + case OP_BNE: + exec->BNE(inst); + PC_not_affected = false; + break; + case OP_BLT: + exec->BLT(inst); + PC_not_affected = false; + break; + case OP_BGE: + exec->BGE(inst); + PC_not_affected = false; + break; + case OP_BLTU: + exec->BLTU(inst); + PC_not_affected = false; + break; + case OP_BGEU: + exec->BGEU(inst); + PC_not_affected = false; + break; + case OP_LB: + exec->LB(inst); + break; + case OP_LH: + exec->LH(inst); + break; + case OP_LW: + exec->LW(inst); + break; + case OP_LBU: + exec->LBU(inst); + break; + case OP_LHU: + exec->LHU(inst); + break; + case OP_SB: + exec->SB(inst); + break; + case OP_SH: + exec->SH(inst); + break; + case OP_SW: + exec->SW(inst); + break; + case OP_ADDI: + exec->ADDI(inst); + break; + case OP_SLTI: + exec->SLTI(inst); + break; + case OP_SLTIU: + exec->SLTIU(inst); + break; + case OP_XORI: + exec->XORI(inst); + break; + case OP_ORI: + exec->ORI(inst); + break; + case OP_ANDI: + exec->ANDI(inst); + break; + case OP_SLLI: + PC_not_affected = exec->SLLI(inst); + break; + case OP_SRLI: + exec->SRLI(inst); + break; + case OP_SRAI: + exec->SRAI(inst); + break; + case OP_ADD: + exec->ADD(inst); + break; + case OP_SUB: + exec->SUB(inst); + break; + case OP_SLL: + exec->SLL(inst); + break; + case OP_SLT: + exec->SLT(inst); + break; + case OP_SLTU: + exec->SLTU(inst); + break; + case OP_XOR: + exec->XOR(inst); + break; + case OP_SRL: + exec->SRL(inst); + break; + case OP_SRA: + exec->SRA(inst); + break; + case OP_OR: + exec->OR(inst); + break; + case OP_AND: + exec->AND(inst); + break; + case OP_FENCE: + exec->FENCE(inst); + break; + case OP_ECALL: + exec->ECALL(inst); + break; + case OP_EBREAK: + exec->EBREAK(inst); + break; + case OP_CSRRW: + exec->CSRRW(inst); + break; + case OP_CSRRS: + exec->CSRRS(inst); + break; + case OP_CSRRC: + exec->CSRRC(inst); + break; + case OP_CSRRWI: + exec->CSRRWI(inst); + break; + case OP_CSRRSI: + exec->CSRRSI(inst); + break; + case OP_CSRRCI: + exec->CSRRCI(inst); + break; - case OP_MRET: - exec->MRET(inst); - PC_not_affected = false; - break; - case OP_SRET: - exec->SRET(inst); - PC_not_affected = false; - break; - case OP_WFI: - exec->WFI(inst); - break; - case OP_SFENCE: - exec->SFENCE(inst); - break; - default: - std::cout << "Wrong instruction" << endl; - inst.dump(); - exec->NOP(inst); - //sc_stop(); - break; - } + case OP_MRET: + exec->MRET(inst); + PC_not_affected = false; + break; + case OP_SRET: + exec->SRET(inst); + PC_not_affected = false; + break; + case OP_WFI: + exec->WFI(inst); + break; + case OP_SFENCE: + exec->SFENCE(inst); + break; + default: + std::cout << "Wrong instruction" << endl; + inst.dump(); + exec->NOP(inst); + //sc_stop(); + break; + } - return PC_not_affected; + return PC_not_affected; } /** @@ -449,80 +452,103 @@ bool CPU::process_base_instruction(Instruction &inst) { */ void CPU::CPU_thread(void) { - tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload; - uint32_t INSTR; - sc_time delay = SC_ZERO_TIME; - bool PC_not_affected = false; - bool incPCby2 = false; + tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload; + uint32_t INSTR; + sc_time delay = SC_ZERO_TIME; + bool PC_not_affected = false; + bool incPCby2 = false; + tlm::tlm_dmi dmi_data; + unsigned char* dmi_ptr = NULL; - trans->set_command( tlm::TLM_READ_COMMAND ); - trans->set_data_ptr( reinterpret_cast(&INSTR) ); - trans->set_data_length( 4 ); - trans->set_streaming_width( 4 ); // = data_length to indicate no streaming - trans->set_byte_enable_ptr( 0 ); // 0 indicates unused - trans->set_dmi_allowed( false ); // Mandatory initial value - trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); + trans->set_command(tlm::TLM_READ_COMMAND); + trans->set_data_ptr(reinterpret_cast(&INSTR)); + trans->set_data_length(4); + trans->set_streaming_width(4); // = data_length to indicate no streaming + trans->set_byte_enable_ptr(0); // 0 indicates unused + trans->set_dmi_allowed(false); // Mandatory initial value + trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); - //register_bank->dump(); + //if (trans->is_dmi_allowed() ) { +// if (true) { +// dmi_ptr_valid = instr_bus->get_direct_mem_ptr(*trans, dmi_data); +// dmi_ptr = dmi_data.get_dmi_ptr(); +// } + //register_bank->dump(); - while(1) { - /* Get new PC value */ - //cout << "CPU: PC 0x" << hex << (uint32_t) register_bank->getPC() << endl; - trans->set_address( register_bank->getPC() ); - instr_bus->b_transport( *trans, delay); + while (1) { + /* Get new PC value */ + //cout << "CPU: PC 0x" << hex << (uint32_t) register_bank->getPC() << endl; + //dmi_ptr_valid = true; + if (dmi_ptr_valid == true) { + /* if memory_offset at Memory module is set, this won't work */ + memcpy(&INSTR, dmi_ptr + register_bank->getPC(), 4); + } else { + cout << "No DMI access" << endl; + trans->set_address(register_bank->getPC()); + instr_bus->b_transport(*trans, delay); - perf->codeMemoryRead(); + if (trans->is_response_error()) { + SC_REPORT_ERROR("CPU base", "Read memory"); + } - if ( trans->is_response_error() ) { - SC_REPORT_ERROR("CPU base", "Read memory"); - } else { - log->SC_log(Log::INFO) << "PC: 0x" << hex - << register_bank->getPC() << ". "; + dmi_ptr_valid = instr_bus->get_direct_mem_ptr(*trans, dmi_data); + if (dmi_ptr_valid) { + dmi_ptr = dmi_data.get_dmi_ptr(); + } + } - Instruction inst(INSTR); + perf->codeMemoryRead(); - /* check what type of instruction is and execute it */ - switch(inst.check_extension()) { - case BASE_EXTENSION: - PC_not_affected = process_base_instruction(inst); - incPCby2 = false; - break; - case C_EXTENSION: - PC_not_affected = process_c_instruction(inst); - incPCby2 = true; - break; - case M_EXTENSION: - PC_not_affected = process_m_instruction(inst); - incPCby2 = false; - break; - case A_EXTENSION: - PC_not_affected = process_a_instruction(inst); - incPCby2 = false; - break; - default: - std::cout << "Extension not implemented yet" << std::endl; - inst.dump(); - exec->NOP(inst); - } // switch (inst.check_extension()) - } + log->SC_log(Log::INFO) << "PC: 0x" << hex << register_bank->getPC() + << ". "; - perf->instructionsInc(); + Instruction inst(INSTR); - if (PC_not_affected == true) { - register_bank->incPC(incPCby2); - } + /* check what type of instruction is and execute it */ + switch (inst.check_extension()) { + case BASE_EXTENSION: + PC_not_affected = process_base_instruction(inst); + incPCby2 = false; + break; + case C_EXTENSION: + PC_not_affected = process_c_instruction(inst); + incPCby2 = true; + break; + case M_EXTENSION: + PC_not_affected = process_m_instruction(inst); + incPCby2 = false; + break; + case A_EXTENSION: + PC_not_affected = process_a_instruction(inst); + incPCby2 = false; + break; + default: + std::cout << "Extension not implemented yet" << std::endl; + inst.dump(); + exec->NOP(inst); + } // switch (inst.check_extension()) - /* Process IRQ (if any) */ - cpu_process_IRQ(); + perf->instructionsInc(); - /* Fixed instruction time to 10 ns (i.e. 100 MHz)*/ - sc_core::wait(10, SC_NS); - } // while(1) + if (PC_not_affected == true) { + register_bank->incPC(incPCby2); + } + + /* Process IRQ (if any) */ + cpu_process_IRQ(); + + /* Fixed instruction time to 10 ns (i.e. 100 MHz)*/ + sc_core::wait(10, SC_NS); + } // while(1) } // CPU_thread - void CPU::call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay) { - interrupt = true; - /* Socket caller send a cause (its id) */ - memcpy(&int_cause, trans.get_data_ptr(), sizeof(int)); + interrupt = true; + /* Socket caller send a cause (its id) */ + memcpy(&int_cause, trans.get_data_ptr(), sizeof(int)); +} + +void CPU::invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) +{ + dmi_ptr_valid = false; } diff --git a/src/Memory.cpp b/src/Memory.cpp index f4e03b2..ffc74c2 100644 --- a/src/Memory.cpp +++ b/src/Memory.cpp @@ -26,7 +26,8 @@ Memory::Memory(sc_module_name name, bool use_file): sc_module(name) socket.register_b_transport( this, &Memory::b_transport); socket.register_get_direct_mem_ptr(this, &Memory::get_direct_mem_ptr); socket.register_transport_dbg( this, &Memory::transport_dbg); - + memory_offset = 0; + program_counter = 0; //memset(mem, 0, SIZE*sizeof(uint8_t)); } @@ -82,7 +83,11 @@ void Memory::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) // Set DMI hint to indicated that DMI is supported // ********************************************* - trans.set_dmi_allowed(true); + if (memory_offset == 0) { + trans.set_dmi_allowed(true); + } else { + trans.set_dmi_allowed(false); + } // Obliged to set response status to indicate successful completion trans.set_response_status( tlm::TLM_OK_RESPONSE ); @@ -142,7 +147,7 @@ void Memory::readHexFile(string filename) { address = address + extended_address; //cout << "00 address 0x" << hex << address << endl; for (i=0; i < byte_count; i++) { - mem[address+i] = stol(line.substr(9+(i*2), 2), nullptr, 16); + mem[address+i] = stol(line.substr(9 + (i * 2), 2), nullptr, 16); } } else if (line.substr(7,2) == "02") { /* Extended segment address */ @@ -157,14 +162,12 @@ void Memory::readHexFile(string filename) { cout << "03 PC set to 0x" << hex << program_counter << endl; } else if (line.substr(7,2) == "04") { /* Start segment address */ - //extended_address = stol(line.substr(9,4), nullptr, 16) << 16; memory_offset = stol(line.substr(9,4), nullptr, 16) << 16; extended_address = 0; cout << "04 address set to 0x" << hex << extended_address << endl; cout << "04 offset set to 0x" << hex << memory_offset << endl; } else if (line.substr(7,2) == "05") { program_counter = stol(line.substr(9,8), nullptr, 16); - //program_counter = 0; cout << "05 PC set to 0x" << hex << program_counter << endl; } } diff --git a/src/Simulator.cpp b/src/Simulator.cpp index 27544f1..41aa47d 100644 --- a/src/Simulator.cpp +++ b/src/Simulator.cpp @@ -41,14 +41,11 @@ SC_MODULE(Simulator) BusCtrl* Bus; Trace *trace; Timer *timer; -// Log *log; uint32_t start_PC; SC_CTOR(Simulator) { -// log = Log::getInstance(); - MainMemory = new Memory("Main_Memory", filename); start_PC = MainMemory->getPCfromHEX(); @@ -127,16 +124,15 @@ void process_arguments(int argc, char* argv[]) { break; } } + if (filename.empty()) { filename = std::string(argv[optind]); } - } int sc_main(int argc, char* argv[]) { - /* Capture Ctrl+C and finish the simulation */ signal(SIGINT, intHandler);