diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mutils.adb | 4 | ||||
| -rw-r--r-- | src/mutils.ads | 3 | ||||
| -rw-r--r-- | src/synth/synth-oper.adb | 24 | 
3 files changed, 31 insertions, 0 deletions
diff --git a/src/mutils.adb b/src/mutils.adb index 1b40bff79..d51891f02 100644 --- a/src/mutils.adb +++ b/src/mutils.adb @@ -24,4 +24,8 @@ package body Mutils is        return 64;     end Clog2; +   function Is_Power2 (V : Uns64) return Boolean is +   begin +      return (V and (V - 1)) = 0; +   end Is_Power2;  end Mutils; diff --git a/src/mutils.ads b/src/mutils.ads index 4275fe6c0..1a3afd4f1 100644 --- a/src/mutils.ads +++ b/src/mutils.ads @@ -4,4 +4,7 @@ package Mutils is     --  Return the ceiling log2 of V.     --  Returns 0 for 0.     function Clog2 (V : Uns64) return Integer; + +   --  Return True IFF V is 0 or a power of 2. +   function Is_Power2 (V : Uns64) return Boolean;  end Mutils; diff --git a/src/synth/synth-oper.adb b/src/synth/synth-oper.adb index b5480a2b9..b887a66ed 100644 --- a/src/synth/synth-oper.adb +++ b/src/synth/synth-oper.adb @@ -21,6 +21,8 @@  with Ada.Unchecked_Conversion;  with Types; use Types;  with Types_Utils; use Types_Utils; +with Mutils; +  with Vhdl.Ieee.Std_Logic_1164; use Vhdl.Ieee.Std_Logic_1164;  with Vhdl.Std_Package;  with Vhdl.Errors; use Vhdl.Errors; @@ -182,6 +184,7 @@ package body Synth.Oper is                                      Right_Expr : Node;                                      Expr : Node) return Value_Acc     is +      Ctxt : constant Context_Acc := Get_Build (Syn_Inst);        Def : constant Iir_Predefined_Functions :=          Get_Implicit_Definition (Imp);        Inter_Chain : constant Node := @@ -710,6 +713,27 @@ package body Synth.Oper is           when Iir_Predefined_Integer_Div =>              return Synth_Int_Dyadic (Id_Sdiv);           when Iir_Predefined_Integer_Mod => +            if Is_Static_Val (Right) then +               --  Optimize when the divisor is a power of 2. +               declare +                  use Mutils; +                  Etype : constant Type_Acc := +                    Get_Value_Type (Syn_Inst, Expr_Type); +                  R : constant Int64 := Get_Static_Discrete (Right); +                  Log_R : Natural; +                  N : Net; +               begin +                  if R > 0 and then Is_Power2 (Uns64 (R)) then +                     Log_R := Clog2 (Uns64 (R)); +                     pragma Assert (Log_R <= Natural (Left.Typ.W)); +                     N := Get_Net (Left); +                     N := Build2_Extract (Ctxt, N, 0, Width (Log_R)); +                     N := Build2_Uresize (Ctxt, N, Left.Typ.W, +                                          Get_Location (Expr)); +                     return Create_Value_Net (N, Etype); +                  end if; +               end; +            end if;              return Synth_Int_Dyadic (Id_Smod);           when Iir_Predefined_Integer_Rem =>              return Synth_Int_Dyadic (Id_Srem);  | 
