Closed tomoyuki-nakabayashi closed 6 years ago
VecDeque
https://doc.rust-lang.org/nightly/core/fmt/trait.Write.html
Write traitを実装するもの、をTxにすればうまくできる気がする。
テンプレートとLifetimeを両方書くとややこしいな。ただ、Lifetimeもtraitと思えばまぁ?
struct Uart16550<'a, T: 'a> {
tx_buffer: &'a mut T,
}
impl<'a, T: 'a + Write> Uart16550<'a, T> {
fn new(buffer: &'a mut T) -> Uart16550<T> {
Uart16550 {
tx_buffer: buffer,
}
}
fn write(&mut self, c: char) {
write!(self.tx_buffer, "{}", c).expect("Printing to serial failed")
}
}
メモリマップドにせねばならぬ。
一旦、メモリマッピング固定のinterconnectを作って、それをCPUが持つ形にするか。
UART、テスト時は、TXバッファを読み込みできるようにするか。 エミュレーション時は、読み込みするとErr返せば良い気がする。
ダメですな。 テスト時はファイルに書き込んで、テスト終了時に再オープンして中身を確かめるか。
UART自体は完成した。Interconnectにつないで、CPUから使えるようにしょう。
うあ、インテグレーションテストだと、プロダクトコードはtest設定じゃないのか。これはうっかり。
$ cargo run -- tests/asms/hello
Finished dev [unoptimized + debuginfo] target(s) in 0.14s
Running `target/debug/rustemu86 tests/asms/hello`
Program load... 53 bytes.
Hello
Finish emulation. 13 instructions executed.
それはともかく、力づくHelloが動いたのを喜ぶか。
UartWriteを知っていていいのは、Interconnectまでだよなぁ。 そうなると、Interconnectはジェネリックにできない。
http://keens.github.io/blog/2017/05/06/rustkazenidezainpata_n23tane/
Factoryパターンでtrait objectを返そう。
この方がシンプルだ。
pub fn uart_factory(target: Target) -> Uart16550 {
match target {
Target::Stdout => Uart16550 { tx_writer: Box::new(StdoutWriter::new()) },
Target::File => Uart16550 { tx_writer: Box::new(FileWriter::new()) },
}
}
文字列出力&インテグレーションテスト用。 出力先を標準出力か、バッファかを、DIできるようにすると、テストで使える。