aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2022-09-04 06:12:20 +0200
committerTristan Gingold <tgingold@free.fr>2022-09-05 19:54:08 +0200
commita060bbe2f05b222b977989c2baa04faa72c5d4fd (patch)
tree45594b3ca271c76667e1cf31638cd70cba51c600 /src/synth
parent0d6b21c3b5639af8b321cc7f85fbf03da78d7edb (diff)
downloadghdl-a060bbe2f05b222b977989c2baa04faa72c5d4fd.tar.gz
ghdl-a060bbe2f05b222b977989c2baa04faa72c5d4fd.tar.bz2
ghdl-a060bbe2f05b222b977989c2baa04faa72c5d4fd.zip
synth: add evaluation for ieee.std_logic_arith
Diffstat (limited to 'src/synth')
-rw-r--r--src/synth/synth-ieee-numeric_std.adb21
-rw-r--r--src/synth/synth-ieee-std_logic_arith.adb522
-rw-r--r--src/synth/synth-ieee-std_logic_arith.ads70
-rw-r--r--src/synth/synth-ieee-utils.adb183
-rw-r--r--src/synth/synth-ieee-utils.ads26
-rw-r--r--src/synth/synth-vhdl_eval.adb402
6 files changed, 1181 insertions, 43 deletions
diff --git a/src/synth/synth-ieee-numeric_std.adb b/src/synth/synth-ieee-numeric_std.adb
index 8ec10fdd9..7a5ce751d 100644
--- a/src/synth/synth-ieee-numeric_std.adb
+++ b/src/synth/synth-ieee-numeric_std.adb
@@ -812,34 +812,19 @@ package body Synth.Ieee.Numeric_Std is
return Mul_Sgn_Sgn (L, Rv, Loc);
end Mul_Sgn_Int;
- -- Note: SRC = DST is allowed.
- procedure Neg_Vec (Src : Memory_Ptr; Dst : Memory_Ptr; Typ : Type_Acc)
- is
- Len : constant Uns32 := Typ.Abound.Len;
- Vb, Carry : Sl_X01;
- begin
- Carry := '1';
- for I in 1 .. Len loop
- Vb := Sl_To_X01 (Read_Std_Logic (Src, Len - I));
- Vb := Not_Table (Vb);
- Write_Std_Logic (Dst, Len - I, Xor_Table (Carry, Vb));
- Carry := And_Table (Carry, Vb);
- end loop;
- end Neg_Vec;
-
function Neg_Vec_Notyp (V : Memtyp) return Memory_Ptr
is
Res : Memory_Ptr;
begin
Res := Alloc_Memory (V.Typ, Current_Pool);
- Neg_Vec (V.Mem, Res, V.Typ);
+ Neg_Vec (V.Mem, Res, V.Typ.Abound.Len);
return Res;
end Neg_Vec_Notyp;
procedure Neg_Vec (V : Memtyp) is
begin
- Neg_Vec (V.Mem, V.Mem, V.Typ);
+ Neg_Vec (V.Mem, V.Mem, V.Typ.Abound.Len);
end Neg_Vec;
function Has_0x (V : Memtyp) return Sl_X01
@@ -875,7 +860,7 @@ package body Synth.Ieee.Numeric_Std is
(+Loc, "NUMERIC_STD.""-"": non logical value detected");
Fill (Res, 'X');
else
- Neg_Vec (V.Mem, Res.Mem, V.Typ);
+ Neg_Vec (V.Mem, Res.Mem, V.Typ.Abound.Len);
end if;
return Res;
end Neg_Vec;
diff --git a/src/synth/synth-ieee-std_logic_arith.adb b/src/synth/synth-ieee-std_logic_arith.adb
new file mode 100644
index 000000000..befb217d0
--- /dev/null
+++ b/src/synth/synth-ieee-std_logic_arith.adb
@@ -0,0 +1,522 @@
+-- std_logic_arith
+-- Copyright (C) 2022 Tristan Gingold
+--
+-- This file is part of GHDL.
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <gnu.org/licenses>.
+
+with Types_Utils; use Types_Utils;
+
+with Elab.Memtype; use Elab.Memtype;
+
+with Synth.Errors; use Synth.Errors;
+with Synth.Ieee.Utils; use Synth.Ieee.Utils;
+with Synth.Ieee.Std_Logic_1164; use Synth.Ieee.Std_Logic_1164;
+
+package body Synth.Ieee.Std_Logic_Arith is
+
+ function Create_Res_Type (Otyp : Type_Acc; Len : Uns32) return Type_Acc is
+ begin
+ if Otyp.Abound.Len = Len
+ and then Otyp.Abound.Right = 0
+ and then Otyp.Abound.Dir = Dir_Downto
+ and then not Otyp.Is_Global
+ then
+ -- Try to reuse the same type as the parameter.
+ -- But the result type must be allocated on the expr_pool.
+ -- FIXME: is this code ever executed ?
+ pragma Assert (Otyp.Abound.Left = Int32 (Len) - 1);
+ return Otyp;
+ end if;
+ return Create_Vec_Type_By_Length (Len, Otyp.Arr_El);
+ end Create_Res_Type;
+
+ procedure Fill (Res : Memory_Ptr; Len : Uns32; V : Std_Ulogic) is
+ begin
+ for I in 1 .. Len loop
+ Write_Std_Logic (Res, I - 1, V);
+ end loop;
+ end Fill;
+
+ procedure Add_Sub_Vec_Vec (Res : Memory_Ptr;
+ Len : Uns32;
+ L, R : Memory_Ptr;
+ Llen, Rlen : Uns32;
+ Lsign, Rsign : Boolean;
+ Is_Sub : Boolean)
+ is
+ Lb, Rb, Carry : Sl_X01;
+ R_Ext, L_Ext : Sl_X01;
+ begin
+
+ if Lsign and Llen > 0 then
+ -- Extend with the sign bit.
+ L_Ext := Sl_To_X01 (Read_Std_Logic (L, 0));
+ else
+ -- Extend with '0'.
+ L_Ext := '0';
+ end if;
+ if Rsign and Rlen > 0 then
+ R_Ext := Sl_To_X01 (Read_Std_Logic (R, 0));
+ else
+ R_Ext := '0';
+ end if;
+
+ if Is_Sub then
+ Carry := '1';
+ else
+ Carry := '0';
+ end if;
+
+ for I in 1 .. Len loop
+ if I > Llen then
+ Lb := L_Ext;
+ else
+ Lb := Sl_To_X01 (Read_Std_Logic (L, Llen - I));
+ end if;
+ if I > Rlen then
+ Rb := R_Ext;
+ else
+ Rb := Sl_To_X01 (Read_Std_Logic (R, Rlen - I));
+ end if;
+ if Is_Sub then
+ Rb := Not_Table (Rb);
+ end if;
+
+ if Lb = 'X' or Rb = 'X' then
+ Fill (Res, Len, 'X');
+ exit;
+ end if;
+ Write_Std_Logic (Res, Len - I, Compute_Sum (Carry, Rb, Lb));
+ Carry := Compute_Carry (Carry, Rb, Lb);
+ end loop;
+ end Add_Sub_Vec_Vec;
+
+ procedure Warn_X (Loc : Location_Type) is
+ begin
+ Warning_Msg_Synth
+ (Loc,
+ "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, "
+ & "the result will be 'X'(es).");
+ end Warn_X;
+
+ function Add_Sub_Uns_Sgn_Sgn (L, R : Memtyp;
+ Is_Sub : Boolean;
+ Loc : Location_Type) return Memtyp
+ is
+ Llen : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := R.Typ.Abound.Len;
+ Len : constant Uns32 := Uns32'Max (Llen + 1, Rlen);
+ Res : Memtyp;
+ begin
+ Res.Typ := Create_Res_Type (L.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
+ Add_Sub_Vec_Vec
+ (Res.Mem, Len, L.Mem, R.Mem, Llen, Rlen, False, True, Is_Sub);
+
+ if Read_Std_Logic (Res.Mem, 0) = 'X' then
+ Warn_X (Loc);
+ end if;
+
+ return Res;
+ end Add_Sub_Uns_Sgn_Sgn;
+
+ function Add_Uns_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Uns_Sgn_Sgn (L, R, False, Loc);
+ end Add_Uns_Sgn_Sgn;
+
+ function Sub_Uns_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Uns_Sgn_Sgn (L, R, True, Loc);
+ end Sub_Uns_Sgn_Sgn;
+
+ function Add_Sub_Sgn_Uns_Sgn (L, R : Memtyp;
+ Is_Sub : Boolean;
+ Loc : Location_Type) return Memtyp
+ is
+ Llen : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := R.Typ.Abound.Len;
+ Len : constant Uns32 := Uns32'Max (Llen, Rlen + 1);
+ Res : Memtyp;
+ begin
+ Res.Typ := Create_Res_Type (L.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
+ Add_Sub_Vec_Vec
+ (Res.Mem, Len, L.Mem, R.Mem, Llen, Rlen, True, False, Is_Sub);
+
+ if Read_Std_Logic (Res.Mem, 0) = 'X' then
+ Warn_X (Loc);
+ end if;
+
+ return Res;
+ end Add_Sub_Sgn_Uns_Sgn;
+
+ function Add_Sgn_Uns_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Sgn_Uns_Sgn (L, R, False, Loc);
+ end Add_Sgn_Uns_Sgn;
+
+ function Sub_Sgn_Uns_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Sgn_Uns_Sgn (L, R, True, Loc);
+ end Sub_Sgn_Uns_Sgn;
+
+ -- Convert integer V to a std logic vector of length LEN at M.
+ procedure To_Unsigned (M : Memory_Ptr; Len : Uns32; V : Uns64)
+ is
+ R : Uns64;
+ begin
+ R := V;
+ for I in reverse 1 .. Len loop
+ Write_Std_Logic (M, I - 1, Uns_To_01 (R and 1));
+ R := Shift_Right (R, 1);
+ end loop;
+ end To_Unsigned;
+
+ procedure To_Signed (M : Memory_Ptr; Len : Uns32; V : Uns64)
+ is
+ R : Uns64;
+ begin
+ R := V;
+ for I in reverse 1 .. Len loop
+ Write_Std_Logic (M, I - 1, Uns_To_01 (R and 1));
+ R := Shift_Right_Arithmetic (R, 1);
+ end loop;
+ end To_Signed;
+
+ function Add_Sub_Vec_Int (L : Memtyp;
+ R : Int64;
+ Signed : Boolean;
+ Is_Sub : Boolean;
+ Loc : Location_Type) return Memtyp
+ is
+ Len : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := Uns32'Min (Len, 64);
+ Rm : aliased Memory_Array (1 .. Size_Type (Rlen));
+ Rmem : constant Memory_Ptr := To_Memory_Ptr (Rm'Address);
+ Res : Memtyp;
+ begin
+ Res.Typ := Create_Res_Type (L.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
+ if Signed then
+ To_Signed (Rmem, Rlen, To_Uns64 (R));
+ else
+ To_Unsigned (Rmem, Rlen, To_Uns64 (R));
+ end if;
+ Add_Sub_Vec_Vec
+ (Res.Mem, Len, L.Mem, Rmem, Len, Rlen, False, Signed, Is_Sub);
+
+ if Read_Std_Logic (Res.Mem, 0) = 'X' then
+ Warn_X (Loc);
+ end if;
+
+ return Res;
+ end Add_Sub_Vec_Int;
+
+ function Add_Uns_Int_Uns (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Vec_Int (L, R, True, False, Loc);
+ end Add_Uns_Int_Uns;
+
+ function Sub_Uns_Int_Uns (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Vec_Int (L, R, True, True, Loc);
+ end Sub_Uns_Int_Uns;
+
+ function Add_Sgn_Int_Sgn (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Vec_Int (L, R, True, False, Loc);
+ end Add_Sgn_Int_Sgn;
+
+ function Sub_Sgn_Int_Sgn (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Vec_Int (L, R, True, True, Loc);
+ end Sub_Sgn_Int_Sgn;
+
+ function Add_Sub_Int_Vec (L : Int64;
+ R : Memtyp;
+ Signed : Boolean;
+ Is_Sub : Boolean;
+ Loc : Location_Type) return Memtyp
+ is
+ Len : constant Uns32 := R.Typ.Abound.Len;
+ Llen : constant Uns32 := Uns32'Min (Len, 64);
+ Lm : aliased Memory_Array (1 .. Size_Type (Llen));
+ Lmem : constant Memory_Ptr := To_Memory_Ptr (Lm'Address);
+ Res : Memtyp;
+ begin
+ Res.Typ := Create_Res_Type (R.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
+ if Signed then
+ To_Signed (Lmem, Llen, To_Uns64 (L));
+ else
+ To_Unsigned (Lmem, Llen, To_Uns64 (L));
+ end if;
+ Add_Sub_Vec_Vec
+ (Res.Mem, Len, Lmem, R.Mem, Llen, Len, Signed, False, Is_Sub);
+
+ if Read_Std_Logic (Res.Mem, 0) = 'X' then
+ Warn_X (Loc);
+ end if;
+
+ return Res;
+ end Add_Sub_Int_Vec;
+
+ function Sub_Int_Uns_Uns (L : Int64; R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Int_Vec (L, R, False, True, Loc);
+ end Sub_Int_Uns_Uns;
+
+ function Sub_Int_Sgn_Sgn (L : Int64; R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Int_Vec (L, R, True, True, Loc);
+ end Sub_Int_Sgn_Sgn;
+
+ function Add_Sub_Vec_Log (L, R : Memtyp;
+ Is_Sub : Boolean;
+ Loc : Location_Type) return Memtyp
+ is
+ Len : constant Uns32 := L.Typ.Abound.Len;
+ Res : Memtyp;
+ begin
+ Res.Typ := Create_Res_Type (L.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
+ Add_Sub_Vec_Vec
+ (Res.Mem, Len, L.Mem, R.Mem, Len, 1, False, False, Is_Sub);
+
+ if Read_Std_Logic (Res.Mem, 0) = 'X' then
+ Warn_X (Loc);
+ end if;
+
+ return Res;
+ end Add_Sub_Vec_Log;
+
+ function Add_Uns_Log_Uns (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Vec_Log (L, R, False, Loc);
+ end Add_Uns_Log_Uns;
+
+ function Add_Sgn_Log_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Vec_Log (L, R, False, Loc);
+ end Add_Sgn_Log_Sgn;
+
+ function Sub_Uns_Log_Uns (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Vec_Log (L, R, True, Loc);
+ end Sub_Uns_Log_Uns;
+
+ function Sub_Sgn_Log_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Vec_Log (L, R, True, Loc);
+ end Sub_Sgn_Log_Sgn;
+
+ function Add_Sub_Log_Vec (L, R : Memtyp;
+ Is_Sub : Boolean;
+ Loc : Location_Type) return Memtyp
+ is
+ Len : constant Uns32 := R.Typ.Abound.Len;
+ Res : Memtyp;
+ begin
+ Res.Typ := Create_Res_Type (R.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
+ Add_Sub_Vec_Vec
+ (Res.Mem, Len, L.Mem, R.Mem, 1, Len, False, False, Is_Sub);
+
+ if Read_Std_Logic (Res.Mem, 0) = 'X' then
+ Warn_X (Loc);
+ end if;
+
+ return Res;
+ end Add_Sub_Log_Vec;
+
+ function Sub_Log_Uns_Uns (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Log_Vec (L, R, True, Loc);
+ end Sub_Log_Uns_Uns;
+
+ function Sub_Log_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Add_Sub_Log_Vec (L, R, True, Loc);
+ end Sub_Log_Sgn_Sgn;
+
+ function Neg_Sgn_Sgn (L : Memtyp; Loc : Location_Type) return Memtyp
+ is
+ Len : constant Uns32 := L.Typ.Abound.Len;
+ Res : Memtyp;
+ begin
+ Res.Typ := Create_Res_Type (L.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
+ Neg_Vec (L.Mem, Res.Mem, Len);
+
+ if Read_Std_Logic (Res.Mem, 0) = 'X' then
+ Warn_X (Loc);
+ end if;
+
+ return Res;
+ end Neg_Sgn_Sgn;
+
+ function Abs_Sgn_Sgn (L : Memtyp; Loc : Location_Type) return Memtyp
+ is
+ Len : constant Uns32 := L.Typ.Abound.Len;
+ Res : Memtyp;
+ begin
+ Res.Typ := Create_Res_Type (L.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
+ Abs_Vec (L.Mem, Res.Mem, Len);
+
+ -- Humm, there is no warning if the MSB is '0'.
+ if Read_Std_Logic (Res.Mem, 0) = 'X' then
+ Warn_X (Loc);
+ end if;
+
+ return Res;
+ end Abs_Sgn_Sgn;
+
+ function Mul_Vec_Vec (L, R : Memtyp;
+ L_Sign, R_Sign : Boolean;
+ Loc : Location_Type) return Memtyp
+ is
+ Llen : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := R.Typ.Abound.Len;
+ Len : constant Uns32 := Llen + Rlen + Boolean'Pos (L_Sign xor R_Sign);
+ Res : Memtyp;
+ begin
+ Res.Typ := Create_Res_Type (L.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
+ Mul_Vec (L.Mem, R.Mem, Llen, Rlen, L_Sign, R_Sign, Res.Mem);
+ if Read_Std_Logic (Res.Mem, 0) = 'X' then
+ Warn_X (Loc);
+ end if;
+
+ return Res;
+ end Mul_Vec_Vec;
+
+ function Mul_Uns_Uns_Uns (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Mul_Vec_Vec (L, R, False, False, Loc);
+ end Mul_Uns_Uns_Uns;
+
+ function Mul_Sgn_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Mul_Vec_Vec (L, R, True, True, Loc);
+ end Mul_Sgn_Sgn_Sgn;
+
+ function Mul_Uns_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Mul_Vec_Vec (L, R, False, True, Loc);
+ end Mul_Uns_Sgn_Sgn;
+
+ function Mul_Sgn_Uns_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Mul_Vec_Vec (L, R, True, False, Loc);
+ end Mul_Sgn_Uns_Sgn;
+
+ function Has_X (V : Memtyp) return Boolean is
+ begin
+ for I in 1 .. V.Typ.Abound.Len loop
+ if Sl_To_X01 (Read_Std_Logic (V.Mem, I - 1)) = 'X' then
+ return True;
+ end if;
+ end loop;
+ return False;
+ end Has_X;
+
+ function Compare_Uns_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Order_Type
+ is
+ X_In_L : constant Boolean := Has_X (L);
+ X_In_R : constant Boolean := Has_X (R);
+ begin
+ if X_In_L or X_In_R then
+ Warn_X (Loc);
+ if X_In_L and X_In_R then
+ return Equal;
+ elsif X_In_L then
+ return Less;
+ else
+ return Greater;
+ end if;
+ end if;
+
+ return Compare_Vec (L.Mem, R.Mem,
+ L.Typ.Abound.Len, R.Typ.Abound.Len,
+ False, True);
+ end Compare_Uns_Sgn;
+
+ function Compare_Uns_Int (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Order_Type
+ is
+ Len : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := Uns32'Min (Len + 1, 64);
+ Rm : aliased Memory_Array (1 .. 64);
+ Rmem : constant Memory_Ptr := To_Memory_Ptr (Rm'Address);
+ begin
+ if Has_X (L) then
+ Warn_X (Loc);
+ return Less;
+ end if;
+
+ To_Signed (Rmem, Rlen, To_Uns64 (R));
+ return Compare_Vec (L.Mem, Rmem, Len, Rlen, False, True);
+ end Compare_Uns_Int;
+
+ function Compare_Sgn_Int (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Order_Type
+ is
+ Len : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := Uns32'Min (Len, 64);
+ Rm : aliased Memory_Array (1 .. 64);
+ Rmem : constant Memory_Ptr := To_Memory_Ptr (Rm'Address);
+ begin
+ if Has_X (L) then
+ Warn_X (Loc);
+ return Less;
+ end if;
+
+ To_Signed (Rmem, Rlen, To_Uns64 (R));
+ return Compare_Vec (L.Mem, Rmem, Len, Rlen, True, True);
+ end Compare_Sgn_Int;
+
+end Synth.Ieee.Std_Logic_Arith;
diff --git a/src/synth/synth-ieee-std_logic_arith.ads b/src/synth/synth-ieee-std_logic_arith.ads
new file mode 100644
index 000000000..0c8d400f0
--- /dev/null
+++ b/src/synth/synth-ieee-std_logic_arith.ads
@@ -0,0 +1,70 @@
+-- std_logic_arith
+-- Copyright (C) 2022 Tristan Gingold
+--
+-- This file is part of GHDL.
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <gnu.org/licenses>.
+
+with Types; use Types;
+
+with Elab.Vhdl_Objtypes; use Elab.Vhdl_Objtypes;
+
+package Synth.Ieee.Std_Logic_Arith is
+
+ -- "+"
+ function Add_Uns_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Add_Sgn_Uns_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Add_Uns_Int_Uns (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp;
+ function Add_Sgn_Int_Sgn (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp;
+
+ function Add_Uns_Log_Uns (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Add_Sgn_Log_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+
+ -- "-"
+ function Sub_Uns_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Sub_Sgn_Uns_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Sub_Uns_Int_Uns (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp;
+ function Sub_Int_Uns_Uns (L : Int64; R : Memtyp; Loc : Location_Type)
+ return Memtyp;
+ function Sub_Sgn_Int_Sgn (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp;
+ function Sub_Int_Sgn_Sgn (L : Int64; R : Memtyp; Loc : Location_Type)
+ return Memtyp;
+ function Sub_Uns_Log_Uns (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Sub_Sgn_Log_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Sub_Log_Uns_Uns (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Sub_Log_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+
+ -- Unary
+ function Neg_Sgn_Sgn (L : Memtyp; Loc : Location_Type) return Memtyp;
+ function Abs_Sgn_Sgn (L : Memtyp; Loc : Location_Type) return Memtyp;
+
+ -- "*"
+ function Mul_Uns_Uns_Uns (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Mul_Sgn_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Mul_Uns_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+ function Mul_Sgn_Uns_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp;
+
+ -- Comparison
+ function Compare_Uns_Sgn (L, R : Memtyp; Loc : Location_Type)
+ return Order_Type;
+ function Compare_Uns_Int (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Order_Type;
+ function Compare_Sgn_Int (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Order_Type;
+
+end Synth.Ieee.Std_Logic_Arith;
diff --git a/src/synth/synth-ieee-utils.adb b/src/synth/synth-ieee-utils.adb
new file mode 100644
index 000000000..db1a48d71
--- /dev/null
+++ b/src/synth/synth-ieee-utils.adb
@@ -0,0 +1,183 @@
+-- Simple logic utilities for ieee.std_logic
+-- Copyright (C) 2019 Tristan Gingold
+--
+-- This file is part of GHDL.
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <gnu.org/licenses>.
+
+package body Synth.Ieee.Utils is
+ procedure Neg_Vec (Src : Memory_Ptr; Dst : Memory_Ptr; Len : Uns32)
+ is
+ Vb, Carry : Sl_X01;
+ begin
+ Carry := '1';
+ for I in 1 .. Len loop
+ Vb := Sl_To_X01 (Read_Std_Logic (Src, Len - I));
+ Vb := Not_Table (Vb);
+ Write_Std_Logic (Dst, Len - I, Xor_Table (Carry, Vb));
+ Carry := And_Table (Carry, Vb);
+ end loop;
+ end Neg_Vec;
+
+ procedure Abs_Vec (Src : Memory_Ptr; Dst : Memory_Ptr; Len : Uns32) is
+ begin
+ if Len > 0 and then Sl_To_X01 (Read_Std_Logic (Src, 0)) = '1' then
+ Neg_Vec (Src, Dst, Len);
+ else
+ for I in 1 .. Size_Type (Len) loop
+ Write_U8 (Dst + (I - 1), Read_U8 (Src + (I - 1)));
+ end loop;
+ end if;
+ end Abs_Vec;
+
+ procedure Fill (Res : Memory_Ptr; Len : Uns32; V : Std_Ulogic) is
+ begin
+ for I in 1 .. Len loop
+ Write_Std_Logic (Res, I - 1, V);
+ end loop;
+ end Fill;
+
+ procedure Mul_Vec (L, R : Memory_Ptr;
+ Llen, Rlen : Uns32;
+ L_Sign, R_Sign : Boolean;
+ Res : Memory_Ptr)
+ is
+ Res_Len : constant Uns32 :=
+ Llen + Rlen + Boolean'Pos (L_Sign xor R_Sign);
+ Lb, Rb, Vb, Carry : Sl_X01;
+ begin
+ -- Check for 'X' in L.
+ for I in 1 .. Llen loop
+ if Read_Std_Logic (L, I - 1) = 'X' then
+ Fill (Res, Res_Len, 'X');
+ return;
+ end if;
+ end loop;
+
+ -- Init RES.
+ Fill (Res, Res_Len, '0');
+
+ if Rlen = 0 then
+ return;
+ end if;
+
+ -- Shift and add L.
+ for I in 1 .. Rlen - Boolean'Pos (R_Sign) loop
+ Rb := Sl_To_X01 (Read_Std_Logic (R, Rlen - I));
+ if Rb = '1' then
+ -- Compute res := res + shift_left (l, i).
+ Carry := '0';
+ for J in 1 .. Llen loop
+ Lb := Read_Std_Logic (L, Llen - J);
+ Vb := Read_Std_Logic (Res, Res_Len - (I + J - 1));
+ Write_Std_Logic
+ (Res, Res_Len - (I + J - 1), Compute_Sum (Carry, Vb, Lb));
+ Carry := Compute_Carry (Carry, Vb, Lb);
+ end loop;
+ -- Propagate carry.
+ if L_Sign then
+ -- Sign extend.
+ Lb := Read_Std_Logic (L, 0);
+ else
+ Lb := '0';
+ end if;
+ for J in I + Llen .. Res_Len loop
+ exit when Lb = '0' and Carry = '0';
+ Vb := Read_Std_Logic (Res, Res_Len - J);
+ Write_Std_Logic (Res, Res_Len - J, Compute_Sum (Carry, Vb, Lb));
+ Carry := Compute_Carry (Carry, Vb, Lb);
+ end loop;
+ elsif Rb = 'X' then
+ Fill (Res, Res_Len, 'X');
+ exit;
+ end if;
+ end loop;
+ if R_Sign and then Read_Std_Logic (R, 0) = '1' then
+ -- R is a negative number. It is considered as:
+ -- -2**n + (Rn-1 Rn-2 ... R0).
+ -- Compute res := res - 2**n * l.
+ Carry := '1';
+ for I in 1 .. Llen loop
+ -- Start at len - (rlen - 1) = llen + 1
+ Vb := Read_Std_Logic (Res, Llen - I + 1);
+ Lb := Not_Table (Read_Std_Logic (L, Llen - I));
+ Write_Std_Logic (Res, Llen - I + 1, Compute_Sum (Carry, Vb, Lb));
+ Carry := Compute_Carry (Carry, Vb, Lb);
+ end loop;
+ -- The last bit.
+ Vb := Read_Std_Logic (Res, 0);
+ Lb := Not_Table (Read_Std_Logic (L, 0));
+ Write_Std_Logic (Res, 0, Compute_Sum (Carry, Vb, Lb));
+ end if;
+ end Mul_Vec;
+
+ function Compare_Bit (Lb, Rb : Sl_01;
+ L_Sign, R_Sign : Boolean) return Order_Type is
+ begin
+ if Lb = '1' and Rb = '0' then
+ if L_Sign then
+ return Less;
+ else
+ return Greater;
+ end if;
+ elsif Lb = '0' and Rb = '1' then
+ if R_Sign then
+ return Greater;
+ else
+ return Less;
+ end if;
+ else
+ return Equal;
+ end if;
+ end Compare_Bit;
+
+ function Compare_Vec (L, R : Memory_Ptr;
+ Llen, Rlen : Uns32;
+ L_Sign, R_Sign : Boolean) return Order_Type
+ is
+ Lb, Rb : Sl_01;
+ begin
+ -- The sign.
+ if L_Sign and Llen > 0 then
+ Lb := Sl_To_01 (Read_Std_Logic (L, 0));
+ else
+ Lb := '0';
+ end if;
+ if R_Sign and Rlen > 0 then
+ Rb := Sl_To_01 (Read_Std_Logic (R, 0));
+ else
+ Rb := '0';
+ end if;
+ if Lb /= Rb then
+ return Compare_Bit (Lb, Rb, L_Sign, R_Sign);
+ end if;
+
+ -- Same sign.
+ for I in reverse 1 .. Uns32'Max (Llen, Rlen) loop
+ if I <= Llen then
+ Lb := Sl_To_01 (Read_Std_Logic (L, Llen - I));
+ end if;
+ if I <= Rlen then
+ Rb := Sl_To_01 (Read_Std_Logic (R, Rlen - I));
+ end if;
+ if Lb = '0' and Rb = '1' then
+ return Less;
+ elsif Lb = '1' and Rb = '0' then
+ return Greater;
+ end if;
+ end loop;
+ return Equal;
+ end Compare_Vec;
+
+end Synth.Ieee.Utils;
diff --git a/src/synth/synth-ieee-utils.ads b/src/synth/synth-ieee-utils.ads
index d2fe7d5b4..564fbb74c 100644
--- a/src/synth/synth-ieee-utils.ads
+++ b/src/synth/synth-ieee-utils.ads
@@ -18,6 +18,8 @@
with Types; use Types;
+with Elab.Memtype; use Elab.Memtype;
+
with Synth.Ieee.Std_Logic_1164; use Synth.Ieee.Std_Logic_1164;
package Synth.Ieee.Utils is
@@ -40,6 +42,30 @@ package Synth.Ieee.Utils is
Sl_To_X01 : constant Sl_To_X01_Array :=
('0' | 'L' => '0', '1' | 'H' => '1', others => 'X');
+ type Sl_To_01_Array is array (Std_Ulogic) of Sl_01;
+ Sl_To_01 : constant Sl_To_X01_Array :=
+ ('1' | 'H' => '1', others => '0');
+
type Uns_To_01_Array is array (Uns64 range 0 .. 1) of Sl_X01;
Uns_To_01 : constant Uns_To_01_Array := (0 => '0', 1 => '1');
+
+ procedure Fill (Res : Memory_Ptr; Len : Uns32; V : Std_Ulogic);
+
+ -- Note: SRC = DST is allowed.
+ procedure Neg_Vec (Src : Memory_Ptr; Dst : Memory_Ptr; Len : Uns32);
+
+ -- Note: SRC = DST is allowed.
+ procedure Abs_Vec (Src : Memory_Ptr; Dst : Memory_Ptr; Len : Uns32);
+
+ -- Multiplication.
+ -- Length of RES is LLEN + RLEN + 1 (if L_SIGN /= R_SIGN)
+ procedure Mul_Vec (L, R : Memory_Ptr;
+ Llen, Rlen : Uns32;
+ L_Sign, R_Sign : Boolean;
+ Res : Memory_Ptr);
+
+ -- Assume no X (they are considered as '0').
+ function Compare_Vec (L, R : Memory_Ptr;
+ Llen, Rlen : Uns32;
+ L_Sign, R_Sign : Boolean) return Order_Type;
end Synth.Ieee.Utils;
diff --git a/src/synth/synth-vhdl_eval.adb b/src/synth/synth-vhdl_eval.adb
index 5d97528dd..7c189720b 100644
--- a/src/synth/synth-vhdl_eval.adb
+++ b/src/synth/synth-vhdl_eval.adb
@@ -40,6 +40,7 @@ with Synth.Source; use Synth.Source;
with Synth.Vhdl_Expr; use Synth.Vhdl_Expr;
with Synth.Ieee.Std_Logic_1164; use Synth.Ieee.Std_Logic_1164;
with Synth.Ieee.Numeric_Std; use Synth.Ieee.Numeric_Std;
+with Synth.Ieee.Std_Logic_Arith; use Synth.Ieee.Std_Logic_Arith;
package body Synth.Vhdl_Eval is
-- As log2(3m) is directly referenced, the program must be linked with -lm
@@ -279,6 +280,7 @@ package body Synth.Vhdl_Eval is
-- Execute shift and rot.
-- ZERO is the value to be used for '0' (for shifts).
+ -- It is 0 for bit, 2 for std_logic.
function Execute_Shift_Operator (Left : Memtyp;
Count : Int64;
Zero : Ghdl_U8;
@@ -923,10 +925,11 @@ package body Synth.Vhdl_Eval is
| Iir_Predefined_Ieee_Numeric_Std_Ror_Uns_Int
| Iir_Predefined_Ieee_Numeric_Std_Ror_Sgn_Int =>
return Execute_Shift_Operator
- (Left, Read_Discrete (Right), Std_Ulogic'Pos('0'),
+ (Left, Read_Discrete (Right), Std_Ulogic'Pos('0'),
Iir_Predefined_Array_Ror);
- when Iir_Predefined_Ieee_Numeric_Std_Eq_Uns_Uns =>
+ when Iir_Predefined_Ieee_Numeric_Std_Eq_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Eq_Uns_Uns =>
declare
Res : Boolean;
begin
@@ -947,21 +950,24 @@ package body Synth.Vhdl_Eval is
Res := Compare_Uns_Nat (Right, Left, Greater, +Expr) = Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Eq_Sgn_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Eq_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Eq_Sgn_Sgn =>
declare
Res : Boolean;
begin
Res := Compare_Sgn_Sgn (Left, Right, Greater, +Expr) = Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Eq_Sgn_Int =>
+ when Iir_Predefined_Ieee_Numeric_Std_Eq_Sgn_Int
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Eq_Sgn_Int =>
declare
Res : Boolean;
begin
Res := Compare_Sgn_Int (Left, Right, Greater, +Expr) = Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Eq_Int_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Eq_Int_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Eq_Int_Sgn =>
declare
Res : Boolean;
begin
@@ -969,7 +975,8 @@ package body Synth.Vhdl_Eval is
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Ne_Uns_Uns =>
+ when Iir_Predefined_Ieee_Numeric_Std_Ne_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Ne_Uns_Uns =>
declare
Res : Boolean;
begin
@@ -990,22 +997,41 @@ package body Synth.Vhdl_Eval is
Res := Compare_Uns_Nat (Right, Left, Greater, +Expr) /= Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Ne_Sgn_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Ne_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Ne_Sgn_Sgn =>
declare
Res : Boolean;
begin
Res := Compare_Sgn_Sgn (Left, Right, Greater, +Expr) /= Equal;
return Create_Memory_Boolean (Res);
end;
+ when Iir_Predefined_Ieee_Numeric_Std_Ne_Sgn_Int
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Ne_Sgn_Int =>
+ declare
+ Res : Boolean;
+ begin
+ Res := Compare_Sgn_Int (Left, Right, Greater, +Expr) /= Equal;
+ return Create_Memory_Boolean (Res);
+ end;
+ when Iir_Predefined_Ieee_Numeric_Std_Ne_Int_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Ne_Int_Sgn =>
+ declare
+ Res : Boolean;
+ begin
+ Res := Compare_Sgn_Int (Right, Left, Greater, +Expr) /= Equal;
+ return Create_Memory_Boolean (Res);
+ end;
- when Iir_Predefined_Ieee_Numeric_Std_Gt_Uns_Uns =>
+ when Iir_Predefined_Ieee_Numeric_Std_Gt_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Gt_Uns_Uns =>
declare
Res : Boolean;
begin
Res := Compare_Uns_Uns (Left, Right, Less, +Expr) = Greater;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Gt_Sgn_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Gt_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Gt_Sgn_Sgn =>
declare
Res : Boolean;
begin
@@ -1026,14 +1052,16 @@ package body Synth.Vhdl_Eval is
Res := Compare_Uns_Nat (Left, Right, Less, +Expr) = Greater;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Gt_Sgn_Int =>
+ when Iir_Predefined_Ieee_Numeric_Std_Gt_Sgn_Int
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Gt_Sgn_Int =>
declare
Res : Boolean;
begin
Res := Compare_Sgn_Int (Left, Right, Less, +Expr) = Greater;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Gt_Int_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Gt_Int_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Gt_Int_Sgn =>
declare
Res : Boolean;
begin
@@ -1041,7 +1069,8 @@ package body Synth.Vhdl_Eval is
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Ge_Uns_Uns =>
+ when Iir_Predefined_Ieee_Numeric_Std_Ge_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Ge_Uns_Uns =>
declare
Res : Boolean;
begin
@@ -1062,21 +1091,24 @@ package body Synth.Vhdl_Eval is
Res := Compare_Uns_Nat (Left, Right, Less, +Expr) >= Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Ge_Sgn_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Ge_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Ge_Sgn_Sgn =>
declare
Res : Boolean;
begin
Res := Compare_Sgn_Sgn (Left, Right, Less, +Expr) >= Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Ge_Sgn_Int =>
+ when Iir_Predefined_Ieee_Numeric_Std_Ge_Sgn_Int
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Ge_Sgn_Int =>
declare
Res : Boolean;
begin
Res := Compare_Sgn_Int (Left, Right, Less, +Expr) >= Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Ge_Int_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Ge_Int_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Ge_Int_Sgn =>
declare
Res : Boolean;
begin
@@ -1084,7 +1116,8 @@ package body Synth.Vhdl_Eval is
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Le_Uns_Uns =>
+ when Iir_Predefined_Ieee_Numeric_Std_Le_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Le_Uns_Uns =>
declare
Res : Boolean;
begin
@@ -1105,21 +1138,24 @@ package body Synth.Vhdl_Eval is
Res := Compare_Nat_Uns (Left, Right, Greater, +Expr) <= Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Le_Sgn_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Le_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Le_Sgn_Sgn =>
declare
Res : Boolean;
begin
Res := Compare_Sgn_Sgn (Left, Right, Greater, +Expr) <= Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Le_Int_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Le_Int_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Le_Int_Sgn =>
declare
Res : Boolean;
begin
Res := Compare_Sgn_Int (Right, Left, Less, +Expr) >= Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Le_Sgn_Int =>
+ when Iir_Predefined_Ieee_Numeric_Std_Le_Sgn_Int
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Le_Sgn_Int =>
declare
Res : Boolean;
begin
@@ -1127,7 +1163,8 @@ package body Synth.Vhdl_Eval is
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Lt_Uns_Uns =>
+ when Iir_Predefined_Ieee_Numeric_Std_Lt_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Lt_Uns_Uns =>
declare
Res : Boolean;
begin
@@ -1148,21 +1185,24 @@ package body Synth.Vhdl_Eval is
Res := Compare_Nat_Uns (Left, Right, Greater, +Expr) < Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Lt_Sgn_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Lt_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Lt_Sgn_Sgn =>
declare
Res : Boolean;
begin
Res := Compare_Sgn_Sgn (Left, Right, Greater, +Expr) < Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Lt_Int_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Lt_Int_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Lt_Int_Sgn =>
declare
Res : Boolean;
begin
Res := Compare_Sgn_Int (Right, Left, Less, +Expr) > Equal;
return Create_Memory_Boolean (Res);
end;
- when Iir_Predefined_Ieee_Numeric_Std_Lt_Sgn_Int =>
+ when Iir_Predefined_Ieee_Numeric_Std_Lt_Sgn_Int
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Lt_Sgn_Int =>
declare
Res : Boolean;
begin
@@ -1170,6 +1210,180 @@ package body Synth.Vhdl_Eval is
return Create_Memory_Boolean (Res);
end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Lt_Uns_Sgn =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Left, Right, +Expr);
+ return Create_Memory_Boolean (Res < Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Lt_Sgn_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Right, Left, +Expr);
+ return Create_Memory_Boolean (Res > Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Lt_Uns_Int =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Left, Read_Discrete (Right), +Expr);
+ return Create_Memory_Boolean (Res < Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Lt_Int_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Right, Read_Discrete (Left), +Expr);
+ return Create_Memory_Boolean (Res > Equal);
+ end;
+
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Le_Uns_Sgn =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Left, Right, +Expr);
+ return Create_Memory_Boolean (Res <= Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Le_Sgn_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Right, Left, +Expr);
+ return Create_Memory_Boolean (Res >= Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Le_Uns_Int =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Left, Read_Discrete (Right), +Expr);
+ return Create_Memory_Boolean (Res <= Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Le_Int_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Right, Read_Discrete (Left), +Expr);
+ return Create_Memory_Boolean (Res >= Equal);
+ end;
+
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Gt_Uns_Sgn =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Left, Right, +Expr);
+ return Create_Memory_Boolean (Res > Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Gt_Sgn_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Right, Left, +Expr);
+ return Create_Memory_Boolean (Res < Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Gt_Uns_Int =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Left, Read_Discrete (Right), +Expr);
+ return Create_Memory_Boolean (Res > Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Gt_Int_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Right, Read_Discrete (Left), +Expr);
+ return Create_Memory_Boolean (Res < Equal);
+ end;
+
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Ge_Uns_Sgn =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Left, Right, +Expr);
+ return Create_Memory_Boolean (Res >= Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Ge_Sgn_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Right, Left, +Expr);
+ return Create_Memory_Boolean (Res <= Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Ge_Uns_Int =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Left, Read_Discrete (Right), +Expr);
+ return Create_Memory_Boolean (Res >= Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Ge_Int_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Right, Read_Discrete (Left), +Expr);
+ return Create_Memory_Boolean (Res <= Equal);
+ end;
+
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Eq_Uns_Sgn =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Left, Right, +Expr);
+ return Create_Memory_Boolean (Res = Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Eq_Sgn_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Right, Left, +Expr);
+ return Create_Memory_Boolean (Res = Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Eq_Uns_Int =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Left, Read_Discrete (Right), +Expr);
+ return Create_Memory_Boolean (Res = Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Eq_Int_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Right, Read_Discrete (Left), +Expr);
+ return Create_Memory_Boolean (Res = Equal);
+ end;
+
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Ne_Uns_Sgn =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Left, Right, +Expr);
+ return Create_Memory_Boolean (Res /= Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Ne_Sgn_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Sgn (Right, Left, +Expr);
+ return Create_Memory_Boolean (Res /= Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Ne_Uns_Int =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Left, Read_Discrete (Right), +Expr);
+ return Create_Memory_Boolean (Res /= Equal);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Ne_Int_Uns =>
+ declare
+ Res : Order_Type;
+ begin
+ Res := Compare_Uns_Int (Right, Read_Discrete (Left), +Expr);
+ return Create_Memory_Boolean (Res /= Equal);
+ end;
+
when Iir_Predefined_Ieee_Numeric_Std_Add_Uns_Uns
| Iir_Predefined_Ieee_Std_Logic_Unsigned_Add_Slv_Slv
| Iir_Predefined_Ieee_Std_Logic_Arith_Add_Uns_Uns_Slv
@@ -1195,7 +1409,8 @@ package body Synth.Vhdl_Eval is
return Add_Uns_Nat (Right, To_Uns64 (Read_Discrete (Left)), +Expr);
when Iir_Predefined_Ieee_Numeric_Std_Add_Sgn_Sgn
- | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Sgn_Sgn_Sgn =>
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Sgn_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Sgn_Sgn_Slv =>
return Add_Sgn_Sgn (Left, Right, +Expr);
when Iir_Predefined_Ieee_Numeric_Std_Add_Sgn_Int =>
return Add_Sgn_Int (Left, Read_Discrete (Right), +Expr);
@@ -1207,8 +1422,42 @@ package body Synth.Vhdl_Eval is
when Iir_Predefined_Ieee_Numeric_Std_Add_Log_Sgn =>
return Add_Sgn_Sgn (Log_To_Vec (Left, Right), Right, +Expr);
+ -- std_logic_arith."+"
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Add_Uns_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Uns_Sgn_Slv =>
+ return Add_Uns_Sgn_Sgn (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Add_Sgn_Uns_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Sgn_Uns_Slv =>
+ return Add_Sgn_Uns_Sgn (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Add_Uns_Int_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Uns_Int_Slv =>
+ return Add_Uns_Int_Uns (Left, Read_Discrete (Right), +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Add_Int_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Int_Uns_Slv =>
+ return Add_Uns_Int_Uns (Right, Read_Discrete (Left), +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Add_Sgn_Int_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Sgn_Int_Slv =>
+ return Add_Sgn_Int_Sgn (Left, Read_Discrete (Right), +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Add_Int_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Int_Sgn_Slv =>
+ return Add_Sgn_Int_Sgn (Right, Read_Discrete (Left), +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Add_Uns_Log_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Uns_Log_Slv =>
+ return Add_Uns_Log_Uns (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Add_Log_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Log_Uns_Slv =>
+ return Add_Uns_Log_Uns (Right, Left, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Add_Sgn_Log_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Sgn_Log_Slv =>
+ return Add_Sgn_Log_Sgn (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Add_Log_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Add_Log_Sgn_Slv =>
+ return Add_Sgn_Log_Sgn (Right, Left, +Expr);
+
when Iir_Predefined_Ieee_Numeric_Std_Sub_Uns_Uns
| Iir_Predefined_Ieee_Numeric_Std_Unsigned_Sub_Slv_Slv
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Uns_Uns_Slv
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Uns_Uns_Uns
| Iir_Predefined_Ieee_Std_Logic_Unsigned_Sub_Slv_Slv =>
return Sub_Uns_Uns (Left, Right, +Expr);
when Iir_Predefined_Ieee_Numeric_Std_Sub_Uns_Nat
@@ -1227,7 +1476,9 @@ package body Synth.Vhdl_Eval is
| Iir_Predefined_Ieee_Std_Logic_Unsigned_Sub_Log_Slv =>
return Sub_Uns_Uns (Log_To_Vec (Left, Right), Right, +Expr);
- when Iir_Predefined_Ieee_Numeric_Std_Sub_Sgn_Sgn =>
+ when Iir_Predefined_Ieee_Numeric_Std_Sub_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Sgn_Sgn_Slv
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Sgn_Sgn_Sgn =>
return Sub_Sgn_Sgn (Left, Right, +Expr);
when Iir_Predefined_Ieee_Numeric_Std_Sub_Sgn_Int =>
return Sub_Sgn_Int (Left, Read_Discrete (Right), +Expr);
@@ -1239,6 +1490,38 @@ package body Synth.Vhdl_Eval is
when Iir_Predefined_Ieee_Numeric_Std_Sub_Log_Sgn =>
return Sub_Sgn_Sgn (Log_To_Vec (Left, Right), Right, +Expr);
+ -- std_logic_arith."-"
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Uns_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Uns_Sgn_Slv =>
+ return Sub_Uns_Sgn_Sgn (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Sgn_Uns_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Sgn_Uns_Slv =>
+ return Sub_Sgn_Uns_Sgn (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Uns_Int_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Uns_Int_Slv =>
+ return Sub_Uns_Int_Uns (Left, Read_Discrete (Right), +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Int_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Int_Uns_Slv =>
+ return Sub_Int_Uns_Uns (Read_Discrete (Left), Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Sgn_Int_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Sgn_Int_Slv =>
+ return Sub_Sgn_Int_Sgn (Left, Read_Discrete (Right), +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Int_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Int_Sgn_Slv =>
+ return Sub_Int_Sgn_Sgn (Read_Discrete (Left), Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Uns_Log_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Uns_Log_Slv =>
+ return Sub_Uns_Log_Uns (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Log_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Log_Uns_Slv =>
+ return Sub_Log_Uns_Uns (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Sgn_Log_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Sgn_Log_Slv =>
+ return Sub_Sgn_Log_Sgn (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Log_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Sub_Log_Sgn_Slv =>
+ return Sub_Log_Sgn_Sgn (Left, Right, +Expr);
+
when Iir_Predefined_Ieee_Numeric_Std_Mul_Uns_Uns =>
return Mul_Uns_Uns (Left, Right, +Expr);
when Iir_Predefined_Ieee_Numeric_Std_Mul_Nat_Uns =>
@@ -1253,6 +1536,20 @@ package body Synth.Vhdl_Eval is
when Iir_Predefined_Ieee_Numeric_Std_Mul_Int_Sgn =>
return Mul_Int_Sgn (Read_Discrete (Left), Right, +Expr);
+ -- std_logic_arith."*"
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Mul_Uns_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Mul_Uns_Uns_Slv =>
+ return Mul_Uns_Uns_Uns (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Mul_Sgn_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Mul_Sgn_Sgn_Slv =>
+ return Mul_Sgn_Sgn_Sgn (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Mul_Uns_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Mul_Uns_Sgn_Slv =>
+ return Mul_Uns_Sgn_Sgn (Left, Right, +Expr);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Mul_Sgn_Uns_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Mul_Sgn_Uns_Slv =>
+ return Mul_Sgn_Uns_Sgn (Left, Right, +Expr);
+
when Iir_Predefined_Ieee_Numeric_Std_Div_Uns_Uns =>
return Div_Uns_Uns (Left, Right, +Expr);
when Iir_Predefined_Ieee_Numeric_Std_Div_Uns_Nat =>
@@ -1689,6 +1986,20 @@ package body Synth.Vhdl_Eval is
| Iir_Predefined_Ieee_Numeric_Std_Xnor_Sgn =>
return Eval_Vector_Reduce ('0', Operand, Xor_Table, True);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Id_Uns_Uns
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Id_Uns_Slv
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Id_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Id_Sgn_Slv =>
+ return Operand;
+
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Neg_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Neg_Sgn_Slv =>
+ return Neg_Sgn_Sgn (Operand, +Expr);
+
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Abs_Sgn_Sgn
+ | Iir_Predefined_Ieee_Std_Logic_Arith_Abs_Sgn_Slv =>
+ return Abs_Sgn_Sgn (Operand, +Expr);
+
when others =>
Error_Msg_Synth
(+Expr, "eval_static_monadic_predefined: unhandled "
@@ -2213,6 +2524,27 @@ package body Synth.Vhdl_Eval is
return Resize_Vec
(Get_Memtyp (Param1), Param2.Typ.Abound.Len, True);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Ext =>
+ declare
+ Len : Int64;
+ begin
+ Len := Read_Discrete (Param2);
+ if Len < 0 then
+ Len := 0;
+ end if;
+ return Resize_Vec (Get_Memtyp (Param1), Uns32 (Len), False);
+ end;
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Sxt =>
+ declare
+ Len : Int64;
+ begin
+ Len := Read_Discrete (Param2);
+ if Len < 0 then
+ Len := 0;
+ end if;
+ return Resize_Vec (Get_Memtyp (Param1), Uns32 (Len), True);
+ end;
+
when Iir_Predefined_Ieee_1164_To_Stdulogic =>
declare
B : Std_Ulogic;
@@ -2415,6 +2747,26 @@ package body Synth.Vhdl_Eval is
return Minmax (Get_Memtyp (Param1), Get_Memtyp (Param2),
False, False);
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Shl_Uns =>
+ return Execute_Shift_Operator
+ (Get_Memtyp (Param1), Read_Discrete (Param2),
+ Std_Ulogic'Pos('0'), Iir_Predefined_Array_Sll);
+
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Shl_Sgn =>
+ return Execute_Shift_Operator
+ (Get_Memtyp (Param1), Read_Discrete (Param2),
+ Std_Ulogic'Pos('0'), Iir_Predefined_Array_Sla);
+
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Shr_Uns =>
+ return Execute_Shift_Operator
+ (Get_Memtyp (Param1), Read_Discrete (Param2),
+ Std_Ulogic'Pos('0'), Iir_Predefined_Array_Srl);
+
+ when Iir_Predefined_Ieee_Std_Logic_Arith_Shr_Sgn =>
+ return Execute_Shift_Operator
+ (Get_Memtyp (Param1), Read_Discrete (Param2),
+ Std_Ulogic'Pos('0'), Iir_Predefined_Array_Sra);
+
when Iir_Predefined_Ieee_Math_Real_Sign =>
declare
Val : constant Fp64 := Read_Fp64 (Param1);