diff --git a/common.vhdl b/common.vhdl index d743c2d..39ebfb1 100644 --- a/common.vhdl +++ b/common.vhdl @@ -547,7 +547,9 @@ package common is iside : std_ulogic; load : std_ulogic; priv : std_ulogic; - sprn : std_ulogic_vector(9 downto 0); + ric : std_ulogic_vector(1 downto 0); + sprnf : std_ulogic; + sprnt : std_ulogic; addr : std_ulogic_vector(63 downto 0); rs : std_ulogic_vector(63 downto 0); end record; diff --git a/core.vhdl b/core.vhdl index a91b729..641c12d 100644 --- a/core.vhdl +++ b/core.vhdl @@ -154,6 +154,10 @@ architecture behave of core is signal dbg_spr_ack : std_ulogic; signal dbg_spr_addr : std_ulogic_vector(7 downto 0); signal dbg_spr_data : std_ulogic_vector(63 downto 0); + signal dbg_ls_spr_req : std_ulogic; + signal dbg_ls_spr_ack : std_ulogic; + signal dbg_ls_spr_addr : std_ulogic_vector(1 downto 0); + signal dbg_ls_spr_data : std_ulogic_vector(63 downto 0); signal ctrl_debug : ctrl_t; @@ -432,6 +436,10 @@ begin m_in => mmu_to_loadstore1, dc_stall => dcache_stall_out, events => loadstore_events, + dbg_spr_req => dbg_ls_spr_req, + dbg_spr_ack => dbg_ls_spr_ack, + dbg_spr_addr => dbg_ls_spr_addr, + dbg_spr_data => dbg_ls_spr_data, log_out => log_data(149 downto 140) ); @@ -518,6 +526,10 @@ begin dbg_spr_ack => dbg_spr_ack, dbg_spr_addr => dbg_spr_addr, dbg_spr_data => dbg_spr_data, + dbg_ls_spr_req => dbg_ls_spr_req, + dbg_ls_spr_ack => dbg_ls_spr_ack, + dbg_ls_spr_addr => dbg_ls_spr_addr, + dbg_ls_spr_data => dbg_ls_spr_data, log_data => log_data, log_read_addr => log_rd_addr, log_read_data => log_rd_data, diff --git a/core_debug.vhdl b/core_debug.vhdl index a1d4a94..c060f74 100644 --- a/core_debug.vhdl +++ b/core_debug.vhdl @@ -39,12 +39,18 @@ entity core_debug is dbg_gpr_addr : out gspr_index_t; dbg_gpr_data : in std_ulogic_vector(63 downto 0); - -- SPR register read port + -- SPR register read port for SPRs in execute1 dbg_spr_req : out std_ulogic; dbg_spr_ack : in std_ulogic; dbg_spr_addr : out std_ulogic_vector(7 downto 0); dbg_spr_data : in std_ulogic_vector(63 downto 0); + -- SPR register read port for SPRs in loadstore1 and mmu + dbg_ls_spr_req : out std_ulogic; + dbg_ls_spr_ack : in std_ulogic; + dbg_ls_spr_addr : out std_ulogic_vector(1 downto 0); + dbg_ls_spr_data : in std_ulogic_vector(63 downto 0); + -- Core logging data log_data : in std_ulogic_vector(255 downto 0); log_read_addr : in std_ulogic_vector(31 downto 0); @@ -128,7 +134,7 @@ architecture behave of core_debug is begin -- Single cycle register accesses on DMI except for GSPR data dmi_ack <= dmi_req when dmi_addr /= DBG_CORE_GSPR_DATA - else dbg_gpr_ack or dbg_spr_ack; + else dbg_gpr_ack or dbg_spr_ack or dbg_ls_spr_ack; -- Status register read composition stat_reg <= (2 => terminated, @@ -137,6 +143,7 @@ begin others => '0'); gspr_data <= dbg_gpr_data when gspr_index(5) = '0' else + dbg_ls_spr_data when dbg_ls_spr_req = '1' else dbg_spr_data when spr_index_valid = '1' else (others => '0'); @@ -245,16 +252,22 @@ begin variable odd : std_ulogic; begin if rising_edge(clk) then - if rst = '1' or dmi_req = '0' or dmi_addr /= DBG_CORE_GSPR_DATA then - dbg_gpr_req <= '0'; - dbg_spr_req <= '0'; - else - dbg_gpr_req <= not gspr_index(5); - dbg_spr_req <= gspr_index(5); + dbg_gpr_req <= '0'; + dbg_spr_req <= '0'; + dbg_ls_spr_req <= '0'; + if rst = '0' and dmi_req = '1' and dmi_addr = DBG_CORE_GSPR_DATA then + if gspr_index(5) = '0' then + dbg_gpr_req <= '1'; + elsif gspr_index(4 downto 2) = "111" then + dbg_ls_spr_req <= '1'; + else + dbg_spr_req <= '1'; + end if; end if; -- Map 0 - 0x1f to GPRs, 0x20 - 0x3f to SPRs, and 0x40 - 0x5f to FPRs dbg_gpr_addr <= gspr_index(6) & gspr_index(4 downto 0); + dbg_ls_spr_addr <= gspr_index(1 downto 0); -- For SPRs, use the same mapping as when the fast SPRs were in the GPR file valid := '1'; diff --git a/loadstore1.vhdl b/loadstore1.vhdl index 9dab15b..92ebeec 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -35,6 +35,12 @@ entity loadstore1 is events : out Loadstore1EventType; + -- Access to SPRs from core_debug module + dbg_spr_req : in std_ulogic; + dbg_spr_ack : out std_ulogic; + dbg_spr_addr : in std_ulogic_vector(1 downto 0); + dbg_spr_data : out std_ulogic_vector(63 downto 0); + log_out : out std_ulogic_vector(9 downto 0) ); end loadstore1; @@ -123,6 +129,8 @@ architecture behave of loadstore1 is one_cycle : std_ulogic; wr_sel : std_ulogic_vector(1 downto 0); addr0 : std_ulogic_vector(63 downto 0); + sprsel : std_ulogic_vector(1 downto 0); + dbg_spr_rd : std_ulogic; end record; type reg_stage3_t is record @@ -146,6 +154,8 @@ architecture behave of loadstore1 is intr_vec : integer range 0 to 16#fff#; srr1 : std_ulogic_vector(15 downto 0); events : Loadstore1EventType; + dbg_spr : std_ulogic_vector(63 downto 0); + dbg_spr_ack : std_ulogic; end record; signal req_in : request_t; @@ -664,6 +674,20 @@ begin v.busy := '1'; end if; + v.dbg_spr_rd := dbg_spr_req and not (v.req.valid and v.req.read_spr); + if v.dbg_spr_rd = '0' then + v.sprsel(1) := v.req.sprn(1); + if v.req.sprn(1) = '1' then + -- DSISR and DAR + v.sprsel(0) := v.req.sprn(0); + else + -- PID and PTCR + v.sprsel(0) := v.req.sprn(8); + end if; + else + v.sprsel := dbg_spr_addr; + end if; + r2in <= v; end process; @@ -763,21 +787,26 @@ begin v.load_data := data_permuted; end if; + -- SPR mux + if r2.sprsel(1) = '1' then + if r2.sprsel(0) = '0' then + sprval := x"00000000" & r3.dsisr; + else + sprval := r3.dar; + end if; + else + sprval := m_in.sprval; + end if; + if dbg_spr_req = '0' then + v.dbg_spr_ack := '0'; + elsif r2.dbg_spr_rd = '1' and r3.dbg_spr_ack = '0' then + v.dbg_spr := sprval; + v.dbg_spr_ack := '1'; + end if; + if r2.req.valid = '1' then if r2.req.read_spr = '1' then write_enable := '1'; - -- partial decode on SPR number should be adequate given - -- the restricted set that get sent down this path - if r2.req.sprn(8) = '0' and r2.req.sprn(5) = '0' then - if r2.req.sprn(0) = '0' then - sprval := x"00000000" & r3.dsisr; - else - sprval := r3.dar; - end if; - else - -- reading one of the SPRs in the MMU - sprval := m_in.sprval; - end if; end if; if r2.req.align_intr = '1' then -- generate alignment interrupt @@ -940,8 +969,10 @@ begin m_out.load <= r2.req.load; m_out.priv <= r2.req.priv_mode; m_out.tlbie <= r2.req.tlbie; + m_out.ric <= r2.req.sprn(3 downto 2); m_out.mtspr <= mmu_mtspr; - m_out.sprn <= r2.req.sprn; + m_out.sprnf <= r2.sprsel(0); + m_out.sprnt <= r2.req.sprn(8); m_out.addr <= r2.req.addr; m_out.slbia <= r2.req.is_slbia; m_out.rs <= r2.req.store_data; @@ -967,6 +998,10 @@ begin flush <= exception; + -- SPR values for core_debug + dbg_spr_data <= r3.dbg_spr; + dbg_spr_ack <= r3.dbg_spr_ack; + -- Update registers r3in <= v; diff --git a/mmu.vhdl b/mmu.vhdl index d80caf4..d95cd3c 100644 --- a/mmu.vhdl +++ b/mmu.vhdl @@ -81,8 +81,8 @@ architecture behave of mmu is begin -- Multiplex internal SPR values back to loadstore1, selected - -- by l_in.sprn. - l_out.sprval <= r.ptcr when l_in.sprn(8) = '1' else x"00000000" & r.pid; + -- by l_in.sprnf. + l_out.sprval <= r.ptcr when l_in.sprnf = '1' else x"00000000" & r.pid; mmu_0: process(clk) begin @@ -259,9 +259,8 @@ begin -- RB[IS] != 0 or RB[AP] != 0, or for slbia v.inval_all := l_in.slbia or l_in.addr(11) or l_in.addr(10) or l_in.addr(7) or l_in.addr(6) or l_in.addr(5); - -- The RIC field of the tlbie instruction comes across on the - -- sprn bus as bits 2--3. RIC=2 flushes process table caches. - if l_in.sprn(3) = '1' then + -- RIC=2 or 3 flushes process table caches. + if l_in.ric(1) = '1' then v.pt0_valid := '0'; v.pt3_valid := '0'; v.ptb_valid := '0'; @@ -291,7 +290,7 @@ begin -- Move to PID needs to invalidate L1 TLBs and cached -- pgtbl0 value. Move to PTCR does that plus -- invalidating the cached pgtbl3 and prtbl values as well. - if l_in.sprn(8) = '0' then + if l_in.sprnt = '0' then v.pid := l_in.rs(31 downto 0); else v.ptcr := l_in.rs; diff --git a/scripts/mw_debug/mw_debug.c b/scripts/mw_debug/mw_debug.c index ef5b1ec..81e8094 100644 --- a/scripts/mw_debug/mw_debug.c +++ b/scripts/mw_debug/mw_debug.c @@ -551,6 +551,10 @@ static const char *fast_spr_names[] = "hsprg0", "hsprg1", "xer", "tar", }; +static const char *ldst_spr_names[] = { + "pidr", "ptcr", "dsisr", "dar" +}; + static void gpr_read(uint64_t reg, uint64_t count) { uint64_t data; @@ -566,8 +570,10 @@ static void gpr_read(uint64_t reg, uint64_t count) printf("r%"PRId64, reg); else if ((reg - 32) < sizeof(fast_spr_names) / sizeof(fast_spr_names[0])) printf("%s", fast_spr_names[reg - 32]); - else if (reg < 64) + else if (reg < 60) printf("gspr%"PRId64, reg); + else if (reg < 64) + printf("%s", ldst_spr_names[reg - 60]); else printf("FPR%"PRId64, reg - 64); printf(":\t%016"PRIx64"\n", data);