Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat CI: Add CI for stable version #10

Closed
wants to merge 45 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
714c114
README: Initial do-core1 specification
Feb 6, 2021
9140799
d0-core1: Hello world
Feb 6, 2021
dc29416
d0-core1: Add 2 variables
Feb 6, 2021
9b60cb1
do-core1: Enforce 16 bits registers
Feb 6, 2021
ec80d40
do-core1: 2-operand addition
Feb 6, 2021
9d576e6
do-core1: Define an addition function
Feb 6, 2021
e88c977
do-core1: Check for the only supported opcode
Feb 6, 2021
b763b8e
do-core1: Add OpCode Enumeration
Feb 6, 2021
c9cd17a
do-core1: Shut dead code warnings off
Feb 6, 2021
8b94d78
do-core1: Implement the XOR instruction
Feb 6, 2021
d1532df
do-core1: Register pretty printing
Feb 6, 2021
c00eee8
do-core1: Initial instruction disassembler
Feb 6, 2021
4548168
do-core1: Implement OpCode::from_u8
Feb 6, 2021
0dab8b5
do-core1: Add an Instruction structure
Feb 6, 2021
83f7f46
do-core1: Add first instruction unit test
Feb 6, 2021
5c55473
do-core1: Add more Instruction unit tests
Feb 6, 2021
1c25159
do-core1: Initial command line parsing
Feb 6, 2021
ba816dc
do-core1: Initial error handling
Feb 6, 2021
4989db4
do-core1: Initial error pattern matching
Feb 6, 2021
e79bf77
do-core1: Handle OpCode::from_u8 error
Feb 6, 2021
f631761
do-core1: Use the ? operator
Feb 6, 2021
973dd69
do-core1: Report addition overflow errors
Feb 6, 2021
4e11edf
do-core1: Fix unit tests
Feb 6, 2021
60d6647
do-core1: Add negative unit tests
Feb 6, 2021
9ac5ad7
do-core1: Define a registers array
Feb 6, 2021
c21cb86
do-core1: Add a routine for dumping a do-core1 CPU state
Feb 6, 2021
626d130
do-core1: Initial arbitrary registers initialization
Feb 6, 2021
1453f13
do-core1: Initial do-core crate
Mar 7, 2021
cea21e9
do-core1: First do-core usage
Mar 7, 2021
de1a5fd
do-core1: Move Instruction to the do-core crate
Mar 7, 2021
348ea0f
do-core1: do-core: Add opcode and operand getters
Mar 7, 2021
fbccc78
do-core1: Move instruction unit tests to do-core
Mar 7, 2021
cae98d7
do-core1: Move our core implementations to do-core
Mar 7, 2021
4701d0c
do-core: Add Core unit tests
Mar 7, 2021
11f8f0b
do-core: Initial memory implementation
Mar 11, 2021
75926f0
do-core: memory: Add unit tests
Mar 11, 2021
c5b39ef
do-core: core: Implement LD and ST
Mar 11, 2021
bce393c
do-core: instruction: Implement FromStr for OpCode
Mar 19, 2021
90bc5b7
do-core : run cargo fmt
Mar 19, 2021
8e484ee
feat : Basic CI
Mar 23, 2021
2c1c9d6
fix CI : use workspace option for tests
Mar 23, 2021
f11847a
feat CI : add clippy lint
Mar 23, 2021
25a8afb
fix CI: typo in build.yml
Mar 23, 2021
8b976ef
feat CI: add format command
Mar 23, 2021
08e05e0
fix CI : clippy action
Mar 23, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
on: [push, pull_request]
name: build
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v2

- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable

- name: Build the application
uses: actions-rs/cargo@v1
with:
command: build

- name: Run tests
uses: actions-rs/cargo@v1
with:
command: test
args: --workspace

- name: Lint the code
uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Check if code formatted
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check --verbose
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
118 changes: 118 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "do-core1"
version = "0.1.0"
authors = ["Samuel Ortiz <sameo@linux.intel.com>"]
edition = "2018"

[dependencies]
clap = "2.33.3"
do-core = { path = "do-core" }

[workspace]
members = [
"do-core"
]
53 changes: 52 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,53 @@
# do-core1
DO processor

The `do-core1` is a simple processor architecture, mostly for educational purposes.

It aims at being a support for system programming and computer architecture fundamentals courses.

## Instruction Set Architecture

The do-core1 [Instruction Set Architecture (ISA)](https://en.wikipedia.org/wiki/Instruction_set) is a simple [Reduced Instruction Set Computer (RISC)](https://en.wikipedia.org/wiki/Reduced_instruction_set_computer)
processor architecture, with a very limited memory model and instruction and register set.

### Registers

`do-core1` exposes **8 general purpose registers**: `R0`, `R1`, `R2`, `R3`, `R4`, `R5`, `R6`, `R7`.

It also uses one Instruction Pointer (`RIP`) register and a operation flags (`RFLAGS`) register.

All `do-core1` registers are **16 bits wide**.

### Memory Model

`do-core1` can address up to **4KiB (4096 bytes) of physical memory**.

### Instruction Set

`do-core1` is a [RISC](https://en.wikipedia.org/wiki/Reduced_instruction_set_computer) architecture and executes fixed-length
instructions of 16 bits.

The `do-core1` is a 2-operand architecture, i.e. its instruction takes at most 2 operands.
`do-core1` operands are register indexes.

A `do-core1` instruction can be split into an operation code (opcode), the first operand (op0)
and the second operand (op1). The opcode is 8 bits long, and both operands are 4 bits long:

```
do-core instruction (16 bits)

Bits |15 8|7 4|3 0|
-------------------------------------------------------------
| Opcode (bits 15-8) | op0 (bits 7-4) | op1 (bits 3-0) |
-------------------------------------------------------------
```

The `do-core1` is a [load-store](https://en.wikipedia.org/wiki/Load%E2%80%93store_architecture)
architecture and supports the following instructions:


| Opcode | Instruction | Description |
|--------|--------------|----------------------------------------------------------------------|
| `0x00` | `LD Rn, Rm` | Load the value at the memory address contained in `Rm` into `Rn` |
| `0x01` | `ST Rn, Rm` | Store the value from `Rn` into the memory address contained in `Rm` |
| `0x02` | `ADD Rn, Rm` | Add the value contained in `Rm` into `Rn` (`Rn = Rn + Rm`) |
| `0x03` | `XOR Rn, Rm` | Perform a bitwise exclusive OR between `Rn` and `Rm`(`Rn = Rn ^ Rm`) |
7 changes: 7 additions & 0 deletions do-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "do-core"
version = "0.1.0"
authors = ["Samuel Ortiz <sameo@linux.intel.com>"]
edition = "2018"

[dependencies]
140 changes: 140 additions & 0 deletions do-core/src/core.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
use crate::instruction::{Instruction, OpCode};
use crate::memory::Memory;
use crate::{Error, MAX_REGISTER_INDEX, MEMORY_SIZE};

pub struct Core {
registers: [u16; MAX_REGISTER_INDEX as usize + 1],
memory: Memory,
}

impl Core {
pub fn new() -> Self {
let mut core = Core {
registers: [0u16; MAX_REGISTER_INDEX as usize + 1],
memory: Memory::new(MEMORY_SIZE),
};

// Arbitrary initial registers value.
// Registers will eventually be initialized through memory loads.
for (index, register) in core.registers.iter_mut().enumerate() {
*register = index as u16 * 0x10;
}

core
}

pub fn register(&self, index: u8) -> Result<u16, Error> {
if index > MAX_REGISTER_INDEX {
return Err(Error::Op0OutOfRange);
}

Ok(self.registers[index as usize])
}

pub fn dump(&self, preamble: &str) {
println!("do-core1: {}:", preamble);
for (index, register) in self.registers.iter().enumerate() {
println!("\tR{}: {:#x?}", index, *register);
}
}

pub fn decode(&mut self, insn: u16) -> Result<Instruction, Error> {
Instruction::disassemble(insn)
}

pub fn execute(&mut self, insn: Instruction) -> Result<(), Error> {
let opcode = insn.opcode();

match opcode {
OpCode::ADD => self.add(insn)?,
OpCode::XOR => self.xor(insn)?,
OpCode::LD => self.load(insn)?,
OpCode::ST => self.store(insn)?,
}

Ok(())
}

fn add(&mut self, insn: Instruction) -> Result<(), Error> {
let op0 = insn.op0() as usize;
let op1 = insn.op1() as usize;

self.registers[op0] =
self.registers[op0]
.checked_add(self.registers[op1])
.ok_or(Error::AdditionOverflow(
self.registers[op0],
self.registers[op1],
))?;

Ok(())
}

fn xor(&mut self, insn: Instruction) -> Result<(), Error> {
let op0 = insn.op0() as usize;
let op1 = insn.op1() as usize;

self.registers[op0] ^= self.registers[op1];

Ok(())
}

fn load(&mut self, insn: Instruction) -> Result<(), Error> {
let op0 = insn.op0() as usize;
let op1 = insn.op1() as usize;

self.registers[op0] = self.memory.load(self.registers[op1])?.into();

Ok(())
}

fn store(&mut self, insn: Instruction) -> Result<(), Error> {
let op0 = insn.op0() as usize;
let op1 = insn.op1() as usize;

self.memory
.store(self.registers[op1], self.registers[op0] as u8)
}
}

#[cfg(test)]
mod tests {
use crate::core::Core;
use crate::Error;

#[test]
fn test_core_add_r4_r5() -> Result<(), Error> {
let insn = 0x245;
let mut cpu = Core::new();

let r4 = cpu.register(4)?;
let r5 = cpu.register(5)?;

let decoded_insn = cpu.decode(insn)?;
cpu.execute(decoded_insn)?;

let new_r4 = cpu.register(4)?;

assert_eq!(new_r4, r4 + r5);

Ok(())
}

#[test]
fn test_core_xor_r1_r7() -> Result<(), Error> {
let insn = 0x317;
let mut cpu = Core::new();

let r1 = cpu.register(1)?;
let r7 = cpu.register(7)?;

let decoded_insn = cpu.decode(insn)?;
cpu.execute(decoded_insn)?;

let new_r1 = cpu.register(1)?;

assert_eq!(new_r1, r1 ^ r7);

Ok(())
}
}
Loading