use super::control_logic::*;
use logicsim::*;
pub struct ComputerIO {
pub ig: InitializedGateGraph,
pub clock: LeverHandle,
pub reset: LeverHandle,
pub ack: LeverHandle,
pub input: WordInput,
pub write_input: LeverHandle,
pub input_busy: OutputHandle,
pub output: OutputHandle,
pub output_updated: OutputHandle,
}
pub fn mk_computer(rom_in: &[u16], ram_address_space: usize) -> ComputerIO {
let mut graph = GateGraphBuilder::new();
let g = &mut graph;
let bits = 8;
let bus = Bus::new(g, bits, "main_bus");
wire!(g, clock);
wire!(g, reset);
let clock_lever = clock.make_lever(g);
let reset_lever = reset.make_lever(g);
let ack_lever = g.lever("ack");
let nclock = g.not1(clock.bit(), "nclock");
let mut rom_data = Vec::new();
for word in rom_in {
rom_data.extend_from_slice(&word.to_ne_bytes())
}
let signals = ControlSignalsSet::new(g);
let pc_output = counter(
g,
clock.bit(),
signals.pc_enable().bit(),
signals.jmp().bit(),
signals.pc_out().bit(),
reset.bit(),
bus.bits(),
"pc",
);
bus.connect(g, &pc_output);
let rega_buffer = register(
g,
clock.bit(),
signals.rega_in().bit(),
ON,
reset.bit(),
bus.bits(),
"rega_buffer",
);
let rega_output = register(g, nclock, ON, ON, reset.bit(), ®a_buffer, "rega");
let rega_bus_output = bus_multiplexer(
g,
&[signals.rega_out().bit()],
&[&zeros(bits), ®a_output],
"rega_bus",
);
bus.connect(g, ®a_bus_output);
let regb_output = register(
g,
clock.bit(),
signals.regb_in().bit(),
ON,
reset.bit(),
bus.bits(),
"regb",
);
let regb_bus_output = bus_multiplexer(
g,
&[signals.regb_out().bit()],
&[&zeros(bits), ®b_output],
"regb_bus",
);
bus.connect(g, ®b_bus_output);
let alu_output = aluish(
g,
signals.cin().bit(),
signals.alu_out().bit(),
signals.alu_invert_regb().bit(),
®a_output,
®b_output,
"alu",
);
bus.connect(g, &alu_output);
let address_reg_output = register(
g,
clock.bit(),
signals.address_reg_in().bit(),
ON,
reset.bit(),
bus.bits(),
"areg",
);
let address_reg_bus_output = bus_multiplexer(
g,
&[signals.address_reg_out().bit()],
&[&zeros(bits), &address_reg_output],
"areg_bus",
);
bus.connect(g, &address_reg_bus_output);
let ram_address_space_bit = address_reg_output[bits - 1];
let rom_address_space_bit = g.not1(ram_address_space_bit, "ram_address_bit");
let rom_read_enable = g.and2(
signals.rom_out().bit(),
rom_address_space_bit,
"rom_read_enable",
);
let rom_output = rom(g, rom_read_enable, &address_reg_output, &rom_data, "rom");
bus.connect(g, &rom_output);
let ram_read_enable = g.and2(
signals.ram_out().bit(),
ram_address_space_bit,
"ram_read_enable",
);
let ram_write_enable = g.and2(
signals.ram_in().bit(),
ram_address_space_bit,
"ram_write_enable",
);
let ram_output = ram(
g,
ram_read_enable,
ram_write_enable,
clock.bit(),
reset.bit(),
&address_reg_output[0..ram_address_space],
bus.bits(),
"ram",
);
bus.connect(g, &ram_output);
let rego_output = io_register(
g,
clock.bit(),
signals.rego_in().bit(),
ON,
reset.bit(),
bus.bits(),
ack_lever.bit(),
"rego",
);
let regi_input = WordInput::new(g, bits, "regi_input");
let regi_write = g.lever("regi_write");
let regi_clock = g.or2(clock.bit(), regi_write.bit(), "regi_clock");
let (regi_changed, regi_output) = io_register(
g,
regi_clock,
regi_write.bit(),
signals.regi_out().bit(),
reset.bit(),
®i_input.bits(),
signals.regi_ack().bit(),
"regi",
);
let regi_busy_buffer = d_flip_flop(
g,
regi_changed,
nclock,
reset.bit(),
ON,
ON,
"regi_busy_buffer",
);
let regi_busy = g.output1(regi_busy_buffer, "regi_busy");
bus.connect(g, ®i_output);
let rega_zero = bus_multiplexer(g, ®a_output, &[&ones(1)], "rega_zero");
setup_control_logic(
g,
rega_zero[0],
regi_changed,
bus.clone(),
clock.bit(),
reset.bit(),
signals,
);
let t = std::time::Instant::now();
let output = g.output(®o_output.1, "output");
let output_updated = g.output1(rego_output.0, "updated");
let mut ig = graph.init();
ig.run_until_stable(100).unwrap();
ig.pulse_lever_stable(reset_lever);
println!("Init+reset time: {}ms", t.elapsed().as_millis());
println!("");
ComputerIO {
ig,
clock: clock_lever,
reset: reset_lever,
ack: ack_lever,
input: regi_input,
write_input: regi_write,
input_busy: regi_busy,
output,
output_updated,
}
}