aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2019-07-31 20:33:40 +0200
committerTristan Gingold <tgingold@free.fr>2019-07-31 20:33:40 +0200
commitf6d4d0d916e772d3e21701f53a7dbb6b0abe756d (patch)
treed33a90396f50030a5a9ddcfb277136c15e0a80d2
parent3f4fcc9904a2f84505a701e822944c49812dde3a (diff)
downloadghdl-f6d4d0d916e772d3e21701f53a7dbb6b0abe756d.tar.gz
ghdl-f6d4d0d916e772d3e21701f53a7dbb6b0abe756d.tar.bz2
ghdl-f6d4d0d916e772d3e21701f53a7dbb6b0abe756d.zip
synth: refactoring in synth-inference.
-rw-r--r--src/synth/synth-inference.adb266
1 files changed, 137 insertions, 129 deletions
diff --git a/src/synth/synth-inference.adb b/src/synth/synth-inference.adb
index 6e0ba1648..de9ea4dff 100644
--- a/src/synth/synth-inference.adb
+++ b/src/synth/synth-inference.adb
@@ -177,155 +177,163 @@ package body Synth.Inference is
end case;
end Extract_Clock;
- function Infere (Ctxt : Context_Acc; Val : Net; Prev_Val : Net) return Net
+ function Infere_FF (Ctxt : Context_Acc;
+ Prev_Val : Net;
+ Last_Mux : Instance;
+ Clk : Net;
+ Enable : Net) return Net
is
- pragma Assert (Val /= No_Net);
- pragma Assert (Prev_Val /= No_Net);
- Last_Mux : Instance;
- Len : Integer;
+ Sel : constant Input := Get_Mux2_Sel (Last_Mux);
+ I0 : constant Input := Get_Mux2_I0 (Last_Mux);
+ I1 : constant Input := Get_Mux2_I1 (Last_Mux);
+ O : constant Net := Get_Output (Last_Mux, 0);
+ Data : Net;
+ Res : Net;
+ Sig : Instance;
+ Init : Net;
+ Init_Input : Input;
+ Rst : Net;
+ Rst_Val : Net;
begin
- Find_Longest_Loop (Val, Prev_Val, Last_Mux, Len);
- if Len < 0 then
- -- No logical loop
- return Val;
- elsif Len = 0 then
- -- Self assignment.
- return Val;
+ -- Create and return the DFF.
+ Disconnect (Sel);
+ if Get_Driver (I0) /= Prev_Val then
+ -- There must be no 'else' part for clock expression.
+ raise Internal_Error;
+ end if;
+ -- Don't try to free driver of I0 as this is Prev_Val.
+ Disconnect (I0);
+ Data := Get_Driver (I1);
+ -- Don't try to free driver of I1 as it is reconnected.
+ Disconnect (I1);
+ if Enable /= No_Net then
+ Data := Build_Mux2 (Ctxt, Enable, Prev_Val, Data);
end if;
+ -- If the signal declaration has an initial value, move it
+ -- to the dff.
+ Sig := Get_Parent (Prev_Val);
+ if Get_Id (Get_Module (Sig)) = Id_Isignal then
+ Init_Input := Get_Input (Sig, 1);
+ Init := Get_Driver (Init_Input);
+ Disconnect (Init_Input);
+ else
+ Init := No_Net;
+ end if;
+
+ Rst_Val := No_Net;
+ Rst := No_Net;
+
declare
- Sel : constant Input := Get_Mux2_Sel (Last_Mux);
- I0 : constant Input := Get_Mux2_I0 (Last_Mux);
- I1 : constant Input := Get_Mux2_I1 (Last_Mux);
- O : constant Net := Get_Output (Last_Mux, 0);
- Data : Net;
- Clk : Net;
- Enable : Net;
- Res : Net;
- Sig : Instance;
- Init : Net;
- Init_Input : Input;
- Rst : Net;
- Rst_Val : Net;
+ Mux : Instance;
+ Sel : Net;
+ Last_Out : Net;
+ Mux_Rst : Net;
+ Mux_Rst_Val : Net;
begin
- Extract_Clock (Get_Driver (Sel), Clk, Enable);
- if Clk = No_Net then
- -- No clock -> latch
- raise Internal_Error;
- else
- -- Create and return the DFF.
- Disconnect (Sel);
- if Get_Driver (I0) /= Prev_Val then
- -- There must be no 'else' part for clock expression.
+ Last_Out := O;
+
+ while Is_Connected (Last_Out) loop
+ if not Has_One_Connection (Last_Out) then
+ -- TODO.
raise Internal_Error;
end if;
- -- Don't try to free driver of I0 as this is Prev_Val.
- Disconnect (I0);
- Data := Get_Driver (I1);
- -- Don't try to free driver of I1 as it is reconnected.
- Disconnect (I1);
- if Enable /= No_Net then
- Data := Build_Mux2 (Ctxt, Enable, Prev_Val, Data);
+
+ Mux := Get_Parent (Get_First_Sink (Last_Out));
+ if Get_Id (Mux) /= Id_Mux2 then
+ raise Internal_Error;
end if;
- -- If the signal declaration has an initial value, move it
- -- to the dff.
- Sig := Get_Parent (Prev_Val);
- if Get_Id (Get_Module (Sig)) = Id_Isignal then
- Init_Input := Get_Input (Sig, 1);
- Init := Get_Driver (Init_Input);
- Disconnect (Init_Input);
+ Sel := Get_Driver (Get_Mux2_Sel (Mux));
+ if Get_Driver (Get_Mux2_I0 (Mux)) = O then
+ Mux_Rst_Val := Get_Driver (Get_Mux2_I1 (Mux));
+ Mux_Rst := Sel;
+ elsif Get_Driver (Get_Mux2_I1 (Mux)) = O then
+ Mux_Rst_Val := Get_Driver (Get_Mux2_I0 (Mux));
+ Mux_Rst := Build_Monadic (Ctxt, Id_Not, Sel);
else
- Init := No_Net;
+ -- Cannot happen.
+ raise Internal_Error;
end if;
+ Last_Out := Get_Output (Mux, 0);
- Rst_Val := No_Net;
- Rst := No_Net;
-
- declare
- Mux : Instance;
- Sel : Net;
- Last_Out : Net;
- Mux_Rst : Net;
- Mux_Rst_Val : Net;
- begin
- Last_Out := O;
-
- while Is_Connected (Last_Out) loop
- if not Has_One_Connection (Last_Out) then
- -- TODO.
- raise Internal_Error;
- end if;
-
- Mux := Get_Parent (Get_First_Sink (Last_Out));
- if Get_Id (Mux) /= Id_Mux2 then
- raise Internal_Error;
- end if;
-
- Sel := Get_Driver (Get_Mux2_Sel (Mux));
- if Get_Driver (Get_Mux2_I0 (Mux)) = O then
- Mux_Rst_Val := Get_Driver (Get_Mux2_I1 (Mux));
- Mux_Rst := Sel;
- elsif Get_Driver (Get_Mux2_I1 (Mux)) = O then
- 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;
+ if Rst = No_Net then
+ -- Remove the last mux.
+ Disconnect (Get_Mux2_I0 (Mux));
+ Disconnect (Get_Mux2_I1 (Mux));
+ Disconnect (Get_Mux2_Sel (Mux));
- Last_Out := Get_Output (Mux, 0);
+ Redirect_Inputs (Last_Out, Mux_Rst_Val);
+ Free_Instance (Mux);
- if Rst = No_Net then
- -- Remove the last mux.
- Disconnect (Get_Mux2_I0 (Mux));
- Disconnect (Get_Mux2_I1 (Mux));
- Disconnect (Get_Mux2_Sel (Mux));
+ Rst := Mux_Rst;
+ Rst_Val := Mux_Rst_Val;
+ else
+ Rst := Build_Dyadic (Ctxt, Id_Or, Mux_Rst, Rst);
+ Rst_Val := Last_Out;
+ end if;
+ end loop;
+ end;
- Redirect_Inputs (Last_Out, Mux_Rst_Val);
- Free_Instance (Mux);
+ if Rst = No_Net then
+ pragma Assert (Rst_Val = No_Net);
+ if Init /= No_Net then
+ Res := Build_Idff (Ctxt, Clk, D => Data, Init => Init);
+ else
+ Res := Build_Dff (Ctxt, Clk, D => Data);
+ end if;
+ else
+ if Init /= No_Net then
+ Res := Build_Iadff (Ctxt, Clk, D => Data,
+ Rst => Rst, Rst_Val => Rst_Val,
+ Init => Init);
+ else
+ Res := Build_Adff (Ctxt, Clk, D => Data,
+ Rst => Rst, Rst_Val => Rst_Val);
+ end if;
+ end if;
- Rst := Mux_Rst;
- Rst_Val := Mux_Rst_Val;
- else
- Rst := Build_Dyadic (Ctxt, Id_Or, Mux_Rst, Rst);
- Rst_Val := Last_Out;
- end if;
- end loop;
- end;
+ -- The output of the mux may be read later in the process,
+ -- like this:
+ -- if clk'event and clk = '1' then
+ -- d := i + 1;
+ -- end if;
+ -- d1 := d + 1;
+ -- So connections to the mux output are redirected to dff
+ -- output.
+ Redirect_Inputs (O, Res);
- if Rst = No_Net then
- pragma Assert (Rst_Val = No_Net);
- if Init /= No_Net then
- Res := Build_Idff (Ctxt, Clk, D => Data, Init => Init);
- else
- Res := Build_Dff (Ctxt, Clk, D => Data);
- end if;
- else
- if Init /= No_Net then
- Res := Build_Iadff (Ctxt, Clk, D => Data,
- Rst => Rst, Rst_Val => Rst_Val,
- Init => Init);
- else
- Res := Build_Adff (Ctxt, Clk, D => Data,
- Rst => Rst, Rst_Val => Rst_Val);
- end if;
- end if;
+ Free_Instance (Last_Mux);
+ return Res;
+ end Infere_FF;
- -- The output of the mux may be read later in the process,
- -- like this:
- -- if clk'event and clk = '1' then
- -- d := i + 1;
- -- end if;
- -- d1 := d + 1;
- -- So connections to the mux output are redirected to dff
- -- output.
- Redirect_Inputs (O, Res);
+ function Infere (Ctxt : Context_Acc; Val : Net; Prev_Val : Net) return Net
+ is
+ pragma Assert (Val /= No_Net);
+ pragma Assert (Prev_Val /= No_Net);
+ Last_Mux : Instance;
+ Len : Integer;
+ Sel : Input;
+ Clk : Net;
+ Enable : Net;
+ begin
+ Find_Longest_Loop (Val, Prev_Val, Last_Mux, Len);
+ if Len < 0 then
+ -- No logical loop
+ return Val;
+ elsif Len = 0 then
+ -- Self assignment.
+ return Val;
+ end if;
- Free_Instance (Last_Mux);
- return Res;
- end if;
- end;
+ Sel := Get_Mux2_Sel (Last_Mux);
+ Extract_Clock (Get_Driver (Sel), Clk, Enable);
+ if Clk = No_Net then
+ -- No clock -> latch
+ raise Internal_Error;
+ else
+ return Infere_FF (Ctxt, Prev_Val, Last_Mux, Clk, Enable);
+ end if;
end Infere;
end Synth.Inference;