668d23a531e5a767209514865e878ab00a530f08
[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 }
31
32 reg_t sim_t::get_fromhost()
33 {
34 while(fromhost == 0)
35 applink->wait_for_packet();
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::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::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["mem"] = &sim_t::interactive_mem;
75 funcs["until"] = &sim_t::interactive_until;
76 funcs["q"] = &sim_t::interactive_quit;
77
78 try
79 {
80 if(funcs.count(cmd))
81 (this->*funcs[cmd])(args);
82 }
83 catch(trap_t t) {}
84 }
85 }
86 }
87
88 void sim_t::step_all(size_t n, size_t interleave, bool noisy)
89 {
90 for(size_t j = 0; j < n; j+=interleave)
91 for(int i = 0; i < (int)procs.size(); i++)
92 procs[i].step(interleave,noisy);
93 }
94
95 void sim_t::interactive_run_noisy(const std::vector<std::string>& args)
96 {
97 interactive_run(args,true);
98 }
99
100 void sim_t::interactive_run_silent(const std::vector<std::string>& args)
101 {
102 interactive_run(args,false);
103 }
104
105 void sim_t::interactive_run(const std::vector<std::string>& args, bool noisy)
106 {
107 if(args.size())
108 step_all(atoi(args[0].c_str()),1,noisy);
109 else
110 while(1) step_all(1,1,noisy);
111 }
112
113 void sim_t::interactive_run_proc_noisy(const std::vector<std::string>& args)
114 {
115 interactive_run_proc(args,true);
116 }
117
118 void sim_t::interactive_run_proc_silent(const std::vector<std::string>& args)
119 {
120 interactive_run_proc(args,false);
121 }
122
123 void sim_t::interactive_run_proc(const std::vector<std::string>& a, bool noisy)
124 {
125 if(a.size() == 0)
126 return;
127
128 int p = atoi(a[0].c_str());
129 if(p >= (int)procs.size())
130 return;
131
132 if(a.size() == 2)
133 procs[p].step(atoi(a[1].c_str()),noisy);
134 else
135 while(1) procs[p].step(1,noisy);
136 }
137
138 void sim_t::interactive_quit(const std::vector<std::string>& args)
139 {
140 exit(0);
141 }
142
143 reg_t sim_t::get_pc(const std::vector<std::string>& args)
144 {
145 if(args.size() != 1)
146 throw trap_illegal_instruction;
147
148 int p = atoi(args[0].c_str());
149 if(p >= (int)procs.size())
150 throw trap_illegal_instruction;
151
152 return procs[p].pc;
153 }
154
155 reg_t sim_t::get_reg(const std::vector<std::string>& args)
156 {
157 if(args.size() != 2)
158 throw trap_illegal_instruction;
159
160 int p = atoi(args[0].c_str());
161 int r = atoi(args[1].c_str());
162 if(p >= (int)procs.size() || r >= NGPR)
163 throw trap_illegal_instruction;
164
165 return procs[p].R[r];
166 }
167
168 void sim_t::interactive_reg(const std::vector<std::string>& args)
169 {
170 printf("0x%016llx\n",(unsigned long long)get_reg(args));
171 }
172
173 reg_t sim_t::get_mem(const std::vector<std::string>& args)
174 {
175 if(args.size() != 1)
176 throw trap_illegal_instruction;
177
178 reg_t addr = strtol(args[0].c_str(),NULL,16), val;
179 mmu_t mmu(mem,memsz);
180 switch(addr % 8)
181 {
182 case 0:
183 val = mmu.load_uint64(addr);
184 break;
185 case 4:
186 val = mmu.load_uint32(addr);
187 break;
188 case 2:
189 case 6:
190 val = mmu.load_uint16(addr);
191 break;
192 default:
193 val = mmu.load_uint8(addr);
194 break;
195 }
196 return val;
197 }
198
199 void sim_t::interactive_mem(const std::vector<std::string>& args)
200 {
201 printf("0x%016llx\n",(unsigned long long)get_mem(args));
202 }
203
204 void sim_t::interactive_until(const std::vector<std::string>& args)
205 {
206 if(args.size() < 3)
207 return;
208
209 std::string cmd = args[0];
210 reg_t val = strtol(args[args.size()-1].c_str(),NULL,16);
211
212 std::vector<std::string> args2;
213 args2 = std::vector<std::string>(args.begin()+1,args.end()-1);
214
215 while(1)
216 {
217 reg_t current;
218 if(args[0] == "reg")
219 current = get_reg(args2);
220 else if(args[0] == "pc")
221 current = get_pc(args2);
222 else if(args[0] == "mem")
223 current = get_mem(args2);
224 else
225 return;
226
227 if(current == val)
228 break;
229
230 step_all(1,1,false);
231 }
232 }