/******************************************************************************* HARPtools by Chad D. Kersey, Summer 2011 *******************************************************************************/ #ifndef EMU_INSTRUMENTATION #define EMU_INSTRUMENTATION #endif #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); 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; return rval; } 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); } 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); } 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; 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); } private: class Cpu { public: Cpu(Harp::OSDomain &osd); Cpu(): dec(NULL), core(NULL) {} ~Cpu() { if (dec) delete dec; if (core) delete core; } bool idle() const { return false; } int get_tid() const { return 0; } bool get_prot() const { return core->getSupervisorMode(); } uint64_t run(uint64_t n); void interrupt(int vec) { core->interrupt(vec); } bool booted() const { return core->running(); } Harp::OSDomain *osd; Harp::Decoder *dec; Harp::Core *core; }; 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