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;
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;
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)
);
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,
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);
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,
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');
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';
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;
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
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;
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;
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
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;
flush <= exception;
+ -- SPR values for core_debug
+ dbg_spr_data <= r3.dbg_spr;
+ dbg_spr_ack <= r3.dbg_spr_ack;
+
-- Update registers
r3in <= v;
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
-- 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';
-- 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;
"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;
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);