Example #1
0
File: app.c Project: THofstee/pslse
int main(int argc, char *argv[])
{

	// Open first AFU found
	struct cxl_afu_h *afu_h;
	afu_h = cxl_afu_next(NULL);
	if (!afu_h) {
		fprintf(stderr, "\nNo AFU found!\n\n");
		return -1;
	}
	afu_h = cxl_afu_open_h(afu_h, CXL_VIEW_DEDICATED);
	if (!afu_h) {
		perror("cxl_afu_open_h");
		return -1;
	}
	// Prepare WED
	struct wed *wed = NULL;
	if (posix_memalign((void **)&wed, CACHELINE_BYTES, sizeof(struct wed))) {
		perror("posix_memalign");
		return -1;
	}
	printf("Allocated WED memory @ 0x%016" PRIx64 "\n", (uint64_t) wed);
	wed->endian_test = 1;
	wed->status = 0;

	// Start AFU
	cxl_afu_attach(afu_h, (uint64_t) wed);

	// Map AFU MMIO registers, if needed
	printf("Mapping AFU registers...\n");
	if ((cxl_mmio_map(afu_h, CXL_MMIO_BIG_ENDIAN)) < 0) {
		perror("cxl_mmio_map");
		return -1;
	}

  /**************************************************************************

  Do something here and wait for results.
  
  cxl_mmio_*() functions can only be used here between cxl_mmio_map and
  cxl_mmio_unmap.

  Presumably your application will possibly monitor and/or possibly update
  values in the wed struct or some other place in memory that AFU was
  informed that it could access.  Maybe a bit in the wed struct like those in
  the example "status" field could be updated by the AFU to indicate that
  it has completed a job.  In this example that is why the status field is
  made volatile.  This prevents the compiler from optimization polling of
  the status field.

  **************************************************************************/

	// Unmap AFU MMIO registers, if previously mapped
	cxl_mmio_unmap(afu_h);

	// Free AFU
	cxl_afu_free(afu_h);

	return 0;
}
Example #2
0
int main(int argc, char *argv[])
{
	struct cxl_afu_h *afu_h;
	uint64_t wed, wed_check, rand64, rand64_check;
	uint32_t rand32_upper, rand32_lower;
	unsigned seed;
	int opt, option_index;
	char *name;

	name = strrchr(argv[0], '/');
	if (name)
		name++;
	else
		name = argv[0];

	static struct option long_options[] = {
		{"help",	no_argument,		0,		'h'},
		{"seed",	required_argument,	0,		's'},
		{NULL, 0, 0, 0}
	};

	option_index = 0;
	seed = time(NULL);
	while ((opt = getopt_long (argc, argv, "hs:",
				   long_options, &option_index)) >= 0) {
		switch (opt)
		{
		case 0:
			break;
		case 's':
			seed = strtoul(optarg, NULL, 0);
			break;
		case 'h':
		default:
			usage(name);
			return 0;
		}
	}

	// Seed random number generator
	srand(seed);
	printf("%s: seed=%d\n", name, seed);

	// Find first AFU in system
	afu_h = cxl_afu_next(NULL);
	if (!afu_h) {
		fprintf(stderr, "FAILED:No AFU found!\n");
		goto done;
	}

	// Open AFU
	afu_h = cxl_afu_open_h(afu_h, CXL_VIEW_DEDICATED);
	if (!afu_h) {
		perror("FAILED:cxl_afu_open_h");
		goto done;
	}

	printf("Attempt mapping AFU registers before attach\n");
	if ((cxl_mmio_map(afu_h, CXL_MMIO_BIG_ENDIAN)) == 0) {
		printf("FAILED:cxl_mmio_map");
		goto done;
	}

	printf("Attempt mmio read before successful mapping\n");
	if (cxl_mmio_read64(afu_h, 0x8, &wed_check) == 0) {
		printf("FAILED:cxl_mmio_read64");
		goto done;
	}

	// Generate random 64-bit value for WED
	wed = rand();
	wed <<= 32;
	wed |= rand();

	// Start AFU passing random WED value
	cxl_afu_attach(afu_h, wed);

	// Map AFU MMIO registers
	printf("Mapping AFU registers...\n");
	if ((cxl_mmio_map(afu_h, CXL_MMIO_BIG_ENDIAN)) < 0) {
		perror("FAILED:cxl_mmio_map");
		goto done;
	}

	/////////////////////////////////////////////////////
	// CHECK 1 - WED value was passed to AFU correctly //
	/////////////////////////////////////////////////////

	// Read WED from AFU and verify
	if (cxl_mmio_read64(afu_h, 0x8, &wed_check) < 0) {
		perror("FAILED:cxl_mmio_read64");
		goto done;
	}
	if (wed != wed_check) {
		printf("\nFAILED:WED mismatch!\n");
		printf("\tExpected:0x%016"PRIx64"\n", wed);
		printf("\tActual  :0x%016"PRIx64"\n", wed_check);
		goto done;
	}
	printf("WED check complete\n");

	//////////////////////////////////////////////////////////////
	// CHECK 2 - Write 64-bit value and check with 32-bit reads //
	//////////////////////////////////////////////////////////////

	// Write random 64-bit value to MMIO space
	rand64 = rand();
	rand64 <<= 32;
	rand64 |= rand();
	if (cxl_mmio_write64(afu_h, 0x17f0, rand64) < 0) {
		perror("FAILED:cxl_mmio_write64");
		goto done;
	}

	// Use two 32-bit read to check 64-bit value written
	if (cxl_mmio_read32(afu_h, 0x17f0, &rand32_upper) < 0) {
		perror("FAILED:cxl_mmio_read32");
		goto done;
	}
	if (cxl_mmio_read32(afu_h, 0x17f4, &rand32_lower) < 0) {
		perror("FAILED:cxl_mmio_read32");
		goto done;
	}
	rand64_check = (uint64_t) rand32_upper;
	rand64_check <<= 32;
	rand64_check |= (uint64_t) rand32_lower;
	if (rand64 != rand64_check) {
		printf("\nFAILED:64-bit write => 32-bit reads mismatch!\n");
		printf("\tExpected:0x%016"PRIx64"\n", rand64);
		printf("\tActual  :0x%016"PRIx64"\n", rand64_check);
		goto done;
	}
	printf("64-bit write => 32-bit reads check complete\n");

	//////////////////////////////////////////////////////////////
	// CHECK 3 - Write 32-bit values and check with 64-bit read //
	//////////////////////////////////////////////////////////////

	// Write two random 32-bit values to a single 64-bit MMIO register
	rand32_upper = rand();
	if (cxl_mmio_write32(afu_h, 0x17f8, rand32_upper) < 0) {
		perror("FAILED:cxl_mmio_write32");
		goto done;
	}
	rand32_lower = rand();
	if (cxl_mmio_write32(afu_h, 0x17fc, rand32_lower) < 0) {
		perror("FAILED:cxl_mmio_write32");
		goto done;
	}

	// Build 64-bit value from two 32-bit values
	rand64 = (uint64_t) rand32_upper;
	rand64 <<= 32;
	rand64 |= (uint64_t) rand32_lower;

	// Check 32-bit writes with one 64-bit read
	if (cxl_mmio_read64(afu_h, 0x17f8, &rand64_check) < 0) {
		perror("FAILED:cxl_mmio_read64");
		goto done;
	}
	if (rand64 != rand64_check) {
		printf("\nFAILED:32-bit writes => 64-bit read mismatch!\n");
		printf("\tExpected:0x%016"PRIx64"\n", rand64);
		printf("\tActual  :0x%016"PRIx64"\n", rand64_check);
		goto done;
	}
	printf("32-bit writes => 64-bit read check complete\n");

	// Report test as passing
	printf("PASSED\n");
done:
	if (afu_h) {
		// Unmap AFU MMIO registers
		cxl_mmio_unmap(afu_h);
		// Free AFU     
		cxl_afu_free(afu_h);
	}

	return 0;
}
Example #3
0
int main(int argc, char *argv[])
{
#ifdef PSL9
	MachineConfig machine;
	char *cacheline0, *cacheline1, *name;
	uint64_t wed;
	unsigned seed;
	int i, quadrant, byte, opt, option_index;
	int response;
	int context, machine_number;

	name = strrchr(argv[0], '/');
	if (name)
		name++;
	else
		name = argv[0];

	static struct option long_options[] = {
		{"help",	no_argument,		0,		'h'},
		{"seed",	required_argument,	0,		's'},
		{NULL, 0, 0, 0}
	};

	option_index = 0;
	seed = time(NULL);
	while ((opt = getopt_long (argc, argv, "hs:",
				   long_options, &option_index)) >= 0) {
		switch (opt)
		{
		case 0:
			break;
		case 's':
			seed = strtoul(optarg, NULL, 0);
			break;
		case 'h':
		default:
			usage(name);
			return 0;
		}
	}

	// Seed random number generator
	srand(seed);
	printf("%s: seed=%d\n", name, seed);

	// find first AFU found
	struct cxl_afu_h *afu_h, *afu_m, *afu_s;
	afu_m = afu_s = NULL;
	
        afu_h = cxl_afu_next(NULL);
	if (!afu_h) {
		fprintf(stderr, "\nNo AFU found!\n\n");
		goto done;
	}
	
        
        // afu master 
	afu_m = cxl_afu_open_h(afu_h, CXL_VIEW_MASTER);
	if (!afu_m) {
		perror("cxl_afu_open_h for master");
		goto done;
	}

	// Set WED to random value
	wed = rand();
	wed <<= 32;
	wed |= rand();

	// Start AFU for master
	printf("Attach AFU master\n");
	if (cxl_afu_attach(afu_m, wed) < 0) {
            perror("FAILED:cxl_afu_attach for master");
		goto done;
        }

	printf("wed = 0x%"PRIx64"\n", wed);

	// Map AFU MMIO registers
	printf("Mapping AFU master registers...\n");
	if ((cxl_mmio_map(afu_m, CXL_MMIO_BIG_ENDIAN)) < 0) {
		perror("cxl_mmio_map for master");
		goto done;

	}
	printf("End AFU master mmio map\n");

	context = cxl_afu_get_process_element(afu_m);

	printf("Master context = %d\n", context);
	// Allocate aligned memory for two cachelines
	if (posix_memalign((void **)&cacheline0, CACHELINE_BYTES, CACHELINE_BYTES) != 0) {
		perror("FAILED:posix_memalign");
		goto done;
	}
	if (posix_memalign((void **)&cacheline1, CACHELINE_BYTES, CACHELINE_BYTES) != 0) {
		perror("FAILED:posix_memalign");
		goto done;
	}

	// Pollute first cacheline with random values
	printf("CACHELINE0 = 0x");
	for (i = 0; i < CACHELINE_BYTES; i++)
	{
		cacheline0[i] = rand();
		printf("%02x", cacheline0[i]);
	}
	printf("\n");
	// Initialize machine configuration
	printf("initialize machine\n");
	init_machine(&machine);
	printf("End init machine\n");

	// Use AFU Machine 0 to read the first cacheline from memory to AFU
	printf("Configure, enable and run machine\n");
	if ((response = config_enable_and_run_machine(afu_m, &machine, 0, context, PSL_COMMAND_XLAT_RD_P0, CACHELINE_BYTES, 0, 0, (uint64_t)cacheline0, CACHELINE_BYTES, DIRECTED_M)) < 0)
	{
		printf("FAILED:config_enable_and_run_machine for master XLAT_RD response = %d\n", response);
		goto done;
	}
	printf("End configure enable and run machine for XLAT_RD\n");
	// Check for valid response
	if (response != PSL_RESPONSE_DONE)
	{
		printf("FAILED: Unexpected response code 0x%x\n", response);
		goto done;
	}

	printf("Completed cacheline read\n");

	// Use AFU Machine 0 to write the data to the second cacheline
	if ((response = config_enable_and_run_machine(afu_m, &machine, 0, context, PSL_COMMAND_XLAT_WR_P0, CACHELINE_BYTES, 0, 0, (uint64_t)cacheline1, CACHELINE_BYTES, DIRECTED_M)) < 0)
	{
		printf("FAILED:config_enable_and_run_machine for master XLAT_WR response = %d\n", response);
		goto done;
	}
	printf("End configure enable and run machine for XLAT WR\n");
	// Check for valid response
	if (response != PSL_RESPONSE_DONE)
	{
		printf("FAILED: Unexpected response code 0x%x\n", response);
		goto done;
	}

	// Test if copy from cacheline0 to cacheline1 was successful
	if (memcmp(cacheline0,cacheline1, CACHELINE_BYTES) != 0) {
		printf("FAILED:memcmp\n");
		for (quadrant = 0; quadrant < 4; quadrant++) {
			printf("DEBUG: Expected  Q%d 0x", quadrant);
			for (byte = 0; byte < CACHELINE_BYTES /4; byte++) {
				printf("%02x", cacheline0[byte+(quadrant*32)]);
			}
			printf("\n");
		}
		for (quadrant = 0; quadrant < 4; quadrant++) {
			printf("DEBUG: Actual  Q%d 0x", quadrant);
			for (byte = 0; byte < CACHELINE_BYTES / 4; byte++) {
				printf("%02x", cacheline1[byte+(quadrant*32)]);
			}
			printf("\n");
		}
		goto done;
	}

	printf("Master AFU: PASSED\n");
        
        // afu slave
        // find next afu
        afu_h = cxl_afu_next(NULL);
	if (!afu_h) {
		fprintf(stderr, "\nNo AFU found!\n\n");
		goto done;
	}
	afu_s = cxl_afu_open_h(afu_h, CXL_VIEW_SLAVE);
	if (!afu_s) {
		perror("cxl_afu_open_h for slave");
		goto done;
	}

	// Set WED to random value
	wed = rand();
	wed <<= 32;
	wed |= rand();
	// Start AFU for slave
	if (cxl_afu_attach(afu_s, wed) < 0) {
            perror("FAILED:cxl_afu_attach for slave");
		goto done;
        }

	// Map AFU MMIO registers
	printf("Mapping AFU slave registers...\n");
	if ((cxl_mmio_map(afu_s, CXL_MMIO_BIG_ENDIAN)) < 0) {
		perror("cxl_mmio_map for slave");
		goto done;
	}
	printf("End AFU slave mmio map\n");

	context = cxl_afu_get_process_element(afu_s);
	printf("Slave context = %d\n", context);

	machine_number = 20;

        // Allocate aligned memory for two cachelines
	if (posix_memalign((void **)&cacheline0, CACHELINE_BYTES, CACHELINE_BYTES) != 0) {
		perror("FAILED:posix_memalign");
		goto done;
	}
	if (posix_memalign((void **)&cacheline1, CACHELINE_BYTES, CACHELINE_BYTES) != 0) {
		perror("FAILED:posix_memalign");
		goto done;
	}

	// Pollute first cacheline with random values
	for (i = 0; i < CACHELINE_BYTES; i++)
		cacheline0[i] = rand();

	// Initialize machine configuration
	//init_machine(&machine);

	// Use AFU Machine 1 to read the first cacheline from memory to AFU
	printf("Start config enable and run machine for slave\n");
	if ((response = config_enable_and_run_machine(afu_s, &machine, machine_number, context, PSL_COMMAND_XLAT_RD_P0, CACHELINE_BYTES, 0, 0, (uint64_t)cacheline0, CACHELINE_BYTES, DIRECTED)) < 0)
	{
		printf("FAILED:config_enable_and_run_machine for slave");
		goto done;
	}
	printf("End config enable and run machine for slave\n");
	// Check for valid response
	if (response != PSL_RESPONSE_DONE)
	{
		printf("FAILED: Unexpected response code 0x%x\n", response);
		goto done;
	}

	printf("Completed cacheline read for slave\n");

	// Use AFU Machine 1 to write the data to the second cacheline
	if ((response = config_enable_and_run_machine(afu_s, &machine, machine_number, context, PSL_COMMAND_XLAT_WR_P0, CACHELINE_BYTES, 0, 0, (uint64_t)cacheline1, CACHELINE_BYTES, DIRECTED)) < 0)
	{
		printf("FAILED:config_enable_and_run_machine for slave");
		goto done;
	}

	// Check for valid response
	if (response != PSL_RESPONSE_DONE)
	{
		printf("FAILED: Unexpected response code 0x%x\n", response);
		goto done;
	}

	// Test if copy from cacheline0 to cacheline1 was successful
	if (memcmp(cacheline0,cacheline1, CACHELINE_BYTES) != 0) {
		printf("FAILED:memcmp\n");
		for (quadrant = 0; quadrant < 4; quadrant++) {
			printf("DEBUG: Expected  Q%d 0x", quadrant);
			for (byte = 0; byte < CACHELINE_BYTES /4; byte++) {
				printf("%02x", cacheline0[byte+(quadrant*32)]);
			}
			printf("\n");
		}
		for (quadrant = 0; quadrant < 4; quadrant++) {
			printf("DEBUG: Actual  Q%d 0x", quadrant);
			for (byte = 0; byte < CACHELINE_BYTES / 4; byte++) {
				printf("%02x", cacheline1[byte+(quadrant*32)]);
			}
			printf("\n");
		}
		goto done;
	}

	printf("Slave AFU: PASSED\n");
        
done:
        // unmap and free slave afu 
        if (afu_s) {
            cxl_mmio_unmap(afu_s);
            cxl_afu_free(afu_s);
        }
        // unmap and free master afu
	if (afu_m) {
		// Unmap AFU MMIO registers
		cxl_mmio_unmap(afu_m);

		// Free AFU
		cxl_afu_free(afu_m);
	}
       
#endif
	return 0;
}