1- use std:: borrow:: Borrow ;
1+ use std:: {
2+ borrow:: Borrow ,
3+ sync:: { Arc , Mutex } ,
4+ } ;
25
36use openvm_circuit:: {
47 arch:: {
@@ -23,15 +26,16 @@ use struct_reflection::{StructReflection, StructReflectionHelper};
2326
2427use crate :: {
2528 FrameBridge , FrameBus , FrameState , VmAdapterChipWom , WomBridge , WomController , WomRecord ,
26- adapters:: { compose, decompose} ,
29+ adapters:: { compose, decompose, frame_allocator :: FrameAllocator } ,
2730} ;
2831
2932use super :: RV32_REGISTER_NUM_LIMBS ;
3033
3134#[ derive( Debug ) ]
3235pub struct AllocateFrameAdapterChipWom {
3336 pub air : AllocateFrameAdapterAirWom ,
34- next_fp : u32 ,
37+ frame_stack : Arc < Mutex < Vec < u32 > > > ,
38+ frame_allocator : Arc < Mutex < FrameAllocator > > ,
3539}
3640
3741impl AllocateFrameAdapterChipWom {
@@ -41,6 +45,8 @@ impl AllocateFrameAdapterChipWom {
4145 frame_bus : FrameBus ,
4246 memory_bridge : MemoryBridge ,
4347 wom_bridge : WomBridge ,
48+ frame_allocator : Arc < Mutex < FrameAllocator > > ,
49+ frame_stack : Arc < Mutex < Vec < u32 > > > ,
4450 ) -> Self {
4551 Self {
4652 air : AllocateFrameAdapterAirWom {
@@ -49,8 +55,8 @@ impl AllocateFrameAdapterChipWom {
4955 frame_bridge : FrameBridge :: new ( frame_bus) ,
5056 _memory_bridge : memory_bridge,
5157 } ,
52- // Start from 8 because 0 and 4 are used by the startup code.
53- next_fp : 8 ,
58+ frame_allocator ,
59+ frame_stack ,
5460 }
5561 }
5662}
@@ -214,9 +220,18 @@ impl<F: PrimeField32> VmAdapterChipWom<F> for AllocateFrameAdapterChipWom {
214220 } ;
215221 let amount_bytes = RV32_REGISTER_NUM_LIMBS as u32 * amount;
216222
217- let allocated_ptr = self . next_fp ;
218-
219- self . next_fp += amount_bytes;
223+ let allocated_ptr = self
224+ . frame_allocator
225+ . lock ( )
226+ . unwrap ( )
227+ . allocate ( amount_bytes)
228+ . expect ( "WOM frame allocation failed: not enough free contiguous space" ) ;
229+
230+ {
231+ let mut frame_stack = self . frame_stack . lock ( ) . unwrap ( ) ;
232+ frame_stack. push ( allocated_ptr) ;
233+ //println!("A STACK: {frame_stack:?}");
234+ }
220235
221236 let amount_bytes = decompose ( amount_bytes) ;
222237
@@ -280,3 +295,90 @@ impl<F: PrimeField32> VmAdapterChipWom<F> for AllocateFrameAdapterChipWom {
280295 & self . air
281296 }
282297}
298+
299+ pub mod frame_allocator {
300+ use std:: collections:: { BTreeMap , btree_map:: Entry } ;
301+
302+ use serde:: { Deserialize , Serialize } ;
303+
304+ #[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord , Serialize , Deserialize ) ]
305+ pub struct Range {
306+ pub start : u32 ,
307+ pub end : u32 ,
308+ }
309+
310+ #[ derive( Debug , Serialize , Deserialize ) ]
311+ pub struct FrameAllocator {
312+ /// The set of free frame ranges, indexed by its length.
313+ free_ranges : BTreeMap < u32 , Vec < Range > > ,
314+ /// The set of allocated frame ranges. Maps start address to end address.
315+ allocated_ranges : BTreeMap < u32 , u32 > ,
316+ }
317+
318+ impl FrameAllocator {
319+ pub fn new ( largest_address : u32 , existing_allocations : BTreeMap < u32 , u32 > ) -> Self {
320+ // Initialize free_ranges based on existing_allocations
321+ let mut free_ranges: BTreeMap < u32 , Vec < Range > > = BTreeMap :: new ( ) ;
322+ let mut current_start = 0 ;
323+
324+ for ( start, end) in & existing_allocations {
325+ if current_start < * start {
326+ let range = Range {
327+ start : current_start,
328+ end : * start,
329+ } ;
330+ let length = range. end - range. start ;
331+ free_ranges. entry ( length) . or_default ( ) . push ( range) ;
332+ }
333+ current_start = * end;
334+ }
335+
336+ if current_start < largest_address {
337+ let range = Range {
338+ start : current_start,
339+ end : largest_address,
340+ } ;
341+ let length = range. end - range. start ;
342+ free_ranges. entry ( length) . or_default ( ) . push ( range) ;
343+ }
344+
345+ Self {
346+ free_ranges,
347+ allocated_ranges : existing_allocations,
348+ }
349+ }
350+
351+ pub fn allocate ( & mut self , size : u32 ) -> Option < u32 > {
352+ // Find a free range that can accommodate the requested size
353+ let fittest_len = * self . free_ranges . range_mut ( size..) . next ( ) ?. 0 ;
354+
355+ // Apparently there is no way find this entry without searching again...
356+ // TODO: change this when https://github.com/rust-lang/rust/issues/107540
357+ // is stabilized.
358+ let Entry :: Occupied ( mut entry) = self . free_ranges . entry ( fittest_len) else {
359+ unreachable ! ( ) ;
360+ } ;
361+ let mut range = entry. get_mut ( ) . pop ( ) . unwrap ( ) ;
362+ if entry. get ( ) . is_empty ( ) {
363+ entry. remove ( ) ;
364+ }
365+
366+ let allocated_start = range. start ;
367+ range. start += size;
368+
369+ if range. start < range. end {
370+ let length = range. end - range. start ;
371+ self . free_ranges . entry ( length) . or_default ( ) . push ( range) ;
372+ }
373+
374+ self . allocated_ranges
375+ . insert ( allocated_start, allocated_start + size) ;
376+
377+ Some ( allocated_start)
378+ }
379+
380+ pub fn get_allocated_ranges ( & self ) -> & BTreeMap < u32 , u32 > {
381+ & self . allocated_ranges
382+ }
383+ }
384+ }
0 commit comments