-
Notifications
You must be signed in to change notification settings - Fork 3
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
Implement Zicntr extenstion #16
Changes from 7 commits
dc7e882
987d42a
d06399d
1bda86c
6070377
e97ddcc
fabfb52
6a305e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use super::super::{DecodeUtil, DecodingError}; | ||
use crate::instruction::zicntr_extension::ZicntrOpcode; | ||
|
||
pub fn parse_opcode(inst: u32) -> Result<ZicntrOpcode, DecodingError> { | ||
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<usize> { | ||
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<usize> { | ||
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<usize> { | ||
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<i32> { | ||
match opkind { | ||
ZicntrOpcode::RDCYCLE | ||
| ZicntrOpcode::RDTIME | ||
| ZicntrOpcode::RDINSTRET | ||
| ZicntrOpcode::RDCYCLE_H | ||
| ZicntrOpcode::RDTIME_H | ||
| 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<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( | ||
0b1100_0000_0001_0000_0010_0111_1111_0011, | ||
OpcodeKind::Zicntr(ZicntrOpcode::RDTIME), | ||
Some(15), | ||
None, | ||
None, | ||
None, | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
//! 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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
RDINSTRET, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
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, | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name
RDCYCLE
contains a capitalized acronym