esp32emu / tools /bench.mjs
HelloSun's picture
ESP32 emulator update
8d577f5 verified
Raw History Blame Contribute Delete
4.01 kB
import fs from 'fs';
import { createESP32, ESP32 } from '../web/js/soc.js';
const wasmBytes = fs.readFileSync(new URL('../wasm/xtensa.wasm', import.meta.url));
for (const eng of ['wasm', 'js']) {
const soc = eng === 'wasm' ? await createESP32({ wasmBytes }) : new ESP32({});
soc.reset('power');
// program at 0x40080000 (IRAM): mixed loop
const code = [];
const e = (...b) => code.push(...b);
// movi a2, 0x7fff? use loop counter in a3 via l32r-free sequence: movi a3,1000(?) up to 2047 via movi (imm12)
// loop: addi a4,a4,1 ; add a5,a4,a3 ; xor a6,a5,a4 ; s32i a6,a1?no. use a7 as pointer to DRAM
// encode by assembling with objdump-free manual encodings:
// movi a3, 2000 -> 0xA3 0x07 0xD0? use: movi a3, -1 ... keep simple: use loop instruction.
// We'll use: loopgtz a3, end ; addi.n a4,a4,1 ; add.n a5,a4,a4 ; xor a6,a5,a4 ; s32i a6,a7,0 ; l32i a8,a7,0 ; end: ; j start
const asm = [
0xa0, 0x20, 0x00, // placeholder will be replaced
];
const mem = soc.h8; const base = 0x40080000;
const off = (soc.cpus[0].rd[base >>> 12] + base) | 0;
// bytes: movi a3, 2047 : r=10 (MOVI) imm8=0xFF, s=7 (imm12 hi), t=3 => inst = imm8<<16 | 0xA<<12 | s<<8 | t<<4 | 2
const w = (i) => [i & 255, (i >> 8) & 255, (i >> 16) & 255];
const prog = [];
prog.push(...w((0xFF << 16) | (0xA << 12) | (7 << 8) | (3 << 4) | 2)); // movi a3, 2047
// movi a7, DRAM addr: use l32r? skip: use a1 (sp) region: a1 holds 0? set a7 via movi 0x...: use add.n? simply movi a7, 0x7ff? that's addr 0x7ff (unmapped slow!). use window: set a7 = pc-based? use call0 trick -> skip, use address in IRAM-literal: l32r a7, lit
// literal at start+0x40: value 0x3ffb0000
const litAddr = base + 0x40;
// l32r a7, lit : imm16 = ((lit - ((pc+3)&~3))>>2) & 0xFFFF
const pcL = base + 3; const imm16 = (((litAddr - ((pcL + 3) & ~3)) >> 2) & 0xFFFF);
prog.push(...w((imm16 << 8) | (7 << 4) | 1)); // l32r a7, lit
const loopStart = base + prog.length;
// loopgtz a3, end (BI1 m=1 B1 r=10): inst= imm8<<16 | 10<<12 | s<<8 | (n=3,m=1 -> t=0b0111) <<4 | 6
const bodyIns = [];
bodyIns.push(0x4a, 0x1b); // addi.n a4,a4,1 ? (placeholder replaced below)
const narrow = (op0, t, s, r) => [(t << 4) | op0, (r << 4) | s];
const body = [];
const ONLY_ADD = process.env.ONLY_ADD === '1';
if (ONLY_ADD) { for (let k = 0; k < 8; k++) body.push(...narrow(0xA, 4, 4, 5)); } else {
body.push(...narrow(0xB, 1, 4, 4)); // addi.n a4,a4,1 (t=1) r=4,s=4
body.push(...narrow(0xA, 4, 4, 5)); // add.n a5,a4,a4
body.push(...w((0x3 << 20) | (0x0 << 16) | (6 << 12) | (5 << 8) | (4 << 4) | 0)); // xor a6,a5,a4 (op2=3 op1=0)
body.push(...w((0x06 << 12) | (7 << 8) | (6 << 4) | 2) .map((b,i)=>b)); // s32i a6,a7,0 : r=6 -> inst = imm8(0)<<16 | r=6<<12 | s=7<<8 | t=6<<4 | 2
body.push(...w((0x02 << 12) | (7 << 8) | (8 << 4) | 2)); // l32i a8,a7,0 (r=2)
body.push(...narrow(0xA, 9, 8, 6)); }
const loopLen = body.length;
// loop instr: lend = pc+4+imm8
const loopInst = (loopLen << 16) | (10 << 12) | (3 << 8) | (0x7 << 4) | 6;
prog.push(...w(loopInst));
prog.push(...body);
// j start (backwards): J: op0=6,n=0 imm18 = off ; target = pc+4+off
const jpc = base + prog.length; const joff = (loopStart - 4 - 0 - jpc); // jump back to the loop instruction
const j18 = ((loopStart - (jpc + 4)) & 0x3FFFF);
prog.push(...w((j18 << 6) | 6));
while (prog.length < 0x40) prog.push(0);
prog.push(0, 0, 0xfb, 0x3f); // literal 0x3ffb0000
mem.set(prog, off);
const c = soc.cpus[0];
c.pc = base; c.ps = 0x20; c.cpenable = 0; c.chkInt = false; c.intenable = 0;
const N = 30e6; const t0 = process.hrtime.bigint();
for (let i = 0; i < N; i += 100000) c.run(100000);
const dt = Number(process.hrtime.bigint() - t0) / 1e9;
console.log(eng, (N / dt / 1e6).toFixed(1), 'MIPS', 'pc', (c.pc >>> 0).toString(16), 'a4', c.ar[(c.wb4 + 4) & 63]);
}