diff options
author | Tristan Gingold <tgingold@free.fr> | 2020-03-15 08:36:32 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2020-03-15 08:36:32 +0100 |
commit | 0b0133bf964f472103a551a590de05e20d8722f5 (patch) | |
tree | 092f41ed47aa584fad78e65ae6930185ae879e38 /src/synth | |
parent | 2d1b95e84c340ead27d1ef12160812ae4cd92677 (diff) | |
download | ghdl-0b0133bf964f472103a551a590de05e20d8722f5.tar.gz ghdl-0b0133bf964f472103a551a590de05e20d8722f5.tar.bz2 ghdl-0b0133bf964f472103a551a590de05e20d8722f5.zip |
synth: refactoring inference (WIP).
Diffstat (limited to 'src/synth')
-rw-r--r-- | src/synth/netlists-inference.adb | 41 | ||||
-rw-r--r-- | src/synth/synth-environment.adb | 101 |
2 files changed, 87 insertions, 55 deletions
diff --git a/src/synth/netlists-inference.adb b/src/synth/netlists-inference.adb index 177e10020..e391a6769 100644 --- a/src/synth/netlists-inference.adb +++ b/src/synth/netlists-inference.adb @@ -27,7 +27,6 @@ with Netlists.Internings; with Netlists.Folds; use Netlists.Folds; with Netlists.Memories; use Netlists.Memories; -with Synth.Flags; with Synth.Source; use Synth.Source; with Synth.Errors; use Synth.Errors; @@ -770,32 +769,28 @@ package body Netlists.Inference is Enable : Net; Res : Net; begin - if not Synth.Flags.Flag_Debug_Noinference then - if Get_First_Sink (Prev_Val) = No_Input then - -- PREV_VAL is never read, so there cannot be any loop. - -- This is an important optimization for control signals. - Len := -1; - else - Find_Longest_Loop (Val, Prev_Val, Last_Mux, Len); - end if; - else - Len := -1; + if Get_First_Sink (Prev_Val) = No_Input then + -- PREV_VAL is never read, so there cannot be any loop. + -- This is an important optimization for control signals. + return Val; end if; + + Find_Longest_Loop (Val, Prev_Val, Last_Mux, Len); if Len <= 0 then -- No logical loop or self assignment. - Res := Val; + return Val; + end if; + + -- So there is a logical loop. + Sel := Get_Mux2_Sel (Last_Mux); + Extract_Clock (Ctxt, Get_Driver (Sel), Clk, Enable); + if Clk = No_Net then + -- No clock -> latch or combinational loop + Res := Infere_Latch (Ctxt, Val, Prev_Val, Stmt); else - -- So there is a logical loop. - Sel := Get_Mux2_Sel (Last_Mux); - Extract_Clock (Ctxt, Get_Driver (Sel), Clk, Enable); - if Clk = No_Net then - -- No clock -> latch or combinational loop - Res := Infere_Latch (Ctxt, Val, Prev_Val, Stmt); - else - -- Clock -> FF - Res := Infere_FF (Ctxt, Prev_Val, Off, Last_Mux, - Clk, Enable, Stmt); - end if; + -- Clock -> FF + Res := Infere_FF (Ctxt, Prev_Val, Off, Last_Mux, + Clk, Enable, Stmt); end if; return Res; diff --git a/src/synth/synth-environment.adb b/src/synth/synth-environment.adb index e24239dcd..83fa6fdc3 100644 --- a/src/synth/synth-environment.adb +++ b/src/synth/synth-environment.adb @@ -28,6 +28,7 @@ with Netlists.Inference; with Errorout; use Errorout; +with Synth.Flags; with Synth.Errors; use Synth.Errors; with Synth.Source; use Synth.Source; @@ -324,57 +325,93 @@ package body Synth.Environment is Wire_Rec.Nbr_Final_Assign := Wire_Rec.Nbr_Final_Assign + 1; end Add_Conc_Assign; + procedure Pop_And_Merge_Phi_Wire (Ctxt : Builders.Context_Acc; + Asgn_Rec : Seq_Assign_Record; + Stmt : Source.Syn_Src) + is + Wid : constant Wire_Id := Asgn_Rec.Id; + Wire_Rec : Wire_Id_Record renames Wire_Id_Table.Table (Wid); + Outport : constant Net := Wire_Rec.Gate; + -- Must be connected to an Id_Output or Id_Signal + pragma Assert (Outport /= No_Net); + P : Partial_Assign; + begin + -- Check output is not already assigned. + pragma Assert (Get_Input_Net (Get_Net_Parent (Outport), 0) = No_Net); + + P := Asgn_Rec.Asgns; + pragma Assert (P /= No_Partial_Assign); + while P /= No_Partial_Assign loop + declare + Pa : Partial_Assign_Record renames Partial_Assign_Table.Table (P); + Res : Net; + begin + if Synth.Flags.Flag_Debug_Noinference then + Res := Pa.Value; + else + Res := Inference.Infere + (Ctxt, Pa.Value, Pa.Offset, Outport, Stmt); + end if; + + Add_Conc_Assign (Wid, Res, Pa.Offset, Stmt); + P := Pa.Next; + end; + end loop; + end Pop_And_Merge_Phi_Wire; + -- This procedure is called after each concurrent statement to assign -- values to signals. procedure Pop_And_Merge_Phi (Ctxt : Builders.Context_Acc; Stmt : Source.Syn_Src) is Phi : Phi_Type; - Asgn : Seq_Assign; + First, Last : Seq_Assign; + Asgn, Next_Asgn : Seq_Assign; begin Pop_Phi (Phi); + First := No_Seq_Assign; + Last := No_Seq_Assign; + + -- First variables. Asgn := Phi.First; while Asgn /= No_Seq_Assign loop declare Asgn_Rec : Seq_Assign_Record renames Assign_Table.Table (Asgn); - Wid : constant Wire_Id := Asgn_Rec.Id; - Wire_Rec : Wire_Id_Record renames Wire_Id_Table.Table (Wid); - Outport : constant Net := Wire_Rec.Gate; - -- Must be connected to an Id_Output or Id_Signal - pragma Assert (Outport /= No_Net); - P : Partial_Assign; + Wire_Rec : Wire_Id_Record renames + Wire_Id_Table.Table (Asgn_Rec.Id); begin - case Wire_Rec.Kind is - when Wire_Output - | Wire_Signal - | Wire_Variable => - -- Check output is not already assigned. - pragma Assert - (Get_Input_Net (Get_Net_Parent (Outport), 0) = No_Net); - - when others => - raise Internal_Error; - end case; + Next_Asgn := Asgn_Rec.Chain; + Asgn_Rec.Chain := No_Seq_Assign; - P := Asgn_Rec.Asgns; - pragma Assert (P /= No_Partial_Assign); - while P /= No_Partial_Assign loop - declare - Pa : Partial_Assign_Record renames - Partial_Assign_Table.Table (P); - Res : Net; - begin - Res := Inference.Infere - (Ctxt, Pa.Value, Pa.Offset, Outport, Stmt); - Add_Conc_Assign (Wid, Res, Pa.Offset, Stmt); - P := Pa.Next; - end; - end loop; + if Wire_Rec.Kind = Wire_Variable then + Pop_And_Merge_Phi_Wire (Ctxt, Asgn_Rec, Stmt); + else + if First = No_Seq_Assign then + First := Asgn; + else + Set_Assign_Chain (Last, Asgn); + end if; + Last := Asgn; + end if; + Asgn := Next_Asgn; + end; + end loop; + -- Then signals. + Asgn := First; + while Asgn /= No_Seq_Assign loop + declare + Asgn_Rec : Seq_Assign_Record renames Assign_Table.Table (Asgn); + Wire_Rec : Wire_Id_Record renames + Wire_Id_Table.Table (Asgn_Rec.Id); + begin + pragma Assert (Wire_Rec.Kind /= Wire_Variable); + Pop_And_Merge_Phi_Wire (Ctxt, Asgn_Rec, Stmt); Asgn := Asgn_Rec.Chain; end; end loop; + -- FIXME: free wires. end Pop_And_Merge_Phi; |