cffe3baeac521f5c2e91c6f1dd1dde74e5eabe86
[riscv-isa-sim.git] / riscv / htif.cc
1 #include "htif.h"
2 #include "common.h"
3 #include "sim.h"
4 #include <unistd.h>
5 #include <stdexcept>
6 #include <stdlib.h>
7 #include <errno.h>
8 #include <assert.h>
9 #include <stddef.h>
10 #include <poll.h>
11
12 enum
13 {
14 APP_CMD_READ_MEM,
15 APP_CMD_WRITE_MEM,
16 APP_CMD_READ_CONTROL_REG,
17 APP_CMD_WRITE_CONTROL_REG,
18 APP_CMD_ACK,
19 APP_CMD_NACK
20 };
21
22 #define APP_MAX_DATA_SIZE 1024U
23 #define HTIF_DATA_ALIGN 8U
24 struct packet
25 {
26 reg_t cmd : 4;
27 reg_t data_size : 12;
28 reg_t seqno : 8;
29 reg_t addr : 40;
30
31 uint64_t data[APP_MAX_DATA_SIZE/8];
32 };
33
34 htif_t::htif_t(int _tohost_fd, int _fromhost_fd)
35 : sim(NULL), tohost_fd(_tohost_fd), fromhost_fd(_fromhost_fd),
36 reset(true), seqno(1)
37 {
38 }
39
40 htif_t::~htif_t()
41 {
42 close(tohost_fd);
43 close(fromhost_fd);
44 }
45
46 void htif_t::init(sim_t* _sim)
47 {
48 sim = _sim;
49 }
50
51 void htif_t::wait_for_start()
52 {
53 while (reset)
54 wait_for_packet();
55 }
56
57 void htif_t::send_packet(packet* p)
58 {
59 size_t data_size = p->data_size*HTIF_DATA_ALIGN;
60 size_t bytes = write(tohost_fd, p, offsetof(packet,data) + data_size);
61 if(bytes != offsetof(packet,data) + data_size)
62 {
63 const char* error = (ssize_t)bytes == -1 ? strerror(errno) : "not all bytes sent";
64 fprintf(stderr,"HTIF error: %s\n", error);
65 exit(-1);
66 }
67 }
68
69 void htif_t::nack(uint8_t nack_seqno)
70 {
71 packet p = {APP_CMD_NACK,0,nack_seqno,0};
72 send_packet(&p);
73 }
74
75 int htif_t::wait_for_packet()
76 {
77 while(1)
78 {
79 packet p;
80 ssize_t bytes = read(fromhost_fd,&p,sizeof(p));
81 if(bytes < (ssize_t)offsetof(packet,data))
82 {
83 const char* error = bytes == -1 ? strerror(errno) : "too few bytes read";
84 fprintf(stderr,"HTIF error: %s\n", error);
85 exit(-1);
86 }
87
88 if(p.seqno != seqno)
89 {
90 nack(p.seqno);
91 continue;
92 }
93
94 packet ackpacket = {APP_CMD_ACK,0,seqno,0};
95 reg_t pcr_coreid = p.addr >> 20;
96 reg_t pcr_reg = p.addr & ((1<<20)-1);
97
98 switch(p.cmd)
99 {
100 case APP_CMD_READ_MEM:
101 assert(p.data_size <= APP_MAX_DATA_SIZE/HTIF_DATA_ALIGN);
102 assert(p.addr < sim->memsz/HTIF_DATA_ALIGN);
103 assert(p.addr+p.data_size <= sim->memsz/HTIF_DATA_ALIGN);
104 ackpacket.data_size = p.data_size;
105
106 assert(HTIF_DATA_ALIGN == sizeof(uint64_t));
107 for(size_t i = 0; i < p.data_size; i++)
108 ackpacket.data[i] = sim->mmu->load_uint64((p.addr+i)*HTIF_DATA_ALIGN);
109 break;
110 case APP_CMD_WRITE_MEM:
111 assert(p.data_size*HTIF_DATA_ALIGN <= bytes - offsetof(packet,data));
112 assert(p.addr < sim->memsz/HTIF_DATA_ALIGN);
113 assert(p.addr+p.data_size <= sim->memsz/HTIF_DATA_ALIGN);
114
115 for(size_t i = 0; i < p.data_size; i++)
116 sim->mmu->store_uint64((p.addr+i)*HTIF_DATA_ALIGN, p.data[i]);
117 break;
118 case APP_CMD_READ_CONTROL_REG:
119 case APP_CMD_WRITE_CONTROL_REG:
120 {
121 assert(pcr_coreid < sim->num_cores());
122 assert(p.data_size == 1);
123 ackpacket.data_size = 1;
124 reg_t pcr = sim->procs[pcr_coreid]->get_pcr(pcr_reg);
125 if (pcr_reg == PCR_TOHOST)
126 sim->procs[pcr_coreid]->tohost = 0;
127 memcpy(ackpacket.data, &pcr, sizeof(pcr));
128
129 if (p.cmd == APP_CMD_READ_CONTROL_REG)
130 break;
131
132 if (pcr_reg == PCR_RESET)
133 {
134 reset = p.data[0] & 1;
135 sim->procs[pcr_coreid]->reset(reset);
136 }
137 else
138 {
139 reg_t pcr;
140 memcpy(&pcr, p.data, sizeof(pcr));
141 sim->procs[pcr_coreid]->set_pcr(pcr_reg, pcr);
142 }
143 break;
144 }
145 }
146
147 send_packet(&ackpacket);
148 seqno++;
149 return p.cmd;
150 }
151 }
152