DMI access added (if available)
This commit is contained in:
parent
24a27f39fe
commit
d42d67b991
|
@ -86,6 +86,9 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Log *log;
|
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
|
#endif
|
||||||
|
|
|
@ -70,6 +70,9 @@ private:
|
||||||
bool interrupt;
|
bool interrupt;
|
||||||
uint32_t int_cause;
|
uint32_t int_cause;
|
||||||
bool irq_already_down;
|
bool irq_already_down;
|
||||||
|
|
||||||
|
bool dmi_ptr_valid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Process and triggers IRQ if all conditions met
|
* @brief Process and triggers IRQ if all conditions met
|
||||||
|
@ -100,6 +103,8 @@ private:
|
||||||
* When called it triggers an IRQ
|
* When called it triggers an IRQ
|
||||||
*/
|
*/
|
||||||
void call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay);
|
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
|
#endif
|
||||||
|
|
|
@ -10,6 +10,8 @@ BusCtrl::BusCtrl(sc_module_name name): sc_module(name)
|
||||||
cpu_instr_socket.register_b_transport(this, &BusCtrl::b_transport);
|
cpu_instr_socket.register_b_transport(this, &BusCtrl::b_transport);
|
||||||
cpu_data_socket.register_b_transport(this, &BusCtrl::b_transport);
|
cpu_data_socket.register_b_transport(this, &BusCtrl::b_transport);
|
||||||
log = Log::getInstance();
|
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 );
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
84
src/CPU.cpp
84
src/CPU.cpp
|
@ -1,9 +1,8 @@
|
||||||
#include "CPU.h"
|
#include "CPU.h"
|
||||||
|
|
||||||
SC_HAS_PROCESS(CPU);
|
SC_HAS_PROCESS(CPU);
|
||||||
CPU::CPU(sc_module_name name, uint32_t PC): sc_module(name)
|
CPU::CPU(sc_module_name name, uint32_t PC) :
|
||||||
, instr_bus("instr_bus")
|
sc_module(name), instr_bus("instr_bus") {
|
||||||
{
|
|
||||||
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,6 +19,9 @@ CPU::CPU(sc_module_name name, uint32_t PC): sc_module(name)
|
||||||
int_cause = 0;
|
int_cause = 0;
|
||||||
irq_already_down = false;
|
irq_already_down = false;
|
||||||
|
|
||||||
|
dmi_ptr_valid = false;
|
||||||
|
instr_bus.register_invalidate_direct_mem_ptr( this, &CPU::invalidate_direct_mem_ptr);
|
||||||
|
|
||||||
SC_THREAD(CPU_thread);
|
SC_THREAD(CPU_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +48,7 @@ bool CPU::cpu_process_IRQ() {
|
||||||
|
|
||||||
csr_temp = register_bank->getCSR(CSR_MIP);
|
csr_temp = register_bank->getCSR(CSR_MIP);
|
||||||
|
|
||||||
if ( (csr_temp & MIP_MEIP ) == 0 ) {
|
if ((csr_temp & MIP_MEIP) == 0) {
|
||||||
csr_temp |= MIP_MEIP; // MEIP bit in MIP register (11th bit)
|
csr_temp |= MIP_MEIP; // MEIP bit in MIP register (11th bit)
|
||||||
register_bank->setCSR(CSR_MIP, csr_temp);
|
register_bank->setCSR(CSR_MIP, csr_temp);
|
||||||
log->SC_log(Log::DEBUG) << "Interrupt!" << endl;
|
log->SC_log(Log::DEBUG) << "Interrupt!" << endl;
|
||||||
|
@ -54,7 +56,8 @@ bool CPU::cpu_process_IRQ() {
|
||||||
/* updated MEPC register */
|
/* updated MEPC register */
|
||||||
old_pc = register_bank->getPC();
|
old_pc = register_bank->getPC();
|
||||||
register_bank->setCSR(CSR_MEPC, old_pc);
|
register_bank->setCSR(CSR_MEPC, old_pc);
|
||||||
log->SC_log(Log::INFO) << "Old PC Value 0x" << hex << old_pc << endl;
|
log->SC_log(Log::INFO) << "Old PC Value 0x" << hex << old_pc
|
||||||
|
<< endl;
|
||||||
|
|
||||||
/* update MCAUSE register */
|
/* update MCAUSE register */
|
||||||
register_bank->setCSR(CSR_MCAUSE, 0x80000000);
|
register_bank->setCSR(CSR_MCAUSE, 0x80000000);
|
||||||
|
@ -62,7 +65,8 @@ bool CPU::cpu_process_IRQ() {
|
||||||
/* set new PC address */
|
/* set new PC address */
|
||||||
new_pc = register_bank->getCSR(CSR_MTVEC);
|
new_pc = register_bank->getCSR(CSR_MTVEC);
|
||||||
//new_pc = new_pc & 0xFFFFFFFC; // last two bits always to 0
|
//new_pc = new_pc & 0xFFFFFFFC; // last two bits always to 0
|
||||||
log->SC_log(Log::DEBUG) << "NEW PC Value 0x" << hex << new_pc << endl;
|
log->SC_log(Log::DEBUG) << "NEW PC Value 0x" << hex << new_pc
|
||||||
|
<< endl;
|
||||||
register_bank->setPC(new_pc);
|
register_bank->setPC(new_pc);
|
||||||
|
|
||||||
ret_value = true;
|
ret_value = true;
|
||||||
|
@ -86,7 +90,7 @@ bool CPU::process_c_instruction(Instruction &inst) {
|
||||||
|
|
||||||
C_Instruction c_inst(inst.getInstr());
|
C_Instruction c_inst(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;
|
||||||
|
@ -182,7 +186,7 @@ bool CPU::process_m_instruction(Instruction &inst) {
|
||||||
|
|
||||||
M_Instruction m_inst(inst.getInstr());
|
M_Instruction m_inst(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;
|
||||||
|
@ -217,13 +221,12 @@ bool CPU::process_m_instruction(Instruction &inst) {
|
||||||
return PC_not_affected;
|
return PC_not_affected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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_Instruction a_inst(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;
|
||||||
|
@ -270,7 +273,7 @@ bool CPU::process_a_instruction(Instruction inst) {
|
||||||
bool CPU::process_base_instruction(Instruction &inst) {
|
bool CPU::process_base_instruction(Instruction &inst) {
|
||||||
bool PC_not_affected = true;
|
bool PC_not_affected = true;
|
||||||
|
|
||||||
switch(inst.decode()) {
|
switch (inst.decode()) {
|
||||||
case OP_LUI:
|
case OP_LUI:
|
||||||
exec->LUI(inst);
|
exec->LUI(inst);
|
||||||
break;
|
break;
|
||||||
|
@ -454,35 +457,55 @@ void CPU::CPU_thread(void) {
|
||||||
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;
|
||||||
|
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));
|
||||||
trans->set_data_length( 4 );
|
trans->set_data_length(4);
|
||||||
trans->set_streaming_width( 4 ); // = data_length to indicate no streaming
|
trans->set_streaming_width(4); // = data_length to indicate no streaming
|
||||||
trans->set_byte_enable_ptr( 0 ); // 0 indicates unused
|
trans->set_byte_enable_ptr(0); // 0 indicates unused
|
||||||
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() ) {
|
||||||
|
// if (true) {
|
||||||
|
// dmi_ptr_valid = instr_bus->get_direct_mem_ptr(*trans, dmi_data);
|
||||||
|
// dmi_ptr = dmi_data.get_dmi_ptr();
|
||||||
|
// }
|
||||||
//register_bank->dump();
|
//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;
|
//cout << "CPU: PC 0x" << hex << (uint32_t) register_bank->getPC() << endl;
|
||||||
trans->set_address( register_bank->getPC() );
|
//dmi_ptr_valid = true;
|
||||||
instr_bus->b_transport( *trans, delay);
|
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);
|
||||||
|
|
||||||
|
if (trans->is_response_error()) {
|
||||||
|
SC_REPORT_ERROR("CPU base", "Read memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
dmi_ptr_valid = instr_bus->get_direct_mem_ptr(*trans, dmi_data);
|
||||||
|
if (dmi_ptr_valid) {
|
||||||
|
dmi_ptr = dmi_data.get_dmi_ptr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
perf->codeMemoryRead();
|
perf->codeMemoryRead();
|
||||||
|
|
||||||
if ( trans->is_response_error() ) {
|
log->SC_log(Log::INFO) << "PC: 0x" << hex << register_bank->getPC()
|
||||||
SC_REPORT_ERROR("CPU base", "Read memory");
|
<< ". ";
|
||||||
} else {
|
|
||||||
log->SC_log(Log::INFO) << "PC: 0x" << hex
|
|
||||||
<< register_bank->getPC() << ". ";
|
|
||||||
|
|
||||||
Instruction inst(INSTR);
|
Instruction inst(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;
|
||||||
|
@ -504,7 +527,6 @@ void CPU::CPU_thread(void) {
|
||||||
inst.dump();
|
inst.dump();
|
||||||
exec->NOP(inst);
|
exec->NOP(inst);
|
||||||
} // switch (inst.check_extension())
|
} // switch (inst.check_extension())
|
||||||
}
|
|
||||||
|
|
||||||
perf->instructionsInc();
|
perf->instructionsInc();
|
||||||
|
|
||||||
|
@ -520,9 +542,13 @@ void CPU::CPU_thread(void) {
|
||||||
} // while(1)
|
} // while(1)
|
||||||
} // CPU_thread
|
} // CPU_thread
|
||||||
|
|
||||||
|
|
||||||
void CPU::call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay) {
|
void CPU::call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay) {
|
||||||
interrupt = true;
|
interrupt = true;
|
||||||
/* Socket caller send a cause (its id) */
|
/* Socket caller send a cause (its id) */
|
||||||
memcpy(&int_cause, trans.get_data_ptr(), sizeof(int));
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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_b_transport( this, &Memory::b_transport);
|
||||||
socket.register_get_direct_mem_ptr(this, &Memory::get_direct_mem_ptr);
|
socket.register_get_direct_mem_ptr(this, &Memory::get_direct_mem_ptr);
|
||||||
socket.register_transport_dbg( this, &Memory::transport_dbg);
|
socket.register_transport_dbg( this, &Memory::transport_dbg);
|
||||||
|
memory_offset = 0;
|
||||||
|
program_counter = 0;
|
||||||
//memset(mem, 0, SIZE*sizeof(uint8_t));
|
//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
|
// Set DMI hint to indicated that DMI is supported
|
||||||
// *********************************************
|
// *********************************************
|
||||||
|
|
||||||
|
if (memory_offset == 0) {
|
||||||
trans.set_dmi_allowed(true);
|
trans.set_dmi_allowed(true);
|
||||||
|
} else {
|
||||||
|
trans.set_dmi_allowed(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Obliged to set response status to indicate successful completion
|
// Obliged to set response status to indicate successful completion
|
||||||
trans.set_response_status( tlm::TLM_OK_RESPONSE );
|
trans.set_response_status( tlm::TLM_OK_RESPONSE );
|
||||||
|
@ -142,7 +147,7 @@ void Memory::readHexFile(string filename) {
|
||||||
address = address + extended_address;
|
address = address + extended_address;
|
||||||
//cout << "00 address 0x" << hex << address << endl;
|
//cout << "00 address 0x" << hex << address << endl;
|
||||||
for (i=0; i < byte_count; i++) {
|
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") {
|
} else if (line.substr(7,2) == "02") {
|
||||||
/* Extended segment address */
|
/* Extended segment address */
|
||||||
|
@ -157,14 +162,12 @@ void Memory::readHexFile(string filename) {
|
||||||
cout << "03 PC set to 0x" << hex << program_counter << endl;
|
cout << "03 PC set to 0x" << hex << program_counter << endl;
|
||||||
} else if (line.substr(7,2) == "04") {
|
} else if (line.substr(7,2) == "04") {
|
||||||
/* Start segment address */
|
/* Start segment address */
|
||||||
//extended_address = stol(line.substr(9,4), nullptr, 16) << 16;
|
|
||||||
memory_offset = stol(line.substr(9,4), nullptr, 16) << 16;
|
memory_offset = stol(line.substr(9,4), nullptr, 16) << 16;
|
||||||
extended_address = 0;
|
extended_address = 0;
|
||||||
cout << "04 address set to 0x" << hex << extended_address << endl;
|
cout << "04 address set to 0x" << hex << extended_address << endl;
|
||||||
cout << "04 offset set to 0x" << hex << memory_offset << endl;
|
cout << "04 offset set to 0x" << hex << memory_offset << endl;
|
||||||
} else if (line.substr(7,2) == "05") {
|
} else if (line.substr(7,2) == "05") {
|
||||||
program_counter = stol(line.substr(9,8), nullptr, 16);
|
program_counter = stol(line.substr(9,8), nullptr, 16);
|
||||||
//program_counter = 0;
|
|
||||||
cout << "05 PC set to 0x" << hex << program_counter << endl;
|
cout << "05 PC set to 0x" << hex << program_counter << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,14 +41,11 @@ SC_MODULE(Simulator)
|
||||||
BusCtrl* Bus;
|
BusCtrl* Bus;
|
||||||
Trace *trace;
|
Trace *trace;
|
||||||
Timer *timer;
|
Timer *timer;
|
||||||
// Log *log;
|
|
||||||
|
|
||||||
uint32_t start_PC;
|
uint32_t start_PC;
|
||||||
|
|
||||||
SC_CTOR(Simulator)
|
SC_CTOR(Simulator)
|
||||||
{
|
{
|
||||||
// log = Log::getInstance();
|
|
||||||
|
|
||||||
MainMemory = new Memory("Main_Memory", filename);
|
MainMemory = new Memory("Main_Memory", filename);
|
||||||
start_PC = MainMemory->getPCfromHEX();
|
start_PC = MainMemory->getPCfromHEX();
|
||||||
|
|
||||||
|
@ -127,16 +124,15 @@ void process_arguments(int argc, char* argv[]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename.empty()) {
|
if (filename.empty()) {
|
||||||
filename = std::string(argv[optind]);
|
filename = std::string(argv[optind]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int sc_main(int argc, char* argv[])
|
int sc_main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/* Capture Ctrl+C and finish the simulation */
|
/* Capture Ctrl+C and finish the simulation */
|
||||||
signal(SIGINT, intHandler);
|
signal(SIGINT, intHandler);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue