+// See LICENSE for license details.
+
#include "htif.h"
-#include "common.h"
#include "sim.h"
+#include "encoding.h"
#include <unistd.h>
#include <stdexcept>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
+#include <stddef.h>
+#include <poll.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_isasim_t::htif_isasim_t(sim_t* _sim, const std::vector<std::string>& args)
+ : htif_pthread_t(args), sim(_sim), reset(true), seqno(1)
{
}
-htif_t::~htif_t()
+bool htif_isasim_t::tick()
{
- close(tohost_fd);
- close(fromhost_fd);
-}
+ if (done())
+ return false;
-void htif_t::init(sim_t* _sim)
-{
- sim = _sim;
-}
+ do tick_once(); while (reset);
-void htif_t::wait_for_start()
-{
- while(wait_for_packet() != APP_CMD_START);
+ return true;
}
-void htif_t::wait_for_tohost_write()
+void htif_isasim_t::tick_once()
{
- while(wait_for_packet() != APP_CMD_READ_CONTROL_REG);
-}
+ packet_header_t hdr;
+ recv(&hdr, sizeof(hdr));
-void htif_t::wait_for_fromhost_write()
-{
- while(wait_for_packet() != APP_CMD_WRITE_CONTROL_REG);
-}
+ char buf[hdr.get_packet_size()];
+ memcpy(buf, &hdr, sizeof(hdr));
+ recv(buf + sizeof(hdr), hdr.get_payload_size());
+ packet_t p(buf);
-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);
- }
-}
+ assert(hdr.seqno == seqno);
-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)
+ switch (hdr.cmd)
{
- packet p;
- int bytes = read(fromhost_fd,&p,sizeof(p));
- if(bytes < (int)offsetof(packet,data))
+ case HTIF_CMD_READ_MEM:
{
- const char* error = bytes == -1 ? strerror(errno) : "too few bytes read";
- fprintf(stderr,"HTIF error: %s\n", error);
- exit(-1);
+ packet_header_t ack(HTIF_CMD_ACK, seqno, hdr.data_size, 0);
+ send(&ack, sizeof(ack));
+
+ uint64_t buf[hdr.data_size];
+ for (size_t i = 0; i < hdr.data_size; i++)
+ buf[i] = sim->debug_mmu->load_uint64((hdr.addr+i)*HTIF_DATA_ALIGN);
+ send(buf, hdr.data_size * sizeof(buf[0]));
+ break;
}
-
- if(p.seqno != seqno)
+ case HTIF_CMD_WRITE_MEM:
{
- nack(p.seqno);
- continue;
- }
+ const uint64_t* buf = (const uint64_t*)p.get_payload();
+ for (size_t i = 0; i < hdr.data_size; i++)
+ sim->debug_mmu->store_uint64((hdr.addr+i)*HTIF_DATA_ALIGN, buf[i]);
- packet ackpacket = {APP_CMD_ACK,seqno,0,0};
-
- switch(p.cmd)
+ packet_header_t ack(HTIF_CMD_ACK, seqno, 0, 0);
+ send(&ack, sizeof(ack));
+ break;
+ }
+ case HTIF_CMD_READ_CONTROL_REG:
+ case HTIF_CMD_WRITE_CONTROL_REG:
{
- 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));
+ assert(hdr.data_size == 1);
+ reg_t coreid = hdr.addr >> 20;
+ reg_t regno = hdr.addr & ((1<<20)-1);
+ uint64_t old_val, new_val = 0 /* shut up gcc */;
+
+ packet_header_t ack(HTIF_CMD_ACK, seqno, 1, 0);
+ send(&ack, sizeof(ack));
+
+ if (coreid == 0xFFFFF) // system control register space
+ {
+ uint64_t scr = sim->get_scr(regno);
+ send(&scr, sizeof(scr));
break;
+ }
+
+ processor_t* proc = sim->get_core(coreid);
+ bool write = hdr.cmd == HTIF_CMD_WRITE_CONTROL_REG;
+ if (write)
+ memcpy(&new_val, p.get_payload(), sizeof(new_val));
+
+ switch (regno)
+ {
+ case CSR_MTOHOST:
+ old_val = proc->get_state()->tohost;
+ if (write)
+ proc->get_state()->tohost = new_val;
+ break;
+ case CSR_MFROMHOST:
+ old_val = proc->get_state()->fromhost;
+ if (write && old_val == 0)
+ proc->set_csr(CSR_MFROMHOST, new_val);
+ break;
+ case CSR_MRESET:
+ old_val = !proc->running();
+ if (write)
+ {
+ reset = reset & (new_val & 1);
+ proc->reset(new_val & 1);
+ }
+ break;
+ default:
+ abort();
+ }
+
+ send(&old_val, sizeof(old_val));
+ break;
}
-
- send_packet(&ackpacket);
- seqno++;
- return p.cmd;
+ default:
+ abort();
}
+ seqno++;
}
+bool htif_isasim_t::done()
+{
+ if (reset)
+ return false;
+ return !sim->running();
+}