head 1.13; access; symbols bg2_23:1.13 bg2_22:1.13 bg2_21:1.13 bg2_20:1.13 bg2_16:1.13 bg2_15:1.12 bg2_12:1.12 bg2_07:1.12 isorc2008_submission:1.6 handbook_alpha_edition:1.1 jtres2007_submission:1.1; locks; strict; comment @# @; 1.13 date 2008.06.20.15.43.05; author martin; state Exp; branches; next 1.12; commitid 6ab6485bd0044567; 1.12 date 2008.03.11.12.38.06; author martin; state Exp; branches; next 1.11; commitid 178a47d67d2b4567; 1.11 date 2008.02.23.23.18.46; author martin; state Exp; branches; next 1.10; commitid b7347c0a9b84567; 1.10 date 2008.02.22.14.09.16; author 9914pich; state Exp; branches; next 1.9; commitid 241647bed78a4567; 1.9 date 2008.02.22.13.18.20; author 9914pich; state Exp; branches; next 1.8; commitid d9447becb9b4567; 1.8 date 2008.01.10.16.46.50; author 9914pich; state Exp; branches; next 1.7; commitid 482147864bf94567; 1.7 date 2007.12.07.08.22.32; author 9914pich; state Exp; branches; next 1.6; commitid 4ecb475902c74567; 1.6 date 2007.12.04.17.22.33; author martin; state Exp; branches; next 1.5; commitid 6b7847558cd74567; 1.5 date 2007.12.03.17.04.09; author martin; state Exp; branches; next 1.4; commitid 7382475437044567; 1.4 date 2007.12.02.20.56.40; author martin; state Exp; branches; next 1.3; commitid 3e2a47531c064567; 1.3 date 2007.12.02.15.36.09; author martin; state Exp; branches; next 1.2; commitid 177b4752d0e24567; 1.2 date 2007.11.22.14.38.13; author 9914pich; state Exp; branches; next 1.1; commitid 1c3f474594544567; 1.1 date 2007.06.01.13.16.30; author 9914pich; state Exp; branches; next ; commitid 21e46601c2d4567; desc @@ 1.13 log @CPU count from sys device @ text @-- -- -- This file is a part of JOP, the Java Optimized Processor -- -- Copyright (C) 2001-2008, Martin Schoeberl (martin@@jopdesign.com) -- -- 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 3 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, see . -- -- -- sc_sys.vhd -- -- counter, interrrupt handling and watchdog bit -- -- Author: Martin Schoeberl martin@@jopdesign.com -- -- address map: -- -- 0 read clk counter, write irq ena -- 1 read 1 MHz counter, write timer val (us) -- 2 write generates sw-int (for yield()) -- 3 write wd port -- 4 write generates SW exception, read exception reason -- -- todo: -- -- -- 2003-07-05 new IO standard -- 2003-08-15 us counter, irq added -- 2005-11-30 change interface to SimpCon -- 2006-01-11 added exception -- 2007-03-17 changed interrupts to records -- 2007-06-01 changed name from sc_cnt to sc_sys -- 2007-11-22 added global lock and bootup of CMP -- 2007-12-03 prioritized interrupt processing -- 2007-12-07 global lock redesign -- -- state for a single interrupt -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity intstate is port ( clk : in std_logic; reset : in std_logic; irq : in std_logic; -- external request ena : in std_logic; -- local enable ack : in std_logic; -- is served clear : in std_logic; -- reset pending interrupt pending : out std_logic -- the output request ); end intstate; architecture rtl of intstate is signal flag : std_logic; begin -- TODO: add minimum interarrival time process(clk, reset) begin if reset='1' then flag <= '0'; elsif rising_edge(clk) then if ack='1' or clear='1' then flag <= '0'; elsif irq='1' then flag <= '1'; end if; end if; end process; pending <= flag and ena; end rtl; -- -- the sc_sys component -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.jop_types.all; entity sc_sys is generic (addr_bits : integer; clk_freq : integer; cpu_id : integer; cpu_cnt : integer; num_io_int : integer := 2); -- a default value to play with SW interrupts port ( clk : in std_logic; reset : in std_logic; -- SimpCon interface address : in std_logic_vector(addr_bits-1 downto 0); wr_data : in std_logic_vector(31 downto 0); rd, wr : in std_logic; rd_data : out std_logic_vector(31 downto 0); rdy_cnt : out unsigned(1 downto 0); -- -- Interrupts from IO devices -- irq_in : out irq_bcf_type; irq_out : in irq_ack_type; exc_req : in exception_type; io_int : in std_logic_vector(num_io_int-1 downto 0) := "00"; sync_out : in sync_out_type := NO_SYNC; sync_in : out sync_in_type; wd : out std_logic -- remove the comment for RAM access counting -- ram_count : in std_logic ); end sc_sys ; architecture rtl of sc_sys is signal clock_cnt : std_logic_vector(31 downto 0); signal pre_scale : std_logic_vector(7 downto 0); signal us_cnt : std_logic_vector(31 downto 0); constant div_val : integer := clk_freq/1000000-1; signal timer_int : std_logic; signal timer_cnt : std_logic_vector(31 downto 0); signal timer_equ : std_logic; signal timer_dly : std_logic; signal exc_type : std_logic_vector(7 downto 0); signal cpu_identity : std_logic_vector(31 downto 0); signal lock_reqest : std_logic; -- remove the comment for RAM access counting -- signal ram_counter : std_logic_vector(31 downto 0); signal cnt_ena : unsigned(31 downto 0); -- -- signals for interrupt handling -- signal int_pend : std_logic; signal int_ena : std_logic; signal exc_pend : std_logic; signal irq_gate : std_logic; signal irq_dly : std_logic; signal exc_dly : std_logic; -- -- signals for interrupt source state machines -- constant NUM_INT : integer := num_io_int+1; -- plus timer interrupt signal hwreq : std_logic_vector(NUM_INT-1 downto 0); signal swreq : std_logic_vector(NUM_INT-1 downto 0); signal intreq : std_logic_vector(NUM_INT-1 downto 0); signal mask : std_logic_vector(NUM_INT-1 downto 0); signal ack : std_logic_vector(NUM_INT-1 downto 0); signal pending : std_logic_vector(NUM_INT-1 downto 0); signal prioint : std_logic_vector(4 downto 0); signal intnr : std_logic_vector(4 downto 0); -- processing int number signal clearall : std_logic; begin cpu_identity <= std_logic_vector(to_unsigned(cpu_id,32)); rdy_cnt <= "11" when (sync_out.halted='1' and lock_reqest='1') else "00"; -- -- read cnt values -- process(clk, reset) begin if reset='1' then rd_data <= (others => '0'); elsif rising_edge(clk) then if rd='1' then case address(3 downto 0) is when "0000" => rd_data <= clock_cnt; when "0001" => rd_data <= us_cnt; when "0010" => rd_data(4 downto 0) <= intnr; rd_data(31 downto 5) <= (others => '0'); when "0100" => rd_data(7 downto 0) <= exc_type; rd_data(31 downto 8) <= (others => '0'); when "0101" => rd_data(0) <= lock_reqest; rd_data(31 downto 1) <= (others => '0'); when "0110" => rd_data <= cpu_identity; when "0111" => rd_data(0) <= sync_out.s_out; rd_data(31 downto 1) <= (others => '0'); -- remove the comment for RAM access counting -- when "1010" => -- rd_data(31 downto 0) <= ram_counter; when "1011" => rd_data <= std_logic_vector(to_unsigned(cpu_cnt, 32)); when others => -- nothing end case; end if; end if; end process; -- -- compare timer value and us counter -- and generate single shot -- process(us_cnt, timer_cnt) begin timer_equ <= '0'; if us_cnt = timer_cnt then timer_equ <= '1'; end if; end process; process(clk, reset) begin if reset='1' then timer_dly <= '0'; elsif rising_edge(clk) then timer_dly <= timer_equ; end if; end process; timer_int <= timer_equ and not timer_dly; -- -- int processing from timer and yield request -- hwreq(0) <= timer_int; hwreq(NUM_INT-1 downto 1) <= io_int; process(prioint, irq_out.ack_irq) begin ack <= (others => '0'); ack(to_integer(unsigned(prioint))) <= irq_out.ack_irq; end process; gen_int: for i in 0 to NUM_INT-1 generate intreq(i) <= hwreq(i) or swreq(i); cis: entity work.intstate port map(clk, reset, irq => intreq(i), ena => mask(i), ack => ack(i), clear => clearall, pending => pending(i) ); end generate; -- find highest priority pending interrupt process(pending) begin int_pend <= '0'; prioint <= (others => '0'); for i in NUM_INT-1 downto 0 loop if pending(i)='1' then int_pend <= '1'; prioint <= std_logic_vector(to_unsigned(i, 5)); exit; end if; end loop; end process; -- -- interrupt processing -- process(clk, reset) begin if reset='1' then irq_dly <= '0'; exc_dly <= '0'; intnr <= (others => '0'); elsif rising_edge(clk) then irq_dly <= irq_gate; exc_dly <= exc_pend; -- save processing interrupt number if irq_out.ack_irq='1' then intnr <= prioint; end if; end if; end process; irq_gate <= int_pend and int_ena; irq_in.irq <= irq_gate and not irq_dly; irq_in.exc <= exc_pend and not exc_dly; irq_in.ena <= int_ena; -- -- counters -- pre_scale is 8 bit => fmax = 255 MHz -- process(clk, reset) begin if (reset='1') then clock_cnt <= (others => '0'); us_cnt <= (others => '0'); pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); elsif rising_edge(clk) then clock_cnt <= std_logic_vector(unsigned(clock_cnt) + 1); pre_scale <= std_logic_vector(unsigned(pre_scale) - 1); if pre_scale = "00000000" then pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); us_cnt <= std_logic_vector(unsigned(us_cnt) + 1); end if; end if; end process; -- -- io write processing and exception processing -- process(clk, reset) begin if (reset='1') then int_ena <= '0'; timer_cnt <= (others => '0'); wd <= '0'; sync_in.s_in <= '0'; sync_in.lock_req <= '0'; lock_reqest <= '0'; exc_type <= (others => '0'); exc_pend <= '0'; swreq <= (others => '0'); mask <= (others => '0'); clearall <= '0'; elsif rising_edge(clk) then exc_pend <= '0'; swreq <= (others => '0'); clearall <= '0'; -- disable interrupts on a taken interrupt or excption if irq_out.ack_irq='1' or irq_out.ack_exc='1' then int_ena <= '0'; end if; -- exceptions from core or memory if exc_req.spov='1' then exc_type(2 downto 0) <= EXC_SPOV; exc_pend <= '1'; end if; if exc_req.np='1' then exc_type(2 downto 0) <= EXC_NP; exc_pend <= '1'; end if; if exc_req.ab='1' then exc_type(2 downto 0) <= EXC_AB; exc_pend <= '1'; end if; if wr='1' then case address(3 downto 0) is when "0000" => int_ena <= wr_data(0); when "0001" => timer_cnt <= wr_data; when "0010" => swreq(to_integer(unsigned(wr_data))) <= '1'; when "0011" => wd <= wr_data(0); when "0100" => exc_type <= wr_data(7 downto 0); exc_pend <= '1'; when "0101" => sync_in.lock_req <= wr_data(0); lock_reqest <= wr_data(0); when "0110" => -- nothing, processor id is read only when "0111" => sync_in.s_in <= wr_data(0); when "1000" => mask <= wr_data(NUM_INT-1 downto 0); when "1001" => clearall <= '1'; when "1010" => -- nothing, ram_counter is read only when others => end case; end if; end if; end process; -- remove the comment for RAM access counting -- process(clk, reset) -- begin -- if reset = '1' then -- ram_counter <= (others => '0'); -- elsif rising_edge(clk) then -- if (ram_count='0') then -- ram_counter <= std_logic_vector(unsigned(ram_counter) + 1); -- end if; -- end if; -- end process; end rtl; @ 1.12 log @global interrupt enable in bcfetch (bug fix) @ text @d112 1 d233 2 @ 1.11 log @JOP goes GPL @ text @d167 2 d327 1 @ 1.10 log @no message @ text @d2 21 @ 1.9 log @included atomic @ text @a100 1 atomic : in std_logic; @ 1.8 log @Memory access counter included @ text @d101 1 @ 1.7 log @global lock redesign @ text @d117 3 d142 3 d187 2 a188 2 case address(2 downto 0) is when "000" => d190 1 a190 1 when "001" => d192 1 a192 1 when "010" => d195 1 a195 1 when "100" => d198 1 a198 1 when "101" => d201 1 a201 1 when "110" => d203 1 a203 2 -- when "111" => when others => d206 5 d400 4 a403 1 -- when "1001" => a404 1 clearall <= '1'; d411 12 @ 1.6 log @comments @ text @d27 1 a27 1 -- d137 2 a138 2 signal cpu_identity : std_logic_vector(31 downto 0); signal rdy_cnt_help : std_logic; d168 1 a168 1 rdy_cnt <= "11" when sync_out.release='1' else "00"; d193 1 a193 1 rd_data(0) <= rdy_cnt_help; d333 2 a334 2 sync_in.lock <= '0'; rdy_cnt_help <= '0'; d382 2 a383 2 sync_in.lock <= wr_data(0); rdy_cnt_help <= wr_data(0); @ 1.5 log @new interrupt controller @ text @d26 1 a26 1 -- 2007-12-02 interrupt processing redesign d91 1 a91 1 num_io_int : integer := 2); @ 1.4 log @Move most interrupt logic to sc_sys. Interrupt ack from jfetch, interrupt disable on handling. @ text @d11 1 a11 1 -- 1 read 1 MHz counter, write timer val (us) + irq ack d29 51 d90 2 a91 1 cpu_id : integer); d110 2 a129 4 signal yield_int : std_logic; signal timer : std_logic; signal yield : std_logic; d151 14 d176 1 a176 1 if (reset='1') then d186 3 d218 2 a219 2 process(clk, reset, timer_equ) begin if (reset='1') then a230 1 process(clk, reset) begin d232 2 a233 16 if (reset='1') then timer <= '0'; yield <= '0'; elsif rising_edge(clk) then if irq_out.ack_irq='1' then timer <= '0'; yield <= '0'; else if timer_int='1' then timer <= '1'; end if; if yield_int='1' then yield <= '1'; end if; end if; end if; d235 3 d240 27 a266 1 int_pend <= timer or yield; d273 1 a273 1 if (reset='1') then d276 1 d282 4 d339 4 a344 1 yield_int <= '0'; d346 2 d369 2 a370 2 case address(2 downto 0) is when "000" => d372 1 a372 1 when "001" => d374 3 a376 3 when "010" => yield_int <= '1'; when "011" => d378 1 a378 1 when "100" => d381 1 a381 1 when "101" => d384 1 a384 1 when "110" => d386 5 d392 1 a392 2 -- when "111" => sync_in.s_in <= wr_data(0); @ 1.3 log @additional signal from bcfetch to sc_sys (int ack) @ text @d26 2 a76 1 signal int_ack : std_logic; d81 1 a81 1 signal irq_cnt : std_logic_vector(31 downto 0); d91 10 d144 1 a144 1 process(us_cnt, irq_cnt) begin d146 1 a146 1 if us_cnt = irq_cnt then d164 1 a164 1 process(clk, reset, timer_int, yield_int) begin d170 1 a170 1 if int_ack='1' then d185 24 a208 1 irq_in.irq <= timer or yield; d243 2 a244 3 irq_in.irq_ena <= '0'; irq_cnt <= (others => '0'); int_ack <= '0'; d251 1 a251 1 irq_in.exc_int <= '0'; a254 1 int_ack <= '0'; d256 1 d258 4 a261 1 irq_in.exc_int <= '0'; d263 1 d266 1 a266 1 irq_in.exc_int <= '1'; d270 1 a270 1 irq_in.exc_int <= '1'; d274 1 a274 1 irq_in.exc_int <= '1'; d280 1 a280 1 irq_in.irq_ena <= wr_data(0); d282 1 a282 2 irq_cnt <= wr_data; int_ack <= '1'; d289 1 a289 1 irq_in.exc_int <= '1'; @ 1.2 log @added global lock synchronization @ text @d6 1 a6 1 -- Author: Martin Schoeberl martin@@good-ear.com d53 2 a54 1 irq_in : out irq_in_type; @ 1.1 log @no message @ text @d25 1 a25 1 -- d56 1 a56 1 sync_out : in sync_out_type; d86 2 a87 1 d92 2 a93 2 rdy_cnt <= "00"; -- no wait states d113 3 d213 2 d253 3 @