Commit 0c478130 authored by logan's avatar logan
Browse files

major modification

parent 76f81fdf
Pipeline #241063 failed with stages
in 3 minutes and 30 seconds
......@@ -116,7 +116,6 @@ public:
void cacheprocess(ac_int<32, false> addr, memMask mask, directoryOpType opType, ac_int<4, false> hartid, ac_int<INTERFACE_SIZE * 8, false> dataIn,
ac_int<INTERFACE_SIZE * 8, false>& dataOut, bool& waitOut)
{
// bit size is the log(setSize)
ac_int<LOG_SET_SIZE, false> place = addr.slc<LOG_SET_SIZE>(LOG_LINE_SIZE);
// startAddress is log(lineSize) + log(setSize) + 2
......
......@@ -38,8 +38,8 @@ struct Core {
/* Memory */
// Interface size are configured with 4 bytes interface size (32 bits)
//CacheMemory<4, 16, 64> *dm, *im;
CacheMemory<4, 16, 64>*dm, *im;
CacheMemory<4, 16, 64> *dm, *im;
//MemoryInterface<4>*dm, *im;
/* Registers */
ac_int<32, true> regFile[32];
......@@ -64,5 +64,6 @@ struct Core {
};
void doCycle(struct Core& core, bool globalStall, bool ir_timer = false, bool ipi = false);
void initCore(Core& core);
#endif // __CORE_H__
......@@ -214,6 +214,8 @@ public:
ac_int<32, false> mhpmevent31;
*/
ac_int<32, false> result_reg;
bool setPC_reg;
bool csrUsed_reg;
bool process(struct DCtoEx dctoEx, ac_int<1, false> ir_timer, ac_int<1, false> ipi, ac_int<32, false> &result, bool& setPC, bool stall_cpu){
......@@ -222,9 +224,18 @@ public:
// External Interrupts
this->mip[IR_M_SOFT] = ipi;// & this->mie[IR_M_SOFT]; // inter processor interrupt
this->mip[IR_M_TIMER] = ir_timer; // & this->mie[IR_M_TIMER]; // timer interrupt (mtime, mtimecmp)
if(stall_cpu){
setPC = setPC_reg;
result = result_reg;
return csrUsed_reg;
} else {
setPC_reg = false;
csrUsed_reg = false;
}
// ZiCSR : CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI
if (!stall_cpu && dctoEx.we && dctoEx.opCode == RISCV_SYSTEM && (dctoEx.funct3 == RISCV_SYSTEM_CSRRW || dctoEx.funct3 == RISCV_SYSTEM_CSRRS || dctoEx.funct3 == RISCV_SYSTEM_CSRRC ||
if (dctoEx.we && dctoEx.opCode == RISCV_SYSTEM && (dctoEx.funct3 == RISCV_SYSTEM_CSRRW || dctoEx.funct3 == RISCV_SYSTEM_CSRRS || dctoEx.funct3 == RISCV_SYSTEM_CSRRC ||
dctoEx.funct3 == RISCV_SYSTEM_CSRRWI || dctoEx.funct3 == RISCV_SYSTEM_CSRRSI || dctoEx.funct3 == RISCV_SYSTEM_CSRRCI)){
//We are in a CSR function
......@@ -285,7 +296,7 @@ public:
// Machine Trap Setup
case CSR_MSTATUS:
result_reg = this->mstatus;
this->mstatus = (result & andMask) | orMask;// XS and FS should be zero anyway [15:13]
this->mstatus = (result_reg & andMask) | orMask;// XS and FS should be zero anyway [15:13]
break;
case CSR_MISA:
result_reg = 0x40001100;
......@@ -301,100 +312,101 @@ public:
case CSR_MIE:
// We can protect that write in order to prevent the system to enable unsupported interrupts
result_reg = this->mie;
this->mie = (result & andMask) | orMask;
this->mie = (result_reg & andMask) | orMask;
break;
case CSR_MTVEC:
result_reg = this->mtvec;
this->mtvec = (result & andMask) | orMask;
this->mtvec = (result_reg & andMask) | orMask;
break;
// Machine Trap Handling
case CSR_MSCRATCH:
result_reg = this->mscratch;
this->mscratch = (result & andMask) | orMask;
this->mscratch = (result_reg & andMask) | orMask;
break;
case CSR_MEPC:
result_reg = this->mepc;
this->mepc = (result & andMask) | orMask;
this->mepc = (result_reg & andMask) | orMask;
break;
case CSR_MCAUSE:
result_reg = this->mcause;
this->mcause = (result & andMask) | orMask;
this->mcause = (result_reg & andMask) | orMask;
break;
case CSR_MTVAL:
result_reg = this->mtval;
this->mtval = (result & andMask) | orMask;
this->mtval = (result_reg & andMask) | orMask;
break;
case CSR_MIP:
result_reg = this->mip;
this->mip = (result & andMask) | orMask;
this->mip = (result_reg & andMask) | orMask;
break;
// Machine Counter/Timers
case CSR_MCYCLE:
result_reg = this->mcycle.slc<32>(0);
this->mcycle.set_slc(0, (result & andMask) | orMask);
this->mcycle.set_slc(0, (result_reg & andMask) | orMask);
break;
case CSR_MCYCLEH:
result = this->mcycle.slc<32>(32);
this->mcycle.set_slc(32, (result & andMask) | orMask);
result_reg = this->mcycle.slc<32>(32);
this->mcycle.set_slc(32, (result_reg & andMask) | orMask);
break;
case CSR_MINSTRET:
result_reg = this->minstret.slc<32>(0);
this->minstret.set_slc(0, (result & andMask) | orMask);
this->minstret.set_slc(0, (result_reg & andMask) | orMask);
break;
case CSR_MINSTRETH:
result = this->minstret.slc<32>(32);
this->minstret.set_slc(32, (result & andMask) | orMask);
result_reg = this->minstret.slc<32>(32);
this->minstret.set_slc(32, (result_reg & andMask) | orMask);
break;
case CSR_MHPMCOUNTER3:
result_reg = this->mhpmcounter3.slc<32>(0);
this->mhpmcounter3.set_slc(0, (result & andMask) | orMask);
this->mhpmcounter3.set_slc(0, (result_reg & andMask) | orMask);
break;
case CSR_MHPMCOUNTER3H:
result_reg = this->mhpmcounter3.slc<32>(32);
this->mhpmcounter3.set_slc(32, (result & andMask) | orMask);
this->mhpmcounter3.set_slc(32, (result_reg & andMask) | orMask);
break;
case CSR_MHPMCOUNTER4:
result_reg = this->mhpmcounter4.slc<32>(0);
this->mhpmcounter4.set_slc(0, (result & andMask) | orMask);
this->mhpmcounter4.set_slc(0, (result_reg & andMask) | orMask);
break;
case CSR_MHPMCOUNTER4H:
result_reg = this->mhpmcounter4.slc<32>(32);
this->mhpmcounter4.set_slc(32, (result & andMask) | orMask);
this->mhpmcounter4.set_slc(32, (result_reg & andMask) | orMask);
break;
// Machine Counter Setup
case CSR_MCOUNTINHIBIT:
result_reg = this->mcountinhibit;
this->mcountinhibit = (result & andMask) | orMask;
this->mcountinhibit = (result_reg & andMask) | orMask;
break;
case CSR_MHPMEVENT3:
result_reg = this->mhpmevent3;
this->mhpmevent3 = (result & andMask) | orMask;
this->mhpmevent3 = (result_reg & andMask) | orMask;
break;
case CSR_MHPMEVENT4:
result_reg = this->mhpmevent4;
this->mhpmevent4 = (result & andMask) | orMask;
this->mhpmevent4 = (result_reg & andMask) | orMask;
break;
default:
break;
}
result = result_reg;
return true;
}
if (dctoEx.we && dctoEx.opCode == RISCV_SYSTEM && dctoEx.funct3 == RISCV_PRIV){
setPC_reg = false;
csrUsed_reg = true;
}
if (dctoEx.we && dctoEx.opCode == RISCV_SYSTEM && dctoEx.funct3 == RISCV_PRIV){
//We handle a ecall or a ebreak
// Wait For Interrupt (WFI) : NOP instructions for the moment
switch(dctoEx.funct12){
case RISCV_SYSTEM_ENV_ECALL:
//ECALL jumps to the IRQ handler code, whose adress is stored in mtvec lower bits
this->mepc = dctoEx.pc;
this->mepc = dctoEx.pc;
this->mcause = 11;// environment call from machine mode 0x00000 -> exception
result_reg = mtvec;
setPC = true & HAS_KERNEL_SYSCALL_HANDLER;
result_reg = mtvec;
setPC_reg = true & HAS_KERNEL_SYSCALL_HANDLER;
break;
case RISCV_SYSTEM_ENV_MRET:
//MRET jumps back to the address stored in mepc
result_reg = this->mepc;
setPC = true & HAS_KERNEL_SYSCALL_HANDLER;
setPC_reg = true & HAS_KERNEL_SYSCALL_HANDLER;
//We change interrupt enable bits (MIE = MPIE and MPIE = 1)
if(!stall_cpu) {
this->mstatus[3] = this->mstatus[7];
......@@ -402,19 +414,21 @@ public:
}
break;
case RISCV_SYSTEM_ENV_EBREAK:
this->mepc = dctoEx.pc;
this->mepc = dctoEx.pc;
this->mcause = 3;// break debug !
result_reg = mtvec;
setPC = true & HAS_KERNEL_SYSCALL_HANDLER;
result_reg = mtvec;
setPC_reg = true & HAS_KERNEL_SYSCALL_HANDLER;
break;
default:
setPC_reg = false;
break;
}
csrUsed_reg = false;
}
result = result_reg;
return false;
setPC = setPC_reg;
return csrUsed_reg;
}
};
......
......@@ -3,7 +3,7 @@
#include <ac_int.h>
typedef enum { BYTE = 0, HALF, WORD, BYTE_U, HALF_U, LONG } memMask;
typedef enum { NOMASK = 0, BYTE, HALF, WORD, BYTE_U, HALF_U, LONG } memMask;
//typedef enum { NONE = 0, LOAD, STORE } memOpType;
......@@ -18,7 +18,7 @@ struct cacheDirectoryInterfaceBase {
directoryOpType interfaceRequest;
ac_int<1, false> interfaceAck;
ac_int<1, false> releaseAck;
memMask mask;
// data_req
ac_int<32, false> buffer;
};
......@@ -32,8 +32,11 @@ typedef struct cacheDirectoryInterfaceIn : public cacheDirectoryInterfaceBase {
template <unsigned int INTERFACE_SIZE> class MemoryInterface {
protected:
bool wait;
bool wait=false;
directoryOpType lastOpType = NONE;
memMask lastMask = NOMASK;
ac_int<INTERFACE_SIZE * 8, false> buffer;
public:
virtual void process(ac_int<32, false> addr, memMask mask, directoryOpType opType, ac_int<4, false> hartid, ac_int<INTERFACE_SIZE * 8, false> dataIn,
ac_int<INTERFACE_SIZE * 8, false>& dataOut, bool& waitOut) =0;
......@@ -53,24 +56,40 @@ public:
{
// Incomplete memory only works for 32 bits
assert(INTERFACE_SIZE == 4);
if (waitOut) {
if (this->wait) {
waitOut = !bufferOut->releaseAck;
bufferOut->interfaceAck = !bufferOut->releaseAck;
dataOut = bufferIn->buffer;
this->wait = !this->wait;
this->buffer = bufferIn->buffer;
} else if (opType != NONE) {
bufferOut->addr = addr;
bufferOut->interfaceAck = 1;
bufferOut->interfaceRequest = opType;
bufferOut->buffer = dataIn;
waitOut = (opType == WRITEHIT || opType == MISS_WRITE || opType == MISS_READ || opType == DATA_FIRST_SEND || opType == DATA_SEND || opType == DATA_LAST_SEND) ? true : false;
//enable ---> (opType != WRITEHIT && opType != MISS_WRITE && opType != MISS_READ && opType != DATA_FIRST_SEND && opType != DATA_SEND && opType != DATA_LAST_SEND) ? false : true;
if(opType == STORE || (bufferOut->addr != addr) || (bufferOut->addr == addr && (this->lastOpType != opType || this->lastMask != mask) )){
bufferOut->addr = addr;
bufferOut->interfaceAck = 1;
bufferOut->interfaceRequest = opType;
bufferOut->buffer = dataIn;
bufferOut->mask = mask;
this->lastOpType = opType;
this->lastMask = mask;
waitOut = (opType==LOAD || opType == WRITEHIT || opType == MISS_WRITE || opType == MISS_READ || opType == DATA_FIRST_SEND || opType == DATA_SEND || opType == DATA_LAST_SEND) ? true : false;
this->wait = waitOut;
//enable ---> (opType != WRITEHIT && opType != MISS_WRITE && opType != MISS_READ && opType != DATA_FIRST_SEND && opType != DATA_SEND && opType != DATA_LAST_SEND) ? false : true;
} else {
// we already load it !
this->wait = false;
waitOut = false;
dataOut = this->buffer;
}
} else {
bufferOut->interfaceAck = 0; // STORE case
}
#ifndef __HLS__
if (PRINT_CONSOLE && opType == STORE && addr == UART_RXTX){
//UART
if(dataIn != 0x1B)
if(dataIn != 0x1B){
printf("%c", (char) dataIn);
}
}
#endif
}
......
......@@ -41,7 +41,7 @@
#define NB_CORES 1
#define HAS_PHYS_MULTICORES (NB_CORES > 2)
// Memory size
#define DRAM_SIZE ((size_t)1 << 24) // ~67 MB
#define DRAM_SIZE ((size_t)1 << 19) // ~67 MB
// ROM and RAM address
#define ROMRAM 0x30000
// Stack first address
......
......@@ -23,15 +23,32 @@ BasicSimulator::BasicSimulator(std::string binaryFile, std::vector<std::string>
mem.resize(DRAM_SIZE, 0);
for (unsigned i = 0; i < NB_CORES; i++){
interfaceIn[i][0].interfaceAck = 0;
interfaceIn[i][1].interfaceAck = 0;
interfaceIn[i][0].interfaceAck = 0;
interfaceIn[i][1].interfaceAck = 0;
interfaceOut[i][0].interfaceAck = 0;
interfaceOut[i][1].interfaceAck = 0;
interfaceIn[i][0].releaseAck = 1;
interfaceIn[i][1].releaseAck = 1;
interfaceOut[i][0].releaseAck = 1;
interfaceOut[i][1].releaseAck = 1;
interfaceIn[i][0].buffer = 0;
interfaceIn[i][1].buffer = 0;
interfaceOut[i][0].buffer = 0;
interfaceOut[i][1].buffer = 0;
// Init zero
memset((char*)&core[i], 0, sizeof(Core));
initCore(core[i]);
// Init Core PC
core[i].regFile[2] = STACK_INIT;
core[i].csrUnit.mhartid = ac_int<4, false>(i);
//IncompleteMemory<4> * imInterface = new IncompleteMemory<4>(&interfaceIn[i][0], &interfaceOut[i][0]);
//IncompleteMemory<4> * dmInterface = new IncompleteMemory<4>(&interfaceIn[i][1], &interfaceOut[i][1]);
//core[i].im = imInterface;
//core[i].dm = dmInterface;
core[i].im = new CacheMemory<4, 16, 64>(new IncompleteMemory<4>(&interfaceIn[i][0], &interfaceOut[i][0]), false);
core[i].dm = new CacheMemory<4, 16, 64>(new IncompleteMemory<4>(&interfaceIn[i][1], &interfaceOut[i][1]), false);
clint.ir_timer[i] = 0;
......@@ -138,11 +155,13 @@ void BasicSimulator::printCycle()
{
if(DEBUG){
if (!core[0].stallSignals[0] && !core[0].stallIm && !core[0].stallDm) {
printf("Debug trace : %x [%x]", (unsigned int)core[0].dctoEx.pc, (unsigned int)core[0].dctoEx.we);
printf("Debug trace : %x [%x] ", (unsigned int)core[0].dctoEx.pc, (unsigned int)core[0].dctoEx.we);
std::cout << printDecodedInstrRISCV(core[0].dctoEx.instruction);
for (const auto &reg : core[0].regFile)
printf("%x ", (unsigned int)reg);
std::cout << std::endl;
} else {
//printf("Debug trace : %d %d %d\n", core[0].stallSignals[0], core[0].stallIm, core[0].stallDm);
}
}
}
......@@ -187,8 +206,7 @@ void BasicSimulator::stb(ac_int<32, false> addr, ac_int<4, false> hartid, ac_int
bool stall = true;
bool enable[1] = {true};
while (stall){
if(enable)
core[hartid].dm->cacheprocess(addr, BYTE, STORE, hartid, value, wordRes, stall);
core[hartid].dm->nextLevel->process(addr, BYTE, STORE, hartid, value, wordRes, stall);
doDirectory(this->mem, NB_CORES, enable, this->interfaceIn, this->interfaceOut);
}
}
......@@ -227,7 +245,7 @@ ac_int<8, true> BasicSimulator::ldb(ac_int<32, false> addr, ac_int<4, false> har
bool stall = true;
bool enable[1] = {true};
while (stall){
core[hartid].dm->cacheprocess(addr, BYTE_U, LOAD, 0, hartid, wordRes, stall);
core[hartid].dm->nextLevel->process(addr, BYTE_U, LOAD, 0, hartid, wordRes, stall);
doDirectory(this->mem, NB_CORES, enable, this->interfaceIn, this->interfaceOut);
}
......
......@@ -486,7 +486,7 @@ void forwardUnit(ac_int<5, false> decodeRs1, bool decodeUseRs1, ac_int<5, false>
void doCycle(struct Core& core, // Core containing all values
bool globalStall, bool ir_timer, bool ipi)
{
// printf("PC : %x\n", core.pc);
//printf("PC : %x\n", core.pc);
bool localStall = globalStall;
core.stallSignals[0] = 0;
......@@ -494,8 +494,6 @@ void doCycle(struct Core& core, // Core containing all values
core.stallSignals[2] = 0;
core.stallSignals[3] = 0;
core.stallSignals[4] = 0;
core.stallIm = false;
core.stallDm = false;
core.stallMultAlu = false;
// declare temporary structs
......@@ -560,10 +558,11 @@ void doCycle(struct Core& core, // Core containing all values
forwardRegisters.forwardWBtoVal2 = 0;
forwardRegisters.forwardWBtoVal3 = 0;
// declare temporary register fileut
ac_int<32, false> nextInst, csrResult=0, multResult=0;
// declare temporary register
static ac_int<32, false> nextInst = 0;
ac_int<32, false> csrResult=0, multResult=0;
core.im->cacheprocess(core.pc, WORD, (!localStall && !core.stallDm && !core.stallSignals[STALL_FETCH]) ? LOAD : NONE, core.csrUnit.mhartid.slc<4>(0), 0, nextInst, core.stallIm);
core.im->nextLevel->process(core.pc, WORD, (!localStall ) ? LOAD : NONE, core.csrUnit.mhartid.slc<4>(0), 0, nextInst, core.stallIm);
fetch(core.pc, ftoDC_temp, nextInst);
decode(core.ftoDC, dctoEx_temp, core.regFile);
......@@ -577,8 +576,8 @@ void doCycle(struct Core& core, // Core containing all values
bool multUsed = core.multiplicationUnit.process(core.dctoEx, multResult, core.stallMultAlu);// idempotent by construction
core.stallSignals[STALL_EXECUTE] = core.stallMultAlu;// do not transmit the result - not valid yet !
core.stallSignals[STALL_DECODE] = core.stallMultAlu;// block the propagation of future instructions
core.stallSignals[STALL_FETCH] = core.stallMultAlu;// block the propagation of future instructions
core.stallSignals[STALL_DECODE] = core.stallMultAlu;// block the propagation of future instructions
core.stallSignals[STALL_FETCH] = core.stallMultAlu;// block the propagation of future instructions
// CSR UNIT
......@@ -591,8 +590,9 @@ void doCycle(struct Core& core, // Core containing all values
if (multUsed)
extoMem_temp.result = multResult;
if (csrUsed)
if (csrUsed){
extoMem_temp.result = csrResult;
}
if (setCSRPC) {
extoMem_temp.nextPC = csrResult;
extoMem_temp.isBranch = true;
......@@ -604,7 +604,7 @@ void doCycle(struct Core& core, // Core containing all values
mstatus : most important csr -> control and track the hart's current operating state
*/
if (core.csrUnit.mip[IR_M_TIMER] && core.csrUnit.mie[IR_M_TIMER] && core.csrUnit.mstatus[MSTATUS_MIE]) {
// flushing strategy
if(!core.flushing){
core.csrUnit.mepc = extoMem_temp.isBranch ? extoMem_temp.nextPC : ( core.ftoDC.we ? core.ftoDC.pc : core.pc );
......@@ -618,12 +618,12 @@ void doCycle(struct Core& core, // Core containing all values
core.stallSignals[STALL_FETCH] = 1;
if (!(core.memtoWB.we || core.extoMem.we || core.dctoEx.we)) {
core.stallSignals[STALL_FETCH] = 0; // free branch unit to choose the right PC
core.stallSignals[STALL_FETCH] = 0; // free branch unit to choose the right PC
core.csrUnit.mstatus[MSTATUS_MPIE] = core.csrUnit.mstatus[MSTATUS_MIE];
core.csrUnit.mstatus[MSTATUS_MIE] = 0;
core.flushing = false;
core.csrUnit.mcause = 0x80000000 | IR_M_TIMER;
ftoDC_temp.nextPCFetch = core.csrUnit.mtvec;
core.csrUnit.mstatus[MSTATUS_MIE] = 0;
core.flushing = false;
core.csrUnit.mcause = 0x80000000 | IR_M_TIMER;
ftoDC_temp.nextPCFetch = core.csrUnit.mtvec;
}
}
/*
......@@ -667,7 +667,7 @@ void doCycle(struct Core& core, // Core containing all values
directoryOpType opType = (!core.stallSignals[STALL_MEMORY] && !localStall && memtoWB_temp.we && !core.stallIm && memtoWB_temp.isLoad) ? LOAD
: (!core.stallSignals[STALL_MEMORY] && !localStall && memtoWB_temp.we && !core.stallIm && memtoWB_temp.isStore ? STORE : NONE);
core.dm->cacheprocess(memtoWB_temp.address, mask, opType, core.csrUnit.mhartid.slc<4>(0), memtoWB_temp.valueToWrite, memtoWB_temp.result, core.stallDm);
core.dm->nextLevel->process(memtoWB_temp.address, mask, opType, core.csrUnit.mhartid.slc<4>(0), memtoWB_temp.valueToWrite, memtoWB_temp.result, core.stallDm);
// commit the changes to the pipeline register
if (!core.stallSignals[STALL_FETCH] && !localStall && !core.stallIm && !core.stallDm) {
......@@ -676,7 +676,7 @@ void doCycle(struct Core& core, // Core containing all values
if (!core.stallSignals[STALL_DECODE] && !localStall && !core.stallIm && !core.stallDm) {
core.dctoEx = dctoEx_temp;
if (forwardRegisters.forwardExtoVal1 && extoMem_temp.we)
core.dctoEx.lhs = extoMem_temp.result;
else if (forwardRegisters.forwardMemtoVal1 && memtoWB_temp.we)
......@@ -729,6 +729,8 @@ void doCycle(struct Core& core, // Core containing all values
if (wbOut_temp.we && !localStall && !core.stallIm && !core.stallDm){
core.csrUnit.minstret++; // the number of instructions retired : CPI
}
//printf("Temp Debug trace : %x [%x, %x, %x, %x, %x, %x, %x] ", (unsigned int)extoMem_temp.result, (unsigned int)dctoEx_temp.we, dctoEx_temp.useRs1, (unsigned int)dctoEx_temp.rs1, (unsigned int)extoMem_temp.rd, extoMem_temp.useRd, core.dctoEx.lhs, memtoWB_temp.result);
//std::cout << printDecodedInstrRISCV(dctoEx_temp.instruction) << "\n";
}
// ac_int<32, false> imData[DRAM_SIZE]
......
#include <simulator.h>
#define MEMMASK 0xffffff
void doClint(Clint &clint, std::vector< ac_int<32, false> >& mem){
......@@ -26,10 +27,10 @@ void doClint(Clint &clint, std::vector< ac_int<32, false> >& mem){
}
void doEarlyConsole(std::vector< ac_int<32, false> >& mem){
ac_int<32, false>* p_mem = mem.data();
static int time = 0;
ac_int<32, false>* p_mem = mem.data();
static int time = 0;
static bool is_time_to_print = false;
const int baudrate = 10000;// time of the early print
const int baudrate = 20000;// time of the early print
// Security Section
// BOOT Security MANAGEMENT
if(!is_time_to_print){
......@@ -61,9 +62,108 @@ void doUART(std::vector< ac_int<32, false> >& mem){
p_mem[(UART_TXFULL>>2)] = 0; // never full !
}
void memoryStoreLoad(ac_int<32, false>* data, ac_int<32, false> addr, memMask mask, directoryOpType opType,
ac_int<4 * 8, false> dataIn,
ac_int<4 * 8, false> &dataOut) {
// no latency, wait is always set to false
//if( (addr>>2) > DRAM_SIZE){exit(-1);}
ac_int<8, true> signedByte;
ac_int<16, true> signedHalf;
ac_int<32, true> signedWord;
switch (opType) {
case STORE:
switch (mask) {
case BYTE:
case BYTE_U:
data[(addr >>2) & MEMMASK].set_slc((((int)addr.slc<2>(0)) << 3),
dataIn.template slc<8>(0));
break;
case HALF:
case HALF_U:
data[(addr >>2) & MEMMASK].set_slc((addr[1] ? 16 : 0),
dataIn.template slc<16>(0));
break;
case WORD:
data[(addr >>2) & MEMMASK].set_slc(0,
dataIn.template slc<32>(0));
break;
case LONG:
data[(addr >>2) & MEMMASK].set_slc(0, dataIn);
break;
}
break;
case LOAD:
switch (mask) {
case BYTE:
signedByte = data[(addr >>2) & MEMMASK].template slc<8>(
(((int)addr.slc<2>(0)) << 3));
signedWord = signedByte;
dataOut.set_slc(0, signedWord);
break;
case HALF:
signedHalf = data[(addr >>2) & MEMMASK].template slc<16>((addr[1] ? 16 : 0));
signedWord = signedHalf;
dataOut.set_slc(0, signedWord);
break;
case WORD:
dataOut = data[(addr >>2) & MEMMASK].template slc<32>(0);
break;
case BYTE_U:
dataOut = data[(addr >>2) & MEMMASK].template slc<8>(
(((int)addr.slc<2>(0)) << 3)) & 0xff;
break;
case HALF_U:
dataOut = data[(addr >>2) & MEMMASK].template slc<16>((addr[1] ? 16 : 0)) & 0xffff;
break;
case LONG:
dataOut = data[(addr >>2) & MEMMASK].template slc<32>(0);
break;
}
}
}
void doDirectory(std::vector< ac_int<32, false> >& mem, const int nb_cores, bool enable[], cacheDirectoryInterfaceIn bufferIn[][2], cacheDirectoryInterfaceOut bufferOut[][2]) {
// Directory Architecture
ac_int<32, false>* p_mem = mem.data();
for(int i = 0; i < nb_cores; i++) { // i is the id of the core
for(int j = 0; j < 2; j++) { // 0: IM ; 1: DM
//bufferIn[i][j].interfaceAck = !bufferIn[i][j].releaseAck;
if(bufferOut[i][j].releaseAck)// releaseAck should stay for one cycle to avoid collision
bufferOut[i][j].releaseAck = 0;
if(bufferOut[i][j].interfaceAck == 1){
bufferOut[i][j].releaseAck = 0;
enable[i] = true;
if (bufferOut[i][j].interfaceRequest == STORE){ // CLINT-UART
ac_int<32, false> dataOut_temp = 0;
memoryStoreLoad(p_mem, bufferOut[i][j].addr, bufferOut[i][j].mask, bufferOut[i][j].interfaceRequest, bufferOut[i][j].buffer, dataOut_temp);
//printf("%d STORE (directory): [%x %x %x] \n", j, bufferOut[i][j].buffer, bufferOut[i][j].addr, bufferOut[i][j].mask);
bufferOut[i][j].releaseAck = 1;
} else if (bufferOut[i][j].interfaceRequest == LOAD){ // CLINT-UART