diff --git a/hdl/rtl/hydra_core.vhd b/hdl/rtl/hydra_core.vhd index 20e933223133f73a56fe9d83ca3a27506153b6a5..86651f8079c2f84faacb5075c829fae2e2c3d182 100644 --- a/hdl/rtl/hydra_core.vhd +++ b/hdl/rtl/hydra_core.vhd @@ -125,14 +125,15 @@ architecture arch of hydra_core is signal nbr_iram_scrub_corr : std_logic_vector (31 downto 0); signal nbr_dram_scrub_corr : std_logic_vector (31 downto 0); signal nbr_iram_scrub_uncorr_curr, nbr_iram_scrub_uncorr_last : std_logic_vector (15 downto 0); - signal nbr_dram_scrub_uncorr : std_logic_vector (31 downto 0); + signal nbr_dram_scrub_uncorr_curr, nbr_dram_scrub_uncorr_last : std_logic_vector (15 downto 0); signal nbr_iram_scrub_cycle : std_logic_vector (7 downto 0); + signal nbr_dram_scrub_cycle : std_logic_vector (7 downto 0); signal iram_ecc_err, iram_ecc_fatal : std_logic; signal iram_scrub_se, iram_scrub_de : std_logic; signal dram_ecc_err, dram_ecc_fatal : std_logic; signal dram_scrub_se, dram_scrub_de : std_logic; signal iram_scrub_en, dram_scrub_en : std_logic; - signal iram_scrub_cycle : std_logic; + signal iram_scrub_cycle, dram_scrub_cycle : std_logic; signal scrub_cfg_wr, scrub_cfg_iram_val, scrub_cfg_dram_val : std_logic; signal nbr_cpu_data_err : std_logic_vector (31 downto 0); signal nbr_cpu_iaddr_err : std_logic_vector (31 downto 0); @@ -283,6 +284,7 @@ begin ecc_fatal_o => dram_ecc_fatal, scrub_se_o => dram_scrub_se, scrub_de_o => dram_scrub_de, + scrub_cycle_o => dram_scrub_cycle, scrubber_period_i => dram_scrub_period ); @@ -429,7 +431,9 @@ begin nbr_iram_scrub_uncorr_curr <= (others => '0'); nbr_iram_scrub_uncorr_last <= (others => '0'); nbr_iram_scrub_cycle <= (others => '0'); - nbr_dram_scrub_uncorr <= (others => '0'); + nbr_dram_scrub_uncorr_curr <= (others => '0'); + nbr_dram_scrub_uncorr_last <= (others => '0'); + nbr_dram_scrub_cycle <= (others => '0'); else if iram_ecc_err = '1' then nbr_iram_ecc_corr <= std_logic_vector(unsigned(nbr_iram_ecc_corr) + 1); @@ -451,8 +455,13 @@ begin if dram_scrub_se = '1' then nbr_dram_scrub_corr <= std_logic_vector(unsigned(nbr_dram_scrub_corr) + 1); end if; - if dram_scrub_de = '1' then - nbr_dram_scrub_uncorr <= std_logic_vector(unsigned(nbr_dram_scrub_uncorr) + 1); + if dram_scrub_de = '1' and nbr_dram_scrub_uncorr_curr(15) /= '1' then + nbr_dram_scrub_uncorr_curr <= std_logic_vector(unsigned(nbr_dram_scrub_uncorr_curr) + 1); + end if; + if dram_scrub_cycle = '1' then + nbr_dram_scrub_uncorr_last <= nbr_dram_scrub_uncorr_curr; + nbr_dram_scrub_uncorr_curr <= (others => '0'); + nbr_dram_scrub_cycle <= std_logic_vector(unsigned(nbr_dram_scrub_cycle) + 1); end if; end if; end if; @@ -538,7 +547,9 @@ begin iram_scrub_cycle_i => nbr_iram_scrub_cycle, dram_ecc_se_i => nbr_dram_ecc_corr, dram_scrub_se_i => nbr_dram_scrub_corr, - dram_scrub_de_i => nbr_dram_scrub_uncorr, + dram_scrub_de_curr_i => nbr_dram_scrub_uncorr_curr, + dram_scrub_de_last_i => nbr_dram_scrub_uncorr_last, + dram_scrub_cycle_i => nbr_dram_scrub_cycle, cpu_data_err_i => nbr_cpu_data_err, cpu_iaddr_err_i => nbr_cpu_iaddr_err, dram_ecc_mask_o => dram_ecc_mask, diff --git a/hdl/rtl/hydra_dram.vhd b/hdl/rtl/hydra_dram.vhd index 4b52beffdd166835a98bec1f105f6d01136cf67b..be09c73e4db19435ac6193cf49f9397ecad1de7f 100644 --- a/hdl/rtl/hydra_dram.vhd +++ b/hdl/rtl/hydra_dram.vhd @@ -58,6 +58,7 @@ entity hydra_dram is ecc_fatal_o : out std_logic; scrub_se_o : out std_logic; scrub_de_o : out std_logic; + scrub_cycle_o : out std_logic; -- Scrubber scrubber_period_i : in std_logic_vector(15 downto 0) @@ -79,10 +80,16 @@ architecture arch of hydra_dram is signal w_done, n_w_done : std_logic; signal n_ecc_one, n_ecc_fatal : std_logic; - signal last_addr, n_last_addr, scrub_addr : std_logic_vector(g_RAM_LOG_SIZE - 1 downto 2); + signal last_addr, n_last_addr : std_logic_vector(g_RAM_LOG_SIZE - 1 downto 2); signal last_we, n_last_we : std_logic; signal last_sel, n_last_sel : std_logic_vector(3 downto 0); + -- The scrubber counter has an extra bit to signal a new cycle. + signal scrub_addr_ext : std_logic_vector(g_RAM_LOG_SIZE - 1 + 1 downto 2); + alias scrub_cycle : std_logic is scrub_addr_ext (g_RAM_LOG_SIZE); + alias scrub_addr : std_logic_vector(g_RAM_LOG_SIZE - 1 downto 2) is scrub_addr_ext (g_RAM_LOG_SIZE - 1 downto 2); + signal scrub_cycle_d1, scrub_cycle_d2 : std_logic; + signal scrub_counter : unsigned(15 downto 0); signal scrub_rd, scrub_done, scrub_done_d, n_scrub_done : std_logic; signal n_scrub_de, n_scrub_se : std_logic; @@ -135,17 +142,25 @@ begin err_o <= rerr_one; done_o <= r_done or w_done; + -- We need to delay scrub_cycle_o so that it happens after a possible + -- error on the last address. + scrub_cycle_o <= scrub_cycle_d2; + p_scrub: process (clk_i) begin if rising_edge(clk_i) then - if rst_n_i = '0' then + if rst_n_i = '0' or scrub_cycle_d2 = '1' then scrub_counter <= unsigned(scrubber_period_i); - scrub_addr <= (others => '0'); + scrub_addr_ext <= (others => '0'); scrub_rd <= '0'; + scrub_cycle_d2 <= '0'; + scrub_cycle_d1 <= '0'; else + scrub_cycle_d1 <= scrub_cycle; + scrub_cycle_d2 <= scrub_cycle_d1; if scrub_done = '1' and rerr_one = '0' then scrub_counter <= unsigned(scrubber_period_i); - scrub_addr <= std_logic_vector(unsigned(scrub_addr) + 1); + scrub_addr_ext <= std_logic_vector(unsigned(scrub_addr_ext) + 1); scrub_rd <= '0'; elsif scrub_en_i = '1' then if scrub_counter = (scrub_counter'range => '0') then @@ -247,7 +262,7 @@ begin ren <= '1'; n_r_done <= '1'; end if; - elsif scrub_en_i = '1' then + elsif scrub_en_i = '1' and scrub_cycle = '0' then -- scrub if idle addr <= scrub_addr; ren <= '1'; diff --git a/hdl/rtl/hydra_supervisor_regs.cheby b/hdl/rtl/hydra_supervisor_regs.cheby index 2f7351e5f6da636fe5fab4b853b2aca5adb22853..363bade9a54651b98725ef393918f72da0e185f1 100644 --- a/hdl/rtl/hydra_supervisor_regs.cheby +++ b/hdl/rtl/hydra_supervisor_regs.cheby @@ -105,15 +105,29 @@ memory-map: description: Number of ECC correctable errors for dram width: 32 access: ro + - reg: + name: dram_scrub_cycle + description: DRAM scrubber cycle number. + width: 8 + access: ro - reg: name: dram_scrub_se description: Number of ECC corrected errors by scrubber in dram width: 32 access: ro - reg: - name: dram_scrub_de - description: Number of ECC uncorrected errors by scrubber in dram - width: 32 + name: dram_scrub_de_curr + description: > + Number of ECC uncorrected errors by scrubber in dram in the current + scrubber cycle. Saturate. + width: 16 + access: ro + - reg: + name: dram_scrub_de_last + description: > + Number of ECC uncorrected errors by scrubber in dram during the last + scrubber cycle. Saturate. + width: 16 access: ro - reg: name: cpu_data_err diff --git a/hdl/rtl/hydra_supervisor_regs.vhd b/hdl/rtl/hydra_supervisor_regs.vhd index 25e172baab23c20120bb6400191e6b9d3776f90f..8c3b900e57ab596f1f380e3131ceb884ab8098b8 100644 --- a/hdl/rtl/hydra_supervisor_regs.vhd +++ b/hdl/rtl/hydra_supervisor_regs.vhd @@ -69,11 +69,19 @@ entity hydra_supervisor_regs is -- Number of ECC correctable errors for dram dram_ecc_se_i : in std_logic_vector(31 downto 0); + -- DRAM scrubber cycle number. + dram_scrub_cycle_i : in std_logic_vector(7 downto 0); + -- Number of ECC corrected errors by scrubber in dram dram_scrub_se_i : in std_logic_vector(31 downto 0); - -- Number of ECC uncorrected errors by scrubber in dram - dram_scrub_de_i : in std_logic_vector(31 downto 0); + -- Number of ECC uncorrected errors by scrubber in dram in the current scrubber cycle. Saturate. + + dram_scrub_de_curr_i : in std_logic_vector(15 downto 0); + + -- Number of ECC uncorrected errors by scrubber in dram during the last scrubber cycle. Saturate. + + dram_scrub_de_last_i : in std_logic_vector(15 downto 0); -- Number of CPU errors on data bus cpu_data_err_i : in std_logic_vector(31 downto 0); @@ -228,9 +236,13 @@ begin -- Register dram_ecc_se + -- Register dram_scrub_cycle + -- Register dram_scrub_se - -- Register dram_scrub_de + -- Register dram_scrub_de_curr + + -- Register dram_scrub_de_last -- Register cpu_data_err @@ -342,33 +354,39 @@ begin -- Reg dram_ecc_se wr_ack_int <= wr_req_d0; when "01100" => - -- Reg dram_scrub_se + -- Reg dram_scrub_cycle wr_ack_int <= wr_req_d0; when "01101" => - -- Reg dram_scrub_de + -- Reg dram_scrub_se wr_ack_int <= wr_req_d0; when "01110" => - -- Reg cpu_data_err + -- Reg dram_scrub_de_curr wr_ack_int <= wr_req_d0; when "01111" => - -- Reg cpu_iaddr_err + -- Reg dram_scrub_de_last wr_ack_int <= wr_req_d0; when "10000" => + -- Reg cpu_data_err + wr_ack_int <= wr_req_d0; + when "10001" => + -- Reg cpu_iaddr_err + wr_ack_int <= wr_req_d0; + when "10010" => -- Reg dram_ecc_mask dram_ecc_mask_wreq <= wr_req_d0; wr_ack_int <= dram_ecc_mask_wack; - when "10001" => + when "10011" => -- Reg iram_de_addr wr_ack_int <= wr_req_d0; - when "10010" => + when "10100" => -- Reg scrub_cfg scrub_cfg_wreq <= wr_req_d0; wr_ack_int <= wr_req_d0; - when "10011" => + when "10101" => -- Reg iram_scrub_period iram_scrub_period_wreq <= wr_req_d0; wr_ack_int <= iram_scrub_period_wack; - when "10100" => + when "10110" => -- Reg dram_scrub_period dram_scrub_period_wreq <= wr_req_d0; wr_ack_int <= dram_scrub_period_wack; @@ -383,7 +401,8 @@ begin cpu_recovery_i, force_divergence_i, wd_period_i, wd_count_i, iram_ecc_se_i, iram_scrub_cycle_i, iram_scrub_se_i, iram_scrub_de_curr_i, iram_scrub_de_last_i, dram_ecc_se_i, - dram_scrub_se_i, dram_scrub_de_i, cpu_data_err_i, cpu_iaddr_err_i, + dram_scrub_cycle_i, dram_scrub_se_i, dram_scrub_de_curr_i, + dram_scrub_de_last_i, cpu_data_err_i, cpu_iaddr_err_i, dram_ecc_mask_reg, iram_de_addr_i, scrub_cfg_iram_en_i, scrub_cfg_dram_en_i, iram_scrub_period_reg, dram_scrub_period_reg) begin -- By default ack read requests @@ -449,42 +468,53 @@ begin rd_ack_d0 <= rd_req_int; rd_dat_d0 <= dram_ecc_se_i; when "01100" => - -- Reg dram_scrub_se + -- Reg dram_scrub_cycle rd_ack_d0 <= rd_req_int; - rd_dat_d0 <= dram_scrub_se_i; + rd_dat_d0(7 downto 0) <= dram_scrub_cycle_i; + rd_dat_d0(31 downto 8) <= (others => '0'); when "01101" => - -- Reg dram_scrub_de + -- Reg dram_scrub_se rd_ack_d0 <= rd_req_int; - rd_dat_d0 <= dram_scrub_de_i; + rd_dat_d0 <= dram_scrub_se_i; when "01110" => + -- Reg dram_scrub_de_curr + rd_ack_d0 <= rd_req_int; + rd_dat_d0(15 downto 0) <= dram_scrub_de_curr_i; + rd_dat_d0(31 downto 16) <= (others => '0'); + when "01111" => + -- Reg dram_scrub_de_last + rd_ack_d0 <= rd_req_int; + rd_dat_d0(15 downto 0) <= dram_scrub_de_last_i; + rd_dat_d0(31 downto 16) <= (others => '0'); + when "10000" => -- Reg cpu_data_err rd_ack_d0 <= rd_req_int; rd_dat_d0 <= cpu_data_err_i; - when "01111" => + when "10001" => -- Reg cpu_iaddr_err rd_ack_d0 <= rd_req_int; rd_dat_d0 <= cpu_iaddr_err_i; - when "10000" => + when "10010" => -- Reg dram_ecc_mask rd_ack_d0 <= rd_req_int; rd_dat_d0(7 downto 0) <= dram_ecc_mask_reg; rd_dat_d0(31 downto 8) <= (others => '0'); - when "10001" => + when "10011" => -- Reg iram_de_addr rd_ack_d0 <= rd_req_int; rd_dat_d0 <= iram_de_addr_i; - when "10010" => + when "10100" => -- Reg scrub_cfg rd_ack_d0 <= rd_req_int; rd_dat_d0(0) <= scrub_cfg_iram_en_i; rd_dat_d0(1) <= scrub_cfg_dram_en_i; rd_dat_d0(31 downto 2) <= (others => '0'); - when "10011" => + when "10101" => -- Reg iram_scrub_period rd_ack_d0 <= rd_req_int; rd_dat_d0(15 downto 0) <= iram_scrub_period_reg; rd_dat_d0(31 downto 16) <= (others => '0'); - when "10100" => + when "10110" => -- Reg dram_scrub_period rd_ack_d0 <= rd_req_int; rd_dat_d0(15 downto 0) <= dram_scrub_period_reg; diff --git a/sw/include/hydra_supervisor_regs.h b/sw/include/hydra_supervisor_regs.h index b74baf723a97318bbc7995dd8f8aef83c89acd52..54c4ab3cf713a3ee91432afc919d19d7aab268f0 100644 --- a/sw/include/hydra_supervisor_regs.h +++ b/sw/include/hydra_supervisor_regs.h @@ -1,6 +1,6 @@ #ifndef __CHEBY__HYDRA_SUPERVISOR_REGS__H__ #define __CHEBY__HYDRA_SUPERVISOR_REGS__H__ -#define HYDRA_SUPERVISOR_REGS_SIZE 82 /* 0x52 */ +#define HYDRA_SUPERVISOR_REGS_SIZE 90 /* 0x5a */ /* Cause of a reset */ #define HYDRA_SUPERVISOR_REGS_RESET_CAUSE 0x0UL @@ -47,35 +47,43 @@ /* Number of ECC correctable errors for dram */ #define HYDRA_SUPERVISOR_REGS_DRAM_ECC_SE 0x2cUL +/* DRAM scrubber cycle number. */ +#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_CYCLE 0x30UL + /* Number of ECC corrected errors by scrubber in dram */ -#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_SE 0x30UL +#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_SE 0x34UL + +/* Number of ECC uncorrected errors by scrubber in dram in the current scrubber cycle. Saturate. + */ +#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_DE_CURR 0x38UL -/* Number of ECC uncorrected errors by scrubber in dram */ -#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_DE 0x34UL +/* Number of ECC uncorrected errors by scrubber in dram during the last scrubber cycle. Saturate. + */ +#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_DE_LAST 0x3cUL /* Number of CPU errors on data bus */ -#define HYDRA_SUPERVISOR_REGS_CPU_DATA_ERR 0x38UL +#define HYDRA_SUPERVISOR_REGS_CPU_DATA_ERR 0x40UL /* Number of CPU errors on instruction bus */ -#define HYDRA_SUPERVISOR_REGS_CPU_IADDR_ERR 0x3cUL +#define HYDRA_SUPERVISOR_REGS_CPU_IADDR_ERR 0x44UL /* Change ECC bits on dram writes for testing */ -#define HYDRA_SUPERVISOR_REGS_DRAM_ECC_MASK 0x40UL +#define HYDRA_SUPERVISOR_REGS_DRAM_ECC_MASK 0x48UL /* Address of the last fatal error */ -#define HYDRA_SUPERVISOR_REGS_IRAM_DE_ADDR 0x44UL +#define HYDRA_SUPERVISOR_REGS_IRAM_DE_ADDR 0x4cUL /* configuration of scrubbers */ -#define HYDRA_SUPERVISOR_REGS_SCRUB_CFG 0x48UL +#define HYDRA_SUPERVISOR_REGS_SCRUB_CFG 0x50UL #define HYDRA_SUPERVISOR_REGS_SCRUB_CFG_IRAM_EN 0x1UL #define HYDRA_SUPERVISOR_REGS_SCRUB_CFG_DRAM_EN 0x2UL /* Maximum number of cycles between a scrub */ -#define HYDRA_SUPERVISOR_REGS_IRAM_SCRUB_PERIOD 0x4cUL +#define HYDRA_SUPERVISOR_REGS_IRAM_SCRUB_PERIOD 0x54UL #define HYDRA_SUPERVISOR_REGS_IRAM_SCRUB_PERIOD_PRESET 0x7ffUL /* Maximum number of cycles between a scrub */ -#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_PERIOD 0x50UL +#define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_PERIOD 0x58UL #define HYDRA_SUPERVISOR_REGS_DRAM_SCRUB_PERIOD_PRESET 0x7ffUL struct hydra_supervisor_regs { @@ -126,37 +134,54 @@ struct hydra_supervisor_regs { /* [0x2c]: REG (ro) Number of ECC correctable errors for dram */ uint32_t dram_ecc_se; - /* [0x30]: REG (ro) Number of ECC corrected errors by scrubber in dram */ + /* [0x30]: REG (ro) DRAM scrubber cycle number. */ + uint8_t dram_scrub_cycle; + + /* padding to: 52 words */ + uint8_t __padding_3[3]; + + /* [0x34]: REG (ro) Number of ECC corrected errors by scrubber in dram */ uint32_t dram_scrub_se; - /* [0x34]: REG (ro) Number of ECC uncorrected errors by scrubber in dram */ - uint32_t dram_scrub_de; + /* [0x38]: REG (ro) Number of ECC uncorrected errors by scrubber in dram in the current scrubber cycle. Saturate. + */ + uint16_t dram_scrub_de_curr; - /* [0x38]: REG (ro) Number of CPU errors on data bus */ + /* padding to: 60 words */ + uint8_t __padding_4[2]; + + /* [0x3c]: REG (ro) Number of ECC uncorrected errors by scrubber in dram during the last scrubber cycle. Saturate. + */ + uint16_t dram_scrub_de_last; + + /* padding to: 64 words */ + uint8_t __padding_5[2]; + + /* [0x40]: REG (ro) Number of CPU errors on data bus */ uint32_t cpu_data_err; - /* [0x3c]: REG (ro) Number of CPU errors on instruction bus */ + /* [0x44]: REG (ro) Number of CPU errors on instruction bus */ uint32_t cpu_iaddr_err; - /* [0x40]: REG (rw) Change ECC bits on dram writes for testing */ + /* [0x48]: REG (rw) Change ECC bits on dram writes for testing */ uint8_t dram_ecc_mask; - /* padding to: 68 words */ - uint8_t __padding_3[3]; + /* padding to: 76 words */ + uint8_t __padding_6[3]; - /* [0x44]: REG (ro) Address of the last fatal error */ + /* [0x4c]: REG (ro) Address of the last fatal error */ uint32_t iram_de_addr; - /* [0x48]: REG (rw) configuration of scrubbers */ + /* [0x50]: REG (rw) configuration of scrubbers */ uint32_t scrub_cfg; - /* [0x4c]: REG (rw) Maximum number of cycles between a scrub */ + /* [0x54]: REG (rw) Maximum number of cycles between a scrub */ uint16_t iram_scrub_period; - /* padding to: 80 words */ - uint8_t __padding_4[2]; + /* padding to: 88 words */ + uint8_t __padding_7[2]; - /* [0x50]: REG (rw) Maximum number of cycles between a scrub */ + /* [0x58]: REG (rw) Maximum number of cycles between a scrub */ uint16_t dram_scrub_period; }; diff --git a/sw/sf2-test/main.c b/sw/sf2-test/main.c index 592f89bb673098b42f5cf15090ae41e979d0323d..d981060cfd9bc9f91fa8febcaa9f442594112346 100644 --- a/sw/sf2-test/main.c +++ b/sw/sf2-test/main.c @@ -30,7 +30,7 @@ static enum t_test TEST_CPU3_RECOVER, TEST_CPU1_FATAL, TEST_RAM, - TEST_DONE + TEST_DONE, } next_test; static void @@ -62,15 +62,14 @@ uart_raw_putc (unsigned char c) *(volatile unsigned *)UART_TX = c; } -static unsigned char +static int uart_raw_getc (void) { - /* Wait until DR (data ready, bit 0) is set. */ - do { - SUPERVISOR->wd_key = WD_KEY; - } while (!(*(volatile unsigned*)UART_LSR & 0x1)); - - return *(volatile unsigned *)UART_RX; + /* Check if DR (data ready, bit 0) is set. */ + if (*(volatile unsigned*)UART_LSR & 0x1) + return *(volatile unsigned *)UART_RX; + else + return -1; } static void @@ -163,6 +162,7 @@ int main (void) { unsigned v; + int c; SUPERVISOR->wd_key = WD_KEY; uart_init (); @@ -219,24 +219,27 @@ main (void) break; case TEST_DRAM_SCRUB: + uart_putc('*'); if (SUPERVISOR->dram_scrub_se != 0 - || SUPERVISOR->dram_scrub_de != 0) + || SUPERVISOR->dram_scrub_de_curr != 0 + || SUPERVISOR->dram_scrub_de_last != 0 + || SUPERVISOR->dram_scrub_cycle != 0) unreachable(); uart_puts("Scrub DRAM"); SUPERVISOR->scrub_cfg = HYDRA_SUPERVISOR_REGS_SCRUB_CFG_DRAM_EN; next_test = TEST_IRAM_SE; do { - v = SUPERVISOR->dram_scrub_de; SUPERVISOR->wd_key = WD_KEY; - } while (v == 0); + } while (SUPERVISOR->dram_scrub_cycle == 0); /* Because the scrubber is always running, the counter is always incrementing. So the original value is kept. */ uart_putc('\n'); - if (SUPERVISOR->dram_scrub_se != 1 || v > 2) { + if (SUPERVISOR->dram_scrub_se != 1 + || SUPERVISOR->dram_scrub_de_last != 2) { uart_puts ("se:"); uart_put_hex8 (SUPERVISOR->dram_scrub_se); uart_puts (", de:"); - uart_put_hex8 (v); + uart_put_hex8 (SUPERVISOR->dram_scrub_de_last); unreachable(); } /* Remove the errors */ @@ -330,8 +333,40 @@ main (void) next_test++; SUPERVISOR->wd_key = WD_KEY; SUPERVISOR->wd_period = 100000000; - uart_puts ("Hello diot.\n"); - while (1) + break; + } + + while (1) { + uart_puts ("i-nfo, r-ecover, l-oop\n"); + while ((c = uart_raw_getc()) == -1) ; + switch (c) { + case 'i': + v = SUPERVISOR->wd_count; + uart_puts ("wd count: "); + uart_put_hex8 (v); + uart_putc ('\n'); + uart_puts ("ecc dram: se:"); + uart_put_hex8 (SUPERVISOR->dram_scrub_se); + uart_puts (", de:"); + uart_put_hex8 (SUPERVISOR->dram_scrub_de_last); + uart_putc ('\n'); + uart_puts ("ecc iram: se:"); + uart_put_hex8 (SUPERVISOR->iram_scrub_se); + uart_puts (", de:"); + uart_put_hex8 (SUPERVISOR->iram_scrub_de_last); + uart_putc ('\n'); + break; + case 'r': + /* Generate reset for recovery */ + SUPERVISOR->cpu = HYDRA_SUPERVISOR_REGS_CPU_RECOVERY; + + unreachable(); + case 'l': + while (1) + ; + default: + break; + } } }