/************************************************/ /* */ /* File : rockmfifo_private.c */ /* Description : ROCKM FIFO specific library */ /* private part */ /* */ /* Author: Sfiligoi Igor */ /* */ /* Created : 16.06.1997 */ /* Last modified: 01.07.1997 */ /* */ /************************************************/ #include <stdlib.h> #include <Error.h> #include <bits.h> #include "RockM_field_access.h" #include "rockmfifo_private.h" /* return the number of elements held in the cache */ unsigned int rockm_fifo_cache_get_nrels(ROCKM_FIFO_id fifo_id) { if (fifo_id->head==fifo_id->tail) return 0; /* empty */ else if (fifo_id->head<fifo_id->tail) return fifo_id->tail-fifo_id->head; else return ROCKM_FIFO_CACHE_SIZE+fifo_id->tail-fifo_id->head; } int rockm_fifo_cache_read(ROCKM_FIFO_id fifo_id, /* IN : fifo id */ unsigned int nrels, /* IN : nr. of elements to read */ unsigned int *data) /* OUT: data from the cache, must be allocated by caller */ { int csize; int i; csize = rockm_fifo_cache_get_nrels(fifo_id); if (csize<nrels) return ROCKM_ERROR_FIFO_EMPTY; for (i=0; i<nrels; i++) { data[i] = fifo_id->cache[fifo_id->head]; fifo_id->head++; if (fifo_id->head>=ROCKM_FIFO_CACHE_SIZE) fifo_id->head=0; /* wrap */ } return ROCKM_ERROR_OK; } int rockm_fifo_cache_return(ROCKM_FIFO_id fifo_id, /* IN : fifo_id */ unsigned int *data, /* IN : data to be returned to the cache */ unsigned int nrels) /* IN : nr. of elements of data to return */ { int i; for (i=nrels; i>0; i--) { if (fifo_id->head>0) fifo_id->head--; else fifo_id->head = ROCKM_FIFO_CACHE_SIZE-1; if (fifo_id->head==fifo_id->tail) { /* ERROR, cache overflow */ ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_cache_return","Cache overflow."); return ROCKM_ERROR_UNKNOWN; } fifo_id->cache[fifo_id->head] = data[i-1]; } return ROCKM_ERROR_OK; } /* this routine needs the data to be at the fisical start of the cache */ /* no range checking is done */ /* read the data field by field */ int rockm_fifo_fillcache_singular(ROCKM_FIFO_id fifo_id, /* IN : fifo id */ unsigned int nrels) /* IN : nr of elements to read, ignore actual size */ { unsigned int i; RockM_reg_declaration; for (i=0; (RockM_read_d_e(fifo_id->rockm_id))&&(i<nrels); i++) { FIFO = RockM_read_fifo(fifo_id->rockm_id); if (NVD==0) break; /* exit as if an Empty Fifo was found */ else { fifo_id->cache[fifo_id->tail++] = DATA; } } if (i<nrels) return ROCKM_ERROR_FIFO_EMPTY; else return ROCKM_ERROR_OK; } int rockm_fifo_fillcache(ROCKM_FIFO_id fifo_id, /* IN : fifo id */ unsigned int nrels) /* IN : fill the cache at least with the nr elements */ /* if more than ROCKM_FIFO_FIFO_SIZE, truncated to ROCKM_FIFO_FIFO_SIZE */ { int csize; unsigned int minread; unsigned int maxread; /* max elements that can be read */ int err; if (nrels>ROCKM_FIFO_FIFO_SIZE) nrels=ROCKM_FIFO_FIFO_SIZE; csize = rockm_fifo_cache_get_nrels(fifo_id); if (csize>=nrels) return ROCKM_ERROR_OK; /* nothing to do */ if (csize>0) { /* put the data at fisical start of the cache */ unsigned int *buffer; buffer = (unsigned int *) malloc(csize*sizeof(unsigned int)); rockm_fifo_cache_read(fifo_id,csize,buffer); memcpy(fifo_id->cache,buffer,csize*sizeof(unsigned int)); fifo_id->head = 0; fifo_id->tail = csize; free(buffer); } else { /* this simplifies the cache */ fifo_id->head=0; fifo_id->tail=0; } /* now all the data is at the fisical start of the cache */ /* read only the missing elements */ minread = nrels - csize; maxread = ROCKM_FIFO_FIFO_SIZE - csize; err = rockm_fifo_fillcache_singular(fifo_id,minread); if ((err!=ROCKM_ERROR_OK)&&(err!=ROCKM_ERROR_FIFO_EMPTY)) { /* serious error */ ErrorSetF(err,"rockm_fifo_fillcache","Error found: %s",ErrorGetMessage()); return err; } /* no error */ /* reget csize */ csize = rockm_fifo_cache_get_nrels(fifo_id); if (csize<nrels) return ROCKM_ERROR_FIFO_EMPTY; /* the fillcache has not obtained enough elements */ else return ROCKM_ERROR_OK; }