Version funcionando

This commit is contained in:
Miguel 2025-04-18 17:21:26 +02:00
parent c62ce45987
commit a35f891eb7
4 changed files with 826 additions and 389 deletions

View File

@ -0,0 +1,477 @@
<?xml version="1.0" encoding="utf-8"?>
<Document>
<Engineering version="V18" />
<SW.Blocks.FC ID="0">
<AttributeList>
<AutoNumber>false</AutoNumber>
<HeaderFamily>TASK2</HeaderFamily>
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
<Section Name="Input" />
<Section Name="Output" />
<Section Name="InOut" />
<Section Name="Temp" />
<Section Name="Constant" />
<Section Name="Return">
<Member Name="Ret_Val" Datatype="Void" />
</Section>
</Sections></Interface>
<MemoryLayout>Standard</MemoryLayout>
<Name>BlenderCtrl_ProdModeInit</Name>
<Namespace />
<Number>2012</Number>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
<SetENOAutomatically>false</SetENOAutomatically>
</AttributeList>
<ObjectList>
<MultilingualText ID="1" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="4" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="5" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="6" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="7" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="8" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<SW.Blocks.CompileUnit ID="9" CompositionName="CompileUnits">
<AttributeList>
<NetworkSource><FlgNet xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4">
<Parts>
<Call UId="21">
<CallInfo Name="BlenderPID_PIDResInteg" BlockType="FC" />
</Call>
</Parts>
<Wires>
<Wire UId="22">
<Powerrail />
<NameCon UId="21" Name="en" />
</Wire>
</Wires>
</FlgNet></NetworkSource>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="A" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="B" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="C" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="D" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="E" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="F" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="10" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="11" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="12" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="13" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text>PID Reset Integral</Text>
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="14" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="15" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="16" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="17" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="18" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="19" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>
<SW.Blocks.CompileUnit ID="1A" CompositionName="CompileUnits">
<AttributeList>
<NetworkSource><FlgNet xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4">
<Parts>
<Call UId="21">
<CallInfo Name="BlenderCtrl_InitErrors" BlockType="FC" />
</Call>
</Parts>
<Wires>
<Wire UId="22">
<Powerrail />
<NameCon UId="21" Name="en" />
</Wire>
</Wires>
</FlgNet></NetworkSource>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="1B" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="1C" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1D" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1E" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1F" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="20" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="21" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="22" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="23" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="24" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text>Ctrl Init Errors</Text>
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="25" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="26" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="27" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="28" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="29" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="2A" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>
<SW.Blocks.CompileUnit ID="2B" CompositionName="CompileUnits">
<AttributeList>
<NetworkSource><FlgNet xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4">
<Parts>
<Access Scope="LiteralConstant" UId="21">
<Constant>
<ConstantType>Real</ConstantType>
<ConstantValue>0.0</ConstantValue>
</Constant>
</Access>
<Access Scope="GlobalVariable" UId="22">
<Symbol>
<Component Name="HMI_Variables_Status" />
<Component Name="Analog_Values" />
<Component Name="TP301RunOutCount" />
</Symbol>
</Access>
<Part Name="Move" UId="23" DisabledENO="false">
<TemplateValue Name="Card" Type="Cardinality">1</TemplateValue>
</Part>
</Parts>
<Wires>
<Wire UId="24">
<IdentCon UId="21" />
<NameCon UId="23" Name="in" />
</Wire>
<Wire UId="25">
<NameCon UId="23" Name="out1" />
<IdentCon UId="22" />
</Wire>
<Wire UId="26">
<Powerrail />
<NameCon UId="23" Name="en" />
</Wire>
</Wires>
</FlgNet></NetworkSource>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="2C" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2D" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="2E" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="2F" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="30" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="31" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="32" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="33" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="34" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="35" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text>RunOut Counter</Text>
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="36" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="37" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="38" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="39" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3A" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3B" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>
<MultilingualText ID="3C" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="3D" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text>Prode Mode Init</Text>
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3E" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3F" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="40" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="41" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="42" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="43" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.FC>
</Document>

View File

@ -30,49 +30,74 @@ 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
// Cond: "Blender_Variables_Pers"."gProdSec" = 60
"m1MinONS" := "Blender_Variables_Pers"."gProdSec" = 60;
// Network 5: Minute Counter
"Blender_Variables_Pers"."gProdSec" := 0;
"Blender_Variables_Pers"."gProdMin" := "Blender_Variables_Pers"."gProdMin" + 1;
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
// Cond: "Blender_Variables_Pers"."gProdMin" = 60
"m1HourONS" := "Blender_Variables_Pers"."gProdMin" = 60;
// Network 7: Hour Counter
"Blender_Variables_Pers"."gProdMin" := 0;
"Blender_Variables_Pers"."gProdHour" := "Blender_Variables_Pers"."gProdHour" + 1;
"Blender_Variables_Pers"."gBlendingMaintHour" := "Blender_Variables_Pers"."gBlendingMaintHour" + 1;
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
"Blender_Variables_Pers"."gProdSec" := 0;
"Blender_Variables_Pers"."gProdMin" := 0;
"Blender_Variables_Pers"."gProdHour" := 0;
// 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;
@ -81,20 +106,25 @@ BEGIN
"I_DIRunning_sec" := "Blender_Variables_Pers"."gRunningSeconds";
"MOD60" := "I_DIRunning_sec" MOD DINT#60;
// Cond: "MOD60" = DINT#0
// 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;
// Edge detection PBox 41 -> P_TRIG_FUNC(CLK := (("MOD60" = DINT#0 AND "Procedure_Variables"."Blender_Run"."Running") AND "CLK_1.0S"), M := "M19012") (CLK inferred)
// Edge PBox 41 -> P_TRIG_FUNC(CLK := (("MOD60" = DINT#0 AND "Procedure_Variables"."Blender_Run"."Running") AND "CLK_1.0S"), M := "M19012")
"mRunMin" := P_TRIG_FUNC(CLK := (("MOD60" = DINT#0 AND "Procedure_Variables"."Blender_Run"."Running") AND "CLK_1.0S"), M := "M19012");
// 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;
// Cond: "MOD60" = DINT#0
IF "MOD60" = DINT#0 THEN
"Blender_Variables_Pers"."gRunningMaintHour" := "Blender_Variables_Pers"."gRunningMaintHour" + 1;
END_IF;

View File

@ -66,7 +66,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 26: \"Procedure_Variables\".\"Blender_Run\".\"Running\""
"scl": "// RLO: \"Procedure_Variables\".\"Blender_Run\".\"Running\""
},
{
"instruction_uid": "27",
@ -86,7 +86,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 27: \"Procedure_Variables\".\"Blender_Run\".\"Running\" AND \"CLK_1.0S\""
"scl": "// RLO: \"Procedure_Variables\".\"Blender_Run\".\"Running\" AND \"CLK_1.0S\""
},
{
"instruction_uid": "28",
@ -146,7 +146,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 24: \"SLIM_Variables\".\"ResetHour\""
"scl": "// RLO: \"SLIM_Variables\".\"ResetHour\""
},
{
"instruction_uid": "25",
@ -200,7 +200,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 26: \"gBlenderBlending\""
"scl": "// RLO: \"gBlenderBlending\""
},
{
"instruction_uid": "27",
@ -220,7 +220,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 27: \"gBlenderBlending\" AND \"CLK_1.0S\""
"scl": "// RLO: \"gBlenderBlending\" AND \"CLK_1.0S\""
},
{
"instruction_uid": "28",
@ -287,7 +287,7 @@
}
},
"outputs": {},
"scl": "// Comparison Eq 24: \"Blender_Variables_Pers\".\"gProdSec\" = 60"
"scl": "// Cond: \"Blender_Variables_Pers\".\"gProdSec\" = 60"
},
{
"instruction_uid": "25",
@ -331,7 +331,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 27: \"m1MinONS\""
"scl": "IF \"m1MinONS\" THEN\n \"Blender_Variables_Pers\".\"gProdSec\" := 0;\n \"Blender_Variables_Pers\".\"gProdMin\" := \"Blender_Variables_Pers\".\"gProdMin\" + 1;\nEND_IF;"
},
{
"instruction_uid": "28",
@ -361,8 +361,8 @@
}
]
},
"grouped": true,
"scl": "\"Blender_Variables_Pers\".\"gProdSec\" := 0;"
"scl": "// Logic included in grouped IF (by UID 27)",
"grouped": true
},
{
"instruction_uid": "29",
@ -398,8 +398,8 @@
}
]
},
"grouped": true,
"scl": "\"Blender_Variables_Pers\".\"gProdMin\" := \"Blender_Variables_Pers\".\"gProdMin\" + 1;"
"scl": "// Logic included in grouped IF (by UID 27)",
"grouped": true
}
]
},
@ -430,7 +430,7 @@
}
},
"outputs": {},
"scl": "// Comparison Eq 24: \"Blender_Variables_Pers\".\"gProdMin\" = 60"
"scl": "// Cond: \"Blender_Variables_Pers\".\"gProdMin\" = 60"
},
{
"instruction_uid": "25",
@ -474,7 +474,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 30: \"m1HourONS\""
"scl": "IF \"m1HourONS\" THEN\n \"Blender_Variables_Pers\".\"gProdMin\" := 0;\n \"Blender_Variables_Pers\".\"gProdHour\" := \"Blender_Variables_Pers\".\"gProdHour\" + 1;\n \"Blender_Variables_Pers\".\"gBlendingMaintHour\" := \"Blender_Variables_Pers\".\"gBlendingMaintHour\" + 1;\nEND_IF;"
},
{
"instruction_uid": "31",
@ -504,8 +504,8 @@
}
]
},
"grouped": true,
"scl": "\"Blender_Variables_Pers\".\"gProdMin\" := 0;"
"scl": "// Logic included in grouped IF (by UID 30)",
"grouped": true
},
{
"instruction_uid": "32",
@ -541,8 +541,8 @@
}
]
},
"grouped": true,
"scl": "\"Blender_Variables_Pers\".\"gProdHour\" := \"Blender_Variables_Pers\".\"gProdHour\" + 1;"
"scl": "// Logic included in grouped IF (by UID 30)",
"grouped": true
},
{
"instruction_uid": "33",
@ -578,8 +578,8 @@
}
]
},
"grouped": true,
"scl": "\"Blender_Variables_Pers\".\"gBlendingMaintHour\" := \"Blender_Variables_Pers\".\"gBlendingMaintHour\" + 1;"
"scl": "// Logic included in grouped IF (by UID 30)",
"grouped": true
}
]
},
@ -603,7 +603,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 29: \"gBlenderCIPMode\""
"scl": "// RLO: \"gBlenderCIPMode\""
},
{
"instruction_uid": "30",
@ -617,7 +617,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 30: \"gBlenderRinseMode\""
"scl": "// RLO: \"gBlenderRinseMode\""
},
{
"instruction_uid": "31",
@ -637,7 +637,7 @@
}
},
"outputs": {},
"scl": "// Logic O 31: \"gBlenderCIPMode\" OR \"gBlenderRinseMode\""
"scl": "IF \"gBlenderCIPMode\" OR \"gBlenderRinseMode\" THEN\n \"Blender_Variables_Pers\".\"gProdSec\" := 0;\n \"Blender_Variables_Pers\".\"gProdMin\" := 0;\n \"Blender_Variables_Pers\".\"gProdHour\" := 0;\nEND_IF;"
},
{
"instruction_uid": "32",
@ -667,8 +667,8 @@
}
]
},
"grouped": true,
"scl": "\"Blender_Variables_Pers\".\"gProdSec\" := 0;"
"scl": "// Logic included in grouped IF (by UID 31)",
"grouped": true
},
{
"instruction_uid": "33",
@ -698,8 +698,8 @@
}
]
},
"grouped": true,
"scl": "\"Blender_Variables_Pers\".\"gProdMin\" := 0;"
"scl": "// Logic included in grouped IF (by UID 31)",
"grouped": true
},
{
"instruction_uid": "34",
@ -729,8 +729,8 @@
}
]
},
"grouped": true,
"scl": "\"Blender_Variables_Pers\".\"gProdHour\" := 0;"
"scl": "// Logic included in grouped IF (by UID 31)",
"grouped": true
}
]
},
@ -754,7 +754,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 26: \"Procedure_Variables\".\"Blender_Run\".\"Running\""
"scl": "// RLO: \"Procedure_Variables\".\"Blender_Run\".\"Running\""
},
{
"instruction_uid": "27",
@ -774,7 +774,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 27: \"Procedure_Variables\".\"Blender_Run\".\"Running\" AND \"CLK_1.0S\""
"scl": "// RLO: \"Procedure_Variables\".\"Blender_Run\".\"Running\" AND \"CLK_1.0S\""
},
{
"instruction_uid": "28",
@ -914,7 +914,7 @@
}
},
"outputs": {},
"scl": "// Comparison Eq 37: \"MOD60\" = DINT#0"
"scl": "// Cond: \"MOD60\" = DINT#0"
},
{
"instruction_uid": "38",
@ -934,7 +934,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 38: \"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\""
"scl": "// RLO: \"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\""
},
{
"instruction_uid": "39",
@ -954,7 +954,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 39: (\"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\") AND \"CLK_1.0S\""
"scl": "// RLO: (\"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\") AND \"CLK_1.0S\""
},
{
"instruction_uid": "40",
@ -1004,7 +1004,7 @@
}
},
"outputs": {},
"scl": "// Edge detection PBox 41 -> P_TRIG_FUNC(CLK := ((\"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\") AND \"CLK_1.0S\"), M := \"M19012\") (CLK inferred)"
"scl": "// Edge PBox 41 -> P_TRIG_FUNC(CLK := ((\"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\") AND \"CLK_1.0S\"), M := \"M19012\")"
},
{
"instruction_uid": "42",
@ -1048,7 +1048,7 @@
}
},
"outputs": {},
"scl": "// RLO updated by Contact 32: \"mRunMin\""
"scl": "// RLO: \"mRunMin\""
},
{
"instruction_uid": "33",
@ -1148,7 +1148,7 @@
}
},
"outputs": {},
"scl": "// Comparison Eq 35: \"MOD60\" = DINT#0"
"scl": "// Cond: \"MOD60\" = DINT#0"
},
{
"instruction_uid": "36",

View File

@ -94,7 +94,7 @@ def get_scl_representation(source_info, network_id, scl_map, access_map):
)
return f"_ERR_UNKNOWN_SRC_{source_info.get('uid')}_"
else:
print(f"Advertencia: Tipo de fuente desconocido o inválido: {source_info}")
print(f"Advertencia: Tipo de fuente desconocido: {source_info}")
return f"_ERR_INVALID_SRC_TYPE_"
@ -120,7 +120,7 @@ def get_target_scl_name(instruction, output_pin_name, network_id, default_to_tem
target_scl = dest_access.get("name")
if not target_scl:
print(
f"Error: Variable destino para {instr_uid}.{output_pin_name} sin nombre (UID: {dest_access.get('uid')}). {'Usando temp.' if default_to_temp else 'Ignorando.'}"
f"Error: Var destino {instr_uid}.{output_pin_name} sin nombre (UID: {dest_access.get('uid')}). {'Usando temp.' if default_to_temp else 'Ignorando.'}"
)
target_scl = (
generate_temp_var_name(network_id, instr_uid, output_pin_name)
@ -129,7 +129,7 @@ def get_target_scl_name(instruction, output_pin_name, network_id, default_to_tem
)
elif dest_access.get("type") == "constant":
print(
f"Advertencia: Instr {instr_uid} intenta escribir en constante UID {dest_access.get('uid')}. {'Usando temp.' if default_to_temp else 'Ignorando.'}"
f"Advertencia: Instr {instr_uid} escribe en const UID {dest_access.get('uid')}. {'Usando temp.' if default_to_temp else 'Ignorando.'}"
)
target_scl = (
generate_temp_var_name(network_id, instr_uid, output_pin_name)
@ -138,7 +138,7 @@ def get_target_scl_name(instruction, output_pin_name, network_id, default_to_tem
)
else:
print(
f"Advertencia: Destino de {instr_uid}.{output_pin_name} no es var/const: {dest_access.get('type')}. {'Usando temp.' if default_to_temp else 'Ignorando.'}"
f"Advertencia: Destino {instr_uid}.{output_pin_name} no es var/const: {dest_access.get('type')}. {'Usando temp.' if default_to_temp else 'Ignorando.'}"
)
target_scl = (
generate_temp_var_name(network_id, instr_uid, output_pin_name)
@ -150,262 +150,16 @@ def get_target_scl_name(instruction, output_pin_name, network_id, default_to_tem
return target_scl
# --- Procesadores de Instrucciones (MODIFICADOS para Agrupación) ---
# --- Procesadores de Instrucciones (SIMPLIFICADOS - Siempre generan IF si EN no es TRUE) ---
def check_if_grouped(instruction, network_id):
"""Verifica si la entrada EN de esta instrucción viene de una fuente
que alimenta a más de un bloque funcional en la misma red."""
en_input = instruction.get("inputs", {}).get("en")
if not isinstance(en_input, dict) or en_input.get("type") != "connection":
return False, None # No está conectado a otra instrucción o no tiene EN
source_uid = en_input.get("source_instruction_uid")
source_pin = en_input.get("source_pin")
if not source_uid or not source_pin:
return False, None # Información de fuente inválida
consumer_count = 0
network_logic = next(
(net["logic"] for net in data.get("networks", []) if net["id"] == network_id),
[],
)
for instr in network_logic:
other_en = instr.get("inputs", {}).get("en")
if (
isinstance(other_en, dict)
and other_en.get("type") == "connection"
and other_en.get("source_instruction_uid") == source_uid
and other_en.get("source_pin") == source_pin
):
# Contar solo bloques funcionales como consumidores
instr_type_orig = (
instr.get("type", "").replace(SCL_SUFFIX, "").replace("_error", "")
)
if instr_type_orig in [
"Move",
"Add",
"Sub",
"Mul",
"Div",
"Mod",
"Convert",
]: # Ampliar si es necesario
consumer_count += 1
is_grouped = consumer_count > 1
# print(f"DEBUG: Check group for {instruction['instruction_uid']}: source={source_uid}.{source_pin}, consumers={consumer_count}, is_grouped={is_grouped}")
return is_grouped, (source_uid, source_pin)
def process_move(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False
en_input = instruction["inputs"].get("en")
en_scl = (
"TRUE"
if en_input is None
else get_scl_representation(en_input, network_id, scl_map, access_map)
)
in_scl = get_scl_representation(
instruction["inputs"].get("in"), network_id, scl_map, access_map
)
if en_scl is None or in_scl is None:
return False
target_scl = get_target_scl_name(
instruction, "out1", network_id, default_to_temp=False
)
if target_scl is None:
print(f"Advertencia: MOVE UID: {instr_uid} no tiene destino claro.")
return False
scl_core = f"{target_scl} := {in_scl};"
# --- Lógica de Agrupación ---
is_grouped, _ = check_if_grouped(instruction, network_id)
if is_grouped:
scl_final = scl_core # Solo el core si es parte de grupo
instruction["grouped"] = True # Marcar como agrupado
elif en_scl != "TRUE":
scl_final = f"IF {en_scl} THEN\n {scl_core}\nEND_IF;"
else:
scl_final = scl_core
# --- Fin Lógica de Agrupación ---
instruction["scl"] = scl_final
instruction["type"] = instr_type + SCL_SUFFIX
return True
def process_add(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False
en_input = instruction["inputs"].get("en")
en_scl = (
"TRUE"
if en_input is None
else get_scl_representation(en_input, network_id, scl_map, access_map)
)
in1_scl = get_scl_representation(
instruction["inputs"].get("in1"), network_id, scl_map, access_map
)
in2_scl = get_scl_representation(
instruction["inputs"].get("in2"), network_id, scl_map, access_map
)
if en_scl is None or in1_scl is None or in2_scl is None:
return False
target_scl = get_target_scl_name(
instruction, "out", network_id, default_to_temp=True
)
if target_scl is None:
print(f"Error Interno: No se pudo det. destino ADD {instr_uid}")
instruction["type"] += "_error"
return True
op1 = f"({in1_scl})" if " " in in1_scl else in1_scl
op2 = f"({in2_scl})" if " " in in2_scl else in2_scl
scl_core = f"{target_scl} := {op1} + {op2};"
is_grouped, _ = check_if_grouped(instruction, network_id)
if is_grouped:
scl_final = scl_core
instruction["grouped"] = True
elif en_scl != "TRUE":
scl_final = f"IF {en_scl} THEN\n {scl_core}\nEND_IF;"
else:
scl_final = scl_core
instruction["scl"] = scl_final
instruction["type"] = instr_type + SCL_SUFFIX
map_key_out = (network_id, instr_uid, "out")
scl_map[map_key_out] = target_scl
map_key_eno = (network_id, instr_uid, "eno")
scl_map[map_key_eno] = en_scl
return True
# --- (Aplica lógica similar de 'check_if_grouped' a process_convert, process_mod, etc.) ---
# Ejemplo para process_convert:
def process_convert(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False
en_input = instruction["inputs"].get("en")
en_scl = (
"TRUE"
if en_input is None
else get_scl_representation(en_input, network_id, scl_map, access_map)
)
in_scl = get_scl_representation(
instruction["inputs"].get("in"), network_id, scl_map, access_map
)
if en_scl is None or in_scl is None:
return False
target_scl = get_target_scl_name(
instruction, "out", network_id, default_to_temp=True
)
if target_scl is None:
print(f"Error Interno: No se pudo det. destino CONVERT {instr_uid}")
instruction["type"] += "_error"
return True
conversion_expr = in_scl
scl_core = f"{target_scl} := {conversion_expr};"
is_grouped, _ = check_if_grouped(instruction, network_id)
if is_grouped:
scl_final = scl_core
instruction["grouped"] = True
elif en_scl != "TRUE":
scl_final = f"IF {en_scl} THEN\n {scl_core}\nEND_IF;"
else:
scl_final = scl_core
instruction["scl"] = scl_final
instruction["type"] = instr_type + SCL_SUFFIX
map_key_out = (network_id, instr_uid, "out")
scl_map[map_key_out] = target_scl
map_key_eno = (network_id, instr_uid, "eno")
scl_map[map_key_eno] = en_scl
return True
# Ejemplo para process_mod:
def process_mod(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False
en_input = instruction["inputs"].get("en")
en_scl = (
"TRUE"
if en_input is None
else get_scl_representation(en_input, network_id, scl_map, access_map)
)
in1_scl = get_scl_representation(
instruction["inputs"].get("in1"), network_id, scl_map, access_map
)
in2_scl = get_scl_representation(
instruction["inputs"].get("in2"), network_id, scl_map, access_map
)
if en_scl is None or in1_scl is None or in2_scl is None:
return False
target_scl = get_target_scl_name(
instruction, "out", network_id, default_to_temp=True
)
if target_scl is None:
print(f"Error Interno: No se pudo det. destino MOD {instr_uid}")
instruction["type"] += "_error"
return True
op1 = f"({in1_scl})" if " " in in1_scl else in1_scl
op2 = f"({in2_scl})" if " " in in2_scl else in2_scl
scl_core = f"{target_scl} := {op1} MOD {op2};"
is_grouped, _ = check_if_grouped(instruction, network_id)
if is_grouped:
scl_final = scl_core
instruction["grouped"] = True
elif en_scl != "TRUE":
scl_final = f"IF {en_scl} THEN\n {scl_core}\nEND_IF;"
else:
scl_final = scl_core
instruction["scl"] = scl_final
instruction["type"] = instr_type + SCL_SUFFIX
map_key_out = (network_id, instr_uid, "out")
scl_map[map_key_out] = target_scl
map_key_eno = (network_id, instr_uid, "eno")
scl_map[map_key_eno] = en_scl
return True
# --- (process_contact, process_eq, process_coil, process_o, process_pbox - sin cambios respecto a la versión anterior) ---
# ... (Asegúrate de tener las versiones funcionales de estos aquí) ...
def process_contact(instruction, network_id, scl_map, access_map):
# (Sin cambios respecto a la versión funcional anterior, solo actualiza scl_map)
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False
is_negated = False
is_negated = False # TODO
in_input = instruction["inputs"].get("in")
in_rlo_scl = (
"TRUE"
@ -421,25 +175,25 @@ def process_contact(instruction, network_id, scl_map, access_map):
if not (term.startswith('"') and term.endswith('"')):
if " " in term and not (term.startswith("(") and term.endswith(")")):
term = f"({term})"
new_rlo_scl = ""
if in_rlo_scl == "TRUE":
new_rlo_scl = term
else:
if ("AND" in in_rlo_scl or "OR" in in_rlo_scl) and not (
in_rlo_scl.startswith("(") and in_rlo_scl.endswith(")")
):
in_rlo_processed = f"({in_rlo_scl})"
else:
in_rlo_processed = in_rlo_scl
new_rlo_scl = f"{in_rlo_processed} AND {term}"
new_rlo_scl = (
term
if in_rlo_scl == "TRUE"
else (
f"({in_rlo_scl}) AND {term}"
if ("AND" in in_rlo_scl or "OR" in in_rlo_scl)
and not (in_rlo_scl.startswith("(") and in_rlo_scl.endswith(")"))
else f"{in_rlo_scl} AND {term}"
)
)
map_key = (network_id, instr_uid, "out")
scl_map[map_key] = new_rlo_scl
instruction["scl"] = f"// RLO updated by Contact {instr_uid}: {new_rlo_scl}"
instruction["scl"] = f"// RLO: {new_rlo_scl}" # SCL es solo comentario aquí
instruction["type"] = instr_type + SCL_SUFFIX
return True
def process_eq(instruction, network_id, scl_map, access_map):
# (Sin cambios respecto a la versión funcional anterior, solo actualiza scl_map)
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
@ -467,12 +221,13 @@ def process_eq(instruction, network_id, scl_map, access_map):
return False
map_key_eno = (network_id, instr_uid, "eno")
scl_map[map_key_eno] = pre_scl
instruction["scl"] = f"// Comparison Eq {instr_uid}: {comparison_scl}"
instruction["scl"] = f"// Cond: {comparison_scl}"
instruction["type"] = instr_type + SCL_SUFFIX
return True
def process_coil(instruction, network_id, scl_map, access_map):
# (Sin cambios respecto a la versión funcional anterior)
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
@ -499,7 +254,179 @@ def process_coil(instruction, network_id, scl_map, access_map):
return True
def process_convert(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False
en_input = instruction["inputs"].get("en")
# Ahora EN debe existir si es necesario, no asumimos TRUE si falta
en_scl = (
get_scl_representation(en_input, network_id, scl_map, access_map)
if en_input
else "TRUE"
) # Asumir TRUE solo si no hay 'en' key
in_scl = get_scl_representation(
instruction["inputs"].get("in"), network_id, scl_map, access_map
)
if en_scl is None or in_scl is None:
return False # Esperar si dependencias no listas
target_scl = get_target_scl_name(
instruction, "out", network_id, default_to_temp=True
)
if target_scl is None:
print(f"Error: Sin destino CONVERT {instr_uid}")
instruction["type"] += "_error"
return True
conversion_expr = in_scl # TODO: Logica de conversion explicita
scl_core = f"{target_scl} := {conversion_expr};"
scl_final = (
f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core
)
instruction["scl"] = scl_final
instruction["type"] = instr_type + SCL_SUFFIX
map_key_out = (network_id, instr_uid, "out")
scl_map[map_key_out] = target_scl
map_key_eno = (network_id, instr_uid, "eno")
scl_map[map_key_eno] = en_scl
return True
def process_mod(instruction, network_id, scl_map, access_map):
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False
en_input = instruction["inputs"].get("en")
en_scl = (
get_scl_representation(en_input, network_id, scl_map, access_map)
if en_input
else "TRUE"
)
in1_scl = get_scl_representation(
instruction["inputs"].get("in1"), network_id, scl_map, access_map
)
in2_scl = get_scl_representation(
instruction["inputs"].get("in2"), network_id, scl_map, access_map
)
if en_scl is None or in1_scl is None or in2_scl is None:
return False
target_scl = get_target_scl_name(
instruction, "out", network_id, default_to_temp=True
)
if target_scl is None:
print(f"Error: Sin destino MOD {instr_uid}")
instruction["type"] += "_error"
return True
op1 = f"({in1_scl})" if " " in in1_scl else in1_scl
op2 = f"({in2_scl})" if " " in in2_scl else in2_scl
scl_core = f"{target_scl} := {op1} MOD {op2};"
scl_final = (
f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core
)
instruction["scl"] = scl_final
instruction["type"] = instr_type + SCL_SUFFIX
map_key_out = (network_id, instr_uid, "out")
scl_map[map_key_out] = target_scl
map_key_eno = (network_id, instr_uid, "eno")
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"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False
en_input = instruction["inputs"].get("en")
en_scl = (
get_scl_representation(en_input, network_id, scl_map, access_map)
if en_input
else "TRUE"
)
in1_scl = get_scl_representation(
instruction["inputs"].get("in1"), network_id, scl_map, access_map
)
in2_scl = get_scl_representation(
instruction["inputs"].get("in2"), network_id, scl_map, access_map
)
if en_scl is None or in1_scl is None or in2_scl is None:
return False
target_scl = get_target_scl_name(
instruction, "out", network_id, default_to_temp=True
)
if target_scl is None:
print(f"Error: Sin destino ADD {instr_uid}")
instruction["type"] += "_error"
return True
op1 = f"({in1_scl})" if " " in in1_scl else in1_scl
op2 = f"({in2_scl})" if " " in in2_scl else in2_scl
scl_core = f"{target_scl} := {op1} + {op2};"
scl_final = (
f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core
)
instruction["scl"] = scl_final
instruction["type"] = instr_type + SCL_SUFFIX
map_key_out = (network_id, instr_uid, "out")
scl_map[map_key_out] = target_scl
map_key_eno = (network_id, instr_uid, "eno")
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"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
return False
en_input = instruction["inputs"].get("en")
en_scl = (
get_scl_representation(en_input, network_id, scl_map, access_map)
if en_input
else "TRUE"
)
in_scl = get_scl_representation(
instruction["inputs"].get("in"), network_id, scl_map, access_map
)
if en_scl is None or in_scl is None:
return False
target_scl = get_target_scl_name(
instruction, "out1", network_id, default_to_temp=False
) # No usar temp por defecto
if target_scl is None:
print(f"Advertencia: MOVE {instr_uid} sin destino claro.")
return False # No procesar
scl_core = f"{target_scl} := {in_scl};"
scl_final = (
f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core
)
instruction["scl"] = scl_final
instruction["type"] = instr_type + SCL_SUFFIX
return True
def process_pbox(instruction, network_id, scl_map, access_map, network_logic_list):
# (Sin cambios respecto a la versión funcional anterior)
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
@ -575,7 +502,7 @@ def process_pbox(instruction, network_id, scl_map, access_map, network_logic_lis
clk_source_found = True
break
if not clk_source_found:
print(f"Error: No se pudo inferir CLK para PBOX {instr_uid}")
print(f"Error: No se pudo inferir CLK PBOX {instr_uid}")
instruction["scl"] = f"// ERROR: PBox {instr_uid} sin CLK"
instruction["type"] += "_error"
return True
@ -585,9 +512,7 @@ def process_pbox(instruction, network_id, scl_map, access_map, network_logic_lis
if is_likely_p_trig:
clk_signal_formatted = f"({rlo_scl})" if " " in rlo_scl else rlo_scl
result_scl = f"P_TRIG_FUNC(CLK := {clk_signal_formatted}, M := {mem_bit_scl})"
scl_comment = (
f"// Edge detection PBox {instr_uid} -> {result_scl} (CLK inferred)"
)
scl_comment = f"// Edge PBox {instr_uid} -> {result_scl}"
else:
print(f"Advertencia: PBox {instr_uid} no como P_TRIG. Pasando bit.")
result_scl = mem_bit_scl
@ -600,6 +525,7 @@ def process_pbox(instruction, network_id, scl_map, access_map, network_logic_lis
def process_o(instruction, network_id, scl_map, access_map):
# (Sin cambios respecto a la versión funcional anterior)
instr_uid = instruction["instruction_uid"]
instr_type = instruction["type"]
if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type:
@ -640,11 +566,11 @@ def process_o(instruction, network_id, scl_map, access_map):
return True
# --- NUEVO: Procesador de Agrupación ---
# --- NUEVO: Procesador de Agrupación (Refinado) ---
def process_group_ifs(instruction, network_id, scl_map, access_map):
"""
Busca instrucciones que generan condiciones (Contact, O, Eq, PBox)
y, si habilitan un grupo de bloques funcionales, construye el bloque IF agrupado.
Busca instrucciones que generan condiciones (Contact, O, Eq, PBox) ya procesadas
y, si habilitan un grupo (>1) de bloques funcionales, construye el bloque IF agrupado.
Modifica el campo 'scl' de la instrucción generadora de condición.
"""
instr_uid = instruction["instruction_uid"]
@ -652,7 +578,7 @@ def process_group_ifs(instruction, network_id, scl_map, access_map):
instr_type_original = instr_type.replace("_scl", "").replace("_error", "")
made_change = False
# Solo actuar sobre generadores de condición ya procesados
# Solo actuar sobre generadores de condición ya procesados (_scl)
if not instr_type.endswith("_scl") or instr_type_original not in [
"Contact",
"O",
@ -664,22 +590,24 @@ def process_group_ifs(instruction, network_id, scl_map, access_map):
"Le",
"PBox",
]:
return False # No es un generador de condición procesado relevante
# Si ya contiene un IF agrupado (de un pase anterior o error), no hacer nada
if instruction.get("scl", "").strip().startswith("IF"):
return False
# Obtener la condición generada por esta instrucción
# Evitar reagrupar si ya se hizo
if instruction.get("scl", "").strip().startswith("IF"):
# print(f"DEBUG Group: {instr_uid} ya tiene IF, saltando agrupación.")
return False
# Obtener la condición generada por esta instrucción (debería estar en scl_map)
map_key_out = (network_id, instr_uid, "out")
condition_scl = scl_map.get(map_key_out)
if condition_scl is None or condition_scl == "TRUE" or condition_scl == "FALSE":
return False # No agrupar para condiciones triviales
# No agrupar para condiciones triviales o no encontradas
if condition_scl is None or condition_scl in ["TRUE", "FALSE"]:
return False
# Encontrar todos los bloques funcionales habilitados DIRECTAMENTE por esta condición
grouped_instructions_core_scl = []
consumer_uids_processed_in_group = set() # Para marcar consumidores agrupados
grouped_instructions_cores = [] # Lista de SCL 'core'
consumer_instr_list = [] # Lista de instrucciones consumidoras
network_logic = next(
(net["logic"] for net in data["networks"] if net["id"] == network_id), []
)
@ -688,15 +616,15 @@ def process_group_ifs(instruction, network_id, scl_map, access_map):
for consumer_instr in network_logic:
consumer_uid = consumer_instr["instruction_uid"]
# Saltar si el consumidor ya fue marcado como agrupado por otra condición
# Saltar si ya está agrupado por otra condición
if consumer_instr.get("grouped", False):
continue
consumer_en = consumer_instr.get("inputs", {}).get("en")
consumer_type = consumer_instr.get("type", "")
consumer_type = consumer_instr.get("type", "") # Tipo actual (_scl o no)
consumer_type_original = consumer_type.replace("_scl", "").replace("_error", "")
# Verificar si está conectado a nuestra salida 'out'
# ¿Está conectado a nuestra salida 'out'?
if (
isinstance(consumer_en, dict)
and consumer_en.get("type") == "connection"
@ -704,42 +632,59 @@ def process_group_ifs(instruction, network_id, scl_map, access_map):
and consumer_en.get("source_pin") == "out"
):
# Verificar si es un bloque funcional procesado y si su SCL es solo el 'core'
if (
consumer_type.endswith("_scl")
and consumer_type_original
in ["Move", "Add", "Sub", "Mul", "Div", "Mod", "Convert"]
and consumer_instr.get("scl")
and not consumer_instr["scl"].strip().startswith("IF")
): # Asegurarse de que NO tenga IF
# ¿Es un bloque funcional procesado?
if consumer_type.endswith("_scl") and consumer_type_original in [
"Move",
"Add",
"Sub",
"Mul",
"Div",
"Mod",
"Convert",
]:
core_scl = consumer_instr["scl"].strip()
grouped_instructions_core_scl.append(core_scl)
consumer_uids_processed_in_group.add(consumer_uid)
consumer_scl = consumer_instr.get("scl", "")
# Extraer el SCL core (la parte DENTRO del IF o la línea única si no había IF)
core_scl = None
if consumer_scl.strip().startswith("IF"):
match = re.search(r"THEN\s*(.+)\s*END_IF;", consumer_scl, re.DOTALL)
if match:
core_scl = match.group(1).strip()
elif consumer_scl and not consumer_scl.strip().startswith(
"//"
): # Si no es IF y no es solo comentario
core_scl = consumer_scl.strip()
# Si encontramos más de un consumidor agrupado
if len(grouped_instructions_core_scl) > 1:
if core_scl:
grouped_instructions_cores.append(core_scl)
consumer_instr_list.append(
consumer_instr
) # Guardar referencia a la instrucción
# else: # Comentado para reducir ruido
# print(f"DEBUG Group: Consumidor {consumer_uid} no tenía SCL core extraíble.")
# Si encontramos más de un consumidor
if len(grouped_instructions_cores) > 1:
print(
f"INFO: Agrupando {len(grouped_instructions_core_scl)} instrucciones para condición de {instr_type_original} UID {instr_uid}"
f"INFO: Agrupando {len(grouped_instructions_cores)} instrucciones bajo condición de {instr_type_original} UID {instr_uid}"
)
# Construir el bloque IF agrupado
scl_grouped = [f"IF {condition_scl} THEN"]
for core_line in grouped_instructions_core_scl:
scl_grouped.append(f" {core_line}") # Añadir indentación
for core_line in grouped_instructions_cores:
# Añadir indentación adecuada si el core tiene múltiples líneas
indented_core = "\n".join(
[f" {line.strip()}" for line in core_line.splitlines()]
)
scl_grouped.append(indented_core)
scl_grouped.append("END_IF;")
final_grouped_scl = "\n".join(scl_grouped)
# Sobrescribir el campo 'scl' de la instrucción generadora de condición
# Sobrescribir 'scl' de la instrucción generadora
instruction["scl"] = final_grouped_scl
# Marcar los consumidores para que generate_scl los ignore
for consumer_uid_to_mark in consumer_uids_processed_in_group:
for instr_to_mark in network_logic:
if instr_to_mark["instruction_uid"] == consumer_uid_to_mark:
# Añadir comentario y flag
instr_to_mark["scl"] = f"{GROUPED_COMMENT} (by UID {instr_uid})"
instr_to_mark["grouped"] = True
break
# Marcar los consumidores
for consumer_instr in consumer_instr_list:
consumer_instr["scl"] = f"{GROUPED_COMMENT} (by UID {instr_uid})"
consumer_instr["grouped"] = True
made_change = True
return made_change
@ -751,21 +696,19 @@ def process_group_ifs(instruction, network_id, scl_map, access_map):
def process_json_to_scl(json_filepath):
"""Lee el JSON, aplica los procesadores iterativamente y guarda el resultado."""
if not os.path.exists(json_filepath):
print(f"Error: Archivo JSON no encontrado en {json_filepath}")
print(f"Error: JSON no encontrado: {json_filepath}")
return
print(f"Cargando JSON desde: {json_filepath}")
try:
with open(json_filepath, "r", encoding="utf-8") as f:
global data
data = json.load(f)
except Exception as e:
print(f"Error al cargar o parsear JSON: {e}")
print(f"Error al cargar JSON: {e}")
return
# Reconstruir access_map dinámicamente
network_access_maps = {}
# print("Creando mapas de acceso por red...")
# print("Creando mapas de acceso por red...") # Comentado para brevedad
for network in data.get("networks", []):
net_id = network["id"]
current_access_map = {}
@ -800,7 +743,7 @@ def process_json_to_scl(json_filepath):
max_passes = 25
passes = 0
# Lista de procesadores base + procesador de agrupación
# Lista y mapa de procesadores base
base_processors = [
process_convert,
process_mod,
@ -824,12 +767,11 @@ def process_json_to_scl(json_filepath):
print(f"\n--- Pase {passes} ---")
# --- FASE 1: Procesadores Base ---
print(f"DEBUG: Iniciando Fase 1 (Procesadores Base) - Pase {passes}")
# print(f"DEBUG: Iniciando Fase 1 (Procesadores Base) - Pase {passes}") # Debug
for network in data.get("networks", []):
network_id = network["id"]
access_map = network_access_maps.get(network_id, {})
network_logic = network.get("logic", [])
for instruction in network_logic:
instr_type_original = instruction["type"]
if (
@ -837,11 +779,9 @@ def process_json_to_scl(json_filepath):
or "_error" in instr_type_original
or instruction.get("grouped", False)
):
continue # Saltar ya procesados, erróneos o agrupados
continue
instr_type_lower_lookup = instr_type_original.lower()
func_to_call = processor_map.get(instr_type_lower_lookup)
if func_to_call:
try:
changed = False
@ -857,59 +797,49 @@ def process_json_to_scl(json_filepath):
changed = func_to_call(
instruction, network_id, scl_map, access_map
)
if changed:
# print(f"DEBUG: Cambio BASE detectado por {func_to_call.__name__} en UID {instruction['instruction_uid']}")
made_change_in_base_pass = True
except Exception as e:
print(
f"ERROR(Base) al ejecutar {func_to_call.__name__} en UID {instruction.get('instruction_uid')} Red {network_id}: {e}"
f"ERROR(Base) {func_to_call.__name__} UID {instruction.get('instruction_uid')}: {e}"
)
traceback.print_exc()
instruction["scl"] = f"// ERROR during base processing: {e}"
instruction["scl"] = f"// ERROR base: {e}"
instruction["type"] += "_error"
made_change_in_base_pass = True # Considerar error como cambio
made_change_in_base_pass = True
# --- FASE 2: Procesador de Agrupación ---
print(f"DEBUG: Iniciando Fase 2 (Agrupación IF) - Pase {passes}")
# print(f"DEBUG: Iniciando Fase 2 (Agrupación IF) - Pase {passes}") # Debug
for network in data.get("networks", []):
network_id = network["id"]
access_map = network_access_maps.get(network_id, {})
network_logic = network.get("logic", [])
for instruction in network_logic:
# Solo intentar agrupar en generadores de condición ya procesados
if instruction["type"].endswith("_scl") and not instruction.get(
"grouped", False
):
): # Solo en generadores procesados y no agrupados
try:
group_changed = process_group_ifs(
instruction, network_id, scl_map, access_map
)
if group_changed:
# print(f"DEBUG: Cambio GROUP detectado por process_group_ifs en UID {instruction['instruction_uid']}")
made_change_in_group_pass = True
except Exception as e:
print(
f"ERROR(Group) al ejecutar process_group_ifs en UID {instruction.get('instruction_uid')}: {e}"
f"ERROR(Group) process_group_ifs UID {instruction.get('instruction_uid')}: {e}"
)
traceback.print_exc()
# No marcar la instrucción como error por fallo en agrupación
# Decidir si continuar: Hubo algún cambio en CUALQUIERA de las fases?
# Decidir si continuar
if not made_change_in_base_pass and not made_change_in_group_pass:
print(
f"\n--- No se hicieron cambios en el pase {passes}. Proceso completado. ---"
)
break
else:
print(
f"DEBUG: Cambios en Pase {passes}: Base={made_change_in_base_pass}, Grupo={made_change_in_group_pass}. Continuando..."
)
# else: print(f"DEBUG: Cambios Pase {passes}: Base={made_change_in_base_pass}, Grupo={made_change_in_group_pass}. Continuando...") # Debug
if passes == max_passes:
print(
f"\n--- Límite de {max_passes} pases alcanzado. Puede haber dependencias circulares o lógica no procesada. ---"
)
print(f"\n--- Límite de {max_passes} pases alcanzado. ---")
# --- Guardar JSON Final ---
output_filename = json_filepath.replace(".json", "_scl_processed.json")
@ -919,10 +849,10 @@ def process_json_to_scl(json_filepath):
json.dump(data, f, indent=4, ensure_ascii=False)
print("Guardado completado.")
except Exception as e:
print(f"Error al guardar el JSON procesado: {e}")
print(f"Error al guardar JSON: {e}")
# --- Ejecución ---
if __name__ == "__main__":
input_json_file = "BlenderRun_ProdTime_simplified.json"
input_json_file = "BlenderRun_ProdTime_simplified.json" # Asegúrate que este es el generado por x1_to_json.py MODIFICADO
process_json_to_scl(input_json_file)