diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vhdl/evaluation.adb | 131 | ||||
-rw-r--r-- | src/vhdl/evaluation.ads | 7 | ||||
-rw-r--r-- | src/vhdl/translate/trans-chap7.adb | 136 |
3 files changed, 226 insertions, 48 deletions
diff --git a/src/vhdl/evaluation.adb b/src/vhdl/evaluation.adb index 7cc3608eb..72c5a9152 100644 --- a/src/vhdl/evaluation.adb +++ b/src/vhdl/evaluation.adb @@ -2392,6 +2392,7 @@ package body Evaluation is El : Iir; begin Idx := Eval_Static_Expr (Get_Nth_Element (Indexes, 0)); + Set_Nth_Element (Indexes, 0, Idx); Pos := Eval_Pos_In_Range (Index_Range, Idx); El := Get_Nth_Element (Get_Simple_Aggregate_List (Aggr), Natural (Pos)); @@ -2442,9 +2443,137 @@ package body Evaluation is when others => Error_Kind ("eval_indexed_name", Prefix); end case; - return Null_Iir; end Eval_Indexed_Name; + function Eval_Indexed_Aggregate_By_Offset + (Aggr : Iir; Off : Iir_Index32; Dim : Natural := 0) return Iir + is + Prefix_Type : constant Iir := Get_Type (Aggr); + Indexes_Type : constant Iir_Flist := + Get_Index_Subtype_List (Prefix_Type); + Assoc : Iir; + Assoc_Expr : Iir; + Assoc_Len : Iir_Index32; + Aggr_Bounds : Iir; + Cur_Off : Iir_Index32; + Res : Iir; + Left_Pos : Iir_Int64; + Assoc_Pos : Iir_Int64; + begin + Aggr_Bounds := Eval_Static_Range (Get_Nth_Element (Indexes_Type, Dim)); + Left_Pos := Eval_Pos (Eval_Discrete_Range_Left (Aggr_Bounds)); + + Cur_Off := 0; + Assoc := Get_Association_Choices_Chain (Aggr); + Assoc_Expr := Null_Iir; + while Assoc /= Null_Iir loop + if not Get_Same_Alternative_Flag (Assoc) then + Assoc_Expr := Assoc; + end if; + case Get_Kind (Assoc) is + when Iir_Kind_Choice_By_None => + if Get_Element_Type_Flag (Assoc) then + if Off = Cur_Off then + return Get_Associated_Expr (Assoc); + end if; + Assoc_Len := 1; + else + Res := Get_Associated_Expr (Assoc); + Assoc_Len := Iir_Index32 + (Eval_Discrete_Range_Length + (Get_Index_Type (Get_Type (Res), 0))); + if Off >= Cur_Off and then Off < Cur_Off + Assoc_Len then + return Eval_Indexed_Name_By_Offset (Res, Off - Cur_Off); + end if; + end if; + Cur_Off := Cur_Off + Assoc_Len; + when Iir_Kind_Choice_By_Expression => + Assoc_Pos := Eval_Pos (Get_Choice_Expression (Assoc)); + case Get_Direction (Aggr_Bounds) is + when Iir_To => + Cur_Off := Iir_Index32 (Assoc_Pos - Left_Pos); + when Iir_Downto => + Cur_Off := Iir_Index32 (Left_Pos - Assoc_Pos); + end case; + if Cur_Off = Off then + return Get_Associated_Expr (Assoc); + end if; + when Iir_Kind_Choice_By_Range => + declare + Rng : Iir; + Left : Iir_Int64; + Right : Iir_Int64; + Hi, Lo : Iir_Int64; + Lo_Off, Hi_Off : Iir_Index32; + begin + Rng := Eval_Range (Get_Choice_Range (Assoc)); + Set_Choice_Range (Assoc, Rng); + + Left := Eval_Pos (Get_Left_Limit (Rng)); + Right := Eval_Pos (Get_Right_Limit (Rng)); + case Get_Direction (Rng) is + when Iir_To => + Lo := Left; + Hi := Right; + when Iir_Downto => + Lo := Right; + Hi := Left; + end case; + case Get_Direction (Aggr_Bounds) is + when Iir_To => + Lo_Off := Iir_Index32 (Lo - Left_Pos); + Hi_Off := Iir_Index32 (Hi - Left_Pos); + when Iir_Downto => + Lo_Off := Iir_Index32 (Left_Pos - Lo); + Hi_Off := Iir_Index32 (Left_Pos - Hi); + end case; + if Off >= Lo_Off and then Off <= Hi_Off then + Res := Get_Associated_Expr (Assoc); + if Get_Element_Type_Flag (Assoc) then + return Res; + else + return Eval_Indexed_Name_By_Offset + (Res, Off - Lo_Off); + end if; + end if; + end; + when Iir_Kind_Choice_By_Others => + return Get_Associated_Expr (Assoc_Expr); + when others => + raise Internal_Error; + end case; + Assoc := Get_Chain (Assoc); + end loop; + raise Internal_Error; + end Eval_Indexed_Aggregate_By_Offset; + + function Eval_Indexed_Name_By_Offset (Prefix : Iir; Off : Iir_Index32) + return Iir + is + begin + case Get_Kind (Prefix) is + when Iir_Kind_Aggregate => + return Eval_Indexed_Aggregate_By_Offset (Prefix, Off); + when Iir_Kind_String_Literal8 => + declare + Id : constant String8_Id := Get_String8_Id (Prefix); + El_Type : constant Iir := + Get_Element_Subtype (Get_Type (Prefix)); + Enums : constant Iir_Flist := + Get_Enumeration_Literal_List (El_Type); + Lit : Pos32; + begin + Lit := Str_Table.Element_String8 (Id, Int32 (Off + 1)); + return Get_Nth_Element (Enums, Natural (Lit)); + end; + when Iir_Kind_Simple_Aggregate => + return Get_Nth_Element (Get_Simple_Aggregate_List (Prefix), + Natural (Off)); + when others => + Error_Kind ("eval_indexed_name_by_offset", Prefix); + end case; + end Eval_Indexed_Name_By_Offset; + function Eval_Static_Expr (Expr: Iir) return Iir is Res : Iir; diff --git a/src/vhdl/evaluation.ads b/src/vhdl/evaluation.ads index 05feac652..09975cd6a 100644 --- a/src/vhdl/evaluation.ads +++ b/src/vhdl/evaluation.ads @@ -166,6 +166,13 @@ package Evaluation is function Eval_Value_Attribute (Value : String; Atype : Iir; Orig : Iir) return Iir; + -- From one-dimensional array expression PREFIX extract element at + -- offset OFF (from 0 to length - 1). Note that the element is directly + -- returned, not a copy of it (so it should be referenced if stored in + -- the tree). + function Eval_Indexed_Name_By_Offset (Prefix : Iir; Off : Iir_Index32) + return Iir; + -- Return the simple name, character literal or operator sumbol of ID, -- using the same format as SIMPLE_NAME attribute. function Eval_Simple_Name (Id : Name_Id) return String; diff --git a/src/vhdl/translate/trans-chap7.adb b/src/vhdl/translate/trans-chap7.adb index e8034ffda..64cb3ec58 100644 --- a/src/vhdl/translate/trans-chap7.adb +++ b/src/vhdl/translate/trans-chap7.adb @@ -212,12 +212,36 @@ package body Trans.Chap7 is Build_Array_Choices_Vector (Vect, Index_Range, Assocs); if Dim = Nbr_Dims then - for I in Vect'Range loop - New_Array_Aggr_El - (List, - Translate_Static_Expression - (Get_Associated_Expr (Vect (I)), El_Type)); - end loop; + declare + Idx : Natural; + Assoc : Iir; + Expr : Iir; + El : Iir; + Assoc_Len : Iir_Index32; + begin + Idx := 0; + while Idx < Natural (Len) loop + Assoc := Vect (Idx); + Expr := Get_Associated_Expr (Assoc); + if Get_Element_Type_Flag (Assoc) then + New_Array_Aggr_El + (List, + Translate_Static_Expression (Expr, El_Type)); + Idx := Idx + 1; + else + Assoc_Len := Iir_Index32 + (Eval_Discrete_Range_Length + (Get_Choice_Range (Assoc))); + for I in 0 .. Assoc_Len - 1 loop + El := Eval_Indexed_Name_By_Offset (Expr, I); + New_Array_Aggr_El + (List, + Translate_Static_Expression (El, El_Type)); + Idx := Idx + 1; + end loop; + end if; + end loop; + end; else for I in Vect'Range loop Translate_Static_Array_Aggregate_1 @@ -2928,13 +2952,12 @@ package body Trans.Chap7 is Close_Temp; end Translate_Array_Aggregate_Gen_String; - procedure Translate_Array_Aggregate_Gen - (Base_Ptr : Mnode; - Bounds_Ptr : Mnode; - Aggr : Iir; - Aggr_Type : Iir; - Dim : Natural; - Var_Index : O_Dnode) + procedure Translate_Array_Aggregate_Gen (Base_Ptr : Mnode; + Bounds_Ptr : Mnode; + Aggr : Iir; + Aggr_Type : Iir; + Dim : Natural; + Var_Index : O_Dnode) is Index_List : Iir_Flist; Expr_Type : Iir; @@ -2942,16 +2965,16 @@ package body Trans.Chap7 is -- Assign EXPR to current position (defined by index VAR_INDEX), and -- update VAR_INDEX. Handles sub-aggregates. - procedure Do_Assign (Assoc : Iir; Expr : Iir) + procedure Do_Assign (Assoc : Iir; Expr : Iir; Assoc_Len : out Iir_Int64) is Dest : Mnode; - Len : Iir_Int64; begin if Final then if Get_Element_Type_Flag (Assoc) then Dest := Chap3.Index_Base (Base_Ptr, Aggr_Type, New_Obj_Value (Var_Index)); Translate_Assign (Dest, Expr, Expr_Type); + Assoc_Len := 1; Inc_Var (Var_Index); else Dest := Chap3.Slice_Base (Base_Ptr, Aggr_Type, @@ -2959,17 +2982,19 @@ package body Trans.Chap7 is Translate_Assign (Dest, Expr, Get_Type (Expr)); -- FIXME: handle non-static expression type (at least for -- choice by range). - Len := Eval_Discrete_Type_Length + Assoc_Len := Eval_Discrete_Type_Length (Get_Index_Type (Get_Type (Expr), 0)); New_Assign_Stmt (New_Obj (Var_Index), - New_Dyadic_Op (ON_Add_Ov, - New_Obj_Value (Var_Index), - New_Lit (New_Index_Lit (Unsigned_64 (Len))))); + New_Dyadic_Op + (ON_Add_Ov, + New_Obj_Value (Var_Index), + New_Lit (New_Index_Lit (Unsigned_64 (Assoc_Len))))); end if; else Translate_Array_Aggregate_Gen (Base_Ptr, Bounds_Ptr, Expr, Aggr_Type, Dim + 1, Var_Index); + Assoc_Len := 1; end if; end Do_Assign; @@ -2977,6 +3002,7 @@ package body Trans.Chap7 is is P : Natural; El : Iir; + Assoc_Len : Iir_Int64; begin -- First, assign positionnal association. -- FIXME: count the number of positionnal association and generate @@ -2987,14 +3013,8 @@ package body Trans.Chap7 is loop exit when El = Null_Iir; exit when Get_Kind (El) /= Iir_Kind_Choice_By_None; - Do_Assign (El, Get_Associated_Expr (El)); - if not Final or else Get_Element_Type_Flag (El) then - P := P + 1; - else - P := P + Natural - (Eval_Discrete_Type_Length - (Get_Index_Type (Get_Type (Get_Associated_Expr (El)), 0))); - end if; + Do_Assign (El, Get_Associated_Expr (El), Assoc_Len); + P := P + Natural (Assoc_Len); El := Get_Chain (El); end loop; @@ -3035,7 +3055,8 @@ package body Trans.Chap7 is New_Lit (Ghdl_Index_0), Ghdl_Bool_Type)); - Do_Assign (El, Get_Associated_Expr (El)); + Do_Assign (El, Get_Associated_Expr (El), Assoc_Len); + pragma Assert (Assoc_Len = 1); Dec_Var (Var_Len); Finish_Loop_Stmt (Label); Close_Temp; @@ -3045,6 +3066,7 @@ package body Trans.Chap7 is procedure Translate_Array_Aggregate_Gen_Named is El : Iir; + Assoc_Len : Iir_Int64; begin El := Get_Association_Choices_Chain (Aggr); @@ -3057,9 +3079,11 @@ package body Trans.Chap7 is -- Handled by positional. raise Internal_Error; when Iir_Kind_Choice_By_Expression => - Do_Assign (El, Get_Associated_Expr (El)); + Do_Assign (El, Get_Associated_Expr (El), Assoc_Len); return; when Iir_Kind_Choice_By_Range => + -- FIXME: todo. + pragma Assert (Get_Element_Type_Flag (El)); declare Var_Length : O_Dnode; Var_I : O_Dnode; @@ -3077,7 +3101,7 @@ package body Trans.Chap7 is New_Obj_Value (Var_I), New_Obj_Value (Var_Length), Ghdl_Bool_Type)); - Do_Assign (El, Get_Associated_Expr (El)); + Do_Assign (El, Get_Associated_Expr (El), Assoc_Len); Inc_Var (Var_I); Finish_Loop_Stmt (Label); Close_Temp; @@ -3090,11 +3114,13 @@ package body Trans.Chap7 is -- Several choices.. declare - Range_Type : Iir; + Range_Type : constant Iir := + Get_Base_Type (Get_Index_Type (Index_List, Dim - 1)); + Rtinfo : constant Type_Info_Acc := Get_Info (Range_Type); Var_Pos : O_Dnode; Var_Len : O_Dnode; + Var_Alen : O_Dnode; Range_Ptr : Mnode; - Rtinfo : Type_Info_Acc; If_Blk : O_If_Block; Case_Blk : O_Case_Block; Label : O_Snode; @@ -3104,27 +3130,26 @@ package body Trans.Chap7 is Open_Temp; -- Create a loop from left +- number of positionnals associations -- to/downto right. - Range_Type := Get_Base_Type (Get_Index_Type (Index_List, Dim - 1)); - Rtinfo := Get_Info (Range_Type); Var_Pos := Create_Temp (Rtinfo.Ortho_Type (Mode_Value)); Range_Ptr := Stabilize (Chap3.Bounds_To_Range (Bounds_Ptr, Aggr_Type, Dim)); New_Assign_Stmt (New_Obj (Var_Pos), M2E (Chap3.Range_To_Left (Range_Ptr))); - Var_Len := Create_Temp (Ghdl_Index_Type); + Var_Len := Create_Temp (Ghdl_Index_Type); Len_Tmp := M2E (Chap3.Range_To_Length (Range_Ptr)); New_Assign_Stmt (New_Obj (Var_Len), Len_Tmp); + Var_Alen := Create_Temp (Ghdl_Index_Type); + -- Start loop. Start_Loop_Stmt (Label); -- Check if end of loop. - Gen_Exit_When - (Label, - New_Compare_Op (ON_Eq, - New_Obj_Value (Var_Len), - New_Lit (Ghdl_Index_0), - Ghdl_Bool_Type)); + Gen_Exit_When (Label, + New_Compare_Op (ON_Eq, + New_Obj_Value (Var_Len), + New_Lit (Ghdl_Index_0), + Ghdl_Bool_Type)); -- convert aggr into a case statement. Start_Case_Stmt (Case_Blk, New_Obj_Value (Var_Pos)); @@ -3138,7 +3163,10 @@ package body Trans.Chap7 is if not Get_Same_Alternative_Flag (El) then Expr := Get_Associated_Expr (El); end if; - Do_Assign (El, Expr); + Do_Assign (El, Expr, Assoc_Len); + New_Assign_Stmt + (New_Obj (Var_Alen), + New_Lit (New_Index_Lit (Unsigned_64 (Assoc_Len)))); El := Get_Chain (El); end loop; Finish_Case_Stmt (Case_Blk); @@ -3149,13 +3177,27 @@ package body Trans.Chap7 is M2E (Chap3.Range_To_Dir (Range_Ptr)), New_Lit (Ghdl_Dir_To_Node), Ghdl_Bool_Type)); - Chap8.Gen_Update_Iterator (Var_Pos, Iir_To, Unsigned_64 (1), - Range_Type); + New_Assign_Stmt + (New_Obj (Var_Pos), + New_Dyadic_Op + (ON_Add_Ov, + New_Obj_Value (Var_Pos), + New_Convert_Ov (New_Obj_Value (Var_Alen), + Rtinfo.Ortho_Type (Mode_Value)))); New_Else_Stmt (If_Blk); - Chap8.Gen_Update_Iterator (Var_Pos, Iir_Downto, Unsigned_64 (1), - Range_Type); + New_Assign_Stmt + (New_Obj (Var_Pos), + New_Dyadic_Op + (ON_Sub_Ov, + New_Obj_Value (Var_Pos), + New_Convert_Ov (New_Obj_Value (Var_Alen), + Rtinfo.Ortho_Type (Mode_Value)))); Finish_If_Stmt (If_Blk); - Dec_Var (Var_Len); + -- Update var_len. + New_Assign_Stmt (New_Obj (Var_Len), + New_Dyadic_Op (ON_Sub_Ov, + New_Obj_Value (Var_Len), + New_Obj_Value (Var_Alen))); Finish_Loop_Stmt (Label); Close_Temp; end; |