use inttypes macros to print uint64_t
[riscv-isa-sim.git] / riscv / interactive.cc
1 // See LICENSE for license details.
2
3 #include "sim.h"
4 #include "htif.h"
5 #include <sys/mman.h>
6 #include <map>
7 #include <iostream>
8 #include <climits>
9 #include <cinttypes>
10 #include <assert.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <sstream>
14 #include <string>
15 #include <vector>
16
17 static std::string readline()
18 {
19 std::string s;
20 while (1)
21 {
22 char ch;
23 assert(read(1, &ch, 1) == 1);
24
25 if (ch == '\x7f')
26 {
27 if (s.empty())
28 continue;
29 s.erase(s.end()-1);
30 }
31
32 assert(write(1, &ch, 1) == 1);
33 if (ch == '\n')
34 return s;
35 if (ch != '\x7f')
36 s += ch;
37 }
38 }
39
40 void sim_t::interactive()
41 {
42 std::cout << ": " << std::flush;
43 std::string s = readline();
44
45 std::stringstream ss(s);
46 std::string cmd, tmp;
47 std::vector<std::string> args;
48 if (!(ss >> cmd))
49 {
50 interactive_run_noisy(std::string("r"), std::vector<std::string>(1,"1"));
51 return;
52 }
53 while (ss >> tmp)
54 args.push_back(tmp);
55
56 typedef void (sim_t::*interactive_func)(const std::string&, const std::vector<std::string>&);
57 std::map<std::string,interactive_func> funcs;
58
59 funcs["r"] = &sim_t::interactive_run_noisy;
60 funcs["rs"] = &sim_t::interactive_run_silent;
61 funcs["rp"] = &sim_t::interactive_run_proc_noisy;
62 funcs["rps"] = &sim_t::interactive_run_proc_silent;
63 funcs["reg"] = &sim_t::interactive_reg;
64 funcs["fregs"] = &sim_t::interactive_fregs;
65 funcs["fregd"] = &sim_t::interactive_fregd;
66 funcs["mem"] = &sim_t::interactive_mem;
67 funcs["str"] = &sim_t::interactive_str;
68 funcs["until"] = &sim_t::interactive_until;
69 funcs["while"] = &sim_t::interactive_until;
70 funcs["q"] = &sim_t::interactive_quit;
71
72 try
73 {
74 if(funcs.count(cmd))
75 (this->*funcs[cmd])(cmd, args);
76 }
77 catch(trap_t t) {}
78 }
79
80 void sim_t::interactive_run_noisy(const std::string& cmd, const std::vector<std::string>& args)
81 {
82 interactive_run(cmd,args,true);
83 }
84
85 void sim_t::interactive_run_silent(const std::string& cmd, const std::vector<std::string>& args)
86 {
87 interactive_run(cmd,args,false);
88 }
89
90 void sim_t::interactive_run(const std::string& cmd, const std::vector<std::string>& args, bool noisy)
91 {
92 size_t steps = args.size() ? atoll(args[0].c_str()) : -1;
93 step(steps, noisy);
94 }
95
96 void sim_t::interactive_run_proc_noisy(const std::string& cmd, const std::vector<std::string>& args)
97 {
98 interactive_run_proc(cmd,args,true);
99 }
100
101 void sim_t::interactive_run_proc_silent(const std::string& cmd, const std::vector<std::string>& args)
102 {
103 interactive_run_proc(cmd,args,false);
104 }
105
106 void sim_t::interactive_run_proc(const std::string& cmd, const std::vector<std::string>& a, bool noisy)
107 {
108 if(a.size() == 0)
109 return;
110
111 int p = atoi(a[0].c_str());
112 if(p >= (int)num_cores())
113 return;
114
115 size_t steps = a.size() > 1 ? atoll(a[1].c_str()) : -1;
116 procs[p]->step(steps, noisy);
117 }
118
119 void sim_t::interactive_quit(const std::string& cmd, const std::vector<std::string>& args)
120 {
121 exit(0);
122 }
123
124 reg_t sim_t::get_pc(const std::vector<std::string>& args)
125 {
126 if(args.size() != 1)
127 throw trap_illegal_instruction;
128
129 int p = atoi(args[0].c_str());
130 if(p >= (int)num_cores())
131 throw trap_illegal_instruction;
132
133 return procs[p]->pc;
134 }
135
136 reg_t sim_t::get_reg(const std::vector<std::string>& args)
137 {
138 if(args.size() != 2)
139 throw trap_illegal_instruction;
140
141 int p = atoi(args[0].c_str());
142 int r = atoi(args[1].c_str());
143 if(p >= (int)num_cores() || r >= NXPR)
144 throw trap_illegal_instruction;
145
146 return procs[p]->XPR[r];
147 }
148
149 reg_t sim_t::get_freg(const std::vector<std::string>& args)
150 {
151 if(args.size() != 2)
152 throw trap_illegal_instruction;
153
154 int p = atoi(args[0].c_str());
155 int r = atoi(args[1].c_str());
156 if(p >= (int)num_cores() || r >= NFPR)
157 throw trap_illegal_instruction;
158
159 return procs[p]->FPR[r];
160 }
161
162 void sim_t::interactive_reg(const std::string& cmd, const std::vector<std::string>& args)
163 {
164 printf("0x%016" PRIx64 "\n", get_reg(args));
165 }
166
167 union fpr
168 {
169 reg_t r;
170 float s;
171 double d;
172 };
173
174 void sim_t::interactive_fregs(const std::string& cmd, const std::vector<std::string>& args)
175 {
176 fpr f;
177 f.r = get_freg(args);
178 printf("%g\n",f.s);
179 }
180
181 void sim_t::interactive_fregd(const std::string& cmd, const std::vector<std::string>& args)
182 {
183 fpr f;
184 f.r = get_freg(args);
185 printf("%g\n",f.d);
186 }
187
188 reg_t sim_t::get_mem(const std::vector<std::string>& args)
189 {
190 if(args.size() != 1 && args.size() != 2)
191 throw trap_illegal_instruction;
192
193 std::string addr_str = args[0];
194 if(args.size() == 2)
195 {
196 int p = atoi(args[0].c_str());
197 if(p >= (int)num_cores())
198 throw trap_illegal_instruction;
199 mmu->set_sr(procs[p]->sr);
200 mmu->set_ptbr(procs[p]->mmu.get_ptbr());
201 addr_str = args[1];
202 }
203
204 reg_t addr = strtol(addr_str.c_str(),NULL,16), val;
205 if(addr == LONG_MAX)
206 addr = strtoul(addr_str.c_str(),NULL,16);
207
208 switch(addr % 8)
209 {
210 case 0:
211 val = mmu->load_uint64(addr);
212 break;
213 case 4:
214 val = mmu->load_uint32(addr);
215 break;
216 case 2:
217 case 6:
218 val = mmu->load_uint16(addr);
219 break;
220 default:
221 val = mmu->load_uint8(addr);
222 break;
223 }
224 return val;
225 }
226
227 void sim_t::interactive_mem(const std::string& cmd, const std::vector<std::string>& args)
228 {
229 printf("0x%016" PRIx64 "\n", get_mem(args));
230 }
231
232 void sim_t::interactive_str(const std::string& cmd, const std::vector<std::string>& args)
233 {
234 if(args.size() != 1)
235 throw trap_illegal_instruction;
236
237 reg_t addr = strtol(args[0].c_str(),NULL,16);
238
239 char ch;
240 while((ch = mmu->load_uint8(addr++)))
241 putchar(ch);
242
243 putchar('\n');
244 }
245
246 void sim_t::interactive_until(const std::string& cmd, const std::vector<std::string>& args)
247 {
248 if(args.size() < 3)
249 return;
250
251 std::string scmd = args[0];
252 reg_t val = strtol(args[args.size()-1].c_str(),NULL,16);
253 if(val == LONG_MAX)
254 val = strtoul(args[args.size()-1].c_str(),NULL,16);
255
256 std::vector<std::string> args2;
257 args2 = std::vector<std::string>(args.begin()+1,args.end()-1);
258
259 while (1)
260 {
261 reg_t current;
262 if(scmd == "reg")
263 current = get_reg(args2);
264 else if(scmd == "pc")
265 current = get_pc(args2);
266 else if(scmd == "mem")
267 current = get_mem(args2);
268 else
269 return;
270
271 if(cmd == "until" && current == val)
272 break;
273 if(cmd == "while" && current != val)
274 break;
275
276 step(1, false);
277 }
278 }