Skip to content

Latest commit

 

History

History
131 lines (89 loc) · 5.75 KB

API.markdown

File metadata and controls

131 lines (89 loc) · 5.75 KB

FRISC API

Introduction

FRISCjs user interfaces (the browser Web app and NodeJs console app) 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);
};