Prepare for debug
This commit is contained in:
parent
5927dade4d
commit
4c60d6ae75
14
inc/CPU.h
14
inc/CPU.h
|
@ -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
|
||||||
|
|
175
src/CPU.cpp
175
src/CPU.cpp
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue