1use crate::{
4 BLOCK_BASE, BlockDevice, CONSOLE_BASE, Console, DEVICE_BASE, DEVICE_STRIDE, Device, TIMER_BASE,
5 Timer,
6};
7use ternaria_arith::{Trit, Tryte, Word};
8use ternaria_mem::{Addressable, Memory, MemoryError, irq};
9
10pub struct Bus {
16 pub ram: Memory,
18 pub console: Console,
20 pub timer: Timer,
22 pub block: BlockDevice,
24}
25
26impl Bus {
27 pub fn new(console: Console, timer: Timer, block: BlockDevice) -> Bus {
29 Bus {
30 ram: Memory::new(),
31 console,
32 timer,
33 block,
34 }
35 }
36
37 pub fn with_image(image: impl Into<Vec<u8>>) -> Bus {
39 Bus::new(Console::new(), Timer::new(), BlockDevice::new(image))
40 }
41
42 pub fn tick(&mut self) {
44 self.timer.tick();
45 }
46
47 fn route(&mut self, addr: i64) -> Option<(&mut dyn Device, i64)> {
49 if !(DEVICE_BASE..DEVICE_BASE + 3 * DEVICE_STRIDE).contains(&addr) {
50 return None;
51 }
52 if addr < TIMER_BASE {
53 Some((&mut self.console, addr - CONSOLE_BASE))
54 } else if addr < BLOCK_BASE {
55 Some((&mut self.timer, addr - TIMER_BASE))
56 } else {
57 Some((&mut self.block, addr - BLOCK_BASE))
58 }
59 }
60}
61
62impl Addressable for Bus {
63 fn is_privileged(&self, addr: Word) -> bool {
65 let a = addr.value();
66 (DEVICE_BASE..DEVICE_BASE + 3 * DEVICE_STRIDE).contains(&a)
67 }
68
69 fn interrupts(&self) -> Word {
71 let mut trits = [Trit::Zero; 27];
72 if self.timer.is_firing() {
73 trits[irq::TIMER] = Trit::Pos;
74 }
75 if self.console.has_input() {
76 trits[irq::CONSOLE] = Trit::Pos;
77 }
78 Word::from_trits(trits)
79 }
80
81 fn read_tryte(&mut self, addr: Word) -> Result<Tryte, MemoryError> {
82 let a = addr.value();
83 match self.route(a) {
84 Some((dev, off)) => dev.read(off),
85 None => self.ram.read_tryte(addr),
86 }
87 }
88
89 fn write_tryte(&mut self, addr: Word, value: Tryte) -> Result<(), MemoryError> {
90 let a = addr.value();
91 match self.route(a) {
92 Some((dev, off)) => dev.write(off, value),
93 None => self.ram.write_tryte(addr, value),
94 }
95 }
96
97 fn read_word(&mut self, addr: Word) -> Result<Word, MemoryError> {
98 let a = addr.value();
99 if self.route(a).is_none() {
100 return self.ram.read_word(addr);
101 }
102 if a.rem_euclid(3) != 0 {
105 return Err(MemoryError::Misaligned { addr: a });
106 }
107 let mut trytes = [Tryte::ZERO; Word::TRYTES];
108 for (i, slot) in trytes.iter_mut().enumerate() {
109 *slot = self.read_tryte(Word::from_value(a + i as i64))?;
110 }
111 Ok(Word::from_trytes(trytes))
112 }
113
114 fn write_word(&mut self, addr: Word, value: Word) -> Result<(), MemoryError> {
115 let a = addr.value();
116 if self.route(a).is_none() {
117 return self.ram.write_word(addr, value);
118 }
119 if a.rem_euclid(3) != 0 {
120 return Err(MemoryError::Misaligned { addr: a });
121 }
122 for i in 0..Word::TRYTES {
123 self.write_tryte(Word::from_value(a + i as i64), value.tryte(i))?;
124 }
125 Ok(())
126 }
127}