import json import os # --- Funciones Procesadoras por Tipo de Instrucción --- # Cada función recibe el diccionario de la instrucción del JSON. # Por ahora, solo imprimen información. def process_contact(instruction): """Procesa una instrucción 'Contact'.""" print(f" [Contact] UID: {instruction['instruction_uid']}") operand = instruction['inputs'].get('operand', {}) print(f" - Checks: {operand.get('scope', '?')} UID: {operand.get('uid', '?')}") # Adaptar si 'unknown_access' se resuelve in_source = instruction['inputs'].get('in', {}) if in_source.get('type') == 'powerrail': print(" - Input: Power Rail") elif in_source.get('type') == 'connection': print(f" - Input: From instruction {in_source.get('source_instruction_uid', '?')} (Pin: {in_source.get('source_pin', '?')})") else: print(f" - Input: {in_source}") def process_coil(instruction): """Procesa una instrucción 'Coil'.""" print(f" [Coil] UID: {instruction['instruction_uid']}") operand = instruction['inputs'].get('operand', {}) print(f" - Assigns to: {operand.get('scope', '?')} UID: {operand.get('uid', '?')}") in_source = instruction['inputs'].get('in', {}) if in_source.get('type') == 'connection': print(f" - Condition from: instruction {in_source.get('source_instruction_uid', '?')} (Pin: {in_source.get('source_pin', '?')})") else: print(f" - Condition: {in_source}") def process_add(instruction): """Procesa una instrucción 'Add'.""" print(f" [Add] UID: {instruction['instruction_uid']}") in1 = instruction['inputs'].get('in1', {}) in2 = instruction['inputs'].get('in2', {}) en = instruction['inputs'].get('en', {}) outputs = instruction['outputs'].get('out', []) print(f" - Input 1: {in1.get('scope', '?')} UID: {in1.get('uid', '?')}") print(f" - Input 2: {in2.get('scope', '?')} UID: {in2.get('uid', '?')}") if en.get('type') == 'powerrail': print(" - Enabled by: Power Rail (Direct)") # Si Add pudiera conectarse directo elif en.get('type') == 'connection': print(f" - Enabled by: instruction {en.get('source_instruction_uid', '?')} (Pin: {en.get('source_pin', '?')})") elif en: # Si 'en' no está presente o no es conexión/powerrail (poco común en Add) print(f" - Enabled by: {en}") else: print(" - Enabled by: Power Rail (Implícito, sin EN)") # Asumir si no hay pin 'en' for output in outputs: print(f" - Output to: {output.get('scope', '?')} UID: {output.get('uid', '?')}") def process_move(instruction): """Procesa una instrucción 'Move'.""" print(f" [Move] UID: {instruction['instruction_uid']}") in_val = instruction['inputs'].get('in', {}) en = instruction['inputs'].get('en', {}) outputs = instruction['outputs'].get('out1', []) # Asumiendo pin 'out1' para Move print(f" - Input Value: {in_val.get('scope', '?')} UID: {in_val.get('uid', '?')}") if en.get('type') == 'powerrail': print(" - Enabled by: Power Rail") elif en.get('type') == 'connection': print(f" - Enabled by: instruction {en.get('source_instruction_uid', '?')} (Pin: {en.get('source_pin', '?')})") elif en: print(f" - Enabled by: {en}") else: print(" - Enabled by: Power Rail (Implícito, sin EN)") for output in outputs: print(f" - Output to: {output.get('scope', '?')} UID: {output.get('uid', '?')}") def process_eq(instruction): """Procesa una instrucción 'Eq' (Equal).""" print(f" [Compare EQ] UID: {instruction['instruction_uid']}") in1 = instruction['inputs'].get('in1', {}) in2 = instruction['inputs'].get('in2', {}) pre = instruction['inputs'].get('pre', {}) # Condición previa (usualmente PowerRail o conexión) print(f" - Input 1: {in1.get('scope', '?')} UID: {in1.get('uid', '?')}") print(f" - Input 2: {in2.get('scope', '?')} UID: {in2.get('uid', '?')}") if pre.get('type') == 'powerrail': print(" - Pre-condition: Power Rail") elif pre.get('type') == 'connection': print(f" - Pre-condition: instruction {pre.get('source_instruction_uid', '?')} (Pin: {pre.get('source_pin', '?')})") else: print(f" - Pre-condition: {pre}") # La salida 'out' de Eq usualmente va a otra instrucción (Contact, Coil, Enable pin) # Lo veremos cuando procesemos la instrucción destino def process_mod(instruction): """Procesa una instrucción 'Mod' (Modulo).""" print(f" [Modulo] UID: {instruction['instruction_uid']}") in1 = instruction['inputs'].get('in1', {}) in2 = instruction['inputs'].get('in2', {}) en = instruction['inputs'].get('en', {}) outputs = instruction['outputs'].get('out', []) eno_outputs = instruction['outputs'].get('eno', []) # Mod también puede tener ENO print(f" - Input 1 (Dividend): {in1.get('scope', '?')} UID: {in1.get('uid', '?')}") print(f" - Input 2 (Divisor): {in2.get('scope', '?')} UID: {in2.get('uid', '?')}") if en.get('type') == 'powerrail': print(" - Enabled by: Power Rail") elif en.get('type') == 'connection': print(f" - Enabled by: instruction {en.get('source_instruction_uid', '?')} (Pin: {en.get('source_pin', '?')})") elif en: print(f" - Enabled by: {en}") else: print(" - Enabled by: Power Rail (Implícito, sin EN)") for output in outputs: print(f" - Output (Remainder) to: {output.get('scope', '?')} UID: {output.get('uid', '?')}") # ENO normalmente se conecta a pines 'en' o 'pre' de la siguiente instrucción def process_convert(instruction): """Procesa una instrucción 'Convert'.""" print(f" [Convert] UID: {instruction['instruction_uid']}") in_val = instruction['inputs'].get('in', {}) en = instruction['inputs'].get('en', {}) outputs = instruction['outputs'].get('out', []) # Podríamos extraer los tipos de datos de TemplateValue si estuvieran en el JSON # template_vals = instruction.get('template_values', {}) print(f" - Input Value: {in_val.get('scope', '?')} UID: {in_val.get('uid', '?')}") if en.get('type') == 'powerrail': print(" - Enabled by: Power Rail") elif en.get('type') == 'connection': print(f" - Enabled by: instruction {en.get('source_instruction_uid', '?')} (Pin: {en.get('source_pin', '?')})") elif en: print(f" - Enabled by: {en}") else: print(" - Enabled by: Power Rail (Implícito, sin EN)") for output in outputs: print(f" - Output to: {output.get('scope', '?')} UID: {output.get('uid', '?')}") # print(f" (Expected DestType: {template_vals.get('DestType', '?')})") def process_or(instruction): """Procesa una instrucción 'O' (OR).""" # Las instrucciones 'O' en LAD suelen representar la unión de ramas paralelas. # Este parser simple solo muestra las entradas directas. Reconstruir la lógica OR completa requeriría más análisis. print(f" [OR Logic] UID: {instruction['instruction_uid']}") in1 = instruction['inputs'].get('in1', {}) in2 = instruction['inputs'].get('in2', {}) # Podría haber in3, in4... si Cardinality > 2 if in1.get('type') == 'connection': print(f" - Input 1 from: instruction {in1.get('source_instruction_uid', '?')} (Pin: {in1.get('source_pin', '?')})") else: print(f" - Input 1: {in1}") if in2.get('type') == 'connection': print(f" - Input 2 from: instruction {in2.get('source_instruction_uid', '?')} (Pin: {in2.get('source_pin', '?')})") else: print(f" - Input 2: {in2}") # La salida 'out' de O usualmente va a otra instrucción (Contact, Coil, Enable pin) def process_pbox(instruction): """Procesa una instrucción 'PBox'.""" # PBox puede ser muchas cosas (Rising Edge, Falling Edge, Set, Reset, etc.) # Necesitaríamos más información o convenciones para saber qué hace exactamente. print(f" [PBox - Special?] UID: {instruction['instruction_uid']}") inputs = instruction.get('inputs', {}) outputs = instruction.get('outputs', {}) for pin, source in inputs.items(): if source.get('type') == 'connection': print(f" - Input Pin '{pin}' from: instruction {source.get('source_instruction_uid', '?')} (Pin: {source.get('source_pin', '?')})") elif source.get('type') == 'powerrail': print(f" - Input Pin '{pin}': Power Rail") else: print(f" - Input Pin '{pin}': {source.get('scope', '?')} UID: {source.get('uid', '?')}") # La salida de PBox la veremos en el destino def process_unknown(instruction): """Procesa una instrucción de tipo desconocido.""" print(f" [Unknown Type: {instruction.get('type', 'N/A')}] UID: {instruction['instruction_uid']}") print(f" - Inputs: {instruction.get('inputs')}") print(f" - Outputs: {instruction.get('outputs')}") # --- Mapeo de Tipos a Funciones --- instruction_handlers = { "Contact": process_contact, "Coil": process_coil, "Add": process_add, "Move": process_move, "Eq": process_eq, "Mod": process_mod, "Convert": process_convert, "O": process_or, # 'O' representa un OR lógico en FlgNet "PBox": process_pbox, # Tipo genérico, tratar como desconocido por ahora # Añade más tipos aquí si aparecen } # --- Función Principal de Procesamiento --- def process_logic_data(data): """Itera sobre el JSON cargado y procesa cada instrucción.""" print("=" * 40) print(f"Processing Block: {data.get('block_name')} ({data.get('block_number')})") print(f"Language: {data.get('language')}") print("-" * 40) # Opcional: Imprimir interfaz print("Interface:") for section, members in data.get('interface', {}).items(): if members: print(f" {section}:") for member in members: print(f" - {member['name']} ({member['datatype']})") print("-" * 40) # Procesar Redes print("Networks:") for network in data.get('networks', []): print(f"\nNetwork ID: {network.get('id')} - Title: '{network.get('title', '')}'") if 'error' in network: print(f" ERROR en esta red: {network['error']}") continue if not network.get('logic'): print(" (No logic instructions found in JSON for this network)") continue for instruction in network.get('logic', []): instruction_type = instruction.get('type') # Obtener el handler adecuado, o el default si no se encuentra handler = instruction_handlers.get(instruction_type, process_unknown) try: handler(instruction) except Exception as e: print(f" ERROR procesando instrucción UID {instruction.get('instruction_uid')} (Tipo: {instruction_type}): {e}") # Considerar imprimir más detalles del error o de la instrucción # import traceback # traceback.print_exc() # --- Ejecución --- if __name__ == "__main__": json_file = 'BlenderRun_ProdTime_simplified.json' # El archivo generado por el script anterior if not os.path.exists(json_file): print(f"Error: Archivo JSON no encontrado en {json_file}") print("Asegúrate de haber ejecutado el script de conversión XML a JSON primero.") else: try: with open(json_file, 'r', encoding='utf-8') as f: logic_data = json.load(f) process_logic_data(logic_data) except json.JSONDecodeError as e: print(f"Error: El archivo JSON ({json_file}) no es válido: {e}") except Exception as e: print(f"Ocurrió un error inesperado al cargar o procesar el JSON: {e}") import traceback traceback.print_exc()