Skip to content
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

Riscv-fpu #368

Merged
merged 23 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d77288e
Updated with ECALL fix from SWIM-v2
rharding8 Mar 27, 2024
af693bd
Added Coprocessor. Implemented instruction_decode.
rharding8 Mar 27, 2024
23213e5
Updated Datapath logic for FPU and implemented FLW
rharding8 Mar 28, 2024
7dbadeb
Implemented FSW all the way. Still errors.
rharding8 Mar 28, 2024
f5c369a
Added logic for Floating Point Addition,
rharding8 Mar 28, 2024
e1532c9
Implemented Sqrt function and fixed funct7 match
rharding8 Mar 28, 2024
4d753d1
Implemented FMIN and FMAX.
rharding8 Mar 28, 2024
d436914
Implemented Conversion from Float Registers
rharding8 Mar 28, 2024
bfac4a2
Implemented conversion from Integer Registers
rharding8 Mar 28, 2024
4de6fa9
Fixed formatting.
rharding8 Mar 28, 2024
7356d31
Implemented Sign-Injection functions.
rharding8 Mar 28, 2024
e578a95
Implemented FCMP instructions.
rharding8 Mar 28, 2024
53af4bf
Added FCLASS.
rharding8 Mar 28, 2024
9d78bd1
Implemented Fused Multiplication Instructions (R4s)
rharding8 Mar 29, 2024
5fd4c73
Fixed the Floating Point inputs and outputs to 32
rharding8 Mar 29, 2024
05ea414
Implemented Final Float Instructions.
rharding8 Mar 29, 2024
23821d2
Removed pointless functions and control signals.
rharding8 Mar 29, 2024
6ae78b7
Merge branch 'swim-v2' into riscv-fpu
rharding8 Mar 29, 2024
e049880
Fixed issues. Every instruction aside from FLW is
rharding8 Mar 29, 2024
f81a840
One instruction was wrong. Fixed now.
rharding8 Mar 29, 2024
bb6b004
Fixed my idiotic programming. Everything works now
rharding8 Mar 29, 2024
e35fa7b
Fixed final instructions.
rharding8 Mar 29, 2024
ecf76fd
Connect the FP registers to the visual display
brooksmckinley Mar 29, 2024
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
5 changes: 5 additions & 0 deletions src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ pub async fn emulation_core_agent(scope: ReactorScope<Command, DatapathUpdate>)
state.updates.changed_stack,
RiscStateUpdate::UpdateStack(datapath.stack.clone())
);
send_update_riscv!(
state.scope,
state.updates.changed_coprocessor_registers,
RiscStateUpdate::UpdateCoprocessorRegisters(datapath.coprocessor.registers)
);
}
}
state.updates = Default::default();
Expand Down
18 changes: 17 additions & 1 deletion src/agent/datapath_reducer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use crate::emulation_core::mips::gp_registers::{GpRegisterType, GpRegisters};
use crate::emulation_core::mips::memory::Memory;
use crate::emulation_core::register::{RegisterType, Registers};
use crate::emulation_core::riscv::datapath::{RiscDatapathState, RiscStage};
use crate::emulation_core::riscv::registers::{RiscGpRegisterType, RiscGpRegisters};
use crate::emulation_core::riscv::registers::{
RiscFpRegisters, RiscGpRegisterType, RiscGpRegisters,
};
use crate::emulation_core::stack::Stack;
use gloo_console::log;
use std::rc::Rc;
Expand Down Expand Up @@ -40,6 +42,7 @@ pub struct MipsCoreState {
pub struct RiscCoreState {
pub state: RiscDatapathState,
pub registers: RiscGpRegisters,
pub coprocessor_registers: RiscFpRegisters,
pub memory: Memory,
pub current_stage: RiscStage,
pub stack: Stack,
Expand Down Expand Up @@ -151,6 +154,12 @@ impl Reducible for DatapathReducer {
stack,
..self.riscv.clone()
},
RiscStateUpdate::UpdateCoprocessorRegisters(coprocessor_registers) => {
RiscCoreState {
coprocessor_registers,
..self.riscv.clone()
}
}
},
..(*self).clone()
},
Expand Down Expand Up @@ -180,6 +189,13 @@ impl DatapathReducer {
}
}

pub fn get_dyn_fp_registers(&self) -> Vec<(Rc<dyn RegisterType>, u64)> {
match self.current_architecture {
MIPS => self.mips.coprocessor_registers.get_dyn_register_list(),
RISCV => self.riscv.coprocessor_registers.get_dyn_register_list(),
}
}

pub fn get_memory(&self) -> &Memory {
match self.current_architecture {
MIPS => &self.mips.memory,
Expand Down
3 changes: 2 additions & 1 deletion src/agent/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::emulation_core::mips::fp_registers::FpRegisters;
use crate::emulation_core::mips::gp_registers::GpRegisters;
use crate::emulation_core::mips::memory::Memory;
use crate::emulation_core::riscv::datapath::{RiscDatapathState, RiscStage};
use crate::emulation_core::riscv::registers::RiscGpRegisters;
use crate::emulation_core::riscv::registers::{RiscFpRegisters, RiscGpRegisters};
use crate::emulation_core::stack::Stack;
use crate::emulation_core::{architectures::AvailableDatapaths, mips::datapath::Stage};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -44,6 +44,7 @@ pub enum MipsStateUpdate {
pub enum RiscStateUpdate {
UpdateState(RiscDatapathState),
UpdateRegisters(RiscGpRegisters),
UpdateCoprocessorRegisters(RiscFpRegisters),
UpdateMemory(Memory),
UpdateStage(RiscStage),
UpdateStack(Stack),
Expand Down
3 changes: 1 addition & 2 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ use web_sys::HtmlInputElement;
use yew::prelude::*;
use yew::{html, Html, Properties};

use swim::emulation_core::register::Registers;
use swim::emulation_core::riscv::datapath::RiscStage;
use yew_agent::Spawnable;

Expand Down Expand Up @@ -657,7 +656,7 @@ fn app(props: &AppProps) -> Html {
</div>

// Right column
<Regview gp={datapath_state.get_dyn_gp_registers()} fp={datapath_state.mips.coprocessor_registers.get_dyn_register_list()} pc_limit={*pc_limit} communicator={props.communicator}/>
<Regview gp={datapath_state.get_dyn_gp_registers()} fp={datapath_state.get_dyn_fp_registers()} pc_limit={*pc_limit} communicator={props.communicator}/>
</div>
</>
}
Expand Down
1 change: 1 addition & 0 deletions src/emulation_core/riscv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

pub mod constants;
pub mod control_signals;
pub mod coprocessor;
pub mod datapath;
pub mod datapath_signals;
pub mod instruction;
Expand Down
16 changes: 16 additions & 0 deletions src/emulation_core/riscv/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub const FUNCT_SOP37: u8 = 0b011111;
/// Used for R-type instructions.
pub const OPCODE_OP: u8 = 0b0110011;
pub const OPCODE_OP_32: u8 = 0b0111011;
pub const OPCODE_OP_FP: u8 = 0b1010011;

/// Used for I-type instructions.
pub const OPCODE_IMM: u8 = 0b0010011;
Expand All @@ -52,11 +53,13 @@ pub const OPCODE_IMM_32: u8 = 0b0011011;
pub const OPCODE_JALR: u8 = 0b1100111;
// LOAD
pub const OPCODE_LOAD: u8 = 0b0000011;
pub const OPCODE_LOAD_FP: u8 = 0b0000111;
// SYSTEM
pub const OPCODE_SYSTEM: u8 = 0b1110011;

/// Used for S-type instructions.
pub const OPCODE_STORE: u8 = 0b0100011;
pub const OPCODE_STORE_FP: u8 = 0b0100111;

/// Used for B-type instructions.
pub const OPCODE_BRANCH: u8 = 0b1100011;
Expand All @@ -70,6 +73,19 @@ pub const OPCODE_AUIPC: u8 = 0b0010111;
/// Used for J-type instructions.
pub const OPCODE_JAL: u8 = 0b1101111;

/// Used for R4-type instructions.
// FMADD.S
pub const OPCODE_MADD: u8 = 0b1000011;
// FMSUB.S
pub const OPCODE_MSUB: u8 = 0b1000111;
// FNMSUB.S
pub const OPCODE_NMSUB: u8 = 0b1001011;
// FNMADD.S
pub const OPCODE_NMADD: u8 = 0b1001111;

/// Not a Number
pub const RISC_NAN: u32 = 0x7fc00000;

// "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
// replaces, so this was chosen as the mnemonic for this project.
Expand Down
220 changes: 220 additions & 0 deletions src/emulation_core/riscv/control_signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,223 @@ pub enum RegWriteEn {
NoWrite = 0,
YesWrite = 1,
}

pub mod floating_point {

use super::super::constants::*;
use serde::{Deserialize, Serialize};

#[derive(Clone, Default, PartialEq, Serialize, Deserialize, Debug)]
pub struct FpuControlSignals {
pub round_mode: RoundingMode,
pub data_src: DataSrc,
pub data_write: DataWrite,
pub fpu_alu_op: FpuAluOp,
pub fpu_mem_to_reg: FpuMemToReg,
pub fpu_reg_dst: FpuRegDst,
pub fpu_reg_write: FpuRegWrite,
}

/// Determines the source of the `Data` register in the floating-point unit.
///
/// This is a special intermediary register that facilitates passing data between
/// the main processing unit and the floating-point unit.
#[derive(Clone, Default, PartialEq, Serialize, Deserialize, Debug)]
pub enum DataSrc {
/// Use data from the main processing unit. Specifically, the data from register
/// `rs1` from a given instruction. This value can additionally be used in the cases
/// where this register is not written to.
MainProcessorUnit = 0,

/// Use data from the floating-point unit. Specifically, the data from register `rs1`
/// from a given instruction.
#[default]
FloatingPointUnitRS1 = 1,

/// Use data from the floating-point unit. Specifically, the data from the comparator.
FloatingPointUnitComp = 2,

/// Use data from the floating-point unit. Specifically, the Classify Mask.
FloatingPointUnitMask = 3,

/// Use the un-altered bits from the floating-point unit.
FloatingPointBits = 4,

/// Use the un-altered bits from the main unit.
MainProcessorBits = 5,
}

/// Determines whether to write to the `Data` register in the floating-point unit.
///
/// This acts as a toggle for the source of data to the main processing unit register
/// file. Additionally, it acts as a toggle for a source to the floating-point unit
/// register file (this could be overridden by the [`FpuMemToReg`] control signal).
/// For the latter two functions, it is imperative to unset the [`RegWriteEn`](super::RegWriteEn) and
/// [`FpuRegWrite`] control signals in cases where registers should not be modified
/// with unintended data.
#[derive(Clone, Default, PartialEq, Serialize, Deserialize, Debug)]
pub enum DataWrite {
/// - Do not write to the data register.
/// - Source data to write to the main processing unit register file from the main
/// processing unit. This implies either the ALU result or the data read from memory
/// - Source data to write to the floating-point register file from the floating-point
/// ALU.
#[default]
NoWrite = 0,

/// - Write to the data register.
/// - Source data to write to the main processing unit register file from the
/// floating-point unit. Specifically, this is the data stored in the `Data` register
/// in the FPU, likely from register `rs1` from a given instruction. This data source
/// overrides the decision given by the [`MemToReg`](super::MemToReg) control signal.
/// - Source data to write to the floating-point register file from the `Data` register
/// in the FPU, likely from register `rs1` from a given instruction.
YesWrite = 1,
}

/// This doubly determines the operations sent to the floating-point ALU and the
/// floating-point comparator.
///
/// Only one of these units are effectively utilized in any given instruction.
///
/// The fifth bit of the control signal represents either a single-precision
/// floating-point operation (0), or a double-precision floating-point operation (1).
/// This fifth bit is determined by [`FpuRegWidth`].
///
/// *Implementation note:* The bits set for the comparator are intended to match
/// the bits used in the `cond` field of a `c.cond.fmt` instruction.
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub enum FpuAluOp {
#[default]
/// `_00000` (0):
/// - ALU: Perform an addition.
Addition = 0,

/// `_00001` (1):
/// - ALU: Perform a subtraction.
Subtraction = 1,

/// `_00010` (2):
/// - ALU: Perform a multiplication.
/// - Comparator: Set if equal.
MultiplicationOrEqual = 2,

/// `_00011` (3):
/// - ALU: Perform a division.
Division = 3,

/// `_00100` (4):
/// - ALU: Perform a Square Root.
Sqrt = 4,

/// `_00101` (5):
/// - ALU: Take the Minimum value.
Min = 5,

/// `_00110` (6):
/// - ALU: Take the Maximum value.
Max = 6,

/// `_00111` (7):
/// - ALU: Sign-Injection.
SGNJ = 7,

/// `_01000` (8):
/// - ALU: Negative Sign-Injection.
SGNJN = 8,

/// `_01001` (9):
/// - ALU: Xor Sign-Injection.
SGNJX = 9,

/// `_01010` (10):
/// - ALU: Classification Mask.
Class = 10,

/// `_01011` (11):
/// - ALU: Fused Multiplication-Addition.
MAdd = 11,

/// `_01100` (12):
/// - ALU: Fused Multiplication-Subtraction.
MSub = 12,

/// `_01101` (13):
/// - ALU: Fused Negated Multiplication-Subtraction.
NMSub = 13,

/// `_01110` (14):
/// - ALU: Fused Negated Multiplication-Addition.
NMAdd = 14,

/// `_10000` (16):
/// - Comparator: Set if less than.
Slt = 16,

/// `_10001` (17):
/// - Comparator: Set if less than or equal.
Sle = 17,
}

impl FpuAluOp {
/// Get the corresponding control signal given a function code.
pub fn from_function(function: u8) -> Result<Self, String> {
match function {
FUNCTION_C_EQ => Ok(Self::MultiplicationOrEqual),
FUNCTION_C_LT => Ok(Self::Slt),
FUNCTION_C_LE => Ok(Self::Sle),
_ => Err(format!("Unsupported function code `{function}`")),
}
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub enum RoundingMode {
RNE = 0,
RTZ = 1,
RDN = 2,
RUP = 3,
RMM = 4,
#[default]
DRM = 7,
}

/// Determines, given that [`FpuRegWrite`] is set, what the source of a floating-point
/// register's new data will be.
///
/// This decision, if set, overrides the decision from the [`DataWrite`] control signal.
#[derive(Clone, Default, PartialEq, Serialize, Deserialize, Debug)]
pub enum FpuMemToReg {
/// Do not use data from memory. Use the result of the [`DataWrite`] control signal.
#[default]
UseDataWrite = 0,

/// Use data from memory.
UseMemory = 1,
}

/// Determines, given that [`FpuRegWrite`] is set, which destination register to write
/// to, which largely depends on the instruction format.
#[derive(Clone, Default, PartialEq, Serialize, Deserialize, Debug)]
pub enum FpuRegDst {
/// Use register `rs1`.
Reg1 = 0,

/// Use register `rs2`.
Reg2 = 1,

/// Use register `rd`.
#[default]
Reg3 = 2,
}

/// Determines if the floating-point register file should be written to.
#[derive(Clone, Default, PartialEq, Serialize, Deserialize, Debug)]
pub enum FpuRegWrite {
/// Do not write to the floating-point register file.
#[default]
NoWrite = 0,

/// Write to the floating-point register file.
YesWrite = 1,
}
}
Loading
Loading