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