Prepare for debug

This commit is contained in:
mariusmonton 2021-02-21 13:48:41 +01:00
parent 5927dade4d
commit 4c60d6ae75
2 changed files with 106 additions and 83 deletions

View File

@ -52,8 +52,9 @@ public:
* @brief Constructor * @brief Constructor
* @param name Module name * @param name Module name
* @param PC Program Counter initialize value * @param PC Program Counter initialize value
* @param debug To start debugging
*/ */
CPU(sc_core::sc_module_name name, uint32_t PC); CPU(sc_core::sc_module_name name, uint32_t PC, bool debug);
/** /**
* @brief Destructor * @brief Destructor
@ -62,6 +63,11 @@ public:
MemoryInterface *mem_intf; MemoryInterface *mem_intf;
bool CPU_step(void);
Registers *getRegisterBank() {return register_bank;}
private: private:
Registers *register_bank; Registers *register_bank;
Performance *perf; Performance *perf;
@ -80,6 +86,12 @@ private:
sc_core::sc_time default_time; sc_core::sc_time default_time;
bool dmi_ptr_valid; bool dmi_ptr_valid;
tlm::tlm_generic_payload trans;
uint32_t INSTR;
unsigned char *dmi_ptr = nullptr;
/** /**
* *
* @brief Process and triggers IRQ if all conditions met * @brief Process and triggers IRQ if all conditions met

View File

@ -5,13 +5,12 @@
\date August 2018 \date August 2018
*/ */
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#include "CPU.h" #include "CPU.h"
SC_HAS_PROCESS(CPU); SC_HAS_PROCESS(CPU);
CPU::CPU(sc_core::sc_module_name const name, uint32_t PC) : CPU::CPU(sc_core::sc_module_name const name, uint32_t PC, bool debug) :
sc_module(name), instr_bus("instr_bus"), default_time(10, sc_module(name), instr_bus("instr_bus"), default_time(10,
sc_core::SC_NS) { sc_core::SC_NS), INSTR(0) {
register_bank = new Registers(); register_bank = new Registers();
mem_intf = new MemoryInterface(); mem_intf = new MemoryInterface();
@ -19,8 +18,6 @@ CPU::CPU(sc_core::sc_module_name const name, uint32_t PC) :
log = Log::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, (0x10000000 / 4) - 1);
irq_line_socket.register_b_transport(this, &CPU::call_interrupt); irq_line_socket.register_b_transport(this, &CPU::call_interrupt);
@ -40,8 +37,19 @@ CPU::CPU(sc_core::sc_module_name const name, uint32_t PC) :
a_inst = new A_extension(0, register_bank, mem_intf); a_inst = new A_extension(0, register_bank, mem_intf);
m_qk = new tlm_utils::tlm_quantumkeeper(); m_qk = new tlm_utils::tlm_quantumkeeper();
m_qk->reset();
SC_THREAD(CPU_thread); trans.set_command(tlm::TLM_READ_COMMAND);
trans.set_data_ptr(reinterpret_cast<unsigned char*>(&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);
if (!debug) {
SC_THREAD(CPU_thread);
}
} }
CPU::~CPU() { CPU::~CPU() {
@ -105,84 +113,87 @@ bool CPU::cpu_process_IRQ() {
return ret_value; return ret_value;
} }
bool CPU::CPU_step(void) {
bool incPCby2 = false;
bool PC_not_affected = false;
/* Get new PC value */
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 {
sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
tlm::tlm_dmi dmi_data;
trans.set_address(register_bank->getPC());
instr_bus->b_transport(trans, delay);
if (trans.is_response_error()) {
SC_REPORT_ERROR("CPU base", "Read memory");
}
if (trans.is_dmi_allowed()) {
dmi_ptr_valid = instr_bus->get_direct_mem_ptr(trans, dmi_data);
if (dmi_ptr_valid) {
std::cout << "Get DMI_PTR " << std::endl;
dmi_ptr = dmi_data.get_dmi_ptr();
}
}
}
perf->codeMemoryRead();
log->SC_log(Log::INFO) << "PC: 0x" << std::hex << register_bank->getPC()
<< ". ";
inst->setInstr(INSTR);
bool breakpoint = false;
/* check what type of instruction is and execute it */
switch (inst->check_extension()) {
[[likely]] case BASE_EXTENSION:
PC_not_affected = exec->process_instruction(inst, &breakpoint);
incPCby2 = false;
break;
case C_EXTENSION:
PC_not_affected = c_inst->process_instruction(inst, &breakpoint);
incPCby2 = true;
break;
case M_EXTENSION:
PC_not_affected = m_inst->process_instruction(inst);
incPCby2 = false;
break;
case A_EXTENSION:
PC_not_affected = a_inst->process_instruction(inst);
incPCby2 = false;
break;
[[unlikely]] default:
std::cout << "Extension not implemented yet" << std::endl;
inst->dump();
exec->NOP();
}
if (breakpoint == true) {
std::cout << "Breakpoint set to true\n";
}
perf->instructionsInc();
if (PC_not_affected == true) {
register_bank->incPC(incPCby2);
}
return breakpoint;
}
void CPU::CPU_thread(void) { void CPU::CPU_thread(void) {
tlm::tlm_generic_payload *trans = new tlm::tlm_generic_payload; sc_core::sc_time instr_time = default_time;
uint32_t INSTR;
sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
bool PC_not_affected = false;
bool incPCby2 = false;
tlm::tlm_dmi dmi_data;
unsigned char *dmi_ptr = nullptr;
trans->set_command(tlm::TLM_READ_COMMAND);
trans->set_data_ptr(reinterpret_cast<unsigned char*>(&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);
m_qk->reset();
while (1) { while (1) {
/* Get new PC value */
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 {
trans->set_address(register_bank->getPC());
instr_bus->b_transport(*trans, delay);
if (trans->is_response_error()) { /* Process one instruction */
SC_REPORT_ERROR("CPU base", "Read memory"); CPU_step();
}
if (trans->is_dmi_allowed()) {
dmi_ptr_valid = instr_bus->get_direct_mem_ptr(*trans, dmi_data);
if (dmi_ptr_valid) {
std::cout << "Get DMI_PTR " << std::endl;
dmi_ptr = dmi_data.get_dmi_ptr();
}
}
}
perf->codeMemoryRead();
log->SC_log(Log::INFO) << "PC: 0x" << std::hex << register_bank->getPC()
<< ". ";
inst->setInstr(INSTR);
/* check what type of instruction is and execute it */
switch (inst->check_extension()) {
[[likely]] case BASE_EXTENSION:
PC_not_affected = exec->process_instruction(inst);
incPCby2 = false;
break;
case C_EXTENSION:
PC_not_affected = c_inst->process_instruction(inst);
incPCby2 = true;
break;
case M_EXTENSION:
PC_not_affected = m_inst->process_instruction(inst);
incPCby2 = false;
break;
case A_EXTENSION:
PC_not_affected = a_inst->process_instruction(inst);
incPCby2 = false;
break;
[[unlikely]] default:
std::cout << "Extension not implemented yet" << std::endl;
inst->dump();
exec->NOP();
}
perf->instructionsInc();
if (PC_not_affected == true) {
register_bank->incPC(incPCby2);
}
/* Process IRQ (if any) */ /* Process IRQ (if any) */
cpu_process_IRQ(); cpu_process_IRQ();
@ -196,7 +207,7 @@ void CPU::CPU_thread(void) {
m_qk->sync(); m_qk->sync();
} }
#else #else
sc_core::wait(default_time); sc_core::wait(instr_time);
#endif #endif
} // while(1) } // while(1)
} // CPU_thread } // CPU_thread
@ -210,7 +221,7 @@ void CPU::call_interrupt(tlm::tlm_generic_payload &trans,
} }
void CPU::invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) { void CPU::invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) {
(void) start; (void) start;
(void) end; (void) end;
dmi_ptr_valid = false; dmi_ptr_valid = false;
} }