diff options
Diffstat (limited to 'src/synth/synth-stmts.adb')
-rw-r--r-- | src/synth/synth-stmts.adb | 195 |
1 files changed, 139 insertions, 56 deletions
diff --git a/src/synth/synth-stmts.adb b/src/synth/synth-stmts.adb index 999c585c2..e6a65d465 100644 --- a/src/synth/synth-stmts.adb +++ b/src/synth/synth-stmts.adb @@ -36,7 +36,6 @@ with PSL.Nodes; with PSL.NFAs; with PSL.Errors; -with Synth.Types; use Synth.Types; with Synth.Errors; use Synth.Errors; with Synth.Decls; use Synth.Decls; with Synth.Expr; use Synth.Expr; @@ -54,7 +53,7 @@ package body Synth.Stmts is function Synth_Waveform (Syn_Inst : Synth_Instance_Acc; Wf : Node; - Targ_Type : Node) return Value_Acc is + Targ_Type : Type_Acc) return Value_Acc is begin if Get_Kind (Wf) = Iir_Kind_Unaffected_Waveform then -- TODO @@ -68,7 +67,7 @@ package body Synth.Stmts is -- Warning null; end if; - if Targ_Type = Null_Node then + if Targ_Type = null then return Synth_Expression (Syn_Inst, Get_We_Value (Wf)); else return Synth_Expression_With_Type @@ -89,19 +88,17 @@ package body Synth.Stmts is procedure Synth_Assignment_Aggregate (Syn_Inst : Synth_Instance_Acc; Target : Node; + Target_Type : Type_Acc; Val : Value_Acc; Loc : Node) is - Targ_Type : constant Node := Get_Type (Target); - Bnd : Bound_Type; Choice : Node; Assoc : Node; Pos : Uns32; begin - if Is_Vector_Type (Targ_Type) then - Bnd := Expr.Synth_Array_Bounds (Syn_Inst, Targ_Type, 0); + if Target_Type.Kind = Type_Vector then Choice := Get_Association_Choices_Chain (Target); - Pos := Bnd.Len; + Pos := Target_Type.W; while Is_Valid (Choice) loop Assoc := Get_Associated_Expr (Choice); case Get_Kind (Choice) is @@ -204,14 +201,53 @@ package body Synth.Stmts is end case; end Synth_Assignment_Prefix; - procedure Synth_Assignment (Syn_Inst : Synth_Instance_Acc; - Target : Node; - Val : Value_Acc; - Loc : Node) is + type Target_Kind is + (Target_Simple, Target_Aggregate, Target_Memory); + + type Target_Info (Kind : Target_Kind := Target_Simple) is record + -- In all cases, the type of the target is known or computed. + Targ_Type : Type_Acc; + + case Kind is + when Target_Simple => + -- For a simple target, the destination is known. + Wid : Wire_Id; + Off : Uns32; + when Target_Aggregate => + -- For an aggregate: the type is computed and the details will + -- be handled at the assignment. + Aggr : Node; + when Target_Memory => + -- For a memory: the destination is known. + Mem_Wid : Wire_Id; + Mem_Off : Uns32; + Mem_Val : Net; + end case; + end record; + + function Synth_Target (Syn_Inst : Synth_Instance_Acc; + Target : Node) return Target_Info is begin case Get_Kind (Target) is when Iir_Kind_Aggregate => - Synth_Assignment_Aggregate (Syn_Inst, Target, Val, Loc); + declare + Targ_Type : constant Node := Get_Type (Target); + Base_Typ : Type_Acc; + Bnd : Bound_Type; + begin + Base_Typ := + Get_Value_Type (Syn_Inst, Get_Base_Type (Targ_Type)); + case Base_Typ.Kind is + when Type_Unbounded_Vector => + Bnd := Expr.Synth_Array_Bounds (Syn_Inst, Targ_Type, 0); + return Target_Info' (Kind => Target_Aggregate, + Targ_Type => Create_Vector_Type + (Bnd, Base_Typ.Uvec_El), + Aggr => Target); + when others => + raise Internal_Error; + end case; + end; when Iir_Kind_Simple_Name | Iir_Kind_Selected_Element | Iir_Kind_Interface_Signal_Declaration @@ -224,13 +260,17 @@ package body Synth.Stmts is Typ : Type_Acc; begin Synth_Assignment_Prefix (Syn_Inst, Target, Wid, Off, Typ); - Synth_Assign (Wid, Typ, Val, Off, Loc); + return Target_Info'(Kind => Target_Simple, + Targ_Type => Typ, + Wid => Wid, + Off => Off); end; when Iir_Kind_Indexed_Name => declare Wid : Wire_Id; Off : Uns32; Typ : Type_Acc; + El_Typ : Type_Acc; Voff : Net; Mul : Uns32; @@ -244,20 +284,27 @@ package body Synth.Stmts is Wid, Off, Typ); Synth_Indexed_Name (Syn_Inst, Target, Typ, Voff, Mul, Idx_Off, W); + El_Typ := Get_Array_Element (Typ); if Voff = No_Net then -- FIXME: check index. pragma Assert (Mul = 0); - Synth_Assign (Wid, Get_Array_Element (Typ), - Val, Off + Idx_Off, Loc); + return Target_Info'(Kind => Target_Simple, + Targ_Type => El_Typ, + Wid => Wid, + Off => Off + Idx_Off); else Targ_Net := Get_Current_Assign_Value (Build_Context, Wid, Off, Get_Type_Width (Typ)); V := Build_Dyn_Insert - (Build_Context, Targ_Net, Get_Net (Val), + (Build_Context, Targ_Net, No_Net, Voff, Mul, Int32 (Idx_Off)); Set_Location (V, Target); - Synth_Assign (Wid, Typ, Create_Value_Net (V, Typ), Off, Loc); + return Target_Info'(Kind => Target_Memory, + Targ_Type => El_Typ, + Mem_Wid => Wid, + Mem_Off => Off, + Mem_Val => V); end if; end; when Iir_Kind_Slice_Name => @@ -285,55 +332,90 @@ package body Synth.Stmts is Targ_Net := Get_Current_Assign_Value (Build_Context, Wid, Off, Get_Type_Width (Typ)); V := Build_Dyn_Insert - (Build_Context, Targ_Net, Get_Net (Val), + (Build_Context, Targ_Net, No_Net, Inp, Step, Sl_Off); Set_Location (V, Target); - Synth_Assign - (Wid, Res_Type, Create_Value_Net (V, Res_Type), Off, Loc); + return Target_Info'(Kind => Target_Memory, + Targ_Type => Res_Type, + Mem_Wid => Wid, + Mem_Off => Off, + Mem_Val => V); else - Synth_Assign (Wid, Res_Type, Val, Off + Uns32 (Sl_Off), Loc); + return Target_Info'(Kind => Target_Simple, + Targ_Type => Res_Type, + Wid => Wid, + Off => Off + Uns32 (Sl_Off)); end if; end; when others => - Error_Kind ("synth_assignment", Target); + Error_Kind ("synth_target", Target); end case; + end Synth_Target; + + procedure Synth_Assignment (Syn_Inst : Synth_Instance_Acc; + Target : Target_Info; + Val : Value_Acc; + Loc : Node) is + begin + case Target.Kind is + when Target_Aggregate => + Synth_Assignment_Aggregate + (Syn_Inst, Target.Aggr, Target.Targ_Type, Val, Loc); + when Target_Simple => + Synth_Assign (Target.Wid, Target.Targ_Type, Val, Target.Off, Loc); + when Target_Memory => + declare + Inst : constant Instance := Get_Net_Parent (Target.Mem_Val); + begin + Connect (Get_Input (Inst, 1), Get_Net (Val)); + Synth_Assign + (Target.Mem_Wid, Target.Targ_Type, + Create_Value_Net (Target.Mem_Val, Target.Targ_Type), + Target.Mem_Off, Loc); + end; + end case; + end Synth_Assignment; + + procedure Synth_Assignment (Syn_Inst : Synth_Instance_Acc; + Target : Node; + Val : Value_Acc; + Loc : Node) + is + Info : Target_Info; + begin + Info := Synth_Target (Syn_Inst, Target); + Synth_Assignment (Syn_Inst, Info, Val, Loc); end Synth_Assignment; -- Concurrent or sequential simple signal assignment procedure Synth_Simple_Signal_Assignment (Syn_Inst : Synth_Instance_Acc; Stmt : Node) is - Target : constant Node := Get_Target (Stmt); - Wf_Type : Node; + Targ : Target_Info; Val : Value_Acc; begin - -- FIXME: correctly handle target type when it is a slice. - case Get_Kind (Target) is - when Iir_Kind_Slice_Name - | Iir_Kind_Aggregate => - Wf_Type := Null_Node; - when others => - Wf_Type := Get_Type (Target); - end case; - Val := Synth_Waveform (Syn_Inst, Get_Waveform_Chain (Stmt), Wf_Type); - Synth_Assignment (Syn_Inst, Target, Val, Stmt); + Targ := Synth_Target (Syn_Inst, Get_Target (Stmt)); + Val := Synth_Waveform + (Syn_Inst, Get_Waveform_Chain (Stmt), Targ.Targ_Type); + Synth_Assignment (Syn_Inst, Targ, Val, Stmt); end Synth_Simple_Signal_Assignment; procedure Synth_Conditional_Signal_Assignment (Syn_Inst : Synth_Instance_Acc; Stmt : Node) is - Target : constant Node := Get_Target (Stmt); - Targ_Type : constant Node := Get_Type (Target); + Targ : Target_Info; Cond : Node; Cwf : Node; Val, Cond_Val : Value_Acc; First, Last : Net; V : Net; begin + Targ := Synth_Target (Syn_Inst, Get_Target (Stmt)); Last := No_Net; Cwf := Get_Conditional_Waveform_Chain (Stmt); while Cwf /= Null_Node loop - Val := Synth_Waveform (Syn_Inst, Get_Waveform_Chain (Cwf), Targ_Type); + Val := Synth_Waveform + (Syn_Inst, Get_Waveform_Chain (Cwf), Targ.Targ_Type); V := Get_Net (Val); Cond := Get_Condition (Cwf); if Cond /= Null_Node then @@ -352,32 +434,34 @@ package body Synth.Stmts is Last := V; Cwf := Get_Chain (Cwf); end loop; - Val := Create_Value_Net (First, Get_Value_Type (Syn_Inst, Targ_Type)); - Synth_Assignment (Syn_Inst, Target, Val, Stmt); + Val := Create_Value_Net (First, Targ.Targ_Type); + Synth_Assignment (Syn_Inst, Targ, Val, Stmt); end Synth_Conditional_Signal_Assignment; procedure Synth_Variable_Assignment (Syn_Inst : Synth_Instance_Acc; Stmt : Node) is - Target : constant Node := Get_Target (Stmt); + Targ : Target_Info; Val : Value_Acc; begin + Targ := Synth_Target (Syn_Inst, Get_Target (Stmt)); Val := Synth_Expression_With_Type - (Syn_Inst, Get_Expression (Stmt), Get_Type (Target)); - Synth_Assignment (Syn_Inst, Target, Val, Stmt); + (Syn_Inst, Get_Expression (Stmt), Targ.Targ_Type); + Synth_Assignment (Syn_Inst, Targ, Val, Stmt); end Synth_Variable_Assignment; procedure Synth_Conditional_Variable_Assignment (Syn_Inst : Synth_Instance_Acc; Stmt : Node) is Target : constant Node := Get_Target (Stmt); - Targ_Type : constant Node := Get_Type (Target); + Targ_Type : Type_Acc; Cond : Node; Ce : Node; Val, Cond_Val : Value_Acc; V : Net; First, Last : Net; begin + Targ_Type := Get_Value_Type (Syn_Inst, Get_Type (Target)); Last := No_Net; Ce := Get_Conditional_Expression_Chain (Stmt); while Ce /= Null_Node loop @@ -399,7 +483,7 @@ package body Synth.Stmts is Last := V; Ce := Get_Chain (Ce); end loop; - Val := Create_Value_Net (First, Get_Value_Type (Syn_Inst, Targ_Type)); + Val := Create_Value_Net (First, Targ_Type); Synth_Assignment (Syn_Inst, Target, Val, Stmt); end Synth_Conditional_Variable_Assignment; @@ -972,12 +1056,13 @@ package body Synth.Stmts is use Vhdl.Sem_Expr; Targ : constant Node := Get_Target (Stmt); - Targ_Type : constant Node := Get_Type (Targ); Expr : constant Node := Get_Expression (Stmt); Choices : constant Node := Get_Selected_Waveform_Chain (Stmt); Choice : Node; + Targ_Type : Type_Acc; + Case_Info : Choice_Info_Type; Annex_Arr : Annex_Array_Acc; @@ -995,6 +1080,7 @@ package body Synth.Stmts is Sel : Value_Acc; Sel_Net : Net; begin + Targ_Type := Get_Value_Type (Syn_Inst, Get_Type (Targ)); -- Create a net for the expression. Sel := Synth_Expression (Syn_Inst, Expr); @@ -1088,10 +1174,9 @@ package body Synth.Stmts is -- Generate the muxes tree. Synth_Case (Sel_Net, Case_El.all, Default, Res); - Synth_Assignment - (Syn_Inst, Get_Target (Stmt), - Create_Value_Net (Res, Get_Value_Type (Syn_Inst, Targ_Type)), - Stmt); + Synth_Assignment (Syn_Inst, Get_Target (Stmt), + Create_Value_Net (Res, Targ_Type), + Stmt); end; -- free. @@ -1107,7 +1192,7 @@ package body Synth.Stmts is Assoc_Chain : Node) is Inter : Node; - Inter_Type : Node; + Inter_Type : Type_Acc; Assoc : Node; Assoc_Inter : Node; Actual : Node; @@ -1117,7 +1202,7 @@ package body Synth.Stmts is Assoc_Inter := Inter_Chain; while Is_Valid (Assoc) loop Inter := Get_Association_Interface (Assoc, Assoc_Inter); - Inter_Type := Get_Type (Inter); + Inter_Type := Get_Value_Type (Subprg_Inst, Get_Type (Inter)); case Iir_Parameter_Modes (Get_Mode (Inter)) is when Iir_In_Mode => @@ -1138,8 +1223,7 @@ package body Synth.Stmts is raise Internal_Error; end case; - Val := Synth_Subtype_Conversion - (Val, Get_Value_Type (Subprg_Inst, Inter_Type), True, Assoc); + Val := Synth_Subtype_Conversion (Val, Inter_Type, True, Assoc); case Iir_Kinds_Interface_Object_Declaration (Get_Kind (Inter)) is when Iir_Kind_Interface_Constant_Declaration @@ -1173,8 +1257,7 @@ package body Synth.Stmts is Inter := Get_Association_Interface (Assoc, Assoc_Inter); if Get_Mode (Inter) = Iir_Out_Mode then - Val := Synth_Expression_With_Type - (Subprg_Inst, Inter, Get_Type (Inter)); + Val := Synth_Expression (Subprg_Inst, Inter); Synth_Assignment (Caller_Inst, Get_Actual (Assoc), Val, Assoc); end if; |