disasm/sim: changed interface, added readline to sim
[calu.git] / 3b_sim / sim.cpp
1 #include <iostream>
2 #include <iomanip>
3 #include <fstream>
4 #include <boost/tokenizer.hpp>
5 #include <boost/program_options.hpp>
6 #include <boost/lexical_cast.hpp>
7 #include <string>
8 #include <map>
9 #include <list>
10
11 #include <boost/function.hpp>
12 #include <boost/functional.hpp>
13 #include <boost/tuple/tuple.hpp>
14
15 #include "disasm.h"
16 #include "ccpu.hpp"
17 #include "CInstrFactory.hpp"
18 #include "uint32_from_hex.hpp"
19
20 #include "SReadline/SReadline.h"
21 using namespace swift;
22
23 typedef boost::function<void (const vector<string> &)> Func;
24 typedef boost::tuple<string, Func> CompleterElement;
25
26 typedef list<CompleterElement> MyCompleterContainer;
27
28 class LookupFunctor
29 {
30         public:
31                 // Creates a functor and memorises tokens
32                 LookupFunctor(const vector<string>&  tokens) : Tokens(tokens) {}
33
34                 // Compares the first token only
35                 bool operator()(const CompleterElement& ele) const
36                 {
37                         return (strncmp(Tokens.begin()->c_str(), ele.get<0>().c_str(), Tokens.begin()->size()) == 0);
38                 }
39
40         private:
41                 const vector<string> &Tokens;
42 };
43
44
45
46
47 class CHelpExec
48 {
49         private:
50                 const MyCompleterContainer &m_completers;
51
52         public:
53                 CHelpExec(const MyCompleterContainer &cont) : m_completers(cont) {}
54
55                 void operator() (const vector<string>&)
56                 {
57                         cout << "Available commands: " << endl;
58                         for(auto iter = m_completers.begin(); iter != m_completers.end(); ++iter) {
59                                 cout << (*iter).get<0>() << endl;
60                         }
61                 }
62 };
63
64 void close_prog(const std::vector<std::string> &);
65
66 CCpu* Iinstr::m_cpu;
67
68 CCpu* global_cpu = NULL;
69
70 void doExit(const vector<string>&)
71 {
72         exit(EXIT_SUCCESS);
73 }
74
75 void execStep(const vector<string>& in)
76 {
77         int count = 1;
78         if(in.size() == 2) {
79                 try {
80                         count = lexical_cast<int>(in.back());
81                 }
82                 catch(bad_cast&) {
83                         cerr << "given parameter to step is not a number" << endl;
84                 }
85         }
86         while(count > 0) {
87                 try {
88                         global_cpu->tick();
89                 }
90                 catch(std::string& e) {
91                         cerr << e << endl;
92                 }
93                 count--;
94         }
95 }
96
97 void printReg(const vector<string>&)
98 {
99         int i, start = 0, end = 15;
100         /* Todo: 
101          * 1) make 2 columns
102          * 2) let use select registers to show (one register, range of registers)
103          */
104         
105         for(i = start; i <= end; i++) {
106                 cout << setw(2) << i << ": 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getRegister(i) << std::dec << endl;
107         }
108 }
109
110
111 using boost::lexical_cast;
112 using boost::bad_lexical_cast;
113
114 using namespace std;
115
116 using namespace boost::program_options;
117 namespace po = boost::program_options;
118
119 std::string progName;
120
121 int main(int argc, char* argv[])
122 {
123         progName = argv[0];
124         ifstream inFile;
125         try {
126                 po::options_description desc("Allowed options");
127                 desc.add_options()
128                 ("help,h","produce help message")
129                 ("file,f",value<string>(), "input file")
130                 ;
131
132                 po::positional_options_description p;
133                 p.add("file",1);
134
135                 po::variables_map vm;
136                 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
137                 po::notify(vm);
138
139                 if(vm.count("help")) {
140                         cout << desc << endl;
141                         return EXIT_FAILURE;
142                 }
143
144                 if(vm.count("file")) {
145 #ifdef DEBUG 
146                         cout << "going to open file " << vm["file"].as<string>() << endl;
147 #endif
148                         inFile.open(vm["file"].as<string>(), ios::in);
149                         if(!inFile) {
150                                 cerr << "Error opening file " << vm["file"].as<string>() << endl;
151                                 return EXIT_FAILURE;
152                         }
153                 }
154                 else {
155                         cout << "not input file given!" << endl << endl;
156                         cout << desc << endl;
157                         return EXIT_FAILURE;
158                 }
159         }
160         catch(std::exception& ex) {
161                 cout << ex.what() << endl;
162         }
163
164
165         string dir = "./instr/";
166
167         map<short, Iinstr*> instr;
168
169         CInstrFactory instrFab;
170         try {
171                 instrFab.loadLibsIntoMap(instr, dir);
172         }
173         catch(std::bad_alloc& e) {
174                 cerr << progName << ": bad_alloc caught " << e.what() << endl;
175                 exit(EXIT_FAILURE); 
176         }
177         catch(std::string& s) {
178                 cerr << progName << ": " << s << endl;
179                 exit(EXIT_FAILURE);
180         }
181
182         CCpu cpu(16,1000,1000);
183
184         global_cpu = &cpu;
185
186         Iinstr::setCPU(&cpu);
187
188
189         std::string str = "";
190         int addr = 0;
191         boost::char_separator<char> sep(";", "", boost::keep_empty_tokens);
192         boost::tokenizer<boost::char_separator<char> > tokens(str, sep);
193         disasm disasm(instr);
194         while(getline(inFile, str)) {
195                 int count = 0;
196                 tokens.assign(str);
197                 stringstream out;
198                 int type = 0;
199                 for(auto tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
200                         if(tok_iter == tokens.begin()) {
201                                 try {
202                                         type = lexical_cast<int>(*tok_iter);
203                                         count++;
204                                         continue;
205                                 }
206                                 catch(bad_lexical_cast &) {
207                                         break;
208                                 }
209                                 cout << endl;
210                         }
211                         switch(type) {
212                                 case 0:
213                                         if(count == 1) {
214                                                 try {
215                                                         addr = lexical_cast<uint32_from_hex>(*tok_iter);
216                                                 }
217                                                 catch(bad_lexical_cast& e) {
218                                                         cerr << e.what() << endl;
219                                                         exit(EXIT_FAILURE);
220                                                 }
221                                         }
222                                         else if(count == 2) {
223                                                 try {
224                                                         CDat data = lexical_cast<uint32_from_hex>(*tok_iter);
225                                                         cpu.setRAM(addr, data);
226                                                 }
227                                                 catch(bad_lexical_cast& e) {
228                                                         cerr << e.what() << endl;
229                                                         exit(EXIT_FAILURE);
230                                                 }
231                                         }
232                                         break;
233                                 case 1:
234                                         if(count == 1) {
235                                                 try {
236                                                         addr = lexical_cast<uint32_from_hex>(*tok_iter);
237                                                 }
238                                                 catch(bad_lexical_cast& e) {
239                                                         cerr << e.what() << endl;
240                                                         exit(EXIT_FAILURE);
241                                                 }
242                                         }
243                                         else if(count == 2) {
244                                                 Iinstr *pi = disasm.decode(*tok_iter);
245                                                 cpu.setProg(addr, pi);
246                                         }
247                                         break;
248                                 case 2:
249                                 case 3:
250                                         cerr << "ignoring labels and comments for now" << endl;
251                                 default:
252                                         cerr << "i was to lazy to implement the other format types for now" << endl;
253                         }
254                         count++;
255                 }
256         }
257         inFile.close();
258
259         cout << endl;
260
261 /*
262         for(int i = 0; i <= 32; i += 4) {
263                 Iinstr *pinstr = cpu.getProg(i);
264                 if(pinstr != NULL) {
265                         cout << i << " : " << std::hex << i << std::dec << " " << pinstr->toString() << endl;
266                 }
267                 else {
268                         cout << "Null at " << i << " : " << std::hex << i << endl;
269                 }
270         }
271
272         for(int i = 0; i <= 32; i += 4) {
273                 CDat data = cpu.getRAM(i);
274                 cout << i << " : " << std::hex << i << std::dec << " " << data << endl;
275         }
276 */
277         cpu.setRegister(1, 4);
278         cpu.setRegister(2, 0);
279         cpu.setRAM(0,5);
280         cpu.setRAM(4,50);
281         cpu.setRAM(8,32);
282         cpu.setRAM(12,45);
283
284         // following: job of the bootloader
285         //set stackpointer
286         cpu.setStack(500);
287         //set return to nowhere for ret
288         cpu.setRAM(500,50);
289
290         SReadline Reader;
291
292         MyCompleterContainer Completers;
293
294         CHelpExec HelpExec(Completers);
295
296         Completers.push_back(CompleterElement("help", boost::bind1st( boost::mem_fun( &CHelpExec::operator()), &HelpExec)));
297         Completers.push_back(CompleterElement("quit", &doExit));
298         Completers.push_back(CompleterElement("exit", &doExit));
299         Completers.push_back(CompleterElement("q", &doExit));
300         Completers.push_back(CompleterElement("step [count]",&execStep));
301         Completers.push_back(CompleterElement("reg",&printReg));
302
303         Reader.RegisterCompletions(Completers);
304
305         string UserInput;
306         vector<string> Tokens, lastTokens;
307         bool EndOfInput = false;
308
309         auto Found(Completers.end());
310
311         Func lastFunc = NULL;
312
313
314         while(1) {
315                 UserInput = Reader.GetLine("> ", Tokens, EndOfInput);
316                 if(EndOfInput) {
317                         break;
318                 }
319
320                 if(!Tokens.empty()) {
321                         Found = find_if(Completers.begin(), Completers.end(), LookupFunctor(Tokens));
322
323                         if(Found != Completers.end()) {
324                                 if((*Found).get<1>() != 0) {
325                                         lastFunc = (*Found).get<1>();
326                                         lastFunc(Tokens);
327                                         lastTokens = Tokens;
328                                         //(*Found).get<1>()(Tokens);
329                                 }
330                         }
331                         else {
332                                 lastFunc = NULL;
333                                 cout << "Unknown command. 'help' displays help" << endl;
334                         }
335                 }
336                 else {
337                         if(lastFunc != NULL) {
338                                 lastFunc(lastTokens);
339                         }
340                         else {
341                                 cout << "Unknown command. 'help' displays help" << endl;
342                         }
343                 }
344         }
345
346
347 /*
348         for(int i = 0; ; i++) {
349                 try {
350                         cpu.tick();
351                         cout << " reg0: " << cpu.getRegister(0) <<  " reg1: " << cpu.getRegister(1);
352                         cout << " reg2: " << cpu.getRegister(2) <<  " reg3: " << cpu.getRegister(3);
353                         cout << " reg4: " << cpu.getRegister(4) <<  " reg5: " << cpu.getRegister(5);
354                         cout << endl << endl;
355
356                 }
357                 catch(string& e) {
358                         cerr << e << endl;
359                         break;
360                 }
361         }
362 */
363         return EXIT_SUCCESS;
364 }