Skip to content
Snippets Groups Projects
Commit fb094809 authored by Tristan Gingold's avatar Tristan Gingold
Browse files

rtl: triplicate cpu, add cpu voter

parent ac655fe9
No related merge requests found
files = ['hydra_core.vhd', 'hydra_iram.vhd', 'hydra_dram.vhd', files = ['hydra_core.vhd', 'hydra_iram.vhd', 'hydra_dram.vhd',
'hydra_supervisor_regs.vhd'] 'hydra_supervisor_regs.vhd', 'hydra_triple_cpu.vhd']
...@@ -91,6 +91,7 @@ architecture arch of hydra_core is ...@@ -91,6 +91,7 @@ architecture arch of hydra_core is
signal im_rd, im_valid : std_logic; signal im_rd, im_valid : std_logic;
signal im1_done, im1_dm_en, im1_err : std_logic; signal im1_done, im1_dm_en, im1_err : std_logic;
signal im2_err, im2_valid : std_logic; signal im2_err, im2_valid : std_logic;
signal err_cpu : std_logic;
signal dm_addr, dm_data_s, dm_data_l : std_logic_vector(31 downto 0); signal dm_addr, dm_data_s, dm_data_l : std_logic_vector(31 downto 0);
signal dm_data_select : std_logic_vector(3 downto 0); signal dm_data_select : std_logic_vector(3 downto 0);
...@@ -126,22 +127,17 @@ architecture arch of hydra_core is ...@@ -126,22 +127,17 @@ architecture arch of hydra_core is
signal wd_period, wd_period_val, wd_counter, wd_key_val : std_logic_vector(31 downto 0); signal wd_period, wd_period_val, wd_counter, wd_key_val : std_logic_vector(31 downto 0);
signal wd_period_wr, wd_key_wr, wd_timeout : std_logic; signal wd_period_wr, wd_key_wr, wd_timeout : std_logic;
signal force_divergence, force_divergence_d, dm_force_divergence : std_logic;
begin begin
cpu_rst <= cpu_rst_err or (not cpu_rst_n_i); cpu_rst <= cpu_rst_err or (not cpu_rst_n_i);
dwb_o <= dwb_out; dwb_o <= dwb_out;
U_cpu_core : urv_cpu U_cpu_core : entity work.hydra_triple_cpu
generic map (
g_timer_frequency => 0,
g_with_hw_debug => 0,
g_with_hw_mul => 0,
g_with_hw_div => 0
)
port map ( port map (
clk_i => clk_sys_i, clk_i => clk_sys_i,
rst_i => cpu_rst, rst_i => cpu_rst,
irq_i => '0',
im_addr_o => im_addr, im_addr_o => im_addr,
im_rd_o => im_rd, im_rd_o => im_rd,
im_data_i => im_data, im_data_i => im_data,
...@@ -154,14 +150,9 @@ begin ...@@ -154,14 +150,9 @@ begin
dm_load_o => dm_load, dm_load_o => dm_load,
dm_load_done_i => dm_load_done, dm_load_done_i => dm_load_done,
dm_store_done_i => dm_store_done, dm_store_done_i => dm_store_done,
dbg_force_i => '0',
dbg_enabled_o => open, dm_force_divergence_i => dm_force_divergence,
dbg_insn_i => x"0000_0000", err_cpu_o => err_cpu);
dbg_insn_set_i => '0',
dbg_insn_ready_o => open,
dbg_mbx_data_i => x"0000_0000",
dbg_mbx_write_i => '0',
dbg_mbx_data_o => open);
-- Add registers on uRV data bus -- Add registers on uRV data bus
process (clk_sys_i) process (clk_sys_i)
...@@ -259,6 +250,8 @@ begin ...@@ -259,6 +250,8 @@ begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
dm_store_done <= '0'; dm_store_done <= '0';
dm_load_done <= '0'; dm_load_done <= '0';
dm_force_divergence <= '0';
force_divergence_d <= force_divergence;
if rst_n_i = '0' then if rst_n_i = '0' then
dwb_out.cyc <= '0'; dwb_out.cyc <= '0';
...@@ -325,14 +318,19 @@ begin ...@@ -325,14 +318,19 @@ begin
or (dm_select_wb = '0' and sv_wb_in.ack = '1') or (dm_select_wb = '0' and sv_wb_in.ack = '1')
then then
if dm_wb_write = '0' then if dm_wb_write = '0' then
-- Read acked
dm_load_done <= '1';
reg_dm_load <= '0';
if dm_select_wb = '1' then if dm_select_wb = '1' then
-- from peripheral
dm_wb_rdata <= f_x_to_zero(dwb_i.dat); dm_wb_rdata <= f_x_to_zero(dwb_i.dat);
else else
-- from supervisor
dm_wb_rdata <= sv_wb_in.dat; dm_wb_rdata <= sv_wb_in.dat;
dm_force_divergence <= force_divergence_d;
end if; end if;
dm_load_done <= '1';
reg_dm_load <= '0';
else else
-- Write acked
dm_store_done <= '1'; dm_store_done <= '1';
reg_dm_store <= '0'; reg_dm_store <= '0';
end if; end if;
...@@ -374,7 +372,7 @@ begin ...@@ -374,7 +372,7 @@ begin
end process p_wishbone_master; end process p_wishbone_master;
-- Stats -- Stats
p_stats: process (clk_sys_i) p_ecc_stats: process (clk_sys_i)
begin begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
if rst_n_i = '0' then if rst_n_i = '0' then
...@@ -400,7 +398,7 @@ begin ...@@ -400,7 +398,7 @@ begin
end process; end process;
-- Watchdog -- Watchdog
process (clk_sys_i) p_watchdog: process (clk_sys_i)
begin begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
if rst_n_i = '0' then if rst_n_i = '0' then
...@@ -418,11 +416,12 @@ begin ...@@ -418,11 +416,12 @@ begin
-- Timeout -- Timeout
wd_timeout <= '1'; wd_timeout <= '1';
wd_counter <= wd_period; wd_counter <= wd_period;
elsif wd_key_wr = '1' and wd_key_val = x"c0423bc9" then elsif cpu_rst = '1' or (wd_key_wr = '1' and wd_key_val = x"c0423bc9") then
-- Key -> reload -- Key -> reload
-- Also restart the watchdog if the cpu is reset.
wd_counter <= wd_period; wd_counter <= wd_period;
elsif cpu_rst = '0' then else
-- Decrement the watchdog only when the CPU is running -- Decrement the watchdog
wd_counter <= std_logic_vector(unsigned(wd_counter) - 1); wd_counter <= std_logic_vector(unsigned(wd_counter) - 1);
end if; end if;
end if; end if;
...@@ -431,7 +430,7 @@ begin ...@@ -431,7 +430,7 @@ begin
end process; end process;
-- Supervisor -- Supervisor
process (clk_sys_i) p_sv: process (clk_sys_i)
begin begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
if rst_n_i = '0' then if rst_n_i = '0' then
...@@ -441,10 +440,10 @@ begin ...@@ -441,10 +440,10 @@ begin
cpu_rst_err <= '0'; cpu_rst_err <= '0';
else else
cpu_rst_err <= '0'; cpu_rst_err <= '0';
if dram_ecc_fatal = '1' or iram_ecc_fatal = '1' or wd_timeout = '1' then if dram_ecc_fatal = '1' or iram_ecc_fatal = '1' or wd_timeout = '1' or err_cpu = '1' then
-- Reset CPU on error. -- Reset CPU on error.
cpu_rst_err <= '1'; cpu_rst_err <= '1';
reset_cause_cpu <= '0'; reset_cause_cpu <= err_cpu;
reset_cause_ecc <= dram_ecc_fatal or iram_ecc_fatal; reset_cause_ecc <= dram_ecc_fatal or iram_ecc_fatal;
reset_cause_wd <= wd_timeout; reset_cause_wd <= wd_timeout;
end if; end if;
...@@ -461,6 +460,11 @@ begin ...@@ -461,6 +460,11 @@ begin
reset_cause_cpu_i => reset_cause_cpu, reset_cause_cpu_i => reset_cause_cpu,
reset_cause_ecc_i => reset_cause_ecc, reset_cause_ecc_i => reset_cause_ecc,
reset_cause_watchdog_i => reset_cause_wd, reset_cause_watchdog_i => reset_cause_wd,
cpu_status_i => "000",
cpu_boot_done_i => '0',
cpu_recovery_i => '0',
force_divergence_i => x"00000000",
force_divergence_rd_o => force_divergence,
wd_period_i => wd_period, wd_period_i => wd_period,
wd_period_o => wd_period_val, wd_period_o => wd_period_val,
wd_period_wr_o => wd_period_wr, wd_period_wr_o => wd_period_wr,
......
...@@ -23,6 +23,34 @@ memory-map: ...@@ -23,6 +23,34 @@ memory-map:
name: watchdog name: watchdog
description: Watchdog timeout description: Watchdog timeout
range: 2 range: 2
- reg:
name: cpu
description: state of cpus
width: 32
access: rw
x-hdl:
type: wire
write-strobe: True
children:
- field:
name: status
description: Status of cpus, set when running (RO)
range: 2-0
- field:
name: boot_done
description: Set on reset to disable compairison. To be cleared after initialization
range: 8
- field:
name: recovery
description: Set to start recovery (will reset all the cpus)
range: 9
- reg:
name: force_divergence
description: Each cpu will read a different value from this registers
width: 32
access: ro
x-hdl:
read-strobe: True
- reg: - reg:
name: wd_period name: wd_period
description: Nbr of cycles before watchdog timeout. Can be written once per reset description: Nbr of cycles before watchdog timeout. Can be written once per reset
......
...@@ -22,6 +22,22 @@ entity hydra_supervisor_regs is ...@@ -22,6 +22,22 @@ entity hydra_supervisor_regs is
-- Watchdog timeout -- Watchdog timeout
reset_cause_watchdog_i : in std_logic; reset_cause_watchdog_i : in std_logic;
-- state of cpus
-- Status of cpus, set when running (RO)
cpu_status_i : in std_logic_vector(2 downto 0);
cpu_status_o : out std_logic_vector(2 downto 0);
-- Set on reset to disable compairison. To be cleared after initialization
cpu_boot_done_i : in std_logic;
cpu_boot_done_o : out std_logic;
-- Set to start recovery (will reset all the cpus)
cpu_recovery_i : in std_logic;
cpu_recovery_o : out std_logic;
cpu_wr_o : out std_logic;
-- Each cpu will read a different value from this registers
force_divergence_i : in std_logic_vector(31 downto 0);
force_divergence_rd_o : out std_logic;
-- Nbr of cycles before watchdog timeout. Can be written once per reset -- Nbr of cycles before watchdog timeout. Can be written once per reset
wd_period_i : in std_logic_vector(31 downto 0); wd_period_i : in std_logic_vector(31 downto 0);
wd_period_o : out std_logic_vector(31 downto 0); wd_period_o : out std_logic_vector(31 downto 0);
...@@ -66,6 +82,7 @@ architecture syn of hydra_supervisor_regs is ...@@ -66,6 +82,7 @@ architecture syn of hydra_supervisor_regs is
signal ack_int : std_logic; signal ack_int : std_logic;
signal wb_rip : std_logic; signal wb_rip : std_logic;
signal wb_wip : std_logic; signal wb_wip : std_logic;
signal cpu_wreq : std_logic;
signal wd_period_wreq : std_logic; signal wd_period_wreq : std_logic;
signal wd_key_reg : std_logic_vector(31 downto 0); signal wd_key_reg : std_logic_vector(31 downto 0);
signal wd_key_wreq : std_logic; signal wd_key_wreq : std_logic;
...@@ -133,6 +150,14 @@ begin ...@@ -133,6 +150,14 @@ begin
-- Register reset_cause -- Register reset_cause
-- Register cpu
cpu_status_o <= wr_dat_d0(2 downto 0);
cpu_boot_done_o <= wr_dat_d0(8);
cpu_recovery_o <= wr_dat_d0(9);
cpu_wr_o <= cpu_wreq;
-- Register force_divergence
-- Register wd_period -- Register wd_period
wd_period_o <= wr_dat_d0; wd_period_o <= wr_dat_d0;
wd_period_wr_o <= wd_period_wreq; wd_period_wr_o <= wd_period_wreq;
...@@ -198,6 +223,7 @@ begin ...@@ -198,6 +223,7 @@ begin
-- Process for write requests. -- Process for write requests.
process (wr_adr_d0, wr_req_d0, wd_key_wack, iram_scrub_wack, dram_scrub_wack) begin process (wr_adr_d0, wr_req_d0, wd_key_wack, iram_scrub_wack, dram_scrub_wack) begin
cpu_wreq <= '0';
wd_period_wreq <= '0'; wd_period_wreq <= '0';
wd_key_wreq <= '0'; wd_key_wreq <= '0';
iram_scrub_wreq <= '0'; iram_scrub_wreq <= '0';
...@@ -207,33 +233,40 @@ begin ...@@ -207,33 +233,40 @@ begin
-- Reg reset_cause -- Reg reset_cause
wr_ack_int <= wr_req_d0; wr_ack_int <= wr_req_d0;
when "0001" => when "0001" =>
-- Reg cpu
cpu_wreq <= wr_req_d0;
wr_ack_int <= wr_req_d0;
when "0010" =>
-- Reg force_divergence
wr_ack_int <= wr_req_d0;
when "0011" =>
-- Reg wd_period -- Reg wd_period
wd_period_wreq <= wr_req_d0; wd_period_wreq <= wr_req_d0;
wr_ack_int <= wr_req_d0; wr_ack_int <= wr_req_d0;
when "0010" => when "0100" =>
-- Reg wd_count -- Reg wd_count
wr_ack_int <= wr_req_d0; wr_ack_int <= wr_req_d0;
when "0011" => when "0101" =>
-- Reg wd_key -- Reg wd_key
wd_key_wreq <= wr_req_d0; wd_key_wreq <= wr_req_d0;
wr_ack_int <= wd_key_wack; wr_ack_int <= wd_key_wack;
when "0100" => when "0110" =>
-- Reg iram_ecc_corr -- Reg iram_ecc_corr
wr_ack_int <= wr_req_d0; wr_ack_int <= wr_req_d0;
when "0101" => when "0111" =>
-- Reg iram_ecc_uncorr -- Reg iram_ecc_uncorr
wr_ack_int <= wr_req_d0; wr_ack_int <= wr_req_d0;
when "0110" => when "1000" =>
-- Reg dram_ecc_corr -- Reg dram_ecc_corr
wr_ack_int <= wr_req_d0; wr_ack_int <= wr_req_d0;
when "0111" => when "1001" =>
-- Reg dram_ecc_uncorr -- Reg dram_ecc_uncorr
wr_ack_int <= wr_req_d0; wr_ack_int <= wr_req_d0;
when "1000" => when "1010" =>
-- Reg iram_scrub -- Reg iram_scrub
iram_scrub_wreq <= wr_req_d0; iram_scrub_wreq <= wr_req_d0;
wr_ack_int <= iram_scrub_wack; wr_ack_int <= iram_scrub_wack;
when "1001" => when "1011" =>
-- Reg dram_scrub -- Reg dram_scrub
dram_scrub_wreq <= wr_req_d0; dram_scrub_wreq <= wr_req_d0;
wr_ack_int <= dram_scrub_wack; wr_ack_int <= dram_scrub_wack;
...@@ -244,11 +277,13 @@ begin ...@@ -244,11 +277,13 @@ begin
-- Process for read requests. -- Process for read requests.
process (adr_int, rd_req_int, reset_cause_cpu_i, reset_cause_ecc_i, process (adr_int, rd_req_int, reset_cause_cpu_i, reset_cause_ecc_i,
reset_cause_watchdog_i, wd_period_i, wd_count_i, iram_ecc_corr_i, reset_cause_watchdog_i, cpu_status_i, cpu_boot_done_i, cpu_recovery_i,
force_divergence_i, wd_period_i, wd_count_i, iram_ecc_corr_i,
iram_ecc_uncorr_i, dram_ecc_corr_i, dram_ecc_uncorr_i, iram_ecc_uncorr_i, dram_ecc_corr_i, dram_ecc_uncorr_i,
iram_scrub_period_reg, dram_scrub_period_reg) begin iram_scrub_period_reg, dram_scrub_period_reg) begin
-- By default ack read requests -- By default ack read requests
rd_dat_d0 <= (others => 'X'); rd_dat_d0 <= (others => 'X');
force_divergence_rd_o <= '0';
case adr_int(5 downto 2) is case adr_int(5 downto 2) is
when "0000" => when "0000" =>
-- Reg reset_cause -- Reg reset_cause
...@@ -258,38 +293,51 @@ begin ...@@ -258,38 +293,51 @@ begin
rd_dat_d0(2) <= reset_cause_watchdog_i; rd_dat_d0(2) <= reset_cause_watchdog_i;
rd_dat_d0(31 downto 3) <= (others => '0'); rd_dat_d0(31 downto 3) <= (others => '0');
when "0001" => when "0001" =>
-- Reg cpu
rd_ack_d0 <= rd_req_int;
rd_dat_d0(2 downto 0) <= cpu_status_i;
rd_dat_d0(7 downto 3) <= (others => '0');
rd_dat_d0(8) <= cpu_boot_done_i;
rd_dat_d0(9) <= cpu_recovery_i;
rd_dat_d0(31 downto 10) <= (others => '0');
when "0010" =>
-- Reg force_divergence
force_divergence_rd_o <= rd_req_int;
rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= force_divergence_i;
when "0011" =>
-- Reg wd_period -- Reg wd_period
rd_ack_d0 <= rd_req_int; rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= wd_period_i; rd_dat_d0 <= wd_period_i;
when "0010" => when "0100" =>
-- Reg wd_count -- Reg wd_count
rd_ack_d0 <= rd_req_int; rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= wd_count_i; rd_dat_d0 <= wd_count_i;
when "0011" => when "0101" =>
-- Reg wd_key -- Reg wd_key
rd_ack_d0 <= rd_req_int; rd_ack_d0 <= rd_req_int;
when "0100" => when "0110" =>
-- Reg iram_ecc_corr -- Reg iram_ecc_corr
rd_ack_d0 <= rd_req_int; rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= iram_ecc_corr_i; rd_dat_d0 <= iram_ecc_corr_i;
when "0101" => when "0111" =>
-- Reg iram_ecc_uncorr -- Reg iram_ecc_uncorr
rd_ack_d0 <= rd_req_int; rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= iram_ecc_uncorr_i; rd_dat_d0 <= iram_ecc_uncorr_i;
when "0110" => when "1000" =>
-- Reg dram_ecc_corr -- Reg dram_ecc_corr
rd_ack_d0 <= rd_req_int; rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= dram_ecc_corr_i; rd_dat_d0 <= dram_ecc_corr_i;
when "0111" => when "1001" =>
-- Reg dram_ecc_uncorr -- Reg dram_ecc_uncorr
rd_ack_d0 <= rd_req_int; rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= dram_ecc_uncorr_i; rd_dat_d0 <= dram_ecc_uncorr_i;
when "1000" => when "1010" =>
-- Reg iram_scrub -- Reg iram_scrub
rd_ack_d0 <= rd_req_int; rd_ack_d0 <= rd_req_int;
rd_dat_d0(15 downto 0) <= iram_scrub_period_reg; rd_dat_d0(15 downto 0) <= iram_scrub_period_reg;
rd_dat_d0(31 downto 16) <= (others => '0'); rd_dat_d0(31 downto 16) <= (others => '0');
when "1001" => when "1011" =>
-- Reg dram_scrub -- Reg dram_scrub
rd_ack_d0 <= rd_req_int; rd_ack_d0 <= rd_req_int;
rd_dat_d0(15 downto 0) <= dram_scrub_period_reg; rd_dat_d0(15 downto 0) <= dram_scrub_period_reg;
......
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.urv_pkg.all;
entity hydra_triple_cpu is
port (
clk_i : in std_logic;
rst_i : in std_logic;
im_data_i : in std_logic_vector (31 downto 0);
im_valid_i : in std_logic;
im_addr_o : out std_logic_vector (31 downto 0);
im_rd_o : out std_logic;
dm_addr_o : out std_logic_vector (31 downto 0);
dm_data_s_o : out std_logic_vector (31 downto 0);
dm_data_l_i : in std_logic_vector (31 downto 0);
dm_load_done_i : in std_logic;
dm_store_done_i : in std_logic;
dm_data_select_o : out std_logic_vector (3 downto 0);
dm_store_o : out std_logic;
dm_load_o : out std_logic;
-- If set, will give different values to each cpu.
dm_force_divergence_i : in std_logic;
-- Set to 1 if an output differs
err_cpu_o : out std_logic);
end entity hydra_triple_cpu;
architecture arch of hydra_triple_cpu is
type t_slv32_x3 is array(1 to 3) of std_logic_vector(31 downto 0);
type t_slv4_x3 is array(1 to 3) of std_logic_vector(3 downto 0);
subtype t_sl_x3 is std_logic_vector(1 to 3);
signal im_addr, dm_addr, dm_data_s, dm_data_l : t_slv32_x3;
signal err_im_addr, err_dm_addr, err_dm_data_s : std_logic;
signal dm_data_select : t_slv4_x3;
signal err_dm_data_select : std_logic;
signal im_rd, dm_store, dm_load : t_sl_x3;
signal err_dm_store, err_dm_load, err_im_rd : std_logic;
signal en_im, en_dm_load, en_dm_store : std_logic;
begin
gen_triple: for i in 1 to 3 generate
inst_cpu : urv_cpu
generic map (
g_timer_frequency => 0,
g_with_hw_debug => 0,
g_with_hw_mul => 0,
g_with_hw_div => 0
)
port map (
clk_i => clk_i,
rst_i => rst_i,
irq_i => '0',
im_addr_o => im_addr(i),
im_rd_o => im_rd(i),
im_data_i => im_data_i,
im_valid_i => im_valid_i,
dm_addr_o => dm_addr(i),
dm_data_s_o => dm_data_s(i),
dm_data_l_i => dm_data_l(i),
dm_data_select_o => dm_data_select(i),
dm_store_o => dm_store(i),
dm_load_o => dm_load(i),
dm_load_done_i => dm_load_done_i,
dm_store_done_i => dm_store_done_i,
dbg_force_i => '0',
dbg_enabled_o => open,
dbg_insn_i => x"0000_0000",
dbg_insn_set_i => '0',
dbg_insn_ready_o => open,
dbg_mbx_data_i => x"0000_0000",
dbg_mbx_write_i => '0',
dbg_mbx_data_o => open);
end generate;
inst_voter_im_addr: entity work.voter_vec_status
generic map (
g_WIDTH => 32
)
port map (
a => im_addr(1),
b => im_addr(2),
c => im_addr(3),
res => im_addr_o,
err => err_im_addr
);
inst_voter_dm_addr: entity work.voter_vec_status
generic map (
g_WIDTH => 32
)
port map (
a => dm_addr(1),
b => dm_addr(2),
c => dm_addr(3),
res => dm_addr_o,
err => err_dm_addr
);
inst_voter_dm_data_s: entity work.voter_vec_status
generic map (
g_WIDTH => 32
)
port map (
a => dm_data_s(1),
b => dm_data_s(2),
c => dm_data_s(3),
res => dm_data_s_o,
err => err_dm_data_s
);
inst_voter_dm_data_select: entity work.voter_vec_status
generic map (
g_WIDTH => 4
)
port map (
a => dm_data_select(1),
b => dm_data_select(2),
c => dm_data_select(3),
res => dm_data_select_o,
err => err_dm_data_select
);
inst_voter_im_rd: entity work.voter_status
port map (
inp => im_rd,
res => im_rd_o,
err => err_im_rd
);
inst_voter_dm_load: entity work.voter_status
port map (
inp => dm_load,
res => dm_load_o,
err => err_dm_load
);
inst_voter_dm_store: entity work.voter_status
port map (
inp => dm_store,
res => dm_store_o,
err => err_dm_store
);
dm_data_l(1) <= dm_data_l_i when dm_force_divergence_i = '0' else x"0000_0001";
dm_data_l(2) <= dm_data_l_i when dm_force_divergence_i = '0' else x"0000_0002";
dm_data_l(3) <= dm_data_l_i when dm_force_divergence_i = '0' else x"0000_0004";
en_im <= im_rd(1) or im_rd(2) or im_rd(3);
en_dm_load <= dm_load(1) or dm_load(2) or dm_load(3);
en_dm_store <= dm_store(1) or dm_store(2) or dm_store(3);
err_cpu_o <= (en_im and err_im_addr) or err_im_rd
or ((en_dm_load or en_dm_store) and err_dm_addr)
or (en_dm_store and (err_dm_data_s or err_dm_data_select)) or err_dm_load or err_dm_store;
end arch;
#ifndef __CHEBY__HYDRA_SUPERVISOR_REGS__H__ #ifndef __CHEBY__HYDRA_SUPERVISOR_REGS__H__
#define __CHEBY__HYDRA_SUPERVISOR_REGS__H__ #define __CHEBY__HYDRA_SUPERVISOR_REGS__H__
#define HYDRA_SUPERVISOR_REGS_SIZE 40 /* 0x28 */ #define HYDRA_SUPERVISOR_REGS_SIZE 48 /* 0x30 */
/* Cause of a reset */ /* Cause of a reset */
#define HYDRA_SUPERVISOR_REGS_RESET_CAUSE 0x0UL #define HYDRA_SUPERVISOR_REGS_RESET_CAUSE 0x0UL
...@@ -8,35 +8,45 @@ ...@@ -8,35 +8,45 @@
#define HYDRA_SUPERVISOR_REGS_RESET_CAUSE_ECC 0x2UL #define HYDRA_SUPERVISOR_REGS_RESET_CAUSE_ECC 0x2UL
#define HYDRA_SUPERVISOR_REGS_RESET_CAUSE_WATCHDOG 0x4UL #define HYDRA_SUPERVISOR_REGS_RESET_CAUSE_WATCHDOG 0x4UL
/* state of cpus */
#define HYDRA_SUPERVISOR_REGS_CPU 0x4UL
#define HYDRA_SUPERVISOR_REGS_CPU_STATUS_MASK 0x7UL
#define HYDRA_SUPERVISOR_REGS_CPU_STATUS_SHIFT 0
#define HYDRA_SUPERVISOR_REGS_CPU_BOOT_DONE 0x100UL
#define HYDRA_SUPERVISOR_REGS_CPU_RECOVERY 0x200UL
/* Each cpu will read a different value from this registers */
#define HYDRA_SUPERVISOR_REGS_FORCE_DIVERGENCE 0x8UL
/* Nbr of cycles before watchdog timeout. Can be written once per reset */ /* Nbr of cycles before watchdog timeout. Can be written once per reset */
#define HYDRA_SUPERVISOR_REGS_WD_PERIOD 0x4UL #define HYDRA_SUPERVISOR_REGS_WD_PERIOD 0xcUL
#define HYDRA_SUPERVISOR_REGS_WD_PERIOD_PRESET 0x7d0UL #define HYDRA_SUPERVISOR_REGS_WD_PERIOD_PRESET 0x7d0UL
/* Current counter value (decremented) */ /* Current counter value (decremented) */
#define HYDRA_SUPERVISOR_REGS_WD_COUNT 0x8UL #define HYDRA_SUPERVISOR_REGS_WD_COUNT 0x10UL
/* Write 0xc0423bc9 to restart watchdog counter */ /* Write 0xc0423bc9 to restart watchdog counter */
#define HYDRA_SUPERVISOR_REGS_WD_KEY 0xcUL #define HYDRA_SUPERVISOR_REGS_WD_KEY 0x14UL
/* Number of ECC correctable errors for iram */ /* Number of ECC correctable errors for iram */
#define HYDRA_SUPERVISOR_REGS_IRAM_ECC_CORR 0x10UL #define HYDRA_SUPERVISOR_REGS_IRAM_ECC_CORR 0x18UL
/* Number of ECC uncorrectable errors for iram */ /* Number of ECC uncorrectable errors for iram */
#define HYDRA_SUPERVISOR_REGS_IRAM_ECC_UNCORR 0x14UL #define HYDRA_SUPERVISOR_REGS_IRAM_ECC_UNCORR 0x1cUL
/* Number of ECC correctable errors for dram */ /* Number of ECC correctable errors for dram */
#define HYDRA_SUPERVISOR_REGS_DRAM_ECC_CORR 0x18UL #define HYDRA_SUPERVISOR_REGS_DRAM_ECC_CORR 0x20UL
/* Number of ECC uncorrectable errors for dram */ /* Number of ECC uncorrectable errors for dram */
#define HYDRA_SUPERVISOR_REGS_DRAM_ECC_UNCORR 0x1cUL #define HYDRA_SUPERVISOR_REGS_DRAM_ECC_UNCORR 0x24UL
/* Maximum number of cycles between a scrub */ /* Maximum number of cycles between a scrub */
#define HYDRA_SUPERVISOR_REGS_IRAM_SCRUB 0x20UL #define HYDRA_SUPERVISOR_REGS_IRAM_SCRUB 0x28UL
#define HYDRA_SUPERVISOR_REGS_IRAM_SCRUB_PERIOD_MASK 0xffffUL #define HYDRA_SUPERVISOR_REGS_IRAM_SCRUB_PERIOD_MASK 0xffffUL
#define HYDRA_SUPERVISOR_REGS_IRAM_SCRUB_PERIOD_SHIFT 0 #define HYDRA_SUPERVISOR_REGS_IRAM_SCRUB_PERIOD_SHIFT 0
/* Maximum number of cycles between a scrub */ /* Maximum number of cycles between a scrub */
#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB 0x24UL #define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB 0x2cUL
#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_PERIOD_MASK 0xffffUL #define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_PERIOD_MASK 0xffffUL
#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_PERIOD_SHIFT 0 #define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_PERIOD_SHIFT 0
...@@ -44,31 +54,37 @@ struct hydra_supervisor_regs { ...@@ -44,31 +54,37 @@ struct hydra_supervisor_regs {
/* [0x0]: REG (ro) Cause of a reset */ /* [0x0]: REG (ro) Cause of a reset */
uint32_t reset_cause; uint32_t reset_cause;
/* [0x4]: REG (rw) Nbr of cycles before watchdog timeout. Can be written once per reset */ /* [0x4]: REG (rw) state of cpus */
uint32_t cpu;
/* [0x8]: REG (ro) Each cpu will read a different value from this registers */
uint32_t force_divergence;
/* [0xc]: REG (rw) Nbr of cycles before watchdog timeout. Can be written once per reset */
uint32_t wd_period; uint32_t wd_period;
/* [0x8]: REG (ro) Current counter value (decremented) */ /* [0x10]: REG (ro) Current counter value (decremented) */
uint32_t wd_count; uint32_t wd_count;
/* [0xc]: REG (wo) Write 0xc0423bc9 to restart watchdog counter */ /* [0x14]: REG (wo) Write 0xc0423bc9 to restart watchdog counter */
uint32_t wd_key; uint32_t wd_key;
/* [0x10]: REG (ro) Number of ECC correctable errors for iram */ /* [0x18]: REG (ro) Number of ECC correctable errors for iram */
uint32_t iram_ecc_corr; uint32_t iram_ecc_corr;
/* [0x14]: REG (ro) Number of ECC uncorrectable errors for iram */ /* [0x1c]: REG (ro) Number of ECC uncorrectable errors for iram */
uint32_t iram_ecc_uncorr; uint32_t iram_ecc_uncorr;
/* [0x18]: REG (ro) Number of ECC correctable errors for dram */ /* [0x20]: REG (ro) Number of ECC correctable errors for dram */
uint32_t dram_ecc_corr; uint32_t dram_ecc_corr;
/* [0x1c]: REG (ro) Number of ECC uncorrectable errors for dram */ /* [0x24]: REG (ro) Number of ECC uncorrectable errors for dram */
uint32_t dram_ecc_uncorr; uint32_t dram_ecc_uncorr;
/* [0x20]: REG (rw) Maximum number of cycles between a scrub */ /* [0x28]: REG (rw) Maximum number of cycles between a scrub */
uint32_t iram_scrub; uint32_t iram_scrub;
/* [0x24]: REG (rw) Maximum number of cycles between a scrub */ /* [0x2c]: REG (rw) Maximum number of cycles between a scrub */
uint32_t dram_scrub; uint32_t dram_scrub;
}; };
......
...@@ -114,10 +114,13 @@ main (void) ...@@ -114,10 +114,13 @@ main (void)
while (1) while (1)
uart_puts("Error\n"); uart_puts("Error\n");
} }
else {
while (1) { /* Read a different value. */
SUPERVISOR->wd_key = WD_KEY; v = SUPERVISOR->force_divergence;
uart_puts ("Hello diot.\n"); uart_put_hex_digit(v & 0x0f);
}
while (1) {
SUPERVISOR->wd_key = WD_KEY;
uart_puts ("Hello diot.\n");
} }
} }
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment