riscv_etrace/packet/
encoder.rs1use core::num::NonZeroUsize;
6use core::ops;
7
8use super::error::Error;
9use super::truncate::TruncateNum;
10use super::width::Widths;
11
12pub struct Encoder<'d, U> {
14 data: &'d mut [u8],
15 bit_pos: usize,
16 bytes_committed: usize,
17 field_widths: Widths,
18 unit: U,
19 hart_index_width: u8,
20 timestamp_width: u8,
21 trace_type_width: u8,
22 compress: bool,
23}
24
25impl<'d, U> Encoder<'d, U> {
26 pub(super) fn new(
28 field_widths: Widths,
29 unit: U,
30 hart_index_width: u8,
31 timestamp_width: u8,
32 trace_type_width: u8,
33 compress: bool,
34 ) -> Self {
35 Self {
36 data: &mut [],
37 bit_pos: 0,
38 bytes_committed: 0,
39 field_widths,
40 unit,
41 hart_index_width,
42 timestamp_width,
43 trace_type_width,
44 compress,
45 }
46 }
47
48 pub fn reset(&mut self, data: &'d mut [u8]) {
50 self.data = data;
51 self.bit_pos = 0;
52 self.bytes_committed = 0;
53 }
54
55 pub fn uncommitted(&self) -> usize {
57 self.data.len() - self.bytes_committed
58 }
59
60 pub fn encode(&mut self, data: &impl Encode<'d, U>) -> Result<(), Error> {
62 data.encode(self)
63 }
64
65 pub fn unit(&self) -> &U {
67 &self.unit
68 }
69
70 pub(super) fn widths(&self) -> &Widths {
72 &self.field_widths
73 }
74
75 pub(super) fn hart_index_width(&self) -> u8 {
77 self.hart_index_width
78 }
79
80 pub(super) fn timestamp_width(&self) -> u8 {
82 self.timestamp_width
83 }
84
85 pub(super) fn trace_type_width(&self) -> u8 {
87 self.trace_type_width
88 }
89
90 pub(super) fn first_uncommitted_chunk<const N: usize>(
96 &mut self,
97 ) -> Result<&'d mut [u8; N], Error> {
98 let (chunk, data) = core::mem::take(&mut self.data)
99 .split_at_mut_checked(self.bytes_committed)
100 .and_then(|(_, d)| d.split_first_chunk_mut())
101 .ok_or_else(|| {
102 self.reset(&mut []);
103 Error::BufferTooSmall
104 })?;
105 self.reset(data);
106 Ok(chunk)
107 }
108
109 pub(super) fn write_bit(&mut self, bit: bool) -> Result<(), Error> {
111 let byte_pos = self.bit_pos >> 3;
112 let byte = self.get_byte(byte_pos)?;
113 let mask = 0xff << (self.bit_pos & 0x7);
114 let byte = if bit { byte | mask } else { byte & !mask };
115 self.write_byte(byte, byte_pos)?;
116 self.bit_pos += 1;
117 Ok(())
118 }
119
120 pub(super) fn write_differential_bit(&mut self, bit: bool) -> Result<(), Error> {
124 let byte_pos = self.bit_pos >> 3;
125 let mut byte = self.get_byte(byte_pos)?;
126 if bit {
127 byte ^= 0xff << (self.bit_pos & 0x7);
128 }
129 self.write_byte(byte, byte_pos)?;
130 self.bit_pos += 1;
131 Ok(())
132 }
133
134 pub(super) fn write_bits<T>(&mut self, bits: T, bit_count: u8) -> Result<(), Error>
141 where
142 T: Copy
143 + ops::Shl<usize, Output = T>
144 + ops::Shr<usize, Output = T>
145 + ops::BitOrAssign<T>
146 + TruncateNum,
147 {
148 let Some(bit_count) = NonZeroUsize::new(bit_count.into()) else {
149 return Ok(());
150 };
151
152 let bit_pos = self.bit_pos & 0x07;
153 let mut byte_pos = self.bit_pos >> 3;
154
155 let mut byte = self.get_byte(byte_pos)?;
156 byte &= (1 << bit_pos) - 1;
157 byte |= bits.lsb() << bit_pos;
158
159 let mut bits_written = 8 - bit_pos;
160 while bits_written < bit_count.get() {
161 self.write_byte(byte, byte_pos)?;
162 byte_pos += 1;
163 byte = (bits >> bits_written).lsb();
164 bits_written += 8;
165 }
166
167 if let Some(upper) = NonZeroUsize::new(bits_written - bit_count.get()) {
168 let mask = !(0xff >> upper.get());
169 if (bits >> (bit_count.get() - 1)).lsb() & 1 != 0 {
170 byte |= mask;
171 } else {
172 byte &= !mask;
173 }
174 }
175
176 self.write_byte(byte, byte_pos)?;
177 self.bit_pos += bit_count.get();
178 Ok(())
179 }
180
181 fn get_byte(&mut self, byte_pos: usize) -> Result<u8, Error> {
186 if byte_pos < self.bytes_committed {
187 return self
188 .data
189 .get(byte_pos)
190 .copied()
191 .ok_or(Error::BufferTooSmall);
192 }
193
194 let last_committed = self.bytes_committed.saturating_sub(1);
195 let last_committed = self.data.get(last_committed).ok_or(Error::BufferTooSmall)?;
196 if last_committed & 0x80 != 0 {
197 Ok(0xff)
198 } else {
199 Ok(0x00)
200 }
201 }
202
203 fn write_byte(&mut self, byte: u8, byte_pos: usize) -> Result<(), Error> {
207 let data: &mut [u8] = self.data;
208 let split = data
209 .split_at_mut_checked(byte_pos)
210 .map(|(d, t)| (d, t.first_mut()));
211 let (data, target) = if let Some(split) = split {
212 split
213 } else {
214 (data, None)
215 };
216
217 if let Some((extend, fill)) = data
218 .split_at_mut_checked(self.bytes_committed)
219 .and_then(|(c, f)| c.last().map(|e| (e & 0x80 != 0, f)))
220 {
221 if self.compress && matches!((byte, extend), (0x00, false) | (0xff, true)) {
222 return Ok(());
223 }
224 fill.fill(if extend { 0xff } else { 0x00 });
225 }
226
227 *target.ok_or(Error::BufferTooSmall)? = byte;
228 self.bytes_committed = byte_pos + 1;
229 Ok(())
230 }
231}
232
233pub trait Encode<'d, U>: Sized {
237 fn encode(&self, encoder: &mut Encoder<'d, U>) -> Result<(), Error>;
239}
240
241#[cfg(feature = "either")]
242impl<'d, L: Encode<'d, U>, R: Encode<'d, U>, U> Encode<'d, U> for either::Either<L, R> {
243 fn encode(&self, encoder: &mut Encoder<'d, U>) -> Result<(), Error> {
244 either::for_both!(self, e => e.encode(encoder))
245 }
246}