From 49fcbaa5b232ec9d2df1804f9e4261f08cf02580 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 9 Jan 2025 19:27:58 +1100 Subject: [PATCH] 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 --- common.vhdl | 1 - core.vhdl | 4 ++++ execute1.vhdl | 16 ++++++++-------- soc.vhdl | 18 ++++++++++++++++++ 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/common.vhdl b/common.vhdl index 1c8642b..31793a8 100644 --- a/common.vhdl +++ b/common.vhdl @@ -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); diff --git a/core.vhdl b/core.vhdl index 187e176..bf0708e 100644 --- a/core.vhdl +++ b/core.vhdl @@ -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, diff --git a/execute1.vhdl b/execute1.vhdl index 08bc694..c5b2dc4 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -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); diff --git a/soc.vhdl b/soc.vhdl index 0ed234d..36f34e9 100644 --- a/soc.vhdl +++ b/soc.vhdl @@ -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),