Added Data Memory bus. Implemented LW & SW instructions.
This commit is contained in:
parent
c5ec56ec08
commit
1c9bfe8c60
|
@ -0,0 +1,6 @@
|
||||||
|
li t1, 150
|
||||||
|
li t2, 300
|
||||||
|
li t3, -250
|
||||||
|
sw t1, -4(t2)
|
||||||
|
li t1, 500
|
||||||
|
lw t1, -4(t2)
|
|
@ -40,9 +40,10 @@ public:
|
||||||
CPU(sc_module_name name);
|
CPU(sc_module_name name);
|
||||||
~CPU();
|
~CPU();
|
||||||
|
|
||||||
|
RISC_V_execute *exec;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Registers *register_bank;
|
Registers *register_bank;
|
||||||
RISC_V_execute *exec;
|
|
||||||
Performance *perf;
|
Performance *perf;
|
||||||
Log *log;
|
Log *log;
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
const sc_time LATENCY;
|
const sc_time LATENCY;
|
||||||
|
|
||||||
Memory(sc_module_name name, string filename);
|
Memory(sc_module_name name, string filename);
|
||||||
|
Memory(sc_module_name name, bool use_file);
|
||||||
// TLM-2 blocking transport method
|
// TLM-2 blocking transport method
|
||||||
virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay );
|
virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay );
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ public:
|
||||||
RISC_V_execute(sc_module_name name,
|
RISC_V_execute(sc_module_name name,
|
||||||
Registers *register_bank);
|
Registers *register_bank);
|
||||||
|
|
||||||
|
/* Quick & dirty way to publish a socket though modules */
|
||||||
|
tlm_utils::simple_initiator_socket<RISC_V_execute> data_bus;
|
||||||
|
|
||||||
void LUI(Instruction &inst);
|
void LUI(Instruction &inst);
|
||||||
void AUIPC(Instruction &inst);
|
void AUIPC(Instruction &inst);
|
||||||
|
@ -93,9 +95,10 @@ public:
|
||||||
void CSRRCI(Instruction &inst);
|
void CSRRCI(Instruction &inst);
|
||||||
|
|
||||||
void NOP(Instruction &inst);
|
void NOP(Instruction &inst);
|
||||||
private:
|
|
||||||
|
|
||||||
uint32_t readDataMem(uint32_t addr);
|
private:
|
||||||
|
uint32_t readDataMem(uint32_t addr, int size);
|
||||||
|
void writeDataMem(uint32_t addr, uint32_t data, int size);
|
||||||
Registers *regs;
|
Registers *regs;
|
||||||
Performance *perf;
|
Performance *perf;
|
||||||
Log *log;
|
Log *log;
|
||||||
|
|
10
src/CPU.cpp
10
src/CPU.cpp
|
@ -4,9 +4,7 @@
|
||||||
SC_HAS_PROCESS(CPU);
|
SC_HAS_PROCESS(CPU);
|
||||||
CPU::CPU(sc_module_name name): sc_module(name)
|
CPU::CPU(sc_module_name name): sc_module(name)
|
||||||
, instr_bus("instr_bus")
|
, instr_bus("instr_bus")
|
||||||
//, exec("RISC_V_exec", ®ister_bank)
|
{
|
||||||
//, data_bus("data_bus")
|
|
||||||
{
|
|
||||||
register_bank = new Registers();
|
register_bank = new Registers();
|
||||||
exec = new RISC_V_execute("RISC_V_execute", register_bank);
|
exec = new RISC_V_execute("RISC_V_execute", register_bank);
|
||||||
perf = Performance::getInstance();
|
perf = Performance::getInstance();
|
||||||
|
@ -71,6 +69,12 @@ void CPU::CPU_thread(void) {
|
||||||
case OP_BNE:
|
case OP_BNE:
|
||||||
exec->BNE(inst);
|
exec->BNE(inst);
|
||||||
break;
|
break;
|
||||||
|
case OP_LW:
|
||||||
|
exec->LW(inst);
|
||||||
|
break;
|
||||||
|
case OP_SW:
|
||||||
|
exec->SW(inst);
|
||||||
|
break;
|
||||||
case OP_ADDI:
|
case OP_ADDI:
|
||||||
exec->ADDI(inst);
|
exec->ADDI(inst);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -12,7 +12,7 @@ Log* Log::getInstance()
|
||||||
|
|
||||||
Log::Log(const char* filename) {
|
Log::Log(const char* filename) {
|
||||||
m_stream.open(filename);
|
m_stream.open(filename);
|
||||||
currentLogLevel = Log::INFO;
|
currentLogLevel = Log::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::SC_log(std::string msg, enum LogLevel level) {
|
void Log::SC_log(std::string msg, enum LogLevel level) {
|
||||||
|
|
|
@ -16,6 +16,17 @@ Memory::Memory(sc_module_name name, string filename): sc_module(name)
|
||||||
SC_THREAD(invalidation_process);
|
SC_THREAD(invalidation_process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Memory::Memory(sc_module_name name, bool use_file): sc_module(name)
|
||||||
|
,socket("socket")
|
||||||
|
,LATENCY(SC_ZERO_TIME) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
memset(mem, 0, SIZE*sizeof(int));
|
||||||
|
|
||||||
|
SC_THREAD(invalidation_process);
|
||||||
|
}
|
||||||
|
|
||||||
void Memory::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay )
|
void Memory::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay )
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@ SC_HAS_PROCESS(RISC_V_execute);
|
||||||
RISC_V_execute::RISC_V_execute(sc_module_name name
|
RISC_V_execute::RISC_V_execute(sc_module_name name
|
||||||
, Registers *register_bank)
|
, Registers *register_bank)
|
||||||
: sc_module(name)
|
: sc_module(name)
|
||||||
|
, data_bus("data_bus")
|
||||||
, regs(register_bank) {
|
, regs(register_bank) {
|
||||||
perf = Performance::getInstance();
|
perf = Performance::getInstance();
|
||||||
log = Log::getInstance();
|
log = Log::getInstance();
|
||||||
|
@ -69,7 +70,7 @@ void RISC_V_execute::JALR(Instruction &inst) {
|
||||||
|
|
||||||
void RISC_V_execute::BEQ(Instruction &inst) {
|
void RISC_V_execute::BEQ(Instruction &inst) {
|
||||||
int rs1, rs2;
|
int rs1, rs2;
|
||||||
int new_pc;
|
int new_pc = 0;
|
||||||
|
|
||||||
rs1 = inst.rs1();
|
rs1 = inst.rs1();
|
||||||
rs2 = inst.rs2();
|
rs2 = inst.rs2();
|
||||||
|
@ -85,7 +86,7 @@ void RISC_V_execute::BEQ(Instruction &inst) {
|
||||||
|
|
||||||
void RISC_V_execute::BNE(Instruction &inst) {
|
void RISC_V_execute::BNE(Instruction &inst) {
|
||||||
int rs1, rs2;
|
int rs1, rs2;
|
||||||
int new_pc;
|
int new_pc = 0;
|
||||||
|
|
||||||
rs1 = inst.rs1();
|
rs1 = inst.rs1();
|
||||||
rs2 = inst.rs2();
|
rs2 = inst.rs2();
|
||||||
|
@ -100,7 +101,7 @@ void RISC_V_execute::BNE(Instruction &inst) {
|
||||||
|
|
||||||
void RISC_V_execute::BLT(Instruction &inst) {
|
void RISC_V_execute::BLT(Instruction &inst) {
|
||||||
int rs1, rs2;
|
int rs1, rs2;
|
||||||
int new_pc;
|
int new_pc = 0;
|
||||||
|
|
||||||
rs1 = inst.rs1();
|
rs1 = inst.rs1();
|
||||||
rs2 = inst.rs2();
|
rs2 = inst.rs2();
|
||||||
|
@ -115,7 +116,7 @@ void RISC_V_execute::BLT(Instruction &inst) {
|
||||||
|
|
||||||
void RISC_V_execute::BGE(Instruction &inst) {
|
void RISC_V_execute::BGE(Instruction &inst) {
|
||||||
int rs1, rs2;
|
int rs1, rs2;
|
||||||
int new_pc;
|
int new_pc = 0;
|
||||||
|
|
||||||
rs1 = inst.rs1();
|
rs1 = inst.rs1();
|
||||||
rs2 = inst.rs2();
|
rs2 = inst.rs2();
|
||||||
|
@ -130,7 +131,7 @@ void RISC_V_execute::BGE(Instruction &inst) {
|
||||||
|
|
||||||
void RISC_V_execute::BLTU(Instruction &inst) {
|
void RISC_V_execute::BLTU(Instruction &inst) {
|
||||||
int rs1, rs2;
|
int rs1, rs2;
|
||||||
int new_pc;
|
int new_pc = 0;
|
||||||
|
|
||||||
rs1 = inst.rs1();
|
rs1 = inst.rs1();
|
||||||
rs2 = inst.rs2();
|
rs2 = inst.rs2();
|
||||||
|
@ -145,7 +146,7 @@ void RISC_V_execute::BLTU(Instruction &inst) {
|
||||||
|
|
||||||
void RISC_V_execute::BGEU(Instruction &inst) {
|
void RISC_V_execute::BGEU(Instruction &inst) {
|
||||||
int rs1, rs2;
|
int rs1, rs2;
|
||||||
int new_pc;
|
int new_pc = 0;
|
||||||
|
|
||||||
rs1 = inst.rs1();
|
rs1 = inst.rs1();
|
||||||
rs2 = inst.rs2();
|
rs2 = inst.rs2();
|
||||||
|
@ -158,19 +159,43 @@ void RISC_V_execute::BGEU(Instruction &inst) {
|
||||||
log->SC_log(Log::INFO) << "BGEU R" << rs1 << " > R" << rs2 << "? -> PC (" << new_pc << ")" << endl;
|
log->SC_log(Log::INFO) << "BGEU R" << rs1 << " > R" << rs2 << "? -> PC (" << new_pc << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RISC_V_execute::LB(Instruction &inst) {
|
void RISC_V_execute::LW(Instruction &inst) {
|
||||||
uint32_t mem_addr = 0;
|
uint32_t mem_addr = 0;
|
||||||
int rd, rs1;
|
int rd, rs1;
|
||||||
uint32_t imm = 0;
|
int32_t imm = 0;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
|
|
||||||
rd = inst.rd();
|
rd = inst.rd();
|
||||||
rs1 = inst.rs1();
|
rs1 = inst.rs1();
|
||||||
imm = inst.imm_U() << 12;
|
imm = inst.imm_I();
|
||||||
|
|
||||||
mem_addr = imm + rs1;
|
mem_addr = imm + regs->getValue(rs1);
|
||||||
data = readDataMem(mem_addr);
|
data = readDataMem(mem_addr, 4);
|
||||||
regs->setValue(rd, data);
|
regs->setValue(rd, data);
|
||||||
|
|
||||||
|
cout << "LW Data: " << data << endl;
|
||||||
|
log->SC_log(Log::INFO) << "LW: R" << rs1 << " + " << imm << " (@0x"
|
||||||
|
<< hex <<mem_addr << dec << ") -> R" << rd << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RISC_V_execute::SW(Instruction &inst) {
|
||||||
|
uint32_t mem_addr = 0;
|
||||||
|
int rs1, rs2;
|
||||||
|
int32_t imm = 0;
|
||||||
|
uint32_t data;
|
||||||
|
|
||||||
|
rs1 = inst.rs1();
|
||||||
|
rs2 = inst.rs2();
|
||||||
|
imm = inst.imm_S();
|
||||||
|
|
||||||
|
mem_addr = imm + regs->getValue(rs1);
|
||||||
|
data = regs->getValue(rs2);
|
||||||
|
|
||||||
|
writeDataMem(mem_addr, data, 4);
|
||||||
|
|
||||||
|
log->SC_log(Log::INFO) << "SW: R" << rs2 << " -> R" << rs1 << " + "
|
||||||
|
<< imm << " (@0x" << hex <<mem_addr << dec << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RISC_V_execute::ADDI(Instruction &inst) {
|
void RISC_V_execute::ADDI(Instruction &inst) {
|
||||||
|
@ -581,12 +606,41 @@ void RISC_V_execute::NOP(Instruction &inst) {
|
||||||
* @param addr address to access to
|
* @param addr address to access to
|
||||||
* @return data value read
|
* @return data value read
|
||||||
*/
|
*/
|
||||||
uint32_t RISC_V_execute::readDataMem(uint32_t addr) {
|
uint32_t RISC_V_execute::readDataMem(uint32_t addr, int size) {
|
||||||
// tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload;
|
uint32_t data;
|
||||||
// sc_time delay = SC_ZERO_TIME;
|
tlm::tlm_generic_payload trans;
|
||||||
|
sc_time delay = SC_ZERO_TIME;
|
||||||
|
|
||||||
// data_bus->b_transport(*trans, delay);
|
trans.set_command( tlm::TLM_READ_COMMAND );
|
||||||
|
trans.set_data_ptr( reinterpret_cast<unsigned char*>(&data) );
|
||||||
|
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_address( addr );
|
||||||
|
|
||||||
return 0;
|
data_bus->b_transport( trans, delay);
|
||||||
|
|
||||||
|
cout << "RD addr: " << addr << " data: " << data << endl;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RISC_V_execute::writeDataMem(uint32_t addr, uint32_t data, int size) {
|
||||||
|
tlm::tlm_generic_payload trans;
|
||||||
|
sc_time delay = SC_ZERO_TIME;
|
||||||
|
|
||||||
|
trans.set_command( tlm::TLM_WRITE_COMMAND );
|
||||||
|
trans.set_data_ptr( reinterpret_cast<unsigned char*>(&data) );
|
||||||
|
trans.set_data_length( size );
|
||||||
|
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_address( addr );
|
||||||
|
|
||||||
|
data_bus->b_transport( trans, delay);
|
||||||
|
|
||||||
|
cout << "WR addr: " << addr << " data: " << data << endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,23 +20,27 @@ SC_MODULE(Top)
|
||||||
{
|
{
|
||||||
//Initiator *initiator;
|
//Initiator *initiator;
|
||||||
CPU *cpu;
|
CPU *cpu;
|
||||||
Memory *memory;
|
Memory *InstrMemory;
|
||||||
|
Memory *DataMemory;
|
||||||
|
|
||||||
sc_signal<bool> IRQ;
|
sc_signal<bool> IRQ;
|
||||||
|
|
||||||
SC_CTOR(Top)
|
SC_CTOR(Top)
|
||||||
{
|
{
|
||||||
cpu = new CPU("cpu");
|
cpu = new CPU("cpu");
|
||||||
memory = new Memory("memory", filename);
|
InstrMemory = new Memory("InstrMemory", filename);
|
||||||
|
DataMemory = new Memory("Datamemory", false);
|
||||||
|
|
||||||
cpu->instr_bus.bind(memory->socket);
|
cpu->instr_bus.bind(InstrMemory->socket);
|
||||||
|
cpu->exec->data_bus.bind(DataMemory->socket);
|
||||||
//cpu->interrupt.bind(IRQ);
|
//cpu->interrupt.bind(IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Top() {
|
~Top() {
|
||||||
cout << "Top destructor" << endl;
|
cout << "Top destructor" << endl;
|
||||||
delete cpu;
|
delete cpu;
|
||||||
delete memory;
|
delete InstrMemory;
|
||||||
|
delete DataMemory;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue