Separated warp and core in preparation for wspawn support.
This commit is contained in:
54
src/core.cpp
54
src/core.cpp
@@ -29,21 +29,45 @@ void Harp::reg_doWrite(Word cpuId, Word regNum) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Core::Core(const ArchDef &a, Decoder &d, MemoryUnit &mem, Word id) :
|
Core::Core(const ArchDef &a, Decoder &d, MemoryUnit &mem, Word id):
|
||||||
a(a), iDec(d), mem(mem), pc(0), interruptEnable(false), supervisorMode(true),
|
a(a), iDec(d), mem(mem)
|
||||||
activeThreads(1), reg(0), pred(0), shadowReg(a.getNRegs()),
|
{
|
||||||
shadowPReg(a.getNPRegs()), interruptEntry(0), id(id)
|
w.push_back(Warp(this));
|
||||||
|
|
||||||
|
// TODO: core-level initialization
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Core::interrupt(Word r0) {
|
||||||
|
w[0].interrupt(r0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::step() {
|
||||||
|
for (unsigned i = 0; i < w.size(); ++i)
|
||||||
|
w[i].step();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Core::running() const {
|
||||||
|
for (unsigned i = 0; i < w.size(); ++i)
|
||||||
|
if (!w[i].running()) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Warp::Warp(Core *c, Word id) :
|
||||||
|
core(c), pc(0), interruptEnable(false),
|
||||||
|
supervisorMode(true), activeThreads(1), reg(0), pred(0),
|
||||||
|
shadowReg(core->a.getNRegs()), shadowPReg(core->a.getNPRegs()),
|
||||||
|
interruptEntry(0), id(id)
|
||||||
{
|
{
|
||||||
/* Build the register file. */
|
/* Build the register file. */
|
||||||
Word regNum(0);
|
Word regNum(0);
|
||||||
for (Word j = 0; j < a.getNThds(); ++j) {
|
for (Word j = 0; j < core->a.getNThds(); ++j) {
|
||||||
reg.push_back(vector<Reg<Word> >(0));
|
reg.push_back(vector<Reg<Word> >(0));
|
||||||
for (Word i = 0; i < a.getNRegs(); ++i) {
|
for (Word i = 0; i < core->a.getNRegs(); ++i) {
|
||||||
reg[j].push_back(Reg<Word>(id, regNum++));
|
reg[j].push_back(Reg<Word>(id, regNum++));
|
||||||
}
|
}
|
||||||
|
|
||||||
pred.push_back(vector<Reg<bool> >(0));
|
pred.push_back(vector<Reg<bool> >(0));
|
||||||
for (Word i = 0; i < a.getNPRegs(); ++i) {
|
for (Word i = 0; i < core->a.getNPRegs(); ++i) {
|
||||||
pred[j].push_back(Reg<bool>(id, regNum++));
|
pred[j].push_back(Reg<bool>(id, regNum++));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,11 +76,11 @@ Core::Core(const ArchDef &a, Decoder &d, MemoryUnit &mem, Word id) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set initial register contents. */
|
/* Set initial register contents. */
|
||||||
reg[0][0] = (a.getNThds()<<(a.getWordSize()*8 / 2)) | id;
|
reg[0][0] = (core->a.getNThds()<<(core->a.getWordSize()*8 / 2)) | id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::step() {
|
void Warp::step() {
|
||||||
Size fetchPos(0), decPos, wordSize(a.getWordSize());
|
Size fetchPos(0), decPos, wordSize(core->a.getWordSize());
|
||||||
vector<Byte> fetchBuffer(wordSize);
|
vector<Byte> fetchBuffer(wordSize);
|
||||||
|
|
||||||
if (activeThreads == 0) return;
|
if (activeThreads == 0) return;
|
||||||
@@ -73,10 +97,10 @@ void Core::step() {
|
|||||||
fetchMore = false;
|
fetchMore = false;
|
||||||
unsigned fetchSize(wordSize - (pc+fetchPos)%wordSize);
|
unsigned fetchSize(wordSize - (pc+fetchPos)%wordSize);
|
||||||
fetchBuffer.resize(fetchPos + fetchSize);
|
fetchBuffer.resize(fetchPos + fetchSize);
|
||||||
Word fetched = mem.fetch(pc + fetchPos, supervisorMode);
|
Word fetched = core->mem.fetch(pc + fetchPos, supervisorMode);
|
||||||
writeWord(fetchBuffer, fetchPos, fetchSize, fetched);
|
writeWord(fetchBuffer, fetchPos, fetchSize, fetched);
|
||||||
decPos = 0;
|
decPos = 0;
|
||||||
inst = iDec.decode(fetchBuffer, decPos);
|
inst = core->iDec.decode(fetchBuffer, decPos);
|
||||||
} catch (OutOfBytes o) {
|
} catch (OutOfBytes o) {
|
||||||
D(3, "Caught OutOfBytes. Fetching more.");
|
D(3, "Caught OutOfBytes. Fetching more.");
|
||||||
fetchMore = true;
|
fetchMore = true;
|
||||||
@@ -91,9 +115,9 @@ void Core::step() {
|
|||||||
D(3, "0x" << hex << pc << ": " << *inst);
|
D(3, "0x" << hex << pc << ": " << *inst);
|
||||||
|
|
||||||
#ifdef EMU_INSTRUMENTATION
|
#ifdef EMU_INSTRUMENTATION
|
||||||
{ Addr pcPhys(mem.virtToPhys(pc));
|
{ Addr pcPhys(core->mem.virtToPhys(pc));
|
||||||
Harp::OSDomain::osDomain->
|
Harp::OSDomain::osDomain->
|
||||||
do_inst(0, pc, pcPhys, decPos, mem.getPtr(pcPhys, decPos),
|
do_inst(0, pc, pcPhys, decPos, core->mem.getPtr(pcPhys, decPos),
|
||||||
(enum inst_type)inst->instTable[inst->getOpcode()].iType);
|
(enum inst_type)inst->instTable[inst->getOpcode()].iType);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -146,7 +170,7 @@ void Core::step() {
|
|||||||
delete inst;
|
delete inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::interrupt(Word r0) {
|
bool Warp::interrupt(Word r0) {
|
||||||
if (!interruptEnable) return false;
|
if (!interruptEnable) return false;
|
||||||
|
|
||||||
#ifdef EMU_INSTRUMENTATION
|
#ifdef EMU_INSTRUMENTATION
|
||||||
|
|||||||
@@ -67,9 +67,27 @@ namespace Harp {
|
|||||||
Word pc;
|
Word pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Warp;
|
||||||
|
|
||||||
class Core {
|
class Core {
|
||||||
public:
|
public:
|
||||||
Core(const ArchDef &a, Decoder &d, MemoryUnit &mem, Word id=0);
|
Core(const ArchDef &a, Decoder &d, MemoryUnit &mem, Word id=0);
|
||||||
|
|
||||||
|
bool interrupt(Word r0);
|
||||||
|
bool running() const;
|
||||||
|
void step();
|
||||||
|
|
||||||
|
const ArchDef &a;
|
||||||
|
Decoder &iDec;
|
||||||
|
MemoryUnit &mem;
|
||||||
|
|
||||||
|
std::vector<Warp> w;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Warp {
|
||||||
|
public:
|
||||||
|
Warp(Core *c, Word id=0);
|
||||||
|
|
||||||
void step();
|
void step();
|
||||||
bool interrupt(Word r0);
|
bool interrupt(Word r0);
|
||||||
bool running() const { return activeThreads; }
|
bool running() const { return activeThreads; }
|
||||||
@@ -78,9 +96,7 @@ namespace Harp {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// private:
|
// private:
|
||||||
const ArchDef a;
|
Core *core;
|
||||||
Decoder &iDec;
|
|
||||||
MemoryUnit &mem;
|
|
||||||
|
|
||||||
Word pc, interruptEntry, shadowPc, id;
|
Word pc, interruptEntry, shadowPc, id;
|
||||||
Size activeThreads, shadowActiveThreads;
|
Size activeThreads, shadowActiveThreads;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
namespace Harp {
|
namespace Harp {
|
||||||
class Core;
|
class Warp;
|
||||||
class Ref;
|
class Ref;
|
||||||
|
|
||||||
static const Size MAX_REG_SOURCES(3);
|
static const Size MAX_REG_SOURCES(3);
|
||||||
@@ -53,7 +53,7 @@ namespace Harp {
|
|||||||
predicated(false), nRsrc(0), nPsrc(0), immsrcPresent(false),
|
predicated(false), nRsrc(0), nPsrc(0), immsrcPresent(false),
|
||||||
rdestPresent(false), pdestPresent(false), refLiteral(NULL) {}
|
rdestPresent(false), pdestPresent(false), refLiteral(NULL) {}
|
||||||
|
|
||||||
void executeOn(Core &core);
|
void executeOn(Warp &warp);
|
||||||
friend std::ostream &operator<<(std::ostream &, Instruction &);
|
friend std::ostream &operator<<(std::ostream &, Instruction &);
|
||||||
|
|
||||||
/* Setters used to "craft" the instruction. */
|
/* Setters used to "craft" the instruction. */
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ ostream &Harp::operator<<(ostream& os, Instruction &inst) {
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instruction::executeOn(Core &c) {
|
void Instruction::executeOn(Warp &c) {
|
||||||
D(3, "Begin instruction execute.");
|
D(3, "Begin instruction execute.");
|
||||||
|
|
||||||
/* If I try to execute a privileged instruction in user mode, throw an
|
/* If I try to execute a privileged instruction in user mode, throw an
|
||||||
@@ -135,7 +135,7 @@ void Instruction::executeOn(Core &c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Size nextActiveThreads = c.activeThreads;
|
Size nextActiveThreads = c.activeThreads;
|
||||||
Size wordSz = c.a.getWordSize();
|
Size wordSz = c.core->a.getWordSize();
|
||||||
Word nextPc = c.pc;
|
Word nextPc = c.pc;
|
||||||
|
|
||||||
bool sjOnce(true), // Has not yet split or joined once.
|
bool sjOnce(true), // Has not yet split or joined once.
|
||||||
@@ -157,9 +157,9 @@ void Instruction::executeOn(Core &c) {
|
|||||||
break;
|
break;
|
||||||
case EI: c.interruptEnable = true;
|
case EI: c.interruptEnable = true;
|
||||||
break;
|
break;
|
||||||
case TLBADD: c.mem.tlbAdd(reg[rsrc[0]], reg[rsrc[1]], reg[rsrc[2]]);
|
case TLBADD: c.core->mem.tlbAdd(reg[rsrc[0]], reg[rsrc[1]], reg[rsrc[2]]);
|
||||||
break;
|
break;
|
||||||
case TLBFLUSH: c.mem.tlbFlush();
|
case TLBFLUSH: c.core->mem.tlbFlush();
|
||||||
break;
|
break;
|
||||||
case ADD: reg[rdest] = reg[rsrc[0]] + reg[rsrc[1]];
|
case ADD: reg[rdest] = reg[rsrc[0]] + reg[rsrc[1]];
|
||||||
reg[rdest].trunc(wordSz);
|
reg[rdest].trunc(wordSz);
|
||||||
@@ -253,15 +253,15 @@ void Instruction::executeOn(Core &c) {
|
|||||||
case LD: memAddr = reg[rsrc[0]] + immsrc;
|
case LD: memAddr = reg[rsrc[0]] + immsrc;
|
||||||
#ifdef EMU_INSTRUMENTATION
|
#ifdef EMU_INSTRUMENTATION
|
||||||
Harp::OSDomain::osDomain->
|
Harp::OSDomain::osDomain->
|
||||||
do_mem(0, memAddr, c.mem.virtToPhys(memAddr), 8, true);
|
do_mem(0, memAddr, c.core->mem.virtToPhys(memAddr), 8, true);
|
||||||
#endif
|
#endif
|
||||||
reg[rdest] = c.mem.read(memAddr, c.supervisorMode);
|
reg[rdest] = c.core->mem.read(memAddr, c.supervisorMode);
|
||||||
break;
|
break;
|
||||||
case ST: memAddr = reg[rsrc[1]] + immsrc;
|
case ST: memAddr = reg[rsrc[1]] + immsrc;
|
||||||
c.mem.write(memAddr, reg[rsrc[0]], c.supervisorMode);
|
c.core->mem.write(memAddr, reg[rsrc[0]], c.supervisorMode);
|
||||||
#ifdef EMU_INSTRUMENTATION
|
#ifdef EMU_INSTRUMENTATION
|
||||||
Harp::OSDomain::osDomain->
|
Harp::OSDomain::osDomain->
|
||||||
do_mem(0, memAddr, c.mem.virtToPhys(memAddr), 8, true);
|
do_mem(0, memAddr, c.core->mem.virtToPhys(memAddr), 8, true);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case LDI: reg[rdest] = immsrc;
|
case LDI: reg[rdest] = immsrc;
|
||||||
|
|||||||
Reference in New Issue
Block a user