DMI access added (if available)

This commit is contained in:
mariusmonton 2019-03-28 22:52:36 +01:00
parent 24a27f39fe
commit d42d67b991
6 changed files with 516 additions and 472 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
} }
} }

View File

@ -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);