Improve performance for branchy code
[riscv-isa-sim.git] / riscv / htif.cc
1 // See LICENSE for license details.
2
3 #include "htif.h"
4 #include "sim.h"
5 #include "encoding.h"
6 #include <unistd.h>
7 #include <stdexcept>
8 #include <stdlib.h>
9 #include <errno.h>
10 #include <assert.h>
11 #include <stddef.h>
12 #include <poll.h>
13
14 htif_isasim_t::htif_isasim_t(sim_t* _sim, const std::vector<std::string>& args)
15 : htif_pthread_t(args), sim(_sim), reset(true), seqno(1)
16 {
17 }
18
19 bool htif_isasim_t::tick()
20 {
21 if (done())
22 return false;
23
24 do tick_once(); while (reset);
25
26 return true;
27 }
28
29 void htif_isasim_t::tick_once()
30 {
31 packet_header_t hdr;
32 recv(&hdr, sizeof(hdr));
33
34 char buf[hdr.get_packet_size()];
35 memcpy(buf, &hdr, sizeof(hdr));
36 recv(buf + sizeof(hdr), hdr.get_payload_size());
37 packet_t p(buf);
38
39 assert(hdr.seqno == seqno);
40
41 switch (hdr.cmd)
42 {
43 case HTIF_CMD_READ_MEM:
44 {
45 packet_header_t ack(HTIF_CMD_ACK, seqno, hdr.data_size, 0);
46 send(&ack, sizeof(ack));
47
48 uint64_t buf[hdr.data_size];
49 for (size_t i = 0; i < hdr.data_size; i++)
50 buf[i] = sim->debug_mmu->load_uint64((hdr.addr+i)*HTIF_DATA_ALIGN);
51 send(buf, hdr.data_size * sizeof(buf[0]));
52 break;
53 }
54 case HTIF_CMD_WRITE_MEM:
55 {
56 const uint64_t* buf = (const uint64_t*)p.get_payload();
57 for (size_t i = 0; i < hdr.data_size; i++)
58 sim->debug_mmu->store_uint64((hdr.addr+i)*HTIF_DATA_ALIGN, buf[i]);
59
60 packet_header_t ack(HTIF_CMD_ACK, seqno, 0, 0);
61 send(&ack, sizeof(ack));
62 break;
63 }
64 case HTIF_CMD_READ_CONTROL_REG:
65 case HTIF_CMD_WRITE_CONTROL_REG:
66 {
67 assert(hdr.data_size == 1);
68 reg_t coreid = hdr.addr >> 20;
69 reg_t regno = hdr.addr & ((1<<20)-1);
70 uint64_t old_val, new_val = 0 /* shut up gcc */;
71
72 packet_header_t ack(HTIF_CMD_ACK, seqno, 1, 0);
73 send(&ack, sizeof(ack));
74
75 if (coreid == 0xFFFFF) // system control register space
76 {
77 uint64_t scr = sim->get_scr(regno);
78 send(&scr, sizeof(scr));
79 break;
80 }
81
82 processor_t* proc = sim->get_core(coreid);
83 bool write = hdr.cmd == HTIF_CMD_WRITE_CONTROL_REG;
84 if (write)
85 memcpy(&new_val, p.get_payload(), sizeof(new_val));
86
87 // TODO mapping HTIF regno to CSR[4:0] is arbitrary; consider alternative
88 switch (regno)
89 {
90 case CSR_HARTID & 0x1f:
91 old_val = coreid;
92 break;
93 case CSR_TOHOST & 0x1f:
94 old_val = proc->get_state()->tohost;
95 if (write)
96 proc->get_state()->tohost = new_val;
97 break;
98 case CSR_FROMHOST & 0x1f:
99 old_val = proc->get_state()->fromhost;
100 if (write && old_val == 0)
101 proc->set_fromhost(new_val);
102 break;
103 case CSR_RESET & 0x1f:
104 old_val = !proc->running();
105 if (write)
106 {
107 reset = reset & (new_val & 1);
108 proc->reset(new_val & 1);
109 }
110 break;
111 default:
112 abort();
113 }
114
115 send(&old_val, sizeof(old_val));
116 break;
117 }
118 default:
119 abort();
120 }
121 seqno++;
122 }
123
124 bool htif_isasim_t::done()
125 {
126 if (reset)
127 return false;
128 return !sim->running();
129 }