aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2020-03-15 08:36:32 +0100
committerTristan Gingold <tgingold@free.fr>2020-03-15 08:36:32 +0100
commit0b0133bf964f472103a551a590de05e20d8722f5 (patch)
tree092f41ed47aa584fad78e65ae6930185ae879e38 /src/synth
parent2d1b95e84c340ead27d1ef12160812ae4cd92677 (diff)
downloadghdl-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.adb41
-rw-r--r--src/synth/synth-environment.adb101
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;