#ifndef COLIBRI_TIER_H #define COLIBRI_TIER_H #include /* Pick one RAM/VRAM hot-store slot to replace from recent routing heat. * The fixed margin handles tiny samples; the 25% margin prevents ping-pong. */ static int tier_pick_swap(const uint32_t *heat, int nexpert, const int *pinned, int npin, int *slot, int *eid, long *gain){ if(!heat || !pinned || npin<1 || nexpert<1) return 0; int cold=0; for(int z=1;zfh){ fh=heat[e]; hot=e; } } if(hot<0) return 0; uint32_t fc=heat[pinned[cold]]; if(fh<=fc+(fc>>2)+4) return 0; *slot=cold; *eid=hot; *gain=(long)fh-(long)fc; return 1; } /* LFRU: frequency is the primary signal; recency breaks close calls. A recent * access contributes at most 255 points while one frequency count is worth * 256, so a merely recent expert cannot displace a genuinely hotter one. */ static uint64_t tier_lfru_score(uint32_t heat, uint32_t last, uint32_t clock){ uint32_t age=clock-last, recent=age<255?255-age:0; return ((uint64_t)heat<<8)|recent; } static int tier_pick_lfru(const uint32_t *heat, const uint32_t *last, uint32_t clock, int nexpert, const int *pinned, int npin, int *slot, int *eid, long *gain){ if(!heat||!last||!pinned||npin<1||nexpert<1) return 0; int cold=0; for(int z=1;zhs)){ hot=e; hs=score; } } if(hot<0) return 0; uint64_t cs=tier_lfru_score(heat[pinned[cold]],last[pinned[cold]],clock); /* Retain the existing 25%+4-frequency hysteresis in score units. */ if(hs<=cs+(cs>>2)+(4u<<8)) return 0; *slot=cold; *eid=hot; *gain=(long)((hs-cs)>>8); return 1; } static void tier_decay(uint32_t *heat, int nexpert){ for(int e=0;e>=1; } #endif