323):
324 """Simple script to create an OKS configuration file for all
325 ReadoutApplications defined in a readout map.
326
327 The file will automatically include the relevant schema files and
328 any other OKS files you specify.
329
330 Example:
331 generate_readoutOKS -i hosts \
332 -i appmodel/connections.data.xml -i appmodel/moduleconfs \
333 config/np04readoutmap.data.xml readoutApps.data.xml
334
335 Will load hosts, connections and moduleconfs data files as well as
336 the readoutmap (config/np04readoutmap.data.xml) and write the
337 generated apps to readoutApps.data.xml.
338
339 generate_readoutOKS --session --segment \
340 -i appmodel/fsm -i hosts \
341 -i appmodel/connections.data.xml -i appmodel/moduleconfs \
342 config/np04readoutmap.data.xml np04readout-session.data.xml
343
344 Will do the same but in addition it will generate a containing
345 Segment for the apps and a containing Session for the Segment.
346
347 NB: Currently FSM generation is not implemented so you must include
348 an fsm file in order to generate a Segment
349
350 """
351
352 if not readoutmap.endswith(".data.xml"):
353 readoutmap = readoutmap + ".data.xml"
354
355 print(f"Readout map file {readoutmap}")
356
357 includefiles = [
358 "schema/confmodel/dunedaq.schema.xml",
359 "schema/appmodel/application.schema.xml",
360 "schema/appmodel/trigger.schema.xml",
361 "schema/appmodel/fdmodules.schema.xml",
362 "schema/appmodel/wiec.schema.xml",
363 readoutmap,
364 ]
365
366 searchdirs = [path for path in os.environ["DUNEDAQ_DB_PATH"].split(":")]
367 searchdirs.append(os.path.dirname(oksfile))
368 for inc in include:
369
370 match = False
371 inc = inc.removesuffix(".xml")
372 if inc.endswith(".data"):
373 sub_dirs = ["config", "data"]
374 elif inc.endswith(".schema"):
375 sub_dirs = ["schema"]
376 else:
377 sub_dirs = ["*"]
378 inc = inc + "*"
379 for path in searchdirs:
380
381 matches = glob.glob(f"{inc}.xml", root_dir=path)
382 if len(matches) == 0:
383 for search_dir in sub_dirs:
384
385 matches = glob.glob(f"{search_dir}/{inc}.xml", root_dir=path)
386 for filename in matches:
387 if filename not in includefiles:
388 print(f"Adding {filename} to include list")
389 includefiles.append(filename)
390 else:
391 print(f"{filename} already in include list")
392 match = True
393 break
394 if match:
395 break
396 if match:
397 break
398 else:
399 for filename in matches:
400 if filename not in includefiles:
401 print(f"Adding {filename} to include list")
402 includefiles.append(filename)
403 else:
404 print(f"{filename} already in include list")
405 match = True
406 break
407
408 if not match:
409 print(f"Error could not find include file for {inc}")
410 return
411
414 if not oksfile.endswith(".data.xml"):
415 oksfile = oksfile + ".data.xml"
416 print(f"Creating OKS database file {oksfile}")
417 db.create_db(oksfile, includefiles)
418 db.set_active(oksfile)
419
420 detector_connections = db.get_dals(class_name="DetectorToDaqConnection")
421 daqapp_control = db.get_dal(class_name="Service", uid="daqapp_control")
422 rccontroller_control = db.get_dal(class_name="Service", uid="rccontroller_control")
423
424 try:
425 rule = db.get_dal(
426 class_name="NetworkConnectionRule", uid="data-req-readout-net-rule"
427 )
428 except:
429 print(
430 'Expected NetworkConnectionRule "data-req-readout-net-rule" not found in input databases!'
431 )
432 else:
433 netrules = [rule]
434
435 for rule in ["tpset-net-rule", "ts-net-rule", "ta-net-rule"]:
436 netrules.append(db.get_dal(class_name="NetworkConnectionRule", uid=rule))
437
438 try:
439 rule = db.get_dal(
440 class_name="QueueConnectionRule", uid="fd-dlh-data-requests-queue-rule"
441 )
442 except:
443 print(
444 'Expected QueueConnectionRule "fd-dlh-data-requests-queue-rule" not found in input databases!'
445 )
446 else:
447 qrules = [rule]
448 for rule in [
449 "fa-queue-rule",
450 "tp-queue-rule",
451 ]:
452 qrules.append(db.get_dal(class_name="QueueConnectionRule", uid=rule))
453
454 hosts = []
455 if len(hosts_to_use) == 0:
456 for vhost in db.get_dals(class_name="VirtualHost"):
457 if vhost.id == "vlocalhost":
458 hosts.append(vhost.id)
459 if "vlocalhost" not in hosts:
460 cpus = dal.ProcessingResource("cpus", cpu_cores=[0, 1, 2, 3])
461 db.update_dal(cpus)
462 phdal = dal.PhysicalHost("localhost", contains=[cpus])
463 db.update_dal(phdal)
464 host = dal.VirtualHost("vlocalhost", runs_on=phdal, uses=[cpus])
465 db.update_dal(host)
466 hosts.append("vlocalhost")
467 else:
468 for vhost in db.get_dals(class_name="VirtualHost"):
469 if vhost.id in hosts_to_use:
470 hosts.append(vhost.id)
471 assert len(hosts) > 0
472
473 rohw = dal.RoHwConfig(f"rohw-{detector_connections[0].id}")
474 db.update_dal(rohw)
475
476 opmon_conf = db.get_dal(class_name="OpMonConf", uid="slow-all-monitoring")
477
478 appnum = 0
479 nicrec = None
480 flxcard = None
481 wm_conf = None
482 hermes_conf = None
483 ruapps = []
484 for connection in detector_connections:
485
486 geo_id = connection.get("GeoId")
487 det_id = geo_id[0].detector_id
488 if det_id == 0:
489 raise Exception(f"Unable to determine detector ID from Hardware Map!")
490
491 tphandler = db.get_dal(class_name="DataHandlerConf", uid="def-tp-handler")
492
493 if det_id == 2:
494 if "DAPHNEStream" in emulated_file_name:
495 linkhandler = db.get_dal(
496 class_name="DataHandlerConf", uid="def-pds-stream-link-handler"
497 )
498 det_q = db.get_dal(
499 class_name="QueueConnectionRule", uid="pds-stream-raw-data-rule"
500 )
501 else:
502 linkhandler = db.get_dal(
503 class_name="DataHandlerConf", uid="def-pds-link-handler"
504 )
505 det_q = db.get_dal(
506 class_name="QueueConnectionRule", uid="pds-raw-data-rule"
507 )
508
509 elif det_id == 3:
510 linkhandler = db.get_dal(
511 class_name="DataHandlerConf", uid="def-link-handler"
512 )
513 det_q = db.get_dal(
514 class_name="QueueConnectionRule", uid="wib-eth-raw-data-rule"
515 )
516 elif det_id == 11:
517 linkhandler = db.get_dal(
518 class_name="DataHandlerConf", uid="def-tde-link-handler"
519 )
520 det_q = db.get_dal(
521 class_name="QueueConnectionRule", uid="tde-raw-data-rule"
522 )
523 elif det_id == 12:
524 linkhandler = db.get_dal(
525 class_name="DataHandlerConf", uid="def-crt-bern-link-handler"
526 )
527 det_q = db.get_dal(
528 class_name="QueueConnectionRule", uid="crt-bern-raw-data-rule"
529 )
530 elif det_id == 13:
531 linkhandler = db.get_dal(
532 class_name="DataHandlerConf", uid="def-crt-grenoble-link-handler"
533 )
534 det_q = db.get_dal(
535 class_name="QueueConnectionRule", uid="crt-grenoble-raw-data-rule"
536 )
537
538 hostnum = appnum % len(hosts)
539
540 host = db.get_dal(class_name="VirtualHost", uid=hosts[hostnum])
541
542
543 if connection.className() == "NetworkDetectorToDaqConnection":
544 receiver = connection.net_receiver
545 elif connection.className() == "FelixDetectorToDaqConnection":
546 receiver = connection.felix_receiver
547
548
549 if type(receiver).__name__ == "FakeDataReceiver":
550 if nicrec == None:
551 try:
552 stream_emu = db.get_dal(
553 class_name="StreamEmulationParameters", uid="stream-emu"
554 )
555 stream_emu.data_file_name = resolve_asset_file(emulated_file_name)
556 db.update_dal(stream_emu)
557 except:
558 stream_emu = dal.StreamEmulationParameters(
559 "stream-emu",
560 data_file_name=resolve_asset_file(emulated_file_name),
561 input_file_size_limit=5777280,
562 set_t0=True,
563 random_population_size=100000,
564 frame_error_rate_hz=0,
565 generate_periodic_adc_pattern=True,
566 TP_rate_per_channel=1,
567 )
568 db.update_dal(stream_emu)
569
570 print("Generating fake DataReaderConf")
571 nicrec = dal.DPDKReaderConf(
572 f"nicrcvr-fake-gen",
573 template_for="FDFakeReaderModule",
574 emulation_mode=1,
575 emulation_conf=stream_emu,
576 )
577 db.update_dal(nicrec)
578 datareader = nicrec
579 elif type(receiver).__name__ == "DPDKReceiver":
580 if nicrec == None:
581 print("Generating DPDKReaderConf")
582 nicrec = dal.DPDKReaderConf(
583 f"nicrcvr-dpdk-gen", template_for="DPDKReaderModule"
584 )
585 db.update_dal(nicrec)
586 if wm_conf == None:
587 try:
588 wm_conf = db.get_dal("WIBModuleConf", "def-wib-conf")
589 except:
590 print(
591 'Expected WIBModuleConf "def-wib-conf" not found in input databases!'
592 )
593 if hermes_conf == None:
594 try:
595 hermes_conf = db.get_dal("HermesModuleConf", "def-hermes-conf")
596 except:
597 print(
598 'Expected HermesModuleConf "def-hermes-conf" not found in input databases!'
599 )
600
601 datareader = nicrec
602
603 wiec_app = dal.WIECApplication(
604 f"wiec-{connection.id}",
605 application_name="daq_application",
606 runs_on=host,
607 detector_connections=[connection],
608 wib_module_conf=wm_conf,
609 hermes_module_conf=hermes_conf,
610 exposes_service=[daqapp_control],
611 )
612 db.update_dal(wiec_app)
613
614 elif type(receiver).__name__ == "FelixInterface":
615 if flxcard == None:
616 print("Generating Felix DataReaderConf")
617 flxcard = dal.DataReaderConf(
618 f"flxConf-1", template_for="FelixReaderModule"
619 )
620 db.update_dal(flxcard)
621 datareader = flxcard
622 else:
623 print(
624 f"ReadoutGroup contains unknown interface type {type(receiver).__name__}"
625 )
626 continue
627
628 db.commit()
629
630
631 dataRequests = db.get_dal(class_name="Service", uid="dataRequests")
632 timeSyncs = db.get_dal(class_name="Service", uid="timeSyncs")
633 triggerActivities = db.get_dal(class_name="Service", uid="triggerActivities")
634 triggerPrimitives = db.get_dal(class_name="Service", uid="triggerPrimitives")
635
636
637 readout_start = db.get_dal(class_name="ActionPlan", uid="readout-start")
638 readout_stop = db.get_dal(class_name="ActionPlan", uid="readout-stop")
639
640 ru = dal.ReadoutApplication(
641 f"ru-{connection.id}",
642 application_name="daq_application",
643 runs_on=host,
644 detector_connections=[connection],
645 network_rules=netrules,
646 queue_rules=qrules + [det_q],
647 link_handler=linkhandler,
648 data_reader=datareader,
649 opmon_conf=opmon_conf,
650 tp_generation_enabled=tpg_enabled,
651 ta_generation_enabled=tpg_enabled,
652 uses=rohw,
653 exposes_service=[daqapp_control, dataRequests, timeSyncs],
654 action_plans=[readout_start, readout_stop],
655 )
656 if tpg_enabled:
657 ru.tp_handler = tphandler
658 tp_sources = []
659 tpbaseid = (appnum * 3) + 100
660
661
662 for plane in range(1 if det_id not in [3, 10, 11] else 3):
663 s_id = tpbaseid + plane
664 tps_dal = dal.SourceIDConf(
665 f"tp-srcid-{s_id}", sid=s_id, subsystem="Trigger"
666 )
667 db.update_dal(tps_dal)
668 tp_sources.append(tps_dal)
669 ru.tp_source_ids = tp_sources
670 ru.exposes_service += [triggerActivities, triggerPrimitives]
671 appnum = appnum + 1
672 print(f"{ru=}")
673 db.update_dal(ru)
674 db.commit()
675 ruapps.append(ru)
676 if appnum == 0:
677 print(f"No ReadoutApplications generated\n")
678 return
679
680 db.commit()
681
682 if generate_segment:
683
684 fsm = db.get_dal(class_name="FSMconfiguration", uid="FSMconfiguration_noAction")
685 controller = dal.RCApplication(
686 "ru-controller",
687 application_name="drunc-controller",
688 runs_on=host,
689 fsm=fsm,
690 opmon_conf=opmon_conf,
691 exposes_service=[rccontroller_control],
692 )
693 db.update_dal(controller)
694 db.commit()
695
696 seg = dal.Segment(f"ru-segment", controller=controller, applications=ruapps)
697 db.update_dal(seg)
698 db.commit()
699
700 db.commit()
701 return
702
703