rename Machine -> LogicalHardware

This commit is contained in:
bQUARKz 2026-01-16 05:41:51 +00:00
parent d1c87ef6e7
commit 85a5f2d63f
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
5 changed files with 38 additions and 37 deletions

View File

@ -1,8 +1,8 @@
pub mod machine; pub mod logical_hardware;
pub mod peripherals; pub mod peripherals;
pub mod vm; pub mod vm;
mod model; mod model;
mod native_interface; mod native_interface;
mod utilz; mod utilz;
pub use machine::Machine; pub use logical_hardware::LogicalHardware;

View File

@ -5,7 +5,7 @@ use std::sync::Arc;
/// PROMETEU "hardware lógico" (v0). /// PROMETEU "hardware lógico" (v0).
/// O Host alimenta INPUT SIGNALS e chama `step_frame()` em 60Hz. /// O Host alimenta INPUT SIGNALS e chama `step_frame()` em 60Hz.
pub struct Machine { pub struct LogicalHardware {
pub gfx: Gfx, pub gfx: Gfx,
pub audio: Audio, pub audio: Audio,
pub pad: Pad, pub pad: Pad,
@ -23,13 +23,13 @@ pub struct Machine {
impl Machine { impl LogicalHardware {
pub const W: usize = 320; pub const W: usize = 320;
pub const H: usize = 180; pub const H: usize = 180;
pub const CYCLES_PER_FRAME: u64 = 100_000; // Exemplo de budget pub const CYCLES_PER_FRAME: u64 = 100_000; // Exemplo de budget
pub fn new() -> Self { pub fn new() -> Self {
let mut machine = Self { let mut logical_hardware = Self {
gfx: Gfx::new(Self::W, Self::H), gfx: Gfx::new(Self::W, Self::H),
audio: Audio::new(), audio: Audio::new(),
pad: Pad::default(), pad: Pad::default(),
@ -44,9 +44,9 @@ impl Machine {
}; };
// Inicializa samples básicos // Inicializa samples básicos
machine.sample_square = Some(Arc::new(Self::create_square_sample(440.0, 0.1))); logical_hardware.sample_square = Some(Arc::new(Self::create_square_sample(440.0, 0.1)));
machine logical_hardware
} }
pub fn get_color(&self, index: usize) -> Color { pub fn get_color(&self, index: usize) -> Color {
@ -116,7 +116,7 @@ impl Machine {
let start = std::time::Instant::now(); let start = std::time::Instant::now();
self.begin_frame(signals); self.begin_frame(signals);
// Retira a VM temporariamente para executar run_budget passando self (Machine) como NativeInterface. // Retira a VM temporariamente para executar run_budget passando self (Logical Hardware) como NativeInterface.
// Como VirtualMachine implementa Default, usamos std::mem::take. // Como VirtualMachine implementa Default, usamos std::mem::take.
let mut vm = std::mem::take(&mut self.vm); let mut vm = std::mem::take(&mut self.vm);
let _result = vm.run_budget(Self::CYCLES_PER_FRAME, self); let _result = vm.run_budget(Self::CYCLES_PER_FRAME, self);

View File

@ -1,11 +1,11 @@
use crate::vm::{Value, VirtualMachine}; use crate::vm::{Value, VirtualMachine};
use crate::Machine; use crate::LogicalHardware;
pub trait NativeInterface { pub trait NativeInterface {
fn syscall(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String>; fn syscall(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String>;
} }
impl NativeInterface for Machine { impl NativeInterface for LogicalHardware {
fn syscall(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String> { fn syscall(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String> {
match id { match id {
// system.has_cart() -> bool // system.has_cart() -> bool

View File

@ -726,10 +726,10 @@ mod tests {
#[test] #[test]
fn test_system_run_cart() { fn test_system_run_cart() {
use crate::Machine; use crate::LogicalHardware;
use crate::model::Cartridge; use crate::model::Cartridge;
let mut machine = Machine::new(); let mut logical_hardware = LogicalHardware::new();
// 1. Verifica que não tem cartucho inicialmente // 1. Verifica que não tem cartucho inicialmente
let mut rom = Vec::new(); let mut rom = Vec::new();
@ -738,12 +738,12 @@ mod tests {
utilz::emit_u32(&mut rom, 0x0001); utilz::emit_u32(&mut rom, 0x0001);
utilz::emit_op(&mut rom, OpCode::Halt); utilz::emit_op(&mut rom, OpCode::Halt);
machine.vm = VirtualMachine::new(rom, vec![]); logical_hardware.vm = VirtualMachine::new(rom, vec![]);
let mut vm = std::mem::take(&mut machine.vm); let mut vm = std::mem::take(&mut logical_hardware.vm);
vm.run_budget(100, &mut machine).unwrap(); vm.run_budget(100, &mut logical_hardware).unwrap();
machine.vm = vm; logical_hardware.vm = vm;
assert_eq!(machine.vm.pop().unwrap(), Value::Boolean(false)); assert_eq!(logical_hardware.vm.pop().unwrap(), Value::Boolean(false));
// 2. Adiciona um cartucho e roda // 2. Adiciona um cartucho e roda
let mut cart_rom = Vec::new(); let mut cart_rom = Vec::new();
@ -754,7 +754,7 @@ mod tests {
let cart_pool = vec![Value::Integer(42)]; let cart_pool = vec![Value::Integer(42)];
let cart = Cartridge::new(Program::new(cart_rom, cart_pool)); let cart = Cartridge::new(Program::new(cart_rom, cart_pool));
machine.load_cartridge(cart); logical_hardware.load_cartridge(cart);
// Código para rodar o cartucho // Código para rodar o cartucho
let mut boot_rom = Vec::new(); let mut boot_rom = Vec::new();
@ -762,14 +762,14 @@ mod tests {
utilz::emit_op(&mut boot_rom, OpCode::Syscall); utilz::emit_op(&mut boot_rom, OpCode::Syscall);
utilz::emit_u32(&mut boot_rom, 0x0002); utilz::emit_u32(&mut boot_rom, 0x0002);
machine.vm = VirtualMachine::new(boot_rom, vec![]); logical_hardware.vm = VirtualMachine::new(boot_rom, vec![]);
let mut vm = std::mem::take(&mut machine.vm); let mut vm = std::mem::take(&mut logical_hardware.vm);
vm.run_budget(1000, &mut machine).unwrap(); vm.run_budget(1000, &mut logical_hardware).unwrap();
machine.vm = vm; logical_hardware.vm = vm;
// Após o run_budget, a VM deve ter executado o cartucho // Após o run_budget, a VM deve ter executado o cartucho
assert_eq!(machine.vm.operand_stack.last(), Some(&Value::Integer(42))); assert_eq!(logical_hardware.vm.operand_stack.last(), Some(&Value::Integer(42)));
assert!(machine.vm.halted); assert!(logical_hardware.vm.halted);
} }
#[test] #[test]

View File

@ -6,7 +6,7 @@ mod audio_mixer;
use audio_mixer::AudioMixer; use audio_mixer::AudioMixer;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use prometeu_core::peripherals::{AudioCommand, InputSignals, OUTPUT_SAMPLE_RATE}; use prometeu_core::peripherals::{AudioCommand, InputSignals, OUTPUT_SAMPLE_RATE};
use prometeu_core::Machine; use prometeu_core::LogicalHardware;
use ringbuf::traits::{Consumer, Producer, Split}; use ringbuf::traits::{Consumer, Producer, Split};
use ringbuf::HeapRb; use ringbuf::HeapRb;
use std::sync::Arc; use std::sync::Arc;
@ -32,7 +32,7 @@ struct PrometeuApp {
window: Option<&'static Window>, window: Option<&'static Window>,
pixels: Option<Pixels<'static>>, pixels: Option<Pixels<'static>>,
machine: Machine, logical_hardware: LogicalHardware,
input_signals: InputSignals, input_signals: InputSignals,
@ -58,7 +58,7 @@ impl PrometeuApp {
window: None, window: None,
pixels: None, pixels: None,
machine: Machine::new(), logical_hardware: LogicalHardware::new(),
input_signals: InputSignals::default(), input_signals: InputSignals::default(),
@ -160,7 +160,7 @@ impl ApplicationHandler for PrometeuApp {
let size = window.inner_size(); let size = window.inner_size();
let surface_texture = SurfaceTexture::new(size.width, size.height, window); let surface_texture = SurfaceTexture::new(size.width, size.height, window);
let mut pixels = Pixels::new(Machine::W as u32, Machine::H as u32, surface_texture) let mut pixels = Pixels::new(LogicalHardware::W as u32, LogicalHardware::H as u32, surface_texture)
.expect("failed to create Pixels"); .expect("failed to create Pixels");
pixels.frame_mut().fill(0); pixels.frame_mut().fill(0);
@ -195,7 +195,7 @@ impl ApplicationHandler for PrometeuApp {
let frame = pixels.frame_mut(); let frame = pixels.frame_mut();
// Borrow imutável do core (campo diferente, ok) // Borrow imutável do core (campo diferente, ok)
let src = self.machine.gfx.front_buffer(); let src = self.logical_hardware.gfx.front_buffer();
draw_rgb565_to_rgba8(src, frame); draw_rgb565_to_rgba8(src, frame);
} // <- frame borrow termina aqui } // <- frame borrow termina aqui
@ -268,11 +268,11 @@ impl ApplicationHandler for PrometeuApp {
// 🔥 O coração do determinismo: consome o tempo em fatias exatas de 60Hz // 🔥 O coração do determinismo: consome o tempo em fatias exatas de 60Hz
while self.accumulator >= self.frame_target_dt { while self.accumulator >= self.frame_target_dt {
self.machine.step_frame(&self.input_signals); self.logical_hardware.step_frame(&self.input_signals);
// Envia comandos de áudio gerados neste frame para a thread de áudio // Envia comandos de áudio gerados neste frame para a thread de áudio
if let Some(producer) = &mut self.audio_producer { if let Some(producer) = &mut self.audio_producer {
for cmd in self.machine.audio.commands.drain(..) { for cmd in self.logical_hardware.audio.commands.drain(..) {
let _ = producer.try_push(cmd); let _ = producer.try_push(cmd);
} }
} }
@ -294,10 +294,11 @@ impl ApplicationHandler for PrometeuApp {
if stats_elapsed >= Duration::from_secs(1) { if stats_elapsed >= Duration::from_secs(1) {
if let Some(window) = self.window { if let Some(window) = self.window {
let fps = self.frames_since_last_update as f64 / stats_elapsed.as_secs_f64(); let fps = self.frames_since_last_update as f64 / stats_elapsed.as_secs_f64();
let kb = self.machine.gfx.memory_usage_bytes() as f64 / 1024.0; let kb = self.logical_hardware.gfx.memory_usage_bytes() as f64 / 1024.0;
// comparação fixa sempre contra 60Hz, manter mesmo quando fazer teste de stress na CPU
let frame_budget_us = 16666.0; let frame_budget_us = 16666.0;
let cpu_load_core = (self.machine.last_frame_cpu_time_us as f64 / frame_budget_us) * 100.0; let cpu_load_core = (self.logical_hardware.last_frame_cpu_time_us as f64 / frame_budget_us) * 100.0;
let cpu_load_audio = if self.audio_load_samples > 0 { let cpu_load_audio = if self.audio_load_samples > 0 {
// O load real é (tempo total processando) / (tempo total de parede). // O load real é (tempo total processando) / (tempo total de parede).
@ -308,7 +309,7 @@ impl ApplicationHandler for PrometeuApp {
let title = format!( let title = format!(
"PROMETEU | GFX: {:.1} KB | FPS: {:.1} | Load: {:.1}% (C) + {:.1}% (A) | Frame: {}", "PROMETEU | GFX: {:.1} KB | FPS: {:.1} | Load: {:.1}% (C) + {:.1}% (A) | Frame: {}",
kb, fps, cpu_load_core, cpu_load_audio, self.machine.frame_index kb, fps, cpu_load_core, cpu_load_audio, self.logical_hardware.frame_index
); );
window.set_title(&title); window.set_title(&title);
} }
@ -327,13 +328,13 @@ impl ApplicationHandler for PrometeuApp {
/// Depois podemos fazer letterbox/aspect-ratio correto. /// Depois podemos fazer letterbox/aspect-ratio correto.
fn window_to_fb(wx: f32, wy: f32, window: &Window) -> (i32, i32) { fn window_to_fb(wx: f32, wy: f32, window: &Window) -> (i32, i32) {
let size = window.inner_size(); let size = window.inner_size();
let fb_w = Machine::W as f32; let fb_w = LogicalHardware::W as f32;
let fb_h = Machine::H as f32; let fb_h = LogicalHardware::H as f32;
let x = (wx * fb_w / size.width as f32).floor() as i32; let x = (wx * fb_w / size.width as f32).floor() as i32;
let y = (wy * fb_h / size.height as f32).floor() as i32; let y = (wy * fb_h / size.height as f32).floor() as i32;
(x.clamp(0, Machine::W as i32 - 1), y.clamp(0, Machine::H as i32 - 1)) (x.clamp(0, LogicalHardware::W as i32 - 1), y.clamp(0, LogicalHardware::H as i32 - 1))
} }
/// Copia RGB565 (u16) -> RGBA8888 (u8[4]) para o frame do pixels. /// Copia RGB565 (u16) -> RGBA8888 (u8[4]) para o frame do pixels.