aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/synth-ieee-numeric_std.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/synth/synth-ieee-numeric_std.adb')
-rw-r--r--src/synth/synth-ieee-numeric_std.adb830
1 files changed, 722 insertions, 108 deletions
diff --git a/src/synth/synth-ieee-numeric_std.adb b/src/synth/synth-ieee-numeric_std.adb
index f8b7bc960..f850456b0 100644
--- a/src/synth/synth-ieee-numeric_std.adb
+++ b/src/synth/synth-ieee-numeric_std.adb
@@ -21,7 +21,6 @@ with Types_Utils; use Types_Utils;
with Elab.Memtype; use Elab.Memtype;
with Synth.Errors; use Synth.Errors;
-with Synth.Ieee.Std_Logic_1164; use Synth.Ieee.Std_Logic_1164;
package body Synth.Ieee.Numeric_Std is
subtype Sl_01 is Std_Ulogic range '0' .. '1';
@@ -48,35 +47,36 @@ package body Synth.Ieee.Numeric_Std is
function Create_Res_Type (Otyp : Type_Acc; Len : Uns32) return Type_Acc is
begin
- if Otyp.Vbound.Len = Len
- and then Otyp.Vbound.Right = 0
- and then Otyp.Vbound.Dir = Dir_Downto
+ if Otyp.Abound.Len = Len
+ and then Otyp.Abound.Right = 0
+ and then Otyp.Abound.Dir = Dir_Downto
then
- pragma Assert (Otyp.Vbound.Left = Int32 (Len) - 1);
+ pragma Assert (Otyp.Abound.Left = Int32 (Len) - 1);
return Otyp;
end if;
- return Create_Vec_Type_By_Length (Len, Otyp.Vec_El);
+ return Create_Vec_Type_By_Length (Len, Otyp.Arr_El);
end Create_Res_Type;
procedure Fill (Res : Memtyp; V : Std_Ulogic) is
begin
- for I in 1 .. Res.Typ.Vbound.Len loop
+ for I in 1 .. Res.Typ.Abound.Len loop
Write_Std_Logic (Res.Mem, I - 1, V);
end loop;
end Fill;
- procedure Warn_Compare_Null (Loc : Syn_Src) is
+ procedure Warn_Compare_Null (Loc : Location_Type) is
begin
- Warning_Msg_Synth (+Loc, "null argument detected, returning false");
+ Warning_Msg_Synth (Loc, "null argument detected, returning false");
end Warn_Compare_Null;
- procedure Warn_Compare_Meta (Loc : Syn_Src) is
+ procedure Warn_Compare_Meta (Loc : Location_Type) is
begin
- Warning_Msg_Synth (+Loc, "metavalue detected, returning false");
+ Warning_Msg_Synth (Loc, "metavalue detected, returning false");
end Warn_Compare_Meta;
- function Compare_Uns_Uns
- (Left, Right : Memtyp; Err : Order_Type; Loc : Syn_Src) return Order_Type
+ function Compare_Uns_Uns (Left, Right : Memtyp;
+ Err : Order_Type;
+ Loc : Location_Type) return Order_Type
is
Lw : constant Uns32 := Left.Typ.W;
Rw : constant Uns32 := Right.Typ.W;
@@ -129,8 +129,9 @@ package body Synth.Ieee.Numeric_Std is
return Equal;
end Compare_Uns_Uns;
- function Compare_Uns_Nat
- (Left, Right : Memtyp; Err : Order_Type; Loc : Syn_Src) return Order_Type
+ function Compare_Uns_Nat (Left, Right : Memtyp;
+ Err : Order_Type;
+ Loc : Location_Type) return Order_Type
is
Lw : constant Uns32 := Left.Typ.W;
Rval : constant Uns64 := To_Uns64 (Read_Discrete (Right));
@@ -183,8 +184,9 @@ package body Synth.Ieee.Numeric_Std is
return Equal;
end Compare_Uns_Nat;
- function Compare_Nat_Uns
- (Left, Right : Memtyp; Err : Order_Type; Loc : Syn_Src) return Order_Type
+ function Compare_Nat_Uns (Left, Right : Memtyp;
+ Err : Order_Type;
+ Loc : Location_Type) return Order_Type
is
Rw : constant Uns32 := Right.Typ.W;
Lval : constant Uns64 := To_Uns64 (Read_Discrete (Left));
@@ -237,8 +239,9 @@ package body Synth.Ieee.Numeric_Std is
return Equal;
end Compare_Nat_Uns;
- function Compare_Sgn_Sgn
- (Left, Right : Memtyp; Err : Order_Type; Loc : Syn_Src) return Order_Type
+ function Compare_Sgn_Sgn (Left, Right : Memtyp;
+ Err : Order_Type;
+ Loc : Location_Type) return Order_Type
is
Lw : constant Uns32 := Left.Typ.W;
Rw : constant Uns32 := Right.Typ.W;
@@ -293,8 +296,9 @@ package body Synth.Ieee.Numeric_Std is
return Res;
end Compare_Sgn_Sgn;
- function Compare_Sgn_Int
- (Left, Right : Memtyp; Err : Order_Type; Loc : Syn_Src) return Order_Type
+ function Compare_Sgn_Int (Left, Right : Memtyp;
+ Err : Order_Type;
+ Loc : Location_Type) return Order_Type
is
Lw : constant Uns32 := Left.Typ.W;
Rval : constant Int64 := Read_Discrete (Right);
@@ -341,23 +345,25 @@ package body Synth.Ieee.Numeric_Std is
return Res;
end Compare_Sgn_Int;
- function Add_Vec_Vec (L, R : Memtyp; Signed : Boolean; Loc : Syn_Src)
+ function Add_Vec_Vec (L, R : Memtyp; Signed : Boolean; Loc : Location_Type)
return Memtyp
is
- Llen : constant Uns32 := L.Typ.Vbound.Len;
- Rlen : constant Uns32 := R.Typ.Vbound.Len;
+ Llen : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := R.Typ.Abound.Len;
Len : constant Uns32 := Uns32'Max (Llen, Rlen);
Res : Memtyp;
Lb, Rb, Carry : Sl_X01;
R_Ext, L_Ext : Sl_X01;
begin
- Res.Typ := Create_Res_Type (L.Typ, Len);
- Res := Create_Memory (Res.Typ);
-
- if Len = 0 then
+ if Rlen = 0 or Llen = 0 then
+ Res.Typ := Create_Res_Type (L.Typ, 0);
+ Res := Create_Memory (Res.Typ);
return Res;
end if;
+ Res.Typ := Create_Res_Type (L.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
if Signed then
-- Extend with the sign bit.
L_Ext := Sl_To_X01 (Read_Std_Logic (L.Mem, 0));
@@ -392,20 +398,37 @@ package body Synth.Ieee.Numeric_Std is
return Res;
end Add_Vec_Vec;
- function Add_Uns_Uns (L, R : Memtyp; Loc : Syn_Src) return Memtyp is
+ function Add_Uns_Uns (L, R : Memtyp; Loc : Location_Type) return Memtyp is
begin
return Add_Vec_Vec (L, R, False, Loc);
end Add_Uns_Uns;
- function Add_Sgn_Sgn (L, R : Memtyp; Loc : Syn_Src) return Memtyp is
+ function Log_To_Vec (Val : Memtyp; Vec : Memtyp) return Memtyp
+ is
+ Len : constant Uns32 := Vec.Typ.Abound.Len;
+ Res : Memtyp;
+ begin
+ if Len = 0 then
+ -- FIXME: is it an error ?
+ return Vec;
+ end if;
+ Res := Create_Memory (Vec.Typ);
+ Fill (Res, '0');
+ Write_U8 (Res.Mem + Size_Type (Len - 1), Read_U8 (Val.Mem));
+ return Res;
+ end Log_To_Vec;
+
+ function Add_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp is
begin
return Add_Vec_Vec (L, R, True, Loc);
end Add_Sgn_Sgn;
- function Add_Vec_Int
- (L : Memtyp; R : Uns64; Signed : Boolean; Loc : Syn_Src) return Memtyp
+ function Add_Vec_Int (L : Memtyp;
+ R : Uns64;
+ Signed : Boolean;
+ Loc : Location_Type) return Memtyp
is
- Len : constant Uns32 := L.Typ.Vbound.Len;
+ Len : constant Uns32 := L.Typ.Abound.Len;
Res : Memtyp;
V : Uns64;
Lb, Rb, Carry : Sl_X01;
@@ -437,33 +460,37 @@ package body Synth.Ieee.Numeric_Std is
return Res;
end Add_Vec_Int;
- function Add_Sgn_Int (L : Memtyp; R : Int64; Loc : Syn_Src) return Memtyp is
+ function Add_Sgn_Int (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp is
begin
return Add_Vec_Int (L, To_Uns64 (R), True, Loc);
end Add_Sgn_Int;
- function Add_Uns_Nat (L : Memtyp; R : Uns64; Loc : Syn_Src) return Memtyp is
+ function Add_Uns_Nat (L : Memtyp; R : Uns64; Loc : Location_Type)
+ return Memtyp is
begin
return Add_Vec_Int (L, R, True, Loc);
end Add_Uns_Nat;
- function Sub_Vec_Vec (L, R : Memtyp; Signed : Boolean; Loc : Syn_Src)
+ function Sub_Vec_Vec (L, R : Memtyp; Signed : Boolean; Loc : Location_Type)
return Memtyp
is
- Llen : constant Uns32 := L.Typ.Vbound.Len;
- Rlen : constant Uns32 := R.Typ.Vbound.Len;
+ Llen : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := R.Typ.Abound.Len;
Len : constant Uns32 := Uns32'Max (Llen, Rlen);
Res : Memtyp;
Lb, Rb, Carry : Sl_X01;
R_Ext, L_Ext : Sl_X01;
begin
- Res.Typ := Create_Res_Type (L.Typ, Len);
- Res := Create_Memory (Res.Typ);
-
- if Len = 0 then
+ if Llen = 0 or Rlen = 0 then
+ Res.Typ := Create_Res_Type (L.Typ, 0);
+ Res := Create_Memory (Res.Typ);
return Res;
end if;
+ Res.Typ := Create_Res_Type (L.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
if Signed then
-- Extend with the sign bit.
L_Ext := Sl_To_X01 (Read_Std_Logic (L.Mem, 0));
@@ -499,20 +526,22 @@ package body Synth.Ieee.Numeric_Std is
return Res;
end Sub_Vec_Vec;
- function Sub_Uns_Uns (L, R : Memtyp; Loc : Syn_Src) return Memtyp is
+ function Sub_Uns_Uns (L, R : Memtyp; Loc : Location_Type) return Memtyp is
begin
return Sub_Vec_Vec (L, R, False, Loc);
end Sub_Uns_Uns;
- function Sub_Sgn_Sgn (L, R : Memtyp; Loc : Syn_Src) return Memtyp is
+ function Sub_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp is
begin
return Sub_Vec_Vec (L, R, True, Loc);
end Sub_Sgn_Sgn;
- function Sub_Vec_Int
- (L : Memtyp; R : Uns64; Signed : Boolean; Loc : Syn_Src) return Memtyp
+ function Sub_Vec_Int (L : Memtyp;
+ R : Uns64;
+ Signed : Boolean;
+ Loc : Location_Type) return Memtyp
is
- Len : constant Uns32 := L.Typ.Vbound.Len;
+ Len : constant Uns32 := L.Typ.Abound.Len;
Res : Memtyp;
V : Uns64;
Lb, Rb, Carry : Sl_X01;
@@ -545,20 +574,73 @@ package body Synth.Ieee.Numeric_Std is
return Res;
end Sub_Vec_Int;
- function Sub_Sgn_Int (L : Memtyp; R : Int64; Loc : Syn_Src) return Memtyp is
+ function Sub_Sgn_Int (L : Memtyp;
+ R : Int64;
+ Loc : Location_Type) return Memtyp is
begin
return Sub_Vec_Int (L, To_Uns64 (R), True, Loc);
end Sub_Sgn_Int;
- function Sub_Uns_Nat (L : Memtyp; R : Uns64; Loc : Syn_Src) return Memtyp is
+ function Sub_Uns_Nat (L : Memtyp; R : Uns64; Loc : Location_Type)
+ return Memtyp is
begin
return Sub_Vec_Int (L, R, True, Loc);
end Sub_Uns_Nat;
- function Mul_Uns_Uns (L, R : Memtyp; Loc : Syn_Src) return Memtyp
+ function Sub_Int_Vec (L : Uns64;
+ R : Memtyp;
+ Signed : Boolean;
+ Loc : Location_Type) return Memtyp
+ is
+ Len : constant Uns32 := R.Typ.Abound.Len;
+ Res : Memtyp;
+ V : Uns64;
+ Lb, Rb, Carry : Sl_X01;
+ begin
+ Res.Typ := Create_Res_Type (R.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+ if Len < 1 then
+ return Res;
+ end if;
+ V := L;
+ Carry := '1';
+ for I in 1 .. Len loop
+ Lb := Uns_To_01 (V and 1);
+ Rb := Sl_To_X01 (Read_Std_Logic (R.Mem, Len - I));
+ if Rb = 'X' then
+ Warning_Msg_Synth
+ (+Loc, "NUMERIC_STD.""+"": non logical value detected");
+ Fill (Res, 'X');
+ exit;
+ end if;
+ Rb := Not_Table (Rb);
+ Write_Std_Logic (Res.Mem, Len - I, Compute_Sum (Carry, Rb, Lb));
+ Carry := Compute_Carry (Carry, Rb, Lb);
+ if Signed then
+ V := Shift_Right_Arithmetic (V, 1);
+ else
+ V := Shift_Right (V, 1);
+ end if;
+ end loop;
+ return Res;
+ end Sub_Int_Vec;
+
+ function Sub_Nat_Uns (L : Uns64; R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Sub_Int_Vec (L, R, False, Loc);
+ end Sub_Nat_Uns;
+
+ function Sub_Int_Sgn (L : Int64; R : Memtyp; Loc : Location_Type)
+ return Memtyp is
+ begin
+ return Sub_Int_Vec (To_Uns64 (L), R, True, Loc);
+ end Sub_Int_Sgn;
+
+ function Mul_Uns_Uns (L, R : Memtyp; Loc : Location_Type) return Memtyp
is
- Llen : constant Uns32 := L.Typ.Vbound.Len;
- Rlen : constant Uns32 := R.Typ.Vbound.Len;
+ Llen : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := R.Typ.Abound.Len;
Len : constant Uns32 := Llen + Rlen;
Res : Memtyp;
Lb, Rb, Vb, Carry : Sl_X01;
@@ -601,7 +683,7 @@ package body Synth.Ieee.Numeric_Std is
function To_Unsigned (Val : Uns64; Vtyp : Type_Acc) return Memtyp
is
- Vlen : constant Uns32 := Vtyp.Vbound.Len;
+ Vlen : constant Uns32 := Vtyp.Abound.Len;
Res : Memtyp;
E : Std_Ulogic;
begin
@@ -617,32 +699,34 @@ package body Synth.Ieee.Numeric_Std is
return Res;
end To_Unsigned;
- function Mul_Nat_Uns (L : Uns64; R : Memtyp; Loc : Syn_Src) return Memtyp
+ function Mul_Nat_Uns (L : Uns64; R : Memtyp; Loc : Location_Type)
+ return Memtyp
is
Lv : Memtyp;
begin
- if R.Typ.Vbound.Len = 0 then
+ if R.Typ.Abound.Len = 0 then
return Create_Memory (R.Typ); -- FIXME: typ
end if;
Lv := To_Unsigned (L, R.Typ);
return Mul_Uns_Uns (Lv, R, Loc);
end Mul_Nat_Uns;
- function Mul_Uns_Nat (L : Memtyp; R : Uns64; Loc : Syn_Src) return Memtyp
+ function Mul_Uns_Nat (L : Memtyp; R : Uns64; Loc : Location_Type)
+ return Memtyp
is
Rv : Memtyp;
begin
- if L.Typ.Vbound.Len = 0 then
+ if L.Typ.Abound.Len = 0 then
return Create_Memory (L.Typ); -- FIXME: typ
end if;
Rv := To_Unsigned (R, L.Typ);
return Mul_Uns_Uns (L, Rv, Loc);
end Mul_Uns_Nat;
- function Mul_Sgn_Sgn (L, R : Memtyp; Loc : Syn_Src) return Memtyp
+ function Mul_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp
is
- Llen : constant Uns32 := L.Typ.Vbound.Len;
- Rlen : constant Uns32 := R.Typ.Vbound.Len;
+ Llen : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := R.Typ.Abound.Len;
Len : constant Uns32 := Llen + Rlen;
Res : Memtyp;
Lb, Rb, Vb, Carry : Sl_X01;
@@ -703,7 +787,7 @@ package body Synth.Ieee.Numeric_Std is
function To_Signed (Val : Int64; Vtyp : Type_Acc) return Memtyp
is
- Vlen : constant Uns32 := Vtyp.Vbound.Len;
+ Vlen : constant Uns32 := Vtyp.Abound.Len;
Uval : constant Uns64 := To_Uns64 (Val);
Res : Memtyp;
E : Std_Ulogic;
@@ -720,22 +804,24 @@ package body Synth.Ieee.Numeric_Std is
return Res;
end To_Signed;
- function Mul_Int_Sgn (L : Int64; R : Memtyp; Loc : Syn_Src) return Memtyp
+ function Mul_Int_Sgn (L : Int64; R : Memtyp; Loc : Location_Type)
+ return Memtyp
is
Lv : Memtyp;
begin
- if R.Typ.Vbound.Len = 0 then
+ if R.Typ.Abound.Len = 0 then
return Create_Memory (R.Typ); -- FIXME: typ
end if;
Lv := To_Signed (L, R.Typ);
return Mul_Sgn_Sgn (Lv, R, Loc);
end Mul_Int_Sgn;
- function Mul_Sgn_Int (L : Memtyp; R : Int64; Loc : Syn_Src) return Memtyp
+ function Mul_Sgn_Int (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp
is
Rv : Memtyp;
begin
- if L.Typ.Vbound.Len = 0 then
+ if L.Typ.Abound.Len = 0 then
return Create_Memory (L.Typ); -- FIXME: typ
end if;
Rv := To_Signed (R, L.Typ);
@@ -745,7 +831,7 @@ package body Synth.Ieee.Numeric_Std is
-- Note: SRC = DST is allowed.
procedure Neg_Vec (Src : Memory_Ptr; Dst : Memory_Ptr; Typ : Type_Acc)
is
- Len : constant Uns32 := Typ.Vbound.Len;
+ Len : constant Uns32 := Typ.Abound.Len;
Vb, Carry : Sl_X01;
begin
Carry := '1';
@@ -772,9 +858,25 @@ package body Synth.Ieee.Numeric_Std is
Neg_Vec (V.Mem, V.Mem, V.Typ);
end Neg_Vec;
- function Neg_Vec (V : Memtyp; Loc : Syn_Src) return Memtyp
+ function Has_0x (V : Memtyp) return Sl_X01
is
- Len : constant Uns32 := V.Typ.Vbound.Len;
+ Res : Sl_X01 := '0';
+ E : Sl_X01;
+ begin
+ for I in 0 .. V.Typ.Abound.Len - 1 loop
+ E := To_X01 (Read_Std_Logic (V.Mem, I));
+ if E = 'X' then
+ return 'X';
+ elsif E = '1' then
+ Res := '1';
+ end if;
+ end loop;
+ return Res;
+ end Has_0x;
+
+ function Neg_Vec (V : Memtyp; Loc : Location_Type) return Memtyp
+ is
+ Len : constant Uns32 := V.Typ.Abound.Len;
Res : Memtyp;
begin
Res.Typ := Create_Res_Type (V.Typ, Len);
@@ -784,10 +886,12 @@ package body Synth.Ieee.Numeric_Std is
return Res;
end if;
- Neg_Vec (V.Mem, Res.Mem, V.Typ);
- if Read_Std_Logic (Res.Mem, 0) = 'X' then
+ if Has_0x (V) = 'X' then
Warning_Msg_Synth
(+Loc, "NUMERIC_STD.""-"": non logical value detected");
+ Fill (Res, 'X');
+ else
+ Neg_Vec (V.Mem, Res.Mem, V.Typ);
end if;
return Res;
end Neg_Vec;
@@ -808,10 +912,10 @@ package body Synth.Ieee.Numeric_Std is
end loop;
end To_01X;
- function Abs_Vec (V : Memtyp; Loc : Syn_Src) return Memtyp
+ function Abs_Vec (V : Memtyp; Loc : Location_Type) return Memtyp
is
pragma Unreferenced (Loc);
- Len : constant Uns32 := V.Typ.Vbound.Len;
+ Len : constant Uns32 := V.Typ.Abound.Len;
Res : Memtyp;
Msb : Sl_X01;
begin
@@ -844,7 +948,6 @@ package body Synth.Ieee.Numeric_Std is
Res := Create_Memory (Res.Typ);
if Len = 0 then
- Fill (Res, '0');
return Res;
end if;
@@ -883,31 +986,87 @@ package body Synth.Ieee.Numeric_Std is
return Res;
end Shift_Vec;
- function Resize_Vec (Val : Memtyp;
- Size : Uns32;
- Signed : Boolean) return Memtyp
+ function Rotate_Vec (Val : Memtyp;
+ Amt : Uns32;
+ Right : Boolean) return Memtyp
is
- Old_Size : constant Uns32 := Uns32 (Vec_Length (Val.Typ));
+ Len : constant Uns32 := Uns32 (Vec_Length (Val.Typ));
+ Cnt : Uns32;
Res : Memtyp;
- Pad, B : Std_Ulogic;
+ B : Std_Ulogic;
begin
- Res.Typ := Create_Res_Type (Val.Typ, Size);
+ Res.Typ := Create_Res_Type (Val.Typ, Len);
Res := Create_Memory (Res.Typ);
+ if Len = 0 then
+ return Res;
+ end if;
+
+ Cnt := Amt rem Len;
+ pragma Unreferenced (Amt);
+
+ if Right then
+ for I in 1 .. Len - Cnt loop
+ B := Read_Std_Logic (Val.Mem, I - 1);
+ Write_Std_Logic (Res.Mem, Cnt + I - 1, B);
+ end loop;
+ for I in 1 .. Cnt loop
+ B := Read_Std_Logic (Val.Mem, Len - I);
+ Write_Std_Logic (Res.Mem, Cnt - I, B);
+ end loop;
+ else
+ for I in 1 .. Cnt loop
+ B := Read_Std_Logic (Val.Mem, I - 1);
+ Write_Std_Logic (Res.Mem, Len - Cnt + I - 1, B);
+ end loop;
+ for I in 1 .. Len - Cnt loop
+ B := Read_Std_Logic (Val.Mem, Len - I);
+ Write_Std_Logic (Res.Mem, Len - Cnt - I, B);
+ end loop;
+ end if;
+ return Res;
+ end Rotate_Vec;
+
+ procedure Resize_Vec (Dest : Memtyp; Val : Memtyp; Signed : Boolean)
+ is
+ Size : constant Uns32 := Dest.Typ.Abound.Len;
+ Old_Size : constant Uns32 := Val.Typ.Abound.Len;
+ L : Uns32;
+ Pad, B : Std_Ulogic;
+ begin
+ if Size = 0 then
+ return;
+ end if;
+
if Signed and then Old_Size > 0 then
Pad := Read_Std_Logic (Val.Mem, 0);
+ Write_Std_Logic (Dest.Mem, 0, Pad);
+ L := Size - 1;
else
Pad := '0';
+ L := Size;
end if;
- for I in 1 .. Size loop
+ for I in 1 .. L loop
if I <= Old_Size then
B := Read_Std_Logic (Val.Mem, Old_Size - I);
else
B := Pad;
end if;
- Write_Std_Logic (Res.Mem, Size - I, B);
+ Write_Std_Logic (Dest.Mem, Size - I, B);
end loop;
+ end Resize_Vec;
+
+ function Resize_Vec (Val : Memtyp;
+ Size : Uns32;
+ Signed : Boolean) return Memtyp
+ is
+ Res : Memtyp;
+ begin
+ Res.Typ := Create_Res_Type (Val.Typ, Size);
+ Res := Create_Memory (Res.Typ);
+
+ Resize_Vec (Res, Val, Signed);
return Res;
end Resize_Vec;
@@ -916,11 +1075,11 @@ package body Synth.Ieee.Numeric_Std is
procedure Divmod (Num, Dem : Memtyp; Quot, Remain : Memtyp)
is
- Nlen : constant Uns32 := Num.Typ.Vbound.Len;
- Dlen : constant Uns32 := Dem.Typ.Vbound.Len;
+ Nlen : constant Uns32 := Num.Typ.Abound.Len;
+ Dlen : constant Uns32 := Dem.Typ.Abound.Len;
pragma Assert (Nlen > 0);
pragma Assert (Dlen > 0);
- pragma Assert (Quot.Typ.Vbound.Len = Nlen);
+ pragma Assert (Quot.Typ = null or else Quot.Typ.Abound.Len = Nlen);
Reg : Std_Logic_Vector_Type (0 .. Dlen);
Sub : Std_Logic_Vector_Type (0 .. Dlen - 1);
Carry : Sl_X01;
@@ -944,40 +1103,26 @@ package body Synth.Ieee.Numeric_Std is
-- Extra REG bit.
Carry := Compute_Carry (Carry, Reg (0), '1');
-- Test
- Write_Std_Logic (Quot.Mem, I, Carry);
+ if Quot.Mem /= null then
+ Write_Std_Logic (Quot.Mem, I, Carry);
+ end if;
if Carry = '1' then
Reg (0) := '0';
Reg (1 .. Dlen) := Sub;
end if;
end loop;
if Remain /= Null_Memtyp then
- pragma Assert (Remain.Typ.Vbound.Len = Dlen);
+ pragma Assert (Remain.Typ.Abound.Len = Dlen);
for I in 0 .. Dlen - 1 loop
Write_Std_Logic (Remain.Mem, I, Reg (I + 1));
end loop;
end if;
end Divmod;
- function Has_0x (V : Memtyp) return Sl_X01
+ function Div_Uns_Uns (L, R : Memtyp; Loc : Location_Type) return Memtyp
is
- Res : Sl_X01 := '0';
- E : Sl_X01;
- begin
- for I in 0 .. V.Typ.Vbound.Len - 1 loop
- E := To_X01 (Read_Std_Logic (V.Mem, I));
- if E = 'X' then
- return 'X';
- elsif E = '1' then
- Res := '1';
- end if;
- end loop;
- return Res;
- end Has_0x;
-
- function Div_Uns_Uns (L, R : Memtyp; Loc : Syn_Src) return Memtyp
- is
- Nlen : constant Uns32 := L.Typ.Vbound.Len;
- Dlen : constant Uns32 := R.Typ.Vbound.Len;
+ Nlen : constant Uns32 := L.Typ.Abound.Len;
+ Dlen : constant Uns32 := R.Typ.Abound.Len;
Quot : Memtyp;
R0 : Sl_X01;
begin
@@ -1003,10 +1148,34 @@ package body Synth.Ieee.Numeric_Std is
return Quot;
end Div_Uns_Uns;
- function Div_Sgn_Sgn (L, R : Memtyp; Loc : Syn_Src) return Memtyp
+ function Div_Uns_Nat (L : Memtyp; R : Uns64; Loc : Location_Type)
+ return Memtyp
+ is
+ Rv : Memtyp;
+ begin
+ if L.Typ.Abound.Len = 0 then
+ return Create_Memory (L.Typ); -- FIXME: typ
+ end if;
+ Rv := To_Unsigned (R, L.Typ);
+ return Div_Uns_Uns (L, Rv, Loc);
+ end Div_Uns_Nat;
+
+ function Div_Nat_Uns (L : Uns64; R : Memtyp; Loc : Location_Type)
+ return Memtyp
+ is
+ Lv : Memtyp;
+ begin
+ if R.Typ.Abound.Len = 0 then
+ return Create_Memory (R.Typ); -- FIXME: typ
+ end if;
+ Lv := To_Unsigned (L, R.Typ);
+ return Div_Uns_Uns (Lv, R, Loc);
+ end Div_Nat_Uns;
+
+ function Div_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp
is
- Nlen : constant Uns32 := L.Typ.Vbound.Len;
- Dlen : constant Uns32 := R.Typ.Vbound.Len;
+ Nlen : constant Uns32 := L.Typ.Abound.Len;
+ Dlen : constant Uns32 := R.Typ.Abound.Len;
Quot : Memtyp;
R0 : Sl_X01;
Lu : Memtyp;
@@ -1057,4 +1226,449 @@ package body Synth.Ieee.Numeric_Std is
return Quot;
end Div_Sgn_Sgn;
+ function Div_Sgn_Int (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp
+ is
+ Rv : Memtyp;
+ begin
+ if L.Typ.Abound.Len = 0 then
+ return Create_Memory (L.Typ); -- FIXME: typ
+ end if;
+ Rv := To_Signed (R, L.Typ);
+ return Div_Sgn_Sgn (L, Rv, Loc);
+ end Div_Sgn_Int;
+
+ function Div_Int_Sgn (L : Int64; R : Memtyp; Loc : Location_Type)
+ return Memtyp
+ is
+ Lv : Memtyp;
+ begin
+ if R.Typ.Abound.Len = 0 then
+ return Create_Memory (R.Typ); -- FIXME: typ
+ end if;
+ Lv := To_Signed (L, R.Typ);
+ return Div_Sgn_Sgn (Lv, R, Loc);
+ end Div_Int_Sgn;
+
+ function Rem_Uns_Uns (L, R : Memtyp; Loc : Location_Type) return Memtyp
+ is
+ Nlen : constant Uns32 := L.Typ.Abound.Len;
+ Dlen : constant Uns32 := R.Typ.Abound.Len;
+ Rema : Memtyp;
+ R0 : Sl_X01;
+ begin
+ Rema.Typ := Create_Res_Type (R.Typ, Dlen);
+ Rema := Create_Memory (Rema.Typ);
+ if Nlen = 0 or Dlen = 0 then
+ return Rema;
+ end if;
+
+ R0 := Has_0x (R);
+ if Has_0x (L) = 'X' or R0 = 'X' then
+ Warning_Msg_Synth
+ (+Loc, "NUMERIC_STD.""rem"": non logical value detected");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+ if R0 = '0' then
+ Error_Msg_Synth (+Loc, "NUMERIC_STD.""rem"": division by 0");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+ Divmod (L, R, Null_Memtyp, Rema);
+ return Rema;
+ end Rem_Uns_Uns;
+
+ function Rem_Uns_Nat (L : Memtyp; R : Uns64; Loc : Location_Type)
+ return Memtyp
+ is
+ Rv : Memtyp;
+ begin
+ if L.Typ.Abound.Len = 0 then
+ return Create_Memory (L.Typ); -- FIXME: typ
+ end if;
+ Rv := To_Unsigned (R, L.Typ);
+ return Rem_Uns_Uns (L, Rv, Loc);
+ end Rem_Uns_Nat;
+
+ function Rem_Nat_Uns (L : Uns64; R : Memtyp; Loc : Location_Type)
+ return Memtyp
+ is
+ Lv : Memtyp;
+ begin
+ if R.Typ.Abound.Len = 0 then
+ return Create_Memory (R.Typ); -- FIXME: typ
+ end if;
+ Lv := To_Unsigned (L, R.Typ);
+ return Rem_Uns_Uns (Lv, R, Loc);
+ end Rem_Nat_Uns;
+
+ function Rem_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp
+ is
+ Nlen : constant Uns32 := L.Typ.Abound.Len;
+ Dlen : constant Uns32 := R.Typ.Abound.Len;
+ Rema : Memtyp;
+ R0 : Sl_X01;
+ Lu : Memtyp;
+ Ru : Memtyp;
+ Neg : Boolean;
+ begin
+ Rema.Typ := Create_Res_Type (L.Typ, Dlen);
+ Rema := Create_Memory (Rema.Typ);
+ if Nlen = 0 or Dlen = 0 then
+ return Rema;
+ end if;
+
+ R0 := Has_0x (R);
+ if Has_0x (L) = 'X' or R0 = 'X' then
+ Warning_Msg_Synth
+ (+Loc, "NUMERIC_STD.""rem"": non logical value detected");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+ if R0 = '0' then
+ Error_Msg_Synth (+Loc, "NUMERIC_STD.""rem"": division by 0");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+
+ if To_X01 (Read_Std_Logic (L.Mem, 0)) = '1' then
+ Lu.Typ := L.Typ;
+ Lu.Mem := Neg_Vec_Notyp (L);
+ Neg := True;
+ else
+ Neg := False;
+ Lu := L;
+ end if;
+
+ if To_X01 (Read_Std_Logic (R.Mem, 0)) = '1' then
+ Ru.Typ := R.Typ;
+ Ru.Mem := Neg_Vec_Notyp (R);
+ else
+ Ru := R;
+ end if;
+
+ Divmod (Lu, Ru, Null_Memtyp, Rema);
+
+ -- Result of rem has the sign of the dividend.
+ if Neg then
+ Neg_Vec (Rema);
+ end if;
+ return Rema;
+ end Rem_Sgn_Sgn;
+
+ function Rem_Sgn_Int (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp
+ is
+ Rv : Memtyp;
+ begin
+ if L.Typ.Abound.Len = 0 then
+ return Create_Memory (L.Typ); -- FIXME: typ
+ end if;
+ Rv := To_Signed (R, L.Typ);
+ return Rem_Sgn_Sgn (L, Rv, Loc);
+ end Rem_Sgn_Int;
+
+ function Rem_Int_Sgn (L : Int64; R : Memtyp; Loc : Location_Type)
+ return Memtyp
+ is
+ Lv : Memtyp;
+ begin
+ if R.Typ.Abound.Len = 0 then
+ return Create_Memory (R.Typ); -- FIXME: typ
+ end if;
+ Lv := To_Signed (L, R.Typ);
+ return Rem_Sgn_Sgn (Lv, R, Loc);
+ end Rem_Int_Sgn;
+
+ function Mod_Sgn_Sgn (L, R : Memtyp; Loc : Location_Type) return Memtyp
+ is
+ Nlen : constant Uns32 := L.Typ.Abound.Len;
+ Dlen : constant Uns32 := R.Typ.Abound.Len;
+ Rema : Memtyp;
+ R0 : Sl_X01;
+ Lu : Memtyp;
+ Ru : Memtyp;
+ L_Neg, R_Neg : Boolean;
+ begin
+ Rema.Typ := Create_Res_Type (L.Typ, Dlen);
+ Rema := Create_Memory (Rema.Typ);
+ if Nlen = 0 or Dlen = 0 then
+ return Rema;
+ end if;
+
+ R0 := Has_0x (R);
+ if Has_0x (L) = 'X' or R0 = 'X' then
+ Warning_Msg_Synth
+ (+Loc, "NUMERIC_STD.""rem"": non logical value detected");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+ if R0 = '0' then
+ Error_Msg_Synth (+Loc, "NUMERIC_STD.""rem"": division by 0");
+ Fill (Rema, 'X');
+ return Rema;
+ end if;
+
+ if To_X01 (Read_Std_Logic (L.Mem, 0)) = '1' then
+ Lu.Typ := L.Typ;
+ Lu.Mem := Neg_Vec_Notyp (L);
+ L_Neg := True;
+ else
+ Lu := L;
+ L_Neg := False;
+ end if;
+
+ if To_X01 (Read_Std_Logic (R.Mem, 0)) = '1' then
+ Ru.Typ := R.Typ;
+ Ru.Mem := Neg_Vec_Notyp (R);
+ R_Neg := True;
+ else
+ Ru := R;
+ R_Neg := False;
+ end if;
+
+ Divmod (Lu, Ru, Null_Memtyp, Rema);
+
+ if Has_0x (Rema) = '0' then
+ -- If the remainder is 0, then the modulus is 0.
+ return Rema;
+ else
+ -- Result of rem has the sign of the divisor.
+ if R_Neg then
+ if L_Neg then
+ Neg_Vec (Rema);
+ return Rema;
+ else
+ return Add_Vec_Vec (R, Rema, True, Loc);
+ end if;
+ else
+ if L_Neg then
+ return Sub_Vec_Vec (R, Rema, True, Loc);
+ else
+ return Rema;
+ end if;
+ end if;
+ end if;
+ end Mod_Sgn_Sgn;
+
+ function Mod_Sgn_Int (L : Memtyp; R : Int64; Loc : Location_Type)
+ return Memtyp
+ is
+ Rv : Memtyp;
+ begin
+ if L.Typ.Abound.Len = 0 then
+ return Create_Memory (L.Typ); -- FIXME: typ
+ end if;
+ Rv := To_Signed (R, L.Typ);
+ return Mod_Sgn_Sgn (L, Rv, Loc);
+ end Mod_Sgn_Int;
+
+ function Mod_Int_Sgn (L : Int64; R : Memtyp; Loc : Location_Type)
+ return Memtyp
+ is
+ Lv : Memtyp;
+ begin
+ if R.Typ.Abound.Len = 0 then
+ return Create_Memory (R.Typ); -- FIXME: typ
+ end if;
+ Lv := To_Signed (L, R.Typ);
+ return Mod_Sgn_Sgn (Lv, R, Loc);
+ end Mod_Int_Sgn;
+
+ function Minmax (L, R : Memtyp; Is_Signed : Boolean; Is_Max : Boolean)
+ return Memtyp
+ is
+ Len : constant Uns32 := Uns32'Max (L.Typ.Abound.Len, R.Typ.Abound.Len);
+ Res : Memtyp;
+ Lt : Boolean;
+ begin
+ if L.Typ.Abound.Len = 0 or R.Typ.Abound.Len = 0 then
+ Res.Typ := Create_Res_Type (L.Typ, 0);
+ Res := Create_Memory (Res.Typ);
+ return Res;
+ end if;
+
+ Res.Typ := Create_Res_Type (L.Typ, Len);
+ Res := Create_Memory (Res.Typ);
+
+ if Has_0x (L) = 'X' or else Has_0x (R) = 'X' then
+ Fill (Res, 'X');
+ return Res;
+ end if;
+
+ if Is_Signed then
+ Lt := Compare_Sgn_Sgn (L, R, Less, No_Location) = Less;
+ else
+ Lt := Compare_Uns_Uns (L, R, Less, No_Location) = Less;
+ end if;
+
+ if Lt xor Is_Max then
+ Resize_Vec (Res, L, False);
+ else
+ Resize_Vec (Res, R, False);
+ end if;
+ return Res;
+ end Minmax;
+
+ function Offset_To_Index (Off : Int32; Typ : Type_Acc) return Int32 is
+ begin
+ case Typ.Abound.Dir is
+ when Dir_To =>
+ return Typ.Abound.Left + Off;
+ when Dir_Downto =>
+ return Typ.Abound.Left - Off;
+ end case;
+ end Offset_To_Index;
+
+ function Find_Rightmost (Arg : Memtyp; Val : Memtyp) return Int32
+ is
+ Len : constant Uns32 := Arg.Typ.Abound.Len;
+ Y : Std_Ulogic;
+ begin
+ Y := Read_Std_Logic (Val.Mem, 0);
+
+ for I in reverse 1 .. Len loop
+ if Match_Eq_Table (Read_Std_Logic (Arg.Mem, I - 1), Y) = '1' then
+ return Offset_To_Index (Int32 (I - 1), Arg.Typ);
+ end if;
+ end loop;
+ return -1;
+ end Find_Rightmost;
+
+ function Find_Leftmost (Arg : Memtyp; Val : Memtyp) return Int32
+ is
+ Len : constant Uns32 := Arg.Typ.Abound.Len;
+ Y : Std_Ulogic;
+ begin
+ Y := Read_Std_Logic (Val.Mem, 0);
+
+ for I in 1 .. Len loop
+ if Match_Eq_Table (Read_Std_Logic (Arg.Mem, I - 1), Y) = '1' then
+ return Offset_To_Index (Int32 (I - 1), Arg.Typ);
+ end if;
+ end loop;
+ return -1;
+ end Find_Leftmost;
+
+ function Match_Vec (L, R : Memtyp; Loc : Location_Type) return Boolean
+ is
+ Llen : constant Uns32 := L.Typ.Abound.Len;
+ Rlen : constant Uns32 := R.Typ.Abound.Len;
+ begin
+ if Llen = 0 or Rlen = 0 then
+ Warn_Compare_Null (Loc);
+ return False;
+ end if;
+ if Llen /= Rlen then
+ Warning_Msg_Synth
+ (+Loc, "NUMERIC_STD.STD_MATCH: length mismatch, returning FALSE");
+ return False;
+ end if;
+
+ for I in 1 .. Llen loop
+ if Match_Eq_Table (Read_Std_Logic (L.Mem, I - 1),
+ Read_Std_Logic (R.Mem, I - 1)) /= '1'
+ then
+ return False;
+ end if;
+ end loop;
+ return True;
+ end Match_Vec;
+
+ function Match_Eq_Vec_Vec (Left, Right : Memtyp;
+ Is_Signed : Boolean;
+ Loc : Location_Type) return Std_Ulogic
+ is
+ Lw : constant Uns32 := Left.Typ.W;
+ Rw : constant Uns32 := Right.Typ.W;
+ Len : constant Uns32 := Uns32'Max (Left.Typ.W, Right.Typ.W);
+ L, R, T : Std_Ulogic;
+ Res : Std_Ulogic;
+ begin
+ if Len = 0 then
+ Warn_Compare_Null (Loc);
+ return 'X';
+ end if;
+
+ Res := '1';
+ for I in 1 .. Len loop
+ if I > Lw then
+ if not Is_Signed then
+ L := '0';
+ end if;
+ else
+ L := Read_Std_Logic (Left.Mem, Lw - I);
+ end if;
+ if I > Rw then
+ if not Is_Signed then
+ R := '0';
+ end if;
+ else
+ R := Read_Std_Logic (Right.Mem, Rw - I);
+ end if;
+ T := Match_Eq_Table (L, R);
+ if T = 'U' then
+ return T;
+ elsif T = 'X' or Res = 'X' then
+ -- Lower priority than 'U'.
+ Res := 'X';
+ elsif T = '0' then
+ Res := '0';
+ end if;
+ end loop;
+ return Res;
+ end Match_Eq_Vec_Vec;
+
+ function Has_Xd (V : Memtyp) return Std_Ulogic
+ is
+ Res : Std_Ulogic;
+ E : Std_Ulogic;
+ begin
+ Res := '0';
+ for I in 0 .. V.Typ.Abound.Len - 1 loop
+ E := Read_Std_Logic (V.Mem, I);
+ if E = '-' then
+ return '-';
+ elsif To_X01 (E) = 'X' then
+ Res := 'X';
+ end if;
+ end loop;
+ return Res;
+ end Has_Xd;
+
+ function Match_Cmp_Vec_Vec (Left, Right : Memtyp;
+ Map : Order_Map_Type;
+ Is_Signed : Boolean;
+ Loc : Location_Type) return Memtyp
+ is
+ Llen : constant Uns32 := Left.Typ.Abound.Len;
+ Rlen : constant Uns32 := Right.Typ.Abound.Len;
+ L, R : Std_Ulogic;
+ Res : Std_Ulogic;
+ Cmp : Order_Type;
+ begin
+ if Rlen = 0 or Llen = 0 then
+ Warn_Compare_Null (Loc);
+ Res := 'X';
+ else
+ L := Has_Xd (Left);
+ R := Has_Xd (Right);
+ if L = '-' or R = '-' then
+ Warning_Msg_Synth (+Loc, "'-' found in compare string");
+ Res := 'X';
+ elsif L = 'X' or R = 'X' then
+ Res := 'X';
+ else
+ if Is_Signed then
+ Cmp := Compare_Sgn_Sgn (Left, Right, Equal, Loc);
+ else
+ Cmp := Compare_Uns_Uns (Left, Right, Equal, Loc);
+ end if;
+ Res := Map (Cmp);
+ end if;
+ end if;
+
+ return Create_Memory_U8 (Std_Ulogic'Pos (Res), Logic_Type);
+ end Match_Cmp_Vec_Vec;
end Synth.Ieee.Numeric_Std;