Skip to content

Commit 9dff8ec

Browse files
authored
Merge pull request #4 from ErickOF/feature-filter_module
Adding filter module and testbench using PV model
2 parents cd37879 + 544a6d5 commit 9dff8ec

File tree

9 files changed

+327
-1
lines changed

9 files changed

+327
-1
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,7 @@ pyrightconfig.json
223223
tools/datagen/src/imgs/*_grayscale_image*
224224
tools/datagen/src/imgs/*_noisy_image*
225225
tools/datagen/src/imgs/*_sobel_*
226+
227+
# Ignore VCD files
228+
*.vcd
229+
test

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "stb"]
2+
path = stb
3+
url = https://github.com/nothings/stb

modules/filter/Makefile

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Adding stb lib for image handling
2+
INCDIR_STB=lib/stb
3+
INCLUDES_STB := $(wildcard $(INCDIR_STB)/*.h)
4+
5+
# Include common Makefile
6+
include ../Makefile
7+
8+
# Include stb lib for compilation
9+
INCLUDES += INCLUDES_STB
10+
11+
# Defining preprocessor directive for debug
12+
ifdef IPS_DEBUG_EN
13+
CFLAGS += -DIPS_DEBUG_EN
14+
LFLAGS += -DIPS_DEBUG_EN
15+
endif # IPS_DEBUG_EN
16+
17+
# Defining preprocessor directive for dumping enable
18+
ifdef IPS_DUMP_EN
19+
CFLAGS += -DIPS_DUMP_EN
20+
LFLAGS += -DIPS_DUMP_EN
21+
endif # IPS_DUMP_EN
22+
23+
# Defining preprocessor directive for test mode one window random
24+
ifdef TEST_MODE_ONE_WINDOW_RANDOM
25+
CFLAGS += -DTEST_MODE_ONE_WINDOW -DTEST_MODE_ONE_WINDOW_RANDOM
26+
LFLAGS += -DTEST_MODE_ONE_WINDOW -DTEST_MODE_ONE_WINDOW_RANDOM
27+
endif # TEST_MODE_ONE_WINDOW_RANDOM
28+
29+
# Defining preprocessor directive for test mode one wildcard normal
30+
ifdef TEST_MODE_ONE_WINDOW_NORMAL
31+
CFLAGS += -DTEST_MODE_ONE_WINDOW -DTEST_MODE_ONE_WINDOW_NORMAL
32+
LFLAGS += -DTEST_MODE_ONE_WINDOW -DTEST_MODE_ONE_WINDOW_NORMAL
33+
endif # TEST_MODE_ONE_WINDOW_NORMAL
34+
35+
36+
# Run the compiled file
37+
run:
38+
@./test
39+
40+
# Show waveform
41+
waveform:
42+
@gtkwave ips_filter.vcd

modules/filter/README.md

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,63 @@
11
# **Filter Module**
22

3-
Add compilation instructions
3+
## **Filter Algorithm: Mean Filter**
4+
The mean filter algorithm replaces each pixel value with the average of all
5+
pixel values in an N by N window (N = 3, 5, 7, etc), where the pixel to
6+
replace is the centering pixel. Assuming that the centering pixel is in (0, 0)
7+
position:
8+
9+
$
10+
img(row, col) = \sum_{i = -N/2}^{N/2} {\sum_{j = -N/2}^{-N/2} {img(row + i, col + j)}}
11+
$
12+
13+
Also, it can computed using a convolution like:
14+
15+
$
16+
img(row, col) = \begin{bmatrix}
17+
\frac{1}{N^{2}} & \dots & \frac{1}{N^{2}} \\
18+
\vdots & \ddots & \vdots \\
19+
\frac{1}{N^{2}} & \dots & \frac{1}{N^{2}}
20+
\end{bmatrix}
21+
\ast
22+
\begin{bmatrix}
23+
img(row - N/2, col - N/2) & \dots & img(row + N/2, col + N/2) \\
24+
\vdots & \ddots & \vdots \\
25+
img(row + N/2, col - N/2) & \dots & img(row + N/2, col + N/2)
26+
\end{bmatrix}
27+
$
28+
29+
30+
## **Usage**
31+
32+
A Makefile is used to compile the testbench and filter module. There are some
33+
Makefile targets to compile the different modules and tests. By default, the
34+
PV model is compiled. The available test options are:
35+
36+
* `TEST_MODE_ONE_WINDOW_NORMAL`: Runs only one window with fixed values.
37+
* `TEST_MODE_ONE_WINDOW_RANDOM`: Runs only one window with random values.
38+
39+
Some additional options can used to debug and dump the waveform:
40+
41+
* `IPS_DEBUG_EN`: Prints the kernel, each window value, and the result.
42+
* `IPS_DUMP_EN`: Creates a VCD file with each value of the window and kernel,
43+
and the result.
44+
45+
### **Compilation**
46+
Runs the `make` command with the corresponding switches to compile.
47+
48+
For instance, to run only one window in debug mode and dump the signals:
49+
50+
```shell
51+
make TEST_MODE_ONE_WINDOW_RANDOM=1 IPS_DUMP_EN=1 IPS_DEBUG_EN=1
52+
```
53+
54+
### **Run**
55+
56+
```shell
57+
make run
58+
```
59+
60+
### **Open Waveform**
61+
```shell
62+
make waveform
63+
```

modules/filter/include/ips_filter_at_model.hpp

Whitespace-only changes.

modules/filter/include/ips_filter_lt_model.hpp

Whitespace-only changes.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#ifndef IPS_FILTER_FILTER_HPP
2+
#define IPS_FILTER_FILTER_HPP
3+
#ifdef IPS_DEBUG_EN
4+
#include <iostream>
5+
#endif // IPS_DEBUG_ENi
6+
#ifdef IPS_DUMP_EN
7+
#include <sstream>
8+
#endif // IPS_DUMP_EN
9+
#include <systemc.h>
10+
#include <vector>
11+
12+
13+
template <typename IN = sc_uint<8>, typename OUT = sc_uint<8>, uint8_t N = 3>
14+
SC_MODULE(Filter)
15+
{
16+
//-----------------------------Local Variables-----------------------------
17+
#ifdef IPS_DUMP_EN
18+
sc_trace_file* wf;
19+
#endif // IPS_DUMP_EN
20+
OUT* kernel;
21+
22+
/**
23+
* @brief Default constructor for Filter
24+
*/
25+
SC_CTOR(Filter);
26+
//template <typename IN, typename OUT, uint8_t N>
27+
#ifdef IPS_DUMP_EN
28+
Filter(sc_core::sc_module_name name, sc_core::sc_trace_file* wf)
29+
: sc_core::sc_module(name), wf(wf)
30+
#else
31+
Filter(sc_core::sc_module_name name) : sc_core::sc_module(name)
32+
#endif // IPS_DUMP_EN
33+
{
34+
SC_METHOD(init_kernel);
35+
}
36+
37+
//---------------------------------Methods---------------------------------
38+
void filter(IN* img_window, OUT& result);
39+
void init_kernel();
40+
};
41+
42+
template <typename IN, typename OUT, uint8_t N>
43+
void Filter<IN, OUT, N>::filter(IN* img_window, OUT& result)
44+
{
45+
size_t i;
46+
size_t j;
47+
48+
result = (OUT) 0;
49+
50+
for (i = 0; i < N; ++i)
51+
for (j = 0; j < N; ++j)
52+
result += this->kernel[i * N + j] * ((OUT) img_window[i * N + j]);
53+
}
54+
55+
template <typename IN, typename OUT, uint8_t N>
56+
void Filter<IN, OUT, N>::init_kernel()
57+
{
58+
// Init a kernel of N x N with default value of 1 / (N * N)
59+
this->kernel = new OUT[N * N];
60+
std::fill_n(this->kernel, N * N, ((OUT) 1) / ((OUT) N * N));
61+
#ifdef IPS_DEBUG_EN
62+
SC_REPORT_INFO(this->name(), "init_kernel result");
63+
size_t i, j;
64+
65+
for (i = 0; i < N; ++i)
66+
{
67+
for (j = 0; j < N; ++j)
68+
{
69+
std::cout << "[" << this->kernel[i * N + j] << "]";
70+
71+
#ifdef IPS_DUMP_EN
72+
std::ostringstream var_name;
73+
var_name << "kernel_" << i << "_" << j;
74+
sc_trace(this->wf, this->kernel[i * N + j], var_name.str());
75+
#endif // IPS_DUMP_EN
76+
}
77+
78+
std::cout << std::endl;
79+
}
80+
#endif // IPS_DEBUG_EN
81+
}
82+
#endif // IPS_FILTER_FILTER_HPP

modules/filter/src/tb_filter.cpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#ifdef TEST_MODE_ONE_WINDOW_RANDOM
2+
#include <cstdlib>
3+
#endif // TEST_MODE_ONE_WINDOW_RANDOM
4+
#ifdef IPS_DUMP_EN
5+
#include <sstream>
6+
#endif // IPS_DUMP_EN
7+
#include <systemc.h>
8+
9+
#define IPS_FILTER_PV_EN
10+
11+
#define IPS_FILTER_KERNEL_SIZE 3
12+
#define IPS_IN_TYPE_TB float
13+
#define IPS_OUT_TYPE_TB float
14+
15+
#ifdef IPS_FILTER_AT_EN
16+
#include "ips_filter_at_model.hpp"
17+
#elif defined(IPS_FILTER_LT_EN)
18+
#include "ips_filter_lt_model.hpp"
19+
#elif defined(IPS_FILTER_PV_EN)
20+
#include "ips_filter_pv_model.hpp"
21+
#else
22+
#error "No IPS_FILTER macro is defined. Please define one of IPS_FILTER_AT_EN, IPS_FILTER_LT_EN, or IPS_FILTER_PV_EN."
23+
#endif // IPS_FILTER_XX_EN
24+
25+
26+
#ifdef TEST_MODE_ONE_WINDOW
27+
#ifdef IPS_DUMP_EN
28+
void run_one_window(sc_trace_file* wf)
29+
#else
30+
void run_one_window()
31+
#endif // IPS_DUMP_EN
32+
{
33+
#ifdef IPS_DEBUG_EN
34+
#ifdef TEST_MODE_ONE_WINDOW_RANDOM
35+
SC_REPORT_INFO("TEST_MODE_ONE_WINDOW_NORMAL", "Running test");
36+
#elif defined(TEST_MODE_ONE_WINDOW_NORMAL)
37+
SC_REPORT_INFO("TEST_MODE_ONE_WINDOW_NORMAL", "Running test");
38+
#else
39+
SC_REPORT_INFO("TEST_MODE_ONE_WINDOW_DEFAULT", "Running test");
40+
#endif // TEST_MODE_ONE_WINDOW_RANDOM
41+
SC_REPORT_INFO("Initialize window", "Window value");
42+
#endif
43+
44+
// Variables
45+
IPS_IN_TYPE_TB *img_window;
46+
IPS_OUT_TYPE_TB result;
47+
48+
// Initialize image window
49+
img_window = new IPS_IN_TYPE_TB[IPS_FILTER_KERNEL_SIZE * IPS_FILTER_KERNEL_SIZE];
50+
51+
for (size_t i = 0; i < IPS_FILTER_KERNEL_SIZE; ++i)
52+
{
53+
for (size_t j = 0; j < IPS_FILTER_KERNEL_SIZE; ++j)
54+
{
55+
IPS_IN_TYPE_TB value;
56+
57+
#ifdef TEST_MODE_ONE_WINDOW_RANDOM
58+
value = (IPS_IN_TYPE_TB) (rand() % 256);
59+
#elif defined(TEST_MODE_ONE_WINDOW_NORMAL)
60+
value = (IPS_IN_TYPE_TB) (i * IPS_FILTER_KERNEL_SIZE + j);
61+
#else
62+
value = (IPS_IN_TYPE_TB) i;
63+
#endif // TEST_MODE_ONE_WINDOW
64+
65+
img_window[i * IPS_FILTER_KERNEL_SIZE + j] = value;
66+
67+
#ifdef IPS_DUMP_EN
68+
std::ostringstream var_name;
69+
var_name << "img_window_" << i << "_" << j;
70+
sc_trace(wf, img_window[i * IPS_FILTER_KERNEL_SIZE + j], var_name.str());
71+
#endif // IPS_DUMP_EN
72+
#ifdef IPS_DEBUG_EN
73+
std::cout << "[" << img_window[i * IPS_FILTER_KERNEL_SIZE + j] << "]";
74+
#endif // IPS_DUMP_EN
75+
}
76+
77+
#ifdef IPS_DEBUG_EN
78+
std::cout << std::endl;
79+
#endif // IPS_DEBUG_EN
80+
}
81+
82+
// Instantiate filter module and do the connection
83+
#ifdef IPS_DUMP_EN
84+
Filter<IPS_IN_TYPE_TB, IPS_OUT_TYPE_TB, IPS_FILTER_KERNEL_SIZE> filter("filter", wf);
85+
#else
86+
Filter<IPS_IN_TYPE_TB, IPS_OUT_TYPE_TB, IPS_FILTER_KERNEL_SIZE> filter("filter");
87+
#endif // IPS_DEBUG_EN
88+
89+
sc_start();
90+
91+
#ifdef IPS_DEBUG_EN
92+
std::cout << "Test starting" << std::endl;
93+
std::cout << "@" << sc_time_stamp() << std::endl;
94+
#endif // IPS_DEBUG_EN
95+
96+
// Apply convolution
97+
filter.filter(img_window, result);
98+
#ifdef IPS_DEBUG_EN
99+
SC_REPORT_INFO("TEST_MODE_ONE_WINDOW", "filtering");
100+
std::cout << "Result = " << result << std::endl;
101+
#endif // IPS_DEBUG_EN
102+
103+
#ifdef IPS_DUMP_EN
104+
sc_trace(wf, result, "result");
105+
sc_start(1, SC_NS);
106+
#endif // IPS_DUMP_EN
107+
108+
delete [] img_window;
109+
}
110+
#endif // TEST_MODE_ONE_WINDOW
111+
112+
113+
int sc_main(int, char*[])
114+
{
115+
// Pass command linke arguments
116+
sc_argc();
117+
sc_argv();
118+
119+
#ifdef IPS_DUMP_EN
120+
// Open VCD file
121+
sc_trace_file* wf = sc_create_vcd_trace_file("ips_filter");
122+
wf->set_time_unit(1, SC_NS);
123+
#endif // IPS_DUMP_EN
124+
125+
#ifdef TEST_MODE_ONE_WINDOW
126+
run_one_window(wf);
127+
#endif // TEST_MODE_ONE_WINDOW
128+
129+
#ifdef IPS_DUMP_EN
130+
std::cout << "@" << sc_time_stamp() << " Terminating simulation" << std::endl;
131+
sc_close_vcd_trace_file(wf);
132+
#endif // IPS_DUMP_EN
133+
return 0;
134+
}

stb

Submodule stb added at 013ac3b

0 commit comments

Comments
 (0)