DMI access added (if available)
This commit is contained in:
parent
24a27f39fe
commit
d42d67b991
|
@ -86,6 +86,9 @@ public:
|
|||
|
||||
private:
|
||||
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
|
||||
|
|
|
@ -70,6 +70,9 @@ private:
|
|||
bool interrupt;
|
||||
uint32_t int_cause;
|
||||
bool irq_already_down;
|
||||
|
||||
bool dmi_ptr_valid;
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Process and triggers IRQ if all conditions met
|
||||
|
@ -100,6 +103,8 @@ private:
|
|||
* When called it triggers an IRQ
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -10,6 +10,8 @@ BusCtrl::BusCtrl(sc_module_name name): sc_module(name)
|
|||
cpu_instr_socket.register_b_transport(this, &BusCtrl::b_transport);
|
||||
cpu_data_socket.register_b_transport(this, &BusCtrl::b_transport);
|
||||
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 );
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
SC_HAS_PROCESS(CPU);
|
||||
CPU::CPU(sc_module_name name, uint32_t PC): sc_module(name)
|
||||
, instr_bus("instr_bus")
|
||||
{
|
||||
CPU::CPU(sc_module_name name, uint32_t PC) :
|
||||
sc_module(name), instr_bus("instr_bus") {
|
||||
register_bank = new Registers();
|
||||
exec = new Execute("Execute", register_bank);
|
||||
perf = Performance::getInstance();
|
||||
|
@ -20,6 +19,9 @@ CPU::CPU(sc_module_name name, uint32_t PC): sc_module(name)
|
|||
int_cause = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -46,7 +48,7 @@ bool CPU::cpu_process_IRQ() {
|
|||
|
||||
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)
|
||||
register_bank->setCSR(CSR_MIP, csr_temp);
|
||||
log->SC_log(Log::DEBUG) << "Interrupt!" << endl;
|
||||
|
@ -54,7 +56,8 @@ bool CPU::cpu_process_IRQ() {
|
|||
/* updated MEPC register */
|
||||
old_pc = register_bank->getPC();
|
||||
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 */
|
||||
register_bank->setCSR(CSR_MCAUSE, 0x80000000);
|
||||
|
@ -62,7 +65,8 @@ bool CPU::cpu_process_IRQ() {
|
|||
/* set new PC address */
|
||||
new_pc = register_bank->getCSR(CSR_MTVEC);
|
||||
//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);
|
||||
|
||||
ret_value = true;
|
||||
|
@ -86,7 +90,7 @@ bool CPU::process_c_instruction(Instruction &inst) {
|
|||
|
||||
C_Instruction c_inst(inst.getInstr());
|
||||
|
||||
switch(c_inst.decode()) {
|
||||
switch (c_inst.decode()) {
|
||||
case OP_C_ADDI4SPN:
|
||||
PC_not_affected = exec->C_ADDI4SPN(inst);
|
||||
break;
|
||||
|
@ -182,7 +186,7 @@ bool CPU::process_m_instruction(Instruction &inst) {
|
|||
|
||||
M_Instruction m_inst(inst.getInstr());
|
||||
|
||||
switch(m_inst.decode()) {
|
||||
switch (m_inst.decode()) {
|
||||
case OP_M_MUL:
|
||||
exec->M_MUL(inst);
|
||||
break;
|
||||
|
@ -217,13 +221,12 @@ bool CPU::process_m_instruction(Instruction &inst) {
|
|||
return PC_not_affected;
|
||||
}
|
||||
|
||||
|
||||
bool CPU::process_a_instruction(Instruction inst) {
|
||||
bool PC_not_affected = true;
|
||||
|
||||
A_Instruction a_inst(inst.getInstr());
|
||||
|
||||
switch(a_inst.decode()) {
|
||||
switch (a_inst.decode()) {
|
||||
case OP_A_LR:
|
||||
exec->A_LR(inst);
|
||||
break;
|
||||
|
@ -270,7 +273,7 @@ bool CPU::process_a_instruction(Instruction inst) {
|
|||
bool CPU::process_base_instruction(Instruction &inst) {
|
||||
bool PC_not_affected = true;
|
||||
|
||||
switch(inst.decode()) {
|
||||
switch (inst.decode()) {
|
||||
case OP_LUI:
|
||||
exec->LUI(inst);
|
||||
break;
|
||||
|
@ -454,35 +457,55 @@ void CPU::CPU_thread(void) {
|
|||
sc_time delay = SC_ZERO_TIME;
|
||||
bool PC_not_affected = false;
|
||||
bool incPCby2 = false;
|
||||
tlm::tlm_dmi dmi_data;
|
||||
unsigned char* dmi_ptr = NULL;
|
||||
|
||||
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 );
|
||||
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 (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();
|
||||
|
||||
while(1) {
|
||||
while (1) {
|
||||
/* Get new PC value */
|
||||
//cout << "CPU: PC 0x" << hex << (uint32_t) register_bank->getPC() << endl;
|
||||
trans->set_address( register_bank->getPC() );
|
||||
instr_bus->b_transport( *trans, delay);
|
||||
//dmi_ptr_valid = true;
|
||||
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();
|
||||
|
||||
if ( trans->is_response_error() ) {
|
||||
SC_REPORT_ERROR("CPU base", "Read memory");
|
||||
} else {
|
||||
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);
|
||||
|
||||
/* check what type of instruction is and execute it */
|
||||
switch(inst.check_extension()) {
|
||||
switch (inst.check_extension()) {
|
||||
case BASE_EXTENSION:
|
||||
PC_not_affected = process_base_instruction(inst);
|
||||
incPCby2 = false;
|
||||
|
@ -504,7 +527,6 @@ void CPU::CPU_thread(void) {
|
|||
inst.dump();
|
||||
exec->NOP(inst);
|
||||
} // switch (inst.check_extension())
|
||||
}
|
||||
|
||||
perf->instructionsInc();
|
||||
|
||||
|
@ -520,9 +542,13 @@ void CPU::CPU_thread(void) {
|
|||
} // while(1)
|
||||
} // CPU_thread
|
||||
|
||||
|
||||
void CPU::call_interrupt(tlm::tlm_generic_payload &trans, sc_time &delay) {
|
||||
interrupt = true;
|
||||
/* Socket caller send a cause (its id) */
|
||||
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_get_direct_mem_ptr(this, &Memory::get_direct_mem_ptr);
|
||||
socket.register_transport_dbg( this, &Memory::transport_dbg);
|
||||
|
||||
memory_offset = 0;
|
||||
program_counter = 0;
|
||||
//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
|
||||
// *********************************************
|
||||
|
||||
if (memory_offset == 0) {
|
||||
trans.set_dmi_allowed(true);
|
||||
} else {
|
||||
trans.set_dmi_allowed(false);
|
||||
}
|
||||
|
||||
// Obliged to set response status to indicate successful completion
|
||||
trans.set_response_status( tlm::TLM_OK_RESPONSE );
|
||||
|
@ -142,7 +147,7 @@ void Memory::readHexFile(string filename) {
|
|||
address = address + extended_address;
|
||||
//cout << "00 address 0x" << hex << address << endl;
|
||||
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") {
|
||||
/* Extended segment address */
|
||||
|
@ -157,14 +162,12 @@ void Memory::readHexFile(string filename) {
|
|||
cout << "03 PC set to 0x" << hex << program_counter << endl;
|
||||
} else if (line.substr(7,2) == "04") {
|
||||
/* Start segment address */
|
||||
//extended_address = stol(line.substr(9,4), nullptr, 16) << 16;
|
||||
memory_offset = stol(line.substr(9,4), nullptr, 16) << 16;
|
||||
extended_address = 0;
|
||||
cout << "04 address set to 0x" << hex << extended_address << endl;
|
||||
cout << "04 offset set to 0x" << hex << memory_offset << endl;
|
||||
} else if (line.substr(7,2) == "05") {
|
||||
program_counter = stol(line.substr(9,8), nullptr, 16);
|
||||
//program_counter = 0;
|
||||
cout << "05 PC set to 0x" << hex << program_counter << endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,14 +41,11 @@ SC_MODULE(Simulator)
|
|||
BusCtrl* Bus;
|
||||
Trace *trace;
|
||||
Timer *timer;
|
||||
// Log *log;
|
||||
|
||||
uint32_t start_PC;
|
||||
|
||||
SC_CTOR(Simulator)
|
||||
{
|
||||
// log = Log::getInstance();
|
||||
|
||||
MainMemory = new Memory("Main_Memory", filename);
|
||||
start_PC = MainMemory->getPCfromHEX();
|
||||
|
||||
|
@ -127,16 +124,15 @@ void process_arguments(int argc, char* argv[]) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (filename.empty()) {
|
||||
filename = std::string(argv[optind]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int sc_main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
|
||||
/* Capture Ctrl+C and finish the simulation */
|
||||
signal(SIGINT, intHandler);
|
||||
|
||||
|
|
Loading…
Reference in New Issue