Provide debug access to SPRs in loadstore1 and mmu

They are accessible as GSPR 0x3c - PID, 0x3d - PTCR, 0x3e - DSISR
and 0x3f - DAR.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/379/head
Paul Mackerras 3 years ago
parent d0f319290f
commit af814a0d5e

@ -547,7 +547,9 @@ package common is
iside : std_ulogic; iside : std_ulogic;
load : std_ulogic; load : std_ulogic;
priv : 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); addr : std_ulogic_vector(63 downto 0);
rs : std_ulogic_vector(63 downto 0); rs : std_ulogic_vector(63 downto 0);
end record; end record;

@ -154,6 +154,10 @@ architecture behave of core is
signal dbg_spr_ack : std_ulogic; signal dbg_spr_ack : std_ulogic;
signal dbg_spr_addr : std_ulogic_vector(7 downto 0); signal dbg_spr_addr : std_ulogic_vector(7 downto 0);
signal dbg_spr_data : std_ulogic_vector(63 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; signal ctrl_debug : ctrl_t;


@ -432,6 +436,10 @@ begin
m_in => mmu_to_loadstore1, m_in => mmu_to_loadstore1,
dc_stall => dcache_stall_out, dc_stall => dcache_stall_out,
events => loadstore_events, 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) log_out => log_data(149 downto 140)
); );


@ -518,6 +526,10 @@ begin
dbg_spr_ack => dbg_spr_ack, dbg_spr_ack => dbg_spr_ack,
dbg_spr_addr => dbg_spr_addr, dbg_spr_addr => dbg_spr_addr,
dbg_spr_data => dbg_spr_data, 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_data => log_data,
log_read_addr => log_rd_addr, log_read_addr => log_rd_addr,
log_read_data => log_rd_data, log_read_data => log_rd_data,

@ -39,12 +39,18 @@ entity core_debug is
dbg_gpr_addr : out gspr_index_t; dbg_gpr_addr : out gspr_index_t;
dbg_gpr_data : in std_ulogic_vector(63 downto 0); 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_req : out std_ulogic;
dbg_spr_ack : in std_ulogic; dbg_spr_ack : in std_ulogic;
dbg_spr_addr : out std_ulogic_vector(7 downto 0); dbg_spr_addr : out std_ulogic_vector(7 downto 0);
dbg_spr_data : in std_ulogic_vector(63 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 -- Core logging data
log_data : in std_ulogic_vector(255 downto 0); log_data : in std_ulogic_vector(255 downto 0);
log_read_addr : in std_ulogic_vector(31 downto 0); log_read_addr : in std_ulogic_vector(31 downto 0);
@ -128,7 +134,7 @@ architecture behave of core_debug is
begin begin
-- Single cycle register accesses on DMI except for GSPR data -- Single cycle register accesses on DMI except for GSPR data
dmi_ack <= dmi_req when dmi_addr /= DBG_CORE_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 -- Status register read composition
stat_reg <= (2 => terminated, stat_reg <= (2 => terminated,
@ -137,6 +143,7 @@ begin
others => '0'); others => '0');


gspr_data <= dbg_gpr_data when gspr_index(5) = '0' else 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 dbg_spr_data when spr_index_valid = '1' else
(others => '0'); (others => '0');


@ -245,16 +252,22 @@ begin
variable odd : std_ulogic; variable odd : std_ulogic;
begin begin
if rising_edge(clk) then 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_gpr_req <= '0'; dbg_spr_req <= '0';
dbg_spr_req <= '0'; dbg_ls_spr_req <= '0';
else if rst = '0' and dmi_req = '1' and dmi_addr = DBG_CORE_GSPR_DATA then
dbg_gpr_req <= not gspr_index(5); if gspr_index(5) = '0' then
dbg_spr_req <= gspr_index(5); 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; end if;


-- Map 0 - 0x1f to GPRs, 0x20 - 0x3f to SPRs, and 0x40 - 0x5f to FPRs -- 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_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 -- For SPRs, use the same mapping as when the fast SPRs were in the GPR file
valid := '1'; valid := '1';

@ -35,6 +35,12 @@ entity loadstore1 is


events : out Loadstore1EventType; 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) log_out : out std_ulogic_vector(9 downto 0)
); );
end loadstore1; end loadstore1;
@ -123,6 +129,8 @@ architecture behave of loadstore1 is
one_cycle : std_ulogic; one_cycle : std_ulogic;
wr_sel : std_ulogic_vector(1 downto 0); wr_sel : std_ulogic_vector(1 downto 0);
addr0 : std_ulogic_vector(63 downto 0); addr0 : std_ulogic_vector(63 downto 0);
sprsel : std_ulogic_vector(1 downto 0);
dbg_spr_rd : std_ulogic;
end record; end record;


type reg_stage3_t is record type reg_stage3_t is record
@ -146,6 +154,8 @@ architecture behave of loadstore1 is
intr_vec : integer range 0 to 16#fff#; intr_vec : integer range 0 to 16#fff#;
srr1 : std_ulogic_vector(15 downto 0); srr1 : std_ulogic_vector(15 downto 0);
events : Loadstore1EventType; events : Loadstore1EventType;
dbg_spr : std_ulogic_vector(63 downto 0);
dbg_spr_ack : std_ulogic;
end record; end record;


signal req_in : request_t; signal req_in : request_t;
@ -664,6 +674,20 @@ begin
v.busy := '1'; v.busy := '1';
end if; 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; r2in <= v;
end process; end process;


@ -763,21 +787,26 @@ begin
v.load_data := data_permuted; v.load_data := data_permuted;
end if; 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.valid = '1' then
if r2.req.read_spr = '1' then if r2.req.read_spr = '1' then
write_enable := '1'; 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; end if;
if r2.req.align_intr = '1' then if r2.req.align_intr = '1' then
-- generate alignment interrupt -- generate alignment interrupt
@ -940,8 +969,10 @@ begin
m_out.load <= r2.req.load; m_out.load <= r2.req.load;
m_out.priv <= r2.req.priv_mode; m_out.priv <= r2.req.priv_mode;
m_out.tlbie <= r2.req.tlbie; m_out.tlbie <= r2.req.tlbie;
m_out.ric <= r2.req.sprn(3 downto 2);
m_out.mtspr <= mmu_mtspr; 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.addr <= r2.req.addr;
m_out.slbia <= r2.req.is_slbia; m_out.slbia <= r2.req.is_slbia;
m_out.rs <= r2.req.store_data; m_out.rs <= r2.req.store_data;
@ -967,6 +998,10 @@ begin


flush <= exception; flush <= exception;


-- SPR values for core_debug
dbg_spr_data <= r3.dbg_spr;
dbg_spr_ack <= r3.dbg_spr_ack;

-- Update registers -- Update registers
r3in <= v; r3in <= v;



@ -81,8 +81,8 @@ architecture behave of mmu is


begin begin
-- Multiplex internal SPR values back to loadstore1, selected -- Multiplex internal SPR values back to loadstore1, selected
-- by l_in.sprn. -- by l_in.sprnf.
l_out.sprval <= r.ptcr when l_in.sprn(8) = '1' else x"00000000" & r.pid; l_out.sprval <= r.ptcr when l_in.sprnf = '1' else x"00000000" & r.pid;


mmu_0: process(clk) mmu_0: process(clk)
begin begin
@ -259,9 +259,8 @@ begin
-- RB[IS] != 0 or RB[AP] != 0, or for slbia -- 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 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); 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 -- RIC=2 or 3 flushes process table caches.
-- sprn bus as bits 2--3. RIC=2 flushes process table caches. if l_in.ric(1) = '1' then
if l_in.sprn(3) = '1' then
v.pt0_valid := '0'; v.pt0_valid := '0';
v.pt3_valid := '0'; v.pt3_valid := '0';
v.ptb_valid := '0'; v.ptb_valid := '0';
@ -291,7 +290,7 @@ begin
-- Move to PID needs to invalidate L1 TLBs and cached -- Move to PID needs to invalidate L1 TLBs and cached
-- pgtbl0 value. Move to PTCR does that plus -- pgtbl0 value. Move to PTCR does that plus
-- invalidating the cached pgtbl3 and prtbl values as well. -- 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); v.pid := l_in.rs(31 downto 0);
else else
v.ptcr := l_in.rs; v.ptcr := l_in.rs;

@ -551,6 +551,10 @@ static const char *fast_spr_names[] =
"hsprg0", "hsprg1", "xer", "tar", "hsprg0", "hsprg1", "xer", "tar",
}; };


static const char *ldst_spr_names[] = {
"pidr", "ptcr", "dsisr", "dar"
};

static void gpr_read(uint64_t reg, uint64_t count) static void gpr_read(uint64_t reg, uint64_t count)
{ {
uint64_t data; uint64_t data;
@ -566,8 +570,10 @@ static void gpr_read(uint64_t reg, uint64_t count)
printf("r%"PRId64, reg); printf("r%"PRId64, reg);
else if ((reg - 32) < sizeof(fast_spr_names) / sizeof(fast_spr_names[0])) else if ((reg - 32) < sizeof(fast_spr_names) / sizeof(fast_spr_names[0]))
printf("%s", fast_spr_names[reg - 32]); printf("%s", fast_spr_names[reg - 32]);
else if (reg < 64) else if (reg < 60)
printf("gspr%"PRId64, reg); printf("gspr%"PRId64, reg);
else if (reg < 64)
printf("%s", ldst_spr_names[reg - 60]);
else else
printf("FPR%"PRId64, reg - 64); printf("FPR%"PRId64, reg - 64);
printf(":\t%016"PRIx64"\n", data); printf(":\t%016"PRIx64"\n", data);

Loading…
Cancel
Save