From 3f3ed159f0f2968723efd49898618082aeeb7ba3 Mon Sep 17 00:00:00 2001 From: Cassie Jones Date: Fri, 10 Jan 2020 23:32:01 -0500 Subject: [PATCH] Implement mov and add tests --- toolchain/Cargo.lock | 382 ++++++++++++++++++++++++++++++++++++++ toolchain/Cargo.toml | 3 + toolchain/src/cpu.rs | 77 +++++--- toolchain/src/cpu/test.rs | 37 ++++ toolchain/src/inst.rs | 27 ++- 5 files changed, 503 insertions(+), 23 deletions(-) diff --git a/toolchain/Cargo.lock b/toolchain/Cargo.lock index e24cc9f..d7d2e0b 100644 --- a/toolchain/Cargo.lock +++ b/toolchain/Cargo.lock @@ -1,5 +1,387 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" + +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "bit-set" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" + +[[package]] +name = "c2-chacha" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" +dependencies = [ + "ppv-lite86", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" + +[[package]] +name = "num-traits" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +dependencies = [ + "autocfg 1.0.0", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" + +[[package]] +name = "proptest" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f" +dependencies = [ + "bit-set", + "bitflags", + "byteorder", + "lazy_static", + "num-traits", + "quick-error", + "rand 0.6.5", + "rand_chacha 0.1.1", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.7", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha 0.2.1", + "rand_core 0.5.1", + "rand_hc 0.2.0", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.3.1", +] + +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +dependencies = [ + "c2-chacha", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.7", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" + +[[package]] +name = "regex-syntax" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e734e891f5b408a29efbf8309e656876276f49ab6a6ac208600b4419bd893d90" + +[[package]] +name = "remove_dir_all" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +dependencies = [ + "winapi", +] + +[[package]] +name = "rusty-fork" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dd93264e10c577503e926bd1430193eeb5d21b059148910082245309b424fae" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "tempfile" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +dependencies = [ + "cfg-if", + "libc", + "rand 0.7.3", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "toolchain" version = "0.1.0" +dependencies = [ + "proptest", +] + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/toolchain/Cargo.toml b/toolchain/Cargo.toml index e910a73..976c29c 100644 --- a/toolchain/Cargo.toml +++ b/toolchain/Cargo.toml @@ -7,3 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] + +[dev-dependencies] +proptest = "0.9.4" diff --git a/toolchain/src/cpu.rs b/toolchain/src/cpu.rs index b5be390..232617c 100644 --- a/toolchain/src/cpu.rs +++ b/toolchain/src/cpu.rs @@ -1,4 +1,4 @@ -use crate::inst::Reg; +use crate::inst::{Inst, Reg}; use std::ops::{Index, IndexMut}; #[cfg(test)] @@ -8,6 +8,43 @@ struct RegFile { values: [u8; 4], } +pub struct Cpu { + init: bool, + pc: u16, + reg: RegFile, + memory: Vec, +} + +impl Cpu { + pub fn new() -> Self { + Cpu { + init: false, + pc: 0, + reg: RegFile { values: [0; 4] }, + memory: vec![0; 1 << 16], + } + } + + pub fn reg(&self, reg: Reg) -> u8 { + self.reg[reg] + } + + pub fn mem(&self) -> &[u8] { + &self.memory[..] + } + + pub fn mem_mut(&mut self) -> &mut [u8] { + &mut self.memory[..] + } + + pub fn run_inst(&mut self, inst: &Inst) { + match *inst { + Inst::Move(dst, src) => self.reg[dst] = self.reg[src], + _ => todo!(), + } + } +} + impl Index for RegFile { type Output = u8; fn index(&self, index: Reg) -> &u8 { @@ -31,28 +68,24 @@ impl IndexMut for RegFile { } } -pub struct Cpu { - init: bool, - pc: u16, - reg: RegFile, - memory: Vec, -} - -impl Cpu { - pub fn new() -> Self { - Cpu { - init: false, - pc: 0, - reg: RegFile { values: [0; 4] }, - memory: vec![0; 1 << 16], - } - } - - pub fn mem(&self) -> &[u8] { - &self.memory[..] +impl std::fmt::Debug for RegFile { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + fmt.debug_struct("RegFile") + .field("r0", &self[Reg::R0]) + .field("r1", &self[Reg::R1]) + .field("r2", &self[Reg::R2]) + .field("r3", &self[Reg::R3]) + .finish() } +} - pub fn mem_mut(&mut self) -> &mut [u8] { - &mut self.memory[..] +impl std::fmt::Debug for Cpu { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + fmt.debug_struct("Cpu") + .field("init", &self.init) + .field("pc", &self.pc) + .field("reg", &self.reg) + .field("mem", &format_args!("[...]")) + .finish() } } diff --git a/toolchain/src/cpu/test.rs b/toolchain/src/cpu/test.rs index 8b13789..5057354 100644 --- a/toolchain/src/cpu/test.rs +++ b/toolchain/src/cpu/test.rs @@ -1 +1,38 @@ +use super::*; +use crate::inst::{Inst, Reg}; +use proptest::prelude::*; +fn cpu() -> impl Strategy { + ( + 0..1024u16, + [any::(); 4], + prop::collection::vec(any::(), 0..1024), + ) + .prop_map(|(pc, reg, memory)| Cpu { + init: true, + pc, + reg: RegFile { values: reg }, + memory, + }) +} + +fn reg() -> impl Strategy { + (0..4).prop_map(|r| match r { + 0 => Reg::R0, + 1 => Reg::R1, + 2 => Reg::R2, + 3 => Reg::R3, + _ => unreachable!(), + }) +} + +proptest! { + #[test] + fn run_move(mut cpu in cpu(), dst in reg(), src in reg()) { + let inst = Inst::Move(dst, src); + let val = cpu.reg(src); + cpu.run_inst(&inst); + prop_assert_eq!(val, cpu.reg(src)); + prop_assert_eq!(val, cpu.reg(dst)); + } +} diff --git a/toolchain/src/inst.rs b/toolchain/src/inst.rs index 83fe047..f67d0cb 100644 --- a/toolchain/src/inst.rs +++ b/toolchain/src/inst.rs @@ -1,6 +1,7 @@ mod decode; mod encode; +#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)] pub enum Reg { R0, R1, @@ -8,11 +9,13 @@ pub enum Reg { R3, } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum RegPair { R1R0, R3R2, } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Op1 { Inc, Dec, @@ -20,6 +23,7 @@ pub enum Op1 { Compl, } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum OpI { Add7(Imm7), Sub6(Imm6), @@ -32,6 +36,7 @@ pub enum OpI { Xor(Imm8), } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Op2 { Add, Sub, @@ -44,12 +49,18 @@ pub enum Op2 { Bic, } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Imm3(u8); +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Imm5(u8); +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Imm6(u8); +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Imm7(u8); +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Imm8(u8); +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Addr { Imm(Imm7), Off(Reg, Imm5), @@ -57,8 +68,19 @@ pub enum Addr { Pair(RegPair), } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Cond { + Eq, + Ne, + Test, + TestNot, + Lt, + Ult, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Inst { - Mov(Reg, Reg), + Move(Reg, Reg), CallR(Reg), Alu1(Reg, Op1), Load(Reg, Addr), @@ -66,6 +88,9 @@ pub enum Inst { JumpR(Reg), JumpI(Imm8), CallI(Imm8), + // @TODO: Implement the PartialEq for Cond symmetric in the registers for + // Eq, Ne, Test, and TestNot. + Branch(Cond, Reg, Reg), AluI(Reg, OpI), Skip(Reg, Reg), Alu2(Reg, Op2, Reg), -- 2.43.2