UNPKG

friscjs

Version:

FRISC processor simulator in JavaScript

132 lines (89 loc) 6.02 kB
# 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); };