code wiki / _hdl_build / nx_rv64_fast.nx
nx_rv64_fast.nx
buildroot/runtime/_hdl_build/nx_rv64_fast.nx
about
nx_rv64_fast.nx -- a PREDECODED RV64 interpreter (the first perf-engineering step toward closing the QEMU-TCG gap
for the sovereign emulator). Where the behavioral sim re-decodes EVERY instruction EVERY step, this DECODES ONCE
(fills a decoded-op table indexed by word) then runs a tight dispatch loop -- so a hot loop pays decode cost only
per STATIC instruction, not per DYNAMIC step. Deterministic + bit-exact (nx_rv64_fast_gate proves equivalence with
the golden behavioral sim). RV64I base integer subset; flat memory @0x80000000; SiFive-finisher halt (store to
0x100000). NOT a JIT (emits no native code) -- the honest decode-cache rung. Device-aware: routes the virtio-MMIO
window to the sovereign device model (rv64im_min_virtio), so the speedup applies to REAL driver workloads too, not
just pure compute. license_tier: ORIGINAL
dependencies 4 imports · 25 importers
diagram shows first 10 each side; +0 more imports, +15 more importers in the complete lists below.
imports: nx_syscalls.nxnishi_hdl_primitives.nxrv64im_min_virtio.nxnx_rvc_expand.nx
imported by: nx_asm_oracle.nxnx_hwtest_matrix.nxnx_jit_ra_probe.nxnx_mulh_diag.nxnx_rv64_cjit_gate.nxnx_rv64_ctier_gate.nxnx_rv64_difftest.nxnx_rv64_fast_dev_gate.nxnx_rv64_fast_gate.nxnx_rv64_jit.nxnx_rv64_jit_fwd_gate.nxnx_rv64_jit_gate.nxnx_rv64_jit_mem_gate.nxnx_rv64_jit_ra_gate.nxnx_rv64_jit_w_gate.nxnx_rv64_m_gate.nxnx_rv64_mulh_gate.nxnx_rv64_qemu_fuzz.nxnx_rv64_qemu_oracle.nxnx_rv64_realc_gate.nxnx_rv64_run_bin_fast.nxnx_rv64_run_bin_tier.nxnx_rv64_tier.nxnx_rv64_tier_gate.nxnx_rv64_toolchain_gate.nx
structs
| none |
consts
| 14 | const FK_ILL: i64 = 0 |
| 15 | const FK_LUI: i64 = 1 |
| 16 | const FK_ADDI: i64 = 2 |
| 17 | const FK_ANDI: i64 = 3 |
| 18 | const FK_ORI: i64 = 4 |
| 19 | const FK_XORI: i64 = 5 |
| 20 | const FK_SLLI: i64 = 6 |
| 21 | const FK_SRLI: i64 = 7 |
| 22 | const FK_SRAI: i64 = 8 |
| 23 | const FK_ADD: i64 = 9 |
| 24 | const FK_SUB: i64 = 10 |
| 25 | const FK_AND: i64 = 11 |
| 26 | const FK_OR: i64 = 12 |
| 27 | const FK_XOR: i64 = 13 |
| 28 | const FK_SLL: i64 = 14 |
| 29 | const FK_SRL: i64 = 15 |
| 30 | const FK_SRA: i64 = 16 |
| 31 | const FK_LW: i64 = 17 |
| 32 | const FK_LBU: i64 = 18 |
| 33 | const FK_LHU: i64 = 19 |
| 34 | const FK_LD: i64 = 20 |
| 35 | const FK_SW: i64 = 21 |
| 36 | const FK_SB: i64 = 22 |
| 37 | const FK_SH: i64 = 23 |
| 38 | const FK_SD: i64 = 24 |
| 39 | const FK_BEQ: i64 = 25 |
| 40 | const FK_BNE: i64 = 26 |
| 41 | const FK_BLT: i64 = 27 |
| 42 | const FK_BGE: i64 = 28 |
| 43 | const FK_BLTU: i64 = 29 |
| 44 | const FK_BGEU: i64 = 30 |
| 45 | const FK_JAL: i64 = 31 |
| 46 | const FK_JALR: i64 = 32 |
| 47 | const FK_MUL: i64 = 33 |
| 48 | const FK_DIV: i64 = 34 |
| 49 | const FK_DIVU: i64 = 35 |
| 50 | const FK_REM: i64 = 36 |
| 51 | const FK_REMU: i64 = 37 |
| 52 | const FK_MULH: i64 = 38 |
| 53 | const FK_MULHSU: i64 = 39 |
| 54 | const FK_MULHU: i64 = 40 |
| 55 | const FK_AUIPC: i64 = 41 |
| 58 | const FK_ADDIW: i64 = 42 |
| 59 | const FK_SLLIW: i64 = 43 |
| 60 | const FK_SRLIW: i64 = 44 |
| 61 | const FK_SRAIW: i64 = 45 |
| 62 | const FK_ADDW: i64 = 46 |
| 63 | const FK_SUBW: i64 = 47 |
| 64 | const FK_SLLW: i64 = 48 |
| 65 | const FK_SRLW: i64 = 49 |
| 66 | const FK_SRAW: i64 = 50 |
| 67 | const FK_MULW: i64 = 51 |
| 68 | const FK_DIVW: i64 = 52 |
| 69 | const FK_DIVUW: i64 = 53 |
| 70 | const FK_REMW: i64 = 54 |
| 71 | const FK_REMUW: i64 = 55 |
| 72 | const FK_AMOW: i64 = 56 // A extension, .w (32-bit); imm holds funct5 |
| 73 | const FK_AMOD: i64 = 57 // A extension, .d (64-bit) |
| 74 | const FK_MEMBASE: i64 = 0x80000000 |
| 75 | const FK_FINISHER: i64 = 0x100000 |
| 89 | const FK_UART_THR: i64 = 0x10000000 |
functions
| 77 | func fk_w32(c: *u8, o: i64) -> i64 { return (c[o] as i64)|((c[o+1] as i64)<<8)|((c[o+2] as i64)<<16)|((c[o+3] as i64)<<24) } |
| 78 | func fk_sext(v: i64, bits: i64) -> i64 { let m: i64 = 1 << (bits-1); if (v & m) != 0 { return v - (1 << bits) } return v } |
| 79 | func fk_imm_i(w: i64) -> i64 { return fk_sext((w>>20)&0xFFF, 12) } |
| 80 | func fk_imm_s(w: i64) -> i64 { return fk_sext((((w>>25)&0x7F)<<5)|((w>>7)&0x1F), 12) } |
| 81 | func fk_imm_b(w: i64) -> i64 { return fk_sext((((w>>31)&1)<<12)|(((w>>7)&1)<<11)|(((w>>25)&0x3F)<<5)|(((w>>8)&0xF)<<1), 13) } |
| 82 | func fk_imm_u(w: i64) -> i64 { return fk_sext(w & 0xFFFFF000, 32) } |
| 83 | func fk_imm_j(w: i64) -> i64 { return fk_sext((((w>>31)&1)<<20)|(((w>>12)&0xFF)<<12)|(((w>>20)&1)<<11)|(((w>>21)&0x3FF)<<1), 21) } |
| 84 | func fk_ltu(x: i64, y: i64) -> i64 { if (x<0) != (y<0) { if x<0 { return 0 } return 1 } if x < y { return 1 } return 0 } |
| 85 | func fk_srlmask(sh: i64) -> i64 { if sh==0 { return 0-1 } return (1 << (64-sh)) - 1 } called by 1: fk_step |
| 86 | func fk_sext32(v: i64) -> i64 { return fk_sext(v & 0xffffffff, 32) } // RV64 *W result: low 32 bits sign-extended to 64 |
| 92 | func fk_tx_reset(buf: *u8) -> i64 { fk_txcap_ptr = buf as i64; fk_txcnt = 0; return 0 } |
| 93 | func fk_tx_count() -> i64 { return fk_txcnt } |
| 104 | func fk_amo(addr: i64, v: i64, f5: i64, mem: *u8, membytes: i64, width: i64) -> i64 |
| 122 | func udiv_mod(a: i64, b: i64, wantrem: i64) -> i64 |
| 130 | func sdiv64(a: i64, b: i64) -> i64 { if b==0 { return 0-1 } if a==(1<<63) { if b==(0-1) { return a } } return a/b } |
| 131 | func srem64(a: i64, b: i64) -> i64 { if b==0 { return a } if a==(1<<63) { if b==(0-1) { return 0 } } return a%b } |
| 135 | func mulhu64(a: i64, b: i64) -> i64 |
| 145 | func mulh64(a: i64, b: i64) -> i64 { var h: i64=mulhu64(a,b); if a<0 { h=h-b } if b<0 { h=h-a } return h } |
| 146 | func mulhsu64(a: i64, b: i64) -> i64 { var h: i64=mulhu64(a,b); if a<0 { h=h-b } return h } // a signed, b unsigned |
| 149 | func fk_predecode(code: *u8, nbytes: i64, opk: *i64, rd: *i64, rs1: *i64, rs2: *i64, imm: *i64) -> i64 |
| 182 | func fk_ld(mem: *u8, o: i64, w: i64) -> i64 { var v: i64=0; var i: i64=0; while i<w { v=v|((mem[o+i] as i64)<<(i*8)); i=i+1 } return v } |
| 183 | func fk_st(mem: *u8, o: i64, w: i64, val: i64) -> i64 { var i: i64=0; while i<w { mem[o+i]=((val>>(i*8))&0xff) as u8; i=i+1 } return 0 } |
| 184 | func fk_memok(o: i64, w: i64, membytes: i64) -> i64 { if o<0 { return 0 } if o+w>membytes { return 0 } return 1 } |
| 186 | func fk_mmio_hit(dev: *NxVirtioMmio, addr: i64) -> i64 { if (dev as i64)==0 { return 0 } if addr < dev.base { return 0 } if addr >= dev.base + 0x100 { return 0 } return 1 } called by 1: fk_step |
| 191 | func fk_step(opk: *i64, rd: *i64, rs1: *i64, rs2: *i64, imm: *i64, idx: i64, pc: i64, ilen: i64, reg: *i64, mem: *u8, membytes: i64, dev: *NxVirtioMmio, valbox: *i64, haltbox: *i64) -> i64 called by 4: fk_runfk_run_ctier_runtier_run_c calls 18: fk_amofk_srlmaskmulh64mulhu64mulhsu64sdiv64+12 |
| 266 | func fk_run(opk: *i64, rd: *i64, rs1: *i64, rs2: *i64, imm: *i64, ncount: i64, reg: *i64, mem: *u8, membytes: i64, maxsteps: i64, dev: *NxVirtioMmio) -> i64 |
| 287 | func fk_decode_one(w: i64, i: i64, opk: *i64, rd: *i64, rs1: *i64, rs2: *i64, imm: *i64) -> i64 |
| 315 | func fk_predecode_c(code: *u8, nbytes: i64, opk: *i64, rd: *i64, rs1: *i64, rs2: *i64, imm: *i64) -> i64 |
| 329 | func fk_run_c(opk: *i64, rd: *i64, rs1: *i64, rs2: *i64, imm: *i64, nhalf: i64, reg: *i64, mem: *u8, membytes: i64, maxsteps: i64, dev: *NxVirtioMmio) -> i64 |
| 350 | func main() -> i64 { return 0 } |