diff --git a/src/Makefile b/src/Makefile index 8425760e..ca097840 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 -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 # Harptool. diff --git a/src/core.cpp b/src/core.cpp index be9e591f..dd414556 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -11,9 +11,23 @@ #include "include/enc.h" #include "include/core.h" +#ifdef EMU_INSTRUMENTATION +#include "include/qsim-harp.h" +#endif + using namespace Harp; 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) : a(a), iDec(d), mem(mem), pc(0), interruptEnable(false), supervisorMode(true), activeThreads(1), reg(0), pred(0), shadowReg(a.getNRegs()), shadowPReg(a.getNPRegs()), @@ -66,6 +80,14 @@ void Core::step() { } while (fetchMore); //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 */ pc += decPos; @@ -91,7 +113,7 @@ bool Core::interrupt(Word r0) { if (!interruptEnable) return false; #ifdef EMU_INSTRUMENTATION -#error TODO: instrument Harp::Core::interrupt() + Harp::OSDomain::osDomain->do_int(0, r0); #endif shadowActiveThreads = activeThreads; diff --git a/src/include/core.h b/src/include/core.h index ca6f3cc0..c4d26ff8 100644 --- a/src/include/core.h +++ b/src/include/core.h @@ -13,6 +13,11 @@ #include "mem.h" namespace Harp { +#ifdef EMU_INSTRUMENTATION + void reg_doWrite(Word cpuId, Word regNum); + void reg_doRead(Word cpuId, Word regNum); +#endif + template class Reg { public: Reg(): cpuId(0), regNum(0) {} @@ -26,7 +31,9 @@ namespace Harp { T val; #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 void doWrite() {} void doRead() {} @@ -40,11 +47,11 @@ namespace Harp { bool interrupt(Word r0); bool running() const { return activeThreads; } #ifdef EMU_INSTRUMENTATION - bool supervisorMode() const { return supervisorMode; } + bool getSupervisorMode() const { return supervisorMode; } #endif private: - const ArchDef &a; + const ArchDef a; Decoder &iDec; MemoryUnit &mem; diff --git a/src/include/mem.h b/src/include/mem.h index 4306a180..34a2733b 100644 --- a/src/include/mem.h +++ b/src/include/mem.h @@ -127,6 +127,10 @@ namespace Harp { void tlbRm(Addr va); void tlbFlush() { tlb.clear(); } +#ifdef EMU_INSTRUMENTATION + Addr virtToPhys(Addr va); +#endif + private: class ADecoder { public: diff --git a/src/include/qsim-harp.h b/src/include/qsim-harp.h index d583b979..02c79b7a 100644 --- a/src/include/qsim-harp.h +++ b/src/include/qsim-harp.h @@ -22,7 +22,7 @@ namespace Harp { class OSDomain { public: - OSDomain(Harp::ArchDef arch, std::string imgFile); + OSDomain(Harp::ArchDef &arch, std::string imgFile); bool idle(unsigned i) const { return cpus[i].idle(); } int get_tid(unsigned i) const { return cpus[i].get_tid(); } @@ -89,56 +89,60 @@ namespace Harp { template void mem_wr(T& d, uint64_t paddr); template void mem_wr_virt(unsigned i, T& d, uint64_t vaddr); - private: + static OSDomain *osDomain; + bool do_atomic(unsigned c) { bool rval(false); 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; } - void do_inst(unsigned c, uint64_t va, uint64_t pa, uint8_t l, const char *b, - enum inst_type t) + void do_inst(unsigned c, uint64_t va, uint64_t pa, uint8_t l, + const uint8_t *b, enum inst_type t) { 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) { 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) { 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); 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; } void do_reg(unsigned c, int r, uint8_t s, bool w) { 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() { delete dec; delete core; } bool idle() const { return false; } 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); - void interrupt(int vec) { core.interrupt(vec); } - bool booted() { return core.running(); } + void interrupt(int vec) { core->interrupt(vec); } + bool booted() const { return core->running(); } Harp::Decoder *dec; - Harp::Core core; - Harp::OSDomain &osd; + Harp::Core *core; + Harp::OSDomain *osd; }; Harp::ArchDef arch; @@ -149,12 +153,12 @@ namespace Harp { std::vector cpus; - std::vector atomic_cbs; - std::vector inst_cbs; - std::vector int_cbs; - std::vector mem_cbs; - std::vector magic_cbs; - std::vector reg_cbs; + std::vector atomic_cbs; + std::vector inst_cbs; + std::vector int_cbs; + std::vector mem_cbs; + std::vector magic_cbs; + std::vector reg_cbs; }; }; #endif diff --git a/src/instruction.cpp b/src/instruction.cpp index e7ae05d8..092baf84 100644 --- a/src/instruction.cpp +++ b/src/instruction.cpp @@ -9,6 +9,10 @@ #include "include/core.h" #include "include/harpfloat.h" +#ifdef EMU_INSTRUMENTATION +#include "include/qsim-harp.h" +#endif + using namespace Harp; using namespace std; @@ -102,10 +106,6 @@ ostream &Harp::operator<<(ostream& os, Instruction &inst) { } 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 exception 3. */ if (instTable[op].privileged && !c.supervisorMode) { @@ -195,14 +195,16 @@ void Instruction::executeOn(Core &c) { break; case LD: memAddr = reg[rsrc[0]] + immsrc; #ifdef EMU_INSTRUMENTATION -#error TODO: Instrument memory reads. + Harp::OSDomain::osDomain-> + do_mem(0, memAddr, c.mem.virtToPhys(memAddr), 8, true); #endif reg[rdest] = c.mem.read(memAddr, c.supervisorMode); break; case ST: memAddr = reg[rsrc[1]] + immsrc; c.mem.write(memAddr, reg[rsrc[0]], c.supervisorMode); #ifdef EMU_INSTRUMENTATION -#error TODO: Instrument memory writes. + Harp::OSDomain::osDomain-> + do_mem(0, memAddr, c.mem.virtToPhys(memAddr), 8, true); #endif break; case LDI: reg[rdest] = immsrc; diff --git a/src/mem.cpp b/src/mem.cpp index ec44282a..68885683 100644 --- a/src/mem.cpp +++ b/src/mem.cpp @@ -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 flagMask = sup?8:1; TLBEntry t = tlbLookup(vAddr, flagMask); diff --git a/src/qsim-harp.cpp b/src/qsim-harp.cpp index d17db418..9b11a383 100644 --- a/src/qsim-harp.cpp +++ b/src/qsim-harp.cpp @@ -9,12 +9,23 @@ using namespace Harp; using namespace std; -Harp::OSDomain::OSDomain(ArchDef arch, string imgFile) : - mu(4096, arch.getWordSize()), ram(imgFile.c_str(), arch.getWordSize()), +Harp::OSDomain* Harp::OSDomain::osDomain(NULL); + +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)); - console = new ConsoleMemDevice(arch.getWordSize(), cout, cpus[0].core); + console = new ConsoleMemDevice(arch.getWordSize(), cout, *cpus[0].core); mu.attach(ram, 0); 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. */ } -Harp::OSDomain::Cpu::Cpu(Harp::OSDomain &osd) : - osd(osd), dec(new WordDecoder(osd.arch)), core(osd.arch, *dec, osd.mu) +Harp::OSDomain::Cpu::Cpu(Harp::OSDomain &o) : + /* 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 i; - for (i = 0; i < n; ++i) core.step(); + for (i = 0; i < n; ++i) core->step(); return i; }