// Copyright (c) 2025 taitep // SPDX-License-Identifier: BSD-2-Clause // // This file is part of TRVE (https://gitea.taitep.se/taitep/trve) // See LICENSE file in the project root for full license text. use std::{path::PathBuf, sync::Arc, time::Duration}; use clap::Parser; use trve::{ consts::{Addr, Byte, DWord, HWord, Word}, core::Core, exceptions::MemoryException, gdb, mem::{MemConfig, MemDeviceInterface, MmioRoot, Ram}, }; use anyhow::Result; use crate::basic_uart::BasicUart; mod execload; #[derive(Parser)] struct Args { executable: PathBuf, #[arg(long)] wait: bool, } fn main() -> Result<()> { let args = Args::parse(); let mut ram = Ram::try_new(16 * 1024 * 1024)?; let buf = ram.buf_mut(); let entry_point = execload::load(args.executable, buf)?; let mut mmio_root = MmioRoot::default(); mmio_root.insert(0, Arc::new(DbgOut)); let uart = BasicUart::new(); let uart = uart.spawn_poller(Duration::from_millis(10)); mmio_root.insert(0x10000, uart); let mem_cfg = MemConfig { ram: Arc::new(ram), mmio_root, }; let (cmd_sender, cmd_reciever) = std::sync::mpsc::channel(); gdb::run_stub(cmd_sender.clone()); let mut core = Core::new(mem_cfg, cmd_reciever); core.reset(entry_point); if args.wait { core.run_waiting_for_cmd(); } else { core.run(); } Ok(()) } mod basic_uart; struct DbgOut; impl MemDeviceInterface for DbgOut { fn write_dword(&self, addr: Addr, value: DWord) -> Result<(), MemoryException> { eprintln!("Wrote DWord {value:016x} to Debug-Out address {addr:x}"); Ok(()) } fn write_word(&self, addr: Addr, value: Word) -> Result<(), MemoryException> { eprintln!("Wrote Word {value:08x} to Debug-Out address {addr:x}"); Ok(()) } fn write_hword(&self, addr: Addr, value: HWord) -> Result<(), MemoryException> { eprintln!("Wrote HWord {value:04x} to Debug-Out address {addr:x}"); Ok(()) } fn write_byte(&self, addr: Addr, value: Byte) -> Result<(), MemoryException> { eprintln!("Wrote Byte {value:02x} to Debug-Out address {addr:x}"); Ok(()) } }