copyleft: gplv3 added and set repo to public
[calu.git] / 3b_sim / sim.cpp
1 /*   `Deep Thought', a softcore CPU implemented on a FPGA
2
3     Copyright (C) 2010 Markus Hofstaetter <markus.manrow@gmx.at>
4     Copyright (C) 2010 Martin Perner <e0725782@student.tuwien.ac.at>
5     Copyright (C) 2010 Stefan Rebernig <stefan.rebernig@gmail.com>
6     Copyright (C) 2010 Manfred Schwarz <e0725898@student.tuwien.ac.at>
7     Copyright (C) 2010 Bernhard Urban <lewurm@gmail.com>
8
9     This program is free software: you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation, either version 3 of the License, or
12     (at your option) any later version.
13
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18
19     You should have received a copy of the GNU General Public License
20     along with this program.  If not, see <http://www.gnu.org/licenses/>. */
21
22 #include <iostream>
23 #include <iomanip>
24 #include <fstream>
25 #include <boost/tokenizer.hpp>
26 #include <boost/program_options.hpp>
27 #include <boost/lexical_cast.hpp>
28 #include <string>
29 #include <map>
30 #include <list>
31
32 #include <boost/function.hpp>
33 #include <boost/functional.hpp>
34 #include <boost/tuple/tuple.hpp>
35
36 #include "disasm.h"
37 #include "ccpu.hpp"
38 #include "CInstrFactory.hpp"
39 #include "uint32_from_hex.hpp"
40
41 #include "iext.hpp"
42 #include "extensions/cprog.hpp"
43 #include "extensions/cuart.hpp"
44
45 #include <signal.h>
46
47 #include "SReadline/SReadline.h"
48 using namespace swift;
49
50 #define RAM_END (0x3000)
51 #define PROG_END (0x3000)
52 #define REG_COUNT (16)
53
54 typedef boost::function<void (const vector<string> &)> Func;
55 typedef boost::tuple<string, Func, string> CompleterElement;
56
57 typedef list<CompleterElement> MyCompleterContainer;
58
59 class LookupFunctor
60 {
61         public:
62                 // Creates a functor and memorises tokens
63                 LookupFunctor(const vector<string>&  tokens) : Tokens(tokens) {}
64
65                 // Compares the first token only
66                 bool operator()(const CompleterElement& ele) const
67                 {
68                         return (strncmp(Tokens.begin()->c_str(), ele.get<0>().c_str(), Tokens.begin()->size()) == 0);
69                 }
70
71         private:
72                 const vector<string> &Tokens;
73 };
74
75
76
77
78 class CHelpExec
79 {
80         private:
81                 const MyCompleterContainer &m_completers;
82
83         public:
84                 CHelpExec(const MyCompleterContainer &cont) : m_completers(cont) {}
85
86                 void operator() (const vector<string>&)
87                 {
88                         cout << "Available commands: " << endl;
89                         for(auto iter = m_completers.begin(); iter != m_completers.end(); ++iter) {
90                                 cout << setw(19) << setfill(' ') << (*iter).get<0>() << ": " << (*iter).get<2>() << endl;
91                         }
92                 }
93 };
94
95 void close_prog(const std::vector<std::string> &);
96
97 CCpu* Iinstr::m_cpu;
98 CCpu* Iext::m_cpu;
99 disasm* Iinstr::m_disasm;
100 disasm* Iext::m_disasm;
101
102 CCpu* global_cpu = NULL;
103
104 vector<CDat> breakpoints;
105
106
107 #include <map>
108
109 multimap<int,string> dataCommentsStore, progCommentsStore, dataLabelStore, progLabelStore;
110 map<int,string> dataLineCommentStore, progLineCommentStore;
111
112 bool ignoreBreak = false;
113
114 bool exitProg = false;
115
116 void signalCpuBreak(int)
117 {
118         global_cpu->breakNext();
119 }
120
121 void doExit(const vector<string>&)
122 {
123         exitProg = true;
124 }
125
126 unsigned int convertStringToNum(const std::string& in)
127 {
128         if(in.substr(0,2) == "0x") {
129                 return lexical_cast<uint32_from_hex>(in);
130         }
131         else {
132                 return lexical_cast<unsigned int>(in);
133         }
134 }
135
136
137 void execStep(const vector<string>& in)
138 {
139         int count = 1;
140         if(in.size() == 2) {
141                 try {
142                         count = convertStringToNum(in.back());
143                 }
144                 catch(bad_cast&) {
145                         cerr << "given parameter to step is not a number" << endl;
146                 }
147         }
148         while(count > 0) {
149                 try {
150                         auto breakp = find(breakpoints.begin(), breakpoints.end(), global_cpu->getNextPC());
151                         if(breakp == breakpoints.end() || ignoreBreak) {
152                                 global_cpu->tick();
153                                 ignoreBreak = false;
154                         }
155                         else {
156                                 ignoreBreak = true;
157                                 cout << color(white,red) << "Breakpoint" << color(white,black) << " 0x" << std::hex << setw(8) << setfill('0') << *breakp << std::hex << " hit" << endl;
158                                 break;
159                         }
160                 }
161                 catch(std::string& e) {
162                         cerr << e << endl;
163                 }
164                 count--;
165         }
166 }
167
168 void execRun(const vector<string>&)
169 {
170         while(1) {
171                 try {
172                         auto breakp = find(breakpoints.begin(), breakpoints.end(), global_cpu->getNextPC());
173                         if((breakp == breakpoints.end() || ignoreBreak) && !global_cpu->shouldBreak() ) {
174                                 global_cpu->tick();
175                                 ignoreBreak = false;
176                         }
177                         else {
178                                 ignoreBreak = true;
179                                 cout << color(white,red) << "Breakpoint" << color(white,black) << " 0x" << std::hex << setw(8) << setfill('0') << *breakp << std::hex << " hit" << endl;
180                                 return;
181                         }
182                 }
183                 catch(std::string& e) {
184                         cerr << e << endl;
185                         return;
186                 }
187         }
188 }
189
190 void setPC(const vector<string>& in)
191 {
192         CDat addr = 0;
193         if(in.size() == 2) {
194                 try {
195                         addr = convertStringToNum(in.back());
196                 }
197                 catch(bad_cast&) {
198                         cerr << "given parameter is not a number" << endl;
199                         return;
200                 }
201         }
202         global_cpu->setNextPC(addr);
203         cout << "Set programcounter to 0x" << std::hex << setw(8) << setfill('0') << addr << std::dec << endl;
204 }
205
206
207 void printReg(const vector<string>& in)
208 {
209         int i, start = 0, end = REG_COUNT-1;
210         /* Todo: 
211          * 1) make 2 columns
212          */
213
214         if(in.size() >= 2) {
215                 try {
216                         start = convertStringToNum(in[1]);
217                         if(start < 0 || start > (REG_COUNT-1)) {
218                                 cerr << "start is out of range" << endl;
219                                 return;
220                         }
221                         end = start;
222                 }
223                 catch(bad_cast&) {
224                         cerr << "given parameter is not a number" << endl;
225                         return;
226                 }
227         }
228
229         if(in.size() >= 3) {
230                 try {
231                         end = convertStringToNum(in[2]);
232                         if(start > end || end > (REG_COUNT-1)) {
233                                 cerr << "end is out of range or smaller than start" << endl;
234                                 return;
235                         }
236                 }
237                 catch(bad_cast&) {
238                         cerr << "given parameter is not a number" << endl;
239                         return;
240                 }
241         }
242         
243         for(i = start; i <= end; i++) {
244                 cout << setw(2) << setfill('0') << i << ": 0x";
245                 cout << std::hex <<  setw(8) << setfill('0') << global_cpu->getRegister(i) << " ";
246                 cout << std::dec << setw(10) << setfill(' ') << global_cpu->getRegister(i) << " ";
247                 cout << std::dec << setw(10) << setfill(' ') << (int)global_cpu->getRegister(i) << endl;
248         }
249 }
250
251 void setReg(const vector<string>& in)
252 {
253         int reg = 0;
254         CDat val = 0;
255
256         if(in.size() >= 3) {
257                 try {
258                         reg = convertStringToNum(in[1]);
259                         if(reg < 0 || reg > (REG_COUNT-1)) {
260                                 cerr << "register is out of range" << endl;
261                                 return;
262                         }
263
264                         val = convertStringToNum(in[2]);
265
266                         cout << "Setting register " << reg << " to 0x" << std::hex << setw(8) << setfill('0') << val << std::dec << endl;
267                         global_cpu->setRegister(reg,val);
268                 }
269                 catch(bad_cast&) {
270                         cerr << "given parameter is not a number" << endl;
271                         return;
272                 }
273         }
274 }
275
276 void printRAM(const vector<string>& in)
277 {
278         int i, start = 0, end = 15;
279         /* Todo: 
280          * 1) make 2 columns
281          */
282
283         if(in.size() >= 2) {
284                 try {
285                         start = convertStringToNum(in[1]);
286                         if(start < 0 || start > (RAM_END-1)) {
287                                 cerr << "start is out of range" << endl;
288                                 return;
289                         }
290                         start = (start & (~(BYTE_COUNT-1))) / BYTE_COUNT;
291                         end = start;
292                 }
293                 catch(bad_cast&) {
294                         cerr << "given parameter is not a number" << endl;
295                         return;
296                 }
297         }
298
299         if(in.size() >= 3) {
300                 try {
301                         end = convertStringToNum(in[2]);
302                         if(start > end || end > (RAM_END-1)) {
303                                 cerr << "end is out of range or smaller than start" << endl;
304                                 return;
305                         }
306                         if(end % BYTE_COUNT != 0) {
307                                 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT)+1;
308                         }
309                         else {
310                                 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT);
311                         }
312                 }
313                 catch(bad_cast&) {
314                         cerr << "given parameter is not a number" << endl;
315                         return;
316                 }
317         }
318         for(i = start*BYTE_COUNT; i <= end*BYTE_COUNT; i += BYTE_COUNT) {
319                 {
320                         auto range = dataLabelStore.equal_range(i);
321                         for(auto iter = range.first; iter != range.second; ++iter) {
322                                 cout << color(yellow,black) << iter->second << ":" << color(white,black) << endl;
323                         }
324                 }
325                 {
326                         auto range = dataCommentsStore.equal_range(i);
327                         for(auto iter = range.first; iter != range.second; ++iter) {
328                                 cout << color(blue,black) << ";" << iter->second << color(white,black) << endl;
329                         }
330                 }
331                 cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": 0x";
332                 cout << std::hex << setw(8)  << setfill('0') << global_cpu->getRAM(i) << " ";
333                 cout << std::dec << setw(10) << setfill(' ') << global_cpu->getRAM(i) << " ";
334                 cout << std::dec << setw(10) << setfill(' ') << (int)global_cpu->getRAM(i);
335
336                 auto iter = dataLineCommentStore.find(i);
337                 if(iter != dataLineCommentStore.end()) {
338                         cout << color(blue,black) << " ;" << iter->second << color(white,black);
339                 }
340                 cout << endl;
341
342         }
343 }
344
345 void setRam(const vector<string>& in)
346 {
347         int addr = 0;
348         CDat val = 0;
349
350         if(in.size() >= 3) {
351                 try {
352                         addr = convertStringToNum(in[1]);
353                         if(addr < 0 || addr > (RAM_END-1)) {
354                                 cerr << "RAM-Address is out of range" << endl;
355                                 return;
356                         }
357
358                         addr = (addr & (~(BYTE_COUNT-1))) / BYTE_COUNT;
359                         val = convertStringToNum(in[2]);
360
361                         addr *= BYTE_COUNT;
362
363                         cout << "Setting RAM-Address 0x" << std::hex << setw(8) << setfill('0') << addr;
364                         cout << " to 0x" << setw(8) << setfill('0') << val << std::dec << endl;
365                         global_cpu->setRAM(addr,val);
366                 }
367                 catch(bad_cast&) {
368                         cerr << "given parameter is not a number" << endl;
369                         return;
370                 }
371         }
372 }
373 void printPROG(const vector<string>& in)
374 {
375         int i, start = 0, end = 15;
376         /* Todo: 
377          * 1) make 2 columns
378          */
379
380         if(in.size() >= 2 && in[1][0] == 'c') {
381                 start = global_cpu->getCurPC() / BYTE_COUNT;
382                 end = start + 9;
383         }
384         else if(in.size() >= 2) {
385                 try {
386                         start = convertStringToNum(in[1]);
387                         if(start < 0 || start > (PROG_END-1)) {
388                                 cerr << "start is out of range" << endl;
389                                 return;
390                         }
391                         start = (start & (~(BYTE_COUNT-1))) / BYTE_COUNT;
392                         end = start;
393                 }
394                 catch(bad_cast&) {
395                         cerr << "given parameter is not a number" << endl;
396                         return;
397                 }
398         }
399
400         if(in.size() >= 3) {
401                 try {
402                         end = convertStringToNum(in[2]);
403                         if(start > end || end > (PROG_END-1)) {
404                                 cerr << "end is out of range or smaller than start" << endl;
405                                 return;
406                         }
407                         if(end % BYTE_COUNT != 0) {
408                                 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT)+1;
409                         }
410                         else {
411                                 end = ((end & (~(BYTE_COUNT-1))) / BYTE_COUNT);
412                         }
413
414                 }
415                 catch(bad_cast&) {
416                         cerr << "given parameter is not a number" << endl;
417                         return;
418                 }
419         }
420
421         
422         for(i = start*BYTE_COUNT; i <= end*BYTE_COUNT; i += BYTE_COUNT) {
423                 {
424                         auto range = progLabelStore.equal_range(i);
425                         for(auto iter = range.first; iter != range.second; ++iter) {
426                                 cout << color(yellow,black) << iter->second << ":" << color(white,black) << endl;
427                         }
428                 }
429                 {
430                         auto range = progCommentsStore.equal_range(i);
431                         for(auto iter = range.first; iter != range.second; ++iter) {
432                                 cout << color(blue,black) << ";" << iter->second << color(white,black) << endl;
433                         }
434                 }
435
436                 Iinstr* pi = global_cpu->getProg(i);
437                 if(pi == NULL) {
438                         cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": NOP";
439                 }
440                 else {
441                         cout << std::hex << "0x" << setw(8) << setfill('0') << i << ": " << std::dec << global_cpu->colorifyInstr(pi->toString());
442                 }
443                 auto iter = progLineCommentStore.find(i);
444                 if(iter != progLineCommentStore.end()) {
445                         cout << color(blue,black) << " ;" << iter->second << color(white,black);
446                 }
447                 cout << endl;
448         }
449 }
450
451 void setBreak(const vector<string>& in)
452 {
453         unsigned int addr = 0;
454         if(in.size() == 2) {
455                 try {
456                         addr = convertStringToNum(in.back());
457                         breakpoints.push_back(addr);
458                         cout << "Breakpoint 0x" << std::hex << setw(8) << setfill('0') << addr << std::dec << " set" << endl;
459                 }
460                 catch(bad_cast&) {
461                         cerr << "Given parameter is not a valid address" << endl;
462                 }
463         }
464         else {
465                 cerr << "Invalid parameter count!" << endl;
466         }
467 }
468
469 void listBreaks(const vector<string>&)
470 {
471         for(auto iter = breakpoints.begin(); iter != breakpoints.end(); ++iter) {
472                 cout << "Breakpoint at 0x" << std::hex << setw(8) << setfill('0') << *iter << std::dec << endl;
473         }
474 }
475
476 void getPerf(const vector<string>&)
477 {
478         cout << "current perfcounter is " << std::dec << global_cpu->getPerf() << endl;
479 }
480
481 void resetPerf(const vector<string>&)
482 {
483         cout << "reset perfcounter" << endl;
484         global_cpu->setPerf(0);
485 }
486
487 void applyToExtensions(const vector<string>& in)
488 {
489         global_cpu->applyToExtensions(in);
490 }
491
492
493 void printStatus(const vector<string>&)
494 {
495         CDat stackp = global_cpu->getStack();
496         CDat stackd = global_cpu->getRAM(stackp);
497         cout << "Stack pointer: 0x" << std::hex << setw(8) << setfill('0') << stackp << " @stackpointer: 0x" << setw(8) << stackd << std::dec << " (" << stackd << ")" << endl;
498         cout << "PSW: 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getFlags() << std::dec << endl;
499         cout << "cur PC: 0x" << std::hex << setw(8) << setfill('0') << global_cpu->getCurPC() << " next PC: 0x" << setw(8) << setfill('0') << global_cpu->getNextPC() << std::dec << endl;
500
501 }
502
503 using boost::lexical_cast;
504 using boost::bad_lexical_cast;
505
506 using namespace std;
507
508 using namespace boost::program_options;
509 namespace po = boost::program_options;
510
511 std::string progName;
512
513 int main(int argc, char* argv[])
514 {
515         progName = argv[0];
516         ifstream inFile;
517         try {
518                 po::options_description desc("Allowed options");
519                 desc.add_options()
520                 ("help,h","produce help message")
521                 ("file,f",value<string>(), "input file")
522                 ;
523
524                 po::positional_options_description p;
525                 p.add("file",1);
526
527                 po::variables_map vm;
528                 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
529                 po::notify(vm);
530
531                 if(vm.count("help")) {
532                         cout << desc << endl;
533                         return EXIT_FAILURE;
534                 }
535
536                 if(vm.count("file")) {
537 #ifdef DEBUG 
538                         cout << "going to open file " << vm["file"].as<string>() << endl;
539 #endif
540                         inFile.open(vm["file"].as<string>(), ios::in);
541                         if(!inFile) {
542                                 cerr << "Error opening file " << vm["file"].as<string>() << endl;
543                                 return EXIT_FAILURE;
544                         }
545                 }
546                 else {
547                         cout << "not input file given!" << endl << endl;
548                         cout << desc << endl;
549                         return EXIT_FAILURE;
550                 }
551         }
552         catch(std::exception& ex) {
553                 cout << ex.what() << endl;
554         }
555
556
557         string dir = "./instr/";
558
559         map<short, Iinstr*> instr;
560
561         CInstrFactory instrFab;
562         try {
563                 instrFab.loadLibsIntoMap(instr, dir);
564         }
565         catch(std::bad_alloc& e) {
566                 cerr << progName << ": bad_alloc caught " << e.what() << endl;
567                 exit(EXIT_FAILURE); 
568         }
569         catch(std::string& s) {
570                 cerr << progName << ": " << s << endl;
571                 exit(EXIT_FAILURE);
572         }
573
574         CCpu cpu(REG_COUNT, RAM_END, PROG_END);
575
576         global_cpu = &cpu;
577
578         signal(SIGINT, signalCpuBreak);
579         Iinstr::setCPU(&cpu);
580         Iext::setCPU(&cpu);
581
582         disasm disasm(instr);
583
584         Iinstr::setDisasm(&disasm);
585         Iext::setDisasm(&disasm);
586
587         global_cpu->registerExtension(new Cprog());
588         global_cpu->registerExtension(new Cuart());
589
590         vector<string> commentDefer;
591         vector<string> labelDefer;
592         std::string str = "";
593         int addr = 0;
594         boost::char_separator<char> sep(";", "", boost::keep_empty_tokens);
595         boost::tokenizer<boost::char_separator<char> > tokens(str, sep);
596         while(getline(inFile, str)) {
597                 int count = 0;
598                 tokens.assign(str);
599                 stringstream out;
600                 int type = 0;
601                 for(auto tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
602                         if(tok_iter == tokens.begin()) {
603                                 try {
604                                         type = lexical_cast<int>(*tok_iter);
605                                         count++;
606                                         continue;
607                                 }
608                                 catch(bad_lexical_cast &) {
609                                         break;
610                                 }
611                                 cout << endl;
612                         }
613                         switch(type) {
614                                 case 0:
615                                         if(count == 1) {
616                                                 try {
617                                                         addr = lexical_cast<uint32_from_hex>(*tok_iter);
618                                                         for(unsigned int i = 0; i < commentDefer.size(); i++) {
619                                                                 dataCommentsStore.insert(pair<int,string>(addr, commentDefer.at(i)));
620                                                         }
621                                                         for(unsigned int i = 0; i < labelDefer.size(); i++) {
622                                                                 dataLabelStore.insert(pair<int,string>(addr, labelDefer.at(i)));
623                                                         }
624
625                                                         commentDefer.clear();
626                                                         labelDefer.clear();
627                                                 }
628                                                 catch(bad_lexical_cast& e) {
629                                                         cerr << e.what() << endl;
630                                                         exit(EXIT_FAILURE);
631                                                 }
632                                         }
633                                         else if(count == 2) {
634                                                 try {
635                                                         CDat data = lexical_cast<uint32_from_hex>(*tok_iter);
636                                                         cpu.setRAM(addr, data);
637                                                 }
638                                                 catch(bad_lexical_cast& e) {
639                                                         cerr << e.what() << endl;
640                                                         exit(EXIT_FAILURE);
641                                                 }
642                                         }
643                                         else if(count == 4) {
644                                                 if((*tok_iter).size() > 0) {
645                                                         dataLabelStore.insert(pair<int,string>(addr, *tok_iter));
646                                                 }
647                                         }
648                                         else if(count == 5) {
649                                                 if((*tok_iter).size() > 0) {
650                                                         dataLineCommentStore.insert(pair<int,string>(addr, *tok_iter));
651                                                 }
652                                         }
653                                         break;
654                                 case 1:
655                                         if(count == 1) {
656                                                 try {
657                                                         addr = lexical_cast<uint32_from_hex>(*tok_iter);
658                                                         for(unsigned int i = 0; i < commentDefer.size(); i++) {
659                                                                 progCommentsStore.insert(pair<int,string>(addr, commentDefer.at(i)));
660                                                         }
661                                                         for(unsigned int i = 0; i < labelDefer.size(); i++) {
662                                                                 progLabelStore.insert(pair<int,string>(addr, labelDefer.at(i)));
663                                                         }
664
665                                                         commentDefer.clear();
666                                                         labelDefer.clear();
667                                                 }
668                                                 catch(bad_lexical_cast& e) {
669                                                         cerr << e.what() << endl;
670                                                         exit(EXIT_FAILURE);
671                                                 }
672                                         }
673                                         else if(count == 2) {
674                                                 Iinstr *pi = disasm.decode(*tok_iter);
675                                                 cpu.setProg(addr, pi);
676                                         }
677                                         else if(count == 4) {
678                                                 if((*tok_iter).size() > 0) {
679                                                         progLabelStore.insert(pair<int,string>(addr, *tok_iter));
680                                                 }
681                                         }
682                                         else if(count == 5) {
683                                                 if((*tok_iter).size() > 0) {
684                                                         progLineCommentStore.insert(pair<int,string>(addr, *tok_iter));
685                                                 }
686                                         }
687
688                                         break;
689                                 case 2:
690                                         if((*tok_iter).size() > 0) {
691                                                 commentDefer.push_back(*tok_iter);
692                                         }
693                                         break;
694                                 case 3:
695                                         if((*tok_iter).size() > 0) {
696                                                 labelDefer.push_back(*tok_iter);
697                                         }
698                                         break;
699                                 default:
700                                         cerr << "i was to lazy to implement the other format types for now" << endl;
701                         }
702                         count++;
703                 }
704         }
705         inFile.close();
706
707         cout << endl;
708
709 /*
710         for(int i = 0; i <= 32; i += 4) {
711                 Iinstr *pinstr = cpu.getProg(i);
712                 if(pinstr != NULL) {
713                         cout << i << " : " << std::hex << i << std::dec << " " << pinstr->toString() << endl;
714                 }
715                 else {
716                         cout << "Null at " << i << " : " << std::hex << i << endl;
717                 }
718         }
719
720         for(int i = 0; i <= 32; i += 4) {
721                 CDat data = cpu.getRAM(i);
722                 cout << i << " : " << std::hex << i << std::dec << " " << data << endl;
723         }
724 */
725 /*      cpu.setRegister(1, 4);
726         cpu.setRegister(2, 0);
727         cpu.setRAM(0,5);
728         cpu.setRAM(4,0x66334455);
729         cpu.setRAM(8,32);
730         cpu.setRAM(12,45);
731 */
732         // following: job of the bootloader
733         //set stackpointer
734         cpu.setStack(500);
735         //set return to nowhere for ret
736         cpu.setRAM(500,500);
737
738         SReadline Reader;
739
740         MyCompleterContainer Completers;
741
742         CHelpExec HelpExec(Completers);
743
744         Completers.push_back(CompleterElement("help", boost::bind1st( boost::mem_fun( &CHelpExec::operator()), &HelpExec), "Prints this message"));
745         Completers.push_back(CompleterElement("quit", &doExit, "Exits program"));
746         Completers.push_back(CompleterElement("exit", &doExit, "Exits program"));
747         Completers.push_back(CompleterElement("step [count]",&execStep, "Runs [count] ticks. if count is not given one tick is executed."));
748         Completers.push_back(CompleterElement("dreg [s] [e]",&printReg, "Prints registers. if s is given, only register s is printed. if s and e are given the registers from s to e are printed. if omitted all registers a printed."));
749         Completers.push_back(CompleterElement("ddata [s] [e]",&printRAM, "Prints RAM. if s is given, only RAM-Addr. s is printed. if s and e are given the RAM-Addrs from s to e are printed. if omitted the first 16 RAM-Addrs are printed."));
750         Completers.push_back(CompleterElement("dprog [s] [e]",&printPROG, "Prints program. if s is given, only Prog-Addr. s is printed. if s and e are given the Prog-Addrs from s to e are printed. if omitted the first 16 Prog-Addrs are printed."));
751         Completers.push_back(CompleterElement("break addr",&setBreak, "Sets a breakpoint for address addr."));
752         Completers.push_back(CompleterElement("listbreaks",&listBreaks, "Lists all breakpoints."));
753         Completers.push_back(CompleterElement("run",&execRun, "Runs till next breakpoint or end of program."));
754         Completers.push_back(CompleterElement("setpc [num]",&setPC, "Sets PC to num. if num is omitted 0 is used."));
755         Completers.push_back(CompleterElement("setreg [s] [num]",&setReg, "Sets Register s to num."));
756         Completers.push_back(CompleterElement("setdata [s] [num]",&setRam, "Sets RAM-Addr s to num."));
757         Completers.push_back(CompleterElement("status",&printStatus, "Prints status of CPU."));
758         Completers.push_back(CompleterElement("getperf",&getPerf, "Prints performance counter."));
759         Completers.push_back(CompleterElement("resetperf",&resetPerf, "Resets performance counter to 0."));
760         Completers.push_back(CompleterElement("extension",&applyToExtensions, "Write to extensions."));
761         Reader.RegisterCompletions(Completers);
762
763         string UserInput;
764         vector<string> Tokens, lastTokens;
765         bool EndOfInput = false;
766
767         //tilab g++44 doesn't like auto here
768         MyCompleterContainer::iterator Found(Completers.end());
769
770         Func lastFunc = NULL;
771
772
773         while(!exitProg) {
774                 UserInput = Reader.GetLine("> ", Tokens, EndOfInput);
775                 if(EndOfInput) {
776                         break;
777                 }
778
779                 if(!Tokens.empty()) {
780                         Found = find_if(Completers.begin(), Completers.end(), LookupFunctor(Tokens));
781
782                         if(Found != Completers.end()) {
783                                 if((*Found).get<1>() != 0) {
784                                         lastFunc = (*Found).get<1>();
785                                         lastFunc(Tokens);
786                                         lastTokens = Tokens;
787                                         //(*Found).get<1>()(Tokens);
788                                 }
789                         }
790                         else {
791                                 lastFunc = NULL;
792                                 cout << "Unknown command. 'help' displays help" << endl;
793                         }
794                 }
795                 else {
796                         if(lastFunc != NULL) {
797                                 lastFunc(lastTokens);
798                         }
799                         else {
800                                 cout << "Unknown command. 'help' displays help" << endl;
801                         }
802                 }
803         }
804
805
806 /*
807         for(int i = 0; ; i++) {
808                 try {
809                         cpu.tick();
810                         cout << " reg0: " << cpu.getRegister(0) <<  " reg1: " << cpu.getRegister(1);
811                         cout << " reg2: " << cpu.getRegister(2) <<  " reg3: " << cpu.getRegister(3);
812                         cout << " reg4: " << cpu.getRegister(4) <<  " reg5: " << cpu.getRegister(5);
813                         cout << endl << endl;
814
815                 }
816                 catch(string& e) {
817                         cerr << e << endl;
818                         break;
819                 }
820         }
821 */
822         return EXIT_SUCCESS;
823 }