friscjs
Version:
FRISC processor simulator in JavaScript
132 lines (89 loc) • 6.02 kB
Markdown
# FRISC API
## Introduction
FRISCjs user interfaces (the [browser Web app](https://github.com/izuzak/FRISCjs/blob/master/main.html) and [NodeJs console app](https://github.com/izuzak/FRISCjs/blob/master/main.js)) are built as a layer on top of two generic, pure-JavaScript libraries.
This document describes the API of these two libraries: the FRISC assembler and the FRISC simulator.
Using this API, other user interfaces may be built for any platform supporting JavaScript.
## Installation
In node, install using npm:
npm install friscjs
and then access the assembler and simulator:
var friscjs = require("friscjs");
var asm = friscjs.assembler;
var sim = friscjs.simulator;
In a browser, link to the browser script that contains both the assembler and simulator:
<script src="lib/friscjs-browser.js"></script>
and then access the assembler and simulator:
var asm = friscjs.assembler;
var sim = friscjs.simulator;
## FRISC assembler
The assembler used for assembling FRISC source code using the ``parse()`` method:
``var result = asm.parse(frisc_code_string);``
where ``frisc_code_string`` is a single string containing FRISC code.
E.g.:
lab1 ADD R1, R2, R3
lab2 ADD r2, 5, r5
The result of invoking ``parse()`` is a ``result`` object containing two properties: ``result.mem`` and ``result.ast``.
``result.ast`` is the parser AST output and should be used for debugging purposes only.
It is an array of parse objects, one for each instruction in the source code.
E.g.:
[ { op: 'ADD',
optype: 'aluop',
alusrc1: { type: 'reg', value: [ 'R', '1' ] },
alusrc2: { type: 'reg', value: [ 'R', '2' ] },
aludest: { type: 'reg', value: [ 'R', '3' ] },
curloc: 0,
line: 2,
machineCode: '00100000000000000000000000000000' },
{ op: 'ADD',
optype: 'aluop',
alusrc1: { type: 'reg', value: [ 'r', '2' ] },
alusrc2: { type: 'num', value: 5 },
aludest: { type: 'reg', value: [ 'r', '5' ] },
curloc: 4,
line: 3,
machineCode: '00100100000000000000000000000101' },
]
``result.mem`` is the binary code of the assembled program, which should be loaded into the FRISC simulator.
The binary code is an array of 8-character strings, each string representing the binary value to be stored in FRISC memory at that location.
E.g.:
``[ '00000000', '00000000', '00000000', '00100000', '00000101', '00000000', '00000000', '00100100' ]``
In case of parsing errors, the ``parse()`` method will throw an exception which contains ``line`` and ``column`` properties which denote the line and column at which the parsing error occured:
try {
var result = asm.parse(frisc_code_string);
} catch (e) {
console.log("Parsing error on line " + e.line + " column " + e.column + " -- " + e.toString());
}
## FRISC simulator
The simulator is a constructor for instantiating FRISCjs simulator objects:
``var simulator = new sim();``
A simulator instance object exposes two FRISC components: FRISC memory (`simulator.MEM`) and FRISC cpu (`simulator.MEM`).
### FRISC memory component
The FRISC memory component exposes the following data properties and functions:
* ``MEM._size`` - the size of the memory defined as the number of 1-byte locations. By default, the memory has 256*1024 locations, or 256K.
* ``MEM._memory`` - the memory array itself, containing integers representing bytes at specific locations.
* ``MEM.reset()`` - helper function that sets the value of each memory location to 0.
* ``MEM.loadByteString(program)``, ``MEM.loadBytes(program)``, ``MEM.loadBinaryString(program)`` - helper functions for loading binary FRISC code into memory. ``loadBinaryString`` should be used to load the result of the FRISC assember into the memory:
``simulator.MEM.loadBinaryString(result.mem);``
* ``MEM.readb(addr)``, ``MEM.readw(addr)``, ``MEM.read(addr)`` - helper functions for reading a 1B, 2B or 4B integer value from locations starting from addr.
* ``MEM.writeb(addr, val)``, ``MEM.writeb(addr, val)``, ``MEM.write(addr, val)`` - helper functions for writing a 1B, 2B or 4B integer value val to locations starting from addr.
### FRISC cpu component
The FRISC cpu component exposes the following data properties and functions:
* ``CPU._r`` - a map of the registers of the FRISC cpu: ``{r0:0, r1:0, r2:0, r3:0, r4:0, r5:0, r6:0, r7:0, pc:0, sr:0, iif:1}``
* ``CPU._frequency`` - an integer defining the frequency of the cpu in Hz, by default 1 (Hz).
* ``CPU.run()`` - starts or resumes the cpu, periodically calling ``CPU.performCylce``
* ``CPU.pause()`` - pauses cpu execution
* ``CPU.stop()`` - stops cpu execution
* ``CPU.performCycle()`` - executes one FRISC instruction pointed to by the program counter
* ``CPU.reset()`` - resets the state of the cpu, setting register values to 0 and iif to 1
* ``CPU._decode(instruction)`` - decodes a FRISC instruction (passed as an integer) and returns the instruction's operation name and parameters
The FRISC cpu component also invokes the following event handlers, if they are specified:
* ``CPU.onStop()`` - invoked after the ``CPU.stop()`` method was called
* ``CPU.onBeforeRun()`` - invoked after the ``CPU.run()`` method was called
* ``CPU.onBeforeCycle()`` - invoked at the start of every invocation of ``CPU.performCycle()``
* ``CPU.onBeforeExecute(instruction)`` - invoked during every invocation of ``CPU.performCycle()``, after the instruction to be executed was decoded, but before its execution
* ``CPU.onAfterCycle()`` - invoked at the end of every invocation of ``CPU.performCylce()``
Here is an example of setting an event handler that outputs the FRISC cpu register state after the cpu was stopped:
simulator.CPU.onStop = function() {
console.log("FRISC processor stopped!");
console.log("STATUS of registers:", simulator.CPU._r);
};