9b2677c745a624fb9981fe3b9dccd65b832b4ba6
[riscv-isa-sim.git] / riscv / sim.cc
1 #include "sim.h"
2 #include "applink.h"
3 #include "common.h"
4 #include <sys/mman.h>
5 #include <map>
6 #include <iostream>
7 #include <climits>
8 #include <assert.h>
9
10 sim_t::sim_t(int _nprocs, appserver_link_t* _applink, icsim_t* default_icache, icsim_t* default_dcache)
11 : applink(_applink),
12 procs(_nprocs)
13 {
14 size_t memsz0 = sizeof(size_t) == 8 ? 0x100000000ULL : 0x70000000UL;
15 size_t quantum = std::max(PGSIZE, (reg_t)sysconf(_SC_PAGESIZE));
16 memsz0 = memsz0/quantum*quantum;
17
18 memsz = memsz0;
19 mem = (char*)mmap64(NULL, memsz, PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
20
21 if(mem == MAP_FAILED)
22 {
23 while(mem == MAP_FAILED && (memsz = memsz*10/11/quantum*quantum))
24 mem = (char*)mmap64(NULL, memsz, PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
25 assert(mem != MAP_FAILED);
26 fprintf(stderr, "warning: only got %lu bytes of target mem (wanted %lu)\n",
27 (unsigned long)memsz, (unsigned long)memsz0);
28 }
29
30 mmu = new mmu_t(mem, memsz);
31
32 for(size_t i = 0; i < num_cores(); i++)
33 {
34 procs[i] = new processor_t(this, new mmu_t(mem, memsz));
35 procs[i]->init(i, default_icache, default_dcache);
36 }
37
38 applink->init(this);
39 }
40
41 sim_t::~sim_t()
42 {
43 for(size_t i = 0; i < num_cores(); i++)
44 {
45 mmu_t* pmmu = &procs[i]->mmu;
46 delete procs[i];
47 delete pmmu;
48 }
49 delete mmu;
50 munmap(mem, memsz);
51 }
52
53 void sim_t::set_tohost(reg_t val)
54 {
55 fromhost = 0;
56 tohost = val;
57 applink->wait_for_tohost();
58 }
59
60 reg_t sim_t::get_fromhost()
61 {
62 applink->wait_for_fromhost();
63 return fromhost;
64 }
65
66 void sim_t::send_ipi(reg_t who)
67 {
68 if(who < num_cores())
69 procs[who]->deliver_ipi();
70 }
71
72 void sim_t::run(bool debug)
73 {
74 applink->wait_for_start();
75
76 // start core 0
77 send_ipi(0);
78
79 while(1)
80 {
81 if(!debug)
82 step_all(100,100,false);
83 else
84 {
85 putchar(':');
86 char s[128];
87 std::cin.getline(s,sizeof(s)-1);
88
89 char* p = strtok(s," ");
90 if(!p)
91 {
92 interactive_run_noisy(std::string("r"), std::vector<std::string>(1,"1"));
93 continue;
94 }
95 std::string cmd = p;
96
97 std::vector<std::string> args;
98 while((p = strtok(NULL," ")))
99 args.push_back(p);
100
101
102 typedef void (sim_t::*interactive_func)(const std::string&, const std::vector<std::string>&);
103 std::map<std::string,interactive_func> funcs;
104
105 funcs["r"] = &sim_t::interactive_run_noisy;
106 funcs["rs"] = &sim_t::interactive_run_silent;
107 funcs["rp"] = &sim_t::interactive_run_proc_noisy;
108 funcs["rps"] = &sim_t::interactive_run_proc_silent;
109 funcs["reg"] = &sim_t::interactive_reg;
110 funcs["fregs"] = &sim_t::interactive_fregs;
111 funcs["fregd"] = &sim_t::interactive_fregd;
112 funcs["mem"] = &sim_t::interactive_mem;
113 funcs["str"] = &sim_t::interactive_str;
114 funcs["until"] = &sim_t::interactive_until;
115 funcs["while"] = &sim_t::interactive_until;
116 funcs["q"] = &sim_t::interactive_quit;
117
118 try
119 {
120 if(funcs.count(cmd))
121 (this->*funcs[cmd])(cmd, args);
122 }
123 catch(trap_t t) {}
124 }
125 }
126 }
127
128 void sim_t::step_all(size_t n, size_t interleave, bool noisy)
129 {
130 for(size_t j = 0; j < n; j+=interleave)
131 for(int i = 0; i < (int)num_cores(); i++)
132 procs[i]->step(interleave,noisy);
133 }
134
135 void sim_t::interactive_run_noisy(const std::string& cmd, const std::vector<std::string>& args)
136 {
137 interactive_run(cmd,args,true);
138 }
139
140 void sim_t::interactive_run_silent(const std::string& cmd, const std::vector<std::string>& args)
141 {
142 interactive_run(cmd,args,false);
143 }
144
145 void sim_t::interactive_run(const std::string& cmd, const std::vector<std::string>& args, bool noisy)
146 {
147 if(args.size())
148 step_all(atoll(args[0].c_str()),1,noisy);
149 else
150 while(1) step_all(1,1,noisy);
151 }
152
153 void sim_t::interactive_run_proc_noisy(const std::string& cmd, const std::vector<std::string>& args)
154 {
155 interactive_run_proc(cmd,args,true);
156 }
157
158 void sim_t::interactive_run_proc_silent(const std::string& cmd, const std::vector<std::string>& args)
159 {
160 interactive_run_proc(cmd,args,false);
161 }
162
163 void sim_t::interactive_run_proc(const std::string& cmd, const std::vector<std::string>& a, bool noisy)
164 {
165 if(a.size() == 0)
166 return;
167
168 int p = atoi(a[0].c_str());
169 if(p >= (int)num_cores())
170 return;
171
172 if(a.size() == 2)
173 procs[p]->step(atoi(a[1].c_str()),noisy);
174 else
175 while(1) procs[p]->step(1,noisy);
176 }
177
178 void sim_t::interactive_quit(const std::string& cmd, const std::vector<std::string>& args)
179 {
180 throw quit_sim();
181 }
182
183 reg_t sim_t::get_pc(const std::vector<std::string>& args)
184 {
185 if(args.size() != 1)
186 throw trap_illegal_instruction;
187
188 int p = atoi(args[0].c_str());
189 if(p >= (int)num_cores())
190 throw trap_illegal_instruction;
191
192 return procs[p]->pc;
193 }
194
195 reg_t sim_t::get_reg(const std::vector<std::string>& args)
196 {
197 if(args.size() != 2)
198 throw trap_illegal_instruction;
199
200 int p = atoi(args[0].c_str());
201 int r = atoi(args[1].c_str());
202 if(p >= (int)num_cores() || r >= NXPR)
203 throw trap_illegal_instruction;
204
205 return procs[p]->XPR[r];
206 }
207
208 reg_t sim_t::get_freg(const std::vector<std::string>& args)
209 {
210 if(args.size() != 2)
211 throw trap_illegal_instruction;
212
213 int p = atoi(args[0].c_str());
214 int r = atoi(args[1].c_str());
215 if(p >= (int)num_cores() || r >= NFPR)
216 throw trap_illegal_instruction;
217
218 return procs[p]->FPR[r];
219 }
220
221 reg_t sim_t::get_tohost(const std::vector<std::string>& args)
222 {
223 if(args.size() != 1)
224 throw trap_illegal_instruction;
225
226 int p = atoi(args[0].c_str());
227 if(p >= (int)num_cores())
228 throw trap_illegal_instruction;
229
230 return procs[p]->tohost;
231 }
232
233 void sim_t::interactive_reg(const std::string& cmd, const std::vector<std::string>& args)
234 {
235 printf("0x%016llx\n",(unsigned long long)get_reg(args));
236 }
237
238 union fpr
239 {
240 reg_t r;
241 float s;
242 double d;
243 };
244
245 void sim_t::interactive_fregs(const std::string& cmd, const std::vector<std::string>& args)
246 {
247 fpr f;
248 f.r = get_freg(args);
249 printf("%g\n",f.s);
250 }
251
252 void sim_t::interactive_fregd(const std::string& cmd, const std::vector<std::string>& args)
253 {
254 fpr f;
255 f.r = get_freg(args);
256 printf("%g\n",f.d);
257 }
258
259 reg_t sim_t::get_mem(const std::vector<std::string>& args)
260 {
261 if(args.size() != 1 && args.size() != 2)
262 throw trap_illegal_instruction;
263
264 std::string addr_str = args[0];
265 if(args.size() == 2)
266 {
267 int p = atoi(args[0].c_str());
268 if(p >= (int)num_cores())
269 throw trap_illegal_instruction;
270 mmu->set_vm_enabled(!!(procs[p]->sr & SR_VM));
271 mmu->set_ptbr(procs[p]->mmu.get_ptbr());
272 addr_str = args[1];
273 }
274
275 reg_t addr = strtol(addr_str.c_str(),NULL,16), val;
276 if(addr == LONG_MAX)
277 addr = strtoul(addr_str.c_str(),NULL,16);
278
279 switch(addr % 8)
280 {
281 case 0:
282 val = mmu->load_uint64(addr);
283 break;
284 case 4:
285 val = mmu->load_uint32(addr);
286 break;
287 case 2:
288 case 6:
289 val = mmu->load_uint16(addr);
290 break;
291 default:
292 val = mmu->load_uint8(addr);
293 break;
294 }
295 return val;
296 }
297
298 void sim_t::interactive_mem(const std::string& cmd, const std::vector<std::string>& args)
299 {
300 printf("0x%016llx\n",(unsigned long long)get_mem(args));
301 }
302
303 void sim_t::interactive_str(const std::string& cmd, const std::vector<std::string>& args)
304 {
305 if(args.size() != 1)
306 throw trap_illegal_instruction;
307
308 reg_t addr = strtol(args[0].c_str(),NULL,16);
309
310 char ch;
311 while((ch = mmu->load_uint8(addr++)))
312 putchar(ch);
313
314 putchar('\n');
315 }
316
317 void sim_t::interactive_until(const std::string& cmd, const std::vector<std::string>& args)
318 {
319 if(args.size() < 3)
320 return;
321
322 std::string scmd = args[0];
323 reg_t val = strtol(args[args.size()-1].c_str(),NULL,16);
324 if(val == LONG_MAX)
325 val = strtoul(args[args.size()-1].c_str(),NULL,16);
326
327 std::vector<std::string> args2;
328 args2 = std::vector<std::string>(args.begin()+1,args.end()-1);
329
330 while(1)
331 {
332 reg_t current;
333 if(scmd == "reg")
334 current = get_reg(args2);
335 else if(scmd == "pc")
336 current = get_pc(args2);
337 else if(scmd == "mem")
338 current = get_mem(args2);
339 else if(scmd == "tohost")
340 current = get_tohost(args2);
341 else
342 return;
343
344 if(cmd == "until" && current == val)
345 break;
346 if(cmd == "while" && current != val)
347 break;
348
349 step_all(1,1,false);
350 }
351 }