mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-02-19 23:29:06 +00:00
converted some worker helper files to .ts (loadGen)
This commit is contained in:
parent
613277f0e9
commit
2759acd958
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ scripts
|
|||||||
blog
|
blog
|
||||||
local
|
local
|
||||||
release
|
release
|
||||||
|
gen
|
||||||
|
@ -1,19 +1,74 @@
|
|||||||
|
|
||||||
var Assembler = function(spec) {
|
type AssemblerVar = {
|
||||||
|
bits : number,
|
||||||
|
toks : string[],
|
||||||
|
iprel? : boolean,
|
||||||
|
ipofs? : number
|
||||||
|
}
|
||||||
|
|
||||||
|
type AssemblerRule = {
|
||||||
|
fmt : string,
|
||||||
|
bits : (string | number)[],
|
||||||
|
// added at runtime
|
||||||
|
re? : RegExp,
|
||||||
|
prefix? : string,
|
||||||
|
varlist? : string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
type AssemblerVarList = {[name:string] : AssemblerVar};
|
||||||
|
|
||||||
|
type AssemblerLine = {line:number, offset:number, nbits:number, insns?:string};
|
||||||
|
|
||||||
|
type AssemblerFixup = {
|
||||||
|
sym:string,
|
||||||
|
ofs:number,
|
||||||
|
bitlen:number,
|
||||||
|
bitofs:number,
|
||||||
|
line:number,
|
||||||
|
iprel:boolean,
|
||||||
|
ipofs:number
|
||||||
|
};
|
||||||
|
|
||||||
|
type AssemblerSpec = {
|
||||||
|
name : string,
|
||||||
|
width : number,
|
||||||
|
vars : AssemblerVarList,
|
||||||
|
rules : AssemblerRule[]
|
||||||
|
}
|
||||||
|
|
||||||
|
type AssemblerInstruction = {opcode:number, nbits : number};
|
||||||
|
|
||||||
|
type AssemblerLineResult = {error:string} | AssemblerInstruction;
|
||||||
|
|
||||||
|
type AssemblerError = {msg:string, line:number};
|
||||||
|
|
||||||
|
type AssemblerState = {
|
||||||
|
ip: number,
|
||||||
|
line: number,
|
||||||
|
origin: number,
|
||||||
|
codelen: number,
|
||||||
|
intermediate: any,
|
||||||
|
output: number[],
|
||||||
|
lines: AssemblerLine[],
|
||||||
|
errors: AssemblerError[],
|
||||||
|
fixups: AssemblerFixup[]
|
||||||
|
}
|
||||||
|
|
||||||
|
var Assembler = function(spec : AssemblerSpec) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var ip = 0;
|
var ip = 0;
|
||||||
var origin = 0;
|
var origin = 0;
|
||||||
var linenum = 0;
|
var linenum = 0;
|
||||||
var symbols = {};
|
var symbols : {[name:string] : {value:number}} = {};
|
||||||
var errors = [];
|
var errors : AssemblerError[] = [];
|
||||||
var outwords = [];
|
var outwords : number[] = [];
|
||||||
var asmlines = [];
|
var asmlines : AssemblerLine[] = [];
|
||||||
var fixups = [];
|
var fixups : AssemblerFixup[] = [];
|
||||||
var width = 8;
|
var width = 8;
|
||||||
var codelen = 0;
|
var codelen = 0;
|
||||||
var aborted = false;
|
var aborted = false;
|
||||||
|
|
||||||
function rule2regex(rule, vars) {
|
function rule2regex(rule : AssemblerRule, vars : AssemblerVarList) {
|
||||||
var s = rule.fmt;
|
var s = rule.fmt;
|
||||||
var varlist = [];
|
var varlist = [];
|
||||||
rule.prefix = s.split(/\s+/)[0];
|
rule.prefix = s.split(/\s+/)[0];
|
||||||
@ -24,7 +79,7 @@ var Assembler = function(spec) {
|
|||||||
s = s.replace(/\]/g, '\\]');
|
s = s.replace(/\]/g, '\\]');
|
||||||
s = s.replace(/\./g, '\\.');
|
s = s.replace(/\./g, '\\.');
|
||||||
// TODO: more escapes?
|
// TODO: more escapes?
|
||||||
s = s.replace(/~\w+/g, function(varname) {
|
s = s.replace(/~\w+/g, function(varname:string) {
|
||||||
varname = varname.substr(1);
|
varname = varname.substr(1);
|
||||||
var v = vars[varname];
|
var v = vars[varname];
|
||||||
varlist.push(varname);
|
varlist.push(varname);
|
||||||
@ -49,17 +104,17 @@ var Assembler = function(spec) {
|
|||||||
}
|
}
|
||||||
if (spec) preprocessRules();
|
if (spec) preprocessRules();
|
||||||
|
|
||||||
function warning(msg, line) {
|
function warning(msg:string, line?:number) {
|
||||||
errors.push({msg:msg, line:line?line:linenum});
|
errors.push({msg:msg, line:line?line:linenum});
|
||||||
}
|
}
|
||||||
function fatal(msg, line) {
|
function fatal(msg:string, line?:number) {
|
||||||
warning(msg, line);
|
warning(msg, line);
|
||||||
aborted = true;
|
aborted = true;
|
||||||
}
|
}
|
||||||
function fatalIf(msg, line) {
|
function fatalIf(msg?:string, line?:number) {
|
||||||
if (msg) fatal(msg, line);
|
if (msg) fatal(msg, line);
|
||||||
}
|
}
|
||||||
function hex(v, nd) {
|
function hex(v:number, nd:number) {
|
||||||
try {
|
try {
|
||||||
if (!nd) nd = 2;
|
if (!nd) nd = 2;
|
||||||
var s = v.toString(16).toUpperCase();
|
var s = v.toString(16).toUpperCase();
|
||||||
@ -70,7 +125,7 @@ var Assembler = function(spec) {
|
|||||||
return v+"";
|
return v+"";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function addBytes(result) {
|
function addBytes(result:AssemblerInstruction) {
|
||||||
asmlines.push({
|
asmlines.push({
|
||||||
line:linenum,
|
line:linenum,
|
||||||
offset:ip,
|
offset:ip,
|
||||||
@ -82,7 +137,7 @@ var Assembler = function(spec) {
|
|||||||
outwords[ip++ - origin] = (op >> (nb-1-i)*width) & ((1<<width)-1);
|
outwords[ip++ - origin] = (op >> (nb-1-i)*width) & ((1<<width)-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function addWords(data) {
|
function addWords(data:number[]) {
|
||||||
asmlines.push({
|
asmlines.push({
|
||||||
line:linenum,
|
line:linenum,
|
||||||
offset:ip,
|
offset:ip,
|
||||||
@ -93,7 +148,7 @@ var Assembler = function(spec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseData(toks) {
|
function parseData(toks:string[]) : number[] {
|
||||||
var data = [];
|
var data = [];
|
||||||
for (var i=0; i<toks.length; i++) {
|
for (var i=0; i<toks.length; i++) {
|
||||||
data[i] = parseConst(toks[i]);
|
data[i] = parseConst(toks[i]);
|
||||||
@ -101,7 +156,7 @@ var Assembler = function(spec) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringToData(s) {
|
function stringToData(s:string) : number[] {
|
||||||
var data = [];
|
var data = [];
|
||||||
for (var i=0; i<s.length; i++) {
|
for (var i=0; i<s.length; i++) {
|
||||||
data[i] = s.charCodeAt(i);
|
data[i] = s.charCodeAt(i);
|
||||||
@ -116,17 +171,15 @@ var Assembler = function(spec) {
|
|||||||
ip = Math.floor((ip+align-1)/align)*align;
|
ip = Math.floor((ip+align-1)/align)*align;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseConst(s, nbits) {
|
function parseConst(s:string, nbits?:number) : number {
|
||||||
// TODO: check bit length
|
// TODO: check bit length
|
||||||
if (!s.length)
|
if (s.startsWith("$"))
|
||||||
return s;
|
|
||||||
else if (s.startsWith("$"))
|
|
||||||
return parseInt(s.substr(1), 16);
|
return parseInt(s.substr(1), 16);
|
||||||
else
|
else
|
||||||
return parseInt(s);
|
return parseInt(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.buildInstruction = function(rule, m) {
|
self.buildInstruction = function(rule:AssemblerRule, m:string[]) : AssemblerLineResult {
|
||||||
var opcode = 0;
|
var opcode = 0;
|
||||||
var oplen = 0;
|
var oplen = 0;
|
||||||
// iterate over each component of the rule output ("bits")
|
// iterate over each component of the rule output ("bits")
|
||||||
@ -135,7 +188,7 @@ var Assembler = function(spec) {
|
|||||||
var n,x;
|
var n,x;
|
||||||
// is a string? then it's a bit constant
|
// is a string? then it's a bit constant
|
||||||
// TODO
|
// TODO
|
||||||
if (b.length) {
|
if (typeof b == "string") {
|
||||||
n = b.length;
|
n = b.length;
|
||||||
x = parseInt(b,2);
|
x = parseInt(b,2);
|
||||||
} else {
|
} else {
|
||||||
@ -176,7 +229,7 @@ var Assembler = function(spec) {
|
|||||||
return {opcode:opcode, nbits:oplen};
|
return {opcode:opcode, nbits:oplen};
|
||||||
}
|
}
|
||||||
|
|
||||||
self.loadArch = function(arch) {
|
self.loadArch = function(arch:string) {
|
||||||
if (self.loadJSON) {
|
if (self.loadJSON) {
|
||||||
var json = self.loadJSON(arch + ".json");
|
var json = self.loadJSON(arch + ".json");
|
||||||
if (json && json.vars && json.rules) {
|
if (json && json.vars && json.rules) {
|
||||||
@ -214,7 +267,7 @@ var Assembler = function(spec) {
|
|||||||
warning("Unrecognized directive: " + tokens);
|
warning("Unrecognized directive: " + tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.assemble = function(line) {
|
self.assemble = function(line) : AssemblerInstruction {
|
||||||
linenum++;
|
linenum++;
|
||||||
// remove comments
|
// remove comments
|
||||||
line = line.replace(/[;].*/g, '').trim();
|
line = line.replace(/[;].*/g, '').trim();
|
||||||
@ -253,7 +306,7 @@ var Assembler = function(spec) {
|
|||||||
warning(lastError ? lastError : ("Could not decode instruction: " + line));
|
warning(lastError ? lastError : ("Could not decode instruction: " + line));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.finish = function() {
|
self.finish = function() : AssemblerState {
|
||||||
// apply fixups
|
// apply fixups
|
||||||
for (var i=0; i<fixups.length; i++) {
|
for (var i=0; i<fixups.length; i++) {
|
||||||
var fix = fixups[i];
|
var fix = fixups[i];
|
||||||
@ -262,7 +315,7 @@ var Assembler = function(spec) {
|
|||||||
var ofs = fix.ofs + Math.floor(fix.bitofs/width);
|
var ofs = fix.ofs + Math.floor(fix.bitofs/width);
|
||||||
var shift = fix.bitofs & (width-1);
|
var shift = fix.bitofs & (width-1);
|
||||||
var mask = ((1<<fix.bitlen)-1);
|
var mask = ((1<<fix.bitlen)-1);
|
||||||
var value = parseConst(sym.value, fix.bitlen);
|
var value = parseConst(sym.value+"", fix.bitlen);
|
||||||
if (fix.iprel)
|
if (fix.iprel)
|
||||||
value -= fix.ofs + fix.ipofs;
|
value -= fix.ofs + fix.ipofs;
|
||||||
if (value > mask || value < -mask)
|
if (value > mask || value < -mask)
|
||||||
@ -292,7 +345,7 @@ var Assembler = function(spec) {
|
|||||||
return self.state();
|
return self.state();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.assembleFile = function(text) {
|
self.assembleFile = function(text) : AssemblerState {
|
||||||
var lines = text.split(/\n/g);
|
var lines = text.split(/\n/g);
|
||||||
for (var i=0; i<lines.length && !aborted; i++) {
|
for (var i=0; i<lines.length && !aborted; i++) {
|
||||||
try {
|
try {
|
||||||
@ -305,14 +358,16 @@ var Assembler = function(spec) {
|
|||||||
return self.finish();
|
return self.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state = function() {
|
self.state = function() : AssemblerState {
|
||||||
return {ip:ip, line:linenum, origin:origin, codelen:codelen,
|
return {ip:ip, line:linenum, origin:origin, codelen:codelen,
|
||||||
intermediate:{}, // TODO: listing, symbols?
|
intermediate:{}, // TODO: listing, symbols?
|
||||||
output:outwords, lines:asmlines, errors:errors, fixups:fixups};
|
output:outwords, lines:asmlines, errors:errors, fixups:fixups};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Main
|
// Main
|
||||||
|
declare var module;
|
||||||
if (typeof module !== 'undefined' && require.main === module) {
|
if (typeof module !== 'undefined' && require.main === module) {
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var stdinBuffer = fs.readFileSync(0);
|
var stdinBuffer = fs.readFileSync(0);
|
||||||
@ -331,3 +386,4 @@ if (typeof module !== 'undefined' && require.main === module) {
|
|||||||
var out = asm.assembleFile(code);
|
var out = asm.assembleFile(code);
|
||||||
console.log(out);
|
console.log(out);
|
||||||
}
|
}
|
||||||
|
*/
|
@ -1,7 +1,34 @@
|
|||||||
|
|
||||||
var moduleName, symsName;
|
type V2JS_Var = {
|
||||||
|
wordlen:number,
|
||||||
|
name:string,
|
||||||
|
len:number,
|
||||||
|
ofs:number,
|
||||||
|
arrdim?:number[]
|
||||||
|
}
|
||||||
|
|
||||||
function parseDecls(text, arr, name, bin, bout) {
|
type V2JS_Code = {
|
||||||
|
name:string,
|
||||||
|
ports:V2JS_Var[],
|
||||||
|
signals:V2JS_Var[],
|
||||||
|
funcs:string[],
|
||||||
|
}
|
||||||
|
|
||||||
|
type V2JS_Output = {
|
||||||
|
output:{
|
||||||
|
code:V2JS_Code,
|
||||||
|
name:string,
|
||||||
|
ports:V2JS_Var[],
|
||||||
|
signals:V2JS_Var[],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function translateVerilatorOutputToJS(htext:string, cpptext:string) {
|
||||||
|
|
||||||
|
var moduleName : string;
|
||||||
|
var symsName : string;
|
||||||
|
|
||||||
|
function parseDecls(text:string, arr:V2JS_Var[], name:string, bin?:boolean, bout?:boolean) {
|
||||||
var re = new RegExp(name + "(\\d*)[(](\\w+),(\\d+),(\\d+)[)]", 'gm');
|
var re = new RegExp(name + "(\\d*)[(](\\w+),(\\d+),(\\d+)[)]", 'gm');
|
||||||
var m;
|
var m;
|
||||||
while ((m = re.exec(text))) {
|
while ((m = re.exec(text))) {
|
||||||
@ -36,7 +63,7 @@ function parseDecls(text, arr, name, bin, bout) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildModule(o) {
|
function buildModule(o : V2JS_Code) : string {
|
||||||
var m = '"use strict";\n';
|
var m = '"use strict";\n';
|
||||||
m += '\tvar self = this;\n';
|
m += '\tvar self = this;\n';
|
||||||
for (var i=0; i<o.ports.length; i++) {
|
for (var i=0; i<o.ports.length; i++) {
|
||||||
@ -61,7 +88,7 @@ function buildModule(o) {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
function translateFunction(text) {
|
function translateFunction(text : string) : string {
|
||||||
text = text.trim();
|
text = text.trim();
|
||||||
var funcname = text.match(/(\w+)/)[1];
|
var funcname = text.match(/(\w+)/)[1];
|
||||||
text = text.replace(symsName + "* __restrict ", "");
|
text = text.replace(symsName + "* __restrict ", "");
|
||||||
@ -88,7 +115,7 @@ function translateFunction(text) {
|
|||||||
return "function " + text + "\nself." + funcname + " = " + funcname + ";\n";
|
return "function " + text + "\nself." + funcname + " = " + funcname + ";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
function translateStaticVars(text) {
|
function translateStaticVars(text : string) : string {
|
||||||
var s = "";
|
var s = "";
|
||||||
var m;
|
var m;
|
||||||
var re = /VL_ST_SIG(\d+)[(](\w+?)::(\w+).(\d+).,(\d+),(\d+)[)]/g;
|
var re = /VL_ST_SIG(\d+)[(](\w+?)::(\w+).(\d+).,(\d+),(\d+)[)]/g;
|
||||||
@ -98,7 +125,6 @@ function translateStaticVars(text) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
function translateVerilatorOutputToJS(htext, cpptext) {
|
|
||||||
// parse header file
|
// parse header file
|
||||||
moduleName = /VL_MODULE.(\w+)./.exec(htext)[1];
|
moduleName = /VL_MODULE.(\w+)./.exec(htext)[1];
|
||||||
symsName = moduleName + "__Syms";
|
symsName = moduleName + "__Syms";
|
||||||
@ -132,4 +158,6 @@ function translateVerilatorOutputToJS(htext, cpptext) {
|
|||||||
signals:signals,
|
signals:signals,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -299,6 +299,12 @@ function load(modulename, debug) {
|
|||||||
loaded[modulename] = 1;
|
loaded[modulename] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function loadGen(modulename) {
|
||||||
|
if (!loaded[modulename]) {
|
||||||
|
importScripts('../../gen/'+modulename+".js");
|
||||||
|
loaded[modulename] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
function loadWASM(modulename, debug) {
|
function loadWASM(modulename, debug) {
|
||||||
if (!loaded[modulename]) {
|
if (!loaded[modulename]) {
|
||||||
importScripts("wasm/" + modulename+(debug?"."+debug+".js":".js"));
|
importScripts("wasm/" + modulename+(debug?"."+debug+".js":".js"));
|
||||||
@ -1063,7 +1069,7 @@ var jsasm_module_output;
|
|||||||
var jsasm_module_key;
|
var jsasm_module_key;
|
||||||
|
|
||||||
function compileJSASM(asmcode, platform, options, is_inline) {
|
function compileJSASM(asmcode, platform, options, is_inline) {
|
||||||
load("../assembler");
|
loadGen("worker/assembler");
|
||||||
var asm = new Assembler();
|
var asm = new Assembler();
|
||||||
var includes = [];
|
var includes = [];
|
||||||
asm.loadJSON = function(filename) {
|
asm.loadJSON = function(filename) {
|
||||||
@ -1151,7 +1157,7 @@ function compileInlineASM(code, platform, options, errors, asmlines) {
|
|||||||
// TODO: make compliant with standard msg format
|
// TODO: make compliant with standard msg format
|
||||||
function compileVerilator(step) {
|
function compileVerilator(step) {
|
||||||
loadNative("verilator_bin");
|
loadNative("verilator_bin");
|
||||||
load("../verilator2js");
|
loadGen("worker/verilator2js");
|
||||||
var code = step.code;
|
var code = step.code;
|
||||||
var platform = step.platform || 'verilog';
|
var platform = step.platform || 'verilog';
|
||||||
var errors = [];
|
var errors = [];
|
||||||
|
@ -38,7 +38,7 @@ var includeInThisContext = function(path) {
|
|||||||
vm.runInThisContext(code, path);
|
vm.runInThisContext(code, path);
|
||||||
};
|
};
|
||||||
|
|
||||||
includeInThisContext("src/worker/assembler.js");
|
includeInThisContext("gen/worker/assembler.js");
|
||||||
|
|
||||||
describe('Assemble', function() {
|
describe('Assemble', function() {
|
||||||
it('Should assemble', function() {
|
it('Should assemble', function() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user