From 55291edc559a08316555d2da6b46a8b4a63c3d44 Mon Sep 17 00:00:00 2001 From: Grzegorz Daniluk <grzegorz.daniluk@cern.ch> Date: Thu, 28 Jul 2016 15:03:11 +0200 Subject: [PATCH] wrsw_nic: bw throttling, no throttling yet --- modules/wrsw_nic/Manifest.py | 1 + modules/wrsw_nic/nic_bw_throttling.vhd | 204 ++++++++++++++++++++++++ modules/wrsw_nic/nic_rx_fsm.vhd | 36 ++++- modules/wrsw_nic/nic_wbgen2_pkg.vhd | 24 +-- modules/wrsw_nic/nic_wishbone_slave.vhd | 16 +- modules/wrsw_nic/wr_nic.wb | 26 +++ modules/wrsw_nic/wrsw_nic.vhd | 7 + modules/wrsw_nic/xwrsw_nic.vhd | 8 + top/bare_top/scb_top_bare.vhd | 2 + top/bare_top/wrsw_components_pkg.vhd | 2 + top/bare_top/wrsw_top_pkg.vhd | 2 + 11 files changed, 316 insertions(+), 12 deletions(-) create mode 100644 modules/wrsw_nic/nic_bw_throttling.vhd diff --git a/modules/wrsw_nic/Manifest.py b/modules/wrsw_nic/Manifest.py index b9d124c1..6aeab1db 100644 --- a/modules/wrsw_nic/Manifest.py +++ b/modules/wrsw_nic/Manifest.py @@ -6,6 +6,7 @@ files = [ "nic_constants_pkg.vhd" , "nic_tx_fsm.vhd" , "nic_buffer.vhd" , "nic_elastic_buffer.vhd", + "nic_bw_throttling.vhd", "nic_wbgen2_pkg.vhd", "xwrsw_nic.vhd", "wrsw_nic.vhd"]; diff --git a/modules/wrsw_nic/nic_bw_throttling.vhd b/modules/wrsw_nic/nic_bw_throttling.vhd new file mode 100644 index 00000000..3ca233ee --- /dev/null +++ b/modules/wrsw_nic/nic_bw_throttling.vhd @@ -0,0 +1,204 @@ +library IEEE; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.wr_fabric_pkg.all; +--use work.gencores_pkg.all; + +entity nic_bw_throttling is + generic ( + g_true_random : boolean := false); + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + + pps_p_i : in std_logic; + pps_valid_i : in std_logic; + + snk_i : in t_wrf_sink_in; + snk_o : out t_wrf_sink_out; + src_o : out t_wrf_source_out; + src_i : in t_wrf_source_in; + + bw_o : out std_logic_vector(31 downto 0); + rnd_o : out std_logic_vector(31 downto 0)); +end nic_bw_throttling; + +architecture behav of nic_bw_throttling is + + signal bw_cnt : unsigned(31 downto 0); + signal bw_reg : unsigned(31 downto 0); + signal is_data : std_logic; + + signal drop_frame : std_logic; + type t_fwd_fsm is (WAIT_FRAME, FLUSH, PASS, DROP); + signal state_fwd : t_fwd_fsm; + signal wrf_reg : t_wrf_sink_in; + + signal ring_out : std_logic_vector(31 downto 0); + signal rnd_reg : std_logic_vector(31 downto 0); + --attribute keep : string; + --attribute keep of ring_out : signal is "true"; + --attribute keep_hierarchy : string; + --attribute keep_hierarchy of behav : architecture is "true"; + attribute S : string; + attribute S of ring_out : signal is "true"; + + constant c_LFSR_START : std_logic_vector := x"A5A5"; +begin + + ------------------------------------------------- + -- Random number generation -- + ------------------------------------------------- + GEN_RND: if g_true_random generate + -- based on Generalized Ring Oscillator + ring_out(0) <= ring_out(31) xnor ring_out(0) xnor ring_out(1); + GEN_RND: for I in 1 to 30 generate + ring_out(I) <= ring_out(I-1) xor ring_out(I) xor ring_out(I+1); + end generate; + ring_out(31) <= ring_out(30) xor ring_out(31) xor ring_out(0); + + --GEN_ANTI_META: for J in 0 to 31 generate + -- SYNC_FFS: gc_sync_ffs + -- port map ( + -- clk_i => clk_sys_i, + -- rst_n_i => rst_n_i, + -- data_i => ring_out(J), + -- synced_o => rnd_reg(J)); + --end generate; + process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + rnd_reg <= (others=>'0'); + else + rnd_reg <= ring_out; + end if; + end if; + end process; + end generate; + + GEN_PSEUDO_RND: if not g_true_random generate + -- based on LSFR x^16 + x^15 + x^13 + x^4 + 1 + process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + rnd_reg(31 downto 0) <= (others=>'0'); + rnd_reg(15 downto 0) <= c_LFSR_START; + else + rnd_reg(0) <= rnd_reg(15) xor rnd_reg(14) xor rnd_reg(12) xor rnd_reg(3); + rnd_reg(15 downto 1) <= rnd_reg(14 downto 0); + end if; + end if; + end process; + + end generate; + + rnd_o <= rnd_reg; + + ------------------------------------------------- + -- Forwarding or dropping frames -- + ------------------------------------------------- + drop_frame <= '0'; + + process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + state_fwd <= WAIT_FRAME; + wrf_reg <= c_dummy_snk_in; + + snk_o <= c_dummy_src_in; + src_o <= c_dummy_snk_in; + else + case state_fwd is + when WAIT_FRAME => + snk_o.ack <= '0'; + snk_o.err <= '0'; + snk_o.rty <= '0'; + src_o <= c_dummy_snk_in; + if (snk_i.cyc='1' and snk_i.stb='1') then + -- new frame is transmitted + snk_o.stall <= '1'; + wrf_reg <= snk_i; + + if (drop_frame = '0') then + state_fwd <= FLUSH; + elsif (drop_frame = '1') then + state_fwd <= DROP; + end if; + else + snk_o.stall <= '0'; + end if; + + when FLUSH => + -- flush wrf_reg stored on stall or in WAIT_FRAME + snk_o <= src_i; + if (src_i.stall = '0') then + src_o <= wrf_reg; + state_fwd <= PASS; + end if; + + when PASS => + snk_o <= src_i; + if (src_i.stall = '0') then + src_o <= snk_i; + else + wrf_reg <= snk_i; + state_fwd <= FLUSH; + end if; + + when DROP => + -- ack everything from SNK, pass nothing to SRC + snk_o.stall <= '0'; + snk_o.err <= '0'; + snk_o.rty <= '0'; + src_o <= c_dummy_snk_in; + if (snk_i.stb='1') then + snk_o.ack <= '1'; + else + snk_o.ack <= '0'; + end if; + + if (snk_i.cyc='0' and snk_i.stb='0') then + state_fwd <= WAIT_FRAME; + end if; + end case; + end if; + end if; + end process; + + + ------------------------------------------------- + -- Calculating bandwidth actually going to ARM -- + ------------------------------------------------- + + is_data <= '1' when (snk_i.adr=c_WRF_DATA and snk_i.cyc='1' and snk_i.stb='1') else + '0'; + + process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' or pps_valid_i = '0' then + bw_cnt <= (others=>'0'); + bw_reg <= (others=>'0'); + elsif pps_p_i = '1' then + bw_reg <= bw_cnt; + bw_cnt <= (others=>'0'); + elsif is_data = '1' then + -- we count incoming bytes here + if snk_i.sel(0) = '1' then + -- 16bits carry valid data + bw_cnt <= bw_cnt + 2; + elsif snk_i.sel(0) = '0' then + -- only 8bits carry valid data + bw_cnt <= bw_cnt + 1; + end if; + end if; + end if; + end process; + + bw_o <= std_logic_vector(bw_reg); + +end behav; diff --git a/modules/wrsw_nic/nic_rx_fsm.vhd b/modules/wrsw_nic/nic_rx_fsm.vhd index 6db617cc..a8bc4667 100644 --- a/modules/wrsw_nic/nic_rx_fsm.vhd +++ b/modules/wrsw_nic/nic_rx_fsm.vhd @@ -57,6 +57,8 @@ entity nic_rx_fsm is clk_sys_i : in std_logic; rst_n_i : in std_logic; + pps_p_i : in std_logic; + pps_valid_i : in std_logic; ------------------------------------------------------------------------------- -- WRF sink ------------------------------------------------------------------------------- @@ -121,6 +123,20 @@ architecture behavioral of NIC_RX_FSM is dreq_i : in std_logic); end component; + component nic_bw_throttling + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + pps_p_i : in std_logic; + pps_valid_i : in std_logic; + snk_i : in t_wrf_sink_in; + snk_o : out t_wrf_sink_out; + src_o : out t_wrf_source_out; + src_i : in t_wrf_source_in; + bw_o : out std_logic_vector(31 downto 0); + rnd_o : out std_logic_vector(31 downto 0)); + end component; + type t_rx_fsm_state is (RX_DISABLED, RX_WAIT_SOF, RX_REQUEST_DESCRIPTOR, RX_DATA, RX_UPDATE_DESC, RX_MEM_RESYNC, RX_MEM_FLUSH); @@ -147,17 +163,33 @@ architecture behavioral of NIC_RX_FSM is signal fab_in : t_ep_internal_fabric; signal fab_dreq : std_logic; + + signal bw_src_out : t_wrf_source_out; + signal bw_src_in : t_wrf_source_in; begin + U_Throttling: nic_bw_throttling + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + pps_p_i => pps_p_i, + pps_valid_i => pps_valid_i, + snk_i => snk_i, + snk_o => snk_o, + src_o => bw_src_out, + src_i => bw_src_in, + bw_o => regs_o.bw_i, + rnd_o => regs_o.rnd_i); + U_Buffer : nic_elastic_buffer generic map ( g_depth => 64) port map ( clk_sys_i => clk_sys_i, rst_n_i => rst_n_i, - snk_i => snk_i, - snk_o => snk_o, + snk_i => bw_src_out, --snk_i, + snk_o => bw_src_in, --snk_o, fab_o => fab_in, dreq_i => fab_dreq); diff --git a/modules/wrsw_nic/nic_wbgen2_pkg.vhd b/modules/wrsw_nic/nic_wbgen2_pkg.vhd index d0bb3b3b..f4ab2e05 100644 --- a/modules/wrsw_nic/nic_wbgen2_pkg.vhd +++ b/modules/wrsw_nic/nic_wbgen2_pkg.vhd @@ -3,7 +3,7 @@ --------------------------------------------------------------------------------------- -- File : nic_wbgen2_pkg.vhd -- Author : auto-generated by wbgen2 from wr_nic.wb --- Created : Fri Jul 3 16:18:39 2015 +-- Created : Thu Jul 28 10:18:55 2016 -- Standard : VHDL'87 --------------------------------------------------------------------------------------- -- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wr_nic.wb @@ -27,6 +27,8 @@ package nic_wbgen2_pkg is sr_tx_error_i : std_logic; sr_cur_tx_desc_i : std_logic_vector(2 downto 0); sr_cur_rx_desc_i : std_logic_vector(2 downto 0); + bw_i : std_logic_vector(31 downto 0); + rnd_i : std_logic_vector(31 downto 0); end record; constant c_nic_in_registers_init_value: t_nic_in_registers := ( @@ -35,7 +37,9 @@ package nic_wbgen2_pkg is sr_tx_done_i => '0', sr_tx_error_i => '0', sr_cur_tx_desc_i => (others => '0'), - sr_cur_rx_desc_i => (others => '0') + sr_cur_rx_desc_i => (others => '0'), + bw_i => (others => '0'), + rnd_i => (others => '0') ); -- Output registers (WB slave -> user design) @@ -71,20 +75,20 @@ end package; package body nic_wbgen2_pkg is function f_x_to_zero (x:std_logic) return std_logic is begin -if(x = 'X' or x = 'U') then -return '0'; +if x = '1' then +return '1'; else -return x; -end if; +return '0'; +end if; end function; function f_x_to_zero (x:std_logic_vector) return std_logic_vector is variable tmp: std_logic_vector(x'length-1 downto 0); begin for i in 0 to x'length-1 loop -if(x(i) = 'X' or x(i) = 'U') then -tmp(i):= '0'; +if x(i) = '1' then +tmp(i):= '1'; else -tmp(i):=x(i); +tmp(i):= '0'; end if; end loop; return tmp; @@ -98,6 +102,8 @@ tmp.sr_tx_done_i := f_x_to_zero(left.sr_tx_done_i) or f_x_to_zero(right.sr_tx_do tmp.sr_tx_error_i := f_x_to_zero(left.sr_tx_error_i) or f_x_to_zero(right.sr_tx_error_i); tmp.sr_cur_tx_desc_i := f_x_to_zero(left.sr_cur_tx_desc_i) or f_x_to_zero(right.sr_cur_tx_desc_i); tmp.sr_cur_rx_desc_i := f_x_to_zero(left.sr_cur_rx_desc_i) or f_x_to_zero(right.sr_cur_rx_desc_i); +tmp.bw_i := f_x_to_zero(left.bw_i) or f_x_to_zero(right.bw_i); +tmp.rnd_i := f_x_to_zero(left.rnd_i) or f_x_to_zero(right.rnd_i); return tmp; end function; end package body; diff --git a/modules/wrsw_nic/nic_wishbone_slave.vhd b/modules/wrsw_nic/nic_wishbone_slave.vhd index b0e64f19..1702ae62 100644 --- a/modules/wrsw_nic/nic_wishbone_slave.vhd +++ b/modules/wrsw_nic/nic_wishbone_slave.vhd @@ -3,7 +3,7 @@ --------------------------------------------------------------------------------------- -- File : nic_wishbone_slave.vhd -- Author : auto-generated by wbgen2 from wr_nic.wb --- Created : Fri Jul 3 16:18:39 2015 +-- Created : Thu Jul 28 10:18:55 2016 -- Standard : VHDL'87 --------------------------------------------------------------------------------------- -- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wr_nic.wb @@ -223,6 +223,18 @@ begin rddata_reg(31) <= 'X'; ack_sreg(0) <= '1'; ack_in_progress <= '1'; + when "0010" => + if (wb_we_i = '1') then + end if; + rddata_reg(31 downto 0) <= regs_i.bw_i; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "0011" => + if (wb_we_i = '1') then + end if; + rddata_reg(31 downto 0) <= regs_i.rnd_i; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; when "1000" => if (wb_we_i = '1') then eic_idr_write_int <= '1'; @@ -460,6 +472,8 @@ begin regs_o.sr_tx_error_o <= wrdata_reg(3); -- Current TX descriptor -- Current RX descriptor +-- Bytes-per-second +-- 32-bit random number for throttling -- extra code for reg/fifo/mem: TX descriptors mem -- RAM block instantiation for memory: TX descriptors mem nic_dtx_raminst : wbgen2_dpssram diff --git a/modules/wrsw_nic/wr_nic.wb b/modules/wrsw_nic/wr_nic.wb index 6c63d874..e50197ab 100644 --- a/modules/wrsw_nic/wr_nic.wb +++ b/modules/wrsw_nic/wr_nic.wb @@ -152,6 +152,32 @@ top = peripheral { }; }; + reg { + name = "NIC Bandwidth Register"; + prefix = "BW"; + field { + name = "Bytes-per-second"; + type = SLV; + size = 32; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + load = LOAD_EXT; + }; + }; + + reg { + name = "NIC Random Register"; + prefix = "RND"; + field { + name = "32-bit random number for throttling"; + type = SLV; + size = 32; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + load = LOAD_EXT; + }; + }; + irq { name = "Receive Complete"; prefix = "rcomp"; diff --git a/modules/wrsw_nic/wrsw_nic.vhd b/modules/wrsw_nic/wrsw_nic.vhd index b0147c03..2e933ccd 100644 --- a/modules/wrsw_nic/wrsw_nic.vhd +++ b/modules/wrsw_nic/wrsw_nic.vhd @@ -54,6 +54,9 @@ entity wrsw_nic is clk_sys_i : in std_logic; rst_n_i : in std_logic; + pps_p_i : in std_logic; + pps_valid_i : in std_logic; + ------------------------------------------------------------------------------- -- Pipelined Wishbone interface ------------------------------------------------------------------------------- @@ -120,6 +123,8 @@ architecture rtl of wrsw_nic is port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; + pps_p_i : in std_logic; + pps_valid_i : in std_logic; snk_i : in t_wrf_sink_in; snk_o : out t_wrf_sink_out; src_i : in t_wrf_source_in; @@ -154,6 +159,8 @@ begin port map ( clk_sys_i => clk_sys_i, rst_n_i => rst_n_i, + pps_p_i => pps_p_i, + pps_valid_i => pps_valid_i, snk_i => snk_in, snk_o => snk_out, src_i => src_in, diff --git a/modules/wrsw_nic/xwrsw_nic.vhd b/modules/wrsw_nic/xwrsw_nic.vhd index 3202eff9..aa186cfa 100644 --- a/modules/wrsw_nic/xwrsw_nic.vhd +++ b/modules/wrsw_nic/xwrsw_nic.vhd @@ -67,6 +67,9 @@ entity xwrsw_nic is port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; + + pps_p_i : in std_logic; + pps_valid_i : in std_logic; ------------------------------------------------------------------------------- -- WRF sink @@ -138,6 +141,8 @@ architecture rtl of xwrsw_nic is port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; + pps_p_i : in std_logic; + pps_valid_i : in std_logic; snk_i : in t_wrf_sink_in; snk_o : out t_wrf_sink_out; regs_i : in t_nic_out_registers; @@ -488,6 +493,9 @@ begin -- rtl clk_sys_i => clk_sys_i, rst_n_i => nic_reset_n, + pps_p_i => pps_p_i, + pps_valid_i => pps_valid_i, + snk_i => snk_i, snk_o => snk_o, diff --git a/top/bare_top/scb_top_bare.vhd b/top/bare_top/scb_top_bare.vhd index e76a9201..28cc247a 100644 --- a/top/bare_top/scb_top_bare.vhd +++ b/top/bare_top/scb_top_bare.vhd @@ -607,6 +607,8 @@ begin port map ( clk_sys_i => clk_sys, rst_n_i => rst_n_sys, + pps_p_i => pps_csync, + pps_valid_i => pps_valid, snk_i => endpoint_snk_in(c_NUM_PORTS), snk_o => endpoint_snk_out(c_NUM_PORTS), src_i => endpoint_src_in(c_NUM_PORTS), diff --git a/top/bare_top/wrsw_components_pkg.vhd b/top/bare_top/wrsw_components_pkg.vhd index 68c4c65d..60185f05 100644 --- a/top/bare_top/wrsw_components_pkg.vhd +++ b/top/bare_top/wrsw_components_pkg.vhd @@ -184,6 +184,8 @@ package wrsw_components_pkg is port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; + pps_p_i : in std_logic; + pps_valid_i : in std_logic; snk_i : in t_wrf_sink_in; snk_o : out t_wrf_sink_out; src_i : in t_wrf_source_in; diff --git a/top/bare_top/wrsw_top_pkg.vhd b/top/bare_top/wrsw_top_pkg.vhd index 32f0e1b2..6be38d30 100644 --- a/top/bare_top/wrsw_top_pkg.vhd +++ b/top/bare_top/wrsw_top_pkg.vhd @@ -184,6 +184,8 @@ package wrsw_top_pkg is port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; + pps_p_i : in std_logic; + pps_valid_i : in std_logic; snk_i : in t_wrf_sink_in; snk_o : out t_wrf_sink_out; src_i : in t_wrf_source_in; -- GitLab