Funcion basica de PBox y NBox

This commit is contained in:
Miguel 2025-04-19 01:27:00 +02:00
parent 4bf7619cc1
commit d6125f9433
10 changed files with 3094 additions and 142 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
// Block Name (Original): BlenderRun_ProdTime
// Block Number: 2040
// Original Language: LAD
FUNCTION_BLOCK "BlenderRun_ProdTime"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR_IN_OUT
END_VAR
VAR_TEMP
m1MinONS : Bool;
m1HourONS : Bool;
Buffer : Bool;
mRunMin : Bool;
mRunHr : Bool;
I_DIRunning_sec : DInt;
I_DIRunning_min : DInt;
MOD60 : DInt;
END_VAR
BEGIN
// Network 1: Seconds
// RLO: "Procedure_Variables"."Blender_Run"."Running"
// RLO: "Procedure_Variables"."Blender_Run"."Running" AND "CLK_1.0S"
IF "Procedure_Variables"."Blender_Run"."Running" AND "CLK_1.0S" THEN
"Blender_Variables_Pers"."gSLIM_Sec" := "Blender_Variables_Pers"."gSLIM_Sec" + 1;
END_IF;
// Network 2: Reset Hours
// RLO: "SLIM_Variables"."ResetHour"
IF "SLIM_Variables"."ResetHour" THEN
"Blender_Variables_Pers"."gSLIM_Sec" := 0;
END_IF;
// Network 3: Seconds Counter
// RLO: "gBlenderBlending"
// RLO: "gBlenderBlending" AND "CLK_1.0S"
IF "gBlenderBlending" AND "CLK_1.0S" THEN
"Blender_Variables_Pers"."gProdSec" := "Blender_Variables_Pers"."gProdSec" + 1;
END_IF;
// Network 4: Minute
"m1MinONS" := "Blender_Variables_Pers"."gProdSec" = 60;
// Network 5: Minute Counter
IF "m1MinONS" THEN
"Blender_Variables_Pers"."gProdSec" := 0;
"Blender_Variables_Pers"."gProdMin" := "Blender_Variables_Pers"."gProdMin" + 1;
END_IF;
// Logic included in grouped IF (by UID 27)
// Logic included in grouped IF (by UID 27)
// Network 6: Hour
"m1HourONS" := "Blender_Variables_Pers"."gProdMin" = 60;
// Network 7: Hour Counter
IF "m1HourONS" THEN
"Blender_Variables_Pers"."gProdMin" := 0;
"Blender_Variables_Pers"."gProdHour" := "Blender_Variables_Pers"."gProdHour" + 1;
"Blender_Variables_Pers"."gBlendingMaintHour" := "Blender_Variables_Pers"."gBlendingMaintHour" + 1;
END_IF;
// Logic included in grouped IF (by UID 30)
// Logic included in grouped IF (by UID 30)
// Logic included in grouped IF (by UID 30)
// Network 8: Counter reset
// RLO: "gBlenderCIPMode"
// RLO: "gBlenderRinseMode"
IF "gBlenderCIPMode" OR "gBlenderRinseMode" THEN
"Blender_Variables_Pers"."gProdSec" := 0;
"Blender_Variables_Pers"."gProdMin" := 0;
"Blender_Variables_Pers"."gProdHour" := 0;
END_IF;
// Logic included in grouped IF (by UID 31)
// Logic included in grouped IF (by UID 31)
// Logic included in grouped IF (by UID 31)
// Network 9: Running Seconds
// RLO: "Procedure_Variables"."Blender_Run"."Running"
// RLO: "Procedure_Variables"."Blender_Run"."Running" AND "CLK_1.0S"
IF "Procedure_Variables"."Blender_Run"."Running" AND "CLK_1.0S" THEN
"Blender_Variables_Pers"."gRunningSeconds" := "Blender_Variables_Pers"."gRunningSeconds" + 1;
END_IF;
// Network 10: Running Minutes
"I_DIRunning_sec" := "Blender_Variables_Pers"."gRunningSeconds";
"MOD60" := "I_DIRunning_sec" MOD DINT#60;
// RLO: "MOD60" = DINT#0 AND "Procedure_Variables"."Blender_Run"."Running"
// RLO: ("MOD60" = DINT#0 AND "Procedure_Variables"."Blender_Run"."Running") AND "CLK_1.0S"
IF ("MOD60" = DINT#0 AND "Procedure_Variables"."Blender_Run"."Running") AND "CLK_1.0S" THEN
"Blender_Variables_Pers"."gRunningMinutes" := "Blender_Variables_Pers"."gRunningMinutes" + 1;
END_IF;
// Network 11: Running Hours for Maintenance
// RLO: "mRunMin"
IF "mRunMin" THEN
"I_DIRunning_min" := "Blender_Variables_Pers"."gRunningMinutes";
END_IF;
IF "mRunMin" THEN
"MOD60" := "I_DIRunning_min" MOD DINT#60;
END_IF;
IF "MOD60" = DINT#0 THEN
"Blender_Variables_Pers"."gRunningMaintHour" := "Blender_Variables_Pers"."gRunningMaintHour" + 1;
END_IF;
// Network 12: Running Hours for Maintenance
"HMI_Variables_Status"."System"."BlendingMaintHour" := "Blender_Variables_Pers"."gRunningMaintHour";
END_FUNCTION_BLOCK

View File

@ -233,9 +233,7 @@
<Component Name="Clock_5Hz" /> <Component Name="Clock_5Hz" />
</Symbol> </Symbol>
</Access> </Access>
<Part Name="Contact" UId="24"> <Part Name="Contact" UId="24" />
<Negated Name="operand" />
</Part>
<Part Name="NBox" UId="25" /> <Part Name="NBox" UId="25" />
<Part Name="Coil" UId="26" /> <Part Name="Coil" UId="26" />
</Parts> </Parts>

View File

@ -43,17 +43,17 @@
"template_values": {}, "template_values": {},
"negated_pins": {}, "negated_pins": {},
"inputs": { "inputs": {
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
},
"in": { "in": {
"type": "connection", "type": "connection",
"source_instruction_type": "Contact", "source_instruction_type": "Contact",
"source_instruction_uid": "24", "source_instruction_uid": "24",
"source_pin": "out" "source_pin": "out"
},
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
} }
}, },
"outputs": {} "outputs": {}
@ -92,9 +92,7 @@
"uid": "24", "uid": "24",
"type": "Contact", "type": "Contact",
"template_values": {}, "template_values": {},
"negated_pins": { "negated_pins": {},
"operand": true
},
"inputs": { "inputs": {
"operand": { "operand": {
"uid": "21", "uid": "21",
@ -115,17 +113,17 @@
"template_values": {}, "template_values": {},
"negated_pins": {}, "negated_pins": {},
"inputs": { "inputs": {
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
},
"in": { "in": {
"type": "connection", "type": "connection",
"source_instruction_type": "Contact", "source_instruction_type": "Contact",
"source_instruction_uid": "24", "source_instruction_uid": "24",
"source_pin": "out" "source_pin": "out"
},
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
} }
}, },
"outputs": {} "outputs": {}

View File

@ -44,21 +44,22 @@
"template_values": {}, "template_values": {},
"negated_pins": {}, "negated_pins": {},
"inputs": { "inputs": {
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
},
"in": { "in": {
"type": "connection", "type": "connection",
"source_instruction_type": "Contact", "source_instruction_type": "Contact",
"source_instruction_uid": "24", "source_instruction_uid": "24",
"source_pin": "out" "source_pin": "out"
},
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
} }
}, },
"outputs": {}, "outputs": {},
"scl": "\"stat_M19001\" := \"Clock_10Hz\"; // P_TRIG: \"Clock_10Hz\" AND NOT \"stat_M19001\"" "_edge_mem_update_scl": "\"M19001\" := \"Clock_10Hz\";",
"scl": "// Logic moved to Coil 26"
}, },
{ {
"instruction_uid": "26", "instruction_uid": "26",
@ -81,7 +82,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "\"Clock_5Hz\" := \"Clock_10Hz\" AND NOT \"stat_M19001\";" "scl": "\"Clock_5Hz\" := \"Clock_10Hz\" AND NOT \"M19001\";\\n\"M19001\" := \"Clock_10Hz\"; // P_TRIG(\"Clock_10Hz\") (Mem update handled by consumer)"
} }
] ]
}, },
@ -95,9 +96,7 @@
"uid": "24", "uid": "24",
"type": "Contact_scl", "type": "Contact_scl",
"template_values": {}, "template_values": {},
"negated_pins": { "negated_pins": {},
"operand": true
},
"inputs": { "inputs": {
"operand": { "operand": {
"uid": "21", "uid": "21",
@ -110,7 +109,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// RLO: (NOT \"Clock_10Hz\")" "scl": "// RLO: \"Clock_10Hz\""
}, },
{ {
"instruction_uid": "25", "instruction_uid": "25",
@ -119,21 +118,22 @@
"template_values": {}, "template_values": {},
"negated_pins": {}, "negated_pins": {},
"inputs": { "inputs": {
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
},
"in": { "in": {
"type": "connection", "type": "connection",
"source_instruction_type": "Contact", "source_instruction_type": "Contact",
"source_instruction_uid": "24", "source_instruction_uid": "24",
"source_pin": "out" "source_pin": "out"
},
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
} }
}, },
"outputs": {}, "outputs": {},
"scl": "\"stat_M19001\" := (NOT \"Clock_10Hz\"); // N_TRIG: NOT (NOT \"Clock_10Hz\") AND \"stat_M19001\"" "_edge_mem_update_scl": "\"M19001\" := \"Clock_10Hz\";",
"scl": "// Logic moved to Coil 26"
}, },
{ {
"instruction_uid": "26", "instruction_uid": "26",
@ -156,7 +156,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "\"Clock_5Hz\" := NOT (NOT \"Clock_10Hz\") AND \"stat_M19001\";" "scl": "\"Clock_5Hz\" := NOT \"Clock_10Hz\" AND \"M19001\";\\n\"M19001\" := \"Clock_10Hz\"; // N_TRIG(\"Clock_10Hz\") (Mem update handled by consumer)"
} }
] ]
} }

View File

@ -15,10 +15,6 @@ END_VAR
VAR_IN_OUT VAR_IN_OUT
END_VAR END_VAR
VAR_STAT
"stat_M19001" : Bool; // Memory for edge detection
END_VAR
VAR_TEMP VAR_TEMP
END_VAR END_VAR
@ -27,13 +23,13 @@ BEGIN
// Network 1: Clock Bit // Network 1: Clock Bit
// RLO: "Clock_10Hz" // RLO: "Clock_10Hz"
"stat_M19001" := "Clock_10Hz"; // P_TRIG: "Clock_10Hz" AND NOT "stat_M19001" // Logic moved to Coil 26
"Clock_5Hz" := "Clock_10Hz" AND NOT "stat_M19001"; "Clock_5Hz" := "Clock_10Hz" AND NOT "M19001";\n"M19001" := "Clock_10Hz"; // P_TRIG("Clock_10Hz") (Mem update handled by consumer)
// Network 2: Clock Bit // Network 2: Clock Bit
// RLO: (NOT "Clock_10Hz") // RLO: "Clock_10Hz"
"stat_M19001" := (NOT "Clock_10Hz"); // N_TRIG: NOT (NOT "Clock_10Hz") AND "stat_M19001" // Logic moved to Coil 26
"Clock_5Hz" := NOT (NOT "Clock_10Hz") AND "stat_M19001"; "Clock_5Hz" := NOT "Clock_10Hz" AND "M19001";\n"M19001" := "Clock_10Hz"; // N_TRIG("Clock_10Hz") (Mem update handled by consumer)
END_FUNCTION_BLOCK END_FUNCTION_BLOCK

View File

@ -357,7 +357,7 @@ def convert_xml_to_json(xml_filepath, json_filepath):
# --- Punto de Entrada Principal --- # --- Punto de Entrada Principal ---
if __name__ == "__main__": if __name__ == "__main__":
xml_filename_base = "TestLAD" xml_filename_base = "BlenderRun_ProdTime"
xml_file = f"{xml_filename_base}.xml" xml_file = f"{xml_filename_base}.xml"
json_file = f"{xml_filename_base}_simplified.json" json_file = f"{xml_filename_base}_simplified.json"
convert_xml_to_json(xml_file, json_file) convert_xml_to_json(xml_file, json_file)

View File

@ -258,7 +258,6 @@ def process_contact(instruction, network_id, scl_map, access_map):
instruction["type"] = instr_type + SCL_SUFFIX instruction["type"] = instr_type + SCL_SUFFIX
return True return True
def process_eq(instruction, network_id, scl_map, access_map): def process_eq(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"] instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"] instr_type = instruction["type"]
@ -315,51 +314,126 @@ def process_eq(instruction, network_id, scl_map, access_map):
instruction["type"] = instr_type + SCL_SUFFIX instruction["type"] = instr_type + SCL_SUFFIX
return True return True
# --- process_edge_detector MODIFICADA ---
def process_edge_detector(instruction, network_id, scl_map, access_map):
"""Genera SCL para PBox (P_TRIG) o NBox (N_TRIG).
Guarda la expresión del pulso en scl_map['out'] y la actualización
de memoria en un campo temporal '_edge_mem_update_scl'.
El campo 'scl' principal se deja casi vacío.
"""
instr_uid = instruction["instruction_uid"]
instr_type_original = instruction["type"] # PBox o NBox
if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original:
return False
# 1. Obtener CLK y MemBit original
clk_input = instruction["inputs"].get("in")
mem_bit_input = instruction["inputs"].get("bit")
clk_scl = get_scl_representation(clk_input, network_id, scl_map, access_map)
mem_bit_scl_original = get_scl_representation(mem_bit_input, network_id, scl_map, access_map)
# 2. Verificar dependencias y tipo de MemBit
if clk_scl is None or mem_bit_scl_original is None: return False
if not (mem_bit_input and mem_bit_input.get("type") == "variable"):
instruction["scl"] = f"// ERROR: {instr_type_original} {instr_uid} 'bit' no es variable."
instruction["type"] = instr_type_original + "_error"
return True
# 3. Formatear CLK
clk_scl_formatted = clk_scl
if clk_scl not in ["TRUE", "FALSE"] and \
(' ' in clk_scl or 'AND' in clk_scl or 'OR' in clk_scl or ':=' in clk_scl) and \
not (clk_scl.startswith('(') and clk_scl.endswith(')')):
clk_scl_formatted = f"({clk_scl})"
# 4. Generar Lógica SCL del *pulso*
result_pulse_expression = "FALSE"
scl_comment = ""
if instr_type_original == "PBox": # P_TRIG
result_pulse_expression = f"{clk_scl_formatted} AND NOT {mem_bit_scl_original}"
scl_comment = f"// P_TRIG({clk_scl_formatted})"
elif instr_type_original == "NBox": # N_TRIG
result_pulse_expression = f"NOT {clk_scl_formatted} AND {mem_bit_scl_original}"
scl_comment = f"// N_TRIG({clk_scl_formatted})"
else: # Error
instruction["scl"] = f"// ERROR: Tipo de flanco inesperado {instr_type_original}"
instruction["type"] = instr_type_original + "_error"
return True
# 5. Generar la actualización del bit de memoria
scl_mem_update = f"{mem_bit_scl_original} := {clk_scl_formatted};"
# 6. Almacenar Resultados
map_key_out = (network_id, instr_uid, "out")
scl_map[map_key_out] = result_pulse_expression # Guardar EXPRESIÓN del pulso
instruction['_edge_mem_update_scl'] = scl_mem_update # Guardar UPDATE en campo temporal
instruction['scl'] = f"{scl_comment} (Mem update handled by consumer)" # Dejar SCL principal vacío/comentario
instruction["type"] = instr_type_original + SCL_SUFFIX
# 7. Propagar ENO
map_key_eno = (network_id, instr_uid, "eno")
scl_map[map_key_eno] = clk_scl
return True
# --- process_coil MODIFICADA ---
def process_coil(instruction, network_id, scl_map, access_map): def process_coil(instruction, network_id, scl_map, access_map):
"""Genera la asignación para Coil. Si la entrada viene de PBox/NBox,
añade la actualización de memoria del flanco DESPUÉS de la asignación."""
instr_uid = instruction["instruction_uid"] instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"] instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False return False
in_rlo_scl = get_scl_representation( coil_input_info = instruction["inputs"].get("in")
instruction["inputs"].get("in"), network_id, scl_map, access_map
)
operand_info = instruction["inputs"].get("operand") operand_info = instruction["inputs"].get("operand")
in_rlo_scl = get_scl_representation(coil_input_info, network_id, scl_map, access_map)
operand_scl = get_scl_representation(operand_info, network_id, scl_map, access_map) operand_scl = get_scl_representation(operand_info, network_id, scl_map, access_map)
if in_rlo_scl is None or operand_scl is None: if in_rlo_scl is None or operand_scl is None: return False
return False # Dependencias no listas
# Validar y formatear operando
if not (operand_info and operand_info.get("type") == "variable"): if not (operand_info and operand_info.get("type") == "variable"):
print(f"Error: Operando COIL {instr_uid} no es variable o falta información.") instruction["scl"] = f"// ERROR: Coil {instr_uid} operando no es variable o falta info"
instruction["scl"] = (
f"// ERROR: Coil {instr_uid} operando no es variable o falta info"
)
instruction["type"] = instr_type + "_error" instruction["type"] = instr_type + "_error"
return True # Marcar como procesado (con error)
operand_scl_formatted = format_variable_name(operand_scl)
# Simplificar RLO si es posible
if in_rlo_scl == "(TRUE)":
in_rlo_scl = "TRUE"
elif in_rlo_scl == "(FALSE)":
in_rlo_scl = "FALSE"
# Generar la asignación SCL
scl_final = f"{operand_scl_formatted} := {in_rlo_scl};"
instruction["scl"] = scl_final
instruction["type"] = instr_type + SCL_SUFFIX
# Las bobinas no suelen tener salida ENO explícita en este contexto,
# pero podríamos propagar el RLO de entrada si fuera necesario para alguna lógica posterior.
# map_key_eno = (network_id, instr_uid, "eno")
# scl_map[map_key_eno] = in_rlo_scl
return True return True
operand_scl_formatted = format_variable_name(operand_scl)
if in_rlo_scl == "(TRUE)": in_rlo_scl = "TRUE"
elif in_rlo_scl == "(FALSE)": in_rlo_scl = "FALSE"
# Generar la asignación SCL principal
scl_assignment = f"{operand_scl_formatted} := {in_rlo_scl};"
scl_final = scl_assignment # Inicializar SCL final
# --- Lógica para añadir actualización de memoria de flancos ---
mem_update_scl = 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")
# Buscar la instrucción fuente en la lógica de la red actual
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:
source_type = source_instruction.get("type","").replace('_scl','').replace('_error','')
# Si la fuente es PBox o NBox y tiene el campo temporal con la actualización
if source_type in ["PBox", "NBox"] and '_edge_mem_update_scl' in source_instruction:
mem_update_scl = source_instruction['_edge_mem_update_scl']
# Añadir la actualización DESPUÉS de la asignación de la bobina
scl_final = f"{scl_assignment}\\n{mem_update_scl} {source_instruction.get('scl', '')}" # Añadir también comentario original del PBox/NBox
# Marcar la instrucción PBox/NBox para que x3 no escriba su SCL (que ahora está vacío/comentario)
source_instruction['scl'] = f"// Logic moved to Coil {instr_uid}"
instruction["scl"] = scl_final
instruction["type"] = instr_type + SCL_SUFFIX
return True
def process_convert(instruction, network_id, scl_map, access_map): def process_convert(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"] instr_uid = instruction["instruction_uid"]
@ -424,7 +498,6 @@ def process_convert(instruction, network_id, scl_map, access_map):
scl_map[map_key_eno] = en_scl # ENO sigue a EN scl_map[map_key_eno] = en_scl # ENO sigue a EN
return True return True
def process_mod(instruction, network_id, scl_map, access_map): def process_mod(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"] instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"] instr_type = instruction["type"]
@ -483,7 +556,6 @@ def process_mod(instruction, network_id, scl_map, access_map):
scl_map[map_key_eno] = en_scl scl_map[map_key_eno] = en_scl
return True return True
def process_add(instruction, network_id, scl_map, access_map): def process_add(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"] instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"] instr_type = instruction["type"]
@ -542,7 +614,6 @@ def process_add(instruction, network_id, scl_map, access_map):
scl_map[map_key_eno] = en_scl scl_map[map_key_eno] = en_scl
return True return True
def process_move(instruction, network_id, scl_map, access_map): def process_move(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"] instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"] instr_type = instruction["type"]
@ -608,95 +679,90 @@ def process_move(instruction, network_id, scl_map, access_map):
return True return True
def process_edge_detector(instruction, network_id, scl_map, access_map): # --- FUNCIÓN UNIFICADA CORREGIDA para PBox y NBox ---
"""Genera SCL para PBox (P_TRIG) o NBox (N_TRIG).""" """Genera SCL para PBox (P_TRIG) o NBox (N_TRIG)."""
instr_uid = instruction["instruction_uid"] instr_uid = instruction["instruction_uid"]
instr_type_original = instruction["type"] # PBox o NBox instr_type_original = instruction["type"] # PBox o NBox
if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: # print(f"DEBUG Edge: Intentando procesar {instr_type_original} UID {instr_uid} en Red {network_id}") # Debug
return False
# Obtener CLK (señal de entrada) y MemBit (bit de memoria) if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original:
return False # Ya procesado o error
# 1. Obtener representaciones SCL de las entradas CLK y MemBit
clk_input = instruction["inputs"].get("in") clk_input = instruction["inputs"].get("in")
mem_bit_input = instruction["inputs"].get("bit") mem_bit_input = instruction["inputs"].get("bit")
clk_scl = get_scl_representation(clk_input, network_id, scl_map, access_map) clk_scl = get_scl_representation(clk_input, network_id, scl_map, access_map)
mem_bit_scl_original = get_scl_representation( mem_bit_scl_original = get_scl_representation(mem_bit_input, network_id, scl_map, access_map)
mem_bit_input, network_id, scl_map, access_map
)
if clk_scl is None or mem_bit_scl_original is None: # 2. Verificar si las dependencias están listas
# print(f"DEBUG Edge: Esperando dependencias para {instr_type_original} UID {instr_uid}") if clk_scl is None:
return False # Dependencias no listas # print(f"DEBUG Edge: CLK no resuelto para {instr_type_original} UID {instr_uid}. Esperando.")
return False # Dependencia CLK no lista
if mem_bit_scl_original is None:
# Esto es menos probable, pero por seguridad
print(f"Error: No se pudo resolver MemBit para {instr_type_original} UID {instr_uid}.")
instruction["scl"] = f"// ERROR: {instr_type_original} {instr_uid} MemBit no resuelto."
instruction["type"] = instr_type_original + "_error"
return True # Marcar como error
# Validar que el bit de memoria sea una variable # 3. Validar que el bit de memoria sea una variable
if not (mem_bit_input and mem_bit_input.get("type") == "variable"): if not (mem_bit_input and mem_bit_input.get("type") == "variable"):
print( print(f"Error: {instr_type_original} {instr_uid} 'bit' no es variable o falta información.")
f"Error: {instr_type_original} {instr_uid} 'bit' no es variable o falta información." instruction["scl"] = f"// ERROR: {instr_type_original} {instr_uid} 'bit' no es variable."
)
instruction["scl"] = (
f"// ERROR: {instr_type_original} {instr_uid} 'bit' no es variable."
)
instruction["type"] = instr_type_original + "_error" instruction["type"] = instr_type_original + "_error"
return True # Procesado con error return True # Procesado con error
# --- Renombrar bit de memoria para VAR_STAT --- # 4. Renombrar bit de memoria para VAR_STAT y formatear CLK
# Quitar comillas existentes, añadir prefijo "stat_" y volver a añadir comillas
mem_bit_name_clean = mem_bit_scl_original.strip('"') mem_bit_name_clean = mem_bit_scl_original.strip('"')
stat_mem_bit_scl = ( stat_mem_bit_scl = f'"stat_{mem_bit_name_clean}"' if not mem_bit_name_clean.startswith("stat_") else mem_bit_scl_original
f'"stat_{mem_bit_name_clean}"' # Nombre SCL para la variable estática
)
# Asegurar paréntesis alrededor de CLK si es complejo
# Formatear CLK
clk_scl_formatted = clk_scl clk_scl_formatted = clk_scl
# Añadir paréntesis si es necesario (expresión compleja o asignación previa) # Añadir paréntesis si es necesario (expresión compleja) - No a TRUE/FALSE
# No añadir paréntesis a TRUE/FALSE literales if clk_scl not in ["TRUE", "FALSE"] and \
if ( (' ' in clk_scl or 'AND' in clk_scl or 'OR' in clk_scl or ':=' in clk_scl) and \
clk_scl not in ["TRUE", "FALSE"] not (clk_scl.startswith('(') and clk_scl.endswith(')')):
and (" " in clk_scl or "AND" in clk_scl or "OR" in clk_scl or ":=" in clk_scl)
and not (clk_scl.startswith("(") and clk_scl.endswith(")"))
):
clk_scl_formatted = f"({clk_scl})" clk_scl_formatted = f"({clk_scl})"
# --- Generar Lógica SCL --- # 5. Generar Lógica SCL específica para PBox o NBox
result_scl = "FALSE" # SCL para la salida del flanco (pin 'out') result_pulse_scl = "FALSE" # SCL para la salida del flanco (pin 'out')
scl_comment = "" # Comentario informativo scl_comment = ""
if instr_type_original == "PBox": # Flanco Positivo (P_TRIG) if instr_type_original == "PBox": # Flanco Positivo (P_TRIG)
result_scl = f"{clk_scl_formatted} AND NOT {stat_mem_bit_scl}" # Pulso = CLK actual Y NO Memoria anterior
scl_comment = f"// P_TRIG: {result_scl}" result_pulse_scl = f"{clk_scl_formatted} AND NOT {stat_mem_bit_scl}"
scl_comment = f"// P_TRIG({clk_scl_formatted})"
elif instr_type_original == "NBox": # Flanco Negativo (N_TRIG) elif instr_type_original == "NBox": # Flanco Negativo (N_TRIG)
result_scl = f"NOT {clk_scl_formatted} AND {stat_mem_bit_scl}" # Pulso = NO CLK actual Y Memoria anterior
scl_comment = f"// N_TRIG: {result_scl}" result_pulse_scl = f"NOT {clk_scl_formatted} AND {stat_mem_bit_scl}"
scl_comment = f"// N_TRIG({clk_scl_formatted})"
else: else:
# No debería ocurrir si el mapeo de procesadores es correcto print(f"Error interno: process_edge_detector llamado para tipo inesperado {instr_type_original}")
print( instruction["scl"] = f"// ERROR: Tipo de flanco inesperado {instr_type_original}"
f"Error interno: process_edge_detector llamado para tipo inesperado {instr_type_original}"
)
instruction["scl"] = (
f"// ERROR: Tipo de flanco inesperado {instr_type_original}"
)
instruction["type"] = instr_type_original + "_error" instruction["type"] = instr_type_original + "_error"
return True return True
# La actualización del bit de memoria es igual para P_TRIG y N_TRIG estándar # 6. Generar la actualización del bit de memoria (siempre se actualiza con el estado actual de CLK)
scl_mem_update = f"{stat_mem_bit_scl} := {clk_scl_formatted};" scl_mem_update = f"{stat_mem_bit_scl} := {clk_scl_formatted};"
# --- Almacenar Resultados --- # 7. Almacenar Resultados
# El pulso resultante va al mapa SCL para que lo usen las instrucciones siguientes # - El *pulso* resultante se almacena en el mapa para la salida 'out'.
# - La *actualización de memoria* se almacena en el campo 'scl' de la instrucción.
map_key_out = (network_id, instr_uid, "out") map_key_out = (network_id, instr_uid, "out")
scl_map[map_key_out] = result_scl scl_map[map_key_out] = result_pulse_scl
# print(f"DEBUG Edge: {instr_type_original} UID {instr_uid} -> map['out'] = {result_pulse_scl}") # Debug
# La actualización de memoria es la acción principal de esta instrucción en SCL instruction["scl"] = f"{scl_mem_update} {scl_comment}" # Incluye la acción principal y un comentario
instruction["scl"] = f"{scl_mem_update} {scl_comment}"
instruction["type"] = instr_type_original + SCL_SUFFIX instruction["type"] = instr_type_original + SCL_SUFFIX
# print(f"DEBUG Edge: {instr_type_original} UID {instr_uid} -> instruction['scl'] = {instruction['scl']}") # Debug
# El pin ENO normalmente sigue al CLK en los bloques de flanco estándar # 8. Propagar ENO (generalmente sigue al CLK)
map_key_eno = (network_id, instr_uid, "eno") map_key_eno = (network_id, instr_uid, "eno")
scl_map[map_key_eno] = clk_scl # Usar clk_scl original sin formateo extra scl_map[map_key_eno] = clk_scl # Usar el clk_scl original sin formato extra
return True
# print(f"DEBUG Edge: {instr_type_original} UID {instr_uid} procesado exitosamente.") # Debug
return True # Indicar que se procesó
def process_o(instruction, network_id, scl_map, access_map): def process_o(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"] instr_uid = instruction["instruction_uid"]
@ -760,7 +826,6 @@ def process_o(instruction, network_id, scl_map, access_map):
# La instrucción 'O' no tiene ENO propio, propaga el resultado por 'out' # La instrucción 'O' no tiene ENO propio, propaga el resultado por 'out'
return True return True
def process_call(instruction, network_id, scl_map, access_map): def process_call(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"] instr_uid = instruction["instruction_uid"]
instr_type = instruction.get("type", "") # Usar get con default instr_type = instruction.get("type", "") # Usar get con default
@ -878,7 +943,6 @@ def process_call(instruction, network_id, scl_map, access_map):
return True return True
# --- NUEVO: Procesador de Agrupación (Refinado) --- # --- NUEVO: Procesador de Agrupación (Refinado) ---
def process_group_ifs(instruction, network_id, scl_map, access_map): def process_group_ifs(instruction, network_id, scl_map, access_map):
""" """
@ -1308,7 +1372,7 @@ def process_json_to_scl(json_filepath):
# --- Ejecución --- # --- Ejecución ---
if __name__ == "__main__": if __name__ == "__main__":
# Asegúrate de que el nombre base del archivo XML sea correcto # Asegúrate de que el nombre base del archivo XML sea correcto
xml_filename_base = "TestLAD" # Cambia esto si tu XML se llama diferente xml_filename_base = "BlenderRun_ProdTime" # Cambia esto si tu XML se llama diferente
input_json_file = f"{xml_filename_base}_simplified.json" input_json_file = f"{xml_filename_base}_simplified.json"
if not os.path.exists(input_json_file): if not os.path.exists(input_json_file):

View File

@ -197,7 +197,7 @@ def generate_scl(processed_json_filepath, output_scl_filepath):
# --- Ejecución --- # --- Ejecución ---
if __name__ == "__main__": if __name__ == "__main__":
xml_file = "TestLAD.xml" # CAMBIAR AL NUEVO ARCHIVO XML xml_file = "BlenderRun_ProdTime.xml" # CAMBIAR AL NUEVO ARCHIVO XML
input_json_file = xml_file.replace( input_json_file = xml_file.replace(
".xml", "_simplified_processed.json" ".xml", "_simplified_processed.json"
) # Nombre de salida dinámico ) # Nombre de salida dinámico