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