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