OpenCores
URL https://opencores.org/ocsvn/mips_enhanced/mips_enhanced/trunk

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [gaisler/] [leon3/] [irqmp.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
------------------------------------------------------------------------------
2
--  This file is a part of the GRLIB VHDL IP LIBRARY
3
--  Copyright (C) 2003, Gaisler Research
4
--
5
--  This program is free software; you can redistribute it and/or modify
6
--  it under the terms of the GNU General Public License as published by
7
--  the Free Software Foundation; either version 2 of the License, or
8
--  (at your option) any later version.
9
--
10
--  This program is distributed in the hope that it will be useful,
11
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
--  GNU General Public License for more details.
14
--
15
--  You should have received a copy of the GNU General Public License
16
--  along with this program; if not, write to the Free Software
17
--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
18
-----------------------------------------------------------------------------
19
-- Entity:      irqmp
20
-- File:        irqmp.vhd
21
-- Author:      Jiri Gaisler - Gaisler Research
22
-- Description: Multi-processor APB interrupt controller. Implements a
23
--              two-level interrupt controller for 15 interrupts.
24
------------------------------------------------------------------------------
25
 
26
library ieee;
27
use ieee.std_logic_1164.all;
28
library grlib;
29
use grlib.amba.all;
30
use grlib.stdlib.all;
31
use grlib.devices.all;
32
library gaisler;
33
use gaisler.leon3.all;
34
 
35
entity irqmp is
36
  generic (
37
    pindex  : integer := 0;
38
    paddr   : integer := 0;
39
    pmask   : integer := 16#fff#;
40
    ncpu    : integer := 1;
41
    eirq    : integer := 0
42
  );
43
  port (
44
    rst    : in  std_ulogic;
45
    clk    : in  std_ulogic;
46
    apbi   : in  apb_slv_in_type;
47
    apbo   : out apb_slv_out_type;
48
    irqi   : in  irq_out_vector(0 to ncpu-1);
49
    irqo   : out irq_in_vector(0 to ncpu-1)
50
  );
51
end;
52
 
53
architecture rtl of irqmp is
54
 
55
constant REVISION : integer := 3;
56
 
57
constant pconfig : apb_config_type := (
58
 
59
  1 => apb_iobar(paddr, pmask));
60
 
61
type mask_type is array (0 to ncpu-1) of std_logic_vector(15 downto 1);
62
type mask2_type is array (0 to ncpu-1) of std_logic_vector(15 downto 0);
63
type irl_type is array (0 to ncpu-1) of std_logic_vector(3 downto 0);
64
type irl2_type is array (0 to ncpu-1) of std_logic_vector(4 downto 0);
65
 
66
type reg_type is record
67
  imask         : mask_type;
68
  ilevel        : std_logic_vector(15 downto 1);
69
  ipend         : std_logic_vector(15 downto 1);
70
  iforce        : mask_type;
71
  ibroadcast    : std_logic_vector(15 downto 1);
72
  irl           : irl_type;
73
  cpurst        : std_logic_vector(ncpu-1 downto 0);
74
end record;
75
 
76
type ereg_type is record
77
  imask         : mask2_type;
78
  ipend         : std_logic_vector(15 downto 0);
79
  irl           : irl2_type;
80
end record;
81
 
82
function prioritize(b : std_logic_vector(15 downto 0)) return std_logic_vector is
83
variable a : std_logic_vector(15 downto 0);
84
variable irl : std_logic_vector(3 downto 0);
85
variable level : integer range 0 to 15;
86
begin
87
  irl := "0000"; level := 0; a := b;
88
  for i in 15 downto 0 loop
89
    level := i;
90
    if a(i) = '1' then exit; end if;
91
  end loop;
92
  irl := conv_std_logic_vector(level, 4);
93
  return(irl);
94
end;
95
 
96
signal r, rin : reg_type;
97
signal r2, r2in : ereg_type;
98
 
99
begin
100
 
101
  comb : process(rst, r, r2, apbi, irqi)
102
  variable v : reg_type;
103
  variable temp : mask_type;
104
  variable prdata : std_logic_vector(31 downto 0);
105
  variable tmpirq : std_logic_vector(15 downto 0);
106
  variable tmpvar : std_logic_vector(15 downto 1);
107
  variable cpurun       : std_logic_vector(ncpu-1 downto 0);
108
  variable v2 : ereg_type;
109
  variable irl2 : std_logic_vector(3 downto 0);
110
  variable ipend2 : std_logic_vector(ncpu-1 downto 0);
111
  variable temp2 : mask2_type;
112
  variable neirq : integer;
113
 
114
  begin
115
 
116
    v := r; v.cpurst := (others => '0');
117
    cpurun := (others => '0'); cpurun(0) := '1';
118
    tmpvar := (others => '0'); ipend2 := (others => '0');
119
    v2 := r2;
120
 
121
-- prioritize interrupts
122
 
123
    if eirq /= 0 then
124
      for i in 0 to ncpu-1 loop
125
        temp2(i) := r2.ipend and r2.imask(i);
126
        ipend2(i) := orv(temp2(i));
127
      end loop;
128
    end if;
129
 
130
    for i in 0 to ncpu-1 loop
131
      temp(i) := ((r.iforce(i) or r.ipend) and r.imask(i));
132
      if eirq /= 0 then temp(i)(eirq) := temp(i)(eirq) or ipend2(i); end if;
133
      v.irl(i) := prioritize((temp(i) and r.ilevel) & '0');
134
      if v.irl(i) = "0000" then
135
        if eirq /= 0 then temp(i)(eirq) := temp(i)(eirq) or ipend2(i); end if;
136
        v.irl(i) := prioritize((temp(i) and not r.ilevel) & '0');
137
      end if;
138
    end loop;
139
 
140
-- register read
141
 
142
    prdata := (others => '0');
143
    case apbi.paddr(7 downto 6) is
144
    when "00" =>
145
      case apbi.paddr(4 downto 2) is
146
      when "000" => prdata(15 downto 1) := r.ilevel;
147
      when "001" =>
148
        prdata(15 downto 1) := r.ipend;
149
        if eirq /= 0 then prdata(31 downto 16) := r2.ipend; end if;
150
      when "010" => prdata(15 downto 1) := r.iforce(0);
151
      when "011" =>
152
      when "100" | "101" =>
153
        prdata(31 downto 28) := conv_std_logic_vector(ncpu-1, 4);
154
        prdata(19 downto 16) := conv_std_logic_vector(eirq, 4);
155
        for i in 0 to ncpu -1 loop prdata(i) := irqi(i).pwd; end loop;
156
        if ncpu > 1 then
157
          prdata(27) := '1';
158
          case apbi.paddr(4 downto 2) is
159
            when "101" =>
160
              prdata := (others => '0');
161
              prdata(15 downto 1) := r.ibroadcast;
162
            when others =>
163
          end case;
164
        end if;
165
      when others =>
166
      end case;
167
    when "01" =>
168
      for i in 0 to ncpu-1 loop
169
        if i = conv_integer( apbi.paddr(5 downto 2)) then
170
          prdata(15 downto 1) := r.imask(i);
171
          if eirq /= 0 then prdata(31 downto 16) := r2.imask(i); end if;
172
        end if;
173
      end loop;
174
    when "10" =>
175
      for i in 0 to ncpu-1 loop
176
        if i = conv_integer( apbi.paddr(5 downto 2)) then
177
            prdata(15 downto  1) := r.iforce(i);
178
        end if;
179
      end loop;
180
    when "11" =>
181
      if eirq /= 0 then
182
        for i in 0 to ncpu-1 loop
183
          if i = conv_integer( apbi.paddr(5 downto 2)) then
184
            prdata(4 downto 0) := r2.irl(i);
185
          end if;
186
        end loop;
187
      end if;
188
    when others =>
189
    end case;
190
 
191
-- register write
192
 
193
    if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then
194
      case apbi.paddr(7 downto 6) is
195
      when "00" =>
196
        case apbi.paddr(4 downto 2) is
197
        when "000" => v.ilevel := apbi.pwdata(15 downto 1);
198
        when "001" => v.ipend  := apbi.pwdata(15 downto 1);
199
          if eirq /= 0 then v2.ipend := apbi.pwdata(31 downto 16); end if;
200
        when "010" => v.iforce(0) := apbi.pwdata(15 downto 1);
201
        when "011" => v.ipend  := r.ipend and not apbi.pwdata(15 downto 1);
202
          if eirq /= 0 then v2.ipend := r2.ipend and not apbi.pwdata(31 downto 16); end if;
203
        when "100" =>
204
          for i in 0 to ncpu -1 loop v.cpurst(i) := apbi.pwdata(i); end loop;
205
        when others =>
206
          if ncpu > 1 then
207
            case apbi.paddr(4 downto 2) is
208
              when "101" =>
209
                v.ibroadcast := apbi.pwdata(15 downto 1);
210
              when others =>
211
            end case;
212
          end if;
213
        end case;
214
      when "01" =>
215
        for i in 0 to ncpu-1 loop
216
          if i = conv_integer( apbi.paddr(5 downto 2)) then
217
            v.imask(i) := apbi.pwdata(15 downto 1);
218
            if eirq /= 0 then v2.imask(i) := apbi.pwdata(31 downto 16); end if;
219
          end if;
220
        end loop;
221
      when "10" =>
222
        for i in 0 to ncpu-1 loop
223
          if i = conv_integer( apbi.paddr(5 downto 2)) then
224
            v.iforce(i) := (r.iforce(i) or apbi.pwdata(15 downto 1)) and
225
                        not apbi.pwdata(31 downto 17);
226
          end if;
227
        end loop;
228
      when others =>
229
      end case;
230
    end if;
231
 
232
-- register new interrupts
233
 
234
    for i in 1 to 15 loop
235
      if i > NAHBIRQ-1 then
236
         exit;
237
      end if;
238
      if ncpu = 1 then
239
        v.ipend(i) := v.ipend(i) or apbi.pirq(i);
240
      else
241
        v.ipend(i) := v.ipend(i) or (apbi.pirq(i) and not r.ibroadcast(i));
242
        for j in 0 to ncpu-1 loop
243
          tmpvar := v.iforce(j);
244
          tmpvar(i) := tmpvar(i) or (apbi.pirq(i) and r.ibroadcast(i));
245
          v.iforce(j) := tmpvar;
246
        end loop;
247
      end if;
248
    end loop;
249
 
250
    if eirq /= 0 then
251
      for i in 16 to 31 loop
252
        if i > NAHBIRQ-1 then exit; end if;
253
        v2.ipend(i-16) := v2.ipend(i-16) or apbi.pirq(i);
254
      end loop;
255
    end if;
256
 
257
-- interrupt acknowledge
258
 
259
    for i in 0 to ncpu-1 loop
260
      if irqi(i).intack = '1' then
261
        tmpirq := decode(irqi(i).irl);
262
        temp(i) := tmpirq(15 downto 1);
263
        v.iforce(i) := v.iforce(i) and not temp(i);
264
        v.ipend  := v.ipend and not ((not r.iforce(i)) and temp(i));
265
        if eirq /= 0 then
266
--          v2.irl(i) := '0' & irqi(i).irl;
267
          if eirq = conv_integer(irqi(i).irl) then
268
            v2.irl(i) := orv(temp2(i)) & prioritize(temp2(i));
269
            if v2.irl(i)(4) = '1' then
270
                v2.ipend(conv_integer(v2.irl(i)(3 downto 0))) := '0';
271
            end if;
272
          end if;
273
        end if;
274
      end if;
275
    end loop;
276
 
277
-- reset
278
 
279
    if rst = '0' then
280
      v.imask := (others => (others => '0'));
281
      v.iforce := (others => (others => '0'));
282
      v.ipend := (others => '0');
283
      if ncpu > 1 then
284
        v.ibroadcast := (others => '0');
285
      end if;
286
      v2.ipend := (others => '0');
287
      v2.imask := (others => (others => '0'));
288
      v2.irl := (others => (others => '0'));
289
    end if;
290
 
291
    apbo.prdata <= prdata;
292
    for i in 0 to ncpu-1 loop
293
      irqo(i).irl <= r.irl(i); irqo(i).rst <= r.cpurst(i);
294
      irqo(i).run <= cpurun(i);
295
      irqo(i).rstvec <= (others => '0');  -- Alternate reset vector
296
    end loop;
297
 
298
    rin <= v; r2in <= v2;
299
 
300
  end process;
301
 
302
  apbo.pirq <= (others => '0');
303
  apbo.pconfig <= pconfig;
304
  apbo.pindex <= pindex;
305
 
306
  regs : process(clk)
307
  begin if rising_edge(clk) then r <= rin; end if; end process;
308
 
309
  dor2regs : if eirq /= 0 generate
310
    regs : process(clk)
311
    begin if rising_edge(clk) then r2 <= r2in; end if; end process;
312
  end generate;
313
  nor2regs : if eirq = 0 generate
314
--    r2 <= ((others => "0000000000000000"), "0000000000000000", (others => "00000"));
315
    r2.ipend <= (others => '0');
316
    driveregs: for i in 0 to (ncpu-1) generate
317
      r2.imask(i) <= (others => '0');
318
      r2.irl(i) <= (others => '0');
319
    end generate driveregs;
320
  end generate;
321
 
322
-- pragma translate_off
323
    bootmsg : report_version
324
    generic map ("irqmp" &
325
        ": Multi-processor Interrupt Controller rev " & tost(REVISION) &
326
        ", #cpu " & tost(NCPU) & ", eirq " & tost(eirq));
327
-- pragma translate_on
328
 
329
 
330
end;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.