Skip to content

Commit 2491aa7

Browse files
paulusmackantonblanchard
authored andcommitted
core: Make popcnt* take two cycles
This moves the calculation of the result for popcnt* into the countbits unit, renamed from countzero, so that we can take two cycles to get the result. The motivation for this is that the popcnt* calculation was showing up as a critical path. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
1 parent 6ff3b24 commit 2491aa7

8 files changed

Lines changed: 153 additions & 120 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ core_files = decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \
6060
decode1.vhdl helpers.vhdl insn_helpers.vhdl \
6161
control.vhdl decode2.vhdl register_file.vhdl \
6262
cr_file.vhdl crhelpers.vhdl ppc_fx_insns.vhdl rotator.vhdl \
63-
logical.vhdl countzero.vhdl multiply.vhdl divider.vhdl execute1.vhdl \
63+
logical.vhdl countbits.vhdl multiply.vhdl divider.vhdl execute1.vhdl \
6464
loadstore1.vhdl mmu.vhdl dcache.vhdl writeback.vhdl core_debug.vhdl \
6565
core.vhdl fpu.vhdl pmu.vhdl
6666

countbits.vhdl

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
library ieee;
2+
use ieee.std_logic_1164.all;
3+
use ieee.numeric_std.all;
4+
5+
library work;
6+
use work.helpers.all;
7+
8+
entity bit_counter is
9+
port (
10+
clk : in std_logic;
11+
rs : in std_ulogic_vector(63 downto 0);
12+
count_right : in std_ulogic;
13+
do_popcnt : in std_ulogic;
14+
is_32bit : in std_ulogic;
15+
datalen : in std_ulogic_vector(3 downto 0);
16+
result : out std_ulogic_vector(63 downto 0)
17+
);
18+
end entity bit_counter;
19+
20+
architecture behaviour of bit_counter is
21+
-- signals for count-leading/trailing-zeroes
22+
signal inp : std_ulogic_vector(63 downto 0);
23+
signal sum : std_ulogic_vector(64 downto 0);
24+
signal msb_r : std_ulogic;
25+
signal onehot : std_ulogic_vector(63 downto 0);
26+
signal onehot_r : std_ulogic_vector(63 downto 0);
27+
signal bitnum : std_ulogic_vector(5 downto 0);
28+
signal cntz : std_ulogic_vector(63 downto 0);
29+
30+
-- signals for popcnt
31+
signal dlen_r : std_ulogic_vector(3 downto 0);
32+
signal pcnt_r : std_ulogic;
33+
subtype twobit is unsigned(1 downto 0);
34+
type twobit32 is array(0 to 31) of twobit;
35+
signal pc2 : twobit32;
36+
subtype threebit is unsigned(2 downto 0);
37+
type threebit16 is array(0 to 15) of threebit;
38+
signal pc4 : threebit16;
39+
subtype fourbit is unsigned(3 downto 0);
40+
type fourbit8 is array(0 to 7) of fourbit;
41+
signal pc8 : fourbit8;
42+
signal pc8_r : fourbit8;
43+
subtype sixbit is unsigned(5 downto 0);
44+
type sixbit2 is array(0 to 1) of sixbit;
45+
signal pc32 : sixbit2;
46+
signal popcnt : std_ulogic_vector(63 downto 0);
47+
48+
begin
49+
countzero_r: process(clk)
50+
begin
51+
if rising_edge(clk) then
52+
msb_r <= sum(64);
53+
onehot_r <= onehot;
54+
end if;
55+
end process;
56+
57+
countzero: process(all)
58+
begin
59+
if is_32bit = '0' then
60+
if count_right = '0' then
61+
inp <= bit_reverse(rs);
62+
else
63+
inp <= rs;
64+
end if;
65+
else
66+
inp(63 downto 32) <= x"FFFFFFFF";
67+
if count_right = '0' then
68+
inp(31 downto 0) <= bit_reverse(rs(31 downto 0));
69+
else
70+
inp(31 downto 0) <= rs(31 downto 0);
71+
end if;
72+
end if;
73+
74+
sum <= std_ulogic_vector(unsigned('0' & not inp) + 1);
75+
onehot <= sum(63 downto 0) and inp;
76+
77+
-- The following occurs after a clock edge
78+
bitnum <= bit_number(onehot_r);
79+
80+
cntz <= 57x"0" & msb_r & bitnum;
81+
end process;
82+
83+
popcnt_r: process(clk)
84+
begin
85+
if rising_edge(clk) then
86+
for i in 0 to 7 loop
87+
pc8_r(i) <= pc8(i);
88+
end loop;
89+
dlen_r <= datalen;
90+
pcnt_r <= do_popcnt;
91+
end if;
92+
end process;
93+
94+
popcnt_a: process(all)
95+
begin
96+
for i in 0 to 31 loop
97+
pc2(i) <= unsigned("0" & rs(i * 2 downto i * 2)) + unsigned("0" & rs(i * 2 + 1 downto i * 2 + 1));
98+
end loop;
99+
for i in 0 to 15 loop
100+
pc4(i) <= ('0' & pc2(i * 2)) + ('0' & pc2(i * 2 + 1));
101+
end loop;
102+
for i in 0 to 7 loop
103+
pc8(i) <= ('0' & pc4(i * 2)) + ('0' & pc4(i * 2 + 1));
104+
end loop;
105+
106+
-- after a clock edge
107+
for i in 0 to 1 loop
108+
pc32(i) <= ("00" & pc8_r(i * 4)) + ("00" & pc8_r(i * 4 + 1)) +
109+
("00" & pc8_r(i * 4 + 2)) + ("00" & pc8_r(i * 4 + 3));
110+
end loop;
111+
112+
popcnt <= (others => '0');
113+
if dlen_r(3 downto 2) = "00" then
114+
-- popcntb
115+
for i in 0 to 7 loop
116+
popcnt(i * 8 + 3 downto i * 8) <= std_ulogic_vector(pc8_r(i));
117+
end loop;
118+
elsif dlen_r(3) = '0' then
119+
-- popcntw
120+
for i in 0 to 1 loop
121+
popcnt(i * 32 + 5 downto i * 32) <= std_ulogic_vector(pc32(i));
122+
end loop;
123+
else
124+
popcnt(6 downto 0) <= std_ulogic_vector(('0' & pc32(0)) + ('0' & pc32(1)));
125+
end if;
126+
end process;
127+
128+
result <= cntz when pcnt_r = '0' else popcnt;
129+
130+
end behaviour;
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,27 @@ use work.common.all;
1111
library osvvm;
1212
use osvvm.RandomPkg.all;
1313

14-
entity countzero_tb is
14+
entity countbits_tb is
1515
generic (runner_cfg : string := runner_cfg_default);
16-
end countzero_tb;
16+
end countbits_tb;
1717

18-
architecture behave of countzero_tb is
18+
architecture behave of countbits_tb is
1919
constant clk_period: time := 10 ns;
2020
signal rs: std_ulogic_vector(63 downto 0);
2121
signal is_32bit, count_right: std_ulogic := '0';
2222
signal res: std_ulogic_vector(63 downto 0);
2323
signal clk: std_ulogic;
2424

2525
begin
26-
zerocounter_0: entity work.zero_counter
26+
bitcounter_0: entity work.bit_counter
2727
port map (
2828
clk => clk,
2929
rs => rs,
3030
result => res,
3131
count_right => count_right,
32-
is_32bit => is_32bit
32+
is_32bit => is_32bit,
33+
do_popcnt => '0',
34+
datalen => "0000"
3335
);
3436

3537
clk_process: process

countzero.vhdl

Lines changed: 0 additions & 60 deletions
This file was deleted.

decode2.vhdl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ architecture behaviour of decode2 is
215215
OP_AND => "001", -- logical_result
216216
OP_OR => "001",
217217
OP_XOR => "001",
218-
OP_POPCNT => "001",
219218
OP_PRTY => "001",
220219
OP_CMPB => "001",
221220
OP_EXTS => "001",
@@ -234,7 +233,8 @@ architecture behaviour of decode2 is
234233
OP_DIV => "011",
235234
OP_DIVE => "011",
236235
OP_MOD => "011",
237-
OP_CNTZ => "100", -- countzero_result
236+
OP_CNTZ => "100", -- countbits_result
237+
OP_POPCNT => "100",
238238
OP_MFSPR => "101", -- spr_result
239239
OP_B => "110", -- next_nia
240240
OP_BC => "110",

execute1.vhdl

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ architecture behaviour of execute1 is
106106
signal rotator_result: std_ulogic_vector(63 downto 0);
107107
signal rotator_carry: std_ulogic;
108108
signal logical_result: std_ulogic_vector(63 downto 0);
109-
signal countzero_result: std_ulogic_vector(63 downto 0);
109+
signal do_popcnt: std_ulogic;
110+
signal countbits_result: std_ulogic_vector(63 downto 0);
110111
signal alu_result: std_ulogic_vector(63 downto 0);
111112
signal adder_result: std_ulogic_vector(63 downto 0);
112113
signal misc_result: std_ulogic_vector(63 downto 0);
@@ -284,13 +285,15 @@ begin
284285
datalen => e_in.data_len
285286
);
286287

287-
countzero_0: entity work.zero_counter
288+
countbits_0: entity work.bit_counter
288289
port map (
289290
clk => clk,
290291
rs => c_in,
291292
count_right => e_in.insn(10),
292293
is_32bit => e_in.is_32bit,
293-
result => countzero_result
294+
do_popcnt => do_popcnt,
295+
datalen => e_in.data_len,
296+
result => countbits_result
294297
);
295298

296299
multiply_0: entity work.multiply
@@ -391,7 +394,7 @@ begin
391394
logical_result when "001",
392395
rotator_result when "010",
393396
muldiv_result when "011",
394-
countzero_result when "100",
397+
countbits_result when "100",
395398
spr_result when "101",
396399
next_nia when "110",
397400
misc_result when others;
@@ -813,6 +816,8 @@ begin
813816
rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0';
814817
rot_sign_ext <= '1' when e_in.insn_type = OP_EXTSWSLI else '0';
815818

819+
do_popcnt <= '1' when e_in.insn_type = OP_POPCNT else '0';
820+
816821
illegal := '0';
817822
if r.intr_pending = '1' then
818823
v.e.srr1 := r.e.srr1;
@@ -963,7 +968,7 @@ begin
963968
when OP_ADDG6S =>
964969
when OP_CMPRB =>
965970
when OP_CMPEQB =>
966-
when OP_AND | OP_OR | OP_XOR | OP_POPCNT | OP_PRTY | OP_CMPB | OP_EXTS |
971+
when OP_AND | OP_OR | OP_XOR | OP_PRTY | OP_CMPB | OP_EXTS |
967972
OP_BPERM | OP_BCD =>
968973

969974
when OP_B =>
@@ -1025,7 +1030,7 @@ begin
10251030
end if;
10261031
do_trace := '0';
10271032

1028-
when OP_CNTZ =>
1033+
when OP_CNTZ | OP_POPCNT =>
10291034
v.e.valid := '0';
10301035
v.cntz_in_progress := '1';
10311036
v.busy := '1';
@@ -1220,7 +1225,7 @@ begin
12201225
-- valid_in = 0. Hence they don't happen in the same cycle as any of
12211226
-- the cases above which depend on valid_in = 1.
12221227
if r.cntz_in_progress = '1' then
1223-
-- cnt[lt]z always takes two cycles
1228+
-- cnt[lt]z and popcnt* always take two cycles
12241229
v.e.valid := '1';
12251230
elsif r.mul_in_progress = '1' or r.div_in_progress = '1' then
12261231
if (r.mul_in_progress = '1' and multiply_to_x.valid = '1') or

logical.vhdl

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,7 @@ end entity logical;
2020

2121
architecture behaviour of logical is
2222

23-
subtype twobit is unsigned(1 downto 0);
24-
type twobit32 is array(0 to 31) of twobit;
25-
signal pc2 : twobit32;
26-
subtype threebit is unsigned(2 downto 0);
27-
type threebit16 is array(0 to 15) of threebit;
28-
signal pc4 : threebit16;
29-
subtype fourbit is unsigned(3 downto 0);
30-
type fourbit8 is array(0 to 7) of fourbit;
31-
signal pc8 : fourbit8;
32-
subtype sixbit is unsigned(5 downto 0);
33-
type sixbit2 is array(0 to 1) of sixbit;
34-
signal pc32 : sixbit2;
3523
signal par0, par1 : std_ulogic;
36-
signal popcnt : std_ulogic_vector(63 downto 0);
3724
signal parity : std_ulogic_vector(63 downto 0);
3825
signal permute : std_ulogic_vector(7 downto 0);
3926

@@ -109,35 +96,6 @@ begin
10996
variable negative : std_ulogic;
11097
variable j : integer;
11198
begin
112-
-- population counts
113-
for i in 0 to 31 loop
114-
pc2(i) <= unsigned("0" & rs(i * 2 downto i * 2)) + unsigned("0" & rs(i * 2 + 1 downto i * 2 + 1));
115-
end loop;
116-
for i in 0 to 15 loop
117-
pc4(i) <= ('0' & pc2(i * 2)) + ('0' & pc2(i * 2 + 1));
118-
end loop;
119-
for i in 0 to 7 loop
120-
pc8(i) <= ('0' & pc4(i * 2)) + ('0' & pc4(i * 2 + 1));
121-
end loop;
122-
for i in 0 to 1 loop
123-
pc32(i) <= ("00" & pc8(i * 4)) + ("00" & pc8(i * 4 + 1)) +
124-
("00" & pc8(i * 4 + 2)) + ("00" & pc8(i * 4 + 3));
125-
end loop;
126-
popcnt <= (others => '0');
127-
if datalen(3 downto 2) = "00" then
128-
-- popcntb
129-
for i in 0 to 7 loop
130-
popcnt(i * 8 + 3 downto i * 8) <= std_ulogic_vector(pc8(i));
131-
end loop;
132-
elsif datalen(3) = '0' then
133-
-- popcntw
134-
for i in 0 to 1 loop
135-
popcnt(i * 32 + 5 downto i * 32) <= std_ulogic_vector(pc32(i));
136-
end loop;
137-
else
138-
popcnt(6 downto 0) <= std_ulogic_vector(('0' & pc32(0)) + ('0' & pc32(1)));
139-
end if;
140-
14199
-- parity calculations
142100
par0 <= rs(0) xor rs(8) xor rs(16) xor rs(24);
143101
par1 <= rs(32) xor rs(40) xor rs(48) xor rs(56);
@@ -178,8 +136,6 @@ begin
178136
tmp := not tmp;
179137
end if;
180138

181-
when OP_POPCNT =>
182-
tmp := popcnt;
183139
when OP_PRTY =>
184140
tmp := parity;
185141
when OP_CMPB =>

microwatt.core

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ filesets:
1818
- ppc_fx_insns.vhdl
1919
- sim_console.vhdl
2020
- logical.vhdl
21-
- countzero.vhdl
21+
- countbits.vhdl
2222
- control.vhdl
2323
- execute1.vhdl
2424
- fpu.vhdl

0 commit comments

Comments
 (0)