diff options
author | Tristan Gingold <tgingold@free.fr> | 2020-04-28 08:17:16 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2020-04-28 08:53:10 +0200 |
commit | 83183230bfa25071c6d18df457ba3e2fefa3b001 (patch) | |
tree | 0f50c91af935a535df27aa1342662a0e0ee1f055 /src | |
parent | cf7be93092511d3c05b6d81b989c7ed3103d5fa3 (diff) | |
download | ghdl-83183230bfa25071c6d18df457ba3e2fefa3b001.tar.gz ghdl-83183230bfa25071c6d18df457ba3e2fefa3b001.tar.bz2 ghdl-83183230bfa25071c6d18df457ba3e2fefa3b001.zip |
synth: improve handling of synchronous memory read.
Diffstat (limited to 'src')
-rw-r--r-- | src/synth/netlists-memories.adb | 98 |
1 files changed, 92 insertions, 6 deletions
diff --git a/src/synth/netlists-memories.adb b/src/synth/netlists-memories.adb index 31767e09d..c127b940f 100644 --- a/src/synth/netlists-memories.adb +++ b/src/synth/netlists-memories.adb @@ -454,12 +454,13 @@ package body Netlists.Memories is end if; end Is_Enable_Dff; - procedure Extract_Extract_Dff - (Ctxt : Context_Acc; - Inst : Instance; - Last_Inst : out Instance; - Clk : out Net; - En : out Net) + -- If INST is followed by a dff or a dff+enable (with mux2), return the + -- dff in LAST_INST, the clock in CLK and the enable in EN. + procedure Extract_Extract_Dff (Ctxt : Context_Acc; + Inst : Instance; + Last_Inst : out Instance; + Clk : out Net; + En : out Net) is Val : constant Net := Get_Output (Inst, 0); Inp : Input; @@ -517,6 +518,90 @@ package body Netlists.Memories is En := No_Net; end Extract_Extract_Dff; + -- If dyn_extract gate EXTRACT is followed by a concat and a dff, then + -- swap the dff and the concat. This will allow to merge the dff during + -- the build of mem_rd_sync. + -- This creates new gates (the dff is replicated) that will be removed. + procedure Maybe_Swap_Concat_Dff (Ctxt : Context_Acc; Extract : Instance) + is + Extr_Out : constant Net := Get_Output (Extract, 0); + Concat : Instance; + Concat_Out : Net; + Dff : Instance; + Clk, En : Net; + Loc : Location_Type; + begin + if not Has_One_Connection (Extr_Out) then + -- The dyn_extract is connected to more than one gate. + return; + end if; + + Concat := Get_Input_Parent (Get_First_Sink (Extr_Out)); + case Get_Id (Concat) is + when Concat_Module_Id + | Id_Concatn => + null; + when others => + -- Not a concat. + return; + end case; + + Concat_Out := Get_Output (Concat, 0); + if not Has_One_Connection (Concat_Out) then + -- The concat is connected to more than one gate. + return; + end if; + for I in 1 .. Get_Nbr_Inputs (Concat) loop + declare + Src : constant Net := Get_Input_Net (Concat, I - 1); + begin + if Get_Id (Get_Net_Parent (Src)) /= Id_Dyn_Extract then + -- A source of concat is not a dyn_extract. + return; + end if; + if not Has_One_Connection (Src) then + -- A source of concat drives something else! + return; + end if; + end; + end loop; + + Extract_Extract_Dff (Ctxt, Concat, Dff, Clk, En); + if Clk = No_Net then + return; + end if; + + -- Replicate the dff. + Loc := Get_Location (Dff); + for I in 1 .. Get_Nbr_Inputs (Concat) loop + declare + Inp : constant Input := Get_Input (Concat, I - 1); + Dff2 : Net; + Mux : Net; + Dff2_Inp : Input; + Src : Net; + begin + Src := Disconnect_And_Get (Inp); + + Dff2 := Build_Dff (Ctxt, Clk, Src); + Set_Location (Dff2, Loc); + Connect (Inp, Dff2); + + if En /= No_Net then + Dff2_Inp := Get_Input (Get_Net_Parent (Dff2), 1); + Mux := Build_Mux2 (Ctxt, En, Dff2, Src); + Set_Location (Mux, Loc); + Disconnect (Dff2_Inp); + Connect (Dff2_Inp, Mux); + end if; + end; + end loop; + + -- Reconnect the concat. + Redirect_Inputs (Get_Output (Dff, 0), Concat_Out); + Remove_Instance (Dff); + end Maybe_Swap_Concat_Dff; + -- Create a mem_rd/mem_rd_sync from a dyn_extract gate. -- LAST is the last memory port on the chain. -- ADDR is the address (from the dyn_extract). @@ -1460,6 +1545,7 @@ package body Netlists.Memories is Addr := Get_Driver (Inp2); Disconnect (Inp2); Convert_Memidx (Ctxt, Mem_Sz, Addr, Mem_W); + Maybe_Swap_Concat_Dff (Ctxt, In_Inst); Extract_Extract_Dff (Ctxt, In_Inst, Last_Inst, Clk, En); if Clk /= No_Net and then En = No_Net then En := Build_Const_UB32 (Ctxt, 1, 1); |