/** * Created by sbosse on 3/6/15. */ var Types = require('./afvm_types'); var Manager = require('./afvm_manager'); var Code = require('./afvm_code'); var Net = require('./network'); var assert = function(condition, message) { if (!condition) throw Error("[afvm_processor]" + (typeof message !== "undefined" ? ": " + message : "")); }; var Processor = function (cf_size,cf_nmax,lut_row_size,manager,coding,CCS) { this.CF_SIZE = cf_size; this.CF_NMAX = cf_nmax; this.LUT_ROW_SIZE = lut_row_size; this.manager = manager; this.coding = coding; // Local Code Segment of this VM this.CS=[]; this.CS_SIZE=cf_size*cf_nmax; for(i=0;imanager->PT; this.PRO = this.PT[t.tk_pi]; _proc_mem = this.CS; this.CF = this.PRO.pro_cfroot * this.CF_SIZE; // Load first instruction of root frame => SETLUT _proc_instr = _proc_mem[this.CF]; this.LP = this.CF + _proc_instr.ia; // TP must be loaded from LUT[0] row, which is a copy of a LUT row // containing the actual transition table entry. this.TP = this.LutFrame(0) + this.LutOff(0); this.IP = this.PRO.pro_ip; this.CF = this.PRO.pro_cfcur * this.CF_SIZE; this.CP = 0 }; Processor.prototype.Leave = function (t) { this.PRO.pro_ip = this.IP; this.PRO.pro_cfcur = this.CF/this.CF_SIZE }; Processor.prototype.Info = function (pi) { var res; res = '[PID='+pi+' CF0='+this.PT[pi].pro_cfroot+' CF='+ this.PT[pi].pro_cfcur+' IP='+this.IP+'('+this.PT[pi].pro_ip+')'; res = res + ' GID='+this.PT[pi].pro_gid; res = res + ' PAR='+this.PT[pi].pro_par; res = res + ' DIR='+Net.Direction.tostring(this.PT[pi].pro_dir); res = res + ' AWT='+Types.Process_await.tostring(this.PT[pi].pro_await); res = res + ' ARG='+this.PT[pi].pro_await_arg; res = res+']'; return res; }; /* ** Instruction / Code Control */ Processor.prototype.CurrInstruction = function () { var _proc_mem; // Local & global CS access if (this.CP == 0) _proc_mem = this.CS; else _proc_mem = this.CCS; this.code=_proc_mem[this.CF+this.IP]; this.coding.OfCode(this.code,this.IR); }; Processor.prototype.SetInstruction = function (cf,ip) { this.CF = cf; this.IP = ip }; Processor.prototype.SetCP = function(csi) { this.CP = csi; }; Processor.prototype.NextInstruction = function(delta) { var _proc_mem; // Local & global CS access if (this.CP == 0) _proc_mem = this.CS; else _proc_mem = this.CCS; this.IP = this.IP + delta; this.coding.OfCode(_proc_mem[this.CF+this.IP],this.IR); }; Processor.prototype.GetInstruction = function(delta) { var _proc_mem; // Local & global CS access if (this.CP == 0) _proc_mem = this.CS; else _proc_mem = this.CCS; this.coding.OfCode(_proc_mem[this.CF+this.IP+delta],this.instr); return this.instr; }; Processor.prototype.MatchInstruction = function(i1,i2) { var _proc_data; _proc_data = 0; if (i1.ic == i2.ic) { _proc_data = _proc_data + 1; if (i1.io == i2.io) _proc_data = _proc_data + 1; if (i1.ia == i2.ia) _proc_data = _proc_data + 1; } return _proc_data; }; Processor.prototype.cf_addr = function (cfnum) { return cfnum * this.CF_SIZE; }; Processor.prototype.cf_num = function (cf) { return cf / this.CF_SIZE; }; /* ** LUT ROW MANAGEMENT */ Processor.prototype.LutSize = function () { var _proc_mem,_proc_data; _proc_mem = this.CS; this.coding.OfCode(_proc_mem[this.LP-1],this.instr); _proc_data = this.instr.ia / this.LUT_ROW_SIZE; return _proc_data; }; Processor.prototype.LutFlag = function (entry) { var _proc_mem,_proc_data,_proc_ref_flag; _proc_mem = this.CS; this.coding.OfCode(_proc_mem[this.LP+this.LUT_ROW_SIZE*entry],this.instr); _proc_data = this.instr.ia; _proc_ref_flag = RefKind.R_FREE; if (_proc_data == 1) _proc_ref_flag = Types.RefKind.R_PAR; if (_proc_data == 2) _proc_ref_flag = Types.RefKind.R_VAR; if (_proc_data == 3) _proc_ref_flag = Types.RefKind.R_ACT; if (_proc_data == 4) _proc_ref_flag = Types.RefKind.R_FUN; if (_proc_data == 5) _proc_ref_flag = Types.RefKind.R_FUNG; if (_proc_data < 0) _proc_ref_flag = Types.RefKind.R_SIGH; if (_proc_data == 7) _proc_ref_flag = Types.RefKind.R_TRANS return _proc_ref_flag }; Processor.prototype.SetLutFlag = function (entry,flag) { var _proc_mem,_proc_data; _proc_mem = this.CS; switch(flag) { case Types.RefKind.R_FREE: _proc_data = 0; break; case Types.RefKind.R_PAR: _proc_data = 1; break; case Types.RefKind.R_VAR: _proc_data = 2; break; case Types.RefKind.R_ACT: _proc_data = 3; break; case Types.RefKind.R_FUN: _proc_data = 4; break; case Types.RefKind.R_FUNG: _proc_data = 5; break; case Types.RefKind.R_SIGH: _proc_data = -1; break; //not very meaningful ! case Types.RefKind.R_TRANS: _proc_data = 7; break; }; _proc_mem[this.LP+this.LUT_ROW_SIZE*entry] = this.coding.ToCodeM(Types.Command.DATA,_proc_data); }; Processor.prototype.LutFlagSig = function (entry) { var _proc_mem,_proc_data; _proc_mem = this.CS; this.coding.OfCode(_proc_mem[this.LP+this.LUT_ROW_SIZE*entry],this.instr); _proc_data = Math.abs(this.instr.ia); return _proc_data; }; Processor.prototype.SetLutFlagSig = function(entry,sig) { var _proc_mem,_proc_data; _proc_mem = this.CS; _proc_data = -sig; _proc_mem[this.LP + this.LUT_ROW_SIZE * entry] = this.coding.ToCodeM(Types.Command.DATA, _proc_data); }; /* ** LUT offset ROW[1] is relative to CF start (LUT Sec.) */ Processor.prototype.LutOff = function (entry) { var _proc_mem,_proc_data; _proc_mem = this.CS; this.coding.OfCode(_proc_mem[this.LP + this.LUT_ROW_SIZE * entry + 1],this.instr); _proc_data = this.instr.ia; return _proc_data; }; Processor.prototype.SetLutOff = function (entry,off) { var _proc_mem,_proc_data; _proc_mem = this.CS; _proc_mem[this.LP + this.LUT_ROW_SIZE * entry + 1] = this.coding.ToCodeM(Types.Command.DATA, off); }; Processor.prototype.LutFrame = function (entry) { var _proc_mem,_proc_data; _proc_mem = this.CS; this.coding.OfCode(_proc_mem[this.LP + this.LUT_ROW_SIZE * entry + 2],this.instr); _proc_data = this.instr.ia; return _proc_data }; Processor.prototype.SetLutFrame = function (entry,off) { var _proc_mem,_proc_data; _proc_mem = this.CS; _proc_mem[this.LP + this.LUT_ROW_SIZE * entry + 2] = this.coding.ToCodeM(Types.Command.DATA, off); }; Processor.prototype.LutSec = function (entry) { var _proc_mem,_proc_data; _proc_mem = this.CS; this.coding.OfCode(_proc_mem[this.LP + this.LUT_ROW_SIZE * entry + 3],this.instr); _proc_data = this.instr.ia; return _proc_data }; Processor.prototype.SetLutSec = function (entry,off) { var _proc_mem; _proc_mem = this.CS; _proc_mem[this.LP + this.LUT_ROW_SIZE * entry + 3] = this.coding.ToCodeM(Types.Command.DATA, off); }; /* ** DATA */ Processor.prototype.Store = function (cf,off,data) { var _proc_mem; _proc_mem = this.CS; _proc_mem[cf+off] = this.coding.ToCodeM(Types.Command.DATA,data); }; Processor.prototype.Fetch = function (cf,off) { var _proc_mem; _proc_mem = this.CS; this.coding.OfCode(_proc_mem[cf+off],this.instr); return this.instr.ia; }; /* ** FRAME */ Processor.prototype.RelFrame = function (cf) { var _proc_cf,_proc_data; _proc_cf = cf / this.CF_SIZE; if (_proc_cf == this.PRO.pro_cfroot) _proc_data = -1; else assert(false, "RelFrame: linked frames not supported yet"); // TBD !!! return _proc_data }; Processor.prototype.AbsFrame = function (cf) { var _proc_data; if (cf == -1) _proc_data = this.PRO.pro_cfroot * this.CF_SIZE; else assert(false, "AbsFrame: linked frames not supported yet"); // TBD !!! return _proc_data; }; Processor.prototype.FrameOfAddr = function (addr) { var _proc_cf; _proc_cf = addr / this.CF_SIZE; return _proc_cf }; Processor.prototype.OffsetOfAddr = function (addr) { var _proc_cf,_proc_off; _proc_cf = addr / this.CF_SIZE; _proc_off = addr - (_proc_cf * this.CF_SIZE); return _proc_off; }; /* ** Init code range */ Processor.prototype.Code_init = function(cs,cfnum,offstart,offend,cmd,val) { var i,_proc_cf,_proc_mem; _proc_mem = cs; _proc_cf = this.cf_addr(cfnum); for (i = offstart; i <= offend; i++) { _proc_mem[_proc_cf + i] = this.coding.ToCodeM(cmd,val); } }; Processor.prototype.Code_set = function(cs,cfnum,off,cmd,val) { var _proc_cf,_proc_mem; _proc_mem = cs; _proc_cf = this.cf_addr(cfnum); _proc_mem[_proc_cf + off] = this.coding.ToCodeM(cmd,val); }; String.prototype.replaceAll = function (find, replace) { var str = this; return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace); }; /* ** Read code from string buffer */ Processor.prototype.Code_read = function(cfnum,off,buf) { var csoff; /* ** Buffer format: HHHH HHHH ... ** All command codes in hexadecimal format */ csoff = cfnum * this.CF_SIZE; var buf_flat = buf.replaceAll('\n',' '); var tokens = buf_flat.split(' '); for (var i in tokens) { var token = tokens[i]; if (token != '') { this.CS[csoff+off] = parseInt(token,16); off++; }; }; // Add TWO END commands to mark the end of teh code frame this.CS[csoff+off] = this.coding.ToCodeM(Types.Command.END,0); this.CS[csoff+off+1] = this.coding.ToCodeM(Types.Command.END,0); return (off+2); }; /* ** Formatted printer for code segments. ** Returns a string text. */ Processor.prototype.Code_print = function(cfroot) { var end=0; var str=''; var off=cfroot*this.CF_SIZE; while (off < this.CS_SIZE && end < 2) { this.coding.OfCode(this.CS[off],this.instr); if (this.instr.ic==Types.Command.END) end++; if (end<2) str=str+'['+off+'] '+this.coding.CodePrint(this.CS[off])+'\n'; off++; }; return str; }; /* ** Copy code range */ Processor.prototype.Code_copy = function ( cs, cfnum_src, cfnum_dst, offstart, offend) { var i,_proc_mem,_proc_cf,_proc_code; _proc_mem = cs; for (i = offstart; i <= offend; i++) { _proc_cf = this.cf_addr(cfnum_src); _proc_code = _proc_mem[_proc_cf + i]; _proc_cf = this.cf_addr(cfnum_dst); _proc_mem[_proc_cf + i] = _proc_code; } }; /* ** Transfer a value to code with sign extension if necessary. ** Returns code frame offset of next instruction. */ Processor.prototype.Code_make_val = function ( cs, cfnum, off, v) { var _proc_mem, _proc_cf, _proc_off; _proc_mem = cs; _proc_off = off; _proc_cf = this.cf_addr(cfnum); // TBD EXT(SIGN) -- _proc_mem[_proc_cf + _proc_off] = this.coding.ToCodeM(Types.Command.VAL,v); _proc_off = _proc_off + 1; return _proc_off; }; /* **- Save state (#CF,IP) in the current TRANS-BOOT section of the current process */ Processor.prototype.proc_savestate = function(init,ipoff) { // The LUT must be reinitialized after migration and forking!!!! // Be aware of parameter initialization!!! It is done again. The // parameter values must be coded and dumped to the frame boot section. // Must be done by the compiler before the migration or forking (move/fork) takes place. // Here the current transition table boot section is modified by inserting // a long branch to the current (CF,IP+ipoff) location. // // TP points to the start of the BOOT section ogf the current transition table word _proc_mem = this.CS; _proc_mem[this.TP] = this.coding.ToCodeM(Types.Command.VAL, this.IP + ipoff); // // // TBD: CF <> cfroot! => -LINK# !!! _proc_mem[this.TP + 1] = this.coding.ToCodeM(Types.Command.VAL, -1); _proc_mem[this.TP + 2] = this.coding.ToCodeM(Types.Command.BRANCHL, 0); // // init=false: Suspend with direct branch from frame boot section to current transition boot section // init=true: Suspend with full frame (re)initialization // if (init) _proc_mem[this.LP - 4] = this.coding.ToCodeM(Types.Command.BRANCH, 2); else _proc_mem[this.LP - 4] = this.coding.ToCodeM(Types.Command.NOP, 0); }; /* ** Release a process (decriptor & ressources) ** TBD: linked code frames */ Processor.prototype.proc_free = function(manager,pro) { var cfq; cfq = manager.CQ[pro.pro_vm]; cfq.push(pro.pro_cfroot); pro.pro_flag = Types.Process_state.PROC_NOTUSED; pro.pro_cfroot = -1; pro.pro_cfcur = -1; pro.pro_vm = -1; pro.pro_ip = -1; pro.pro_dir = Net.Direction.ORIGIN; pro.pro_pos = Net.Position(0, 0); pro.pro_gid = -1; pro.pro_par = -1; manager.PQ.push(Types.Token(pro.pro_id, Types.Token_colour.TK_DATA, '', '')); // TBD: tracking and releasing CF chain }; module.exports = { Processor: Processor };