removed CPU64 files (unused)
This commit is contained in:
parent
db682f6055
commit
9b7b5635d2
114
inc/CPU64.h
114
inc/CPU64.h
|
@ -1,114 +0,0 @@
|
||||||
/*!
|
|
||||||
\file CPU.h
|
|
||||||
\brief Main CPU class
|
|
||||||
\author Màrius Montón
|
|
||||||
\date July 2020
|
|
||||||
*/
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#ifndef CPU_BASE_H
|
|
||||||
#define CPU_BASE_H
|
|
||||||
|
|
||||||
#define SC_INCLUDE_DYNAMIC_PROCESSES
|
|
||||||
|
|
||||||
#include "systemc"
|
|
||||||
|
|
||||||
#include "tlm.h"
|
|
||||||
#include "tlm_utils/simple_initiator_socket.h"
|
|
||||||
#include "tlm_utils/tlm_quantumkeeper.h"
|
|
||||||
|
|
||||||
#include "memory.h"
|
|
||||||
#include "MemoryInterface.h"
|
|
||||||
#include "BASE_ISA.h"
|
|
||||||
#include "Registers.h"
|
|
||||||
#include "Log.h"
|
|
||||||
#include "Instruction.h"
|
|
||||||
#include "C_extension.h"
|
|
||||||
#include "M_extension.h"
|
|
||||||
#include "A_extension.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief ISC_V CPU 64 bitsmodel
|
|
||||||
* @param name name of the module
|
|
||||||
*/
|
|
||||||
class CPU64: sc_core::sc_module {
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Instruction Memory bus socket
|
|
||||||
* @param trans transction to perfoem
|
|
||||||
* @param delay time to annotate
|
|
||||||
*/
|
|
||||||
tlm_utils::simple_initiator_socket<CPU64> instr_bus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief IRQ line socket
|
|
||||||
* @param trans transction to perform (empty)
|
|
||||||
* @param delay time to annotate
|
|
||||||
*/
|
|
||||||
tlm_utils::simple_target_socket<CPU64> irq_line_socket;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructor
|
|
||||||
* @param name Module name
|
|
||||||
* @param PC Program Counter initialize value
|
|
||||||
*/
|
|
||||||
CPU64(sc_core::sc_module_name name, uint32_t PC);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destructor
|
|
||||||
*/
|
|
||||||
~CPU64();
|
|
||||||
|
|
||||||
MemoryInterface *mem_intf;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Registers *register_bank;
|
|
||||||
Performance *perf;
|
|
||||||
Log *log;
|
|
||||||
Instruction *inst;
|
|
||||||
C_extension *c_inst;
|
|
||||||
M_extension *m_inst;
|
|
||||||
A_extension *a_inst;
|
|
||||||
BASE_ISA *exec;
|
|
||||||
|
|
||||||
tlm_utils::tlm_quantumkeeper *m_qk;
|
|
||||||
|
|
||||||
bool interrupt;
|
|
||||||
uint32_t int_cause;
|
|
||||||
bool irq_already_down;
|
|
||||||
sc_core::sc_time default_time;
|
|
||||||
bool dmi_ptr_valid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @brief Process and triggers IRQ if all conditions met
|
|
||||||
* @return true if IRQ is triggered, false otherwise
|
|
||||||
*/
|
|
||||||
bool cpu_process_IRQ();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* main thread for CPU simulation
|
|
||||||
* @brief CPU mai thread
|
|
||||||
*/
|
|
||||||
void CPU_thread(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief callback for IRQ simple socket
|
|
||||||
* @param trans transaction to perform (empty)
|
|
||||||
* @param delay time to annotate
|
|
||||||
*
|
|
||||||
* it triggers an IRQ when called
|
|
||||||
*/
|
|
||||||
void call_interrupt(tlm::tlm_generic_payload &trans,
|
|
||||||
sc_core::sc_time &delay);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DMI pointer is not longer valid
|
|
||||||
* @param start memory address region start
|
|
||||||
* @param end memory address region end
|
|
||||||
*/
|
|
||||||
void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
223
src/CPU64.cpp
223
src/CPU64.cpp
|
@ -1,223 +0,0 @@
|
||||||
/*!
|
|
||||||
\file CPU.cpp
|
|
||||||
\brief Main CPU class
|
|
||||||
\author Màrius Montón
|
|
||||||
\date August 2018
|
|
||||||
*/
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
#include "CPU64.h"
|
|
||||||
|
|
||||||
SC_HAS_PROCESS(CPU64);
|
|
||||||
CPU64::CPU64(sc_core::sc_module_name name, uint32_t PC) :
|
|
||||||
sc_module(name), instr_bus("instr_bus"), default_time(10,
|
|
||||||
sc_core::SC_NS) {
|
|
||||||
register_bank = new Registers();
|
|
||||||
mem_intf = new MemoryInterface();
|
|
||||||
|
|
||||||
perf = Performance::getInstance();
|
|
||||||
log = Log::getInstance();
|
|
||||||
|
|
||||||
register_bank->setPC(PC);
|
|
||||||
|
|
||||||
//register_bank->setValue(Registers::sp, (0xD0000 / 4) - 1);
|
|
||||||
register_bank->setValue(Registers::sp, (0x10000000 / 4) - 1);
|
|
||||||
|
|
||||||
irq_line_socket.register_b_transport(this, &CPU64::call_interrupt);
|
|
||||||
interrupt = false;
|
|
||||||
|
|
||||||
int_cause = 0;
|
|
||||||
irq_already_down = false;
|
|
||||||
|
|
||||||
dmi_ptr_valid = false;
|
|
||||||
instr_bus.register_invalidate_direct_mem_ptr(this,
|
|
||||||
&CPU64::invalidate_direct_mem_ptr);
|
|
||||||
|
|
||||||
inst = new Instruction(0);
|
|
||||||
exec = new BASE_ISA(0, register_bank, mem_intf);
|
|
||||||
c_inst = new C_extension(0, register_bank, mem_intf);
|
|
||||||
m_inst = new M_extension(0, register_bank, mem_intf);
|
|
||||||
a_inst = new A_extension(0, register_bank, mem_intf);
|
|
||||||
|
|
||||||
m_qk = new tlm_utils::tlm_quantumkeeper();
|
|
||||||
|
|
||||||
SC_THREAD(CPU_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
CPU64::~CPU64() {
|
|
||||||
std::cout << "*********************************************" << std::endl;
|
|
||||||
register_bank->dump();
|
|
||||||
std::cout << "end time: " << sc_core::sc_time_stamp() << std::endl;
|
|
||||||
perf->dump();
|
|
||||||
std::cout << "*********************************************" << std::endl;
|
|
||||||
delete register_bank;
|
|
||||||
delete mem_intf;
|
|
||||||
delete inst;
|
|
||||||
delete exec;
|
|
||||||
delete c_inst;
|
|
||||||
delete m_inst;
|
|
||||||
delete a_inst;
|
|
||||||
delete m_qk;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CPU64::cpu_process_IRQ() {
|
|
||||||
uint32_t csr_temp;
|
|
||||||
bool ret_value = false;
|
|
||||||
|
|
||||||
if (interrupt == true) {
|
|
||||||
csr_temp = register_bank->getCSR(CSR_MSTATUS);
|
|
||||||
if ((csr_temp & MSTATUS_MIE) == 0) {
|
|
||||||
log->SC_log(Log::DEBUG) << "interrupt delayed" << std::endl;
|
|
||||||
return ret_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
csr_temp = register_bank->getCSR(CSR_MIP);
|
|
||||||
|
|
||||||
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!" << std::endl;
|
|
||||||
|
|
||||||
/* updated MEPC register */
|
|
||||||
uint32_t old_pc = register_bank->getPC();
|
|
||||||
register_bank->setCSR(CSR_MEPC, old_pc);
|
|
||||||
log->SC_log(Log::INFO) << "Old PC Value 0x" << std::hex << old_pc
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
/* update MCAUSE register */
|
|
||||||
register_bank->setCSR(CSR_MCAUSE, 0x80000000);
|
|
||||||
|
|
||||||
/* set new PC address */
|
|
||||||
uint32_t 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" << std::hex << new_pc
|
|
||||||
<< std::endl;
|
|
||||||
register_bank->setPC(new_pc);
|
|
||||||
|
|
||||||
ret_value = true;
|
|
||||||
interrupt = false;
|
|
||||||
irq_already_down = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (irq_already_down == false) {
|
|
||||||
csr_temp = register_bank->getCSR(CSR_MIP);
|
|
||||||
csr_temp &= ~MIP_MEIP;
|
|
||||||
register_bank->setCSR(CSR_MIP, csr_temp);
|
|
||||||
irq_already_down = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPU64::CPU_thread(void) {
|
|
||||||
|
|
||||||
tlm::tlm_generic_payload *trans = new tlm::tlm_generic_payload;
|
|
||||||
uint32_t INSTR;
|
|
||||||
sc_core::sc_time delay = sc_core::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);
|
|
||||||
|
|
||||||
m_qk->reset();
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
/* Get new PC value */
|
|
||||||
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 {
|
|
||||||
trans->set_address(register_bank->getPC());
|
|
||||||
instr_bus->b_transport(*trans, delay);
|
|
||||||
|
|
||||||
if (trans->is_response_error()) {
|
|
||||||
SC_REPORT_ERROR("CPU base", "Read memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trans->is_dmi_allowed()) {
|
|
||||||
dmi_ptr_valid = instr_bus->get_direct_mem_ptr(*trans, dmi_data);
|
|
||||||
if (dmi_ptr_valid) {
|
|
||||||
std::cout << "Get DMI_PTR " << std::endl;
|
|
||||||
dmi_ptr = dmi_data.get_dmi_ptr();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
perf->codeMemoryRead();
|
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << "PC: 0x" << std::hex << register_bank->getPC()
|
|
||||||
<< ". ";
|
|
||||||
|
|
||||||
inst->setInstr(INSTR);
|
|
||||||
|
|
||||||
/* check what type of instruction is and execute it */
|
|
||||||
switch (inst->check_extension()) {
|
|
||||||
[[likely]] case BASE_EXTENSION:
|
|
||||||
PC_not_affected = exec->process_instruction(inst);
|
|
||||||
incPCby2 = false;
|
|
||||||
break;
|
|
||||||
case C_EXTENSION:
|
|
||||||
PC_not_affected = c_inst->process_instruction(inst);
|
|
||||||
incPCby2 = true;
|
|
||||||
break;
|
|
||||||
case M_EXTENSION:
|
|
||||||
PC_not_affected = m_inst->process_instruction(inst);
|
|
||||||
incPCby2 = false;
|
|
||||||
break;
|
|
||||||
case A_EXTENSION:
|
|
||||||
PC_not_affected = a_inst->process_instruction(inst);
|
|
||||||
incPCby2 = false;
|
|
||||||
break;
|
|
||||||
[[unlikely]] default:
|
|
||||||
std::cout << "Extension not implemented yet" << std::endl;
|
|
||||||
inst->dump();
|
|
||||||
exec->NOP();
|
|
||||||
}
|
|
||||||
|
|
||||||
perf->instructionsInc();
|
|
||||||
|
|
||||||
if (PC_not_affected == true) {
|
|
||||||
register_bank->incPC(incPCby2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process IRQ (if any) */
|
|
||||||
cpu_process_IRQ();
|
|
||||||
|
|
||||||
/* Fixed instruction time to 10 ns (i.e. 100 MHz) */
|
|
||||||
//#define USE_QK
|
|
||||||
#ifdef USE_QK
|
|
||||||
// Model time used for additional processing
|
|
||||||
m_qk->inc(default_time);
|
|
||||||
if (m_qk->need_sync()) {
|
|
||||||
m_qk->sync();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
sc_core::wait(10, sc_core::SC_NS);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // while(1)
|
|
||||||
} // CPU_thread
|
|
||||||
|
|
||||||
void CPU64::call_interrupt(tlm::tlm_generic_payload &trans,
|
|
||||||
sc_core::sc_time &delay) {
|
|
||||||
interrupt = true;
|
|
||||||
/* Socket caller send a cause (its id) */
|
|
||||||
memcpy(&int_cause, trans.get_data_ptr(), sizeof(uint32_t));
|
|
||||||
delay = sc_core::SC_ZERO_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPU64::invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) {
|
|
||||||
(void) start;
|
|
||||||
(void) end;
|
|
||||||
dmi_ptr_valid = false;
|
|
||||||
}
|
|
Loading…
Reference in New Issue