From 959f80c052665d07a28e1b1b20e89d6e12d0ced4 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Thu, 6 Aug 2020 07:54:40 +0200 Subject: synth: push extract on mux2 for inference. For #1421 --- src/synth/netlists-folds.adb | 28 ++++++++++++++++++++++++++++ src/synth/netlists-folds.ads | 6 ++++++ src/synth/synth-environment.adb | 35 ++++++++++++++++++----------------- 3 files changed, 52 insertions(+), 17 deletions(-) (limited to 'src/synth') diff --git a/src/synth/netlists-folds.adb b/src/synth/netlists-folds.adb index c4138d0cd..411415901 100644 --- a/src/synth/netlists-folds.adb +++ b/src/synth/netlists-folds.adb @@ -270,6 +270,34 @@ package body Netlists.Folds is end if; end Build2_Extract; + function Build2_Extract_Push + (Ctxt : Context_Acc; I : Net; Off, W : Width) return Net + is + Inst : constant Instance := Get_Net_Parent (I); + Res : Net; + begin + if Off = 0 and then W = Get_Width (I) then + return I; + end if; + + case Get_Id (Inst) is + when Id_Extract => + return Build2_Extract_Push + (Ctxt, Get_Input_Net (Inst, 0), + Off + Get_Param_Uns32 (Inst, 0), W); + when Id_Mux2 => + Res := Build_Mux2 + (Ctxt, + Get_Input_Net (Inst, 0), + Build2_Extract_Push (Ctxt, Get_Input_Net (Inst, 1), Off, W), + Build2_Extract_Push (Ctxt, Get_Input_Net (Inst, 2), Off, W)); + Set_Location (Res, Get_Location (Inst)); + return Res; + when others => + return Build_Extract (Ctxt, I, Off, W); + end case; + end Build2_Extract_Push; + function Build2_Imp (Ctxt : Context_Acc; A, B : Net; Loc : Location_Type) return Net is diff --git a/src/synth/netlists-folds.ads b/src/synth/netlists-folds.ads index 6c63f49bc..3ee69f41c 100644 --- a/src/synth/netlists-folds.ads +++ b/src/synth/netlists-folds.ads @@ -71,6 +71,12 @@ package Netlists.Folds is function Build2_Extract (Ctxt : Context_Acc; I : Net; Off, W : Width) return Net; + -- Likewise, but if I is an output of a mux2, build the extract gates + -- on the input of the mux2 (recursively). + -- The purpose is to keep the control flow of the mux2 tree. + function Build2_Extract_Push + (Ctxt : Context_Acc; I : Net; Off, W : Width) return Net; + -- Return A -> B == !A || B function Build2_Imp (Ctxt : Context_Acc; A, B : Net; Loc : Location_Type) return Net; diff --git a/src/synth/synth-environment.adb b/src/synth/synth-environment.adb index 18133594e..7f552f352 100644 --- a/src/synth/synth-environment.adb +++ b/src/synth/synth-environment.adb @@ -1036,7 +1036,7 @@ package body Synth.Environment is -- If no seq assign, return current value. if First_Seq = No_Seq_Assign then - return Build2_Extract (Ctxt, Wire_Rec.Gate, Off, Wd); + return Build2_Extract_Push (Ctxt, Wire_Rec.Gate, Off, Wd); end if; -- If the current value is static, just return it. @@ -1096,8 +1096,9 @@ package body Synth.Environment is Cur_Wd := Width'Min (Cur_Wd, Pw - (Cur_Off - Pr.Offset)); Append - (Vec, Build_Extract (Ctxt, Pr.Value, - Cur_Off - Pr.Offset, Cur_Wd)); + (Vec, + Build2_Extract_Push (Ctxt, Pr.Value, + Cur_Off - Pr.Offset, Cur_Wd)); end if; exit; end if; @@ -1122,8 +1123,8 @@ package body Synth.Environment is Seq := Get_Assign_Prev (Seq); if Seq = No_Seq_Assign then -- Extract from gate. - Append (Vec, Build_Extract (Ctxt, Wire_Rec.Gate, - Cur_Off, Cur_Wd)); + Append (Vec, Build2_Extract_Push (Ctxt, Wire_Rec.Gate, + Cur_Off, Cur_Wd)); exit; end if; if Get_Assign_Is_Static (Seq) then @@ -1702,9 +1703,9 @@ package body Synth.Environment is -- |----------|| -- P.Off P.Next -- Shrink EL. - P.Value := Build_Extract (Ctxt, P.Value, - Off => V_Next - P.Offset, - W => P_Next - V_Next); + P.Value := Build2_Extract_Push (Ctxt, P.Value, + Off => V_Next - P.Offset, + W => P_Next - V_Next); P.Offset := V_Next; if not Inserted then if Last_El /= No_Partial_Assign then @@ -1724,9 +1725,9 @@ package body Synth.Environment is -- |----------|| -- P.Off P.Next -- Shrink EL. - P.Value := Build_Extract (Ctxt, P.Value, - Off => 0, - W => V.Offset - P.Offset); + P.Value := Build2_Extract_Push (Ctxt, P.Value, + Off => 0, + W => V.Offset - P.Offset); pragma Assert (not Inserted); V.Next := P.Next; P.Next := Asgn; @@ -1742,14 +1743,14 @@ package body Synth.Environment is pragma Assert (not Inserted); Partial_Assign_Table.Append ((Next => P.Next, - Value => Build_Extract (Ctxt, P.Value, - Off => V_Next - P.Offset, - W => P_Next - V_Next), + Value => Build2_Extract_Push (Ctxt, P.Value, + Off => V_Next - P.Offset, + W => P_Next - V_Next), Offset => V_Next)); V.Next := Partial_Assign_Table.Last; - P.Value := Build_Extract (Ctxt, P.Value, - Off => 0, - W => V.Offset - P.Offset); + P.Value := Build2_Extract_Push (Ctxt, P.Value, + Off => 0, + W => V.Offset - P.Offset); P.Next := Asgn; Inserted := True; -- No more possible overlaps. -- cgit v1.2.3