diff --git a/src/include/core.h b/src/include/core.h index 5045f571..ca6f3cc0 100644 --- a/src/include/core.h +++ b/src/include/core.h @@ -39,6 +39,9 @@ namespace Harp { void step(); bool interrupt(Word r0); bool running() const { return activeThreads; } +#ifdef EMU_INSTRUMENTATION + bool supervisorMode() const { return supervisorMode; } +#endif private: const ArchDef &a; diff --git a/src/include/qsim-harp.h b/src/include/qsim-harp.h new file mode 100644 index 00000000..d583b979 --- /dev/null +++ b/src/include/qsim-harp.h @@ -0,0 +1,160 @@ +/******************************************************************************* + HARPtools by Chad D. Kersey, Summer 2011 +*******************************************************************************/ +#ifndef __QSIM_HARP_H +#define __QSIM_HARP_H + +#include "types.h" +#include "core.h" +#include "enc.h" +#include "instruction.h" +#include "mem.h" +#include "obj.h" +#include "archdef.h" + +#include +#include +#include +#include + +#include + +namespace Harp { + class OSDomain { + public: + 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(); } + bool get_prot(unsigned i) const { return cpus[i].get_prot(); } + + int get_n() const { return cpus.size(); } + + uint64_t run(unsigned i, uint64_t n) { return cpus[i].run(n); } + void connect_console(std::ostream &s); + void timer_interrupt() { /* TODO: timer convention */ } + void interrupt(unsigned i, int vec) { cpus[i].interrupt(vec); } + bool booted(unsigned i) const { return cpus[i].booted(); } + void save_state(const char* state_file); + + template + void set_atomic_cb + (T *p, typename Qsim::OSDomain::atomic_cb_obj::atomic_cb_t f) + { + atomic_cbs.push_back(new Qsim::OSDomain::atomic_cb_obj(p, f)); + } + + template + void set_inst_cb + (T* p, typename Qsim::OSDomain::inst_cb_obj::inst_cb_t f) + { + inst_cbs.push_back(new Qsim::OSDomain::inst_cb_obj(p, f)); + } + + template + void set_int_cb + (T *p, typename Qsim::OSDomain::int_cb_obj::int_cb_t f) + { + int_cbs.push_back(new Qsim::OSDomain::int_cb_obj(p, f)); + } + + template + void set_mem_cb + (T *p, typename Qsim::OSDomain::mem_cb_obj::mem_cb_t f) + { + mem_cbs.push_back(new Qsim::OSDomain::mem_cb_obj(p, f)); + } + + template + void set_magic_cb + (T *p, typename Qsim::OSDomain::magic_cb_obj::magic_cb_t f) + { + magic_cbs.push_back(new Qsim::OSDomain::magic_cb_obj(p, f)); + } + + template + void set_io_cb + (T *p, typename Qsim::OSDomain::io_cb_obj::io_cb_t f) + { /* Do nothing. We have no separate IO address space. */ } + + template + void set_reg_cb + (T *p, typename Qsim::OSDomain::reg_cb_obj::reg_cb_t f) + { + reg_cbs.push_back(new Qsim::OSDomain::reg_cb_obj(p, f)); + } + + template void mem_rd(T& d, uint64_t paddr); + template void mem_rd_virt(unsigned i, T& d, uint64_t vaddr); + template void mem_wr(T& d, uint64_t paddr); + template void mem_wr_virt(unsigned i, T& d, uint64_t vaddr); + + private: + bool do_atomic(unsigned c) { + bool rval(false); + for (unsigned i = 0; i < atomic_cbs.size(); ++i) + 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) + { + for (unsigned i = 0; i < inst_cbs.size(); ++i) + 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); + } + + 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); + } + + void 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; + 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); + } + + struct Cpu { + Cpu(Harp::OSDomain &osd); + + bool idle() const { return false; } + int get_tid() const { return 0; } + bool get_prot() const { return core.supervisorMode(); } + uint64_t run(uint64_t n); + void interrupt(int vec) { core.interrupt(vec); } + bool booted() { return core.running(); } + + Harp::Decoder *dec; + Harp::Core core; + Harp::OSDomain &osd; + }; + + Harp::ArchDef arch; + + Harp::MemoryUnit mu; + Harp::RamMemDevice ram; + Harp::ConsoleMemDevice *console; + + 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; + }; +}; +#endif diff --git a/src/instruction.cpp b/src/instruction.cpp index feb94427..e7ae05d8 100644 --- a/src/instruction.cpp +++ b/src/instruction.cpp @@ -194,10 +194,16 @@ void Instruction::executeOn(Core &c) { c.pc = reg[rsrc[0]]; break; case LD: memAddr = reg[rsrc[0]] + immsrc; +#ifdef EMU_INSTRUMENTATION +#error TODO: Instrument memory reads. +#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. +#endif break; case LDI: reg[rdest] = immsrc; break; diff --git a/src/mem.cpp b/src/mem.cpp index e8ca50bd..ec44282a 100644 --- a/src/mem.cpp +++ b/src/mem.cpp @@ -110,9 +110,6 @@ MemoryUnit::TLBEntry MemoryUnit::tlbLookup(Addr vAddr, Word flagMask) { } Word MemoryUnit::read(Addr vAddr, bool sup) { -#ifdef EMU_INSTRUMENTATION -#error TODO: instrument Harp::MemoryUnit::read() -#endif Word flagMask = sup?8:1; TLBEntry t = tlbLookup(vAddr, flagMask); Addr pAddr = t.pfn*pageSize + vAddr%pageSize; @@ -120,9 +117,6 @@ Word MemoryUnit::read(Addr vAddr, bool sup) { } Word MemoryUnit::fetch(Addr vAddr, bool sup) { -#ifdef EMU_INSTRUMENTATION -#error TODO: instrument Harp::MemoryUnit::fetch() -#endif Word flagMask = sup?32:4; TLBEntry t = tlbLookup(vAddr, flagMask); Addr pAddr = t.pfn*pageSize + vAddr%pageSize; @@ -130,9 +124,6 @@ Word MemoryUnit::fetch(Addr vAddr, bool sup) { } void MemoryUnit::write(Addr vAddr, Word w, bool sup) { -#ifdef EMU_INSTRUMENTATION -#error TODO: instrument Harp::MemoryUnit::write() -#endif Word flagMask = sup?16:2; TLBEntry t = tlbLookup(vAddr, flagMask); Addr pAddr = t.pfn*pageSize + vAddr%pageSize; diff --git a/src/qsim-harp.cpp b/src/qsim-harp.cpp new file mode 100644 index 00000000..d17db418 --- /dev/null +++ b/src/qsim-harp.cpp @@ -0,0 +1,36 @@ +/******************************************************************************* + HARPtools by Chad D. Kersey, Summer 2011 +*******************************************************************************/ +#include "include/qsim-harp.h" + +#include +#include + +using namespace Harp; +using namespace std; + +Harp::OSDomain::OSDomain(ArchDef arch, string imgFile) : + mu(4096, arch.getWordSize()), ram(imgFile.c_str(), arch.getWordSize()), +{ + cpus.push_back(Cpu(*this)); + + console = new ConsoleMemDevice(arch.getWordSize(), cout, cpus[0].core); + + mu.attach(ram, 0); + mu.attach(*console, 1ll<<(arch.getWordSize()*8 - 1)); +} + +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) +{ +} + +uint64_t Harp::OSDomain::Cpu::run(uint64_t n) { + uint64_t i; + for (i = 0; i < n; ++i) core.step(); + return i; +}