Some (untested) code for a QSim interface.
git-svn-id: http://www.cdkersey.com/harp/harptool@33 0246edb2-e076-4747-b392-db732a341fa2
This commit is contained in:
@@ -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;
|
||||
|
||||
160
src/include/qsim-harp.h
Normal file
160
src/include/qsim-harp.h
Normal file
@@ -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 <stdint.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <qsim.h>
|
||||
|
||||
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 <typename T>
|
||||
void set_atomic_cb
|
||||
(T *p, typename Qsim::OSDomain::atomic_cb_obj<T>::atomic_cb_t f)
|
||||
{
|
||||
atomic_cbs.push_back(new Qsim::OSDomain::atomic_cb_obj<T>(p, f));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void set_inst_cb
|
||||
(T* p, typename Qsim::OSDomain::inst_cb_obj<T>::inst_cb_t f)
|
||||
{
|
||||
inst_cbs.push_back(new Qsim::OSDomain::inst_cb_obj<T>(p, f));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void set_int_cb
|
||||
(T *p, typename Qsim::OSDomain::int_cb_obj<T>::int_cb_t f)
|
||||
{
|
||||
int_cbs.push_back(new Qsim::OSDomain::int_cb_obj<T>(p, f));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void set_mem_cb
|
||||
(T *p, typename Qsim::OSDomain::mem_cb_obj<T>::mem_cb_t f)
|
||||
{
|
||||
mem_cbs.push_back(new Qsim::OSDomain::mem_cb_obj<T>(p, f));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void set_magic_cb
|
||||
(T *p, typename Qsim::OSDomain::magic_cb_obj<T>::magic_cb_t f)
|
||||
{
|
||||
magic_cbs.push_back(new Qsim::OSDomain::magic_cb_obj<T>(p, f));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void set_io_cb
|
||||
(T *p, typename Qsim::OSDomain::io_cb_obj<T>::io_cb_t f)
|
||||
{ /* Do nothing. We have no separate IO address space. */ }
|
||||
|
||||
template <typename T>
|
||||
void set_reg_cb
|
||||
(T *p, typename Qsim::OSDomain::reg_cb_obj<T>::reg_cb_t f)
|
||||
{
|
||||
reg_cbs.push_back(new Qsim::OSDomain::reg_cb_obj<T>(p, f));
|
||||
}
|
||||
|
||||
template <typename T> void mem_rd(T& d, uint64_t paddr);
|
||||
template <typename T> void mem_rd_virt(unsigned i, T& d, uint64_t vaddr);
|
||||
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);
|
||||
|
||||
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 <Harp::OSDomain::Cpu> cpus;
|
||||
|
||||
std::vector <Harp::OSdomain::atomic_cb_obj_base*> atomic_cbs;
|
||||
std::vector <Harp::OSdomain::inst_cb_obj_base*> inst_cbs;
|
||||
std::vector <Harp::OSdomain::int_cb_obj_base*> int_cbs;
|
||||
std::vector <Harp::OSdomain::mem_cb_obj_base*> mem_cbs;
|
||||
std::vector <Harp::OSdomain::magic_cb_obj_base*> magic_cbs;
|
||||
std::vector <Harp::OSdomain::reg_cb_obj_base*> reg_cbs;
|
||||
};
|
||||
};
|
||||
#endif
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
36
src/qsim-harp.cpp
Normal file
36
src/qsim-harp.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*******************************************************************************
|
||||
HARPtools by Chad D. Kersey, Summer 2011
|
||||
*******************************************************************************/
|
||||
#include "include/qsim-harp.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user