Skip to main content

logicsim/circuits/
bus_multiplexer.rs

1use super::decoder;
2use crate::graph::*;
3
4fn mkname(name: String) -> String {
5    format!("BUSMUX:{}", name)
6}
7
8/// Returns one of the `inputs` selected by `address`.
9/// Conceptually it is a combination of [multiplexers](https://en.wikipedia.org/wiki/Multiplexer), one for each I/O bit.
10///
11/// The output width will be the width of the widest of the inputs.
12/// If not enough inputs are provided, the rest of the address space will be filled with [OFF].
13///
14/// # Example
15/// ```
16/// # use logicsim::{GateGraphBuilder,constant,bus_multiplexer};
17/// # let mut g = GateGraphBuilder::new();
18/// let input1 = constant(3u8);
19/// let input2 = constant(5u8);
20///
21/// let address = g.lever("address");
22///
23/// // Notice the carry and invert in bits are on.
24/// let result = bus_multiplexer(&mut g, &[address.bit()], &[&input1, &input2], "busmux");
25/// let output = g.output(&result, "result");
26///
27/// let ig = &mut g.init();
28/// ig.run_until_stable(2).unwrap();
29///
30/// assert_eq!(output.u8(ig), 3);
31///
32/// ig.flip_lever_stable(address);
33/// assert_eq!(output.u8(ig), 5);
34///
35/// ig.flip_lever_stable(address);
36/// assert_eq!(output.u8(ig), 3);
37/// ```
38///
39/// # Panics
40///
41/// Will panic if not enough `address` bits are provided to address every `input`.
42pub fn bus_multiplexer<S: Into<String>>(
43    g: &mut GateGraphBuilder,
44    address: &[GateIndex],
45    inputs: &[&[GateIndex]],
46    name: S,
47) -> Vec<GateIndex> {
48    assert!(
49        2usize.pow(address.len() as u32) >= inputs.len(),
50        "`address` doesn't have enough bits to address every input, address bits: {} input len:{}",
51        address.len(),
52        inputs.len(),
53    );
54
55    let name = mkname(name.into());
56
57    let width = inputs.iter().map(|i| i.len()).max().unwrap_or(0);
58    let out: Vec<_> = (0..width).map(|_| g.or(name.clone())).collect();
59
60    let decoded = decoder(g, address, name.clone());
61
62    for (input, input_enabled) in inputs.iter().zip(decoded) {
63        for (bit, big_or) in input.iter().zip(out.iter()) {
64            let and = g.and2(*bit, input_enabled, name.clone());
65            g.dpush(*big_or, and);
66        }
67    }
68    out
69}