aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/netlists-memories.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/synth/netlists-memories.adb')
-rw-r--r--src/synth/netlists-memories.adb151
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);