aad-assignment-1/aad_coin_miner_dna_shape_cu...

180 lines
5.1 KiB
C

//
// Arquiteturas de Alto Desempenho 2025/2026
//
// DETI Coin Miner - DNA Helix Generator
//
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "aad_data_types.h"
#include "aad_sha1_cpu.h"
#include "aad_cuda_utilities.h"
#include "aad_vault.h"
#define PI 3.14159265
#define COINS_STORAGE_SIZE 1024u
static volatile int keep_running = 1;
void signal_handler(int signum) {
(void)signum;
keep_running = 0;
}
//
// Visual Generator: Creates one line of the DNA Helix
//
void generate_dna_row(int row_idx, u32_t *template_buffer) {
char line_str[64];
memset(line_str, 0, 64);
// 1. Standard Header (12 bytes)
memcpy(line_str, "DETI coin 2 ", 12);
// 2. The Visual Area (Bytes 12 to 47 -> 36 chars wide)
// We draw two sine waves.
// Center is roughly at relative index 18.
int width = 36;
int center = width / 2;
double amplitude = 14.0;
double frequency = 0.3;
// Fill background with space
for(int i=12; i < 48; i++) line_str[i] = ' ';
// Calculate positions
int pos1 = center + (int)(amplitude * sin(row_idx * frequency));
int pos2 = center + (int)(amplitude * sin(row_idx * frequency + PI)); // 180 deg out of phase
// Draw the helix strands
// Valid visual range is index 12 to 47
if(pos1 >= 0 && pos1 < width) line_str[12 + pos1] = '(';
if(pos2 >= 0 && pos2 < width) line_str[12 + pos2] = ')';
// Draw the "rungs" connecting the DNA strands
int left = (pos1 < pos2) ? pos1 : pos2;
int right = (pos1 < pos2) ? pos2 : pos1;
// Add some "biology" chars in the middle
if (row_idx % 2 == 0) {
int mid = 12 + (left + right) / 2;
line_str[mid] = (row_idx % 4 == 0) ? '-' : '+';
}
// 3. The Mining Area (Bytes 48-53)
// Initialize with placeholders (GPU will overwrite these)
for(int i=48; i<54; i++) line_str[i] = '.';
// 4. Mandatory Suffix
line_str[54] = '\n';
line_str[55] = (char)0x80; // Padding
// 5. Convert char buffer to u32 array (Endian safe copy)
// We copy 14 words (56 bytes)
for(int i=0; i<14; i++) {
u08_t *ptr = (u08_t*)&template_buffer[i];
ptr[3] = line_str[i*4 + 0];
ptr[2] = line_str[i*4 + 1];
ptr[1] = line_str[i*4 + 2];
ptr[0] = line_str[i*4 + 3];
}
}
int main(int argc, char *argv[])
{
cuda_data_t cd;
u32_t *host_storage;
u32_t *host_template;
u64_t base_nonce = 0;
int current_row = 0;
signal(SIGINT, signal_handler);
// Initialize CUDA
memset(&cd, 0, sizeof(cd));
cd.device_number = 0;
cd.cubin_file_name = "coin_miner_cuda_kernel.cubin";
cd.kernel_name = "mine_visual_row_kernel"; // Note the new kernel name
// Allocations
cd.data_size[0] = COINS_STORAGE_SIZE * sizeof(u32_t); // Storage for found coins
cd.data_size[1] = 16 * sizeof(u32_t); // Storage for the Row Template
initialize_cuda(&cd);
host_storage = (u32_t *)cd.host_data[0];
host_template = (u32_t *)cd.host_data[1];
// Configure Kernel
cd.block_dim_x = RECOMMENDED_CUDA_BLOCK_SIZE;
cd.grid_dim_x = 128; // Smaller grid is fine since we stop as soon as we find ONE coin
printf("Generating DNA Helix Blockchain...\n");
printf("Press Ctrl+C to stop.\n\n");
cd.n_kernel_arguments = 3;
cd.arg[0] = &cd.device_data[0]; // Storage
cd.arg[1] = &cd.device_data[1]; // Template
cd.arg[2] = &base_nonce; // Nonce
while(keep_running)
{
// 1. Generate the visual template for this specific row
generate_dna_row(current_row, host_template);
// 2. Reset storage counter
host_storage[0] = 1u;
// 3. Copy Template and Reset Counter to GPU
// We copy both buffers (idx 0 and 1)
host_to_device_copy(&cd, 0);
host_to_device_copy(&cd, 1);
int coin_found = 0;
// 4. Loop until we find a coin for THIS row
while(!coin_found && keep_running) {
cd.arg[2] = &base_nonce; // Update nonce pointer arg
launch_kernel(&cd);
// Check if we found something
device_to_host_copy(&cd, 0);
u32_t count = host_storage[0];
if(count > 1) {
// Coin found!
u32_t coin[14];
// Extract the first found coin
for(int i=0; i<14; i++) coin[i] = host_storage[1+i];
save_coin(coin); // Save to disk
// Visual Feedback to Console (Reconstruct char string for display)
char debug_str[56];
for(int i=0; i<14; i++) {
u32_t w = coin[i];
debug_str[i*4+0] = (w >> 24) & 0xFF;
debug_str[i*4+1] = (w >> 16) & 0xFF;
debug_str[i*4+2] = (w >> 8) & 0xFF;
debug_str[i*4+3] = w & 0xFF;
}
// Only print the visual part (hide the ugly mining bits at the end)
printf("%.54s\n", debug_str);
coin_found = 1;
current_row++; // Advance to next visual row
}
base_nonce += (cd.grid_dim_x * cd.block_dim_x);
}
}
save_coin(NULL);
terminate_cuda(&cd);
return 0;
}