diff options
Diffstat (limited to 'src/synth/synth-expr.adb')
-rw-r--r-- | src/synth/synth-expr.adb | 100 |
1 files changed, 73 insertions, 27 deletions
diff --git a/src/synth/synth-expr.adb b/src/synth/synth-expr.adb index 988cb89c3..9e5ccff6a 100644 --- a/src/synth/synth-expr.adb +++ b/src/synth/synth-expr.adb @@ -893,6 +893,50 @@ package body Synth.Expr is return Off; end Dyn_Index_To_Offset; + -- Return the bounds of a one dimensional array/vector type and the + -- width of the element. + procedure Get_Onedimensional_Array_Bounds + (Typ : Type_Acc; Bnd : out Bound_Type; El_Typ : out Type_Acc) is + begin + case Typ.Kind is + when Type_Vector => + El_Typ := Typ.Vec_El; + Bnd := Typ.Vbound; + when Type_Array => + El_Typ := Typ.Arr_El; + Bnd := Typ.Abounds.D (1); + when others => + raise Internal_Error; + end case; + end Get_Onedimensional_Array_Bounds; + + function Create_Onedimensional_Array_Subtype + (Btyp : Type_Acc; Bnd : Bound_Type) return Type_Acc + is + Res : Type_Acc; + Bnds : Bound_Array_Acc; + begin + case Btyp.Kind is + when Type_Vector => + Res := Create_Vector_Type (Bnd, Btyp.Vec_El); + when Type_Unbounded_Vector => + Res := Create_Vector_Type (Bnd, Btyp.Uvec_El); + when Type_Array => + pragma Assert (Btyp.Abounds.Len = 1); + Bnds := Create_Bound_Array (1); + Bnds.D (1) := Bnd; + Res := Create_Array_Type (Bnds, Btyp.Arr_El); + when Type_Unbounded_Array => + pragma Assert (Btyp.Uarr_Ndim = 1); + Bnds := Create_Bound_Array (1); + Bnds.D (1) := Bnd; + Res := Create_Array_Type (Bnds, Btyp.Uarr_El); + when others => + raise Internal_Error; + end case; + return Res; + end Create_Onedimensional_Array_Subtype; + procedure Synth_Indexed_Name (Syn_Inst : Synth_Instance_Acc; Name : Node; Pfx_Type : Type_Acc; @@ -906,6 +950,7 @@ package body Synth.Expr is Idx_Val : Value_Acc; Idx_Type : Type_Acc; Bnd : Bound_Type; + El_Typ : Type_Acc; begin if Get_Nbr_Elements (Indexes) /= 1 then Error_Msg_Synth (+Name, "multi-dim arrays not yet supported"); @@ -917,21 +962,13 @@ package body Synth.Expr is (Syn_Inst, Get_Base_Type (Get_Type (Idx_Expr))); Idx_Val := Synth_Expression_With_Type (Syn_Inst, Idx_Expr, Idx_Type); - case Pfx_Type.Kind is - when Type_Vector => - W := 1; - Bnd := Pfx_Type.Vbound; - when Type_Array => - W := Get_Type_Width (Pfx_Type.Arr_El); - Bnd := Pfx_Type.Abounds.D (1); - when others => - raise Internal_Error; - end case; + Get_Onedimensional_Array_Bounds (Pfx_Type, Bnd, El_Typ); + W := El_Typ.W; if Idx_Val.Kind = Value_Discrete then Voff := No_Net; Mul := 0; - Off := Index_To_Offset (Bnd, Idx_Val.Scal, Name); + Off := Index_To_Offset (Bnd, Idx_Val.Scal, Name) * W; else Voff := Dyn_Index_To_Offset (Bnd, Idx_Val, Name); Off := 0; @@ -947,11 +984,13 @@ package body Synth.Expr is Mul : Uns32; Off : Uns32; W : Width; + El_Typ : Type_Acc; Res : Net; begin Pfx_Val := Synth_Expression (Syn_Inst, Get_Prefix (Name)); Synth_Indexed_Name (Syn_Inst, Name, Pfx_Val.Typ, Voff, Mul, Off, W); + El_Typ := Get_Array_Element (Pfx_Val.Typ); if Voff = No_Net then pragma Assert (Mul = 0); @@ -960,13 +999,14 @@ package body Synth.Expr is else Res := Build_Extract (Build_Context, Get_Net (Pfx_Val), Off, W); Set_Location (Res, Name); - return Create_Value_Net (Res, Get_Array_Element (Pfx_Val.Typ)); + return Create_Value_Net (Res, El_Typ); end if; else - Res := Build_Dyn_Extract - (Build_Context, Get_Net (Pfx_Val), Voff, Mul, Int32 (Off), W); + pragma Assert (Off = 0); + Res := Build_Dyn_Extract (Build_Context, Get_Net (Pfx_Val), + Voff, Mul, Off, W); Set_Location (Res, Name); - return Create_Value_Net (Res, Get_Array_Element (Pfx_Val.Typ)); + return Create_Value_Net (Res, El_Typ); end if; end Synth_Indexed_Name; @@ -1096,7 +1136,7 @@ package body Synth.Expr is Right : Net; Inp : out Net; Step : out Uns32; - Off : out Int32; + Off : out Uns32; Width : out Uns32) is L_Inp, R_Inp : Net; @@ -1137,10 +1177,10 @@ package body Synth.Expr is case Pfx_Bnd.Dir is when Iir_To => - Off := L_Add - Pfx_Bnd.Left; + Off := Uns32 (L_Add - Pfx_Bnd.Left); Width := Uns32 (R_Add - L_Add + 1); when Iir_Downto => - Off := R_Add - Pfx_Bnd.Right; + Off := Uns32 (R_Add - Pfx_Bnd.Right); Width := Uns32 (L_Add - R_Add + 1); end case; end Synth_Extract_Dyn_Suffix; @@ -1151,7 +1191,7 @@ package body Synth.Expr is Res_Bnd : out Bound_Type; Inp : out Net; Step : out Uns32; - Off : out Int32; + Off : out Uns32; Wd : out Uns32) is Expr : constant Node := Get_Suffix (Name); @@ -1204,7 +1244,7 @@ package body Synth.Expr is Len => Wd, Left => Int32 (L), Right => Int32 (R)); - Off := Pfx_Bnd.Right - Res_Bnd.Right; + Off := Uns32 (Pfx_Bnd.Right - Res_Bnd.Right); when Iir_Downto => Wd := Width (L - R + 1); Res_Bnd := (Dir => Iir_Downto, @@ -1213,7 +1253,7 @@ package body Synth.Expr is Len => Wd, Left => Int32 (L), Right => Int32 (R)); - Off := Res_Bnd.Right - Pfx_Bnd.Right; + Off := Uns32 (Res_Bnd.Right - Pfx_Bnd.Right); end case; end; else @@ -1235,27 +1275,33 @@ package body Synth.Expr is Pfx_Node : constant Node := Get_Prefix (Name); Pfx : constant Value_Acc := Synth_Expression_With_Basetype (Syn_Inst, Pfx_Node); + Pfx_Bnd : Bound_Type; + El_Typ : Type_Acc; Res_Bnd : Bound_Type; Res_Type : Type_Acc; Inp : Net; Step : Uns32; - Off : Int32; + Off : Uns32; Wd : Uns32; N : Net; begin + Get_Onedimensional_Array_Bounds (Pfx.Typ, Pfx_Bnd, El_Typ); + Synth_Slice_Suffix - (Syn_Inst, Name, Pfx.Typ.Vbound, Res_Bnd, Inp, Step, Off, Wd); + (Syn_Inst, Name, Pfx_Bnd, Res_Bnd, Inp, Step, Off, Wd); if Inp /= No_Net then N := Build_Dyn_Extract (Build_Context, Get_Net (Pfx), - Inp, Step, Off, Wd); + Inp, Step * El_Typ.W, Off * El_Typ.W, + Wd * El_Typ.W); Set_Location (N, Name); -- TODO: the bounds cannot be created as they are not known. - Res_Type := Create_Slice_Type (Wd, Pfx.Typ.Vec_El); + Res_Type := Create_Slice_Type (Wd, El_Typ); return Create_Value_Net (N, Res_Type); else - N := Build_Extract (Build_Context, Get_Net (Pfx), Uns32 (Off), Wd); + N := Build_Extract (Build_Context, Get_Net (Pfx), + Off * El_Typ.W, Wd * El_Typ.W); Set_Location (N, Name); - Res_Type := Create_Vector_Type (Res_Bnd, Pfx.Typ.Vec_El); + Res_Type := Create_Onedimensional_Array_Subtype (Pfx.Typ, Res_Bnd); return Create_Value_Net (N, Res_Type); end if; end Synth_Slice_Name; |