mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-03-06 19:11:16 +00:00
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>
This commit is contained in:
@@ -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;
|
||||
|
||||
12
core.vhdl
12
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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
11
mmu.vhdl
11
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user