diff options
author | Tristan Gingold <tgingold@free.fr> | 2019-10-27 21:06:08 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2019-10-27 21:06:08 +0100 |
commit | 497e1e575201f5d3ff68cbd4dc4c0ab9003edf00 (patch) | |
tree | 64a498d78eb6c4d91288c8f73214c77d92422138 /src | |
parent | 21732824cfea2164654635beb5fb28ebd6b37c35 (diff) | |
download | ghdl-497e1e575201f5d3ff68cbd4dc4c0ab9003edf00.tar.gz ghdl-497e1e575201f5d3ff68cbd4dc4c0ab9003edf00.tar.bz2 ghdl-497e1e575201f5d3ff68cbd4dc4c0ab9003edf00.zip |
netlists: add code to expand dyn_extract gates (WIP).
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 |