Skip to content

Add helper function for fixed points #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Apr 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion jbpf_tests/common/jbpf_test_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,22 @@ struct packet

struct test_packet
{
int test_passed;
int32_t test_passed;
// extra fields for testing fixedpt
float test_float_1;
float test_float_2;
float test_float_3;
float test_float_4;
float test_float_5;
float test_float_6;
double test_double_1;
double test_double_2;
double test_double_3;
double test_double_4;
double test_double_5;
double test_double_6;
int32_t test_int_1;
int64_t test_int64_1;
};

struct packet4
Expand Down
140 changes: 140 additions & 0 deletions jbpf_tests/functional/helper_functions/jbpf_fixpoint_codelet_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
/**
* This codelet tests the fixpoint helper function.
* It loads the jbpf_helper_fixpoint codeletset and calls the test_single_result hook.
* Inside the hook call, the codelet will call the helper functions:
* 1. float_to_fixed
* 2. fixed_to_float
* 3. double_to_fixed
* 4. fixed_to_double
* 5. fixedpt_add
* 6. fixedpt_sub
* 7. fixedpt_mul
* 8. fixedpt_div
* 9. fixedpt_rconst
* The values are verified here.
* The test is repeated 10000 times.
*/

#include <assert.h>
#include <pthread.h>

#include "jbpf.h"
#include "jbpf_agent_common.h"
#include "jbpf_helper_utils.h"

// Contains the struct and hook definitions
#include "jbpf_test_def.h"
#include <math.h>

jbpf_io_stream_id_t stream_id_c1 = {
.id = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}};

#define MAX_ITERATION (10000)

int
main(int argc, char** argv)
{
struct jbpf_codeletset_load_req codeletset_req_c1 = {0};
struct jbpf_codeletset_unload_req codeletset_unload_req_c1 = {0};
const char* jbpf_path = getenv("JBPF_PATH");
struct jbpf_config config = {0};
struct test_packet data = {0};

JBPF_UNUSED(codeletset_unload_req_c1);

jbpf_set_default_config_options(&config);

config.lcm_ipc_config.has_lcm_ipc_thread = false;

assert(jbpf_init(&config) == 0);

// The thread will be calling hooks, so we need to register it
jbpf_register_thread();

// The name of the codeletset
strcpy(codeletset_req_c1.codeletset_id.name, "jbpf_fixpoint_test");

// Create max possible codelets
codeletset_req_c1.num_codelet_descriptors = 1;

// The codelet has just one output channel and no shared maps
codeletset_req_c1.codelet_descriptor[0].num_in_io_channel = 0;
codeletset_req_c1.codelet_descriptor[0].num_out_io_channel = 0;

// Link the map to a stream id
memcpy(&codeletset_req_c1.codelet_descriptor[0].out_io_channel[0].stream_id, &stream_id_c1, JBPF_STREAM_ID_LEN);
// The output channel of the codelet does not have a serializer
codeletset_req_c1.codelet_descriptor[0].out_io_channel[0].has_serde = false;
codeletset_req_c1.codelet_descriptor[0].num_linked_maps = 0;

// The path of the codelet
assert(jbpf_path != NULL);
snprintf(
codeletset_req_c1.codelet_descriptor[0].codelet_path,
JBPF_PATH_LEN,
"%s/jbpf_tests/test_files/codelets/helper_function_fixpoint/jbpf_helper_fixpoint.o",
jbpf_path);
strcpy(codeletset_req_c1.codelet_descriptor[0].codelet_name, "jbpf-fixpoint-example");

snprintf(codeletset_req_c1.codelet_descriptor[0].hook_name, JBPF_HOOK_NAME_LEN, "test_single_result");

// Load the codeletset
assert(jbpf_codeletset_load(&codeletset_req_c1, NULL) == JBPF_CODELET_LOAD_SUCCESS);

// iterate the increment operation
for (int iter = 0; iter < MAX_ITERATION; ++iter) {
// call the hook to perform the tests in the codelet
hook_test_single_result(&data, 1);
// verify the correctness of the results
// the values are computed in the codelet
// Test case 1: convert two floats to fixedpt and add them, then convert back to float
// 1.23 + 2.34 = 3.57
assert(fabs(data.test_float_1 - 3.57) < 0.01);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please explain why this needs to be tested with inequalities? Is the expected accuracy of the test not known a priori? The same question applies for all the other tests below.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because there is an precision loss performing float addition, especially, the floats are converted to fixedpt and then converted back.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But isn't the loss of precision known? Can it change depending on where the test runs? If not, why not check against specific values?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand. This is how we compare floats in the test. See here

// Test case 2: convert two doubles to fixedpt and add them, then convert back to double
// 3.45 + 4.56 = 8.01
assert(fabs(data.test_double_1 - 8.01) < 0.01);
// Test case 3: test fixed_to_float
assert(fabs(data.test_float_2 - 3.14) < 0.01);
// Test case 4: test fixed_to_double
assert(fabs(data.test_double_2 - 2.71) < 0.01);
// Test case 5: test float_to_fixed
assert(data.test_int_1 == fixedpt_rconst(1.2));
// Test case 6: test double_to_fixed
assert(data.test_int64_1 == fixedpt_rconst(2.345));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be converted to float and then do a comparison between floats?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test 3 to 6 are for each function, which are sufficient.

// Test case 7: test fixedpt_sub
// 5.1 - 2.9 = 2.2
assert(fabs(data.test_float_3 - 2.2) < 0.01);
// Test case 8: test fixedpt_mul
// 2.5 * 1.3 = 3.25
assert(fabs(data.test_float_4 - 3.25) < 0.01);
// Test case 9: test fixedpt_div
// 7.5 / 2.5 = 3.0
assert(fabs(data.test_float_5 - 3.0) < 0.01);
// Test case 10: test fixedpt_sub for double
// 5.1 - 2.9 = 2.2
assert(fabs(data.test_double_3 - 2.2) < 0.01);
// Test case 11: test fixedpt_mul for double
// 2.5 * 1.3 = 3.25
assert(fabs(data.test_double_4 - 3.25) < 0.01);
// Test case 12: test fixedpt_div for double
// 7.5 / 2.5 = 3.0
assert(fabs(data.test_double_5 - 3.0) < 0.01);
// Test case 13: mixed operations for float
// (1.23 + 2.34 * 3.45) / 4.56 = 2.04
assert(fabs(data.test_float_6 - 2.04) < 0.01);
// Test case 14: mixed operations for double
// (1.23 + 2.34 * 3.45) / 4.56 = 2.04
assert(fabs(data.test_double_6 - 2.04) < 0.01);
}

// Unload the codeletsets
codeletset_unload_req_c1.codeletset_id = codeletset_req_c1.codeletset_id;
assert(jbpf_codeletset_unload(&codeletset_unload_req_c1, NULL) == JBPF_CODELET_UNLOAD_SUCCESS);

// Stop
jbpf_stop();

printf("Test completed successfully\n");
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include ../Makefile.defs
include ../Makefile.common
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
/**
* The purpose of the codelet is to make sure we can use the following functions:
* 1. float_to_fixed
* 2. fixed_to_float
* 3. double_to_fixed
* 4. fixed_to_double
*/

#include "jbpf_helper.h"
#include "jbpf_test_def.h"
#include "jbpf_helper_utils.h"

SEC("jbpf_generic")
uint64_t
jbpf_main(void* state)
{
struct jbpf_generic_ctx* ctx = (struct jbpf_generic_ctx*)state;
struct test_packet* data = (struct test_packet*)ctx->data;
struct test_packet* data_end = (struct test_packet*)ctx->data_end;
if (data + 1 > data_end) {
return 1;
}

// Test case 1: convert two floats to fixedpt and add them, then convert back to float
float a = 1.23;
float b = 2.34;
// 3.57
data->test_float_1 = fixed_to_float(fixedpt_add(float_to_fixed(a), float_to_fixed(b)));

// Test case 2: convert two doubles to fixedpt and add them, then convert back to double
double c = 3.45;
double d = 4.56;
// 8.01
data->test_double_1 = fixed_to_double(fixedpt_add(double_to_fixed(c), double_to_fixed(d)));

// Test case 3: test fixed_to_float
data->test_float_2 = fixed_to_float(fixedpt_rconst(3.14));

// Test case 4: test fixed_to_double
data->test_double_2 = fixed_to_double(fixedpt_rconst(2.71));

// Test case 5: test float_to_fixed
data->test_int_1 = float_to_fixed(1.2);

// Test case 6: test double_to_fixed
data->test_int64_1 = double_to_fixed(2.345);

// Test case 7: test fixedpt_sub
data->test_float_3 = fixed_to_float(fixedpt_sub(fixedpt_rconst(5.1), fixedpt_rconst(2.9)));

// Test case 8: test fixedpt_mul
data->test_float_4 = fixed_to_float(fixedpt_mul(fixedpt_rconst(2.5), fixedpt_rconst(1.3)));

// Test case 9: test fixedpt_div
data->test_float_5 = fixed_to_float(fixedpt_div(fixedpt_rconst(7.5), fixedpt_rconst(2.5)));

// Test case 10: test fixedpt_sub for double
data->test_double_3 = fixed_to_double(fixedpt_sub(double_to_fixed(5.1), double_to_fixed(2.9)));

// Test case 11: test fixedpt_mul for double
data->test_double_4 = fixed_to_double(fixedpt_mul(double_to_fixed(2.5), double_to_fixed(1.3)));

// Test case 12: test fixedpt_div for double
data->test_double_5 = fixed_to_double(fixedpt_div(double_to_fixed(7.5), double_to_fixed(2.5)));

// Test case 13: mixed operations for float
float a1 = 1.23;
float b1 = 2.34;
double c1 = 3.45;
double d1 = 4.56;
// (a1 + b2 * c1) / d1 = (1.23 + 2.34 * 3.45) / 4.56 = 2.04
data->test_float_6 = fixed_to_float(fixedpt_div(
fixedpt_add(float_to_fixed(a1), fixedpt_mul(float_to_fixed(b1), double_to_fixed(c1))), double_to_fixed(d1)));

// Test case 14: mixed operations for double
double a2 = 1.23;
double b2 = 2.34;
double c2 = 3.45;
double d2 = 4.56;
// (a2 + b2 * c2) / d2 = (1.23 + 2.34 * 3.45) / 4.56 = 2.04
data->test_double_6 = fixed_to_double(fixedpt_div(
fixedpt_add(double_to_fixed(a2), fixedpt_mul(double_to_fixed(b2), double_to_fixed(c2))), double_to_fixed(d2)));

return 0;
}
Binary file not shown.
Loading