Example - 6.0 English - PG104

Complex Multiplier LogiCORE IP Product Guide (PG104)

Document ID
PG104
Release Date
2024-11-26
Version
6.0 English

The run_bitacc_cmodel.c file contains example code to show basic operation of the C model. Part of this example code is shown here. The comments assist in understanding the code.

#include <iostream>
#include <complex>
#define _USE_MATH_DEFINES
#include <math.h>
#include <fstream> // for debug only
#include "cmpy_v6_0_bitacc_cmodel.h"
#include "gmp.h"
using namespace std;
#define DATA_SIZE 10
int main()
{
size_t ii; //loop variable for data samples
xip_uint roundbit;
xip_complex value;
// Create a configuration structure
xip_cmpy_v6_0_config config, config_ret;
xip_cmpy_v6_0_status status = xip_cmpy_v6_0_default_config(&config);
if (status != XIP_CMPY_V6_0_STATUS_OK) {
cerr << "ERROR: Could not get C model default configuration" << endl;
return XIP_STATUS_ERROR;
}
//Configure this instance.
config.APortWidth = 16;
config.BPortWidth = 16;
config.OutputWidth = 33;
config.RoundMode = XIP_CMPY_V6_0_TRUNCATE; //Note that the check later in this
file assumes full width
// Create model object
xip_cmpy_v6_0* cmpy_std;
cmpy_std = xip_cmpy_v6_0_create(&config, &msg_print, 0);
if (status != XIP_CMPY_V6_0_STATUS_OK) {
cerr << "ERROR: Could not create C model state object" << endl;
return XIP_STATUS_ERROR;
}
// Can we read back the updated configuration correctly?
if (xip_cmpy_v6_0_get_config(cmpy_std, &config_ret) != XIP_CMPY_V6_0_STATUS_OK) {
cerr << "ERROR: Could not retrieve C model configuration" << endl;
}
int number_of_samples = DATA_SIZE;
// Create input data structure for operand A samples
xip_array_complex* reqa = xip_array_complex_create();
xip_array_complex_reserve_dim(reqa,1); //dimensions are (Number of samples)
reqa->dim_size = 1;
reqa->dim[0] = number_of_samples;
reqa->data_size = reqa->dim[0];
if (xip_array_complex_reserve_data(reqa,reqa->data_size) == XIP_STATUS_OK) {
cout << "INFO: Reserved memory for request as [" << number_of_samples << "] array
" << endl;
} else {
cout << "ERROR: Unable to reserve memory for input data packet!" << endl;
exit(2);
}
// Create input data structure for operand B samples
xip_array_complex* reqb = xip_array_complex_create();
xip_array_complex_reserve_dim(reqb,1); //dimensions are (Number of samples)
reqb->dim_size = 1;
reqb->dim[0] = number_of_samples;
reqb->data_size = reqb->dim[0];
if (xip_array_complex_reserve_data(reqb,reqb->data_size) == XIP_STATUS_OK) {
cout << "INFO: Reserved memory for request as [" << number_of_samples << "] array
" << endl;
} else {
cout << "ERROR: Unable to reserve memory for input data packet!" << endl;
exit(2);
}
// Create input data structure for ctrl input (Round bit)
xip_array_uint* reqctrl = xip_array_uint_create();
xip_array_uint_reserve_dim(reqctrl,1); //dimensions are (Number of samples)
reqctrl->dim_size = 1;
reqctrl->dim[0] = number_of_samples;
reqctrl->data_size = reqctrl->dim[0];
if (xip_array_uint_reserve_data(reqctrl,reqctrl->data_size) == XIP_STATUS_OK) {
cout << "INFO: Reserved memory for request as [" << number_of_samples << "] array
" << endl;
} else {
cout << "ERROR: Unable to reserve memory for input data packet!" << endl;
exit(2);
}
//create example input data
xip_complex a,b;
for (ii = 0; ii < DATA_SIZE; ii++)
{
roundbit = ii % 2;
a.re = (xip_real)ii;
a.im = (xip_real)ii;
b.re = (xip_real)(16-ii);
b.im = (xip_real)ii;
if (xip_array_complex_set_data(reqa, a, ii) != XIP_STATUS_OK)
cerr << "Error in xip_array_complex_set_data" << endl;
if (xip_array_complex_set_data(reqb, b, ii) != XIP_STATUS_OK)
cerr << "Error in xip_array_complex_set_data" << endl;
if (xip_array_uint_set_data(reqctrl, roundbit, ii) != XIP_STATUS_OK)
cerr << "Error in xip_array_uint_set_data" << endl;
// Request memory for output data
xip_array_complex* response = xip_array_complex_create();
xip_array_complex_reserve_dim(response,1); //dimensions are (Number of samples)
response->dim_size = 1;
response->dim[0] = number_of_samples;
response->data_size = response->dim[0];
if (xip_array_complex_reserve_data(response,response->data_size) ==
XIP_STATUS_OK) {
cout << "INFO: Reserved memory for response as [" << number_of_samples << "]
array " << endl;
} else {
cout << "ERROR: Unable to reserve memory for output data packet!" << endl;
exit(3);
}
// Run the model
cout << "Running the C model..." << endl;
if (xip_cmpy_v6_0_data_do(cmpy_std, reqa, reqb, reqctrl, response) !=
XIP_CMPY_V6_0_STATUS_OK) {
cerr << "ERROR: C model did not complete successfully" << endl;
xip_array_complex_destroy(reqa);
xip_array_complex_destroy(reqb);
xip_array_uint_destroy(reqctrl);
xip_array_complex_destroy(response);
xip_cmpy_v6_0_destroy(cmpy_std);
return XIP_STATUS_ERROR;
} else {
cout << "C model completed successfully" << endl;
}
// Check response is correct
for (ii = 0; ii < DATA_SIZE; ii++)
{
//This example has natural width, so simple calculation
xip_complex expected, got, x, y;
xip_array_complex_get_data(reqa, &x, ii);
xip_array_complex_get_data(reqb, &y, ii);
xip_array_complex_get_data(response, &got, ii);
//Note that the following equations assume that the output width is the full
natural
//width of the calculation, i.e. neither truncation nor rounding occurs
expected.re = x.re*y.re - x.im*y.im;
expected.im = x.re*y.im + x.im*y.re;
if (expected.re != got.re || expected.im != got.im) {
cerr << "ERROR: C model data output is incorrect for sample" << ii << "Expected
real = " << expected.re << " imag = " << expected.im << " Got real = " << got.re <<
" imag = " << got.im << endl;
xip_array_complex_destroy(reqa);
xip_array_complex_destroy(reqb);
xip_array_uint_destroy(reqctrl);
xip_array_complex_destroy(response);
xip_cmpy_v6_0_destroy(cmpy_std);
return XIP_STATUS_ERROR;
} else {
cout << "Sample " << ii << " was as expected" << endl;
}
}
cout << "C model data output is correct" << endl;
// Clean up
xip_array_complex_destroy(reqa);
xip_array_complex_destroy(reqb);
xip_array_uint_destroy(reqctrl);
xip_array_complex_destroy(response);
cout << "C model input and output data freed" << endl;
xip_cmpy_v6_0_destroy(cmpy_std);
cout << "C model destroyed" << endl;