mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-05-05 07:44: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;
|
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;
|
||||||
|
|||||||
12
core.vhdl
12
core.vhdl
@@ -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;
|
||||||
|
|
||||||
|
|||||||
11
mmu.vhdl
11
mmu.vhdl
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user