Skip to content

Commit

Permalink
Add extend example + renamed ChipType to ChipSet (deprecating ChipType)
Browse files Browse the repository at this point in the history
  • Loading branch information
VincentFoulon80 committed Mar 24, 2023
1 parent 0926a7b commit 64c12c0
Show file tree
Hide file tree
Showing 22 changed files with 283 additions and 133 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ license = "MIT"
name = "virt-ic"
readme = "README.md"
repository = "https://github.com/VincentFoulon80/virt-ic"
version = "0.5.1"
version = "0.5.2"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Take a look at the [generated documentation](https://docs.rs/virt-ic/).
# Examples

See [examples](https://github.com/VincentFoulon80/virt-ic/tree/master/examples) :
- **extend** : An example of how to add custom chips, by extending the built-in chipset
- **pins** : Read and write a set of pins using Pin::read and Pin::write
- **ram** : A simple test of a RAM chip
- **readme** : Same example as provided in this readme
Expand Down
142 changes: 142 additions & 0 deletions examples/extend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
use std::time::Duration;

use custom_chip::MyCustomChip;
use virt_ic::{
board::{Board, Trace},
chip::{gates::AndGate, generators::Generator, Chip, ChipBuilder, ChipSet},
impl_chip_type,
};

mod custom_chip {
use std::time::Duration;

use virt_ic::{
chip::{ChipBuilder, ChipRunner, Pin, PinId, PinType},
generate_chip, State,
};

use crate::CustomChipSet;

#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct MyCustomChip {
pub vcc: Pin,
pub gnd: Pin,
pub a: Pin,
pub na: Pin,
}

impl MyCustomChip {
pub const VCC: PinId = 1;
pub const GND: PinId = 2;
pub const A: PinId = 3;
pub const NA: PinId = 4;
}

impl ChipBuilder<CustomChipSet> for MyCustomChip {
fn build() -> CustomChipSet {
CustomChipSet::MyCustomChip(MyCustomChip {
vcc: Pin::from(PinType::Input),
gnd: Pin::from(PinType::Output),
a: Pin::from(PinType::Input),
na: Pin::from(PinType::Output),
})
}
}

generate_chip!(
MyCustomChip,
vcc: MyCustomChip::VCC,
gnd: MyCustomChip::GND,
a: MyCustomChip::A,
na: MyCustomChip::NA
);

impl ChipRunner for MyCustomChip {
fn run(&mut self, _: Duration) {
if self.vcc.state.as_logic(3.3) == State::High {
self.gnd.state = State::Low;
self.na.state = State::from(!bool::from(self.a.state.as_logic(3.3)));
}
}
}
}

#[derive(Debug, Clone)]
pub enum CustomChipSet {
MyCustomChip(MyCustomChip),
Builtin(ChipSet),
}

impl_chip_type!(CustomChipSet: (MyCustomChip, Builtin));

impl From<ChipSet> for CustomChipSet {
fn from(value: ChipSet) -> Self {
CustomChipSet::Builtin(value)
}
}

fn main() {
// create a new board
let mut board: Board<CustomChipSet> = Board::new();
// place an AND gate to the board
let and_gate = board.register_chip(AndGate::build().into());
// also place a generator
let vcc = board.register_chip(ChipSet::from(Generator::build()).into());
let gnd = board
.register_chip(ChipSet::from(Generator::build().with_state(virt_ic::State::Low)).into());

let custom = board.register_chip(MyCustomChip::build());

// Connect the AndGate's VCC, A and B pins with the Generator
let mut trace = Trace::new();
trace.connect(vcc, Generator::OUT);
trace.connect(and_gate, AndGate::VCC);
trace.connect(custom, MyCustomChip::VCC);
trace.connect(custom, MyCustomChip::A);
trace.connect(and_gate, AndGate::B);
let trace_vcc = board.register_trace(trace);

board.connect(custom, MyCustomChip::NA, and_gate, AndGate::A);

// Alternative way to connect chips via board, connect GND pins
let trace_gnd = board.register_trace(Trace::from(vec![
(gnd, Generator::OUT),
(and_gate, AndGate::GND),
(custom, MyCustomChip::GND),
]));

// simulate the board for 10ms
board.run_realtime(Duration::from_millis(10));

// check the results
if let Some(chip) = board.get_chip(&and_gate) {
println!(
"A={:?}, \tB={:?}, \tA&B={:?}",
chip.get_pin(AndGate::A).map(|p| p.state),
chip.get_pin(AndGate::B).map(|p| p.state),
chip.get_pin(AndGate::AB).map(|p| p.state)
);
}

// disconnect AndGate's pin B from VCC and connect it instead to GND
if let Some(t) = board.get_trace_mut(&trace_vcc) {
t.disconnect(custom, MyCustomChip::A)
}
if let Some(t) = board.get_trace_mut(&trace_gnd) {
t.connect(custom, MyCustomChip::A)
}

// simulate the board for another 10ms
board.run_realtime(Duration::from_millis(10));

// check the results
if let Some(chip) = board.get_chip(&and_gate) {
println!(
"A={:?}, \tB={:?}, \tA&B={:?}",
chip.get_pin(AndGate::A).map(|p| p.state),
chip.get_pin(AndGate::B).map(|p| p.state),
chip.get_pin(AndGate::AB).map(|p| p.state)
);
}
}
4 changes: 2 additions & 2 deletions examples/ram.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::time::Duration;

use virt_ic::{
chip::{memories::Ram256B, ChipBuilder, ChipRunner, ChipType, Pin},
chip::{memories::Ram256B, ChipBuilder, ChipRunner, ChipSet, Pin},
State,
};

fn main() {
if let ChipType::Ram256B(mut ram) = Ram256B::build() {
if let ChipSet::Ram256B(mut ram) = Ram256B::build() {
ram.vcc.state = State::High;

ram.run(Duration::from_millis(10));
Expand Down
4 changes: 2 additions & 2 deletions examples/readme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use std::time::Duration;

use virt_ic::{
board::{Board, Trace},
chip::{gates::AndGate, generators::Generator, Chip, ChipBuilder, ChipType},
chip::{gates::AndGate, generators::Generator, Chip, ChipBuilder, ChipSet},
};

fn main() {
// create a new board
let mut board: Board<ChipType> = Board::new();
let mut board: Board<ChipSet> = Board::new();
// place an AND gate to the board
let and_gate = board.register_chip(AndGate::build());
// also place a generator
Expand Down
6 changes: 3 additions & 3 deletions examples/save.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ use std::time::Duration;
use ron::ser::PrettyConfig;
use virt_ic::{
board::{Board, Trace},
chip::{gates::AndGate, generators::Generator, ChipBuilder, ChipType},
chip::{gates::AndGate, generators::Generator, ChipBuilder, ChipSet},
};

fn main() {
let mut board: Board<ChipType> = Board::new();
let mut board: Board<ChipSet> = Board::new();

let and_gate = board.register_chip(AndGate::build());

Expand All @@ -29,7 +29,7 @@ fn main() {

println!("{}", saved);

let mut board2: Board<ChipType> = ron::de::from_str(&saved).unwrap();
let mut board2: Board<ChipSet> = ron::de::from_str(&saved).unwrap();

if let Some(t) = board2.get_trace_mut(&trace) {
t.disconnect(and_gate, AndGate::A);
Expand Down
28 changes: 14 additions & 14 deletions examples/segment-display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use virt_ic::{
generators::Generator,
inputs::Button,
outputs::{SegmentDisplay, SevenSegmentsDecoder},
ChipBuilder, ChipType,
ChipBuilder, ChipSet,
},
};

fn main() {
let mut board: Board<ChipType> = Board::new();
let mut board: Board<ChipSet> = Board::new();

let seg_dec = board.register_chip(SevenSegmentsDecoder::build());

Expand Down Expand Up @@ -85,55 +85,55 @@ fn main() {

board.run_realtime(Duration::from_millis(100));

if let Some(ChipType::SegmentDisplay(display)) = board.get_chip(&display) {
if let Some(ChipSet::SegmentDisplay(display)) = board.get_chip(&display) {
println!("{}:\n{}", display.as_char(), display.to_string());
}

if let Some(ChipType::Button(a)) = board.get_chip_mut(&btn_a) {
if let Some(ChipSet::Button(a)) = board.get_chip_mut(&btn_a) {
a.press();
}

board.run_realtime(Duration::from_millis(100));

if let Some(ChipType::SegmentDisplay(display)) = board.get_chip(&display) {
if let Some(ChipSet::SegmentDisplay(display)) = board.get_chip(&display) {
println!("{}:\n{}", display.as_char(), display.to_string());
}

if let Some(ChipType::Button(a)) = board.get_chip_mut(&btn_a) {
if let Some(ChipSet::Button(a)) = board.get_chip_mut(&btn_a) {
a.release();
}
if let Some(ChipType::Button(b)) = board.get_chip_mut(&btn_b) {
if let Some(ChipSet::Button(b)) = board.get_chip_mut(&btn_b) {
b.press();
}

board.run_realtime(Duration::from_millis(100));

if let Some(ChipType::SegmentDisplay(display)) = board.get_chip(&display) {
if let Some(ChipSet::SegmentDisplay(display)) = board.get_chip(&display) {
println!("{}:\n{}", display.as_char(), display.to_string());
}
if let Some(ChipType::Button(b)) = board.get_chip_mut(&btn_b) {
if let Some(ChipSet::Button(b)) = board.get_chip_mut(&btn_b) {
b.release();
}
if let Some(ChipType::Button(c)) = board.get_chip_mut(&btn_c) {
if let Some(ChipSet::Button(c)) = board.get_chip_mut(&btn_c) {
c.press();
}

board.run_realtime(Duration::from_millis(100));

if let Some(ChipType::SegmentDisplay(display)) = board.get_chip(&display) {
if let Some(ChipSet::SegmentDisplay(display)) = board.get_chip(&display) {
println!("{}:\n{}", display.as_char(), display.to_string());
}

if let Some(ChipType::Button(c)) = board.get_chip_mut(&btn_c) {
if let Some(ChipSet::Button(c)) = board.get_chip_mut(&btn_c) {
c.release();
}
if let Some(ChipType::Button(d)) = board.get_chip_mut(&btn_d) {
if let Some(ChipSet::Button(d)) = board.get_chip_mut(&btn_d) {
d.press();
}

board.run_realtime(Duration::from_millis(100));

if let Some(ChipType::SegmentDisplay(display)) = board.get_chip(&display) {
if let Some(ChipSet::SegmentDisplay(display)) = board.get_chip(&display) {
println!("{}:\n{}", display.as_char(), display.to_string());
}
}
12 changes: 6 additions & 6 deletions examples/sr-latch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::time::Duration;

use virt_ic::{
board::{Board, Trace},
chip::{gates::NandGate, generators::Generator, inputs::Button, Chip, ChipBuilder, ChipType},
chip::{gates::NandGate, generators::Generator, inputs::Button, Chip, ChipBuilder, ChipSet},
};

/// ```txt
Expand All @@ -21,7 +21,7 @@ use virt_ic::{
/// \
/// ```
fn main() {
let mut board: Board<ChipType> = Board::new();
let mut board: Board<ChipSet> = Board::new();

let nand = board.register_chip(NandGate::build());

Expand All @@ -48,23 +48,23 @@ fn main() {
println!("initial state");
dbg!(board.get_chip(&nand).and_then(|c| c.get_pin(NandGate::AB)));

if let Some(ChipType::Button(btn)) = board.get_chip_mut(&set_btn) {
if let Some(ChipSet::Button(btn)) = board.get_chip_mut(&set_btn) {
btn.press();
}
board.run(Duration::from_millis(1));
if let Some(ChipType::Button(btn)) = board.get_chip_mut(&set_btn) {
if let Some(ChipSet::Button(btn)) = board.get_chip_mut(&set_btn) {
btn.release();
}
board.run(Duration::from_millis(1));

println!("after set");
dbg!(board.get_chip(&nand).and_then(|c| c.get_pin(NandGate::AB)));

if let Some(ChipType::Button(btn)) = board.get_chip_mut(&reset_btn) {
if let Some(ChipSet::Button(btn)) = board.get_chip_mut(&reset_btn) {
btn.press();
}
board.run(Duration::from_millis(1));
if let Some(ChipType::Button(btn)) = board.get_chip_mut(&reset_btn) {
if let Some(ChipSet::Button(btn)) = board.get_chip_mut(&reset_btn) {
btn.release();
}
board.run(Duration::from_millis(1));
Expand Down
12 changes: 6 additions & 6 deletions examples/test-6502.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use virt_ic::{
gates::NotGate,
generators::Generator,
memories::{Ram256B, Rom256B},
ChipBuilder, ChipType,
ChipBuilder, ChipSet,
},
};

Expand All @@ -26,7 +26,7 @@ use virt_ic::{
/// This example will show the content of ROM, RAM then run the CPU for a certain amount of time,
/// and finally show the content of RAM after the simulation has ended.
fn main() {
let mut board: Board<ChipType> = Board::new();
let mut board: Board<ChipSet> = Board::new();

// assemble a 6502 program
let mut prg = nes6502::Assembler::assemble(&[
Expand Down Expand Up @@ -127,11 +127,11 @@ fn main() {

board.run(Duration::from_millis(1));

if let Some(ChipType::Rom256B(rom)) = board.get_chip(&rom) {
if let Some(ChipSet::Rom256B(rom)) = board.get_chip(&rom) {
println!("ROM CONTENT");
println!("{}", rom.to_string());
}
if let Some(ChipType::Ram256B(ram)) = board.get_chip(&ram) {
if let Some(ChipSet::Ram256B(ram)) = board.get_chip(&ram) {
println!("RAM CONTENT");
println!("{}", ram.to_string());
}
Expand All @@ -140,12 +140,12 @@ fn main() {
for _ in 0..160 {
board.run_realtime(Duration::from_millis(20));

if let Some(ChipType::Nes6502(cpu)) = board.get_chip(&cpu) {
if let Some(ChipSet::Nes6502(cpu)) = board.get_chip(&cpu) {
println!("{}", cpu.to_string());
}
}

if let Some(ChipType::Ram256B(ram)) = board.get_chip(&ram) {
if let Some(ChipSet::Ram256B(ram)) = board.get_chip(&ram) {
println!("RAM CONTENT");
println!("{}", ram.to_string());
}
Expand Down
Loading

0 comments on commit 64c12c0

Please sign in to comment.