diff options
author | Tristan Gingold <tgingold@free.fr> | 2019-08-01 04:21:40 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2019-08-01 04:21:40 +0200 |
commit | d8daefafb575227a1644b2f24bd604dcbfc76c75 (patch) | |
tree | 97c886e5e2534e1af718dd4fb822ff8e09034462 /src/synth | |
parent | e02c802538cd52c55f881118380fa0d06da3acce (diff) | |
download | ghdl-d8daefafb575227a1644b2f24bd604dcbfc76c75.tar.gz ghdl-d8daefafb575227a1644b2f24bd604dcbfc76c75.tar.bz2 ghdl-d8daefafb575227a1644b2f24bd604dcbfc76c75.zip |
synth: refactor inference, add comment, strengthen check.
Diffstat (limited to 'src/synth')
-rw-r--r-- | src/synth/synth-environment.adb | 30 | ||||
-rw-r--r-- | src/synth/synth-environment.ads | 2 | ||||
-rw-r--r-- | src/synth/synth-inference.adb | 53 | ||||
-rw-r--r-- | src/synth/synth-inference.ads | 8 |
4 files changed, 62 insertions, 31 deletions
diff --git a/src/synth/synth-environment.adb b/src/synth/synth-environment.adb index 0986d5f69..0051f48fa 100644 --- a/src/synth/synth-environment.adb +++ b/src/synth/synth-environment.adb @@ -131,9 +131,22 @@ package body Synth.Environment is Conc_Assign_Table.Table (Asgn).Next := Chain; end Set_Conc_Chain; - procedure Add_Conc_Assign - (Wire_Rec : in out Wire_Id_Record; Val : Net; Stmt : Source.Syn_Src) + procedure Add_Conc_Assign_Partial + (Wid : Wire_Id; Val : Net; Off : Uns32; Stmt : Source.Syn_Src) is + Wire_Rec : Wire_Id_Record renames Wire_Id_Table.Table (Wid); + begin + Conc_Assign_Table.Append ((Next => Wire_Rec.Final_Assign, + Value => Val, + Offset => Off, + Stmt => Stmt)); + Wire_Rec.Final_Assign := Conc_Assign_Table.Last; + Wire_Rec.Nbr_Final_Assign := Wire_Rec.Nbr_Final_Assign + 1; + end Add_Conc_Assign_Partial; + + procedure Add_Conc_Assign (Wid : Wire_Id; Val : Net; Stmt : Source.Syn_Src) + is + Wire_Rec : Wire_Id_Record renames Wire_Id_Table.Table (Wid); Inst : constant Instance := Get_Parent (Val); V : Net; Off : Uns32; @@ -155,12 +168,7 @@ package body Synth.Environment is V := Val; Off := 0; end if; - Conc_Assign_Table.Append ((Next => Wire_Rec.Final_Assign, - Value => V, - Offset => Off, - Stmt => Stmt)); - Wire_Rec.Final_Assign := Conc_Assign_Table.Last; - Wire_Rec.Nbr_Final_Assign := Wire_Rec.Nbr_Final_Assign + 1; + Add_Conc_Assign_Partial (Wid, V, Off, Stmt); end Add_Conc_Assign; -- This procedure is called after each concurrent statement to assign @@ -199,9 +207,7 @@ package body Synth.Environment is raise Internal_Error; end if; - Drv := Inference.Infere (Ctxt, Asgn_Rec.Value, Outport); - - Add_Conc_Assign (Wire_Rec, Drv, Stmt); + Inference.Infere (Ctxt, Wid, Asgn_Rec.Value, Outport, Stmt); when others => raise Internal_Error; end case; @@ -284,7 +290,7 @@ package body Synth.Environment is Last_Asgn := No_Conc_Assign; Expected_Off := 0; Last_Off := Get_Width (Wire_Rec.Gate); - while Expected_Off < Last_Off loop + while (Expected_Off < Last_Off) or Asgn /= No_Conc_Assign loop if Asgn /= No_Conc_Assign then Next_Off := Get_Conc_Offset (Asgn); else diff --git a/src/synth/synth-environment.ads b/src/synth/synth-environment.ads index 0cdddc08f..c16a3cc0b 100644 --- a/src/synth/synth-environment.ads +++ b/src/synth/synth-environment.ads @@ -109,6 +109,8 @@ package Synth.Environment is function Current_Phi return Phi_Id; pragma Inline (Current_Phi); + procedure Add_Conc_Assign (Wid : Wire_Id; Val : Net; Stmt : Source.Syn_Src); + procedure Finalize_Assignments (Ctxt : Builders.Context_Acc); private type Wire_Id is new Uns32; diff --git a/src/synth/synth-inference.adb b/src/synth/synth-inference.adb index de9ea4dff..ebe478fa7 100644 --- a/src/synth/synth-inference.adb +++ b/src/synth/synth-inference.adb @@ -177,11 +177,13 @@ package body Synth.Inference is end case; end Extract_Clock; - function Infere_FF (Ctxt : Context_Acc; - Prev_Val : Net; - Last_Mux : Instance; - Clk : Net; - Enable : Net) return Net + procedure Infere_FF (Ctxt : Context_Acc; + Wid : Wire_Id; + Prev_Val : Net; + Last_Mux : Instance; + Clk : Net; + Enable : Net; + Stmt : Source.Syn_Src) is Sel : constant Input := Get_Mux2_Sel (Last_Mux); I0 : constant Input := Get_Mux2_I0 (Last_Mux); @@ -196,6 +198,9 @@ package body Synth.Inference is Rst_Val : Net; begin -- Create and return the DFF. + + -- 1. Remove the mux that creates the loop (will be replaced by the + -- dff). Disconnect (Sel); if Get_Driver (I0) /= Prev_Val then -- There must be no 'else' part for clock expression. @@ -206,6 +211,9 @@ package body Synth.Inference is Data := Get_Driver (I1); -- Don't try to free driver of I1 as it is reconnected. Disconnect (I1); + -- If there is a condition with the clock, that's an enable which + -- keep the previous value if the condition is false. Add the mux + -- for it. if Enable /= No_Net then Data := Build_Mux2 (Ctxt, Enable, Prev_Val, Data); end if; @@ -221,9 +229,10 @@ package body Synth.Inference is Init := No_Net; end if; + -- Look for asynchronous set/reset. They are muxes after the loop + -- mux. In theory, there can be many set/reset with a defined order. Rst_Val := No_Net; Rst := No_Net; - declare Mux : Instance; Sel : Net; @@ -276,6 +285,7 @@ package body Synth.Inference is end loop; end; + -- Create the FF. if Rst = No_Net then pragma Assert (Rst_Val = No_Net); if Init /= No_Net then @@ -305,10 +315,15 @@ package body Synth.Inference is Redirect_Inputs (O, Res); Free_Instance (Last_Mux); - return Res; + + Add_Conc_Assign (Wid, Res, Stmt); end Infere_FF; - function Infere (Ctxt : Context_Acc; Val : Net; Prev_Val : Net) return Net + procedure Infere (Ctxt : Context_Acc; + Wid : Wire_Id; + Val : Net; + Prev_Val : Net; + Stmt : Source.Syn_Src) is pragma Assert (Val /= No_Net); pragma Assert (Prev_Val /= No_Net); @@ -321,19 +336,21 @@ package body Synth.Inference is Find_Longest_Loop (Val, Prev_Val, Last_Mux, Len); if Len < 0 then -- No logical loop - return Val; + Add_Conc_Assign (Wid, Val, Stmt); elsif Len = 0 then -- Self assignment. - return Val; - end if; - - Sel := Get_Mux2_Sel (Last_Mux); - Extract_Clock (Get_Driver (Sel), Clk, Enable); - if Clk = No_Net then - -- No clock -> latch - raise Internal_Error; + Add_Conc_Assign (Wid, Val, Stmt); else - return Infere_FF (Ctxt, Prev_Val, Last_Mux, Clk, Enable); + -- So there is a logical loop. + 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 + -- Clock -> FF + Infere_FF (Ctxt, Wid, Prev_Val, Last_Mux, Clk, Enable, Stmt); + end if; end if; end Infere; end Synth.Inference; diff --git a/src/synth/synth-inference.ads b/src/synth/synth-inference.ads index 5777e04e4..371932f3e 100644 --- a/src/synth/synth-inference.ads +++ b/src/synth/synth-inference.ads @@ -20,10 +20,16 @@ with Netlists; use Netlists; with Netlists.Builders; use Netlists.Builders; +with Synth.Environment; use Synth.Environment; +with Synth.Source; package Synth.Inference is -- To be called when there is an assignment to a signal/output of VAL and -- the previous value is PREV_VAL (an Id_Signal or Id_Output). -- If there is a loop, infere a dff or a latch or emit an error. - function Infere (Ctxt : Context_Acc; Val : Net; Prev_Val : Net) return Net; + procedure Infere (Ctxt : Context_Acc; + Wid : Wire_Id; + Val : Net; + Prev_Val : Net; + Stmt : Source.Syn_Src); end Synth.Inference; |