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; | ||||||
|  |  | ||||||
|  | @ -4,8 +4,6 @@ | ||||||
| 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); | ||||||
|  | @ -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