Skip to main content

oxilean_std/repr/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use super::functions::*;
6use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
7
8/// A memory layout descriptor for a Rust/C type.
9///
10/// Tracks size, alignment, and stride (size rounded up to alignment).
11#[allow(dead_code)]
12pub struct MemoryLayout {
13    /// Name of the type.
14    pub type_name: String,
15    /// Size of the type in bytes.
16    pub size: usize,
17    /// Alignment of the type in bytes.
18    pub align: usize,
19}
20#[allow(dead_code)]
21impl MemoryLayout {
22    /// Create a new `MemoryLayout`.
23    pub fn new(type_name: impl Into<String>, size: usize, align: usize) -> Self {
24        Self {
25            type_name: type_name.into(),
26            size,
27            align,
28        }
29    }
30    /// The stride: size rounded up to the alignment boundary.
31    pub fn stride(&self) -> usize {
32        (self.size + self.align - 1) & !(self.align - 1)
33    }
34    /// Check whether this layout is valid (align is a power of two, size ≤ stride).
35    pub fn is_valid(&self) -> bool {
36        self.align > 0 && self.align.is_power_of_two() && self.size <= self.stride()
37    }
38    /// Compute the offset needed to align `offset` to this type's alignment.
39    pub fn align_offset(&self, offset: usize) -> usize {
40        let mask = self.align - 1;
41        (offset + mask) & !mask
42    }
43    /// Return a description of this layout.
44    pub fn describe(&self) -> String {
45        format!(
46            "{}: size={}, align={}, stride={}",
47            self.type_name,
48            self.size,
49            self.align,
50            self.stride()
51        )
52    }
53}
54/// A C-ABI struct layout: a list of fields with names, sizes, and alignments.
55#[allow(dead_code)]
56pub struct CStructLayout {
57    /// Name of the struct.
58    pub name: String,
59    /// Fields: (name, size, alignment).
60    pub fields: Vec<(String, usize, usize)>,
61}
62#[allow(dead_code)]
63impl CStructLayout {
64    /// Create a new (empty) `CStructLayout`.
65    pub fn new(name: impl Into<String>) -> Self {
66        Self {
67            name: name.into(),
68            fields: Vec::new(),
69        }
70    }
71    /// Add a field with the given name, size, and alignment.
72    pub fn add_field(mut self, name: impl Into<String>, size: usize, align: usize) -> Self {
73        self.fields.push((name.into(), size, align));
74        self
75    }
76    /// Compute the byte offset of the n-th field following C ABI rules.
77    pub fn field_offset(&self, idx: usize) -> usize {
78        let mut offset = 0usize;
79        for (i, (_, size, align)) in self.fields.iter().enumerate() {
80            let mask = align - 1;
81            offset = (offset + mask) & !mask;
82            if i == idx {
83                return offset;
84            }
85            offset += size;
86        }
87        offset
88    }
89    /// Total size of the struct including trailing padding.
90    pub fn total_size(&self) -> usize {
91        if self.fields.is_empty() {
92            return 0;
93        }
94        let max_align = self.fields.iter().map(|(_, _, a)| *a).max().unwrap_or(1);
95        let mut offset = 0usize;
96        for (_, size, align) in &self.fields {
97            let mask = align - 1;
98            offset = (offset + mask) & !mask;
99            offset += size;
100        }
101        let mask = max_align - 1;
102        (offset + mask) & !mask
103    }
104    /// Describe this struct layout.
105    pub fn describe(&self) -> String {
106        let offsets: Vec<String> = (0..self.fields.len())
107            .map(|i| {
108                format!(
109                    "  [{}] {} @ offset {}",
110                    i,
111                    self.fields[i].0,
112                    self.field_offset(i)
113                )
114            })
115            .collect();
116        format!(
117            "struct {} {{\n{}\n}} size={}",
118            self.name,
119            offsets.join("\n"),
120            self.total_size()
121        )
122    }
123}
124/// A pointer representation descriptor (tagged, fat, raw, vtable).
125#[allow(dead_code)]
126pub enum PointerKind {
127    /// A simple raw pointer.
128    Raw,
129    /// A fat pointer: (data, metadata).
130    Fat { metadata_size: usize },
131    /// A tagged pointer: low bits encode a tag.
132    Tagged { tag_bits: u32 },
133    /// A vtable pointer for a trait object.
134    VTable { num_methods: usize },
135}
136/// Represents a pointer with its kind and target address width.
137#[allow(dead_code)]
138pub struct PointerRepr {
139    /// Kind of this pointer.
140    pub kind: PointerKind,
141    /// Address size in bytes (e.g. 8 on 64-bit).
142    pub addr_bytes: usize,
143}
144#[allow(dead_code)]
145impl PointerRepr {
146    /// Create a raw pointer for a 64-bit target.
147    pub fn raw64() -> Self {
148        Self {
149            kind: PointerKind::Raw,
150            addr_bytes: 8,
151        }
152    }
153    /// Create a fat pointer for a 64-bit target.
154    pub fn fat64(metadata_size: usize) -> Self {
155        Self {
156            kind: PointerKind::Fat { metadata_size },
157            addr_bytes: 8,
158        }
159    }
160    /// Create a tagged pointer with `tag_bits` low-order tag bits.
161    pub fn tagged(tag_bits: u32) -> Self {
162        Self {
163            kind: PointerKind::Tagged { tag_bits },
164            addr_bytes: 8,
165        }
166    }
167    /// Total size in bytes of this pointer representation.
168    pub fn total_size(&self) -> usize {
169        match &self.kind {
170            PointerKind::Raw => self.addr_bytes,
171            PointerKind::Fat { metadata_size } => self.addr_bytes + metadata_size,
172            PointerKind::Tagged { .. } => self.addr_bytes,
173            PointerKind::VTable { .. } => self.addr_bytes * 2,
174        }
175    }
176    /// Describe this pointer representation.
177    pub fn describe(&self) -> String {
178        match &self.kind {
179            PointerKind::Raw => format!("*raw ({} bytes)", self.addr_bytes),
180            PointerKind::Fat { metadata_size } => {
181                format!(
182                    "*fat (addr={} meta={} total={})",
183                    self.addr_bytes,
184                    metadata_size,
185                    self.total_size()
186                )
187            }
188            PointerKind::Tagged { tag_bits } => {
189                format!("*tagged ({} tag bits, {} bytes)", tag_bits, self.addr_bytes)
190            }
191            PointerKind::VTable { num_methods } => {
192                format!(
193                    "*dyn ({} methods, {} bytes)",
194                    num_methods,
195                    self.total_size()
196                )
197            }
198        }
199    }
200}
201/// Describes an IEEE 754 floating-point format.
202#[allow(dead_code)]
203pub struct Ieee754Descriptor {
204    /// Name of the format (e.g. "binary32", "binary64").
205    pub name: String,
206    /// Total width in bits.
207    pub total_bits: u32,
208    /// Number of exponent bits.
209    pub exponent_bits: u32,
210    /// Number of mantissa (significand) bits (not counting implicit leading 1).
211    pub mantissa_bits: u32,
212}
213#[allow(dead_code)]
214impl Ieee754Descriptor {
215    /// Create a new `Ieee754Descriptor`.
216    pub fn new(name: impl Into<String>, total: u32, exp: u32, mant: u32) -> Self {
217        Self {
218            name: name.into(),
219            total_bits: total,
220            exponent_bits: exp,
221            mantissa_bits: mant,
222        }
223    }
224    /// IEEE 754 binary32 (single precision).
225    pub fn binary32() -> Self {
226        Self::new("binary32", 32, 8, 23)
227    }
228    /// IEEE 754 binary64 (double precision).
229    pub fn binary64() -> Self {
230        Self::new("binary64", 64, 11, 52)
231    }
232    /// The exponent bias: `2^(exponent_bits - 1) - 1`.
233    pub fn exponent_bias(&self) -> u32 {
234        (1u32 << (self.exponent_bits - 1)) - 1
235    }
236    /// The maximum representable finite exponent.
237    pub fn max_exponent(&self) -> i32 {
238        self.exponent_bias() as i32
239    }
240    /// Check whether the format is valid (bits add up).
241    pub fn is_valid(&self) -> bool {
242        self.total_bits == 1 + self.exponent_bits + self.mantissa_bits
243    }
244    /// Describe this format.
245    pub fn describe(&self) -> String {
246        format!(
247            "{}: total={} sign=1 exp={} mant={} bias={}",
248            self.name,
249            self.total_bits,
250            self.exponent_bits,
251            self.mantissa_bits,
252            self.exponent_bias()
253        )
254    }
255}
256/// A descriptor for a bit-field: its name, offset and width within a word.
257#[allow(dead_code)]
258pub struct BitfieldDescriptor {
259    /// Name of the bit-field.
260    pub name: String,
261    /// Bit offset within the containing word.
262    pub offset: u32,
263    /// Width in bits.
264    pub width: u32,
265}
266#[allow(dead_code)]
267impl BitfieldDescriptor {
268    /// Create a new `BitfieldDescriptor`.
269    pub fn new(name: impl Into<String>, offset: u32, width: u32) -> Self {
270        Self {
271            name: name.into(),
272            offset,
273            width,
274        }
275    }
276    /// The bitmask for this field (within a 64-bit word).
277    pub fn mask(&self) -> u64 {
278        let raw = if self.width >= 64 {
279            !0u64
280        } else {
281            (1u64 << self.width) - 1
282        };
283        raw << self.offset
284    }
285    /// Extract this field's value from a word.
286    pub fn extract(&self, word: u64) -> u64 {
287        (word & self.mask()) >> self.offset
288    }
289    /// Insert `value` into `word` for this field.
290    pub fn insert(&self, word: u64, value: u64) -> u64 {
291        let m = self.mask();
292        (word & !m) | ((value << self.offset) & m)
293    }
294    /// Check that this field fits within a word of `word_bits` bits.
295    pub fn fits_in(&self, word_bits: u32) -> bool {
296        self.offset + self.width <= word_bits
297    }
298}
299/// The concrete state of a CPU register file (for simulation).
300#[allow(dead_code)]
301pub struct RegisterFileState {
302    /// Register values indexed by register number.
303    pub regs: Vec<u64>,
304}
305#[allow(dead_code)]
306impl RegisterFileState {
307    /// Create a zeroed register file with `count` registers.
308    pub fn new(count: usize) -> Self {
309        Self {
310            regs: vec![0u64; count],
311        }
312    }
313    /// Read the value of register `r`.
314    pub fn read(&self, r: usize) -> Option<u64> {
315        self.regs.get(r).copied()
316    }
317    /// Write `value` to register `r`.
318    pub fn write(&mut self, r: usize, value: u64) {
319        if r < self.regs.len() {
320            self.regs[r] = value;
321        }
322    }
323    /// Verify the read-after-write property for a register.
324    pub fn verify_raw(&mut self, r: usize, v: u64) -> bool {
325        self.write(r, v);
326        self.read(r) == Some(v)
327    }
328    /// Number of registers.
329    pub fn count(&self) -> usize {
330        self.regs.len()
331    }
332    /// Describe the register file state.
333    pub fn describe(&self) -> String {
334        let parts: Vec<String> = self
335            .regs
336            .iter()
337            .enumerate()
338            .map(|(i, v)| format!("r{}=0x{:x}", i, v))
339            .collect();
340        format!("[{}]", parts.join(", "))
341    }
342}