Lot of changes:
* memory module parses 03 field and sets Program Counter (PC) to right value * almost all RV32I instructions implemented * added Trace module to mimic ARM ITM module * added BusCtrl module as bus controler (very simple) to allow CPU & RISC_V_execute to access memory & peripherals * lot of minor changes
This commit is contained in:
parent
79cff335e3
commit
8dcbf09589
|
@ -30,6 +30,8 @@
|
||||||
*.exe
|
*.exe
|
||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
|
*.elf
|
||||||
|
*.hex
|
||||||
|
|
||||||
Log.txt
|
Log.txt
|
||||||
helper.ods
|
helper.ods
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*!
|
||||||
|
\file Trace.h
|
||||||
|
\brief Basic TLM-2 Trace module
|
||||||
|
\author Màrius Montón
|
||||||
|
\date September 2018
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BUSCTRL_H__
|
||||||
|
#define __BUSCTRL_H__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#define SC_INCLUDE_DYNAMIC_PROCESSES
|
||||||
|
|
||||||
|
#include "systemc"
|
||||||
|
|
||||||
|
#include "tlm.h"
|
||||||
|
#include "tlm_utils/simple_initiator_socket.h"
|
||||||
|
#include "tlm_utils/simple_target_socket.h"
|
||||||
|
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
using namespace sc_core;
|
||||||
|
using namespace sc_dt;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
#define TRACE_MEMORY_ADDRESS 0x40000000
|
||||||
|
|
||||||
|
class BusCtrl: sc_module {
|
||||||
|
public:
|
||||||
|
// TLM-2 socket, defaults to 32-bits wide, base protocol
|
||||||
|
tlm_utils::simple_target_socket<BusCtrl> cpu_instr_socket;
|
||||||
|
tlm_utils::simple_target_socket<BusCtrl> cpu_data_socket;
|
||||||
|
tlm_utils::simple_initiator_socket<BusCtrl> data_memory_socket;
|
||||||
|
tlm_utils::simple_initiator_socket<BusCtrl> trace_socket;
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
BusCtrl(sc_module_name name);
|
||||||
|
|
||||||
|
// TLM-2 blocking transport method
|
||||||
|
virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay );
|
||||||
|
|
||||||
|
private:
|
||||||
|
Log *log;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -37,7 +37,7 @@ public:
|
||||||
|
|
||||||
//sc_in<sc_signal<bool> > interrupt;
|
//sc_in<sc_signal<bool> > interrupt;
|
||||||
|
|
||||||
CPU(sc_module_name name);
|
CPU(sc_module_name name, uint32_t PC);
|
||||||
~CPU();
|
~CPU();
|
||||||
|
|
||||||
RISC_V_execute *exec;
|
RISC_V_execute *exec;
|
||||||
|
|
|
@ -29,10 +29,10 @@ class Log {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum LogLevel{
|
enum LogLevel{
|
||||||
INFO=0,
|
ERROR = 0,
|
||||||
DEBUG,
|
DEBUG,
|
||||||
WARNING,
|
WARNING,
|
||||||
ERROR
|
INFO
|
||||||
} currentLogLevel;
|
} currentLogLevel;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,14 @@ public:
|
||||||
// TLM-2 socket, defaults to 32-bits wide, base protocol
|
// TLM-2 socket, defaults to 32-bits wide, base protocol
|
||||||
tlm_utils::simple_target_socket<Memory> socket;
|
tlm_utils::simple_target_socket<Memory> socket;
|
||||||
|
|
||||||
enum { SIZE = 1024 };
|
enum { SIZE = 1024 * 1024 };
|
||||||
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);
|
Memory(sc_module_name name, bool use_file);
|
||||||
|
|
||||||
|
virtual uint32_t getPCfromHEX();
|
||||||
|
|
||||||
// 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 );
|
||||||
|
|
||||||
|
@ -53,8 +56,10 @@ public:
|
||||||
|
|
||||||
virtual unsigned int transport_dbg(tlm::tlm_generic_payload& trans);
|
virtual unsigned int transport_dbg(tlm::tlm_generic_payload& trans);
|
||||||
|
|
||||||
|
private:
|
||||||
int mem[SIZE];
|
int mem[SIZE];
|
||||||
|
|
||||||
|
uint32_t program_counter;
|
||||||
/**
|
/**
|
||||||
* Reads file and stores in Code Memory. Uses propietary file format
|
* Reads file and stores in Code Memory. Uses propietary file format
|
||||||
* @brief Reads file and stores in Code Memory
|
* @brief Reads file and stores in Code Memory
|
||||||
|
|
|
@ -24,6 +24,73 @@ using namespace std;
|
||||||
class Registers {
|
class Registers {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum {
|
||||||
|
x0 = 0,
|
||||||
|
x1 = 1,
|
||||||
|
x2,
|
||||||
|
x3,
|
||||||
|
x4,
|
||||||
|
x5,
|
||||||
|
x6,
|
||||||
|
x7,
|
||||||
|
x8,
|
||||||
|
x9,
|
||||||
|
x10,
|
||||||
|
x11,
|
||||||
|
x12,
|
||||||
|
x13,
|
||||||
|
x14,
|
||||||
|
x15,
|
||||||
|
x16,
|
||||||
|
x17,
|
||||||
|
x18,
|
||||||
|
x19,
|
||||||
|
x20,
|
||||||
|
x21,
|
||||||
|
x22,
|
||||||
|
x23,
|
||||||
|
x24,
|
||||||
|
x25,
|
||||||
|
x26,
|
||||||
|
x27,
|
||||||
|
x28,
|
||||||
|
x29,
|
||||||
|
x30,
|
||||||
|
x31,
|
||||||
|
zero = x0,
|
||||||
|
ra = x1,
|
||||||
|
sp = x2,
|
||||||
|
gp = x3,
|
||||||
|
tp = x4,
|
||||||
|
t0 = x5,
|
||||||
|
t1 = x6,
|
||||||
|
t2 = x7,
|
||||||
|
s0 = x8,
|
||||||
|
fp = x8,
|
||||||
|
s1 = x9,
|
||||||
|
a0 = x10,
|
||||||
|
a1 = x11,
|
||||||
|
a2 = x12,
|
||||||
|
a3 = x13,
|
||||||
|
a4 = x14,
|
||||||
|
a5 = x15,
|
||||||
|
a6 = x16,
|
||||||
|
a7 = x17,
|
||||||
|
s2 = x18,
|
||||||
|
s3 = x19,
|
||||||
|
s4 = x20,
|
||||||
|
s5 = x21,
|
||||||
|
s6 = x22,
|
||||||
|
s7 = x23,
|
||||||
|
s8 = x24,
|
||||||
|
s9 = x25,
|
||||||
|
s10 = x26,
|
||||||
|
s11 = x27,
|
||||||
|
t3 = x28,
|
||||||
|
t4 = x29,
|
||||||
|
t5 = x30,
|
||||||
|
t6 = x31
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Default constructor
|
* Default constructor
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*!
|
||||||
|
\file Trace.h
|
||||||
|
\brief Basic TLM-2 Trace module
|
||||||
|
\author Màrius Montón
|
||||||
|
\date September 2018
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TRACE_H__
|
||||||
|
#define __TRACE_H__
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#define SC_INCLUDE_DYNAMIC_PROCESSES
|
||||||
|
|
||||||
|
#include "systemc"
|
||||||
|
|
||||||
|
#include "tlm.h"
|
||||||
|
#include "tlm_utils/simple_target_socket.h"
|
||||||
|
|
||||||
|
using namespace sc_core;
|
||||||
|
using namespace sc_dt;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Trace: sc_module {
|
||||||
|
public:
|
||||||
|
// TLM-2 socket, defaults to 32-bits wide, base protocol
|
||||||
|
tlm_utils::simple_target_socket<Trace> socket;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
Trace(sc_module_name name);
|
||||||
|
|
||||||
|
// TLM-2 blocking transport method
|
||||||
|
virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,35 @@
|
||||||
|
#include "BusCtrl.h"
|
||||||
|
|
||||||
|
SC_HAS_PROCESS(BusCtrl);
|
||||||
|
BusCtrl::BusCtrl(sc_module_name name): sc_module(name)
|
||||||
|
,cpu_instr_socket("cpu_instr_socket")
|
||||||
|
,cpu_data_socket("cpu_data_socket")
|
||||||
|
,data_memory_socket("data_memory_socket")
|
||||||
|
,trace_socket("trace_socket")
|
||||||
|
{
|
||||||
|
cpu_instr_socket.register_b_transport(this, &BusCtrl::b_transport);
|
||||||
|
cpu_data_socket.register_b_transport(this, &BusCtrl::b_transport);
|
||||||
|
log = Log::getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BusCtrl::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) {
|
||||||
|
tlm::tlm_command cmd = trans.get_command();
|
||||||
|
sc_dt::uint64 adr = trans.get_address() / 4;
|
||||||
|
|
||||||
|
if (adr == TRACE_MEMORY_ADDRESS / 4) {
|
||||||
|
trace_socket->b_transport(trans, delay);
|
||||||
|
} else {
|
||||||
|
data_memory_socket->b_transport(trans, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (cmd == tlm::TLM_READ_COMMAND) {
|
||||||
|
log->SC_log(Log::DEBUG) << "RD Address: @0x" << hex << adr << dec << endl;
|
||||||
|
} else {
|
||||||
|
log->SC_log(Log::DEBUG) << "WR Address: @0x" << hex << adr << dec << endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
trans.set_response_status( tlm::TLM_OK_RESPONSE );
|
||||||
|
}
|
114
src/CPU.cpp
114
src/CPU.cpp
|
@ -2,7 +2,7 @@
|
||||||
#include "CPU.h"
|
#include "CPU.h"
|
||||||
|
|
||||||
SC_HAS_PROCESS(CPU);
|
SC_HAS_PROCESS(CPU);
|
||||||
CPU::CPU(sc_module_name name): sc_module(name)
|
CPU::CPU(sc_module_name name, uint32_t PC): sc_module(name)
|
||||||
, instr_bus("instr_bus")
|
, instr_bus("instr_bus")
|
||||||
{
|
{
|
||||||
register_bank = new Registers();
|
register_bank = new Registers();
|
||||||
|
@ -10,6 +10,7 @@ CPU::CPU(sc_module_name name): sc_module(name)
|
||||||
perf = Performance::getInstance();
|
perf = Performance::getInstance();
|
||||||
log = Log::getInstance();
|
log = Log::getInstance();
|
||||||
|
|
||||||
|
register_bank->setPC(PC);
|
||||||
SC_THREAD(CPU_thread);
|
SC_THREAD(CPU_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ CPU::~CPU() {
|
||||||
perf->dump();
|
perf->dump();
|
||||||
cout << "*********************************************" << endl;
|
cout << "*********************************************" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* main thread for CPU simulation
|
* main thread for CPU simulation
|
||||||
* @brief CPU mai thread
|
* @brief CPU mai thread
|
||||||
|
@ -49,8 +51,8 @@ void CPU::CPU_thread(void) {
|
||||||
if ( trans->is_response_error() ) {
|
if ( trans->is_response_error() ) {
|
||||||
SC_REPORT_ERROR("CPU base", "Read memory");
|
SC_REPORT_ERROR("CPU base", "Read memory");
|
||||||
} else {
|
} else {
|
||||||
// cout << "INSTR: " << INSTR << endl;
|
log->SC_log(Log::INFO) << "PC: " << hex << register_bank->getPC()
|
||||||
log->SC_log(Log::INFO) << "PC: " << register_bank->getPC() << endl;
|
<< dec << endl;
|
||||||
Instruction inst(INSTR);
|
Instruction inst(INSTR);
|
||||||
|
|
||||||
switch(inst.decode()) {
|
switch(inst.decode()) {
|
||||||
|
@ -63,45 +65,127 @@ void CPU::CPU_thread(void) {
|
||||||
case OP_JAL:
|
case OP_JAL:
|
||||||
exec->JAL(inst);
|
exec->JAL(inst);
|
||||||
break;
|
break;
|
||||||
|
case OP_JALR:
|
||||||
|
exec->JALR(inst);
|
||||||
|
break;
|
||||||
case OP_BEQ:
|
case OP_BEQ:
|
||||||
exec->BEQ(inst);
|
exec->BEQ(inst);
|
||||||
break;
|
break;
|
||||||
case OP_BNE:
|
case OP_BNE:
|
||||||
exec->BNE(inst);
|
exec->BNE(inst);
|
||||||
break;
|
break;
|
||||||
|
case OP_BLT:
|
||||||
|
exec->BLT(inst);
|
||||||
|
break;
|
||||||
|
case OP_BGE:
|
||||||
|
exec->BGE(inst);
|
||||||
|
break;
|
||||||
|
case OP_BLTU:
|
||||||
|
exec->BLTU(inst);
|
||||||
|
break;
|
||||||
|
case OP_BGEU:
|
||||||
|
exec->BGEU(inst);
|
||||||
|
break;
|
||||||
|
case OP_LB:
|
||||||
|
exec->LB(inst);
|
||||||
|
break;
|
||||||
|
case OP_LH:
|
||||||
|
exec->LB(inst);
|
||||||
|
break;
|
||||||
case OP_LW:
|
case OP_LW:
|
||||||
exec->LW(inst);
|
exec->LW(inst);
|
||||||
break;
|
break;
|
||||||
|
case OP_LBU:
|
||||||
|
exec->LBU(inst);
|
||||||
|
break;
|
||||||
|
case OP_LHU:
|
||||||
|
exec->LHU(inst);
|
||||||
|
break;
|
||||||
|
case OP_SB:
|
||||||
|
exec->SB(inst);
|
||||||
|
break;
|
||||||
|
case OP_SH:
|
||||||
|
exec->SH(inst);
|
||||||
|
break;
|
||||||
case OP_SW:
|
case OP_SW:
|
||||||
exec->SW(inst);
|
exec->SW(inst);
|
||||||
break;
|
break;
|
||||||
case OP_ADDI:
|
case OP_ADDI:
|
||||||
exec->ADDI(inst);
|
exec->ADDI(inst);
|
||||||
break;
|
break;
|
||||||
|
case OP_SLTI:
|
||||||
|
exec->SLTI(inst);
|
||||||
|
break;
|
||||||
|
case OP_SLTIU:
|
||||||
|
exec->SLTIU(inst);
|
||||||
|
break;
|
||||||
|
case OP_XORI:
|
||||||
|
exec->XORI(inst);
|
||||||
|
break;
|
||||||
|
case OP_ORI:
|
||||||
|
exec->ORI(inst);
|
||||||
|
break;
|
||||||
|
case OP_ANDI:
|
||||||
|
exec->ANDI(inst);
|
||||||
|
break;
|
||||||
|
case OP_SLLI:
|
||||||
|
exec->SLLI(inst);
|
||||||
|
break;
|
||||||
|
case OP_SRLI:
|
||||||
|
exec->SRLI(inst);
|
||||||
|
break;
|
||||||
|
case OP_SRAI:
|
||||||
|
exec->SRAI(inst);
|
||||||
|
break;
|
||||||
case OP_ADD:
|
case OP_ADD:
|
||||||
exec->ADD(inst);
|
exec->ADD(inst);
|
||||||
break;
|
break;
|
||||||
case OP_SUB:
|
case OP_SUB:
|
||||||
exec->SUB(inst);
|
exec->SUB(inst);
|
||||||
break;
|
break;
|
||||||
|
case OP_SLL:
|
||||||
|
exec->SLL(inst);
|
||||||
|
break;
|
||||||
|
case OP_SLT:
|
||||||
|
exec->SLT(inst);
|
||||||
|
break;
|
||||||
|
case OP_SLTU:
|
||||||
|
exec->SLTU(inst);
|
||||||
|
break;
|
||||||
|
case OP_XOR:
|
||||||
|
exec->XOR(inst);
|
||||||
|
break;
|
||||||
|
case OP_SRL:
|
||||||
|
exec->SRL(inst);
|
||||||
|
break;
|
||||||
|
case OP_SRA:
|
||||||
|
exec->SRA(inst);
|
||||||
|
break;
|
||||||
|
case OP_OR:
|
||||||
|
exec->OR(inst);
|
||||||
|
break;
|
||||||
|
case OP_AND:
|
||||||
|
exec->AND(inst);
|
||||||
|
break;
|
||||||
|
#if 0
|
||||||
|
case OP_CSRRW:
|
||||||
|
exec->CSRRW(inst);
|
||||||
|
break;
|
||||||
|
case OP_CSRRS:
|
||||||
|
exec->CSRRS(inst);
|
||||||
|
break;
|
||||||
|
case OP_CSRRC:
|
||||||
|
exec->CSRRC(inst);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
|
cout << endl << "Instruction not implemented: ";
|
||||||
|
inst.dump();
|
||||||
exec->NOP(inst);
|
exec->NOP(inst);
|
||||||
}
|
}
|
||||||
perf->instructionsInc();
|
perf->instructionsInc();
|
||||||
|
|
||||||
register_bank->incPC();
|
register_bank->incPC();
|
||||||
|
|
||||||
/* Simulation control, we stop at 10 instructions (if no NOP found)*/
|
|
||||||
if (register_bank->getPC() == 10*4) {
|
|
||||||
cout << "*********************************************" << endl;
|
|
||||||
register_bank->dump();
|
|
||||||
cout << sc_time_stamp() << endl;
|
|
||||||
cout << "*********************************************" << endl;
|
|
||||||
|
|
||||||
perf->dump();
|
|
||||||
|
|
||||||
sc_stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // while(1)
|
} // while(1)
|
||||||
} // CPU_thread
|
} // CPU_thread
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
Instruction::Instruction(sc_int<32> instr) {
|
Instruction::Instruction(sc_int<32> instr) {
|
||||||
m_instr = instr;
|
m_instr = instr;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
opCodes Instruction::decode() {
|
opCodes Instruction::decode() {
|
||||||
|
|
|
@ -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::ERROR;
|
currentLogLevel = Log::INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::SC_log(std::string msg, enum LogLevel level) {
|
void Log::SC_log(std::string msg, enum LogLevel level) {
|
||||||
|
@ -22,6 +22,7 @@ void Log::SC_log(std::string msg, enum LogLevel level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream& Log::SC_log(enum LogLevel level) {
|
std::ofstream& Log::SC_log(enum LogLevel level) {
|
||||||
|
|
||||||
if (level >= currentLogLevel) {
|
if (level >= currentLogLevel) {
|
||||||
m_stream << "time " << sc_core::sc_time_stamp() << ": ";
|
m_stream << "time " << sc_core::sc_time_stamp() << ": ";
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,11 @@ Memory::Memory(sc_module_name name, bool use_file): sc_module(name)
|
||||||
SC_THREAD(invalidation_process);
|
SC_THREAD(invalidation_process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t Memory::getPCfromHEX() {
|
||||||
|
return program_counter;
|
||||||
|
|
||||||
|
}
|
||||||
void Memory::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay )
|
void Memory::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay )
|
||||||
{
|
{
|
||||||
tlm::tlm_command cmd = trans.get_command();
|
tlm::tlm_command cmd = trans.get_command();
|
||||||
|
@ -58,8 +63,8 @@ void Memory::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cout << "MEM: addr=" << adr << endl;
|
//cout << "MEM: addr=" << hex << adr << endl << endl;
|
||||||
// cout << "MEM: data=" << mem[adr] << endl;
|
//cout << "MEM: data=" << mem[adr] << endl;
|
||||||
|
|
||||||
// Obliged to implement read and write commands
|
// Obliged to implement read and write commands
|
||||||
if ( cmd == tlm::TLM_READ_COMMAND )
|
if ( cmd == tlm::TLM_READ_COMMAND )
|
||||||
|
@ -158,6 +163,7 @@ void Memory::readHexFile(string filename) {
|
||||||
int byte_count;
|
int byte_count;
|
||||||
int address;
|
int address;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
int extended_address = 0;
|
||||||
|
|
||||||
hexfile.open(filename);
|
hexfile.open(filename);
|
||||||
|
|
||||||
|
@ -165,12 +171,12 @@ void Memory::readHexFile(string filename) {
|
||||||
while(getline(hexfile, line) ) {
|
while(getline(hexfile, line) ) {
|
||||||
/* # is a comentary in the file */
|
/* # is a comentary in the file */
|
||||||
if (line[0] == ':') {
|
if (line[0] == ':') {
|
||||||
|
|
||||||
if (line.substr(7,2) == "00")
|
if (line.substr(7,2) == "00")
|
||||||
{
|
{
|
||||||
/* Data */
|
/* Data */
|
||||||
byte_count = stol(line.substr(1,2), nullptr, 16);
|
byte_count = stol(line.substr(1,2), nullptr, 16);
|
||||||
address = stol(line.substr(3,4), nullptr, 16) / 4;
|
address = stol(line.substr(3,4), nullptr, 16) / 4;
|
||||||
|
address = address + extended_address;
|
||||||
|
|
||||||
for (i=0; i < byte_count/4; i++) {
|
for (i=0; i < byte_count/4; i++) {
|
||||||
mem[address+i] = stol(line.substr(9+(i*8), 2), nullptr, 16);
|
mem[address+i] = stol(line.substr(9+(i*8), 2), nullptr, 16);
|
||||||
|
@ -178,6 +184,15 @@ void Memory::readHexFile(string filename) {
|
||||||
mem[address+i] |= stol(line.substr(13+(i*8),2), nullptr, 16) << 16;
|
mem[address+i] |= stol(line.substr(13+(i*8),2), nullptr, 16) << 16;
|
||||||
mem[address+i] |= stol(line.substr(15+(i*8),2), nullptr, 16) << 24;
|
mem[address+i] |= stol(line.substr(15+(i*8),2), nullptr, 16) << 24;
|
||||||
}
|
}
|
||||||
|
} else if (line.substr(7,2) == "02") {
|
||||||
|
/* Extended segment address */
|
||||||
|
extended_address = stol(line.substr(9,4), nullptr, 16 ) * 4;
|
||||||
|
} else if (line.substr(7,2) == "03") {
|
||||||
|
/* Start segment address */
|
||||||
|
uint32_t code_segment;
|
||||||
|
code_segment = stol(line.substr(9,4), nullptr, 16) * 16; /* ? */
|
||||||
|
program_counter = stol(line.substr(13,4), nullptr, 16);
|
||||||
|
program_counter = program_counter + code_segment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,4 +200,11 @@ void Memory::readHexFile(string filename) {
|
||||||
} else {
|
} else {
|
||||||
SC_REPORT_ERROR("Memory", "Open file error");
|
SC_REPORT_ERROR("Memory", "Open file error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for(int i = 50;i<100; i++) {
|
||||||
|
cout << "Dump address: 0x" << hex << extended_address + i << ": 0x" <<
|
||||||
|
mem[extended_address+i] << dec << endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ void RISC_V_execute::LUI(Instruction &inst) {
|
||||||
rd = inst.rd();
|
rd = inst.rd();
|
||||||
imm = inst.imm_U() << 12;
|
imm = inst.imm_U() << 12;
|
||||||
regs->setValue(rd, imm);
|
regs->setValue(rd, imm);
|
||||||
log->SC_log(Log::INFO) << "LUI R" << rd << " -> " << imm << endl;
|
log->SC_log(Log::INFO) << "LUI R" << rd << " <- " << imm << endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,10 +47,10 @@ void RISC_V_execute::JAL(Instruction &inst) {
|
||||||
new_pc = regs->getPC();
|
new_pc = regs->getPC();
|
||||||
regs->setValue(rd, new_pc);
|
regs->setValue(rd, new_pc);
|
||||||
|
|
||||||
new_pc = new_pc + mem_addr;
|
new_pc = new_pc + mem_addr - 4;
|
||||||
regs->setPC(new_pc);
|
regs->setPC(new_pc);
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << "JAL R" << rd << " PC + " << mem_addr << " -> PC (" << new_pc << ")" << endl;
|
log->SC_log(Log::INFO) << "JAL: R" << rd << " PC + " << mem_addr << " -> PC (" << new_pc << ")" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RISC_V_execute::JALR(Instruction &inst) {
|
void RISC_V_execute::JALR(Instruction &inst) {
|
||||||
|
@ -320,7 +320,7 @@ void RISC_V_execute::ADDI(Instruction &inst) {
|
||||||
calc = regs->getValue(rs1) + imm;
|
calc = regs->getValue(rs1) + imm;
|
||||||
regs->setValue(rd, calc);
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << "ADDI: R" << rs1 << " + " << imm << " -> R" << rd << endl;
|
log->SC_log(Log::INFO) << dec << "ADDI: R" << rs1 << " + " << imm << " -> R" << rd << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RISC_V_execute::SLTI(Instruction &inst) {
|
void RISC_V_execute::SLTI(Instruction &inst) {
|
||||||
|
@ -406,7 +406,7 @@ void RISC_V_execute::ANDI(Instruction &inst) {
|
||||||
regs->setValue(rd, calc);
|
regs->setValue(rd, calc);
|
||||||
|
|
||||||
log->SC_log(Log::INFO) << "ANDI: R" << rs1 << " AND " << imm
|
log->SC_log(Log::INFO) << "ANDI: R" << rs1 << " AND " << imm
|
||||||
<< "-> R" << rd << endl;
|
<< " -> R" << rd << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RISC_V_execute::SLLI(Instruction &inst) {
|
void RISC_V_execute::SLLI(Instruction &inst) {
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
Registers::Registers() {
|
Registers::Registers() {
|
||||||
|
|
||||||
memset(register_bank, 0, sizeof(int32_t)*32);
|
memset(register_bank, 0, sizeof(int32_t)*32); // 32 registers of 32 bits each
|
||||||
perf = Performance::getInstance();
|
perf = Performance::getInstance();
|
||||||
|
|
||||||
|
register_bank[sp] = 1024-1; // SP points to end of memory
|
||||||
register_PC = 0;
|
register_PC = 0x10000; // default _start address
|
||||||
}
|
}
|
||||||
|
|
||||||
void Registers::dump(void) {
|
void Registers::dump(void) {
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include "CPU.h"
|
#include "CPU.h"
|
||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
|
#include "BusCtrl.h"
|
||||||
|
#include "Trace.h"
|
||||||
|
|
||||||
using namespace sc_core;
|
using namespace sc_core;
|
||||||
using namespace sc_dt;
|
using namespace sc_dt;
|
||||||
|
@ -20,27 +22,42 @@ SC_MODULE(Top)
|
||||||
{
|
{
|
||||||
//Initiator *initiator;
|
//Initiator *initiator;
|
||||||
CPU *cpu;
|
CPU *cpu;
|
||||||
Memory *InstrMemory;
|
//Memory *InstrMemory;
|
||||||
Memory *DataMemory;
|
//Memory *DataMemory;
|
||||||
|
Memory *MainMemory;
|
||||||
|
BusCtrl* Bus;
|
||||||
|
Trace *trace;
|
||||||
|
|
||||||
|
uint32_t start_PC;
|
||||||
sc_signal<bool> IRQ;
|
sc_signal<bool> IRQ;
|
||||||
|
|
||||||
SC_CTOR(Top)
|
SC_CTOR(Top)
|
||||||
{
|
{
|
||||||
cpu = new CPU("cpu");
|
|
||||||
InstrMemory = new Memory("InstrMemory", filename);
|
|
||||||
DataMemory = new Memory("Datamemory", false);
|
|
||||||
|
|
||||||
cpu->instr_bus.bind(InstrMemory->socket);
|
|
||||||
cpu->exec->data_bus.bind(DataMemory->socket);
|
MainMemory = new Memory("Main_Memory", filename);
|
||||||
|
start_PC = MainMemory->getPCfromHEX();
|
||||||
|
|
||||||
|
cpu = new CPU("cpu", start_PC);
|
||||||
|
|
||||||
|
Bus = new BusCtrl("BusCtrl");
|
||||||
|
trace = new Trace("Trace");
|
||||||
|
|
||||||
|
cpu->instr_bus.bind(Bus->cpu_instr_socket);
|
||||||
|
cpu->exec->data_bus.bind(Bus->cpu_data_socket);
|
||||||
|
|
||||||
|
Bus->data_memory_socket.bind(MainMemory->socket);
|
||||||
|
Bus->trace_socket.bind(trace->socket);
|
||||||
|
|
||||||
//cpu->interrupt.bind(IRQ);
|
//cpu->interrupt.bind(IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Top() {
|
~Top() {
|
||||||
cout << "Top destructor" << endl;
|
cout << "Top destructor" << endl;
|
||||||
delete cpu;
|
delete cpu;
|
||||||
delete InstrMemory;
|
delete MainMemory;
|
||||||
delete DataMemory;
|
delete Bus;
|
||||||
|
delete trace;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include "Trace.h"
|
||||||
|
|
||||||
|
SC_HAS_PROCESS(Trace);
|
||||||
|
Trace::Trace(sc_module_name name): sc_module(name)
|
||||||
|
,socket("socket") {
|
||||||
|
socket.register_b_transport(this, &Trace::b_transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Trace::b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) {
|
||||||
|
//tlm::tlm_command cmd = trans.get_command();
|
||||||
|
//sc_dt::uint64 adr = trans.get_address() / 4;
|
||||||
|
unsigned char* ptr = trans.get_data_ptr();
|
||||||
|
//unsigned int len = trans.get_data_length();
|
||||||
|
//unsigned char* byt = trans.get_byte_enable_ptr();
|
||||||
|
//unsigned int wid = trans.get_streaming_width();
|
||||||
|
|
||||||
|
|
||||||
|
cout << (char) *ptr;
|
||||||
|
|
||||||
|
trans.set_response_status( tlm::TLM_OK_RESPONSE );
|
||||||
|
}
|
Loading…
Reference in New Issue