aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2023-01-06 21:05:13 +0100
committerTristan Gingold <tgingold@free.fr>2023-01-06 21:05:13 +0100
commit8c8d9a8bf91d22d4cb7c350a016e0cdcfdae2ef9 (patch)
tree69fe1c4e5f9d5a16da49fa6dbc813379f97d2823
parenta0cc0a8059b97339c158a87937461676fcb87dae (diff)
downloadghdl-8c8d9a8bf91d22d4cb7c350a016e0cdcfdae2ef9.tar.gz
ghdl-8c8d9a8bf91d22d4cb7c350a016e0cdcfdae2ef9.tar.bz2
ghdl-8c8d9a8bf91d22d4cb7c350a016e0cdcfdae2ef9.zip
synth: handle value attribute for physical types
-rw-r--r--src/grt/grt-values.adb25
-rw-r--r--src/grt/grt-values.ads3
-rw-r--r--src/synth/elab-vhdl_expr.adb73
3 files changed, 89 insertions, 12 deletions
diff --git a/src/grt/grt-values.adb b/src/grt/grt-values.adb
index 7a2f09ed5..b2e98f6a0 100644
--- a/src/grt/grt-values.adb
+++ b/src/grt/grt-values.adb
@@ -234,38 +234,40 @@ package body Grt.Values is
return Value_F64 (S, Len, Pos);
end Ghdl_Value_F64;
- procedure Ghdl_Value_Physical_Split (Str : Std_String_Ptr;
+ procedure Ghdl_Value_Physical_Split (Str : Std_String_Basep;
+ Len : Ghdl_Index_Type;
Is_Real : out Boolean;
Lit_Pos : out Ghdl_Index_Type;
Lit_End : out Ghdl_Index_Type;
Unit_Pos : out Ghdl_Index_Type)
is
- S : constant Std_String_Basep := Str.Base;
- Len : Ghdl_Index_Type := Str.Bounds.Dim_1.Length;
+ L : Ghdl_Index_Type;
begin
-- LRM 14.1
-- Leading and trailing whitespace is allowed and ignored.
Lit_Pos := 0;
- Remove_Whitespaces (S, Len, Lit_Pos);
+ L := Len;
+ Remove_Whitespaces (Str, L, Lit_Pos);
+ pragma Unreferenced (Len);
-- Split between abstract literal (optionnal) and unit name.
Lit_End := Lit_Pos;
Is_Real := False;
- while Lit_End < Len loop
- exit when Is_Whitespace (S (Lit_End));
- if S (Lit_End) = '.' then
+ while Lit_End < L loop
+ exit when Is_Whitespace (Str (Lit_End));
+ if Str (Lit_End) = '.' then
Is_Real := True;
end if;
Lit_End := Lit_End + 1;
end loop;
- if Lit_End = Len then
+ if Lit_End = L then
-- No literal
Unit_Pos := Lit_Pos;
Lit_End := 0;
else
Unit_Pos := Lit_End + 1;
- while Unit_Pos < Len loop
- exit when not Is_Whitespace (S (Unit_Pos));
+ while Unit_Pos < L loop
+ exit when not Is_Whitespace (Str (Unit_Pos));
Unit_Pos := Unit_Pos + 1;
end loop;
end if;
@@ -294,7 +296,8 @@ package body Grt.Values is
Remove_Whitespaces (S, Len, Lit_Pos);
-- Extract literal and unit
- Ghdl_Value_Physical_Split (Str, Found_Real, Lit_Pos, Lit_End, Unit_Pos);
+ Ghdl_Value_Physical_Split
+ (S, Len, Found_Real, Lit_Pos, Lit_End, Unit_Pos);
-- Find unit value
Multiple := null;
diff --git a/src/grt/grt-values.ads b/src/grt/grt-values.ads
index 369c69cfd..8a81d1fbd 100644
--- a/src/grt/grt-values.ads
+++ b/src/grt/grt-values.ads
@@ -31,7 +31,8 @@ package Grt.Values is
-- Set LIT_POS to the position of the first character of the numeric
-- literal (after whitespaces are skipped).
-- Set LIT_END to the position of the next character of the numeric lit.
- procedure Ghdl_Value_Physical_Split (Str : Std_String_Ptr;
+ procedure Ghdl_Value_Physical_Split (Str : Std_String_Basep;
+ Len : Ghdl_Index_Type;
Is_Real : out Boolean;
Lit_Pos : out Ghdl_Index_Type;
Lit_End : out Ghdl_Index_Type;
diff --git a/src/synth/elab-vhdl_expr.adb b/src/synth/elab-vhdl_expr.adb
index 1119f6ae9..c32601ef1 100644
--- a/src/synth/elab-vhdl_expr.adb
+++ b/src/synth/elab-vhdl_expr.adb
@@ -38,7 +38,9 @@ with Synth.Errors; use Synth.Errors;
with Grt.Types;
with Grt.Vhdl_Types;
+with Grt.Strings;
with Grt.To_Strings;
+with Grt.Values;
with Grt.Vstrings;
package body Elab.Vhdl_Expr is
@@ -99,6 +101,24 @@ package body Elab.Vhdl_Expr is
return Synth_Subtype_Conversion (null, Vt, Dtype, Bounds, Loc);
end Exec_Subtype_Conversion;
+ -- Return True iff ID = S, case insensitive.
+ function Match_Id (Id : Name_Id; S : String) return Boolean is
+ begin
+ if Name_Table.Get_Name_Length (Id) /= S'Length then
+ return False;
+ end if;
+ declare
+ Img : constant String (S'Range) := Name_Table.Image (Id);
+ begin
+ for I in Img'Range loop
+ if Grt.Strings.To_Lower (S (I)) /= Img (I) then
+ return False;
+ end if;
+ end loop;
+ return True;
+ end;
+ end Match_Id;
+
function Exec_Value_Attribute (Syn_Inst : Synth_Instance_Acc; Attr : Node)
return Valtyp
is
@@ -163,6 +183,59 @@ package body Elab.Vhdl_Expr is
return No_Valtyp;
end if;
end;
+ when Iir_Kind_Physical_Type_Definition =>
+ declare
+ use Grt.Types;
+ use Grt.Vhdl_Types;
+ Value1 : String renames Value (First .. Last);
+ F : constant Ghdl_Index_Type := Ghdl_Index_Type (First);
+ S : constant Std_String_Basep :=
+ To_Std_String_Basep (Value1'Address);
+ Len : constant Ghdl_Index_Type :=
+ Ghdl_Index_Type (Last - First + 1);
+ Is_Real : Boolean;
+ Lit_Pos : Ghdl_Index_Type;
+ Lit_End : Ghdl_Index_Type;
+ Unit_Pos : Ghdl_Index_Type;
+ Unit_F, Unit_L : Positive;
+ Mult : Int64;
+ Unit : Iir;
+ Unit_Id : Name_Id;
+ Val_F : Grt.To_Strings.Value_F64_Result;
+ begin
+ Grt.Values.Ghdl_Value_Physical_Split
+ (S, Len, Is_Real, Lit_Pos, Lit_End, Unit_Pos);
+ Unit_F := Positive (Unit_Pos + 1);
+
+ -- Find unit.
+ Unit_L := Unit_F;
+ for I in Unit_F .. Last loop
+ exit when Grt.Strings.Is_Whitespace (Value1 (I));
+ Unit_L := I;
+ end loop;
+
+ Unit := Get_Primary_Unit (Btype);
+ while Unit /= Null_Iir loop
+ Unit_Id := Get_Identifier (Unit);
+ exit when Match_Id (Unit_Id, Value1 (Unit_F .. Unit_L));
+ Unit := Get_Chain (Unit);
+ end loop;
+
+ if Unit = Null_Iir then
+ Error_Msg_Synth (Syn_Inst, Attr, "incorrect unit name");
+ return No_Valtyp;
+ end if;
+ Mult := Get_Value (Get_Physical_Literal (Unit));
+
+ if Is_Real then
+ Val_F := Grt.To_Strings.Value_F64 (S, Lit_End, F);
+ Val := Int64 (Val_F.Val * Ghdl_F64 (Mult));
+ else
+ Val := Int64 (Grt.Values.Value_I64 (S, Lit_End, F))
+ * Mult;
+ end if;
+ end;
+
when others =>
Error_Msg_Elab (+Attr, "unhandled type for 'value");
return No_Valtyp;