1-- Analysis for translation. 2-- Copyright (C) 2009 Tristan Gingold 3-- 4-- This program is free software: you can redistribute it and/or modify 5-- it under the terms of the GNU General Public License as published by 6-- the Free Software Foundation, either version 2 of the License, or 7-- (at your option) any later version. 8-- 9-- This program is distributed in the hope that it will be useful, 10-- but WITHOUT ANY WARRANTY; without even the implied warranty of 11-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12-- GNU General Public License for more details. 13-- 14-- You should have received a copy of the GNU General Public License 15-- along with this program. If not, see <gnu.org/licenses>. 16 17with Errorout; 18with Simple_IO; 19with Vhdl.Utils; use Vhdl.Utils; 20with Vhdl.Nodes_Walk; use Vhdl.Nodes_Walk; 21with Vhdl.Prints; 22with Vhdl.Errors; use Vhdl.Errors; 23 24package body Trans_Analyzes is 25 Driver_List : Iir_List; 26 27 Has_After : Boolean; 28 29 function Extract_Driver_Target (Target : Iir) return Walk_Status 30 is 31 Base : Iir; 32 Prefix : Iir; 33 begin 34 Base := Get_Object_Prefix (Target); 35 -- Assigment to subprogram interface does not create a driver. 36 if Get_Kind (Base) = Iir_Kind_Interface_Signal_Declaration 37 and then Is_Parameter (Base) 38 then 39 return Walk_Continue; 40 end if; 41 42 Prefix := Get_Longuest_Static_Prefix (Target); 43 Add_Element (Driver_List, Prefix); 44 if Has_After then 45 Set_After_Drivers_Flag (Base, True); 46 end if; 47 return Walk_Continue; 48 end Extract_Driver_Target; 49 50 -- Set Has_After to True iff WF requires a non-direct driver. 51 procedure Extract_Has_After (Wf : Iir) is 52 begin 53 -- Disconnect, or time expression. 54 if Wf = Null_Iir 55 or else Get_Chain (Wf) /= Null_Iir 56 or else Get_Time (Wf) /= Null_Iir 57 or else Get_Kind (Get_We_Value (Wf)) = Iir_Kind_Null_Literal 58 then 59 Has_After := True; 60 end if; 61 end Extract_Has_After; 62 63 function Extract_Driver_Stmt (Stmt : Iir) return Walk_Status 64 is 65 Status : Walk_Status; 66 pragma Unreferenced (Status); 67 begin 68 -- Clear Has_After. It will be set to True if a signal assignment 69 -- has an delay expression or a null transaction. 70 -- (It is cleared for any statement, just to factorize code). 71 Has_After := False; 72 73 case Iir_Kinds_Sequential_Statement (Get_Kind (Stmt)) is 74 when Iir_Kind_Simple_Signal_Assignment_Statement => 75 declare 76 Wf : constant Iir := Get_Waveform_Chain (Stmt); 77 begin 78 if Is_Null (Wf) 79 or else Get_Kind (Wf) /= Iir_Kind_Unaffected_Waveform 80 then 81 -- Not unaffected or implicit disconnect. 82 Extract_Has_After (Wf); 83 Status := Walk_Assignment_Target 84 (Get_Target (Stmt), Extract_Driver_Target'Access); 85 end if; 86 end; 87 when Iir_Kind_Signal_Force_Assignment_Statement 88 | Iir_Kind_Signal_Release_Assignment_Statement => 89 null; 90 when Iir_Kind_Conditional_Signal_Assignment_Statement => 91 declare 92 Cond_Wf : Iir; 93 Wf : Iir; 94 Has_Drv : Boolean; 95 begin 96 Cond_Wf := Get_Conditional_Waveform_Chain (Stmt); 97 Has_Drv := False; 98 while Cond_Wf /= Null_Iir loop 99 Wf := Get_Waveform_Chain (Cond_Wf); 100 if Get_Kind (Wf) /= Iir_Kind_Unaffected_Waveform then 101 -- Not unaffected 102 Extract_Has_After (Wf); 103 Has_Drv := True; 104 end if; 105 Cond_Wf := Get_Chain (Cond_Wf); 106 end loop; 107 if Has_Drv then 108 Status := Walk_Assignment_Target 109 (Get_Target (Stmt), Extract_Driver_Target'Access); 110 end if; 111 end; 112 when Iir_Kind_Selected_Waveform_Assignment_Statement => 113 declare 114 Swf : Iir; 115 Wf : Iir; 116 Has_Drv : Boolean; 117 begin 118 Swf := Get_Selected_Waveform_Chain (Stmt); 119 Has_Drv := False; 120 while Swf /= Null_Iir loop 121 if not Get_Same_Alternative_Flag (Swf) then 122 Wf := Get_Associated_Chain (Swf); 123 if Get_Kind (Wf) /= Iir_Kind_Unaffected_Waveform then 124 -- Not unaffected 125 Extract_Has_After (Wf); 126 Has_Drv := True; 127 end if; 128 end if; 129 Swf := Get_Chain (Swf); 130 end loop; 131 if Has_Drv then 132 Status := Walk_Assignment_Target 133 (Get_Target (Stmt), Extract_Driver_Target'Access); 134 end if; 135 end; 136 when Iir_Kind_Procedure_Call_Statement => 137 declare 138 Call : constant Iir := Get_Procedure_Call (Stmt); 139 Assoc : Iir; 140 Formal : Iir; 141 Inter : Iir; 142 begin 143 -- Very pessimist. 144 Has_After := True; 145 146 Assoc := Get_Parameter_Association_Chain (Call); 147 Inter := Get_Interface_Declaration_Chain 148 (Get_Implementation (Call)); 149 while Assoc /= Null_Iir loop 150 Formal := Get_Association_Interface (Assoc, Inter); 151 if Get_Kind (Assoc) 152 = Iir_Kind_Association_Element_By_Expression 153 and then 154 Get_Kind (Formal) = Iir_Kind_Interface_Signal_Declaration 155 and then Get_Mode (Formal) /= Iir_In_Mode 156 then 157 Status := Extract_Driver_Target (Get_Actual (Assoc)); 158 end if; 159 Next_Association_Interface (Assoc, Inter); 160 end loop; 161 end; 162 when Iir_Kind_Null_Statement 163 | Iir_Kind_Assertion_Statement 164 | Iir_Kind_Report_Statement 165 | Iir_Kind_Wait_Statement 166 | Iir_Kind_Return_Statement 167 | Iir_Kind_Next_Statement 168 | Iir_Kind_Exit_Statement 169 | Iir_Kind_Variable_Assignment_Statement 170 | Iir_Kind_Conditional_Variable_Assignment_Statement 171 | Iir_Kind_For_Loop_Statement 172 | Iir_Kind_While_Loop_Statement 173 | Iir_Kind_Case_Statement 174 | Iir_Kind_If_Statement 175 | Iir_Kind_Break_Statement => 176 null; 177 end case; 178 return Walk_Continue; 179 end Extract_Driver_Stmt; 180 181 procedure Extract_Drivers_Sequential_Stmt_Chain (Chain : Iir) 182 is 183 Status : Walk_Status; 184 pragma Unreferenced (Status); 185 begin 186 Status := Walk_Sequential_Stmt_Chain (Chain, Extract_Driver_Stmt'Access); 187 end Extract_Drivers_Sequential_Stmt_Chain; 188 189 procedure Extract_Drivers_Declaration_Chain (Chain : Iir) 190 is 191 Decl : Iir := Chain; 192 begin 193 while Decl /= Null_Iir loop 194 195 -- Only procedures and impure functions may contain assignment. 196 if Get_Kind (Decl) = Iir_Kind_Procedure_Body 197 or else (Get_Kind (Decl) = Iir_Kind_Function_Body 198 and then 199 not Get_Pure_Flag (Get_Subprogram_Specification (Decl))) 200 then 201 Extract_Drivers_Declaration_Chain (Get_Declaration_Chain (Decl)); 202 Extract_Drivers_Sequential_Stmt_Chain 203 (Get_Sequential_Statement_Chain (Decl)); 204 end if; 205 206 Decl := Get_Chain (Decl); 207 end loop; 208 end Extract_Drivers_Declaration_Chain; 209 210 function Extract_Drivers (Proc : Iir) return Iir_List 211 is 212 begin 213 Driver_List := Create_Iir_List; 214 Extract_Drivers_Declaration_Chain (Get_Declaration_Chain (Proc)); 215 Extract_Drivers_Sequential_Stmt_Chain 216 (Get_Sequential_Statement_Chain (Proc)); 217 218 return Driver_List; 219 end Extract_Drivers; 220 221 procedure Free_Drivers_List (List : in out Iir_List) 222 is 223 It : List_Iterator; 224 begin 225 It := List_Iterate (List); 226 while Is_Valid (It) loop 227 Set_After_Drivers_Flag (Get_Object_Prefix (Get_Element (It)), False); 228 Next (It); 229 end loop; 230 Destroy_Iir_List (List); 231 end Free_Drivers_List; 232 233 procedure Dump_Drivers (Proc : Iir; List : Iir_List) 234 is 235 use Simple_IO; 236 use Errorout; 237 El : Iir; 238 It : List_Iterator; 239 begin 240 Report_Msg (Msgid_Note, Semantic, +Proc, 241 "List of drivers for %n:", (1 => +Proc)); 242 Report_Msg (Msgid_Note, Semantic, +Proc, 243 " (declared at %l)", (1 => +Proc)); 244 It := List_Iterate (List); 245 while Is_Valid (It) loop 246 El := Get_Element (It); 247 if Get_After_Drivers_Flag (Get_Object_Prefix (El)) then 248 Put ("* "); 249 else 250 Put (" "); 251 end if; 252 Vhdl.Prints.Disp_Vhdl (El); 253 New_Line; 254 Next (It); 255 end loop; 256 end Dump_Drivers; 257 258end Trans_Analyzes; 259