Program Listing for File interpreter.cu#
↰ Return to documentation for file (src/interpreter.cu
)
#include "utils.h"
#include "evm.cuh"
#include <getopt.h>
template<class params>
void run_interpreter(char *read_json_filename, char *write_json_filename) {
typedef evm_t<params> evm_t;
typedef typename evm_t::evm_instances_t evm_instances_t;
typedef arith_env_t<params> arith_t;
evm_instances_t cpu_instances;
#ifndef ONLY_CPU
evm_instances_t tmp_gpu_instances, *gpu_instances;
cgbn_error_report_t *report;
CUDA_CHECK(cudaDeviceReset());
#endif
arith_t arith(cgbn_report_monitor, 0);
//read the json file with the global state
cJSON *read_root = get_json_from_file(read_json_filename);
if(read_root == NULL) {
printf("Error: could not read the json file\n");
exit(EXIT_FAILURE);
}
cJSON *write_root = cJSON_CreateObject();
const cJSON *test = NULL;
cJSON_ArrayForEach(test, read_root) {
// get instaces to run
printf("Generating instances\n");
evm_t::get_cpu_instances(cpu_instances, test);
#ifndef ONLY_CPU
evm_t::get_gpu_instances(tmp_gpu_instances, cpu_instances);
CUDA_CHECK(cudaMalloc(&gpu_instances, sizeof(evm_instances_t)));
CUDA_CHECK(cudaMemcpy(gpu_instances, &tmp_gpu_instances, sizeof(evm_instances_t), cudaMemcpyHostToDevice));
#endif
printf("Instances generated\n");
// create a cgbn_error_report for CGBN to report back errors
#ifndef ONLY_CPU
CUDA_CHECK(cgbn_error_report_alloc(&report));
size_t heap_size;
cudaDeviceGetLimit(&heap_size, cudaLimitMallocHeapSize);
heap_size = 4;
heap_size = heap_size*1024*1024*1024;
CUDA_CHECK(cudaDeviceSetLimit(cudaLimitMallocHeapSize, heap_size));
CUDA_CHECK(cudaDeviceSetLimit(cudaLimitStackSize, 256*1024));
printf("Heap size: %zu\n", heap_size);
cudaDeviceGetLimit(&heap_size, cudaLimitMallocHeapSize);
printf("Heap size: %zu\n", heap_size);
#endif
#ifndef ONLY_CPU
printf("Running GPU kernel ...\n");
CUDA_CHECK(cudaDeviceSynchronize());
kernel_evm<params><<<cpu_instances.count, params::TPI>>>(report, gpu_instances);
//CUDA_CHECK(cudaPeekAtLastError());
// error report uses managed memory, so we sync the device (or stream) and check for cgbn errors
CUDA_CHECK(cudaDeviceSynchronize());
printf("GPU kernel finished\n");
CGBN_CHECK(report);
// copy the results back to the CPU
printf("Copying results back to CPU\n");
CUDA_CHECK(cudaMemcpy(&tmp_gpu_instances, gpu_instances, sizeof(evm_instances_t), cudaMemcpyDeviceToHost));
evm_t::get_cpu_instances_from_gpu_instances(cpu_instances, tmp_gpu_instances);
printf("Results copied\n");
#else
printf("Running CPU EVM\n");
// run the evm
evm_t *evm = NULL;
uint32_t tmp_error;
for(uint32_t instance = 0; instance < cpu_instances.count; instance++) {
printf("Running instance %d\n", instance);
evm = new evm_t(
arith,
cpu_instances.world_state_data,
cpu_instances.block_data,
cpu_instances.sha3_parameters,
&(cpu_instances.transactions_data[instance]),
&(cpu_instances.accessed_states_data[instance]),
&(cpu_instances.touch_states_data[instance]),
&(cpu_instances.logs_data[instance]),
#ifdef TRACER
&(cpu_instances.tracers_data[instance]),
#endif
instance,
&(cpu_instances.errors[instance]));
evm->run(tmp_error);
delete evm;
evm = NULL;
}
printf("CPU EVM finished\n");
#endif
// print the results
printf("Printing the results ...\n");
evm_t::print_evm_instances_t(arith, cpu_instances);
printf("Results printed\n");
// print to json files
printf("Printing to json files ...\n");
cJSON_AddItemToObject(
write_root,
test->string,
evm_t::json_from_evm_instances_t(arith, cpu_instances));
printf("Json files printed\n");
// free the memory
printf("Freeing the memory ...\n");
evm_t::free_instances(cpu_instances);
#ifndef ONLY_CPU
CUDA_CHECK(cudaFree(gpu_instances));
CUDA_CHECK(cgbn_error_report_free(report));
CUDA_CHECK(cudaDeviceReset());
#endif
}
cJSON_Delete(read_root);
char *json_str=cJSON_Print(write_root);
FILE *fp=fopen(write_json_filename, "w");
fprintf(fp, "%s", json_str);
fclose(fp);
free(json_str);
cJSON_Delete(write_root);
}
int main(int argc, char *argv[]) {//getting the input
char *read_json_filename = NULL;
char *write_json_filename = NULL;
static struct option long_options[] = {
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{0, 0, 0, 0}};
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, "i:o:", long_options, &option_index)) != -1)
{
switch (opt)
{
case 'i':
read_json_filename = optarg;
break;
case 'o':
write_json_filename = optarg;
break;
default:
fprintf(stderr, "Usage: %s --input <json_filename> --output <json_filename>\n", argv[0]);
exit(EXIT_FAILURE);
}
}
if (!read_json_filename || !write_json_filename)
{
fprintf(stderr, "Both --input and --output flags are required\n");
exit(EXIT_FAILURE);
}
run_interpreter<utils_params>(read_json_filename, write_json_filename);
}