1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
//! Traits for CPU and Peripheral devices that advance their internal state via a clock signal

use core::fmt;

use crate::bus::BusAccess;

/// Represents a device that can change state with the passage of a clock signal
///
/// Typically this would represent both CPU devices and peripheral devices that use a clock
/// signal to advance some internal process, such as a timer or state machine
pub trait Step<Address, Bus>
where
    Address: Copy,
    Bus: BusAccess<Address>,
{
    /// A type that is return if the step cannot be performed
    ///
    /// Note: this is not the same as BusAccess::Error
    type Error; //: From<Bus::Error>;

    /// Returns true if this device is still running.  This can be used to detect a stop or halt condition
    fn is_running(&mut self) -> bool;

    /// Reset the device to its initial state, as if the device's reset signal was asserted
    fn reset(&mut self, now: Bus::Instant, bus: &mut Bus) -> Result<(), Self::Error>;

    /// Step the process by one unit of time, and return the time at which this function should be called again
    ///
    /// The given `Instant` is the time at which this step occurs, and the returned `Instant` is the time that the
    /// next step should occur, according to the device itself.  The given bus can be used to access the system
    /// during this step of execution
    fn step(&mut self, now: Bus::Instant, bus: &mut Bus) -> Result<Bus::Instant, Self::Error>;
}

// TODO should this depend on Step, which is the most common way it will be used, even though it technically could
// be used for a device that just has a bus interface with no clock
/// Inspect the state of a device, and emit it to an object that implements `fmt::Write`
pub trait Inspect<Address, Bus, Writer>
where
    Address: Copy,
    Bus: BusAccess<Address>,
    Writer: fmt::Write,
{
    /// A type that describes the types of information or state that this device can emit
    type InfoType;

    /// A type that is returned if the data cannot be written as expected
    type Error;

    /// Write the given information type to the given writer, or return an error
    fn inspect(
        &mut self,
        info: Self::InfoType,
        bus: &mut Bus,
        writer: &mut Writer,
    ) -> Result<(), Self::Error>;

    /// Write a brief summary of the device's current state to the given writer, or return an error
    fn brief_summary(&mut self, bus: &mut Bus, writer: &mut Writer) -> Result<(), Self::Error>;

    /// Write a detailed summary of the device's current state to the given writer, or return an error
    fn detailed_summary(&mut self, bus: &mut Bus, writer: &mut Writer) -> Result<(), Self::Error>;
}

/// Control the execution of a CPU device for debugging purposes
pub trait Debug<Address, Bus, Writer>: Inspect<Address, Bus, Writer> + Step<Address, Bus>
where
    Address: Copy,
    Bus: BusAccess<Address>,
    Writer: fmt::Write,
{
    /// Represents an error that can occur while debugging
    type DebugError;

    /// Returns the `Address` where execution will take place the next time `step()` is called
    fn get_execution_address(&mut self) -> Result<Address, Self::DebugError>;
    /// Sets the `Address` where execution will take place the next time `step()` is called
    fn set_execution_address(&mut self, address: Address) -> Result<(), Self::DebugError>;

    /// Add a breakpoint
    fn add_breakpoint(&mut self, address: Address);
    /// Remove a breakpoint
    fn remove_breakpoint(&mut self, address: Address);
    /// Clear all breakpoints
    fn clear_breakpoints(&mut self);
}

#[cfg(test)]
mod test {
    use super::*;

    use crate::time::Instant;
    use crate::{BasicBusError, BusAdapter, ErrorType};
    use std::ops::Range;
    use std::str;
    use std::time::Duration;

    #[derive(Clone, Debug)]
    enum Error {
        BusError,
    }

    impl ErrorType for Error {}

    impl From<BasicBusError> for Error {
        fn from(_err: BasicBusError) -> Self {
            Error::BusError
        }
    }

    struct Memory(Vec<u8>);

    impl BusAccess<u32> for Memory {
        type Instant = Duration;
        type Error = BasicBusError;

        fn read(
            &mut self,
            _now: Duration,
            addr: u32,
            data: &mut [u8],
        ) -> Result<usize, Self::Error> {
            let addr = addr as usize;
            data.copy_from_slice(&self.0[addr..addr + data.len()]);
            Ok(data.len())
        }

        fn write(&mut self, _now: Duration, addr: u32, data: &[u8]) -> Result<usize, Self::Error> {
            let addr = addr as usize;
            self.0[addr..addr + data.len()].copy_from_slice(data);
            Ok(data.len())
        }
    }

    #[derive(Clone, Debug)]
    enum OutputError {
        Utf8Error,
    }

    impl ErrorType for OutputError {}

    impl From<OutputError> for Error {
        fn from(_err: OutputError) -> Self {
            Error::BusError
        }
    }

    struct Output();

    impl BusAccess<u16> for Output {
        type Instant = Duration;
        type Error = OutputError;

        fn read(
            &mut self,
            _now: Duration,
            _addr: u16,
            _data: &mut [u8],
        ) -> Result<usize, Self::Error> {
            Ok(0)
        }

        fn write(&mut self, _now: Duration, _addr: u16, data: &[u8]) -> Result<usize, Self::Error> {
            let string = str::from_utf8(data).map_err(|_| OutputError::Utf8Error)?;
            print!("{}", string);
            Ok(data.len())
        }
    }

    struct FixedBus {
        output: Output,
        memory: Memory,
    }

    impl BusAccess<u64> for FixedBus {
        type Instant = Duration;
        type Error = Error;

        fn read(
            &mut self,
            now: Duration,
            addr: u64,
            data: &mut [u8],
        ) -> Result<usize, Self::Error> {
            if (0..0x1_0000).contains(&addr) {
                self.memory
                    .read(now, addr as u32 % 0x1_0000, data)
                    .map_err(|_| Error::BusError)
            } else {
                self.output
                    .read(now, addr as u16, data)
                    .map_err(|_| Error::BusError)
            }
        }

        fn write(&mut self, now: Duration, addr: u64, data: &[u8]) -> Result<usize, Self::Error> {
            if (0..0x1_0000).contains(&addr) {
                self.memory
                    .write(now, addr as u32 % 0x1_0000, data)
                    .map_err(|_| Error::BusError)
            } else {
                self.output
                    .write(now, addr as u16, data)
                    .map_err(|_| Error::BusError)
            }
        }
    }

    struct DynamicBus {
        devices: Vec<(
            Range<u64>,
            Box<dyn BusAccess<u64, Instant = Duration, Error = Error>>,
        )>,
    }

    impl BusAccess<u64> for DynamicBus {
        type Instant = Duration;
        type Error = Error;

        fn read(
            &mut self,
            now: Duration,
            addr: u64,
            data: &mut [u8],
        ) -> Result<usize, Self::Error> {
            for (range, device) in self.devices.iter_mut() {
                if range.contains(&addr) {
                    return device.read(now, addr, data).map_err(|_| Error::BusError);
                }
            }
            Ok(0)
        }

        fn write(&mut self, now: Duration, addr: u64, data: &[u8]) -> Result<usize, Self::Error> {
            for (range, device) in self.devices.iter_mut() {
                if range.contains(&addr) {
                    return device.write(now, addr, data).map_err(|_| Error::BusError);
                }
            }
            Ok(0)
        }
    }

    #[derive(Default)]
    struct Cpu {
        pc: u64,
        sum: u32,
        running: bool,
    }

    impl<Bus> Step<u64, Bus> for Cpu
    where
        Bus: BusAccess<u64, Instant = Duration>,
        Error: From<Bus::Error>,
    {
        type Error = Error;

        fn is_running(&mut self) -> bool {
            self.running
        }

        fn reset(&mut self, now: Duration, bus: &mut Bus) -> Result<(), Self::Error> {
            self.running = true;
            self.pc = bus.read_beu32(now, 0x0000)? as u64;
            Ok(())
        }

        fn step(&mut self, now: Duration, bus: &mut Bus) -> Result<Duration, Self::Error> {
            if self.running {
                let value = bus.read_beu32(now, self.pc)?;
                self.pc += 4;

                if value == 0 {
                    self.running = false;
                } else {
                    self.sum += value;
                }
            }
            Ok(now + Duration::from_nanos(100))
        }
    }

    #[test]
    fn test_static_system() {
        let memory = Memory(vec![0; 1024]);
        let output = Output();

        let mut bus = FixedBus { memory, output };

        let mut cpu = Cpu::default();

        let location = 0x100;
        bus.memory
            .write_beu32(Duration::START, 0x0000, location as u32)
            .unwrap();

        for i in 0..100 {
            bus.memory
                .write_beu32(Duration::START, location + 4 * i as u32, 1 + i as u32)
                .unwrap();
        }

        fn run_static_test<A, B, C>(bus: &mut B, cpu: &mut C) -> Result<(), C::Error>
        where
            A: Copy,
            B: BusAccess<A, Instant = Duration>,
            C: Step<A, B>,
            C::Error: From<B::Error>,
        {
            cpu.reset(Duration::START, bus)?;

            while cpu.is_running() {
                cpu.step(Duration::START, bus)?;
            }
            Ok(())
        }

        run_static_test(&mut bus, &mut cpu).unwrap();

        assert_eq!(cpu.sum, 5050);
    }

    #[cfg(feature = "alloc")]
    #[test]
    fn test_dynamic_system() {
        let memory = Memory(vec![0; 1024]);
        let output = Output();

        let mut bus = DynamicBus {
            devices: vec![
                (
                    0..0x1_0000,
                    Box::new(BusAdapter::new(memory, |addr| addr as u32)),
                ),
                (
                    0x2_0000..0x2_0010,
                    Box::new(BusAdapter::new(output, |addr| addr as u16)),
                ),
            ],
        };

        let mut cpu = Cpu::default();

        let location = 0x100 as u64;
        bus.write_beu32(Duration::START, 0x0000, location as u32)
            .unwrap();

        for i in 0..100 {
            bus.write_beu32(Duration::START, location + 4 * i as u64, 1 + i as u32)
                .unwrap();
        }

        type Bus = Box<dyn BusAccess<u64, Instant = Duration, Error = Error>>;

        //let _trait_obj_cpu: &mut dyn Step<Bus, Error = Error> = &mut cpu;

        fn run_dynamic_test(
            mut bus: Bus,
            cpu: &mut dyn Step<u64, Bus, Error = Error>,
        ) -> Result<(), Error> {
            cpu.reset(Duration::START, &mut bus)?;

            while cpu.is_running() {
                cpu.step(Duration::START, &mut bus)?;
            }
            Ok(())
        }

        run_dynamic_test(Box::new(bus), &mut cpu).unwrap();

        assert_eq!(cpu.sum, 5050);
    }
}