This library is a Integrated Circuit Emulator backend that can simulate interactions between multiple chips.
Note that for now there is mostly Digital circuit emulation, Analog signals are kinda present but still need work.
You start by creating a Board, register Chips and Traces, and link Chip pins together to form a virtual circuit. You can then run the circuit to emulate the chips and links between them.
This library is a Backend emulator, it means that there is no GUI to create boards.
The entire library has been rewritten from scratch in order to ease the use of this crate, remove all those Rc<RefCell>
that were degrading the readability of your code. Thus, virt-ic up before 0.5.0 is completely incompatible with newer versions.
- Build Boards with chips and traces between them
- Simulate the board for a certain duration with a certain step, it's also possible to run it in realtime !
- Save and load the board to backup your design or continue your simulation later
- Generator
- Logic Gates (And, Or, Not, Nand, Nor)
- Button
- Clock
- Memory (RAM, ROM)
- Segment display
- CPU (a 6502, missing interrupts and decimal mode)
This project is open to any contribution, from code reviewing to direct contribution ! You can :
- Suggest or Improve current code
- Suggest or Add new features
- Suggest or Add new built-in chips
- Any initiative is welcome !
use std::time::Duration;
use virt_ic::{
board::{Board, Trace},
chip::{gates::AndGate, generators::Generator, Chip, ChipBuilder, ChipType},
};
fn main() {
// create a new board
let mut board: Board<ChipType> = Board::new();
// place an AND gate to the board
let and_gate = board.register_chip(AndGate::build());
// also place a generator
let vcc = board.register_chip(Generator::build().into());
let gnd = board.register_chip(Generator::build().with_state(virt_ic::State::Low).into());
// 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(and_gate, AndGate::A);
trace.connect(and_gate, AndGate::B);
let trace_vcc = board.register_trace(trace);
// Alternative way to connect chips via board, connect GND pins
let trace_gnd = board.connect(gnd, Generator::OUT, and_gate, AndGate::GND);
// simulate the board for 10ms
board.run(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(and_gate, AndGate::B)
}
if let Some(t) = board.get_trace_mut(&trace_gnd) {
t.connect(and_gate, AndGate::B)
}
// simulate the board for another 10ms
board.run(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)
);
}
}
Take a look at the generated documentation.
See 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
- save : Board saving and loading example
- segment-display : Simple segment display test
- sr-latch : Example of a working SR-Latch
- test-6502 : Test the Nes6502 CPU with a small program and basic ROM and RAM layout