Update README
[riscv-isa-sim.git] / riscv / sim.cc
1 // See LICENSE for license details.
2
3 #include "sim.h"
4 #include "mmu.h"
5 #include "dts.h"
6 #include "remote_bitbang.h"
7 #include <map>
8 #include <iostream>
9 #include <sstream>
10 #include <climits>
11 #include <cstdlib>
12 #include <cassert>
13 #include <signal.h>
14 #include <unistd.h>
15 #include <sys/wait.h>
16 #include <sys/types.h>
17
18 volatile bool ctrlc_pressed = false;
19 static void handle_signal(int sig)
20 {
21 if (ctrlc_pressed)
22 exit(-1);
23 ctrlc_pressed = true;
24 signal(sig, &handle_signal);
25 }
26
27 sim_t::sim_t(const char* isa, size_t nprocs, bool halted, reg_t start_pc,
28 std::vector<std::pair<reg_t, mem_t*>> mems,
29 const std::vector<std::string>& args,
30 std::vector<int> const hartids, unsigned progsize,
31 unsigned max_bus_master_bits, bool require_authentication)
32 : htif_t(args), mems(mems), procs(std::max(nprocs, size_t(1))),
33 start_pc(start_pc), current_step(0), current_proc(0), debug(false),
34 histogram_enabled(false), dtb_enabled(true), remote_bitbang(NULL),
35 debug_module(this, progsize, max_bus_master_bits, require_authentication)
36 {
37 signal(SIGINT, &handle_signal);
38
39 for (auto& x : mems)
40 bus.add_device(x.first, x.second);
41
42 debug_module.add_device(&bus);
43
44 debug_mmu = new mmu_t(this, NULL);
45
46 if (hartids.size() == 0) {
47 for (size_t i = 0; i < procs.size(); i++) {
48 procs[i] = new processor_t(isa, this, i, halted);
49 }
50 }
51 else {
52 if (hartids.size() != procs.size()) {
53 std::cerr << "Number of specified hartids doesn't match number of processors" << strerror(errno) << std::endl;
54 exit(1);
55 }
56 for (size_t i = 0; i < procs.size(); i++) {
57 procs[i] = new processor_t(isa, this, hartids[i], halted);
58 }
59 }
60
61 clint.reset(new clint_t(procs));
62 bus.add_device(CLINT_BASE, clint.get());
63 }
64
65 sim_t::~sim_t()
66 {
67 for (size_t i = 0; i < procs.size(); i++)
68 delete procs[i];
69 delete debug_mmu;
70 }
71
72 void sim_thread_main(void* arg)
73 {
74 ((sim_t*)arg)->main();
75 }
76
77 void sim_t::main()
78 {
79 if (!debug && log)
80 set_procs_debug(true);
81
82 while (!done())
83 {
84 if (debug || ctrlc_pressed)
85 interactive();
86 else
87 step(INTERLEAVE);
88 if (remote_bitbang) {
89 remote_bitbang->tick();
90 }
91 }
92 }
93
94 int sim_t::run()
95 {
96 host = context_t::current();
97 target.init(sim_thread_main, this);
98 return htif_t::run();
99 }
100
101 void sim_t::step(size_t n)
102 {
103 for (size_t i = 0, steps = 0; i < n; i += steps)
104 {
105 steps = std::min(n - i, INTERLEAVE - current_step);
106 procs[current_proc]->step(steps);
107
108 current_step += steps;
109 if (current_step == INTERLEAVE)
110 {
111 current_step = 0;
112 procs[current_proc]->get_mmu()->yield_load_reservation();
113 if (++current_proc == procs.size()) {
114 current_proc = 0;
115 clint->increment(INTERLEAVE / INSNS_PER_RTC_TICK);
116 }
117
118 host->switch_to();
119 }
120 }
121 }
122
123 void sim_t::set_debug(bool value)
124 {
125 debug = value;
126 }
127
128 void sim_t::set_log(bool value)
129 {
130 log = value;
131 }
132
133 void sim_t::set_histogram(bool value)
134 {
135 histogram_enabled = value;
136 for (size_t i = 0; i < procs.size(); i++) {
137 procs[i]->set_histogram(histogram_enabled);
138 }
139 }
140
141 void sim_t::set_procs_debug(bool value)
142 {
143 for (size_t i=0; i< procs.size(); i++)
144 procs[i]->set_debug(value);
145 }
146
147 bool sim_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes)
148 {
149 if (addr + len < addr)
150 return false;
151 return bus.load(addr, len, bytes);
152 }
153
154 bool sim_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)
155 {
156 if (addr + len < addr)
157 return false;
158 return bus.store(addr, len, bytes);
159 }
160
161 void sim_t::make_dtb()
162 {
163 const int reset_vec_size = 8;
164
165 start_pc = start_pc == reg_t(-1) ? get_entry_point() : start_pc;
166
167 uint32_t reset_vec[reset_vec_size] = {
168 0x297, // auipc t0,0x0
169 0x28593 + (reset_vec_size * 4 << 20), // addi a1, t0, &dtb
170 0xf1402573, // csrr a0, mhartid
171 get_core(0)->get_xlen() == 32 ?
172 0x0182a283u : // lw t0,24(t0)
173 0x0182b283u, // ld t0,24(t0)
174 0x28067, // jr t0
175 0,
176 (uint32_t) (start_pc & 0xffffffff),
177 (uint32_t) (start_pc >> 32)
178 };
179
180 std::vector<char> rom((char*)reset_vec, (char*)reset_vec + sizeof(reset_vec));
181
182 dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, procs, mems);
183 std::string dtb = dts_compile(dts);
184
185 rom.insert(rom.end(), dtb.begin(), dtb.end());
186 const int align = 0x1000;
187 rom.resize((rom.size() + align - 1) / align * align);
188
189 boot_rom.reset(new rom_device_t(rom));
190 bus.add_device(DEFAULT_RSTVEC, boot_rom.get());
191 }
192
193 char* sim_t::addr_to_mem(reg_t addr) {
194 auto desc = bus.find_device(addr);
195 if (auto mem = dynamic_cast<mem_t*>(desc.second))
196 if (addr - desc.first < mem->size())
197 return mem->contents() + (addr - desc.first);
198 return NULL;
199 }
200
201 // htif
202
203 void sim_t::reset()
204 {
205 if (dtb_enabled)
206 make_dtb();
207 }
208
209 void sim_t::idle()
210 {
211 target.switch_to();
212 }
213
214 void sim_t::read_chunk(addr_t taddr, size_t len, void* dst)
215 {
216 assert(len == 8);
217 auto data = debug_mmu->load_uint64(taddr);
218 memcpy(dst, &data, sizeof data);
219 }
220
221 void sim_t::write_chunk(addr_t taddr, size_t len, const void* src)
222 {
223 assert(len == 8);
224 uint64_t data;
225 memcpy(&data, src, sizeof data);
226 debug_mmu->store_uint64(taddr, data);
227 }
228
229 void sim_t::proc_reset(unsigned id)
230 {
231 debug_module.proc_reset(id);
232 }