Skip to content

Commit c5abe3c

Browse files
authored
Merge pull request #440 from paulusmack/compliance
More compliance improvements - [H]DEXCR, no-op SPRs, writable TB
2 parents bae24b1 + 413907e commit c5abe3c

9 files changed

+193
-30
lines changed

common.vhdl

+36-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ package common is
3939
constant SPR_DAR : spr_num_t := 19;
4040
constant SPR_TB : spr_num_t := 268;
4141
constant SPR_TBU : spr_num_t := 269;
42+
constant SPR_TBLW : spr_num_t := 284;
43+
constant SPR_TBUW : spr_num_t := 285;
4244
constant SPR_DEC : spr_num_t := 22;
4345
constant SPR_SRR0 : spr_num_t := 26;
4446
constant SPR_SRR1 : spr_num_t := 27;
@@ -71,6 +73,14 @@ package common is
7173
constant SPR_DAWRX1 : spr_num_t := 189;
7274
constant SPR_HASHKEYR : spr_num_t := 468;
7375
constant SPR_HASHPKEYR : spr_num_t := 469;
76+
constant SPR_DEXCR : spr_num_t := 828;
77+
constant SPR_DEXCRU : spr_num_t := 812;
78+
constant SPR_HDEXCR : spr_num_t := 471;
79+
constant SPR_HDEXCU : spr_num_t := 455;
80+
constant SPR_NOOP0 : spr_num_t := 808;
81+
constant SPR_NOOP1 : spr_num_t := 809;
82+
constant SPR_NOOP2 : spr_num_t := 810;
83+
constant SPR_NOOP3 : spr_num_t := 811;
7484

7585
-- PMU registers
7686
constant SPR_UPMC1 : spr_num_t := 771;
@@ -167,6 +177,7 @@ package common is
167177
ispmu : std_ulogic;
168178
ronly : std_ulogic;
169179
wonly : std_ulogic;
180+
noop : std_ulogic;
170181
end record;
171182
constant spr_id_init : spr_id := (sel => "0000", others => '0');
172183

@@ -184,6 +195,7 @@ package common is
184195
constant SPRSEL_DSCR : spr_selector := 4x"b";
185196
constant SPRSEL_PIR : spr_selector := 4x"c";
186197
constant SPRSEL_CIABR : spr_selector := 4x"d";
198+
constant SPRSEL_DEXCR : spr_selector := 4x"e";
187199
constant SPRSEL_XER : spr_selector := 4x"f";
188200

189201
-- FSCR and HFSCR bit numbers
@@ -266,6 +278,16 @@ package common is
266278
pri : std_ulogic_vector(31 downto 0); -- 8 bits each for 4 cpus
267279
end record;
268280

281+
-- Bits in each half of DEXCR and HDEXCR
282+
subtype aspect_bits_t is std_ulogic_vector(4 downto 0);
283+
constant aspect_bits_init : aspect_bits_t := (others => '1');
284+
-- Bit numbers in aspect_bits_t
285+
constant DEXCR_SBHE : integer := 4; -- speculative branch hint enable
286+
constant DEXCR_IBRTPD : integer := 3; -- indirect branch recurrent target prediction disable
287+
constant DEXCR_SRAPD : integer := 2; -- subroutine return address prediction disable
288+
constant DEXCR_NPHIE : integer := 1; -- non-privileged hash instruction enable
289+
constant DEXCR_PHIE : integer := 0; -- privileged hash instruction enable
290+
269291
-- This needs to die...
270292
type ctrl_t is record
271293
wait_state: std_ulogic;
@@ -287,14 +309,26 @@ package common is
287309
heir: std_ulogic_vector(63 downto 0);
288310
dscr: std_ulogic_vector(24 downto 0);
289311
ciabr: std_ulogic_vector(63 downto 0);
312+
dexcr_pnh: aspect_bits_t;
313+
dexcr_pro: aspect_bits_t;
314+
hdexcr_hyp: aspect_bits_t;
315+
hdexcr_enf: aspect_bits_t;
290316
end record;
291317
constant ctrl_t_init : ctrl_t :=
292318
(wait_state => '0', run => '1', xer_low => 18x"0",
293319
fscr_ic => x"0", fscr_pref => '1', fscr_scv => '1', fscr_tar => '1', fscr_dscr => '1',
294320
hfscr_ic => x"0", hfscr_pref => '1', hfscr_tar => '1', hfscr_dscr => '1', hfscr_fp => '1',
295321
dscr => (others => '0'),
322+
dexcr_pnh => aspect_bits_init, dexcr_pro => aspect_bits_init,
323+
hdexcr_hyp => aspect_bits_init, hdexcr_enf => aspect_bits_init,
296324
others => (others => '0'));
297325

326+
type timebase_ctrl is record
327+
reset : std_ulogic;
328+
rd_prot : std_ulogic; -- read-protect => userspace can't read TB
329+
freeze : std_ulogic;
330+
end record;
331+
298332
type Fetch1ToIcacheType is record
299333
req: std_ulogic;
300334
fetch_fail : std_ulogic;
@@ -604,6 +638,7 @@ package common is
604638
e2stall : std_ulogic;
605639
msr : std_ulogic_vector(63 downto 0);
606640
hashkey : std_ulogic_vector(63 downto 0);
641+
hash_enable : std_ulogic;
607642
end record;
608643
constant Execute1ToLoadstore1Init : Execute1ToLoadstore1Type :=
609644
(valid => '0', op => OP_ILLEGAL, ci => '0', byte_reverse => '0',
@@ -616,7 +651,7 @@ package common is
616651
length => (others => '0'),
617652
mode_32bit => '0', is_32bit => '0', prefixed => '0',
618653
repeat => '0', second => '0', e2stall => '0',
619-
msr => (others => '0'), hashkey => (others => '0'));
654+
msr => (others => '0'), hashkey => (others => '0'), hash_enable => '0');
620655

621656
type Loadstore1ToExecute1Type is record
622657
busy : std_ulogic;

core.vhdl

+4-3
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ entity core is
3131
-- Alternate reset (0xffff0000) for use by DRAM init fw
3232
alt_reset : in std_ulogic;
3333

34-
-- Global timebase
35-
timebase : in std_ulogic_vector(63 downto 0);
34+
-- Global timebase control
35+
tb_ctrl : in timebase_ctrl;
3636

3737
-- Wishbone interface
3838
wishbone_insn_in : in wishbone_slave_out;
@@ -309,6 +309,7 @@ begin
309309
busy_in => decode2_busy_in,
310310
stall_out => decode2_stall_out,
311311
flush_in => flush,
312+
tb_ctrl => tb_ctrl,
312313
complete_in => complete,
313314
stopped_out => dbg_core_is_stopped,
314315
d_in => decode1_to_decode2,
@@ -376,7 +377,7 @@ begin
376377
port map (
377378
clk => clk,
378379
rst => rst_ex1,
379-
timebase => timebase,
380+
tb_ctrl => tb_ctrl,
380381
flush_in => flush,
381382
busy_out => ex1_busy_out,
382383
e_in => decode2_to_execute1,

decode1.vhdl

+16
Original file line numberDiff line numberDiff line change
@@ -457,11 +457,20 @@ architecture behaviour of decode1 is
457457
i.ispmu := '0';
458458
i.ronly := '0';
459459
i.wonly := '0';
460+
i.noop := '0';
460461
case sprn is
461462
when SPR_TB =>
462463
i.sel := SPRSEL_TB;
464+
i.ronly := '1';
463465
when SPR_TBU =>
464466
i.sel := SPRSEL_TBU;
467+
i.ronly := '1';
468+
when SPR_TBLW =>
469+
i.sel := SPRSEL_TB;
470+
i.wonly := '1';
471+
when SPR_TBUW =>
472+
i.sel := SPRSEL_TB;
473+
i.wonly := '1';
465474
when SPR_DEC =>
466475
i.sel := SPRSEL_DEC;
467476
when SPR_PVR =>
@@ -499,6 +508,13 @@ architecture behaviour of decode1 is
499508
i.sel := SPRSEL_PIR;
500509
when SPR_CIABR =>
501510
i.sel := SPRSEL_CIABR;
511+
when SPR_DEXCR | SPR_HDEXCR =>
512+
i.sel := SPRSEL_DEXCR;
513+
when SPR_DEXCRU | SPR_HDEXCU =>
514+
i.sel := SPRSEL_DEXCR;
515+
i.ronly := '1';
516+
when SPR_NOOP0 | SPR_NOOP1 | SPR_NOOP2 | SPR_NOOP3 =>
517+
i.noop := '1';
502518
when others =>
503519
i.valid := '0';
504520
end case;

decode2.vhdl

+10-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ entity decode2 is
2727

2828
flush_in: in std_ulogic;
2929

30+
tb_ctrl : timebase_ctrl;
31+
3032
d_in : in Decode1ToDecode2Type;
3133

3234
e_out : out Decode2ToExecute1Type;
@@ -696,16 +698,23 @@ begin
696698
if op = OP_MFSPR then
697699
if d_in.ram_spr.valid = '1' then
698700
v.e.result_sel := "101"; -- ramspr_result
699-
elsif d_in.spr_info.valid = '0' or d_in.spr_info.wonly = '1' then
701+
elsif d_in.spr_info.valid = '0' or d_in.spr_info.wonly = '1' or
702+
d_in.spr_info.noop = '1' then
700703
-- Privileged mfspr to invalid/unimplemented SPR numbers
701704
-- writes the contents of RT back to RT (i.e. it's a no-op)
705+
-- as does any mfspr from the reserved/noop SPR numbers
702706
v.e.result_sel := "001"; -- logical_result
703707
end if;
704708
end if;
705709
v.e.privileged := d_in.decode.privileged;
706710
if (op = OP_MFSPR or op = OP_MTSPR) and d_in.insn(20) = '1' then
707711
v.e.privileged := '1';
708712
end if;
713+
-- Reading TB is privileged if syscon_tb_ctrl.rd_protect is 1
714+
if tb_ctrl.rd_prot = '1' and op = OP_MFSPR and d_in.spr_info.valid = '1' and
715+
(d_in.spr_info.sel = SPRSEL_TB or d_in.spr_info.sel = SPRSEL_TBU) then
716+
v.e.privileged := '1';
717+
end if;
709718
v.e.prefixed := d_in.prefixed;
710719
v.e.prefix := d_in.prefix;
711720
v.e.illegal_suffix := d_in.illegal_suffix;

execute1.vhdl

+89-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ entity execute1 is
3434
ext_irq_in : std_ulogic;
3535
interrupt_in : WritebackToExecute1Type;
3636

37-
timebase : std_ulogic_vector(63 downto 0);
37+
tb_ctrl : timebase_ctrl;
3838

3939
-- asynchronous
4040
l_out : out Execute1ToLoadstore1Type;
@@ -101,6 +101,8 @@ architecture behaviour of execute1 is
101101
write_ciabr : std_ulogic;
102102
enter_wait : std_ulogic;
103103
scv_trap : std_ulogic;
104+
write_tbl : std_ulogic;
105+
write_tbu : std_ulogic;
104106
end record;
105107
constant side_effect_init : side_effect_type := (others => '0');
106108

@@ -279,6 +281,10 @@ architecture behaviour of execute1 is
279281

280282
signal stage2_stall : std_ulogic;
281283

284+
signal timebase : std_ulogic_vector(63 downto 0);
285+
signal tb_next : std_ulogic_vector(63 downto 0);
286+
signal tb_carry : std_ulogic;
287+
282288
type privilege_level is (USER, SUPER);
283289
type op_privilege_array is array(insn_type_t) of privilege_level;
284290
constant op_privilege: op_privilege_array := (
@@ -425,6 +431,32 @@ architecture behaviour of execute1 is
425431
return ret;
426432
end;
427433

434+
-- return contents of DEXCR or HDEXCR
435+
-- top 32 bits are zeroed for access via non-privileged number
436+
function assemble_dexcr(c: ctrl_t; insn: std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
437+
variable ret : std_ulogic_vector(63 downto 0);
438+
variable spr : std_ulogic_vector(9 downto 0);
439+
variable dexh, dexl : aspect_bits_t;
440+
begin
441+
ret := (others => '0');
442+
spr := insn(15 downto 11) & insn(20 downto 16);
443+
if spr(9) = '1' then
444+
dexh := c.dexcr_pnh;
445+
dexl := c.dexcr_pro;
446+
else
447+
dexh := c.hdexcr_hyp;
448+
dexl := c.hdexcr_enf;
449+
end if;
450+
if spr(4) = '0' then
451+
dexl := (others => '0');
452+
end if;
453+
ret := dexh(DEXCR_SBHE) & "00" & dexh(DEXCR_IBRTPD) & dexh(DEXCR_SRAPD) &
454+
dexh(DEXCR_NPHIE) & dexh(DEXCR_PHIE) & 25x"0" &
455+
dexl(DEXCR_SBHE) & "00" & dexl(DEXCR_IBRTPD) & dexl(DEXCR_SRAPD) &
456+
dexl(DEXCR_NPHIE) & dexl(DEXCR_PHIE) & 25x"0";
457+
return ret;
458+
end;
459+
428460
-- Tell vivado to keep the hierarchy for the random module so that the
429461
-- net names in the xdc file match.
430462
attribute keep_hierarchy : string;
@@ -527,6 +559,43 @@ begin
527559
p_out => pmu_to_x
528560
);
529561

562+
-- Timebase just increments at the system clock frequency.
563+
-- Ideally it would (appear to) run at 512MHz like IBM POWER systems,
564+
-- but Linux seems to cope OK with it being 100MHz or whatever.
565+
tbase: process(clk)
566+
begin
567+
if rising_edge(clk) then
568+
if tb_ctrl.reset = '1' then
569+
timebase <= (others => '0');
570+
tb_carry <= '0';
571+
else
572+
timebase <= tb_next;
573+
tb_carry <= and(tb_next(31 downto 0));
574+
end if;
575+
end if;
576+
end process;
577+
578+
tbase_comb: process(all)
579+
variable thi, tlo : std_ulogic_vector(31 downto 0);
580+
variable carry : std_ulogic;
581+
begin
582+
tlo := timebase(31 downto 0);
583+
thi := timebase(63 downto 32);
584+
carry := '0';
585+
if stage2_stall = '0' and ex1.se.write_tbl = '1' then
586+
tlo := ex1.e.write_data(31 downto 0);
587+
elsif tb_ctrl.freeze = '0' then
588+
tlo := std_ulogic_vector(unsigned(tlo) + 1);
589+
carry := tb_carry;
590+
end if;
591+
if stage2_stall = '0' and ex1.se.write_tbu = '1' then
592+
thi := ex1.e.write_data(31 downto 0);
593+
else
594+
thi := std_ulogic_vector(unsigned(thi) + carry);
595+
end if;
596+
tb_next <= thi & tlo;
597+
end process;
598+
530599
dbg_ctrl_out <= ctrl;
531600
log_rd_addr <= ex2.log_addr_spr;
532601

@@ -1306,7 +1375,7 @@ begin
13061375
when OP_DARN =>
13071376
when OP_MFMSR =>
13081377
when OP_MFSPR =>
1309-
if e_in.spr_is_ram = '1' then
1378+
if e_in.spr_is_ram = '1' or e_in.spr_select.noop = '1' then
13101379
if e_in.valid = '1' and not is_X(e_in.insn) then
13111380
report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
13121381
"=" & to_hstring(alu_result);
@@ -1398,6 +1467,10 @@ begin
13981467
v.se.write_dscr := '1';
13991468
when SPRSEL_CIABR =>
14001469
v.se.write_ciabr := '1';
1470+
when SPRSEL_TB =>
1471+
v.se.write_tbl := '1';
1472+
when SPRSEL_TBU =>
1473+
v.se.write_tbu := '1';
14011474
when others =>
14021475
end case;
14031476
end if;
@@ -1600,6 +1673,7 @@ begin
16001673
variable go : std_ulogic;
16011674
variable bypass_valid : std_ulogic;
16021675
variable is_scv : std_ulogic;
1676+
variable dex : aspect_bits_t;
16031677
begin
16041678
v := ex1;
16051679
if busy_out = '0' then
@@ -1735,6 +1809,13 @@ begin
17351809
bperm_start <= go and actions.start_bperm;
17361810
pmu_trace <= go and actions.do_trace;
17371811

1812+
-- evaluate DEXCR/HDEXCR bits that apply at present
1813+
if ex1.msr(MSR_PR) = '0' then
1814+
dex := ctrl.hdexcr_hyp;
1815+
else
1816+
dex := ctrl.dexcr_pro or ctrl.hdexcr_enf;
1817+
end if;
1818+
17381819
if not HAS_FPU and ex1.div_in_progress = '1' then
17391820
v.div_in_progress := not divider_to_x.valid;
17401821
v.busy := not divider_to_x.valid;
@@ -1850,6 +1931,11 @@ begin
18501931
lv.second := e_in.second;
18511932
lv.e2stall := fp_in.f2stall;
18521933
lv.hashkey := ramspr_odd;
1934+
if e_in.insn(7) = '0' then
1935+
lv.hash_enable := dex(DEXCR_PHIE);
1936+
else
1937+
lv.hash_enable := dex(DEXCR_NPHIE);
1938+
end if;
18531939

18541940
-- Outputs to FPU
18551941
fv.op := e_in.insn_type;
@@ -1897,6 +1983,7 @@ begin
18971983
39x"0" & ctrl.dscr when SPRSEL_DSCR,
18981984
56x"0" & std_ulogic_vector(to_unsigned(CPU_INDEX, 8)) when SPRSEL_PIR,
18991985
ctrl.ciabr when SPRSEL_CIABR,
1986+
assemble_dexcr(ctrl, ex1.insn) when SPRSEL_DEXCR,
19001987
assemble_xer(ex1.e.xerc, ctrl.xer_low) when others;
19011988

19021989
stage2_stall <= l_in.l2stall or fp_in.f2stall;

include/microwatt_soc.h

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@
6767
#define SYS_REG_GIT_IS_DIRTY (1ull << 63)
6868
#define SYS_REG_CPU_CTRL 0x58
6969
#define SYS_REG_CPU_CTRL_ENABLE 0xff
70+
#define SYS_REG_TB_CTRL 0x60
71+
#define SYS_REG_TB_CTRL_FREEZE 0x01
72+
#define SYS_REG_TB_CTRL_RD_PROTECT 0x02
7073

7174
/*
7275
* Register definitions for the potato UART

0 commit comments

Comments
 (0)