From dc7e88212de93ae104939296c9992c94cdf6a0e1 Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 13 Aug 2024 18:42:33 +0900 Subject: [PATCH 1/8] [add] add zicntr_extension.rs --- src/instruction.rs | 1 + src/instruction/zicntr_extension.rs | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/instruction/zicntr_extension.rs diff --git a/src/instruction.rs b/src/instruction.rs index 364c568..ca39669 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -5,6 +5,7 @@ pub mod base_i; pub mod c_extension; pub mod m_extension; pub mod priv_extension; +pub mod zicntr_extension; pub mod zicsr_extension; pub mod zifencei_extension; diff --git a/src/instruction/zicntr_extension.rs b/src/instruction/zicntr_extension.rs new file mode 100644 index 0000000..7b4b884 --- /dev/null +++ b/src/instruction/zicntr_extension.rs @@ -0,0 +1,21 @@ +//! Zicntr extension Instruction. + +use super::{InstFormat, Opcode}; +use core::fmt::{self, Display, Formatter}; + +/// Insturctions in Zicntr Extension. +#[allow(non_camel_case_types)] +#[derive(Debug, PartialEq)] +pub enum ZicntrOpcode { + // For Rv32, these instructions indicate lower 32 bits. + // For Rv64, these instructions do not exist. + RDCYCLE_H, + RDTIME_H, + RDINSTRET_H, + + // For Rv32, these instructions indicate upper 32 bits. + // For Rv64, these instructions can access the full 64-bit CSRs directly. + RDCYCLE, + RDTIME, + RDINSTRET, +} From 987d42a7eb9ad2ce8ca2e157ac149a252a854e5d Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 13 Aug 2024 18:48:36 +0900 Subject: [PATCH 2/8] [add] implement `Display` and `Opcode` trait for `ZicntrOpcode` --- src/instruction.rs | 9 +++++++++ src/instruction/zicntr_extension.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/instruction.rs b/src/instruction.rs index ca39669..7325092 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -195,6 +195,9 @@ impl Display for Instruction { self.imm.unwrap(), ) } + InstFormat::CSRcntrformat => { + write!(f, "{} {}", self.opc, reg2str(self.rd.unwrap()),) + } InstFormat::Uncategorized => { write!( f, @@ -379,6 +382,12 @@ pub enum InstFormat { /// ``` CSRuiformat, + /// Zicntr extension format + /// ```ignore + /// rdtime rd + /// ``` + CSRcntrformat, + /// M-extension instruction format /// ```ignore /// mul rd, rs1, rs2 diff --git a/src/instruction/zicntr_extension.rs b/src/instruction/zicntr_extension.rs index 7b4b884..948a9c9 100644 --- a/src/instruction/zicntr_extension.rs +++ b/src/instruction/zicntr_extension.rs @@ -19,3 +19,29 @@ pub enum ZicntrOpcode { RDTIME, RDINSTRET, } + +impl Display for ZicntrOpcode { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + ZicntrOpcode::RDCYCLE_H => write!(f, "rdcycleh"), + ZicntrOpcode::RDTIME_H => write!(f, "rdtimeh"), + ZicntrOpcode::RDINSTRET_H => write!(f, "rdinstreth"), + ZicntrOpcode::RDCYCLE => write!(f, "rdcycle"), + ZicntrOpcode::RDTIME => write!(f, "rdtime"), + ZicntrOpcode::RDINSTRET => write!(f, "rdinstret"), + } + } +} + +impl Opcode for ZicntrOpcode { + fn get_format(&self) -> InstFormat { + match self { + ZicntrOpcode::RDCYCLE_H + | ZicntrOpcode::RDTIME_H + | ZicntrOpcode::RDINSTRET_H + | ZicntrOpcode::RDCYCLE + | ZicntrOpcode::RDTIME + | ZicntrOpcode::RDINSTRET => InstFormat::CSRcntrformat, + } + } +} From d06399d1407cb2fb4e4364e8c883a81ef3668c76 Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 13 Aug 2024 20:21:26 +0900 Subject: [PATCH 3/8] [add] add decode/inst_32/zicntr_extension.rs --- src/decode/inst_32.rs | 1 + src/decode/inst_32/zicntr_extension.rs | 73 ++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/decode/inst_32/zicntr_extension.rs diff --git a/src/decode/inst_32.rs b/src/decode/inst_32.rs index bb86fac..aea8b08 100644 --- a/src/decode/inst_32.rs +++ b/src/decode/inst_32.rs @@ -2,6 +2,7 @@ mod a_extension; mod base_i; mod m_extension; mod priv_extension; +mod zicntr_extension; mod zicsr_extension; mod zifencei_extension; diff --git a/src/decode/inst_32/zicntr_extension.rs b/src/decode/inst_32/zicntr_extension.rs new file mode 100644 index 0000000..dc0ce43 --- /dev/null +++ b/src/decode/inst_32/zicntr_extension.rs @@ -0,0 +1,73 @@ +use super::super::{DecodeUtil, DecodingError}; +use crate::instruction::zicntr_extension::ZicntrOpcode; + +pub fn parse_opcode(inst: u32) -> Result { + let opmap: u8 = u8::try_from(inst.slice(6, 0)).unwrap(); + let funct3: u8 = u8::try_from(inst.slice(14, 12)).unwrap(); + let csr_num: u16 = u16::try_from(inst.slice(31, 20)).unwrap(); + + match opmap { + 0b111_0011 => match funct3 { + 0b010 => match csr_num { + 0xc00 => Ok(ZicntrOpcode::RDCYCLE), + 0xc01 => Ok(ZicntrOpcode::RDTIME), + 0xc02 => Ok(ZicntrOpcode::RDINSTRET), + 0xc80 => Ok(ZicntrOpcode::RDCYCLE_H), + 0xc81 => Ok(ZicntrOpcode::RDTIME_H), + 0xc82 => Ok(ZicntrOpcode::RDINSTRET_H), + _ => Err(DecodingError::InvalidOpcode), + }, + _ => Err(DecodingError::InvalidFunct3), + }, + _ => Err(DecodingError::InvalidOpcode), + } +} + +#[allow(clippy::unnecessary_wraps)] +pub fn parse_rd(inst: u32, opkind: &ZicntrOpcode) -> Option { + let rd: usize = inst.slice(11, 7) as usize; + match opkind { + ZicntrOpcode::RDCYCLE + | ZicntrOpcode::RDTIME + | ZicntrOpcode::RDINSTRET + | ZicntrOpcode::RDCYCLE_H + | ZicntrOpcode::RDTIME_H + | ZicntrOpcode::RDINSTRET_H => Some(rd), + } +} + +#[allow(clippy::unnecessary_wraps)] +pub fn parse_rs1(_inst: u32, opkind: &ZicntrOpcode) -> Option { + match opkind { + ZicntrOpcode::RDCYCLE + | ZicntrOpcode::RDTIME + | ZicntrOpcode::RDINSTRET + | ZicntrOpcode::RDCYCLE_H + | ZicntrOpcode::RDTIME_H + | ZicntrOpcode::RDINSTRET_H => None, + } +} + +#[allow(clippy::unnecessary_wraps)] +pub fn parse_rs2(_inst: u32, opkind: &ZicntrOpcode) -> Option { + match opkind { + ZicntrOpcode::RDCYCLE + | ZicntrOpcode::RDTIME + | ZicntrOpcode::RDINSTRET + | ZicntrOpcode::RDCYCLE_H + | ZicntrOpcode::RDTIME_H + | ZicntrOpcode::RDINSTRET_H => None, + } +} + +#[allow(clippy::cast_possible_wrap, clippy::unnecessary_wraps)] +pub fn parse_imm(_inst: u32, opkind: &ZicntrOpcode) -> Option { + match opkind { + ZicntrOpcode::RDCYCLE + | ZicntrOpcode::RDTIME + | ZicntrOpcode::RDINSTRET + | ZicntrOpcode::RDCYCLE_H + | ZicntrOpcode::RDTIME_H + | ZicntrOpcode::RDINSTRET_H => None, + } +} From 1bda86c7bec6e4a131c35aee4195b15309b8cf92 Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 13 Aug 2024 20:41:24 +0900 Subject: [PATCH 4/8] [wip][add] add zicntr exntesion definition --- src/instruction.rs | 5 +++++ src/lib.rs | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/instruction.rs b/src/instruction.rs index 7325092..cfad371 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -16,6 +16,7 @@ use base_i::BaseIOpcode; use c_extension::COpcode; use m_extension::MOpcode; use priv_extension::PrivOpcode; +use zicntr_extension::ZicntrOpcode; use zicsr_extension::ZicsrOpcode; use zifencei_extension::ZifenceiOpcode; @@ -438,6 +439,8 @@ pub enum OpcodeKind { Zifencei(ZifenceiOpcode), /// Control and Status Register Instructions Zicsr(ZicsrOpcode), + /// Base Counters and Timers + Zicntr(ZicntrOpcode), /// Privileged Instructions Priv(PrivOpcode), } @@ -451,6 +454,7 @@ impl Display for OpcodeKind { Self::C(opc) => write!(f, "{opc}"), Self::Zifencei(opc) => write!(f, "{opc}"), Self::Zicsr(opc) => write!(f, "{opc}"), + Self::Zicntr(opc) => write!(f, "{opc}"), Self::Priv(opc) => write!(f, "{opc}"), } } @@ -466,6 +470,7 @@ impl OpcodeKind { Self::C(opc) => opc.get_format(), Self::Zifencei(opc) => opc.get_format(), Self::Zicsr(opc) => opc.get_format(), + Self::Zicntr(opc) => opc.get_format(), Self::Priv(opc) => opc.get_format(), } } diff --git a/src/lib.rs b/src/lib.rs index e7f8b7b..722fcf7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,6 +60,8 @@ enum Extensions { Zifencei, /// Control and Status Register Instructions Zicsr, + /// Base Counters and Timers + Zicntr, /// Privileged Instructions Priv, } From 60703775a6b6edd25882f695ba8a95c3ce2a7521 Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 13 Aug 2024 22:50:55 +0900 Subject: [PATCH 5/8] [add] add the match pattern to decode trait function --- src/decode/inst_32.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/decode/inst_32.rs b/src/decode/inst_32.rs index aea8b08..05fb1d9 100644 --- a/src/decode/inst_32.rs +++ b/src/decode/inst_32.rs @@ -41,6 +41,7 @@ impl Decode for u32 { self, )?)), Ok(Extensions::Zicsr) => Ok(OpcodeKind::Zicsr(zicsr_extension::parse_opcode(self)?)), + Ok(Extensions::Zicntr) => Ok(OpcodeKind::Zicntr(zicntr_extension::parse_opcode(self)?)), Ok(Extensions::Priv) => Ok(OpcodeKind::Priv(priv_extension::parse_opcode(self)?)), Ok(Extensions::C) => Err(DecodingError::Not32BitInst), Err(decoding_err) => Err(decoding_err), @@ -54,6 +55,7 @@ impl Decode for u32 { OpcodeKind::A(opc) => Ok(a_extension::parse_rd(self, opc)), OpcodeKind::Zifencei(opc) => Ok(zifencei_extension::parse_rd(self, opc)), OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::parse_rd(self, opc)), + OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::parse_rd(self, opc)), OpcodeKind::Priv(opc) => Ok(priv_extension::parse_rd(self, opc)), OpcodeKind::C(_) => Err(DecodingError::Not32BitInst), } @@ -66,6 +68,7 @@ impl Decode for u32 { OpcodeKind::A(opc) => Ok(a_extension::parse_rs1(self, opc)), OpcodeKind::Zifencei(opc) => Ok(zifencei_extension::parse_rs1(self, opc)), OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::parse_rs1(self, opc)), + OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::parse_rs1(self, opc)), OpcodeKind::Priv(opc) => Ok(priv_extension::parse_rs1(self, opc)), OpcodeKind::C(_) => Err(DecodingError::Not32BitInst), } @@ -78,6 +81,7 @@ impl Decode for u32 { OpcodeKind::A(opc) => Ok(a_extension::parse_rs2(self, opc)), OpcodeKind::Zifencei(opc) => Ok(zifencei_extension::parse_rs2(self, opc)), OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::parse_rs2(self, opc)), + OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::parse_rs2(self, opc)), OpcodeKind::Priv(opc) => Ok(priv_extension::parse_rs2(self, opc)), OpcodeKind::C(_) => Err(DecodingError::Not32BitInst), } @@ -90,6 +94,7 @@ impl Decode for u32 { OpcodeKind::A(opc) => Ok(a_extension::parse_imm(self, opc)), OpcodeKind::Zifencei(opc) => Ok(zifencei_extension::parse_imm(self, opc)), OpcodeKind::Zicsr(opc) => Ok(zicsr_extension::parse_imm(self, opc)), + OpcodeKind::Zicntr(opc) => Ok(zicntr_extension::parse_imm(self, opc)), OpcodeKind::Priv(opc) => Ok(priv_extension::parse_imm(self, opc)), OpcodeKind::C(_) => Err(DecodingError::Not32BitInst), } From e97ddccd9137cc4d611291483b4aa84553a1d164 Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 13 Aug 2024 23:16:30 +0900 Subject: [PATCH 6/8] [add] add Zicntr case to `DecodeUtil::parse_extension` --- src/decode/inst_32.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/decode/inst_32.rs b/src/decode/inst_32.rs index 05fb1d9..554f269 100644 --- a/src/decode/inst_32.rs +++ b/src/decode/inst_32.rs @@ -110,6 +110,7 @@ impl DecodeUtil for u32 { let opmap: u8 = u8::try_from(self.slice(6, 0)).unwrap(); let funct3: u8 = u8::try_from(self.slice(14, 12)).unwrap(); let funct7: u8 = u8::try_from(self.slice(31, 25)).unwrap(); + let csr: u16 = u16::try_from(self.slice(31, 20)).unwrap(); match opmap { 0b000_1111 => Ok(Extensions::Zifencei), @@ -128,6 +129,11 @@ impl DecodeUtil for u32 { 0b000_0000 => Ok(Extensions::BaseI), _ => Ok(Extensions::Priv), }, + 0b010 => match csr { + // csrrs rd, (cycle|time|instret), zero + 0xc00..=0xc02 | 0xc80..=0xc82 => Ok(Extensions::Zicntr), + _ => Ok(Extensions::Zicsr), + }, _ => Ok(Extensions::Zicsr), }, _ => Ok(Extensions::BaseI), From fabfb524993b6f3e5ca0d2bc3af4c778773f3ce2 Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 13 Aug 2024 23:30:44 +0900 Subject: [PATCH 7/8] [add] add unit test to zicntr_extension.rs --- src/decode/inst_32/zicntr_extension.rs | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/decode/inst_32/zicntr_extension.rs b/src/decode/inst_32/zicntr_extension.rs index dc0ce43..1fbd18c 100644 --- a/src/decode/inst_32/zicntr_extension.rs +++ b/src/decode/inst_32/zicntr_extension.rs @@ -71,3 +71,37 @@ pub fn parse_imm(_inst: u32, opkind: &ZicntrOpcode) -> Option { | ZicntrOpcode::RDINSTRET_H => None, } } + +#[cfg(test)] +#[allow(unused_variables)] +mod test_zicntr { + #[test] + #[allow(overflowing_literals)] + fn zicntr_decode_test() { + use super::*; + use crate::{Decode, Isa, OpcodeKind}; + + let test_32 = |inst_32: u32, + op: OpcodeKind, + rd: Option, + rs1: Option, + rs2: Option, + imm: Option| { + 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( + 0b1100_0000_0001_0000_0010_0111_1111_0011, + OpcodeKind::Zicntr(ZicntrOpcode::RDTIME), + Some(15), + None, + None, + None, + ) + } +} From 6a305e37043756837a2a2e1674f13c3fb831fc5a Mon Sep 17 00:00:00 2001 From: Alingof Date: Tue, 13 Aug 2024 23:38:56 +0900 Subject: [PATCH 8/8] [refactor] fix clippy warning --- src/instruction/zicntr_extension.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/instruction/zicntr_extension.rs b/src/instruction/zicntr_extension.rs index 948a9c9..eef1681 100644 --- a/src/instruction/zicntr_extension.rs +++ b/src/instruction/zicntr_extension.rs @@ -4,7 +4,7 @@ use super::{InstFormat, Opcode}; use core::fmt::{self, Display, Formatter}; /// Insturctions in Zicntr Extension. -#[allow(non_camel_case_types)] +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] #[derive(Debug, PartialEq)] pub enum ZicntrOpcode { // For Rv32, these instructions indicate lower 32 bits.