42 L1MenuFlags.MenuSetup = flags.Trigger.triggerMenuSetup
57 AlgCategory.TOPO : 0, AlgCategory.MUCTPI : 0, AlgCategory.LEGACY : 0 }
61 for cat
in AlgCategory.getAllCategories():
65 L1MenuFlags.CTPVersion = 4
68 self.
l1menu.setBunchGroupSplitting()
71 log.error(
"Generating L1 menu %s is not possible", self.
menuName)
73 log.info(
"=== Generating L1 menu %s ===", self.
menuName)
173 Add all L1Topo triggers that are part of the menu as allowed input to the menu
179 for cat
in AlgCategory.getAllCategories():
182 outputLines += algo.outputs
if (
type(algo.outputs)
is list)
else [ algo.outputs ]
183 _topoTriggers[cat] = sorted(outputLines)
184 log.info(
"... found %i topo triggerlines (source: %s)", len(_topoTriggers[cat]), cat )
185 log.debug(
"%r", _topoTriggers[cat])
188 multibitPattern = re.compile(
r"(?P<line>.*)\[(?P<bit>\d+)\]")
189 for cat
in [AlgCategory.TOPO, AlgCategory.MUCTPI, AlgCategory.LEGACY]:
190 multibitTopoTriggers =
set()
191 for topoLineName
in _topoTriggers[cat]:
192 m = multibitPattern.match(topoLineName)
194 topoThrName = cat.prefix + m.groupdict()[
'line']
195 multibitTopoTriggers.add( topoThrName )
197 topoThrName = cat.prefix + topoLineName
200 for topoThrName
in multibitTopoTriggers:
220 def writeJSON(self, outputFile, bgsOutputFile = None, destdir="./"):
222 outputFile = destdir.rstrip(
'/') +
'/' + outputFile
223 if bgsOutputFile
is not None:
224 bgsOutputFile = destdir.rstrip(
'/') +
'/' + bgsOutputFile
226 bgsOutputFile = bgsOutputFile).
writeJSON(pretty=
True)
227 return outputFile, bgsOutputFile
229 log.error(
"No menu was generated, can not create json file")
261 Defines the list if item and threshold names that will be in the menu
262 Calls defineMenu() of the correct module 'Menu_<menuname>.py'
263 Menu.defineMenu() defines the menu via L1MenuFlags "items", "thresholds",
267 log.info(
"Reading TriggerMenuMT.Menu.Menu_%s", self.
menuFilesToLoad[0])
268 menumodule = __import__(
'TriggerMenuMT.L1.Menu.Menu_%s' % self.
menuFilesToLoad[0], globals(), locals(), [
'defineMenu'], 0)
269 menumodule.defineMenu()
270 log.info(
"... L1 menu '%s' contains %i items", self.
menuFilesToLoad[0], len(L1MenuFlags.items()))
272 log.info(
"Reading TriggerMenuMT.Menu.Menu_%s", self.
menuFilesToLoad[1])
273 topomenumodule = __import__(
'TriggerMenuMT.L1.Menu.Menu_%s' % self.
menuFilesToLoad[1], globals(), locals(), [
'defineMenu'], 0)
274 topomenumodule.defineInputsMenu()
277 for boardName, boardDef
in L1MenuFlags.boards().items():
278 if "connectors" in boardDef:
279 connectorCount += len(boardDef[
"connectors"])
280 for c
in boardDef[
"connectors"]:
281 if "thresholds" in c:
282 algoCount += len(c[
"thresholds"])
283 elif "algorithmGroups" in c:
284 for t
in c[
"algorithmGroups"]:
285 algoCount += len(t[
"algorithms"])
287 for t
in c[
"signalGroups"]:
288 algoCount += len(t[
"signals"])
289 log.info(
"... L1Topo menu '%s' contains %i boards (%s)", self.
menuFilesToLoad[0], len(L1MenuFlags.boards()),
', '.join(L1MenuFlags.boards().keys()))
290 log.info(
" with %i connectors and %i input signals", connectorCount, algoCount)
293 log.info(
"Reading TriggerMenuMT.Menu.Menu_%s", self.
menuFilesToLoad[2])
294 legacymenumodule = __import__(
'TriggerMenuMT.L1.Menu.Menu_%s' % self.
menuFilesToLoad[2], globals(), locals(), [
'defineMenu'], 0)
295 legacymenumodule.defineLegacyInputsMenu()
296 log.info(
"... L1 legacy menu %s contains %i legacy boards (%s)", self.
menuFilesToLoad[2], len(L1MenuFlags.legacyBoards()),
', '.join(L1MenuFlags.legacyBoards().keys()))
297 except ImportError
as ie:
298 if ie.name ==
'TriggerMenuMT.L1.Menu.Menu_%s' % self.
menuFilesToLoad[2]:
299 log.info(
"==> No menu defining the legacy inputs was found, will assume this intended. %s %s %s",
300 ie.msg, ie.name, ie.path)
306 Registers the list if items and thresholds that could be used in the menu
307 Calls registerItem() of the correct module 'ItemDef.py'
309 from .Base.Items
import MenuItem
310 MenuItem.setMenuConfig(self)
311 from .Base.Thresholds
import Threshold
312 Threshold.setMenuConfig(self)
315 for algCat
in [AlgCategory.TOPO, AlgCategory.MUCTPI, AlgCategory.MULTI, AlgCategory.LEGACY]:
317 defFile =
"TriggerMenuMT.L1.Config.%s" % self.
currentAlgoDef.defFile
318 log.info(
"Reading %s", defFile)
319 import_module(defFile).__getattribute__(self.
currentAlgoDef.defFile).registerTopoAlgos(self)
322 log.info(
"Reading TriggerMenuMT.Config.ThreholdDef")
323 from .Config.ThresholdDef
import ThresholdDef
324 ThresholdDef.registerThresholds(self, self.
menuFullName)
329 log.info(
"Reading TriggerMenuMT.Config.ThreholdDefLegacy")
330 from .Config.ThresholdDefLegacy
import ThresholdDefLegacy
331 ThresholdDefLegacy.registerThresholds(self, self.
menuFullName)
334 log.info(
"Turning topo algo outputs into thresholds (except multiplicity counters)")
340 log.info(
"Reading TriggerMenuMT.Config.ItemDef")
398 allBoardsWithTopo = list( filter (
399 lambda b : BoardType.fromBoardName(b[0])
in [BoardType.TOPO, BoardType.MUCTPI],
400 chain(L1MenuFlags.boards().items(), L1MenuFlags.legacyBoards().items())
408 for (boardName, boardDef)
in allBoardsWithTopo:
409 currentTopoCategory = AlgCategory.getCategoryFromBoardName(boardName)
410 for connDef
in boardDef[
"connectors"]:
411 if connDef[
"format"] ==
'multiplicity':
413 for algGrp
in connDef[
"algorithmGroups"]:
414 for topodef
in algGrp[
"algorithms"]:
416 nLines += len(topodef.outputlines)
418 outputlines = list(dict.fromkeys(
map(
lambda x: re.split(
r"\[\d\]",x)[0], topodef.outputlines)))
419 for lineName
in outputlines:
420 thrName = currentTopoCategory.prefix + lineName
423 if 'legacy' in boardDef:
424 msg =
'Threshold %s is required for board %s, connector %s (file L1/Menu/Menu_%s.py), but it is not registered. ' % (thrName, boardName, connDef[
'name'], self.
menuFilesToLoad[2])
425 msg +=
'Please add L1Topo alg with output %s to L1/Config/TopoAlgoDefLegacy.py.' % (thrName.split(
'_',1)[-1])
427 msg =
'Threshold %s is required for board %s, connector %s (file L1/Menu/Menu_%s.py), but it is not registered. ' % (thrName, boardName, connDef[
'name'], self.
menuFilesToLoad[1])
428 msg +=
'Please add L1Topo alg with output %s to L1/Config/TopoAlgoDef.py.' % (thrName.split(
'_',1)[-1])
430 raise RuntimeError(msg)
432 self.
l1menu.addThreshold( thr )
433 log.info(
"Generating topo menu using %i topo algorithms with %i trigger lines", nAlgos, nLines )
441 allRequiredSortedInputs = {
442 AlgCategory.TOPO :
set(),
443 AlgCategory.MUCTPI :
set(),
444 AlgCategory.LEGACY :
set()
448 for (boardName, boardDef)
in allBoardsWithTopo:
449 for connDef
in boardDef[
"connectors"]:
450 if (
'muctpi' in boardName.lower())
and (connDef[
"format"]==
'multiplicity'):
454 currentTopoCategory = AlgCategory.getCategoryFromBoardName(boardName)
455 if currentTopoCategory == AlgCategory.TOPO
and connDef[
"format"] ==
'multiplicity':
456 currentTopoCategory = AlgCategory.MULTI
460 if connDef[
"format"] ==
'multiplicity':
461 for thrName
in connDef[
"thresholds"]:
464 nBits = connDef[
"nbitsDefault"]
465 if type(thrName)==tuple:
466 (thrName,nBits) = thrName
469 algoname =
"Mult_" + thrName
470 algoNames += [ algoname ]
471 algoNbits += [ int(nBits) ]
473 elif connDef[
"format"] ==
'topological':
474 for algGrp
in connDef[
"algorithmGroups"]:
475 for topodef
in algGrp[
"algorithms"]:
476 algoNames += [ topodef.algoname ]
478 fpgaNames += [str(algGrp[
'fpga'])]
479 for algoName, algoBits, fpgaName
in zip(algoNames, algoNbits, fpgaNames):
483 if algoBits != algo.nbits:
484 msg =
"Algorithm %s defined with %i bits, but the associated threshold has %i bits " % (algo.name, algo.nbits, algoBits)
485 raise RuntimeError(msg)
486 self.
l1menu.checkBoardInputs(algo, connDef[
"name"], fpgaName)
488 self.
l1menu.addTopoAlgo( algo, category = currentTopoCategory )
491 if algo.isDecisionAlg():
492 allRequiredSortedInputs[currentTopoCategory].update( algo.inputs )
495 for cat
in allRequiredSortedInputs:
496 for input
in allRequiredSortedInputs[cat]:
499 self.
l1menu.addTopoAlgo( sortingAlgo, category = cat )
505 if len(self.
l1menu.items) > 0:
506 log.info(
"L1MenuConfig.generate() has already been called. Will ignore")
510 Generates the menu structure from the list of item and threshold names in the L1MenuFlags
516 from .Base.BunchGroupSet
import createDefaultBunchGroupSet
517 self.
l1menu.ctp.bunchGroupSet = createDefaultBunchGroupSet(flags)
524 allBoards = (list(L1MenuFlags.boards().items()) + list(L1MenuFlags.legacyBoards().items()))
530 ItemDef.registerItems_AllCTPIn(self)
532 for (boardName, boardDef)
in L1MenuFlags.legacyBoards().items():
533 for connDef
in boardDef[
"connectors"]:
535 if connDef[
"type"] ==
"ctpin" and connDef[
"format"] ==
"multiplicity":
536 self.
l1menu.checkL1CaloThresholds(connDef[
"thresholds"], boardName, connDef[
"name"])
538 list_of_undefined_thresholds = []
540 for (boardName, boardDef)
in L1MenuFlags.boards().items():
541 for connDef
in boardDef[
"connectors"]:
542 if connDef[
"type"] ==
"ctpin" or connDef[
"format"] !=
"multiplicity":
544 for thrName
in connDef[
"thresholds"]:
545 if type(thrName)
is tuple:
546 (thrName, _) = thrName
547 if (thrName
is None)
or (thrName
in self.
l1menu.thresholds):
550 if threshold
is None:
551 log.error(
'Threshold %s is required in menu on board %s, connector %s, but it is not defined', thrName, boardName, connDef[
'name'] )
552 list_of_undefined_thresholds += [ thrName ]
554 self.
l1menu.addThreshold( threshold )
556 zbThrName = connDef[
"zeroBias"]
559 log.error(
'Zero bias threshold %s is listed in menu but not defined', zbThrName )
560 list_of_undefined_thresholds += [ zbThrName ]
562 self.
l1menu.addThreshold( zbThr )
568 for (boardName, boardDef)
in L1MenuFlags.boards().items():
569 for connDef
in boardDef[
"connectors"]:
570 if connDef[
"format"] !=
"simple":
572 for sGrp
in connDef[
"signalGroups"]:
573 for thrName
in sGrp[
"signals"]:
574 if type(thrName)
is tuple:
575 (thrName, _) = thrName
576 if thrName
is None or thrName
in self.
l1menu.thresholds:
579 if threshold
is None:
580 log.error(
'Threshold %s is required in menu on board %s, connector %s, but it is not defined', thrName, boardName, connDef[
'name'] )
581 list_of_undefined_thresholds += [ thrName ]
583 self.
l1menu.addThreshold( threshold )
586 for (boardName, boardDef)
in allBoards:
587 for connDef
in boardDef[
"connectors"]:
588 if connDef[
"type"] !=
"ctpin":
590 for entry
in connDef[
"thresholds"]:
591 if type(entry)
is dict:
593 thrNames = sum([x.outputlines
for x
in entry[
"algorithms"]],[])
594 elif type(entry)
is str:
596 elif type(entry)
is tuple:
597 thrNames = [ entry[0] ]
599 for thrName
in thrNames:
600 if thrName
is None or thrName
in self.
l1menu.thresholds:
603 if threshold
is None:
604 log.error(
'Threshold %s is listed in menu but not defined', thrName )
605 list_of_undefined_thresholds += [ thrName ]
607 self.
l1menu.addThreshold( threshold )
609 zbThrName = connDef[
"zeroBias"]
612 log.error(
'Zero bias threshold %s is listed in menu but not defined', zbThrName )
613 list_of_undefined_thresholds += [ zbThrName ]
615 self.
l1menu.addThreshold( zbThr )
619 if len(list_of_undefined_thresholds)>0:
620 raise RuntimeError(
"Found undefined threshold in menu %s, please add these thresholds to l1menu/ThresholdDef.py: %s" % \
621 (self.
l1menu.menuName,
', '.join(list_of_undefined_thresholds)) )
630 ctpIdMap = L1MenuFlags.CtpIdMap()
631 for itemName
in L1MenuFlags.items():
633 if registeredItem
is None:
634 msg =
"L1 item '%s' has not been defined in L1/Config/ItemDef.py" % itemName
636 raise RuntimeError(msg)
638 if itemName
in ctpIdMap:
639 newCTPID = ctpIdMap[itemName]
640 registeredItem.setCtpid(newCTPID)
642 for thrName
in registeredItem.thresholdNames():
643 if thrName
not in self.
l1menu.thresholds:
644 isLegacyThr = any(filter(
lambda x: thrName.startswith(x), [
"R2TOPO_",
"EM",
"HA",
"J",
"XE",
"TE",
"XS"]))
646 msg =
"L1 item {item} has been added to the menu L1/Menu/Menu_{menu}.py, but the required threshold {thr} is not listed as input in L1/Menu/Menu_{menu_inputs}.py".format(item=itemName, thr=thrName, menu=self.
menuFilesToLoad[0], menu_inputs=self.
menuFilesToLoad[2]
if isLegacyThr
else self.
menuFilesToLoad[1])
648 raise RuntimeError(msg)
650 itemsForMenu += [ registeredItem ]
655 assigned_ctpids =
set([item.ctpid
for item
in itemsForMenu])
656 available_ctpids = sorted( list(
set(range(Limits.MaxTrigItems)) - assigned_ctpids ), reverse=
True )
659 for item
in itemsForMenu:
661 if not item.name.startswith(
'L1_CALREQ'):
662 item.setTriggerType( item.trigger_type | TT.phys )
665 if len(available_ctpids)==0:
666 raise RuntimeError(
"No more CTP IDs available at L1!!")
667 item.setCtpid( available_ctpids.pop() )
669 self.
l1menu.addItem( item )
675 for (boardName, boardDef)
in allBoards:
676 for connDef
in boardDef[
"connectors"]:
677 self.
l1menu.addConnector( connDef )
683 for (boardName, boardDef)
in allBoards:
684 self.
l1menu.addBoard(boardDef)
689 legacyThresholdsSet =
set()
690 for conn
in self.
l1menu.connectors:
691 if not conn.isLegacy():
693 legacyThresholdsSet.update(conn.triggerThresholds())
694 for item
in self.
l1menu.items:
695 item.markLegacy(legacyThresholdsSet)
708 self.
l1menu.setupCTPMonitoring()
720 if 'pp' in self.
l1menu.menuName:
721 self.
l1menu.checkLegacyThresholds()
725 TopoAlgoDefMultiplicity.checkMultAlgoFWconstraints(self.
l1menu)
728 self.
l1menu.checkCountCTPInputsOutput()
731 self.
l1menu.checkCTPINconnectors()
734 self.
l1menu.checkPerfThresholds()
737 self.
l1menu.checkPtMinToTopo()
740 self.
l1menu.checkL1TopoParams()
743 self.
l1menu.checkItemsHaveInputs()
746 self.
l1menu.checkTOPObits()
750 self.
l1menu.checkHFmonitoring()
754 Set the correct mapping of thresholds according to the
755 order it was given in L1MenuFlags.thresholds list. That list
756 is usually defined in the setupMenu function of each menu
758 NIM and CALREQ types are not remapped !!
761 alreadyUsedMappingNumbers = ddict(set)
762 for thr
in self.
l1menu.thresholds:
765 alreadyUsedMappingNumbers[thr.ttype].
add(thr.mapping)
767 nextFreeMapping = ddict(
lambda: 0)
768 for k
in alreadyUsedMappingNumbers:
769 nextFreeMapping[k] = 0
770 for thr
in self.
l1menu.thresholds():
772 while nextFreeMapping[thr.ttype]
in alreadyUsedMappingNumbers[thr.ttype]:
773 nextFreeMapping[thr.ttype] += 1
774 log.debug(
'Setting mapping of threshold %s as %i', thr, nextFreeMapping[thr.ttype])
775 thr.mapping = nextFreeMapping[thr.ttype]
776 nextFreeMapping[thr.ttype] += 1