friscjs
Version:
FRISC processor simulator in JavaScript
228 lines (195 loc) • 7.84 kB
JavaScript
var fs = require("fs");
var path = require("path");
var asm = require("./../lib/index.js").assembler;
var sim = require("./../lib/index.js").simulator;
var argv = process.argv;
var isVerboseMode = argv.indexOf("-v") > -1;
if (isVerboseMode) {
argv.splice(argv.indexOf("-v"), 1);
}
var debug = function(str) {
if (isVerboseMode) {
console.error(str);
}
};
var cpufreq = 1000;
if (argv.indexOf("-cpufreq") > -1) {
cpufreq = parseInt(argv[argv.indexOf("-cpufreq") + 1], 10);
argv.splice(argv.indexOf("-cpufreq") + 1, 1);
argv.splice(argv.indexOf("-cpufreq"), 1);
}
var memsize = 256*1024;
if (argv.indexOf("-memsize") > -1) {
memsize = 1024*parseInt(argv[argv.indexOf("-memsize") + 1], 10);
argv.splice(argv.indexOf("-memsize") + 1, 1);
argv.splice(argv.indexOf("-memsize"), 1);
}
console.error("");
console.error("*********************************************************");
console.error("** FRISCjs - FRISC simulator in JavaScript");
console.error("** ");
console.error("** Usage instructions:");
console.error("** ");
console.error("** pass filename argument with the FRISC program:");
console.error("** > node main.js filename");
console.error("** or input the FRISC program via stdin:");
console.error("** > cat filename | node main.js");
console.error("** ");
console.error("** Note: the simulator has a memory module of 256KB,");
console.error("** i.e. from 0x00000000 to 0x0003FFFF.");
console.error("** ");
console.error("** Verbose debugging mode can be turned on by passing");
console.error("** specifying the -v flag, e.g.:");
console.error("** ");
console.error("** > node main.js -v filename");
console.error("** or");
console.error("** > cat filename | node main.js -v");
console.error("** ");
console.error("** The CPU frequency (in Hz) can be set with the -cpufreq");
console.error("** flag argument (default value is 1000):");
console.error("** ");
console.error("** > node main.js -cpufreq 2 filename");
console.error("** or");
console.error("** > cat filename | node main.js -cpufreq 2");
console.error("** ");
console.error("** Memory size (in number of 1K locations) can be set with");
console.error("** the -memsize flag argument (default value is 256):");
console.error("** ");
console.error("** > node main.js -memsize 64 filename");
console.error("** or");
console.error("** > cat filename | node main.js -memsize 64");
console.error("** ");
console.error("** Execution flow:");
console.error("** ");
console.error("** 1) compilation of the FRISC program to machine code ");
console.error("** 2) step-by-step execution of FRISC program ");
console.error("** with logging of processor state at each step ");
console.error("** to stderr (if in verbose mode)");
console.error("** 3) output of r6 to stdout after program execution");
console.error("** ");
console.error("** GUI version of FRISC simulator is available at:");
console.error("** ");
console.error("** http://fer-ppj.github.com/FRISCjs/main.html");
console.error("** ");
console.error("** Bug reports:");
console.error("** ");
console.error("** mailto:ppj@zemris.fer.hr, or ");
console.error("** http://github.com/fer-ppj/FRISCjs/issues");
console.error("*********************************************************");
console.error("");
// determine method for acquiring the input program
if (argv.length > 2) {
// the process is passed an argument which points to a filename with the
// program
var filename = path.normalize(argv[2]);
console.error("");
console.error("*********************************************************");
console.error("Reading program from file: " + filename);
console.error("*********************************************************");
console.error("");
if (!(fs.existsSync(filename))) {
console.error("ERROR: File does not exist!");
console.log("ERROR");
} else {
var program = fs.readFileSync(filename);
runProgram(program);
}
} else {
// the process should read the program from process.stdin
console.error("");
console.error("*********************************************************");
console.error("Reading program from stdin, line-by-line.");
console.error("Press CTRL+D to stop reading and execute program.");
console.error("*********************************************************");
console.error("");
var program = "";
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function (chunk) {
program += chunk;
});
process.stdin.on('end', function () {
runProgram(program);
});
}
function cpuStateToString(simulator) {
var retVal = "";
for (var key in simulator.CPU._r) {
if (key !== 'sr') {
retVal += key + ": " + simulator.CPU._r[key].toString() + " ";
} else {
retVal += key + ": " + simulator.CPU._r[key].toString() + " ( ";
for (var flag in simulator.CPU._f) {
retVal += flag + ": " + simulator.CPU._getFlag(simulator.CPU._f[flag]) + " ";
}
retVal += ") ";
}
}
return retVal;
}
function instructionToString(instruction) {
if (typeof instruction.args === 'undefined' || instruction.args === null) {
return instruction.op;
} else {
return instruction.op + " " + instruction.args.join(" ");
}
}
function runProgram(frisc_asmsource) {
console.error("");
console.error("*********************************************************");
console.error("Input FRISC program:");
console.error("*********************************************************");
console.error("");
console.error(frisc_asmsource.toString());
console.error("");
console.error("*********************************************************");
console.error("Parsing input FRISC program.");
console.error("*********************************************************");
console.error("");
var result;
try {
result = asm.parse(frisc_asmsource.toString());
} catch (e) {
console.error("Parsing error on line " + e.line + " column " + e.column + " -- " + e.toString());
return;
}
simulator = new sim();
simulator.MEM._size = memsize;
simulator.CPU._frequency = cpufreq;
simulator.CPU.onBeforeRun = function() {
console.error("");
console.error("*********************************************************");
console.error("Starting simulation!");
console.error("*********************************************************");
console.error("");
};
simulator.CPU.onBeforeCycle = function() {
debug("");
debug("*********************************************************");
debug("New CPU cycle starting!");
debug("*********************************************************");
debug("");
debug("## CPU state: " + cpuStateToString(simulator));
};
simulator.CPU.onAfterCycle = function() {
debug("## CPU state: " + cpuStateToString(simulator));
};
simulator.CPU.onBeforeExecute = function(instruction) {
debug("## Executing FRISC instruction: " + instructionToString(instruction));
};
simulator.CPU.onStop = function() {
console.error("");
console.error("*********************************************************");
console.error("FRISC processor stopped! Status of CPU R6: " + simulator.CPU._r.r6);
console.error("*********************************************************");
console.error("");
console.log(simulator.CPU._r.r6);
};
try {
simulator.MEM.loadBinaryString(result.mem);
} catch (e) {
console.error("Loading error -- " + e.toString());
return;
}
simulator.CPU.run();
}