From 9cec02a48c94505246ad829692817035c0b422f7 Mon Sep 17 00:00:00 2001
From: Tristan Gingold <tgingold@free.fr>
Date: Wed, 3 Jun 2015 03:39:39 +0200
Subject: Reimplementation of std_logic_1164.

---
 libraries/redist1164/build.py                  | 361 ++++++++++++
 libraries/redist1164/std_logic_1164-body.proto | 123 ++++
 libraries/redist1164/std_logic_1164-body.vhdl  | 768 +++++++++++++++++++++++++
 libraries/redist1164/std_logic_1164.vhdl       | 143 +++++
 4 files changed, 1395 insertions(+)
 create mode 100644 libraries/redist1164/build.py
 create mode 100644 libraries/redist1164/std_logic_1164-body.proto
 create mode 100644 libraries/redist1164/std_logic_1164-body.vhdl
 create mode 100644 libraries/redist1164/std_logic_1164.vhdl

diff --git a/libraries/redist1164/build.py b/libraries/redist1164/build.py
new file mode 100644
index 000000000..6255938d8
--- /dev/null
+++ b/libraries/redist1164/build.py
@@ -0,0 +1,361 @@
+#!/usr/bin/env python
+#  Generate the body of ieee.std_logic_1164 from a template.
+#  This file is part of GHDL.
+#  Copyright (C) 2015 Tristan Gingold
+#
+#  GHDL is free software; you can redistribute it and/or modify it under
+#  the terms of the GNU General Public License as published by the Free
+#  Software Foundation; either version 2, or (at your option) any later
+#  version.
+#
+#  GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+#  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+#  for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with GCC; see the file COPYING3.  If not see
+#  <http://www.gnu.org/licenses/>.
+
+import re
+import sys
+
+binary_funcs = [ "and", "nand", "or", "nor", "xor" ]
+
+# Python modelisation of std_ulogic type.
+std_logic = "UX01ZWLH-"
+
+# Normalization map.
+ux01_map = { 'U': 'U',
+             'X': 'X', 'Z': 'X', 'W': 'X', '-': 'X',
+             '0': '0', 'L': '0',
+             '1': '1', 'H': '1' }
+
+def sl_and(a,b):
+    """and definition"""
+    na = ux01_map[a]
+    nb = ux01_map[b]
+    if na == '0' or nb == '0':
+        return '0'
+    if na == 'U' or nb == 'U':
+        return 'U'
+    if na == 'X' or nb == 'X':
+        return 'X'
+    return '1'
+
+def sl_not(a):
+    """not definition"""
+    na = ux01_map[a]
+    if na == 'U':
+        return 'U'
+    if na == 'X':
+        return 'X'
+    if na == '1':
+        return '0'
+    else:
+        return '1'
+
+def sl_or(a,b):
+    "or definition"
+    return sl_not(sl_and (sl_not(a), sl_not(b)))
+
+def sl_xor(a,b):
+    "xor definition"
+    return sl_or(sl_and(a, sl_not(b)),
+                 sl_and(sl_not(a), b))
+
+# Stream to write.
+out=sys.stdout
+
+def w(s):
+    "Write S to the output"
+    out.write(s)
+
+def gen_log_table2(name, func):
+    "Generate a logic table for binary operator NAME using its model FUNC"
+    w("""
+  constant {0}_table : table_2d :=
+  --  UX01ZWLH-
+    (""".format(name))
+    for a in std_logic:
+        w('"')
+        for b in std_logic:
+            w(func (a, b))
+        w('"')
+        if a != '-':
+            w(',')
+        else:
+            w(' ')
+        w('   -- {}\n'.format(a))
+        w('     ')
+    w(');\n')
+
+def gen_log_table1(name, func):
+    "Generate a logic table for unary operator NAME using its model FUNC"
+    w("""
+  constant {0}_table : table_1d :=
+  --  UX01ZWLH-
+     """.format(name))
+    w('"')
+    for b in std_logic:
+        w(func (b))
+    w('";\n')
+
+def disp_tables():
+    "Generate logic tables"
+    gen_log_table2("and", sl_and)
+    gen_log_table2("nand", lambda a,b : sl_not(sl_and(a, b)))
+    gen_log_table2("or", sl_or)
+    gen_log_table2("nor", lambda a,b : sl_not(sl_or(a,b)))
+    gen_log_table2("xor", sl_xor)
+    if "xnor" in binary_funcs:
+        gen_log_table2("xnor", lambda a,b : sl_not(sl_xor(a,b)))
+    gen_log_table1("not", sl_not)
+
+vec_types = ['ulogic', 'logic']
+
+def disp_scalar_binary(fun):
+    "Generate scalar binary function body"
+    w("""
+  function "{0}" (l, r : std_ulogic) return UX01 is
+  begin
+    return {0}_table (l, r);
+  end "{0}";\n""".format(fun))
+
+def disp_scalar_unary(fun):
+    "Generate scalar unary function body"
+    w("""
+  function "{0}" (l : std_ulogic) return UX01 is
+  begin
+    return {0}_table (l);
+  end "{0}";\n""".format(fun))
+
+def disp_vec_binary(func, typ):
+    "Generate vector binary function body"
+    w("""
+  function "{0}" (l, r : std_{1}_vector) return std_{1}_vector
+  is
+    subtype res_type is std_{1}_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_{1}_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded '{0}' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := {0}_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "{0}";\n""".format(func, typ))
+
+def disp_vec_unary(func, typ):
+    "Generate vector unary function body"
+    w("""
+  function "{0}" (l : std_{1}_vector) return std_{1}_vector
+  is
+    subtype res_type is std_{1}_vector (1 to l'length);
+    alias la : res_type is l;
+    variable res : res_type;
+  begin
+    for I in res_type'range loop
+      res (I) := {0}_table (la (I));
+    end loop;
+    return res;
+  end "{0}";\n""".format(func, typ))
+
+def disp_all_log_funcs():
+    "Generate all function bodies for logic operators"
+    for f in binary_funcs:
+        disp_scalar_binary(f)
+    disp_scalar_unary("not")
+    for v in vec_types:
+        typ = "std_" + v + "_vector"
+        for f in binary_funcs:
+            disp_vec_binary(f, v)
+        disp_vec_unary("not", v)
+
+def disp_sv_to_bv_conv(typ):
+    "Generate logic vector to bit vector function body"
+    w("""
+  function to_bitvector (s : std_{0}_vector; xmap : bit := '0')
+    return bit_vector
+  is
+    subtype res_range is natural range s'length - 1 downto 0;
+    alias as : std_{0}_vector (res_range) is s;
+    variable res : bit_vector (res_range);
+    variable b : bit;
+  begin
+    for I in res_range loop
+      --  Inline for efficiency.
+      case as (I) is
+        when '0' | 'L' =>
+          b := '0';
+        when '1' | 'H' =>
+          b := '1';
+        when others =>
+          b := xmap;
+      end case;
+      res (I) := b;
+    end loop;
+    return res;
+  end to_bitvector;\n""".format(typ))
+
+def disp_bv_to_sv_conv(typ):
+    "Generate bit vector to logic vector function body"
+    w("""
+  function to_std{0}vector (b : bit_vector) return std_{0}_vector is
+    subtype res_range is natural range b'length - 1 downto 0;
+    alias ab : bit_vector (res_range) is b;
+    variable res : std_{0}_vector (res_range);
+  begin
+    for I in res_range loop
+      res (I) := bit_to_std (ab (I));
+    end loop;
+    return res;
+  end to_std{0}vector;\n""".format(typ))
+
+def disp_sv_to_sv_conv(s,d):
+    "Generate logic vector to logic vector function body"
+    w("""
+  function to_std{1}vector (b : std_{0}_vector) return std_{1}_vector
+  is
+    subtype res_type is std_{1}_vector (b'length - 1 downto 0);
+  begin
+    return res_type (b);
+  end to_std{1}vector;\n""".format(s,d))
+
+def disp_all_conv_funcs():
+    "Generate conversion function bodies"
+    for v in vec_types:
+        disp_sv_to_bv_conv(v)
+    for v in vec_types:
+        disp_bv_to_sv_conv(v)
+    disp_sv_to_sv_conv('logic', 'ulogic')
+    disp_sv_to_sv_conv('ulogic', 'logic')
+
+def disp_conv_vec_vec(typ, v):
+    "Generate function body for vector conversion"
+    utyp = typ.upper();
+    w("""
+  function to_{1} (s : std_{2}_vector) return std_{2}_vector
+  is
+    subtype res_type is std_{2}_vector (1 to s'length);
+    alias sa : res_type is s;
+    variable res : res_type;
+  begin
+    for i in res_type'range loop
+      res (i) := std_to_{0} (sa (i));
+    end loop;
+    return res;
+  end to_{1};\n""".format(typ, utyp, v))
+
+def disp_conv_std(typ):
+    "Generate function body for scalar conversion"
+    utyp = typ.upper();
+    w("""
+  function to_{1} (s : std_ulogic) return {1} is
+  begin
+    return std_to_{0} (s);
+  end to_{1};\n""".format(typ, utyp))
+
+def disp_conv_bv_vec(typ, v):
+    "Generate function body for bit vector conversion"
+    utyp = typ.upper();
+    w("""
+  function to_{1} (b : bit_vector) return std_{2}_vector
+  is
+    subtype res_range is natural range 1 to b'length;
+    alias ba : bit_vector (res_range) is b;
+    variable res : std_{2}_vector (res_range);
+  begin
+    for i in res_range loop
+      res (i) := bit_to_x01 (ba (i));
+    end loop;
+    return res;
+  end to_{1};\n""".format(typ, utyp, v))
+
+def disp_conv_b_t(typ):
+    "Generate function body for bit conversion"
+    utyp = typ.upper();
+    w("""
+  function to_{1} (b : bit) return {1} is
+  begin
+    return bit_to_x01 (b);
+  end to_{1};\n""".format(typ, utyp))
+
+def disp_all_norm_funcs():
+    "Generate all function bodies for conversion"
+    for typ in [ "x01", "x01z", "ux01" ]:
+        for v in vec_types:
+            disp_conv_vec_vec(typ, v)
+        disp_conv_std (typ)
+        for v in vec_types:
+            disp_conv_bv_vec(typ, v)
+        disp_conv_b_t(typ)
+
+def disp_all_isx_funcs():
+    "Generate all function bodies for isx functions"
+    for v in vec_types:
+        w("""
+  function is_X (s : std_{0}_vector) return boolean is
+  begin
+    for i in s'range loop
+      if std_x (s (i)) then
+        return true;
+      end if;
+    end loop;
+    return false;
+  end is_X;\n""".format(v))
+
+    w("""
+  function is_X (s : std_ulogic) return boolean is
+  begin
+    return std_x (s);
+  end is_X;\n""")
+
+
+# Patterns to replace
+pats = {'  @TAB\n' : disp_tables,
+        '  @LOG\n' : disp_all_log_funcs,
+        '  @CONV\n': disp_all_conv_funcs,
+        '  @NORM\n': disp_all_norm_funcs,
+        '  @ISX\n' : disp_all_isx_funcs }
+
+spec_file='std_logic_1164.vhdl'
+proto_file='std_logic_1164-body.proto'
+
+def gen_body():
+    w('--  This file was generated from ' + proto_file + '\n')
+    for line in open(proto_file):
+        if line in pats:
+            pats[line]()
+            continue
+        w(line)
+
+# Copy spec
+out=open('std_logic_1164.v87', 'w')
+for line in open(spec_file):
+    if '"xnor"' in line:
+        w("--" + line[2:])
+    else:
+        w(line)
+out.close()
+
+out=open('std_logic_1164.v93', 'w')
+for line in open(spec_file):
+    w(line)
+out.close()
+
+# Generate bodies
+out=open('std_logic_1164-body.v87', 'w')
+gen_body()
+out.close()
+
+binary_funcs.append("xnor")
+out=open('std_logic_1164-body.v93', 'w')
+gen_body()
+out.close()
diff --git a/libraries/redist1164/std_logic_1164-body.proto b/libraries/redist1164/std_logic_1164-body.proto
new file mode 100644
index 000000000..aacf4c2b2
--- /dev/null
+++ b/libraries/redist1164/std_logic_1164-body.proto
@@ -0,0 +1,123 @@
+--  This is an implementation of -*- vhdl -*- ieee.std_logic_1164 based only
+--  on the specifications.  This file is part of GHDL.
+--  Copyright (C) 2015 Tristan Gingold
+--
+--  GHDL is free software; you can redistribute it and/or modify it under
+--  the terms of the GNU General Public License as published by the Free
+--  Software Foundation; either version 2, or (at your option) any later
+--  version.
+--
+--  GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+--  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+--  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+--  for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with GCC; see the file COPYING3.  If not see
+--  <http://www.gnu.org/licenses/>.
+
+--  This is a template file.  To avoid errors and duplication, the python
+--  script build.py generate most of the bodies.
+
+package body std_logic_1164 is
+
+  type table_1d is array (std_ulogic) of std_ulogic;
+  type table_2d is array (std_ulogic, std_ulogic) of std_ulogic;
+
+  constant resolution : table_2d :=
+  --  UX01ZWLH-
+    ("UUUUUUUUU",   --  U
+     "UXXXXXXXX",   --  X
+     "UX0X0000X",   --  0
+     "UXX11111X",   --  1
+     "UX01ZWLHX",   --  Z
+     "UX01WWWWX",   --  W
+     "UX01LWLWX",   --  L
+     "UX01HWWHX",   --  H
+     "UXXXXXXXX"    --  -
+     );
+
+  function resolved (s : std_ulogic_vector) return std_ulogic
+  is
+    variable res : std_ulogic := 'Z';
+  begin
+    for I in s'range loop
+      res := resolution (res, s (I));
+    end loop;
+    return res;
+  end resolved;
+
+  @TAB
+
+  @LOG
+
+  --  Conversion functions.
+  --  The result range (for vectors) is S'Length - 1 downto 0.
+  --  XMAP is return for values not in '0', '1', 'L', 'H'.
+  function to_bit (s : std_ulogic; xmap : bit := '0') return bit is
+  begin
+    case s is
+      when '0' | 'L' =>
+        return '0';
+      when '1' | 'H' =>
+        return '1';
+      when others =>
+        return xmap;
+    end case;
+  end to_bit;
+
+  type bit_to_std_table is array (bit) of std_ulogic;
+  constant bit_to_std : bit_to_std_table := "01";
+
+  @CONV
+
+  function to_stdulogic (b : bit) return std_ulogic is
+  begin
+    return bit_to_std (b);
+  end to_stdulogic;
+
+  --  Normalization.
+  type table_std_x01 is array (std_ulogic) of X01;
+  constant std_to_x01 : table_std_x01 := ('U' | 'X' | 'Z' | 'W' | '-' => 'X',
+                                          '0' | 'L'                   => '0',
+                                          '1' | 'H'                   => '1');
+
+  type table_bit_x01 is array (bit) of X01;
+  constant bit_to_x01 : table_bit_x01 := ('0' => '0',
+                                          '1' => '1');
+
+
+  type table_std_x01z is array (std_ulogic) of X01Z;
+  constant std_to_x01z : table_std_x01 := ('U' | 'X' | 'W' | '-' => 'X',
+                                           '0' | 'L'             => '0',
+                                           '1' | 'H'             => '1',
+                                           'Z'                   => 'Z');
+
+  type table_std_ux01 is array (std_ulogic) of UX01;
+  constant std_to_ux01 : table_std_ux01 := ('U'                   => 'U',
+                                            'X' | 'Z' | 'W' | '-' => 'X',
+                                            '0' | 'L'             => '0',
+                                            '1' | 'H'             => '1');
+
+  @NORM
+
+  function rising_edge (signal s : std_ulogic) return boolean is
+  begin
+    return s'event
+      and to_x01 (s'last_value) = '0'
+      and to_x01 (s) = '1';
+  end rising_edge;
+
+  function falling_edge (signal s : std_ulogic) return boolean is
+  begin
+    return s'event
+      and to_x01 (s'last_value) = '1'
+      and to_x01 (s) = '0';
+  end falling_edge;
+
+  type std_x_array is array (std_ulogic) of boolean;
+  constant std_x : std_x_array := ('U' | 'X' | 'Z' | 'W' | '-' => true,
+                                   '0' | '1' | 'L' | 'H' => false);
+
+  @ISX
+end std_logic_1164;
diff --git a/libraries/redist1164/std_logic_1164-body.vhdl b/libraries/redist1164/std_logic_1164-body.vhdl
new file mode 100644
index 000000000..f5170fa76
--- /dev/null
+++ b/libraries/redist1164/std_logic_1164-body.vhdl
@@ -0,0 +1,768 @@
+--  This is an implementation of -*- vhdl -*- ieee.std_logic_1164 based only
+--  on the specifications.  This file is part of GHDL.
+--  Copyright (C) 2015 Tristan Gingold
+--
+--  GHDL is free software; you can redistribute it and/or modify it under
+--  the terms of the GNU General Public License as published by the Free
+--  Software Foundation; either version 2, or (at your option) any later
+--  version.
+--
+--  GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+--  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+--  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+--  for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with GCC; see the file COPYING3.  If not see
+--  <http://www.gnu.org/licenses/>.
+
+--  This is a template file.  To avoid errors and duplication, the python
+--  script build.py generate most of the bodies.
+
+package body std_logic_1164 is
+
+  type table_1d is array (std_ulogic) of std_ulogic;
+  type table_2d is array (std_ulogic, std_ulogic) of std_ulogic;
+
+  constant resolution : table_2d :=
+  --  UX01ZWLH-
+    ("UUUUUUUUU",   --  U
+     "UXXXXXXXX",   --  X
+     "UX0X0000X",   --  0
+     "UXX11111X",   --  1
+     "UX01ZWLHX",   --  Z
+     "UX01WWWWX",   --  W
+     "UX01LWLWX",   --  L
+     "UX01HWWHX",   --  H
+     "UXXXXXXXX"    --  -
+     );
+
+  function resolved (s : std_ulogic_vector) return std_ulogic
+  is
+    variable res : std_ulogic := 'Z';
+  begin
+    for I in s'range loop
+      res := resolution (res, s (I));
+    end loop;
+    return res;
+  end resolved;
+
+
+  constant and_table : table_2d :=
+  --  UX01ZWLH-
+    ("UU0UUU0UU",   -- U
+     "UX0XXX0XX",   -- X
+     "000000000",   -- 0
+     "UX01XX01X",   -- 1
+     "UX0XXX0XX",   -- Z
+     "UX0XXX0XX",   -- W
+     "000000000",   -- L
+     "UX01XX01X",   -- H
+     "UX0XXX0XX"    -- -
+     );
+
+  constant nand_table : table_2d :=
+  --  UX01ZWLH-
+    ("UU1UUU1UU",   -- U
+     "UX1XXX1XX",   -- X
+     "111111111",   -- 0
+     "UX10XX10X",   -- 1
+     "UX1XXX1XX",   -- Z
+     "UX1XXX1XX",   -- W
+     "111111111",   -- L
+     "UX10XX10X",   -- H
+     "UX1XXX1XX"    -- -
+     );
+
+  constant or_table : table_2d :=
+  --  UX01ZWLH-
+    ("UUU1UUU1U",   -- U
+     "UXX1XXX1X",   -- X
+     "UX01XX01X",   -- 0
+     "111111111",   -- 1
+     "UXX1XXX1X",   -- Z
+     "UXX1XXX1X",   -- W
+     "UX01XX01X",   -- L
+     "111111111",   -- H
+     "UXX1XXX1X"    -- -
+     );
+
+  constant nor_table : table_2d :=
+  --  UX01ZWLH-
+    ("UUU0UUU0U",   -- U
+     "UXX0XXX0X",   -- X
+     "UX10XX10X",   -- 0
+     "000000000",   -- 1
+     "UXX0XXX0X",   -- Z
+     "UXX0XXX0X",   -- W
+     "UX10XX10X",   -- L
+     "000000000",   -- H
+     "UXX0XXX0X"    -- -
+     );
+
+  constant xor_table : table_2d :=
+  --  UX01ZWLH-
+    ("UUUUUUUUU",   -- U
+     "UXXXXXXXX",   -- X
+     "UX01XX01X",   -- 0
+     "UX10XX10X",   -- 1
+     "UXXXXXXXX",   -- Z
+     "UXXXXXXXX",   -- W
+     "UX01XX01X",   -- L
+     "UX10XX10X",   -- H
+     "UXXXXXXXX"    -- -
+     );
+
+  constant xnor_table : table_2d :=
+  --  UX01ZWLH-
+    ("UUUUUUUUU",   -- U
+     "UXXXXXXXX",   -- X
+     "UX10XX10X",   -- 0
+     "UX01XX01X",   -- 1
+     "UXXXXXXXX",   -- Z
+     "UXXXXXXXX",   -- W
+     "UX10XX10X",   -- L
+     "UX01XX01X",   -- H
+     "UXXXXXXXX"    -- -
+     );
+
+  constant not_table : table_1d :=
+  --  UX01ZWLH-
+     "UX10XX10X";
+
+
+  function "and" (l, r : std_ulogic) return UX01 is
+  begin
+    return and_table (l, r);
+  end "and";
+
+  function "nand" (l, r : std_ulogic) return UX01 is
+  begin
+    return nand_table (l, r);
+  end "nand";
+
+  function "or" (l, r : std_ulogic) return UX01 is
+  begin
+    return or_table (l, r);
+  end "or";
+
+  function "nor" (l, r : std_ulogic) return UX01 is
+  begin
+    return nor_table (l, r);
+  end "nor";
+
+  function "xor" (l, r : std_ulogic) return UX01 is
+  begin
+    return xor_table (l, r);
+  end "xor";
+
+  function "xnor" (l, r : std_ulogic) return UX01 is
+  begin
+    return xnor_table (l, r);
+  end "xnor";
+
+  function "not" (l : std_ulogic) return UX01 is
+  begin
+    return not_table (l);
+  end "not";
+
+  function "and" (l, r : std_ulogic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_ulogic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'and' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := and_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "and";
+
+  function "nand" (l, r : std_ulogic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_ulogic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'nand' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := nand_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "nand";
+
+  function "or" (l, r : std_ulogic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_ulogic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'or' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := or_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "or";
+
+  function "nor" (l, r : std_ulogic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_ulogic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'nor' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := nor_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "nor";
+
+  function "xor" (l, r : std_ulogic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_ulogic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'xor' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := xor_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "xor";
+
+  function "xnor" (l, r : std_ulogic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_ulogic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'xnor' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := xnor_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "xnor";
+
+  function "not" (l : std_ulogic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (1 to l'length);
+    alias la : res_type is l;
+    variable res : res_type;
+  begin
+    for I in res_type'range loop
+      res (I) := not_table (la (I));
+    end loop;
+    return res;
+  end "not";
+
+  function "and" (l, r : std_logic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_logic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'and' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := and_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "and";
+
+  function "nand" (l, r : std_logic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_logic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'nand' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := nand_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "nand";
+
+  function "or" (l, r : std_logic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_logic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'or' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := or_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "or";
+
+  function "nor" (l, r : std_logic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_logic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'nor' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := nor_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "nor";
+
+  function "xor" (l, r : std_logic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_logic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'xor' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := xor_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "xor";
+
+  function "xnor" (l, r : std_logic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (1 to l'length);
+    alias la : res_type is l;
+    alias ra : std_logic_vector (1 to r'length) is r;
+    variable res : res_type;
+  begin
+    if la'length /= ra'length then
+      assert false
+        report "arguments of overloaded 'xnor' operator are not of the same length"
+        severity failure;
+    else
+      for I in res_type'range loop
+        res (I) := xnor_table (la (I), ra (I));
+      end loop;
+    end if;
+    return res;
+  end "xnor";
+
+  function "not" (l : std_logic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (1 to l'length);
+    alias la : res_type is l;
+    variable res : res_type;
+  begin
+    for I in res_type'range loop
+      res (I) := not_table (la (I));
+    end loop;
+    return res;
+  end "not";
+
+  --  Conversion functions.
+  --  The result range (for vectors) is S'Length - 1 downto 0.
+  --  XMAP is return for values not in '0', '1', 'L', 'H'.
+  function to_bit (s : std_ulogic; xmap : bit := '0') return bit is
+  begin
+    case s is
+      when '0' | 'L' =>
+        return '0';
+      when '1' | 'H' =>
+        return '1';
+      when others =>
+        return xmap;
+    end case;
+  end to_bit;
+
+  type bit_to_std_table is array (bit) of std_ulogic;
+  constant bit_to_std : bit_to_std_table := "01";
+
+
+  function to_bitvector (s : std_ulogic_vector; xmap : bit := '0')
+    return bit_vector
+  is
+    subtype res_range is natural range s'length - 1 downto 0;
+    alias as : std_ulogic_vector (res_range) is s;
+    variable res : bit_vector (res_range);
+    variable b : bit;
+  begin
+    for I in res_range loop
+      --  Inline for efficiency.
+      case as (I) is
+        when '0' | 'L' =>
+          b := '0';
+        when '1' | 'H' =>
+          b := '1';
+        when others =>
+          b := xmap;
+      end case;
+      res (I) := b;
+    end loop;
+    return res;
+  end to_bitvector;
+
+  function to_bitvector (s : std_logic_vector; xmap : bit := '0')
+    return bit_vector
+  is
+    subtype res_range is natural range s'length - 1 downto 0;
+    alias as : std_logic_vector (res_range) is s;
+    variable res : bit_vector (res_range);
+    variable b : bit;
+  begin
+    for I in res_range loop
+      --  Inline for efficiency.
+      case as (I) is
+        when '0' | 'L' =>
+          b := '0';
+        when '1' | 'H' =>
+          b := '1';
+        when others =>
+          b := xmap;
+      end case;
+      res (I) := b;
+    end loop;
+    return res;
+  end to_bitvector;
+
+  function to_stdulogicvector (b : bit_vector) return std_ulogic_vector is
+    subtype res_range is natural range b'length - 1 downto 0;
+    alias ab : bit_vector (res_range) is b;
+    variable res : std_ulogic_vector (res_range);
+  begin
+    for I in res_range loop
+      res (I) := bit_to_std (ab (I));
+    end loop;
+    return res;
+  end to_stdulogicvector;
+
+  function to_stdlogicvector (b : bit_vector) return std_logic_vector is
+    subtype res_range is natural range b'length - 1 downto 0;
+    alias ab : bit_vector (res_range) is b;
+    variable res : std_logic_vector (res_range);
+  begin
+    for I in res_range loop
+      res (I) := bit_to_std (ab (I));
+    end loop;
+    return res;
+  end to_stdlogicvector;
+
+  function to_stdulogicvector (b : std_logic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (b'length - 1 downto 0);
+  begin
+    return res_type (b);
+  end to_stdulogicvector;
+
+  function to_stdlogicvector (b : std_ulogic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (b'length - 1 downto 0);
+  begin
+    return res_type (b);
+  end to_stdlogicvector;
+
+  function to_stdulogic (b : bit) return std_ulogic is
+  begin
+    return bit_to_std (b);
+  end to_stdulogic;
+
+  --  Normalization.
+  type table_std_x01 is array (std_ulogic) of X01;
+  constant std_to_x01 : table_std_x01 := ('U' | 'X' | 'Z' | 'W' | '-' => 'X',
+                                          '0' | 'L'                   => '0',
+                                          '1' | 'H'                   => '1');
+
+  type table_bit_x01 is array (bit) of X01;
+  constant bit_to_x01 : table_bit_x01 := ('0' => '0',
+                                          '1' => '1');
+
+
+  type table_std_x01z is array (std_ulogic) of X01Z;
+  constant std_to_x01z : table_std_x01 := ('U' | 'X' | 'W' | '-' => 'X',
+                                           '0' | 'L'             => '0',
+                                           '1' | 'H'             => '1',
+                                           'Z'                   => 'Z');
+
+  type table_std_ux01 is array (std_ulogic) of UX01;
+  constant std_to_ux01 : table_std_ux01 := ('U'                   => 'U',
+                                            'X' | 'Z' | 'W' | '-' => 'X',
+                                            '0' | 'L'             => '0',
+                                            '1' | 'H'             => '1');
+
+
+  function to_X01 (s : std_ulogic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (1 to s'length);
+    alias sa : res_type is s;
+    variable res : res_type;
+  begin
+    for i in res_type'range loop
+      res (i) := std_to_x01 (sa (i));
+    end loop;
+    return res;
+  end to_X01;
+
+  function to_X01 (s : std_logic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (1 to s'length);
+    alias sa : res_type is s;
+    variable res : res_type;
+  begin
+    for i in res_type'range loop
+      res (i) := std_to_x01 (sa (i));
+    end loop;
+    return res;
+  end to_X01;
+
+  function to_X01 (s : std_ulogic) return X01 is
+  begin
+    return std_to_x01 (s);
+  end to_X01;
+
+  function to_X01 (b : bit_vector) return std_ulogic_vector
+  is
+    subtype res_range is natural range 1 to b'length;
+    alias ba : bit_vector (res_range) is b;
+    variable res : std_ulogic_vector (res_range);
+  begin
+    for i in res_range loop
+      res (i) := bit_to_x01 (ba (i));
+    end loop;
+    return res;
+  end to_X01;
+
+  function to_X01 (b : bit_vector) return std_logic_vector
+  is
+    subtype res_range is natural range 1 to b'length;
+    alias ba : bit_vector (res_range) is b;
+    variable res : std_logic_vector (res_range);
+  begin
+    for i in res_range loop
+      res (i) := bit_to_x01 (ba (i));
+    end loop;
+    return res;
+  end to_X01;
+
+  function to_X01 (b : bit) return X01 is
+  begin
+    return bit_to_x01 (b);
+  end to_X01;
+
+  function to_X01Z (s : std_ulogic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (1 to s'length);
+    alias sa : res_type is s;
+    variable res : res_type;
+  begin
+    for i in res_type'range loop
+      res (i) := std_to_x01z (sa (i));
+    end loop;
+    return res;
+  end to_X01Z;
+
+  function to_X01Z (s : std_logic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (1 to s'length);
+    alias sa : res_type is s;
+    variable res : res_type;
+  begin
+    for i in res_type'range loop
+      res (i) := std_to_x01z (sa (i));
+    end loop;
+    return res;
+  end to_X01Z;
+
+  function to_X01Z (s : std_ulogic) return X01Z is
+  begin
+    return std_to_x01z (s);
+  end to_X01Z;
+
+  function to_X01Z (b : bit_vector) return std_ulogic_vector
+  is
+    subtype res_range is natural range 1 to b'length;
+    alias ba : bit_vector (res_range) is b;
+    variable res : std_ulogic_vector (res_range);
+  begin
+    for i in res_range loop
+      res (i) := bit_to_x01 (ba (i));
+    end loop;
+    return res;
+  end to_X01Z;
+
+  function to_X01Z (b : bit_vector) return std_logic_vector
+  is
+    subtype res_range is natural range 1 to b'length;
+    alias ba : bit_vector (res_range) is b;
+    variable res : std_logic_vector (res_range);
+  begin
+    for i in res_range loop
+      res (i) := bit_to_x01 (ba (i));
+    end loop;
+    return res;
+  end to_X01Z;
+
+  function to_X01Z (b : bit) return X01Z is
+  begin
+    return bit_to_x01 (b);
+  end to_X01Z;
+
+  function to_UX01 (s : std_ulogic_vector) return std_ulogic_vector
+  is
+    subtype res_type is std_ulogic_vector (1 to s'length);
+    alias sa : res_type is s;
+    variable res : res_type;
+  begin
+    for i in res_type'range loop
+      res (i) := std_to_ux01 (sa (i));
+    end loop;
+    return res;
+  end to_UX01;
+
+  function to_UX01 (s : std_logic_vector) return std_logic_vector
+  is
+    subtype res_type is std_logic_vector (1 to s'length);
+    alias sa : res_type is s;
+    variable res : res_type;
+  begin
+    for i in res_type'range loop
+      res (i) := std_to_ux01 (sa (i));
+    end loop;
+    return res;
+  end to_UX01;
+
+  function to_UX01 (s : std_ulogic) return UX01 is
+  begin
+    return std_to_ux01 (s);
+  end to_UX01;
+
+  function to_UX01 (b : bit_vector) return std_ulogic_vector
+  is
+    subtype res_range is natural range 1 to b'length;
+    alias ba : bit_vector (res_range) is b;
+    variable res : std_ulogic_vector (res_range);
+  begin
+    for i in res_range loop
+      res (i) := bit_to_x01 (ba (i));
+    end loop;
+    return res;
+  end to_UX01;
+
+  function to_UX01 (b : bit_vector) return std_logic_vector
+  is
+    subtype res_range is natural range 1 to b'length;
+    alias ba : bit_vector (res_range) is b;
+    variable res : std_logic_vector (res_range);
+  begin
+    for i in res_range loop
+      res (i) := bit_to_x01 (ba (i));
+    end loop;
+    return res;
+  end to_UX01;
+
+  function to_UX01 (b : bit) return UX01 is
+  begin
+    return bit_to_x01 (b);
+  end to_UX01;
+
+  function rising_edge (signal s : std_ulogic) return boolean is
+  begin
+    return s'event
+      and to_x01 (s'last_value) = '0'
+      and to_x01 (s) = '1';
+  end rising_edge;
+
+  function falling_edge (signal s : std_ulogic) return boolean is
+  begin
+    return s'event
+      and to_x01 (s'last_value) = '1'
+      and to_x01 (s) = '0';
+  end falling_edge;
+
+  type std_x_array is array (std_ulogic) of boolean;
+  constant std_x : std_x_array := ('U' | 'X' | 'Z' | 'W' | '-' => true,
+                                   '0' | '1' | 'L' | 'H' => false);
+
+
+  function is_X (s : std_ulogic_vector) return boolean is
+  begin
+    for i in s'range loop
+      if std_x (s (i)) then
+        return true;
+      end if;
+    end loop;
+    return false;
+  end is_X;
+
+  function is_X (s : std_logic_vector) return boolean is
+  begin
+    for i in s'range loop
+      if std_x (s (i)) then
+        return true;
+      end if;
+    end loop;
+    return false;
+  end is_X;
+
+  function is_X (s : std_ulogic) return boolean is
+  begin
+    return std_x (s);
+  end is_X;
+end std_logic_1164;
diff --git a/libraries/redist1164/std_logic_1164.vhdl b/libraries/redist1164/std_logic_1164.vhdl
new file mode 100644
index 000000000..0ee62a1a6
--- /dev/null
+++ b/libraries/redist1164/std_logic_1164.vhdl
@@ -0,0 +1,143 @@
+--  This is an implementation of ieee.std_logic_1164 based only on the
+--  specifications.  This file is part of GHDL.
+--  Copyright (C) 2015 Tristan Gingold
+--
+--  GHDL is free software; you can redistribute it and/or modify it under
+--  the terms of the GNU General Public License as published by the Free
+--  Software Foundation; either version 2, or (at your option) any later
+--  version.
+--
+--  GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
+--  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+--  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+--  for more details.
+--
+--  You should have received a copy of the GNU General Public License
+--  along with GCC; see the file COPYING3.  If not see
+--  <http://www.gnu.org/licenses/>.
+
+--  This package is valid for VHDL version until but not including 2008.
+--  For VHDL87, the functions xnor should be removed.
+
+package std_logic_1164 is
+
+  --  Unresolved logic state.
+  type std_ulogic is
+    ('U',  --  Uninitialized, this is also the default value.
+     'X',  --  Unknown / conflict value (forcing level).
+     '0',  --  0 (forcing level).
+     '1',  --  1 (forcing level).
+     'Z',  --  High impedance.
+     'W',  --  Unknown / conflict (weak level).
+     'L',  --  0 (weak level).
+     'H',  --  1 (weak level).
+     '-'   --  Don't care.
+     );
+
+  --  Vector of logic state.
+  type std_ulogic_vector is array (natural range <>) of std_ulogic;
+
+  --  Resolution function.
+  --  If S is empty, returns 'Z'.
+  --  If S has one element, return the element.
+  --  Otherwise, 'U' is the strongest.
+  --       then  'X'
+  --       then  '0' and '1'
+  --       then  'W'
+  --       then  'H' and 'L'
+  --       then  'Z'.
+  function resolved (s : std_ulogic_vector) return std_ulogic;
+
+  --  Resolved logic state.
+  subtype std_logic is resolved std_ulogic;
+
+  --  Vector of std_logic.
+  type std_logic_vector is array (natural range <>) of std_logic;
+
+  --  Subtypes of std_ulogic.  The names give the values.
+  subtype X01   is resolved std_ulogic range 'X' to '1';
+  subtype X01Z  is resolved std_ulogic range 'X' to 'Z';
+  subtype UX01  is resolved std_ulogic range 'U' to '1';
+  subtype UX01Z is resolved std_ulogic range 'U' to 'Z';
+
+  --  Logical operators.
+  --  For logical operations, the inputs are first normalized to UX01:
+  --  0 and L are normalized to 0, 1 and 1 are normalized to 1, U isnt changed,
+  --  all other states are normalized to X.
+  --  Then the classical electric rules are followed.
+  function "and"  (l, r : std_ulogic) return UX01;
+  function "nand" (l, r : std_ulogic) return UX01;
+  function "or"   (l, r : std_ulogic) return UX01;
+  function "nor"  (l, r : std_ulogic) return UX01;
+  function "xor"  (l, r : std_ulogic) return UX01;
+  function "xnor" (l, r : std_ulogic) return UX01;
+  function "not"  (l : std_ulogic) return UX01;
+
+  --  Logical operators for vectors.
+  --  An assertion of severity failure fails if the length of L and R aren't
+  --  equal.  The result range is 1 to L'Length.
+  function "and"  (l, r : std_logic_vector) return std_logic_vector;
+  function "nand" (l, r : std_logic_vector) return std_logic_vector;
+  function "or"   (l, r : std_logic_vector) return std_logic_vector;
+  function "nor"  (l, r : std_logic_vector) return std_logic_vector;
+  function "xor"  (l, r : std_logic_vector) return std_logic_vector;
+  function "xnor" (l, r : std_logic_vector) return std_logic_vector;
+  function "not"  (l : std_logic_vector) return std_logic_vector;
+
+  function "and"  (l, r : std_ulogic_vector) return std_ulogic_vector;
+  function "nand" (l, r : std_ulogic_vector) return std_ulogic_vector;
+  function "or"   (l, r : std_ulogic_vector) return std_ulogic_vector;
+  function "nor"  (l, r : std_ulogic_vector) return std_ulogic_vector;
+  function "xor"  (l, r : std_ulogic_vector) return std_ulogic_vector;
+  function "xnor" (l, r : std_ulogic_vector) return std_ulogic_vector;
+  function "not"  (l : std_ulogic_vector) return std_ulogic_vector;
+
+  --  Conversion functions.
+  --  The result range (for vectors) is S'Length - 1 downto 0.
+  --  XMAP is return for values not in '0', '1', 'L', 'H'.
+  function to_bit (s : std_ulogic; xmap : bit := '0') return bit;
+  function to_bitvector (s : std_logic_vector; xmap : bit := '0')
+    return bit_vector;
+  function to_bitvector (s : std_ulogic_vector; xmap : bit := '0')
+    return bit_vector;
+
+  function to_stdulogic (b : bit) return std_ulogic;
+  function to_stdlogicvector (b : bit_vector) return std_logic_vector;
+  function to_stdlogicvector (b : std_ulogic_vector) return std_logic_vector;
+  function to_stdulogicvector (b : bit_vector) return std_ulogic_vector;
+  function to_stdulogicvector (b : std_logic_vector) return std_ulogic_vector;
+
+  --  Normalization.
+  --  The result range (for vectors) is 1 to S'Length.
+  function to_X01 (s : std_logic_vector) return std_logic_vector;
+  function to_X01 (s : std_ulogic_vector) return std_ulogic_vector;
+  function to_X01 (s : std_ulogic) return X01;
+  function to_X01 (b : bit_vector) return std_logic_vector;
+  function to_X01 (b : bit_vector) return std_ulogic_vector;
+  function to_X01 (b : bit) return X01;
+
+  function to_X01Z (s : std_logic_vector) return std_logic_vector;
+  function to_X01Z (s : std_ulogic_vector) return std_ulogic_vector;
+  function to_X01Z (s : std_ulogic) return X01Z;
+  function to_X01Z (b : bit_vector) return std_logic_vector;
+  function to_X01Z (b : bit_vector) return std_ulogic_vector;
+  function to_X01Z (b : bit) return X01Z;
+
+  function to_UX01 (s : std_logic_vector) return std_logic_vector;
+  function to_UX01 (s : std_ulogic_vector) return std_ulogic_vector;
+  function to_UX01 (s : std_ulogic) return UX01;
+  function to_UX01 (b : bit_vector) return std_logic_vector;
+  function to_UX01 (b : bit_vector) return std_ulogic_vector;
+  function to_UX01 (b : bit) return UX01;
+
+  --  Edge detection.
+  --  An edge is detected in case of event on s, and X01 normalized value
+  --  rises from 0 to 1 or falls from 1 to 0.
+  function rising_edge (signal s : std_ulogic) return boolean;
+  function falling_edge (signal s : std_ulogic) return boolean;
+
+  --  Test for unknown.  Only 0, 1, L and H are known values.
+  function is_X (s : std_ulogic_vector) return boolean;
+  function is_X (s : std_logic_vector) return boolean;
+  function is_X (s : std_ulogic) return boolean;
+end std_logic_1164;
-- 
cgit v1.2.3