aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/netlists-inference.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2020-03-22 08:23:36 +0100
committerTristan Gingold <tgingold@free.fr>2020-03-22 08:23:36 +0100
commit283a032e58d32a72873c647e017da3760bdedb53 (patch)
tree332b757b61753d9c43ddf191b26c67b4e9e1a727 /src/synth/netlists-inference.adb
parente3bac06b441a7e5b95b0a0f662c5e0fce8f57d3c (diff)
downloadghdl-283a032e58d32a72873c647e017da3760bdedb53.tar.gz
ghdl-283a032e58d32a72873c647e017da3760bdedb53.tar.bz2
ghdl-283a032e58d32a72873c647e017da3760bdedb53.zip
synth: handle reuse of inferred dff in the same process.
Fix tgingold/ghdlsynth-beta#93
Diffstat (limited to 'src/synth/netlists-inference.adb')
-rw-r--r--src/synth/netlists-inference.adb47
1 files changed, 37 insertions, 10 deletions
diff --git a/src/synth/netlists-inference.adb b/src/synth/netlists-inference.adb
index e391a6769..0526988ca 100644
--- a/src/synth/netlists-inference.adb
+++ b/src/synth/netlists-inference.adb
@@ -469,6 +469,7 @@ package body Netlists.Inference is
-- LAST_MUX is the mux whose input 0 is the loop and clock for selector.
function Infere_FF (Ctxt : Context_Acc;
+ Val : Net;
Prev_Val : Net;
Off : Uns32;
Last_Mux : Instance;
@@ -513,17 +514,20 @@ package body Netlists.Inference is
declare
Done : Boolean;
Mux : Instance;
+ -- Previous mux to be free.
+ Prev_Mux : Instance;
Sel : Net;
Last_Out : Net;
Mux_Not_Rst : Net;
Mux_Rst : Net;
Mux_Rst_Val : Net;
begin
+ Prev_Mux := No_Instance;
Last_Out := O;
-- Initially, the final output is not connected. So walk from the
-- clocked mux until reaching the final output.
- Done := not Is_Connected (Last_Out);
+ Done := Last_Out = Val;
while not Done loop
if not Has_One_Connection (Last_Out)
@@ -542,12 +546,10 @@ package body Netlists.Inference is
if Get_Driver (Get_Mux2_I0 (Mux)) = Last_Out then
Mux_Rst_Val := Get_Driver (Get_Mux2_I1 (Mux));
Mux_Rst := Sel;
- elsif Get_Driver (Get_Mux2_I1 (Mux)) = Last_Out then
+ else
+ pragma Assert (Get_Driver (Get_Mux2_I1 (Mux)) = Last_Out);
Mux_Rst_Val := Get_Driver (Get_Mux2_I0 (Mux));
Mux_Rst := Build_Monadic (Ctxt, Id_Not, Sel);
- else
- -- Cannot happen.
- raise Internal_Error;
end if;
Last_Out := Get_Output (Mux, 0);
@@ -579,6 +581,11 @@ package body Netlists.Inference is
else
Enable := Build_Dyadic (Ctxt, Id_And, Enable, Mux_Not_Rst);
end if;
+
+ if Prev_Mux /= No_Instance then
+ Remove_Instance (Prev_Mux);
+ end if;
+ Prev_Mux := Mux;
else
-- Assume this is a reset value.
-- FIXME: check for no logical loop.
@@ -592,7 +599,11 @@ package body Netlists.Inference is
-- The output of the mux is now the reset value.
Redirect_Inputs (Last_Out, Mux_Rst_Val);
- Free_Instance (Mux);
+
+ if Prev_Mux /= No_Instance then
+ Remove_Instance (Prev_Mux);
+ end if;
+ Prev_Mux := Mux;
Rst := Mux_Rst;
Rst_Val := Mux_Rst_Val;
@@ -600,12 +611,19 @@ package body Netlists.Inference is
else
Rst := Build_Dyadic (Ctxt, Id_Or, Mux_Rst, Rst);
Rst_Val := Last_Out;
+
+ if Prev_Mux /= No_Instance then
+ Remove_Instance (Prev_Mux);
+ end if;
+ Prev_Mux := No_Instance;
end if;
end if;
end loop;
- end;
- Free_Instance (Last_Mux);
+ if Prev_Mux /= No_Instance then
+ Free_Instance (Mux);
+ end if;
+ end;
if Off = 0
and then Can_Infere_RAM (Data, Prev_Val)
@@ -629,6 +647,12 @@ package body Netlists.Inference is
-- Create the FF.
Res := Infere_FF_Create (Ctxt, Rst, Rst_Val, Init, Clk, Data,
Els, Mux_Loc);
+
+ -- The output may already be used (if the target is a variable that
+ -- is read). So redirect the net.
+ Redirect_Inputs (Get_Output (Last_Mux, 0), Res);
+ Free_Instance (Last_Mux);
+
return Res;
end Infere_FF;
@@ -762,7 +786,7 @@ package body Netlists.Inference is
is
pragma Assert (Val /= No_Net);
pragma Assert (Prev_Val /= No_Net);
- Last_Mux : Instance;
+ First_Mux, Last_Mux : Instance;
Len : Integer;
Sel : Input;
Clk : Net;
@@ -789,7 +813,10 @@ package body Netlists.Inference is
Res := Infere_Latch (Ctxt, Val, Prev_Val, Stmt);
else
-- Clock -> FF
- Res := Infere_FF (Ctxt, Prev_Val, Off, Last_Mux,
+ First_Mux := Get_Net_Parent (Val);
+ pragma Assert (Get_Id (First_Mux) = Id_Mux2);
+
+ Res := Infere_FF (Ctxt, Val, Prev_Val, Off, Last_Mux,
Clk, Enable, Stmt);
end if;