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