1--  PSL - HDL interface.
2--  Copyright (C) 2002-2016 Tristan Gingold
3--
4--  This program is free software: you can redistribute it and/or modify
5--  it under the terms of the GNU General Public License as published by
6--  the Free Software Foundation, either version 2 of the License, or
7--  (at your option) any later version.
8--
9--  This program is distributed in the hope that it will be useful,
10--  but WITHOUT ANY WARRANTY; without even the implied warranty of
11--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12--  GNU General Public License for more details.
13--
14--  You should have received a copy of the GNU General Public License
15--  along with this program.  If not, see <gnu.org/licenses>.
16
17with Tables;
18with PSL.Types; use PSL.Types;
19
20package body PSL.Hash is
21
22   type Index_Type is new Natural;
23   No_Index : constant Index_Type := 0;
24
25   type Cell_Record is record
26      Res : Node;
27      Next : Index_Type;
28   end record;
29
30   Hash_Size : constant Index_Type := 127;
31
32   package Cells is new Tables
33     (Table_Component_Type => Cell_Record,
34      Table_Index_Type => Index_Type,
35      Table_Low_Bound => 0,
36      Table_Initial => 256);
37
38   procedure Init is
39   begin
40      Cells.Set_Last (Hash_Size - 1);
41      for I in 0 .. Hash_Size - 1 loop
42         Cells.Table (I) := (Res => Null_Node, Next => No_Index);
43      end loop;
44   end Init;
45
46   function Get_PSL_Node (Hdl : Int32; Loc : Location_Type) return Node
47   is
48      Idx : Index_Type := Index_Type (Hdl mod Int32 (Hash_Size));
49      N_Idx : Index_Type;
50      Res : Node;
51   begin
52      --  In the primary table.
53      Res := Cells.Table (Idx).Res;
54      if Res = Null_Node then
55         Res := Create_Node (N_HDL_Bool);
56         Set_HDL_Node (Res, Hdl);
57         Set_Location (Res, Loc);
58         Cells.Table (Idx).Res := Res;
59         return Res;
60      end if;
61
62      loop
63         if Get_HDL_Node (Res) = Hdl then
64            return Res;
65         end if;
66         --  Look in collisions chain
67         N_Idx := Cells.Table (Idx).Next;
68         exit when N_Idx = No_Index;
69         Idx := N_Idx;
70         Res := Cells.Table (Idx).Res;
71      end loop;
72      Res := Create_Node (N_HDL_Bool);
73      Set_HDL_Node (Res, Hdl);
74      Set_Location (Res, Loc);
75      Cells.Append ((Res => Res, Next => No_Index));
76      Cells.Table (Idx).Next := Cells.Last;
77      return Res;
78   end Get_PSL_Node;
79end PSL.Hash;
80