ramspr_wraddr : ramspr_index;
ramspr_write_even : std_ulogic;
ramspr_write_odd : std_ulogic;
+ dbg_spr_access : std_ulogic;
dec_ctr : std_ulogic;
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
spr_is_ram => '0',
ramspr_even_rdaddr => 0, ramspr_odd_rdaddr => 0, ramspr_rd_odd => '0',
ramspr_wraddr => 0, ramspr_write_even => '0', ramspr_write_odd => '0',
+ dbg_spr_access => '0',
dec_ctr => '0',
others => (others => '0'));
signal dbg_gpr_ack : std_ulogic;
signal dbg_gpr_addr : gspr_index_t;
signal dbg_gpr_data : std_ulogic_vector(63 downto 0);
+ signal dbg_spr_req : std_ulogic;
+ 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 ctrl_debug : ctrl_t;
execute2_bypass => execute2_bypass,
execute2_cr_bypass => execute2_cr_bypass,
writeback_bypass => writeback_bypass,
+ dbg_spr_req => dbg_spr_req,
+ dbg_spr_addr => dbg_spr_addr,
log_out => log_data(119 downto 110)
);
decode2_busy_in <= ex1_busy_out;
dc_events => dcache_events,
ic_events => icache_events,
terminate_out => terminate,
+ dbg_spr_req => dbg_spr_req,
+ dbg_spr_ack => dbg_spr_ack,
+ dbg_spr_addr => dbg_spr_addr,
+ dbg_spr_data => dbg_spr_data,
sim_dump => sim_ex_dump,
sim_dump_done => sim_cr_dump,
log_out => log_data(134 downto 120),
dbg_gpr_ack => dbg_gpr_ack,
dbg_gpr_addr => dbg_gpr_addr,
dbg_gpr_data => dbg_gpr_data,
+ dbg_spr_req => dbg_spr_req,
+ dbg_spr_ack => dbg_spr_ack,
+ dbg_spr_addr => dbg_spr_addr,
+ dbg_spr_data => dbg_spr_data,
log_data => log_data,
log_read_addr => log_rd_addr,
log_read_data => log_rd_data,
nia : in std_ulogic_vector(63 downto 0);
msr : in std_ulogic_vector(63 downto 0);
- -- GSPR register read port
+ -- GPR/FPR register read port
dbg_gpr_req : out std_ulogic;
dbg_gpr_ack : in std_ulogic;
dbg_gpr_addr : out gspr_index_t;
dbg_gpr_data : in std_ulogic_vector(63 downto 0);
+ -- SPR register read port
+ 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);
+
-- Core logging data
log_data : in std_ulogic_vector(255 downto 0);
log_read_addr : in std_ulogic_vector(31 downto 0);
signal do_icreset : std_ulogic;
signal terminated : std_ulogic;
signal do_gspr_rd : std_ulogic;
- signal gspr_index : gspr_index_t;
+ signal gspr_index : std_ulogic_vector(7 downto 0);
+ signal gspr_data : std_ulogic_vector(63 downto 0);
+
+ signal spr_index_valid : std_ulogic;
signal log_dmi_addr : std_ulogic_vector(31 downto 0) := (others => '0');
signal log_dmi_data : std_ulogic_vector(63 downto 0) := (others => '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;
- dbg_gpr_req <= dmi_req when dmi_addr = DBG_CORE_GSPR_DATA
- else '0';
+ else dbg_gpr_ack or dbg_spr_ack;
-- Status register read composition
stat_reg <= (2 => terminated,
0 => stopping,
others => '0');
+ gspr_data <= dbg_gpr_data when gspr_index(5) = '0' else
+ dbg_spr_data when spr_index_valid = '1' else
+ (others => '0');
+
-- DMI read data mux
with dmi_addr select dmi_dout <=
stat_reg when DBG_CORE_STAT,
nia when DBG_CORE_NIA,
msr when DBG_CORE_MSR,
- dbg_gpr_data when DBG_CORE_GSPR_DATA,
+ gspr_data when DBG_CORE_GSPR_DATA,
log_write_addr & log_dmi_addr when DBG_CORE_LOG_ADDR,
log_dmi_data when DBG_CORE_LOG_DATA,
log_dmi_trigger when DBG_CORE_LOG_TRIGGER,
terminated <= '0';
end if;
elsif dmi_addr = DBG_CORE_GSPR_INDEX then
- gspr_index <= dmi_din(gspr_index_t'left downto 0);
+ gspr_index <= dmi_din(7 downto 0);
elsif dmi_addr = DBG_CORE_LOG_ADDR then
log_dmi_addr <= dmi_din(31 downto 0);
do_dmi_log_rd <= '1';
end if;
end process;
- dbg_gpr_addr <= gspr_index;
+ gspr_access: process(clk)
+ variable valid : std_ulogic;
+ variable sel : spr_selector;
+ variable isram : std_ulogic;
+ variable raddr : ramspr_index;
+ 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);
+ 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);
+
+ -- For SPRs, use the same mapping as when the fast SPRs were in the GPR file
+ valid := '1';
+ sel := "000";
+ isram := '1';
+ raddr := 0;
+ odd := '0';
+ case gspr_index(4 downto 0) is
+ when 5x"00" =>
+ raddr := RAMSPR_LR;
+ when 5x"01" =>
+ odd := '1';
+ raddr := RAMSPR_CTR;
+ when 5x"02" | 5x"03" =>
+ odd := gspr_index(0);
+ raddr := RAMSPR_SRR0;
+ when 5x"04" | 5x"05" =>
+ odd := gspr_index(0);
+ raddr := RAMSPR_HSRR0;
+ when 5x"06" | 5x"07" =>
+ odd := gspr_index(0);
+ raddr := RAMSPR_SPRG0;
+ when 5x"08" | 5x"09" =>
+ odd := gspr_index(0);
+ raddr := RAMSPR_SPRG2;
+ when 5x"0a" | 5x"0b" =>
+ odd := gspr_index(0);
+ raddr := RAMSPR_HSPRG0;
+ when 5x"0c" =>
+ isram := '0';
+ sel := SPRSEL_XER;
+ when 5x"0d" =>
+ raddr := RAMSPR_TAR;
+ when others =>
+ valid := '0';
+ end case;
+ dbg_spr_addr <= isram & sel & std_ulogic_vector(to_unsigned(raddr, 3)) & odd;
+ spr_index_valid <= valid;
+ end if;
+ end process;
-- Core control signals generated by the debug module
core_stop <= stopping and not do_step;
execute2_cr_bypass : in cr_bypass_data_t;
writeback_bypass : in bypass_data_t;
+ -- Access to SPRs from core_debug module
+ dbg_spr_req : in std_ulogic;
+ dbg_spr_addr : in std_ulogic_vector(7 downto 0);
+
log_out : out std_ulogic_vector(9 downto 0)
);
end entity decode2;
reg_o_valid : std_ulogic;
input_ov : std_ulogic;
output_ov : std_ulogic;
+ read_rspr : std_ulogic;
end record;
constant reg_type_init : reg_type :=
(e => Decode2ToExecute1Init, repeat => NONE, others => '0');
" tag=" & integer'image(dc2in.e.instr_tag.tag) & std_ulogic'image(dc2in.e.instr_tag.valid);
end if;
dc2 <= dc2in;
+ elsif dc2.read_rspr = '0' then
+ -- Update debug SPR access signals even when stalled
+ -- if the instruction in dc2.e doesn't read any SPRs.
+ dc2.e.dbg_spr_access <= dc2in.e.dbg_spr_access;
+ dc2.e.ramspr_even_rdaddr <= dc2in.e.ramspr_even_rdaddr;
+ dc2.e.ramspr_odd_rdaddr <= dc2in.e.ramspr_odd_rdaddr;
+ dc2.e.ramspr_rd_odd <= dc2in.e.ramspr_rd_odd;
end if;
end if;
end process;
variable op : insn_type_t;
variable valid_in : std_ulogic;
variable decctr : std_ulogic;
+ variable sprs_busy : std_ulogic;
begin
v := dc2;
if dc2.busy = '0' then
v.e := Decode2ToExecute1Init;
+ sprs_busy := '0';
+
if d_in.valid = '1' then
v.prev_sgl := dc2.sgl_pipe;
v.sgl_pipe := d_in.decode.sgl_pipe;
v.e.ramspr_odd_rdaddr := RAMSPR_CTR;
v.e.ramspr_wraddr := RAMSPR_CTR;
v.e.ramspr_write_odd := '1';
+ sprs_busy := '1';
end if;
if v.e.lr = '1' then
-- write LR
else
v.e.ramspr_even_rdaddr := RAMSPR_TAR;
end if;
+ sprs_busy := '1';
when OP_MFSPR =>
v.e.ramspr_even_rdaddr := d_in.ram_spr.index;
v.e.ramspr_odd_rdaddr := d_in.ram_spr.index;
v.e.ramspr_rd_odd := d_in.ram_spr.isodd;
v.e.spr_is_ram := d_in.ram_spr.valid;
+ sprs_busy := d_in.ram_spr.valid;
when OP_MTSPR =>
v.e.ramspr_wraddr := d_in.ram_spr.index;
v.e.ramspr_write_even := d_in.ram_spr.valid and not d_in.ram_spr.isodd;
when OP_RFID =>
v.e.ramspr_even_rdaddr := RAMSPR_SRR0;
v.e.ramspr_odd_rdaddr := RAMSPR_SRR1;
+ sprs_busy := '1';
when others =>
end case;
+ v.read_rspr := sprs_busy and d_in.valid;
case d_in.decode.length is
when is1B =>
-- Privileged mfspr to invalid/unimplemented SPR numbers
-- writes the contents of RT back to RT (i.e. it's a no-op)
v.e.result_sel := "001"; -- logical_result
- elsif d_in.spr_info.ispmu = '1' then
- v.e.result_sel := "100"; -- pmuspr_result
end if;
end if;
stall_out <= dc2.busy or deferred;
+ v.e.dbg_spr_access := dbg_spr_req and not v.read_rspr;
+ if v.e.dbg_spr_access = '1' then
+ v.e.ramspr_even_rdaddr := to_integer(unsigned(dbg_spr_addr(3 downto 1)));
+ v.e.ramspr_odd_rdaddr := to_integer(unsigned(dbg_spr_addr(3 downto 1)));
+ v.e.ramspr_rd_odd := dbg_spr_addr(0);
+ end if;
+
-- Update registers
dc2in <= v;
dc_events : in DcacheEventType;
ic_events : in IcacheEventType;
+ -- 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(7 downto 0);
+ dbg_spr_data : out std_ulogic_vector(63 downto 0);
+
-- debug
sim_dump : in std_ulogic;
sim_dump_done : out std_ulogic;
end if;
end process;
+ ex_dbg_spr: process(clk)
+ begin
+ if rising_edge(clk) then
+ if rst = '0' and dbg_spr_req = '1' then
+ if e_in.dbg_spr_access = '1' and dbg_spr_ack = '0' then
+ if dbg_spr_addr(7) = '1' then
+ dbg_spr_data <= ramspr_result;
+ else
+ dbg_spr_data <= assemble_xer(xerc_in, ctrl.xer_low);
+ end if;
+ dbg_spr_ack <= '1';
+ end if;
+ else
+ dbg_spr_ack <= '0';
+ end if;
+ end if;
+ end process;
+
-- Data path for integer instructions (first execute stage)
execute1_dp: process(all)
variable a_inv : std_ulogic_vector(63 downto 0);
{
"lr", "ctr", "srr0", "srr1", "hsrr0", "hsrr1",
"sprg0", "sprg1", "sprg2", "sprg3",
- "hsprg0", "hsprg1", "xer"
+ "hsprg0", "hsprg1", "xer", "tar",
};
static void gpr_read(uint64_t reg, uint64_t count)