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

Implemented Zicboz Extension #34

Merged
merged 4 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod base_i;
mod c_extension;
mod m_extension;
mod priv_extension;
mod zicboz_extension;
mod zicfiss_extension;
mod zicntr_extension;
mod zicsr_extension;
Expand Down
17 changes: 14 additions & 3 deletions src/decode/inst_32.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{
a_extension, base_i, m_extension, priv_extension, zicfiss_extension, zicntr_extension,
zicsr_extension, zifencei_extension,
a_extension, base_i, m_extension, priv_extension, zicboz_extension, zicfiss_extension,
zicntr_extension, zicsr_extension, zifencei_extension,
};
use super::{Decode, DecodeUtil, DecodingError};
use crate::instruction::{InstFormat, Instruction, OpcodeKind};
Expand Down Expand Up @@ -48,6 +48,9 @@ impl Decode for u32 {
Ok(Extensions::Zicntr) => Ok(OpcodeKind::Zicntr(
zicntr_extension::bit_32::parse_opcode(self)?,
)),
Ok(Extensions::Zicboz) => Ok(OpcodeKind::Zicboz(
zicboz_extension::bit_32::parse_opcode(self)?,
)),
Ok(Extensions::Priv) => Ok(OpcodeKind::Priv(priv_extension::bit_32::parse_opcode(
self,
)?)),
Expand All @@ -65,6 +68,7 @@ impl Decode for u32 {
OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::bit_32::parse_rd(self, opc)),
OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::bit_32::parse_rd(self, opc)),
OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::bit_32::parse_rd(self, opc)),
OpcodeKind::Zicboz(opc) => Ok(zicboz_extension::bit_32::parse_rd(self, opc)),
OpcodeKind::Priv(opc) => Ok(priv_extension::bit_32::parse_rd(self, opc)),
OpcodeKind::C(_) => Err(DecodingError::Not32BitInst),
}
Expand All @@ -79,6 +83,7 @@ impl Decode for u32 {
OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::bit_32::parse_rs1(self, opc)),
OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::bit_32::parse_rs1(self, opc)),
OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::bit_32::parse_rs1(self, opc)),
OpcodeKind::Zicboz(opc) => Ok(zicboz_extension::bit_32::parse_rs1(self, opc)),
OpcodeKind::Priv(opc) => Ok(priv_extension::bit_32::parse_rs1(self, opc)),
OpcodeKind::C(_) => Err(DecodingError::Not32BitInst),
}
Expand All @@ -93,6 +98,7 @@ impl Decode for u32 {
OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::bit_32::parse_rs2(self, opc)),
OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::bit_32::parse_rs2(self, opc)),
OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::bit_32::parse_rs2(self, opc)),
OpcodeKind::Zicboz(opc) => Ok(zicboz_extension::bit_32::parse_rs2(self, opc)),
OpcodeKind::Priv(opc) => Ok(priv_extension::bit_32::parse_rs2(self, opc)),
OpcodeKind::C(_) => Err(DecodingError::Not32BitInst),
}
Expand All @@ -107,6 +113,7 @@ impl Decode for u32 {
OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::bit_32::parse_imm(self, opc)),
OpcodeKind::Zicfiss(opc) => Ok(zicfiss_extension::bit_32::parse_imm(self, opc)),
OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::bit_32::parse_imm(self, opc)),
OpcodeKind::Zicboz(opc) => Ok(zicboz_extension::bit_32::parse_imm(self, opc)),
OpcodeKind::Priv(opc) => Ok(priv_extension::bit_32::parse_imm(self, opc)),
OpcodeKind::C(_) => Err(DecodingError::Not32BitInst),
}
Expand All @@ -127,7 +134,11 @@ impl DecodeUtil for u32 {
let csr: u16 = u16::try_from(self.slice(31, 20)).unwrap();

match opmap {
0b000_1111 => Ok(Extensions::Zifencei),
0b000_1111 => match funct3 {
0b000 => Ok(Extensions::Zifencei),
0b010 => Ok(Extensions::Zicboz),
_ => Err(DecodingError::UnknownExtension),
},
0b010_1111 => match funct5 {
0b00000 | 0b00001 | 0b00010 | 0b00011 | 0b00100 | 0b01000 | 0b01100 | 0b10000
| 0b10100 | 0b11000 | 0b11100 => Ok(Extensions::A),
Expand Down
91 changes: 91 additions & 0 deletions src/decode/zicboz_extension.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
pub mod bit_32 {
use super::super::{DecodeUtil, DecodingError};
use crate::instruction::zicboz_extension::ZicbozOpcode;

pub fn parse_opcode(inst: u32) -> Result<ZicbozOpcode, DecodingError> {
let opmap: u8 = u8::try_from(inst.slice(6, 0)).unwrap();
let funct3: u8 = u8::try_from(inst.slice(14, 12)).unwrap();
let field_11_7: u8 = u8::try_from(inst.slice(11, 7)).unwrap();
let cbo_num: u16 = u16::try_from(inst.slice(31, 20)).unwrap();

match opmap {
0b000_1111 => match funct3 {
0b010 => match cbo_num {
0b100 => match field_11_7 {
0x0 => Ok(ZicbozOpcode::CBO_ZERO),
_ => Err(DecodingError::InvalidOpcode),
},
_ => Err(DecodingError::InvalidOpcode),
},
_ => Err(DecodingError::InvalidFunct3),
},
_ => Err(DecodingError::InvalidOpcode),
}
}

#[allow(clippy::unnecessary_wraps)]
pub fn parse_rd(_inst: u32, _opkind: &ZicbozOpcode) -> Option<usize> {
None
}

#[allow(clippy::unnecessary_wraps)]
pub fn parse_rs1(inst: u32, opkind: &ZicbozOpcode) -> Option<usize> {
let rs1: u8 = u8::try_from(inst.slice(19, 15)).unwrap();
match opkind {
ZicbozOpcode::CBO_ZERO => Some(rs1.into()),
}
}

#[allow(clippy::unnecessary_wraps)]
pub fn parse_rs2(_inst: u32, _opkind: &ZicbozOpcode) -> Option<usize> {
None
}

#[allow(clippy::cast_possible_wrap, clippy::unnecessary_wraps)]
pub fn parse_imm(_inst: u32, _opkind: &ZicbozOpcode) -> Option<i32> {
None
}
}

#[cfg(test)]
#[allow(unused_variables)]
mod test_zicboz {
#[test]
#[allow(overflowing_literals)]
fn zicboz_decode_test() {
use crate::instruction::zicboz_extension::ZicbozOpcode;
use crate::{Decode, Isa, OpcodeKind};

let test_32 = |inst_32: u32,
op: OpcodeKind,
rd: Option<usize>,
rs1: Option<usize>,
rs2: Option<usize>,
imm: Option<i32>| {
let op_32 = inst_32.parse_opcode(Isa::Rv64).unwrap();
assert!(matches!(&op_32, op));
assert_eq!(inst_32.parse_rd(&op_32).unwrap(), rd);
assert_eq!(inst_32.parse_rs1(&op_32).unwrap(), rs1);
assert_eq!(inst_32.parse_rs2(&op_32).unwrap(), rs2);
assert_eq!(inst_32.parse_imm(&op_32, Isa::Rv64).unwrap(), imm);
};

test_32(
0b0000_0000_0100_1010_1010_0000_0000_1111,
OpcodeKind::Zicboz(ZicbozOpcode::CBO_ZERO),
None,
Some(21),
None,
None,
);

test_32(
0b0000_0000_0100_1000_0010_0000_0000_1111,
OpcodeKind::Zicboz(ZicbozOpcode::CBO_ZERO),
None,
Some(16),
None,
None,
);
}
}
2 changes: 1 addition & 1 deletion src/decode/zicntr_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,6 @@ mod test_zicntr {
None,
None,
None,
)
);
}
}
2 changes: 1 addition & 1 deletion src/decode/zifencei_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,6 @@ mod test_zifenci {
Some(0),
None,
Some(0b0011_0011),
)
);
}
}
6 changes: 6 additions & 0 deletions src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod base_i;
pub mod c_extension;
pub mod m_extension;
pub mod priv_extension;
pub mod zicboz_extension;
pub mod zicfiss_extension;
pub mod zicntr_extension;
pub mod zicsr_extension;
Expand All @@ -17,6 +18,7 @@ use base_i::BaseIOpcode;
use c_extension::COpcode;
use m_extension::MOpcode;
use priv_extension::PrivOpcode;
use zicboz_extension::ZicbozOpcode;
use zicfiss_extension::ZicfissOpcode;
use zicntr_extension::ZicntrOpcode;
use zicsr_extension::ZicsrOpcode;
Expand Down Expand Up @@ -446,6 +448,8 @@ pub enum OpcodeKind {
C(COpcode),
/// Instruction-Fetch Fence,
Zifencei(ZifenceiOpcode),
/// Cache-Block Zero Instructions
Zicboz(ZicbozOpcode),
/// Control and Status Register Instructions
Zicsr(ZicsrOpcode),
/// CFI Shadow Stack
Expand All @@ -464,6 +468,7 @@ impl Display for OpcodeKind {
Self::A(opc) => write!(f, "{opc}"),
Self::C(opc) => write!(f, "{opc}"),
Self::Zifencei(opc) => write!(f, "{opc}"),
Self::Zicboz(opc) => write!(f, "{opc}"),
Self::Zicsr(opc) => write!(f, "{opc}"),
Self::Zicfiss(opc) => write!(f, "{opc}"),
Self::Zicntr(opc) => write!(f, "{opc}"),
Expand All @@ -481,6 +486,7 @@ impl OpcodeKind {
Self::A(opc) => opc.get_format(),
Self::C(opc) => opc.get_format(),
Self::Zifencei(opc) => opc.get_format(),
Self::Zicboz(opc) => opc.get_format(),
Self::Zicsr(opc) => opc.get_format(),
Self::Zicfiss(opc) => opc.get_format(),
Self::Zicntr(opc) => opc.get_format(),
Expand Down
29 changes: 29 additions & 0 deletions src/instruction/zicboz_extension.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! Zicboz extension Instruction.
//!
//! The RISC-V Instruction Set Manual Volume I p.108 19.7.4 cbo.zero

use super::{InstFormat, Opcode};
use core::fmt::{self, Display, Formatter};

/// Insturctions in Zicboz Extension.
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Debug, PartialEq)]
pub enum ZicbozOpcode {
CBO_ZERO,
}

impl Display for ZicbozOpcode {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
ZicbozOpcode::CBO_ZERO => write!(f, "cbo.zero"),
}
}
}

impl Opcode for ZicbozOpcode {
fn get_format(&self) -> InstFormat {
match self {
ZicbozOpcode::CBO_ZERO => InstFormat::OnlyRs1,
}
}
}
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ enum Extensions {
C,
/// Instruction-Fetch Fence
Zifencei,
/// Cache-Block Zero Instructions
Zicboz,
/// Control and Status Register Instructions
Zicsr,
/// Shadow Stack
Expand Down Expand Up @@ -137,7 +139,7 @@ mod tests {
.unwrap()
.opc,
OpcodeKind::BaseI(BaseIOpcode::JAL),
)
);
}

#[test]
Expand Down Expand Up @@ -165,6 +167,6 @@ mod tests {
.unwrap()
.opc,
OpcodeKind::BaseI(BaseIOpcode::JAL),
)
);
}
}
Loading