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