From f33ab7adaf25c78fa88beac25df4f0d596b9d94c Mon Sep 17 00:00:00 2001
From: Tristan Gingold <tgingold@free.fr>
Date: Wed, 30 Jun 2021 06:58:25 +0200
Subject: vhdl: handle mod/rem for physical.  Fix #1810

---
 src/vhdl/translate/trans-chap7.adb | 6 +++++-
 src/vhdl/vhdl-evaluation.adb       | 7 +++++++
 src/vhdl/vhdl-nodes.ads            | 2 ++
 src/vhdl/vhdl-sem_utils.adb        | 9 +++++++++
 4 files changed, 23 insertions(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/vhdl/translate/trans-chap7.adb b/src/vhdl/translate/trans-chap7.adb
index 618ca996d..07c28ac33 100644
--- a/src/vhdl/translate/trans-chap7.adb
+++ b/src/vhdl/translate/trans-chap7.adb
@@ -1095,6 +1095,8 @@ package body Trans.Chap7 is
       Iir_Predefined_Physical_Absolute => ON_Abs_Ov,
       Iir_Predefined_Physical_Minus => ON_Sub_Ov,
       Iir_Predefined_Physical_Plus => ON_Add_Ov,
+      Iir_Predefined_Physical_Rem => ON_Rem_Ov,
+      Iir_Predefined_Physical_Mod => ON_Mod_Ov,
 
       Iir_Predefined_Floating_Greater => ON_Gt,
       Iir_Predefined_Floating_Greater_Equal => ON_Ge,
@@ -6134,7 +6136,9 @@ package body Trans.Chap7 is
             | Iir_Predefined_Physical_Negation
             | Iir_Predefined_Physical_Absolute
             | Iir_Predefined_Physical_Plus
-            | Iir_Predefined_Physical_Minus =>
+            | Iir_Predefined_Physical_Minus
+            | Iir_Predefined_Physical_Mod
+            | Iir_Predefined_Physical_Rem =>
             pragma Assert (Predefined_To_Onop (Kind) /= ON_Nil);
             return;
 
diff --git a/src/vhdl/vhdl-evaluation.adb b/src/vhdl/vhdl-evaluation.adb
index 0486b8808..c0f666c6f 100644
--- a/src/vhdl/vhdl-evaluation.adb
+++ b/src/vhdl/vhdl-evaluation.adb
@@ -1826,6 +1826,13 @@ package body Vhdl.Evaluation is
               (Int64 (Fp64 (Get_Physical_Value (Left))
                           / Get_Fp_Value (Right)), Orig);
 
+         when Iir_Predefined_Physical_Mod =>
+            return Build_Physical
+              (Get_Physical_Value (Left) mod Get_Value (Right), Orig);
+         when Iir_Predefined_Physical_Rem =>
+            return Build_Physical
+              (Get_Physical_Value (Left) rem Get_Value (Right), Orig);
+
          when Iir_Predefined_Physical_Minimum =>
             return Build_Physical (Int64'Min (Get_Physical_Value (Left),
                                                   Get_Physical_Value (Right)),
diff --git a/src/vhdl/vhdl-nodes.ads b/src/vhdl/vhdl-nodes.ads
index aaf640389..017e58929 100644
--- a/src/vhdl/vhdl-nodes.ads
+++ b/src/vhdl/vhdl-nodes.ads
@@ -5424,6 +5424,8 @@ package Vhdl.Nodes is
       Iir_Predefined_Physical_Integer_Div,
       Iir_Predefined_Physical_Real_Div,
       Iir_Predefined_Physical_Physical_Div,
+      Iir_Predefined_Physical_Mod,
+      Iir_Predefined_Physical_Rem,
 
       --  LRM08 5.2.6 Predefined operations on scalar types.
       Iir_Predefined_Physical_Minimum,
diff --git a/src/vhdl/vhdl-sem_utils.adb b/src/vhdl/vhdl-sem_utils.adb
index b33d5682a..bb258aaf6 100644
--- a/src/vhdl/vhdl-sem_utils.adb
+++ b/src/vhdl/vhdl-sem_utils.adb
@@ -899,6 +899,7 @@ package body Vhdl.Sem_Utils is
             Add_Unary (Name_Op_Minus, Iir_Predefined_Physical_Negation);
             Add_Unary (Name_Op_Plus, Iir_Predefined_Physical_Identity);
 
+            --  Physical OP integer, with OP is multiplication and division.
             declare
                Inter_Chain : Iir;
             begin
@@ -912,6 +913,7 @@ package body Vhdl.Sem_Utils is
                               Inter_Chain, Type_Definition);
             end;
 
+            --  Integer * physical
             declare
                Inter_Chain : Iir;
             begin
@@ -922,6 +924,7 @@ package body Vhdl.Sem_Utils is
                               Inter_Chain, Type_Definition);
             end;
 
+            --  Physical OP real, wher OP is multiplication and division.
             declare
                Inter_Chain : Iir;
             begin
@@ -934,6 +937,7 @@ package body Vhdl.Sem_Utils is
                               Inter_Chain, Type_Definition);
             end;
 
+            --  Real * physical
             declare
                Inter_Chain : Iir;
             begin
@@ -943,6 +947,8 @@ package body Vhdl.Sem_Utils is
                Add_Operation (Name_Op_Mul, Iir_Predefined_Real_Physical_Mul,
                               Inter_Chain, Type_Definition);
             end;
+
+            --  Physical / physical -> integer.
             Add_Operation (Name_Op_Div, Iir_Predefined_Physical_Physical_Div,
                            Binary_Chain,
                            Std_Package.Convertible_Integer_Type_Definition);
@@ -950,6 +956,9 @@ package body Vhdl.Sem_Utils is
             Add_Unary (Name_Abs, Iir_Predefined_Physical_Absolute);
 
             if Vhdl_Std >= Vhdl_08 then
+               Add_Binary (Name_Mod, Iir_Predefined_Physical_Mod);
+               Add_Binary (Name_Rem, Iir_Predefined_Physical_Rem);
+
                --  LRM08 5.2.6 Predefined operations on scalar types
                --  Given a type declaration that declares a scalar type T, the
                --  following operations are implicitely declared immediately
-- 
cgit v1.2.3