aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/netlists-concats.adb
blob: b013085144985544684849c9489f6d2fb437e46a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
--  Provide a simple way to concat an unknown number of nets.
--  Copyright (C) 2019 Tristan Gingold
--
--  This file is part of GHDL.
--
--  This program 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 of the License, or
--  (at your option) any later version.
--
--  This program 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 this program; if not, write to the Free Software
--  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
--  MA 02110-1301, USA.

package body Netlists.Concats is
   procedure Append (C : in out Concat_Type; N : Net) is
   begin
      if C.Len < C.Sarr'Last then
         C.Len := C.Len + 1;
         C.Sarr (C.Len) := N;
      elsif C.Len > C.Sarr'Last then
         C.Len := C.Len + 1;
         Net_Tables.Append (C.Darr, N);
      else
         --  Switch to the dynamic array.
         C.Len := C.Len + 1;
         Net_Tables.Init (C.Darr);
         Net_Tables.Set_Last (C.Darr, C.Len);
         C.Darr.Table (C.Sarr'Range) := C.Sarr;
         C.Darr.Table (C.Len) := N;
      end if;
   end Append;

   --  Get the concatenation of all nets in C.  Reset C.
   procedure Build (Ctxt : Context_Acc; C : in out Concat_Type; N : out Net)
   is
      Inst : Instance;
      Wd : Width;
   begin
      case C.Len is
         when Int32'First .. 0 =>
            raise Internal_Error;
         when 1 =>
            N := C.Sarr (1);
         when 2 =>
            N := Build_Concat2 (Ctxt, C.Sarr (2), C.Sarr (1));
         when 3 =>
            N := Build_Concat3 (Ctxt, C.Sarr (3), C.Sarr (2), C.Sarr (1));
         when 4 =>
            N := Build_Concat4
              (Ctxt, C.Sarr (4), C.Sarr (3), C.Sarr (2), C.Sarr (1));
         when 5 .. Static_Last =>
            Wd := 0;
            for I in 1 .. C.Len loop
               Wd := Wd + Get_Width (C.Sarr (I));
            end loop;

            N := Build_Concatn (Ctxt, Wd, Uns32 (C.Len));
            Inst := Get_Parent (N);
            for I in 1 .. C.Len loop
               Connect (Get_Input (Inst, Port_Idx (I - 1)), C.Sarr (I));
            end loop;
         when Static_Last + 1 .. Int32'Last =>
            pragma Assert (C.Len = Net_Tables.Last (C.Darr));
            Wd := 0;
            for I in 1 .. C.Len loop
               Wd := Wd + Get_Width (C.Darr.Table (I));
            end loop;

            N := Build_Concatn (Ctxt, Wd, Uns32 (C.Len));
            Inst := Get_Parent (N);
            for I in Net_Tables.First .. C.Len loop
               Connect (Get_Input (Inst, Port_Idx (I - 1)), C.Darr.Table (I));
            end loop;
            --  Free the vector.
            Net_Tables.Free (C.Darr);
      end case;

      C.Len := 0;
   end Build;
end Netlists.Concats;