From a036958a9adc31011729aab02af9eec48f80bc8a Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Mon, 27 Jun 2022 19:28:01 +0200 Subject: synth: rework #2109 - remove null wires --- src/ghdldrv/ghdlsynth.adb | 2 ++ src/synth/netlists-cleanup.adb | 27 ++++++++++++++++ src/synth/netlists-cleanup.ads | 6 ++++ src/synth/netlists-disp_verilog.adb | 3 -- src/synth/netlists-expands.adb | 62 +++++++++++++++++++++++-------------- src/synth/netlists-memories.adb | 5 +++ src/synth/synth-flags.ads | 4 +++ src/synth/synthesis.adb | 4 +++ 8 files changed, 87 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/ghdldrv/ghdlsynth.adb b/src/ghdldrv/ghdlsynth.adb index 8ee8e02d8..138dca8df 100644 --- a/src/ghdldrv/ghdlsynth.adb +++ b/src/ghdldrv/ghdlsynth.adb @@ -227,6 +227,8 @@ package body Ghdlsynth is Flag_Debug_Elaborate := True; elsif Option = "-de" then Flag_Debug_Noexpand := True; + elsif Option = "-dn" then + Flag_Debug_Nonull := True; elsif Option = "-t" then Flag_Trace_Statements := True; elsif Option = "-i" then diff --git a/src/synth/netlists-cleanup.adb b/src/synth/netlists-cleanup.adb index c2fc603b4..52b3c87e0 100644 --- a/src/synth/netlists-cleanup.adb +++ b/src/synth/netlists-cleanup.adb @@ -385,4 +385,31 @@ package body Netlists.Cleanup is end; end Mark_And_Sweep; + procedure Replace_Null_Inputs (Ctxt : Context_Acc; M : Module) + is + Inst : Instance; + Drv : Net; + Inp : Input; + Null_X : Net; + begin + Null_X := No_Net; + + Inst := Get_First_Instance (M); + while Inst /= No_Instance loop + for I in 1 .. Get_Nbr_Inputs (Inst) loop + Inp := Get_Input (Inst, I - 1); + Drv := Get_Driver (Inp); + if Drv /= No_Net and then Get_Width (Drv) = 0 then + if Null_X = No_Net then + Null_X := Build_Const_X (Ctxt, 0); + end if; + Disconnect (Inp); + Connect (Inp, Null_X); + end if; + end loop; + + Inst := Get_Next_Instance (Inst); + end loop; + end Replace_Null_Inputs; + end Netlists.Cleanup; diff --git a/src/synth/netlists-cleanup.ads b/src/synth/netlists-cleanup.ads index be4f0e0fb..a13e66c47 100644 --- a/src/synth/netlists-cleanup.ads +++ b/src/synth/netlists-cleanup.ads @@ -16,6 +16,8 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . +with Netlists.Builders; use Netlists.Builders; + package Netlists.Cleanup is -- Remove instances of module M whose outputs are not connected. -- Their inputs will be deconnected, which can result in new instances @@ -26,6 +28,10 @@ package Netlists.Cleanup is -- sweep algorithm. procedure Mark_And_Sweep (M : Module); + -- Reconnection inputs of width 0 (the null inputs) to an Const_X gate. + -- This will make all the null logic unconnected and ready to be cleaned. + procedure Replace_Null_Inputs (Ctxt : Context_Acc; M : Module); + -- Remove Id_Output gates. procedure Remove_Output_Gates (M : Module); end Netlists.Cleanup; diff --git a/src/synth/netlists-disp_verilog.adb b/src/synth/netlists-disp_verilog.adb index b2461bf2f..f28a1b536 100644 --- a/src/synth/netlists-disp_verilog.adb +++ b/src/synth/netlists-disp_verilog.adb @@ -1149,9 +1149,6 @@ package body Netlists.Disp_Verilog is or else (Flag_Merge_Edge and then Id in Edge_Module_Id and then not Need_Edge (Inst)) - or else (not Flag_Null_Wires - and then Get_Nbr_Outputs (Inst) = 1 - and then Get_Width (Get_Output (Inst, 0)) = 0) then -- Not displayed. null; diff --git a/src/synth/netlists-expands.adb b/src/synth/netlists-expands.adb index efb9fc93f..0f69dd93d 100644 --- a/src/synth/netlists-expands.adb +++ b/src/synth/netlists-expands.adb @@ -46,6 +46,9 @@ package body Netlists.Expands is N := Addr_Net; Nbr_Els := 1; P := Memidx_Arr'Last; + if P = 0 then + return; + end if; loop Ninst := Get_Net_Parent (N); case Get_Id (Ninst) is @@ -213,34 +216,47 @@ package body Netlists.Expands is -- 2. compute number of cells. Gather_Memidx (Addr_Net, Memidx_Arr, Nbr_Els); - -- 2. build extract gates - Els := new Case_Element_Array (1 .. Nbr_Els); - declare - Idx : Positive; - Off : Uns32; - Sel : Uns64; - begin - Idx := 1; - Off := Get_Param_Uns32 (Inst, 0); - Sel := 0; - Fill_Els (Ctxt, Memidx_Arr, 1, Val, Els, Idx, Addr_Net, Off, W, Sel); - end; + if Nbr_Els = 1 then + -- There is only one element, so it's not really dynamic. + -- Just return the value. + Res := Get_Input_Net (Inst, 0); + -- Disconnect the address + Addr := Disconnect_And_Get (Inst, 1); + if not Is_Connected (Addr) then + -- Should be a Const_X. + Remove_Instance (Get_Net_Parent (Addr)); + end if; + else + -- 2. build extract gates + Els := new Case_Element_Array (1 .. Nbr_Els); + declare + Idx : Positive; + Off : Uns32; + Sel : Uns64; + begin + Idx := 1; + Off := Get_Param_Uns32 (Inst, 0); + Sel := 0; + Fill_Els (Ctxt, Memidx_Arr, + 1, Val, Els, Idx, Addr_Net, Off, W, Sel); + end; - -- 3. build mux tree - Disconnect (Get_Input (Inst, 1)); - Extract_Address (Ctxt, Addr_Net, Ndims, Addr); - Truncate_Address (Ctxt, Addr, Nbr_Els); - Def := No_Net; - Synth_Case (Ctxt, Addr, Els.all, Def, Res, Loc); + -- 3. build mux tree + Disconnect (Get_Input (Inst, 1)); + Extract_Address (Ctxt, Addr_Net, Ndims, Addr); + Truncate_Address (Ctxt, Addr, Nbr_Els); + Def := No_Net; + Synth_Case (Ctxt, Addr, Els.all, Def, Res, Loc); + + -- 4. remove old dyn_extract. + Remove_Memidx (Memidx_Arr); + + Free_Case_Element_Array (Els); + end if; - -- 4. remove old dyn_extract. Disconnect (Get_Input (Inst, 0)); Redirect_Inputs (Get_Output (Inst, 0), Res); Remove_Instance (Inst); - - Remove_Memidx (Memidx_Arr); - - Free_Case_Element_Array (Els); end Expand_Dyn_Extract; procedure Generate_Decoder (Ctxt : Context_Acc; diff --git a/src/synth/netlists-memories.adb b/src/synth/netlists-memories.adb index 2764ec380..ffc3316ba 100644 --- a/src/synth/netlists-memories.adb +++ b/src/synth/netlists-memories.adb @@ -243,6 +243,11 @@ package body Netlists.Memories is end if; Res := Res + 1; N := Get_Input_Net (Inst, 0); + when Id_Const_X => + -- For a null wire. + pragma Assert (Res = 0); + pragma Assert (Get_Width (N) = 0); + return 0; when others => raise Internal_Error; end case; diff --git a/src/synth/synth-flags.ads b/src/synth/synth-flags.ads index fed17efc1..211c01c1d 100644 --- a/src/synth/synth-flags.ads +++ b/src/synth/synth-flags.ads @@ -51,8 +51,12 @@ package Synth.Flags is Flag_Debug_Nomemory2 : Boolean := False; + -- Do not expand dynamic gates. Flag_Debug_Noexpand : Boolean := False; + -- Do not transform null net to null X. + Flag_Debug_Nonull : Boolean := False; + Flag_Trace_Statements : Boolean := False; -- Display source of elaborated design. diff --git a/src/synth/synthesis.adb b/src/synth/synthesis.adb index 310a30a59..911b2d5f6 100644 --- a/src/synth/synthesis.adb +++ b/src/synth/synthesis.adb @@ -79,6 +79,10 @@ package body Synthesis is procedure Instance_Passes (Ctxt : Context_Acc; M : Module) is begin + if not Synth.Flags.Flag_Debug_Nonull then + Netlists.Cleanup.Replace_Null_Inputs (Ctxt, M); + end if; + -- Remove unused gates. This is not only an optimization but also -- a correctness point: there might be some unsynthesizable gates, like -- the one created for 'rising_egde (clk) and not rst'. -- cgit v1.2.3