diff options
| author | Tristan Gingold <tgingold@free.fr> | 2022-08-19 06:12:36 +0200 | 
|---|---|---|
| committer | Tristan Gingold <tgingold@free.fr> | 2022-08-19 06:49:51 +0200 | 
| commit | 21bab65e5ed98ba4b1db124a635c0de31af08818 (patch) | |
| tree | 2ac1b22d51747dde7a61d16215eb410cde18fac3 | |
| parent | fe6edccd9c03f40878cc1d27b07c024407d63bff (diff) | |
| download | ghdl-21bab65e5ed98ba4b1db124a635c0de31af08818.tar.gz ghdl-21bab65e5ed98ba4b1db124a635c0de31af08818.tar.bz2 ghdl-21bab65e5ed98ba4b1db124a635c0de31af08818.zip | |
simul: handle resolved signals (WIP)
| -rw-r--r-- | src/simul/simul-vhdl_elab.ads | 3 | ||||
| -rw-r--r-- | src/simul/simul-vhdl_simul.adb | 337 | ||||
| -rw-r--r-- | src/synth/synth-vhdl_stmts.adb | 36 | ||||
| -rw-r--r-- | src/synth/synth-vhdl_stmts.ads | 5 | 
4 files changed, 332 insertions, 49 deletions
| diff --git a/src/simul/simul-vhdl_elab.ads b/src/simul/simul-vhdl_elab.ads index 14ca462a0..c17555920 100644 --- a/src/simul/simul-vhdl_elab.ads +++ b/src/simul/simul-vhdl_elab.ads @@ -50,6 +50,7 @@ package Simul.Vhdl_Elab is     type Driver_Index_Type is new Nat32;     subtype Sensitivity_Index_Type is Driver_Index_Type; +   No_Process_Index : constant Process_Index_Type := 0;     No_Driver_Index : constant Driver_Index_Type := 0;     No_Sensitivity_Index : constant Sensitivity_Index_Type := 0; @@ -64,7 +65,7 @@ package Simul.Vhdl_Elab is     package Processes_Table is new Tables       (Table_Component_Type => Proc_Record_Type,        Table_Index_Type => Process_Index_Type, -      Table_Low_Bound => 1, +      Table_Low_Bound => No_Process_Index + 1,        Table_Initial => 128);     type Simultaneous_Record is record diff --git a/src/simul/simul-vhdl_simul.adb b/src/simul/simul-vhdl_simul.adb index 5d691e807..8ba0442ed 100644 --- a/src/simul/simul-vhdl_simul.adb +++ b/src/simul/simul-vhdl_simul.adb @@ -18,16 +18,19 @@  with System;  with Ada.Unchecked_Conversion; +with Ada.Unchecked_Deallocation;  with Simple_IO;  with Utils_IO;  with Vhdl.Errors; +with Vhdl.Utils;  with Vhdl.Sem_Inst;  with Vhdl.Canon;  with Elab.Vhdl_Objtypes; use Elab.Vhdl_Objtypes;  with Elab.Vhdl_Values; use Elab.Vhdl_Values; +with Elab.Vhdl_Types;  with Elab.Vhdl_Decls;  with Elab.Debugger; @@ -1368,10 +1371,190 @@ package body Simul.Vhdl_Simul is  --      end if;     end Create_Processes; +   type Resolver_Read_Mode is (Read_Port, Read_Driver); + +   procedure Resolver_Read_Value (Dst : Memtyp; +                                  Sig : Memory_Ptr; +                                  Mode : Resolver_Read_Mode; +                                  Index : Ghdl_Index_Type) +   is +      Val : Ghdl_Value_Ptr; +   begin +      case Dst.Typ.Kind is +         when Type_Bit +           | Type_Logic +           | Type_Discrete => +            null; +         when others => +            raise Internal_Error; +      end case; +      case Mode is +         when Read_Port => +            Val := Ghdl_Signal_Read_Port (Read_Sig (Sig), Index); +         when Read_Driver => +            Val := Ghdl_Signal_Read_Driver (Read_Sig (Sig), Index); +      end case; +      case Dst.Typ.Kind is +         when Type_Bit => +            Write_U8 (Dst.Mem, Ghdl_B1'Pos (Val.B1)); +         when Type_Logic => +            Write_U8 (Dst.Mem, Val.E8); +         when others => +            raise Internal_Error; +      end case; +   end Resolver_Read_Value; + +   procedure Write_Ghdl_Value (Mt : Memtyp; Val : out Value_Union) is +   begin +      case Mt.Typ.Kind is +         when Type_Bit => +            Val.B1 := Ghdl_B1'Val (Read_U8 (Mt.Mem)); +         when Type_Logic => +            Val.E8 := Read_U8 (Mt.Mem); +         when others => +            raise Internal_Error; +      end case; +   end Write_Ghdl_Value; + +   type Write_Signal_Enum is +     (Write_Signal_Driving_Value, +      Write_Signal_Effective_Value); + +   procedure Exec_Write_Signal (Sig: Memory_Ptr; +                                Val : Memtyp; +                                Attr : Write_Signal_Enum) +   is +      S : Ghdl_Signal_Ptr; +   begin +      case Val.Typ.Kind is +         when Type_Bit +           | Type_Logic => +            S := Read_Sig (Sig); +            case Attr is +               when Write_Signal_Driving_Value => +                  Write_Ghdl_Value (Val, S.Driving_Value); +               when Write_Signal_Effective_Value => +                  Write_Ghdl_Value (Val, S.Value_Ptr.all); +            end case; +         when others => +            raise Internal_Error; +      end case; +   end Exec_Write_Signal; + +   type Nbr_Sources_Vector is array (Uns32 range <>) of Natural; +   type Nbr_Sources_Vector_Acc is access Nbr_Sources_Vector; +   procedure Free is new Ada.Unchecked_Deallocation +     (Nbr_Sources_Vector, Nbr_Sources_Vector_Acc); + +   --  Compute the number of sources (drivers + conn) for each scalar +   --  sub-element of signal SIG. +   procedure Compute_Nbr_Sources (Vec : in out Nbr_Sources_Vector; +                                  Sig : Signal_Index_Type) +   is +      type Proc_Sources_Vector is array (Uns32 range <>) of +        Process_Index_Type; +      type Proc_Sources_Vector_Acc is access Proc_Sources_Vector; +      procedure Free is new Ada.Unchecked_Deallocation +        (Proc_Sources_Vector, Proc_Sources_Vector_Acc); +      Procs : Proc_Sources_Vector_Acc; + +      S : Signal_Entry renames Signals_Table.Table (Sig); +      Drv : Driver_Index_Type; +      Conn : Connect_Index_Type; +   begin +      Drv := S.Drivers; + +      if S.Connect = No_Connect_Index then +         if Drv = No_Driver_Index then +            --  No connections, no drivers. +            return; +         end if; + +         declare +            E : Driver_Entry renames Drivers_Table.Table (Drv); +            Off : Uns32; +         begin +            if E.Prev_Sig = No_Driver_Index then +               --  Only one driver, this is probably a very common case. +               pragma Assert (E.Typ.W > 0); +               Off := E.Off.Net_Off; +               for I in Off .. Off + E.Typ.W - 1 loop +                  Vec (I) := Vec (I) + 1; +               end loop; +               return; +            end if; +         end; +      end if; + +      if Drv /= No_Driver_Index then + +         --  Count number of drivers. +         --  We know that drivers from the same process are consecutive in the +         --  driver list for a signal (because drivers are registered by +         --  process). +         Procs := new Proc_Sources_Vector'(0 .. S.Typ.W - 1 => +                                             No_Process_Index); +         loop +            declare +               E : Driver_Entry renames Drivers_Table.Table (Drv); +               Off : constant Uns32 := E.Off.Net_Off; +            begin +               for I in Off .. Off + E.Typ.W - 1 loop +                  if Procs (I) /= E.Proc then +                     Procs (I) := E.Proc; +                     Vec (I) := Vec (I) + 1; +                  end if; +               end loop; + +               Drv := E.Prev_Sig; +            end; +            exit when Drv = No_Driver_Index; +         end loop; +         Free (Procs); +      end if; + +      Conn := S.Connect; +      while Conn /= No_Connect_Index loop +         declare +            C : Connect_Entry renames Connect_Table.Table (Conn); +            Off : Uns32; +         begin +            if C.Formal.Base = Sig then +               if C.Drive_Formal then +                  Off := C.Formal.Offs.Net_Off; +                  for I in Off .. Off + C.Formal.Typ.W - 1 loop +                     Vec (I) := Vec (I) + 1; +                  end loop; +               end if; +               Conn := C.Formal_Link; +            else +               pragma Assert (C.Actual.Base = Sig); +               if C.Drive_Actual then +                  if C.Collapsed then +                     --  A connection with collapsed signal. +                     --  Recurse on the formal. +                     pragma Assert (C.Formal.Offs = (0, 0)); +                     pragma Assert (C.Formal.Typ.W = S.Typ.W); +                     Compute_Nbr_Sources (Vec, C.Formal.Base); +                  else +                     Off := C.Actual.Offs.Net_Off; +                     for I in Off .. Off + C.Actual.Typ.W - 1 loop +                        Vec (I) := Vec (I) + 1; +                     end loop; +                  end if; +               end if; +               Conn := C.Actual_Link; +            end if; +         end; +      end loop; +   end Compute_Nbr_Sources; +     type Resolv_Instance_Type is record        Func : Iir;        Inst : Synth_Instance_Acc;        Sig : Memory_Ptr; +      Idx_Typ : Type_Acc; +      Arr_Typ : Type_Acc;     end record;     type Resolv_Instance_Acc is access Resolv_Instance_Type; @@ -1389,68 +1572,130 @@ package body Simul.Vhdl_Simul is                                Bool_Vec : System.Address;                                Vec_Len : Ghdl_Index_Type;                                Nbr_Drv : Ghdl_Index_Type; -                              Nbr_Ports : Ghdl_Index_Type) is +                              Nbr_Ports : Ghdl_Index_Type) +   is +      pragma Unreferenced (Val); + +      R : Resolv_Instance_Type; +      pragma Import (Ada, R); +      for R'Address use Instance_Addr; + +      type Bool_Array is array (1 .. Nbr_Drv) of Boolean; +      Vec : Bool_Array; +      pragma Import (Ada, Vec); +      for Vec'Address use Bool_Vec; + +      Len : constant Iir_Index32 := Iir_Index32 (Vec_Len + Nbr_Ports); +      Bnd : Bound_Type; + +      El_Typ : constant Type_Acc := R.Arr_Typ.Uarr_El; +      Stride : constant Size_Type := El_Typ.Sz; +      Arr_Typ : Type_Acc; +      Arr : Memtyp; +      Off : Size_Type; + +      Res : Valtyp; + +      Instance_Mark, Expr_Mark : Mark_Type;     begin -      raise Internal_Error; +      Mark (Expr_Mark, Expr_Pool); +      Mark (Instance_Mark, Instance_Pool.all); + +      --  Create the type. +      Bnd := Elab.Vhdl_Types.Create_Bounds_From_Length (R.Idx_Typ.Drange, Len); +      Arr_Typ := Create_Array_Type (Bnd, True, El_Typ); + +      --  Allocate the array. +      Arr := Create_Memory (Arr_Typ); + +      --  Write ports. +      Off := 0; +      for I in 1 .. Nbr_Ports loop +         Resolver_Read_Value ((El_Typ, Arr.Mem + Off), +                              R.Sig, Read_Port, I - 1); +         Off := Off + Stride; +      end loop; + +      --  Write drivers. +      for I in 1 .. Nbr_Drv loop +         if Vec (I) then +            Resolver_Read_Value ((El_Typ, Arr.Mem + Off), +                                 R.Sig, Read_Driver, I - 1); +            Off := Off + Stride; +         end if; +      end loop; + +      --  Call resolution function +      Res := Exec_Resolution_Call (R.Inst, R.Func, Create_Value_Memory (Arr)); + +      --  Set driving value. +      Exec_Write_Signal (R.Sig, (Res.Typ, Res.Val.Mem), +                         Write_Signal_Driving_Value); + +      Release (Expr_Mark, Expr_Pool); +      Release (Instance_Mark, Instance_Pool.all);     end Resolution_Proc; -   -- Create a new signal, using DEFAULT as initial value. -   -- Set its number. -   procedure Create_User_Signal (Inst : Synth_Instance_Acc; -                                 Mode : Mode_Signal_Type; -                                 Signal: Node; -                                 Typ : Type_Acc; -                                 Sig : Memory_Ptr; -                                 Val : Memory_Ptr) +   procedure Create_User_Signal (Idx : Signal_Index_Type)     is ---      use Grt.Signals; +      E : Signal_Entry renames Signals_Table.Table (Idx);        procedure Create_Signal (Val : Memory_Ptr; -                               Sig : Memory_Ptr; +                               Sig_Off : Uns32; +--                               Sig : Memory_Ptr;                                 Sig_Type: Iir;                                 Typ : Type_Acc; +                               Vec : Nbr_Sources_Vector;                                 Already_Resolved : Boolean)        is           Sub_Resolved : Boolean := Already_Resolved;           Resolv_Func : Iir;           Resolv_Instance : Resolv_Instance_Acc;           S : Ghdl_Signal_Ptr; +         Arr_Type : Iir; +         Idx_Type : Iir;        begin           if not Already_Resolved             and then Get_Kind (Sig_Type) in Iir_Kinds_Subtype_Definition           then              Resolv_Func := Get_Resolution_Indication (Sig_Type); -         else -            Resolv_Func := Null_Iir; -         end if; -         if False and Resolv_Func /= Null_Iir then -            Sub_Resolved := True; -            Resolv_Instance := new Resolv_Instance_Type' -              (Func => Get_Named_Entity (Resolv_Func), -               Inst => Inst, -               Sig => Sig); -            Grt.Signals.Ghdl_Signal_Create_Resolution -              (Resolution_Proc'Access, -               Resolv_Instance.all'Address, -               System.Null_Address, -               Ghdl_Index_Type (Typ.W)); +            if Resolv_Func /= Null_Iir +              and then Vec (Sig_Off) > 1 +            then +               Sub_Resolved := True; +               Resolv_Func := Get_Named_Entity (Resolv_Func); +               Arr_Type := +                 Get_Type (Get_Interface_Declaration_Chain (Resolv_Func)); +               Idx_Type := Vhdl.Utils.Get_Index_Type (Arr_Type, 0); +               Resolv_Instance := new Resolv_Instance_Type' +                 (Func => Resolv_Func, +                  Inst => E.Inst, +                  Sig => Sig_Index (E.Sig, Sig_Off), +                  Idx_Typ => Get_Subtype_Object (E.Inst, Idx_Type), +                  Arr_Typ => Get_Subtype_Object (E.Inst, Arr_Type)); +               Grt.Signals.Ghdl_Signal_Create_Resolution +                 (Resolution_Proc'Access, +                  Resolv_Instance.all'Address, +                  System.Null_Address, +                  Ghdl_Index_Type (Typ.W)); +            end if;           end if;           case Typ.Kind is              when Type_Bit =>                 S := Grt.Signals.Ghdl_Create_Signal_B1                   (To_Ghdl_Value_Ptr (To_Address (Val)),                    null, System.Null_Address); -               Write_Sig (Sig, S); +               Write_Sig (Sig_Index (E.Sig, Sig_Off), S);              when Type_Logic =>                 S := Grt.Signals.Ghdl_Create_Signal_E8                   (To_Ghdl_Value_Ptr (To_Address (Val)),                    null, System.Null_Address); -               Write_Sig (Sig, S); +               Write_Sig (Sig_Index (E.Sig, Sig_Off), S);              when Type_Float =>                 S := Grt.Signals.Ghdl_Create_Signal_F64                   (To_Ghdl_Value_Ptr (To_Address (Val)),                    null, System.Null_Address); -               Write_Sig (Sig, S); +               Write_Sig (Sig_Index (E.Sig, Sig_Off), S);              when Type_Discrete =>                 if Typ.Sz = 1 then                    S := Grt.Signals.Ghdl_Create_Signal_E8 @@ -1467,7 +1712,7 @@ package body Simul.Vhdl_Simul is                 else                    raise Internal_Error;                 end if; -               Write_Sig (Sig, S); +               Write_Sig (Sig_Index (E.Sig, Sig_Off), S);              when Type_Vector                | Type_Array =>                 declare @@ -1481,8 +1726,9 @@ package body Simul.Vhdl_Simul is                    end if;                    for I in 1 .. Len loop                       Create_Signal (Val + Size_Type (I - 1) * Typ.Arr_El.Sz, -                                    Sig_Index (Sig, (Len - I) * Typ.Arr_El.W), -                                    El_Type, Typ.Arr_El, Already_Resolved); +                                    Sig_Off + (Len - I) * Typ.Arr_El.W, +                                    El_Type, Typ.Arr_El, +                                    Vec, Already_Resolved);                    end loop;                 end;              when Type_Record => @@ -1495,9 +1741,9 @@ package body Simul.Vhdl_Simul is                       El := Get_Nth_Element (List, Natural (I - 1));                       Create_Signal                         (Val + Typ.Rec.E (I).Offs.Mem_Off, -                        Sig_Index (Sig, Typ.Rec.E (I).Offs.Net_Off), +                        Sig_Off + Typ.Rec.E (I).Offs.Net_Off,                          Get_Type (El), Typ.Rec.E (I).Typ, -                        Sub_Resolved); +                        Vec, Sub_Resolved);                    end loop;                 end; @@ -1512,7 +1758,7 @@ package body Simul.Vhdl_Simul is           end case;        end Create_Signal; -      Sig_Type: constant Iir := Get_Type (Signal); +      Sig_Type: constant Iir := Get_Type (E.Decl);        Kind : Kind_Signal_Type;        type Iir_Kind_To_Kind_Signal_Type is @@ -1520,16 +1766,21 @@ package body Simul.Vhdl_Simul is        Iir_Kind_To_Kind_Signal : constant Iir_Kind_To_Kind_Signal_Type :=          (Iir_Register_Kind  => Kind_Signal_Register,           Iir_Bus_Kind       => Kind_Signal_Bus); + +      Vec : Nbr_Sources_Vector_Acc;     begin -      if Get_Guarded_Signal_Flag (Signal) then -         Kind := Iir_Kind_To_Kind_Signal (Get_Signal_Kind (Signal)); +      if Get_Guarded_Signal_Flag (E.Decl) then +         Kind := Iir_Kind_To_Kind_Signal (Get_Signal_Kind (E.Decl));        else           Kind := Kind_Signal_No;        end if; -      Grt.Signals.Ghdl_Signal_Set_Mode (Mode, Kind, True); +      Grt.Signals.Ghdl_Signal_Set_Mode (E.Kind, Kind, True); -      Create_Signal (Val, Sig, Sig_Type, Typ, False); +      Vec := new Nbr_Sources_Vector'(0 .. E.Typ.W - 1 => 0); +      Compute_Nbr_Sources (Vec.all, Idx); +      Create_Signal (E.Val, 0, Sig_Type, E.Typ, Vec.all, False); +      Free (Vec);     end Create_User_Signal;     function Alloc_Signal_Memory (Vtype : Type_Acc) return Memory_Ptr @@ -1543,7 +1794,9 @@ package body Simul.Vhdl_Simul is        return To_Memory_Ptr (M);     end Alloc_Signal_Memory; -   procedure Create_Signal (E : in out Signal_Entry) is +   procedure Create_Signal (Idx : Signal_Index_Type) +   is +      E : Signal_Entry renames Signals_Table.Table (Idx);     begin        E.Sig := Alloc_Signal_Memory (E.Typ);        case E.Kind is @@ -1560,7 +1813,7 @@ package body Simul.Vhdl_Simul is           when Mode_Above =>              raise Internal_Error;           when Mode_Signal_User => -            Create_User_Signal (E.Inst, E.Kind, E.Decl, E.Typ, E.Sig, E.Val); +            Create_User_Signal (Idx);           when Mode_Conv_In | Mode_Conv_Out | Mode_End =>              raise Internal_Error;        end case; @@ -1578,7 +1831,7 @@ package body Simul.Vhdl_Simul is                 --  TODO: keep val ?                 E.Val := Signals_Table.Table (E.Collapsed_By).Val;              else -               Create_Signal (E); +               Create_Signal (I);              end if;           end;        end loop; diff --git a/src/synth/synth-vhdl_stmts.adb b/src/synth/synth-vhdl_stmts.adb index d60d7095c..50aaae65a 100644 --- a/src/synth/synth-vhdl_stmts.adb +++ b/src/synth/synth-vhdl_stmts.adb @@ -2236,12 +2236,11 @@ package body Synth.Vhdl_Stmts is     function Synth_Static_Subprogram_Call (Syn_Inst : Synth_Instance_Acc;                                            Sub_Inst : Synth_Instance_Acc; -                                          Call     : Node; +                                          Imp      : Node;                                            Bod      : Node; -                                          Init : Association_Iterator_Init) -                                         return Valtyp +                                          Init : Association_Iterator_Init; +                                          Loc : Node) return Valtyp     is -      Imp  : constant Node := Get_Implementation (Call);        Is_Func : constant Boolean := Is_Function_Declaration (Imp);        Res : Valtyp;        C : Seq_Context (Mode_Static); @@ -2271,7 +2270,7 @@ package body Synth.Vhdl_Stmts is           if Is_Func then              if C.Nbr_Ret = 0 then                 Error_Msg_Synth -                 (+Call, "function call completed without a return statement"); +                 (+Loc, "function call completed without a return statement");                 Res := No_Valtyp;              else                 pragma Assert (C.Nbr_Ret = 1); @@ -2338,7 +2337,7 @@ package body Synth.Vhdl_Stmts is           if Get_Instance_Const (Sub_Inst) then              Res := Synth_Static_Subprogram_Call -              (Syn_Inst, Sub_Inst, Call, Bod, Init); +              (Syn_Inst, Sub_Inst, Imp, Bod, Init, Call);           else              Res := Synth_Dynamic_Subprogram_Call                (Syn_Inst, Sub_Inst, Call, Init); @@ -2446,6 +2445,31 @@ package body Synth.Vhdl_Stmts is        end case;     end Synth_Procedure_Call; +   function Exec_Resolution_Call (Syn_Inst : Synth_Instance_Acc; +                                  Func : Node; +                                  Arg : Valtyp) return Valtyp +   is +      Bod : constant Node := Vhdl.Sem_Inst.Get_Subprogram_Body_Origin (Func); +      Inter : constant Node := Get_Interface_Declaration_Chain (Func); +      Init : Association_Iterator_Init; +      Res : Valtyp; +      Sub_Inst : Synth_Instance_Acc; +   begin +      Sub_Inst := Synth_Subprogram_Call_Instance (Syn_Inst, Func, Bod); +      Set_Instance_Const (Sub_Inst, True); + +      Create_Object (Sub_Inst, Inter, Arg); + +      Init := Association_Iterator_Build (Inter, Null_Node); + +      Res := Synth_Static_Subprogram_Call +        (Syn_Inst, Sub_Inst, Func, Bod, Init, Func); + +      Free_Instance (Sub_Inst); + +      return Res; +   end Exec_Resolution_Call; +     --  Return True iff WID is a static wire and its value is V.     function Is_Static_Bit (Wid : Wire_Id; V : Ghdl_U8) return Boolean     is diff --git a/src/synth/synth-vhdl_stmts.ads b/src/synth/synth-vhdl_stmts.ads index 44ffe890b..f41c8ca0c 100644 --- a/src/synth/synth-vhdl_stmts.ads +++ b/src/synth/synth-vhdl_stmts.ads @@ -122,6 +122,11 @@ package Synth.Vhdl_Stmts is        Inter_Chain : Node;        Assoc_Chain : Node); +   --  For simulation. +   function Exec_Resolution_Call (Syn_Inst : Synth_Instance_Acc; +                                  Func : Node; +                                  Arg : Valtyp) return Valtyp; +     --  Return the statements chain to be executed.     function Execute_Static_Case_Statement       (Inst : Synth_Instance_Acc; Stmt : Node; Sel : Valtyp) return Node; | 
