aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2010-07-21 20:12:09 -0700
committerAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2010-07-21 20:12:09 -0700
commitd2c5b5c15930668588f88bd1186031dded771261 (patch)
tree1de56d755bd58cc91c7c54db6c2e94633991d36f
parent7a38f874326755f131afe2bd336c0a261d58d4f2 (diff)
downloadriscv-isa-sim-d2c5b5c15930668588f88bd1186031dded771261.zip
riscv-isa-sim-d2c5b5c15930668588f88bd1186031dded771261.tar.gz
riscv-isa-sim-d2c5b5c15930668588f88bd1186031dded771261.tar.bz2
[pk,sim] first cut of appserver communication link
-rw-r--r--riscv/applink.cc137
-rw-r--r--riscv/applink.h26
-rw-r--r--riscv/insns/dmfc0.h9
-rw-r--r--riscv/insns/dmtc0.h4
-rw-r--r--riscv/insns/mfc0.h9
-rw-r--r--riscv/insns/mtc0.h4
-rw-r--r--riscv/processor.cc10
-rw-r--r--riscv/processor.h7
-rw-r--r--riscv/riscv-isa-run.cc28
-rw-r--r--riscv/riscv.mk.in2
-rw-r--r--riscv/sim.cc37
-rw-r--r--riscv/sim.h21
12 files changed, 267 insertions, 27 deletions
diff --git a/riscv/applink.cc b/riscv/applink.cc
new file mode 100644
index 0000000..fdd6cc7
--- /dev/null
+++ b/riscv/applink.cc
@@ -0,0 +1,137 @@
+#include "applink.h"
+#include "common.h"
+#include "sim.h"
+#include <unistd.h>
+#include <stdexcept>
+
+enum
+{
+ APP_CMD_READ_MEM,
+ APP_CMD_WRITE_MEM,
+ APP_CMD_READ_CONTROL_REG,
+ APP_CMD_WRITE_CONTROL_REG,
+ APP_CMD_START,
+ APP_CMD_STOP,
+ APP_CMD_ACK,
+ APP_CMD_NACK
+};
+
+#define APP_DATA_ALIGN 8
+#define APP_MAX_DATA_SIZE 1024
+struct packet
+{
+ uint16_t cmd;
+ uint16_t seqno;
+ uint32_t data_size;
+ uint64_t addr;
+ uint8_t data[APP_MAX_DATA_SIZE];
+};
+
+class packet_error : public std::runtime_error
+{
+public:
+ packet_error(const std::string& s) : std::runtime_error(s) {}
+};
+class io_error : public packet_error
+{
+public:
+ io_error(const std::string& s) : packet_error(s) {}
+};
+
+appserver_link_t::appserver_link_t(int _tohost_fd, int _fromhost_fd)
+ : sim(NULL), tohost_fd(_tohost_fd), fromhost_fd(_fromhost_fd)
+{
+}
+
+void appserver_link_t::init(sim_t* _sim)
+{
+ sim = _sim;
+}
+
+void appserver_link_t::wait_for_start()
+{
+ while(wait_for_packet() != APP_CMD_START);
+}
+
+void appserver_link_t::send_packet(packet* p)
+{
+ while(1) try
+ {
+ int bytes = write(fromhost_fd,p,offsetof(packet,data)+p->data_size);
+ if(bytes == -1 || (size_t)bytes != offsetof(packet,data)+p->data_size)
+ throw io_error("write failed");
+ }
+ catch(io_error e)
+ {
+ fprintf(stderr,"warning: %s\n",e.what());
+ }
+}
+
+void appserver_link_t::nack(uint16_t nack_seqno)
+{
+ packet p = {APP_CMD_NACK,nack_seqno,0,0};
+ send_packet(&p);
+}
+
+int appserver_link_t::wait_for_packet()
+{
+ while(1) try
+ {
+ packet p;
+ int bytes = read(fromhost_fd,&p,sizeof(p));
+ if(bytes != offsetof(packet,data))
+ throw io_error("read failed");
+
+ if(p.seqno != seqno)
+ {
+ nack(p.seqno);
+ continue;
+ }
+
+ packet ackpacket = {APP_CMD_ACK,seqno,0,0};
+
+ switch(p.cmd)
+ {
+ case APP_CMD_START:
+ break;
+ case APP_CMD_STOP:
+ exit(0);
+ case APP_CMD_READ_MEM:
+ demand(p.addr % APP_DATA_ALIGN == 0, "misaligned address");
+ demand(p.data_size % APP_DATA_ALIGN == 0, "misaligned data");
+ demand(p.data_size <= APP_MAX_DATA_SIZE, "long read data");
+ demand(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz, "out of bounds");
+ memcpy(ackpacket.data,sim->mem+p.addr,p.data_size);
+ ackpacket.data_size = p.data_size;
+ break;
+ case APP_CMD_WRITE_MEM:
+ demand(p.addr % APP_DATA_ALIGN == 0, "misaligned address");
+ demand(p.data_size % APP_DATA_ALIGN == 0, "misaligned data");
+ demand(p.data_size <= bytes - offsetof(packet,data), "short packet");
+ demand(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz, "out of bounds");
+ memcpy(sim->mem+p.addr,p.data,p.data_size);
+ break;
+ case APP_CMD_READ_CONTROL_REG:
+ demand(p.addr == 16,"bad control reg");
+ demand(p.data_size == sizeof(reg_t),"bad control reg size");
+ ackpacket.data_size = sizeof(reg_t);
+ memcpy(ackpacket.data,&sim->tohost,sizeof(reg_t));
+ break;
+ case APP_CMD_WRITE_CONTROL_REG:
+ demand(p.addr == 17,"bad control reg");
+ demand(p.data_size == sizeof(reg_t),"bad control reg size");
+ sim->tohost = 0;
+ memcpy(&sim->fromhost,ackpacket.data,sizeof(reg_t));
+ break;
+ }
+
+ send_packet(&ackpacket);
+ seqno++;
+ return p.cmd;
+ }
+ catch(io_error e)
+ {
+ fprintf(stderr,"warning: %s\n",e.what());
+ }
+}
+
diff --git a/riscv/applink.h b/riscv/applink.h
new file mode 100644
index 0000000..b153b1f
--- /dev/null
+++ b/riscv/applink.h
@@ -0,0 +1,26 @@
+#ifndef _APPLINK_H
+#define _APPLINK_H
+
+#include <stdint.h>
+
+class sim_t;
+struct packet;
+class appserver_link_t
+{
+public:
+ appserver_link_t(int _tohost_fd, int _fromhost_fd);
+ void init(sim_t* _sim);
+ void wait_for_start();
+ int wait_for_packet();
+
+private:
+ sim_t* sim;
+ int tohost_fd;
+ int fromhost_fd;
+ uint16_t seqno;
+
+ void nack(uint16_t seqno);
+ void send_packet(packet* p);
+};
+
+#endif
diff --git a/riscv/insns/dmfc0.h b/riscv/insns/dmfc0.h
index 38b16b5..b905d31 100644
--- a/riscv/insns/dmfc0.h
+++ b/riscv/insns/dmfc0.h
@@ -15,6 +15,15 @@ switch(insn.rtype.rs)
case 3:
RT = ebase;
break;
+
+ case 8:
+ RT = MEMSIZE >> 12;
+ break;
+
+ case 17:
+ RT = sim->get_fromhost();
+ break;
+
default:
RT = -1;
}
diff --git a/riscv/insns/dmtc0.h b/riscv/insns/dmtc0.h
index 0c9c4ff..3347605 100644
--- a/riscv/insns/dmtc0.h
+++ b/riscv/insns/dmtc0.h
@@ -12,4 +12,8 @@ switch(insn.rtype.rs)
case 3:
ebase = RT & ~0xFFF;
break;
+
+ case 16:
+ sim->set_tohost(RT);
+ break;
}
diff --git a/riscv/insns/mfc0.h b/riscv/insns/mfc0.h
index 9d3595e..f57539a 100644
--- a/riscv/insns/mfc0.h
+++ b/riscv/insns/mfc0.h
@@ -14,6 +14,15 @@ switch(insn.rtype.rs)
case 3:
RT = sext32(ebase);
break;
+
+ case 8:
+ RT = sext32(MEMSIZE >> 12);
+ break;
+
+ case 17:
+ RT = sext32(sim->get_fromhost());
+ break;
+
default:
RT = -1;
}
diff --git a/riscv/insns/mtc0.h b/riscv/insns/mtc0.h
index 3b34f7a..f018cf6 100644
--- a/riscv/insns/mtc0.h
+++ b/riscv/insns/mtc0.h
@@ -20,4 +20,8 @@ switch(insn.rtype.rs)
case 9:
printf("%ld insns retired\n",counters[0]);
exit(0);
+
+ case 16:
+ sim->set_tohost(sext32(RT));
+ break;
}
diff --git a/riscv/processor.cc b/riscv/processor.cc
index d10d45c..23761d3 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -5,9 +5,10 @@
#include "processor.h"
#include "common.h"
#include "config.h"
+#include "sim.h"
-processor_t::processor_t(int _id, char* _mem, size_t _memsz)
- : id(_id), mmu(_mem,_memsz)
+processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz)
+ : sim(_sim), mmu(_mem,_memsz)
{
memset(R,0,sizeof(R));
pc = 0;
@@ -19,6 +20,11 @@ processor_t::processor_t(int _id, char* _mem, size_t _memsz)
memset(counters,0,sizeof(counters));
}
+void processor_t::init(uint32_t _id)
+{
+ id = _id;
+}
+
void processor_t::set_sr(uint32_t val)
{
sr = val & ~SR_ZERO;
diff --git a/riscv/processor.h b/riscv/processor.h
index 6724e2c..33ca939 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -6,13 +6,18 @@
#include "trap.h"
#include "mmu.h"
+class sim_t;
+
class processor_t
{
public:
- processor_t(int _id, char* _mem, size_t _memsz);
+ processor_t(sim_t* _sim, char* _mem, size_t _memsz);
+ void init(uint32_t _id);
void step(size_t n, bool noisy);
private:
+ sim_t* sim;
+
// architected state
reg_t R[NGPR];
reg_t pc;
diff --git a/riscv/riscv-isa-run.cc b/riscv/riscv-isa-run.cc
index 1acb721..ced7913 100644
--- a/riscv/riscv-isa-run.cc
+++ b/riscv/riscv-isa-run.cc
@@ -1,27 +1,39 @@
#include <unistd.h>
+#include <fcntl.h>
#include "common.h"
#include "sim.h"
+#include "applink.h"
int main(int argc, char** argv)
{
- sim_t s(1,MEMSIZE);
-
bool debug = false;
+ int nprocs = 1;
+ int fromhost_fd = -1, tohost_fd = -1;
- for(int c; (c = getopt(argc,argv,"-d")) != -1; )
+ for(int c; (c = getopt(argc,argv,"dpf:t:")) != -1; )
{
switch(c)
{
- case '\1':
- s.load_elf(optarg);
- break;
case 'd':
debug = true;
break;
- case '?':
- demand(0,"unrecognized option %c",optopt);
+ case 'p':
+ nprocs = atoi(optarg);
+ break;
+ case 'f':
+ fromhost_fd = atoi(optarg);
+ break;
+ case 't':
+ tohost_fd = atoi(optarg);
+ break;
}
}
+ demand(fcntl(fromhost_fd,F_GETFD) >= 0, "fromhost file not open");
+ demand(fcntl(tohost_fd,F_GETFD) >= 0, "tohost file not open");
+
+ appserver_link_t applink(fromhost_fd,tohost_fd);
+
+ sim_t s(nprocs,MEMSIZE,&applink);
s.run(debug);
}
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index ada62d5..54fc380 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -1,6 +1,7 @@
riscv_subproject_deps =
riscv_hdrs = \
+ applink.h \
common.h \
decode.h \
execute.h \
@@ -12,6 +13,7 @@ riscv_hdrs = \
insns/*.h \
riscv_srcs = \
+ applink.cc \
load_elf.cc \
processor.cc \
sim.cc \
diff --git a/riscv/sim.cc b/riscv/sim.cc
index a4a31ec..dede8de 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -1,4 +1,5 @@
#include "sim.h"
+#include "applink.h"
#include "common.h"
#include "load_elf.h"
#include <sys/mman.h>
@@ -24,20 +25,20 @@ private:
size_t size;
};
-sim_t::sim_t(int _nprocs, size_t _memsz)
- : nprocs(_nprocs), memsz(_memsz)
+sim_t::sim_t(int _nprocs, size_t _memsz, appserver_link_t* _applink)
+ : applink(_applink),
+ memsz(_memsz),
+ mem((char*)mmap64(NULL, memsz, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0)),
+ procs(std::vector<processor_t>(_nprocs,processor_t(this,mem,memsz)))
{
- mem = (char*)mmap(NULL, memsz, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
demand(mem != MAP_FAILED, "couldn't allocate target machine's memory");
- procs = (processor_t*)malloc(sizeof(*procs)*nprocs);
- for(int i = 0; i < nprocs; i++)
- new(&procs[i]) processor_t(i,mem,memsz);
+ for(int i = 0; i < (int)procs.size(); i++)
+ procs[i].init(i);
}
sim_t::~sim_t()
{
- free(procs);
}
void sim_t::load_elf(const char* fn)
@@ -45,9 +46,23 @@ void sim_t::load_elf(const char* fn)
memory_t loader(mem, memsz);
::load_elf(fn,&loader);
}
+void sim_t::set_tohost(reg_t val)
+{
+ fromhost = 0;
+ tohost = val;
+}
+
+reg_t sim_t::get_fromhost()
+{
+ while(fromhost == 0)
+ applink->wait_for_packet();
+ return fromhost;
+}
void sim_t::run(bool debug)
{
+ applink->wait_for_start();
+
while(1)
{
if(!debug)
@@ -96,7 +111,7 @@ void sim_t::run(bool debug)
void sim_t::step_all(size_t n, size_t interleave, bool noisy)
{
for(size_t j = 0; j < n; j+=interleave)
- for(int i = 0; i < nprocs; i++)
+ for(int i = 0; i < (int)procs.size(); i++)
procs[i].step(interleave,noisy);
}
@@ -134,7 +149,7 @@ void sim_t::interactive_run_proc(const std::vector<std::string>& a, bool noisy)
return;
int p = atoi(a[0].c_str());
- if(p >= nprocs)
+ if(p >= (int)procs.size())
return;
if(a.size() == 2)
@@ -154,7 +169,7 @@ reg_t sim_t::get_pc(const std::vector<std::string>& args)
throw trap_illegal_instruction;
int p = atoi(args[0].c_str());
- if(p >= nprocs)
+ if(p >= (int)procs.size())
throw trap_illegal_instruction;
return procs[p].pc;
@@ -167,7 +182,7 @@ reg_t sim_t::get_reg(const std::vector<std::string>& args)
int p = atoi(args[0].c_str());
int r = atoi(args[1].c_str());
- if(p >= nprocs || r >= NGPR)
+ if(p >= (int)procs.size() || r >= NGPR)
throw trap_illegal_instruction;
return procs[p].R[r];
diff --git a/riscv/sim.h b/riscv/sim.h
index 6d2ac9b..59795d9 100644
--- a/riscv/sim.h
+++ b/riscv/sim.h
@@ -5,22 +5,31 @@
#include <string>
#include "processor.h"
-const int MEMSIZE = 0x7D000000;
+const long MEMSIZE = 0x100000000;
+
+class appserver_link_t;
class sim_t
{
public:
- sim_t(int _nprocs, size_t _memsz);
+ sim_t(int _nprocs, size_t _memsz, appserver_link_t* _applink);
~sim_t();
void load_elf(const char* fn);
void run(bool debug);
+ void set_tohost(reg_t val);
+ reg_t get_fromhost();
+
private:
- processor_t* procs;
- int nprocs;
+ // global architected state
+ reg_t tohost;
+ reg_t fromhost;
+
+ appserver_link_t* applink;
- char* mem;
size_t memsz;
+ char* mem;
+ std::vector<processor_t> procs;
void step_all(size_t n, size_t interleave, bool noisy);
@@ -41,6 +50,8 @@ private:
reg_t get_reg(const std::vector<std::string>& args);
reg_t get_mem(const std::vector<std::string>& args);
reg_t get_pc(const std::vector<std::string>& args);
+
+ friend class appserver_link_t;
};
#endif