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