- Fixes to hkl code

- Fixes to make RITA work
- tasub extended to calculate UB from cell alone, support for elastic mode
- New MultiCounter as abstraction for counting on HM's
- regression test driver for counters
This commit is contained in:
koennecke
2006-09-13 07:12:00 +00:00
parent 87d81cf474
commit cb3bf30bbf
33 changed files with 1961 additions and 671 deletions

380
multicounter.c Normal file
View File

@ -0,0 +1,380 @@
/**
* The MultiCounter is another counter which coordinates multiple
* counting objects, counters and histogram memories. It also calls a
* script function after TransferData which collects counters and monitors.
* The purpose is to have a flexible counter abstraction for upper level
* code such as maximizers and scan functions. The script can deal with
* counting on monitors or on sums of histogram memories.
*
* This is a bit unclean. The counter driver is of no use, therefore its
* private data structure is used to hold the other counters and the name
* of the script. It would have been better to inherit from counter but
* that would have required lost of type casts. I am to lazy for this.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, September 2006
*/
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <tcl.h>
#include "multicounter.h"
#include "counter.h"
#include "HistMem.h"
#include "macro.h"
#include "splitter.h"
#define MAXSLAVE 16
/*=============== code for the driver ======================================*/
typedef struct {
void *slaveData[MAXSLAVE];
pICountable slaves[MAXSLAVE];
char *transferScript;
int nSlaves;
}MultiCounter, *pMultiCounter;
/*--------------------------------------------------------------------------*/
static void KillMultiDriver(struct __COUNTER *data){
pMultiCounter self = (pMultiCounter)data->pData;
if(self == NULL){
return;
}
if(self->transferScript != NULL){
free(self->transferScript);
}
free(self);
}
/*============== countable interface functions ============================*/
static int MMCCHalt(void *pData){
int i, retVal = OKOK, status;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
status = self->slaves[i]->Halt(self->slaveData[i]);
if(status != OKOK)
retVal = status;
}
return retVal;
}
/*-------------------------------------------------------------------------*/
static int MMCCStart(void *pData, SConnection *pCon)
{
int i, status;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
self->slaves[i]->SetCountParameters(self->slaveData[i],
pCount->pDriv->fPreset, pCount->pDriv->eMode);
status = self->slaves[i]->StartCount(self->slaveData[i],pCon);
if(status != OKOK){
MMCCHalt(pData);
return status;
}
}
pCount->isUpToDate = 0;
pCount->tStart = time(NULL);
InvokeCallBack(pCount->pCall,COUNTSTART,pCon);
return OKOK;
}
/*-------------------------------------------------------------------------*/
static int MMCCStatus(void *pData, SConnection *pCon){
int status,i;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pDummy pDum = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
status = self->slaves[0]->CheckCountStatus(self->slaveData[0],pCon);
if(status == HWIdle || status == HWFault){
/*
stop counting on slaves when finished or when an error
occurred.
*/
InvokeCallBack(pCount->pCall,COUNTEND,pCon);
MMCCHalt(pCount);
}
for(i = 1; i < MAXSLAVE; i++){
if(self->slaves[i] != NULL){
pDum = (pDummy)self->slaveData[i];
if(strcmp(pDum->pDescriptor->name,"HistMem") == 0){
HistDirty((pHistMem)self->slaveData[i]);
}
}
}
return status;
}
/*-------------------------------------------------------------------------*/
static int MMCCPause(void *pData, SConnection *pCon){
int i, status;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
status = self->slaves[i]->Pause(self->slaveData[i],pCon);
if(status != OKOK){
MMCCHalt(pCount);
return status;
}
}
return OKOK;
}
/*--------------------------------------------------------------------------*/
static int MMCCContinue(void *pData, SConnection *pCon){
int i, status;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
status = self->slaves[i]->Continue(self->slaveData[i],pCon);
if(status != OKOK){
MMCCHalt(pCount);
return status;
}
}
return OKOK;
}
/*------------------------------------------------------------------------*/
static char *getNextMMCCNumber(char *pStart, char pNumber[80]){
int charCount = 0;
pNumber[0] = '\0';
/* advance to first digit */
while(isspace(*pStart) && *pStart != '\0'){
pStart++;
}
if(*pStart == '\0'){
return NULL;
}
/* copy */
while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){
pNumber[charCount] = *pStart;
pStart++;
charCount++;
}
pNumber[charCount] = '\0';
return pStart;
}
/*-------------------------------------------------------------------------*/
static void loadCountData(pCounter pCount, const char *data){
char *pPtr = NULL;
char pNumber[80];
int i = 0;
pPtr = (char *)data;
pPtr = getNextMMCCNumber(pPtr,pNumber);
pCount->pDriv->fTime = atof(pNumber);
while(pPtr != NULL && i < MAXCOUNT){
pPtr = getNextMMCCNumber(pPtr,pNumber);
pCount->pDriv->lCounts[i] = atoi(pNumber);
i++;
}
}
/*--------------------------------------------------------------------------*/
static int MMCCTransfer(void *pData, SConnection *pCon){
int i, retVal = OKOK, status;
char pBueffel[132];
pCounter pCount = NULL;
pMultiCounter self = NULL;
int tclStatus;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
status = self->slaves[i]->TransferData(self->slaveData[i], pCon);
if(status != OKOK){
retVal = status;
sprintf(pBueffel,"WARNING: slave histogram %d failed to transfer data",
i);
SCWrite(pCon,pBueffel,eWarning);
}
}
if(self->transferScript != NULL){
MacroPush(pCon);
tclStatus = Tcl_Eval(InterpGetTcl(pServ->pSics), self->transferScript);
if(tclStatus != TCL_OK){
snprintf(pBueffel,131,"ERROR: TransferScript returned: %s",
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
SCWrite(pCon,pBueffel,eError);
MacroPop();
return HWFault;
}
MacroPop();
loadCountData(pCount,Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
}
return retVal;
}
/*-------------------------------------------------------------------------*/
static void MMCCParameter(void *pData, float fPreset, CounterMode eMode ){
int i;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
self->slaves[i]->SetCountParameters(self->slaveData[i], fPreset,
eMode);
}
}
/*=============== Interpreter Interface ================================ */
int MultiCounterAction(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]){
pMultiCounter self = NULL;
pCounter pCount = NULL;
char buffer[256];
if(argc > 1){
strtolower(argv[1]);
if(strcmp(argv[1],"transferscript") == 0){
pCount = (pCounter)pData;
self = (pMultiCounter)pCount->pDriv->pData;
if(argc < 3){
SCPrintf(pCon,eValue,"%s.transferscript = %s",
argv[0],self->transferScript);
return 1;
} else {
if(!SCMatchRights(pCon,usUser)){
return 0;
}
if(self->transferScript != NULL){
free(self->transferScript);
}
Arg2Text(argc-2,&argv[2],buffer,255);
self->transferScript = strdup(buffer);
SCSendOK(pCon);
return 1;
}
}
}
return CountAction(pCon,pSics,pData,argc,argv);
}
/*------------------------------------------------------------------------*/
int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]){
int i, status;
pCounter pNew = NULL;
char pBueffel[132];
CommandList *pCom;
pICountable pCount;
pMultiCounter self = NULL;
pCounterDriver pDriv = NULL;
/*
need at least two parameters
*/
if(argc < 3){
SCWrite(pCon,"ERROR: insufficient number of arguments to MakeMultiCounter",
eError);
return 0;
}
/*
allocate our data structure
*/
self = malloc(sizeof(MultiCounter));
pDriv = malloc(sizeof(CounterDriver));
if(self == NULL || pDriv == NULL){
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounter",eError);
return 0;
}
memset(self,0,sizeof(MultiCounter));
memset(pDriv,0,sizeof(CounterDriver));
pDriv->pData = self;
pDriv->KillPrivate = KillMultiDriver;
pDriv->iNoOfMonitors = MAXCOUNT;
pNew = CreateCounter(argv[1],pDriv);
if(pNew == NULL){
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounter",eError);
return 0;
}
/*
assign interface functions
*/
pNew->pCountInt->Halt = MMCCHalt;
pNew->pCountInt->StartCount = MMCCStart;
pNew->pCountInt->CheckCountStatus = MMCCStatus;
pNew->pCountInt->Pause = MMCCPause;
pNew->pCountInt->Continue = MMCCContinue;
pNew->pCountInt->TransferData = MMCCTransfer;
pNew->pCountInt->SetCountParameters = MMCCParameter;
/*
now loop through the remaining arguments, thereby entering them into
the slave list.
*/
for(i = 2; i < argc; i++){
pCom = FindCommand(pSics,argv[i]);
if(!pCom){
sprintf(pBueffel,"ERROR: object %s not found in MakeMultiCounter",
argv[i]);
SCWrite(pCon,pBueffel,eError);
continue;
}
pCount = GetCountableInterface(pCom->pData);
if(!pCount){
sprintf(pBueffel,"ERROR: object %s is NOT countable",
argv[i]);
SCWrite(pCon,pBueffel,eError);
continue;
}
self->slaves[self->nSlaves] = pCount;
self->slaveData[self->nSlaves] = pCom->pData;
self->nSlaves++;
}
/*
now install our action command and we are done
*/
status = AddCommand(pSics,argv[1],MultiCounterAction,DeleteCounter,
pNew);
if(!status){
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
SCWrite(pCon,pBueffel,eError);
DeleteCounter(pNew);
return 0;
}
return 1;
}