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