# Profile Management System ## Overview Il sistema di gestione dei profili è stato completamente ristrutturato per supportare una configurazione gerarchica a tre livelli che rispecchia fedelmente il formato `targets.ini` della vecchia applicazione C++/Qt. ## Struttura ### 1. GlobalConfig Configurazione globale del sistema: - **ip**: Indirizzo IP per la comunicazione SRIO - **port**: Porta per comunicazione TFTP/SRIO - **srio_base**: Indirizzo base SRIO (es. 0x500000) - **fpga_base**: Indirizzo base FPGA (es. 0x0) - **fpga_sector**: Dimensione settore FPGA (es. 0x010000) - **smart**: Flag modalità smart (0 o 1) - **section**: Sezione flash di default (es. "APP1") - **default_target**: Target di default da usare ### 2. FlashModel Definizione riutilizzabile di modelli FPGA: - **id_model**: ID univoco del modello (0, 1, 2, ...) - **model**: Nome del modello (es. "xcku040", "rfif") - **description**: Descrizione leggibile - **flash_type**: Tipo di flash (0 o 1) - **is_4byte_addressing**: True per indirizzamento a 4 byte - **num_sectors**: Numero totale di settori - **golden_start/stop**: Area Golden (firmware di boot) - **user_start/stop**: Area User (firmware applicativo) - **test_address**: Indirizzo opzionale per test ### 3. FlashTarget Target specifico (FPGA installata): - **id_target**: ID univoco del target (es. "EIF_FPGA1") - **description**: Descrizione leggibile - **slot_address**: Indirizzo slot SRIO (es. 0x13) - **architecture**: Architettura (es. "Xilinx", "RFIF") - **name**: Nome del target - **file_prefix**: Prefisso per i file firmware - **id_model**: Riferimento all'ID del modello - **binary_path**: Path opzionale al file binario ## Utilizzo ### Caricamento da INI ```python from pathlib import Path from pydownloadfwviasrio.profiles import ProfileManager # Crea manager e carica da targets.ini manager = ProfileManager() manager.load_from_ini(Path("_OLD/Vecchia_app/FpgaBeamMeUp/targets.ini")) # Salva in formato JSON manager.config_path = Path("flash_profiles.json") manager.save() ``` ### Caricamento da JSON ```python from pydownloadfwviasrio.profiles import ProfileManager # Carica configurazione esistente manager = ProfileManager(Path("flash_profiles.json")) # Accedi alla configurazione globale print(f"IP: {manager.global_config.ip}") print(f"Port: {manager.global_config.port}") ``` ### Accesso ai Target e Modelli ```python # Ottieni un target specifico target = manager.get_target("AESA_RFIF") if target: print(f"Slot: 0x{target.slot_address:02X}") print(f"Architecture: {target.architecture}") # Ottieni il modello associato model = manager.get_model(target.id_model) if model: print(f"Model: {model.model}") print(f"Sectors: {model.num_sectors}") print(f"Addressing: {'4-byte' if model.is_4byte_addressing else '3-byte'}") # O usa il metodo comodo per ottenere entrambi result = manager.get_target_with_model("AESA_RFIF") if result: target, model = result # ... usa target e model ``` ### Iterazione sui Target ```python # Lista tutti i target disponibili for id_target in manager.list_targets(): target = manager.get_target(id_target) model = manager.get_model(target.id_model) print(f"{id_target}: {target.description}") print(f" Model: {model.model} ({model.description})") ``` ### Aggiunta/Modifica ```python from pydownloadfwviasrio.profiles import FlashModel, FlashTarget # Aggiungi un nuovo modello new_model = FlashModel( id_model=3, model="xcku115", description="512Mbit xcku115", flash_type=1, is_4byte_addressing=True, num_sectors=1024, golden_start=0x00000000, golden_stop=0x01FFFFFF, user_start=0x02000000, user_stop=0x03FFFFFF, ) manager.add_model(new_model) # Aggiungi un nuovo target new_target = FlashTarget( id_target="TEST_FPGA1", description="Test FPGA 0x20", slot_address=0x20, architecture="Xilinx", name="TEST_FPGA1", file_prefix="TEST_FPGA1", id_model=3, # Riferimento al modello appena creato ) manager.add_target(new_target) # Salva le modifiche manager.save() ``` ### Esportazione in INI ```python # Esporta la configurazione in formato INI manager.export_to_ini(Path("new_targets.ini")) ``` ## Vantaggi della Nuova Struttura 1. **DRY (Don't Repeat Yourself)**: I modelli si definiscono una volta sola e vengono referenziati dai target 2. **Manutenibilità**: Modifiche al modello si propagano automaticamente a tutti i target che lo usano 3. **Estensibilità**: Facile aggiungere nuovi target senza duplicare configurazioni 4. **Retrocompatibilità**: Supporta sia formato JSON che INI 5. **Type Safety**: Uso di dataclass con type hints per validazione automatica ## Migrazione da Vecchio Formato Il vecchio formato (lista di `FlashProfile`) è deprecato ma ancora supportato per retrocompatibilità. Per convertire: ```python from pydownloadfwviasrio.profiles import initialize_from_targets_ini # Conversione automatica da targets.ini manager = initialize_from_targets_ini( ini_path=Path("_OLD/Vecchia_app/FpgaBeamMeUp/targets.ini"), json_path=Path("flash_profiles.json") ) ``` ## File di Configurazione Iniziali Il progetto include già un file `flash_profiles.json` generato dal `targets.ini` originale con: - **3 modelli**: xcku040, xcku060, rfif - **9 target**: EIF_FPGA1/2, XIF1_FPGA1/2, XIF2_FPGA1/2, DFE_FPGA1/2, AESA_RFIF ## Script di Utilità Nella cartella `tools/` sono disponibili: - **convert_ini_to_json.py**: Converte targets.ini in flash_profiles.json - **example_profile_usage.py**: Esempio completo di utilizzo del sistema - **test_conversion.py**: Test di conversione bidirezionale INI ↔ JSON ## Esempio Completo ```python from pathlib import Path from pydownloadfwviasrio.profiles import ProfileManager # Carica configurazione manager = ProfileManager(Path("flash_profiles.json")) # Ottieni target di default con modello default_id = manager.global_config.default_target result = manager.get_target_with_model(default_id) if result: target, model = result print(f"Programming target: {target.id_target}") print(f"Slot address: 0x{target.slot_address:02X}") print(f"IP:Port: {manager.global_config.ip}:{manager.global_config.port}") print(f"Model: {model.model}") print(f"Flash type: {model.flash_type}") print(f"Addressing: {'4-byte' if model.is_4byte_addressing else '3-byte'}") print(f"Golden area: 0x{model.golden_start:08X} - 0x{model.golden_stop:08X}") print(f"User area: 0x{model.user_start:08X} - 0x{model.user_stop:08X}") # Qui puoi usare questi dati per la programmazione... ```