Implement CTRL register

The CTRL register has a single bit called RUN.  It has some unusual
behaviours:

- It can only be written via SPR number 152, which is privileged
- It can only be read via SPR number 136, which is non-privileged
- Reading in problem state (user mode) returns the RUN bit in bit 0,
  but reading in privileged state (hypervisor mode) returns the RUN
  bit in bits 0 and 15.
- Reading SPR 152 in problem state causes a HEAI (illegal instruction)
  interrupt, but reading in privileged state is a no-op; this is the
  same as for an unimplemented SPR.

The RUN bit goes to the PMU and is also plumbed out to drive a LED on
the Arty board.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/434/head
Paul Mackerras 2 years ago
parent ff0744b795
commit 7bc7f335f1

@ -58,6 +58,8 @@ package common is
constant SPR_FSCR : spr_num_t := 153; constant SPR_FSCR : spr_num_t := 153;
constant SPR_HFSCR : spr_num_t := 190; constant SPR_HFSCR : spr_num_t := 190;
constant SPR_HEIR : spr_num_t := 339; constant SPR_HEIR : spr_num_t := 339;
constant SPR_CTRL : spr_num_t := 136;
constant SPR_CTRLW : spr_num_t := 152;


-- PMU registers -- PMU registers
constant SPR_UPMC1 : spr_num_t := 771; constant SPR_UPMC1 : spr_num_t := 771;
@ -148,6 +150,8 @@ package common is
sel : spr_selector; sel : spr_selector;
valid : std_ulogic; valid : std_ulogic;
ispmu : std_ulogic; ispmu : std_ulogic;
ronly : std_ulogic;
wonly : std_ulogic;
end record; end record;
constant spr_id_init : spr_id := (sel => "0000", others => '0'); constant spr_id_init : spr_id := (sel => "0000", others => '0');


@ -161,6 +165,7 @@ package common is
constant SPRSEL_FSCR : spr_selector := 4x"7"; constant SPRSEL_FSCR : spr_selector := 4x"7";
constant SPRSEL_HFSCR : spr_selector := 4x"8"; constant SPRSEL_HFSCR : spr_selector := 4x"8";
constant SPRSEL_HEIR : spr_selector := 4x"9"; constant SPRSEL_HEIR : spr_selector := 4x"9";
constant SPRSEL_CTRL : spr_selector := 4x"a";
constant SPRSEL_XER : spr_selector := 4x"f"; constant SPRSEL_XER : spr_selector := 4x"f";


-- FSCR and HFSCR bit numbers -- FSCR and HFSCR bit numbers
@ -243,6 +248,7 @@ package common is


-- This needs to die... -- This needs to die...
type ctrl_t is record type ctrl_t is record
run: std_ulogic;
tb: std_ulogic_vector(63 downto 0); tb: std_ulogic_vector(63 downto 0);
dec: std_ulogic_vector(63 downto 0); dec: std_ulogic_vector(63 downto 0);
msr: std_ulogic_vector(63 downto 0); msr: std_ulogic_vector(63 downto 0);
@ -258,7 +264,7 @@ package common is
heir: std_ulogic_vector(63 downto 0); heir: std_ulogic_vector(63 downto 0);
end record; end record;
constant ctrl_t_init : ctrl_t := constant ctrl_t_init : ctrl_t :=
(xer_low => 18x"0", (run => '1', xer_low => 18x"0",
fscr_ic => x"0", fscr_pref => '1', fscr_tar => '1', fscr_ic => x"0", fscr_pref => '1', fscr_tar => '1',
hfscr_ic => x"0", hfscr_pref => '1', hfscr_tar => '1', hfscr_fp => '1', hfscr_ic => x"0", hfscr_pref => '1', hfscr_tar => '1', hfscr_fp => '1',
others => (others => '0')); others => (others => '0'));

@ -48,6 +48,7 @@ entity core is


ext_irq : in std_ulogic; ext_irq : in std_ulogic;


run_out : out std_ulogic;
terminated_out : out std_logic terminated_out : out std_logic
); );
end core; end core;
@ -390,6 +391,7 @@ begin
ls_events => loadstore_events, ls_events => loadstore_events,
dc_events => dcache_events, dc_events => dcache_events,
ic_events => icache_events, ic_events => icache_events,
run_out => run_out,
terminate_out => terminate, terminate_out => terminate,
dbg_spr_req => dbg_spr_req, dbg_spr_req => dbg_spr_req,
dbg_spr_ack => dbg_spr_ack, dbg_spr_ack => dbg_spr_ack,

@ -430,6 +430,8 @@ architecture behaviour of decode1 is
i.sel := "0000"; i.sel := "0000";
i.valid := '1'; i.valid := '1';
i.ispmu := '0'; i.ispmu := '0';
i.ronly := '0';
i.wonly := '0';
case sprn is case sprn is
when SPR_TB => when SPR_TB =>
i.sel := SPRSEL_TB; i.sel := SPRSEL_TB;
@ -458,6 +460,12 @@ architecture behaviour of decode1 is
i.sel := SPRSEL_HFSCR; i.sel := SPRSEL_HFSCR;
when SPR_HEIR => when SPR_HEIR =>
i.sel := SPRSEL_HEIR; i.sel := SPRSEL_HEIR;
when SPR_CTRL =>
i.sel := SPRSEL_CTRL;
i.ronly := '1';
when SPR_CTRLW =>
i.sel := SPRSEL_CTRL;
i.wonly := '1';
when others => when others =>
i.valid := '0'; i.valid := '0';
end case; end case;

@ -420,6 +420,8 @@ begin
v.e.input_cr := d_in.decode.input_cr; v.e.input_cr := d_in.decode.input_cr;
v.e.output_cr := d_in.decode.output_cr; v.e.output_cr := d_in.decode.output_cr;


v.e.spr_select := d_in.spr_info;

-- Work out whether XER SO/OV/OV32 bits are set -- Work out whether XER SO/OV/OV32 bits are set
-- or used by this instruction -- or used by this instruction
v.e.rc := decode_rc(d_in.decode.rc, d_in.insn); v.e.rc := decode_rc(d_in.decode.rc, d_in.insn);
@ -454,6 +456,9 @@ begin
v.e.uses_tar := '1'; v.e.uses_tar := '1';
when others => when others =>
end case; end case;
if d_in.spr_info.wonly = '1' then
v.e.spr_select.valid := '0';
end if;
end if; end if;
when OP_MTSPR => when OP_MTSPR =>
if is_X(d_in.insn) then if is_X(d_in.insn) then
@ -474,7 +479,9 @@ begin
v.e.uses_tar := '1'; v.e.uses_tar := '1';
when others => when others =>
end case; end case;
if d_in.spr_info.valid = '1' and d_in.valid = '1' then if d_in.spr_info.ronly = '1' then
v.e.spr_select.valid := '0';
elsif d_in.spr_info.valid = '1' and d_in.valid = '1' then
v.sgl_pipe := '1'; v.sgl_pipe := '1';
end if; end if;
end if; end if;
@ -505,8 +512,6 @@ begin
v.e.repeat := '1'; v.e.repeat := '1';
end if; end if;


v.e.spr_select := d_in.spr_info;

if decctr = '1' then if decctr = '1' then
-- read and write CTR -- read and write CTR
v.e.ramspr_odd_rdaddr := RAMSPR_CTR; v.e.ramspr_odd_rdaddr := RAMSPR_CTR;
@ -602,7 +607,7 @@ begin
if op = OP_MFSPR then if op = OP_MFSPR then
if d_in.ram_spr.valid = '1' then if d_in.ram_spr.valid = '1' then
v.e.result_sel := "101"; -- ramspr_result v.e.result_sel := "101"; -- ramspr_result
elsif d_in.spr_info.valid = '0' then elsif d_in.spr_info.valid = '0' or d_in.spr_info.wonly = '1' then
-- Privileged mfspr to invalid/unimplemented SPR numbers -- Privileged mfspr to invalid/unimplemented SPR numbers
-- writes the contents of RT back to RT (i.e. it's a no-op) -- writes the contents of RT back to RT (i.e. it's a no-op)
v.e.result_sel := "001"; -- logical_result v.e.result_sel := "001"; -- logical_result

@ -45,6 +45,7 @@ entity execute1 is


dbg_ctrl_out : out ctrl_t; dbg_ctrl_out : out ctrl_t;


run_out : out std_ulogic;
icache_inval : out std_ulogic; icache_inval : out std_ulogic;
terminate_out : out std_ulogic; terminate_out : out std_ulogic;


@ -92,6 +93,7 @@ architecture behaviour of execute1 is
write_hic : std_ulogic; write_hic : std_ulogic;
write_heir : std_ulogic; write_heir : std_ulogic;
set_heir : std_ulogic; set_heir : std_ulogic;
write_ctrl : std_ulogic;
end record; end record;
constant side_effect_init : side_effect_type := (others => '0'); constant side_effect_init : side_effect_type := (others => '0');


@ -404,6 +406,15 @@ architecture behaviour of execute1 is
return ret; return ret;
end; end;


function assemble_ctrl(c: ctrl_t; msrpr: std_ulogic) return std_ulogic_vector is
variable ret : std_ulogic_vector(63 downto 0);
begin
ret := (others => '0');
ret(0) := c.run;
ret(15) := c.run and not msrpr;
return ret;
end;

-- Tell vivado to keep the hierarchy for the random module so that the -- Tell vivado to keep the hierarchy for the random module so that the
-- net names in the xdc file match. -- net names in the xdc file match.
attribute keep_hierarchy : string; attribute keep_hierarchy : string;
@ -523,7 +534,7 @@ begin
x_to_pmu.addr_v <= '0'; x_to_pmu.addr_v <= '0';
x_to_pmu.spr_num <= ex1.pmu_spr_num; x_to_pmu.spr_num <= ex1.pmu_spr_num;
x_to_pmu.spr_val <= ex1.e.write_data; x_to_pmu.spr_val <= ex1.e.write_data;
x_to_pmu.run <= '1'; x_to_pmu.run <= ctrl.run;


-- XER forwarding. The CA and CA32 bits are only modified by instructions -- XER forwarding. The CA and CA32 bits are only modified by instructions
-- that are handled here, so for them we can just use the result most -- that are handled here, so for them we can just use the result most
@ -1334,6 +1345,8 @@ begin
v.se.write_hfscr := '1'; v.se.write_hfscr := '1';
when SPRSEL_HEIR => when SPRSEL_HEIR =>
v.se.write_heir := '1'; v.se.write_heir := '1';
when SPRSEL_CTRL =>
v.se.write_ctrl := '1';
when others => when others =>
end case; end case;
end if; end if;
@ -1773,6 +1786,7 @@ begin
assemble_fscr(ctrl) when SPRSEL_FSCR, assemble_fscr(ctrl) when SPRSEL_FSCR,
assemble_hfscr(ctrl) when SPRSEL_HFSCR, assemble_hfscr(ctrl) when SPRSEL_HFSCR,
ctrl.heir when SPRSEL_HEIR, ctrl.heir when SPRSEL_HEIR,
assemble_ctrl(ctrl, ex1.msr(MSR_PR)) when SPRSEL_CTRL,
assemble_xer(ex1.e.xerc, ctrl.xer_low) when others; assemble_xer(ex1.e.xerc, ctrl.xer_low) when others;


stage2_stall <= l_in.l2stall or fp_in.f2stall; stage2_stall <= l_in.l2stall or fp_in.f2stall;
@ -1943,6 +1957,9 @@ begin
ctrl_tmp.heir(63 downto 32) <= (others => '0'); ctrl_tmp.heir(63 downto 32) <= (others => '0');
end if; end if;
end if; end if;
if ex1.se.write_ctrl = '1' then
ctrl_tmp.run <= ex1.e.write_data(0);
end if;
end if; end if;


if interrupt_in.intr = '1' then if interrupt_in.intr = '1' then
@ -1981,6 +1998,7 @@ begin
e_out <= ex2.e; e_out <= ex2.e;
e_out.msr <= msr_copy(ctrl.msr); e_out.msr <= msr_copy(ctrl.msr);


run_out <= ctrl.run;
terminate_out <= ex2.se.terminate; terminate_out <= ex2.se.terminate;
icache_inval <= ex2.se.icache_inval; icache_inval <= ex2.se.icache_inval;



@ -142,6 +142,9 @@ end entity toplevel;


architecture behaviour of toplevel is architecture behaviour of toplevel is


-- Status
signal run_out : std_ulogic;

-- Reset signals: -- Reset signals:
signal soc_rst : std_ulogic; signal soc_rst : std_ulogic;
signal pll_rst : std_ulogic; signal pll_rst : std_ulogic;
@ -263,6 +266,7 @@ begin
system_clk => system_clk, system_clk => system_clk,
rst => soc_rst, rst => soc_rst,
sw_soc_reset => sw_rst, sw_soc_reset => sw_rst,
run_out => run_out,


-- UART signals -- UART signals
uart0_txd => uart_main_tx, uart0_txd => uart_main_tx,
@ -742,6 +746,7 @@ begin
led4 <= system_clk_locked; led4 <= system_clk_locked;
led5 <= eth_clk_locked; led5 <= eth_clk_locked;
led6 <= not soc_rst; led6 <= not soc_rst;
led7 <= run_out;


-- GPIO -- GPIO
gpio_in(10) <= btn0; gpio_in(10) <= btn0;

@ -99,6 +99,8 @@ entity soc is
rst : in std_ulogic; rst : in std_ulogic;
system_clk : in std_ulogic; system_clk : in std_ulogic;


run_out : out std_ulogic;

-- "Large" (64-bit) DRAM wishbone -- "Large" (64-bit) DRAM wishbone
wb_dram_in : out wishbone_master_out; wb_dram_in : out wishbone_master_out;
wb_dram_out : in wishbone_slave_out := wishbone_slave_out_init; wb_dram_out : in wishbone_slave_out := wishbone_slave_out_init;
@ -366,6 +368,7 @@ begin
clk => system_clk, clk => system_clk,
rst => rst_core, rst => rst_core,
alt_reset => alt_reset_d, alt_reset => alt_reset_d,
run_out => run_out,
wishbone_insn_in => wishbone_icore_in, wishbone_insn_in => wishbone_icore_in,
wishbone_insn_out => wishbone_icore_out, wishbone_insn_out => wishbone_icore_out,
wishbone_data_in => wishbone_dcore_in, wishbone_data_in => wishbone_dcore_in,

Loading…
Cancel
Save