diff --git a/core.vhdl b/core.vhdl index 0e60905..acb37cc 100644 --- a/core.vhdl +++ b/core.vhdl @@ -95,6 +95,13 @@ architecture behave of core is 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; @@ -213,6 +220,10 @@ begin 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 ); @@ -244,6 +255,7 @@ begin f_out => execute1_to_fetch1, e_out => execute1_to_writeback, icache_inval => ex1_icache_inval, + dbg_msr_out => msr, terminate_out => terminate ); @@ -301,6 +313,11 @@ begin 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 ); diff --git a/core_debug.vhdl b/core_debug.vhdl index ae4414e..c97213b 100644 --- a/core_debug.vhdl +++ b/core_debug.vhdl @@ -26,6 +26,13 @@ entity core_debug is 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 @@ -61,6 +68,15 @@ architecture behave of core_debug is -- 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); @@ -70,10 +86,15 @@ architecture behave of core_debug is 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, @@ -85,6 +106,8 @@ begin 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 @@ -126,6 +149,8 @@ begin 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)); @@ -143,6 +168,8 @@ begin 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; diff --git a/decode2.vhdl b/decode2.vhdl index edcc50c..b239392 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -285,9 +285,9 @@ begin 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 => diff --git a/execute1.vhdl b/execute1.vhdl index c479a45..82776e2 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -32,6 +32,8 @@ entity execute1 is e_out : out Execute1ToWritebackType; + dbg_msr_out : out std_ulogic_vector(63 downto 0); + icache_inval : out std_ulogic; terminate_out : out std_ulogic ); @@ -217,6 +219,8 @@ begin 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; diff --git a/register_file.vhdl b/register_file.vhdl index 6a4c989..2cffeea 100644 --- a/register_file.vhdl +++ b/register_file.vhdl @@ -17,6 +17,11 @@ entity register_file is 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 @@ -26,6 +31,9 @@ end entity register_file; 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) @@ -45,6 +53,7 @@ begin -- 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)))); @@ -56,7 +65,14 @@ begin 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 @@ -73,6 +89,24 @@ begin 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)