ab_riscv_interpreter/v/zvexx/
config.rs1#[cfg(test)]
4mod tests;
5pub mod zvexx_config_helpers;
6
7use crate::v::vector_registers::VectorRegistersExt;
8use crate::{
9 CsrError, Csrs, ExecutableInstruction, ExecutableInstructionCsr, ExecutableInstructionOperands,
10 ExecutionError, ExecutionResult, FetchInstructionResult, InstructionFetcher,
11 OpaqueThreadedExecutionResult, ProgramCounter, RegisterFile, Rs1Rs2OperandValues,
12 Rs1Rs2Operands, ThreadedExecutableInstruction, ThreadedExecutionResult,
13};
14use ab_riscv_macros::instruction_execution;
15use ab_riscv_primitives::prelude::*;
16
17#[instruction_execution]
18const impl<Reg, Hart> ExecutableInstructionOperands for ZveXxConfigInstruction<Hart>
19where
20 Reg: Register,
21 Hart: VectorHartConfig<Reg = Reg>,
22{
23}
24
25#[instruction_execution]
26const impl<Reg, Hart, Env> ExecutableInstructionCsr<Env> for ZveXxConfigInstruction<Hart>
27where
28 Reg: [const] Register,
29 Hart: VectorHartConfig<Reg = Reg>,
30 Env: [const] Csrs<Reg>,
31{
32 #[inline(always)]
37 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
38 fn prepare_csr_read(
39 _env: &Env,
40 csr_index: u16,
41 _will_write: bool,
42 raw_value: Reg::Type,
43 output_value: &mut Reg::Type,
44 ) -> Result<bool, CsrError> {
45 if VectorCsr::from_csr_index(csr_index).is_some() {
46 *output_value = raw_value;
47 Ok(true)
48 } else {
49 Ok(false)
51 }
52 }
53
54 #[inline(always)]
63 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
64 fn prepare_csr_write(
65 env: &mut Env,
66 csr_index: u16,
67 write_value: Reg::Type,
68 output_value: &mut Reg::Type,
69 ) -> Result<bool, CsrError> {
70 if let Some(vcsr) = VectorCsr::from_csr_index(csr_index) {
71 *output_value = match vcsr {
73 VectorCsr::Vstart => {
74 let max = Reg::Type::from(u16::MAX);
76 write_value.min(max)
77 }
78 VectorCsr::Vxsat => {
79 let masked = write_value & Reg::Type::from(1u8);
80 let old_vcsr = env.read_csr(VectorCsr::Vcsr.to_csr_index())?;
82 let new_vcsr = (old_vcsr & !Reg::Type::from(1u8)) | masked;
83 env.write_csr(VectorCsr::Vcsr.to_csr_index(), new_vcsr)?;
84 masked
85 }
86 VectorCsr::Vxrm => {
87 let masked = write_value & Reg::Type::from(0b11u8);
88 let old_vcsr = env.read_csr(VectorCsr::Vcsr.to_csr_index())?;
90 let new_vcsr = (old_vcsr & !Reg::Type::from(0b110u8)) | (masked << 1u8);
91 env.write_csr(VectorCsr::Vcsr.to_csr_index(), new_vcsr)?;
92 masked
93 }
94 VectorCsr::Vcsr => {
95 let new_vxsat = write_value & Reg::Type::from(1u8);
97 env.write_csr(VectorCsr::Vxsat.to_csr_index(), new_vxsat)?;
98
99 let new_vxrm = (write_value >> 1u8) & Reg::Type::from(0b11u8);
101 env.write_csr(VectorCsr::Vxrm.to_csr_index(), new_vxrm)?;
102
103 write_value & Reg::Type::from(0b111u8)
104 }
105 VectorCsr::Vl | VectorCsr::Vtype | VectorCsr::Vlenb => {
106 Err(CsrError::ReadOnly { csr_index })?
108 }
109 };
110 Ok(true)
111 } else {
112 Ok(false)
113 }
114 }
115}
116
117#[instruction_execution]
118const impl<Reg, Hart, Regs, Env, Memory, PC> ExecutableInstruction<Regs, Env, Memory, PC>
119 for ZveXxConfigInstruction<Hart>
120where
121 Reg: [const] Register,
122 Hart: VectorHartConfig<Reg = Reg>,
123 Regs: [const] RegisterFile<Reg>,
124 Env: [const] VectorRegistersExt<Hart = Hart>,
125 PC: [const] ProgramCounter<Reg::Type, Memory>,
126{
127 #[inline(always)]
128 #[cfg_attr(feature = "no-panic", no_panic_const::no_panic(const))]
129 fn execute(
130 self,
131 Rs1Rs2OperandValues {
132 rs1_value,
133 rs2_value,
134 }: Rs1Rs2OperandValues<Reg::Type>,
135 _regs: &mut Regs,
136 env: &mut Env,
137 _memory: &mut Memory,
138 program_counter: &PC,
139 ) -> ExecutionResult<Reg> {
140 match self {
141 Self::Vsetvli { rd, rs1, vtypei } => {
142 let rd_value = zvexx_config_helpers::apply_vsetvl(
143 env,
144 program_counter,
145 rd,
146 rs1,
147 rs1_value,
148 Reg::Type::from(vtypei),
149 )?;
150
151 ExecutionResult::Continue {
152 rd,
153 value: rd_value,
154 }
155 }
156 Self::Vsetivli { rd, uimm, vtypei } => {
157 let rd_value =
158 zvexx_config_helpers::apply_vsetivli(env, program_counter, uimm, vtypei)?;
159
160 ExecutionResult::Continue {
161 rd,
162 value: rd_value,
163 }
164 }
165 Self::Vsetvl { rd, rs1, rs2: _ } => {
166 let vtype_raw = rs2_value;
167 let rd_value = zvexx_config_helpers::apply_vsetvl(
168 env,
169 program_counter,
170 rd,
171 rs1,
172 rs1_value,
173 vtype_raw,
174 )?;
175
176 ExecutionResult::Continue {
177 rd,
178 value: rd_value,
179 }
180 }
181 }
182 }
183}