mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-05-28 23:41:32 +00:00
verilog: fixed wasm array views, compare test, loadROM async?
This commit is contained in:
parent
f4d8435c59
commit
854a6a2cdc
|
@ -90,7 +90,7 @@ export function isVarDecl(arg:any): arg is HDLVariableDef {
|
|||
}
|
||||
|
||||
export interface HDLConstant extends HDLDataTypeObject {
|
||||
cvalue: number;
|
||||
cvalue: number; //TODO: BigInt?
|
||||
}
|
||||
|
||||
export function isConstExpr(arg:any): arg is HDLConstant {
|
||||
|
|
|
@ -17,7 +17,7 @@ interface Options {
|
|||
}
|
||||
|
||||
const GLOBALOFS = 0;
|
||||
const MEMORY = "0";
|
||||
const MEMORY = "$$MEM";
|
||||
const GLOBAL = "$$GLOBAL";
|
||||
const CHANGEDET = "$$CHANGE";
|
||||
const TRACERECLEN = "$$treclen";
|
||||
|
@ -191,7 +191,7 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
this.bmod = new binaryen.Module();
|
||||
this.genTypes();
|
||||
var membytes = this.globals.len;
|
||||
var memblks = Math.ceil(membytes / 65536) + 1;
|
||||
var memblks = Math.ceil(membytes / 65536);
|
||||
this.bmod.setMemory(memblks, memblks, MEMORY); // memory is in 64k chunks
|
||||
this.genFuncs();
|
||||
}
|
||||
|
@ -223,9 +223,8 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
}
|
||||
|
||||
tick() {
|
||||
// TODO: faster, save state
|
||||
this.state.clk ^= 1;
|
||||
(this.instance.exports as any).eval(GLOBALOFS);
|
||||
this.eval();
|
||||
}
|
||||
|
||||
tick2(iters: number) {
|
||||
|
@ -245,6 +244,9 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
}
|
||||
|
||||
enableTracing() {
|
||||
if (this.outputbytes == 0) throw new Error(`outputbytes == 0`);
|
||||
if (this.outputbytes % 8) throw new Error(`outputbytes must be 8-byte aligned`);
|
||||
if (this.traceBufferSize % 8) throw new Error(`trace buffer size must be 8-byte aligned`);
|
||||
this.traceStartOffset = this.globals.lookup(TRACEBUF).offset;
|
||||
this.traceEndOffset = this.traceStartOffset + this.traceBufferSize - this.outputbytes;
|
||||
this.state[TRACEEND] = this.traceEndOffset;
|
||||
|
@ -287,6 +289,7 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
for (const [varname, vardef] of Object.entries(this.hdlmod.vardefs)) {
|
||||
if (vardef.isOutput) state.addVar(vardef);
|
||||
}
|
||||
if (state.len == 0) state.addEntry("___", 1); // ensure as least 8 output bytes for trace buffer
|
||||
state.alignTo(8);
|
||||
this.outputbytes = state.len;
|
||||
// followed by inputs and internal vars
|
||||
|
@ -340,7 +343,9 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
}
|
||||
// create helper functions
|
||||
this.addHelperFunctions();
|
||||
// create wasm module
|
||||
// link imported functions
|
||||
this.addImportedFunctions();
|
||||
// validate wasm module
|
||||
//console.log(this.bmod.emitText());
|
||||
//this.bmod.optimize();
|
||||
if (!this.bmod.validate())
|
||||
|
@ -351,7 +356,7 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
//console.log(this.bmod.emitText());
|
||||
var wasmData = this.bmod.emitBinary();
|
||||
var compiled = await WebAssembly.compile(wasmData);
|
||||
this.instance = await WebAssembly.instantiate(compiled, {});
|
||||
this.instance = await WebAssembly.instantiate(compiled, this.getImportObject());
|
||||
this.databuf = (this.instance.exports[MEMORY] as any).buffer;
|
||||
this.data8 = new Uint8Array(this.databuf);
|
||||
this.data16 = new Uint16Array(this.databuf);
|
||||
|
@ -372,9 +377,9 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
if (elsize == 1) {
|
||||
return new Uint8Array(this.databuf, base + vref.offset, vref.size);
|
||||
} else if (elsize == 2) {
|
||||
return new Uint16Array(this.databuf, (base + vref.offset) >> 1, vref.size >> 1);
|
||||
return new Uint16Array(this.databuf, (base>>1) + vref.offset, vref.size >> 1);
|
||||
} else if (elsize == 4) {
|
||||
return new Uint32Array(this.databuf, (base + vref.offset) >> 2, vref.size >> 2);
|
||||
return new Uint32Array(this.databuf, (base>>2) + vref.offset, vref.size >> 2);
|
||||
}
|
||||
} else {
|
||||
if (vref.size == 1) {
|
||||
|
@ -433,7 +438,24 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
this.addCopyTraceRecFunction();
|
||||
this.addEvalFunction();
|
||||
this.addTick2Function();
|
||||
}
|
||||
|
||||
private addImportedFunctions() {
|
||||
// TODO: this.bmod.addFunctionImport("$$rand", "builtins", "$$rand", binaryen.createType([]), binaryen.i64);
|
||||
this.bmod.addFunctionImport("$display", "builtins", "$display", binaryen.createType([binaryen.i32]), binaryen.none);
|
||||
this.bmod.addFunctionImport("$finish", "builtins", "$finish", binaryen.createType([binaryen.i32]), binaryen.none);
|
||||
this.bmod.addFunctionImport("$stop", "builtins", "$stop", binaryen.createType([binaryen.i32]), binaryen.none);
|
||||
}
|
||||
|
||||
private getImportObject() : {} {
|
||||
var n = 0;
|
||||
return {
|
||||
builtins: {
|
||||
$display: (o) => { if (++n < 100) console.log('...',o); }, // TODO
|
||||
$finish: (o) => { this.finished = true; },
|
||||
$stop: (o) => { this.stopped = true; },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private addCopyTraceRecFunction() {
|
||||
|
@ -621,8 +643,10 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
if (isLogicType(e.dtype)) {
|
||||
if (size <= 4)
|
||||
return this.bmod.i32.const(e.cvalue);
|
||||
else if (size <= 8)
|
||||
return this.bmod.i64.const(e.cvalue, e.cvalue >> 32); // TODO: bigint?
|
||||
else
|
||||
throw new HDLError(e, `constants > 32 bits not supported`)
|
||||
throw new HDLError(e, `constants > 64 bits not supported`)
|
||||
} else {
|
||||
throw new HDLError(e, `non-logic constants not supported`)
|
||||
}
|
||||
|
@ -817,6 +841,12 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
_redxor2wasm(e: HDLUnop, opts:Options) {
|
||||
//TODO
|
||||
}
|
||||
*/
|
||||
|
||||
_or2wasm(e: HDLBinop, opts:Options) {
|
||||
return this.i3264(e.dtype).or(this.e2w(e.left), this.e2w(e.right));
|
||||
}
|
||||
|
@ -864,5 +894,6 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
|||
_lts2wasm(e: HDLBinop, opts:Options) {
|
||||
return this.i3264(e.dtype).lt_s(this.e2w(e.left), this.e2w(e.right));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ export class VerilogXMLParser implements HDLUnit {
|
|||
|
||||
constructor() {
|
||||
// TODO: other types
|
||||
this.dtypes['QData'] = {left:63, right:0};
|
||||
this.dtypes['IData'] = {left:31, right:0};
|
||||
}
|
||||
|
||||
|
@ -602,6 +603,7 @@ export class VerilogXMLParser implements HDLUnit {
|
|||
visit_concat(node: XMLNode) { return this.__visit_binop(node); } // TODO?
|
||||
visit_shiftl(node: XMLNode) { return this.__visit_binop(node); }
|
||||
visit_shiftr(node: XMLNode) { return this.__visit_binop(node); }
|
||||
visit_shiftrs(node: XMLNode) { return this.__visit_binop(node); }
|
||||
|
||||
visit_mul(node: XMLNode) { return this.__visit_binop(node); }
|
||||
visit_div(node: XMLNode) { return this.__visit_binop(node); }
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
import { arrayCompare } from "../util";
|
||||
import { HDLModuleJS } from "./hdlruntime";
|
||||
import { HDLModuleWASM } from "./hdlwasm";
|
||||
import { VerilogXMLParser } from "./vxmlparser";
|
||||
|
@ -13,7 +14,7 @@ try {
|
|||
console.log(parser.cur_node);
|
||||
throw e;
|
||||
}
|
||||
console.log(parser);
|
||||
//console.log(parser);
|
||||
var modname = 'TOP'; //process.argv[3];
|
||||
|
||||
async function testWASM() {
|
||||
|
@ -58,5 +59,54 @@ async function testJS() {
|
|||
//console.log(emitter);
|
||||
}
|
||||
|
||||
testWASM().then(testJS);
|
||||
async function testJSvsWASM() {
|
||||
const top = parser.modules[modname];
|
||||
const constpool = parser.modules['@CONST-POOL@'];
|
||||
var jmod = new HDLModuleJS(top, constpool);
|
||||
jmod.init();
|
||||
jmod.powercycle();
|
||||
var bmod = new HDLModuleWASM(top, constpool);
|
||||
await bmod.init();
|
||||
bmod.powercycle();
|
||||
var varnames = Object.keys(top.vardefs);
|
||||
var exit = false;
|
||||
for (var i=0; i<100000000; i++) {
|
||||
for (var vname of varnames) {
|
||||
var jvalue = jmod.state[vname];
|
||||
var bvalue = bmod.state[vname];
|
||||
if (typeof jvalue === 'number') {
|
||||
if (jvalue != bvalue) {
|
||||
console.log('*** Value for', vname, 'differs', jvalue, bvalue);
|
||||
exit = true;
|
||||
}
|
||||
} else if ((jvalue as any).buffer != null) {
|
||||
if (!arrayCompare(jvalue as any, bvalue as any)) {
|
||||
console.log('*** Value for', vname, 'differs', jvalue, bvalue);
|
||||
exit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jmod.isFinished() || bmod.isFinished()) {
|
||||
if (jmod.isFinished() != bmod.isFinished()) {
|
||||
console.log('*** Abnormal finish', jmod.isFinished(), bmod.isFinished());
|
||||
}
|
||||
exit = true;
|
||||
}
|
||||
if (jmod.isStopped() || bmod.isStopped()) {
|
||||
if (jmod.isStopped() != bmod.isStopped()) {
|
||||
console.log('*** Abnormal stop', jmod.isStopped(), bmod.isStopped());
|
||||
}
|
||||
exit = true;
|
||||
}
|
||||
if (exit) {
|
||||
console.log('exit iteration', i);
|
||||
break;
|
||||
}
|
||||
jmod.tick2(1);
|
||||
bmod.tick2(1);
|
||||
}
|
||||
}
|
||||
|
||||
testJSvsWASM();
|
||||
//testWASM().then(testJS);
|
||||
|
||||
|
|
|
@ -1178,7 +1178,7 @@ function setCompileOutput(data: WorkerResult) {
|
|||
try {
|
||||
clearBreakpoint(); // so we can replace memory (TODO: change toolbar btn)
|
||||
_resetRecording();
|
||||
platform.loadROM(getCurrentPresetTitle(), rom);
|
||||
platform.loadROM(getCurrentPresetTitle(), rom); // TODO: should be async?
|
||||
current_output = rom;
|
||||
if (!userPaused) _resume();
|
||||
measureBuildTime();
|
||||
|
|
|
@ -292,6 +292,9 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
if (!novideo) {
|
||||
this.refreshVideoFrame();
|
||||
}
|
||||
if (this.isBlocked()) {
|
||||
this.pause();
|
||||
}
|
||||
return cyclesPerFrame; //TODO?
|
||||
}
|
||||
|
||||
|
@ -529,6 +532,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: can this be async?
|
||||
async loadROM(title:string, output:any) {
|
||||
var unit = output as HDLUnit;
|
||||
var topmod = unit.modules['TOP'];
|
||||
|
|
|
@ -12,15 +12,14 @@ Object.assign(global, verilog); // copy global VL_* properties
|
|||
|
||||
// TODO: must define $
|
||||
|
||||
function loadPlatform(msg) {
|
||||
async function loadPlatform(msg) {
|
||||
var platform = new VerilogPlatform();
|
||||
platform.resume = function() { }; // prevent resume after reset
|
||||
try {
|
||||
//console.log(msg.output.ports);
|
||||
//console.log(msg.output.signals);
|
||||
platform.loadROM("ROM", msg.output);
|
||||
platform.loadROM("ROM", msg.output);
|
||||
platform.loadROM("ROM", msg.output);
|
||||
await platform.loadROM("ROM", msg.output);
|
||||
await platform.loadROM("ROM", msg.output);
|
||||
for (var i=0; i<100000 && !platform.isBlocked(); i++) {
|
||||
platform.tick();
|
||||
}
|
||||
|
@ -47,7 +46,7 @@ function testPerf(msg) {
|
|||
var niters = 5000000;
|
||||
|
||||
console.time("before");
|
||||
for (var i=0; i<niters; i++)
|
||||
for (var i=0; i<niters && !platform.isBlocked(); i++)
|
||||
platform.tick();
|
||||
console.timeEnd("before");
|
||||
|
||||
|
@ -55,7 +54,7 @@ function testPerf(msg) {
|
|||
platform.reset();
|
||||
platform.loadState(state);
|
||||
console.time("after");
|
||||
for (var i=0; i<niters; i++)
|
||||
for (var i=0; i<niters && !platform.isBlocked(); i++)
|
||||
platform.tick();
|
||||
console.timeEnd("after");
|
||||
|
||||
|
@ -63,13 +62,13 @@ function testPerf(msg) {
|
|||
}
|
||||
|
||||
function compileVerilator(filename, code, callback, nerrors) {
|
||||
global.postMessage = function(msg) {
|
||||
global.postMessage = async function(msg) {
|
||||
if (msg.errors && msg.errors.length) {
|
||||
console.log(msg.errors);
|
||||
assert.equal(nerrors||0, msg.errors.length, "errors");
|
||||
} else {
|
||||
assert.equal(nerrors||0, 0, "errors");
|
||||
loadPlatform(msg);
|
||||
await loadPlatform(msg);
|
||||
//testPerf(msg);
|
||||
if (filename.indexOf('t_') >= 0) {
|
||||
//assert.ok(verilog.vl_finished);
|
||||
|
|
Loading…
Reference in New Issue
Block a user