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

View File

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

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

View File

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

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

View File

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