Emulation of FPGA clusterfinder
authorsgorbuno <sgorbuno@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 20 May 2011 09:24:04 +0000 (09:24 +0000)
committersgorbuno <sgorbuno@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 20 May 2011 09:24:04 +0000 (09:24 +0000)
-- This line, and those below, will be ignored--

M    HLT/CMakelibAliHLTTPC.pkg
A    HLT/TPCLib/HWCFemulator
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFSupport.h
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFProcessorUnit.h
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFMergerUnit.h
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDivisionUnit.h
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFConsistencyControlComponent.h
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFExtractorUnit.cxx
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulatorComponent.cxx
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFSupport.cxx
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulator.h
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFProcessorUnit.cxx
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFMergerUnit.cxx
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDataTypes.h
A    HLT/TPCLib/HWCFemulator/macro
A    HLT/TPCLib/HWCFemulator/macro/hwcfCheck.C
A    HLT/TPCLib/HWCFemulator/macro/makeConfigurationObjectTPCHWClusterFinder.C
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDivisionUnit.cxx
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFConsistencyControlComponent.cxx
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulator.cxx
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFExtractorUnit.h
A    HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulatorComponent.h
M    HLT/TPCLib/AliHLTTPCAgent.cxx
A    OCDB/HLT/ConfigTPC/TPCHWClusterFinder

21 files changed:
HLT/CMakelibAliHLTTPC.pkg
HLT/TPCLib/AliHLTTPCAgent.cxx
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFConsistencyControlComponent.cxx [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFConsistencyControlComponent.h [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDataTypes.h [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDivisionUnit.cxx [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDivisionUnit.h [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulator.cxx [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulator.h [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulatorComponent.cxx [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulatorComponent.h [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFExtractorUnit.cxx [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFExtractorUnit.h [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFMergerUnit.cxx [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFMergerUnit.h [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFProcessorUnit.cxx [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFProcessorUnit.h [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFSupport.cxx [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFSupport.h [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/macro/hwcfCheck.C [new file with mode: 0644]
HLT/TPCLib/HWCFemulator/macro/makeConfigurationObjectTPCHWClusterFinder.C [new file with mode: 0644]

index d8e5d13..42f7792 100644 (file)
@@ -125,16 +125,24 @@ set ( CLASS_HDRS
     AliHLTTPCHWCFDataReverterComponent.h
     AliHLTTPCTrackMCMarkerComponent.h
     AliHLTTPCdEdxComponent.h
+    HWCFemulator/AliHLTTPCHWCFExtractorUnit.h
+    HWCFemulator/AliHLTTPCHWCFProcessorUnit.h
+    HWCFemulator/AliHLTTPCHWCFMergerUnit.h
+    HWCFemulator/AliHLTTPCHWCFDivisionUnit.h
+    HWCFemulator/AliHLTTPCHWCFEmulator.h
+    HWCFemulator/AliHLTTPCHWCFSupport.h
+    HWCFemulator/AliHLTTPCHWCFEmulatorComponent.h
+    HWCFemulator/AliHLTTPCHWCFConsistencyControlComponent.h
 )
 
 string ( REPLACE ".h" ".cxx" MODULE_SRCS "${CLASS_HDRS}")
 list(APPEND MODULE_SRCS AliHLTTPCLog.cxx)
 
-set ( MODULE_HDRS      ${CLASS_HDRS} AliHLTTPCLog.h AliHLTTPCLogging.h AliHLTTPCSpacePointData.h AliHLTTPCRootTypes.h AliHLTTPCDigitData.h AliHLTTPCTrackSegmentData.h AliHLTTPCVertexData.h AliHLTTPCTrackletDataFormat.h AliHLTTPCClusterDataFormat.h AliHLTTPCModels.h AliHLTTPCClusterMCData.h )
+set ( MODULE_HDRS      ${CLASS_HDRS} AliHLTTPCLog.h AliHLTTPCLogging.h AliHLTTPCSpacePointData.h AliHLTTPCRootTypes.h AliHLTTPCDigitData.h AliHLTTPCTrackSegmentData.h AliHLTTPCVertexData.h AliHLTTPCTrackletDataFormat.h AliHLTTPCClusterDataFormat.h AliHLTTPCModels.h AliHLTTPCClusterMCData.h HWCFemulator/AliHLTTPCHWCFDataTypes.h)
 
 set ( MODULE_DHDR )
 
-set ( EINCLUDE  HLT/TPCLib HLT/TPCLib/tracking HLT/TPCLib/comp HLT/TPCLib/tracking-ca HLT/TPCLib/merger-ca HLT/TPCLib/offline HLT/BASE HLT/BASE/util HLT/RCU TPC RAW STEER)
+set ( EINCLUDE  HLT/TPCLib HLT/TPCLib/tracking HLT/TPCLib/comp HLT/TPCLib/tracking-ca HLT/TPCLib/merger-ca HLT/TPCLib/offline HLT/TPCLib/HWCFemulator HLT/BASE HLT/BASE/util HLT/RCU TPC RAW STEER)
 set ( ELIBS  dl)
 
 set ( ELIBS  "HLTbase AliHLTRCU AliHLTUtil CDB ESD STEER STEERBase TPCrec TPCcalib TPCbase RAWDatarec RAWDatabase -lEG")
@@ -161,7 +169,7 @@ if(NOT DHDR)
 endif(NOT DHDR)
 
 set ( EDEFINE  ${HLTDEFS})
-set ( PACKCXXFLAGS  "${HLTCXXFLAGS} -Wshadow")
+set ( PACKCXXFLAGS  "${HLTCXXFLAGS} -Wshadow -Wall -O3")
 set ( PACKCFLAGS  ${HLTCLFAGS})
 set ( PACKDCXXFLAGS  ${HLTDCXXFLAGS})
 set ( PACKSOFLAGS ${HLTSOFLAGS})
index 4296c1f..c7e2a26 100644 (file)
@@ -74,6 +74,8 @@ AliHLTTPCAgent gAliHLTTPCAgent;
 // #include "AliHLTTPCCalibTimeGainComponent.h"
 // #include "AliHLTTPCCalibrationComponent.h"
 #include "AliHLTTPCDataCheckerComponent.h"
+#include "AliHLTTPCHWCFEmulatorComponent.h"
+#include "AliHLTTPCHWCFConsistencyControlComponent.h"
 
 /** ROOT macro for the implementation of ROOT specific class methods */
 ClassImp(AliHLTTPCAgent)
@@ -306,7 +308,8 @@ int AliHLTTPCAgent::RegisterComponents(AliHLTComponentHandler* pHandler) const
 //   pHandler->AddComponent(new AliHLTTPCCalibTimeGainComponent);
 //   pHandler->AddComponent(new AliHLTTPCCalibrationComponent);
   pHandler->AddComponent(new AliHLTTPCDataCheckerComponent);
-
+  pHandler->AddComponent(new AliHLTTPCHWCFEmulatorComponent);
+  pHandler->AddComponent(new AliHLTTPCHWCFConsistencyControlComponent);
   return 0;
 }
 
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFConsistencyControlComponent.cxx b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFConsistencyControlComponent.cxx
new file mode 100644 (file)
index 0000000..b5c4651
--- /dev/null
@@ -0,0 +1,420 @@
+//****************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project          * 
+//* ALICE Experiment at CERN, All rights reserved.                           *
+//*                                                                          *
+//* Primary Authors: Sergey Gorbunov, Torsten Alt                            *
+//* Developers:      Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
+//*                  Torsten Alt <talt@cern.ch>                              *
+//*                  for The ALICE HLT Project.                              *
+//*                                                                          *
+//* Permission to use, copy, modify and distribute this software and its     *
+//* documentation strictly for non-commercial purposes is hereby granted     *
+//* without fee, provided that the above copyright notice appears in all     *
+//* copies and that both the copyright notice and this permission notice     *
+//* appear in the supporting documentation. The authors make no claims       *
+//* about the suitability of this software for any purpose. It is            *
+//* provided "as is" without express or implied warranty.                    *
+//****************************************************************************
+
+//  @file   AliHLTTPCHWCFConsistencyControlComponent.cxx
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  Comparison of TPC clusters produced by FPGA clusterfinder and by FPGA Emulator 
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+
+
+#if __GNUC__>= 3
+using namespace std;
+#endif
+#include "AliHLTTPCHWCFConsistencyControlComponent.h"
+
+#include "AliHLTTPCDefinitions.h"
+#include "AliHLTTPCHWCFDataTypes.h"
+#include "AliHLTTPCClusterMCData.h"
+
+#include "AliGRPObject.h"
+#include "AliCDBEntry.h"
+#include "AliCDBManager.h"
+#include "AliRawDataHeader.h"
+#include <cstdlib>
+#include <cerrno>
+#include "TString.h"
+#include "TObjString.h"
+#include "TObjArray.h"
+
+
+#include <sys/time.h>
+#include "TFile.h"
+
+AliHLTTPCHWCFConsistencyControlComponent::AliHLTTPCHWCFConsistencyControlComponent()
+  :
+  AliHLTProcessor(),
+  fNDismatch(0),
+  fNBlocks(0),
+  fBenchmark("TPCHWConsistencyControl")
+{
+  // see header file for class documentation
+  // or
+  // refer to README to build package
+  // or
+  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+}
+
+
+AliHLTTPCHWCFConsistencyControlComponent::AliHLTTPCHWCFConsistencyControlComponent(const AliHLTTPCHWCFConsistencyControlComponent&)
+  :
+  AliHLTProcessor(),
+  fNDismatch(0),
+  fNBlocks(0),
+  fBenchmark("TPCHWConsistencyControl")
+{
+  // dummy
+}
+
+AliHLTTPCHWCFConsistencyControlComponent& AliHLTTPCHWCFConsistencyControlComponent::operator=(const AliHLTTPCHWCFConsistencyControlComponent&)
+{
+  // dummy
+  return *this;
+}
+
+AliHLTTPCHWCFConsistencyControlComponent::~AliHLTTPCHWCFConsistencyControlComponent()
+{
+  // see header file for class documentation
+}
+
+// Public functions to implement AliHLTComponent's interface.
+// These functions are required for the registration process
+
+const char* AliHLTTPCHWCFConsistencyControlComponent::GetComponentID()
+{
+  // see header file for class documentation
+  return "TPCHWCFConsistenyControl";
+}
+
+void AliHLTTPCHWCFConsistencyControlComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
+{
+  // see header file for class documentation
+  list.clear();
+  list.push_back( AliHLTTPCDefinitions::fgkHWClustersDataType| kAliHLTDataOriginTPC );
+}
+
+AliHLTComponentDataType AliHLTTPCHWCFConsistencyControlComponent::GetOutputDataType()
+{
+  // see header file for class documentation
+  return kAliHLTVoidDataType;//kMultipleDataType;
+}
+
+int AliHLTTPCHWCFConsistencyControlComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
+{
+  // see header file for class documentation
+  tgtList.clear();
+  return tgtList.size();
+}
+
+
+void AliHLTTPCHWCFConsistencyControlComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
+{
+  // see header file for class documentation
+  // XXX TODO: Find more realistic values.  
+  constBase = 0;
+  inputMultiplier = 6;
+}
+
+
+AliHLTComponent* AliHLTTPCHWCFConsistencyControlComponent::Spawn()
+{
+  // see header file for class documentation
+  return new AliHLTTPCHWCFConsistencyControlComponent();
+}
+
+void AliHLTTPCHWCFConsistencyControlComponent::GetOCDBObjectDescription( TMap* const /*targetMap*/){
+// Get a list of OCDB object description needed for the particular component
+  /*
+  if (!targetMap) return;
+  
+  // OCDB entries for component arguments
+  targetMap->Add(new TObjString("HLT/ConfigTPC/TPCHWClusterFinder"), new TObjString("component arguments, empty at the moment"));
+  */
+}
+
+
+int AliHLTTPCHWCFConsistencyControlComponent::DoInit( int argc, const char** argv )
+{
+  // see header file for class documentation
+
+  TString arguments = "";
+  for ( int i = 0; i < argc; i++ ) {
+    if ( !arguments.IsNull() ) arguments += " ";
+    arguments += argv[i];
+  }
+
+  return Configure( NULL, NULL, arguments.Data()  );
+}
+
+int AliHLTTPCHWCFConsistencyControlComponent::Reconfigure( const char* cdbEntry, const char* chainId )
+{
+  // Reconfigure the component from OCDB
+
+  return Configure( cdbEntry, chainId, NULL );
+}
+
+int AliHLTTPCHWCFConsistencyControlComponent::ScanConfigurationArgument(int argc, const char** argv)
+{
+  // see header file for class documentation
+  TString arguments = "";
+  for ( int i = 0; i < argc; i++ ) {
+    if ( !arguments.IsNull() ) arguments += " ";
+    arguments += argv[i];
+  }
+  return ReadConfigurationString(arguments);
+}
+
+
+
+void AliHLTTPCHWCFConsistencyControlComponent::SetDefaultConfiguration()
+{
+  // Set default configuration for the FPGA ClusterFinder Emulator component
+  // Some parameters can be later overwritten from the OCDB
+
+  fNDismatch = 0;
+  fNBlocks = 0;
+  fBenchmark.Reset();
+  fBenchmark.SetTimer(0,"total");
+  fBenchmark.SetTimer(1,"reco");    
+}
+
+int AliHLTTPCHWCFConsistencyControlComponent::ReadConfigurationString(  const char* arguments )
+{
+  // Set configuration parameters for the FPGA ClusterFinder Emulator component
+  // from the string
+
+  int iResult = 0;
+  if ( !arguments ) return iResult;
+
+  TString allArgs = arguments;
+  TString argument;
+  int bMissingParam = 0;
+
+  TObjArray* pTokens = allArgs.Tokenize( " " );
+
+  int nArgs =  pTokens ? pTokens->GetEntries() : 0;
+
+  for ( int i = 0; i < nArgs; i++ ) {
+    argument = ( ( TObjString* )pTokens->At( i ) )->GetString();
+    if ( argument.IsNull() ) continue;
+
+    //if ( argument.CompareTo( "-deconvolute-time" ) == 0 ) {
+    //if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+    //fDoDeconvTime  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+    //HLTInfo( "Time deconvolution is set to: %d", fDoDeconvTime );
+    //continue;
+    //}
+
+    HLTError( "Unknown option \"%s\"", argument.Data() );
+    iResult = -EINVAL;
+  }
+  delete pTokens;
+
+  if ( bMissingParam ) {
+    HLTError( "Specifier missed for parameter \"%s\"", argument.Data() );
+    iResult = -EINVAL;
+  }
+
+  return iResult;
+}
+
+
+int AliHLTTPCHWCFConsistencyControlComponent::ReadCDBEntry( const char* /*cdbEntry*/, const char* /*chainId*/ )
+{
+  // Read configuration from OCDB
+  return 0;
+  /*
+  const char* defaultNotify = "";
+
+  if ( !cdbEntry ){
+    cdbEntry = "HLT/ConfigTPC/TPCHWClusterFinder";
+    defaultNotify = " (default)";
+    chainId = 0;
+  }
+
+  HLTInfo( "configure from entry \"%s\"%s, chain id %s", cdbEntry, defaultNotify, ( chainId != NULL && chainId[0] != 0 ) ? chainId : "<none>" );
+  AliCDBEntry *pEntry = AliCDBManager::Instance()->Get( cdbEntry );//,GetRunNo());
+  
+  if ( !pEntry ) {
+    HLTError( "cannot fetch object \"%s\" from CDB", cdbEntry );
+    return -EINVAL;
+  }
+
+  TObjString* pString = dynamic_cast<TObjString*>( pEntry->GetObject() );
+
+  if ( !pString ) {
+    HLTError( "configuration object \"%s\" has wrong type, required TObjString", cdbEntry );
+    return -EINVAL;
+  }
+
+  HLTInfo( "received configuration object string: \"%s\"", pString->GetString().Data() );
+
+  return  ReadConfigurationString( pString->GetString().Data() );
+  */
+}
+
+
+int AliHLTTPCHWCFConsistencyControlComponent::Configure( const char* cdbEntry, const char* chainId, const char *commandLine )
+{
+  // Configure the component
+  // There are few levels of configuration,
+  // parameters which are set on one step can be overwritten on the next step
+
+  //* read hard-coded values
+
+  SetDefaultConfiguration();
+
+  //* read the default CDB entry
+
+  int iResult1 = ReadCDBEntry( NULL, chainId );
+
+  //* read the actual CDB entry if required
+
+  int iResult2 = ( cdbEntry ) ? ReadCDBEntry( cdbEntry, chainId ) : 0;
+
+  //* read extra parameters from input (if they are)
+
+  int iResult3 = 0;
+
+  if ( commandLine && commandLine[0] != '\0' ) {
+    HLTInfo( "received configuration string from HLT framework: \"%s\"", commandLine );
+    iResult3 = ReadConfigurationString( commandLine );
+  }
+
+  return iResult1 ? iResult1 : ( iResult2 ? iResult2 : iResult3 );
+}
+
+
+int AliHLTTPCHWCFConsistencyControlComponent::DoDeinit()
+{
+  // see header file for class documentation 
+  return 0;
+}
+
+
+int AliHLTTPCHWCFConsistencyControlComponent::DoEvent( const AliHLTComponentEventData& evtData, 
+                                                      const AliHLTComponentBlockData* blocks, 
+                                                      AliHLTComponentTriggerData& /*trigData*/, AliHLTUInt8_t* /*outputPtr*/, 
+                                                      AliHLTUInt32_t& size, 
+                                                      vector<AliHLTComponentBlockData>& /*outputBlocks*/ )
+{
+  // see header file for class documentation
+
+  int iResult=0;
+  //AliHLTUInt32_t maxSize = size;
+  size = 0;
+  
+  if(!IsDataEvent()){
+    return 0;
+  }
+
+  fBenchmark.StartNewEvent();
+  fBenchmark.Start(0);
+  bool *checkedBlocks = new bool[evtData.fBlockCnt];
+  for( unsigned long i=0; i<evtData.fBlockCnt; i++ ) checkedBlocks[i] = 0;
+  
+  for ( unsigned long ndx1 = 0; ndx1 < evtData.fBlockCnt; ndx1++ ){
+    
+    const AliHLTComponentBlockData* iter1 = blocks+ndx1;
+    fBenchmark.AddInput(iter1->fSize);
+    
+    if (  iter1->fDataType != (AliHLTTPCDefinitions::fgkHWClustersDataType | kAliHLTDataOriginTPC) 
+         ) continue;
+    if( checkedBlocks[ndx1] ) continue;// block already checked
+
+    checkedBlocks[ndx1] = 1;
+    int slice1 = AliHLTTPCDefinitions::GetMinSliceNr( *iter1 );
+    int patch1 = AliHLTTPCDefinitions::GetMinPatchNr( *iter1 );
+    
+    int nSecondBlocksFound=0;    
+    bool sizeInconsistency = 0;        
+    AliHLTInt64_t intDiff = 0;
+    AliHLTFloat64_t floatDiff = 0;
+    
+    for ( unsigned long ndx2 = ndx1+1; ndx2 < evtData.fBlockCnt; ndx2++ ){
+      
+      const AliHLTComponentBlockData* iter2 = blocks+ndx2;      
+      if (  iter2->fDataType != (AliHLTTPCDefinitions::fgkHWClustersDataType | kAliHLTDataOriginTPC)
+           ) continue;
+            
+      int slice2 = AliHLTTPCDefinitions::GetMinSliceNr( *iter2 );
+      int patch2 = AliHLTTPCDefinitions::GetMinPatchNr( *iter2 );
+      if( slice1!=slice2 || patch1!=patch2 ) continue;
+
+      if( checkedBlocks[ndx2] ) continue;
+
+      checkedBlocks[ndx2] = 1;
+
+      nSecondBlocksFound++;
+      
+      int nWordsHeader =  sizeof(AliRawDataHeader)/4;
+      int nWords = iter1->fSize/4;
+      const AliHLTUInt32_t *p1 = (const AliHLTUInt32_t *) iter1->fPtr;
+      const AliHLTUInt32_t *p2 = (const AliHLTUInt32_t *) iter2->fPtr;
+
+      // compare size 
+
+      bool sizeInc = 
+       ( iter1->fSize != iter2->fSize )
+       || ( iter1->fSize % 4 != 0 ) || ( iter2->fSize % 4 !=0 )
+       || iter1->fSize < sizeof(AliRawDataHeader)      
+       || iter2->fSize < sizeof(AliRawDataHeader)
+       || (nWords>0 && (!iter1->fPtr || !iter2->fPtr) );
+      
+      sizeInconsistency = sizeInconsistency || sizeInc;
+
+      if( !sizeInc ){
+       bool RCUtrailer = 0;
+       for( AliHLTInt32_t i=0; i<nWords; i++){
+         if( RCUtrailer || i<nWordsHeader || ( (i-nWordsHeader)%5==0) ){
+           // integer data
+           if( p1[i]>>30 == 0x2 ) RCUtrailer = 1;
+           long int d = (long int) p1[i] - (long int) p2[i];
+           if( abs(d)>intDiff ) intDiff = d;
+         } else {
+           // float data
+           AliHLTFloat64_t f1 = *(AliHLTFloat32_t*)&p1[i];
+           AliHLTFloat64_t f2 = *(AliHLTFloat32_t*)&p2[i];
+           double w = fabs(f1 + f2)/2;
+           if( w>1.e-20 ){
+             AliHLTFloat64_t d = fabs(f1 - f2)/w;
+             if( d > floatDiff ) floatDiff = d;              
+           }
+         }
+       }
+      }         
+    }
+
+    HLTInfo("HWCF consistency check for slice %d patch %d: wrong NBlocks: %d, wrong size: %d, intDiff: %d, floatDiff: %.10f %s", slice1, patch1, 
+           (nSecondBlocksFound!=1),sizeInconsistency,intDiff, floatDiff*100.,"%"); 
+    if( (nSecondBlocksFound!=1) || sizeInconsistency || intDiff!=0 || floatDiff>1.e-6 ){
+      fNDismatch++;
+      HLTWarning("HWCF consistency check for slice %d patch %d: wrong NBlocks: %d, wrong size: %d, intDiff: %d, floatDiff: %.10f %s", slice1, patch1, 
+                (nSecondBlocksFound!=1),sizeInconsistency,intDiff, floatDiff*100.,"%"); 
+    }
+    fNBlocks++;
+  }
+  
+  delete[] checkedBlocks;
+   
+  HLTInfo("HWCF consistency check: %.10f %s of %ld data blocks are OK",
+         (double)(fNBlocks-fNDismatch)/(double)fNBlocks*100.,"%",fNBlocks);
+  
+  if( fNDismatch>0 ){
+    HLTWarning("HWCF inconsistency: %ld of %ld data blocks are not OK",
+              fNDismatch,fNBlocks);      
+  }  
+  
+  fBenchmark.Stop(0);  
+  HLTInfo(fBenchmark.GetStatistics());
+  return iResult;
+}
+
+
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFConsistencyControlComponent.h b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFConsistencyControlComponent.h
new file mode 100644 (file)
index 0000000..077b1e0
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef ALIHLTTPCHWCFCONSISTENCYCONTROLCOMPONENT_H
+#define ALIHLTTPCHWCFCONSISTENCYCONTROLCOMPONENT_H
+
+//* This file is property of and copyright by the ALICE HLT Project        * 
+//* ALICE Experiment at CERN, All rights reserved.                         *
+//* See cxx source for full Copyright notice                               *
+
+//  @file   AliHLTTPCHWCFConsistencyControlComponent.h
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  Comparison of TPC clusters produced by FPGA clusterfinder and by FPGA Emulator 
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+
+
+
+#include "AliHLTProcessor.h"
+#include "AliHLTComponentBenchmark.h"
+
+/**
+ * @class AliHLTTPCHWCFConsistencyControlComponent
+ * The FPGA clusterfinder emulator for TPC
+ * Comparison of TPC clusters produced by FPGA clusterfinder and by FPGA Emulator
+ * ( see AliHLTTPCHWCFEmulator class )
+ *
+ * <h2>General properties:</h2>
+ *
+ * Component ID: \b TPCHWCFConsistenyControl <br>
+ * Library: \b libAliHLTTPC
+ * Input Data Types: @ref  AliHLTTPCDefinitions::fgkHWClustersDataType <br>
+ * Output Data Types: @ref  <br> 
+ *
+ *
+ * Mandatory arguments: <br>
+ * <!-- NOTE: ignore the \li. <i> and </i>: it's just doxygen formatting -->
+ *
+ * Optional arguments: <br>
+ * <!-- NOTE: ignore the \li. <i> and </i>: it's just doxygen formatting -->
+ *
+ * <h2>Default CDB entries:</h2>
+ * None
+ *
+ * @ingroup alihlt_tpc_components
+ */
+class AliHLTTPCHWCFConsistencyControlComponent : public AliHLTProcessor
+{
+ public:      
+  /**
+   * constructor 
+   */
+  AliHLTTPCHWCFConsistencyControlComponent();
+  /** destructor */
+  virtual ~AliHLTTPCHWCFConsistencyControlComponent();
+  
+  // Public functions to implement AliHLTComponent's interface.
+  // These functions are required for the registration process
+
+  /** interface function, see AliHLTComponent for description */
+  const char* GetComponentID();
+
+  /** interface function, see AliHLTComponent for description */
+  void GetInputDataTypes( vector<AliHLTComponentDataType>& list);
+
+  /** interface function, see AliHLTComponent for description */
+  AliHLTComponentDataType GetOutputDataType();
+
+  /** interface function, see AliHLTComponent for description */
+  int GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList);
+
+  /** interface function, see AliHLTComponent for description */
+  virtual void GetOutputDataSize( unsigned long& constBase, double& inputMultiplier );
+
+  /** interface function, see AliHLTComponent for description */
+  AliHLTComponent* Spawn();
+
+  /** interface function, see @ref AliHLTComponent for description */
+  void GetOCDBObjectDescription( TMap* const targetMap);
+
+ protected:
+  
+  // Protected functions to implement AliHLTComponent's interface.
+  // These functions provide initialization as well as the actual processing
+  // capabilities of the component. 
+  
+     /** @copydoc AliHLTComponent::DoInit
+      */
+    int DoInit( int argc, const char **argv );
+
+    /** @copydoc AliHLTComponent::DoDeinit
+     */
+    int DoDeinit();
+
+    /**  @copydoc @ref AliHLTComponent::Reconfigure
+     */
+    int Reconfigure( const char* cdbEntry, const char* chainId );
+
+    /**  @copydoc @ref AliHLTComponent::ScanConfigurationArgument
+     */
+    int ScanConfigurationArgument(int argc, const char** argv);
+
+    /** @copydoc @ref AliHLTProcessor::DoEvent
+     */
+    int DoEvent( const AliHLTComponentEventData& evtData, const AliHLTComponentBlockData* blocks, 
+                AliHLTComponentTriggerData& trigData, AliHLTUInt8_t* outputPtr, 
+                AliHLTUInt32_t& size, vector<AliHLTComponentBlockData>& outputBlocks );
+
+     
+    using AliHLTProcessor::DoEvent;
+  
+ private:
+
+  /** copy constructor prohibited */
+  AliHLTTPCHWCFConsistencyControlComponent(const AliHLTTPCHWCFConsistencyControlComponent&);
+
+  /** assignment operator prohibited */
+  AliHLTTPCHWCFConsistencyControlComponent& operator=(const AliHLTTPCHWCFConsistencyControlComponent&);
+
+  /** Set default configuration */
+  void SetDefaultConfiguration();
+
+  /** scan configuration string */
+  int ReadConfigurationString(  const char* arguments );
+
+  /** read configuration from OCDB */
+  int ReadCDBEntry( const char* cdbEntry, const char* chainId );
+
+  /** read configuration from multiple sources */
+  int Configure( const char* cdbEntry, const char* chainId, const char *commandLine );
+
+  AliHLTUInt64_t fNDismatch;// N inconsistent data blocks
+  AliHLTUInt64_t fNBlocks;// N of data blocks processed
+  AliHLTComponentBenchmark fBenchmark; // benchmark
+};
+#endif
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDataTypes.h b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDataTypes.h
new file mode 100644 (file)
index 0000000..fe918bc
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef ALIHLTTPCHWCFDATATYPES_H
+#define ALIHLTTPCHWCFDATATYPES_H
+//* This file is property of and copyright by the ALICE HLT Project        * 
+//* ALICE Experiment at CERN, All rights reserved.                         *
+//* See cxx source for full Copyright notice                               *
+
+//  @file   AliHLTTPCHWCFDataTypes.h
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  Data types for FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+
+#include "AliHLTDataTypes.h"
+#include "AliHLTTPCClusterMCData.h"
+#include <vector>
+
+
+struct AliHLTTPCHWCFDefinitions
+{
+  static const unsigned int kMaxNTimeBins = 1024+10; // max N time bins
+  static const int kFixedPoint = 12; // N bits after fixed point 
+                                     // for fixed point operations
+};
+
+typedef struct AliHLTTPCHWCFDefinitions AliHLTTPCHWCFDefinitions;
+
+struct AliHLTTPCHWCFBunch
+{
+  //* constructor **/
+  AliHLTTPCHWCFBunch(): fFlag(0), fRow(0), fPad(0), fBranch(0), fBorder(0),
+       fTime(0),fGain(0), fData(), fMC()
+  {}
+
+  AliHLTUInt32_t fFlag; // 0 - Off, 1 - data, 2 - RCU trailer, 3 - end of data
+  AliHLTUInt32_t fRow;  // row number
+  AliHLTUInt32_t fPad;  // pad number
+  bool fBranch;         // 0  - pad belongs to branch A, 1 - pad belongs to branch B
+  bool fBorder;         // is the pad at the border of its branch
+  AliHLTUInt32_t fTime; // time of the first signal
+  AliHLTUInt64_t fGain; // gain correction factor 
+                        //   (fixed point integer with kFixedPoint bits after the point)
+  std::vector<AliHLTUInt32_t> fData;      // signals
+  std::vector<AliHLTTPCClusterMCWeight> fMC; // mc labels
+};
+typedef struct AliHLTTPCHWCFBunch AliHLTTPCHWCFBunch;
+
+struct AliHLTTPCHWCFClusterFragment
+{
+  //* constructor **/
+  AliHLTTPCHWCFClusterFragment():  fFlag(0), fRow(0), fPad(0), fBranch(0), fBorder(0),
+       fQ(0), fT(0), fP(0), fT2(0), fP2(0), fTMean(0),fLastQ(0), fSlope(0), fMC()
+  {}
+
+  AliHLTUInt32_t fFlag; // 0 - Off, 1 - data, 2 - RCU trailer, 3 - end of data
+  AliHLTUInt32_t fRow;  // row number
+  AliHLTUInt32_t fPad;  // pad number
+  bool fBranch;         // 0  - pad belongs to branch A, 1 - pad belongs to branch B
+  bool fBorder;         // is the pad at the border of its branch
+  AliHLTUInt64_t fQ;    // total charge, fixed point integer
+  AliHLTUInt64_t fT;    // sum of time*charge , fixed point integer
+  AliHLTUInt64_t fP;    // sum of pad*charge  , fixed point integer
+  AliHLTUInt64_t fT2;   // sum of time^2*charge , fixed point integer
+  AliHLTUInt64_t fP2;   // sum of pad^2*charge  , fixed point integer
+  AliHLTUInt64_t fTMean;// mean time, used for merging neighbouring pads
+  AliHLTUInt64_t fLastQ; // for merged fragments, charge of the last (highest pad value)
+                         //    fragment bein merged, needed for deconvolution
+  bool fSlope;           // for merged fragments, ==1 if fLastQ decreases
+                         //   ( needed for deconvolution )
+  std::vector<AliHLTTPCClusterMCWeight> fMC; // mc labels
+};
+typedef struct AliHLTTPCHWCFClusterFragment AliHLTTPCHWCFClusterFragment;
+
+struct AliHLTTPCHWCFCluster
+{
+  //* constructor **/
+  AliHLTTPCHWCFCluster(): fFlag(0), fRowQ(0), fT(0), fP(0), fT2(0), fP2(0), fMC()
+  {}
+
+  AliHLTUInt32_t fFlag; // 0 - Off, 1 - data, 2 - RCU trailer, 3 - end of data
+  AliHLTUInt32_t fRowQ; // bits 30-31 = 0x3
+                        // bits 24-29 = row number
+                        // bits 0 -23 = total charge as fixed point integer,
+                        //              with 6 bits after the point
+  AliHLTUInt32_t fT;    // mean time, 32-bit float stored as 32-bit integer
+  AliHLTUInt32_t fP;    // mean pad,  32-bit float stored as 32-bit integer
+  AliHLTUInt32_t fT2;   // mean time^2, 32-bit float stored as 32-bit integer
+  AliHLTUInt32_t fP2;   // mean pad^2,  32-bit float stored as 32-bit integer
+
+  AliHLTTPCClusterMCLabel fMC; // mc label
+};
+typedef struct AliHLTTPCHWCFCluster AliHLTTPCHWCFCluster;
+
+#endif
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDivisionUnit.cxx b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDivisionUnit.cxx
new file mode 100644 (file)
index 0000000..a6c1cf6
--- /dev/null
@@ -0,0 +1,141 @@
+//****************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project          * 
+//* ALICE Experiment at CERN, All rights reserved.                           *
+//*                                                                          *
+//* Primary Authors: Sergey Gorbunov, Torsten Alt                            *
+//* Developers:      Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
+//*                  Torsten Alt <talt@cern.ch>                              *
+//*                  for The ALICE HLT Project.                              *
+//*                                                                          *
+//* Permission to use, copy, modify and distribute this software and its     *
+//* documentation strictly for non-commercial purposes is hereby granted     *
+//* without fee, provided that the above copyright notice appears in all     *
+//* copies and that both the copyright notice and this permission notice     *
+//* appear in the supporting documentation. The authors make no claims       *
+//* about the suitability of this software for any purpose. It is            *
+//* provided "as is" without express or implied warranty.                    *
+//****************************************************************************
+
+//  @file   AliHLTTPCHWCFDivisionUnit.cxx
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @date   
+//  @brief  Division unit of FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note 
+
+#include "AliHLTTPCHWCFDivisionUnit.h"
+#include <iostream>
+#include <algorithm>
+
+
+AliHLTTPCHWCFDivisionUnit::AliHLTTPCHWCFDivisionUnit()
+  : 
+  fSinglePadSuppression(1), fClusterLowerLimit(0), fkInput(0),fOutput()
+{
+  //constructor 
+}
+
+
+AliHLTTPCHWCFDivisionUnit::~AliHLTTPCHWCFDivisionUnit()
+{   
+  //destructor 
+}
+
+AliHLTTPCHWCFDivisionUnit::AliHLTTPCHWCFDivisionUnit(const AliHLTTPCHWCFDivisionUnit&)
+  : 
+  fSinglePadSuppression(1),fClusterLowerLimit(0),fkInput(0),fOutput()
+{
+}
+
+
+AliHLTTPCHWCFDivisionUnit& AliHLTTPCHWCFDivisionUnit::operator=(const AliHLTTPCHWCFDivisionUnit&)
+{
+  // dummy  
+  return *this;
+}
+
+int AliHLTTPCHWCFDivisionUnit::Init()
+{
+  // initialise
+  fkInput = 0;
+  return 0;
+}
+  
+
+int AliHLTTPCHWCFDivisionUnit::InputStream( const AliHLTTPCHWCFClusterFragment *fragment )
+{
+  // input stream of data
+  fkInput = fragment;
+  if( fkInput ){
+    //if( fInput->fFlag==1 && fInput->fQ>0 ){
+    //std::cout<<"Division: input F "<<fInput->fFlag<<" R "<<fInput->fRow
+    //       <<" C "<<(fInput->fQ>>12)
+    //       <<" P "<<fInput->fPad
+    //       <<" T "<<fInput->fTMean
+    //       <<" CoGPad "<<((float)fInput->fP)/fInput->fQ
+    //       <<" CoGTime "<<((float)fInput->fT)/fInput->fQ
+    //       <<std::endl;
+    //} else std::cout<<"Division: input F "<<fInput->fFlag<<" R "<<fInput->fRow<<" P "<<fInput->fPad
+    //     <<" Q "<<(fInput->fQ>>12)<<std::endl;
+  }
+  return 0;
+}
+
+const AliHLTTPCHWCFCluster *AliHLTTPCHWCFDivisionUnit::OutputStream()
+{ 
+  // output stream of data
+
+  if( !fkInput ) return 0;
+
+  if( fkInput->fFlag==2 ){ // RCU trailer word
+    fOutput.fFlag = 2;
+    fOutput.fRowQ = fkInput->fRow; // rcu word
+    fkInput = 0;
+    return &fOutput;;
+  }
+
+  if( fkInput->fFlag!=1 ) return 0;
+  
+  if( fkInput->fQ==0 ) return 0;
+  if( fSinglePadSuppression && fkInput->fQ==fkInput->fLastQ && !fkInput->fBorder ) return 0;
+  if( fkInput->fQ < fClusterLowerLimit ) return 0;
+
+  AliHLTFloat32_t q = fkInput->fQ;
+  
+  fOutput.fFlag = 1;
+  fOutput.fRowQ = (((AliHLTUInt32_t) 0x3)<<30) + ((fkInput->fRow &0x3f)<<24) + ((fkInput->fQ>>(AliHLTTPCHWCFDefinitions::kFixedPoint-6))&0xFFFFFF);              
+  *((AliHLTFloat32_t*)&fOutput.fP) = (float)fkInput->fP/q;
+  *((AliHLTFloat32_t*)&fOutput.fT) = (float)fkInput->fT/q;
+  *((AliHLTFloat32_t*)&fOutput.fP2) = (float)fkInput->fP2/q;
+  *((AliHLTFloat32_t*)&fOutput.fT2) = (float)fkInput->fT2/q;
+  // MC part
+
+  AliHLTTPCClusterMCWeight emptyWeight = {-1,0};
+
+  fOutput.fMC.fClusterID[0] = emptyWeight;
+  fOutput.fMC.fClusterID[1] = emptyWeight;
+  fOutput.fMC.fClusterID[2] = emptyWeight;
+  
+  vector<AliHLTTPCClusterMCWeight> labels = fkInput->fMC;
+  sort(labels.begin(), labels.end(), CompareMCLabels);
+  for( unsigned int i=1; i<labels.size(); i++ ){
+    if(labels[i-1].fMCID==labels[i].fMCID ){
+      labels[i-1].fWeight+=labels[i].fWeight;
+      labels[i].fWeight = 0;
+    }
+  }
+
+  sort(labels.begin(), labels.end(), CompareMCWeights );
+    
+  for( unsigned int i=0; i<3 && i<labels.size(); i++ ){
+    if( labels[i].fMCID <0 ) continue;
+    fOutput.fMC.fClusterID[i] = labels[i];
+  }
+
+  fkInput = 0;
+
+  return &fOutput;
+}
+
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDivisionUnit.h b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFDivisionUnit.h
new file mode 100644 (file)
index 0000000..126e896
--- /dev/null
@@ -0,0 +1,67 @@
+//* This file is property of and copyright by the ALICE HLT Project        * 
+//* ALICE Experiment at CERN, All rights reserved.                         *
+//* See cxx source for full Copyright notice                               *
+
+#ifndef ALIHLTTPCHWCFDIVISIONUNIT_H
+#define ALIHLTTPCHWCFDIVISIONUNIT_H
+
+#include "AliHLTTPCHWCFDataTypes.h"
+
+
+//  @class   AliHLTTPCHWCFDivisionUnit
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  Division unit of FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+//
+class AliHLTTPCHWCFDivisionUnit
+{
+ public:  
+
+  static bool CompareMCWeights(const AliHLTTPCClusterMCWeight &a, const AliHLTTPCClusterMCWeight &b){
+    return a.fWeight < b.fWeight;
+  }
+  static bool CompareMCLabels(const AliHLTTPCClusterMCWeight &a, const AliHLTTPCClusterMCWeight &b){
+    return a.fMCID < b.fMCID;
+  }
+  
+  /** standard constructor */
+  AliHLTTPCHWCFDivisionUnit();
+  
+  /** destructor */
+  ~AliHLTTPCHWCFDivisionUnit();
+
+  /** Suppress clusters wich were not mmerged (except of clusters at branch borders)
+   */
+  void SetSinglePadSuppression( bool val ){ fSinglePadSuppression=val; }
+  
+  /** Lower charge limit for clusters 
+   */
+  void SetClusterLowerLimit( AliHLTUInt32_t val ){ 
+    fClusterLowerLimit = val << AliHLTTPCHWCFDefinitions::kFixedPoint; 
+  }
+  
+  /** initialise */
+  int Init();
+  
+  /** input stream of data */
+  int InputStream( const AliHLTTPCHWCFClusterFragment *fragment );
+
+  /** output stream of data */
+  const AliHLTTPCHWCFCluster *OutputStream();
+
+ private: 
+  
+  /** copy constructor prohibited */
+  AliHLTTPCHWCFDivisionUnit(const AliHLTTPCHWCFDivisionUnit&);
+  /** assignment operator prohibited */
+  AliHLTTPCHWCFDivisionUnit& operator=(const AliHLTTPCHWCFDivisionUnit&);  
+  
+  bool fSinglePadSuppression; // suppress not merged clusters
+  AliHLTUInt64_t fClusterLowerLimit; // lower charge limit for clusters 
+  const AliHLTTPCHWCFClusterFragment *fkInput; // current input 
+  AliHLTTPCHWCFCluster fOutput;  // current output
+};
+
+#endif
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulator.cxx b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulator.cxx
new file mode 100644 (file)
index 0000000..834f569
--- /dev/null
@@ -0,0 +1,205 @@
+//****************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project          * 
+//* ALICE Experiment at CERN, All rights reserved.                           *
+//*                                                                          *
+//* Primary Authors: Sergey Gorbunov, Torsten Alt                            *
+//* Developers:      Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
+//*                  Torsten Alt <talt@cern.ch>                              *
+//*                  for The ALICE HLT Project.                              *
+//*                                                                          *
+//* Permission to use, copy, modify and distribute this software and its     *
+//* documentation strictly for non-commercial purposes is hereby granted     *
+//* without fee, provided that the above copyright notice appears in all     *
+//* copies and that both the copyright notice and this permission notice     *
+//* appear in the supporting documentation. The authors make no claims       *
+//* about the suitability of this software for any purpose. It is            *
+//* provided "as is" without express or implied warranty.                    *
+//****************************************************************************
+
+//  @file   AliHLTTPCHWCFEmulator.cxx
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  FPGA ClusterFinder Emulator for TPC
+//  @note
+
+
+#include "AliHLTTPCHWCFDataTypes.h"
+#include "AliHLTTPCHWCFEmulator.h"
+#include "AliHLTTPCClusterMCData.h"
+
+#include <iostream>
+
+#if __GNUC__ >= 3
+using namespace std;
+#endif
+
+
+AliHLTTPCHWCFEmulator::AliHLTTPCHWCFEmulator()
+  :
+  fkMapping(0),
+  fChannelExtractor(),
+  fChannelProcessor(),
+  fChannelMerger(),
+  fDivisionUnit()
+{
+  //constructor 
+}
+
+AliHLTTPCHWCFEmulator::~AliHLTTPCHWCFEmulator()
+{   
+  //destructor
+}
+
+AliHLTTPCHWCFEmulator::AliHLTTPCHWCFEmulator(const AliHLTTPCHWCFEmulator&)
+  :
+  fkMapping(0),
+  fChannelExtractor(),
+  fChannelProcessor(),
+  fChannelMerger(),
+  fDivisionUnit()
+{
+  // dummy
+}
+
+AliHLTTPCHWCFEmulator& AliHLTTPCHWCFEmulator::operator=(const AliHLTTPCHWCFEmulator&)
+{
+  // dummy
+  return *this;
+}
+
+void AliHLTTPCHWCFEmulator::Init( const AliHLTUInt32_t *mapping, AliHLTUInt32_t config )
+{
+  // Initialisation
+  fkMapping = mapping;
+  
+  fChannelProcessor.SetDeconvolution( config & 0x1 );
+  fChannelMerger.SetDeconvolution( (config>>1) & 0x1 );
+  fDivisionUnit.SetSinglePadSuppression( (config>>3) & 0x1 );
+  fChannelMerger.SetByPassMerger( (config>>4) & 0x1 );
+  fDivisionUnit.SetClusterLowerLimit( (config>>8) & 0xFF );
+  fChannelProcessor.SetSingleSeqLimit( (config>>16) & 0xFF );
+
+  //fChannelMerger.SetDebugLevel(1);
+}
+
+int AliHLTTPCHWCFEmulator::FindClusters( const AliHLTUInt32_t *rawEvent,
+                                        AliHLTUInt32_t rawEventSize32,
+                                        AliHLTUInt32_t *output,
+                                        AliHLTUInt32_t &outputSize32,
+                                        const AliHLTTPCClusterMCLabel *mcLabels,
+                                        AliHLTUInt32_t nMCLabels,
+                                        AliHLTTPCClusterMCData *outputMC
+                                        )
+{  
+  // Loops over all rows finding the clusters 
+
+  AliHLTUInt32_t maxOutputSize32 = outputSize32;
+  outputSize32 = 0;
+  if( outputMC ) outputMC->fCount = 0;   
+  AliHLTUInt32_t maxNMCLabels = nMCLabels;
+  if( !rawEvent ) return -1;    
+
+  // Initialise 
+
+  int ret = 0;
+
+  fChannelExtractor.Init( fkMapping, mcLabels, 3*rawEventSize32 );
+  fChannelProcessor.Init();
+  fChannelMerger.Init();
+  fDivisionUnit.Init();
+
+  // Read the data, word by word 
+  
+  for( AliHLTUInt32_t  iWord=0; iWord<=rawEventSize32; iWord++ ){
+
+    const AliHLTTPCHWCFBunch *bunch=0;
+    const AliHLTTPCHWCFClusterFragment *fragment=0;
+    const AliHLTTPCHWCFClusterFragment *candidate=0;
+    const AliHLTTPCHWCFCluster *cluster = 0;
+    
+    if( iWord<rawEventSize32 ) fChannelExtractor.InputStream(ReadBigEndian(rawEvent[iWord]));
+    else fChannelExtractor.InputEndOfData();
+
+    while( (bunch = fChannelExtractor.OutputStream()) ){ 
+      fChannelProcessor.InputStream(bunch);
+      while( (fragment = fChannelProcessor.OutputStream() )){  
+       fChannelMerger.InputStream( fragment );
+       while( (candidate = fChannelMerger.OutputStream()) ){             
+         fDivisionUnit.InputStream(candidate);
+         while( (cluster = fDivisionUnit.OutputStream()) ){        
+           if( cluster->fFlag==1 ){
+             if( outputSize32+5 > maxOutputSize32 ){ // No space in the output buffer
+               ret = -2;
+               break;
+             }       
+             AliHLTUInt32_t *co = &output[outputSize32];
+             co[0] = WriteBigEndian(cluster->fRowQ);
+             co[1] = cluster->fP;
+             co[2] = cluster->fT;
+             co[3] = cluster->fP2;
+             co[4] = cluster->fT2;
+             outputSize32+=5;
+             if( mcLabels && outputMC && outputMC->fCount < maxNMCLabels){
+               outputMC->fLabels[outputMC->fCount++] = cluster->fMC;
+             }
+           }
+           else if( cluster->fFlag==2 ){
+             if( outputSize32+1 > maxOutputSize32 ){ // No space in the output buffer
+               ret = -2;
+               break;
+             }
+             output[outputSize32++] = cluster->fRowQ;
+           }
+         }
+       }
+      }
+    }
+  }
+  return ret;
+}
+
+AliHLTUInt32_t AliHLTTPCHWCFEmulator::ReadBigEndian ( AliHLTUInt32_t word )
+{  
+  // read the word written in big endian format (lowest byte first)
+
+  const AliHLTUInt8_t *bytes = reinterpret_cast<const AliHLTUInt8_t *>( &word );
+  AliHLTUInt32_t i[4] = {bytes[0],bytes[1],bytes[2],bytes[3]};
+
+  return (i[3]<<24) | (i[2]<<16) | (i[1]<<8) | i[0];
+}
+
+AliHLTUInt32_t AliHLTTPCHWCFEmulator::WriteBigEndian ( AliHLTUInt32_t word )
+{
+  // write the word in big endian format (least byte first)
+  
+  AliHLTUInt32_t ret = 0;
+  AliHLTUInt8_t *bytes = reinterpret_cast<AliHLTUInt8_t *>( &ret );
+  bytes[0] = (word      ) & 0xFF;
+  bytes[1] = (word >>  8) & 0xFF;
+  bytes[2] = (word >> 16) & 0xFF;
+  bytes[3] = (word >> 24) & 0xFF;
+  return ret;
+}
+
+AliHLTUInt32_t AliHLTTPCHWCFEmulator::CreateConfiguration
+(
+ bool doDeconvTime, bool doDeconvPad, bool doFlowControl, 
+ bool doSinglePadSuppression, bool bypassMerger, 
+ AliHLTUInt32_t clusterLowerLimit,AliHLTUInt32_t singleSeqLimit
+ )
+{
+  // static method to create configuration word 
+
+  AliHLTUInt32_t config = 0;
+
+  config |= ( (AliHLTUInt32_t)doDeconvTime & 0x1 );
+  config |= ( (AliHLTUInt32_t)doDeconvPad & 0x1 ) << 1;
+  config |= ( (AliHLTUInt32_t)doFlowControl & 0x1 ) << 2;
+  config |= ( (AliHLTUInt32_t)doSinglePadSuppression & 0x1 ) << 3;
+  config |= ( (AliHLTUInt32_t)bypassMerger & 0x1 ) << 4;
+  config |= ( (AliHLTUInt32_t)clusterLowerLimit & 0xFF )<<8;
+  config |= ( (AliHLTUInt32_t)singleSeqLimit & 0xFF )<<16;
+
+  return config;
+}
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulator.h b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulator.h
new file mode 100644 (file)
index 0000000..9f09cf8
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef ALIHLTTPCHWCFEMULATOR_H
+#define ALIHLTTPCHWCFEMULATOR_H
+
+//* This file is property of and copyright by the ALICE HLT Project        * 
+//* ALICE Experiment at CERN, All rights reserved.                         *
+//* See cxx source for full Copyright notice                               *
+
+#include "AliHLTTPCHWCFExtractorUnit.h"
+#include "AliHLTTPCHWCFProcessorUnit.h"
+#include "AliHLTTPCHWCFMergerUnit.h"
+#include "AliHLTTPCHWCFDivisionUnit.h"
+
+class AliHLTTPCClusterMCData;
+class AliHLTTPCClusterMCLabel;
+
+//  @class   AliHLTTPCHWCFEmulator
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  FPGA ClusterFinder Emulator for TPC
+//  @note
+//
+class AliHLTTPCHWCFEmulator 
+{
+ public:  
+
+  /** standard constructor */
+   AliHLTTPCHWCFEmulator();
+  
+  /** destructor */
+  virtual ~AliHLTTPCHWCFEmulator();
+   
+  /** initialisation 
+   */
+  void Init( const AliHLTUInt32_t *mapping, AliHLTUInt32_t configWord );
+  
+  /** Loops over all rows finding the clusters 
+   */
+  int FindClusters( const AliHLTUInt32_t *rawEvent,
+                   AliHLTUInt32_t rawEventSize32,
+                   AliHLTUInt32_t *output,
+                   AliHLTUInt32_t &outputSize32,
+                   const AliHLTTPCClusterMCLabel *mcLabels,
+                   AliHLTUInt32_t nMCLabels,
+                   AliHLTTPCClusterMCData *outputMC
+                   );
+
+  /* useful tools */
+
+  /** read the word written in big endian format (lowest byte first) 
+   */
+  static AliHLTUInt32_t ReadBigEndian( AliHLTUInt32_t word );
+
+  /** write a word in big endian format (least byte first) 
+   */
+  static  AliHLTUInt32_t WriteBigEndian( AliHLTUInt32_t word );
+
+  /** create configuration word 
+   **/
+  static AliHLTUInt32_t CreateConfiguration
+    ( bool doDeconvTime, bool doDeconvPad, bool doFlowControl,  
+      bool doSinglePadSuppression, bool bypassMerger, 
+      AliHLTUInt32_t clusterLowerLimit,AliHLTUInt32_t singleSeqLimit );
+  /** create default configuration word 
+   **/
+  static AliHLTUInt32_t CreateDefaultConfiguration(){
+    return CreateConfiguration(0,0,0,1,0,0,0);
+  }
+  
+ private: 
+
+  /** copy constructor prohibited */
+  AliHLTTPCHWCFEmulator(const AliHLTTPCHWCFEmulator&);
+  /** assignment operator prohibited */
+  AliHLTTPCHWCFEmulator& operator=(const AliHLTTPCHWCFEmulator&);
+  const AliHLTUInt32_t *fkMapping; //! mapping array
+  AliHLTTPCHWCFExtractorUnit fChannelExtractor; //! transient
+  AliHLTTPCHWCFProcessorUnit fChannelProcessor; //! transient
+  AliHLTTPCHWCFMergerUnit    fChannelMerger; //! transient
+  AliHLTTPCHWCFDivisionUnit  fDivisionUnit;   //! transient
+};
+#endif
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulatorComponent.cxx b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulatorComponent.cxx
new file mode 100644 (file)
index 0000000..eb13e7c
--- /dev/null
@@ -0,0 +1,562 @@
+//****************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project          * 
+//* ALICE Experiment at CERN, All rights reserved.                           *
+//*                                                                          *
+//* Primary Authors: Sergey Gorbunov, Torsten Alt                            *
+//* Developers:      Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
+//*                  Torsten Alt <talt@cern.ch>                              *
+//*                  for The ALICE HLT Project.                              *
+//*                                                                          *
+//* Permission to use, copy, modify and distribute this software and its     *
+//* documentation strictly for non-commercial purposes is hereby granted     *
+//* without fee, provided that the above copyright notice appears in all     *
+//* copies and that both the copyright notice and this permission notice     *
+//* appear in the supporting documentation. The authors make no claims       *
+//* about the suitability of this software for any purpose. It is            *
+//* provided "as is" without express or implied warranty.                    *
+//****************************************************************************
+
+//  @file   AliHLTTPCHWCFEmulatorComponent.cxx
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  HLT Component interface for for FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+
+
+#if __GNUC__>= 3
+using namespace std;
+#endif
+#include "AliHLTTPCHWCFEmulatorComponent.h"
+
+#include "AliHLTTPCDefinitions.h"
+#include "AliHLTTPCHWCFDataTypes.h"
+#include "AliHLTTPCClusterMCData.h"
+
+#include "AliGRPObject.h"
+#include "AliCDBEntry.h"
+#include "AliCDBManager.h"
+#include "AliRawDataHeader.h"
+#include <cstdlib>
+#include <cerrno>
+#include "TString.h"
+#include "TObjString.h"
+#include "TObjArray.h"
+
+
+#include <sys/time.h>
+#include "TFile.h"
+
+AliHLTTPCHWCFEmulatorComponent::AliHLTTPCHWCFEmulatorComponent()
+  :
+  AliHLTProcessor(),
+  fDoDeconvTime(1),
+  fDoDeconvPad(1),
+  fDoMC(1),
+  fDoFlowControl(0),
+  fDoSinglePadSuppression(1),
+  fBypassMerger(0),
+  fClusterLowerLimit(0),
+  fSingleSeqLimit(0),
+  fDebug(0),
+  fCFSupport(),
+  fCFEmulator(),
+  fBenchmark("TPCHWClusterFinderEmulator")
+{
+  // see header file for class documentation
+  // or
+  // refer to README to build package
+  // or
+  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+}
+
+
+AliHLTTPCHWCFEmulatorComponent::AliHLTTPCHWCFEmulatorComponent(const AliHLTTPCHWCFEmulatorComponent&)
+  :
+  AliHLTProcessor(),
+  fDoDeconvTime(1),
+  fDoDeconvPad(1),
+  fDoMC(1),
+  fDoFlowControl(0),
+  fDoSinglePadSuppression(1),
+  fBypassMerger(0),
+  fClusterLowerLimit(0),
+  fSingleSeqLimit(0),
+  fDebug(0),
+  fCFSupport(),
+  fCFEmulator(),
+  fBenchmark("TPCHWClusterFinderEmulator")
+{
+  // dummy
+}
+
+AliHLTTPCHWCFEmulatorComponent& AliHLTTPCHWCFEmulatorComponent::operator=(const AliHLTTPCHWCFEmulatorComponent&)
+{
+  // dummy
+  return *this;
+}
+
+AliHLTTPCHWCFEmulatorComponent::~AliHLTTPCHWCFEmulatorComponent()
+{
+  // see header file for class documentation
+}
+
+// Public functions to implement AliHLTComponent's interface.
+// These functions are required for the registration process
+
+const char* AliHLTTPCHWCFEmulatorComponent::GetComponentID()
+{
+  // see header file for class documentation
+  return "TPCHWClusterFinderEmulator";
+}
+
+void AliHLTTPCHWCFEmulatorComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
+{
+  // see header file for class documentation
+  list.clear();
+  list.push_back( AliHLTTPCDefinitions::fgkUnpackedRawDataType );       
+  list.push_back( kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC );
+}
+
+AliHLTComponentDataType AliHLTTPCHWCFEmulatorComponent::GetOutputDataType()
+{
+  // see header file for class documentation
+  return kAliHLTMultipleDataType;
+}
+
+int AliHLTTPCHWCFEmulatorComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
+{
+  // see header file for class documentation
+  tgtList.clear();
+  tgtList.push_back(AliHLTTPCDefinitions::fgkHWClustersDataType | kAliHLTDataOriginTPC );
+  tgtList.push_back(AliHLTTPCDefinitions::fgkAliHLTDataTypeClusterMCInfo | kAliHLTDataOriginTPC );
+  return tgtList.size();
+}
+
+
+void AliHLTTPCHWCFEmulatorComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
+{
+  // see header file for class documentation
+  // XXX TODO: Find more realistic values.  
+  constBase = 0;
+  inputMultiplier = (6 * 0.4);
+}
+
+
+AliHLTComponent* AliHLTTPCHWCFEmulatorComponent::Spawn()
+{
+  // see header file for class documentation
+  return new AliHLTTPCHWCFEmulatorComponent();
+}
+
+void AliHLTTPCHWCFEmulatorComponent::GetOCDBObjectDescription( TMap* const targetMap){
+// Get a list of OCDB object description needed for the particular component
+  
+  if (!targetMap) return;
+  
+  // OCDB entries for component arguments
+  targetMap->Add(new TObjString("HLT/ConfigTPC/TPCHWClusterFinder"), new TObjString("component arguments, empty at the moment"));
+}
+
+
+int AliHLTTPCHWCFEmulatorComponent::DoInit( int argc, const char** argv )
+{
+  // see header file for class documentation
+
+  TString arguments = "";
+  for ( int i = 0; i < argc; i++ ) {
+    if ( !arguments.IsNull() ) arguments += " ";
+    arguments += argv[i];
+  }
+
+  return Configure( NULL, NULL, arguments.Data()  );
+}
+
+int AliHLTTPCHWCFEmulatorComponent::Reconfigure( const char* cdbEntry, const char* chainId )
+{
+  // Reconfigure the component from OCDB
+
+  return Configure( cdbEntry, chainId, NULL );
+}
+
+int AliHLTTPCHWCFEmulatorComponent::ScanConfigurationArgument(int argc, const char** argv)
+{
+  // see header file for class documentation
+  TString arguments = "";
+  for ( int i = 0; i < argc; i++ ) {
+    if ( !arguments.IsNull() ) arguments += " ";
+    arguments += argv[i];
+  }
+  return ReadConfigurationString(arguments);
+}
+
+
+
+void AliHLTTPCHWCFEmulatorComponent::SetDefaultConfiguration()
+{
+  // Set default configuration for the FPGA ClusterFinder Emulator component
+  // Some parameters can be later overwritten from the OCDB
+
+  fDoDeconvTime = 0;
+  fDoDeconvPad = 0;
+  fDoMC = 1;
+  fDoFlowControl = 0;
+  fDoSinglePadSuppression = 1;
+  fBypassMerger = 0;
+  fClusterLowerLimit = 0;
+  fSingleSeqLimit = 0;
+  fBenchmark.Reset();
+  fBenchmark.SetTimer(0,"total");
+  fBenchmark.SetTimer(1,"reco");    
+}
+
+int AliHLTTPCHWCFEmulatorComponent::ReadConfigurationString(  const char* arguments )
+{
+  // Set configuration parameters for the FPGA ClusterFinder Emulator component
+  // from the string
+
+  int iResult = 0;
+  if ( !arguments ) return iResult;
+
+  TString allArgs = arguments;
+  TString argument;
+  int bMissingParam = 0;
+
+  TObjArray* pTokens = allArgs.Tokenize( " " );
+
+  int nArgs =  pTokens ? pTokens->GetEntries() : 0;
+
+  for ( int i = 0; i < nArgs; i++ ) {
+    argument = ( ( TObjString* )pTokens->At( i ) )->GetString();
+    if ( argument.IsNull() ) continue;
+
+    if ( argument.CompareTo( "-deconvolute-time" ) == 0 ) {
+      if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+      fDoDeconvTime  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+      HLTInfo( "Time deconvolution is set to: %d", fDoDeconvTime );
+      continue;
+    }
+
+    if ( argument.CompareTo( "-deconvolute-pad" ) == 0 ) {
+      if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+      fDoDeconvPad  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+      HLTInfo( "Pad deconvolution is set to: %d", fDoDeconvPad );
+      continue;
+    }
+
+    if ( argument.CompareTo( "-deconvolute" ) == 0 ) {
+      if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+      fDoDeconvTime  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+      fDoDeconvPad  = fDoDeconvTime;
+      HLTInfo( "Time and pad deconvolution is set to: %d", fDoDeconvPad );
+      continue;
+    }
+    if ( argument.CompareTo( "-do-mc" ) == 0 ) {
+      if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+      fDoMC  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+      HLTInfo( "MC processing is set to: %d", fDoMC );
+      continue;
+    }
+
+    if ( argument.CompareTo( "-flow-control" ) == 0 ) {
+      if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+      fDoFlowControl  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+      HLTInfo( "Flow control is set to: %d", fDoFlowControl );
+      continue;
+    }
+
+    if ( argument.CompareTo( "-single-pad-suppression" ) == 0 ) {
+      if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+      fDoSinglePadSuppression  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+      HLTInfo( "Single pad suppression is set to: %d", fDoSinglePadSuppression );
+      continue;
+    }
+    
+    if ( argument.CompareTo( "-bypass-merger" ) == 0 ) {
+      if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+      fBypassMerger  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+      HLTInfo( "Bypassing merger is set to: %d", fBypassMerger );
+      continue;
+    }
+
+    if ( argument.CompareTo( "-cluster-lower-limit" ) == 0 ) {
+      if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+      fClusterLowerLimit  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+      HLTInfo( "Cluster lower limit is set to: %d", fClusterLowerLimit );
+      continue;
+    }
+
+    if ( argument.CompareTo( "-single-sequence-limit" ) == 0 ) {
+      if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+      fSingleSeqLimit  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+      HLTInfo( "Single sequence limit is set to: %d", fSingleSeqLimit );
+      continue;
+    }
+    
+    if ( argument.CompareTo( "-debug-level" ) == 0 ) {
+      if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
+      fDebug  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
+      HLTInfo( "Debug level is set to: %d", fDebug );
+      continue;
+    }
+    
+    HLTError( "Unknown option \"%s\"", argument.Data() );
+    iResult = -EINVAL;
+  }
+  delete pTokens;
+
+  if ( bMissingParam ) {
+    HLTError( "Specifier missed for parameter \"%s\"", argument.Data() );
+    iResult = -EINVAL;
+  }
+
+  return iResult;
+}
+
+
+int AliHLTTPCHWCFEmulatorComponent::ReadCDBEntry( const char* cdbEntry, const char* chainId )
+{
+  // Read configuration from OCDB
+
+  const char* defaultNotify = "";
+
+  if ( !cdbEntry ){
+    cdbEntry = "HLT/ConfigTPC/TPCHWClusterFinder";
+    defaultNotify = " (default)";
+    chainId = 0;
+  }
+
+  HLTInfo( "configure from entry \"%s\"%s, chain id %s", cdbEntry, defaultNotify, ( chainId != NULL && chainId[0] != 0 ) ? chainId : "<none>" );
+  AliCDBEntry *pEntry = AliCDBManager::Instance()->Get( cdbEntry );//,GetRunNo());
+  
+  if ( !pEntry ) {
+    HLTError( "cannot fetch object \"%s\" from CDB", cdbEntry );
+    return -EINVAL;
+  }
+
+  TObjString* pString = dynamic_cast<TObjString*>( pEntry->GetObject() );
+
+  if ( !pString ) {
+    HLTError( "configuration object \"%s\" has wrong type, required TObjString", cdbEntry );
+    return -EINVAL;
+  }
+
+  HLTInfo( "received configuration object string: \"%s\"", pString->GetString().Data() );
+
+  return  ReadConfigurationString( pString->GetString().Data() );
+}
+
+
+int AliHLTTPCHWCFEmulatorComponent::Configure( const char* cdbEntry, const char* chainId, const char *commandLine )
+{
+  // Configure the component
+  // There are few levels of configuration,
+  // parameters which are set on one step can be overwritten on the next step
+
+  //* read hard-coded values
+
+  SetDefaultConfiguration();
+
+  //* read the default CDB entry
+
+  int iResult1 = ReadCDBEntry( NULL, chainId );
+
+  //* read the actual CDB entry if required
+
+  int iResult2 = ( cdbEntry ) ? ReadCDBEntry( cdbEntry, chainId ) : 0;
+
+  //* read extra parameters from input (if they are)
+
+  int iResult3 = 0;
+
+  if ( commandLine && commandLine[0] != '\0' ) {
+    HLTInfo( "received configuration string from HLT framework: \"%s\"", commandLine );
+    iResult3 = ReadConfigurationString( commandLine );
+  }
+
+  return iResult1 ? iResult1 : ( iResult2 ? iResult2 : iResult3 );
+}
+
+
+int AliHLTTPCHWCFEmulatorComponent::DoDeinit()
+{
+  // see header file for class documentation 
+  return 0;
+}
+
+
+int AliHLTTPCHWCFEmulatorComponent::DoEvent( const AliHLTComponentEventData& evtData, 
+                                                       const AliHLTComponentBlockData* blocks, 
+                                                       AliHLTComponentTriggerData& /*trigData*/, AliHLTUInt8_t* outputPtr, 
+                                                       AliHLTUInt32_t& size, 
+                                                       vector<AliHLTComponentBlockData>& outputBlocks )
+{
+  // see header file for class documentation
+
+  int iResult=0;
+  AliHLTUInt32_t maxSize = size;
+  size = 0;
+  
+  if(!IsDataEvent()){
+    return 0;
+  }
+
+  fBenchmark.StartNewEvent();
+  fBenchmark.Start(0);
+
+  AliHLTUInt32_t configWord = AliHLTTPCHWCFEmulator::CreateConfiguration
+    ( fDoDeconvTime, fDoDeconvPad, fDoFlowControl, fDoSinglePadSuppression, fBypassMerger, fClusterLowerLimit, fSingleSeqLimit );
+
+  for ( unsigned long ndx = 0; ndx < evtData.fBlockCnt; ndx++ )
+    {
+      const AliHLTComponentBlockData* iter = blocks+ndx;
+      
+      if (  iter->fDataType != (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC) 
+           &&  iter->fDataType != AliHLTTPCDefinitions::fgkUnpackedRawDataType ) continue;
+
+      int slice = AliHLTTPCDefinitions::GetMinSliceNr( *iter );
+      int patch = AliHLTTPCDefinitions::GetMinPatchNr( *iter );
+      const char *str=Form("slice %d patch %d:", slice, patch);
+
+      fBenchmark.AddInput(iter->fSize);
+      if (!iter->fPtr) continue;
+      // create input block for the HW cluster finder
+
+      const AliHLTUInt32_t *rawEvent=0;
+      const AliHLTTPCClusterMCLabel *mcLabels = 0;
+      AliHLTUInt32_t rawEventSize32 = 0;
+      AliHLTUInt32_t nMCLabels = 0;
+
+      if( fCFSupport.CreateRawEvent( iter, rawEvent, rawEventSize32, mcLabels, nMCLabels )<0 ) continue; 
+      if( !fDoMC ){
+       mcLabels = 0;
+       nMCLabels = 0;
+      }
+
+      // book memory for the output
+      
+      AliHLTUInt32_t maxNClusters = rawEventSize32 + 1; // N 32-bit words in input
+      AliHLTUInt32_t clustersSize32 = maxNClusters*5;
+      AliHLTUInt32_t nOutputMC = maxNClusters;
+
+      AliHLTUInt32_t headerSize = sizeof(AliRawDataHeader);                   
+      AliHLTUInt8_t *outBlock = new AliHLTUInt8_t[ headerSize+clustersSize32*sizeof(AliHLTUInt32_t) ];
+      
+      AliHLTTPCClusterMCData *outMC = reinterpret_cast<AliHLTTPCClusterMCData *>(new AliHLTTPCClusterMCLabel[nOutputMC+1]);
+      
+      if( !outBlock || !outMC ){
+       HLTWarning("%s Not enouth memory!!!", str);
+       delete[] outBlock;
+       delete[] outMC;
+       continue;       
+      }
+      
+      // fill CDH header here, since the HW clusterfinder does not receive it
+      
+      AliRawDataHeader *cdhHeader = reinterpret_cast<AliRawDataHeader*>(iter->fPtr);
+      AliRawDataHeader *outCDHHeader = reinterpret_cast<AliRawDataHeader*>(outBlock);      
+      *outCDHHeader = *cdhHeader;
+      outCDHHeader->fSize = 0xFFFFFFFF;
+
+      AliHLTUInt32_t *outClusters = reinterpret_cast<AliHLTUInt32_t*> (outBlock + headerSize);
+     
+      fBenchmark.Start(1);
+      fCFEmulator.Init
+       ( fCFSupport.GetMapping(patch), configWord );
+      
+      int err = fCFEmulator.FindClusters( rawEvent, rawEventSize32, 
+                                         outClusters, clustersSize32, 
+                                         mcLabels, nMCLabels,
+                                         outMC );
+      fBenchmark.Stop(1);
+      if( err==-1 ){ HLTWarning("NULL input pointer (warning %d)",err);}
+      else if( err==-2 ){  HLTWarning("No space left in the output buffer (warning %d)",err); }
+      else if( err<0 ){ HLTWarning("HWCF emulator finished with error code %d",err); }
+      if( err<0 ){
+       delete[] outBlock;
+       delete[] outMC;
+       continue;
+      }
+
+      if( fDebug ){
+       printf("\nHWCF Emulator: output clusters for slice%d patch %d:\n",slice,patch);
+       for( AliHLTUInt32_t i=0; i<clustersSize32; i+=5 ){
+         AliHLTUInt32_t *c = outClusters+i;
+         AliHLTUInt32_t flag = (c[0]>>30);       
+         if( flag == 0x3){ //beginning of a cluster
+           int padRow  = (c[0]>>24)&0x3f;
+           int q  = (c[0]&0xFFFFFF)>>6; 
+           double p   = *((AliHLTFloat32_t*)&c[1]);
+           double t  = *((AliHLTFloat32_t*)&c[2]);
+           AliHLTFloat32_t p2 = *((AliHLTFloat32_t*)&c[3]);
+           AliHLTFloat32_t t2 = *((AliHLTFloat32_t*)&c[4]);
+           printf("N: %3d    R: %3d    C: %4d    P:  %7.4f    T:  %8.4f    DP: %6.4f    DT: %6.4f\n", 
+                  i/5+1, padRow, q, p, t, sqrt(p2-p*p), sqrt(t2-t*t));
+
+           if( outMC && outMC->fCount>0 ){
+             printf("        MC: (%3d,%6.1f) (%3d,%6.1f) (%3d,%6.1f)\n",
+                    outMC->fLabels[i/5].fClusterID[0].fMCID,outMC->fLabels[i/5].fClusterID[0].fWeight,
+                    outMC->fLabels[i/5].fClusterID[1].fMCID,outMC->fLabels[i/5].fClusterID[1].fWeight,
+                    outMC->fLabels[i/5].fClusterID[2].fMCID,outMC->fLabels[i/5].fClusterID[2].fWeight
+                    );
+           }
+         }
+       }
+      }
+          
+
+      AliHLTUInt32_t outSize = headerSize + clustersSize32*sizeof(AliHLTUInt32_t);
+      
+      if( size + outSize <= maxSize ){
+       
+       memcpy( outputPtr, outBlock, outSize );
+       
+       AliHLTComponentBlockData bd;
+       FillBlockData( bd );
+       bd.fOffset = size;
+       bd.fSize = outSize;
+       bd.fSpecification = iter->fSpecification;
+       bd.fDataType = AliHLTTPCDefinitions::fgkHWClustersDataType | kAliHLTDataOriginTPC;
+       outputBlocks.push_back( bd );
+       fBenchmark.AddOutput(bd.fSize);
+       size+= bd.fSize;
+       outputPtr+=bd.fSize;
+      } else {
+       HLTWarning( "Output buffer (%db) is too small, required %db", maxSize, size+outSize);
+       iResult=-ENOSPC;
+      }
+
+      if( fDoMC && outMC && outMC->fCount>0 ){
+       int s = sizeof(AliHLTTPCClusterMCData) + outMC->fCount*sizeof(AliHLTTPCClusterMCLabel);
+       if( size + s <= maxSize ){
+         memcpy( outputPtr, outMC, s );                  
+         AliHLTComponentBlockData bdMCInfo;
+         FillBlockData( bdMCInfo );
+         bdMCInfo.fOffset = size;
+         bdMCInfo.fSize = s;
+         bdMCInfo.fSpecification = iter->fSpecification;
+         bdMCInfo.fDataType = AliHLTTPCDefinitions::fgkAliHLTDataTypeClusterMCInfo | kAliHLTDataOriginTPC;
+         outputBlocks.push_back( bdMCInfo );
+         fBenchmark.AddOutput(bdMCInfo.fSize);
+         size+=bdMCInfo.fSize;
+         outputPtr+=bdMCInfo.fSize; 
+       } else {        
+         HLTWarning( "Output buffer (%db) is too small, required %db", maxSize, size+s);
+         iResult=-ENOSPC;          
+       }
+      }
+      
+      delete[] outBlock;
+      delete[] outMC;      
+    }
+  
+  fBenchmark.Stop(0);  
+  HLTInfo(fBenchmark.GetStatistics());
+  return iResult;
+}
+
+
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulatorComponent.h b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFEmulatorComponent.h
new file mode 100644 (file)
index 0000000..ed7f783
--- /dev/null
@@ -0,0 +1,155 @@
+#ifndef ALIHLTTPCHWCFEMULATORCOMPONENT_H
+#define ALIHLTTPCHWCFEMULATORCOMPONENT_H
+
+//* This file is property of and copyright by the ALICE HLT Project        * 
+//* ALICE Experiment at CERN, All rights reserved.                         *
+//* See cxx source for full Copyright notice                               *
+
+//  @file   AliHLTTPCHWCFEmulatorComponent.h
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  HLT Component interface for for FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+
+
+
+#include "AliHLTProcessor.h"
+#include "AliHLTComponentBenchmark.h"
+#include "AliHLTTPCHWCFSupport.h"
+#include "AliHLTTPCHWCFEmulator.h"
+
+class AliHLTTPCHWCFEmulator;
+class AliHLTTPCDigitReader;
+class AliTPCTransform;
+
+/**
+ * @class AliHLTTPCHWCFEmulatorComponent
+ * The FPGA clusterfinder emulator for TPC
+ * The component implements the interface methods of the @ref AliHLTProcessor
+ * The actual cluster finding algorithm is implemented in @ref AliHLTTPCHWCFEmulator
+ *
+ * <h2>General properties:</h2>
+ *
+ * Component ID: \b TPCHWClusterFinderEmulator <br>
+ * Library: \b libAliHLTTPC
+ * Input Data Types: @ref kAliHLTDataTypeDDLRaw or AliHLTTPCDefinitions::fgkUnpackedRawDataType <br>
+ * Output Data Types: @ref AliHLTTPCDefinitions::fgkHWClustersDataType and AliHLTTPCDefinitions::fgkAliHLTDataTypeClusterMCInfo <br> 
+ *
+ *
+ * Mandatory arguments: <br>
+ * <!-- NOTE: ignore the \li. <i> and </i>: it's just doxygen formatting -->
+ *
+ * Optional arguments: <br>
+ * <!-- NOTE: ignore the \li. <i> and </i>: it's just doxygen formatting -->
+ * \li -deconvolute <br>  
+ *      Turns on deconvolution.
+ * \li -do-mc <br>  
+ *      Provide mc labels for found clusters
+ *
+ * <h2>Default CDB entries:</h2>
+ * None
+ *
+ * @ingroup alihlt_tpc_components
+ */
+class AliHLTTPCHWCFEmulatorComponent : public AliHLTProcessor
+{
+ public:      
+  /**
+   * constructor 
+   */
+  AliHLTTPCHWCFEmulatorComponent();
+  /** destructor */
+  virtual ~AliHLTTPCHWCFEmulatorComponent();
+  
+  // Public functions to implement AliHLTComponent's interface.
+  // These functions are required for the registration process
+
+  /** interface function, see AliHLTComponent for description */
+  const char* GetComponentID();
+
+  /** interface function, see AliHLTComponent for description */
+  void GetInputDataTypes( vector<AliHLTComponentDataType>& list);
+
+  /** interface function, see AliHLTComponent for description */
+  AliHLTComponentDataType GetOutputDataType();
+
+  /** interface function, see AliHLTComponent for description */
+  int GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList);
+
+  /** interface function, see AliHLTComponent for description */
+  virtual void GetOutputDataSize( unsigned long& constBase, double& inputMultiplier );
+
+  /** interface function, see AliHLTComponent for description */
+  AliHLTComponent* Spawn();
+
+  /** interface function, see @ref AliHLTComponent for description */
+  void GetOCDBObjectDescription( TMap* const targetMap);
+
+ protected:
+  
+  // Protected functions to implement AliHLTComponent's interface.
+  // These functions provide initialization as well as the actual processing
+  // capabilities of the component. 
+  
+     /** @copydoc AliHLTComponent::DoInit
+      */
+    int DoInit( int argc, const char **argv );
+
+    /** @copydoc AliHLTComponent::DoDeinit
+     */
+    int DoDeinit();
+
+    /**  @copydoc @ref AliHLTComponent::Reconfigure
+     */
+    int Reconfigure( const char* cdbEntry, const char* chainId );
+
+    /**  @copydoc @ref AliHLTComponent::ScanConfigurationArgument
+     */
+    int ScanConfigurationArgument(int argc, const char** argv);
+
+    /** @copydoc @ref AliHLTProcessor::DoEvent
+     */
+    int DoEvent( const AliHLTComponentEventData& evtData, const AliHLTComponentBlockData* blocks, 
+                AliHLTComponentTriggerData& trigData, AliHLTUInt8_t* outputPtr, 
+                AliHLTUInt32_t& size, vector<AliHLTComponentBlockData>& outputBlocks );
+
+     
+    using AliHLTProcessor::DoEvent;
+  
+ private:
+
+  /** copy constructor prohibited */
+  AliHLTTPCHWCFEmulatorComponent(const AliHLTTPCHWCFEmulatorComponent&);
+
+  /** assignment operator prohibited */
+  AliHLTTPCHWCFEmulatorComponent& operator=(const AliHLTTPCHWCFEmulatorComponent&);
+
+  /** Set default configuration */
+  void SetDefaultConfiguration();
+
+  /** scan configuration string */
+  int ReadConfigurationString(  const char* arguments );
+
+  /** read configuration from OCDB */
+  int ReadCDBEntry( const char* cdbEntry, const char* chainId );
+
+  /** read configuration from multiple sources */
+  int Configure( const char* cdbEntry, const char* chainId, const char *commandLine );
+
+  Bool_t fDoDeconvTime;            // flag to deconvolute in time direction
+  Bool_t fDoDeconvPad;             // flag to deconvolute in pad direction
+  Bool_t fDoMC;                    // flag to provide MC labels
+  Bool_t fDoFlowControl;           // flag to control the data
+  Bool_t fDoSinglePadSuppression;  // flag for single pad suppression
+  Bool_t fBypassMerger;            // flag to bypass cluster merging between pads
+  AliHLTUInt8_t fClusterLowerLimit; // cut clusters at this charge value
+  AliHLTUInt8_t fSingleSeqLimit;    // cut sequences at this charge value
+  
+  Int_t fDebug; // debug level
+  AliHLTTPCHWCFSupport fCFSupport;     // !transient
+  AliHLTTPCHWCFEmulator fCFEmulator;   // !transient
+  AliHLTComponentBenchmark fBenchmark; // benchmark
+  
+};
+#endif
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFExtractorUnit.cxx b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFExtractorUnit.cxx
new file mode 100644 (file)
index 0000000..4403cc5
--- /dev/null
@@ -0,0 +1,248 @@
+//****************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project          * 
+//* ALICE Experiment at CERN, All rights reserved.                           *
+//*                                                                          *
+//* Primary Authors: Sergey Gorbunov, Torsten Alt                            *
+//* Developers:      Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
+//*                  Torsten Alt <talt@cern.ch>                              *
+//*                  for The ALICE HLT Project.                              *
+//*                                                                          *
+//* Permission to use, copy, modify and distribute this software and its     *
+//* documentation strictly for non-commercial purposes is hereby granted     *
+//* without fee, provided that the above copyright notice appears in all     *
+//* copies and that both the copyright notice and this permission notice     *
+//* appear in the supporting documentation. The authors make no claims       *
+//* about the suitability of this software for any purpose. It is            *
+//* provided "as is" without express or implied warranty.                    *
+//****************************************************************************
+
+//  @file   AliHLTTPCHWCFExtractorUnit.cxx
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @date  
+//  @brief  Channel Extractor unit of FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note 
+
+#include "AliHLTTPCHWCFExtractorUnit.h"
+
+AliHLTTPCHWCFExtractorUnit::AliHLTTPCHWCFExtractorUnit()
+  :
+  fStatus(kReadingData),
+  fInput(0),
+  fInputStatus(kEmpty),
+  fkMapping(0),  
+  fBunch(fMemory),
+  fPendingOutput(0),
+  fChannelNumWordsLeft(0),
+  fBunchNumWordsLeft(0),  
+  fkMCLabels(0),
+  fNMCLabels(0),
+  fCurrentMCLabel(0)
+{
+  //constructor 
+  fBunch->fFlag = 0; // wait for the next channel
+}
+
+AliHLTTPCHWCFExtractorUnit::~AliHLTTPCHWCFExtractorUnit()
+{   
+  //destructor  
+}
+
+AliHLTTPCHWCFExtractorUnit::AliHLTTPCHWCFExtractorUnit(const AliHLTTPCHWCFExtractorUnit&)
+  :
+  fStatus(kReadingData),
+  fInput(0),
+  fInputStatus(kEmpty),
+  fkMapping(0),
+  fBunch(fMemory),
+  fPendingOutput(0),
+  fChannelNumWordsLeft(0),
+  fBunchNumWordsLeft(0),  
+  fkMCLabels(0),
+  fNMCLabels(0),
+  fCurrentMCLabel(0)
+{
+  // dummy
+}
+
+AliHLTTPCHWCFExtractorUnit& AliHLTTPCHWCFExtractorUnit::operator=(const AliHLTTPCHWCFExtractorUnit&)
+{
+  // dummy  
+  return *this;
+}
+
+int AliHLTTPCHWCFExtractorUnit::Init( const AliHLTUInt32_t *mapping, const AliHLTTPCClusterMCLabel *mcLabels, AliHLTUInt32_t nMCLables )
+{
+  // initialisation
+
+  fStatus = kReadingData;
+  fInput = 0;
+  fInputStatus = kEmpty;
+  fkMapping = mapping;
+  fBunch->fFlag = 0; // wait for the next channel
+  fBunch->fData.clear();
+  fBunch->fMC.clear();
+  fPendingOutput = 0;  
+  fkMCLabels = mcLabels;
+  fNMCLabels = nMCLables;
+  fCurrentMCLabel = 0;
+  if( !fkMapping ) return  -1;
+  return 0;
+}
+
+int AliHLTTPCHWCFExtractorUnit::InputEndOfData()
+{
+  // input "end of data" signal 
+
+  int ret = 0;
+  if( fInputStatus != kEmpty ) ret = -1;
+  fInputStatus = kEndOfData;
+  return ret;
+}
+
+int AliHLTTPCHWCFExtractorUnit::InputStream( AliHLTUInt32_t word )
+{
+  // input stream of data
+
+  int ret = 0;
+  if( fInputStatus != kEmpty ) ret = -1;
+  fInputStatus = kData;
+  fInput = word;
+  return ret;
+}
+
+const AliHLTTPCHWCFBunch *AliHLTTPCHWCFExtractorUnit::OutputStream()
+{
+  // output stream of data
+  
+  AliHLTTPCHWCFExtractorInputStatus inpStatus = fInputStatus;
+  fInputStatus = kEmpty;
+
+  if( fPendingOutput ){
+    fPendingOutput = 0;
+    return fBunch;
+  }
+
+  if( fStatus == kStop ) return 0;  
+  if( !fkMapping ) inpStatus = kEndOfData;
+
+  AliHLTTPCHWCFBunch *oldBunch = fBunch;
+  AliHLTTPCHWCFBunch *newBunch = ( fBunch == fMemory ) ?fMemory+1 :fMemory;
+
+  if( fStatus == kFinishing || inpStatus == kEndOfData){
+    if( fBunch->fFlag == 1 ){
+      fBunch = newBunch;
+      fPendingOutput = 1;
+    }
+    fBunch->fData.clear();
+    fBunch->fMC.clear();
+    fBunch->fFlag = 3; // end of data
+    fStatus = kStop;    
+    return oldBunch;   
+  }
+
+  if( inpStatus == kEmpty ) return 0;  
+
+  AliHLTUInt32_t flag = (fInput >> 30); 
+  
+  if( flag >= 0x2 ){ //  RCU trailer  
+    if( fBunch->fFlag == 1 ){
+      fBunch = newBunch;
+      fPendingOutput = 1;
+    }
+    fBunch->fData.clear();
+    fBunch->fMC.clear();
+    fBunch->fFlag = 2; // rcu
+    fBunch->fData.push_back(fInput);
+    fStatus = ( flag == 0x2 ) ?kReadingRCU :kFinishing;
+    return oldBunch;   
+  }
+  
+  if( fStatus!=kReadingData ) return 0;  
+  
+  if( flag==0x1 ){ // header of a new channel
+        
+    if( fBunch->fFlag==1 ){
+      //cout<<"Extractor: Bunch finished: "<<fBunch->fFlag
+      //<<" R "<<fBunch->fRow<<" P "<<fBunch->fPad<<" T "<<fBunch->fTime<<" NS "<<fBunch->fNSignals<<endl;
+      fBunch = newBunch;
+    }
+    AliHLTUInt32_t  hwAddress = fInput & 0xFFF;
+
+    fBunch->fFlag = 1;
+    fBunch->fBranch = (hwAddress >> 11) & 0x1;
+    if( hwAddress>=fkMapping[0] ) fBunch->fFlag = 0; //readout errors
+    else{
+      AliHLTUInt32_t configWord = fkMapping[hwAddress+1];
+      fBunch->fRow = (configWord>>8) & 0x3F;
+      fBunch->fPad =  configWord & 0xFF;
+      fBunch->fBorder = (configWord>>14) & 0x1;
+      if( !( (configWord>>15) & 0x1 ) ) fBunch->fFlag = 0;// channel not active
+      fBunch->fGain = (configWord>>16 ) & 0x1FFF;
+    }
+    fBunch->fData.clear();
+    fBunch->fMC.clear();
+    fBunch->fTime = 0xFFFFFFFF;
+    fChannelNumWordsLeft= (fInput >> 16) & 0x3FF; // payload size in 10-bit words
+    fBunchNumWordsLeft = 0;
+   
+    if( (fInput >> 29) & 0x1 ) fBunch->fFlag = 0; // there were readout errors
+
+    //cout<<"Extractor: Header of new channel F "<<fBunch->fFlag
+    //<<" R "<<fBunch->fRow<<" P "<<fBunch->fPad<<" NWords10 "<<fChannelNumWordsLeft<<endl;
+  
+  } else if( flag==0x0 ){ 
+    
+    // bunch data, read three 10-bit words
+    
+    for( int ishift=20; fBunch->fFlag==1 && ishift>=0; ishift-=10 ){
+      
+      AliHLTUInt32_t word10 = (fInput >> ishift) & 0x3FF;
+      
+      if( fChannelNumWordsLeft <= 0 || fBunchNumWordsLeft <= 0 ){ // bunch finished
+       //cout<<"Extractor: Bunch finished: "<<fBunch->fFlag
+       //<<" R "<<fBunch->fRow<<" P "<<fBunch->fPad<<" T "<<fBunch->fTime<<" NS "<<fBunch->fNSignals<<endl;    
+       fBunch = newBunch; // push to the output
+       
+       if( fChannelNumWordsLeft <= 0 ){ // wait for the next channel
+         fBunch->fFlag = 0;
+       } else {
+         fBunch->fFlag = 1;
+         fBunch->fRow  = oldBunch->fRow;
+         fBunch->fPad = oldBunch->fPad;
+         fBunch->fBranch = oldBunch->fBranch;
+         fBunch->fBorder = oldBunch->fBorder;
+         fBunch->fGain = oldBunch->fGain;
+         fBunch->fData.clear();
+         fBunch->fMC.clear();    
+         fBunch->fTime = 0xFFFFFFFF;
+         fBunchNumWordsLeft = word10;
+       }
+      } else { // continue the brunch
+       if( fBunch->fTime > AliHLTTPCHWCFDefinitions::kMaxNTimeBins ){ // time has not been read so far
+         fBunch->fTime = word10;
+         //cout<<"Extractor: Bunch time: "<<fBunch->fTime<<endl;
+       } else { // read the signal
+         fBunch->fData.push_back(word10);
+         if( fkMCLabels && fCurrentMCLabel<=fNMCLabels ){
+           fBunch->fMC.push_back( fkMCLabels[fCurrentMCLabel].fClusterID[0] );
+           fBunch->fMC.push_back( fkMCLabels[fCurrentMCLabel].fClusterID[1] );
+           fBunch->fMC.push_back( fkMCLabels[fCurrentMCLabel].fClusterID[2] );
+           fCurrentMCLabel++;
+         }
+         //cout<<"Extractor: Bunch signal["<<fBunch->fNSignals<<"]: "<<word10<<endl;
+       }
+      }
+      fChannelNumWordsLeft--;
+      fBunchNumWordsLeft--;   
+    }
+  }
+
+  if( fBunch==newBunch && oldBunch->fFlag==1 && oldBunch->fData.size()>0 ){
+    return oldBunch;
+  }
+  return 0;
+}
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFExtractorUnit.h b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFExtractorUnit.h
new file mode 100644 (file)
index 0000000..6414c41
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef ALIHLTTPCHWCFEXTRACTORUNIT_H
+#define ALIHLTTPCHWCFEXTRACTORUNIT_H
+//* This file is property of and copyright by the ALICE HLT Project        * 
+//* ALICE Experiment at CERN, All rights reserved.                         *
+//* See cxx source for full Copyright notice                               *
+
+//  @file   AliHLTTPCHWCFExtractorUnit.h
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  Channel Extractor unit of FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+
+#include "AliHLTDataTypes.h"
+#include "AliHLTTPCHWCFDataTypes.h"
+
+class AliHLTTPCHWCFExtractorUnit
+{
+ public:  
+
+  /** standard constructor */
+  AliHLTTPCHWCFExtractorUnit();
+  
+  /** destructor */
+  ~AliHLTTPCHWCFExtractorUnit();
+
+  /** initialisation **/
+  int Init( const AliHLTUInt32_t *mapping, const AliHLTTPCClusterMCLabel *mcLabels, AliHLTUInt32_t nMCLabels );
+
+  /** input stream of data **/
+  int InputStream( AliHLTUInt32_t word );
+
+  /** input "end of data" signal **/  
+  int InputEndOfData();
+
+  /** output stream of data **/
+  const AliHLTTPCHWCFBunch *OutputStream();
+
+ private: 
+
+  enum AliHLTTPCHWCFExtractorStatus{ kReadingData, kReadingRCU, kFinishing, kStop };  
+  enum AliHLTTPCHWCFExtractorInputStatus{ kEmpty, kData, kEndOfData };  
+  
+  /** copy constructor prohibited */
+  AliHLTTPCHWCFExtractorUnit(const AliHLTTPCHWCFExtractorUnit&);
+  /** assignment operator prohibited */
+  AliHLTTPCHWCFExtractorUnit& operator=(const AliHLTTPCHWCFExtractorUnit&);  
+
+  AliHLTTPCHWCFExtractorStatus fStatus; // status of the unit
+  AliHLTUInt32_t fInput;  // current input
+  AliHLTTPCHWCFExtractorInputStatus fInputStatus; // input status
+  const AliHLTUInt32_t *fkMapping; // mapping array
+  AliHLTTPCHWCFBunch fMemory[2];  // memory for current bunch and pending output 
+  AliHLTTPCHWCFBunch *fBunch;     // current bunch
+  bool fPendingOutput; // is there something in the output buffer
+
+  AliHLTInt32_t fChannelNumWordsLeft; // n 10-bit words left in the channel
+  AliHLTInt32_t fBunchNumWordsLeft;// n 10-bit words left in the bunch
+
+  const AliHLTTPCClusterMCLabel *fkMCLabels; // pointer to mc labels
+  AliHLTUInt32_t fNMCLabels;                 // N mc labels
+  AliHLTUInt32_t fCurrentMCLabel;            // mc label to read next
+};
+
+#endif
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFMergerUnit.cxx b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFMergerUnit.cxx
new file mode 100644 (file)
index 0000000..1a695ac
--- /dev/null
@@ -0,0 +1,219 @@
+//****************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project          * 
+//* ALICE Experiment at CERN, All rights reserved.                           *
+//*                                                                          *
+//* Primary Authors: Sergey Gorbunov, Torsten Alt                            *
+//* Developers:      Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
+//*                  Torsten Alt <talt@cern.ch>                              *
+//*                  for The ALICE HLT Project.                              *
+//*                                                                          *
+//* Permission to use, copy, modify and distribute this software and its     *
+//* documentation strictly for non-commercial purposes is hereby granted     *
+//* without fee, provided that the above copyright notice appears in all     *
+//* copies and that both the copyright notice and this permission notice     *
+//* appear in the supporting documentation. The authors make no claims       *
+//* about the suitability of this software for any purpose. It is            *
+//* provided "as is" without express or implied warranty.                    *
+//****************************************************************************
+
+//  @file   AliHLTTPCHWCFMergerUnit.cxx
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @date   
+//  @brief  Channel Merger unit of FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note 
+
+#include "AliHLTTPCHWCFMergerUnit.h"
+#include <iostream>
+
+AliHLTTPCHWCFMergerUnit::AliHLTTPCHWCFMergerUnit()
+  :
+  fDebug(0),
+  fMatchDistance(3),
+  fMatchTimeFollow(1),
+  fDeconvolute(0),
+  fByPassMerger(0),
+  fInput()
+{
+  //constructor 
+  Init();
+}
+
+
+AliHLTTPCHWCFMergerUnit::~AliHLTTPCHWCFMergerUnit()
+{   
+  //destructor 
+}
+
+AliHLTTPCHWCFMergerUnit::AliHLTTPCHWCFMergerUnit(const AliHLTTPCHWCFMergerUnit&)
+  :
+  fDebug(0),
+  fMatchDistance(3),
+  fMatchTimeFollow(1),
+  fDeconvolute(0),
+  fByPassMerger(0),
+  fInput()
+{
+  // dummy
+  Init();
+}
+
+AliHLTTPCHWCFMergerUnit& AliHLTTPCHWCFMergerUnit::operator=(const AliHLTTPCHWCFMergerUnit&)
+{
+  // dummy  
+  return *this;
+}
+
+int AliHLTTPCHWCFMergerUnit::Init()
+{
+  // initialise 
+
+  fInput.fFlag = 0;
+  for( int i=0; i<2; i++ ){
+    fSearchRange[i] = fMemory[i];
+    fInsertRange[i] = (fMemory[i]+AliHLTTPCHWCFDefinitions::kMaxNTimeBins);
+    fSearchStart[i] = 0;
+    fSearchEnd[i] = 0;
+    fInsertEnd[i] = 0;
+    fInsertRow[i] = -1;
+    fInsertPad[i] = -1;
+  }    
+  return 0;
+}
+
+int AliHLTTPCHWCFMergerUnit::InputStream( const AliHLTTPCHWCFClusterFragment *fragment )
+{
+  // input stream of data 
+
+  fInput.fFlag = 0;
+
+  if( fragment ){
+    fInput = *fragment;
+    fInput.fSlope = 0;
+    fInput.fLastQ = fInput.fQ;
+    if( fDebug ){
+      std::cout<<"Merger: input F: "<<fragment->fFlag<<" R: "<<fragment->fRow
+              <<" Q: "<<(fragment->fQ>>AliHLTTPCHWCFDefinitions::kFixedPoint)
+              <<" P: "<<fragment->fPad<<" Tmean: "<<fragment->fTMean;          
+      if( fragment->fFlag==1 && fragment->fQ > 0 ){
+       std::cout<<" Pw: "<<((float)fragment->fP)/fragment->fQ
+                <<" Tw: "<<((float)fragment->fT)/fragment->fQ;
+      }
+      std::cout<<std::endl;
+    }
+  }
+  return 0;
+}
+
+const AliHLTTPCHWCFClusterFragment *AliHLTTPCHWCFMergerUnit::OutputStream()
+{
+  // output stream of data 
+
+  if( fInput.fFlag==0 ) return 0;
+
+  if( fByPassMerger ){
+    fInsertRange[0][0] = fInput;
+    fInput.fFlag = 0;
+    return &fInsertRange[0][0];
+  }
+
+  if( fInput.fFlag!=1 ){
+
+    for( int ib=0; ib<2; ib++){
+      
+      // move insert range to search range
+      
+      if( fSearchStart[ib]>=fSearchEnd[ib] && fInsertEnd[ib]>0 ){      
+       AliHLTTPCHWCFClusterFragment *tmp = fSearchRange[ib];
+       fSearchRange[ib] = fInsertRange[ib];
+       fSearchStart[ib] = 0;
+       fSearchEnd[ib] = fInsertEnd[ib];
+       fInsertRange[ib] = tmp;
+       fInsertEnd[ib] = 0;
+       fInsertPad[ib]++;
+      }    
+
+      // flush the search range
+  
+      if( fSearchStart[ib]<fSearchEnd[ib] ){
+      fSearchStart[ib]++;
+      return &(fSearchRange[ib][fSearchStart[ib]-1]);
+      }    
+    
+      fInsertRow[ib] = -1;
+      fInsertPad[ib] = -1;
+    }
+    
+    fInsertRange[0][0] = fInput; // forward the input
+    fInput.fFlag = 0;
+    return &fInsertRange[0][0];  
+  }
+
+  if( fInput.fFlag!=1 ) return 0; // should not happen
+
+  int ib = fInput.fBranch;
+  
+  // move insert range to search range
+    
+  if( (int)fInput.fRow!=fInsertRow[ib] || (int)fInput.fPad!=fInsertPad[ib] ){
+    
+    if( fSearchStart[ib]>=fSearchEnd[ib] && fInsertEnd[ib]>0 ){
+      // cout<<"move insert range pad "<<fInsertPad[ib]<<endl;
+      AliHLTTPCHWCFClusterFragment *tmp = fSearchRange[ib];
+      fSearchRange[ib] = fInsertRange[ib];
+      fSearchStart[ib] = 0;
+      fSearchEnd[ib] = fInsertEnd[ib];
+      fInsertRange[ib] = tmp;
+      fInsertEnd[ib] = 0;
+      fInsertPad[ib]++;
+    }
+  }
+
+  // flush the search range
+  
+  if( (int)fInput.fRow!=fInsertRow[ib] || (int)fInput.fPad!=fInsertPad[ib] ){
+    if( fSearchStart[ib]<fSearchEnd[ib] ){
+      //cout<<"push from search range at "<<fSearchStart[ib]<<" of "<<fSearchEnd[ib]<<endl;
+      fSearchStart[ib]++;
+      return &(fSearchRange[ib][fSearchStart[ib]-1]);
+    }
+  }
+    
+  fInsertRow[ib] = fInput.fRow;
+  fInsertPad[ib] = fInput.fPad;
+  
+  // flush the search range
+  
+  if( fSearchStart[ib]<fSearchEnd[ib]  && fSearchRange[ib][fSearchStart[ib]].fTMean>=fInput.fTMean+fMatchDistance
+      ){
+    //cout<<"push from search range at "<<fSearchStart[ib]<<" of "<<fSearchEnd[ib]<<endl;
+    fSearchStart[ib]++;
+    return &(fSearchRange[ib][fSearchStart[ib]-1]);
+  }
+
+  // merge 
+    
+  while( fSearchStart[ib]<fSearchEnd[ib]  && fSearchRange[ib][fSearchStart[ib]].fTMean+fMatchDistance>fInput.fTMean ){
+    AliHLTTPCHWCFClusterFragment &s = fSearchRange[ib][fSearchStart[ib]++];
+    if( fDeconvolute && s.fSlope && s.fLastQ<fInput.fLastQ ){
+      //cout<<"push from search range at "<<fSearchStart[ib]-1<<" of "<<fSearchEnd[ib]<<endl;
+      return &s;
+    }
+    // cout<<"merge search range at "<<fSearchStart-1<<" of "<<fSearchEnd<<endl;
+    if( !fInput.fSlope && s.fLastQ > fInput.fQ ) fInput.fSlope = 1;
+    fInput.fQ += s.fQ;
+    fInput.fT += s.fT;
+    fInput.fT2 += s.fT2;
+    fInput.fP += s.fP;
+    fInput.fP2 += s.fP2;
+    fInput.fMC.insert(fInput.fMC.end(), s.fMC.begin(), s.fMC.end());
+    if( !fMatchTimeFollow ) fInput.fTMean = s.fTMean;
+  }
+  
+  // insert 
+  
+  fInsertRange[ib][fInsertEnd[ib]++] = fInput;
+  fInput.fFlag = 0;
+  return 0;
+}
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFMergerUnit.h b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFMergerUnit.h
new file mode 100644 (file)
index 0000000..f11e056
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef ALIHLTTPCHWCFMERGERUNIT_H
+#define ALIHLTTPCHWCFMERGERUNIT_H
+
+//* This file is property of and copyright by the ALICE HLT Project        * 
+//* ALICE Experiment at CERN, All rights reserved.                         *
+//* See cxx source for full Copyright notice                               *
+
+
+#include "AliHLTTPCHWCFDataTypes.h"
+
+
+//  @class   AliHLTTPCHWCFMergerUnit
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  Channel Merger unit of FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+//
+class AliHLTTPCHWCFMergerUnit
+{
+ public:  
+
+  /** standard constructor */
+  AliHLTTPCHWCFMergerUnit();
+  
+  /** destructor */
+  ~AliHLTTPCHWCFMergerUnit();
+
+  /** do cluster deconvolution in pad direction */
+  void SetDebugLevel( int val ){ fDebug = val; }
+
+  /** do cluster deconvolution in pad direction */
+  void SetDeconvolution( bool val ){ fDeconvolute = val; }
+
+  /** bypass the merger */
+  void SetByPassMerger( bool val  ){ fByPassMerger = val; }
+
+  /** set max distance in timebins for matching fragments */
+  void SetMatchDistance( unsigned int val ){ fMatchDistance = val; }
+  
+  /** update MeanTime value when merging fragments */
+  void SetMatchTimeFollow( bool val ){ fMatchTimeFollow = val; }
+
+ /** initialise */
+  int Init();
+  
+  /** input stream of data */
+  int InputStream( const AliHLTTPCHWCFClusterFragment *fragment );
+
+  /** output stream of data */
+  const AliHLTTPCHWCFClusterFragment *OutputStream();
+
+ private: 
+
+  /** copy constructor prohibited */
+  AliHLTTPCHWCFMergerUnit(const AliHLTTPCHWCFMergerUnit&);
+  /** assignment operator prohibited */
+  AliHLTTPCHWCFMergerUnit& operator=(const AliHLTTPCHWCFMergerUnit&);  
+  
+  int  fDebug; // debug level
+  unsigned int fMatchDistance; // max distance in timebins for matching fragments
+  bool fMatchTimeFollow;    // update MeanTime value when merging fragments 
+  bool fDeconvolute; // do cluster deconvolution in pad direction
+  bool fByPassMerger;// bypass the merger 
+  AliHLTTPCHWCFClusterFragment fInput; // current input
+  AliHLTTPCHWCFClusterFragment fMemory[2][AliHLTTPCHWCFDefinitions::kMaxNTimeBins*2]; // memory for 2 channels
+  AliHLTTPCHWCFClusterFragment *fSearchRange[2]; // search range array
+  AliHLTTPCHWCFClusterFragment *fInsertRange[2]; // insert range array
+  int fSearchStart[2];  // index of the first candidate in SR
+  int fSearchEnd[2];    // index of end of SR
+  int fInsertEnd[2];    // index of end of IR
+  int fInsertRow[2];    // current row number in IR
+  int fInsertPad[2];    // current pad number in IR
+};
+
+#endif
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFProcessorUnit.cxx b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFProcessorUnit.cxx
new file mode 100644 (file)
index 0000000..6f704ed
--- /dev/null
@@ -0,0 +1,162 @@
+//****************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project          * 
+//* ALICE Experiment at CERN, All rights reserved.                           *
+//*                                                                          *
+//* Primary Authors: Sergey Gorbunov, Torsten Alt                            *
+//* Developers:      Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
+//*                  Torsten Alt <talt@cern.ch>                              *
+//*                  for The ALICE HLT Project.                              *
+//*                                                                          *
+//* Permission to use, copy, modify and distribute this software and its     *
+//* documentation strictly for non-commercial purposes is hereby granted     *
+//* without fee, provided that the above copyright notice appears in all     *
+//* copies and that both the copyright notice and this permission notice     *
+//* appear in the supporting documentation. The authors make no claims       *
+//* about the suitability of this software for any purpose. It is            *
+//* provided "as is" without express or implied warranty.                    *
+//****************************************************************************
+
+//  @file   AliHLTTPCHWCFProcessorUnit.cxx
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @date   
+//  @brief  Channel Processor unit of FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note 
+
+#include "AliHLTTPCHWCFProcessorUnit.h"
+#include <iostream>
+
+
+AliHLTTPCHWCFProcessorUnit::AliHLTTPCHWCFProcessorUnit()
+  :
+  fOutput(),
+  fkBunch(0),
+  fBunchIndex(0),
+  fDeconvolute(0),
+  fSingleSeqLimit(0)
+{
+  //constructor 
+  Init();
+}
+
+
+AliHLTTPCHWCFProcessorUnit::~AliHLTTPCHWCFProcessorUnit()
+{   
+  //destructor 
+}
+
+AliHLTTPCHWCFProcessorUnit::AliHLTTPCHWCFProcessorUnit(const AliHLTTPCHWCFProcessorUnit&)
+  :
+  fOutput(),
+  fkBunch(0),
+  fBunchIndex(0),
+  fDeconvolute(0),
+  fSingleSeqLimit(0)
+{
+  // dummy
+  Init();
+}
+
+AliHLTTPCHWCFProcessorUnit& AliHLTTPCHWCFProcessorUnit::operator=(const AliHLTTPCHWCFProcessorUnit&)
+{
+  // dummy  
+  return *this;
+}
+
+int AliHLTTPCHWCFProcessorUnit::Init()
+{
+  // initialise  
+
+  fkBunch = 0;
+  return 0;
+}
+
+int AliHLTTPCHWCFProcessorUnit::InputStream( const AliHLTTPCHWCFBunch *bunch )
+{
+  // input stream of data 
+  
+  //if( bunch && bunch->fRow==0 ){
+  //std::cout<<"Processor: input bunch F "<<bunch->fFlag<<" R "<<bunch->fRow<<" P "<<bunch->fPad <<" Br "<<bunch->fBranch<<" bord "<<bunch->fBorder
+  //<<" Time "<<bunch->fTime<<" NS= "<<bunch->fData.size()<<std::endl;
+  //}
+  fkBunch = bunch;
+  fBunchIndex = 0;
+  return 0;
+}
+
+const AliHLTTPCHWCFClusterFragment *AliHLTTPCHWCFProcessorUnit::OutputStream()
+{ 
+  // output stream of data 
+
+  if( !fkBunch ) return 0;
+  
+  fOutput.fFlag = fkBunch->fFlag;
+  fOutput.fRow = fkBunch->fRow;
+  fOutput.fPad = fkBunch->fPad;
+  fOutput.fBranch = fkBunch->fBranch;
+  fOutput.fBorder = fkBunch->fBorder;  
+  fOutput.fQ = 0;
+  fOutput.fT = 0;
+  fOutput.fT2 = 0;
+  fOutput.fP = 0;
+  fOutput.fP2 = 0;
+  fOutput.fTMean =  fkBunch->fTime;
+
+  fOutput.fMC.clear();
+  
+  if( fkBunch->fFlag==2 && fkBunch->fData.size()==1 ){ // rcu trailer word, forward it 
+    fOutput.fRow = fkBunch->fData[0];
+  }    
+  
+  if( fkBunch->fFlag >1 ){
+    fkBunch = 0;
+    fBunchIndex = 0;
+    return &fOutput;
+  }
+
+  if( fkBunch->fFlag < 1 ) return 0;
+
+
+  if( fBunchIndex >= fkBunch->fData.size() || fkBunch->fTime < fBunchIndex ) return 0;  
+
+  AliHLTInt32_t bunchTime0 = fkBunch->fTime - fBunchIndex;
+  AliHLTInt32_t bunchTime = bunchTime0;
+
+  AliHLTUInt64_t qLast = 0;
+  bool slope = 0;
+  AliHLTUInt32_t length = 0;
+  for( ; fBunchIndex<fkBunch->fData.size() && bunchTime>=0; fBunchIndex++, bunchTime--, length++ ){
+    AliHLTUInt64_t q = fkBunch->fData[fBunchIndex]*fkBunch->fGain;
+    if( fDeconvolute && slope && q>qLast ){
+      cout<<"deconvolution time!!!"<<endl;
+      if( length==1 && fOutput.fQ<fSingleSeqLimit ){
+       fOutput.fQ = 0;
+       fOutput.fT = 0;
+       fOutput.fT2 = 0;
+       fOutput.fP = 0;
+       fOutput.fP2 = 0;
+       bunchTime0 = fkBunch->fTime - fBunchIndex;
+       qLast = 0;
+       slope = 0;
+       length = 0;
+      } else {      
+       break;
+      }
+    }
+    if( q<qLast ) slope = 1;
+    qLast = q;
+    fOutput.fQ += q;
+    fOutput.fT += q*bunchTime;
+    fOutput.fT2+= q*bunchTime*bunchTime;
+    fOutput.fP += q*fkBunch->fPad;
+    fOutput.fP2+= q*fkBunch->fPad*fkBunch->fPad;
+    fOutput.fMC.insert(fOutput.fMC.end(),fkBunch->fMC.begin(), fkBunch->fMC.end() );
+  }
+  
+  fOutput.fTMean = (AliHLTUInt64_t)( (bunchTime0 + bunchTime + 1)/2 );
+
+  if( length==1 && fOutput.fQ < fSingleSeqLimit ) return 0;
+
+  return &fOutput;
+}
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFProcessorUnit.h b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFProcessorUnit.h
new file mode 100644 (file)
index 0000000..b313e6f
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef ALIHLTTPCHWCFPROCESSORUNIT_H
+#define ALIHLTTPCHWCFPROCESSORUNIT_H
+
+//* This file is property of and copyright by the ALICE HLT Project        * 
+//* ALICE Experiment at CERN, All rights reserved.                         *
+//* See cxx source for full Copyright notice                               *
+
+
+#include "AliHLTDataTypes.h"
+#include "AliHLTTPCHWCFDataTypes.h"
+
+
+//  @class AliHLTTPCHWCFProcessorUnit
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  Channel Processor unit of FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+//
+class AliHLTTPCHWCFProcessorUnit
+{
+ public:
+
+  /** standard constructor */
+  AliHLTTPCHWCFProcessorUnit();
+  
+  /** destructor */
+  ~AliHLTTPCHWCFProcessorUnit();
+
+  /** do cluster deconvolution in time direction */
+  void SetDeconvolution( bool val ){ fDeconvolute = val; }
+
+  /** lower charge limit for isolated signals
+   */
+  void SetSingleSeqLimit( AliHLTUInt32_t val ){ 
+    fSingleSeqLimit = val << AliHLTTPCHWCFDefinitions::kFixedPoint; 
+  }
+
+  /** initialise */
+  int Init();
+  
+  /** input stream of data */
+  int InputStream( const AliHLTTPCHWCFBunch *bunch );
+
+  /** output stream of data */
+  const AliHLTTPCHWCFClusterFragment *OutputStream();
+  
+ private: 
+
+  /** copy constructor prohibited */
+  AliHLTTPCHWCFProcessorUnit(const AliHLTTPCHWCFProcessorUnit&);
+  /** assignment operator prohibited */
+  AliHLTTPCHWCFProcessorUnit& operator=(const AliHLTTPCHWCFProcessorUnit&);  
+  
+
+  AliHLTTPCHWCFClusterFragment fOutput; // current output
+  const AliHLTTPCHWCFBunch *fkBunch; // current input
+  AliHLTUInt32_t fBunchIndex; // index in bunch
+  bool fDeconvolute;    // do deconvolution in time direction
+  AliHLTUInt64_t fSingleSeqLimit; // lower charge limit for isolated signals
+};
+
+#endif
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFSupport.cxx b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFSupport.cxx
new file mode 100644 (file)
index 0000000..001a7ab
--- /dev/null
@@ -0,0 +1,713 @@
+//****************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project          * 
+//* ALICE Experiment at CERN, All rights reserved.                           *
+//*                                                                          *
+//* Primary Authors: Sergey Gorbunov, Torsten Alt                            *
+//* Developers:      Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
+//*                  Torsten Alt <talt@cern.ch>                              *
+//*                  for The ALICE HLT Project.                              *
+//*                                                                          *
+//* Permission to use, copy, modify and distribute this software and its     *
+//* documentation strictly for non-commercial purposes is hereby granted     *
+//* without fee, provided that the above copyright notice appears in all     *
+//* copies and that both the copyright notice and this permission notice     *
+//* appear in the supporting documentation. The authors make no claims       *
+//* about the suitability of this software for any purpose. It is            *
+//* provided "as is" without express or implied warranty.                    *
+//****************************************************************************
+
+//  @file   AliHLTTPCHWCFSupport.cxx
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  Input interfaces for FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+
+
+#include "AliHLTTPCHWCFSupport.h"
+#include "AliHLTDataTypes.h"
+#include "AliHLTTPCMapping.h"
+#include "AliHLTTPCDigitReaderUnpacked.h"
+#include "AliHLTTPCTransform.h"
+#include "AliHLTTPCDefinitions.h"
+#include "AliRawDataHeader.h"
+#include "AliHLTTPCHWCFEmulator.h"
+
+#if __GNUC__>= 3
+using namespace std;
+#endif
+
+#include <cstdlib>
+#include <algorithm>
+#include <cerrno>
+#include <sys/time.h>
+
+
+AliHLTTPCHWCFSupport::AliHLTTPCHWCFSupport()
+  : 
+  AliHLTLogging(),
+  fEventMemory(0),
+  fEventMCMemory(0)
+{
+  // see header file for class documentation
+  for( int i=0; i<fgkNPatches; i++ ) fMapping[i] = 0;
+}
+
+
+AliHLTTPCHWCFSupport::~AliHLTTPCHWCFSupport()
+{
+  // see header file for class documentation
+  for( int i=0; i<fgkNPatches; i++ ) delete[] fMapping[i];
+  delete[] fEventMemory;
+  delete[] fEventMCMemory;
+}
+
+AliHLTTPCHWCFSupport::AliHLTTPCHWCFSupport(const AliHLTTPCHWCFSupport&)
+  : 
+  AliHLTLogging(),
+  fEventMemory(0),
+  fEventMCMemory(0)
+{
+  // dummy
+}
+
+AliHLTTPCHWCFSupport& AliHLTTPCHWCFSupport::operator=(const AliHLTTPCHWCFSupport&){
+  // dummy
+  return *this;
+}
+
+
+const AliHLTUInt32_t *AliHLTTPCHWCFSupport::GetMapping( int patch )
+{ 
+  // see header file for class documentation
+  if( patch<0 || patch>= fgkNPatches ){
+    HLTFatal("Wrong patch number %d, no mapping is provided.", patch);
+    return 0;
+  }
+  if( !fMapping[patch] ) fMapping[patch] = ReadMapping(patch);
+  return fMapping[patch];
+}
+
+
+AliHLTUInt32_t *AliHLTTPCHWCFSupport::ReadMapping( int patch, const char *mappingFileName ) const
+{
+  // Create mapping array for one patch 
+  // If no mapping file provided, reads from default file
+  // Output: mapping [] array of type AliHLTUInt32_t, where :
+  //
+  // mapping[0] == N hardware adresses in the array (mapping size is maping[0] + 1 )
+  // mapping[hwAddress] == configWord
+  //
+  // configWord consist of:
+  //
+  // bits 0-7: pad number
+  // bits 8-13: row number
+  // bit  14 : flag for border pad
+  // bit  15 : is the pad active
+  // bits 16->28 : gain calibration as 13 bit fixed point,
+  //               with 1 bit position before decimal point
+
+  const AliHLTUInt32_t  kBorderFlag = (1 << 14); 
+  const AliHLTUInt32_t  kActiveFlag = (1 << 15); 
+  
+  if( patch<0 || patch>5 ){
+     HLTFatal("Wrong patch number %d, no mapping is provided.", patch);
+     return 0;
+  }
+  TString filename;
+  
+  if( mappingFileName ){
+    filename = mappingFileName;
+  } else {
+    const char* basePath=getenv("ALICE_ROOT");
+    if (basePath) filename.Form("%s/TPC/mapping/Patch%d.data", basePath,patch);    
+  } 
+  
+  ifstream inFile;
+  inFile.open(filename.Data());
+  if (!inFile) {
+    HLTFatal("Unable to open mapping file: %s   This means no mapping is provided.", filename.Data());
+    return 0;
+  }
+
+  // AliHLTTPCTransform::GetFirstRow returns first row in scheme A.
+  // We have to transform to scheme B by AliHLTTPCTransform::Slice2Sector.
+
+  UInt_t offsetSchemeB=0;
+  {
+    Int_t tmp1=0, tmp2 = 0;
+    AliHLTTPCTransform::Slice2Sector(0, AliHLTTPCTransform::GetFirstRow(patch),
+                                    tmp1, tmp2);
+    offsetSchemeB = (UInt_t) tmp2;
+  }
+
+  AliHLTUInt32_t *mapping = 0; 
+  AliHLTUInt32_t *rowBranchPadHw = 0;
+  bool err = 1;
+  do{
+
+    UInt_t nHWAdd=0;
+    UInt_t maxHWAdd=0;
+
+    if( !(inFile >> nHWAdd ) || !(inFile >> maxHWAdd)  ){
+      HLTError("Mapping file for patch %d corrupted &s", patch,filename.Data());
+      break;
+    }
+
+    if( maxHWAdd > 0xFFF ){
+      HLTError("Max hardware address exceeded for patch %d, max number is %d, number from mapping file is %d.",patch, 0xFFF, maxHWAdd+1);      
+      break;
+    }
+
+    if(nHWAdd > maxHWAdd ){
+      HLTError("Too large number of hardware addresses for patch %d: max number is %d, number from mapping file is %d.",patch, maxHWAdd, nHWAdd );
+      break;
+    }
+      
+    mapping = new AliHLTUInt32_t[maxHWAdd+2];
+    rowBranchPadHw = new AliHLTUInt32_t[nHWAdd];
+    if( !mapping || !rowBranchPadHw ){
+      HLTError("Can not allocate &d bytes of memory", (maxHWAdd+1+nHWAdd)*sizeof(AliHLTUInt32_t));
+      break;
+    }
+
+    for( unsigned int i=0; i<maxHWAdd+2; i++ ) mapping[i] = 0;
+    for( unsigned int i=0; i<nHWAdd; i++ ) rowBranchPadHw[i] = 0;    
+    mapping[0] = maxHWAdd+1;
+    UInt_t nRead = 0;
+    err = 0;
+    while(!err ){
+      UInt_t hwAdd=0;
+      UInt_t row=0;
+      UInt_t pad=0;
+      if( !(inFile>>hwAdd) || !(inFile>>row) || !(inFile>>pad) ) break;      
+
+      err = 1;
+
+      if ( nRead >= nHWAdd ){
+       HLTError("Too many hardware addresses: %d, expected %d, mapping file %s corrupted?", nRead+1,  nHWAdd, filename.Data());
+       break;
+      }
+      if (hwAdd>maxHWAdd) {
+       HLTError("hardware address exceeds max hwAddress %d, mapping file %s corrupted?", maxHWAdd, filename.Data());   
+       break;
+      }
+
+      if( row < offsetSchemeB ){
+       HLTError("row number %d below minimum %d for patch %d, mapping file %s corrupted?", row, offsetSchemeB, patch, filename.Data());        
+       break;    
+      }        
+
+      row -= offsetSchemeB;
+       
+      if( row > 0x3F ){
+       HLTError("row number %d withing patch exceed the maximum %d for patch %d, mapping file %s corrupted?", row, 0x3F, patch, filename.Data());      
+       break;    
+      }
+
+      if( pad > 0xFF ){
+       HLTError("pad number %d exceed the maximum %d for patch %d, mapping file %s corrupted?", pad, 0xFF, patch, filename.Data());    
+       break;    
+      }
+
+      bool active = true; // Currently all channels are always active  
+      AliHLTUInt32_t  gainCalib = (1 << 12); // Gain calib identical for all pads currently
+       
+      AliHLTUInt32_t configWord = ( (row & 0x3F) << 8 ) | (pad & 0xFF);
+      if ( active ) configWord |= kActiveFlag;
+      configWord |= (gainCalib & 0x1FFF) << 16;        
+
+      mapping[1+hwAdd] = configWord;
+       
+      AliHLTUInt32_t branch = (hwAdd >> 11) & 0x1;     
+      rowBranchPadHw[nRead] = (row<<25) | (branch<<24) | (pad<<16) | hwAdd;
+      nRead++;
+      err = 0;
+    }
+    
+    if( err ) break;
+    
+    if ( nRead!= nHWAdd ){
+      HLTError("Too less hardware addresses: %d, expected %d, mapping file %s corrupted?", nRead,  nHWAdd, filename.Data());
+      err = 1;
+      break;
+    }
+    
+    // mark pads at borders of A/B branches 
+      
+    std::sort(rowBranchPadHw, rowBranchPadHw + nHWAdd);
+    int rowBranchLast = -1;
+    for( unsigned int i=0; i<nHWAdd; i++ ){
+      int rowBranch = rowBranchPadHw[i]>>24;
+      if( rowBranch != rowBranchLast ){
+       mapping[1+(rowBranchPadHw[i] & 0xFFF)] |= kBorderFlag;
+       rowBranchLast = rowBranch;
+       if( i>0 ) mapping[1+(rowBranchPadHw[i-1] & 0xFFF)] |= kBorderFlag;        
+      }
+    }
+    mapping[1+(rowBranchPadHw[nRead-1] & 0xFFF)] |= kBorderFlag;
+    
+  } while(0);
+  
+  inFile.close();
+
+  delete[] rowBranchPadHw;
+
+  if( err ){
+    delete[] mapping; 
+    return 0;
+  }
+  return mapping;
+}
+
+
+int AliHLTTPCHWCFSupport::CreateRawEvent
+( const AliHLTComponentBlockData* block, 
+  const AliHLTUInt32_t *&rawEvent, AliHLTUInt32_t &rawEventSize32, 
+  const AliHLTTPCClusterMCLabel *&mcLabels,  AliHLTUInt32_t &nMCLabels 
+)
+{
+  // the method creates TPC raw data out of the input block
+  // MC labels are provided if possible  
+  //
+
+  delete[] fEventMemory;
+  delete[] fEventMCMemory;
+  
+  rawEvent = 0;
+  rawEventSize32 = 0;
+  mcLabels = 0;
+  nMCLabels = 0;
+      
+  if( block->fPtr==NULL ){
+    HLTWarning("NULL pointer to the data block");
+    return 0;
+  }
+
+  Int_t slice = AliHLTTPCDefinitions::GetMinSliceNr( *block );
+  Int_t patch = AliHLTTPCDefinitions::GetMinPatchNr( *block );
+  AliHLTTPCMapping mapping(patch);
+
+  const char *str=Form("slice %d patch %d:", slice, patch);
+
+  if ( block->fDataType == (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC) )
+    {    
+      // already raw format -> only set the pointers and estimate the size
+
+      // read CDH header, estimate size of the data 
+      
+      AliHLTUInt64_t headerSize = sizeof(AliRawDataHeader);                  
+      AliRawDataHeader *cdhHeader = reinterpret_cast<AliRawDataHeader*>(block->fPtr);
+      
+      AliHLTUInt64_t blockSize = block->fSize; // size of the raw data in bytes      
+
+      if( cdhHeader->fSize!=0xFFFFFFFF ){ // use size information from the header
+       blockSize = cdhHeader->fSize;
+       if( blockSize > block->fSize ){
+         HLTWarning("%s Could not find a valid DDL header!",str);
+         return 0;
+       }
+      }
+      
+      if( blockSize < headerSize ){
+       HLTWarning("%s Buffer size is smaller than CDH header size", str);
+       return 0;
+      }
+      
+      rawEvent = reinterpret_cast<AliHLTUInt32_t*> (reinterpret_cast<UChar_t*>(block->fPtr)+headerSize);
+      rawEventSize32 = ( blockSize - headerSize )/sizeof(AliHLTUInt32_t);
+
+    }
+  else if ( block->fDataType == AliHLTTPCDefinitions::fgkUnpackedRawDataType )
+    {
+
+      AliHLTTPCDigitReaderUnpacked digitReader;         
+      digitReader.SetUnsorted(kTRUE);      
+      
+      if( digitReader.InitBlock(block->fPtr,block->fSize,patch,slice)<0 ) {
+       HLTWarning("failed setting up digit reader (InitBlock)");
+       return 0;
+      }
+
+      int nDigitsTotal = 0;
+      int nBunchesTotal = 0;
+     
+      while( digitReader.NextChannel() ){
+       while(digitReader.NextBunch()){
+         nBunchesTotal++;
+         nDigitsTotal+=digitReader.GetBunchSize();
+       }
+      }
+      
+      digitReader.Reset();
+
+      if( digitReader.InitBlock(block->fPtr,block->fSize,patch,slice)<0) {
+       HLTWarning("failed setting up digit reader (InitBlock)");
+       return 0;
+      }
+      
+      Int_t nPadsTotal = 0;
+      Int_t firstRow = AliHLTTPCTransform::GetFirstRow(patch);
+      Int_t nRows = AliHLTTPCTransform::GetNRows(patch);
+
+      for( int i=0; i<nRows; i++ ){
+       nPadsTotal += AliHLTTPCTransform::GetNPads(firstRow+i); 
+      }
+
+      AliHLTUInt32_t totalSize32 = (nDigitsTotal + nBunchesTotal*2)/3+2*nPadsTotal + 10;
+      AliHLTUInt32_t totalNMC = nDigitsTotal + 10;
+      
+      fEventMemory = new AliHLTUInt32_t[totalSize32];
+      if( !fEventMemory ){
+       HLTWarning("Not enougth memory: can not allocate %d bytes",totalSize32*8);
+       return 0;
+      }
+
+      fEventMCMemory = new AliHLTTPCClusterMCLabel[totalNMC];
+      if( !fEventMCMemory ){
+       HLTWarning("Not enougth memory: can not allocate %d bytes",totalNMC*sizeof(AliHLTTPCClusterMCLabel));
+       delete[] fEventMemory;
+       return 0;
+      }
+
+      AliHLTUInt32_t nWords32 = 0;
+      AliHLTUInt32_t mcIndex = 0;
+      int err=0;
+
+      AliHLTTPCDigitData tmpDigit;
+      tmpDigit.fTrackID[0] = -1;
+      tmpDigit.fTrackID[1] = -1;
+      tmpDigit.fTrackID[2] = -1;
+
+      while( !err && digitReader.NextChannel() ){
+       
+       Int_t row=digitReader.GetRow();
+       Int_t pad=digitReader.GetPad();
+
+       // create header
+
+       if( nWords32 >= totalSize32){ err = 1; break; } 
+       
+       AliHLTUInt32_t *header = fEventMemory + nWords32;
+       nWords32++;
+
+       int seek10 = 2;
+       int prevTime = 10000000;
+       int nWords10 = 0;
+       while(digitReader.NextBunch()){
+         
+         Int_t nSignals = digitReader.GetBunchSize();
+         if( nSignals <=0 ){
+           HLTWarning("Empty bunch received");
+           continue;
+         }
+
+         Int_t time = digitReader.GetTime() + nSignals-1;
+         
+         if( time-nSignals+1<0 || time>=AliHLTTPCTransform::GetNTimeBins() ){
+           HLTWarning("Wrong time bins received: %d-%d for row %d pad %d", time-nSignals+1, time, row, pad);
+           break;
+         }
+
+         if( time >= prevTime ){
+           HLTWarning("Unexpected order of TPC bunches in row %d, pad %d", row, pad);      
+           break;
+         }
+
+         prevTime = time-nSignals+1;
+         
+         if( nWords32+( 2+nSignals)/3+1 >= totalSize32 ){ err = 1; break; }
+         if( mcIndex + nSignals   >= totalNMC ){ err = 1; break; }
+
+         if( nWords10 + 2 + nSignals > 0x2FF ){
+           HLTWarning("Too much data in row %d, pad %d", row, pad);        
+           break;
+         }
+
+         nWords10 += 2 + nSignals;
+
+         Add10Word( nWords32, seek10, nSignals + 2 );
+         Add10Word( nWords32, seek10, time );
+         
+         const UInt_t *bunchData = digitReader.GetSignals();
+         const AliHLTTPCDigitData *mcDigits = digitReader.GetBunchDigits();
+         if( !mcDigits ){
+           HLTWarning("No MC labels found for a bunch of digits");
+         }
+
+         for(Int_t is=nSignals-1; is>=0; is--){
+           Add10Word( nWords32, seek10, bunchData[is] );           
+           const AliHLTTPCDigitData &digit = mcDigits ?mcDigits[is] :tmpDigit;
+           int nmc = 0;
+           for( int i=0; i<3; i++ ) if( digit.fTrackID[i] >=0 ) nmc++;      
+           for( int i=0; i<3; i++ ){
+             fEventMCMemory[mcIndex].fClusterID[i].fMCID = digit.fTrackID[i];
+             fEventMCMemory[mcIndex].fClusterID[i].fWeight = 0;
+             if( digit.fTrackID[i] >=0 ){                      
+               fEventMCMemory[mcIndex].fClusterID[i].fWeight  = ((float)bunchData[i])/nmc;
+             }
+           }     
+           mcIndex++;
+         }       
+
+       } // bunches
+       
+      *header = (1<<30) | ((nWords10&0x2FF)<<16) | (mapping.GetHwAddress(row, pad) & 0xFFF);
+
+      }// channels (pads)
+
+      if( err ){
+       HLTError("Internal error: too less memory allocated");  
+      } else {
+       for( AliHLTUInt32_t i=0; i<nWords32; i++ ) fEventMemory[i] = AliHLTTPCHWCFEmulator::WriteBigEndian(fEventMemory[i]);
+       rawEvent = fEventMemory;
+       rawEventSize32 = nWords32;
+       mcLabels = fEventMCMemory;
+       nMCLabels = mcIndex;
+      }
+
+    } // unpacked data type
+
+  return 0;
+}
+
+
+void AliHLTTPCHWCFSupport::Add10Word( AliHLTUInt32_t &nWords32, int &seek10, UInt_t data )
+{
+  // add 10-bit data to the 32-bit word
+  // fEventMemory [nWords32] --- current 32-bit word
+  // *seek10 --- 10-bit position withing the word
+  // pointers are increased, a new word is first initialised to 0
+
+  data = data & 0x3FF; // truncate to 10 bits
+
+  if( seek10 == 2 ){
+    nWords32++;
+    fEventMemory[nWords32-1] = data<<20;
+    seek10 = 1;
+  } else if( seek10 == 1 ){
+    fEventMemory[nWords32-1] &= 0xFFF003FF;
+    fEventMemory[nWords32-1] |= (data<<10);
+    seek10 = 0;
+  } else if( seek10 == 0 ){
+    fEventMemory[nWords32-1] &= 0xFFFFFC00;
+    fEventMemory[nWords32-1] |= data;
+    seek10 = 2;
+  } 
+}
+
+
+
+int AliHLTTPCHWCFSupport::CheckRawData( const AliHLTUInt32_t *buffer,
+                                                  unsigned long bufferSize32, int patch, int slice )
+{
+  //
+  // The procedure checks consistency of the data
+  //
+
+  const unsigned int headerSize32 = 8;
+
+  if (!buffer) return 0;
+
+  const char *str=Form("slice %d patch %d:", slice, patch);
+  
+  if( bufferSize32 < headerSize32 ){
+    HLTWarning("%s Buffer size is smaller than CDH header size", str);
+    return kFALSE;
+  }    
+  
+  // read data header 
+  AliHLTUInt32_t blockSize32 = bufferSize32; // size of the raw data in words
+
+  if( buffer[0]!=0xFFFFFFFF ) blockSize32 = buffer[0]/4; // use size information from the header  
+  if( blockSize32 > bufferSize32 ){  
+    HLTWarning(Form("%s Could not find a valid DDL header!",str));
+    return 0;
+  }
+  
+  UChar_t rcuVer = (UChar_t)( (buffer[1] >> 24) & 0xFF ); 
+
+  if (rcuVer < 2) {
+    HLTWarning("%s Old data format, RCU version %d", str,rcuVer);
+    return 0;
+  }
+
+  // is the block valid
+  //AliHLTUInt32_t blockAttributes = buffer[3]; // block attributes (bits 24-31) and participating sub detectors 
+  //cout<<blockAttributes<<" "<<(blockAttributes >> 24)<<endl;
+  //if ( !( (blockAttributes >> 24) & 1) ) return 0; 
+     
+
+  const AliHLTUInt32_t* fData = buffer + headerSize32;
+  unsigned long  dataSize32 = blockSize32 - headerSize32;       
+  
+  // Read the RCU trailer according to the RCU formware version specified in CDH
+  // Cross-check with version found in the trailer
+  // The two major bit should be 11 (identifies the end of the trailer)    
+  
+  AliHLTUInt32_t word = fData[dataSize32 - 1];
+  
+  if ((word >> 30) != 3) {
+    HLTWarning("%s Last RCU trailer word not found!", str);
+    return 0;
+  }
+  
+  UChar_t ver = (word >> 16) & 0xFF;
+  //AliHLTUInt32_t rcuId = (Int_t)((word >> 7) & 0x1FF);
+  AliHLTUInt32_t rcuTrailerSize32 = (word & 0x7F); // size of RCU trailer data in words
+  
+  if (ver != rcuVer) {
+    HLTWarning("%s Wrong RCU firmware version detected: %d != %d",
+              str,ver,rcuVer);
+    return 0;
+  }  
+
+  if (rcuTrailerSize32 < 2) {
+    HLTWarning(Form("Invalid trailer size found (%d bytes) !",
+                   rcuTrailerSize32*4));
+    return 0;
+  }
+  
+  if( rcuTrailerSize32 > dataSize32 ){
+    HLTWarning(Form("%s Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%ld bytes)!",
+                   str, rcuTrailerSize32*4,dataSize32*4));
+    return 0;    
+  }
+
+  // check the trailer
+
+  Int_t trailerIndex = dataSize32 - rcuTrailerSize32;
+
+  for( unsigned int i=trailerIndex; i<dataSize32-1; i++){
+    if ((fData[i] >> 30) != 2) {
+      HLTWarning("%s Missing RCU trailer identifier pattern!",str);
+      continue;
+    }
+  }
+
+  // Read the payload size  
+  Int_t  rcuPayloadSize32 = fData[trailerIndex] & 0x3FFFFFF;
+
+  if ( rcuPayloadSize32 + rcuTrailerSize32  != dataSize32) {
+    HLTWarning(Form("%s Inconsistent raw data size ! Raw data size - %ld bytes (from CDH), RCU trailer - %d bytes, raw data size (from RCU trailer) - %d bytes !",
+                   str, dataSize32*4,
+                   (rcuTrailerSize32)*4,
+                   rcuPayloadSize32*4));
+    return 0;
+  }
+    
+  
+  //AliHLTTPCMapping *mapping = new AliHLTTPCMapping(patch);
+  const int kMaxNTimeBins = 2000;
+
+  UShort_t  *channelData10 = new UShort_t[kMaxNTimeBins];    // cache for the decoded altro payload
+
+  Int_t position = 0; // current position (32-bit words) in fData
+  while(1){
+
+    // Search for the next Altro channel
+
+    word = 0;
+    while( position < rcuPayloadSize32 ){
+      word = fData[position++];
+      if( (word >> 30) == 1) break;
+    }
+    if (position >= rcuPayloadSize32 ) break; // no next channel found
+    
+    // extract channel payload and hw address
+
+    Int_t channelPayloadSize10 = (word >> 16) & 0x3FF; // payload size in 10-bit words 
+    Int_t channelPayloadSize32 = (channelPayloadSize10+2)/3;
+    Bool_t channelIOErrors = (word >> 29) & 0x1; // check for readout errors    
+    Short_t  channelHWAddress = word & 0xFFF;
+
+    if( position + channelPayloadSize32-1> rcuPayloadSize32 ){
+      HLTWarning(Form("%s Inconsistent channel payload data size: expected <= %d bytes from RCU trailer, found %d bytes in the channel header!",
+                     str,(rcuPayloadSize32 - position)*4, channelPayloadSize32*4 ));
+      continue;
+    }
+
+    //bool channelBranchAB = ((channelHWAddress >> 11) & 0x1);
+    // int channelFEC       = ((channelHWAddress >> 7) & 0xF); // front-end card index
+    //int channelAltro = ((channelHWAddress >> 4) & 0x7); // altro chip index
+    //int channelIndex = (channelHWAddress & 0xF); // channel index
+    //int channelRow = mapping->GetRow(channelHWAddress);
+    //int channelPad = mapping->GetPad(channelHWAddress);
+
+    // Now unpack the Altro data: 10-bit words to 16 bit-words    
+    
+    Int_t channelData10Index = 0;// current position in the payload
+
+    for (Int_t iword = 0; iword < channelPayloadSize32; iword++) {
+      word = fData[position++];
+      if ((word >> 30) != 0) {
+       HLTWarning(Form("%s Unexpected end of payload in altro channel payload! Address=0x%x, word=0x%x",
+                       str, channelHWAddress,word));
+       channelIOErrors = 1;
+       position--;
+       break;
+      }
+      channelData10[channelData10Index++] = (word >> 20) & 0x3FF;
+      channelData10[channelData10Index++] = (word >> 10) & 0x3FF;
+      channelData10[channelData10Index++] = word & 0x3FF;
+    }
+  
+    if ( channelIOErrors ) continue;    
+
+    // read bunches
+
+    Int_t prevTimeBin =  1024;
+    channelData10Index = 0;
+
+    while(1){
+      
+      // Read next Altro bunch 
+  
+      if ((channelData10Index+1 >= channelPayloadSize10) ) break;
+    
+      Int_t bunchLength = channelData10[channelData10Index++];
+      Int_t bunchStartTimeBin = channelData10[channelData10Index++];
+
+      if (bunchLength <= 2) {
+       // Invalid bunch size
+       HLTWarning(Form("%s Too short bunch length (%d) in Address=0x%x!",
+                       str, bunchLength,channelHWAddress));    
+       break;
+      }
+      if( channelData10Index + bunchLength - 2 > channelPayloadSize10 ){
+       // Too long bunch detected
+       HLTWarning(Form("%s Too long bunch detected in Address=0x%x! Expected <= %d 10-bit words, found %d !",
+                       str,channelHWAddress,channelPayloadSize10-channelData10Index,bunchLength));
+       break;
+      }
+            
+      if( bunchStartTimeBin-bunchLength+1 < 0) {
+       HLTWarning(Form("%s Invalid start time-bin in Address=0x%x ! (%d-%d+1) < 0",
+                       str,channelHWAddress,bunchStartTimeBin,bunchLength));
+       break;
+      }
+      if (bunchStartTimeBin >= prevTimeBin) {
+       HLTWarning(Form("%s Invalid start time-bin in Address=0x%x! (%d>=%d)",
+                       str,channelHWAddress,bunchStartTimeBin,prevTimeBin));
+       break;
+      }
+
+      prevTimeBin = bunchStartTimeBin-bunchLength+1;
+  
+      bunchLength -= 2;
+       
+      //UShort_t* bunchData = &channelData10[channelData10Index];   // pointer to the current bunch samples
+      channelData10Index += bunchLength;            
+    }
+  }
+  
+  delete[] channelData10;
+  //delete mapping;
+
+  return 1;
+}
+
diff --git a/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFSupport.h b/HLT/TPCLib/HWCFemulator/AliHLTTPCHWCFSupport.h
new file mode 100644 (file)
index 0000000..baa2cf0
--- /dev/null
@@ -0,0 +1,65 @@
+//* This file is property of and copyright by the ALICE HLT Project        * 
+//* ALICE Experiment at CERN, All rights reserved.                         *
+//* See cxx source for full Copyright notice                               *
+
+//  @file   AliHLTTPCHWCFSupport.h
+//  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+//  @author Torsten Alt <talt@cern.ch> 
+//  @brief  Input interfaces for FPGA ClusterFinder Emulator for TPC
+//  @brief  ( see AliHLTTPCHWCFEmulator class )
+//  @note
+
+#ifndef ALIHLTTPCHWCFSUPPORT_H
+#define ALIHLTTPCHWCFSUPPORT_H
+
+#include "AliHLTLogging.h"
+#include "AliHLTTPCHWCFDataTypes.h"
+
+class AliHLTComponentBlockData;
+
+/**
+ * @class AliHLTTPCHWCFSupport 
+ * The class creates input for the FPGA cluster finder emulator 
+ *
+ * @ingroup alihlt_tpc_components
+ */
+class AliHLTTPCHWCFSupport : public AliHLTLogging
+{
+ public:      
+  /** constructor */
+  AliHLTTPCHWCFSupport();
+  /** destructor */
+  virtual ~AliHLTTPCHWCFSupport();
+  
+  /** method to read mapping file **/
+  AliHLTUInt32_t *ReadMapping( int patch, const char *mappingFileName=0 ) const;
+  /** method returns default mapping for given patch **/
+  const AliHLTUInt32_t *GetMapping( int patch );
+  /** method creates raw event from the HLT data block, error flag returned **/
+  int CreateRawEvent( const AliHLTComponentBlockData* block, 
+                     const AliHLTUInt32_t *&rawEvent, AliHLTUInt32_t &rawEventSize32,
+                     const AliHLTTPCClusterMCLabel *&mcLabels,  AliHLTUInt32_t &nMCLabels );
+
+  /** method to check raw data */
+  int CheckRawData( const AliHLTUInt32_t *buffer, unsigned long bufferSize32, int patch, int slice );
+
+ private:
+
+  static const int fgkNPatches = 6; // n patches in TPC
+
+  /** copy constructor prohibited */
+  AliHLTTPCHWCFSupport(const AliHLTTPCHWCFSupport&);
+  /** assignment operator prohibited */
+  AliHLTTPCHWCFSupport& operator=(const AliHLTTPCHWCFSupport&);
+
+  /** add 10-bit data to the 32-bit word */
+  void Add10Word( AliHLTUInt32_t &nWords32, int &seek10, UInt_t data );
+
+  AliHLTUInt32_t *fMapping[fgkNPatches]; // mapping arrays
+  AliHLTUInt32_t *fEventMemory;          // memory for created event
+  AliHLTTPCClusterMCLabel *fEventMCMemory; // memory for MC labels
+};
+
+#endif
diff --git a/HLT/TPCLib/HWCFemulator/macro/hwcfCheck.C b/HLT/TPCLib/HWCFemulator/macro/hwcfCheck.C
new file mode 100644 (file)
index 0000000..54f5370
--- /dev/null
@@ -0,0 +1,139 @@
+// $Id: rec-hlt-tpc.C 36001 2009-10-26 17:08:56Z kaamodt $
+/*
+ * Example macro to run the HLT Conformal mapping tracker embedded into
+ * AliRoot reconstruction. The reconstruction is done from the TPC raw
+ * data.
+ *
+ * Usage:
+ * <pre>
+ *   rm galice.root & aliroot -b -q hwcfCheck.C | tee rec-hlt-tpc.log
+ *   rm galice.root & aliroot -b -q hwcfCheck.C'("./")' | tee rec-hlt-tpc.log
+ * </pre>
+ *
+ * The macro asumes raw data to be available in the rawx folders, either
+ * simulated or real data. A different input can be specified as parameter
+ * <pre>
+ *   rm galice.root & aliroot -b -q hwcfCheck.C'("./")'
+ * </pre>
+ *
+ * @ingroup alihlt_tpc
+ * @author Matthias.Richter@ift.uib.no
+ */
+
+TString GetFileList( char *basedir, char *filename )
+{
+  TString s = "";
+  int evnt=0;
+  do{
+    TString dir;
+    dir.Form("%sraw%d",basedir,evnt);
+    if( gSystem->AccessPathName(dir.Data()) ) break;
+    TString add;
+    add.Form(" -datafile %s/%s", dir.Data(), filename);
+    if( evnt>0 ) s+=" -nextevent";
+    s+=add;
+    evnt++;
+  }while(1);
+  return s;
+}
+
+void hwcfCheck(const char* basedir="./")
+{
+  
+  if(!gSystem->AccessPathName("galice.root")){
+    cerr << "please delete the galice.root or run at different place." << endl;
+    return;
+  }
+
+  if (!basedir) {
+    cerr << "please specify input or run without arguments" << endl;
+    return;
+  }
+
+  ///////////////////////////////////////////////////////////////////////////////////////////////////
+  //
+  // init the HLT system in order to define the analysis chain below
+  //
+  AliHLTSystem* gHLT=AliHLTPluginBase::GetInstance();
+  ///////////////////////////////////////////////////////////////////////////////////////////////////
+  //
+  // Setting up which output to give
+  //
+  int clusterFinderType=0; // 0 = v3; 1 = decoder; 2 = packed (offline v1)
+  bool bUseCA=true;   // use the CA tracker and merger
+  TString option="libAliHLTUtil.so libAliHLTRCU.so libAliHLTTPC.so loglevel=0x7c chains=";
+
+  ///////////////////////////////////////////////////////////////////////////////////////////////////
+  //
+  // define the analysis chain to be run
+  //
+  int iMinSlice=0;
+  int iMaxSlice=0;
+  int iMinPart=0;
+  int iMaxPart=0;
+  TString clusters;
+  for (int slice=iMinSlice; slice<=iMaxSlice; slice++) {    
+    for (int part=iMinPart; part<=iMaxPart; part++) {
+      int ddlno=768;
+      if (part>1) ddlno+=72+4*slice+(part-2);
+      else ddlno+=2*slice+part;     
+      // raw data publisher 
+      
+      TString arg, publisher, cf, publisherHW;
+
+      arg.Form("-minid %d -datatype 'DDL_RAW ' 'TPC '  -dataspec 0x%02x%02x%02x%02x", ddlno, slice, slice, part, part);
+      publisher.Form("DP_%02d_%d", slice, part);
+      AliHLTConfiguration pubconf(publisher.Data(), "AliRawReaderPublisher", NULL , arg.Data());
+            
+
+      // FPGA cluster finder emulator
+
+      cf.Form("CF_%02d_%d", slice, part);
+      AliHLTConfiguration cfconf(cf.Data(), "TPCHWClusterFinderEmulator", publisher.Data(), "");
+            
+      if(clusters.Length()>0) clusters+=" ";
+      clusters+=cf;
+      
+      TString fname;
+      fname.Form("HWCF_%d.ddl",ddlno);
+      TString flist = GetFileList(basedir,fname.Data());
+
+      cout<<"\n\nFileList for FPGA ddl "<<ddlno<<":"<<endl;
+      cout<<flist.Data()<<endl;
+      cout<<endl;
+
+      arg.Form("-datatype 'HWCLUST1' 'TPC ' %s -dataspec 0x%02x%02x%02x%02x", flist.Data(), slice, slice, part, part);
+
+      publisherHW.Form("DPHW_%02d_%d", slice, part);
+      AliHLTConfiguration pubconf(publisherHW.Data(), "FilePublisher", "", arg.Data());
+          
+      if(clusters.Length()>0) clusters+=" ";
+      clusters+=publisherHW;
+    }
+  }
+
+  
+  AliHLTConfiguration pubconf("ConsistencyControl", "TPCHWCFConsistenyControl", clusters.Data(), "");
+  
+  option+="ConsistencyControl";
+
+
+  ///////////////////////////////////////////////////////////////////////////////////////////////////
+  //
+  // Init and run the reconstruction
+  // All but HLT reconstructio is switched off
+  //
+  AliReconstruction rec;
+  rec.SetInput(basedir);
+  rec.SetRunVertexFinder(kFALSE);
+  rec.SetRunReconstruction("HLT");
+  rec.SetLoadAlignFromCDB(0);
+  rec.SetRunQA(":");
+  rec.SetDefaultStorage("local://$ALICE_ROOT/OCDB");   
+  rec.SetSpecificStorage("GRP/GRP/Data", Form("local://%s",gSystem->pwd()));
+  rec.SetOption("HLT", option);
+  rec.Run();
+}
diff --git a/HLT/TPCLib/HWCFemulator/macro/makeConfigurationObjectTPCHWClusterFinder.C b/HLT/TPCLib/HWCFemulator/macro/makeConfigurationObjectTPCHWClusterFinder.C
new file mode 100644 (file)
index 0000000..7bbba2d
--- /dev/null
@@ -0,0 +1,85 @@
+//-*- Mode: C++ -*-
+/**
+ * @file makeConfigurationObjectTPCHWClusterFinder.C
+ * @brief Creation of HLT component configuration objects in OCDB
+ *
+ * <pre>
+ * Usage: aliroot -b -q makeConfigurationObjectTPCHWClusterFinder.C'("param", "uri", runMin, runMax)'
+ * </pre>
+ *
+ * Create an OCDB entry with a TObjString containing param for
+ * TPCHWClusterFinder
+ *
+ * Parameters: <br>
+ * - param (opt)    string to be stored in the TObjSting, default empty
+ * - uri   (opt)    the OCDB URI, default $ALICE_ROOT   
+ * - runMin (opt)   default 0
+ * - runMax (opt)   default 999999999
+ * 
+ * Current Param : 
+ *  - ""  <pre> aliroot -b -q makeConfigurationObjectTPCHWClusterFinder.C </pre>
+ *
+ * @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
+ * @ingroup alihlt_physics
+ */
+void makeConfigurationObjectTPCHWClusterFinder(const Char_t* param="", const Char_t* cdbUri=NULL,
+                                     Int_t runMin=0, Int_t runMax=AliCDBRunRange::Infinity()) {
+
+  // --------------------------------------
+  // -- Setup CDB
+  // --------------------------------------
+
+  AliCDBManager* man = AliCDBManager::Instance();
+  if (!man) {
+    cerr << "Error : Can not get AliCDBManager" << end;
+    exit;
+  }
+
+  TString storage;
+  if (!man->IsDefaultStorageSet()) {
+    if ( cdbUri ) {
+      storage = cdbUri;
+      if ( storage.Contains("://") == 0 ) {
+       storage = "local://"; 
+       storage += cdbUri;
+      }
+    } 
+    else {
+      storage="local://$ALICE_ROOT/OCDB";
+    }
+    man->SetDefaultStorage(storage);
+  } 
+  else {
+    storage = man->GetDefaultStorage()->GetURI();
+  }
+
+  TString path("HLT/ConfigTPC/TPCHWClusterFinder");
+
+  // --------------------------------------
+  // -- Create Config Object
+  // --------------------------------------
+
+  // here is the actual content of the configuration object
+  TObjString configParam=param;
+
+  TObject *configObj = static_cast<TObject*>(&configParam);
+  // --------------------------------------
+  // -- Fill Object
+  // --------------------------------------
+  
+  if ( !configObj ) {
+    cerr << "Error : No configuration object created" << endl;
+    return;
+  }
+    
+  AliCDBPath cdbPath(path);
+  AliCDBId   cdbId(cdbPath, runMin, runMax);
+  AliCDBMetaData cdbMetaData;
+  man->Put(configObj, cdbId, &cdbMetaData);
+
+  printf("Adding %s type OCDB object to %s [%d,%d] in %s \n",
+        configObj->ClassName(), 
+        path.Data(),
+        runMin, runMax, storage.Data());
+}
+