aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2022-05-31 05:21:38 +0200
committerTristan Gingold <tgingold@free.fr>2022-05-31 18:28:24 +0200
commitc8dffe5ce5f11f4da59dba36129c2e754425f047 (patch)
tree70baab5f7e911fa193a494bcadc34862d95210c1
parentb4e205d65eee6f1065c179f042df1c0fe0ef6d40 (diff)
downloadghdl-c8dffe5ce5f11f4da59dba36129c2e754425f047.tar.gz
ghdl-c8dffe5ce5f11f4da59dba36129c2e754425f047.tar.bz2
ghdl-c8dffe5ce5f11f4da59dba36129c2e754425f047.zip
synth-vhdl_eval: handle more operations (to_string, match)
-rw-r--r--src/synth/synth-ieee-std_logic_1164.ads65
-rw-r--r--src/synth/synth-vhdl_eval.adb187
2 files changed, 229 insertions, 23 deletions
diff --git a/src/synth/synth-ieee-std_logic_1164.ads b/src/synth/synth-ieee-std_logic_1164.ads
index 33a298f81..a98b5537f 100644
--- a/src/synth/synth-ieee-std_logic_1164.ads
+++ b/src/synth/synth-ieee-std_logic_1164.ads
@@ -105,4 +105,69 @@ package Synth.Ieee.Std_Logic_1164 is
-- UX01ZWLH-
"UX10XX10X";
+ Match_Eq_Table : constant Table_2d :=
+ -- UX01ZWLH-
+ ("UUUUUUUU1", -- U
+ "UXXXXXXX1", -- X
+ "UX10XX101", -- 0
+ "UX01XX011", -- 1
+ "UXXXXXXX1", -- Z
+ "UXXXXXXX1", -- W
+ "UX10XX101", -- L
+ "UX01XX011", -- H
+ "111111111" -- -
+ );
+
+ Match_Le_Table : constant Table_2d :=
+ -- UX01ZWLH-
+ ("UUUUUUUU1", -- U
+ "UXXXXXXX1", -- X
+ "UX11XX111", -- 0
+ "UX01XX011", -- 1
+ "UXXXXXXX1", -- Z
+ "UXXXXXXX1", -- W
+ "UX11XX111", -- L
+ "UX01XX011", -- H
+ "111111111" -- -
+ );
+
+ Match_Lt_Table : constant Table_2d :=
+ -- UX01ZWLH-
+ ("UUUUUUUU1", -- U
+ "UXXXXXXX1", -- X
+ "UX01XX011", -- 0
+ "UX00XX001", -- 1
+ "UXXXXXXX1", -- Z
+ "UXXXXXXX1", -- W
+ "UX01XX011", -- L
+ "UX00XX001", -- H
+ "111111111" -- -
+ );
+
+ Match_Ge_Table : constant Table_2d :=
+ -- UX01ZWLH-
+ ("UUUUUUUU1", -- U
+ "UXXXXXXX1", -- X
+ "UX10XX101", -- 0
+ "UX11XX111", -- 1
+ "UXXXXXXX1", -- Z
+ "UXXXXXXX1", -- W
+ "UX10XX101", -- L
+ "UX11XX111", -- H
+ "111111111" -- -
+ );
+
+ Match_Gt_Table : constant Table_2d :=
+ -- UX01ZWLH-
+ ("UUUUUUUU1", -- U
+ "UXXXXXXX1", -- X
+ "UX00XX001", -- 0
+ "UX10XX101", -- 1
+ "UXXXXXXX1", -- Z
+ "UXXXXXXX1", -- W
+ "UX00XX001", -- L
+ "UX10XX101", -- H
+ "111111111" -- -
+ );
+
end Synth.Ieee.Std_Logic_1164;
diff --git a/src/synth/synth-vhdl_eval.adb b/src/synth/synth-vhdl_eval.adb
index e3b998afd..ab50a5e6b 100644
--- a/src/synth/synth-vhdl_eval.adb
+++ b/src/synth/synth-vhdl_eval.adb
@@ -25,6 +25,7 @@ with Grt.Vhdl_Types; use Grt.Vhdl_Types;
with Grt.To_Strings;
with Vhdl.Utils;
+with Vhdl.Evaluation;
with Vhdl.Ieee.Std_Logic_1164; use Vhdl.Ieee.Std_Logic_1164;
with Elab.Memtype; use Elab.Memtype;
@@ -108,6 +109,39 @@ package body Synth.Vhdl_Eval is
return Res;
end Eval_Vector_Dyadic;
+ function Eval_Logic_Vector_Scalar (Vect, Scal : Memtyp;
+ Op : Table_2d;
+ Neg : Boolean := False) return Memtyp
+ is
+ Res : Memtyp;
+ Vs, Vv, Vr : Std_Ulogic;
+ begin
+ Res := Create_Memory (Create_Res_Bound (Vect.Typ));
+ Vs := Read_Std_Logic (Scal.Mem, 0);
+ for I in 1 .. Vect.Typ.Abound.Len loop
+ Vv := Read_Std_Logic (Vect.Mem, I - 1);
+ Vr := Op (Vs, Vv);
+ if Neg then
+ Vr := Not_Table (Vr);
+ end if;
+ Write_Std_Logic (Res.Mem, I - 1, Vr);
+ end loop;
+ return Res;
+ end Eval_Logic_Vector_Scalar;
+
+ function Eval_Logic_Scalar (Left, Right : Memtyp;
+ Op : Table_2d;
+ Neg : Boolean := False) return Memtyp
+ is
+ Res : Std_Ulogic;
+ begin
+ Res := Op (Read_Std_Logic (Left.Mem, 0), Read_Std_Logic (Right.Mem, 0));
+ if Neg then
+ Res := Not_Table (Res);
+ end if;
+ return Create_Memory_U8 (Std_Ulogic'Pos (Res), Left.Typ);
+ end Eval_Logic_Scalar;
+
function Eval_TF_Vector_Dyadic (Left, Right : Memtyp;
Op : Tf_Table_2d;
Loc : Syn_Src) return Memtyp
@@ -325,12 +359,6 @@ package body Synth.Vhdl_Eval is
return Res;
end Execute_Shift_Operator;
- function Get_Static_Ulogic (Op : Memtyp) return Std_Ulogic is
- begin
- pragma Assert (Op.Typ.Kind = Type_Logic);
- return Std_Ulogic'Val (Read_U8 (Op.Mem));
- end Get_Static_Ulogic;
-
procedure Check_Integer_Overflow
(Val : in out Int64; Typ : Type_Acc; Loc : Syn_Src) is
begin
@@ -712,23 +740,54 @@ package body Synth.Vhdl_Eval is
| Iir_Predefined_Ieee_Numeric_Std_Xor_Sgn_Sgn =>
return Eval_Vector_Dyadic (Left, Right, Xor_Table, Expr);
- when Iir_Predefined_Ieee_1164_Scalar_Or =>
- return Create_Memory_U8
- (Std_Ulogic'Pos (Or_Table (Get_Static_Ulogic (Left),
- Get_Static_Ulogic (Right))),
- Res_Typ);
-
when Iir_Predefined_Ieee_1164_Scalar_And =>
- return Create_Memory_U8
- (Std_Ulogic'Pos (And_Table (Get_Static_Ulogic (Left),
- Get_Static_Ulogic (Right))),
- Res_Typ);
-
+ return Eval_Logic_Scalar (Left, Right, And_Table);
+ when Iir_Predefined_Ieee_1164_Scalar_Or =>
+ return Eval_Logic_Scalar (Left, Right, Or_Table);
when Iir_Predefined_Ieee_1164_Scalar_Xor =>
- return Create_Memory_U8
- (Std_Ulogic'Pos (Xor_Table (Get_Static_Ulogic (Left),
- Get_Static_Ulogic (Right))),
- Res_Typ);
+ return Eval_Logic_Scalar (Left, Right, Xor_Table);
+
+ when Iir_Predefined_Std_Ulogic_Match_Equality =>
+ return Eval_Logic_Scalar (Left, Right, Match_Eq_Table);
+ when Iir_Predefined_Std_Ulogic_Match_Inequality =>
+ return Eval_Logic_Scalar (Left, Right, Match_Eq_Table, True);
+ when Iir_Predefined_Std_Ulogic_Match_Greater =>
+ return Eval_Logic_Scalar (Left, Right, Match_Gt_Table);
+ when Iir_Predefined_Std_Ulogic_Match_Greater_Equal =>
+ return Eval_Logic_Scalar (Left, Right, Match_Ge_Table);
+ when Iir_Predefined_Std_Ulogic_Match_Less_Equal =>
+ return Eval_Logic_Scalar (Left, Right, Match_Le_Table);
+ when Iir_Predefined_Std_Ulogic_Match_Less =>
+ return Eval_Logic_Scalar (Left, Right, Match_Lt_Table);
+
+ when Iir_Predefined_Std_Ulogic_Array_Match_Equality =>
+ return Eval_Vector_Dyadic (Left, Right, Match_Eq_Table, Expr);
+
+ when Iir_Predefined_Ieee_1164_And_Suv_Log =>
+ return Eval_Logic_Vector_Scalar (Left, Right, And_Table);
+ when Iir_Predefined_Ieee_1164_Or_Suv_Log =>
+ return Eval_Logic_Vector_Scalar (Left, Right, Or_Table);
+ when Iir_Predefined_Ieee_1164_Xor_Suv_Log =>
+ return Eval_Logic_Vector_Scalar (Left, Right, Xor_Table);
+ when Iir_Predefined_Ieee_1164_Nand_Suv_Log =>
+ return Eval_Logic_Vector_Scalar (Left, Right, And_Table, True);
+ when Iir_Predefined_Ieee_1164_Nor_Suv_Log =>
+ return Eval_Logic_Vector_Scalar (Left, Right, Or_Table, True);
+ when Iir_Predefined_Ieee_1164_Xnor_Suv_Log =>
+ return Eval_Logic_Vector_Scalar (Left, Right, Xor_Table, True);
+
+ when Iir_Predefined_Ieee_1164_And_Log_Suv =>
+ return Eval_Logic_Vector_Scalar (Right, Left, And_Table);
+ when Iir_Predefined_Ieee_1164_Or_Log_Suv =>
+ return Eval_Logic_Vector_Scalar (Right, Left, Or_Table);
+ when Iir_Predefined_Ieee_1164_Xor_Log_Suv =>
+ return Eval_Logic_Vector_Scalar (Right, Left, Xor_Table);
+ when Iir_Predefined_Ieee_1164_Nand_Log_Suv =>
+ return Eval_Logic_Vector_Scalar (Right, Left, And_Table, True);
+ when Iir_Predefined_Ieee_1164_Nor_Log_Suv =>
+ return Eval_Logic_Vector_Scalar (Right, Left, Or_Table, True);
+ when Iir_Predefined_Ieee_1164_Xnor_Log_Suv =>
+ return Eval_Logic_Vector_Scalar (Right, Left, Xor_Table, True);
when Iir_Predefined_Ieee_Numeric_Std_Eq_Uns_Uns =>
declare
@@ -1480,11 +1539,93 @@ package body Synth.Vhdl_Eval is
(Str, First, Ghdl_I64 (Read_Discrete (Param1)));
return String_To_Memtyp (Str (First .. Str'Last), Res_Typ);
end;
+ when Iir_Predefined_Enum_To_String =>
+ return Eval_Enum_To_String (Get_Memtyp (Param1), Res_Typ, Imp);
+ when Iir_Predefined_Floating_To_String =>
+ declare
+ Str : String (1 .. 24);
+ Last : Natural;
+ begin
+ Grt.To_Strings.To_String
+ (Str, Last, Ghdl_F64 (Read_Fp64 (Param1)));
+ return String_To_Memtyp (Str (Str'First .. Last), Res_Typ);
+ end;
+ when Iir_Predefined_Real_To_String_Digits =>
+ declare
+ Str : Grt.To_Strings.String_Real_Format;
+ Last : Natural;
+ Val : Ghdl_F64;
+ Dig : Ghdl_I32;
+ begin
+ Val := Ghdl_F64 (Read_Fp64 (Param1));
+ Dig := Ghdl_I32 (Read_Discrete (Param2));
+ Grt.To_Strings.To_String (Str, Last, Val, Dig);
+ return String_To_Memtyp (Str (Str'First .. Last), Res_Typ);
+ end;
+ when Iir_Predefined_Real_To_String_Format =>
+ declare
+ Format : String (1 .. Natural (Param2.Typ.Abound.Len) + 1);
+ Str : Grt.To_Strings.String_Real_Format;
+ Last : Natural;
+ begin
+ -- Copy format
+ for I in 1 .. Param2.Typ.Abound.Len loop
+ Format (Positive (I)) := Character'Val
+ (Read_U8 (Param2.Val.Mem + Size_Type (I - 1)));
+ end loop;
+ Format (Format'Last) := ASCII.NUL;
+ Grt.To_Strings.To_String
+ (Str, Last, Ghdl_F64 (Read_Fp64 (Param1)),
+ To_Ghdl_C_String (Format'Address));
+ return String_To_Memtyp (Str (Str'First .. Last), Res_Typ);
+ end;
+
+ when Iir_Predefined_Physical_To_String =>
+ declare
+ Phys_Type : constant Node :=
+ Get_Type (Get_Interface_Declaration_Chain (Imp));
+ Id : constant Name_Id :=
+ Get_Identifier (Get_Primary_Unit (Phys_Type));
+ Str : String (1 .. 21);
+ First : Natural;
+ begin
+ Grt.To_Strings.To_String
+ (Str, First, Ghdl_I64 (Read_Discrete (Param1)));
+ return String_To_Memtyp
+ (Str (First .. Str'Last) & ' ' & Name_Table.Image (Id),
+ Res_Typ);
+ end;
+ when Iir_Predefined_Time_To_String_Unit =>
+ declare
+ Time_Type : constant Node :=
+ Get_Type (Get_Interface_Declaration_Chain (Imp));
+ Str : Grt.To_Strings.String_Time_Unit;
+ First : Natural;
+ Unit : Iir;
+ Uval : Int64;
+ begin
+ Uval := Read_Discrete (Param2);
+ Unit := Get_Unit_Chain (Time_Type);
+ while Unit /= Null_Iir loop
+ exit when Vhdl.Evaluation.Get_Physical_Value (Unit) = Uval;
+ Unit := Get_Chain (Unit);
+ end loop;
+ if Unit = Null_Iir then
+ Error_Msg_Synth
+ (+Expr, "to_string for time called with wrong unit");
+ end if;
+ Grt.To_Strings.To_String (Str, First,
+ Ghdl_I64 (Read_Discrete (Param1)),
+ Ghdl_I64 (Uval));
+ return String_To_Memtyp
+ (Str (First .. Str'Last) & ' '
+ & Name_Table.Image (Get_Identifier (Unit)),
+ Res_Typ);
+ end;
+
when Iir_Predefined_Array_Char_To_String =>
return Eval_Array_Char_To_String
(Get_Memtyp (Param1), Res_Typ, Imp);
- when Iir_Predefined_Enum_To_String =>
- return Eval_Enum_To_String (Get_Memtyp (Param1), Res_Typ, Imp);
when Iir_Predefined_Bit_Vector_To_Hstring =>
return Eval_Bit_Vector_To_String (Get_Memtyp (Param1), Res_Typ, 4);