diff --git a/crates/cpu/src/lib.rs b/crates/cpu/src/lib.rs index bae3720..575357b 100644 --- a/crates/cpu/src/lib.rs +++ b/crates/cpu/src/lib.rs @@ -6,3 +6,5 @@ pub mod reg_alloc; pub mod register; pub mod unit; pub mod util; +//TODO read other modules +pub mod main_memory; diff --git a/crates/cpu/src/main_memory.rs b/crates/cpu/src/main_memory.rs new file mode 100644 index 0000000..b933cb9 --- /dev/null +++ b/crates/cpu/src/main_memory.rs @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// See Notices.txt for copyright information + +// first copied code block -- changes needed +use crate::{ + config::CpuConfig, + instruction::{ + AluBranchMOp, LoadStoreMOp, MOp, MOpDestReg, MOpInto, MOpRegNum, MOpTrait, RenamedMOp, + UnitOutRegNum, mop_enum, + }, + register::{FlagsMode, PRegValue}, + unit::unit_base::UnitToRegAlloc, +}; +use fayalite::{ + bundle::{Bundle, BundleType}, + intern::{Intern, Interned}, + prelude::*, +}; + +//input address <32> bit ? +//output data word <8> bit for first test (read only) + +#[hdl_module] +/// add a comment here +pub fn main_memory(config: &CpuConfig) { + #[hdl] + let addr: UInt<64> = m.input(); + #[hdl] + let read_data: UInt<64> = m.output(); + #[hdl] + let en: Bool = m.input(); + + //WIP: add write support + #[hdl] + let write_en: Bool = m.input(); + #[hdl] + let write_data: UInt<64> = m.input(); + + #[hdl] + let cd: ClockDomain = m.input(); + + #[hdl] // FIXME: do not hardcode memory size and content -- + //let mut my_memory = memory_with_init([0x12_hdl_u8, 0x34_hdl_u8, 0x56_hdl_u8, 0x78_hdl_u8]); + let mut my_memory = memory(); + my_memory.depth(256); //TODO make configurable + + let read_port = my_memory.new_read_port(); + connect_any(read_port.addr, addr); + connect_any(read_port.en, addr.cmp_lt(256u64) & en); // and not write_en + connect(read_port.clk, cd.clk); + connect(read_data, read_port.data); + + let write_port = my_memory.new_write_port(); + connect_any(write_port.addr, addr); + connect_any(write_port.en, addr.cmp_lt(256u64) & en & write_en); + connect_any(write_port.data, write_data); + connect(write_port.clk, cd.clk); + + connect_any(write_port.mask, true); //can only write 8 bits at a time +} diff --git a/crates/cpu/tests/main_memory.rs b/crates/cpu/tests/main_memory.rs new file mode 100644 index 0000000..7ac85a2 --- /dev/null +++ b/crates/cpu/tests/main_memory.rs @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// See Notices.txt for copyright information + +use cpu::{ + config::{CpuConfig, UnitConfig}, + instruction::{AddSubMOp, LogicalMOp, MOp, MOpDestReg, MOpRegNum, OutputIntegerMode}, + main_memory::main_memory, + reg_alloc::{FetchedDecodedMOp, reg_alloc}, + register::{FlagsMode, PRegFlagsPowerISA}, + unit::{GlobalState, UnitKind}, +}; +use fayalite::{ + assert_export_firrtl, + firrtl::ExportOptions, + prelude::*, + sim::{Simulation, time::SimDuration, vcd::VcdWriterDecls}, + util::RcWriter, +}; +use std::num::NonZeroUsize; + +//new test - much simpler +#[test] +fn test_main_memory() { + let mut config = CpuConfig::new( + vec![ + UnitConfig::new(UnitKind::AluBranch), + UnitConfig::new(UnitKind::AluBranch), + ], + NonZeroUsize::new(20).unwrap(), + ); + // create a simulation from main_memory() + let mut sim = Simulation::new(main_memory(&config)); + // add a .vcd writer that writes to main_memory.vcd -- this is simple for demo purposes, + // but for our actual code we should do better than just writing + // to main_memory.vcd in the repository's root + //WRONG: sim.add_trace_writer(std::fs::File::create("main_memory.vcd").unwrap()); + + let out_file = std::fs::File::create("main_memory.vcd").unwrap(); + sim.add_trace_writer(VcdWriterDecls::new(out_file)); + + sim.write(sim.io().en, true); + sim.write(sim.io().cd.rst, false); + sim.write(sim.io().cd.clk, false); + sim.write(sim.io().write_en, false); + sim.write(sim.io().write_data, 0xFF00FF00FF00FF00u64); + + // TODO convert to for loop + // you need to write an initial value to all inputs before you can start running the simulation + sim.write(sim.io().addr, 0x12345u64); + // now wait 1us because why not + sim.advance_time(SimDuration::from_micros(1)); //panic here at simulation + + dbg!(sim.read(sim.io().read_data)); // dbg! macro just displays the value you pass to it + + for n in 0u64..4u64 { + sim.write(sim.io().addr, n); + // now wait 1us because why not + sim.advance_time(SimDuration::from_micros(1)); + } + + sim.write(sim.io().write_en, true); + sim.write(sim.io().addr, 0u64); + sim.write(sim.io().write_data, 0xFFFFFFFFFFFFFFFFu64); //fill with ones + + sim.write_clock(sim.io().cd.clk, true); + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(sim.io().cd.clk, false); + sim.advance_time(SimDuration::from_micros(1)); + + sim.write(sim.io().addr, 1u64); + + sim.write_clock(sim.io().cd.clk, true); + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(sim.io().cd.clk, false); + sim.advance_time(SimDuration::from_micros(1)); + + sim.write(sim.io().addr, 2u64); + + sim.write_clock(sim.io().cd.clk, true); + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(sim.io().cd.clk, false); + sim.advance_time(SimDuration::from_micros(1)); + + sim.write(sim.io().addr, 3u64); + + sim.write_clock(sim.io().cd.clk, true); + sim.advance_time(SimDuration::from_micros(1)); + sim.write_clock(sim.io().cd.clk, false); + sim.advance_time(SimDuration::from_micros(1)); + + sim.flush_traces().unwrap(); // make sure everything is written to the output file +}