|
| 1 | +#ifndef IPS_FILTER_AT_MODEL_HPP |
| 2 | +#define IPS_FILTER_AT_MODEL_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 | + |
| 11 | + |
| 12 | +/** |
| 13 | + * @brief Filter module. |
| 14 | + * It takes care of filtering a image/kernel using a median filter or an |
| 15 | + * equivalent convolution like: |
| 16 | + * | 1/N^2 ... 1/N^2 | | img(row - N/2, col - N/2) ... img(row + N/2, col + N/2) | |
| 17 | + * img(row, col) = | ... ... .... | * | ... ... ... | |
| 18 | + * | 1/N^2 ... 1/N^2 | | img(row + N/2, col - N/2) ... img(row + N/2, col + N/2) | |
| 19 | + * |
| 20 | + * @tparam IN - data type of the inputs |
| 21 | + * @tparam OUT - data type of the outputs |
| 22 | + * @tparam N - size of the kernel |
| 23 | + */ |
| 24 | +template <typename IN = sc_uint<8>, typename OUT = sc_uint<8>, uint8_t N = 3> |
| 25 | +SC_MODULE(Filter) |
| 26 | +{ |
| 27 | +protected: |
| 28 | + //----------------------------Internal Variables---------------------------- |
| 29 | +#ifdef IPS_DUMP_EN |
| 30 | + sc_trace_file* wf; |
| 31 | +#endif // IPS_DUMP_EN |
| 32 | + OUT* kernel; |
| 33 | + |
| 34 | + // Event to trigger the filter execution |
| 35 | + sc_event event; |
| 36 | + |
| 37 | + //-----------------------------Internal Methods----------------------------- |
| 38 | + void exec_filter(); |
| 39 | + void init(); |
| 40 | + |
| 41 | +public: |
| 42 | + sc_in<IN* > img_window; |
| 43 | + sc_out<OUT > result; |
| 44 | + /** |
| 45 | + * @brief Default constructor for Filter |
| 46 | + */ |
| 47 | + SC_HAS_PROCESS(Filter); |
| 48 | +#ifdef IPS_DUMP_EN |
| 49 | + /** |
| 50 | + * @brief Construct a new Filter object |
| 51 | + * |
| 52 | + * @param name - name of the module |
| 53 | + * @param wf - waveform file pointer |
| 54 | + */ |
| 55 | + Filter(sc_core::sc_module_name name, sc_core::sc_trace_file* wf) |
| 56 | + : sc_core::sc_module(name), wf(wf) |
| 57 | +#else |
| 58 | + /** |
| 59 | + * @brief Construct a new Filter object |
| 60 | + * |
| 61 | + * @param name - name of the module |
| 62 | + */ |
| 63 | + Filter(sc_core::sc_module_name name) : sc_core::sc_module(name) |
| 64 | +#endif // IPS_DUMP_EN |
| 65 | + { |
| 66 | + // Calling this method by default since it is no time consumer |
| 67 | + // It is assumed that this kernel is already loaded in the model |
| 68 | + // Kernel does not change after synthesis |
| 69 | + SC_METHOD(init); |
| 70 | + // Thread waiting for the request |
| 71 | + SC_THREAD(exec_filter); |
| 72 | + } |
| 73 | + |
| 74 | + //---------------------------------Methods--------------------------------- |
| 75 | + void filter(); |
| 76 | +}; |
| 77 | + |
| 78 | +/** |
| 79 | + * @brief Execute the image filtering |
| 80 | + * |
| 81 | + */ |
| 82 | +template <typename IN, typename OUT, uint8_t N> |
| 83 | +void Filter<IN, OUT, N>::exec_filter() |
| 84 | +{ |
| 85 | + size_t i; |
| 86 | + size_t j; |
| 87 | + |
| 88 | + OUT result_tmp; |
| 89 | + |
| 90 | + while (true) |
| 91 | + { |
| 92 | + // Wait to peform the convolution |
| 93 | + wait(this->event); |
| 94 | + |
| 95 | + // Default value for the result depending on the output datatype |
| 96 | + result_tmp = (OUT) 0; |
| 97 | + |
| 98 | + // Getting the image window to filter |
| 99 | + IN* img_window_tmp = this->img_window.read(); |
| 100 | + |
| 101 | +#ifdef IPS_DEBUG_EN |
| 102 | + std::cout << "Performing convolution" << std::endl; |
| 103 | +#endif // IPS_DEBUG_EN |
| 104 | + |
| 105 | + // Perform the convolution |
| 106 | + for (i = 0; i < N; ++i) |
| 107 | + for (j = 0; j < N; ++j) |
| 108 | + { |
| 109 | +#ifdef IPS_DEBUG_EN |
| 110 | + std::cout << "Starting [" << i << "][" << j << "]" << std::endl; |
| 111 | +#endif // IPS_DEBUG_EN |
| 112 | + result_tmp += this->kernel[i * N + j] * ((OUT) img_window_tmp[i * N + j]); |
| 113 | +#ifdef IPS_DEBUG_EN |
| 114 | + std::cout << "Done [" << i << "][" << j << "]" << std::endl; |
| 115 | +#endif // IPS_DEBUG_EN |
| 116 | + } |
| 117 | + |
| 118 | +#ifdef IPS_DEBUG_EN |
| 119 | + std::cout << "Convolution result is done" << std::endl; |
| 120 | +#endif // IPS_DEBUG_EN |
| 121 | + this->result.write(result_tmp); |
| 122 | + } |
| 123 | +} |
| 124 | + |
| 125 | +/** |
| 126 | + * @brief Filtering image |
| 127 | + * |
| 128 | + * @param img_window - image window to filter |
| 129 | + * @param result - resultant pixel |
| 130 | + */ |
| 131 | +template <typename IN, typename OUT, uint8_t N> |
| 132 | +void Filter<IN, OUT, N>::filter() |
| 133 | +{ |
| 134 | + this->event.notify(DELAY_TIME, SC_NS); |
| 135 | +} |
| 136 | + |
| 137 | +/** |
| 138 | + * @brief Initializes a kernel of N x N with default value of 1 / (N^2) |
| 139 | + * |
| 140 | + */ |
| 141 | +template <typename IN, typename OUT, uint8_t N> |
| 142 | +void Filter<IN, OUT, N>::init() |
| 143 | +{ |
| 144 | + // Init a kernel of N x N with default value of 1 / (N * N) |
| 145 | + this->kernel = new OUT[N * N]; |
| 146 | + std::fill_n(this->kernel, N * N, ((OUT) 1) / ((OUT) N * N)); |
| 147 | + |
| 148 | +#ifdef IPS_DEBUG_EN |
| 149 | + // Print the initialized kernel |
| 150 | + SC_REPORT_INFO(this->name(), "init result"); |
| 151 | + size_t i, j; |
| 152 | + |
| 153 | + for (i = 0; i < N; ++i) |
| 154 | + { |
| 155 | + for (j = 0; j < N; ++j) |
| 156 | + { |
| 157 | + std::cout << "[" << this->kernel[i * N + j] << "]"; |
| 158 | + |
| 159 | +#ifdef IPS_DUMP_EN |
| 160 | + // Adding the signals to the waveform |
| 161 | + std::ostringstream var_name; |
| 162 | + var_name << "kernel_" << i << "_" << j; |
| 163 | + sc_trace(this->wf, this->kernel[i * N + j], var_name.str()); |
| 164 | +#endif // IPS_DUMP_EN |
| 165 | + } |
| 166 | + |
| 167 | + std::cout << std::endl; |
| 168 | + } |
| 169 | +#endif // IPS_DEBUG_EN |
| 170 | +} |
| 171 | +#endif // IPS_FILTER_AT_MODEL_HPP |
0 commit comments