Skip to content

Commit aa7c069

Browse files
committed
Merge branch 'xnevrk03_data_logger_stats' into 'devel'
Upgrade statistics processing for data_logger, refactor histogramer, add memory comp wraps See merge request ndk/ndk-fpga!90
2 parents bf3c431 + 38ae0b4 commit aa7c069

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3684
-776
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99
- Improve documentation
1010
- Improve documentation looks
11+
- Data_logger: Added packages for statistics processing
12+
- Histogramer: Fixed histogram box update
1113

1214
## [0.7.2] - 2024-10-17
1315

comp/base/mem/mem_clear/Modules.tcl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Modules.tcl: Components include script
2+
# Copyright (C) 2024 CESNET
3+
# Author(s): Lukas Nevrkla <[email protected]>
4+
#
5+
# SPDX-License-Identifier: BSD-3-Clause
6+
7+
# Packages
8+
lappend PACKAGES "$OFM_PATH/comp/base/pkg/math_pack.vhd"
9+
lappend PACKAGES "$OFM_PATH/comp/base/pkg/type_pack.vhd"
10+
11+
lappend MOD "$ENTITY_BASE/mem_clear.vhd"

comp/base/mem/mem_clear/mem_clear.vhd

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
-- mem_clear.vhd: Unit for clearing BRAM memories
2+
-- Copyright (C) 2024 CESNET z. s. p. o.
3+
-- Author(s): Lukas Nevrkla <[email protected]>
4+
--
5+
-- SPDX-License-Identifier: BSD-3-Clause
6+
7+
library ieee;
8+
use ieee.std_logic_1164.all;
9+
use ieee.numeric_std.all;
10+
11+
use work.math_pack.all;
12+
use work.type_pack.all;
13+
14+
entity MEM_CLEAR is
15+
generic (
16+
DATA_WIDTH : integer := 32;
17+
ITEMS : integer := 512;
18+
-- Will disable memory clearing during RST
19+
CLEAR_EN : boolean := true
20+
);
21+
port (
22+
CLK : in std_logic;
23+
RST : in std_logic;
24+
25+
-- All addresses were generated
26+
CLEAR_DONE : out std_logic;
27+
-- Clear address given by CLEAR_ADDR
28+
CLEAR_WR : out std_logic;
29+
CLEAR_ADDR : out std_logic_vector(log2(ITEMS) - 1 downto 0)
30+
);
31+
end entity;
32+
33+
architecture FULL of MEM_CLEAR is
34+
35+
type FSM_STATES_T is (
36+
CLEAR,
37+
RUNNING
38+
);
39+
40+
-- State machine --
41+
42+
signal curr_state : FSM_STATES_T;
43+
signal next_state : FSM_STATES_T;
44+
45+
signal addr_i : std_logic_vector(log2(ITEMS)-1 downto 0);
46+
signal addr_r : std_logic_vector(log2(ITEMS)-1 downto 0);
47+
signal rst_r : std_logic;
48+
49+
begin
50+
51+
CLEAR_ADDR <= addr_i;
52+
53+
reg_p : process (CLK)
54+
begin
55+
if (rising_edge(CLK)) then
56+
addr_r <= addr_i;
57+
rst_r <= RST;
58+
end if;
59+
end process;
60+
61+
-------------------
62+
-- STATE MACHINE --
63+
-------------------
64+
65+
state_reg_p : process (CLK)
66+
begin
67+
if (rising_edge(CLK)) then
68+
if (RST = '1') then
69+
if (CLEAR_EN = true) then
70+
curr_state <= CLEAR;
71+
else
72+
curr_state <= RUNNING;
73+
end if;
74+
else
75+
curr_state <= next_state;
76+
end if;
77+
end if;
78+
end process;
79+
80+
-- Output logic
81+
process (all)
82+
begin
83+
CLEAR_DONE <= '0';
84+
CLEAR_WR <= '0';
85+
next_state <= curr_state;
86+
87+
case curr_state is
88+
when CLEAR =>
89+
if (RST = '0') then
90+
CLEAR_wR <= '1';
91+
92+
if (rst_r = '1') then
93+
addr_i <= (others => '0');
94+
else
95+
addr_i <= std_logic_vector(unsigned(addr_r) + 1);
96+
end if;
97+
98+
if (unsigned(addr_i) = (ITEMS - 1)) then
99+
next_state <= RUNNING;
100+
end if;
101+
end if;
102+
103+
when RUNNING =>
104+
CLEAR_DONE <= '1';
105+
end case;
106+
end process;
107+
108+
end architecture;

comp/base/mem/mem_clear/readme.rst

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
.. _mem_clear:
2+
3+
Memory clear
4+
------------
5+
6+
Simple component that will generate addresses for memory clearing when RST is asserted.
7+
8+
Component port and generics description
9+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10+
11+
.. vhdl:autoentity:: MEM_CLEAR
12+
:noautogenerics:
13+
14+
15+
Instance template
16+
^^^^^^^^^^^^^^^^^
17+
18+
.. code-block::
19+
20+
data_clear_i : entity work.MEM_CLEAR
21+
generic map (
22+
DATA_WIDTH => BOX_WIDTH,
23+
ITEMS => BOX_CNT,
24+
CLEAR_EN => CLEAR_BY_RST
25+
)
26+
port map (
27+
CLK => CLK,
28+
RST => RST,
29+
30+
CLEAR_DONE => RST_DONE,
31+
CLEAR_WR => wr_clear,
32+
CLEAR_ADDR => wr_addr_clear
33+
);

comp/debug/data_logger/data_logger.vhd

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,9 @@ begin
350350
generic map(
351351
INPUT_WIDTH => VALUE_WIDTH(i),
352352
BOX_WIDTH => HIST_BOX_WIDTH(i),
353-
BOX_CNT => HIST_BOX_CNT(i)
354-
--READ_PRIOR => READ_PRIOR
353+
BOX_CNT => HIST_BOX_CNT(i),
354+
-- TODO: new value can be lost when read occurs!
355+
READ_PRIOR => true
355356
)
356357
port map(
357358
CLK => CLK,
@@ -380,8 +381,13 @@ begin
380381
-- RST management --
381382
--------------------
382383

383-
rst_intern <= RST or mi_ctrl_reg(CTRL_RST_BIT);
384-
SW_RST <= mi_ctrl_reg(CTRL_RST_BIT);
384+
rst_p : process(CLK)
385+
begin
386+
if (rising_edge(CLK)) then
387+
rst_intern <= RST or mi_ctrl_reg(CTRL_RST_BIT);
388+
SW_RST <= mi_ctrl_reg(CTRL_RST_BIT);
389+
end if;
390+
end process;
385391

386392
rst_done_g : if (VALUE_CNT > 0) generate
387393
rst_done_intern <= and rst_done_vec;

comp/debug/data_logger/mem_logger/mem_logger.vhd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ generic (
5454
MI_ADDR_WIDTH : integer := 32;
5555

5656
-- Specify read latency histogram precision
57-
HISTOGRAM_BOXES : integer := 255;
57+
HISTOGRAM_BOXES : integer := 256;
5858
-- Specify maximum paraller read requests
5959
MAX_PARALEL_READS : integer := 128;
6060
-- Specify read latency ticks count width

comp/debug/data_logger/readme.rst

Lines changed: 109 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,22 +171,124 @@ Instance template (full usage)
171171
Control SW
172172
^^^^^^^^^^
173173

174-
Folder ``data_logger/sw/`` contains ``Python3`` package that provides:
174+
Folder ``data_logger/sw/`` contains following ``Python3`` packages:
175175

176-
* Module for basic interaction with ``DATA_LOGGER``
177-
* Modules for ``DATA_LOGGER`` wraps like ``MEM_LOGGER``
178-
* Simple graph generator based on `matplotlib` library
179-
* Simple PDF / Markdown report generator
180-
* Common tools
176+
* ``data_logger`` ... basic interaction with ``DATA_LOGGER``
177+
* ``mem_logger`` ... basic interaction with ``MEM_LOGGER``
178+
* ``logger_stats`` ... loading firmware statistics (multiple ``DATA_LOGGERS`` can be organized in tree hierarchy)
179+
* ``graph_tools`` ... simple plot functions for statistics from ``logger_stats``
181180

182181
Package can be installed using this command:
183182

184183
* You also need to install ``python nfb`` package
185184

186185
.. code-block::
186+
python3 -m pip install --upgrade pip
187187
188+
# Install nfb:
189+
cd swbase/pynfb
190+
python3 -m pip install Cython
191+
python3 -m pip install .
192+
cd -
193+
194+
# Install this package:
188195
cd data_logger/sw
189-
python3 setup.py install --user
196+
python3 -m pip install .
197+
198+
Example usage of ``logger_stats`` (for more usage see `mem_logger/mem_logger.py`):
199+
200+
.. code-block::
201+
202+
203+
import logger_stats as Stats
204+
from data_logger.data_logger import DataLogger
205+
206+
def create_stats():
207+
# Create DataLoggers
208+
logger_0 = DataLogger(index=0, dev='/dev/nfb0')
209+
logger_1 = DataLogger(index=1, dev='/dev/nfb0')
210+
211+
# Create Stats hierarchy
212+
stats = Stats.LoggerStats('Example stats')
213+
stats_0 = Stats.LoggerStats('Logger 0 stats', logger=logger_0)
214+
stats_1 = Stats.LoggerStats('Logger 1 stats', logger=logger_1)
215+
stats.add_stat(stats_0)
216+
stats.add_stat(stats_1)
217+
218+
# Add basic statistics
219+
stats_0.add_stat(Stats.Constant(index=7, name='X'))
220+
stats_0.add_stat(Stats.Counter(index=7, name='Y'))
221+
stats_0.add_stat(Stats.Value(index=7, name='Z'))
222+
223+
# FSM state statistic
224+
def fms_convert(v):
225+
states = [
226+
'IDLE',
227+
...
228+
]
229+
if v >= len(states):
230+
return "???"
231+
else:
232+
return states[int(v)]
233+
234+
fsm_format = Stats.FormatDefaultValue(format=Stats.FormatNone)
235+
stats_1.add_stat(Stats.Value(2, 'FSM states', convert=fms_convert, format=fsm_format))
236+
237+
# Latency statistic
238+
FREQ = 200 * 10**6
239+
time_conv = Stats.ConvertTime(FREQ)
240+
time_form = Stats.FormatDefaultValue(units='ns')
241+
stats_1.add_stat(Stats.Value(9, 'Latency', convert=time_conv, format=time_form))
242+
243+
# Add value statistic which includes multiple commands
244+
CMDS = [
245+
'CMD_A',
246+
...
247+
]
248+
stats_1.add_stat(Stats.ValueCMD(7, 'Latency of CMDs', cmd_width=2, cmds=CMDS, convert=time_conv, format=time_form))
249+
250+
# Add multiple counters
251+
counters = [
252+
'Counter A',
253+
...
254+
]
255+
stats_1.add_stats(
256+
name='Counters',
257+
names=counters,
258+
indexes=list(range(len(counters))),
259+
constructor=lambda i, n: Stats.Counter(i, n)
260+
)
261+
262+
return stats
263+
264+
265+
stats = create_stats()
266+
stats.load()
267+
print(stats.to_str())
268+
stats.save('stats.npz')
269+
270+
271+
Example usage of ``graph_tools``:
272+
273+
from graph_tools.graph_tools import load_data, plot_counter, plot_value, plot_value_2d
274+
275+
stats = load_data('stats.npz')
276+
277+
node = pd.DataFrame.from_dict(stats['Stats A']['Counters'])
278+
selected = ['Counter A', 'Counter B']
279+
280+
# Plot single counter
281+
plot_counter(node['Counter X'], 'Time', 'Requests', 'Plot title')
282+
283+
# Plot multiple counters
284+
plot_counter(node[selected], 'Time', 'Requests', 'Plot title')
285+
286+
# Plot histogram of the value interface
287+
plot_value(node['Value A'], 'Time', 'Blocks', 'Title' log=True)
288+
289+
# Plot 2D histogram of the value interface history
290+
plot_value_2d(node['Value A'], 'Time', 'Blocks', 'Title' log=True)
291+
190292

191293

192294
MI address space
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +0,0 @@
1-
from data_logger import data_logger
2-
3-
__all__ = ["data_logger"]

0 commit comments

Comments
 (0)