# processors/process_coil.py import sympy from .processor_utils import get_sympy_representation, sympy_expr_to_scl, get_target_scl_name, format_variable_name from .symbol_manager import SymbolManager, extract_plc_variable_name SCL_SUFFIX = "_sympy_processed" def process_coil(instruction, network_id, sympy_map, symbol_manager, data): """Genera la asignación SCL para Coil, simplificando la entrada SymPy.""" instr_uid = instruction["instruction_uid"] instr_type_original = instruction.get("type", "Coil") if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False # Get input expression from SymPy map coil_input_info = instruction["inputs"].get("in") sympy_expr_in = get_sympy_representation(coil_input_info, network_id, sympy_map, symbol_manager) # Get target variable SCL name target_scl_name = get_target_scl_name(instruction, "operand", network_id, default_to_temp=False) # Coil must have explicit target # Check dependencies if sympy_expr_in is None: # print(f"DEBUG Coil {instr_uid}: Input dependency not ready.") return False if target_scl_name is None: print(f"Error: Coil {instr_uid} operando no es variable o falta info.") instruction["scl"] = f"// ERROR: Coil {instr_uid} operando no es variable." instruction["type"] = instr_type_original + "_error" return True # Processed with error # *** Perform Simplification *** try: #simplified_expr = sympy.simplify_logic(sympy_expr_in, force=False) #simplified_expr = sympy_expr_in simplified_expr = sympy.logic.boolalg.to_dnf(sympy_expr_in, simplify=True) except Exception as e: print(f"Error during SymPy simplification for Coil {instr_uid}: {e}") simplified_expr = sympy_expr_in # Fallback to original expression # *** Convert simplified expression back to SCL string *** condition_scl = sympy_expr_to_scl(simplified_expr, symbol_manager) # Generate the final SCL assignment scl_assignment = f"{target_scl_name} := {condition_scl};" scl_final = scl_assignment # --- Handle Edge Detector Memory Update (Logic similar to before) --- # Check if input comes from PBox/NBox and append memory update mem_update_scl_combined = None if isinstance(coil_input_info, dict) and coil_input_info.get("type") == "connection": source_uid = coil_input_info.get("source_instruction_uid") source_pin = coil_input_info.get("source_pin") source_instruction = None network_logic = next((net["logic"] for net in data["networks"] if net["id"] == network_id), []) for instr in network_logic: if instr.get("instruction_uid") == source_uid: source_instruction = instr break if source_instruction: # Check for the original type before suffix was added orig_source_type = source_instruction.get("type", "").replace(SCL_SUFFIX, '').replace('_error', '') if orig_source_type in ["PBox", "NBox"] and '_edge_mem_update_scl' in source_instruction: mem_update_scl_combined = source_instruction.get('_edge_mem_update_scl') if mem_update_scl_combined: scl_final = f"{scl_assignment}\n{mem_update_scl_combined}" # Clear the source SCL? source_instruction['scl'] = f"// Edge Logic handled by Coil {instr_uid}" # Update instruction instruction["scl"] = scl_final instruction["type"] = instr_type_original + SCL_SUFFIX # Coil typically doesn't output to scl_map return True # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para el procesador Coil.""" return {'type_name': 'coil', 'processor_func': process_coil, 'priority': 3}