soc: Implement a global timebase across all cores

Now all cores see the same timebase value at any given instant.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/436/head
Paul Mackerras 4 weeks ago
parent e0c5af9bb1
commit 49fcbaa5b2

@ -264,7 +264,6 @@ package common is
type ctrl_t is record
wait_state: std_ulogic;
run: std_ulogic;
tb: std_ulogic_vector(63 downto 0);
dec: std_ulogic_vector(63 downto 0);
msr: std_ulogic_vector(63 downto 0);
cfar: std_ulogic_vector(63 downto 0);

@ -31,6 +31,9 @@ entity core is
-- Alternate reset (0xffff0000) for use by DRAM init fw
alt_reset : in std_ulogic;

-- Global timebase
timebase : in std_ulogic_vector(63 downto 0);

-- Wishbone interface
wishbone_insn_in : in wishbone_slave_out;
wishbone_insn_out : out wishbone_master_out;
@ -373,6 +376,7 @@ begin
port map (
clk => clk,
rst => rst_ex1,
timebase => timebase,
flush_in => flush,
busy_out => ex1_busy_out,
e_in => decode2_to_execute1,

@ -34,6 +34,8 @@ entity execute1 is
ext_irq_in : std_ulogic;
interrupt_in : WritebackToExecute1Type;

timebase : std_ulogic_vector(63 downto 0);

-- asynchronous
l_out : out Execute1ToLoadstore1Type;
fp_out : out Execute1ToFPUType;
@ -1901,8 +1903,8 @@ begin

-- Slow SPR read mux
with ex1.spr_select.sel select spr_result <=
ctrl.tb when SPRSEL_TB,
32x"0" & ctrl.tb(63 downto 32) when SPRSEL_TBU,
timebase when SPRSEL_TB,
32x"0" & timebase(63 downto 32) when SPRSEL_TBU,
ctrl.dec when SPRSEL_DEC,
32x"0" & PVR_MICROWATT when SPRSEL_PVR,
log_wr_addr & ex2.log_addr_spr when SPRSEL_LOGA,
@ -1956,16 +1958,14 @@ begin
end if;

ctrl_tmp <= ctrl;
-- FIXME: run at 512MHz not core freq
ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1);

x_to_pmu.mfspr <= '0';
x_to_pmu.mtspr <= '0';
x_to_pmu.tbbits(3) <= ctrl.tb(63 - 47);
x_to_pmu.tbbits(2) <= ctrl.tb(63 - 51);
x_to_pmu.tbbits(1) <= ctrl.tb(63 - 55);
x_to_pmu.tbbits(0) <= ctrl.tb(63 - 63);
x_to_pmu.tbbits(3) <= timebase(63 - 47);
x_to_pmu.tbbits(2) <= timebase(63 - 51);
x_to_pmu.tbbits(1) <= timebase(63 - 55);
x_to_pmu.tbbits(0) <= timebase(63 - 63);
x_to_pmu.pmm_msr <= ctrl.msr(MSR_PMM);
x_to_pmu.pr_msr <= ctrl.msr(MSR_PR);


@ -271,6 +271,8 @@ architecture behaviour of soc is

signal core_run_out : std_ulogic_vector(NCPUS-1 downto 0);

signal timebase : std_ulogic_vector(63 downto 0);

function wishbone_widen_data(wb : wb_io_master_out) return wishbone_master_out is
variable wwb : wishbone_master_out;
begin
@ -350,6 +352,21 @@ begin
end if;
end process;

-- Timebase just increments at the system clock frequency.
-- There is currently no way to set it.
-- Ideally it would (appear to) run at 512MHz like IBM POWER systems,
-- but Linux seems to cope OK with it being 100MHz or whatever.
tbase: process(system_clk)
begin
if rising_edge(system_clk) then
if soc_reset = '1' then
timebase <= (others => '0');
else
timebase <= std_ulogic_vector(unsigned(timebase) + 1);
end if;
end if;
end process;

-- Processor cores
processors: for i in 0 to NCPUS-1 generate
core: entity work.core
@ -374,6 +391,7 @@ begin
rst => rst_core(i),
alt_reset => alt_reset_d,
run_out => core_run_out(i),
timebase => timebase,
wishbone_insn_in => wb_masters_in(i + NCPUS),
wishbone_insn_out => wb_masters_out(i + NCPUS),
wishbone_data_in => wb_masters_in(i),

Loading…
Cancel
Save