diff options
-rw-r--r-- | src/synth/elab-vhdl_objtypes.ads | 9 | ||||
-rw-r--r-- | src/synth/synth-vhdl_stmts.adb | 131 |
2 files changed, 109 insertions, 31 deletions
diff --git a/src/synth/elab-vhdl_objtypes.ads b/src/synth/elab-vhdl_objtypes.ads index 6ff20d3b4..3dd777a5e 100644 --- a/src/synth/elab-vhdl_objtypes.ads +++ b/src/synth/elab-vhdl_objtypes.ads @@ -90,8 +90,12 @@ package Elab.Vhdl_Objtypes is subtype Type_Nets is Type_Kind range Type_Bit .. Type_Logic; subtype Type_All_Discrete is Type_Kind range Type_Bit .. Type_Discrete; - subtype Type_Records is - Type_Kind range Type_Unbounded_Record .. Type_Record; + subtype Type_Records is Type_Kind range + Type_Unbounded_Record .. Type_Record; + subtype Type_Arrays is Type_Kind range + Type_Array .. Type_Unbounded_Array; + subtype Type_Vectors is Type_Kind range + Type_Vector .. Type_Unbounded_Vector; type Type_Type (Kind : Type_Kind); type Type_Acc is access Type_Type; @@ -167,6 +171,7 @@ package Elab.Vhdl_Objtypes is Uarr_Idx : Type_Acc; when Type_Record | Type_Unbounded_Record => + -- The first elements is in the LSBs of the net. Rec : Rec_El_Array_Acc; when Type_Access => Acc_Acc : Type_Acc; diff --git a/src/synth/synth-vhdl_stmts.adb b/src/synth/synth-vhdl_stmts.adb index b48b107c5..d60d7095c 100644 --- a/src/synth/synth-vhdl_stmts.adb +++ b/src/synth/synth-vhdl_stmts.adb @@ -274,6 +274,10 @@ package body Synth.Vhdl_Stmts is Res : Type_Acc; begin Base_Typ := Get_Subtype_Object (Syn_Inst, Base_Type); + if Base_Typ.Kind = Type_Record then + return Base_Typ; + end if; + -- It's a basetype, so not bounded. pragma Assert (Base_Typ.Kind = Type_Unbounded_Vector); @@ -383,11 +387,11 @@ package body Synth.Vhdl_Stmts is -- Extract a part of VAL from a target aggregate at offset OFF (offset -- in the array). - function Aggregate_Extract (Ctxt : Context_Acc; - Val : Valtyp; - Off : Uns32; - Typ : Type_Acc; - Loc : Node) return Valtyp + function Aggregate_Array_Extract (Ctxt : Context_Acc; + Val : Valtyp; + Off : Uns32; + Typ : Type_Acc; + Loc : Node) return Valtyp is El_Typ : constant Type_Acc := Get_Array_Element (Val.Typ); begin @@ -417,7 +421,40 @@ package body Synth.Vhdl_Stmts is when others => raise Internal_Error; end case; - end Aggregate_Extract; + end Aggregate_Array_Extract; + + function Aggregate_Record_Extract (Ctxt : Context_Acc; + Val : Valtyp; + El_Idx : Iir_Index32; + Typ : Type_Acc; + Loc : Node) return Valtyp + is + El_Typ : Rec_El_Type renames Val.Typ.Rec.E (El_Idx); + begin + case Val.Val.Kind is + when Value_Net + | Value_Wire => + declare + N : Net; + begin + N := Build2_Extract (Ctxt, Get_Net (Ctxt, Val), + El_Typ.Offs.Net_Off, El_Typ.Typ.W); + Set_Location (N, Loc); + return Create_Value_Net (N, Typ); + end; + when Value_Memory => + declare + Res : Valtyp; + begin + Res := Create_Value_Memory (Typ); + Copy_Memory (Res.Val.Mem, + Val.Val.Mem + El_Typ.Offs.Mem_Off, El_Typ.Typ.Sz); + return Res; + end; + when others => + raise Internal_Error; + end case; + end Aggregate_Record_Extract; procedure Assign_Aggregate (Inst : Synth_Instance_Acc; Target : Node; @@ -426,33 +463,69 @@ package body Synth.Vhdl_Stmts is Loc : Node) is Ctxt : constant Context_Acc := Get_Build (Inst); - Targ_Bnd : constant Bound_Type := Get_Array_Bound (Target_Typ); Choice : Node; - Assoc : Node; - Pos : Uns32; + Assoc_Expr : Node; Targ_Info : Target_Info; begin Choice := Get_Association_Choices_Chain (Target); - Pos := Targ_Bnd.Len; - while Is_Valid (Choice) loop - Assoc := Get_Associated_Expr (Choice); - case Get_Kind (Choice) is - when Iir_Kind_Choice_By_None => - Targ_Info := Synth_Target (Inst, Assoc); - if Get_Element_Type_Flag (Choice) then - Pos := Pos - 1; - else - Pos := Pos - Get_Array_Bound (Targ_Info.Targ_Type).Len; - end if; - Assign (Inst, Targ_Info, - Aggregate_Extract (Ctxt, Val, Pos, - Targ_Info.Targ_Type, Assoc), - Loc); - when others => - Error_Kind ("assign_aggregate", Choice); - end case; - Choice := Get_Chain (Choice); - end loop; + + case Target_Typ.Kind is + when Type_Vectors + | Type_Arrays => + declare + Targ_Bnd : Bound_Type; + Pos : Uns32; + El_Len : Uns32; + begin + Targ_Bnd := Get_Array_Bound (Target_Typ); + Pos := Targ_Bnd.Len; + while Is_Valid (Choice) loop + Assoc_Expr := Get_Associated_Expr (Choice); + Targ_Info := Synth_Target (Inst, Assoc_Expr); + case Get_Kind (Choice) is + when Iir_Kind_Choice_By_None => + if Get_Element_Type_Flag (Choice) then + El_Len := 1; + else + El_Len := Get_Array_Bound (Targ_Info.Targ_Type).Len; + end if; + Pos := Pos - El_Len; + Assign (Inst, Targ_Info, + Aggregate_Array_Extract (Ctxt, Val, Pos, + Targ_Info.Targ_Type, + Assoc_Expr), + Loc); + when others => + Error_Kind ("assign_aggregate(arr)", Choice); + end case; + Choice := Get_Chain (Choice); + end loop; + end; + when Type_Records => + declare + El_Idx : Iir_Index32; + begin + El_Idx := Target_Typ.Rec.E'First; + while Is_Valid (Choice) loop + Assoc_Expr := Get_Associated_Expr (Choice); + Targ_Info := Synth_Target (Inst, Assoc_Expr); + case Get_Kind (Choice) is + when Iir_Kind_Choice_By_None => + Assign (Inst, Targ_Info, + Aggregate_Record_Extract (Ctxt, Val, El_Idx, + Targ_Info.Targ_Type, + Assoc_Expr), + Loc); + El_Idx := El_Idx + 1; + when others => + Error_Kind ("assign_aggregate(rec)", Choice); + end case; + Choice := Get_Chain (Choice); + end loop; + end; + when others => + raise Internal_Error; + end case; end Assign_Aggregate; procedure Synth_Assignment_Aggregate is |