The qsim-harp library builds, built by default, not expected to work yet.
git-svn-id: http://www.cdkersey.com/harp/harptool@35 0246edb2-e076-4747-b392-db732a341fa2
This commit is contained in:
@@ -5,7 +5,7 @@ CXXFLAGS=-g -fPIC
|
|||||||
|
|
||||||
LIB_OBJS=args.o obj.o mem.o core.o instruction.o enc.o util.o lex.yy.o
|
LIB_OBJS=args.o obj.o mem.o core.o instruction.o enc.o util.o lex.yy.o
|
||||||
|
|
||||||
all: harptool libharplib.so libharplib.a
|
all: harptool libharplib.so libharplib.a qsim-harp.so
|
||||||
|
|
||||||
# Use -static so we don't have to install the library in order to just run
|
# Use -static so we don't have to install the library in order to just run
|
||||||
# Harptool.
|
# Harptool.
|
||||||
|
|||||||
24
src/core.cpp
24
src/core.cpp
@@ -11,9 +11,23 @@
|
|||||||
#include "include/enc.h"
|
#include "include/enc.h"
|
||||||
#include "include/core.h"
|
#include "include/core.h"
|
||||||
|
|
||||||
|
#ifdef EMU_INSTRUMENTATION
|
||||||
|
#include "include/qsim-harp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace Harp;
|
using namespace Harp;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
#ifdef EMU_INSTRUMENTATION
|
||||||
|
void Harp::reg_doRead(Word cpuId, Word regNum) {
|
||||||
|
Harp::OSDomain::osDomain->do_reg(cpuId, regNum, 8, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Harp::reg_doWrite(Word cpuId, Word regNum) {
|
||||||
|
Harp::OSDomain::osDomain->do_reg(cpuId, regNum, 8, false);
|
||||||
|
}
|
||||||
|
#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), pc(0), interruptEnable(false), supervisorMode(true),
|
||||||
activeThreads(1), reg(0), pred(0), shadowReg(a.getNRegs()), shadowPReg(a.getNPRegs()),
|
activeThreads(1), reg(0), pred(0), shadowReg(a.getNRegs()), shadowPReg(a.getNPRegs()),
|
||||||
@@ -66,6 +80,14 @@ void Core::step() {
|
|||||||
} while (fetchMore);
|
} while (fetchMore);
|
||||||
//cout << "0x" << hex << pc << ": " << *inst << '\n';
|
//cout << "0x" << hex << pc << ": " << *inst << '\n';
|
||||||
|
|
||||||
|
#ifdef EMU_INSTRUMENTATION
|
||||||
|
{ Addr pcPhys(mem.virtToPhys(pc));
|
||||||
|
Harp::OSDomain::osDomain->
|
||||||
|
do_inst(0, pc, pcPhys, decPos, mem.getPtr(pcPhys, decPos),
|
||||||
|
(enum inst_type)inst->instTable[inst->getOpcode()].iType);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Update pc */
|
/* Update pc */
|
||||||
pc += decPos;
|
pc += decPos;
|
||||||
|
|
||||||
@@ -91,7 +113,7 @@ bool Core::interrupt(Word r0) {
|
|||||||
if (!interruptEnable) return false;
|
if (!interruptEnable) return false;
|
||||||
|
|
||||||
#ifdef EMU_INSTRUMENTATION
|
#ifdef EMU_INSTRUMENTATION
|
||||||
#error TODO: instrument Harp::Core::interrupt()
|
Harp::OSDomain::osDomain->do_int(0, r0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
shadowActiveThreads = activeThreads;
|
shadowActiveThreads = activeThreads;
|
||||||
|
|||||||
@@ -13,6 +13,11 @@
|
|||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
|
||||||
namespace Harp {
|
namespace Harp {
|
||||||
|
#ifdef EMU_INSTRUMENTATION
|
||||||
|
void reg_doWrite(Word cpuId, Word regNum);
|
||||||
|
void reg_doRead(Word cpuId, Word regNum);
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename T> class Reg {
|
template <typename T> class Reg {
|
||||||
public:
|
public:
|
||||||
Reg(): cpuId(0), regNum(0) {}
|
Reg(): cpuId(0), regNum(0) {}
|
||||||
@@ -26,7 +31,9 @@ namespace Harp {
|
|||||||
T val;
|
T val;
|
||||||
|
|
||||||
#ifdef EMU_INSTRUMENTATION
|
#ifdef EMU_INSTRUMENTATION
|
||||||
#error TODO: instrument Harp::Reg.
|
/* Access size here is 8, representing the register size of 64-bit cores. */
|
||||||
|
void doWrite() { reg_doWrite(cpuId, regNum); }
|
||||||
|
void doRead() { reg_doRead(cpuId, regNum); }
|
||||||
#else
|
#else
|
||||||
void doWrite() {}
|
void doWrite() {}
|
||||||
void doRead() {}
|
void doRead() {}
|
||||||
@@ -40,11 +47,11 @@ namespace Harp {
|
|||||||
bool interrupt(Word r0);
|
bool interrupt(Word r0);
|
||||||
bool running() const { return activeThreads; }
|
bool running() const { return activeThreads; }
|
||||||
#ifdef EMU_INSTRUMENTATION
|
#ifdef EMU_INSTRUMENTATION
|
||||||
bool supervisorMode() const { return supervisorMode; }
|
bool getSupervisorMode() const { return supervisorMode; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ArchDef &a;
|
const ArchDef a;
|
||||||
Decoder &iDec;
|
Decoder &iDec;
|
||||||
MemoryUnit &mem;
|
MemoryUnit &mem;
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,10 @@ namespace Harp {
|
|||||||
void tlbRm(Addr va);
|
void tlbRm(Addr va);
|
||||||
void tlbFlush() { tlb.clear(); }
|
void tlbFlush() { tlb.clear(); }
|
||||||
|
|
||||||
|
#ifdef EMU_INSTRUMENTATION
|
||||||
|
Addr virtToPhys(Addr va);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ADecoder {
|
class ADecoder {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
namespace Harp {
|
namespace Harp {
|
||||||
class OSDomain {
|
class OSDomain {
|
||||||
public:
|
public:
|
||||||
OSDomain(Harp::ArchDef arch, std::string imgFile);
|
OSDomain(Harp::ArchDef &arch, std::string imgFile);
|
||||||
|
|
||||||
bool idle(unsigned i) const { return cpus[i].idle(); }
|
bool idle(unsigned i) const { return cpus[i].idle(); }
|
||||||
int get_tid(unsigned i) const { return cpus[i].get_tid(); }
|
int get_tid(unsigned i) const { return cpus[i].get_tid(); }
|
||||||
@@ -89,56 +89,60 @@ namespace Harp {
|
|||||||
template <typename T> void mem_wr(T& d, uint64_t paddr);
|
template <typename T> void mem_wr(T& d, uint64_t paddr);
|
||||||
template <typename T> void mem_wr_virt(unsigned i, T& d, uint64_t vaddr);
|
template <typename T> void mem_wr_virt(unsigned i, T& d, uint64_t vaddr);
|
||||||
|
|
||||||
private:
|
static OSDomain *osDomain;
|
||||||
|
|
||||||
bool do_atomic(unsigned c) {
|
bool do_atomic(unsigned c) {
|
||||||
bool rval(false);
|
bool rval(false);
|
||||||
for (unsigned i = 0; i < atomic_cbs.size(); ++i)
|
for (unsigned i = 0; i < atomic_cbs.size(); ++i)
|
||||||
if (atomic_cbs[i](c)) rval = true;
|
if ((*atomic_cbs[i])(c)) rval = true;
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_inst(unsigned c, uint64_t va, uint64_t pa, uint8_t l, const char *b,
|
void do_inst(unsigned c, uint64_t va, uint64_t pa, uint8_t l,
|
||||||
enum inst_type t)
|
const uint8_t *b, enum inst_type t)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < inst_cbs.size(); ++i)
|
for (unsigned i = 0; i < inst_cbs.size(); ++i)
|
||||||
inst_cbs[i](c, va, pa, l, b, t);
|
(*inst_cbs[i])(c, va, pa, l, b, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_int(unsigned c, int v) {
|
void do_int(unsigned c, int v) {
|
||||||
for (unsigned i = 0; i < int_cbs.size(); ++i)
|
for (unsigned i = 0; i < int_cbs.size(); ++i)
|
||||||
int_cbs[i](c, v);
|
(*int_cbs[i])(c, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_mem(unsigned c, uint64_t va, uint64_t pa, uint8_t s, bool w) {
|
void do_mem(unsigned c, uint64_t va, uint64_t pa, uint8_t s, bool w) {
|
||||||
for (unsigned i = 0; i < mem_cbs.size(); ++i)
|
for (unsigned i = 0; i < mem_cbs.size(); ++i)
|
||||||
mem_cbs[i](c, va, pa, s, w);
|
(*mem_cbs[i])(c, va, pa, s, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_magic(unsigned c, uint64_t r0) {
|
bool do_magic(unsigned c, uint64_t r0) {
|
||||||
bool rval(false);
|
bool rval(false);
|
||||||
for (unsigned i = 0; i < magic_cbs.size(); ++i)
|
for (unsigned i = 0; i < magic_cbs.size(); ++i)
|
||||||
if (magic_cbs[i](c, r0)) rval = true;
|
if ((*magic_cbs[i])(c, r0)) rval = true;
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_reg(unsigned c, int r, uint8_t s, bool w) {
|
void do_reg(unsigned c, int r, uint8_t s, bool w) {
|
||||||
for (unsigned i = 0; i < reg_cbs.size(); ++i)
|
for (unsigned i = 0; i < reg_cbs.size(); ++i)
|
||||||
reg_cbs[i](c, r, s, w);
|
(*reg_cbs[i])(c, r, s, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Cpu {
|
private:
|
||||||
|
class Cpu {
|
||||||
|
public:
|
||||||
Cpu(Harp::OSDomain &osd);
|
Cpu(Harp::OSDomain &osd);
|
||||||
|
~Cpu() { delete dec; delete core; }
|
||||||
|
|
||||||
bool idle() const { return false; }
|
bool idle() const { return false; }
|
||||||
int get_tid() const { return 0; }
|
int get_tid() const { return 0; }
|
||||||
bool get_prot() const { return core.supervisorMode(); }
|
bool get_prot() const { return core->getSupervisorMode(); }
|
||||||
uint64_t run(uint64_t n);
|
uint64_t run(uint64_t n);
|
||||||
void interrupt(int vec) { core.interrupt(vec); }
|
void interrupt(int vec) { core->interrupt(vec); }
|
||||||
bool booted() { return core.running(); }
|
bool booted() const { return core->running(); }
|
||||||
|
|
||||||
Harp::Decoder *dec;
|
Harp::Decoder *dec;
|
||||||
Harp::Core core;
|
Harp::Core *core;
|
||||||
Harp::OSDomain &osd;
|
Harp::OSDomain *osd;
|
||||||
};
|
};
|
||||||
|
|
||||||
Harp::ArchDef arch;
|
Harp::ArchDef arch;
|
||||||
@@ -149,12 +153,12 @@ namespace Harp {
|
|||||||
|
|
||||||
std::vector <Harp::OSDomain::Cpu> cpus;
|
std::vector <Harp::OSDomain::Cpu> cpus;
|
||||||
|
|
||||||
std::vector <Harp::OSdomain::atomic_cb_obj_base*> atomic_cbs;
|
std::vector <Qsim::OSDomain::atomic_cb_obj_base*> atomic_cbs;
|
||||||
std::vector <Harp::OSdomain::inst_cb_obj_base*> inst_cbs;
|
std::vector <Qsim::OSDomain::inst_cb_obj_base*> inst_cbs;
|
||||||
std::vector <Harp::OSdomain::int_cb_obj_base*> int_cbs;
|
std::vector <Qsim::OSDomain::int_cb_obj_base*> int_cbs;
|
||||||
std::vector <Harp::OSdomain::mem_cb_obj_base*> mem_cbs;
|
std::vector <Qsim::OSDomain::mem_cb_obj_base*> mem_cbs;
|
||||||
std::vector <Harp::OSdomain::magic_cb_obj_base*> magic_cbs;
|
std::vector <Qsim::OSDomain::magic_cb_obj_base*> magic_cbs;
|
||||||
std::vector <Harp::OSdomain::reg_cb_obj_base*> reg_cbs;
|
std::vector <Qsim::OSDomain::reg_cb_obj_base*> reg_cbs;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
#include "include/core.h"
|
#include "include/core.h"
|
||||||
#include "include/harpfloat.h"
|
#include "include/harpfloat.h"
|
||||||
|
|
||||||
|
#ifdef EMU_INSTRUMENTATION
|
||||||
|
#include "include/qsim-harp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace Harp;
|
using namespace Harp;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -102,10 +106,6 @@ ostream &Harp::operator<<(ostream& os, Instruction &inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Instruction::executeOn(Core &c) {
|
void Instruction::executeOn(Core &c) {
|
||||||
#ifdef EMU_INSTRUMENTATION
|
|
||||||
#error TODO: instrument Harp::Instruction::executeOn()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 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
|
||||||
exception 3. */
|
exception 3. */
|
||||||
if (instTable[op].privileged && !c.supervisorMode) {
|
if (instTable[op].privileged && !c.supervisorMode) {
|
||||||
@@ -195,14 +195,16 @@ void Instruction::executeOn(Core &c) {
|
|||||||
break;
|
break;
|
||||||
case LD: memAddr = reg[rsrc[0]] + immsrc;
|
case LD: memAddr = reg[rsrc[0]] + immsrc;
|
||||||
#ifdef EMU_INSTRUMENTATION
|
#ifdef EMU_INSTRUMENTATION
|
||||||
#error TODO: Instrument memory reads.
|
Harp::OSDomain::osDomain->
|
||||||
|
do_mem(0, memAddr, c.mem.virtToPhys(memAddr), 8, true);
|
||||||
#endif
|
#endif
|
||||||
reg[rdest] = c.mem.read(memAddr, c.supervisorMode);
|
reg[rdest] = c.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.mem.write(memAddr, reg[rsrc[0]], c.supervisorMode);
|
||||||
#ifdef EMU_INSTRUMENTATION
|
#ifdef EMU_INSTRUMENTATION
|
||||||
#error TODO: Instrument memory writes.
|
Harp::OSDomain::osDomain->
|
||||||
|
do_mem(0, memAddr, c.mem.virtToPhys(memAddr), 8, true);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case LDI: reg[rdest] = immsrc;
|
case LDI: reg[rdest] = immsrc;
|
||||||
|
|||||||
@@ -109,6 +109,13 @@ MemoryUnit::TLBEntry MemoryUnit::tlbLookup(Addr vAddr, Word flagMask) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EMU_INSTRUMENTATION
|
||||||
|
Addr MemoryUnit::virtToPhys(Addr vAddr) {
|
||||||
|
TLBEntry t = tlbLookup(vAddr, 077);
|
||||||
|
return t.pfn*pageSize + vAddr%pageSize;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Word MemoryUnit::read(Addr vAddr, bool sup) {
|
Word MemoryUnit::read(Addr vAddr, bool sup) {
|
||||||
Word flagMask = sup?8:1;
|
Word flagMask = sup?8:1;
|
||||||
TLBEntry t = tlbLookup(vAddr, flagMask);
|
TLBEntry t = tlbLookup(vAddr, flagMask);
|
||||||
|
|||||||
@@ -9,12 +9,23 @@
|
|||||||
using namespace Harp;
|
using namespace Harp;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Harp::OSDomain::OSDomain(ArchDef arch, string imgFile) :
|
Harp::OSDomain* Harp::OSDomain::osDomain(NULL);
|
||||||
mu(4096, arch.getWordSize()), ram(imgFile.c_str(), arch.getWordSize()),
|
|
||||||
|
Harp::OSDomain::OSDomain(ArchDef &arch, string imgFile) :
|
||||||
|
/* TODO: Move the mu to the Cpu. They're sharing a TLB now! */
|
||||||
|
arch(arch), mu(4096, arch.getWordSize()),
|
||||||
|
ram(imgFile.c_str(), arch.getWordSize()),
|
||||||
|
cpus()
|
||||||
{
|
{
|
||||||
|
if (osDomain != NULL) {
|
||||||
|
cout << "Error: OSDomain is a singleton.";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
osDomain = this;
|
||||||
|
|
||||||
cpus.push_back(Cpu(*this));
|
cpus.push_back(Cpu(*this));
|
||||||
|
|
||||||
console = new ConsoleMemDevice(arch.getWordSize(), cout, cpus[0].core);
|
console = new ConsoleMemDevice(arch.getWordSize(), cout, *cpus[0].core);
|
||||||
|
|
||||||
mu.attach(ram, 0);
|
mu.attach(ram, 0);
|
||||||
mu.attach(*console, 1ll<<(arch.getWordSize()*8 - 1));
|
mu.attach(*console, 1ll<<(arch.getWordSize()*8 - 1));
|
||||||
@@ -24,13 +35,15 @@ void Harp::OSDomain::connect_console(std::ostream &s) {
|
|||||||
/* For now this does nothing. ConsoleMemDevice is not redirectable. */
|
/* For now this does nothing. ConsoleMemDevice is not redirectable. */
|
||||||
}
|
}
|
||||||
|
|
||||||
Harp::OSDomain::Cpu::Cpu(Harp::OSDomain &osd) :
|
Harp::OSDomain::Cpu::Cpu(Harp::OSDomain &o) :
|
||||||
osd(osd), dec(new WordDecoder(osd.arch)), core(osd.arch, *dec, osd.mu)
|
/* TODO: This should support non-word decoders! */
|
||||||
|
osd(&o), dec(new WordDecoder(osd->arch)),
|
||||||
|
core(new Core(osd->arch, *dec, osd->mu))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Harp::OSDomain::Cpu::run(uint64_t n) {
|
uint64_t Harp::OSDomain::Cpu::run(uint64_t n) {
|
||||||
uint64_t i;
|
uint64_t i;
|
||||||
for (i = 0; i < n; ++i) core.step();
|
for (i = 0; i < n; ++i) core->step();
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user