SimRam/main.cpp
2012-07-28 15:59:14 +02:00

358 lines
13 KiB
C++
Executable file

//============================================================================
// Name : SimRam
// Author : Andrea Bontempi
// Version : 0.1
// Copyright : GNU GPL3
// Description : RAM Emulator (Von Neumann Machine)
//============================================================================
#include <iostream>
#include <fstream>
#include <string>
#include <boost/program_options.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include "lib.h"
#define REGNUMBER 5 // Default number of registers.
using namespace std;
using namespace boost::program_options;
int main(int argc, char **argv) {
options_description desc("SimRam - RAM Emulator");
desc.add_options()
("help,h", "prints this")
("verbose,v", "enable verbose mode")
("registers,r", value<int>(), "set max number of virtual registers")
("input,i", value<string>(), "input file")
;
positional_options_description p;
p.add("input", -1);
variables_map vm;
store(command_line_parser(argc, argv).
options(desc).positional(p).run(), vm);
notify(vm);
if(vm.count("help"))
{
cout << desc << endl;
return 1;
}
int regnumber;
if(vm.count("reg"))
{
regnumber = vm["reg"].as<int>();
if(vm.count("verbose")) cout << "The number of virtual registers was set to " << regnumber << endl;
} else
{
regnumber = REGNUMBER;
}
string filename = "input.ram";
if(vm.count("input"))
{
filename = vm["input"].as<string>();
if(vm.count("verbose")) cout << "The source code was set to '" << filename << "'" << endl;
}
ifstream source_file (filename.c_str());
if (!source_file.is_open())
{
cout << "<!> Unable to open file" << endl;
return EXIT_FAILURE;
}
int registers[regnumber];
memset(registers,0,sizeof(int)*regnumber);
int inpointer = 0;
string intapetmp;
string outtape;
vector<string> intape;
cout << "Insert input tape (use comma for insert new value): ";
cin >> intapetmp;
boost::algorithm::split(intape, intapetmp, boost::algorithm::is_any_of(","));
if(vm.count("verbose")) cout<<"There are " << intape.size() <<" values in the tape." << endl;
string fetch;
// TODO search LABEL.
map<string, int> know_label;
while(!source_file.eof())
{
getline(source_file, fetch);
if(fetch == "halt" || fetch[0] == '#') continue;
vector<string> line;
boost::algorithm::split(line, fetch, boost::algorithm::is_any_of(" "));
if(line[0] == "label") know_label[line[1]] = source_file.tellg();
}
source_file.clear();
source_file.seekg(0, ios::beg);
while(!source_file.eof())
{
// Fetch
getline(source_file, fetch);
if(fetch == "halt")
{
cout<<"Completed execution with output: "<<outtape<<endl;
source_file.close();
return EXIT_SUCCESS;
} else if(fetch == "" || fetch[0] == '#')
{
continue;
}
vector<string> line;
boost::algorithm::split(line, fetch, boost::algorithm::is_any_of(" "));
// Decode / Execute
// TODO remove pointer overflow on registers
// TODO usa una hashmap con comando --> puntatore funzione per migliorare esecuzione.
if(line[0] == "read")
{
if(vm.count("verbose")) cout<<"Read: "<<intape[inpointer]<<" --> M["<<line[1]<<"]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
if(inpointer >= intape.size())
{
cerr << "<!> The input tape is finished." << endl;
return EXIT_FAILURE;
}
registers[boost::lexical_cast<int>(line[1])] = boost::lexical_cast<int>(intape[inpointer]);
inpointer++;
} else if(line[0] == "read*")
{
if(vm.count("verbose")) cout<<"Read: "<<intape[inpointer]<<" --> M[M["<<line[1]<<"]]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
if(error_registers(registers[boost::lexical_cast<int>(line[1])],regnumber)) return EXIT_FAILURE;
if(inpointer >= intape.size())
{
cerr<<"<!> The input tape is finished."<<endl;
return EXIT_FAILURE;
}
registers[registers[boost::lexical_cast<int>(line[1])]] = boost::lexical_cast<int>(intape[inpointer]);
inpointer++;
} else if(line[0] == "write")
{
if(vm.count("verbose")) cout<<"Write: M["<<line[1]<<"] = "<<registers[boost::lexical_cast<int>(line[1])]<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
outtape += boost::lexical_cast<string>(registers[boost::lexical_cast<int>(line[1])]);
} else if(line[0] == "write=")
{
if(vm.count("verbose")) cout<<"Write: "<<line[1]<<endl;
outtape += line[1];
} else if(line[0] == "write*")
{
if(vm.count("verbose")) cout<<"Write: M[M["<<line[1]<<"]] = "<<registers[registers[boost::lexical_cast<int>(line[1])]]<<endl;
outtape += boost::lexical_cast<string>(registers[registers[boost::lexical_cast<int>(line[1])]]);
} else if(line[0] == "load")
{
if(vm.count("verbose")) cout<<"M["<<line[1]<<"] --> Working Memory"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
registers[0] = registers[boost::lexical_cast<int>(line[1])];
} else if(line[0] == "load=")
{
if(vm.count("verbose")) cout<<"Value: "<<line[1]<<" --> Working Memory"<<endl;
registers[0] = boost::lexical_cast<int>(line[1]);
} else if(line[0] == "load*")
{
if(vm.count("verbose")) cout<<"M[M["<<line[1]<<"]] --> Working Memory"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
if(error_registers(registers[boost::lexical_cast<int>(line[1])],regnumber)) return EXIT_FAILURE;
registers[0] = registers[registers[boost::lexical_cast<int>(line[1])]];
} else if(line[0] == "store")
{
if(vm.count("verbose")) cout<<"Working Memory --> M["<<line[1]<<"]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
registers[boost::lexical_cast<int>(line[1])] = registers[0];
} else if(line[0] == "store*")
{
if(vm.count("verbose")) cout<<"Working Memory --> M[M["<<line[1]<<"]]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
if(error_registers(registers[boost::lexical_cast<int>(line[1])],regnumber)) return EXIT_FAILURE;
registers[registers[boost::lexical_cast<int>(line[1])]] = registers[0];
} else if(line[0] == "add")
{
if(vm.count("verbose")) cout<<"M[0] + M["<<line[1]<<"] --> M[0]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
registers[0] = registers[0] + registers[boost::lexical_cast<int>(line[1])];
} else if(line[0] == "add=")
{
if(vm.count("verbose")) cout<<"M[0] + "<<line[1]<<" --> M[0]"<<endl;
registers[0] = registers[0] + boost::lexical_cast<int>(line[1]);
} else if(line[0] == "add*")
{
if(vm.count("verbose")) cout<<"M[0] + M[M["<<line[1]<<"]] --> M[0]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
if(error_registers(registers[boost::lexical_cast<int>(line[1])],regnumber)) return EXIT_FAILURE;
registers[0] = registers[0] + registers[registers[boost::lexical_cast<int>(line[1])]];
} else if(line[0] == "sub")
{
if(vm.count("verbose")) cout<<"M[0] - M["<<line[1]<<"] --> M[0]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
registers[0] = registers[0] - registers[boost::lexical_cast<int>(line[1])];
} else if(line[0] == "sub=")
{
if(vm.count("verbose")) cout<<"M[0] - "<<line[1]<<" --> M[0]"<<endl;
registers[0] = registers[0] - boost::lexical_cast<int>(line[1]);
} else if(line[0] == "sub*")
{
if(vm.count("verbose")) cout<<"M[0] - M[M["<<line[1]<<"]] --> M[0]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
if(error_registers(registers[boost::lexical_cast<int>(line[1])],regnumber)) return EXIT_FAILURE;
registers[0] = registers[0] - registers[registers[boost::lexical_cast<int>(line[1])]];
} else if(line[0] == "mul")
{
if(vm.count("verbose")) cout<<"M[0] * M["<<line[1]<<"] --> M[0]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
registers[0] = registers[0] * registers[boost::lexical_cast<int>(line[1])];
} else if(line[0] == "mul=")
{
if(vm.count("verbose")) cout<<"M[0] * "<<line[1]<<" --> M[0]"<<endl;
registers[0] = registers[0] * boost::lexical_cast<int>(line[1]);
} else if(line[0] == "mul*")
{
if(vm.count("verbose")) cout<<"M[0] * M[M["<<line[1]<<"]] --> M[0]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
if(error_registers(registers[boost::lexical_cast<int>(line[1])],regnumber)) return EXIT_FAILURE;
registers[0] = registers[0] * registers[registers[boost::lexical_cast<int>(line[1])]];
} else if(line[0] == "div")
{
if(vm.count("verbose")) cout<<"M[0] / M["<<line[1]<<"] --> M[0]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
registers[0] = registers[0] / registers[boost::lexical_cast<int>(line[1])];
} else if(line[0] == "div=")
{
if(vm.count("verbose")) cout<<"M[0] / "<<line[1]<<" --> M[0]"<<endl;
registers[0] = registers[0] / boost::lexical_cast<int>(line[1]);
} else if(line[0] == "div*")
{
if(vm.count("verbose")) cout<<"M[0] / M[M["<<line[1]<<"]] --> M[0]"<<endl;
if(error_registers(boost::lexical_cast<int>(line[1]),regnumber)) return EXIT_FAILURE;
if(error_registers(registers[boost::lexical_cast<int>(line[1])],regnumber)) return EXIT_FAILURE;
registers[0] = registers[0] / registers[registers[boost::lexical_cast<int>(line[1])]];
} else if(line[0] == "jmp" || line[0] == "jump")
{
if(vm.count("verbose")) cout<<"Jump to LABEL '"<<line[1]<<"'"<<endl;
if(know_label[line[1]] == NULL)
{
cerr<<"<!> Label '"<<line[1]<<"' not found."<<endl;
return EXIT_FAILURE;
}
source_file.seekg(know_label[line[1]], ios::beg);
} else if(line[0] == "jz")
{
if(registers[0] == 0)
{
if(vm.count("verbose")) cout<<"Jump to LABEL '"<<line[1]<<"'"<<endl;
if(know_label[line[1]] == NULL)
{
cerr<<"<!> Label '"<<line[1]<<"' not found."<<endl;
return EXIT_FAILURE;
}
source_file.seekg(know_label[line[1]], ios::beg);
}
else
{
if(vm.count("verbose")) cout<<"Can't jump: M[0] != 0 "<<endl;
}
} else if(line[0] == "jgz")
{
if(registers[0] > 0)
{
if(vm.count("verbose")) cout<<"Jump to LABEL '"<<line[1]<<"'"<<endl;
if(know_label[line[1]] == NULL)
{
cerr<<"<!> Label '"<<line[1]<<"' not found."<<endl;
return EXIT_FAILURE;
}
source_file.seekg(know_label[line[1]], ios::beg);
}
else
{
if(vm.count("verbose")) cout<<"Can't jump: M[0] < 0 "<<endl;
}
} else if(line[0] == "label")
{
if(vm.count("verbose")) cout<<"Found LABEL '"<<line[1]<<"'"<<endl;
} else if(line[0] == "debug")
{
if(!vm.count("verbose")) break;
switch(boost::lexical_cast<int>(line[1]))
{
case 1:
cout<<"Registers dump: "<<endl;
for(int i = 0; i < regnumber; i++)
{
cout<<" M["<<i<<"] = "<<registers[i]<<endl;
}
break;
default:
cerr<<"<!> Invalid debug option '"<<line[1]<<"'"<<endl;
return EXIT_FAILURE;
}
} else
{
cerr<<"<!> Syntax error '"<<fetch<<"'"<<endl;
return EXIT_FAILURE;
}
}
source_file.close();
return EXIT_SUCCESS;
}