diff --git a/README.md b/README.md index 447cb66..d4acc29 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ options: -cross_parts=2..inf number of crossover points for cross individuals -l-back number for mutation. how many back gates can use this gate -status show complete generations ids and best loss - -profile for profile extesion print data in format {tranzistros}-{output error}-{score}; + -profile for profile extesion print data in format {tranzistros}-{MAE}-{WCE}-{score}; -max_duration=1..inf maximal time duration of optimalization in minutes -representation={aig, gates, mig} reprezenation of circuic for CGP diff --git a/include/about.h b/include/about.h new file mode 100644 index 0000000..8b7d000 --- /dev/null +++ b/include/about.h @@ -0,0 +1,23 @@ +/** + * yosys-cgploss - Create circuics using Genetic (CGP) + * about program header file + * @author Lukas Plevac + */ + +#include + +namespace about { + + const std::string name = "cgploss"; + const unsigned version = 1; + const std::string authors = "Lukas Plevac "; + const std::string build_time = __DATE__ " " __TIME__; + const int optimalization = __OPTIMIZE_SIZE__; + + + /** + * @brief Print help informations using logger function + * @param logger logger for print text to output + */ + void print_help(void (*logger)(const char *, ...)); +} \ No newline at end of file diff --git a/include/convert.cpp b/include/convert.cpp index 51e1aeb..1d3d2b0 100644 --- a/include/convert.cpp +++ b/include/convert.cpp @@ -225,7 +225,7 @@ mapper_t design2genome(Design* design, representation::representation *repres) { for (auto mod : design->selected_modules()) { if (mod->processes.size() > 0) { - log("[WARNING] Skipping module %s because it contains processes.\n", log_id(mod)); + warning_message("Skipping module %s because it contains processes.\n", log_id(mod)); continue; } @@ -247,7 +247,7 @@ mapper_t design2genome(Design* design, representation::representation *repres) { continue; } - log("[INFO] load: deleting output wire %u - %s from chromosome\n", output.first, output.second.wire->name.c_str()); + info_message("load: deleting output wire %u - %s from chromosome\n", output.first, output.second.wire->name.c_str()); to_del.push_back(output.first); } @@ -260,7 +260,7 @@ mapper_t design2genome(Design* design, representation::representation *repres) { for (auto &it : mod->wires_) { RTLIL::Wire *wire = it.second; if (!wire->port_output && !wire->port_input) { //is inner - log("[INFO] load: deleting inner wire %s\n", wire->name.c_str()); + info_message("load: deleting inner wire %s\n", wire->name.c_str()); mod->wires_.erase(wire->name); } @@ -271,7 +271,7 @@ mapper_t design2genome(Design* design, representation::representation *repres) { repres->chromosome->order(mapper.in, mapper.out); - log("[INFO] load: loaded chromosome with %u gens, %lu inputs and %lu outputs\n", repres->chromosome->size(), mapper.in.size(), mapper.out.size()); + info_message("load: loaded chromosome with %u gens, %lu inputs and %lu outputs\n", repres->chromosome->size(), mapper.in.size(), mapper.out.size()); return mapper; diff --git a/include/generation.h b/include/generation.h index e2a1827..6746b08 100644 --- a/include/generation.h +++ b/include/generation.h @@ -22,6 +22,8 @@ namespace evolution { typedef struct { representation::representation* repres; float score; + float mae; + float wce; } individual_t; /** @@ -105,11 +107,11 @@ namespace evolution { /** * @brief Score individual with simulation - * @param individual reprezenation of individual + * @param index index of individual in generation * @param config_parse config praser with port weights - * @return float score + * @post set .mae .wce and .score in individual */ - float score_individual(representation::representation *individual, config::parse *config_parse); + void score_individual(unsigned index, config::parse *config_parse); /** * @brief replicate individual (copy individual to generation) diff --git a/include/genome.h b/include/genome.h index fd9afc1..8ce90c6 100644 --- a/include/genome.h +++ b/include/genome.h @@ -19,6 +19,8 @@ #define DUMMY_GENE_TYPE 0 // if of dummy gene #define MAX_INPUTS 3 // maximal size of inputs array in gene #define IO_ID_T_UNUSED 0xFFFFFFFF // id of unused input +#define TO_REAL_INPUT(IN) (IN - 2) //convert input index in geneme to real index +#define TO_GENOME_INPUT(IN) (IN + 2) //convert real input index to genome input index namespace genome { typedef uint32_t io_id_t; diff --git a/include/simulation.h b/include/simulation.h index 9192ffd..ef60510 100644 --- a/include/simulation.h +++ b/include/simulation.h @@ -22,6 +22,8 @@ #define VARIANTS_BITS_G {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} #define VARIANTS_BITS_H {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} #define VARIANTS_BITS_ALL0 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +#define VARIANTS_BITS_ALL1 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + //macro for set variant to vector by variant index #define SET_VARIANTS_BITS(VEC, X) { \ @@ -61,9 +63,10 @@ namespace simulation { /** * @brief Get number of one bits in vector * @param vec vestor for operatiom + * @param limit number of bits to count (example: first 8bits) * @return unsigned count of bits */ - unsigned bits_count(io_t vec); + unsigned bits_count(io_t vec, unsigned limit); /** * @brief Return maximal error per one variant diff --git a/src/about.cpp b/src/about.cpp new file mode 100644 index 0000000..3bb4d13 --- /dev/null +++ b/src/about.cpp @@ -0,0 +1,45 @@ +/** + * yosys-cgploss - Create circuics using Genetic (CGP) + * about program implementation file + * @author Lukas Plevac + */ + +#include "about.h" + +namespace about { + void print_help(void (*logger)(const char *, ...)) { + logger("%s V%d\n", about::name.c_str(), about::version); + logger("Yosys extension for aproximate circuits using genetic algoritms.\n\n"); + logger("Build %s with O%d\n", about::build_time.c_str(), about::optimalization); + logger("Authors: %s\n\n", about::authors.c_str()); + logger("Using: %s [options]\n", about::name.c_str()); + logger("Options:\n"); + logger("-wire-test test load and save part, do not use CGP only load and save [DEBUG]\n"); + logger("-save_individuals=file create debug file with all individuals [DEBUG]\n"); + logger("-ports_weights=file ports weights file\n"); + logger("-selection_size=size size of selected individuals on end of generation\n"); + logger("-generation_size=size number of individuals in generation\n"); + logger("-max_one_error=0..inf maximal accepted error of circuic (one combination - WCE)\n"); + logger("-max_abs_error=num maximal accepted abs error of circuic (all combinations - MAE)\n"); + logger("-generations=count count of generations\n"); + logger("-mutations_count=count number of mutation for center of normal distribution\n"); + logger("-mutations_count_sigma=num sigma for normal distribution\n"); + logger("-parents=1..2 number of parents for kid\n"); + logger("-power_accuracy_ratio=0..1 float number for loss (1 - power_accuracy_ratio) * abs_error + power_accuracy_ratio * power_loss\n"); + logger("-cross_parts=2..inf number of crossover points for cross individuals\n"); + logger("-l-back=num number for mutation. how many back gates can use this gate \n"); + logger("-status show complete generations ids and best loss\n"); + logger("-profile for profile extesion print data in format {tranzistros}-{MAE}-{WCE}-{score};\n"); + logger("-max_duration=1..inf maximal time duration of optimalization in minutes\n"); + logger("-representation={aig, gates, mig} reprezenation of circuic for CGP\n\n"); + logger("Example ports weights file:\n"); + logger("# example comment\n"); + logger("# Generic weights\n"); + logger("\\sum: msb-first\n"); + logger("\\spi_data: lsb-first\n\n"); + logger("# Custom multi-bits port LSB [3], ..., MSB [0]\n"); + logger("\\sum2: 1, 2, 4, 8\n\n"); + logger("# Custom one-bits port\n"); + logger("\\sum3 : 100\n\n"); + } +} \ No newline at end of file diff --git a/src/generation.cpp b/src/generation.cpp index 48152a4..4920896 100644 --- a/src/generation.cpp +++ b/src/generation.cpp @@ -77,66 +77,85 @@ namespace evolution { return (a.score < b.score); } - float generation::score_individual(representation::representation *individual, config::parse *config_parse) { + void generation::score_individual(unsigned index, config::parse *config_parse) { - std::vector xor_outputs(individual->chromosome->wire_out.size()); - std::vector test_circuic(individual->chromosome->size()); - std::vector reference_circuic(this->reference->chromosome->size()); - std::vector variant_counter(individual->chromosome->last_input + 2); + this->individuals[index].mae = 0; + this->individuals[index].wce = 0; + unsigned variants_count = 1 << TO_REAL_INPUT(this->individuals[index].repres->chromosome->last_input + 1); - for (unsigned i = 0; i <= individual->chromosome->last_input; i++) { - SET_VARIANTS_BITS(test_circuic[i].vec, i); - SET_VARIANTS_BITS(reference_circuic[i].vec, i); + std::vector xor_outputs(this->individuals[index].repres->chromosome->wire_out.size()); + std::vector test_circuic(this->individuals[index].repres->chromosome->size()); + std::vector reference_circuic(this->reference->chromosome->size()); + std::vector variant_counter(this->individuals[index].repres->chromosome->last_input + 2); + + // set const inputs + SET_VECTOR_TO(test_circuic[0].vec, VARIANTS_BITS_ALL0); + SET_VECTOR_TO(test_circuic[1].vec, VARIANTS_BITS_ALL1); + SET_VECTOR_TO(reference_circuic[0].vec, VARIANTS_BITS_ALL0); + SET_VECTOR_TO(reference_circuic[1].vec, VARIANTS_BITS_ALL1); + + // set varaible inputs + for (unsigned i = TO_GENOME_INPUT(0); i <= this->individuals[index].repres->chromosome->last_input; i++) { + SET_VARIANTS_BITS(test_circuic[i].vec, TO_REAL_INPUT(i)); + SET_VARIANTS_BITS(reference_circuic[i].vec, TO_REAL_INPUT(i)); } unsigned total_error = 0; bool done = false; - if (ONE_SIM_VARIANTS > individual->chromosome->last_input) { + if (ONE_SIM_VARIANTS > TO_REAL_INPUT(this->individuals[index].repres->chromosome->last_input + 1)) { done = true; } do { - individual->simulate(test_circuic); + this->individuals[index].repres->simulate(test_circuic); this->reference->simulate(reference_circuic); + //Calc error using xor unsigned i = 0; - for (auto output: individual->chromosome->wire_out) { + for (auto output: this->individuals[index].repres->chromosome->wire_out) { xor_outputs[i].vec = test_circuic[output.first].vec ^ reference_circuic[this->reference_inverse_wire_out[output.second]].vec; - total_error += simulation::bits_count(xor_outputs[i]) * config_parse->port_weight(output.second); + total_error += simulation::bits_count(xor_outputs[i], variants_count) * config_parse->port_weight(output.second); i++; } - if (simulation::one_max_loss(xor_outputs, individual->chromosome->wire_out, config_parse) > this->max_one_loss) { - return INFINITY; + //WCE + auto current_wce = simulation::one_max_loss(xor_outputs, this->individuals[index].repres->chromosome->wire_out, config_parse); + if (this->individuals[index].wce < current_wce) { + this->individuals[index].wce = current_wce; + + if (current_wce > this->max_one_loss) { + this->individuals[index].score = INFINITY; + return; + } } - for (unsigned i = ONE_SIM_VARIANTS; i <= individual->chromosome->last_input; i++) { + //Update inputs for next simulation + for (unsigned i = ONE_SIM_VARIANTS; i <= TO_REAL_INPUT(this->individuals[index].repres->chromosome->last_input); i++) { variant_counter[i] = (variant_counter[i] + 1) % (1 << (i - ONE_SIM_VARIANTS)); if (variant_counter[i] == 0) { - test_circuic[i].vec = ~test_circuic[i].vec; - reference_circuic[i].vec = ~reference_circuic[i].vec; + test_circuic[TO_GENOME_INPUT(i)].vec = ~test_circuic[TO_GENOME_INPUT(i)].vec; + reference_circuic[TO_GENOME_INPUT(i)].vec = ~reference_circuic[TO_GENOME_INPUT(i)].vec; - if (i == individual->chromosome->last_input) { - if (variant_counter[individual->chromosome->last_input + 1]) { + if (TO_GENOME_INPUT(i) == this->individuals[index].repres->chromosome->last_input) { + if (variant_counter[TO_REAL_INPUT(this->individuals[index].repres->chromosome->last_input + 1)]) { done = true; } - variant_counter[individual->chromosome->last_input + 1]++; + variant_counter[TO_REAL_INPUT(this->individuals[index].repres->chromosome->last_input + 1)]++; } } } } while (!done); - unsigned variants_count = 1 << (individual->chromosome->last_input + 1); - float abs_error = (float) total_error / variants_count; + this->individuals[index].mae = (float) total_error / variants_count; - if (abs_error > this->max_abs_loss) { - return INFINITY; + if (this->individuals[index].mae > this->max_abs_loss) { + this->individuals[index].score = INFINITY; + } else { + this->individuals[index].score = (1 - this->power_accuracy_ratio) * this->individuals[index].mae + this->power_accuracy_ratio * this->individuals[index].repres->power_loss(); } - - return (1 - this->power_accuracy_ratio) * abs_error + this->power_accuracy_ratio * individual->power_loss(); } void generation::selection(unsigned count, config::parse *config_parse) { @@ -148,7 +167,7 @@ namespace evolution { continue; } - this->individuals[i].score = this->score_individual(this->individuals[i].repres, config_parse); + this->score_individual(i, config_parse); } std::sort(this->individuals.begin(), this->individuals.end(), generation::sort_individual_score_asc); @@ -161,7 +180,7 @@ namespace evolution { } unsigned generation::add_individual(representation::representation *individual) { - this->individuals.push_back({individual, 0}); + this->individuals.push_back({individual, 0, 0, 0}); return this->individuals.size() - 1; } diff --git a/src/main.cpp b/src/main.cpp index 96434d4..3256754 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,7 @@ #include "generation.h" #include "config-parse.h" +//Base libs #include #include #include @@ -21,6 +22,7 @@ #include #include #include + //timer #include @@ -29,46 +31,72 @@ #include "gates.h" #include "mig.h" +//about +#include "about.h" + +//Debug macros #define debug_indiv_to_file(debug_indiv_file, repres) if (debug_indiv) {repres->save(debug_indiv_file); } #define debug_generation_to_file(debug_indiv_file, generation, name) if (debug_indiv) {debug_indiv_file << name; for (unsigned i = 0; i < generation->individuals.size(); i++) { debug_indiv_to_file(debug_indiv_file, generation->individuals[i].repres) } } +//messages macros +#define info_message(...) if (param_status) { log("[INFO] " __VA_ARGS__); } +#define warning_message(...) log("[WARNING] " __VA_ARGS__) +#define error_message(...) log("[ERROR] " __VA_ARGS__) USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +/* Params parsing */ +bool wire_test; +bool debug_indiv; +bool param_profile; +unsigned param_selection_count; +unsigned param_generation_size; +unsigned param_max_one_loss; +float param_power_accuracy_ratio; +float param_max_abs_loss; +unsigned param_mutate_center; +unsigned param_mutate_sigma; +unsigned param_generations_count; +unsigned param_parrents_count; +unsigned param_cross_parts; +unsigned param_l_back; +bool param_status; +unsigned param_max_duration; +std::string config_file; +std::string param_repres; + +//include convert functions #include "convert.cpp" struct cgploss : public Pass { cgploss() : Pass("cgploss") {} void help() override { - log("\n"); - log(" cgploss [options]\n"); - log("\n"); + about::print_help(log); } void execute(vector params, Design* design) override { - log("CGP EXTENSION\n"); - - /* Params parsing */ - bool wire_test = false; - bool debug_indiv = false; - bool param_profile = false; - unsigned param_selection_count = 50; - unsigned param_generation_size = 500; - unsigned param_max_one_loss = 0; - float param_power_accuracy_ratio = 0.5; - float param_max_abs_loss = 0; - unsigned param_mutate_center = 2; - unsigned param_mutate_sigma = 2; - unsigned param_generations_count = 100; - unsigned param_parrents_count = 1; - unsigned param_cross_parts = 4; - unsigned param_l_back = 0; - bool param_status = false; - unsigned param_max_duration = 0; - std::string config_file = ""; - std::string param_repres = "aig"; + log("\nStarting cgploss extension. If you need more runtime information use -status\n\n"); + + wire_test = false; + debug_indiv = false; + param_profile = false; + param_selection_count = 50; + param_generation_size = 500; + param_max_one_loss = 0; + param_power_accuracy_ratio = 0.5; + param_max_abs_loss = 0; + param_mutate_center = 2; + param_mutate_sigma = 2; + param_generations_count = 100; + param_parrents_count = 1; + param_cross_parts = 4; + param_l_back = 0; + param_status = false; + param_max_duration = 0; + std::string config_file = ""; + std::string param_repres = "aig"; for (auto param : params) { @@ -86,13 +114,13 @@ struct cgploss : public Pass { auto parsed = param.substr(std::string("-selection_size=").length()); if (!config::parse::is_number(parsed)) { - log("[ERROR] Bad value for -selection_size using default\n"); + error_message("Bad value for -selection_size using default\n"); } else { param_selection_count = stoi(parsed); } if (param_selection_count < 1) { - log("[ERROR] Bad value for -selection_size, min value is 1. using 1\n"); + error_message("Bad value for -selection_size, min value is 1. using 1\n"); param_selection_count = 1; } @@ -100,7 +128,7 @@ struct cgploss : public Pass { auto parsed = param.substr(std::string("-max_duration=").length()); if (!config::parse::is_number(parsed)) { - log("[ERROR] Bad value for -max_duration using default\n"); + error_message("Bad value for -max_duration using default\n"); } else { param_max_duration = stoi(parsed); } @@ -109,13 +137,13 @@ struct cgploss : public Pass { auto parsed = param.substr(std::string("-generation_size=").length()); if (!config::parse::is_number(parsed)) { - log("[ERROR] Bad value for -generation_size using default\n"); + error_message("Bad value for -generation_size using default\n"); } else { param_generation_size = stoi(parsed); } if (param_generation_size < 2) { - log("[ERROR] Bad value for -generation_size, min value is 2. using 2\n"); + error_message("Bad value for -generation_size, min value is 2. using 2\n"); param_generation_size = 2; } @@ -123,7 +151,7 @@ struct cgploss : public Pass { auto parsed = param.substr(std::string("-max_one_error=").length()); if (!config::parse::is_number(parsed)) { - log("[ERROR] Bad value for -max_one_error using default\n"); + error_message("Bad value for -max_one_error using default\n"); } else { param_max_one_loss = stoi(parsed); } @@ -132,7 +160,7 @@ struct cgploss : public Pass { auto parsed = param.substr(std::string("-generations=").length()); if (!config::parse::is_number(parsed)) { - log("[ERROR] Bad value for -generations using default\n"); + error_message("Bad value for -generations using default\n"); } else { param_generations_count = stoi(parsed); } @@ -141,7 +169,7 @@ struct cgploss : public Pass { auto parsed = param.substr(std::string("-mutations_count=").length()); if (!config::parse::is_number(parsed)) { - log("[ERROR] Bad value for -mutations_count using default\n"); + error_message("Bad value for -mutations_count using default\n"); } else { param_mutate_center = stoi(parsed); } @@ -150,7 +178,7 @@ struct cgploss : public Pass { auto parsed = param.substr(std::string("-mutations_count_sigma=").length()); if (!config::parse::is_number(parsed)) { - log("[ERROR] Bad value for -mutations_count_sigma using default\n"); + error_message("Bad value for -mutations_count_sigma using default\n"); } else { param_mutate_sigma = stoi(parsed); } @@ -159,16 +187,16 @@ struct cgploss : public Pass { auto parsed = param.substr(std::string("-parents=").length()); if (!config::parse::is_number(parsed)) { - log("[ERROR] Bad value for -parents using default\n"); + error_message("Bad value for -parents using default\n"); } else { param_parrents_count = stoi(parsed); } if (param_parrents_count > 2) { - log("[ERROR] Bad value for -parents, max value is 2, min value is 1. using 2\n"); + error_message("Bad value for -parents, max value is 2, min value is 1. using 2\n"); param_parrents_count = 2; } else if (param_parrents_count < 1) { - log("[ERROR] Bad value for -parents, max value is 2, min value is 1. using 1\n"); + error_message("Bad value for -parents, max value is 2, min value is 1. using 1\n"); param_parrents_count = 1; } @@ -178,7 +206,7 @@ struct cgploss : public Pass { try { param_power_accuracy_ratio = std::stof(parsed); } catch (std::invalid_argument const& ex) { - log("[ERROR] Bad value for -power_accuracy_ratio using default\n"); + error_message("Bad value for -power_accuracy_ratio using default\n"); } } else if (param.rfind("-max_abs_error=", 0) == 0) { @@ -187,7 +215,7 @@ struct cgploss : public Pass { try { param_max_abs_loss = std::stof(parsed); } catch (std::invalid_argument const& ex) { - log("[ERROR] Bad value for -max_abs_error using default\n"); + error_message("Bad value for -max_abs_error using default\n"); } } else if (param.rfind("-representation=", 0) == 0) { @@ -196,20 +224,20 @@ struct cgploss : public Pass { if (parsed == "gates" || parsed == "mig" || parsed == "aig") { param_repres = parsed; } else { - log("[ERROR] Bad value for -representation using default\n"); + error_message("Bad value for -representation using default\n"); } } else if (param.rfind("-cross_parts=", 0) == 0) { auto parsed = param.substr(std::string("-cross_parts=").length()); if (!config::parse::is_number(parsed)) { - log("[ERROR] Bad value for -cross_parts using default\n"); + error_message("Bad value for -cross_parts using default\n"); } else { param_parrents_count = stoi(parsed); } if (param_parrents_count < 2) { - log("[ERROR] Bad value for -cross_parts, min value is 2. using 2\n"); + error_message("Bad value for -cross_parts, min value is 2. using 2\n"); param_parrents_count = 2; } @@ -217,14 +245,14 @@ struct cgploss : public Pass { auto parsed = param.substr(std::string("-l-back=").length()); if (!config::parse::is_number(parsed)) { - log("[ERROR] Bad value for -l-back using default\n"); + error_message("Bad value for -l-back using default\n"); } else { param_l_back = stoi(parsed); } } else { if (param != "cgploss") { - log("[WARNING] ignorig argument %s\n", param.c_str()); + warning_message("ignorig argument %s\n", param.c_str()); } } @@ -248,38 +276,38 @@ struct cgploss : public Pass { auto error = config->parse_file(config_file_stream, map.out); if (error) { - log("[ERROR] config file parse error on line %d - in failsafe mode using default weights\n", error); + error_message("config file parse error on line %d - in failsafe mode using default weights\n", error); } config_file_stream.close(); } if (param_parrents_count == 2 && param_selection_count < 2) { - log("[ERROR] minimal selection_count for two parents is 2. setting to 2\n"); + error_message("minimal selection_count for two parents is 2. setting to 2\n"); param_selection_count = 2; } if (param_selection_count > param_generation_size) { - log("[ERROR] generation cant be bigger that selection count. setting to selection count\n"); + error_message("generation cant be bigger that selection count. setting to selection count\n"); param_generation_size = param_selection_count; } - log("[INFO] Starting CPG with parameters:\n"); - log(" wire_test : %d\n", wire_test); - log(" save_individuals : %d\n", debug_indiv); - log(" ports_weights : %s\n", config_file.c_str()); - log(" selection_size : %d\n", param_selection_count); - log(" generation_size : %d\n", param_generation_size); - log(" max_one_error : %d\n", param_max_one_loss); - log(" max_abs_error : %f\n", param_max_abs_loss); - log(" generations : %d\n", param_generations_count); - log(" mutations_count : %d\n", param_mutate_center); - log(" mutations_sigma : %d\n", param_mutate_sigma); - log(" parents : %d\n", param_parrents_count); - log(" cross_parts : %d\n", param_cross_parts); - log(" power_accuracy_ratio: %f\n", param_power_accuracy_ratio); - log(" representation : %s\n", param_repres.c_str()); - log(" l-back : %d\n\n", param_l_back); + info_message("Starting CPG with parameters:\n"); + info_message(" wire_test : %d\n", wire_test); + info_message(" save_individuals : %d\n", debug_indiv); + info_message(" ports_weights : %s\n", config_file.c_str()); + info_message(" selection_size : %d\n", param_selection_count); + info_message(" generation_size : %d\n", param_generation_size); + info_message(" max_one_error : %d\n", param_max_one_loss); + info_message(" max_abs_error : %f\n", param_max_abs_loss); + info_message(" generations : %d\n", param_generations_count); + info_message(" mutations_count : %d\n", param_mutate_center); + info_message(" mutations_sigma : %d\n", param_mutate_sigma); + info_message(" parents : %d\n", param_parrents_count); + info_message(" cross_parts : %d\n", param_cross_parts); + info_message(" power_accuracy_ratio: %f\n", param_power_accuracy_ratio); + info_message(" representation : %s\n", param_repres.c_str()); + info_message(" l-back : %d\n\n", param_l_back); if (!wire_test) { std::ofstream debug_indiv_file; @@ -331,11 +359,11 @@ struct cgploss : public Pass { //score generation->selection(param_selection_count, config); - if (param_status) { - log("[INFO] generation %i best individual score %f\n", generation_id, generation->individuals[0].score); - } else if (param_profile) { + info_message("generation %i best individual score %f\n", generation_id, generation->individuals[0].score); + + if (param_profile) { auto p_loss = generation->individuals[0].repres->power_loss(); - log("%i-%f-%f;", p_loss, generation->individuals[0].score - (p_loss * param_power_accuracy_ratio), generation->individuals[0].score); + log("%i-%f-%f-%f;", p_loss, generation->individuals[0].mae, generation->individuals[0].wce, generation->individuals[0].score); } if (param_max_duration > 0) { @@ -343,10 +371,7 @@ struct cgploss : public Pass { auto act_duration = std::chrono::duration_cast(timer_stop - timer_start); if (act_duration.count() >= param_max_duration) { - if (param_status) { - log("[INFO] maximal duration reached\n"); - } - + info_message("maximal duration reached\n") break; } } @@ -362,12 +387,14 @@ struct cgploss : public Pass { debug_indiv_file.close(); } + log("\nAproximation done. Used %d transitors. MAE is %0.2f and WCE is %0.2f.", generation->individuals[0].repres->power_loss(), generation->individuals[0].mae, generation->individuals[0].wce); + delete generation; } genome2design(repres, design); } catch( const std::invalid_argument& e ) { - log("error while loading circuic. Do you run techmap befere? The circuit may be now damaged. Error: %s", e.what()); + error_message("Error while loading circuic. Do you run techmap befere? The circuit may be now damaged. Error: %s", e.what()); } } diff --git a/src/simulation.cpp b/src/simulation.cpp index 4f1906b..d4ced12 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -8,11 +8,16 @@ #include "simulation.h" namespace simulation { - unsigned bits_count(io_t vec) { + unsigned bits_count(io_t vec, unsigned limit) { unsigned count = 0; for (unsigned i = 0; i < SIM_BYTES_COUNT; i++) { for (unsigned j = 0; j < 8; j++) { + + if (i * 8 + j >= limit) { + return count; + } + count += vec.byte[i] & 1; vec.byte[i] = vec.byte[i] >> 1; } diff --git a/tests/config-parser-unit/test.cpp b/tests/config-parser-unit/test.cpp index 4838e8c..6c6869f 100644 --- a/tests/config-parser-unit/test.cpp +++ b/tests/config-parser-unit/test.cpp @@ -25,6 +25,11 @@ #include "config-parse.h" +//messages macros +#define info_message(...) log("[INFO] " __VA_ARGS__) +#define warning_message(...) log("[WARNING] " __VA_ARGS__) +#define error_message(...) log("[ERROR] " __VA_ARGS__) + USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN