diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/synth/netlists-expands.adb | 222 | ||||
| -rw-r--r-- | src/synth/netlists-expands.ads | 25 | ||||
| -rw-r--r-- | src/synth/netlists-memories.ads | 4 | ||||
| -rw-r--r-- | src/synth/synth-flags.ads | 4 | ||||
| -rw-r--r-- | src/synth/synth-insts.adb | 5 | 
5 files changed, 259 insertions, 1 deletions
| diff --git a/src/synth/netlists-expands.adb b/src/synth/netlists-expands.adb new file mode 100644 index 000000000..8689f1f59 --- /dev/null +++ b/src/synth/netlists-expands.adb @@ -0,0 +1,222 @@ +--  Expand dyn gates. +--  Copyright (C) 2019 Tristan Gingold +-- +--  This file is part of GHDL. +-- +--  This program is free software; you can redistribute it and/or modify +--  it under the terms of the GNU General Public License as published by +--  the Free Software Foundation; either version 2 of the License, or +--  (at your option) any later version. +-- +--  This program is distributed in the hope that it will be useful, +--  but WITHOUT ANY WARRANTY; without even the implied warranty of +--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +--  GNU General Public License for more details. +-- +--  You should have received a copy of the GNU General Public License +--  along with this program; if not, write to the Free Software +--  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +--  MA 02110-1301, USA. + +with Netlists.Gates; use Netlists.Gates; +with Netlists.Utils; use Netlists.Utils; +with Netlists.Butils; use Netlists.Butils; +with Netlists.Locations; use Netlists.Locations; +with Netlists.Memories; use Netlists.Memories; + +package body Netlists.Expands is +   function Count_Nbr_Elements (Addr : Net) return Natural +   is +      N : Net; +      Inst, Inst1 : Instance; +      Res : Natural; +      Max : Uns32; +   begin +      N := Addr; +      Res := 1; +      loop +         Inst := Get_Net_Parent (N); +         case Get_Id (Inst) is +            when Id_Memidx => +               Inst1 := Inst; +            when Id_Addidx => +               Inst1 := Get_Net_Parent (Get_Input_Net (Inst, 1)); +               pragma Assert (Get_Id (Inst1) = Id_Memidx); + +               N := Get_Input_Net (Inst, 0); +            when others => +               raise Internal_Error; +         end case; + +         Max := Get_Param_Uns32 (Inst1, 1); +         pragma Assert (Max /= 0); +         Res := Res * Natural (Max); + +         exit when Inst1 = Inst; +      end loop; + +      return Res; +   end Count_Nbr_Elements; + +   --  IDX is the next index to be fill in ELS. +   --  OFF is offset for extraction from VAL. +   --  ADDR_OFF is the address offset. +   procedure Fill_Els (Ctxt : Context_Acc; +                       Val : Net; +                       Els : Case_Element_Array_Acc; +                       Idx : in out Positive; +                       Addr : Net; +                       Off : in out Uns32; +                       W : Width; +                       Sel : in out Uns64) +   is +      Inst : Instance; +      Sub_Inst : Instance; +   begin +      --  Extract memidx. +      Inst := Get_Net_Parent (Addr); +      case Get_Id (Inst) is +         when Id_Memidx => +            --  Found. +            Sub_Inst := No_Instance; +            null; +         when Id_Addidx => +            --  Will recurse. +            Sub_Inst := Get_Net_Parent (Get_Input_Net (Inst, 0)); + +            Inst := Get_Net_Parent (Get_Input_Net (Inst, 1)); +            pragma Assert (Get_Id (Inst) = Id_Memidx); + +         when others => +            raise Internal_Error; +      end case; + +      declare +         Step : constant Uns32 := Get_Param_Uns32 (Inst, 0); +         Max : constant Uns32 := Get_Param_Uns32 (Inst, 1); +      begin +         pragma Assert (Max /= 0); + +         for I in 0 .. Max - 1 loop +            if Sub_Inst /= No_Instance then +               --  recurse. +               raise Internal_Error; +            else +               Els (Idx) := (Sel => Sel, +                             Val => Build_Extract (Ctxt, Val, Off, W)); +               Idx := Idx + 1; +               Sel := Sel + 1; +               Off := Off + Step; +            end if; +         end loop; +      end; +   end Fill_Els; + +   --  Extract address from memidx/addidx and remove those gates. +   procedure Extract_Address +     (Ctxt : Context_Acc; Addr_Net : Net; Ndims : Natural; Addr : out Net) +   is +      Res_Arr : Net_Array (1 .. Int32 (Ndims)); +      P : Int32; +      Inst, Inst1 : Instance; +      Inp : Input; +      N : Net; +   begin +      P := Res_Arr'Last; +      N := Addr_Net; +      loop +         Inst := Get_Net_Parent (N); +         case Get_Id (Inst) is +            when Id_Memidx => +               Inst1 := Inst; +            when Id_Addidx => +               --  Extract memidx. +               Inp := Get_Input (Inst, 1); +               Inst1 := Get_Net_Parent (Get_Driver (Inp)); +               pragma Assert (Get_Id (Inst1) = Id_Memidx); +               Disconnect (Inp); + +               --  Extract next. +               Inp := Get_Input (Inst, 0); +               N := Get_Driver (Inp); +               Disconnect (Inp); + +               Remove_Instance (Inst); +            when others => +               raise Internal_Error; +         end case; + +         --  INST1 is a memidx. +         Inp := Get_Input (Inst1, 0); +         Res_Arr (P) := Get_Driver (Inp); +         P := P - 1; + +         Disconnect (Inp); +         Remove_Instance (Inst1); + +         exit when Inst1 = Inst; +      end loop; +      pragma Assert (P = 0); + +      Addr := Build2_Concat (Ctxt, Res_Arr); +   end Extract_Address; + +   procedure Expand_Dyn_Extract (Ctxt : Context_Acc; Inst : Instance) +   is +      Val : constant Net := Get_Input_Net (Inst, 0); +      Addr_Net : constant Net := Get_Input_Net (Inst, 1); +      Loc : constant Location_Type := Get_Location (Inst); +      W : constant Width := Get_Width (Get_Output (Inst, 0)); +      --  1. compute number of dims, check order. +      Ndims : constant Natural := Count_Memidx (Addr_Net); +      --  2. compute number of cells. +      Nbr_Els : constant Natural := Count_Nbr_Elements (Addr_Net); + +      Els : Case_Element_Array_Acc; +      Idx : Positive; +      Off : Uns32; +      Sel : Uns64; +      Res : Net; +      Addr : Net; +      Def : Net; +   begin +      --  2. build extract gates +      Els := new Case_Element_Array (1 .. Nbr_Els); +      Idx := 1; +      Off := Get_Param_Uns32 (Inst, 0); +      Sel := 0; +      Fill_Els (Ctxt, Val, Els, Idx, Addr_Net, Off, W, Sel); + +      --  3. build mux tree +      Extract_Address (Ctxt, Addr_Net, Ndims, Addr); +      Def := No_Net; +      Synth_Case (Ctxt, Addr, Els.all, Def, Res, Loc); + +      --  4. remove old dyn_extract. +      Disconnect (Get_Input (Inst, 0)); +      Disconnect (Get_Input (Inst, 1)); +      Redirect_Inputs (Get_Output (Inst, 0), Res); +      Remove_Instance (Inst); + +      Free_Case_Element_Array (Els); +   end Expand_Dyn_Extract; + +   procedure Expand_Gates (Ctxt : Context_Acc; M : Module) +   is +      Inst : Instance; +   begin +      Inst := Get_First_Instance (M); +      while Inst /= No_Instance loop +         --  Walk all the instances of M: +         case Get_Id (Inst) is +            when Id_Dyn_Extract => +               Expand_Dyn_Extract (Ctxt, Inst); + +            when others => +               null; +         end case; + +         Inst := Get_Next_Instance (Inst); +      end loop; +   end Expand_Gates; +end Netlists.Expands; diff --git a/src/synth/netlists-expands.ads b/src/synth/netlists-expands.ads new file mode 100644 index 000000000..31dc2b49a --- /dev/null +++ b/src/synth/netlists-expands.ads @@ -0,0 +1,25 @@ +--  Expand dyn gates. +--  Copyright (C) 2019 Tristan Gingold +-- +--  This file is part of GHDL. +-- +--  This program is free software; you can redistribute it and/or modify +--  it under the terms of the GNU General Public License as published by +--  the Free Software Foundation; either version 2 of the License, or +--  (at your option) any later version. +-- +--  This program is distributed in the hope that it will be useful, +--  but WITHOUT ANY WARRANTY; without even the implied warranty of +--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +--  GNU General Public License for more details. +-- +--  You should have received a copy of the GNU General Public License +--  along with this program; if not, write to the Free Software +--  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +--  MA 02110-1301, USA. + +with Netlists.Builders; use Netlists.Builders; + +package Netlists.Expands is +   procedure Expand_Gates (Ctxt : Context_Acc; M : Module); +end Netlists.Expands; diff --git a/src/synth/netlists-memories.ads b/src/synth/netlists-memories.ads index b58ffb29a..f4639c5a6 100644 --- a/src/synth/netlists-memories.ads +++ b/src/synth/netlists-memories.ads @@ -23,4 +23,8 @@ with Netlists.Builders; use Netlists.Builders;  package Netlists.Memories is     --  Try to convert dyn_insert/dyn_extract to memory ports.     procedure Extract_Memories (Ctxt : Context_Acc; M : Module); + +   --  Count the number of memidx in a memory address. +   function Count_Memidx (Addr : Net) return Natural; +  end Netlists.Memories; diff --git a/src/synth/synth-flags.ads b/src/synth/synth-flags.ads index b850d3754..2a22cf304 100644 --- a/src/synth/synth-flags.ads +++ b/src/synth/synth-flags.ads @@ -23,5 +23,7 @@ package Synth.Flags is     Flag_Debug_Nocleanup : Boolean := False; -   Flag_Debug_Nomemory : Boolean := True; +   Flag_Debug_Nomemory : Boolean := False; + +   Flag_Debug_Noexpand : Boolean := True;  end Synth.Flags; diff --git a/src/synth/synth-insts.adb b/src/synth/synth-insts.adb index 055d9b015..69af4a015 100644 --- a/src/synth/synth-insts.adb +++ b/src/synth/synth-insts.adb @@ -29,6 +29,7 @@ with Netlists; use Netlists;  with Netlists.Builders;  with Netlists.Cleanup;  with Netlists.Memories; +with Netlists.Expands;  with Vhdl.Utils; use Vhdl.Utils;  with Vhdl.Errors; @@ -925,6 +926,10 @@ package body Synth.Insts is        if not Synth.Flags.Flag_Debug_Nomemory then           Netlists.Memories.Extract_Memories (Get_Build (Syn_Inst), Inst.M);        end if; + +      if not Synth.Flags.Flag_Debug_Noexpand then +         Netlists.Expands.Expand_Gates (Get_Build (Syn_Inst), Inst.M); +      end if;     end Synth_Instance;     procedure Synth_All_Instances | 
