diff options
author | Tristan Gingold <tgingold@free.fr> | 2023-01-12 18:16:36 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2023-01-12 18:16:36 +0100 |
commit | 00607141b93dbbd38f83c2faeb88db80df1a7739 (patch) | |
tree | 96d48699c3b2db120a8f974b4c1114d00af739f6 | |
parent | e86c5c060f4abd4fc978345e8253df524338f5df (diff) | |
download | ghdl-00607141b93dbbd38f83c2faeb88db80df1a7739.tar.gz ghdl-00607141b93dbbd38f83c2faeb88db80df1a7739.tar.bz2 ghdl-00607141b93dbbd38f83c2faeb88db80df1a7739.zip |
synth: improve handling of 2008 aggregates
-rw-r--r-- | src/synth/synth-vhdl_aggr.adb | 169 |
1 files changed, 142 insertions, 27 deletions
diff --git a/src/synth/synth-vhdl_aggr.adb b/src/synth/synth-vhdl_aggr.adb index 533dedf05..650510e0e 100644 --- a/src/synth/synth-vhdl_aggr.adb +++ b/src/synth/synth-vhdl_aggr.adb @@ -24,6 +24,7 @@ with Netlists.Utils; use Netlists.Utils; with Netlists.Builders; use Netlists.Builders; with Vhdl.Utils; use Vhdl.Utils; +with Vhdl.Nodes_Utils; with Elab.Memtype; use Elab.Memtype; with Elab.Vhdl_Types; use Elab.Vhdl_Types; @@ -114,6 +115,7 @@ package body Synth.Vhdl_Aggr is end case; end Fill_Stride; + -- VEC1_P is true iff RES(1) is a vector (and not an element). procedure Fill_Array_Aggregate (Syn_Inst : Synth_Instance_Acc; Aggr : Node; Res : Valtyp_Array_Acc; @@ -122,7 +124,8 @@ package body Synth.Vhdl_Aggr is Strides : Stride_Array; Dim : Dim_Type; Const_P : out Boolean; - Err_P : out boolean) + Err_P : out Boolean; + Vec1_P : out Boolean) is Bound : constant Bound_Type := Get_Array_Bound (Typ); El_Typ : constant Type_Acc := Get_Array_Element (Typ); @@ -153,6 +156,7 @@ package body Synth.Vhdl_Aggr is is Sub_Const : Boolean; Sub_Err : Boolean; + Sub_Vec1 : Boolean; Val : Valtyp; begin Nbr_Els := Nbr_Els + 1; @@ -165,9 +169,10 @@ package body Synth.Vhdl_Aggr is else Fill_Array_Aggregate (Syn_Inst, Value, Res, El_Typ, Pos, Strides, Dim + 1, - Sub_Const, Sub_Err); + Sub_Const, Sub_Err, Sub_Vec1); Const_P := Const_P and Sub_Const; Err_P := Err_P or Sub_Err; + Vec1_P := Vec1_P or Sub_Vec1; end if; end Set_Elem; @@ -190,6 +195,9 @@ package body Synth.Vhdl_Aggr is if Const_P and then not Is_Static (Val.Val) then Const_P := False; end if; + if Pos = 1 then + Vec1_P := True; + end if; end Set_Vector; Pos : Nat32; @@ -198,6 +206,7 @@ package body Synth.Vhdl_Aggr is Nbr_Els := 0; Const_P := True; Err_P := False; + Vec1_P := False; if Get_Kind (Aggr) = Iir_Kind_String_Literal8 then declare @@ -454,6 +463,35 @@ package body Synth.Vhdl_Aggr is return Res; end Valtyp_Array_To_Net; + function Valtyp_Array_To_Valtyp (Ctxt : Context_Acc; + Tab_Res : Valtyp_Array; + Res_Typ : Type_Acc; + Const_P : Boolean) return Valtyp + is + Res : Valtyp; + begin + if Const_P then + declare + Off : Size_Type; + begin + Res := Create_Value_Memory (Res_Typ, Current_Pool); + Off := 0; + for I in Tab_Res'Range loop + if Tab_Res (I).Val /= null then + -- There can be holes due to sub-arrays. + Write_Value (Res.Val.Mem + Off, Tab_Res (I)); + Off := Off + Tab_Res (I).Typ.Sz; + end if; + end loop; + pragma Assert (Off = Res_Typ.Sz); + end; + else + Res := Create_Value_Net + (Valtyp_Array_To_Net (Ctxt, Tab_Res), Res_Typ); + end if; + return Res; + end Valtyp_Array_To_Valtyp; + function Synth_Aggregate_Array (Syn_Inst : Synth_Instance_Acc; Aggr : Node; Aggr_Typ : Type_Acc) return Valtyp @@ -464,57 +502,132 @@ package body Synth.Vhdl_Aggr is Tab_Res : Valtyp_Array_Acc; Const_P : Boolean; Err_P : Boolean; + Vec1_P : Boolean; Res_Typ : Type_Acc; + El_Typ : Type_Acc; Res : Valtyp; begin Tab_Res := new Valtyp_Array(1 .. Nat32 (Flen)); Tab_Res.all := (others => No_Valtyp); Fill_Array_Aggregate (Syn_Inst, Aggr, Tab_Res, - Aggr_Typ, 1, Strides, 1, Const_P, Err_P); + Aggr_Typ, 1, Strides, 1, Const_P, Err_P, Vec1_P); if Err_P then return No_Valtyp; end if; - case Type_Vectors_Arrays (Aggr_Typ.Kind) is when Type_Array | Type_Vector => Res_Typ := Aggr_Typ; when Type_Array_Unbounded => -- TODO: check all element types have the same bounds ? - Res_Typ := Create_Array_From_Array_Unbounded - (Aggr_Typ, Tab_Res (1).Typ); + if Flen = 0 then + -- No bounds for the elements... + Res_Typ := Create_Array_From_Array_Unbounded + (Aggr_Typ, Aggr_Typ.Arr_El); + else + -- Humm, is it a vector or an element ? + El_Typ := Tab_Res (1).Typ; + if Vec1_P then + El_Typ := El_Typ.Arr_El; + end if; + Res_Typ := Create_Array_From_Array_Unbounded (Aggr_Typ, El_Typ); + end if; when Type_Unbounded_Vector | Type_Unbounded_Array => raise Internal_Error; end case; - if Const_P then - declare - Off : Size_Type; - begin - Res := Create_Value_Memory (Res_Typ, Current_Pool); - Off := 0; - for I in Tab_Res'Range loop - if Tab_Res (I).Val /= null then - -- There can be holes due to sub-arrays. - Write_Value (Res.Val.Mem + Off, Tab_Res (I)); - Off := Off + Tab_Res (I).Typ.Sz; - end if; - end loop; - pragma Assert (Off = Res_Typ.Sz); - end; - else - Res := Create_Value_Net - (Valtyp_Array_To_Net (Ctxt, Tab_Res.all), Res_Typ); - end if; + Res := Valtyp_Array_To_Valtyp (Ctxt, Tab_Res.all, Res_Typ, Const_P); Free_Valtyp_Array (Tab_Res); return Res; end Synth_Aggregate_Array; + function Synth_Aggregate_Array_Concat (Syn_Inst : Synth_Instance_Acc; + Aggr : Node; + Aggr_Typ : Type_Acc) return Valtyp + is + Ctxt : constant Context_Acc := Get_Build (Syn_Inst); + Assoc_Chain : constant Node := Get_Association_Choices_Chain (Aggr); + Flen : constant Natural := + Vhdl.Nodes_Utils.Get_Chain_Length (Assoc_Chain); + El_Typ : constant Type_Acc := Aggr_Typ.Uarr_El; + Assoc : Node; + Value : Node; + Val : Valtyp; + Len : Uns32; + Tab_Res : Valtyp_Array_Acc; + Const_P : Boolean; + Err_P : Boolean; + Res_Typ : Type_Acc; + Res : Valtyp; + Pos : Nat32; + Bnd: Bound_Type; + begin + Tab_Res := new Valtyp_Array(1 .. Nat32 (Flen)); + Tab_Res.all := (others => No_Valtyp); + + Len := 0; + Pos := Tab_Res'First; + Const_P := True; + Assoc := Assoc_Chain; + while Is_Valid (Assoc) loop + -- If there is a choice expression/range, then the array is + -- bounded. + pragma Assert (Get_Kind (Assoc) = Iir_Kind_Choice_By_None); + Value := Get_Associated_Expr (Assoc); + if Get_Element_Type_Flag (Assoc) then + Val := Synth_Expression_With_Type (Syn_Inst, Value, El_Typ); + Val := Synth_Subtype_Conversion + (Syn_Inst, Val, El_Typ, False, Value); + Len := Len + 1; + else + Val := Synth_Expression_With_Basetype (Syn_Inst, Value); + if Val.Typ /= null then + Len := Len + Get_Bound_Length (Val.Typ); + end if; + end if; + + Tab_Res (Pos) := Val; + Pos := Pos + 1; + + if Val = No_Valtyp then + Err_P := True; + else + if Const_P and then not Is_Static (Val.Val) then + Const_P := False; + end if; + end if; + + Assoc := Get_Chain (Assoc); + end loop; + + if Err_P then + return No_Valtyp; + end if; + + -- Create the result type. + Bnd := Create_Bounds_From_Length + (Aggr_Typ.Uarr_Idx.Drange, Iir_Index32 (Len)); + case Aggr_Typ.Kind is + when Type_Unbounded_Vector => + Res_Typ := Create_Vector_Type (Bnd, El_Typ); + when Type_Unbounded_Array => + Res_Typ := Create_Array_Type (Bnd, True, El_Typ); + when others => + raise Internal_Error; + end case; + + Res := Valtyp_Array_To_Valtyp (Ctxt, Tab_Res.all, Res_Typ, Const_P); + + Free_Valtyp_Array (Tab_Res); + + return Res; + end Synth_Aggregate_Array_Concat; + function Synth_Aggregate_Record (Syn_Inst : Synth_Instance_Acc; Aggr : Node; Aggr_Type : Type_Acc) return Valtyp @@ -580,7 +693,8 @@ package body Synth.Vhdl_Aggr is begin case Aggr_Type.Kind is when Type_Unbounded_Array - | Type_Unbounded_Vector => + | Type_Unbounded_Vector + | Type_Array_Unbounded => declare Res_Type : Type_Acc; begin @@ -595,7 +709,8 @@ package body Synth.Vhdl_Aggr is | Type_Unbounded_Array => -- The only possibility is vector elements. pragma Assert (Res_Type.Ulast); - raise Internal_Error; + return Synth_Aggregate_Array_Concat (Syn_Inst, Aggr, + Res_Type); when others => raise Internal_Error; end case; |