Changes required to handle software triggers correctly in the global trigger component.
authoraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 21 Sep 2010 16:16:54 +0000 (16:16 +0000)
committeraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 21 Sep 2010 16:16:54 +0000 (16:16 +0000)
13 files changed:
HLT/BASE/AliHLTCTPData.cxx
HLT/BASE/AliHLTComponent.cxx
HLT/BASE/AliHLTComponent.h
HLT/BASE/AliHLTDataTypes.h
HLT/BASE/AliHLTSystem.cxx
HLT/BASE/AliHLTTask.cxx
HLT/BASE/AliHLTTriggerMenu.h
HLT/BASE/Makefile.am
HLT/trigger/AliHLTGlobalTriggerComponent.cxx
HLT/trigger/AliHLTGlobalTriggerComponent.h
HLT/trigger/Makefile.am
HLT/trigger/test/TriggerConfig.C
HLT/trigger/test/testGlobalTriggerComponent.C

index 52bdf48..5dd6497 100644 (file)
@@ -233,6 +233,7 @@ AliHLTUInt64_t AliHLTCTPData::ActiveTriggers(const AliHLTComponentTriggerData& t
 
   const AliRawDataHeader* cdh = NULL;
   if (AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL) != 0) return (AliHLTUInt64_t)0;
+  if ((cdh->GetL1TriggerMessage() & 0x1) == 0x1) return 0x0;  // invalid for software triggers.
   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
   AliHLTUInt64_t triggerMask = cdh->GetTriggerClasses();
   return triggerMask;
@@ -244,6 +245,7 @@ bool AliHLTCTPData::EvaluateCTPTriggerClass(const char* expression, const AliHLT
   
   const AliRawDataHeader* cdh = NULL;
   if (AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL, true) != 0) return false;
+  if ((cdh->GetL1TriggerMessage() & 0x1) == 0x1) return false;  // invalid for software triggers.
   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
   AliHLTUInt64_t triggerMask = cdh->GetTriggerClasses();
 
@@ -361,6 +363,7 @@ int AliHLTCTPData::Increment(AliHLTComponentTriggerData& trigData)
   const AliRawDataHeader* cdh = NULL;
   int result = AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL, true);
   if (result != 0) return result;
+  if ((cdh->GetL1TriggerMessage() & 0x1) == 0x1) return 0;  // invalid for software triggers.
   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
   AliHLTUInt64_t triggerMask = cdh->GetTriggerClasses();
 
@@ -425,6 +428,7 @@ AliHLTReadoutList AliHLTCTPData::ReadoutList(const AliHLTComponentTriggerData& t
 
   const AliRawDataHeader* cdh = NULL;
   if (AliHLTComponent::ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL, true) != 0) return AliHLTReadoutList();
+  if ((cdh->GetL1TriggerMessage() & 0x1) == 0x1) return AliHLTReadoutList();  // invalid for software triggers.
   // trigger mask is 50 bit wide and is stored in word 5 and 6 of the CDH
   AliHLTUInt64_t triggerMask = cdh->GetTriggerClasses();
 
index 6c5f409..46ab071 100644 (file)
@@ -1785,6 +1785,18 @@ int AliHLTComponent::ProcessEvent( const AliHLTComponentEventData& evtData,
        indexUpdtDCSEvent=i;
       } else if (fpInputBlocks[i].fDataType==kAliHLTDataTypeEvent) {
        fEventType=fpInputBlocks[i].fSpecification;
+       if (fEventType != gkAliEventTypeConfiguration and
+           fEventType != gkAliEventTypeReadPreprocessor
+          )
+       {
+         // We can actually get the event type from the CDH if it is valid.
+         // Otherwise just use the specification of the input block.
+         const AliRawDataHeader* cdh;
+         if (ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL) == 0)
+         {
+           fEventType = ExtractEventTypeFromCDH(cdh);
+         }
+       }
 
        // skip always in case of gkAliEventTypeConfiguration
        if (fpInputBlocks[i].fSpecification==gkAliEventTypeConfiguration) bSkipDataProcessing|=skipModeForce;
@@ -2345,8 +2357,7 @@ bool AliHLTComponent::IsDataEvent(AliHLTUInt32_t* pTgt) const
   // see header file for function documentation
   if (pTgt) *pTgt=fEventType;
   return (fEventType==gkAliEventTypeData ||
-         fEventType==gkAliEventTypeDataReplay ||
-         fEventType==gkAliEventTypeCalibration);
+         fEventType==gkAliEventTypeDataReplay);
 }
 
 int AliHLTComponent::CopyStruct(void* pStruct, unsigned int iStructSize, unsigned int iBlockNo,
@@ -2597,6 +2608,21 @@ int AliHLTComponent::ExtractTriggerData(
   return 0;
 }
 
+AliHLTUInt32_t AliHLTComponent::ExtractEventTypeFromCDH(const AliRawDataHeader* cdh)
+{
+  // see header file for function documentation
+  
+  UChar_t l1msg = cdh->GetL1TriggerMessage();
+  if ((l1msg & 0x1) == 0x0) return gkAliEventTypeData;
+  // The L2SwC bit must be one if we got here, i.e. l1msg & 0x1 == 0x1.
+  if (((l1msg >> 2) & 0xF) == 0xE) return gkAliEventTypeStartOfRun;
+  if (((l1msg >> 2) & 0xF) == 0xF) return gkAliEventTypeEndOfRun;
+  // Check the C1T bit to see if this is a calibration event,
+  // if not then it must be some other software trigger event.
+  if (((l1msg >> 6) & 0x1) == 0x1) return gkAliEventTypeCalibration;
+  return gkAliEventTypeSoftware;
+}
+
 int AliHLTComponent::LoggingVarargs(AliHLTComponentLogSeverity severity, 
                                    const char* originClass, const char* originFunc,
                                    const char* file, int line, ... ) const
index 395079d..92c6ca4 100644 (file)
@@ -746,7 +746,7 @@ class AliHLTComponent : public AliHLTLogging {
    *     AliRawDataHeader* cdh;
    *     ExtractTriggerData(trigData, NULL, NULL, &cdh, NULL);
    *   \endcode
-   * @return the zero on success and one of the following error codes on failure.
+   * @return zero on success or one of the following error codes on failure.
    *   if a non-zero error code is returned then none of the output parameters are
    *   modified.
    *    \li -ENOENT  The <i>trigData</i> structure size is wrong.
@@ -771,7 +771,7 @@ class AliHLTComponent : public AliHLTLogging {
    * [out] @param list  The output readout list to fill.
    * [in] @param printErrors  If true then error messages are generated as necessary
    *                          and suppressed otherwise.
-   * @return the zero on success or one of the error codes returned by ExtractTriggerData.
+   * @return zero on success or one of the error codes returned by ExtractTriggerData.
    */
   static int GetReadoutList(
       const AliHLTComponentTriggerData& trigData, AliHLTReadoutList& list,
@@ -780,6 +780,13 @@ class AliHLTComponent : public AliHLTLogging {
   {
     return ExtractTriggerData(trigData, NULL, NULL, NULL, &list, printErrors);
   }
+
+  /**
+   * Extracts the event type from the given Common Data Header.
+   * [in] @param cdh  The Common Data Header to extract the event type from.
+   * @return the event type code from the CDH.
+   */
+  static AliHLTUInt32_t ExtractEventTypeFromCDH(const AliRawDataHeader* cdh);
   
   /**
    * Stopwatch type for benchmarking.
index a5f80b1..f39985d 100644 (file)
@@ -65,6 +65,7 @@
  *  14       Adding new data block type for HLT global trigger counters.
  *           Adding data block type for ESD content
  *           Adding data block type for forwarded component table blocks
+ *           Adding new event type for software triggers.
  */
 #define ALIHLT_DATA_TYPES_VERSION 14
 
@@ -873,6 +874,8 @@ extern "C" {
   const AliHLTUInt32_t gkAliEventTypeCorruptID=8;
   /** Calibration eventType specification */ 
   const AliHLTUInt32_t gkAliEventTypeCalibration=16;
+  /** Software eventType specification */ 
+  const AliHLTUInt32_t gkAliEventTypeSoftware=24;
   /** DataReplay eventType specification */
   const AliHLTUInt32_t gkAliEventTypeDataReplay=32;
   /** Configuration eventType specification */
index af9b2c7..3a9b5d4 100644 (file)
@@ -364,12 +364,10 @@ int AliHLTSystem::Run(Int_t iNofEvents, int bStop, AliHLTUInt64_t trgMask,
          // reset and prepare for new data
          fpHLTOUTTask->Reset();
        }
-       if (eventtype) {
-         // TODO: translate RawReader event types into the HLT event types
-         // this needs to be done after the analysis framework has been extended to
-         // handle all different cases correctly
+       if (eventtype == 0) {
+         eventtype = gkAliEventTypeData;
        }
-       if ((iResult=ProcessTasks(i, trgMask, timestamp, gkAliEventTypeData))>=0) {
+       if ((iResult=ProcessTasks(i, trgMask, timestamp, eventtype))>=0) {
          fGoodEvents++;
          iCount++;
        } else {
index d964041..9bb842d 100644 (file)
@@ -580,7 +580,19 @@ int AliHLTTask::ProcessTask(Int_t eventNo, AliHLTUInt32_t eventType, AliHLTUInt6
       trigData.fStructSize=sizeof(trigData);
       trigData.fDataSize=sizeof(AliHLTEventTriggerData);
       memset(&evtTrigData, 0, trigData.fDataSize);
+      // Setup the CDH in the trigger data, based on the event type and CTP trigger.
       evtTrigData.fCommonHeaderWordCnt=gkAliHLTCommonHeaderCount;
+      AliHLTUInt8_t l1msg = 0x0;
+      switch (eventType)
+      {
+      case gkAliEventTypeData:        l1msg = 0x00; break;
+      case gkAliEventTypeDataReplay:  l1msg = 0x00; break;
+      case gkAliEventTypeStartOfRun:  l1msg = (0xE << 2) | 0x01; break;
+      case gkAliEventTypeEndOfRun:    l1msg = (0xF << 2) | 0x01; break;
+      case gkAliEventTypeCalibration: l1msg = (0x1 << 6) | 0x01; break;
+      case gkAliEventTypeSoftware:    l1msg = 0x01; break;
+      }
+      evtTrigData.fCommonHeader[1] = AliHLTUInt32_t(l1msg) << 14;
       evtTrigData.fCommonHeader[5]=trgMask&0xffffffff;
       trgMask>>=32;
       evtTrigData.fCommonHeader[6]=trgMask&0x3ffff;
index c71eac6..261b331 100644 (file)
  * just one trigger menu item in a priority group then the groups expressions are
  * explicit. On the other hand, for multiple items in a group they form implicit
  * expression fragments.
+ *
+ * \note CTP trigger class names can be used in the trigger menu since the global
+ *   trigger will generate and add corresponding trigger decision objects to the
+ *   logic on the fly.
+ *   In addition, for software triggers, a special SOFTWARE trigger decision is
+ *   generated and the SOFTWARE name can be used in the trigger menu for this.
+ *   If the software trigger is a calibration event then a trigger decision with
+ *   the name CALIBRATION is generated instead. START_OF_DATA and END_OF_DATA
+ *   symbols are similarly defined for the start and end of data events respectively.
  */
 class AliHLTTriggerMenu : public TObject
 {
index a474be4..cd3ffab 100644 (file)
@@ -22,7 +22,7 @@ bin_SCRIPTS                   = setenv.sh setenv.csh
 lib_LTLIBRARIES                        =  libHLTbase.la
 
 # version info for the library
-LIBRARY_VERSION                        = '9:0:0'
+LIBRARY_VERSION                        = '10:0:0'
 
 # MODDIR is set by the AliRoot build system and denotes the topdir
 # of the module, we must set it since the package definition libHLTbase.pkg
index 340bfda..5dc78fa 100644 (file)
@@ -32,6 +32,7 @@
 #include "AliCDBManager.h"
 #include "AliCDBStorage.h"
 #include "AliCDBEntry.h"
+#include "AliRawDataHeader.h"
 #include "TUUID.h"
 #include "TROOT.h"
 #include "TSystem.h"
@@ -72,6 +73,7 @@ AliHLTGlobalTriggerComponent::AliHLTGlobalTriggerComponent() :
        fDebugMode(false),
        fRuntimeCompile(true),
        fDeleteCodeFile(false),
+       fMakeSoftwareTriggers(true),
        fCodeFileName(),
        fClassName(),
        fCTPDecisions(NULL),
@@ -83,7 +85,9 @@ AliHLTGlobalTriggerComponent::AliHLTGlobalTriggerComponent() :
        fBits(0),
        fDataEventsOnly(true),
        fMonitorPeriod(-1),
-       fUniqueID(0)
+       fUniqueID(0),
+       fSoftwareTrigger(true, "SOFTWARE"),
+       fTotalEventCounter(0)
 {
   // Default constructor.
   
@@ -128,6 +132,7 @@ Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
   fClassName = "";
   fCodeFileName = "";
   fDeleteCodeFile = false;
+  fMakeSoftwareTriggers = true;
   const char* configFileName = NULL;
   const char* codeFileName = NULL;
   fIncludePaths.Clear();
@@ -314,6 +319,12 @@ Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
       }
       continue;
     }
+
+    if (strcmp(argv[i], "-dont-make-software-triggers") == 0)
+    {
+      fMakeSoftwareTriggers = false;
+      continue;
+    }
     
     HLTError("Unknown option '%s'.", argv[i]);
     return -EINVAL;
@@ -378,6 +389,7 @@ Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
   SetDescription(menu->DefaultDescription());
   SetTriggerDomain(menu->DefaultTriggerDomain());
   
+  fTotalEventCounter = 0;
   return 0;
 }
 
@@ -472,7 +484,13 @@ int AliHLTGlobalTriggerComponent::DoTrigger()
   if (pCTPData) {
     AddCTPDecisions(fTrigger, pCTPData, GetTriggerData());
   }
-
+  
+  bool softwareTriggerIsValid = FillSoftwareTrigger();
+  if (softwareTriggerIsValid)
+  {
+    fTrigger->Add(&fSoftwareTrigger, kAliHLTDataTypeTriggerDecision, kAliHLTVoidDataSpec);
+  }
+  
   // Calculate the global trigger result and trigger domain, then create and push
   // back the new global trigger decision object.
   TString description;
@@ -488,7 +506,7 @@ int AliHLTGlobalTriggerComponent::DoTrigger()
     );
 
   decision.SetUniqueID(fUniqueID);
-  decision.SetCounters(fTrigger->GetCounters(), GetEventCount()+1);
+  decision.SetCounters(fTrigger->GetCounters(), fTotalEventCounter+1);
   if (fTrigger->CallFailed()) return -EPROTO;
   
   TClonesArray shortInfo(TNamed::Class(), GetNumberOfInputBlocks());
@@ -544,6 +562,8 @@ int AliHLTGlobalTriggerComponent::DoTrigger()
   // modifies the kCanDelete bit and nothing else.
   if (!TestBit(kSkipCTP) && CTPData()) decision.AddInputObjectRef(const_cast<AliHLTCTPData*>(CTPData()));
   
+  if (softwareTriggerIsValid and TestBit(kIncludeInput)) decision.AddTriggerInput(fSoftwareTrigger);
+  
   static UInt_t lastTime=0;
   TDatime time;
   if (time.Get()-lastTime>60) {
@@ -587,6 +607,8 @@ int AliHLTGlobalTriggerComponent::DoTrigger()
     if (fTrigger->CallFailed()) return -EPROTO;
     return -ENOSPC;
   }
+  
+  ++fTotalEventCounter;
   return 0;
 }
 
@@ -1663,6 +1685,40 @@ bool AliHLTGlobalTriggerComponent::ExtractedOperator(TString& expr, TString& op)
 }
 
 
+bool AliHLTGlobalTriggerComponent::FillSoftwareTrigger()
+{
+  // Fills the fSoftwareTrigger structure.
+  const AliRawDataHeader* cdh;
+  if (ExtractTriggerData(*GetTriggerData(), NULL, NULL, &cdh, NULL) != 0) return false;
+  UChar_t l1msg = cdh->GetL1TriggerMessage();
+  if ((l1msg & 0x1) == 0x0) return false;  // skip physics events.
+  // From here on everything must be a software trigger.
+  if (((l1msg >> 2) & 0xF) == 0xE)
+  {
+    fSoftwareTrigger.Name("START_OF_DATA");
+    fSoftwareTrigger.Description("Generated internal start of data trigger.");
+  }
+  else if (((l1msg >> 2) & 0xF) == 0xF)
+  {
+    fSoftwareTrigger.Name("END_OF_DATA");
+    fSoftwareTrigger.Description("Generated internal end of data trigger.");
+  }
+  else if (((l1msg >> 6) & 0x1) == 0x1)
+  {
+    fSoftwareTrigger.Name("CALIBRATION");
+    fSoftwareTrigger.Description("Generated internal calibration trigger.");
+  }
+  else
+  {
+    fSoftwareTrigger.Name("SOFTWARE");
+    fSoftwareTrigger.Description("Generated internal software trigger.");
+  }
+  UInt_t detectors = cdh->GetSubDetectors();
+  fSoftwareTrigger.ReadoutList( AliHLTReadoutList(Int_t(detectors)) );
+  return true;
+}
+
+
 int AliHLTGlobalTriggerComponent::PrintStatistics(const AliHLTGlobalTrigger* pTrigger, AliHLTComponentLogSeverity level, int offset) const
 {
   // print some statistics
index 08a84b9..12352d2 100644 (file)
@@ -12,6 +12,7 @@
 /// @brief  Declaration of the AliHLTGlobalTriggerComponent component class.
 
 #include "AliHLTTrigger.h"
+#include "AliHLTTriggerDecision.h"
 #include "TClonesArray.h"
 
 class AliHLTTriggerMenu;
@@ -74,6 +75,15 @@ class AliHLTGlobalTrigger;
  * \li -monitoring[=n] <br>
  *      enable monitoring trigger once every n seconds, enable for every event if
  *      parameter n is omitted
+ * \li -dont-make-software-triggers <br>
+ *      This option prevents the Common Data Header from being interpreted to generate
+ *      software event input triggers for the trigger menu. Normally the following default
+ *      triggers are available in the trigger menu:
+ *        START_OF_DATA - start of data event.
+ *        END_OF_DATA - end of data event.
+ *        SOFTWARE - general software trigger.
+ *        CALIBRATION - calibration trigger.
+ *      With this option these will not be automatically generated by the global trigger.
  *
  * <h2>Configuration:</h2>
  * Configured from CDB but can be overridden with the -config argument.
@@ -280,13 +290,22 @@ class AliHLTGlobalTriggerComponent : public AliHLTTrigger
 
   /**
    * Add trigger decisions according to the active CTP trigger classes
-   * An internal TclonesArray holds the trigger decisions to be added. The trigger
+   * An internal TClonesArray holds the trigger decisions to be added. The trigger
    * decisions are updated according to the active CTP trigger mask.
    * \param pTrigger  The instance of the global trigger
    * \param pCTPData  Instance of the CTP data
    * \param trigData  Current trigger data, if NULL, the active trigger data from the CTP data is used
    */
   int AddCTPDecisions(AliHLTGlobalTrigger* pTrigger, const AliHLTCTPData* pCTPData, const AliHLTComponentTriggerData* trigData);
+  
+  /**
+   * This method handles the software trigger by checking the Common Data Header
+   * and filling fSoftwareTrigger with appropriate information for one of the
+   * following triggers: START_OF_DATA, END_OF_DATA, SOFTWARE or CALIBRATION, if
+   * it is indicated in the CDH L1 trigger message.
+   * \returns true if the trigger decision object was filled and false otherwise.
+   */
+  bool FillSoftwareTrigger();
 
   /**
    * Print some statistics based on the trigger counters
@@ -297,6 +316,7 @@ class AliHLTGlobalTriggerComponent : public AliHLTTrigger
   bool fDebugMode;  //! Indicates if the generated global trigger class should be in debug mode.
   bool fRuntimeCompile;  //! Indicates if the generated global trigger class should be compiled
   bool fDeleteCodeFile; //! If true then the code file indicated by fCodeFileName should be deleted during DoDeinit.
+  bool fMakeSoftwareTriggers;  //! Indicates if the software triggers should be filled automatically or not.
   TString fCodeFileName; //! base file name of the generated code for the global trigger
   TString fClassName;  //! The generated/loaded trigger class name.
   TClonesArray* fCTPDecisions; //! AliHLTTriggerDecision objects for the CTP classes
@@ -309,6 +329,8 @@ class AliHLTGlobalTriggerComponent : public AliHLTTrigger
   bool fDataEventsOnly; //! Flag indicating if only data events are processed with trigger logic.
   int fMonitorPeriod; //! Period of the monitoring trigger in s, -1 means monitoring trigger off
   UInt_t fUniqueID; //! Unique ID for the decision output objects.
+  AliHLTTriggerDecision fSoftwareTrigger; //! Software or calibration trigger decision object to be added to trigger logic.
+  AliHLTUInt64_t fTotalEventCounter; //! Counts the total number of events handled.
 
   static const char* fgkTriggerMenuCDBPath; //! The path string to read the trigger menu from the CDB.
   
index 18bee0b..a4ab75f 100644 (file)
@@ -43,7 +43,7 @@ lib_LTLIBRARIES                       =  libAliHLTTrigger.la
 #      increment age.
 #   6. If any interfaces have been removed since the last public release, then
 #      set age to 0. 
-LIBRARY_VERSION                        = '1:0:0'
+LIBRARY_VERSION                        = '2:0:0'
 
 # library sources
 # The source files are specified in libAliHLTTrigger.pkg
index fac0ff6..8fdec80 100644 (file)
@@ -103,6 +103,21 @@ void ComplexTestConfig()
 }
 
 /**
+ * This will make a configuration that will test software triggers.
+ */
+void SoftwareTriggersTestConfig()
+{
+       AliHLTGlobalTriggerConfig config("Software triggers test config");
+       config.AddSymbol("domainPHOS", "AliHLTTriggerDomain", "", "AliHLTTriggerDomain(\"*******:PHOS\")");
+       config.AddSymbol("domainSPD", "AliHLTTriggerDomain", "", "AliHLTTriggerDomain(\"*******:SPD\")");
+       config.AddItem(5, "START_OF_DATA", "START_OF_DATA", "Start of data");
+       config.AddItem(4, "END_OF_DATA", "END_OF_DATA", "End of data");
+       config.AddItem(3, "SOFTWARE", "domainSPD", "Software trigger");
+       config.AddItem(2, "CALIBRATION", "domainPHOS", "Calibration trigger");
+       config.AddItem(1, "triggerMUON", "triggerMUON", "MUON trigger");
+}
+
+/**
  * Top level configuration routine for the global trigger component tests.
  */
 void TriggerConfig(int version = 0)
@@ -114,6 +129,7 @@ void TriggerConfig(int version = 0)
        case 2: PrescalarTestConfig(); break;
        case 3: SymbolTestConfig(); break;
        case 4: ComplexTestConfig(); break;
+       case 5: SoftwareTriggersTestConfig(); break;
        default: AliHLTGlobalTriggerConfig config("Empty test config");
        }
 }
index 1d285df..dfddbee 100644 (file)
@@ -246,6 +246,110 @@ void CallRunTrigger(
 }
 
 /**
+ * Runs a global trigger test chain to test L0 software triggers.
+ * \param config  The configuration version to pass to TriggerConfig.C
+ * \param usecint  If true then the global trigger component uses CINT to interpret
+ *     the code rather than compiling it.
+ * \param debug  If true then the global trigger component generates extra debug
+ *     statements in the on the fly AliHLTGlobalTriggerImp_*.cxx file.
+ * \param customClass  Names the custom class that should be loaded from the file
+ *     <i>\<customClass\>.cxx</i>. This is useful for debugging only. i.e. you can
+ *     edit a generated logic file and test it by hand.
+ */
+void RunTriggerSW(int config = 0, bool usecint = false, bool debug = false, const char* customClass = NULL)
+{
+       AliHLTSystem sys;
+       sys.ScanOptions("ECS=CTP_TRIGGER_CLASS=00:TRIGGER-ALL:00-01-02-03-04-05-06-07-08-09-10-11-12-13-14-15-16-17");
+       sys.LoadComponentLibraries("libAliHLTUtil.so");
+       sys.LoadComponentLibraries("libAliHLTTRD.so");
+       sys.LoadComponentLibraries("libAliHLTMUON.so");
+       sys.LoadComponentLibraries("libAliHLTTrigger.so");
+       if (debug)
+       {
+               AliLog::SetGlobalLogLevel(AliLog::kMaxType);
+               sys.SetGlobalLoggingLevel(kHLTLogAll);
+       }
+       
+       TString cmdline = "-datatype ROOTTOBJ 'HLT ' ";
+       for (int i = 1; i <= 8; i++)
+       {
+               if (i > 1) cmdline += " -nextevent";
+               cmdline += Form(" -datafile testInputFile%d.root", i);
+       }
+       AliHLTConfiguration pub("pub", "ROOTFilePublisher", NULL, cmdline.Data());
+       
+       cmdline = Form("-config $ALICE_ROOT/HLT/trigger/test/TriggerConfig.C(%d)"
+               " -includepath $ALICE_ROOT/include -includepath $ALICE_ROOT/HLT/BASE"
+               " -includepath $ALICE_ROOT/HLT/trigger -include AliHLTEventSummary.h"
+               " -process-all-events",
+               config
+               );
+       if (customClass != NULL) cmdline += Form(" -usecode %s.cxx %s", customClass, customClass);
+       if (usecint) cmdline += " -cint";
+       if (debug) cmdline += " -debug";
+       AliHLTConfiguration proc("proc", "HLTGlobalTrigger", "pub", cmdline.Data());
+       
+       AliHLTConfiguration sink("sink", "ROOTFileWriter", "proc", "-datafile testOutputFile.root -concatenate-events");
+       
+       sys.BuildTaskList("sink");
+       sys.Run(
+               1,   // Number of events to process.
+               0,   // Stop chain at end of run.
+               0x1, // Active CTP trigger mask.
+               0,   // Time stamp.
+               gkAliEventTypeSoftware  // Event type.
+       );
+       sys.Run(
+               1,   // Number of events to process.
+               0,   // Stop chain at end of run.
+               0x1, // Active CTP trigger mask.
+               0,   // Time stamp.
+               gkAliEventTypeCalibration  // Event type.
+       );
+       sys.Run(
+               1,   // Number of events to process.
+               1,   // Stop chain at end of run.
+               0x1, // Active CTP trigger mask.
+               0,   // Time stamp.
+               0    // Event type.
+       );
+}
+
+/**
+ * This method calls the RunTriggerSW method in an independant aliroot process.
+ * This is necessary since we get memory corruption if we run too many instances of
+ * AliHLTSystem in the same process.
+ */
+void CallRunTriggerSW(
+               int config = 0, bool usecint = false, bool debug = false,
+               const char* customClass = NULL, bool showOutput = false
+       )
+{
+       const char* redirection = "> /dev/null";
+       const char* classNameString = "NULL";
+       if (showOutput) redirection = "";
+       if (customClass != NULL) classNameString = Form("\"%s\"", customClass);
+       const char* command = Form(
+                       "aliroot %s <<EOF\n"
+                       "gSystem->Load(\"libAliHLTUtil.so\");\n"
+                       "gSystem->Load(\"libAliHLTTRD.so\");\n"
+                       "gSystem->Load(\"libAliHLTMUON.so\");\n"
+                       "gSystem->Load(\"libAliHLTTrigger.so\");\n"
+                       "gSystem->SetIncludePath(\"-I${ALICE_ROOT}/include"
+                       " -I${ALICE_ROOT}/HLT/BASE -I${ALICE_ROOT}/HLT/trigger\");\n"
+                       ".L $ALICE_ROOT/HLT/trigger/test/testGlobalTriggerComponent.C+\n"
+                       "RunTriggerSW(%d,%d,%d,%s);\n"
+                       "EOF\n",
+                       redirection,
+                       config,
+                       usecint,
+                       debug,
+                       classNameString
+               );
+       gSystem->Exec(command);
+}
+
+/**
  * Checks that a particular decision is as expected and prints error messages
  * if it is not.
  * \param testName  The name of the test being run.
@@ -680,6 +784,153 @@ bool CheckDifferentModes(
 }
 
 /**
+ * This routine is used to check if the global Trigger counters are correct.
+ * \param testName  The name of the test being run.
+ * \param eventNum  The number of the event being checked.
+ * \param decision  The global trigger decision being checked.
+ * \param expectedCounters  The expected counters.
+ * \returns true if the decision is as expected.
+ */
+bool CheckCounters(
+               const char* testName,
+               int eventNum,
+               AliHLTGlobalTriggerDecision* decision,
+               const TArrayL64& expectedCounters
+       )
+{
+       if (decision->Counters().GetSize() != expectedCounters.GetSize())
+       {
+               cerr << "ERROR (Test: " << testName
+                    << "): The result does not have the required number of counters for event "
+                    << eventNum << ". Got " << decision->Counters().GetSize() << " but expected "
+                    << expectedCounters.GetSize() << "." << endl;
+               return false;
+       }
+       for (Int_t i = 0; i < expectedCounters.GetSize(); ++i)
+       {
+               if (decision->Counters()[i] != expectedCounters[i])
+               {
+                       cerr << "ERROR (Test: " << testName
+                            << "): The result does not have the correct counter value for event "
+                            << eventNum << ". Got a value " << decision->Counters()[i]
+                            << " for counter " << i << ", but expected a value of "
+                            << expectedCounters[i] << "." << endl;
+                       return false;
+               }
+       }
+       return true;
+}
+
+/// Routine for checking the result of the SoftwareTriggersTestConfig() config in TriggerConfig.C
+bool CheckSoftwareTriggerTestConfig(const char* testName = "Software trigger config")
+{
+       AliHLTGlobalTriggerDecision* decision = NULL;
+       bool result = false;
+       
+       AliHLTTriggerDomain domainPHOS("*******:PHOS");
+       domainPHOS.Remove(AliHLTReadoutList("PHOS"));
+       AliHLTTriggerDomain domainSPD("*******:SPD");
+       domainSPD.Remove(AliHLTReadoutList("ITSSPD"));
+       AliHLTTriggerDomain domainMUON("TRACKS:MUON");
+       domainMUON.Add(AliHLTReadoutList("MUONTRK MUONTRG"));
+
+       TFile* file = new TFile("testOutputFile.root", "READ");
+       TArrayL64 expectedCounters;
+       expectedCounters.Set(6);
+       
+       decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;1"));
+       result = Check(testName, 1, decision, true, AliHLTTriggerDomain(), "Start of data");
+       if (! result) goto cleanup;
+       expectedCounters[0] = 1; expectedCounters[5] = 1;
+       result = CheckCounters(testName, 1, decision, expectedCounters);
+       if (! result) goto cleanup;
+       
+       decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;2"));
+       result = Check(testName, 2, decision, true, domainSPD, "Software trigger");
+       if (! result) goto cleanup;
+       expectedCounters[2] = 1; expectedCounters[5] = 2;
+       result = CheckCounters(testName, 2, decision, expectedCounters);
+       if (! result) goto cleanup;
+       
+       decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;3"));
+       result = Check(testName, 3, decision, true, domainPHOS, "Calibration trigger");
+       if (! result) goto cleanup;
+       expectedCounters[3] = 1; expectedCounters[5] = 3;
+       result = CheckCounters(testName, 3, decision, expectedCounters);
+       if (! result) goto cleanup;
+       
+       decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;4"));
+       result = Check(testName, 4, decision, true, domainMUON, "MUON trigger");
+       if (! result) goto cleanup;
+       expectedCounters[4] = 1; expectedCounters[5] = 4;
+       result = CheckCounters(testName, 4, decision, expectedCounters);
+       if (! result) goto cleanup;
+       
+       decision = dynamic_cast<AliHLTGlobalTriggerDecision*>(file->Get("HLTGlobalTrigger;5"));
+       result = Check(testName, 5, decision, true, AliHLTTriggerDomain(), "End of data");
+       if (! result) goto cleanup;
+       expectedCounters[1] = 1; expectedCounters[5] = 5;
+       result = CheckCounters(testName, 5, decision, expectedCounters);
+       if (! result) goto cleanup;
+       
+       delete file;
+       return true;
+       
+cleanup:
+       if (decision != NULL)
+       {
+               cout << "========== Dumping incorrect decision ========== " << endl;
+               decision->Print();
+       }
+       delete file;
+       return false;
+}
+
+/**
+ * This method performs the same task as for CheckDifferentModes, but trying to
+ * test the behaviour of the global HLT trigger component with L0 software triggers.
+ * \param version  The trigger menu configuration version to use in <i>RunTrigger</i>.
+ * \param testName  The name of the test being run.
+ * \param customClass  Name of the custom class as passed to <i>RunTrigger</i>.
+ * \param showOutput  If true then the output from the RunTriggerSW method is not suppressed.
+ * \returns true if the different checks succeeded and false otherwise.
+ */
+bool CheckDifferentSWTestModes(
+               int version, const char* testName,
+               const char* customClass = NULL, bool showOutput = false
+       )
+{
+       TString name = testName;
+       name += " in debug mode";
+       cout << "#################### Running test: " << name.Data() << " ####################" << endl;
+       CallRunTriggerSW(version, false, true, customClass, showOutput);
+       if (! CheckSoftwareTriggerTestConfig(testName)) return false;
+       gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
+       
+       name = testName;
+       cout << "#################### Running test: " << name.Data() << " ####################" << endl;
+       CallRunTriggerSW(version, false, false, customClass, showOutput);
+       if (! CheckSoftwareTriggerTestConfig(testName)) return false;
+       gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
+       
+       name = testName;
+       name += " interpreted with CINT in debug mode";
+       cout << "#################### Running test: " << name.Data() << " ####################" << endl;
+       CallRunTriggerSW(version, true, true, customClass, showOutput);
+       if (! CheckSoftwareTriggerTestConfig(testName)) return false;
+       gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
+       
+       name = testName;
+       name += " interpreted with CINT";
+       cout << "#################### Running test: " << name.Data() << " ####################" << endl;
+       CallRunTriggerSW(version, true, false, customClass, showOutput);
+       if (! CheckSoftwareTriggerTestConfig(testName)) return false;
+       gSystem->Exec("rm -f testOutputFile.root");  // Cleanup output file for next test.
+       
+       return true;
+}
+
+/**
  * Runs several tests for the AliHLTGlobalTriggerComponent class.
  * We specifically test if the global trigger menu configuration is interpreted
  * correctly and the trigger logic generated correctly on the fly.
@@ -704,18 +955,32 @@ bool testGlobalTriggerComponent(int configVersion = -1, const char* customClass
                case 2: function = CheckPrescalarTestConfig; break;
                case 3: function = CheckSymbolTestConfig; break;
                case 4: function = CheckComplexTestConfig; break;
+               case 5: break;
                default:
                        cerr << "ERROR: Invalid value for configVersion specified." << endl;
                        return false;
                }
-               bool result = CheckDifferentModes(
-                               function,
-                               configVersion,
-                               Form("Config version %d", configVersion),
-                               numOfEvents,
-                               customClass,
-                               true
-                       );
+               bool result = false;
+               if (configVersion != 5)
+               {
+                       result = CheckDifferentModes(
+                                       function,
+                                       configVersion,
+                                       Form("Config version %d", configVersion),
+                                       numOfEvents,
+                                       customClass,
+                                       true
+                               );
+               }
+               else
+               {
+                       result = CheckDifferentSWTestModes(
+                                       configVersion,
+                                       Form("Config version %d", configVersion),
+                                       customClass,
+                                       true
+                               );
+               }
                return result;
        }
        
@@ -724,6 +989,7 @@ bool testGlobalTriggerComponent(int configVersion = -1, const char* customClass
        if (! CheckDifferentModes(CheckPrescalarTestConfig, 2, "Prescalar config", numOfEvents, customClass)) return false;
        if (! CheckDifferentModes(CheckSymbolTestConfig, 3, "Symbol config", numOfEvents, customClass)) return false;
        if (! CheckDifferentModes(CheckComplexTestConfig, 4, "Complex config", numOfEvents, customClass)) return false;
+       if (! CheckDifferentSWTestModes(5, "Software trigger config", customClass)) return false;
        
        // Cleanup all temporary files generated.
        gSystem->Exec("rm -f testOutputFile.root testInputFile*.root AliHLTGlobalTriggerImpl*");