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;
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;

@ -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,

@ -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';
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_gpr_req <= not gspr_index(5);
dbg_spr_req <= gspr_index(5);
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';

@ -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;

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
-- 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
-- reading one of the SPRs in the MMU
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';
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;


@ -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;

@ -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);

Loading…
Cancel
Save