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 // 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 IF "Procedure_Variables"."Blender_Run"."Running" AND "CLK_1.0S" THEN
"Blender_Variables_Pers"."gSLIM_Sec" := "Blender_Variables_Pers"."gSLIM_Sec" + 1; "Blender_Variables_Pers"."gSLIM_Sec" := "Blender_Variables_Pers"."gSLIM_Sec" + 1;
END_IF; END_IF;
// Network 2: Reset Hours // Network 2: Reset Hours
// RLO: "SLIM_Variables"."ResetHour"
IF "SLIM_Variables"."ResetHour" THEN IF "SLIM_Variables"."ResetHour" THEN
"Blender_Variables_Pers"."gSLIM_Sec" := 0; "Blender_Variables_Pers"."gSLIM_Sec" := 0;
END_IF; END_IF;
// Network 3: Seconds Counter // Network 3: Seconds Counter
// RLO: "gBlenderBlending"
// RLO: "gBlenderBlending" AND "CLK_1.0S"
IF "gBlenderBlending" AND "CLK_1.0S" THEN IF "gBlenderBlending" AND "CLK_1.0S" THEN
"Blender_Variables_Pers"."gProdSec" := "Blender_Variables_Pers"."gProdSec" + 1; "Blender_Variables_Pers"."gProdSec" := "Blender_Variables_Pers"."gProdSec" + 1;
END_IF; END_IF;
// Network 4: Minute // Network 4: Minute
// Cond: "Blender_Variables_Pers"."gProdSec" = 60
"m1MinONS" := "Blender_Variables_Pers"."gProdSec" = 60; "m1MinONS" := "Blender_Variables_Pers"."gProdSec" = 60;
// Network 5: Minute Counter // Network 5: Minute Counter
IF "m1MinONS" THEN
"Blender_Variables_Pers"."gProdSec" := 0; "Blender_Variables_Pers"."gProdSec" := 0;
"Blender_Variables_Pers"."gProdMin" := "Blender_Variables_Pers"."gProdMin" + 1; "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 // Network 6: Hour
// Cond: "Blender_Variables_Pers"."gProdMin" = 60
"m1HourONS" := "Blender_Variables_Pers"."gProdMin" = 60; "m1HourONS" := "Blender_Variables_Pers"."gProdMin" = 60;
// Network 7: Hour Counter // Network 7: Hour Counter
IF "m1HourONS" THEN
"Blender_Variables_Pers"."gProdMin" := 0; "Blender_Variables_Pers"."gProdMin" := 0;
"Blender_Variables_Pers"."gProdHour" := "Blender_Variables_Pers"."gProdHour" + 1; "Blender_Variables_Pers"."gProdHour" := "Blender_Variables_Pers"."gProdHour" + 1;
"Blender_Variables_Pers"."gBlendingMaintHour" := "Blender_Variables_Pers"."gBlendingMaintHour" + 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 // Network 8: Counter reset
// RLO: "gBlenderCIPMode"
// RLO: "gBlenderRinseMode"
IF "gBlenderCIPMode" OR "gBlenderRinseMode" THEN
"Blender_Variables_Pers"."gProdSec" := 0; "Blender_Variables_Pers"."gProdSec" := 0;
"Blender_Variables_Pers"."gProdMin" := 0; "Blender_Variables_Pers"."gProdMin" := 0;
"Blender_Variables_Pers"."gProdHour" := 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 // 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 IF "Procedure_Variables"."Blender_Run"."Running" AND "CLK_1.0S" THEN
"Blender_Variables_Pers"."gRunningSeconds" := "Blender_Variables_Pers"."gRunningSeconds" + 1; "Blender_Variables_Pers"."gRunningSeconds" := "Blender_Variables_Pers"."gRunningSeconds" + 1;
END_IF; END_IF;
@ -81,20 +106,25 @@ BEGIN
"I_DIRunning_sec" := "Blender_Variables_Pers"."gRunningSeconds"; "I_DIRunning_sec" := "Blender_Variables_Pers"."gRunningSeconds";
"MOD60" := "I_DIRunning_sec" MOD DINT#60; "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 IF ("MOD60" = DINT#0 AND "Procedure_Variables"."Blender_Run"."Running") AND "CLK_1.0S" THEN
"Blender_Variables_Pers"."gRunningMinutes" := "Blender_Variables_Pers"."gRunningMinutes" + 1; "Blender_Variables_Pers"."gRunningMinutes" := "Blender_Variables_Pers"."gRunningMinutes" + 1;
END_IF; 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"); "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 // Network 11: Running Hours for Maintenance
// RLO: "mRunMin"
IF "mRunMin" THEN IF "mRunMin" THEN
"I_DIRunning_min" := "Blender_Variables_Pers"."gRunningMinutes"; "I_DIRunning_min" := "Blender_Variables_Pers"."gRunningMinutes";
END_IF; END_IF;
IF "mRunMin" THEN IF "mRunMin" THEN
"MOD60" := "I_DIRunning_min" MOD DINT#60; "MOD60" := "I_DIRunning_min" MOD DINT#60;
END_IF; END_IF;
// Cond: "MOD60" = DINT#0
IF "MOD60" = DINT#0 THEN IF "MOD60" = DINT#0 THEN
"Blender_Variables_Pers"."gRunningMaintHour" := "Blender_Variables_Pers"."gRunningMaintHour" + 1; "Blender_Variables_Pers"."gRunningMaintHour" := "Blender_Variables_Pers"."gRunningMaintHour" + 1;
END_IF; END_IF;

View File

@ -66,7 +66,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// RLO updated by Contact 26: \"Procedure_Variables\".\"Blender_Run\".\"Running\"" "scl": "// RLO: \"Procedure_Variables\".\"Blender_Run\".\"Running\""
}, },
{ {
"instruction_uid": "27", "instruction_uid": "27",
@ -86,7 +86,7 @@
} }
}, },
"outputs": {}, "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", "instruction_uid": "28",
@ -146,7 +146,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// RLO updated by Contact 24: \"SLIM_Variables\".\"ResetHour\"" "scl": "// RLO: \"SLIM_Variables\".\"ResetHour\""
}, },
{ {
"instruction_uid": "25", "instruction_uid": "25",
@ -200,7 +200,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// RLO updated by Contact 26: \"gBlenderBlending\"" "scl": "// RLO: \"gBlenderBlending\""
}, },
{ {
"instruction_uid": "27", "instruction_uid": "27",
@ -220,7 +220,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// RLO updated by Contact 27: \"gBlenderBlending\" AND \"CLK_1.0S\"" "scl": "// RLO: \"gBlenderBlending\" AND \"CLK_1.0S\""
}, },
{ {
"instruction_uid": "28", "instruction_uid": "28",
@ -287,7 +287,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// Comparison Eq 24: \"Blender_Variables_Pers\".\"gProdSec\" = 60" "scl": "// Cond: \"Blender_Variables_Pers\".\"gProdSec\" = 60"
}, },
{ {
"instruction_uid": "25", "instruction_uid": "25",
@ -331,7 +331,7 @@
} }
}, },
"outputs": {}, "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", "instruction_uid": "28",
@ -361,8 +361,8 @@
} }
] ]
}, },
"grouped": true, "scl": "// Logic included in grouped IF (by UID 27)",
"scl": "\"Blender_Variables_Pers\".\"gProdSec\" := 0;" "grouped": true
}, },
{ {
"instruction_uid": "29", "instruction_uid": "29",
@ -398,8 +398,8 @@
} }
] ]
}, },
"grouped": true, "scl": "// Logic included in grouped IF (by UID 27)",
"scl": "\"Blender_Variables_Pers\".\"gProdMin\" := \"Blender_Variables_Pers\".\"gProdMin\" + 1;" "grouped": true
} }
] ]
}, },
@ -430,7 +430,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// Comparison Eq 24: \"Blender_Variables_Pers\".\"gProdMin\" = 60" "scl": "// Cond: \"Blender_Variables_Pers\".\"gProdMin\" = 60"
}, },
{ {
"instruction_uid": "25", "instruction_uid": "25",
@ -474,7 +474,7 @@
} }
}, },
"outputs": {}, "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", "instruction_uid": "31",
@ -504,8 +504,8 @@
} }
] ]
}, },
"grouped": true, "scl": "// Logic included in grouped IF (by UID 30)",
"scl": "\"Blender_Variables_Pers\".\"gProdMin\" := 0;" "grouped": true
}, },
{ {
"instruction_uid": "32", "instruction_uid": "32",
@ -541,8 +541,8 @@
} }
] ]
}, },
"grouped": true, "scl": "// Logic included in grouped IF (by UID 30)",
"scl": "\"Blender_Variables_Pers\".\"gProdHour\" := \"Blender_Variables_Pers\".\"gProdHour\" + 1;" "grouped": true
}, },
{ {
"instruction_uid": "33", "instruction_uid": "33",
@ -578,8 +578,8 @@
} }
] ]
}, },
"grouped": true, "scl": "// Logic included in grouped IF (by UID 30)",
"scl": "\"Blender_Variables_Pers\".\"gBlendingMaintHour\" := \"Blender_Variables_Pers\".\"gBlendingMaintHour\" + 1;" "grouped": true
} }
] ]
}, },
@ -603,7 +603,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// RLO updated by Contact 29: \"gBlenderCIPMode\"" "scl": "// RLO: \"gBlenderCIPMode\""
}, },
{ {
"instruction_uid": "30", "instruction_uid": "30",
@ -617,7 +617,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// RLO updated by Contact 30: \"gBlenderRinseMode\"" "scl": "// RLO: \"gBlenderRinseMode\""
}, },
{ {
"instruction_uid": "31", "instruction_uid": "31",
@ -637,7 +637,7 @@
} }
}, },
"outputs": {}, "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", "instruction_uid": "32",
@ -667,8 +667,8 @@
} }
] ]
}, },
"grouped": true, "scl": "// Logic included in grouped IF (by UID 31)",
"scl": "\"Blender_Variables_Pers\".\"gProdSec\" := 0;" "grouped": true
}, },
{ {
"instruction_uid": "33", "instruction_uid": "33",
@ -698,8 +698,8 @@
} }
] ]
}, },
"grouped": true, "scl": "// Logic included in grouped IF (by UID 31)",
"scl": "\"Blender_Variables_Pers\".\"gProdMin\" := 0;" "grouped": true
}, },
{ {
"instruction_uid": "34", "instruction_uid": "34",
@ -729,8 +729,8 @@
} }
] ]
}, },
"grouped": true, "scl": "// Logic included in grouped IF (by UID 31)",
"scl": "\"Blender_Variables_Pers\".\"gProdHour\" := 0;" "grouped": true
} }
] ]
}, },
@ -754,7 +754,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// RLO updated by Contact 26: \"Procedure_Variables\".\"Blender_Run\".\"Running\"" "scl": "// RLO: \"Procedure_Variables\".\"Blender_Run\".\"Running\""
}, },
{ {
"instruction_uid": "27", "instruction_uid": "27",
@ -774,7 +774,7 @@
} }
}, },
"outputs": {}, "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", "instruction_uid": "28",
@ -914,7 +914,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// Comparison Eq 37: \"MOD60\" = DINT#0" "scl": "// Cond: \"MOD60\" = DINT#0"
}, },
{ {
"instruction_uid": "38", "instruction_uid": "38",
@ -934,7 +934,7 @@
} }
}, },
"outputs": {}, "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", "instruction_uid": "39",
@ -954,7 +954,7 @@
} }
}, },
"outputs": {}, "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", "instruction_uid": "40",
@ -1004,7 +1004,7 @@
} }
}, },
"outputs": {}, "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", "instruction_uid": "42",
@ -1048,7 +1048,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// RLO updated by Contact 32: \"mRunMin\"" "scl": "// RLO: \"mRunMin\""
}, },
{ {
"instruction_uid": "33", "instruction_uid": "33",
@ -1148,7 +1148,7 @@
} }
}, },
"outputs": {}, "outputs": {},
"scl": "// Comparison Eq 35: \"MOD60\" = DINT#0" "scl": "// Cond: \"MOD60\" = DINT#0"
}, },
{ {
"instruction_uid": "36", "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')}_" return f"_ERR_UNKNOWN_SRC_{source_info.get('uid')}_"
else: 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_" 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") target_scl = dest_access.get("name")
if not target_scl: if not target_scl:
print( 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 = ( target_scl = (
generate_temp_var_name(network_id, instr_uid, output_pin_name) 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": elif dest_access.get("type") == "constant":
print( 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 = ( target_scl = (
generate_temp_var_name(network_id, instr_uid, output_pin_name) 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: else:
print( 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 = ( target_scl = (
generate_temp_var_name(network_id, instr_uid, output_pin_name) 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 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): 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_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
is_negated = False is_negated = False # TODO
in_input = instruction["inputs"].get("in") in_input = instruction["inputs"].get("in")
in_rlo_scl = ( in_rlo_scl = (
"TRUE" "TRUE"
@ -421,25 +175,25 @@ def process_contact(instruction, network_id, scl_map, access_map):
if not (term.startswith('"') and term.endswith('"')): if not (term.startswith('"') and term.endswith('"')):
if " " in term and not (term.startswith("(") and term.endswith(")")): if " " in term and not (term.startswith("(") and term.endswith(")")):
term = f"({term})" term = f"({term})"
new_rlo_scl = "" new_rlo_scl = (
if in_rlo_scl == "TRUE": term
new_rlo_scl = term if in_rlo_scl == "TRUE"
else: else (
if ("AND" in in_rlo_scl or "OR" in in_rlo_scl) and not ( f"({in_rlo_scl}) AND {term}"
in_rlo_scl.startswith("(") and in_rlo_scl.endswith(")") 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 f"{in_rlo_scl} AND {term}"
else: )
in_rlo_processed = in_rlo_scl )
new_rlo_scl = f"{in_rlo_processed} AND {term}"
map_key = (network_id, instr_uid, "out") map_key = (network_id, instr_uid, "out")
scl_map[map_key] = new_rlo_scl 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 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):
# (Sin cambios respecto a la versión funcional anterior, solo actualiza scl_map)
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:
@ -467,12 +221,13 @@ def process_eq(instruction, network_id, scl_map, access_map):
return False return False
map_key_eno = (network_id, instr_uid, "eno") map_key_eno = (network_id, instr_uid, "eno")
scl_map[map_key_eno] = pre_scl 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 instruction["type"] = instr_type + SCL_SUFFIX
return True return True
def process_coil(instruction, network_id, scl_map, access_map): 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_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:
@ -499,7 +254,179 @@ def process_coil(instruction, network_id, scl_map, access_map):
return True 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): 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_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:
@ -575,7 +502,7 @@ def process_pbox(instruction, network_id, scl_map, access_map, network_logic_lis
clk_source_found = True clk_source_found = True
break break
if not clk_source_found: 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["scl"] = f"// ERROR: PBox {instr_uid} sin CLK"
instruction["type"] += "_error" instruction["type"] += "_error"
return True return True
@ -585,9 +512,7 @@ def process_pbox(instruction, network_id, scl_map, access_map, network_logic_lis
if is_likely_p_trig: if is_likely_p_trig:
clk_signal_formatted = f"({rlo_scl})" if " " in rlo_scl else rlo_scl 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})" result_scl = f"P_TRIG_FUNC(CLK := {clk_signal_formatted}, M := {mem_bit_scl})"
scl_comment = ( scl_comment = f"// Edge PBox {instr_uid} -> {result_scl}"
f"// Edge detection PBox {instr_uid} -> {result_scl} (CLK inferred)"
)
else: else:
print(f"Advertencia: PBox {instr_uid} no como P_TRIG. Pasando bit.") print(f"Advertencia: PBox {instr_uid} no como P_TRIG. Pasando bit.")
result_scl = mem_bit_scl 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): 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_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:
@ -640,11 +566,11 @@ def process_o(instruction, network_id, scl_map, access_map):
return True return True
# --- NUEVO: Procesador de Agrupación --- # --- 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):
""" """
Busca instrucciones que generan condiciones (Contact, O, Eq, PBox) Busca instrucciones que generan condiciones (Contact, O, Eq, PBox) ya procesadas
y, si habilitan un grupo de bloques funcionales, construye el bloque IF agrupado. 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. Modifica el campo 'scl' de la instrucción generadora de condición.
""" """
instr_uid = instruction["instruction_uid"] 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", "") instr_type_original = instr_type.replace("_scl", "").replace("_error", "")
made_change = False 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 [ if not instr_type.endswith("_scl") or instr_type_original not in [
"Contact", "Contact",
"O", "O",
@ -664,22 +590,24 @@ def process_group_ifs(instruction, network_id, scl_map, access_map):
"Le", "Le",
"PBox", "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 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") map_key_out = (network_id, instr_uid, "out")
condition_scl = scl_map.get(map_key_out) condition_scl = scl_map.get(map_key_out)
if condition_scl is None or condition_scl == "TRUE" or condition_scl == "FALSE": # No agrupar para condiciones triviales o no encontradas
return False # No agrupar para condiciones triviales if condition_scl is None or condition_scl in ["TRUE", "FALSE"]:
return False
# Encontrar todos los bloques funcionales habilitados DIRECTAMENTE por esta condición # Encontrar todos los bloques funcionales habilitados DIRECTAMENTE por esta condición
grouped_instructions_core_scl = [] grouped_instructions_cores = [] # Lista de SCL 'core'
consumer_uids_processed_in_group = set() # Para marcar consumidores agrupados consumer_instr_list = [] # Lista de instrucciones consumidoras
network_logic = next( network_logic = next(
(net["logic"] for net in data["networks"] if net["id"] == network_id), [] (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: for consumer_instr in network_logic:
consumer_uid = consumer_instr["instruction_uid"] 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): if consumer_instr.get("grouped", False):
continue continue
consumer_en = consumer_instr.get("inputs", {}).get("en") 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", "") consumer_type_original = consumer_type.replace("_scl", "").replace("_error", "")
# Verificar si está conectado a nuestra salida 'out' # ¿Está conectado a nuestra salida 'out'?
if ( if (
isinstance(consumer_en, dict) isinstance(consumer_en, dict)
and consumer_en.get("type") == "connection" 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" and consumer_en.get("source_pin") == "out"
): ):
# Verificar si es un bloque funcional procesado y si su SCL es solo el 'core' # ¿Es un bloque funcional procesado?
if ( if consumer_type.endswith("_scl") and consumer_type_original in [
consumer_type.endswith("_scl") "Move",
and consumer_type_original "Add",
in ["Move", "Add", "Sub", "Mul", "Div", "Mod", "Convert"] "Sub",
and consumer_instr.get("scl") "Mul",
and not consumer_instr["scl"].strip().startswith("IF") "Div",
): # Asegurarse de que NO tenga IF "Mod",
"Convert",
]:
core_scl = consumer_instr["scl"].strip() consumer_scl = consumer_instr.get("scl", "")
grouped_instructions_core_scl.append(core_scl) # Extraer el SCL core (la parte DENTRO del IF o la línea única si no había IF)
consumer_uids_processed_in_group.add(consumer_uid) 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 core_scl:
if len(grouped_instructions_core_scl) > 1: 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( 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"] scl_grouped = [f"IF {condition_scl} THEN"]
for core_line in grouped_instructions_core_scl: for core_line in grouped_instructions_cores:
scl_grouped.append(f" {core_line}") # Añadir indentación # 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;") scl_grouped.append("END_IF;")
final_grouped_scl = "\n".join(scl_grouped) 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 instruction["scl"] = final_grouped_scl
# Marcar los consumidores para que generate_scl los ignore # Marcar los consumidores
for consumer_uid_to_mark in consumer_uids_processed_in_group: for consumer_instr in consumer_instr_list:
for instr_to_mark in network_logic: consumer_instr["scl"] = f"{GROUPED_COMMENT} (by UID {instr_uid})"
if instr_to_mark["instruction_uid"] == consumer_uid_to_mark: consumer_instr["grouped"] = True
# Añadir comentario y flag
instr_to_mark["scl"] = f"{GROUPED_COMMENT} (by UID {instr_uid})"
instr_to_mark["grouped"] = True
break
made_change = True made_change = True
return made_change 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): def process_json_to_scl(json_filepath):
"""Lee el JSON, aplica los procesadores iterativamente y guarda el resultado.""" """Lee el JSON, aplica los procesadores iterativamente y guarda el resultado."""
if not os.path.exists(json_filepath): 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 return
print(f"Cargando JSON desde: {json_filepath}") print(f"Cargando JSON desde: {json_filepath}")
try: try:
with open(json_filepath, "r", encoding="utf-8") as f: with open(json_filepath, "r", encoding="utf-8") as f:
global data global data
data = json.load(f) data = json.load(f)
except Exception as e: except Exception as e:
print(f"Error al cargar o parsear JSON: {e}") print(f"Error al cargar JSON: {e}")
return return
# Reconstruir access_map dinámicamente
network_access_maps = {} 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", []): for network in data.get("networks", []):
net_id = network["id"] net_id = network["id"]
current_access_map = {} current_access_map = {}
@ -800,7 +743,7 @@ def process_json_to_scl(json_filepath):
max_passes = 25 max_passes = 25
passes = 0 passes = 0
# Lista de procesadores base + procesador de agrupación # Lista y mapa de procesadores base
base_processors = [ base_processors = [
process_convert, process_convert,
process_mod, process_mod,
@ -824,12 +767,11 @@ def process_json_to_scl(json_filepath):
print(f"\n--- Pase {passes} ---") print(f"\n--- Pase {passes} ---")
# --- FASE 1: Procesadores Base --- # --- 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", []): for network in data.get("networks", []):
network_id = network["id"] network_id = network["id"]
access_map = network_access_maps.get(network_id, {}) access_map = network_access_maps.get(network_id, {})
network_logic = network.get("logic", []) network_logic = network.get("logic", [])
for instruction in network_logic: for instruction in network_logic:
instr_type_original = instruction["type"] instr_type_original = instruction["type"]
if ( if (
@ -837,11 +779,9 @@ def process_json_to_scl(json_filepath):
or "_error" in instr_type_original or "_error" in instr_type_original
or instruction.get("grouped", False) or instruction.get("grouped", False)
): ):
continue # Saltar ya procesados, erróneos o agrupados continue
instr_type_lower_lookup = instr_type_original.lower() instr_type_lower_lookup = instr_type_original.lower()
func_to_call = processor_map.get(instr_type_lower_lookup) func_to_call = processor_map.get(instr_type_lower_lookup)
if func_to_call: if func_to_call:
try: try:
changed = False changed = False
@ -857,59 +797,49 @@ def process_json_to_scl(json_filepath):
changed = func_to_call( changed = func_to_call(
instruction, network_id, scl_map, access_map instruction, network_id, scl_map, access_map
) )
if changed: if changed:
# print(f"DEBUG: Cambio BASE detectado por {func_to_call.__name__} en UID {instruction['instruction_uid']}")
made_change_in_base_pass = True made_change_in_base_pass = True
except Exception as e: except Exception as e:
print( 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() traceback.print_exc()
instruction["scl"] = f"// ERROR during base processing: {e}" instruction["scl"] = f"// ERROR base: {e}"
instruction["type"] += "_error" 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 --- # --- 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", []): for network in data.get("networks", []):
network_id = network["id"] network_id = network["id"]
access_map = network_access_maps.get(network_id, {}) access_map = network_access_maps.get(network_id, {})
network_logic = network.get("logic", []) network_logic = network.get("logic", [])
for instruction in network_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( if instruction["type"].endswith("_scl") and not instruction.get(
"grouped", False "grouped", False
): ): # Solo en generadores procesados y no agrupados
try: try:
group_changed = process_group_ifs( group_changed = process_group_ifs(
instruction, network_id, scl_map, access_map instruction, network_id, scl_map, access_map
) )
if group_changed: if group_changed:
# print(f"DEBUG: Cambio GROUP detectado por process_group_ifs en UID {instruction['instruction_uid']}")
made_change_in_group_pass = True made_change_in_group_pass = True
except Exception as e: except Exception as e:
print( 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() 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: if not made_change_in_base_pass and not made_change_in_group_pass:
print( print(
f"\n--- No se hicieron cambios en el pase {passes}. Proceso completado. ---" f"\n--- No se hicieron cambios en el pase {passes}. Proceso completado. ---"
) )
break break
else: # else: print(f"DEBUG: Cambios Pase {passes}: Base={made_change_in_base_pass}, Grupo={made_change_in_group_pass}. Continuando...") # Debug
print(
f"DEBUG: Cambios en Pase {passes}: Base={made_change_in_base_pass}, Grupo={made_change_in_group_pass}. Continuando..."
)
if passes == max_passes: if passes == max_passes:
print( print(f"\n--- Límite de {max_passes} pases alcanzado. ---")
f"\n--- Límite de {max_passes} pases alcanzado. Puede haber dependencias circulares o lógica no procesada. ---"
)
# --- Guardar JSON Final --- # --- Guardar JSON Final ---
output_filename = json_filepath.replace(".json", "_scl_processed.json") 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) json.dump(data, f, indent=4, ensure_ascii=False)
print("Guardado completado.") print("Guardado completado.")
except Exception as e: except Exception as e:
print(f"Error al guardar el JSON procesado: {e}") print(f"Error al guardar JSON: {e}")
# --- Ejecución --- # --- Ejecución ---
if __name__ == "__main__": 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) process_json_to_scl(input_json_file)