aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2019-09-15 06:32:22 +0200
committerTristan Gingold <tgingold@free.fr>2019-09-15 06:32:22 +0200
commit8b9310deab06d428050153eec5abd33bfb717584 (patch)
tree41a2a0f2cd89be7ce67f71d17c01a60cfb73cf4b /src
parenteb8ec9c2b64110c70f2c1626b50a0ae62ce7126b (diff)
downloadghdl-8b9310deab06d428050153eec5abd33bfb717584.tar.gz
ghdl-8b9310deab06d428050153eec5abd33bfb717584.tar.bz2
ghdl-8b9310deab06d428050153eec5abd33bfb717584.zip
synth-oper: add support of std_match
Diffstat (limited to 'src')
-rw-r--r--src/synth/synth-oper.adb94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/synth/synth-oper.adb b/src/synth/synth-oper.adb
index 59f20ea5a..ac11d0606 100644
--- a/src/synth/synth-oper.adb
+++ b/src/synth/synth-oper.adb
@@ -780,6 +780,85 @@ package body Synth.Oper is
return Create_Value_Net (N, Create_Res_Bound (Left, L));
end Synth_Shift;
+ function Synth_Std_Match (Cst : Value_Acc;
+ Oper : Value_Acc;
+ Expr : Node) return Value_Acc
+ is
+ Wd : constant Width := Cst.Typ.W;
+ Nwords : constant Natural := Natural ((Wd + 31) / 32);
+ Mask : Uns32_Arr_Acc;
+ Vals : Uns32_Arr_Acc;
+ Boff : Natural;
+ Woff : Natural;
+ B : Uns32;
+ M : Uns32;
+ Nv : Net;
+ Nm : Net;
+ Res : Net;
+ begin
+ if Oper.Typ.W /= Wd then
+ Error_Msg_Synth
+ (+Expr, "operands of std_match don't have the same size");
+ return Create_Value_Discrete (0, Boolean_Type);
+ end if;
+
+ pragma Assert (Wd > 0);
+
+ -- Flatten 0/1 DC.
+ Mask := new Uns32_Arr'(0 .. Nwords - 1 => 0);
+ Vals := new Uns32_Arr'(0 .. Nwords - 1 => 0);
+
+ Boff := 0;
+ Woff := 0;
+ for I in reverse Cst.Arr.V'Range loop
+ case Cst.Arr.V (I).Scal is
+ when Vhdl.Ieee.Std_Logic_1164.Std_Logic_0_Pos
+ | Vhdl.Ieee.Std_Logic_1164.Std_Logic_L_Pos =>
+ B := 0;
+ M := 1;
+ when Vhdl.Ieee.Std_Logic_1164.Std_Logic_1_Pos
+ | Vhdl.Ieee.Std_Logic_1164.Std_Logic_H_Pos =>
+ B := 1;
+ M := 1;
+ when Vhdl.Ieee.Std_Logic_1164.Std_Logic_U_Pos
+ | Vhdl.Ieee.Std_Logic_1164.Std_Logic_X_Pos
+ | Vhdl.Ieee.Std_Logic_1164.Std_Logic_Z_Pos
+ | Vhdl.Ieee.Std_Logic_1164.Std_Logic_W_Pos =>
+ -- Never match
+ -- FIXME: warning ?
+ Unchecked_Deallocate (Mask);
+ Unchecked_Deallocate (Vals);
+ return Create_Value_Discrete (0, Boolean_Type);
+ when Vhdl.Ieee.Std_Logic_1164.Std_Logic_D_Pos =>
+ B := 0;
+ M := 0;
+ when others =>
+ raise Internal_Error;
+ end case;
+ Mask (Woff) := Mask (Woff) or Shift_Left (M, Boff);
+ Vals (Woff) := Vals (Woff) or Shift_Left (B, Boff);
+ Boff := Boff + 1;
+ if Boff = 32 then
+ Boff := 0;
+ Woff := Woff + 1;
+ end if;
+ end loop;
+
+ -- Generate and + eq
+ Nv := Build2_Const_Vec (Build_Context, Wd, Vals.all);
+ Set_Location (Nv, Expr);
+ Unchecked_Deallocate (Vals);
+ Nm := Build2_Const_Vec (Build_Context, Wd, Mask.all);
+ Set_Location (Nm, Expr);
+ Unchecked_Deallocate (Mask);
+ Res := Build_Dyadic (Build_Context, Id_And, Get_Net (Oper), Nm);
+ Set_Location (Res, Expr);
+ Res := Build_Compare (Build_Context, Id_Eq, Res, Nv);
+ Set_Location (Res, Expr);
+
+ return Create_Value_Net (Res, Boolean_Type);
+ end Synth_Std_Match;
+
function Eval_To_Unsigned (Arg : Int64; Sz : Int64; Res_Type : Type_Acc)
return Value_Acc
is
@@ -894,6 +973,21 @@ package body Synth.Oper is
begin
return Synth_Shift (Id_Lsr, L, R, Expr);
end;
+ when Iir_Predefined_Ieee_Numeric_Std_Match_Suv =>
+ declare
+ L : constant Value_Acc := Subprg_Inst.Objects (1);
+ R : constant Value_Acc := Subprg_Inst.Objects (2);
+ begin
+ if Is_Const (L) then
+ return Synth_Std_Match (L, R, Expr);
+ elsif Is_Const (R) then
+ return Synth_Std_Match (R, L, Expr);
+ else
+ Error_Msg_Synth
+ (+Expr, "one operand of std_match must be constant");
+ return null;
+ end if;
+ end;
when Iir_Predefined_Ieee_Math_Real_Log2 =>
declare
V : constant Value_Acc := Subprg_Inst.Objects (1);