aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/synth-expr.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/synth/synth-expr.adb')
-rw-r--r--src/synth/synth-expr.adb704
1 files changed, 450 insertions, 254 deletions
diff --git a/src/synth/synth-expr.adb b/src/synth/synth-expr.adb
index a14f7db32..60cd7cc71 100644
--- a/src/synth/synth-expr.adb
+++ b/src/synth/synth-expr.adb
@@ -21,12 +21,13 @@
with Ada.Unchecked_Conversion;
with Ada.Unchecked_Deallocation;
with Std_Names;
+with Str_Table;
with Vhdl.Ieee.Std_Logic_1164;
with Vhdl.Std_Package;
with Vhdl.Errors; use Vhdl.Errors;
with Vhdl.Utils; use Vhdl.Utils;
-with Simul.Execution;
-with Grt.Types; use Grt.Types;
+with Vhdl.Evaluation; use Vhdl.Evaluation;
+with Simul.Annotations; use Simul.Annotations;
with Synth.Errors; use Synth.Errors;
with Synth.Types; use Synth.Types;
@@ -38,21 +39,28 @@ with Netlists.Builders; use Netlists.Builders;
package body Synth.Expr is
function Is_Const (Val : Value_Acc) return Boolean is
begin
- return Val.Kind = Value_Lit;
+ case Val.Kind is
+ when Value_Logic
+ | Value_Discrete =>
+ return True;
+ when Value_Net
+ | Value_Wire
+ | Value_Mux2 =>
+ return False;
+ when others =>
+ -- TODO.
+ raise Internal_Error;
+ end case;
end Is_Const;
function Get_Width (Val : Value_Acc) return Uns32 is
begin
case Val.Kind is
- when Value_Lit =>
- if Is_Bit_Type (Val.Lit_Type) then
- return 1;
- else
- raise Internal_Error;
- end if;
+ when Value_Logic =>
+ return 1;
when Value_Wire
| Value_Net =>
- return Get_Width (Get_Net (Val));
+ return Get_Width (Get_Net (Val, Null_Node));
when others =>
raise Internal_Error; -- TODO
end case;
@@ -60,93 +68,89 @@ package body Synth.Expr is
function Is_Logic (Val : Value_Acc) return Boolean is
begin
- if Val.Kind = Value_Lit then
- case Val.Lit.Kind is
- when Iir_Value_B1 =>
- return True;
- when Iir_Value_E8 =>
- return Is_Bit_Type (Val.Lit_Type);
- when others =>
- return False;
- end case;
- else
- return False;
- end if;
+ return Val.Kind = Value_Logic;
end Is_Logic;
- procedure To_Logic (Lit : Iir_Value_Literal_Acc;
- Val : out Uns32;
- Zx : out Uns32) is
+ procedure From_Std_Logic (Enum : Int64; Val : out Uns32; Zx : out Uns32) is
begin
- case Lit.Kind is
- when Iir_Value_B1 =>
+ case Enum is
+ when Vhdl.Ieee.Std_Logic_1164.Std_Logic_0_Pos
+ | Vhdl.Ieee.Std_Logic_1164.Std_Logic_L_Pos =>
+ Val := 0;
Zx := 0;
- Val := Ghdl_B1'Pos (Lit.B1);
- when Iir_Value_E8 =>
- -- Std_logic.
- case Lit.E8 is
- when Vhdl.Ieee.Std_Logic_1164.Std_Logic_0_Pos
- | Vhdl.Ieee.Std_Logic_1164.Std_Logic_L_Pos =>
- Val := 0;
- Zx := 0;
- when Vhdl.Ieee.Std_Logic_1164.Std_Logic_1_Pos
- | Vhdl.Ieee.Std_Logic_1164.Std_Logic_H_Pos =>
- Val := 1;
- Zx := 0;
- 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_D_Pos =>
- Val := 1;
- Zx := 1;
- when Vhdl.Ieee.Std_Logic_1164.Std_Logic_Z_Pos
- | Vhdl.Ieee.Std_Logic_1164.Std_Logic_W_Pos =>
- Val := 0;
- Zx := 1;
- when others =>
- -- Only 9 values.
- raise Internal_Error;
- end case;
+ when Vhdl.Ieee.Std_Logic_1164.Std_Logic_1_Pos
+ | Vhdl.Ieee.Std_Logic_1164.Std_Logic_H_Pos =>
+ Val := 1;
+ Zx := 0;
+ 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_D_Pos =>
+ Val := 1;
+ Zx := 1;
+ when Vhdl.Ieee.Std_Logic_1164.Std_Logic_Z_Pos
+ | Vhdl.Ieee.Std_Logic_1164.Std_Logic_W_Pos =>
+ Val := 0;
+ Zx := 1;
when others =>
+ -- Only 9 values.
raise Internal_Error;
end case;
+ end From_Std_Logic;
+
+ procedure From_Bit (Enum : Int64; Val : out Uns32) is
+ begin
+ if Enum = 0 then
+ Val := 0;
+ elsif Enum = 1 then
+ Val := 1;
+ else
+ raise Internal_Error;
+ end if;
+ end From_Bit;
+
+ procedure To_Logic
+ (Enum : Int64; Etype : Node; Val : out Uns32; Zx : out Uns32)
+ is
+ Btype : constant Node := Get_Base_Type (Etype);
+ begin
+ if Btype = Vhdl.Ieee.Std_Logic_1164.Std_Ulogic_Type then
+ From_Std_Logic (Enum, Val, Zx);
+ elsif Btype = Vhdl.Std_Package.Boolean_Type_Definition
+ or else Btype = Vhdl.Std_Package.Bit_Type_Definition
+ then
+ From_Bit (Enum, Val);
+ Zx := 0;
+ else
+ raise Internal_Error;
+ end if;
end To_Logic;
function Bit_Extract (Val : Value_Acc; Off : Uns32) return Value_Acc is
begin
case Val.Kind is
- when Value_Lit =>
- declare
- Lit : constant Iir_Value_Literal_Acc := Val.Lit;
- begin
- pragma Assert (Lit.Kind = Iir_Value_Array);
- pragma Assert (Lit.Bounds.Nbr_Dims = 1);
- pragma Assert (Lit.Bounds.D (1).Length >= Iir_Index32 (Off));
- return Create_Value_Lit
- (Lit.Val_Array.V (Lit.Val_Array.Len - Iir_Index32 (Off)),
- Get_Element_Subtype (Val.Lit_Type));
- end;
+ when Value_Array =>
+ pragma Assert (Val.Bounds.D (1).Len >= Off);
+ return Val.Arr.V (Iir_Index32 (Val.Bounds.D (1).Len - Off));
when Value_Net
| Value_Wire =>
return Create_Value_Net
- (Build_Extract_Bit (Build_Context, Get_Net (Val), Off),
- No_Range);
+ (Build_Extract_Bit
+ (Build_Context, Get_Net (Val, Null_Node), Off),
+ No_Bound);
when others =>
raise Internal_Error;
end case;
end Bit_Extract;
- function Vec_Extract (Val : Value_Acc; Off : Uns32; Rng : Value_Range_Acc)
+ function Vec_Extract (Val : Value_Acc; Off : Uns32; Bnd : Value_Bound_Acc)
return Value_Acc is
begin
case Val.Kind is
- when Value_Lit =>
- -- TODO.
- raise Internal_Error;
when Value_Net
| Value_Wire =>
return Create_Value_Net
- (Build_Slice (Build_Context, Get_Net (Val), Off, Rng.Len),
- Rng);
+ (Build_Slice (Build_Context,
+ Get_Net (Val, Null_Node), Off, Bnd.Len), Bnd);
when others =>
raise Internal_Error;
end case;
@@ -165,38 +169,66 @@ package body Synth.Expr is
end if;
end Synth_Uresize;
- function Synth_Uresize (Val : Value_Acc; W : Width) return Net is
+ function Synth_Uresize (Val : Value_Acc; Vtype : Node; W : Width)
+ return Net is
begin
- return Synth_Uresize (Get_Net (Val), W);
+ return Synth_Uresize (Get_Net (Val, Vtype), W);
end Synth_Uresize;
- procedure Fill_Array_Aggregate
- (Syn_Inst : Synth_Instance_Acc;
- Aggr : Node;
- Res : Value_Acc;
- Dim : Iir_Index32;
- Orig : Iir_Index32;
- Stride : Iir_Index32)
+ function Get_Index_Offset (Index: Value_Acc;
+ Bounds: Value_Bound_Acc;
+ Expr: Iir)
+ return Uns32 is
+ begin
+ if Index.Kind = Value_Discrete then
+ declare
+ Left : constant Int64 := Int64 (Bounds.Left);
+ Right : constant Int64 := Int64 (Bounds.Right);
+ begin
+ case Bounds.Dir is
+ when Iir_To =>
+ if Index.Scal >= Left and then Index.Scal <= Right then
+ -- to
+ return Uns32 (Index.Scal - Left);
+ end if;
+ when Iir_Downto =>
+ if Index.Scal <= Left and then Index.Scal >= Right then
+ -- downto
+ return Uns32 (Left - Index.Scal);
+ end if;
+ end case;
+ end;
+ else
+ raise Internal_Error;
+ end if;
+ Error_Msg_Synth (+Expr, "index out of bounds");
+ return 0;
+ end Get_Index_Offset;
+
+ procedure Fill_Array_Aggregate (Syn_Inst : Synth_Instance_Acc;
+ Aggr : Node;
+ Res : Value_Acc;
+ Dim : Natural)
is
- Bound : constant Iir_Value_Literal_Acc := Res.Bounds.D (Dim);
+ Bound : constant Value_Bound_Acc := Res.Bounds.D (1);
Aggr_Type : constant Node := Get_Type (Aggr);
El_Type : constant Node := Get_Element_Subtype (Aggr_Type);
- Idx_Type : constant Node :=
- Get_Index_Type (Aggr_Type, Natural (Dim - 1));
- type Boolean_Array is array (Iir_Index32 range <>) of Boolean;
+ Nbr_Dims : constant Natural := Get_Nbr_Dimensions (Aggr_Type);
+ Idx_Type : constant Node := Get_Index_Type (Aggr_Type, Dim);
+ type Boolean_Array is array (Uns32 range <>) of Boolean;
pragma Pack (Boolean_Array);
- Is_Set : Boolean_Array (0 .. Bound.Length - 1);
+ Is_Set : Boolean_Array (0 .. Bound.Len - 1);
Value : Node;
Assoc : Node;
- Pos : Iir_Index32;
+ Pos : Uns32;
- procedure Set_Elem (Pos : Iir_Index32)
+ procedure Set_Elem (Pos : Uns32)
is
Val : Value_Acc;
begin
- if Dim = Res.Bounds.Nbr_Dims then
+ if Dim = Nbr_Dims - 1 then
Val := Synth_Expression_With_Type (Syn_Inst, Value, El_Type);
- Res.Arr.V (Orig + Stride * Pos) := Val;
+ Res.Arr.V (Iir_Index32 (Pos + 1)) := Val;
pragma Assert (not Is_Set (Pos));
Is_Set (Pos) := True;
else
@@ -212,14 +244,14 @@ package body Synth.Expr is
loop
case Get_Kind (Assoc) is
when Iir_Kind_Choice_By_None =>
- if Pos >= Bound.Length then
+ if Pos >= Bound.Len then
Error_Msg_Synth (+Assoc, "element out of array bound");
else
Set_Elem (Pos);
end if;
Pos := Pos + 1;
when Iir_Kind_Choice_By_Others =>
- while Pos < Bound.Length loop
+ while Pos < Bound.Len loop
if not Is_Set (Pos) then
Set_Elem (Pos);
end if;
@@ -235,8 +267,7 @@ package body Synth.Expr is
if not Is_Const (Idx) then
Error_Msg_Synth (+Ch, "choice is not static");
else
- Set_Elem (Simul.Execution.Get_Index_Offset
- (Idx.Lit, Bound, Ch));
+ Set_Elem (Get_Index_Offset (Idx, Bound, Ch));
end if;
end;
when Iir_Kind_Choice_By_Range =>
@@ -258,7 +289,7 @@ package body Synth.Expr is
(Net_Array, Net_Array_Acc);
-- Convert the one-dimension VAL to a net by concatenating.
- function Vectorize_Array (Val : Value_Acc) return Value_Acc
+ function Vectorize_Array (Val : Value_Acc; Etype : Node) return Value_Acc
is
Arr : Net_Array_Acc;
Len : Iir_Index32;
@@ -285,14 +316,15 @@ package body Synth.Expr is
and then Off < 32
and then Is_Logic (Val.Arr.V (Idx))
loop
- To_Logic (Val.Arr.V (Idx).Lit, B_Va, B_Zx);
+ B_Va := Val.Arr.V (Idx).Log_Val;
+ B_Zx := Val.Arr.V (Idx).Log_Zx;
W_Zx := W_Zx or Shift_Left (B_Zx, Off);
W_Va := W_Va or Shift_Left (B_Va, Off);
Off := Off + 1;
Idx := Idx + 1;
end loop;
if Off = 0 then
- E := Get_Net (Val.Arr.V (Idx));
+ E := Get_Net (Val.Arr.V (Idx), Etype);
Idx := Idx + 1;
else
if W_Zx = 0 then
@@ -336,13 +368,94 @@ package body Synth.Expr is
Len := New_Idx;
end loop;
- Res := Create_Value_Net (Arr (1), Bounds_To_Range (Val.Bounds.D (1)));
+ Res := Create_Value_Net (Arr (1), Val.Bounds.D (1));
Free_Net_Array (Arr);
return Res;
end Vectorize_Array;
+ function Synth_Range_Expression
+ (Syn_Inst : Synth_Instance_Acc; Rng : Node) return Value_Acc
+ is
+ L, R : Value_Acc;
+ Res : Value_Acc;
+ begin
+ L := Synth_Expression (Syn_Inst, Get_Left_Limit (Rng));
+ R := Synth_Expression (Syn_Inst, Get_Right_Limit (Rng));
+ case Get_Kind (Get_Type (Rng)) is
+ when Iir_Kind_Integer_Type_Definition
+ | Iir_Kind_Integer_Subtype_Definition
+ | Iir_Kind_Enumeration_Type_Definition
+ | Iir_Kind_Enumeration_Subtype_Definition
+ | Iir_Kind_Physical_Type_Definition
+ | Iir_Kind_Physical_Subtype_Definition =>
+ Res := Create_Value_Range ((Get_Direction (Rng), L.Scal, R.Scal));
+ when Iir_Kind_Floating_Type_Definition
+ | Iir_Kind_Floating_Subtype_Definition =>
+ Res := Create_Value_Fp_Range ((Get_Direction (Rng), L.Fp, R.Fp));
+ when others =>
+ Error_Kind ("synth_range_expression", Get_Type (Rng));
+ end case;
+ return Res;
+ end Synth_Range_Expression;
+
+ function Synth_Range (Syn_Inst : Synth_Instance_Acc; Bound : Node)
+ return Value_Acc is
+ begin
+ case Get_Kind (Bound) is
+ when Iir_Kind_Range_Expression =>
+ return Synth_Range_Expression (Syn_Inst, Bound);
+ when Iir_Kind_Integer_Subtype_Definition =>
+ return Synth_Range (Syn_Inst, Get_Range_Constraint (Bound));
+ when others =>
+ Error_Kind ("synth_range", Bound);
+ end case;
+ end Synth_Range;
+
+ function Synth_Array_Bounds (Syn_Inst : Synth_Instance_Acc;
+ Atype : Node;
+ Dim : Natural) return Value_Bound_Acc
+ is
+ Info : constant Sim_Info_Acc := Get_Info (Atype);
+ begin
+ if Info = null then
+ pragma Assert (Get_Type_Declarator (Atype) = Null_Node);
+ declare
+ Index_Type : constant Node := Get_Index_Type (Atype, Dim);
+ begin
+ return Synth_Bounds_From_Range (Syn_Inst, Index_Type);
+ end;
+ else
+ declare
+ Bnds : constant Value_Acc := Get_Value (Syn_Inst, Atype);
+ begin
+ return Bnds.Bnds.D (Iir_Index32 (Dim) + 1);
+ end;
+ end if;
+ end Synth_Array_Bounds;
+
+ function Synth_Bounds_From_Range (Syn_Inst : Synth_Instance_Acc;
+ Atype : Node) return Value_Bound_Acc
+ is
+ Rng : Value_Acc;
+ Len : Int64;
+ begin
+ Rng := Synth_Range (Syn_Inst, Atype);
+ case Rng.Rng.Dir is
+ when Iir_To =>
+ Len := Rng.Rng.Right - Rng.Rng.Left + 1;
+ when Iir_Downto =>
+ Len := Rng.Rng.Left - Rng.Rng.Right + 1;
+ end case;
+ if Len < 0 then
+ Len := 0;
+ end if;
+ return Create_Value_Bound
+ ((Rng.Rng.Dir, Int32 (Rng.Rng.Left), Int32 (Rng.Rng.Right),
+ Uns32 (Len)));
+ end Synth_Bounds_From_Range;
+
function Synth_Aggregate (Syn_Inst : Synth_Instance_Acc;
Aggr : Node;
Aggr_Type : Node) return Value_Acc is
@@ -350,22 +463,27 @@ package body Synth.Expr is
case Get_Kind (Aggr_Type) is
when Iir_Kind_Array_Type_Definition
| Iir_Kind_Array_Subtype_Definition =>
+ if not Is_Vector_Type (Aggr_Type) then
+ -- TODO: generalize, in particular multi-dim arrays.
+ raise Internal_Error;
+ end if;
declare
- Bnd : Iir_Value_Literal_Acc;
+ Bnd : Value_Bound_Acc;
+ Bnds : Value_Bound_Array_Acc;
Res : Value_Acc;
begin
-- Create bounds.
- Bnd := Simul.Execution.Create_Array_Bounds_From_Type
- (Syn_Inst.Sim, Aggr_Type, False);
+ Bnd := Synth_Array_Bounds (Syn_Inst, Aggr_Type, 0);
-- Allocate result
- Res := Create_Array_Value (Bnd.Bounds);
+ Bnds := Create_Value_Bound_Array (1);
+ Bnds.D (1) := Bnd;
+ Res := Create_Value_Array (Bnds);
Create_Array_Data (Res);
- Fill_Array_Aggregate
- (Syn_Inst, Aggr, Res,
- 1, 1, Res.Arr.Len / Res.Bounds.D (1).Length);
+ Fill_Array_Aggregate (Syn_Inst, Aggr, Res, 0);
if Is_Vector_Type (Aggr_Type) then
-- Vectorize
- Res := Vectorize_Array (Res);
+ Res := Vectorize_Array
+ (Res, Get_Element_Subtype (Aggr_Type));
end if;
return Res;
end;
@@ -377,57 +495,56 @@ package body Synth.Expr is
end case;
end Synth_Aggregate;
- function Synth_Bit_Eq_Const (Cst : Value_Acc; Expr : Value_Acc; Loc : Node)
- return Value_Acc
+ function Synth_Bit_Eq_Const
+ (Cst : Value_Acc; Expr : Value_Acc; Etype : Node; Loc : Node)
+ return Value_Acc
is
pragma Unreferenced (Loc);
Val : Uns32;
- Xz : Uns32;
+ Zx : Uns32;
begin
- To_Logic (Cst.Lit, Val, Xz);
- if Xz /= 0 then
+ To_Logic (Cst.Scal, Etype, Val, Zx);
+ if Zx /= 0 then
return Create_Value_Net
- (Build_Const_UL32 (Build_Context, 0, 1, 1), No_Range);
+ (Build_Const_UL32 (Build_Context, 0, 1, 1), No_Bound);
elsif Val = 1 then
return Expr;
else
pragma Assert (Val = 0);
return Create_Value_Net
- (Build_Monadic (Build_Context, Id_Not, Get_Net (Expr)), No_Range);
+ (Build_Monadic (Build_Context, Id_Not, Get_Net (Expr, Etype)),
+ No_Bound);
end if;
end Synth_Bit_Eq_Const;
- function Extract_Range (Val : Value_Acc) return Value_Range_Acc is
+ function Extract_Bound (Val : Value_Acc) return Value_Bound_Acc is
begin
case Val.Kind is
when Value_Net =>
- return Val.N_Range;
+ return Val.N_Bound;
when Value_Wire =>
- return Val.W_Range;
+ return Val.W_Bound;
when others =>
raise Internal_Error;
end case;
- end Extract_Range;
+ end Extract_Bound;
-- Create the result range of an operator. According to the ieee standard,
-- the range is LEN-1 downto 0.
- function Create_Res_Range (Prev : Value_Acc; N : Net)
- return Value_Range_Acc
+ function Create_Res_Bound (Prev : Value_Acc; N : Net) return Value_Bound_Acc
is
- Res : Value_Range_Acc;
+ Res : Value_Bound_Acc;
Wd : Width;
begin
case Prev.Kind is
when Value_Net
| Value_Wire =>
- Res := Extract_Range (Prev);
- when Value_Lit =>
- Res := No_Range;
+ Res := Extract_Bound (Prev);
when others =>
raise Internal_Error;
end case;
- if Res /= No_Range
+ if Res /= No_Bound
and then Res.Dir = Iir_Downto
and then Res.Right = 0
then
@@ -436,50 +553,94 @@ package body Synth.Expr is
end if;
Wd := Get_Width (N);
- return Create_Range_Value ((Iir_Downto, Wd, Int32 (Wd - 1), 0));
- end Create_Res_Range;
+ return Create_Value_Bound ((Dir => Iir_Downto,
+ Left => Int32 (Wd - 1),
+ Right => 0,
+ Len => Wd));
+ end Create_Res_Bound;
+
+ function Create_Bounds_From_Length
+ (Syn_Inst : Synth_Instance_Acc; Atype : Iir; Len : Iir_Index32)
+ return Value_Bound_Acc
+ is
+ Res : Value_Bound_Acc;
+ Index_Bounds : Value_Acc;
+ begin
+ Index_Bounds := Synth_Range (Syn_Inst, Atype);
+
+ Res := Create_Value_Bound ((Left => Int32 (Index_Bounds.Rng.Left),
+ Right => 0,
+ Dir => Index_Bounds.Rng.Dir,
+ Len => Uns32 (Len)));
+
+ if Len = 0 then
+ -- Special case.
+ Res.Right := Res.Left;
+ case Index_Bounds.Rng.Dir is
+ when Iir_To =>
+ Res.Left := Res.Right + 1;
+ when Iir_Downto =>
+ Res.Left := Res.Right - 1;
+ end case;
+ else
+ case Index_Bounds.Rng.Dir is
+ when Iir_To =>
+ Res.Right := Res.Left + Int32 (Len - 1);
+ when Iir_Downto =>
+ Res.Right := Res.Left - Int32 (Len - 1);
+ end case;
+ end if;
+ return Res;
+ end Create_Bounds_From_Length;
function Synth_Dyadic_Operation (Syn_Inst : Synth_Instance_Acc;
Def : Iir_Predefined_Functions;
- Left : Value_Acc;
- Right : Value_Acc;
+ Left_Expr : Node;
+ Right_Expr : Node;
Expr : Node) return Value_Acc
is
+ Ltype : constant Node := Get_Type (Left_Expr);
+ Rtype : constant Node := Get_Type (Right_Expr);
+ Left : Value_Acc;
+ Right : Value_Acc;
+
function Synth_Bit_Dyadic (Id : Dyadic_Module_Id) return Value_Acc is
begin
return Create_Value_Net
- (Build_Dyadic (Build_Context, Id, Get_Net (Left), Get_Net (Right)),
- No_Range);
+ (Build_Dyadic (Build_Context, Id,
+ Get_Net (Left, Ltype), Get_Net (Right, Rtype)),
+ No_Bound);
end Synth_Bit_Dyadic;
function Synth_Compare (Id : Compare_Module_Id) return Value_Acc is
begin
return Create_Value_Net
- (Build_Compare (Build_Context, Id, Get_Net (Left), Get_Net (Right)),
- No_Range);
+ (Build_Compare (Build_Context, Id,
+ Get_Net (Left, Ltype), Get_Net (Right, Rtype)),
+ No_Bound);
end Synth_Compare;
function Synth_Vec_Dyadic (Id : Dyadic_Module_Id) return Value_Acc
is
- L : constant Net := Get_Net (Left);
+ L : constant Net := Get_Net (Left, Ltype);
begin
return Create_Value_Net
- (Build_Dyadic (Build_Context, Id, L, Get_Net (Right)),
- Create_Res_Range (Left, L));
+ (Build_Dyadic (Build_Context, Id, L, Get_Net (Right, Rtype)),
+ Create_Res_Bound (Left, L));
end Synth_Vec_Dyadic;
function Synth_Dyadic_Uns (Id : Dyadic_Module_Id; Is_Res_Vec : Boolean)
return Value_Acc
is
- L : constant Net := Get_Net (Left);
- R : constant Net := Get_Net (Right);
+ L : constant Net := Get_Net (Left, Ltype);
+ R : constant Net := Get_Net (Right, Rtype);
W : constant Width := Width'Max (Get_Width (L), Get_Width (R));
- Rtype : Value_Range_Acc;
+ Rtype : Value_Bound_Acc;
begin
if Is_Res_Vec then
- Rtype := Create_Range_Value ((Iir_Downto, W, Int32 (W - 1), 0));
+ Rtype := Create_Value_Bound ((Iir_Downto, Int32 (W - 1), 0, W));
else
- Rtype := No_Range;
+ Rtype := No_Bound;
end if;
return Create_Value_Net
(Build_Dyadic
@@ -487,6 +648,9 @@ package body Synth.Expr is
Rtype);
end Synth_Dyadic_Uns;
begin
+ Left := Synth_Expression (Syn_Inst, Left_Expr);
+ Right := Synth_Expression (Syn_Inst, Right_Expr);
+
case Def is
when Iir_Predefined_Error =>
return null;
@@ -519,11 +683,12 @@ package body Synth.Expr is
return Synth_Bit_Dyadic (Id_Xnor);
when Iir_Predefined_Enum_Equality =>
- if Get_Width (Left) = 1 then
+ if Is_Bit_Type (Ltype) then
+ pragma Assert (Is_Bit_Type (Rtype));
if Is_Const (Left) then
- return Synth_Bit_Eq_Const (Left, Right, Expr);
+ return Synth_Bit_Eq_Const (Left, Right, Ltype, Expr);
elsif Is_Const (Right) then
- return Synth_Bit_Eq_Const (Right, Left, Expr);
+ return Synth_Bit_Eq_Const (Right, Left, Ltype, Expr);
end if;
end if;
return Synth_Compare (Id_Eq);
@@ -535,12 +700,13 @@ package body Synth.Expr is
when Iir_Predefined_Ieee_Numeric_Std_Add_Uns_Nat =>
-- "+" (Unsigned, Natural)
declare
- L : constant Net := Get_Net (Left);
+ L : constant Net := Get_Net (Left, Ltype);
begin
return Create_Value_Net
- (Build_Dyadic (Build_Context, Id_Add,
- L, Synth_Uresize (Right, Get_Width (Left))),
- Create_Res_Range (Left, L));
+ (Build_Dyadic
+ (Build_Context, Id_Add,
+ L, Synth_Uresize (Right, Rtype, Get_Width (Left))),
+ Create_Res_Bound (Left, L));
end;
when Iir_Predefined_Ieee_Numeric_Std_Add_Uns_Uns =>
-- "+" (Unsigned, Unsigned)
@@ -548,12 +714,13 @@ package body Synth.Expr is
when Iir_Predefined_Ieee_Numeric_Std_Sub_Uns_Nat =>
-- "-" (Unsigned, Natural)
declare
- L : constant Net := Get_Net (Left);
+ L : constant Net := Get_Net (Left, Ltype);
begin
return Create_Value_Net
- (Build_Dyadic (Build_Context, Id_Sub,
- L, Synth_Uresize (Right, Get_Width (Left))),
- Create_Res_Range (Left, L));
+ (Build_Dyadic
+ (Build_Context, Id_Sub,
+ L, Synth_Uresize (Right, Rtype, Get_Width (Left))),
+ Create_Res_Bound (Left, L));
end;
when Iir_Predefined_Ieee_Numeric_Std_Sub_Uns_Uns =>
-- "-" (Unsigned, Unsigned)
@@ -562,51 +729,49 @@ package body Synth.Expr is
-- "=" (Unsigned, Natural)
return Create_Value_Net
(Build_Compare (Build_Context, Id_Eq,
- Get_Net (Left),
- Synth_Uresize (Right, Get_Width (Left))),
- No_Range);
+ Get_Net (Left, Ltype),
+ Synth_Uresize (Right, Rtype, Get_Width (Left))),
+ No_Bound);
when Iir_Predefined_Ieee_Numeric_Std_Eq_Uns_Uns =>
-- "=" (Unsigned, Unsigned)
return Create_Value_Net
(Build_Compare (Build_Context, Id_Eq,
- Get_Net (Left), Get_Net (Right)),
- No_Range);
+ Get_Net (Left, Ltype),
+ Get_Net (Right, Rtype)),
+ No_Bound);
when Iir_Predefined_Array_Element_Concat =>
declare
- L : constant Net := Get_Net (Left);
+ L : constant Net := Get_Net (Left, Ltype);
begin
return Create_Value_Net
- (Build_Concat2 (Build_Context, L, Get_Net (Right)),
- Bounds_To_Range (Simul.Execution.Create_Bounds_From_Length
- (Syn_Inst.Sim,
- Get_Index_Type (Get_Type (Expr), 0),
- Iir_Index32 (Get_Width (L) + 1))));
+ (Build_Concat2 (Build_Context, L,
+ Get_Net (Right, Rtype)),
+ Create_Bounds_From_Length
+ (Syn_Inst,
+ Get_Index_Type (Get_Type (Expr), 0),
+ Iir_Index32 (Get_Width (L) + 1)));
end;
when Iir_Predefined_Element_Array_Concat =>
declare
- R : constant Net := Get_Net (Right);
+ R : constant Net := Get_Net (Right, Rtype);
begin
return Create_Value_Net
- (Build_Concat2 (Build_Context, Get_Net (Left), R),
- Bounds_To_Range (Simul.Execution.Create_Bounds_From_Length
- (Syn_Inst.Sim,
- Get_Index_Type (Get_Type (Expr), 0),
- Iir_Index32 (Get_Width (R) + 1))));
+ (Build_Concat2 (Build_Context, Get_Net (Left, Ltype), R),
+ Create_Bounds_From_Length
+ (Syn_Inst,
+ Get_Index_Type (Get_Type (Expr), 0),
+ Iir_Index32 (Get_Width (R) + 1)));
end;
when Iir_Predefined_Integer_Plus =>
if Is_Const (Left) and then Is_Const (Right) then
- return Create_Value_Lit
- (Create_I64_Value (Left.Lit.I64 + Right.Lit.I64),
- Get_Type (Expr));
+ return Create_Value_Discrete (Left.Scal + Right.Scal);
else
-- TODO: non-const.
raise Internal_Error;
end if;
when Iir_Predefined_Integer_Minus =>
if Is_Const (Left) and then Is_Const (Right) then
- return Create_Value_Lit
- (Create_I64_Value (Left.Lit.I64 - Right.Lit.I64),
- Get_Type (Expr));
+ return Create_Value_Discrete (Left.Scal - Right.Scal);
else
-- TODO: non-const.
raise Internal_Error;
@@ -618,24 +783,31 @@ package body Synth.Expr is
end case;
end Synth_Dyadic_Operation;
- function Synth_Monadic_Operation (Def : Iir_Predefined_Functions;
- Operand : Value_Acc;
+ function Synth_Monadic_Operation (Syn_Inst : Synth_Instance_Acc;
+ Def : Iir_Predefined_Functions;
+ Operand_Expr : Node;
Loc : Node) return Value_Acc
is
+ Operand : Value_Acc;
+
function Synth_Bit_Monadic (Id : Monadic_Module_Id) return Value_Acc is
begin
return Create_Value_Net
- (Build_Monadic (Build_Context, Id, Get_Net (Operand)),
- No_Range);
+ (Build_Monadic (Build_Context, Id,
+ Get_Net (Operand, Get_Type (Operand_Expr))),
+ No_Bound);
end Synth_Bit_Monadic;
- function Synth_Vec_Monadic (Id : Monadic_Module_Id) return Value_Acc is
- Op: constant Net := Get_Net (Operand);
+
+ function Synth_Vec_Monadic (Id : Monadic_Module_Id) return Value_Acc
+ is
+ Op: constant Net := Get_Net (Operand, Get_Type (Operand_Expr));
begin
return Create_Value_Net
(Build_Monadic (Build_Context, Id, Op),
- Create_Res_Range (Operand, Op));
+ Create_Res_Bound (Operand, Op));
end Synth_Vec_Monadic;
begin
+ Operand := Synth_Expression (Syn_Inst, Operand_Expr);
case Def is
when Iir_Predefined_Error =>
return null;
@@ -662,27 +834,25 @@ package body Synth.Expr is
return Synth_Name (Syn_Inst, Get_Named_Entity (Name));
when Iir_Kind_Interface_Signal_Declaration
| Iir_Kind_Variable_Declaration
- | Iir_Kind_Signal_Declaration =>
+ | Iir_Kind_Signal_Declaration
+ | Iir_Kind_Constant_Declaration =>
return Get_Value (Syn_Inst, Name);
- when Iir_Kind_Constant_Declaration
- | Iir_Kind_Enumeration_Literal =>
- return Create_Value_Lit
- (Simul.Execution.Execute_Expression (Syn_Inst.Sim, Name),
- Get_Type (Name));
+ when Iir_Kind_Enumeration_Literal =>
+ return Create_Value_Discrete (Int64 (Get_Enum_Pos (Name)));
when others =>
Error_Kind ("synth_name", Name);
end case;
end Synth_Name;
- function In_Range (Rng : Value_Range_Acc; V : Int32) return Boolean is
+ function In_Bounds (Bnd : Value_Bound_Acc; V : Int32) return Boolean is
begin
- case Rng.Dir is
+ case Bnd.Dir is
when Iir_To =>
- return V >= Rng.Left and then V <= Rng.Right;
+ return V >= Bnd.Left and then V <= Bnd.Right;
when Iir_Downto =>
- return V <= Rng.Left and then V >= Rng.Right;
+ return V <= Bnd.Left and then V >= Bnd.Right;
end case;
- end In_Range;
+ end In_Bounds;
function Synth_Indexed_Name (Syn_Inst : Synth_Instance_Acc; Name : Node)
return Value_Acc
@@ -692,24 +862,21 @@ package body Synth.Expr is
Indexes : constant Iir_Flist := Get_Index_List (Name);
Idx_Val : constant Value_Acc :=
Synth_Expression (Syn_Inst, Get_Nth_Element (Indexes, 0));
- Rng : Value_Range_Acc;
- Idx : Int32;
+ Rng : Value_Bound_Acc;
+ Off : Int32;
begin
if Get_Nbr_Elements (Indexes) /= 1 then
Error_Msg_Synth (+Name, "multi-dim arrays not supported");
return null;
end if;
- if Idx_Val.Kind /= Value_Lit
- or else Idx_Val.Lit.Kind /= Iir_Value_I64
- then
+ if Idx_Val.Kind /= Value_Discrete then
Error_Msg_Synth (+Name, "non constant integer index not supported");
return null;
end if;
- Rng := Extract_Range (Pfx);
- Idx := Int32 (Idx_Val.Lit.I64);
- if not In_Range (Rng, Idx) then
+ Rng := Extract_Bound (Pfx);
+ if not In_Bounds (Rng, Int32 (Idx_Val.Scal)) then
Error_Msg_Synth (+Name, "index not within bounds");
return null;
end if;
@@ -717,10 +884,11 @@ package body Synth.Expr is
-- The offset is from the LSB (bit 0). Bit 0 is the rightmost one.
case Rng.Dir is
when Iir_To =>
- return Bit_Extract (Pfx, Uns32 (Rng.Right - Idx));
+ Off := Rng.Right - Int32 (Idx_Val.Scal);
when Iir_Downto =>
- return Bit_Extract (Pfx, Uns32 (Idx - Rng.Right));
+ Off := Int32 (Idx_Val.Scal) - Rng.Right;
end case;
+ return Bit_Extract (Pfx, Uns32 (Off));
end Synth_Indexed_Name;
function Synth_Slice_Name (Syn_Inst : Synth_Instance_Acc; Name : Node)
@@ -729,10 +897,10 @@ package body Synth.Expr is
Pfx : constant Value_Acc :=
Synth_Expression (Syn_Inst, Get_Prefix (Name));
Expr : constant Node := Get_Suffix (Name);
- Res_Rng : Value_Range_Acc;
+ Res_Bnd : Value_Bound_Acc;
Left, Right : Value_Acc;
Dir : Iir_Direction;
- Rng : Value_Range_Acc;
+ Bnd : Value_Bound_Acc;
begin
case Get_Kind (Expr) is
when Iir_Kind_Range_Expression =>
@@ -743,50 +911,48 @@ package body Synth.Expr is
Error_Msg_Synth (+Expr, "only range supported for slices");
end case;
- if Left.Kind /= Value_Lit
- or else Left.Lit.Kind /= Iir_Value_I64
- then
+ if Left.Kind /= Value_Discrete then
Error_Msg_Synth (+Name, "non constant integer left not supported");
return null;
end if;
- if Right.Kind /= Value_Lit
- or else Right.Lit.Kind /= Iir_Value_I64
- then
+ if Right.Kind /= Value_Discrete then
Error_Msg_Synth (+Name, "non constant integer right not supported");
return null;
end if;
- Rng := Extract_Range (Pfx);
- if Rng.Dir /= Dir then
+ Bnd := Extract_Bound (Pfx);
+ if Bnd.Dir /= Dir then
Error_Msg_Synth (+Name, "direction mismatch in slice");
return null;
end if;
- if not In_Range (Rng, Int32 (Left.Lit.I64))
- or else not In_Range (Rng, Int32 (Right.Lit.I64))
+ if not In_Bounds (Bnd, Int32 (Left.Scal))
+ or else not In_Bounds (Bnd, Int32 (Right.Scal))
then
Error_Msg_Synth (+Name, "index not within bounds");
return null;
end if;
- case Rng.Dir is
+ case Bnd.Dir is
when Iir_To =>
- Res_Rng := Create_Range_Value
- (Value_Range'(Dir => Iir_To,
- Len => Width (Right.Lit.I64 - Left.Lit.I64 + 1),
- Left => Int32 (Left.Lit.I64),
- Right => Int32 (Right.Lit.I64)));
+ Res_Bnd := Create_Value_Bound
+ (Value_Bound_Type'
+ (Dir => Iir_To,
+ Len => Width (Right.Scal - Left.Scal + 1),
+ Left => Int32 (Left.Scal),
+ Right => Int32 (Right.Scal)));
return Vec_Extract
- (Pfx, Uns32 (Rng.Right - Res_Rng.Right), Res_Rng);
+ (Pfx, Uns32 (Bnd.Right - Res_Bnd.Right), Res_Bnd);
when Iir_Downto =>
- Res_Rng := Create_Range_Value
- (Value_Range'(Dir => Iir_Downto,
- Len => Width (Left.Lit.I64 - Right.Lit.I64 + 1),
- Left => Int32 (Left.Lit.I64),
- Right => Int32 (Right.Lit.I64)));
+ Res_Bnd := Create_Value_Bound
+ (Value_Bound_Type'
+ (Dir => Iir_Downto,
+ Len => Width (Left.Scal - Right.Scal + 1),
+ Left => Int32 (Left.Scal),
+ Right => Int32 (Right.Scal)));
return Vec_Extract
- (Pfx, Uns32 (Res_Rng.Right - Rng.Right), Res_Rng);
+ (Pfx, Uns32 (Res_Bnd.Right - Bnd.Right), Res_Bnd);
end case;
end Synth_Slice_Name;
@@ -824,7 +990,7 @@ package body Synth.Expr is
Lit : Node;
Posedge : Boolean;
begin
- Clk := Get_Net (Synth_Name (Syn_Inst, Prefix));
+ Clk := Get_Net (Synth_Name (Syn_Inst, Prefix), Get_Type (Prefix));
if Get_Kind (Expr) /= Iir_Kind_Equality_Operator then
Error_Msg_Synth (+Expr, "ill-formed clock-level, '=' expected");
return Build_Edge (Build_Context, Clk);
@@ -880,14 +1046,14 @@ package body Synth.Expr is
Prefix := Extract_Event_Expr_Prefix (Left);
if Is_Valid (Prefix) then
return Create_Value_Net
- (Extract_Clock_Level (Syn_Inst, Right, Prefix), No_Range);
+ (Extract_Clock_Level (Syn_Inst, Right, Prefix), No_Bound);
end if;
-- Try with right.
Prefix := Extract_Event_Expr_Prefix (Right);
if Is_Valid (Prefix) then
return Create_Value_Net
- (Extract_Clock_Level (Syn_Inst, Left, Prefix), No_Range);
+ (Extract_Clock_Level (Syn_Inst, Left, Prefix), No_Bound);
end if;
return null;
@@ -933,6 +1099,32 @@ package body Synth.Expr is
end if;
end Error_Unknown_Operator;
+ function Synth_String_Literal (Syn_Inst : Synth_Instance_Acc; Str : Node)
+ return Value_Acc
+ is
+ pragma Assert (Get_Kind (Str) = Iir_Kind_String_Literal8);
+ Id : constant String8_Id := Get_String8_Id (Str);
+
+ Str_Type : constant Node := Get_Type (Str);
+ Bounds : Value_Bound_Acc;
+ Barr : Value_Bound_Array_Acc;
+ Res : Value_Acc;
+ Pos : Nat8;
+ begin
+ Bounds := Synth_Array_Bounds (Syn_Inst, Str_Type, 0);
+ Barr := Create_Value_Bound_Array (1);
+ Barr.D (1) := Bounds;
+ Res := Create_Value_Array (Barr);
+
+ for I in Res.Arr.V'Range loop
+ -- FIXME: use literal from type ??
+ Pos := Str_Table.Element_String8 (Id, Pos32 (I));
+ Res.Arr.V (I) := Create_Value_Discrete (Int64 (Pos));
+ end loop;
+
+ return Res;
+ end Synth_String_Literal;
+
function Synth_Expression_With_Type
(Syn_Inst : Synth_Instance_Acc; Expr : Node; Expr_Type : Node)
return Value_Acc is
@@ -943,28 +1135,25 @@ package body Synth.Expr is
Imp : constant Node := Get_Implementation (Expr);
Def : constant Iir_Predefined_Functions :=
Get_Implicit_Definition (Imp);
- Left : Value_Acc;
- Right : Value_Acc;
+ Edge : Value_Acc;
begin
-- Match clock-edge
if Def = Iir_Predefined_Boolean_And then
- Left := Synth_Clock_Edge (Syn_Inst, Expr);
- if Left /= null then
- return Left;
+ Edge := Synth_Clock_Edge (Syn_Inst, Expr);
+ if Edge /= null then
+ return Edge;
end if;
end if;
-- FIXME: short-circuit operators ?
- Left := Synth_Expression (Syn_Inst, Get_Left (Expr));
- Right := Synth_Expression (Syn_Inst, Get_Right (Expr));
if Def in Iir_Predefined_Implicit
or else Def in Iir_Predefined_IEEE_Explicit
then
- return Synth_Dyadic_Operation (Syn_Inst, Def,
- Left, Right, Expr);
+ return Synth_Dyadic_Operation
+ (Syn_Inst, Def, Get_Left (Expr), Get_Right (Expr), Expr);
else
Error_Unknown_Operator (Imp, Expr);
- return Left;
+ raise Internal_Error;
end if;
end;
when Iir_Kinds_Monadic_Operator =>
@@ -972,16 +1161,15 @@ package body Synth.Expr is
Imp : constant Node := Get_Implementation (Expr);
Def : constant Iir_Predefined_Functions :=
Get_Implicit_Definition (Imp);
- Operand : Value_Acc;
begin
- Operand := Synth_Expression (Syn_Inst, Get_Operand (Expr));
if Def in Iir_Predefined_Implicit
or else Def in Iir_Predefined_IEEE_Explicit
then
- return Synth_Monadic_Operation (Def, Operand, Expr);
+ return Synth_Monadic_Operation
+ (Syn_Inst, Def, Get_Operand (Expr), Expr);
else
Error_Unknown_Operator (Imp, Expr);
- return Operand;
+ raise Internal_Error;
end if;
end;
when Iir_Kind_Simple_Name =>
@@ -990,13 +1178,19 @@ package body Synth.Expr is
return Synth_Indexed_Name (Syn_Inst, Expr);
when Iir_Kind_Slice_Name =>
return Synth_Slice_Name (Syn_Inst, Expr);
- when Iir_Kind_Character_Literal
- | Iir_Kind_Integer_Literal
- | Iir_Kind_String_Literal8
- | Iir_Kind_Enumeration_Literal =>
- return Create_Value_Lit
- (Simul.Execution.Execute_Expression (Syn_Inst.Sim, Expr),
- Get_Base_Type (Get_Type (Expr)));
+ when Iir_Kind_Character_Literal =>
+ return Synth_Expression_With_Type
+ (Syn_Inst, Get_Named_Entity (Expr), Expr_Type);
+ when Iir_Kind_Integer_Literal =>
+ return Create_Value_Discrete (Get_Value (Expr));
+ when Iir_Kind_Floating_Point_Literal =>
+ return Create_Value_Float (Get_Fp_Value (Expr));
+ when Iir_Kind_Physical_Int_Literal =>
+ return Create_Value_Discrete (Get_Physical_Value (Expr));
+ when Iir_Kind_String_Literal8 =>
+ return Synth_String_Literal (Syn_Inst, Expr);
+ when Iir_Kind_Enumeration_Literal =>
+ return Synth_Name (Syn_Inst, Expr);
when Iir_Kind_Type_Conversion =>
return Synth_Type_Conversion (Syn_Inst, Expr);
when Iir_Kind_Qualified_Expression =>
@@ -1011,16 +1205,18 @@ package body Synth.Expr is
if Imp = Vhdl.Ieee.Std_Logic_1164.Rising_Edge then
Clk := Get_Net
(Synth_Assoc_In
- (Syn_Inst, Get_Parameter_Association_Chain (Expr)));
+ (Syn_Inst, Get_Parameter_Association_Chain (Expr)),
+ Vhdl.Ieee.Std_Logic_1164.Std_Ulogic_Type);
Edge := Build_Edge (Build_Context, Clk);
- return Create_Value_Net (Edge, No_Range);
+ return Create_Value_Net (Edge, No_Bound);
elsif Imp = Vhdl.Ieee.Std_Logic_1164.Falling_Edge then
Clk := Get_Net
(Synth_Assoc_In
- (Syn_Inst, Get_Parameter_Association_Chain (Expr)));
+ (Syn_Inst, Get_Parameter_Association_Chain (Expr)),
+ Vhdl.Ieee.Std_Logic_1164.Std_Ulogic_Type);
Clk := Build_Monadic (Build_Context, Id_Not, Clk);
Edge := Build_Edge (Build_Context, Clk);
- return Create_Value_Net (Edge, No_Range);
+ return Create_Value_Net (Edge, No_Bound);
end if;
Error_Msg_Synth
(+Expr, "user function call to %i is not handled", +Imp);