diff options
Diffstat (limited to 'src/synth/netlists-memories.adb')
-rw-r--r-- | src/synth/netlists-memories.adb | 151 |
1 files changed, 62 insertions, 89 deletions
diff --git a/src/synth/netlists-memories.adb b/src/synth/netlists-memories.adb index 84267ea44..8e62137e6 100644 --- a/src/synth/netlists-memories.adb +++ b/src/synth/netlists-memories.adb @@ -438,7 +438,8 @@ package body Netlists.Memories is -- Return True iff MUX_INP is a mux2 input whose output is connected to a -- dff to create a DFF with enable (the other mux2 input is connected to -- the dff output). - function Is_Enable_Dff (Mux_Inp : Input) return Boolean + procedure Is_Enable_Dff + (Mux_Inp : Input; Res : out Boolean; Inv : out Boolean) is Mux_Inst : constant Instance := Get_Input_Parent (Mux_Inp); pragma Assert (Get_Id (Mux_Inst) = Id_Mux2); @@ -446,42 +447,56 @@ package body Netlists.Memories is Inp : Input; Dff_Inst : Instance; Dff_Out : Net; + Prt : Port_Idx; begin + Inv := False; + Res := False; + Inp := Get_First_Sink (Mux_Out); if Inp = No_Input or else Get_Next_Sink (Inp) /= No_Input then -- The output of the mux must be connected to one input. - return False; + return; end if; + + -- Check if the mux is before a dff. Dff_Inst := Get_Input_Parent (Inp); if Get_Id (Dff_Inst) /= Id_Dff then - return False; + return; end if; + Dff_Out := Get_Output (Dff_Inst, 0); if Mux_Inp = Get_Input (Mux_Inst, 1) then - return Skip_Signal (Get_Input_Net (Mux_Inst, 2)) = Dff_Out; + -- Loop on sel = 1 (so enable is inverted). + Inv := True; + Prt := 2; else - return Skip_Signal (Get_Input_Net (Mux_Inst, 1)) = Dff_Out; + -- Loop on sel = 0. + Prt := 1; end if; + Res := Skip_Signal (Get_Input_Net (Mux_Inst, Prt)) = Dff_Out; end Is_Enable_Dff; - -- INST is a Dyn_Extract. - -- 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. + -- EXTR_INST is a Dyn_Extract. + -- If EXTR_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; + Extr_Inst : Instance; Last_Inst : out Instance; Clk : out Net; En : out Net) is - Val : constant Net := Get_Output (Inst, 0); + Val : constant Net := Get_Output (Extr_Inst, 0); Inp : Input; Iinst : Instance; + Is_Dff : Boolean; + Is_Inv : Boolean; begin Inp := Get_First_Sink (Val); if Get_Next_Sink (Inp) = No_Input then - -- There is a single input. + -- The output of INST (a Dyn_Extract) goes to only one gate. Iinst := Get_Input_Parent (Inp); + if Get_Id (Iinst) = Id_Dff then -- The output of the dyn_extract is directly connected to a dff. -- So this is a synchronous read without enable. @@ -496,7 +511,13 @@ package body Netlists.Memories is Last_Inst := Iinst; return; end; - elsif Get_Id (Iinst) = Id_Mux2 and then Is_Enable_Dff (Inp) then + end if; + if Get_Id (Iinst) = Id_Mux2 then + Is_Enable_Dff (Inp, Is_Dff, Is_Inv); + else + Is_Dff := False; + end if; + if Is_Dff then declare Mux_Out : constant Net := Get_Output (Iinst, 0); Mux_En_Inp : constant Input := Get_Input (Iinst, 0); @@ -504,12 +525,11 @@ package body Netlists.Memories is Mux_I1_Inp : constant Input := Get_Input (Iinst, 2); Dff_Din : constant Input := Get_First_Sink (Mux_Out); Dff_Inst : constant Instance := Get_Input_Parent (Dff_Din); - Dff_Out : constant Net := Get_Output (Dff_Inst, 0); Clk_Inp : constant Input := Get_Input (Dff_Inst, 0); begin Clk := Get_Driver (Clk_Inp); En := Get_Driver (Mux_En_Inp); - if Dff_Out = Get_Driver (Mux_I1_Inp) then + if Is_Inv then En := Build_Monadic (Ctxt, Id_Not, En); Copy_Location (En, Iinst); end if; @@ -525,7 +545,7 @@ package body Netlists.Memories is end if; end if; - Last_Inst := Inst; + Last_Inst := Extr_Inst; Clk := No_Net; En := No_Net; end Extract_Extract_Dff; @@ -1019,89 +1039,43 @@ package body Netlists.Memories is -- VAL is the output of the dyn_extract. -- -- Infere a synchronous read if the dyn_extract is connected to a dff. - function Create_ROM_Read_Port - (Ctxt : Context_Acc; Last : Net; Addr : Net; Val : Net; Step : Width) - return Instance + function Create_ROM_Read_Port (Ctxt : Context_Acc; + Last : Net; + Addr : Net; + Extr_Inst : Instance; + Step : Width) return Instance is + Val : constant Net := Get_Output (Extr_Inst, 0); W : constant Width := Get_Width (Val); Res : Instance; - Inp : Input; - Iinst : Instance; + Dff_Inst : Instance; N : Net; + Clk : Net; + En : Net; begin - Inp := Get_First_Sink (Val); - if Get_Next_Sink (Inp) = No_Input then - -- There is a single input. - Iinst := Get_Input_Parent (Inp); - if Get_Id (Iinst) = Id_Dff then - -- The output of the dyn_extract is directly connected to a dff. - -- So this is a synchronous read without enable. - declare - Clk_Inp : Input; - Clk : Net; - En : Net; - begin - Clk_Inp := Get_Input (Iinst, 0); - Clk := Get_Driver (Clk_Inp); - Disconnect (Clk_Inp); - En := Build_Const_UB32 (Ctxt, 1, 1); - Disconnect (Inp); - Res := Build_Mem_Rd_Sync (Ctxt, Last, Addr, Clk, En, Step); - - -- Slice the output. - N := Get_Output (Res, 1); - N := Build2_Extract (Ctxt, N, 0, W); - - Redirect_Inputs (Get_Output (Iinst, 0), N); - Remove_Instance (Iinst); - return Res; - end; - elsif Get_Id (Iinst) = Id_Mux2 and then Is_Enable_Dff (Inp) then - declare - Mux_Out : constant Net := Get_Output (Iinst, 0); - Mux_En_Inp : constant Input := Get_Input (Iinst, 0); - Mux_I0_Inp : constant Input := Get_Input (Iinst, 1); - Mux_I1_Inp : constant Input := Get_Input (Iinst, 2); - Dff_Din : constant Input := Get_First_Sink (Mux_Out); - Dff_Inst : constant Instance := Get_Input_Parent (Dff_Din); - Dff_Out : constant Net := Get_Output (Dff_Inst, 0); - Clk_Inp : constant Input := Get_Input (Dff_Inst, 0); - Clk : constant Net := Get_Driver (Clk_Inp); - En : Net; - begin - En := Get_Driver (Mux_En_Inp); - if Dff_Out = Get_Driver (Mux_I1_Inp) then - En := Build_Monadic (Ctxt, Id_Not, En); - Copy_Location (En, Dff_Inst); - end if; - Disconnect (Mux_En_Inp); - Disconnect (Mux_I0_Inp); - Disconnect (Mux_I1_Inp); - Disconnect (Dff_Din); - Disconnect (Clk_Inp); - Remove_Instance (Iinst); - Res := Build_Mem_Rd_Sync (Ctxt, Last, Addr, Clk, En, Step); - Set_Location (Res, Get_Location (Dff_Inst)); - - -- Slice the output. - N := Get_Output (Res, 1); - N := Build2_Extract (Ctxt, N, 0, W); - - Redirect_Inputs (Dff_Out, N); - Remove_Instance (Dff_Inst); - return Res; - end; + Extract_Extract_Dff (Ctxt, Extr_Inst, Dff_Inst, Clk, En); + if Dff_Inst /= Extr_Inst then + -- There was a dff, so the read port is synchronous. + if En = No_Net then + En := Build_Const_UB32 (Ctxt, 1, 1); end if; - end if; - -- Replace Dyn_Extract with mem_rd. - Res := Build_Mem_Rd (Ctxt, Last, Addr, Step); + Res := Build_Mem_Rd_Sync (Ctxt, Last, Addr, Clk, En, Step); + else + -- Replace Dyn_Extract with mem_rd (asynchronous read port). + Res := Build_Mem_Rd (Ctxt, Last, Addr, Step); + end if; -- Slice the output. N := Get_Output (Res, 1); N := Build2_Extract (Ctxt, N, 0, W); - Redirect_Inputs (Val, N); + if Dff_Inst /= Extr_Inst then + Redirect_Inputs (Get_Output (Dff_Inst, 0), N); + Remove_Instance (Dff_Inst); + else + Redirect_Inputs (Get_Output (Extr_Inst, 0), N); + end if; return Res; end Create_ROM_Read_Port; @@ -1117,7 +1091,6 @@ package body Netlists.Memories is Extr_Inst : Instance; Addr_Inp : Input; Addr : Net; - Val : Net; Port_Inst : Instance; begin Last := Get_Output (Mem_Inst, 0); @@ -1142,11 +1115,11 @@ package body Netlists.Memories is Addr_Inp := Get_Input (Extr_Inst, 1); Addr := Get_Driver (Addr_Inp); Disconnect (Addr_Inp); - Val := Get_Output (Extr_Inst, 0); Convert_Memidx (Ctxt, Orig, Addr, Step); -- Replace Dyn_Extract with mem_rd. - Port_Inst := Create_ROM_Read_Port (Ctxt, Last, Addr, Val, Step); + Port_Inst := Create_ROM_Read_Port + (Ctxt, Last, Addr, Extr_Inst, Step); Remove_Instance (Extr_Inst); |