1use core::fmt;
10
11use crate::types::{self, Privilege, trap};
12
13use super::decoder::{Decode, Decoder};
14use super::encoder::{Encode, Encoder};
15use super::unit::{self, Unit};
16use super::{Error, util};
17
18#[derive(Copy, Clone, Debug, Eq, PartialEq)]
22pub enum Synchronization<I = unit::ReferenceIOptions, D = unit::ReferenceDOptions> {
23 Start(Start),
24 Trap(Trap),
25 Context(Context),
26 Support(Support<I, D>),
27}
28
29impl<I, D> Synchronization<I, D> {
30 pub fn branch_not_taken(&self) -> Option<bool> {
37 match self {
38 Self::Start(start) => Some(start.branch),
39 Self::Trap(trap) => Some(trap.branch),
40 _ => None,
41 }
42 }
43
44 pub fn as_context(&self) -> Option<&Context> {
49 match self {
50 Self::Start(start) => Some(&start.ctx),
51 Self::Trap(trap) => Some(&trap.ctx),
52 Self::Context(ctx) => Some(ctx),
53 _ => None,
54 }
55 }
56
57 pub fn as_support(&self) -> Option<&Support<I, D>> {
62 match self {
63 Self::Support(supp) => Some(supp),
64 _ => None,
65 }
66 }
67}
68
69impl<I, D> From<Start> for Synchronization<I, D> {
70 fn from(start: Start) -> Self {
71 Self::Start(start)
72 }
73}
74
75impl<I, D> From<Trap> for Synchronization<I, D> {
76 fn from(trap: Trap) -> Self {
77 Self::Trap(trap)
78 }
79}
80
81impl<I, D> From<Context> for Synchronization<I, D> {
82 fn from(ctx: Context) -> Self {
83 Self::Context(ctx)
84 }
85}
86
87impl<I, D> From<Support<I, D>> for Synchronization<I, D> {
88 fn from(support: Support<I, D>) -> Self {
89 Self::Support(support)
90 }
91}
92
93impl<U: Unit> Decode<'_, U> for Synchronization<U::IOptions, U::DOptions> {
94 fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
95 match decoder.read_bits::<u8>(2)? {
96 0b00 => Start::decode(decoder).map(Into::into),
97 0b01 => Trap::decode(decoder).map(Into::into),
98 0b10 => Context::decode(decoder).map(Into::into),
99 0b11 => Support::decode(decoder).map(Into::into),
100 _ => unreachable!(),
101 }
102 }
103}
104
105impl<'d, U> Encode<'d, U> for Synchronization<U::IOptions, U::DOptions>
106where
107 U: Unit,
108 U::IOptions: Encode<'d, U>,
109 U::DOptions: Encode<'d, U>,
110{
111 fn encode(&self, encoder: &mut Encoder<'d, U>) -> Result<(), Error> {
112 match self {
113 Self::Start(start) => {
114 encoder.write_bits(0b00u8, 2)?;
115 encoder.encode(start)
116 }
117 Self::Trap(trap) => {
118 encoder.write_bits(0b01u8, 2)?;
119 encoder.encode(trap)
120 }
121 Self::Context(ctx) => {
122 encoder.write_bits(0b10u8, 2)?;
123 encoder.encode(ctx)
124 }
125 Self::Support(support) => {
126 encoder.write_bits(0b11u8, 2)?;
127 encoder.encode(support)
128 }
129 }
130 }
131}
132
133impl<I: unit::IOptions, D> fmt::Display for Synchronization<I, D> {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 match self {
136 Self::Start(s) => write!(f, "START {s}"),
137 Self::Trap(t) => write!(f, "TRAP {t}"),
138 Self::Context(c) => write!(f, "CTX {c}"),
139 Self::Support(s) => write!(f, "SUPP {s}"),
140 }
141 }
142}
143
144#[derive(Copy, Clone, Debug, Eq, PartialEq)]
149pub struct Start {
150 pub branch: bool,
153 pub ctx: Context,
154 pub address: u64,
156}
157
158impl<U> Decode<'_, U> for Start {
159 fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
160 let branch = decoder.read_bit()?;
161 let ctx = Context::decode(decoder)?;
162 let address = util::read_address(decoder)?;
163 Ok(Start {
164 branch,
165 ctx,
166 address,
167 })
168 }
169}
170
171impl<U> Encode<'_, U> for Start {
172 fn encode(&self, encoder: &mut Encoder<U>) -> Result<(), Error> {
173 encoder.write_bit(self.branch)?;
174 encoder.encode(&self.ctx)?;
175 util::write_address(encoder, self.address)
176 }
177}
178
179impl fmt::Display for Start {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 let address = self.address;
182 write!(f, "{address:#x}")?;
183 if !self.branch {
184 write!(f, ", branch taken")?;
185 }
186 write!(f, ", {}", self.ctx)
187 }
188}
189
190#[derive(Copy, Clone, Debug, Eq, PartialEq)]
195pub struct Trap {
196 pub branch: bool,
199 pub ctx: Context,
200 pub thaddr: bool,
204 pub address: u64,
206 pub info: trap::Info,
207}
208
209impl<U> Decode<'_, U> for Trap {
210 fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
211 let branch = decoder.read_bit()?;
212 let ctx = Context::decode(decoder)?;
213 let ecause = decoder.read_bits(decoder.widths().ecause.get())?;
214 let interrupt = decoder.read_bit()?;
215 let thaddr = decoder.read_bit()?;
216 let address = util::read_address(decoder)?;
217 let tval = if interrupt {
218 None
219 } else {
220 Some(decoder.read_bits(decoder.widths().iaddress.get())?)
221 };
222 Ok(Trap {
223 branch,
224 ctx,
225 thaddr,
226 address,
227 info: trap::Info { ecause, tval },
228 })
229 }
230}
231
232impl<U> Encode<'_, U> for Trap {
233 fn encode(&self, encoder: &mut Encoder<U>) -> Result<(), Error> {
234 encoder.write_bit(self.branch)?;
235 encoder.encode(&self.ctx)?;
236 encoder.write_bits(self.info.ecause, encoder.widths().ecause.get())?;
237 encoder.write_bit(self.info.tval.is_none())?;
238 encoder.write_bit(self.thaddr)?;
239 util::write_address(encoder, self.address)?;
240 if let Some(tval) = self.info.tval {
241 encoder.write_bits(tval, encoder.widths().iaddress.get())?;
242 }
243 Ok(())
244 }
245}
246
247impl fmt::Display for Trap {
248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
249 let info = self.info;
250 let address = self.address;
251 let addr_type = match self.thaddr {
252 true => "handler",
253 false => "EPC",
254 };
255 write!(f, "{info}, {addr_type}: {address:#x}")?;
256 if !self.branch {
257 write!(f, ", branch taken")?;
258 }
259 write!(f, ", {}", self.ctx)
260 }
261}
262
263#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
268pub struct Context {
269 pub privilege: Privilege,
271 pub time: Option<u64>,
272 pub context: u64,
273}
274
275impl From<&Context> for types::Context {
276 fn from(ctx: &Context) -> Self {
277 Self {
278 privilege: ctx.privilege,
279 context: ctx.context,
280 }
281 }
282}
283
284impl From<Context> for types::Context {
285 fn from(ctx: Context) -> Self {
286 (&ctx).into()
287 }
288}
289
290impl<U> Decode<'_, U> for Context {
291 fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
292 let privilege = decoder
293 .read_bits::<u8>(decoder.widths().privilege.get())?
294 .try_into()
295 .map_err(Error::UnknownPrivilege)?;
296 let time = decoder
297 .widths()
298 .time
299 .map(|w| decoder.read_bits(w.get()))
300 .transpose()?;
301 let context_width = decoder.widths().context.map(Into::into).unwrap_or_default();
302 let context = decoder.read_bits(context_width)?;
303 Ok(Context {
304 privilege,
305 time,
306 context,
307 })
308 }
309}
310
311impl<U> Encode<'_, U> for Context {
312 fn encode(&self, encoder: &mut Encoder<U>) -> Result<(), Error> {
313 encoder.write_bits(u8::from(self.privilege), encoder.widths().privilege.get())?;
314 if let Some(width) = encoder.widths().time {
315 encoder.write_bits(self.time.unwrap_or_default(), width.get())?;
316 }
317 if let Some(width) = encoder.widths().context {
318 encoder.write_bits(self.context, width.get())?;
319 }
320 Ok(())
321 }
322}
323
324impl fmt::Display for Context {
325 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
326 write!(f, "{} mode", self.privilege)?;
327 if let Some(time) = self.time {
328 write!(f, ", time: {time}")?;
329 }
330 write!(f, ", context: {}", self.context)
331 }
332}
333
334#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
338pub struct Support<I = unit::ReferenceIOptions, D = unit::ReferenceDOptions> {
339 pub ienable: bool,
340 pub encoder_mode: EncoderMode,
341 pub qual_status: QualStatus,
342 pub ioptions: I,
343 pub denable: bool,
344 pub dloss: bool,
345 pub doptions: D,
346}
347
348impl<U: Unit> Decode<'_, U> for Support<U::IOptions, U::DOptions> {
349 fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
350 let ienable = decoder.read_bit()?;
351 let encoder_mode = decoder
352 .read_bits::<u8>(decoder.unit().encoder_mode_width())?
353 .try_into()
354 .map_err(Error::UnknownEncoderMode)?;
355 let qual_status = QualStatus::decode(decoder)?;
356 let ioptions = U::decode_ioptions(decoder)?;
357 let denable = decoder.read_bit()?;
358 let dloss = decoder.read_bit()?;
359 let doptions = U::decode_doptions(decoder)?;
360 Ok(Support {
361 ienable,
362 encoder_mode,
363 qual_status,
364 ioptions,
365 denable,
366 dloss,
367 doptions,
368 })
369 }
370}
371
372impl<'d, U> Encode<'d, U> for Support<U::IOptions, U::DOptions>
373where
374 U: Unit,
375 U::IOptions: Encode<'d, U>,
376 U::DOptions: Encode<'d, U>,
377{
378 fn encode(&self, encoder: &mut Encoder<'d, U>) -> Result<(), Error> {
379 encoder.write_bit(self.ienable)?;
380 encoder.write_bits(
381 u8::from(self.encoder_mode),
382 encoder.unit().encoder_mode_width(),
383 )?;
384 encoder.encode(&self.qual_status)?;
385 encoder.encode(&self.ioptions)?;
386 encoder.write_bit(self.denable)?;
387 if self.denable {
388 encoder.write_bit(self.dloss)?;
389 encoder.encode(&self.doptions)?;
390 }
391 Ok(())
392 }
393}
394
395impl<I: unit::IOptions, D> fmt::Display for Support<I, D> {
396 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
397 let ienable = util::Enabled(self.ienable);
398 let mode = self.encoder_mode;
399 let qual = self.qual_status;
400 write!(f, "itrace {ienable} ({mode}) {qual}")?;
401 if let Some(mode) = self.ioptions.address_mode() {
402 write!(f, ", {mode} address mode")?;
403 }
404 if self.ioptions.implicit_return() == Some(true) {
405 write!(f, ", implicit return")?;
406 }
407 if self.ioptions.implicit_exception() == Some(true) {
408 write!(f, ", implicit exception")?;
409 }
410 if self.ioptions.branch_prediction() == Some(true) {
411 write!(f, ", branch prediction")?;
412 }
413 if self.ioptions.jump_target_cache() == Some(true) {
414 write!(f, ", jump target cache")?;
415 }
416
417 write!(f, "; dtrace {}", util::Enabled(self.denable))?;
418 if self.dloss {
419 write!(f, " dloss")?;
420 }
421
422 Ok(())
423 }
424}
425
426#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
428pub enum QualStatus {
429 #[default]
431 NoChange,
432 EndedRep,
435 TraceLost,
437 EndedNtr,
440}
441
442impl<U> Decode<'_, U> for QualStatus {
443 fn decode(decoder: &mut Decoder<U>) -> Result<Self, Error> {
444 Ok(match decoder.read_bits::<u8>(2)? {
445 0b00 => QualStatus::NoChange,
446 0b01 => QualStatus::EndedRep,
447 0b10 => QualStatus::TraceLost,
448 0b11 => QualStatus::EndedNtr,
449 _ => unreachable!(),
450 })
451 }
452}
453
454impl<U> Encode<'_, U> for QualStatus {
455 fn encode(&self, encoder: &mut Encoder<U>) -> Result<(), Error> {
456 let value: u8 = match self {
457 Self::NoChange => 0b00,
458 Self::EndedRep => 0b01,
459 Self::TraceLost => 0b10,
460 Self::EndedNtr => 0b11,
461 };
462 encoder.write_bits(value, 2)
463 }
464}
465
466impl fmt::Display for QualStatus {
467 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
468 match self {
469 Self::NoChange => write!(f, "no change"),
470 Self::EndedRep => write!(f, "ended rep"),
471 Self::TraceLost => write!(f, "trace lost"),
472 Self::EndedNtr => write!(f, "ended ntr"),
473 }
474 }
475}
476
477#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
479pub enum EncoderMode {
480 #[default]
481 BranchTrace,
482}
483
484impl TryFrom<u8> for EncoderMode {
485 type Error = u8;
486
487 fn try_from(num: u8) -> Result<Self, Self::Error> {
488 match num {
489 0 => Ok(Self::BranchTrace),
490 e => Err(e),
491 }
492 }
493}
494
495impl From<EncoderMode> for u8 {
496 fn from(mode: EncoderMode) -> Self {
497 match mode {
498 EncoderMode::BranchTrace => 0,
499 }
500 }
501}
502
503impl fmt::Display for EncoderMode {
504 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
505 match self {
506 Self::BranchTrace => write!(f, "branch trace"),
507 }
508 }
509}