Skip to content

Commit

Permalink
improved convolution timing
Browse files Browse the repository at this point in the history
Also removed duplicated testcase and added default generics for out-of-context
synthesis.
  • Loading branch information
marph91 committed Feb 28, 2021
1 parent 19ae8ce commit 29beea8
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 15 deletions.
1 change: 0 additions & 1 deletion sim/test_window_convolution_activation.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,6 @@ def get_threshold(self):
(3, 1, 4, 8),
(3, 1, 1, 4),
(3, 1, 3, 8),
(3, 1, 4, 8),
(3, 1, 8, 16),
(3, 2, 4, 8),
(5, 1, 4, 8),
Expand Down
63 changes: 54 additions & 9 deletions src/convolution.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

library util;
use util.math_pkg.all;
Expand All @@ -10,7 +11,7 @@ entity convolution is
generic (
-- TODO: input bitwidth, for now = 1

C_KERNEL_SIZE : integer range 1 to 7 := 2;
C_KERNEL_SIZE : integer range 1 to 7 := 3;
C_INPUT_CHANNEL : integer := 1
);
port (
Expand All @@ -26,7 +27,33 @@ end entity convolution;

architecture behavioral of convolution is

function find_best_parallelity return integer is
begin

if (C_INPUT_CHANNEL > C_KERNEL_SIZE) then
if (C_INPUT_CHANNEL mod 4 = 0) then
if (C_INPUT_CHANNEL mod 8 = 0) then
if (C_INPUT_CHANNEL mod 16 = 0) then
return 16;
end if;
return 8;
end if;
return 4;
end if;
end if;

return C_KERNEL_SIZE;
end function find_best_parallelity;

constant C_PARALLEL_POPCOUNT : integer := find_best_parallelity;
constant C_SPLIT : integer := integer(ceil(real(islv_data'length) / real(C_PARALLEL_POPCOUNT)));

type t_ones_count is array(natural range<>) of unsigned(oslv_data'range);

signal a_ones_count : t_ones_count(0 to C_SPLIT);

signal sl_add : std_logic := '0';
signal sl_popcount : std_logic := '0';
signal slv_multiplication_result : std_logic_vector(islv_data'range);

signal sl_valid_out : std_logic := '0';
Expand All @@ -36,31 +63,49 @@ begin

proc_convolution : process (isl_clk) is

variable usig_ones_count : unsigned(oslv_data'range);
variable v_usig_popcount : unsigned(oslv_data'range);
variable v_usig_popcount_total : unsigned(oslv_data'range);

begin

if (rising_edge(isl_clk)) then
sl_valid_out <= '0';
assert (C_INPUT_CHANNEL mod C_PARALLEL_POPCOUNT = 0) or
(C_KERNEL_SIZE mod C_PARALLEL_POPCOUNT = 0) severity failure;

sl_popcount <= '0';
sl_add <= '0';
sl_valid_out <= '0';

if (isl_valid = '1') then
-- or map directly to hardware (islv_weights as constant)
slv_multiplication_result <= islv_data xnor islv_weights;
a_ones_count <= (others => (others => '0'));
sl_popcount <= '1';
end if;

-- TODO: The split/adder can be improved.
if (sl_popcount = '1') then
for split in 0 to C_SPLIT - 1 loop
v_usig_popcount := (others => '0');
for i in 0 to C_PARALLEL_POPCOUNT - 1 loop
if (slv_multiplication_result(i + split * C_PARALLEL_POPCOUNT) = '1') then
v_usig_popcount := v_usig_popcount + 1;
end if;
end loop;
a_ones_count(split) <= v_usig_popcount;
end loop;

sl_add <= '1';
end if;

if (sl_add = '1') then
usig_ones_count := (others => '0');
for i in slv_multiplication_result'range loop
if (slv_multiplication_result(i) = '1') then
usig_ones_count := usig_ones_count + 1;
end if;
v_usig_popcount_total := (others => '0');
for split in 0 to C_SPLIT - 1 loop
v_usig_popcount_total := v_usig_popcount_total + a_ones_count(split);
end loop;

slv_data_out <= std_logic_vector(usig_ones_count);
sl_valid_out <= '1';
slv_data_out <= std_logic_vector(v_usig_popcount_total);
end if;
end if;

Expand Down
10 changes: 5 additions & 5 deletions src/window_convolution_activation.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ entity window_convolution_activation is
generic (
-- TODO: input bitwidth, for now = 1

C_KERNEL_SIZE : integer range 1 to 7 := 2;
C_KERNEL_SIZE : integer range 1 to 7 := 3;
C_STRIDE : integer := 1;

C_INPUT_CHANNEL : integer;
C_OUTPUT_CHANNEL : integer;
C_INPUT_CHANNEL : integer := 4;
C_OUTPUT_CHANNEL : integer := 8;

C_IMG_WIDTH : integer;
C_IMG_HEIGHT : integer
C_IMG_WIDTH : integer := 4;
C_IMG_HEIGHT : integer := 4
);
port (
isl_clk : in std_logic;
Expand Down

0 comments on commit 29beea8

Please sign in to comment.