diff options
| author | Tristan Gingold <tgingold@free.fr> | 2019-10-04 05:55:59 +0200 | 
|---|---|---|
| committer | Tristan Gingold <tgingold@free.fr> | 2019-10-04 20:09:21 +0200 | 
| commit | 42ae82d6cb7f7850dc6487cf8908a5d2af6d3c67 (patch) | |
| tree | 79a2f519b6d26c138450b2934598703e166ae0c0 | |
| parent | 37a25955c00ef76c6b33304352c4a6ffb9911f29 (diff) | |
| download | ghdl-42ae82d6cb7f7850dc6487cf8908a5d2af6d3c67.tar.gz ghdl-42ae82d6cb7f7850dc6487cf8908a5d2af6d3c67.tar.bz2 ghdl-42ae82d6cb7f7850dc6487cf8908a5d2af6d3c67.zip | |
synth: preliminary work to support procedure calls.
| -rw-r--r-- | src/synth/synth-stmts.adb | 318 | 
1 files changed, 200 insertions, 118 deletions
| diff --git a/src/synth/synth-stmts.adb b/src/synth/synth-stmts.adb index 7d09680c1..d4eecead1 100644 --- a/src/synth/synth-stmts.adb +++ b/src/synth/synth-stmts.adb @@ -250,7 +250,7 @@ package body Synth.Stmts is              Aggr : Node;           when Target_Memory =>              --  For a memory: the destination is known. -            Mem_Wid : Wire_Id; +            Mem_Obj : Value_Acc;              --  The width of the whole mrmory.              Mem_Width : Width;              --  The dynamic offset. @@ -259,6 +259,8 @@ package body Synth.Stmts is        end case;     end record; +   type Target_Info_Array is array (Natural range <>) of Target_Info; +     function Synth_Target (Syn_Inst : Synth_Instance_Acc;                            Target : Node) return Target_Info is     begin @@ -309,7 +311,7 @@ package body Synth.Stmts is                 else                    return Target_Info'(Kind => Target_Memory,                                        Targ_Type => Typ, -                                      Mem_Wid => Obj.W, +                                      Mem_Obj => Obj,                                        Mem_Width => Rdwd,                                        Mem_Voff => Voff,                                        Mem_Off => Off); @@ -361,13 +363,13 @@ package body Synth.Stmts is                 V : Net;              begin                 V := Get_Current_Assign_Value -                 (Get_Build (Syn_Inst), Target.Mem_Wid, Target.Mem_Off, +                 (Get_Build (Syn_Inst), Target.Mem_Obj.W, Target.Mem_Off,                    Target.Mem_Width);                 V := Build_Dyn_Insert (Get_Build (Syn_Inst), V, Get_Net (Val),                    Target.Mem_Voff, Target.Mem_Off);                 Set_Location (V, Loc);                 Synth_Assign -                 (Target.Mem_Wid, Target.Targ_Type, +                 (Target.Mem_Obj.W, Target.Targ_Type,                    Create_Value_Net (V, Target.Targ_Type), Target.Mem_Off, Loc);              end;        end case; @@ -397,6 +399,10 @@ package body Synth.Stmts is           N := Build_Dyn_Extract             (Get_Build (Syn_Inst), Get_Net (Obj), Voff, Off, Typ.W);        else +         if Off = 0 and then Typ.W = Obj.Typ.W then +            --  Nothing to do if extracting the whole object. +            return Obj; +         end if;           N := Build_Extract (Get_Build (Syn_Inst), Get_Net (Obj), Off, Typ.W);        end if;        Set_Location (N, Loc); @@ -1207,17 +1213,21 @@ package body Synth.Stmts is     procedure Synth_Subprogram_Association (Subprg_Inst : Synth_Instance_Acc;                                             Caller_Inst : Synth_Instance_Acc;                                             Inter_Chain : Node; -                                           Assoc_Chain : Node) +                                           Assoc_Chain : Node; +                                           Infos : out Target_Info_Array)     is +      pragma Assert (Infos'First = 1);        Inter : Node;        Inter_Type : Type_Acc;        Assoc : Node;        Assoc_Inter : Node;        Actual : Node;        Val : Value_Acc; +      Nbr_Inout : Natural;     begin        Set_Instance_Const (Subprg_Inst, True); +      Nbr_Inout := 0;        Assoc := Assoc_Chain;        Assoc_Inter := Inter_Chain;        while Is_Valid (Assoc) loop @@ -1239,8 +1249,25 @@ package body Synth.Stmts is                       raise Internal_Error;                 end case;              when Iir_Out_Mode | Iir_Inout_Mode => -               --  FIXME: todo -               raise Internal_Error; +               Nbr_Inout := Nbr_Inout + 1; +               Actual := Get_Actual (Assoc); +               Infos (Nbr_Inout) := Synth_Target (Caller_Inst, Actual); +               declare +                  Info : Target_Info renames Infos (Nbr_Inout); +               begin +                  case Info.Kind is +                     when Target_Aggregate => +                        raise Internal_Error; +                     when Target_Simple => +                        Val := Synth_Read_Memory +                          (Caller_Inst, Info.Obj, Info.Off, No_Net, +                           Info.Targ_Type, Assoc); +                     when Target_Memory => +                        Val := Synth_Read_Memory +                          (Caller_Inst, Info.Mem_Obj, Info.Mem_Off, +                           Info.Mem_Voff, Info.Targ_Type, Assoc); +                  end case; +               end;           end case;           Val := Synth_Subtype_Conversion (Val, Inter_Type, True, Assoc); @@ -1250,10 +1277,13 @@ package body Synth.Stmts is           end if;           case Iir_Kinds_Interface_Object_Declaration (Get_Kind (Inter)) is -            when Iir_Kind_Interface_Constant_Declaration -              | Iir_Kind_Interface_Variable_Declaration => +            when Iir_Kind_Interface_Constant_Declaration => +               --  Pass by reference. +               Create_Object (Subprg_Inst, Inter, Val); +            when Iir_Kind_Interface_Variable_Declaration =>                 --  FIXME: Arguments are passed by copy.                 Create_Object (Subprg_Inst, Inter, Val); +               raise Internal_Error;              when Iir_Kind_Interface_Signal_Declaration =>                 Create_Object (Subprg_Inst, Inter, Val);              when Iir_Kind_Interface_File_Declaration => @@ -1264,30 +1294,50 @@ package body Synth.Stmts is        end loop;     end Synth_Subprogram_Association; +   procedure Synth_Subprogram_Association (Subprg_Inst : Synth_Instance_Acc; +                                           Caller_Inst : Synth_Instance_Acc; +                                           Inter_Chain : Node; +                                           Assoc_Chain : Node) +   is +      Infos : Target_Info_Array (1 .. 0); +      pragma Unreferenced (Infos); +   begin +      Synth_Subprogram_Association +        (Subprg_Inst, Caller_Inst, Inter_Chain, Assoc_Chain, Infos); +   end Synth_Subprogram_Association; +     procedure Synth_Subprogram_Back_Association       (Subprg_Inst : Synth_Instance_Acc;        Caller_Inst : Synth_Instance_Acc;        Inter_Chain : Node; -      Assoc_Chain : Node) +      Assoc_Chain : Node; +      Infos : Target_Info_Array)     is +      pragma Assert (Infos'First = 1);        Inter : Node;        Assoc : Node;        Assoc_Inter : Node;        Val : Value_Acc; +      Nbr_Inout : Natural;     begin +      Nbr_Inout := 0;        Assoc := Assoc_Chain;        Assoc_Inter := Inter_Chain;        while Is_Valid (Assoc) loop           Inter := Get_Association_Interface (Assoc, Assoc_Inter); -         if Get_Mode (Inter) = Iir_Out_Mode then -            Val := Synth_Expression (Subprg_Inst, Inter); -            Synth_Assignment (Caller_Inst, Get_Actual (Assoc), Val, Assoc); - -         end if; +         case Iir_Parameter_Modes (Get_Mode (Inter)) is +            when Iir_In_Mode => +               null; +            when Iir_Out_Mode | Iir_Inout_Mode => +               Nbr_Inout := Nbr_Inout + 1; +               Val := Synth_Expression (Subprg_Inst, Inter); +               Synth_Assignment (Caller_Inst, Infos (Nbr_Inout), Val, Assoc); +         end case;           Next_Association_Interface (Assoc, Assoc_Inter);        end loop; +      pragma Assert (Nbr_Inout = Infos'Last);     end Synth_Subprogram_Back_Association;     function Synth_Label (Stmt : Node) return Sname @@ -1301,47 +1351,152 @@ package body Synth.Stmts is        end if;     end Synth_Label; -   procedure Synth_Procedure_Call (C : in out Seq_Context; Stmt : Node) +   procedure Count_Associations +     (Inter_Chain : Node; Assoc_Chain : Node; Nbr_Inout : out Natural) +   is +      Assoc : Node; +      Assoc_Inter : Node; +      Inter : Node; +   begin +      Nbr_Inout := 0; + +      Assoc := Assoc_Chain; +      Assoc_Inter := Inter_Chain; +      while Is_Valid (Assoc) loop +         Inter := Get_Association_Interface (Assoc, Assoc_Inter); + +         case Iir_Parameter_Modes (Get_Mode (Inter)) is +            when Iir_In_Mode => +               null; +            when Iir_Out_Mode | Iir_Inout_Mode => +               Nbr_Inout := Nbr_Inout + 1; +         end case; + +         Next_Association_Interface (Assoc, Assoc_Inter); +      end loop; +   end Count_Associations; + +   function Synth_Subprogram_Call +     (Syn_Inst : Synth_Instance_Acc; Call : Node) return Value_Acc     is -      Call : constant Node := Get_Procedure_Call (Stmt);        Imp  : constant Node := Get_Implementation (Call); +      Is_Func : constant Boolean := Is_Function_Declaration (Imp);        Assoc_Chain : constant Node := Get_Parameter_Association_Chain (Call);        Inter_Chain : constant Node := Get_Interface_Declaration_Chain (Imp); -      Subprg_Body : constant Node := Get_Subprogram_Body (Imp); -      Decls_Chain : constant Node := Get_Declaration_Chain (Subprg_Body); -      Sub_C : Seq_Context; -      Sub_Sname : Sname; -      M : Areapools.Mark_Type; +      Bod : constant Node := Get_Subprogram_Body (Imp); +      Area_Mark : Areapools.Mark_Type; +      Res : Value_Acc; +      C : Seq_Context; +      Wire_Mark : Wire_Id; +      Subprg_Phi : Phi_Type; +      Nbr_Inout : Natural;     begin -      if Get_Implicit_Definition (Imp) in Iir_Predefined_Implicit then -         Error_Msg_Synth (+Stmt, "call to implicit %n is not supported", +Imp); -         return; -      elsif Get_Foreign_Flag (Imp) then -         Error_Msg_Synth (+Stmt, "call to foreign %n is not supported", +Imp); -         return; +      Mark (Wire_Mark); +      Areapools.Mark (Area_Mark, Instance_Pool.all); +      C := (Inst => Make_Instance (Syn_Inst, Bod, +                                   New_Internal_Name (Build_Context)), +            Cur_Loop => null, +            W_En => Alloc_Wire (Wire_Variable, Imp), +            W_Ret => Alloc_Wire (Wire_Variable, Imp), +            W_Val => No_Wire_Id, +            Ret_Init => No_Net, +            Ret_Value => null, +            Ret_Typ => null, +            Nbr_Ret => 0); + +      if Is_Func then +         C.W_Val := Alloc_Wire (Wire_Variable, Imp);        end if; -      Areapools.Mark (M, Instance_Pool.all); -      Sub_Sname := New_Sname (Get_Sname (C.Inst), Get_Identifier (Imp)); -      Sub_C.Inst := Make_Instance (C.Inst, Imp, Sub_Sname); +      Count_Associations (Inter_Chain, Assoc_Chain, Nbr_Inout); -      Synth_Subprogram_Association -        (Sub_C.Inst, C.Inst, Inter_Chain, Assoc_Chain); +      declare +         Infos : Target_Info_Array (1 .. Nbr_Inout); +      begin +         Synth_Subprogram_Association +           (C.Inst, Syn_Inst, Inter_Chain, Assoc_Chain, Infos); + +         Push_Phi; -      Synth_Declarations (Sub_C.Inst, Decls_Chain); +         if Is_Func then +            --  Set a default value for the return. +            C.Ret_Typ := Get_Value_Type (Syn_Inst, Get_Return_Type (Imp)); +            Set_Wire_Gate (C.W_Val, +                           Build_Signal (Build_Context, +                                         New_Internal_Name (Build_Context), +                                         C.Ret_Typ.W)); +            C.Ret_Init := Build_Const_X (Build_Context, C.Ret_Typ.W); +            Phi_Assign (Build_Context, C.W_Val, C.Ret_Init, 0); +         end if; -      if Is_Valid (Decls_Chain) then -         Synth_Declarations (Sub_C.Inst, Decls_Chain); +         Set_Wire_Gate +           (C.W_En, Build_Signal (Build_Context, +                                  New_Internal_Name (Build_Context), 1)); +         Phi_Assign (Build_Context, C.W_En, Get_Inst_Bit1 (Syn_Inst), 0); + +         Set_Wire_Gate +           (C.W_Ret, Build_Signal (Build_Context, +                                   New_Internal_Name (Build_Context), 1)); +         Phi_Assign (Build_Context, C.W_Ret, Get_Inst_Bit1 (Syn_Inst), 0); + +         Decls.Synth_Declarations (C.Inst, Get_Declaration_Chain (Bod), True); + +         Synth_Sequential_Statements +           (C, Get_Sequential_Statement_Chain (Bod)); + +         if Is_Func then +            if C.Nbr_Ret = 0 then +               raise Internal_Error; +            elsif C.Nbr_Ret = 1 and then Is_Const (C.Ret_Value) then +               Res := C.Ret_Value; +            else +               Res := Create_Value_Net +                 (Get_Current_Value (Build_Context, C.W_Val), C.Ret_Value.Typ); +            end if; +         else +            Res := null; +            Synth_Subprogram_Back_Association +              (C.Inst, Syn_Inst, Inter_Chain, Assoc_Chain, Infos); +         end if; + +         Pop_Phi (Subprg_Phi); + +         Decls.Finalize_Declarations +           (C.Inst, Get_Declaration_Chain (Bod), True); +         pragma Unreferenced (Infos); +      end; + +      --  Free wires. +      Free_Wire (C.W_En); +      Free_Wire (C.W_Ret); +      if Is_Func then +         Free_Wire (C.W_Val);        end if; -      Synth_Sequential_Statements -        (Sub_C, Get_Sequential_Statement_Chain (Subprg_Body)); +      Free_Instance (C.Inst); +      Areapools.Release (Area_Mark, Instance_Pool.all); -      Synth_Subprogram_Back_Association -        (Sub_C.Inst, C.Inst, Inter_Chain, Assoc_Chain); +      Release (Wire_Mark); -      Free_Instance (Sub_C.Inst); -      Areapools.Release (M, Instance_Pool.all); +      return Res; +   end Synth_Subprogram_Call; + +   procedure Synth_Procedure_Call (C : in out Seq_Context; Stmt : Node) +   is +      Call : constant Node := Get_Procedure_Call (Stmt); +      Imp  : constant Node := Get_Implementation (Call); +      Res : Value_Acc; +   begin +      if Get_Implicit_Definition (Imp) in Iir_Predefined_Implicit then +         Error_Msg_Synth (+Stmt, "call to implicit %n is not supported", +Imp); +         return; +      elsif Get_Foreign_Flag (Imp) then +         Error_Msg_Synth (+Stmt, "call to foreign %n is not supported", +Imp); +         return; +      end if; + +      Res := Synth_Subprogram_Call (C.Inst, Call); +      pragma Assert (Res = null);     end Synth_Procedure_Call;     function In_Range (Rng : Discrete_Range_Type; V : Int64) return Boolean is @@ -1799,20 +1954,11 @@ package body Synth.Stmts is     end Synth_Process_Statement;     function Synth_User_Function_Call -     (Syn_Inst : Synth_Instance_Acc; Expr : Node) return Value_Acc -   is -      Imp  : constant Node := Get_Implementation (Expr); -      Assoc_Chain : constant Node := Get_Parameter_Association_Chain (Expr); -      Inter_Chain : constant Node := Get_Interface_Declaration_Chain (Imp); -      Bod : constant Node := Get_Subprogram_Body (Imp); -      Area_Mark : Areapools.Mark_Type; -      Res : Value_Acc; -      C : Seq_Context; -      Wire_Mark : Wire_Id; -      Subprg_Phi : Phi_Type; +     (Syn_Inst : Synth_Instance_Acc; Expr : Node) return Value_Acc is     begin        --  Is it a call to an ieee function ?        declare +         Imp  : constant Node := Get_Implementation (Expr);           Pkg : constant Node := Get_Parent (Imp);           Unit : Node;           Lib : Node; @@ -1830,71 +1976,7 @@ package body Synth.Stmts is           end if;        end; -      Mark (Wire_Mark); -      Areapools.Mark (Area_Mark, Instance_Pool.all); -      C := (Inst => Make_Instance (Syn_Inst, Bod, -                                   New_Internal_Name (Build_Context)), -            Cur_Loop => null, -            W_En => Alloc_Wire (Wire_Variable, Imp), -            W_Ret => Alloc_Wire (Wire_Variable, Imp), -            W_Val => Alloc_Wire (Wire_Variable, Imp), -            Ret_Init => No_Net, -            Ret_Value => null, -            Ret_Typ => null, -            Nbr_Ret => 0); - -      Synth_Subprogram_Association -        (C.Inst, Syn_Inst, Inter_Chain, Assoc_Chain); - -      Push_Phi; - -      --  Set a default value for the return. -      C.Ret_Typ := Get_Value_Type (Syn_Inst, Get_Return_Type (Imp)); -      Set_Wire_Gate (C.W_Val, Build_Signal (Build_Context, -                                            New_Internal_Name (Build_Context), -                                            C.Ret_Typ.W)); -      C.Ret_Init := Build_Const_X (Build_Context, C.Ret_Typ.W); -      Phi_Assign (Build_Context, C.W_Val, C.Ret_Init, 0); - -      Set_Wire_Gate -        (C.W_En, -         Build_Signal (Build_Context, New_Internal_Name (Build_Context), 1)); -      Phi_Assign (Build_Context, C.W_En, Get_Inst_Bit1 (Syn_Inst), 0); - -      Set_Wire_Gate -        (C.W_Ret, -         Build_Signal (Build_Context, New_Internal_Name (Build_Context), 1)); -      Phi_Assign (Build_Context, C.W_Ret, Get_Inst_Bit1 (Syn_Inst), 0); - -      Decls.Synth_Declarations (C.Inst, Get_Declaration_Chain (Bod), True); - -      Synth_Sequential_Statements (C, Get_Sequential_Statement_Chain (Bod)); - - -      if C.Nbr_Ret = 0 then -         raise Internal_Error; -      elsif C.Nbr_Ret = 1 and then Is_Const (C.Ret_Value) then -         Res := C.Ret_Value; -      else -         Res := Create_Value_Net (Get_Current_Value (Build_Context, C.W_Val), -                                  C.Ret_Value.Typ); -      end if; - -      Pop_Phi (Subprg_Phi); - -      Decls.Finalize_Declarations (C.Inst, Get_Declaration_Chain (Bod), True); - -      --  Free wires. -      Free_Wire (C.W_En); -      Free_Wire (C.W_Ret); -      Free_Wire (C.W_Val); - -      Free_Instance (C.Inst); -      Areapools.Release (Area_Mark, Instance_Pool.all); - -      Release (Wire_Mark); - -      return Res; +      return Synth_Subprogram_Call (Syn_Inst, Expr);     end Synth_User_Function_Call;     procedure Synth_Concurrent_Assertion_Statement | 
