diff --git a/dsa/common/src/asm/asm_opcode.rs b/dsa/common/src/asm/asm_opcode.rs deleted file mode 100644 index 938e49d..0000000 --- a/dsa/common/src/asm/asm_opcode.rs +++ /dev/null @@ -1,67 +0,0 @@ -pub enum AsmOpcode { - Nop, - - // move - Mov, - CMov, - - // load - Ldb, - Ldbs, - Ldh, - Ldhs, - Ldw, - - // store - Stb, - Sth, - Stw, - - // load immediate - Lli, - Lui, - Lwi, - - // comparison - Ieq, - Ine, - Ilt, - Ile, - Igt, - Ige, - - // jump - Jmp, - Jez, - Jnz, - Jic, - Jnc, - - // bitwise - And, - Nand, - Or, - Nor, - Xor, - Xnor, - Not, - - // arithmetic - Add, - Sub, - Shl, - Shr, - Addi, - Subi, - - // utility - Push, - Pop, - Call, - Ret, - - // system - Int, - IRet, - Hlt, -} diff --git a/dsa/emulator/src/backend/processor/processor.rs b/dsa/emulator/src/backend/processor/processor.rs index 2a9c1f6..4339c14 100644 --- a/dsa/emulator/src/backend/processor/processor.rs +++ b/dsa/emulator/src/backend/processor/processor.rs @@ -2,29 +2,21 @@ use std::{ hint::unlikely, ops::AddAssign, sync::{ + Arc, atomic::Ordering, mpsc::{self, TryRecvError}, - Arc, }, thread, time::{Duration, Instant}, }; -use common::isa::instructions::{Instruction, Opcode}; -use common::isa::register::Register; use crate::{ -<<<<<<< HEAD:dsa/emulator/src/processor/processor.rs - config::{IoMapping, MemoryMap, RegionType}, - io::{IoDevice, MappedDevice}, - memory::{mmu::MMU, ram::RandomAccessMemory}, - processor::{interrupts::Interrupt, state::SharedState}, - Page, -======= MemoryBank, Page, SharedState, backend::{memory::mmu::MMU, processor::interrupts::Interrupt}, - config::{IoMapping, MemoryMap, RegionType}, ->>>>>>> refs/remotes/origin/main:dsa/emulator/src/backend/processor/processor.rs + config::{MemoryMap, RegionType}, }; +use common::isa::instructions::{Instruction, Opcode}; +use common::isa::register::Register; pub struct Emulator { internal_state: ProcessorSnapshot, diff --git a/dsa/emulator/src/bin/bench_emu.rs b/dsa/emulator/src/bin/bench_emu.rs index 9c8d9b8..9604f5d 100644 --- a/dsa/emulator/src/bin/bench_emu.rs +++ b/dsa/emulator/src/bin/bench_emu.rs @@ -1,330 +1,332 @@ -use common::isa::instructions::Instruction; -use dsa::{BulkAllocStore, Emulator, Page, RandomAccessMemory}; -/// DSA Emulator Benchmark -/// -/// Place this in `dsa/src/bin/bench.rs` and run with: -/// cargo run --bin bench --release -/// -/// Three workloads are tested: -/// 1. ALU-heavy — tight arithmetic loop, no memory, no branches -/// 2. Memory-heavy — repeated load/store to a working set of addresses -/// 3. Branch-heavy — the bf.dsa dispatch pattern (ieq + jnz chains) -/// -/// Each workload is a hand-assembled flat binary loaded directly into -/// the emulator, bypassing all the args/display/IO plumbing. -use std::{ - thread, - time::{Duration, Instant}, - u16, -}; +// use common::isa::instructions::Instruction; +// use dsa::{Emulator, MemoryBank, Page}; +// /// DSA Emulator Benchmark +// /// +// /// Place this in `dsa/src/bin/bench.rs` and run with: +// /// cargo run --bin bench --release +// /// +// /// Three workloads are tested: +// /// 1. ALU-heavy — tight arithmetic loop, no memory, no branches +// /// 2. Memory-heavy — repeated load/store to a working set of addresses +// /// 3. Branch-heavy — the bf.dsa dispatch pattern (ieq + jnz chains) +// /// +// /// Each workload is a hand-assembled flat binary loaded directly into +// /// the emulator, bypassing all the args/display/IO plumbing. +// use std::{ +// thread, +// time::{Duration, Instant}, +// u16, +// }; -// --------------------------------------------------------------------------- -// Minimal no-op memory map + IO so the emulator boots without a config file. -// --------------------------------------------------------------------------- +// // --------------------------------------------------------------------------- +// // Minimal no-op memory map + IO so the emulator boots without a config file. +// // --------------------------------------------------------------------------- -fn make_emulator() -> Emulator { - use dsa::{ - config::{MemoryMap, Region, RegionType}, - io::display::DisplayDevice, - }; +// fn make_emulator() -> Emulator { +// use dsa::{ +// config::{MemoryMap, Region, RegionType}, +// io::display::Display, +// }; - let mmap = MemoryMap { - table_addr: 0x40000, - regions: vec![ - Region { - base: 0x0000_0000, - size: 0x0010_0000, // 1 MiB RAM - region_type: RegionType::Usable, - identity_map_on_boot: true, - }, - Region { - base: 0x0020_0000, - size: 0x0002_0000, // 128 KiB MMIO (display) - region_type: RegionType::MMIO, - identity_map_on_boot: false, - }, - ], - }; +// let mmap = MemoryMap { +// table_addr: 0x40000, +// regions: vec![ +// Region { +// base: 0x0000_0000, +// size: 0x0010_0000, // 1 MiB RAM +// region_type: RegionType::Usable, +// identity_map_on_boot: true, +// }, +// Region { +// base: 0x0020_0000, +// size: 0x0002_0000, // 128 KiB MMIO (display) +// region_type: RegionType::MMIO, +// identity_map_on_boot: false, +// }, +// ], +// }; - let iomap = vec![dsa::config::IoMapping { - device: dsa::io::DeviceId::Display, - base: 0x0020_0000, - size: 0x0000_07D0, - }]; +// // let iomap = vec![dsa::config::IoMapping { +// // device: dsa::io::DeviceId::Display, +// // base: 0x0020_0000, +// // size: 0x0000_07D0, +// // }]; - let (display, _handle) = DisplayDevice::new(80, 25); - Emulator::new(BulkAllocStore::new()) - .with_device(display) - .apply_memory_map(mmap) - .apply_io_map(iomap) - .unwrap() -} +// // let (display, _handle) = Display::new(80, 25); +// // Emulator::new(MemoryBank::new()) +// // .with_device(display) +// // .apply_memory_map(mmap) +// // .apply_io_map(iomap) +// // .unwrap() +// } -// --------------------------------------------------------------------------- -// Instruction encoding helpers (little-endian words) -// --------------------------------------------------------------------------- +// // --------------------------------------------------------------------------- +// // Instruction encoding helpers (little-endian words) +// // --------------------------------------------------------------------------- -/// Encode an I-type instruction: [op:6][src:5][dst:5][imm:16] -fn enc_i(op: u8, src: u8, dst: u8, imm: u16) -> u32 { - ((op as u32 & 0x3F) << 26) - | ((src as u32 & 0x1F) << 21) - | ((dst as u32 & 0x1F) << 16) - | imm as u32 -} +// /// Encode an I-type instruction: [op:6][src:5][dst:5][imm:16] +// fn enc_i(op: u8, src: u8, dst: u8, imm: u16) -> u32 { +// ((op as u32 & 0x3F) << 26) +// | ((src as u32 & 0x1F) << 21) +// | ((dst as u32 & 0x1F) << 16) +// | imm as u32 +// } -/// Encode an R-type instruction: [op:6][r1:5][r2:5][r3:5][r4:5][u6:6] -fn enc_r(op: u8, r1: u8, r2: u8, r3: u8, r4: u8, u6: u8) -> u32 { - ((op as u32 & 0x3F) << 26) - | ((r1 as u32 & 0x1F) << 21) - | ((r2 as u32 & 0x1F) << 16) - | ((r3 as u32 & 0x1F) << 11) - | ((r4 as u32 & 0x1F) << 6) - | (u6 as u32 & 0x3F) -} +// /// Encode an R-type instruction: [op:6][r1:5][r2:5][r3:5][r4:5][u6:6] +// fn enc_r(op: u8, r1: u8, r2: u8, r3: u8, r4: u8, u6: u8) -> u32 { +// ((op as u32 & 0x3F) << 26) +// | ((r1 as u32 & 0x1F) << 21) +// | ((r2 as u32 & 0x1F) << 16) +// | ((r3 as u32 & 0x1F) << 11) +// | ((r4 as u32 & 0x1F) << 6) +// | (u6 as u32 & 0x3F) +// } -// Register indices — must match your Register enum discriminants -const RG0: u8 = 0; -const RG1: u8 = 1; -const RG2: u8 = 2; -const RG3: u8 = 3; -const RG4: u8 = 4; -const RG5: u8 = 5; -const ZERO: u8 = 16; +// // Register indices — must match your Register enum discriminants +// const RG0: u8 = 0; +// const RG1: u8 = 1; +// const RG2: u8 = 2; +// const RG3: u8 = 3; +// const RG4: u8 = 4; +// const RG5: u8 = 5; +// const ZERO: u8 = 16; -// Opcodes — must match your Opcode enum discriminants. -// Fill these in from your ISA.md / encode.rs. -const OP_NOP: u8 = 0x0D; // adjust to match your actual opcode values -const OP_HLT: u8 = 0x2B; -const OP_ADD: u8 = 0x22; -const OP_ADDI: u8 = 0x23; -const OP_SUBI: u8 = 0x24; -const OP_LDW: u8 = 0x07; -const OP_STW: u8 = 0x0A; -const OP_LLI: u8 = 0x0B; -const OP_LUI: u8 = 0x0C; -const OP_IEQ: u8 = 0x0E; -const OP_JNZ: u8 = 0x15; -const OP_JMP: u8 = 0x12; +// // Opcodes — must match your Opcode enum discriminants. +// // Fill these in from your ISA.md / encode.rs. +// const OP_NOP: u8 = 0x0D; // adjust to match your actual opcode values +// const OP_HLT: u8 = 0x2B; +// const OP_ADD: u8 = 0x22; +// const OP_ADDI: u8 = 0x23; +// const OP_SUBI: u8 = 0x24; +// const OP_LDW: u8 = 0x07; +// const OP_STW: u8 = 0x0A; +// const OP_LLI: u8 = 0x0B; +// const OP_LUI: u8 = 0x0C; +// const OP_IEQ: u8 = 0x0E; +// const OP_JNZ: u8 = 0x15; +// const OP_JMP: u8 = 0x12; -// --------------------------------------------------------------------------- -// Workload 1: ALU-heavy -// -// Counts down from 10_000_000 using subi, jumps back to top. -// Pure register arithmetic, no memory accesses after init. -// Instruction mix: lli, subi, ieq, jnz, hlt -// -// Layout (each word at address = index * 4): -// 0: lli rg0, 0 (upper half of count) [lui follows] -// 4: lui rg0, -// 8: loop: subi rg0, 1, rg0 -// 12: ieq rg0, zero, rg1 -// 16: jnz rg1, zero, 8 [jump to loop] -// 20: hlt -// --------------------------------------------------------------------------- -fn alu_workload() -> Vec { - let count: u32 = 10_000_000; - let lo = (count & 0xFFFF) as u16; - let hi = ((count >> 16) & 0xFFFF) as u16; +// // --------------------------------------------------------------------------- +// // Workload 1: ALU-heavy +// // +// // Counts down from 10_000_000 using subi, jumps back to top. +// // Pure register arithmetic, no memory accesses after init. +// // Instruction mix: lli, subi, ieq, jnz, hlt +// // +// // Layout (each word at address = index * 4): +// // 0: lli rg0, 0 (upper half of count) [lui follows] +// // 4: lui rg0, +// // 8: loop: subi rg0, 1, rg0 +// // 12: ieq rg0, zero, rg1 +// // 16: jnz rg1, zero, 8 [jump to loop] +// // 20: hlt +// // --------------------------------------------------------------------------- +// fn alu_workload() -> Vec { +// let count: u32 = 10_000_000; +// let lo = (count & 0xFFFF) as u16; +// let hi = ((count >> 16) & 0xFFFF) as u16; - let words: &[u32] = &[ - enc_i(OP_LLI, 0, RG0, lo), // 0x00: lli rg0, lo(count) - enc_i(OP_LUI, 0, RG0, hi), // 0x04: lui rg0, hi(count) - // loop @ 0x08: - enc_i(OP_SUBI, RG0, RG0, 1), // 0x08: subi rg0, rg0, 1 - enc_r(OP_IEQ, RG0, ZERO, RG1, 0, 0), // 0x0C: ieq rg0, zero, rg1 - enc_i(OP_JNZ, RG1, ZERO, 0x0008), // 0x10: jnz rg1, zero, 0x08 <- BUG: jnz jumps when rg1!=0 - // rg1=1 when rg0==0, so we want jez here to keep looping - // fix: use jez (jump when rg1==0, i.e. rg0!=0) - enc_i(OP_HLT, 0, 0, 0), // 0x14: hlt - ]; - // Note: replace OP_JNZ above with your JEZ opcode so the loop continues - // while rg0 != 0. JNZ exits when rg1 != 0, i.e. when rg0 == 0 (done). - // The ieq sets rg1=1 only when rg0==0, so jnz rg1 exits the loop correctly. - // Actually this IS correct: loop while ieq returns 0 (rg0 != 0), - // exit when ieq returns 1 (rg0 == 0). jnz rg1 = jump when rg1 != 0 = jump when done. - // We want to jump BACK while not done, so we need jez: - // jez rg1, zero, 0x08 = jump back when rg1==0 (rg0 != 0, not done yet) - // Swap OP_JNZ for your JEZ opcode. - words_to_bytes(words) -} +// let words: &[u32] = &[ +// enc_i(OP_LLI, 0, RG0, lo), // 0x00: lli rg0, lo(count) +// enc_i(OP_LUI, 0, RG0, hi), // 0x04: lui rg0, hi(count) +// // loop @ 0x08: +// enc_i(OP_SUBI, RG0, RG0, 1), // 0x08: subi rg0, rg0, 1 +// enc_r(OP_IEQ, RG0, ZERO, RG1, 0, 0), // 0x0C: ieq rg0, zero, rg1 +// enc_i(OP_JNZ, RG1, ZERO, 0x0008), // 0x10: jnz rg1, zero, 0x08 <- BUG: jnz jumps when rg1!=0 +// // rg1=1 when rg0==0, so we want jez here to keep looping +// // fix: use jez (jump when rg1==0, i.e. rg0!=0) +// enc_i(OP_HLT, 0, 0, 0), // 0x14: hlt +// ]; +// // Note: replace OP_JNZ above with your JEZ opcode so the loop continues +// // while rg0 != 0. JNZ exits when rg1 != 0, i.e. when rg0 == 0 (done). +// // The ieq sets rg1=1 only when rg0==0, so jnz rg1 exits the loop correctly. +// // Actually this IS correct: loop while ieq returns 0 (rg0 != 0), +// // exit when ieq returns 1 (rg0 == 0). jnz rg1 = jump when rg1 != 0 = jump when done. +// // We want to jump BACK while not done, so we need jez: +// // jez rg1, zero, 0x08 = jump back when rg1==0 (rg0 != 0, not done yet) +// // Swap OP_JNZ for your JEZ opcode. +// words_to_bytes(words) +// } -// --------------------------------------------------------------------------- -// Workload 2: Memory-heavy -// -// Repeatedly writes and reads a 64-word working set. -// Tests page table lookup performance under repeated memory access. -// -// rg0 = base address (0x1000, well within RAM, page-aligned) -// rg1 = loop counter (1000 outer iterations) -// rg2 = inner counter (64 words per pass) -// rg3 = scratch for store value -// --------------------------------------------------------------------------- -fn memory_workload() -> Vec { - let base: u32 = 0x1000; - let outer: u16 = 1000; - let inner: u16 = 64; +// // --------------------------------------------------------------------------- +// // Workload 2: Memory-heavy +// // +// // Repeatedly writes and reads a 64-word working set. +// // Tests page table lookup performance under repeated memory access. +// // +// // rg0 = base address (0x1000, well within RAM, page-aligned) +// // rg1 = loop counter (1000 outer iterations) +// // rg2 = inner counter (64 words per pass) +// // rg3 = scratch for store value +// // --------------------------------------------------------------------------- +// fn memory_workload() -> Vec { +// let base: u32 = 0x1000; +// let outer: u16 = 1000; +// let inner: u16 = 64; - let words: &[u32] = &[ - // init - enc_i(OP_LLI, 0, RG0, (base & 0xFFFF) as u16), // rg0 = base - enc_i(OP_LLI, 0, RG1, outer), // rg1 = outer count - // outer_loop @ 0x08: - enc_i(OP_LLI, 0, RG2, inner), // rg2 = inner count - enc_i(OP_LLI, 0, RG3, 0xABCD), // rg3 = value to write - // inner_loop @ 0x10: - enc_i(OP_STW, RG3, RG0, 0), // stw rg3, rg0, 0 - enc_i(OP_LDW, RG0, RG3, 0), // ldw rg0, rg3, 0 (read back) - enc_i(OP_ADDI, RG0, RG0, 4), // rg0 += 4 - enc_i(OP_SUBI, RG2, RG2, 1), // rg2 -= 1 - enc_r(OP_IEQ, RG2, ZERO, RG4, 0, 0), // ieq rg2, zero, rg4 - enc_i(OP_JNZ, RG4, ZERO, 0x0010), // jez rg4 -> inner_loop (swap opcode) - // restore base, dec outer - enc_i(OP_LLI, 0, RG0, (base & 0xFFFF) as u16), - enc_i(OP_SUBI, RG1, RG1, 1), - enc_r(OP_IEQ, RG1, ZERO, RG4, 0, 0), - enc_i(OP_JNZ, RG4, ZERO, 0x0008), // jez rg4 -> outer_loop (swap opcode) - enc_i(OP_HLT, 0, 0, 0), - ]; - words_to_bytes(words) -} +// let words: &[u32] = &[ +// // init +// enc_i(OP_LLI, 0, RG0, (base & 0xFFFF) as u16), // rg0 = base +// enc_i(OP_LLI, 0, RG1, outer), // rg1 = outer count +// // outer_loop @ 0x08: +// enc_i(OP_LLI, 0, RG2, inner), // rg2 = inner count +// enc_i(OP_LLI, 0, RG3, 0xABCD), // rg3 = value to write +// // inner_loop @ 0x10: +// enc_i(OP_STW, RG3, RG0, 0), // stw rg3, rg0, 0 +// enc_i(OP_LDW, RG0, RG3, 0), // ldw rg0, rg3, 0 (read back) +// enc_i(OP_ADDI, RG0, RG0, 4), // rg0 += 4 +// enc_i(OP_SUBI, RG2, RG2, 1), // rg2 -= 1 +// enc_r(OP_IEQ, RG2, ZERO, RG4, 0, 0), // ieq rg2, zero, rg4 +// enc_i(OP_JNZ, RG4, ZERO, 0x0010), // jez rg4 -> inner_loop (swap opcode) +// // restore base, dec outer +// enc_i(OP_LLI, 0, RG0, (base & 0xFFFF) as u16), +// enc_i(OP_SUBI, RG1, RG1, 1), +// enc_r(OP_IEQ, RG1, ZERO, RG4, 0, 0), +// enc_i(OP_JNZ, RG4, ZERO, 0x0008), // jez rg4 -> outer_loop (swap opcode) +// enc_i(OP_HLT, 0, 0, 0), +// ]; +// words_to_bytes(words) +// } -// --------------------------------------------------------------------------- -// Workload 3: Branch-heavy -// -// Mimics the bf.dsa dispatch pattern: compare a value against 8 constants, -// branch on each. Worst case for branch predictor. -// rg0 = current "instruction" (cycles through 8 values) -// rg8-rgf = the 8 bf opcode constants -// --------------------------------------------------------------------------- -fn branch_workload() -> Vec { - // 8 bf opcodes: + - > < . , [ ] - let opcodes: [u16; 8] = [43, 45, 62, 60, 46, 44, 91, 93]; - // We'll cycle rg0 through these values and do the full dispatch chain. - // To keep it self-contained: load opcodes, set outer loop counter, - // inner loop cycles rg0 through all 8 values doing ieq+jnz for each. - let outer: u16 = u16::MAX; +// // --------------------------------------------------------------------------- +// // Workload 3: Branch-heavy +// // +// // Mimics the bf.dsa dispatch pattern: compare a value against 8 constants, +// // branch on each. Worst case for branch predictor. +// // rg0 = current "instruction" (cycles through 8 values) +// // rg8-rgf = the 8 bf opcode constants +// // --------------------------------------------------------------------------- +// fn branch_workload() -> Vec { +// // 8 bf opcodes: + - > < . , [ ] +// let opcodes: [u16; 8] = [43, 45, 62, 60, 46, 44, 91, 93]; +// // We'll cycle rg0 through these values and do the full dispatch chain. +// // To keep it self-contained: load opcodes, set outer loop counter, +// // inner loop cycles rg0 through all 8 values doing ieq+jnz for each. +// let outer: u16 = u16::MAX; - let mut w: Vec = Vec::new(); +// let mut w: Vec = Vec::new(); - // Load 8 opcode constants into rg8-rgf (regs 8-15) - for (i, &op) in opcodes.iter().enumerate() { - w.push(enc_i(OP_LLI, 0, 8 + i as u8, op)); - } - // rg1 = outer counter - w.push(enc_i(OP_LLI, 0, RG1, outer)); +// // Load 8 opcode constants into rg8-rgf (regs 8-15) +// for (i, &op) in opcodes.iter().enumerate() { +// w.push(enc_i(OP_LLI, 0, 8 + i as u8, op)); +// } +// // rg1 = outer counter +// w.push(enc_i(OP_LLI, 0, RG1, outer)); - // outer_loop: - let outer_loop_addr = (w.len() * 4) as u16; +// // outer_loop: +// let outer_loop_addr = (w.len() * 4) as u16; - // rg5 = inner counter (8 opcodes) - w.push(enc_i(OP_LLI, 0, RG5, 8)); - // rg2 = pointer into opcode table (we'll use addi to step rg0 through values) - // For simplicity: just set rg0 to each opcode in sequence via lli each iteration - // This is branch-heavy, not arithmetic-heavy, so the lli overhead is fine. - for (i, &op) in opcodes.iter().enumerate() { - let next_offset = ((w.len() + 4) * 4) as u16; // addr after the jnz - w.push(enc_i(OP_LLI, 0, RG0, op)); // rg0 = opcode - w.push(enc_r(OP_IEQ, RG0, 8 + i as u8, RG4, 0, 0)); // ieq rg0, rgX, rg4 - w.push(enc_i(OP_JNZ, RG4, ZERO, next_offset)); // jnz rg4 (jez to skip) - w.push(enc_i(OP_NOP, 0, 0, 0)); // "handler" nop - } - // dec outer, loop - let after_dispatch = (w.len() * 4) as u16; - w.push(enc_i(OP_SUBI, RG1, RG1, 1)); - w.push(enc_r(OP_IEQ, RG1, ZERO, RG4, 0, 0)); - w.push(enc_i(OP_JNZ, RG4, ZERO, outer_loop_addr)); // jez -> outer_loop - w.push(enc_i(OP_HLT, 0, 0, 0)); +// // rg5 = inner counter (8 opcodes) +// w.push(enc_i(OP_LLI, 0, RG5, 8)); +// // rg2 = pointer into opcode table (we'll use addi to step rg0 through values) +// // For simplicity: just set rg0 to each opcode in sequence via lli each iteration +// // This is branch-heavy, not arithmetic-heavy, so the lli overhead is fine. +// for (i, &op) in opcodes.iter().enumerate() { +// let next_offset = ((w.len() + 4) * 4) as u16; // addr after the jnz +// w.push(enc_i(OP_LLI, 0, RG0, op)); // rg0 = opcode +// w.push(enc_r(OP_IEQ, RG0, 8 + i as u8, RG4, 0, 0)); // ieq rg0, rgX, rg4 +// w.push(enc_i(OP_JNZ, RG4, ZERO, next_offset)); // jnz rg4 (jez to skip) +// w.push(enc_i(OP_NOP, 0, 0, 0)); // "handler" nop +// } +// // dec outer, loop +// let after_dispatch = (w.len() * 4) as u16; +// w.push(enc_i(OP_SUBI, RG1, RG1, 1)); +// w.push(enc_r(OP_IEQ, RG1, ZERO, RG4, 0, 0)); +// w.push(enc_i(OP_JNZ, RG4, ZERO, outer_loop_addr)); // jez -> outer_loop +// w.push(enc_i(OP_HLT, 0, 0, 0)); - words_to_bytes(&w) -} +// words_to_bytes(&w) +// } -fn words_to_bytes(words: &[u32]) -> Vec { - words.iter().flat_map(|w| w.to_le_bytes()).collect() -} +// fn words_to_bytes(words: &[u32]) -> Vec { +// words.iter().flat_map(|w| w.to_le_bytes()).collect() +// } -// --------------------------------------------------------------------------- -// Runner -// --------------------------------------------------------------------------- +// // --------------------------------------------------------------------------- +// // Runner +// // --------------------------------------------------------------------------- -struct BenchResult { - name: &'static str, - instructions: u64, - elapsed: Duration, - mips: f64, -} +// struct BenchResult { +// name: &'static str, +// instructions: u64, +// elapsed: Duration, +// mips: f64, +// } -fn run_bench(name: &'static str, binary: Vec) -> BenchResult { - let mut emu = make_emulator(); - let handle = emu.state_handle(); +// fn run_bench(name: &'static str, binary: Vec) -> BenchResult { +// let mut emu = make_emulator(); +// let handle = emu.state_handle(); - let pages: Vec = Page::paginate(&binary).collect(); - for (i, page) in pages.iter().enumerate() { - emu.memory_mut().write_page(i as u32 * 4096, page); - } +// let pages: Vec = Page::paginate(&binary).collect(); +// for (i, page) in pages.iter().enumerate() { +// emu.memory_mut().write_page(i as u32 * 4096, page); +// } - let start = Instant::now(); - // run() blocks until HLT - emu.run().expect("emulator run failed"); - let elapsed = start.elapsed(); +// let start = Instant::now(); +// // run() blocks until HLT +// emu.run().expect("emulator run failed"); +// let elapsed = start.elapsed(); - // read clock from emulator — we need to expose it. - // For now, estimate from elapsed + target MIPS. - // TODO: expose emulator.clock() -> u64 and use that directly. - let instructions = handle.proc.load().clock as u64; - let mips = instructions as f64 / elapsed.as_micros() as f64; +// // read clock from emulator — we need to expose it. +// // For now, estimate from elapsed + target MIPS. +// // TODO: expose emulator.clock() -> u64 and use that directly. +// let instructions = handle.proc.load().clock as u64; +// let mips = instructions as f64 / elapsed.as_micros() as f64; - BenchResult { - name, - instructions, - elapsed, - mips, - } -} +// BenchResult { +// name, +// instructions, +// elapsed, +// mips, +// } +// } -fn main() { - println!("DSA Emulator Benchmark"); - println!("======================"); - println!(); +// fn main() { +// println!("DSA Emulator Benchmark"); +// println!("======================"); +// println!(); - // NOTE: you need to expose `pub fn clock(&self) -> usize` on Emulator - // and ensure `run()` returns normally on HLT without blocking in idle_wait. - // The idle_wait loop currently spins forever after HLT — for benchmarking, - // you want run() to return when the program halts. Add a flag or check: - // if !self.internal_state.running { break 'emu; } - // after the HLT handler sets running=false. +// // NOTE: you need to expose `pub fn clock(&self) -> usize` on Emulator +// // and ensure `run()` returns normally on HLT without blocking in idle_wait. +// // The idle_wait loop currently spins forever after HLT — for benchmarking, +// // you want run() to return when the program halts. Add a flag or check: +// // if !self.internal_state.running { break 'emu; } +// // after the HLT handler sets running=false. - let workloads: &[(&'static str, fn() -> Vec)] = &[ - ("ALU-heavy (10M countdown)", alu_workload), - ("Memory-heavy (64K rw ops)", memory_workload), - ("Branch-heavy (bf dispatch)", branch_workload), - ]; +// let workloads: &[(&'static str, fn() -> Vec)] = &[ +// ("ALU-heavy (10M countdown)", alu_workload), +// ("Memory-heavy (64K rw ops)", memory_workload), +// ("Branch-heavy (bf dispatch)", branch_workload), +// ]; - let mut results = Vec::new(); - for &(name, build) in workloads { - print!("Running {}... ", name); - let binary = build(); - let result = run_bench(name, binary); - println!("done ({:.1}ms)", result.elapsed.as_secs_f64() * 1000.0); - results.push(result); - } +// let mut results = Vec::new(); +// for &(name, build) in workloads { +// print!("Running {}... ", name); +// let binary = build(); +// let result = run_bench(name, binary); +// println!("done ({:.1}ms)", result.elapsed.as_secs_f64() * 1000.0); +// results.push(result); +// } - println!(); - println!( - "{:<35} {:>12} {:>12} {:>10}", - "Workload", "Instructions", "Time", "MIPS" - ); - println!("{}", "-".repeat(72)); - for r in &results { - println!( - "{:<35} {:>12} {:>10.1}ms {:>10.1}", - r.name, - r.instructions, - r.elapsed.as_secs_f64() * 1000.0, - r.mips, - ); - } +// println!(); +// println!( +// "{:<35} {:>12} {:>12} {:>10}", +// "Workload", "Instructions", "Time", "MIPS" +// ); +// println!("{}", "-".repeat(72)); +// for r in &results { +// println!( +// "{:<35} {:>12} {:>10.1}ms {:>10.1}", +// r.name, +// r.instructions, +// r.elapsed.as_secs_f64() * 1000.0, +// r.mips, +// ); +// } - let avg_mips: f64 = results.iter().map(|r| r.mips).sum::() / results.len() as f64; - println!("{}", "-".repeat(72)); - println!("{:<35} {:>35.1} MIPS avg", "Overall", avg_mips); -} +// let avg_mips: f64 = results.iter().map(|r| r.mips).sum::() / results.len() as f64; +// println!("{}", "-".repeat(72)); +// println!("{:<35} {:>35.1} MIPS avg", "Overall", avg_mips); +// } + +fn main() {} diff --git a/dsa/emulator/src/main.rs b/dsa/emulator/src/main.rs index 20b87df..c2a6400 100644 --- a/dsa/emulator/src/main.rs +++ b/dsa/emulator/src/main.rs @@ -1,17 +1,4 @@ use clap::Parser; -<<<<<<< HEAD -use common::isa::instructions::Instruction; -use dsa::{ - args::DsaArgs, io::display::{DisplayDevice, DisplayHandle}, BulkAllocStore, Emulator, Page, - RandomAccessMemory, - SharedState, -}; -use std::{ - sync::{atomic::Ordering, Arc}, - thread, - time::Duration, -}; -======= use common::prelude::Instruction; use dsa::{Emulator, Page, args::DsaArgs, frontend::run_app}; @@ -19,7 +6,6 @@ use std::thread; const STACK_SIZE: usize = 1024 * 1024 * 16; ->>>>>>> refs/remotes/origin/main fn main() { let args = DsaArgs::parse(); diff --git a/dsa_resources/out.dsb b/dsa_resources/out.dsb index 7b3af3e..6b47949 100644 Binary files a/dsa_resources/out.dsb and b/dsa_resources/out.dsb differ