void TuneFilterDecimate_i::TuningRFChanged(const CORBA::ULongLong *oldValue, const CORBA::ULongLong *newValue)
{
	if (*oldValue != *newValue) {
		boost::mutex::scoped_lock lock(TuneFilterDecimateLock_);
		configureTuner("TuningRF");
	}
}
void TuneFilterDecimate_i::TuningIFChanged(const double *oldValue, const double *newValue)
{
	if (*oldValue != *newValue) {
		boost::mutex::scoped_lock lock(TuneFilterDecimateLock_);
		configureTuner("TuningIF");
	}
}
void TuneFilterDecimate_i::configureTFD(BULKIO::StreamSRI &sri) {
	LOG_TRACE(TuneFilterDecimate_i, "Configuring SRI: "
			<< "sri.xdelta = " << sri.xdelta
			<< "sri.streamID = " << sri.streamID)
					Real tmpInputSampleRate = 1 / sri.xdelta; // Calculate sample rate received from SRI
	bool lastInputComplex = inputComplex;
	if (sri.mode==1)
	{
		inputComplex=true;
		chan_if =0.0; //center of band is 0 if we are complex
	}
	else
	{
		inputComplex = false;
		chan_if = tmpInputSampleRate/4.0; //center of band is fs/4 if we are real
		//output is always complex even if input is real
		sri.mode=1;
	}

	DecimationFactor = floor(tmpInputSampleRate/DesiredOutputRate);
	LOG_DEBUG(TuneFilterDecimate_i, "DecimationFactor = " << DecimationFactor);
	if (DecimationFactor <1) {
		LOG_WARN(TuneFilterDecimate_i, "Decimation less than 1, setting to minimum")
						DecimationFactor=1;
	}

	bool sampleRateChanged =(InputRate != tmpInputSampleRate);
	if (sampleRateChanged)
	{
		InputRate = tmpInputSampleRate;
		LOG_DEBUG(TuneFilterDecimate_i, "Sample rate changed: InputRate = " << InputRate);
	}

	// Calculate new output sample rate & modify the referenced SRI structure
	ActualOutputRate = InputRate / DecimationFactor;
	sri.xdelta = 1.0 / ActualOutputRate;
	LOG_DEBUG(TuneFilterDecimate_i, "Output xdelta = " << sri.xdelta
			<< " ActualOutputRate " << ActualOutputRate);

	if (ActualOutputRate < FilterBW)
		LOG_WARN(TuneFilterDecimate_i, "ActualOutputRate " << ActualOutputRate << " is less than FilterBW " << FilterBW);

	// Retrieve the front-end collected RF to determine the IF
	bool validCollectionRF = false;
	bool validChannelRF = false;
	double collection_rf = getKeywordByID<CORBA::Double>(sri, "COL_RF", validCollectionRF);
	double channel_rf = getKeywordByID<CORBA::Double>(sri, "CHAN_RF", validChannelRF);
	double tmpInputRF;
	if ((validCollectionRF) && (validChannelRF)) {
		LOG_WARN(TuneFilterDecimate_i, "Input SRI contains both COL_RF and CHAN_RF, using CHAN_RF");
		tmpInputRF = channel_rf;
	} else if (validCollectionRF) {
		tmpInputRF = collection_rf;
	} else if (validChannelRF) {
		tmpInputRF = channel_rf;
	} else {
		if (TuneMode == "RF") {
			LOG_WARN(TuneFilterDecimate_i, "Input SRI lacks RF keyword.  RF tuning cannot be performed.");
			return;
		}
		tmpInputRF = 0;
	}
	bool inputComplexChanged = lastInputComplex ^ inputComplex;

	if (tmpInputRF != InputRF) {
		LOG_DEBUG(TuneFilterDecimate_i, "Input RF changed " << tmpInputRF);
		InputRF = tmpInputRF;

		// If the TuneMode is RF, we actually need to retune
		if (TuneMode == "RF") {
			configureTuner("TuningRF");
        } else if (TuneMode == "NORM") {
            configureTuner("TuningNorm");
        }
		TuningRF = InputRF + TuningIF - chan_if;
		LOG_DEBUG(TuneFilterDecimate_i, "Tuning RF: " << TuningRF);
	}
	else if (TuneMode == "RF" && inputComplexChanged)
	{
		//the RF didn't change but the IF is changing because we have switched between real and complex data
		configureTuner("TuningRF");
		LOG_DEBUG(TuneFilterDecimate_i, "Tuning RF: " << TuningRF);
	}

	// Add the CHAN_RF keyword to the SRI if we know the input RF
	if (InputRF != 0) {
		if(!setKeywordByID<CORBA::Double>(sri, "CHAN_RF", (double)TuningRF))
			LOG_WARN(TuneFilterDecimate_i, "SRI Keyword CHAN_RF could not be set.");
	}

	// Reconfigure the tuner classes only if the sample rate has changed
	if ((tuner== NULL) || sampleRateChanged) {
		LOG_DEBUG(TuneFilterDecimate_i, "Remaking tuner");

		if (tuner != NULL) {
			delete tuner;
		}

		if (TuneMode == "NORM") {
			configureTuner("TuningNorm");
		} else if (TuneMode == "IF") {
			configureTuner("TuningIF");
		} else if (TuneMode == "RF") {
			configureTuner("TuningRF");
		}

		tuner = new Tuner(tunerInput, f_complexIn, TuningNorm);
	}

	if ((filter==NULL) || sampleRateChanged || RemakeFilter) {
		LOG_DEBUG(TuneFilterDecimate_i, "Remaking filter");

		if((filter != NULL) || (decimate != NULL)) {
			delete filter;
			delete decimate;
		}
/*
 *                    ASCII ART to explain the filter design
 *
 *  Lowpass (Real filter)
 *  ---------|
 *           \
 *            \
 *             \
 *              |
 *  ----------------------------------
 *  0        FL FL+tw   fsOut/2   fsIn/2
 *
 *  The basic gist is we tune first, then filter.
 *  Then we filter
 *  Then we decimate
 *
 *  This means the filter is a LOWPASS filter which must be designed given the INPUT sampling frequency.
 *  The transition frequency happens at 1/2 the requested tune bandwidth.  Thus FL = FilterBW / 2.0.
 *  We need the transition region to "finish" by fsOut/2 to avoid aliasing, so we do a check for that too.
 *
 */
		Real FL = FilterBW / 2.0;

		//calculate the transition frequency necessary to avoid aliasing
		Real maxTW = (ActualOutputRate/2.0)-FL;
		if (maxTW > 0 && maxTW <  filterProps.TransitionWidth)
		{
			LOG_WARN(TuneFilterDecimate_i, "input transition width "<< filterProps.TransitionWidth<<"  too large - replacing with "<< maxTW);
			filterProps.TransitionWidth = maxTW;
		}

		// We generate our FIR filter taps here. The read-only property 'taps' is set.
		// 	- We use the transition width and ripple specified by the user to create the filter taps.
		// 	- Normalized lowpass cutoff frequency is the only one we need; upper cutoff not used
		RealVector tmpVec;
		taps = filterdesigner_.wdfirHz(tmpVec, FIRFilter::lowpass, filterProps.Ripple, filterProps.TransitionWidth,
				FL, 0, InputRate, MIN_NUM_TAPS, MAX_NUM_TAPS);
		filterCoeff.clear();
		filterCoeff.reserve(tmpVec.size());
		for (RealVector::iterator i = tmpVec.begin(); i!=tmpVec.end(); i++)
			filterCoeff.push_back(*i);

		// Minimum FFT_size implemented
		size_t minFftSize = std::max(MIN_FFT_SIZE, pow2ge(2*taps));
		if(filterProps.FFT_size < minFftSize) {
			LOG_DEBUG(TuneFilterDecimate_i, "FFT_size too small, set to " << minFftSize);
			filterProps.FFT_size = minFftSize;
		} else if (filterProps.FFT_size > MAX_FFT_SIZE)
		{
			LOG_DEBUG(TuneFilterDecimate_i, "FFT_size too large, set to " << MAX_FFT_SIZE);
			filterProps.FFT_size = MAX_FFT_SIZE;
		}
		filter = new firfilter(filterProps.FFT_size, f_realOut, f_complexOut, filterCoeff);
		decimate = new Decimate(f_complexOut, decimateOutput, DecimationFactor);
		RemakeFilter = false;	
	}

	LOG_TRACE(TuneFilterDecimate_i, "Exit configureSRI()");
}
Beispiel #4
0
void init(CodecConfiguration *configuration) {
    // Need to initialize loggers.
    // Then need to pre-allocate pinned memory and Cuda Global Memory.
    gpuTunerCategory = log4c_category_get("performance_tuning_gpu_logger");
    cpuTunerCategory = log4c_category_get("performance_tuning_cpu_logger");
    log4c_init();

    currentMode = PRODUCTION;
    config_t propConfig;
    config_init(&propConfig);
    if (!config_read_file(&propConfig, configuration->propertyFilePath)) {
        fprintf(stderr, "%s:%d - %s\n",
                config_error_file(&propConfig), config_error_line(&propConfig), config_error_text(&propConfig));
        config_destroy(&propConfig);
        return;
    }

    config_lookup_bool(&propConfig, "isUseGpu", &useGpu);
    config_lookup_bool(&propConfig, "isUseDynamicParallelism", &useDynamicParallelism);
    config_lookup_int(&propConfig, "max_packet_size", &maxPacketSize);
    config_lookup_int(&propConfig, "max_batch_size", &maxBatchSize);
    config_lookup_int(&propConfig, "tuner_loop_count", &tunerLoopCount);
    config_lookup_int(&propConfig, "number_of_cpu_cores", &nCpuCores);
    config_lookup_int(&propConfig, "cuda_stream_count", &cudaStreamCount);
    config_lookup_bool(&propConfig, "print_accuracy_log", &printAccuracyLog);

    currentCudaContextSize = (uint32_t) maxBatchSize;
    cudaPduContext = allocatePinnedPduContext(maxBatchSize);
    initCudaParameters((uint32_t) maxBatchSize, ((uint64_t) maxPacketSize * (uint64_t) maxBatchSize));

    int isTunerMode = 0;
    config_lookup_bool(&propConfig, "isTunerMode", &isTunerMode);
    currentMode = isTunerMode ? TUNER : PRODUCTION;
    printf("Is Use GPU %d | Max Packet Size %d | Max Batch Size %d | Tuner Mode %d | Accuracy Log %d\n",
           useGpu, maxPacketSize, maxBatchSize, currentMode, printAccuracyLog);
    fflush(stdout);
    switch (currentMode) {
        case TUNER: {
            configureTuner(&propConfig);
            break;
        }
        default: {
            int x, y, z;
            config_setting_t *block = config_lookup(&propConfig, "production.block");
            config_setting_t *grid = config_lookup(&propConfig, "production.grid");

            config_setting_lookup_int(block, "x", &x);
            config_setting_lookup_int(block, "y", &y);
            config_setting_lookup_int(block, "z", &z);

            blockDimProdction.x = (uint32_t) x;
            blockDimProdction.y = (uint32_t) y;
            blockDimProdction.z = (uint32_t) z;

            config_setting_lookup_int(grid, "x", &x);
            config_setting_lookup_int(grid, "y", &y);
            config_setting_lookup_int(grid, "z", &z);

            gridDimProduction.x = (uint32_t) x;
            gridDimProduction.y = (uint32_t) y;
            gridDimProduction.z = (uint32_t) z;

            config_lookup_int(&propConfig, "production.cpu_decode_threshold", &cpuDecodeThreshold);
        }
    }
}