mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			131 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*****************************************************************************************[Alloc.h]
 | |
| Copyright (c) 2008-2010, Niklas Sorensson
 | |
| 
 | |
| Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 | |
| associated documentation files (the "Software"), to deal in the Software without restriction,
 | |
| including without limitation the rights to use, copy, modify, merge, publish, distribute,
 | |
| sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 | |
| furnished to do so, subject to the following conditions:
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included in all copies or
 | |
| substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 | |
| NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | |
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 | |
| DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
 | |
| OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
| **************************************************************************************************/
 | |
| 
 | |
| 
 | |
| #ifndef Minisat_Alloc_h
 | |
| #define Minisat_Alloc_h
 | |
| 
 | |
| #include "XAlloc.h"
 | |
| #include "Vec.h"
 | |
| 
 | |
| namespace Minisat {
 | |
| 
 | |
| //=================================================================================================
 | |
| // Simple Region-based memory allocator:
 | |
| 
 | |
| template<class T>
 | |
| class RegionAllocator
 | |
| {
 | |
|     T*        memory;
 | |
|     uint32_t  sz;
 | |
|     uint32_t  cap;
 | |
|     uint32_t  wasted_;
 | |
| 
 | |
|     void capacity(uint32_t min_cap);
 | |
| 
 | |
|  public:
 | |
|     // TODO: make this a class for better type-checking?
 | |
|     typedef uint32_t Ref;
 | |
|     enum { Ref_Undef = UINT32_MAX };
 | |
|     enum { Unit_Size = sizeof(T) };
 | |
| 
 | |
|     explicit RegionAllocator(uint32_t start_cap = 1024*1024) : memory(NULL), sz(0), cap(0), wasted_(0){ capacity(start_cap); }
 | |
|     ~RegionAllocator()
 | |
|     {
 | |
|         if (memory != NULL)
 | |
|             ::free(memory);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     uint32_t size      () const      { return sz; }
 | |
|     uint32_t wasted    () const      { return wasted_; }
 | |
| 
 | |
|     Ref      alloc     (int size); 
 | |
|     void     free      (int size)    { wasted_ += size; }
 | |
| 
 | |
|     // Deref, Load Effective Address (LEA), Inverse of LEA (AEL):
 | |
|     T&       operator[](Ref r)       { assert(r < sz); return memory[r]; }
 | |
|     const T& operator[](Ref r) const { assert(r < sz); return memory[r]; }
 | |
| 
 | |
|     T*       lea       (Ref r)       { assert(r < sz); return &memory[r]; }
 | |
|     const T* lea       (Ref r) const { assert(r < sz); return &memory[r]; }
 | |
|     Ref      ael       (const T* t)  { assert((void*)t >= (void*)&memory[0] && (void*)t < (void*)&memory[sz-1]);
 | |
|         return  (Ref)(t - &memory[0]); }
 | |
| 
 | |
|     void     moveTo(RegionAllocator& to) {
 | |
|         if (to.memory != NULL) ::free(to.memory);
 | |
|         to.memory = memory;
 | |
|         to.sz = sz;
 | |
|         to.cap = cap;
 | |
|         to.wasted_ = wasted_;
 | |
| 
 | |
|         memory = NULL;
 | |
|         sz = cap = wasted_ = 0;
 | |
|     }
 | |
| 
 | |
| 
 | |
| };
 | |
| 
 | |
| template<class T>
 | |
| void RegionAllocator<T>::capacity(uint32_t min_cap)
 | |
| {
 | |
|     if (cap >= min_cap) return;
 | |
| 
 | |
|     uint32_t prev_cap = cap;
 | |
|     while (cap < min_cap){
 | |
|         // NOTE: Multiply by a factor (13/8) without causing overflow, then add 2 and make the
 | |
|         // result even by clearing the least significant bit. The resulting sequence of capacities
 | |
|         // is carefully chosen to hit a maximum capacity that is close to the '2^32-1' limit when
 | |
|         // using 'uint32_t' as indices so that as much as possible of this space can be used.
 | |
|         uint32_t delta = ((cap >> 1) + (cap >> 3) + 2) & ~1;
 | |
|         cap += delta;
 | |
| 
 | |
|         if (cap <= prev_cap)
 | |
|             throw OutOfMemoryException();
 | |
|     }
 | |
|     // printf(" .. (%p) cap = %u\n", this, cap);
 | |
| 
 | |
|     assert(cap > 0);
 | |
|     memory = (T*)xrealloc(memory, sizeof(T)*cap);
 | |
| }
 | |
| 
 | |
| 
 | |
| template<class T>
 | |
| typename RegionAllocator<T>::Ref
 | |
| RegionAllocator<T>::alloc(int size)
 | |
| { 
 | |
|     // printf("ALLOC called (this = %p, size = %d)\n", this, size); fflush(stdout);
 | |
|     assert(size > 0);
 | |
|     capacity(sz + size);
 | |
| 
 | |
|     uint32_t prev_sz = sz;
 | |
|     sz += size;
 | |
|     
 | |
|     // Handle overflow:
 | |
|     if (sz < prev_sz)
 | |
|         throw OutOfMemoryException();
 | |
| 
 | |
|     return prev_sz;
 | |
| }
 | |
| 
 | |
| 
 | |
| //=================================================================================================
 | |
| }
 | |
| 
 | |
| #endif
 |