~maddie/STT-implementation

9303aa07fb512637391518873f206ef142ecca29 — kn0000 6 months ago bd62c03
Rewrote lib.rs to fix numerous mistakes and tidy up with constants
2 files changed, 128 insertions(+), 96 deletions(-)

M src/lib.rs
M src/main.rs
M src/lib.rs => src/lib.rs +110 -85
@@ 1,113 1,138 @@
const STACK_SIZE: usize = 1024;
pub const MEMORY_SIZE: usize = 1<<20;
pub const SCREEN_WIDTH: usize = 512;
pub const SCREEN_HEIGHT: usize = 512;
pub const SCREEN_UPDATE_ADDRESS: usize = 0x7FFFF

#[derive(Debug)]
pub struct Stack {
    buffer: [u16;STACK_SIZE],
    index: usize
}

impl Stack {
    fn push(&mut self, value: u16) {
        self.buffer[self.index] = value;
        self.index = (self.index + 1) % STACK_SIZE;
    }

    fn pop(&mut self) -> u16 {
        self.index = (self.index + STACK_SIZE - 1) % STACK_SIZE;
        self.buffer[self.index]
    }
}

pub fn new_stack() -> Stack {
    Stack{
        buffer: [0u16;STACK_SIZE],
        index: 0
    }
}

pub struct Processor {
    pub stack_a: Vec<u16>,
    pub stack_b: Vec<u16>,
    pub memory: [u16;0xFFFFF],
    pub stack_a: Stack,
    pub stack_b: Stack,
    pub memory: [u16;MEMORY_SIZE],
    pub carry: bool,
    pub pc: u16 //program counter
    pub pc: usize
}

impl Processor {
    pub fn run(&mut self) -> bool {
        let instruction = self.memory[self.pc as usize];
        let instruction = self.memory[self.pc] & 0x3FF;
        let (mut stack, off_stack)  = {
            if (instruction & 0x200) == 0 {
                (&mut self.stack_a, &mut self.stack_b)
            }
            else {(&mut self.stack_b, &mut self.stack_a)}
        };
        let mut is_jump = false;
        match instruction & 0x300 {
            0x000 => self.carry = calc(&mut self.stack_a, instruction, self.carry),
            0x100 => self.carry = calc(&mut self.stack_a, instruction, self.carry),
            0x200 => self.stack_a.push(instruction & 0xFF),
            0x300 => {
                if (instruction & 0x80) != 0 {
                    let conditional = (instruction & 0x40) != 0;
                    let relative = (instruction & 0x20) != 0;
                    let save_pc = (instruction & 0x10) != 0;
                    let long_address = (instruction & 0x8) != 0;
                    if !conditional || self.carry {
                        let address;
                        if long_address {address = self.stack_a.pop().unwrap_or(0) | (self.stack_a.pop().unwrap_or(0) << 10)} //lower value on stack is high half of long address
                        else {address = self.stack_a.pop().unwrap_or(0)};
                        if save_pc {self.stack_a.push(self.pc+1)};
                        if relative {self.pc += address}
                        else {self.pc = address};
                        is_jump = true;
                    }

        if instruction & 0x100 == 0 { //calculation
            self.carry = calc(&mut stack, instruction, self.carry);
        }
        else if instruction & 0x80 == 0 { //jump
            let push_pc = (instruction & 0x40) != 0;
            let conditional = (instruction & 0x20) != 0;
            if !conditional || self.carry {
                let address = (stack.pop() as usize) | ((stack.pop() as usize) << 10);
                is_jump = true;
                if push_pc {
                    let a = self.pc + 1;
                    let upper = a & 0b11111111110000000000 >> 10;
                    let lower = a & 0b1111111111;
                    stack.push(upper as u16);
                    stack.push(lower as u16);
                }
                self.pc = address;
            }
        }
        else {
            match instruction & 0x7F {
                0 => { //immediate value
                    self.pc += 1;
                    stack.push(self.memory[self.pc] & 0x3FF);
                }
                1 => {
                    let upper = self.pc & 0b11111111110000000000 >> 10;
                    let lower = self.pc & 0b1111111111;
                    stack.push(upper as u16);
                    stack.push(lower as u16);
                }
                2 => { //swap
                    let a = stack.pop();
                    let b = stack.pop();
                    stack.push(a);
                    stack.push(b);
                }
                3 => off_stack.push(stack.pop()), //move between stacks
                4 => { //push from memory
                    let address = (stack.pop() as usize) | ((stack.pop() as usize) << 10);
                    stack.push(self.memory[address]);
                }
                5 => { //pop to memory
                    let address = (stack.pop() as usize) | ((stack.pop() as usize) << 10);
                    self.memory[address] = stack.pop();
                }
                6 => { //dup
                    let a = stack.pop();
                    stack.push(a);
                    stack.push(a);
                }
                else {
                    let toggle = (instruction & 0x40) != 0;
                    let stack;
                    if toggle {stack = &mut self.stack_b;}
                    else {stack = &mut self.stack_a;};
                    match instruction & 0x3F {
                        0 => { //swap top 2
                            let a = stack.pop().unwrap_or(0);
                            let b = stack.pop().unwrap_or(0);
                            stack.push(a);
                            stack.push(b);
                        }
                        1 => { //clone top
                            let a = stack.pop().unwrap_or(0);
                            stack.push(a);
                            stack.push(a);
                        }
                        2 => { //clone second
                            let a = stack.pop().unwrap_or(0);
                            let b = stack.pop().unwrap_or(0);
                            stack.push(b);
                            stack.push(a);
                            stack.push(b);
                        }
                        3 => { //move between stacks
                            if toggle {self.stack_a.push(self.stack_b.pop().unwrap_or(0));}
                            else {self.stack_b.push(self.stack_a.pop().unwrap_or(0));};
                        }
                        4 => { //push/pop
                            let addr = self.stack_a.pop().unwrap_or(0) as usize;
                            if toggle {
                                let value = self.stack_a.pop().unwrap_or(0);
                                self.memory[addr] = value;
                            }
                            else {self.stack_a.push(self.memory[addr])};
                        }
                        5 => { //long addr push/pop
                            let addr = (self.stack_a.pop().unwrap_or(0) | (self.stack_a.pop().unwrap_or(0) << 10)) as usize;
                            if toggle {
                                let value = self.stack_a.pop().unwrap_or(0);
                                self.memory[addr] = value;
                            }
                            else {self.stack_a.push(self.memory[addr])};
                        }
                        6 => { //set/clear carry
                            self.carry = toggle;
                        }
                        0x3F => return false,
                        _ => ()
                    }
                7 => { //over
                    let a = stack.pop();
                    let b = stack.pop();
                    stack.push(b);
                    stack.push(a);
                    stack.push(b);
                }
                0x7F => return false,
                _ => ()
            }
            _ => unreachable!()
        }
        if !is_jump {self.pc += 1};
        true
    }
}

fn calc(stack: &mut Vec::<u16>, instruction: u16, carry_in: bool) -> bool {
    let operand_a = stack.pop().unwrap_or(0);
    let operand_b = stack.pop().unwrap_or(0);
fn calc(stack: &mut Stack, instruction: u16, carry_in: bool) -> bool {
    let operand_a = stack.pop();
    let operand_b = stack.pop();
    let mut carry = carry_in;
    let mut result = 0;
    for i in 0..10 {
        let bit = 1 << i;
        let count = ((operand_a & bit) >> i) + ((operand_b & bit) >> i) + carry as u16;
        result += ((instruction & (1<<(count+4))) >> count) << i;
        carry = (instruction & (1<<count)) != 0;
        let count = ((operand_a >> i) & 1) + ((operand_b >> i) & 1) + (carry as u16);
        result += ((instruction >> (count+4)) & 1) << i;
        carry = ((instruction >> count) & 1) != 0;
    }
    stack.push(result);
    carry
}

pub fn mem_to_buf(memory: &[u16]) -> [u32;(2<<14)-1] {
    let mut result = [0u32;(2<<14)-1];
pub fn mem_to_buf(memory: &[u16]) -> [u32;SCREEN_WIDTH*SCREEN_HEIGHT] {
    let mut result = [0u32;SCREEN_WIDTH*SCREEN_HEIGHT];
    let mut i = 0;
    for byte in &memory[(2<<20)-(2<<14)..(2<<20)-1] {
    for byte in &memory[(MEMORY_SIZE-SCREEN_WIDTH*SCREEN_HEIGHT)..MEMORY_SIZE] {
        result[i] = (((byte & 0b111000000) as u32) << 15) | (((byte & 0b111000) as u32) << 10) | (((byte & 0b111) as u32) << 5); //shifts 3 bits of each 10 bit value into the rgb channels of the buffer, from the last region of memory
        i += 1;
    }

M src/main.rs => src/main.rs +18 -11
@@ 4,17 4,16 @@ use implementation::*;

fn main() {
    let mut filename = String::new();
    print!("Enter filename of the program to load into memory");
    println!("Enter filename of the program to load into memory");
    io::stdin().read_line(&mut filename).unwrap();
    let program = fs::read_to_string(filename).unwrap();
    let program = fs::read_to_string(filename.trim()).unwrap();

    let mut i = 0;
    let mut memory = [0u16;0xFFFFF];
    let mut memory = [0u16;MEMORY_SIZE];
    for line in program.lines() {
        let mut byte = 0u16;
        let mut count = 0;
        for digit in line.chars() {
            count += 1;
            match digit {
                '0' => {
                    byte = byte << 1;


@@ 26,25 25,33 @@ fn main() {
                }
                _ => ()
            }
            if count > 10 {panic!("10 bits only :)")};
            if count > 10 {panic!("10 bits only :)\nFailed at line {i}")};
        }
        memory[i] = byte;
        i += 1;
    }
    
    let mut processor = Processor {
        stack_a: Vec::new(),
        stack_b: Vec::new(),
        stack_a: new_stack(),
        stack_b: new_stack(),
        memory,
        carry: false,
        pc: 0
    };
    
    let mut window = Window::new("STT Display", 128, 128, WindowOptions::default()).unwrap();
    let mut window = Window::new("STT Display", SCREEN_WIDTH, SCREEN_HEIGHT, WindowOptions::default()).unwrap();
    window.update_with_buffer(&[0;(1<<14)],128,128).unwrap();
    let mut instructions_run = 0;
    while window.is_open() && processor.run() {
        if processor.memory[(2<<20)-(2<<14)-1] != 0 {
            processor.memory[(2<<20)-(2<<14)-1] = 0;
            window.update_with_buffer(&mem_to_buf(&processor.memory), 128, 128).unwrap();
        if processor.memory[SCREEN_UPDATE_ADDRESS] != 0 {
            processor.memory[SCREEN_UPDATE_ADDRESS] = 0;
            window.update_with_buffer(&mem_to_buf(&processor.memory), SCREEN_WIDTH, SCREEN_HEIGHT).unwrap();
        }
        instructions_run += 1;
        if instructions_run%1000 == 0 {
            println!("Program running");
        }
    }

    println!("Stack A: {0:?}\nStack B: {1:?}", processor.stack_a, processor.stack_b);
}