diff options
| -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; | 
