signal dbg_core_rst: std_ulogic;
signal dbg_icache_rst: std_ulogic;
+ signal dbg_gpr_req : std_ulogic;
+ signal dbg_gpr_ack : std_ulogic;
+ signal dbg_gpr_addr : gspr_index_t;
+ signal dbg_gpr_data : std_ulogic_vector(63 downto 0);
+
+ signal msr : std_ulogic_vector(63 downto 0);
+
-- Debug status
signal dbg_core_is_stopped: std_ulogic;
d_in => decode2_to_register_file,
d_out => register_file_to_decode2,
w_in => writeback_to_register_file,
+ dbg_gpr_req => dbg_gpr_req,
+ dbg_gpr_ack => dbg_gpr_ack,
+ dbg_gpr_addr => dbg_gpr_addr,
+ dbg_gpr_data => dbg_gpr_data,
sim_dump => terminate,
sim_dump_done => sim_cr_dump
);
f_out => execute1_to_fetch1,
e_out => execute1_to_writeback,
icache_inval => ex1_icache_inval,
+ dbg_msr_out => msr,
terminate_out => terminate
);
terminate => terminate,
core_stopped => dbg_core_is_stopped,
nia => fetch1_to_icache.nia,
+ msr => msr,
+ dbg_gpr_req => dbg_gpr_req,
+ dbg_gpr_ack => dbg_gpr_ack,
+ dbg_gpr_addr => dbg_gpr_addr,
+ dbg_gpr_data => dbg_gpr_data,
terminated_out => terminated_out
);
terminate : in std_ulogic;
core_stopped : in std_ulogic;
nia : in std_ulogic_vector(63 downto 0);
+ msr : in std_ulogic_vector(63 downto 0);
+
+ -- GSPR 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);
-- Misc
terminated_out : out std_ulogic
-- NIA register (read only for now)
constant DBG_CORE_NIA : std_ulogic_vector(3 downto 0) := "0010";
+ -- MSR (read only)
+ constant DBG_CORE_MSR : std_ulogic_vector(3 downto 0) := "0011";
+
+ -- GSPR register index
+ constant DBG_CORE_GSPR_INDEX : std_ulogic_vector(3 downto 0) := "0100";
+
+ -- GSPR register data
+ constant DBG_CORE_GSPR_DATA : std_ulogic_vector(3 downto 0) := "0101";
+
-- Some internal wires
signal stat_reg : std_ulogic_vector(63 downto 0);
signal do_reset : std_ulogic;
signal do_icreset : std_ulogic;
signal terminated : std_ulogic;
+ signal do_gspr_rd : std_ulogic;
+ signal gspr_index : gspr_index_t;
begin
- -- Single cycle register accesses on DMI
- dmi_ack <= dmi_req;
+ -- 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';
-- Status register read composition
stat_reg <= (2 => terminated,
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,
(others => '0') when others;
-- DMI writes
stopping <= '0';
terminated <= '0';
end if;
+ elsif dmi_addr = DBG_CORE_GSPR_INDEX then
+ gspr_index <= dmi_din(gspr_index_t'left downto 0);
end if;
else
report("DMI read from " & to_string(dmi_addr));
end if;
end process;
+ dbg_gpr_addr <= gspr_index;
+
-- Core control signals generated by the debug module
core_stop <= stopping and not do_step;
core_rst <= do_reset;
decoded_reg_c := decode_input_reg_c (d_in.decode.input_reg_c, d_in.insn, r_in.read3_data);
decoded_reg_o := decode_output_reg (d_in.decode.output_reg_a, d_in.insn, d_in.ispr1);
- r_out.read1_enable <= decoded_reg_a.reg_valid;
- r_out.read2_enable <= decoded_reg_b.reg_valid;
- r_out.read3_enable <= decoded_reg_c.reg_valid;
+ r_out.read1_enable <= decoded_reg_a.reg_valid and d_in.valid;
+ r_out.read2_enable <= decoded_reg_b.reg_valid and d_in.valid;
+ r_out.read3_enable <= decoded_reg_c.reg_valid and d_in.valid;
case d_in.decode.length is
when is1B =>
e_out : out Execute1ToWritebackType;
+ dbg_msr_out : out std_ulogic_vector(63 downto 0);
+
icache_inval : out std_ulogic;
terminate_out : out std_ulogic
);
d_out => divider_to_x
);
+ dbg_msr_out <= ctrl.msr;
+
a_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data1 = '1' else e_in.read_data1;
b_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data2 = '1' else e_in.read_data2;
c_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data3 = '1' else e_in.read_data3;
w_in : in WritebackToRegisterFileType;
+ dbg_gpr_req : in std_ulogic;
+ dbg_gpr_ack : out std_ulogic;
+ dbg_gpr_addr : in gspr_index_t;
+ dbg_gpr_data : out std_ulogic_vector(63 downto 0);
+
-- debug
sim_dump : in std_ulogic;
sim_dump_done : out std_ulogic
architecture behaviour of register_file is
type regfile is array(0 to 63) of std_ulogic_vector(63 downto 0);
signal registers : regfile := (others => (others => '0'));
+ signal rd_port_b : std_ulogic_vector(63 downto 0);
+ signal dbg_data : std_ulogic_vector(63 downto 0);
+ signal dbg_ack : std_ulogic;
begin
-- synchronous writes
register_write_0: process(clk)
-- asynchronous reads
register_read_0: process(all)
+ variable b_addr : gspr_index_t;
begin
if d_in.read1_enable = '1' then
report "Reading GPR " & to_hstring(d_in.read1_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read1_reg))));
report "Reading GPR " & to_hstring(d_in.read3_reg) & " " & to_hstring(registers(to_integer(unsigned(d_in.read3_reg))));
end if;
d_out.read1_data <= registers(to_integer(unsigned(d_in.read1_reg)));
- d_out.read2_data <= registers(to_integer(unsigned(d_in.read2_reg)));
+ -- B read port is multiplexed with reads from the debug circuitry
+ if d_in.read2_enable = '0' and dbg_gpr_req = '1' and dbg_ack = '0' then
+ b_addr := dbg_gpr_addr;
+ else
+ b_addr := d_in.read2_reg;
+ end if;
+ rd_port_b <= registers(to_integer(unsigned(b_addr)));
+ d_out.read2_data <= rd_port_b;
d_out.read3_data <= registers(to_integer(unsigned(gpr_to_gspr(d_in.read3_reg))));
-- Forward any written data
end if;
end process register_read_0;
+ -- Latch read data and ack if dbg read requested and B port not busy
+ dbg_register_read: process(clk)
+ begin
+ if rising_edge(clk) then
+ if dbg_gpr_req = '1' then
+ if d_in.read2_enable = '0' and dbg_ack = '0' then
+ dbg_data <= rd_port_b;
+ dbg_ack <= '1';
+ end if;
+ else
+ dbg_ack <= '0';
+ end if;
+ end if;
+ end process;
+
+ dbg_gpr_ack <= dbg_ack;
+ dbg_gpr_data <= dbg_data;
+
-- Dump registers if core terminates
sim_dump_test: if SIM generate
dump_registers: process(all)