8000 88 support j core by kevinacahalan · Pull Request #108 · SWIM-ucf/SWIM · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

88 support j core #108

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 30, 2023
1 change: 1 addition & 0 deletions src/emulation_core/mips/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub const OPCODE_LW: u8 = 0b100011;
pub const OPCODE_SW: u8 = 0b101011;
pub const OPCODE_LWC1: u8 = 0b110001;
pub const OPCODE_SWC1: u8 = 0b111001;
pub const OPCODE_J: u8 = 0b000010;

// "ENC" is short for encoding. There is no formal name for this field
// in the MIPS64 specification, other than the "shamt"/"sa" field that it
Expand Down
89 changes: 86 additions & 3 deletions src/emulation_core/mips/datapath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,25 @@ pub struct DatapathState {
/// *Data line.* The data after the `DataWrite` multiplexer in the main
/// processor and the main processor register file.
register_write_data: u64,

/// *Jump 26 bit line.* The low 26 bits of the instruction reserved
/// for possible use by the J instruction
lower_26: u32,

/// *Lower 26 << 2 line.* This line carries the low 28 bits for the
/// jump address
lower_26_shifted_left_by_2: u32,

/// *Jump address line.* The line the will carry the combination of
/// the high 4 bits and pc, and the lower_26_for_jump_line bits shifted
/// left by 2.
jump_address: u64,

// *PC + 4 line.* Yeah, just PC + 4
pc_plus_4: u64,

// *New PC line.* In the WB stage this line is written to registers.pc
new_pc: u64,
}

/// The possible stages the datapath could be in during execution.
Expand Down Expand Up @@ -201,6 +220,10 @@ impl MipsDatapath {
/// into the datapath.
fn stage_instruction_fetch(&mut self) {
self.instruction_fetch();

// Upper part of datapath, PC calculation
self.pc_plus_4();

self.coprocessor.set_instruction(self.state.instruction) 10000 ;
}

Expand All @@ -213,6 +236,11 @@ impl MipsDatapath {
self.set_control_signals();
self.read_registers();
self.set_alu_control();

// Upper part of datapath, PC calculation
self.shift_lower_26_left_by_2();
self.construct_jump_address();

self.coprocessor.stage_instruction_decode();
self.coprocessor
.set_data_from_main_processor(self.state.read_data_2);
Expand Down Expand Up @@ -245,9 +273,19 @@ impl MipsDatapath {
MemToReg::UseMemory => self.state.memory_data,
};

// PC calculation stuff from upper part of datapath
self.set_new_pc();

self.coprocessor.stage_memory();
}

fn set_new_pc(&mut self) {
self.state.new_pc = match self.signals.jump {
Jump::NoJump => self.state.pc_plus_4,
Jump::YesJump => self.state.jump_address,
};
}

/// Stage 5 of 5: Writeback (WB)
///
/// Write the result of the instruction's operation to a register,
Expand All @@ -273,6 +311,14 @@ impl MipsDatapath {
}
}

fn pc_plus_4(&mut self) {
self.state.pc_plus_4 += 4;
}

// fn grab_lower_26_of_op(&mut self) {
// self.state.lower_26 = self.state.instruction & 0x03ffffff;
// }

/// Decode an instruction into its individual fields.
fn instruction_decode(&mut self) {
self.instruction = Instruction::from(self.state.instruction);
Expand Down Expand Up @@ -301,10 +347,22 @@ impl MipsDatapath {
self.state.rs = i.base as u32;
self.state.imm = i.offset as u32;
}
_ => unimplemented!(),
Instruction::JType(i) => {
// self.state.lower_26 = self.state.instruction & 0x03ffffff;
self.state.lower_26 = i.addr;
} // _ => unimplemented!(),
}
}

fn shift_lower_26_left_by_2(&mut self) {
self.state.lower_26_shifted_left_by_2 = self.state.lower_26 << 2;
}

fn construct_jump_address(&mut self) {
self.state.jump_address = (self.state.pc_plus_4 & 0xffff_ffff_f000_0000)
| self.state.lower_26_shifted_left_by_2 as u64;
}

/// Extend the sign of a 16-bit value to the other 48 bits of a
/// 64-bit value.
fn sign_extend(&mut self) {
Expand Down Expand Up @@ -562,6 +620,27 @@ impl MipsDatapath {
}
}

/// Set control signals for J-Type instructions
fn set_jtype_control_signals(&mut self, j: JType) {
match j.op {
OPCODE_J => {
self.signals.alu_op = AluOp::Addition;
self.signals.alu_src = AluSrc::ReadRegister2;
self.signals.branch = Branch::NoBranch;
self.signals.imm_shift = ImmShift::Shift0;
self.signals.jump = Jump::YesJump;
self.signals.mem_read = MemRead::NoRead;
self.signals.mem_to_reg = MemToReg::UseAlu;
self.signals.mem_write = MemWrite::NoWrite;
self.signals.mem_write_src = MemWriteSrc::PrimaryUnit;
self.signals.reg_dst = RegDst::Reg2;
self.signals.reg_width = RegWidth::DoubleWord;
self.signals.reg_write = RegWrite::NoWrite;
}
_ => unimplemented!("J-type instruction with opcode `{}`", j.op),
};
}

/// Set the control signals for the datapath based on the
/// instruction's opcode.
fn set_control_signals(&mut self) {
Expand All @@ -572,7 +651,9 @@ impl MipsDatapath {
Instruction::IType(i) => {
self.set_itype_control_signals(i);
}
Instruction::JType(_) => todo!("JType instructions are not supported yet"),
Instruction::JType(j) => {
self.set_jtype_control_signals(j);
}
Instruction::FpuRType(_) => {
self.signals = ControlSignals {
branch: Branch::NoBranch,
Expand Down Expand Up @@ -827,7 +908,9 @@ impl MipsDatapath {
/// Update the program counter register. At the moment, this only
/// increments the PC by 4 and does not support branching or
/// jumping.
///
/// This function is called from the WB stage
fn set_pc(&mut self) {
self.registers.pc += 4;
self.registers.pc = self.state.new_pc;
}
}
5 changes: 5 additions & 0 deletions src/emulation_core/mips/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ impl From<u32> for Instruction {
ft: ((value >> 16) & 0x1F) as u8,
offset: (value & 0xFFFF) as u16,
}),

OPCODE_J => Instruction::JType(JType {
op: ((value >> 26) & 0x3F) as u8,
addr: value & 0x03ffffff,
}),
_ => unimplemented!("opcode `{}` not supported", op),
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/emulation_core/mips/memory.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Data and instruction memory implementation and API.

pub const CAPACITY_BYTES: usize = 4 * 1024; // 4 KB
// pub const CAPACITY_BYTES: usize = 2^12; // 4KB
pub const CAPACITY_BYTES: usize = 64 * 1024; // 64 KB

#[derive(PartialEq)]
pub struct Memory {
Expand Down
52 changes: 51 additions & 1 deletion src/tests/emulation_core/mips.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,7 @@ fn dadd_register_to_itself() {
#[test]
fn dsub_registers_positive_result() {
let mut datapath = MipsDatapath::default();

assert_eq!(datapath.registers.pc, 0);
// dsub rd, rs, rt
// dsub $s5, $s4, $s3
// GPR[rd] <- GPR[rs] - GPR[rt]
Expand All @@ -844,6 +844,7 @@ fn dsub_registers_positive_result() {
datapath.registers.gpr[17] = 163_643_849_115_304; // $s3

datapath.execute_instruction();
assert_eq!(datapath.registers.pc, 4);

assert_eq!(datapath.registers.gpr[19], 4_669_680_037_183_490); // $s5
}
Expand Down Expand Up @@ -1635,4 +1636,53 @@ pub mod coprocessor {
6.1875f32
);
}

pub mod jump_tests {
use super::*;
#[test]
fn jump_test_basic() {
let mut datapath = MipsDatapath::default();

// J
let instruction: u32 = 0b000010_00_00000000_00000000_00000010;
datapath
.memory
.store_word(0, instruction)
.expect("Failed to store instruction.");
datapath.execute_instruction();

assert_eq!(datapath.registers.pc, 8);
}

#[test]
fn jump_test_mid() {
let mut datapath = MipsDatapath::default();

// J
let instruction: u32 = 0x0800_0fff;
datapath
.memory
.store_word(0, instruction)
.expect("Failed to store instruction.");
datapath.execute_instruction();

assert_eq!(datapath.registers.pc, 0x3ffc);
}

#[test]
fn jump_test_hard() {
// Jump to address 0xfff_fffc
let mut datapath = MipsDatapath::default();

// J low_26
let instruction: u32 = 0x0800_0000 | 0x03ff_ffff;
datapath
.memory
.store_word(0, instruction)
.expect("Failed to store instruction.");
datapath.execute_instruction();

assert_eq!(datapath.registers.pc, 0x0fff_fffc);
}
}
}
0