diff options
author | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2011-06-19 20:47:29 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2011-06-19 20:47:29 -0700 |
commit | 77452a26e7d95d29dbaa797595ae683f03a3345b (patch) | |
tree | e7aaae682f73a20ceb4d3366528b0cd38378f49d /riscv/htif.cc | |
parent | 740f981cfd55604d46598144dccac26dd53f643c (diff) | |
download | riscv-isa-sim-77452a26e7d95d29dbaa797595ae683f03a3345b.zip riscv-isa-sim-77452a26e7d95d29dbaa797595ae683f03a3345b.tar.gz riscv-isa-sim-77452a26e7d95d29dbaa797595ae683f03a3345b.tar.bz2 |
temporary undoing of renaming
Diffstat (limited to 'riscv/htif.cc')
-rw-r--r-- | riscv/htif.cc | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/riscv/htif.cc b/riscv/htif.cc new file mode 100644 index 0000000..02809d0 --- /dev/null +++ b/riscv/htif.cc @@ -0,0 +1,143 @@ +#include "htif.h" +#include "common.h" +#include "sim.h" +#include <unistd.h> +#include <stdexcept> +#include <stdlib.h> +#include <errno.h> +#include <assert.h> + +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]; +}; + +htif_t::htif_t(int _tohost_fd, int _fromhost_fd) + : sim(NULL), tohost_fd(_tohost_fd), fromhost_fd(_fromhost_fd), seqno(1) +{ +} + +htif_t::~htif_t() +{ + close(tohost_fd); + close(fromhost_fd); +} + +void htif_t::init(sim_t* _sim) +{ + sim = _sim; +} + +void htif_t::wait_for_start() +{ + while(wait_for_packet() != APP_CMD_START); +} + +void htif_t::wait_for_fromhost_write() +{ + while(wait_for_packet() != APP_CMD_WRITE_CONTROL_REG); +} + +void htif_t::send_packet(packet* p) +{ + int bytes = write(tohost_fd,p,offsetof(packet,data)+p->data_size); + if((size_t)bytes != offsetof(packet,data) + p->data_size) + { + const char* error = bytes == -1 ? strerror(errno) : "not all bytes sent"; + fprintf(stderr,"HTIF error: %s\n", error); + exit(-1); + } +} + +void htif_t::nack(uint16_t nack_seqno) +{ + packet p = {APP_CMD_NACK,nack_seqno,0,0}; + send_packet(&p); +} + +int htif_t::wait_for_packet() +{ + while(1) + { + packet p; + int bytes = read(fromhost_fd,&p,sizeof(p)); + if(bytes < (int)offsetof(packet,data)) + { + const char* error = bytes == -1 ? strerror(errno) : "too few bytes read"; + fprintf(stderr,"HTIF error: %s\n", error); + exit(-1); + } + + 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: + sim->stop(); + break; + case APP_CMD_READ_MEM: + assert(p.addr % APP_DATA_ALIGN == 0); + assert(p.data_size % APP_DATA_ALIGN == 0); + assert(p.data_size <= APP_MAX_DATA_SIZE); + assert(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz); + ackpacket.data_size = p.data_size; + + static_assert(APP_DATA_ALIGN >= sizeof(uint64_t)) + for(size_t i = 0; i < p.data_size/8; i++) + ((uint64_t*)ackpacket.data)[i] = sim->mmu->load_uint64(p.addr+i*8); + break; + case APP_CMD_WRITE_MEM: + assert(p.addr % APP_DATA_ALIGN == 0); + assert(p.data_size % APP_DATA_ALIGN == 0); + assert(p.data_size <= bytes - offsetof(packet,data)); + assert(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz); + + for(size_t i = 0; i < p.data_size/8; i++) + sim->mmu->store_uint64(p.addr+i*8, ((uint64_t*)p.data)[i]); + break; + case APP_CMD_READ_CONTROL_REG: + assert(p.addr == 16); + assert(p.data_size == sizeof(reg_t)); + ackpacket.data_size = sizeof(reg_t); + memcpy(ackpacket.data,&sim->tohost,sizeof(reg_t)); + break; + case APP_CMD_WRITE_CONTROL_REG: + assert(p.addr == 17); + assert(p.data_size == sizeof(reg_t)); + sim->tohost = 0; + memcpy(&sim->fromhost,p.data,sizeof(reg_t)); + break; + } + + send_packet(&ackpacket); + seqno++; + return p.cmd; + } +} + |