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