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" />
</Symbol>
</Access>
<Part Name="Contact" UId="24">
<Negated Name="operand" />
</Part>
<Part Name="Contact" UId="24" />
<Part Name="NBox" UId="25" />
<Part Name="Coil" UId="26" />
</Parts>

View File

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

View File

@ -44,21 +44,22 @@
"template_values": {},
"negated_pins": {},
"inputs": {
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
},
"in": {
"type": "connection",
"source_instruction_type": "Contact",
"source_instruction_uid": "24",
"source_pin": "out"
},
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
}
},
"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",
@ -81,7 +82,7 @@
}
},
"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",
"type": "Contact_scl",
"template_values": {},
"negated_pins": {
"operand": true
},
"negated_pins": {},
"inputs": {
"operand": {
"uid": "21",
@ -110,7 +109,7 @@
}
},
"outputs": {},
"scl": "// RLO: (NOT \"Clock_10Hz\")"
"scl": "// RLO: \"Clock_10Hz\""
},
{
"instruction_uid": "25",
@ -119,21 +118,22 @@
"template_values": {},
"negated_pins": {},
"inputs": {
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
},
"in": {
"type": "connection",
"source_instruction_type": "Contact",
"source_instruction_uid": "24",
"source_pin": "out"
},
"bit": {
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"M19001\""
}
},
"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",
@ -156,7 +156,7 @@
}
},
"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
END_VAR
VAR_STAT
"stat_M19001" : Bool; // Memory for edge detection
END_VAR
VAR_TEMP
END_VAR
@ -27,13 +23,13 @@ BEGIN
// Network 1: Clock Bit
// RLO: "Clock_10Hz"
"stat_M19001" := "Clock_10Hz"; // P_TRIG: "Clock_10Hz" AND NOT "stat_M19001"
"Clock_5Hz" := "Clock_10Hz" AND NOT "stat_M19001";
// Logic moved to Coil 26
"Clock_5Hz" := "Clock_10Hz" AND NOT "M19001";\n"M19001" := "Clock_10Hz"; // P_TRIG("Clock_10Hz") (Mem update handled by consumer)
// Network 2: Clock Bit
// RLO: (NOT "Clock_10Hz")
"stat_M19001" := (NOT "Clock_10Hz"); // N_TRIG: NOT (NOT "Clock_10Hz") AND "stat_M19001"
"Clock_5Hz" := NOT (NOT "Clock_10Hz") AND "stat_M19001";
// RLO: "Clock_10Hz"
// Logic moved to Coil 26
"Clock_5Hz" := NOT "Clock_10Hz" AND "M19001";\n"M19001" := "Clock_10Hz"; // N_TRIG("Clock_10Hz") (Mem update handled by consumer)
END_FUNCTION_BLOCK

View File

@ -357,7 +357,7 @@ def convert_xml_to_json(xml_filepath, json_filepath):
# --- Punto de Entrada Principal ---
if __name__ == "__main__":
xml_filename_base = "TestLAD"
xml_filename_base = "BlenderRun_ProdTime"
xml_file = f"{xml_filename_base}.xml"
json_file = f"{xml_filename_base}_simplified.json"
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
return True
def process_eq(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
@ -315,52 +314,127 @@ def process_eq(instruction, network_id, scl_map, access_map):
instruction["type"] = instr_type + SCL_SUFFIX
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):
"""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_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False
in_rlo_scl = get_scl_representation(
instruction["inputs"].get("in"), network_id, scl_map, access_map
)
coil_input_info = instruction["inputs"].get("in")
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)
if in_rlo_scl is None or operand_scl is None:
return False # Dependencias no listas
if in_rlo_scl is None or operand_scl is None: return False
# Validar y formatear operando
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"
return True # Marcar como procesado (con error)
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"
# 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 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}"
# 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
def process_convert(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
@ -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
return True
def process_mod(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
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
return True
def process_add(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
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
return True
def process_move(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
@ -608,95 +679,90 @@ def process_move(instruction, network_id, scl_map, access_map):
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)."""
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
instr_type_original = instruction["type"] # PBox o NBox
# print(f"DEBUG Edge: Intentando procesar {instr_type_original} UID {instr_uid} en Red {network_id}") # Debug
# 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")
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
)
mem_bit_scl_original = get_scl_representation(mem_bit_input, network_id, scl_map, access_map)
if clk_scl is None or mem_bit_scl_original is None:
# print(f"DEBUG Edge: Esperando dependencias para {instr_type_original} UID {instr_uid}")
return False # Dependencias no listas
# Validar que el bit de memoria sea una variable
if not (mem_bit_input and mem_bit_input.get("type") == "variable"):
print(
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."
)
# 2. Verificar si las dependencias están listas
if clk_scl is None:
# 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 # Procesado con error
return True # Marcar como error
# --- Renombrar bit de memoria para VAR_STAT ---
# Quitar comillas existentes, añadir prefijo "stat_" y volver a añadir comillas
# 3. Validar que el bit de memoria sea una variable
if not (mem_bit_input and mem_bit_input.get("type") == "variable"):
print(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["type"] = instr_type_original + "_error"
return True # Procesado con error
# 4. Renombrar bit de memoria para VAR_STAT y formatear CLK
mem_bit_name_clean = mem_bit_scl_original.strip('"')
stat_mem_bit_scl = (
f'"stat_{mem_bit_name_clean}"' # Nombre SCL para la variable estática
)
stat_mem_bit_scl = f'"stat_{mem_bit_name_clean}"' if not mem_bit_name_clean.startswith("stat_") else mem_bit_scl_original
# Asegurar paréntesis alrededor de CLK si es complejo
# Formatear CLK
clk_scl_formatted = clk_scl
# Añadir paréntesis si es necesario (expresión compleja o asignación previa)
# No añadir paréntesis a TRUE/FALSE literales
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(")"))
):
# Añadir paréntesis si es necesario (expresión compleja) - No a TRUE/FALSE
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})"
# --- Generar Lógica SCL ---
result_scl = "FALSE" # SCL para la salida del flanco (pin 'out')
scl_comment = "" # Comentario informativo
# 5. Generar Lógica SCL específica para PBox o NBox
result_pulse_scl = "FALSE" # SCL para la salida del flanco (pin 'out')
scl_comment = ""
if instr_type_original == "PBox": # Flanco Positivo (P_TRIG)
result_scl = f"{clk_scl_formatted} AND NOT {stat_mem_bit_scl}"
scl_comment = f"// P_TRIG: {result_scl}"
elif instr_type_original == "NBox": # Flanco Negativo (N_TRIG)
result_scl = f"NOT {clk_scl_formatted} AND {stat_mem_bit_scl}"
scl_comment = f"// N_TRIG: {result_scl}"
if instr_type_original == "PBox": # Flanco Positivo (P_TRIG)
# Pulso = CLK actual Y NO Memoria anterior
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)
# Pulso = NO CLK actual Y Memoria anterior
result_pulse_scl = f"NOT {clk_scl_formatted} AND {stat_mem_bit_scl}"
scl_comment = f"// N_TRIG({clk_scl_formatted})"
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}"
)
instruction["scl"] = (
f"// ERROR: Tipo de flanco inesperado {instr_type_original}"
)
print(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"
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};"
# --- Almacenar Resultados ---
# El pulso resultante va al mapa SCL para que lo usen las instrucciones siguientes
# 7. Almacenar Resultados
# - 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")
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}"
instruction["scl"] = f"{scl_mem_update} {scl_comment}" # Incluye la acción principal y un comentario
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")
scl_map[map_key_eno] = clk_scl # Usar clk_scl original sin formateo extra
return True
scl_map[map_key_eno] = clk_scl # Usar el clk_scl original sin formato extra
# 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):
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'
return True
def process_call(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
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
# --- NUEVO: Procesador de Agrupación (Refinado) ---
def process_group_ifs(instruction, network_id, scl_map, access_map):
"""
@ -1308,7 +1372,7 @@ def process_json_to_scl(json_filepath):
# --- Ejecución ---
if __name__ == "__main__":
# 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"
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 ---
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(
".xml", "_simplified_processed.json"
) # Nombre de salida dinámico