removed creation of class every CPU loop. It should get better performance
This commit is contained in:
parent
4838205aba
commit
95b9685ad9
|
@ -57,6 +57,14 @@ public:
|
||||||
*/
|
*/
|
||||||
A_Instruction(sc_uint<32> instr);
|
A_Instruction(sc_uint<32> instr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets instruction
|
||||||
|
* @param p_instr instruction to decode
|
||||||
|
*/
|
||||||
|
void setInstr(uint32_t p_instr) {
|
||||||
|
a_instr = sc_uint<32> (p_instr);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Access to opcode field
|
* @brief Access to opcode field
|
||||||
* @return return opcode field
|
* @return return opcode field
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "tlm.h"
|
#include "tlm.h"
|
||||||
#include "tlm_utils/simple_initiator_socket.h"
|
#include "tlm_utils/simple_initiator_socket.h"
|
||||||
|
#include "tlm_utils/tlm_quantumkeeper.h"
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "Execute.h"
|
#include "Execute.h"
|
||||||
|
@ -66,11 +67,19 @@ private:
|
||||||
Registers *register_bank;
|
Registers *register_bank;
|
||||||
Performance *perf;
|
Performance *perf;
|
||||||
Log *log;
|
Log *log;
|
||||||
|
Instruction * inst;
|
||||||
|
C_Instruction *c_inst;
|
||||||
|
M_Instruction *m_inst;
|
||||||
|
A_Instruction *a_inst;
|
||||||
|
|
||||||
|
tlm_utils::tlm_quantumkeeper *m_qk;
|
||||||
|
|
||||||
bool interrupt;
|
bool interrupt;
|
||||||
uint32_t int_cause;
|
uint32_t int_cause;
|
||||||
bool irq_already_down;
|
bool irq_already_down;
|
||||||
|
|
||||||
|
sc_time default_time;
|
||||||
|
|
||||||
bool dmi_ptr_valid;
|
bool dmi_ptr_valid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -105,6 +105,13 @@ public:
|
||||||
*/
|
*/
|
||||||
C_Instruction(sc_uint<32> instr);
|
C_Instruction(sc_uint<32> instr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets instruction
|
||||||
|
* @param p_instr instruction to decode
|
||||||
|
*/
|
||||||
|
void setInstr(uint32_t p_instr) {
|
||||||
|
m_instr = sc_uint<32> (p_instr);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Access to opcode field
|
* @brief Access to opcode field
|
||||||
* @return return opcode field
|
* @return return opcode field
|
||||||
|
|
|
@ -443,6 +443,10 @@ public:
|
||||||
*/
|
*/
|
||||||
extension_t check_extension();
|
extension_t check_extension();
|
||||||
|
|
||||||
|
|
||||||
|
void setInstr(uint32_t p_instr) {
|
||||||
|
m_instr = p_instr;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @brief return instruction
|
* @brief return instruction
|
||||||
* @return all instruction bits (31:0)
|
* @return all instruction bits (31:0)
|
||||||
|
|
|
@ -51,6 +51,14 @@ public:
|
||||||
*/
|
*/
|
||||||
M_Instruction(sc_uint<32> instr);
|
M_Instruction(sc_uint<32> instr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets instruction
|
||||||
|
* @param p_instr instruction to decode
|
||||||
|
*/
|
||||||
|
void setInstr(uint32_t p_instr) {
|
||||||
|
m_instr = sc_uint<32> (p_instr);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Access to opcode field
|
* @brief Access to opcode field
|
||||||
* @return return opcode field
|
* @return return opcode field
|
||||||
|
|
|
@ -25,7 +25,7 @@ using namespace sc_dt;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Basic TLm-2 memory
|
* @brief Basic TLM-2 memory
|
||||||
*/
|
*/
|
||||||
class Memory: sc_module {
|
class Memory: sc_module {
|
||||||
public:
|
public:
|
||||||
|
|
86
src/CPU.cpp
86
src/CPU.cpp
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
SC_HAS_PROCESS(CPU);
|
SC_HAS_PROCESS(CPU);
|
||||||
CPU::CPU(sc_module_name name, uint32_t PC) :
|
CPU::CPU(sc_module_name name, uint32_t PC) :
|
||||||
sc_module(name), instr_bus("instr_bus") {
|
sc_module(name), instr_bus("instr_bus"), default_time(10, SC_NS) {
|
||||||
register_bank = new Registers();
|
register_bank = new Registers();
|
||||||
exec = new Execute("Execute", register_bank);
|
exec = new Execute("Execute", register_bank);
|
||||||
perf = Performance::getInstance();
|
perf = Performance::getInstance();
|
||||||
|
@ -20,7 +20,15 @@ CPU::CPU(sc_module_name name, uint32_t PC) :
|
||||||
irq_already_down = false;
|
irq_already_down = false;
|
||||||
|
|
||||||
dmi_ptr_valid = false;
|
dmi_ptr_valid = false;
|
||||||
instr_bus.register_invalidate_direct_mem_ptr( this, &CPU::invalidate_direct_mem_ptr);
|
instr_bus.register_invalidate_direct_mem_ptr(this,
|
||||||
|
&CPU::invalidate_direct_mem_ptr);
|
||||||
|
|
||||||
|
inst = new Instruction(0);
|
||||||
|
c_inst = new C_Instruction(0);
|
||||||
|
m_inst = new M_Instruction(0);
|
||||||
|
a_inst = new A_Instruction(0);
|
||||||
|
|
||||||
|
m_qk = new tlm_utils::tlm_quantumkeeper();
|
||||||
|
|
||||||
SC_THREAD(CPU_thread);
|
SC_THREAD(CPU_thread);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +48,7 @@ bool CPU::cpu_process_IRQ() {
|
||||||
|
|
||||||
if (interrupt == true) {
|
if (interrupt == true) {
|
||||||
csr_temp = register_bank->getCSR(CSR_MSTATUS);
|
csr_temp = register_bank->getCSR(CSR_MSTATUS);
|
||||||
if ( (csr_temp & MSTATUS_MIE) == 0) {
|
if ((csr_temp & MSTATUS_MIE) == 0) {
|
||||||
log->SC_log(Log::DEBUG) << "interrupt delayed" << endl;
|
log->SC_log(Log::DEBUG) << "interrupt delayed" << endl;
|
||||||
return ret_value;
|
return ret_value;
|
||||||
}
|
}
|
||||||
|
@ -87,9 +95,9 @@ bool CPU::cpu_process_IRQ() {
|
||||||
bool CPU::process_c_instruction(Instruction &inst) {
|
bool CPU::process_c_instruction(Instruction &inst) {
|
||||||
bool PC_not_affected = true;
|
bool PC_not_affected = true;
|
||||||
|
|
||||||
C_Instruction c_inst(inst.getInstr());
|
c_inst->setInstr(inst.getInstr());
|
||||||
|
|
||||||
switch (c_inst.decode()) {
|
switch (c_inst->decode()) {
|
||||||
case OP_C_ADDI4SPN:
|
case OP_C_ADDI4SPN:
|
||||||
PC_not_affected = exec->C_ADDI4SPN(inst);
|
PC_not_affected = exec->C_ADDI4SPN(inst);
|
||||||
break;
|
break;
|
||||||
|
@ -183,9 +191,9 @@ bool CPU::process_c_instruction(Instruction &inst) {
|
||||||
bool CPU::process_m_instruction(Instruction &inst) {
|
bool CPU::process_m_instruction(Instruction &inst) {
|
||||||
bool PC_not_affected = true;
|
bool PC_not_affected = true;
|
||||||
|
|
||||||
M_Instruction m_inst(inst.getInstr());
|
m_inst->setInstr(inst.getInstr());
|
||||||
|
|
||||||
switch (m_inst.decode()) {
|
switch (m_inst->decode()) {
|
||||||
case OP_M_MUL:
|
case OP_M_MUL:
|
||||||
exec->M_MUL(inst);
|
exec->M_MUL(inst);
|
||||||
break;
|
break;
|
||||||
|
@ -223,9 +231,9 @@ bool CPU::process_m_instruction(Instruction &inst) {
|
||||||
bool CPU::process_a_instruction(Instruction inst) {
|
bool CPU::process_a_instruction(Instruction inst) {
|
||||||
bool PC_not_affected = true;
|
bool PC_not_affected = true;
|
||||||
|
|
||||||
A_Instruction a_inst(inst.getInstr());
|
a_inst->setInstr(inst.getInstr());
|
||||||
|
|
||||||
switch (a_inst.decode()) {
|
switch (a_inst->decode()) {
|
||||||
case OP_A_LR:
|
case OP_A_LR:
|
||||||
exec->A_LR(inst);
|
exec->A_LR(inst);
|
||||||
break;
|
break;
|
||||||
|
@ -441,7 +449,7 @@ bool CPU::process_base_instruction(Instruction &inst) {
|
||||||
//sc_stop();
|
//sc_stop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PC_not_affected;
|
return PC_not_affected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,13 +459,13 @@ bool CPU::process_base_instruction(Instruction &inst) {
|
||||||
*/
|
*/
|
||||||
void CPU::CPU_thread(void) {
|
void CPU::CPU_thread(void) {
|
||||||
|
|
||||||
tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload;
|
tlm::tlm_generic_payload *trans = new tlm::tlm_generic_payload;
|
||||||
uint32_t INSTR;
|
uint32_t INSTR;
|
||||||
sc_time delay = SC_ZERO_TIME;
|
sc_time delay = SC_ZERO_TIME;
|
||||||
bool PC_not_affected = false;
|
bool PC_not_affected = false;
|
||||||
bool incPCby2 = false;
|
bool incPCby2 = false;
|
||||||
tlm::tlm_dmi dmi_data;
|
tlm::tlm_dmi dmi_data;
|
||||||
unsigned char* dmi_ptr = NULL;
|
unsigned char *dmi_ptr = NULL;
|
||||||
|
|
||||||
trans->set_command(tlm::TLM_READ_COMMAND);
|
trans->set_command(tlm::TLM_READ_COMMAND);
|
||||||
trans->set_data_ptr(reinterpret_cast<unsigned char*>(&INSTR));
|
trans->set_data_ptr(reinterpret_cast<unsigned char*>(&INSTR));
|
||||||
|
@ -467,17 +475,11 @@ void CPU::CPU_thread(void) {
|
||||||
trans->set_dmi_allowed(false); // Mandatory initial value
|
trans->set_dmi_allowed(false); // Mandatory initial value
|
||||||
trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
|
||||||
|
|
||||||
//if (trans->is_dmi_allowed() ) {
|
//Instruction inst(0);
|
||||||
// if (true) {
|
m_qk->reset();
|
||||||
// dmi_ptr_valid = instr_bus->get_direct_mem_ptr(*trans, dmi_data);
|
|
||||||
// dmi_ptr = dmi_data.get_dmi_ptr();
|
|
||||||
// }
|
|
||||||
//register_bank->dump();
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
/* Get new PC value */
|
/* 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 (dmi_ptr_valid == true) {
|
||||||
/* if memory_offset at Memory module is set, this won't work */
|
/* if memory_offset at Memory module is set, this won't work */
|
||||||
memcpy(&INSTR, dmi_ptr + register_bank->getPC(), 4);
|
memcpy(&INSTR, dmi_ptr + register_bank->getPC(), 4);
|
||||||
|
@ -490,12 +492,12 @@ void CPU::CPU_thread(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trans->is_dmi_allowed()) {
|
if (trans->is_dmi_allowed()) {
|
||||||
dmi_ptr_valid = instr_bus->get_direct_mem_ptr(*trans, dmi_data);
|
dmi_ptr_valid = instr_bus->get_direct_mem_ptr(*trans, dmi_data);
|
||||||
if (dmi_ptr_valid) {
|
if (dmi_ptr_valid) {
|
||||||
std::cout << "Get DMI_PTR " << std::endl;
|
std::cout << "Get DMI_PTR " << std::endl;
|
||||||
dmi_ptr = dmi_data.get_dmi_ptr();
|
dmi_ptr = dmi_data.get_dmi_ptr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
perf->codeMemoryRead();
|
perf->codeMemoryRead();
|
||||||
|
@ -503,30 +505,30 @@ void CPU::CPU_thread(void) {
|
||||||
log->SC_log(Log::INFO) << "PC: 0x" << hex << register_bank->getPC()
|
log->SC_log(Log::INFO) << "PC: 0x" << hex << register_bank->getPC()
|
||||||
<< ". ";
|
<< ". ";
|
||||||
|
|
||||||
Instruction inst(INSTR);
|
inst->setInstr(INSTR);
|
||||||
|
|
||||||
/* check what type of instruction is and execute it */
|
/* check what type of instruction is and execute it */
|
||||||
switch (inst.check_extension()) {
|
switch (inst->check_extension()) {
|
||||||
case BASE_EXTENSION:
|
case BASE_EXTENSION:
|
||||||
PC_not_affected = process_base_instruction(inst);
|
PC_not_affected = process_base_instruction(*inst);
|
||||||
incPCby2 = false;
|
incPCby2 = false;
|
||||||
break;
|
break;
|
||||||
case C_EXTENSION:
|
case C_EXTENSION:
|
||||||
PC_not_affected = process_c_instruction(inst);
|
PC_not_affected = process_c_instruction(*inst);
|
||||||
incPCby2 = true;
|
incPCby2 = true;
|
||||||
break;
|
break;
|
||||||
case M_EXTENSION:
|
case M_EXTENSION:
|
||||||
PC_not_affected = process_m_instruction(inst);
|
PC_not_affected = process_m_instruction(*inst);
|
||||||
incPCby2 = false;
|
incPCby2 = false;
|
||||||
break;
|
break;
|
||||||
case A_EXTENSION:
|
case A_EXTENSION:
|
||||||
PC_not_affected = process_a_instruction(inst);
|
PC_not_affected = process_a_instruction(*inst);
|
||||||
incPCby2 = false;
|
incPCby2 = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cout << "Extension not implemented yet" << std::endl;
|
std::cout << "Extension not implemented yet" << std::endl;
|
||||||
inst.dump();
|
inst->dump();
|
||||||
exec->NOP(inst);
|
exec->NOP(*inst);
|
||||||
} // switch (inst.check_extension())
|
} // switch (inst.check_extension())
|
||||||
|
|
||||||
perf->instructionsInc();
|
perf->instructionsInc();
|
||||||
|
@ -539,7 +541,18 @@ void CPU::CPU_thread(void) {
|
||||||
cpu_process_IRQ();
|
cpu_process_IRQ();
|
||||||
|
|
||||||
/* Fixed instruction time to 10 ns (i.e. 100 MHz)*/
|
/* Fixed instruction time to 10 ns (i.e. 100 MHz)*/
|
||||||
sc_core::wait(10, SC_NS);
|
//#define USE_QK
|
||||||
|
#ifdef USE_QK
|
||||||
|
// Model time used for additional processing
|
||||||
|
m_qk->inc(default_time);
|
||||||
|
if (m_qk->need_sync()) {
|
||||||
|
m_qk->sync();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
sc_core::wait(10, SC_NS);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
} // while(1)
|
} // while(1)
|
||||||
} // CPU_thread
|
} // CPU_thread
|
||||||
|
|
||||||
|
@ -549,7 +562,6 @@ void CPU::call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay) {
|
||||||
memcpy(&int_cause, trans.get_data_ptr(), sizeof(uint32_t));
|
memcpy(&int_cause, trans.get_data_ptr(), sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
{
|
|
||||||
dmi_ptr_valid = false;
|
dmi_ptr_valid = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue