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