diff options
| author | ducky | 2015-09-23 18:12:13 -0700 |
|---|---|---|
| committer | ducky | 2015-09-23 18:12:13 -0700 |
| commit | a1fdffe5ad740e1a6b496456c9011507e0d61874 (patch) | |
| tree | 1ead405192aaef21ec4fd3845372f837473750b8 /src/main/resources | |
| parent | 0a022b53f5bf40b0c2b1fbcf1fbc8eaabd3cd7c5 (diff) | |
Remove unused files
Diffstat (limited to 'src/main/resources')
| -rw-r--r-- | src/main/resources/emulator.h | 3 | ||||
| -rw-r--r-- | src/main/resources/emulator_api.h | 684 | ||||
| -rw-r--r-- | src/main/resources/emulator_mod.h | 1800 | ||||
| -rw-r--r-- | src/main/resources/sim_api.h | 156 |
4 files changed, 0 insertions, 2643 deletions
diff --git a/src/main/resources/emulator.h b/src/main/resources/emulator.h deleted file mode 100644 index 1286f432..00000000 --- a/src/main/resources/emulator.h +++ /dev/null @@ -1,3 +0,0 @@ -// metaheader for the Chisel emulator and API -#include "emulator_mod.h" -#include "emulator_api.h" diff --git a/src/main/resources/emulator_api.h b/src/main/resources/emulator_api.h deleted file mode 100644 index 38b50963..00000000 --- a/src/main/resources/emulator_api.h +++ /dev/null @@ -1,684 +0,0 @@ -// Header for Chisel emulator API -#ifndef __IS_EMULATOR_API__ -#define __IS_EMULATOR_API__ - -#include "emulator_mod.h" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wsign-compare" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wunused-variable" - -#include <string> -#include <sstream> -#include <map> -#include <cassert> -#include <cerrno> - -/** - * Converts an integer to a std::string without needing additional libraries - * or C++11. - */ -static std::string itos(int in) { - std::stringstream out; - out << in; - return out.str(); -} - -/** - * Copy one val_t array to another. - * nb must be the exact number of bits the val_t represents. - */ -static __attribute__((unused)) void val_cpy(val_t* dst, val_t* src, int nb) { - for (int i=0; i<val_n_words(nb); i++) { - dst[i] = src[i]; - } -} - -/** - * Empty a val_t array (sets to zero). - * nb must be the exact number of bits the val_t represents. - */ -static void val_empty(val_t* dst, int nb) { - for (int i=0; i<val_n_words(nb); i++) { - dst[i] = 0; - } -} - -/** - * Set a val_t array to a integer number. Obviously, the maximum integer - * is capped by the width of a single val_t element. - * nb must be the exact number of bits the val_t represents. - */ -static __attribute__((unused)) void val_set(val_t* dst, val_t nb, val_t num) { - val_empty(dst, nb); - dst[0] = num; -} - -/** - * Sets a dat_t from a string, where the input radix is automatically determined - * from the string (or defaults to 10). - * Returns true on success. - */ -template <int w> -bool dat_from_str(std::string in, dat_t<w>& res, int pos = 0) { - int radix = 10; - int negate = 0; - - /* Handle leading minus sign. */ - if (!in.substr(pos, 1).compare("-")) { - pos++; - negate = 1; - } - - if (!in.substr(pos, 1).compare("d")) { - radix = 10; - pos++; - } else if (!in.substr(pos, 1).compare("h") - || !in.substr(pos, 1).compare("x")) { - radix = 16; - pos++; - } else if (!in.substr(pos, 2).compare("0h") - || !in.substr(pos, 2).compare("0x")) { - radix = 16; - pos += 2; - } else if (!in.substr(pos, 1).compare("b")) { - radix = 2; - pos++; - } else if (!in.substr(pos, 2).compare("0b")) { - radix = 2; - pos += 2; - } - - const int log_max_radix = 4; - assert(radix <= (1 << log_max_radix)); - - dat_t<w> curr_base = 1; - res = 0; - - for (int rpos=in.length()-1; rpos>=pos; rpos--) { - char c = in[rpos]; - val_t c_val = 0; - if (c == '_') { - continue; - } - if (c >= '0' && c <= '9') { - c_val = c - '0'; - } else if (c >= 'a' && c <= 'z') { - c_val = c - 'a' + 10; - } else if (c >= 'A' && c <= 'Z') { - c_val = c - 'A' + 10; - } else { - std::cerr << "dat_from_str: Invalid character '" << c << "' in '" << in << "'" << std::endl; - return false; - } - if (c_val > radix /* || c_val < 0 */) { - std::cerr << "dat_from_str: Invalid character '" << c << "'" << - std::endl; - return false; - } - - dat_t<w> temp_prod = curr_base * dat_t<log_max_radix>(c_val); - res = res + temp_prod; - curr_base = curr_base * dat_t<log_max_radix+1>(radix); - } - if (negate) { - res = -res; - } - return true; -} - -// API base class, providing common functions -class api_base { -public: - api_base(const char* new_name, const char* new_path) : - name(new_name), - path(new_path) - {} - // returns the fully qualified name of this object (path + dot + name) - std::string get_pathname() { - if (*path == '\0') { - return name; - } else { - return get_path() + "." + name; - } - } - // returns the short name of this object - std::string get_name() { - return name; - } - // returns the path of this object (without a trailing dot) - std::string get_path() { - return path; - } -protected: - const char* name; - const char* path; -}; - -// API base (non width templated) class for API accessors to dat_t -class dat_api_base : public api_base { -public: - dat_api_base(const char* new_name, const char* new_path) : - api_base(new_name, new_path) - {} - // returns the value of this wire as a string, or empty string on failure - virtual std::string get_value() = 0; - // sets the value of this wire from a string, returning true on success - virtual bool set_value(std::string value) = 0; - // returns the bitwidth of this wire - virtual std::string get_width() = 0; -}; - -// dat_api dummy class, does nothing except for return errors -// to be used when a real dat_api object can't be found -class dat_dummy : public dat_api_base { -public: - dat_dummy() : - dat_api_base("error", "") - {} - std::string get_value() { - return "error"; - } - - bool set_value(std::string value) { - return false; - } - - std::string get_width() { - return "error"; - } -}; - -template<int w> class dat_api : public dat_api_base { -public: - dat_api(dat_t<w>* new_dat, const char* new_name, const char* new_path) : - dat_api_base(new_name, new_path), - dat_ptr(new_dat) - {} - - std::string get_value() { - return dat_ptr->to_str(); - } - - bool set_value(std::string value) { - return dat_from_str<w>(value, *dat_ptr); - } - - std::string get_width() { - return itos(w); - } - -protected: - dat_t<w>* dat_ptr; -}; - -// API base (non width/depth templated) class for API accessors to mem_t -class mem_api_base : public api_base { -public: - mem_api_base(const char* new_name, const char* new_path) : - api_base(new_name, new_path) - {} - // return the value of an element as a string, or empty string on failure - virtual std::string get_element(std::string index) = 0; - // sets the value of an element from a string, returning true on success - virtual bool set_element(std::string index, std::string value) = 0; - // returns the bitwidth of a memory element - virtual std::string get_width() = 0; - // returns the number of memory elements - virtual std::string get_depth() = 0; -}; - -// mem_api dummy class, does nothing except for return errors -// to be used when a real mem_api object can't be found -class mem_dummy : public mem_api_base { -public: - mem_dummy() : - mem_api_base("error", "") - {} - string get_element(std::string index) { - return "error"; - } - - bool set_element(std::string index, std::string value) { - return false; - } - - std::string get_width() { - return "error"; - } - - std::string get_depth() { - return "error"; - } -}; - -template<int w, int d> class mem_api : public mem_api_base { -public: - mem_api(mem_t<w, d>* new_mem, const char* new_name, const char* new_path) : - mem_api_base(new_name, new_path), - mem_ptr(new_mem) - {} - - string get_element(std::string index) { - int index_int = atoi(index.c_str()); - return mem_ptr->contents[index_int].to_str(); - } - - bool set_element(std::string index, std::string value) { - int index_int = atoi(index.c_str()); - return dat_from_str<w>(value, mem_ptr->contents[index_int]); - } - - std::string get_width() { - return itos(w); - } - - std::string get_depth() { - return itos(d); - } - -protected: - mem_t<w, d>* mem_ptr; -}; - -class mod_api_t { -public: - mod_api_t(): - teefile(NULL) - {} - - void init(mod_t* new_module) { - module = new_module; - init_mapping_table(); - } - - void set_teefile(FILE* new_teefile) { - teefile = new_teefile; - } - - mod_t* get_module() { - return module; - } - - // API basic functions - std::string get_host_name() {return "C++ Emulator API";} - std::string get_api_version() {return "0";} - std::string get_api_support() {return "PeekPoke Introspection";} - - // External access functions & helpers - std::vector< std::string > tokenize(std::string str) { - std::vector< std::string > res; - int i = 0; - int c = ' '; - while ( i < str.size() ) { - while (isspace(c)) { - if (i >= str.size()) return res; - c = str[i++]; - } - std::string s; - while (!isspace(c) && i < str.size()) { - s.push_back(c); - c = str[i++]; - } - if (i >= str.size()) s.push_back(c); - if (s.size() > 0) - res.push_back(s); - } - return res; - } - - // helper to verify command length, returning false and printing an error - // to stderr if the length isn't in the specified range - bool check_command_length(std::vector<std::string>& tokenized_command, - int min_args, int max_args=-1) { - if (tokenized_command.size() - 1 < min_args) { - std::cerr << tokenized_command[0] << " expects at least " << min_args - << " args, got " << tokenized_command.size() - 1 - << std::endl; - return false; - } else if (max_args >= 0 && tokenized_command.size() - 1 > max_args) { - std::cerr << tokenized_command[0] << " expects at most " << max_args - << " args, got " << tokenized_command.size() - 1 - << std::endl; - return false; - } - return true; - } - - // Evaluates an API command, returning the reply as a string (without - // the trailing newline). - // Errors return "error", printing a more detailed description to stderr. - // TODO: find a way to pass errors in-line, so transport layers other than - // stdin/stdout (like TCP/IP) are possible while also communicating errors. - std::string eval_command(string command) { - std::vector<std::string> tokens = tokenize(command); - if (tokens.size() == 0) { - std::cerr << "Empty command: '" << command << "'" << std::endl; - return "error"; - } - if (tokens[0] == "get_host_name") { - // IN: get_host_name - // OUT: API host's name (arbitrary string) - if (!check_command_length(tokens, 0, 0)) { return "error"; } - return get_host_name(); - } else if (tokens[0] == "get_api_version") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: get_api_version - // OUT: API version supported by this host - if (!check_command_length(tokens, 0, 0)) { return "error"; } - return get_api_version(); - } else if (tokens[0] == "get_api_support") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: get_api_support - // OUT: list of supported API features - if (!check_command_length(tokens, 0, 0)) { return "error"; } - return get_api_support(); - } else if (tokens[0] == "clock") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: clock <num_cycles> - // OUT: actual number of cycles stepped - if (!check_command_length(tokens, 1, 1)) { return "error"; } - int cycles = atoi(tokens[1].c_str()); - module->propagate_changes(); - for (int i=0; i<cycles; i++) { - module->clock(dat_t<1>(0)); - } - return itos(cycles); - } else if (tokens[0] == "tick") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: tick - // OUT: ok (on success) - // Update registers without propagation - // updating registers. - module->clock_hi(dat_t<1>(0)); - return "ok"; - } else if (tokens[0] == "propagate") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: propagate - // OUT: ok (on success) - // This function propagates the combinational logic, without - // updating registers. - module->propagate_changes(); - return "ok"; - } else if (tokens[0] == "step") { - // IN: step <num_cycles> - // OUT: actual number of cycles stepped - if (!check_command_length(tokens, 1, 1)) { return "error"; } - int n = atoi(tokens[1].c_str()); - module->propagate_changes(); - int ret = module->step(false, n); - // Do we have print output to report? - int nBytes = module->has_output(); - if (nBytes > 0) { - cout << "PRINT" << " " << nBytes << " " << module->drain_output(); - } - return itos(ret); - } else if (tokens[0] == "set_clocks") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: set_clocks - // OUT: ??? - // I'm not really sure what this is supposed to do, but it was - // in the old command API, so it's here now - std::vector< int > periods; - for (int i = 1; i < tokens.size(); i++) { - int period = atoi(tokens[i].c_str()); - periods.push_back(period); - } - module->setClocks(periods); - return "ok"; - - } else if (tokens[0] == "reset") { - // IN: reset <num_cycles> - // OUT: actual number of cycles in reset - if (!check_command_length(tokens, 0, 1)) { return "error"; } - int cycles = 1; - if (tokens.size() >= 2) { - cycles = atoi(tokens[1].c_str()); - } - for (int i=0; i<cycles; i++) { - module->clock_lo(dat_t<1>(1)); - module->clock_hi(dat_t<1>(1)); - } - module->clock_lo(dat_t<1>(0)); - return itos(cycles); - } else if (tokens[0] == "peek") { - // LEGACY FUNCTION: do not use in new code - // IN: peek <node_name> | peek <mem_name> <mem_index> - // OUT: value - if (!check_command_length(tokens, 1, 2)) { return "error"; } - cerr << "peek is deprecated, use wire_peek or mem_peek" << std::endl; - module->propagate_changes(); - if (tokens.size() == 2) { - return get_dat_by_name(tokens[1])->get_value(); - } else if (tokens.size() == 3) { - return get_mem_by_name(tokens[1])->get_element(tokens[2]); - } - } else if (tokens[0] == "poke") { - // LEGACY FUNCTION: do not use in new code - // IN: poke <node_name> <value> | poke <mem_name> <mem_index> <value> - // OUT: true (on success), false (on failure) - if (!check_command_length(tokens, 2, 3)) { return ""; } - cerr << "poke is deprecated, use wire_poke or mem_poke" << std::endl; - bool success; - if (tokens.size() == 3) { - success = get_dat_by_name(tokens[1])->set_value(tokens[2]); - } else if (tokens.size() == 4) { - success = get_mem_by_name(tokens[1])->set_element(tokens[2], tokens[3]); - } - std::string result; - if (success) { - result = "true"; - module->mark_stale(); - } else { - result = "false"; - } - return result; - } else if (tokens[0] == "wire_peek") { - // IN: wire_peek <node_name> - // OUT: value - if (!check_command_length(tokens, 1, 1)) { return "error"; } - module->propagate_changes(); - return get_dat_by_name(tokens[1])->get_value(); - } else if (tokens[0] == "wire_poke") { - // IN: wire_poke <node_name> <value> - // OUT: ok (on success) - if (!check_command_length(tokens, 2, 2)) { return "error"; } - bool success = get_dat_by_name(tokens[1])->set_value(tokens[2]); - std::string result; - if (success) { - result = "ok"; - module->mark_stale(); - } else { - result = "error"; - } - return result; - } else if (tokens[0] == "mem_peek") { - // IN: mem_peek <mem_name> <mem_index> - // OUT: value - if (!check_command_length(tokens, 2, 2)) { return "error"; } - module->propagate_changes(); - return get_mem_by_name(tokens[1])->get_element(tokens[2]); - } else if (tokens[0] == "mem_poke") { - // IN: mem_poke <mem_name> <mem_index> <value> - // OUT: ok (on success) - if (!check_command_length(tokens, 3, 3)) { return "error"; } - bool success = get_mem_by_name(tokens[1])->set_element(tokens[2], tokens[3]); - std::string result; - if (success) { - result = "ok"; - module->mark_stale(); - } else { - result = "error"; - } - return result; - return success ? "ok" : "error"; - } else if (tokens[0] == "trace") { - // IN: trace n <node_name>+ - // OUT: values - // TODO: ADD MEM PEEK SUPPORT - stringstream ss; - if (!check_command_length(tokens, 2)) { return "bad"; } - int n = atoi(tokens[1].c_str()); - for (int t = 0; t < n; t++) { - for (int i = 2; i < tokens.size(); i++) - ss << " " << get_dat_by_name(tokens[i])->get_value(); - int ret = module->step(false, 1); - // if (!ret) - // return "error"; - } - return ss.str(); - } else if (tokens[0] == "list_wires") { - // IN: list_wires - // OUT: list of wires - if (!check_command_length(tokens, 0, 0)) { return "error"; } - std::string out = ""; - for (std::map<const char*, dat_api_base*>::iterator it = dat_table.begin(); it != dat_table.end(); it++) { - out = out + it->second->get_pathname() + " "; - } - if (out.size() >= 1) { - return out.substr(0, out.size() - 1); - } else { - return ""; - } - } else if (tokens[0] == "list_mems") { - // IN: list_mems - // OUT: list of memories - if (!check_command_length(tokens, 0, 0)) { return "error"; } - std::string out = ""; - for (std::map<const char*, mem_api_base*>::iterator it = mem_table.begin(); it != mem_table.end(); it++) { - out = out + it->second->get_pathname() + " "; - } - if (out.size() >= 1) { - return out.substr(0, out.size() - 1); - } else { - return ""; - } - } else if (tokens[0] == "wire_width") { - // IN: wire_width <node> - // OUT: bitwidth of wire - if (!check_command_length(tokens, 1, 1)) { return "error"; } - return get_dat_by_name(tokens[1])->get_width(); - } else if (tokens[0] == "mem_width") { - // IN: mem_width <node> - // OUT: bitwidth of memory element - if (!check_command_length(tokens, 1, 1)) { return "error"; } - return get_mem_by_name(tokens[1])->get_width(); - } else if (tokens[0] == "mem_depth") { - // IN: mem_depth <node> - // OUT: elements in memory - if (!check_command_length(tokens, 1, 1)) { return "error"; } - return get_mem_by_name(tokens[1])->get_depth(); - } else if (tokens[0] == "referenced_snapshot_save") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: referenced_snapshot_save <name> - // OUT: Reference name (an arbitrary string) for saved snapshot - // of current state, should be equivalent to the input. - // Caution: the state may not be self-consistent (i.e. clk_lo - // does not need to have been applied before this, and calls to - // clk_lo immediately after restoring may change the state). - if (!check_command_length(tokens, 1, 1)) { return "error"; } - module->propagate_changes(); - mod_t *snapshot = module->clone(); - snapshot_table[tokens[1]] = snapshot; - return tokens[1]; - } else if (tokens[0] == "referenced_snapshot_restore") { - // BETA FUNCTION: semantics subject to change, use with caution - // IN: referenced_snapshot_restore <name> - // OUT: ok (on success) - if (!check_command_length(tokens, 1, 1)) { return "error"; } - mod_t *snapshot = get_snapshot_by_reference(tokens[1]); - if (snapshot == NULL) { return "error"; } - bool success = module->set_circuit_from(snapshot); - std::string result; - if (success) { - result = "ok"; - module->mark_stale(); - } else { - result = "error"; - } - return result; - } else { - std::cerr << "Unknown command: '" << tokens[0] << "'" << std::endl; - } - return "error"; - } - - void read_eval_print_loop() { - while (true) { - std::string str_in; - do { - std::getline(cin, str_in); - } while (cin.fail() && errno == EINTR); - - if (!cin.good()) { - break; - } - - if (teefile != NULL) { - fprintf(teefile, "%s\n", str_in.c_str()); - fflush(teefile); - } - if (str_in == "quit") { - break; - } else { - cout << eval_command(str_in) << std::endl; - } - } - } - -protected: - FILE* teefile; - mod_t* module; - - // Mapping table functions - virtual void init_mapping_table() = 0; - - dat_api_base* get_dat_by_name(std::string name) { - if (dat_table.find(name.c_str()) != dat_table.end()) { - return dat_table[name.c_str()]; - } else { - std::cerr << "Unable to find dat '" << name << "'" << std::endl; - return &this_dat_dummy; - } - } - mem_api_base* get_mem_by_name(std::string name) { - if (mem_table.find(name.c_str()) != mem_table.end()) { - return mem_table[name.c_str()]; - } else { - std::cerr << "Unable to find mem '" << name << "'" << std::endl; - return &this_mem_dummy; - } - } - - mod_t* get_snapshot_by_reference(std::string name) { - if (snapshot_table.find(name) != snapshot_table.end()) { - return snapshot_table[name]; - } else { - std::cerr << "Unable to find snapshot reference '" << name << "'" << std::endl; - return NULL; - } - } - - class string_comparator { - public: - bool operator()(const char* x, const char* y) const { - return strcmp(x, y) < 0; - } - }; - - std::map<const char*, dat_api_base*, string_comparator> dat_table; - std::map<const char*, mem_api_base*, string_comparator> mem_table; - // TODO: replace the dummy with explicit NULL checks - this is simple - // but a bit inelegant - dat_dummy this_dat_dummy; - mem_dummy this_mem_dummy; - - // Snapshot functions - std::map<std::string, mod_t*> snapshot_table; -}; - -#pragma GCC diagnostic pop - -#endif diff --git a/src/main/resources/emulator_mod.h b/src/main/resources/emulator_mod.h deleted file mode 100644 index 0d4929d3..00000000 --- a/src/main/resources/emulator_mod.h +++ /dev/null @@ -1,1800 +0,0 @@ -// Header for Chisel emulator module -// defines the mod_t class as well as bit operation functions - -#ifndef __IS_EMULATOR_MOD__ -#define __IS_EMULATOR_MOD__ - -#pragma GCC diagnostic push -#ifdef __clang__ -#pragma GCC diagnostic ignored "-Wunknown-pragmas" -#else -#pragma GCC diagnostic ignored "-Wpragmas" -#endif // __clang__ -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wsign-compare" -#pragma GCC diagnostic ignored "-Wparentheses" -#pragma GCC diagnostic ignored "-Wreturn-type" -#pragma GCC diagnostic ignored "-Wchar-subscripts" -#pragma GCC diagnostic ignored "-Wtype-limits" -#pragma GCC diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wreorder" -#pragma GCC diagnostic ignored "-Wsometimes-uninitialized" -#pragma GCC diagnostic ignored "-pedantic" - -#include <assert.h> -#include <inttypes.h> -#include <stdio.h> -#include <limits.h> -#include <math.h> -#include <vector> -#include <stdarg.h> -#include <string.h> -#include <time.h> -#include <string> -#include <map> -#include <stdlib.h> -#include <iostream> -#include <sstream> -#include <fstream> -#include <stdexcept> - -using namespace std; - -typedef uint64_t val_t; -typedef int64_t sval_t; -typedef uint32_t half_val_t; -#if defined(__GNUC__) && defined(__SIZEOF_INT128__) -#define __HAVE_DUB_VAL_T__ -typedef unsigned __int128 dub_val_t; -#endif - -union flo2int_t { - float f; - val_t i; -}; - -inline float toFloat (val_t x) { - flo2int_t f2i; - f2i.i = x; - return f2i.f; -} - -inline val_t fromFloat (float x) { - flo2int_t f2i; - f2i.f = x; - return f2i.i; -} - -union dbl2int_t { - double f; - val_t i; -}; - -inline double toDouble (val_t x) { - dbl2int_t f2i; - f2i.i = x; - return f2i.f; -} - -inline val_t fromDouble (double x) { - dbl2int_t f2i; - f2i.f = x; - return f2i.i; -} - -#define TERNARY(c, t, f) ((f) ^ (((f) ^ (t)) & -(c))) - -#if defined(__GNUC__) && defined(__x86_64__) -#define TERNARY_1(c, t, f) ({ \ - val_t __res; \ - if (!__builtin_constant_p(c)) { \ - __res = (f); \ - val_t __t = (t); \ - uint8_t __c = (c); \ - asm ("testb $1, %1; cmovne %2, %0" : "+r"(__res) : "rm"(__c), "rm"(__t) : "cc"); \ - } else __res = TERNARY(c, t, f); \ - __res; }) -#else -#define TERNARY_1(c, t, f) TERNARY(c, t, f) -#endif - -#define MASK(v, c) ((v) & -(val_t)(c)) -#ifndef MIN -#define MIN(a, b) TERNARY((a) < (b), (a), (b)) -#endif -#ifndef MAX -#define MAX(a, b) TERNARY((a) > (b), (a), (b)) -#endif -#define CLAMP(a, min, max) MAX(MIN(a, max), min) - -template<uint32_t x, uint32_t shifted=0, bool sticky=false> struct CeilLog { - static uint32_t const v = CeilLog<(x >> 1), shifted + 1, sticky | (x & 1)>::v; -}; - -template<uint32_t shifted, bool sticky> struct CeilLog<0, shifted, sticky> { - static uint32_t const v = -1; -}; - -template<uint32_t shifted, bool sticky> struct CeilLog<1, shifted, sticky> { - static uint32_t const v = sticky ? shifted + 1 : shifted; -}; - -#define val_n_bits() (sizeof(val_t)*8) -#define val_n_half_bits() (val_n_bits()/2) -#define val_all_ones() val_all_ones_or_zeroes(1) -#define val_all_ones_or_zeroes(bit) (val_t(0) - val_t(bit)) -#define val_n_words(n_bits) (1+((n_bits)-1)/val_n_bits()) -#define val_n_half_words(n_bits) (1+((n_bits)-1)/val_n_half_bits()) -#define val_top_bit(v) (val_t(v) >> (val_n_bits()-1)) -#define val_n_full_words(n_bits) ((n_bits)/val_n_bits()) -#define val_n_word_bits(n_bits) ((n_bits) % val_n_bits()) -inline val_t val_n_nibs( void ) { return val_n_bits()>>2; } -inline val_t val_half_mask( void ) { return (((val_t)1)<<(val_n_half_bits()))-1; } -inline val_t val_lo_half( val_t n_bits ) { return n_bits & val_half_mask(); } -inline val_t val_hi_half( val_t n_bits ) { return n_bits >> val_n_half_bits(); } -inline val_t val_n_rem_word_bits( val_t n_bits ) { return val_n_bits() - val_n_word_bits(n_bits); } -//inline val_t dub_val_lo_half( dub_val_t bits ) { return (val_t)bits; } -//inline val_t dub_val_hi_half( dub_val_t bits ) { return (val_t)(bits >> val_n_bits()); } - - -inline void val_to_half_vals ( val_t *fvals, half_val_t *hvals, int nf ) { - for (int i = 0; i < nf; i++) { - hvals[i*2] = val_lo_half(fvals[i]); - hvals[i*2+1] = val_hi_half(fvals[i]); - } -} -inline void half_val_to_vals ( half_val_t *hvals, val_t *vals, int nf ) { - for (int i = 0; i < nf; i++) - vals[i] = ((val_t)hvals[i*2+1] << val_n_half_bits()) | hvals[i*2]; -} - -template <int w> class dat_t; -template <int w> class datz_t; - -template <int w> int datz_eq(dat_t<w> d1, datz_t<w> d2); - -template <int w> inline dat_t<w> DAT(val_t value) { - dat_t<w> res(value); - return res; } - -template <int w> inline dat_t<w> DAT(val_t val1, val_t val0) { - dat_t<w> res; res.values[0] = val0; res.values[1] = val1; return res; -} - -const static char hex_digs[] = - {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - -static void add_n (val_t d[], val_t s0[], val_t s1[], int nw, int nb) { - val_t carry = 0; - for (int i = 0; i < nw; i++) { - d[i] = s0[i] + s1[i] + carry; - carry = ((s0[i] + s1[i]) < s0[i]) || (d[i] < carry); - } -} - -static void neg_n (val_t d[], val_t s0[], int nw, int nb) { - val_t borrow = 0; - for (int i = 0; i < nw; i++) { - d[i] = -s0[i] - borrow; - borrow = s0[i] || d[i]; - } -} - -static void sub_n (val_t d[], val_t s0[], val_t s1[], int nw, int nb) { - val_t borrow = 0; - for (int i = 0; i < nw; i++) { - d[i] = s0[i] - s1[i] - borrow; - borrow = (s0[i] < (s0[i] - s1[i])) || (s0[i] - s1[i]) < d[i]; - } -} - -static void mul_n (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { -// Adapted from Hacker's Delight, from Knuth -#if BYTE_ORDER != LITTLE_ENDIAN -# error mul_n assumes a little-endian architecture -#endif - int nbd = nb0 + nb1; - for (int i = 0; i < val_n_words(nbd); i++) - d[i] = 0; - - half_val_t* w = reinterpret_cast<half_val_t*>(d); - half_val_t* u = reinterpret_cast<half_val_t*>(s0); - half_val_t* v = reinterpret_cast<half_val_t*>(s1); - int m = val_n_half_words(nb0), n = val_n_half_words(nb1), p = val_n_half_words(nbd); - - for (int j = 0; j < n; j++) { - val_t k = 0; - for (int i = 0; i < MIN(m, p-j); i++) { - val_t t = (val_t)u[i]*v[j] + w[i+j] + k; - w[i+j] = t; - k = t >> val_n_half_bits(); - } - if (j+m < p) - w[j+m] = k; - } -} - -static void rsha_n (val_t d[], val_t s0[], int amount, int nw, int w) { - - int n_shift_bits = amount % val_n_bits(); - int n_shift_words = amount / val_n_bits(); - int n_rev_shift_bits = val_n_bits() - n_shift_bits; - int is_zero_carry = n_shift_bits == 0; - int msb = s0[nw-1] >> (w - nw*val_n_bits() - 1); - val_t carry = 0; - - if (msb == 0) - for (int i = 0; i < n_shift_words; i++) { - d[nw-i-1] = 0; - } - - for (int i = nw-1; i >= n_shift_words; i--) { - val_t val = s0[i]; - d[i-n_shift_words] = val >> n_shift_bits | carry; - carry = is_zero_carry ? 0 : val << n_rev_shift_bits; - } - - if (msb == 0) { - return; - } - - int boundary = (w - amount); - - for (int i = nw-1; i >= 0; i--) { - int idx = i*val_n_bits(); - if (idx > boundary) { - d[i] = val_all_ones(); - } else { - d[i] = d[i] | (val_all_ones() << (boundary - idx)); - d[nw-1] = d[nw-1] & (val_all_ones() >> ((nw-1)*val_n_bits() - w)); - return; - } - } -} - -static void rsh_n (val_t d[], val_t s0[], int amount, int nw) { - val_t carry = 0; - int n_shift_bits = amount % val_n_bits(); - int n_shift_words = amount / val_n_bits(); - int n_rev_shift_bits = val_n_bits() - n_shift_bits; - int is_zero_carry = n_shift_bits == 0; - for (int i = 0; i < n_shift_words; i++) - d[nw-i-1] = 0; - for (int i = nw-1; i >= n_shift_words; i--) { - val_t val = s0[i]; - d[i-n_shift_words] = val >> n_shift_bits | carry; - carry = is_zero_carry ? 0 : val << n_rev_shift_bits; - } -} - -static void lsh_n (val_t d[], val_t s0[], int amount, int nwd, int nws) { - val_t carry = 0; - int n_shift_bits = amount % val_n_bits(); - int n_shift_words = amount / val_n_bits(); - int n_rev_shift_bits = val_n_bits() - n_shift_bits; - int is_zero_carry = n_shift_bits == 0; - for (int i = 0; i < nwd; i++) - d[i] = 0; - for (int i = 0; i < (nws-n_shift_words); i++) { - val_t val = s0[i]; - d[i+n_shift_words] = val << n_shift_bits | carry; - carry = is_zero_carry ? 0 : val >> n_rev_shift_bits; - } -} - -static inline val_t mask_val(int n) { - val_t res = val_all_ones() >> (val_n_bits()-n); - return res; -} - -static inline void mask_n (val_t d[], int nw, int nb) { - int n_full_words = val_n_full_words(nb); - int n_word_bits = val_n_word_bits(nb); - for (int i = 0; i < n_full_words; i++) - d[i] = val_all_ones(); - for (int i = n_full_words; i < nw; i++) - d[i] = 0; - if (n_word_bits > 0) - d[n_full_words] = mask_val(n_word_bits); -} - -static inline val_t log2_1 (val_t v) { -#ifdef __GNUC__ - return TERNARY(v != 0, val_n_bits() - 1 - __builtin_clzll(v), 0); -#else - val_t r; - val_t shift; - r = (v > 0xFFFFFFFF) << 5; v >>= r; - shift = (v > 0xFFFF ) << 4; v >>= shift; r |= shift; - shift = (v > 0xFF ) << 3; v >>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; - r |= (v >> 1); - return r; -#endif -} - -static inline val_t reverse_1 (val_t v) { - v = ((v >> 1) & 0x5555555555555555) | ((v & 0x5555555555555555) << 1); - v = ((v >> 2) & 0x3333333333333333) | ((v & 0x3333333333333333) << 2); - v = ((v >> 4) & 0x0F0F0F0F0F0F0F0F) | ((v & 0x0F0F0F0F0F0F0F0F) << 4); - v = ((v >> 8) & 0x00FF00FF00FF00FF) | ((v & 0x00FF00FF00FF00FF) << 8); - v = ((v >> 16) & 0x0000FFFF0000FFFF) | ((v & 0x0000FFFF0000FFFF) << 16); - v = ( v >> 32 ) | ( v << 32); - return v; -} - -static inline val_t priority_encode_1 (val_t v) { -#ifdef __GNUC__ - return TERNARY(v != 0, __builtin_ctzll(v), 0); -#else - if (v == 0) - return 0; - val_t r; - val_t shift; - r = !(v & 0xFFFFFFFF) << 5; v >>= r; - shift = !(v & 0xFFFF ) << 4; v >>= shift; r |= shift; - shift = !(v & 0xFF ) << 3; v >>= shift; r |= shift; - shift = !(v & 0xF ) << 2; v >>= shift; r |= shift; - shift = !(v & 0x3 ) << 1; v >>= shift; r |= shift; - shift = !(v & 0x1 ) << 0; v >>= shift; r |= shift; - return r; -#endif -} - -#define ispow2(x) (((x) & ((x)-1)) == 0) -static inline val_t nextpow2_1(val_t x) { - x--; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - x |= x >> 32; - x++; - return x; -} - -/* -#define __FLOAT_WORD_ORDER LITTLE_ENDIAN - -static inline uint32_t log2_1_32 (uint32_t v) { - union { uint32_t u[2]; double d; } t; // temp - - t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] = 0x43300000; - t.u[__FLOAT_WORD_ORDER!=LITTLE_ENDIAN] = v; - t.d -= 4503599627370496.0; - return (t.u[__FLOAT_WORD_ORDER==LITTLE_ENDIAN] >> 20) - 0x3FF; -} - -static inline val_t log2_1 (val_t v) { - uint32_t r_lo = (uint32_t)v; - uint32_t r_hi = (uint32_t)(v >> 32); - return (((val_t)log2_1_32(r_hi)) << 32)|((val_t)log2_1_32(r_lo)); -} -*/ - -/* -static inline val_t log2_1 (val_t v) { - v |= (v >> 1); - v |= (v >> 2); - v |= (v >> 4); - v |= (v >> 8); - v |= (v >> 16); - v |= (v >> 32); - return ones64(v) - 1; -} -*/ - -/* -static inline val_t log2_1 (val_t v) { - val_t res = 0; - while (v >>= 1) - res++; - return res; -} -*/ - -static inline val_t log2_n (val_t s0[], int nw) { - val_t off = (nw-1)*val_n_bits(); - for (int i = nw-1; i >= 0; i--) { - val_t s0i = s0[i]; - if (s0i > 0) { - val_t res = log2_1(s0i); - return res + off; - } - off -= val_n_bits(); - } - return 0; -} - -template <int nw> -struct bit_word_funs { - static void fill (val_t d[], val_t s0) { - for (int i = 0; i < nw; i++) - d[i] = s0; - } - static void fill_nb (val_t d[], val_t s0, int nb) { - mask_n(d, nw, nb); - for (int i = 0; i < nw; i++) - d[i] = d[i] & s0; - // printf("FILL-NB N\n"); - } - static void copy (val_t d[], val_t s0[], int sww) { - if (sww > nw) { - for (int i = 0; i < nw; i++) { - // printf("A I %d\n", i); fflush(stdout); - d[i] = s0[i]; - } - } else { - for (int i = 0; i < sww; i++) { - // printf("B I %d\n", i); fflush(stdout); - d[i] = s0[i]; - } - for (int i = sww; i < nw; i++) { - // printf("C I %d\n", i); fflush(stdout); - d[i] = 0; - } - } - } - static void mask (val_t d[], int nb) { - mask_n(d, nw, nb); - } - static void add (val_t d[], val_t s0[], val_t s1[], int nb) { - add_n(d, s0, s1, nw, nb); - } - static void neg (val_t d[], val_t s0[], int nb) { - neg_n(d, s0, nw, nb); - } - static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { - sub_n(d, s0, s1, nw, nb); - } - static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { - mul_n(d, s0, s1, nb0, nb1); - } - static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { - for (int i = 0; i < nw; i++) - d[i] = s0[i] ^ s1[i]; - } - static void bit_and (val_t d[], val_t s0[], val_t s1[]) { - for (int i = 0; i < nw; i++) - d[i] = s0[i] & s1[i]; - } - static void bit_or (val_t d[], val_t s0[], val_t s1[]) { - for (int i = 0; i < nw; i++) - d[i] = s0[i] | s1[i]; - } - static void bit_neg (val_t d[], val_t s0[], int nb) { - val_t msk[nw]; - mask_n(msk, nw, nb); - for (int i = 0; i < nw; i++) - d[i] = ~s0[i] & msk[i]; - } - static bool ltu (val_t s0[], val_t s1[]) { - val_t diff[nw]; - sub(diff, s0, s1, nw*val_n_bits()); - return val_top_bit(diff[nw-1]); - } - static bool lt (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; - if (msb_0 != msb_1) { - return msb_0; - } else { - val_t diff[nw]; - sub(diff, s0, s1, nw*val_n_bits()); - return val_top_bit(diff[nw-1]); - } - } - static bool lteu (val_t s0[], val_t s1[]) { - val_t diff[nw]; - sub(diff, s1, s0, nw*val_n_bits()); - return !val_top_bit(diff[nw-1]); - } - static bool lte (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - (nw-1)*val_n_bits() - 1)) & 0x1; - if (msb_0 != msb_1) { - return msb_0; - } else { - val_t diff[nw]; - sub(diff, s1, s0, nw*val_n_bits()); - return !val_top_bit(diff[nw-1]); - } - } - static bool eq (val_t s0[], val_t s1[]) { - for (int i = 0; i < nw; i++) - if (s0[i] != s1[i]) - return false; - return true; - } - static bool neq (val_t s0[], val_t s1[]) { - return !eq(s0, s1); - } - static void rsha (val_t d[], val_t s0[], int amount, int w) { - rsha_n(d, s0, amount, nw, w); - } - static void rsh (val_t d[], val_t s0[], int amount) { - rsh_n(d, s0, amount, nw); - } - static void lsh (val_t d[], val_t s0[], int amount) { - lsh_n(d, s0, amount, nw, nw); - } - static void extract (val_t d[], val_t s0[], int e, int s, int nb) { - // TODO: FINISH THIS - const int bw = e-s+1; - val_t msk[nw]; - mask_n(msk, nw, nb); - if (s == 0) { - // printf("EXT E %d S %d NW %d NB %d: ", e, s, nw, nb); - for (int i = 0; i < nw; i++) { - d[i] = s0[i] & msk[i]; - // printf("%d:%llx ", i, d[i]); - } - } else { - rsh_n(d, s0, s, nw); - // printf("EXT E %d S %d NW %d NB %d: ", e, s, nw, nb); - for (int i = 0; i < nw; i++) { - // printf("I%d:R%llx:M%llx:", i, d[i], msk[i]); - d[i] = d[i] & msk[i]; - // printf("D%llx ", d[i]); - } - } - // printf("\n"); - } - - static void inject (val_t d[], val_t s0[], int e, int s) { - // Opposite of extract: Assign s0 to a subfield of d. - const int bw = e-s+1; - val_t msk[nw]; - val_t msk_lsh[nw]; - val_t s0_lsh[nw]; - mask_n(msk, nw, bw); - lsh_n(msk_lsh, msk, s, nw, nw); - lsh_n(s0_lsh, s0, s, nw, nw); - for (int i = 0; i < nw; i++) { - d[i] = (d[i] & ~msk_lsh[i]) | (s0_lsh[i] & msk_lsh[i]); - } - } - - static void set (val_t d[], val_t s0[]) { - for (int i = 0; i < nw; i++) - d[i] = s0[i]; - } - static void log2 (val_t d[], val_t s0[]) { - d[0] = log2_n(s0, nw); - } -}; - -template <> -struct bit_word_funs<1> { - static void fill (val_t d[], val_t s0) { - d[0] = s0; - } - static void fill_nb (val_t d[], val_t s0, int nb) { - d[0] = mask_val(nb) & s0; - } - static void copy (val_t d[], val_t s0[], int sww) { - d[0] = s0[0]; - } - static void mask (val_t d[], int nb) { - d[0] = mask_val(nb); - } - static void add (val_t d[], val_t s0[], val_t s1[], int nb) { - d[0] = (s0[0] + s1[0]) & mask_val(nb); - } - static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { - d[0] = (s0[0] - s1[0]) & mask_val(nb); - } - static void neg (val_t d[], val_t s0[], int nb) { - d[0] = (- s0[0]) & mask_val(nb); - } - static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { - d[0] = s0[0] * s1[0]; - } - static bool ltu (val_t s0[], val_t s1[]) { - return (s0[0] < s1[0]); - } - static bool lt (val_t s0[], val_t s1[], int w) { - sval_t a = s0[0] << (val_n_bits() - w); - sval_t b = s1[0] << (val_n_bits() - w); - return (a < b); - } - static bool lteu (val_t s0[], val_t s1[]) { - return (s0[0] <= s1[0]); - } - static bool lte (val_t s0[], val_t s1[], int w) { - sval_t a = s0[0] << (val_n_bits() - w); - sval_t b = s1[0] << (val_n_bits() - w); - return (a <= b); - } - static void bit_neg (val_t d[], val_t s0[], int nb) { - d[0] = ~s0[0] & mask_val(nb); - } - static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] ^ s1[0]); - } - static void bit_and (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] & s1[0]); - } - static void bit_or (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] | s1[0]); - } - static bool eq (val_t s0[], val_t s1[]) { - return s0[0] == s1[0]; - } - static bool neq (val_t s0[], val_t s1[]) { - return s0[0] != s1[0]; - } - static void lsh (val_t d[], val_t s0[], int amount) { - d[0] = (s0[0] << amount); - } - static void rsh (val_t d[], val_t s0[], int amount) { - d[0] = (s0[0] >> amount); - } - static void rsha (val_t d[], val_t s0[], int amount, int w) { - d[0] = s0[0] << (val_n_bits() - w); - d[0] = (sval_t(d[0]) >> (val_n_bits() - w + amount)) & mask_val(w); - } - static void extract (val_t d[], val_t s0[], int e, int s, int nb) { - const int bw = e-s+1; - d[0] = (s0[0] >> s) & mask_val(bw); - } - - static void inject (val_t d[], val_t s0[], int e, int s) { - // Opposite of extract: Assign s0 to a subfield of d. - const int bw = e-s+1; - val_t msk = mask_val(bw); - d[0] = ((s0[0] & msk) << s) | (d[0] & ~(msk << s)); - } - - static void set (val_t d[], val_t s0[]) { - d[0] = s0[0]; - } - static void log2 (val_t d[], val_t s0[]) { - d[0] = log2_1(s0[0]); - } -}; - -template <> -struct bit_word_funs<2> { - static void fill (val_t d[], val_t s0) { - d[0] = s0; - d[1] = s0; - } - static void fill_nb (val_t d[], val_t s0, int nb) { - d[0] = s0; - d[1] = mask_val(nb - val_n_bits()) & s0; - } - static void copy (val_t d[], val_t s0[], int sww) { - d[0] = s0[0]; - d[1] = sww > 1 ? s0[1] : 0; - } - static void mask (val_t d[], int nb) { - d[0] = val_all_ones(); - d[1] = mask_val(nb - val_n_bits()); - } - static void add (val_t d[], val_t x[], val_t y[], int nb) { - val_t x0 = x[0]; - val_t sum0 = x0 + y[0]; - val_t carry0 = (sum0 < x0); - d[0] = sum0; - val_t sum1 = x[1] + y[1] + carry0; - d[1] = sum1; - } - static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { - val_t d0 = s0[0] - s1[0]; - d[1] = s0[1] - s1[1] - (s0[0] < d0); - d[0] = d0; - } - static void neg (val_t d[], val_t s0[], int nb) { - val_t d0 = -s0[0]; - d[1] = -s0[1] - (s0[0] != 0); - d[0] = d0; - } - static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { -#ifdef __HAVE_DUB_VAL_T__ - dub_val_t a = s0[0], b = s1[0]; - if (nb0 > val_n_bits()) a |= dub_val_t(s0[1]) << val_n_bits(); - if (nb1 > val_n_bits()) b |= dub_val_t(s1[1]) << val_n_bits(); - dub_val_t res = a * b; - d[0] = res; - d[1] = res >> val_n_bits(); -#else - mul_n(d, s0, s1, nb0, nb1); -#endif - } - static bool ltu (val_t s0[], val_t s1[]) { - return ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] < s1[0])); - } - static bool lt (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - val_n_bits() - 1)) & 0x1; - int cond = msb_0 ^ msb_1; - return (cond && msb_0) - || (!cond && ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] < s1[0]))); - } - static bool lteu (val_t s0[], val_t s1[]) { - return ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] <= s1[0])); - } - static bool lte (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - val_n_bits() - 1)) & 0x1; - int cond = msb_0 ^ msb_1; - return (cond && msb_0) - || (!cond && ((s0[1] < s1[1]) | (s0[1] == s1[1] & s0[0] <= s1[0]))); - } - static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] ^ s1[0]); - d[1] = (s0[1] ^ s1[1]); - } - static void bit_and (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] & s1[0]); - d[1] = (s0[1] & s1[1]); - } - static void bit_or (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] | s1[0]); - d[1] = (s0[1] | s1[1]); - } - static void bit_neg (val_t d[], val_t s0[], int nb) { - d[0] = ~s0[0]; - d[1] = ~s0[1] & mask_val(nb - val_n_bits()); - } - static bool eq (val_t s0[], val_t s1[]) { - return (s0[0] == s1[0]) & (s0[1] == s1[1]); - } - static bool neq (val_t s0[], val_t s1[]) { - return (s0[0] != s1[0]) | (s0[1] != s1[1]); - } - static void extract (val_t d[], val_t s0[], int e, int s, int nb) { - val_t msk[2]; - const int bw = e-s+1; - mask_n(msk, 2, bw); - if (s == 0) { - d[0] = s0[0] & msk[0]; - d[1] = s0[1] & msk[1]; - } else { - rsh(d, s0, s); - d[0] = d[0] & msk[0]; - d[1] = d[1] & msk[1]; - } - } - - static void inject (val_t d[], val_t s0[], int e, int s) { - // Opposite of extract: Assign s0 to a subfield of d. - const int bw = e-s+1; - val_t msk[2]; - val_t msk_lsh[2]; - val_t s0_lsh[2]; - mask_n(msk, 2, bw); - lsh_n(msk_lsh, msk, s, 2, 2); - lsh_n(s0_lsh, s0, s, 2, 2); - d[0] = (d[0] & ~msk_lsh[0]) | (s0_lsh[0] & msk_lsh[0]); - d[1] = (d[1] & ~msk_lsh[1]) | (s0_lsh[1] & msk_lsh[1]); - } - - static void rsha (val_t d[], val_t s0[], int amount, int w) { - sval_t hi = s0[1] << (2*val_n_bits() - w); - if (amount >= val_n_bits()) { - d[0] = hi >> (amount - w + val_n_bits()); - d[1] = hi >> (val_n_bits() - 1); - d[1] = d[1] >> (2*val_n_bits() - w); - } else if (amount == 0) { - d[0] = s0[0]; - d[1] = s0[1]; - } else { - int s = 2*val_n_bits() - w + amount; - d[0] = s0[0] >> amount; - d[0] = d[0] | ((hi >> (2*val_n_bits() - w)) << (val_n_bits() - amount)); - d[1] = hi >> (s >= val_n_bits() ? val_n_bits()-1 : s); - d[1] = d[1] & mask_val(w - val_n_bits()); - } - } - static void rsh (val_t d[], val_t s0[], int amount) { - if (amount >= val_n_bits()) { - d[1] = 0; - d[0] = s0[1] >> (amount - val_n_bits()); - } else if (amount == 0) { - d[0] = s0[0]; - d[1] = s0[1]; - } else { - d[1] = s0[1] >> amount; - d[0] = (s0[1] << (val_n_bits() - amount)) | (s0[0] >> amount); - } - } - static void lsh (val_t d[], val_t s0[], int amount) { - if (amount == 0) - { - d[1] = s0[1]; - d[0] = s0[0]; - } else if (amount >= val_n_bits()) { - d[1] = s0[0] << (amount - val_n_bits()); - d[0] = 0; - } else { - d[1] = (s0[1] << amount) | (s0[0] >> (val_n_bits() - amount)); - d[0] = (s0[0] << amount); - } - } - static void set (val_t d[], val_t s0[]) { - d[0] = s0[0]; - d[1] = s0[1]; - } - static void log2 (val_t d[], val_t s0[]) { - val_t s01 = s0[1]; - if (s01 > 0) - d[0] = log2_1(s01) + val_n_bits(); - else - d[0] = log2_1(s0[0]); - // d[0] = log2_n(s0, 2); - } -}; -template <> -struct bit_word_funs<3> { - static void fill (val_t d[], val_t s0) { - d[0] = s0; - d[1] = s0; - d[2] = s0; - } - static void fill_nb (val_t d[], val_t s0, int nb) { - d[0] = s0; - d[1] = s0; - d[2] = mask_val(nb - 2*val_n_bits()) & s0; - } - static void copy (val_t d[], val_t s0[], int sww) { - d[0] = s0[0]; - d[1] = sww > 1 ? s0[1] : 0; - d[2] = sww > 2 ? s0[2] : 0; - } - static void mask (val_t d[], int nb) { - d[0] = val_all_ones(); - d[1] = val_all_ones(); - d[2] = mask_val(nb - 2*val_n_bits()); - } - static void add (val_t d[], val_t s0[], val_t s1[], int nb) { - add_n(d, s0, s1, 3, nb); - } - static void sub (val_t d[], val_t s0[], val_t s1[], int nb) { - sub_n(d, s0, s1, 3, nb); - } - static void neg (val_t d[], val_t s0[], int nb) { - neg_n(d, s0, 3, nb); - } - static void mul (val_t d[], val_t s0[], val_t s1[], int nb0, int nb1) { - mul_n(d, s0, s1, nb0, nb1); - } - static bool ltu (val_t s0[], val_t s1[]) { - return ((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] < s1[0]))))); - } - static bool lt (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - 2*val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - 2*val_n_bits() - 1)) & 0x1; - int cond = msb_0 ^ msb_1; - return (cond && msb_0) - || (!cond && (((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] < s1[0]))))))); - } - static bool lteu (val_t s0[], val_t s1[]) { - return ((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] <= s1[0]))))); - } - static bool lte (val_t s0[], val_t s1[], int w) { - int msb_0 = (s0[1] >> (w - 2*val_n_bits() - 1)) & 0x1; - int msb_1 = (s1[1] >> (w - 2*val_n_bits() - 1)) & 0x1; - int cond = msb_0 ^ msb_1; - return (cond && msb_0) - || (!cond && ((s0[2] < s1[2]) | ((s0[2] == s1[2]) & ((s0[1] < s1[1]) | ((s0[1] == s1[1]) & (s0[0] <= s1[0])))))); - } - static void bit_xor (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] ^ s1[0]); - d[1] = (s0[1] ^ s1[1]); - d[2] = (s0[2] ^ s1[2]); - } - static void bit_and (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] & s1[0]); - d[1] = (s0[1] & s1[1]); - d[2] = (s0[2] & s1[2]); - } - static void bit_or (val_t d[], val_t s0[], val_t s1[]) { - d[0] = (s0[0] | s1[0]); - d[1] = (s0[1] | s1[1]); - d[2] = (s0[2] | s1[2]); - } - static void bit_neg (val_t d[], val_t s0[], int nb) { - d[0] = ~s0[0]; - d[1] = ~s0[1]; - d[2] = ~s0[2] & mask_val(nb - 2*val_n_bits()); - } - static bool eq (val_t s0[], val_t s1[]) { - return (s0[0] == s1[0]) & (s0[1] == s1[1]) & (s0[2] == s1[2]); - } - static bool neq (val_t s0[], val_t s1[]) { - return (s0[0] != s1[0]) | (s0[1] != s1[1]) | (s0[2] != s1[2]); - } - static void extract (val_t d[], val_t s0[], int e, int s, int nb) { - val_t msk[3]; - const int bw = e-s+1; - mask_n(msk, 3, bw); - if (s == 0) { - d[0] = s0[0] & msk[0]; - d[1] = s0[1] & msk[1]; - d[2] = s0[2] & msk[2]; - } else { - rsh(d, s0, s); - d[0] = d[0] & msk[0]; - d[1] = d[1] & msk[1]; - d[2] = d[2] & msk[2]; - } - } - - static void inject (val_t d[], val_t s0[], int e, int s) { - const int bw = e-s+1; - val_t msk[3]; - val_t msk_lsh[3]; - val_t s0_lsh[3]; - mask_n(msk, 3, bw); - lsh_n(msk_lsh, msk, s, 3, 3); - lsh_n(s0_lsh, s0, s, 3, 3); - d[0] = (d[0] & ~msk_lsh[0]) | (s0_lsh[0] & msk_lsh[0]); - d[1] = (d[1] & ~msk_lsh[1]) | (s0_lsh[1] & msk_lsh[1]); - d[2] = (d[2] & ~msk_lsh[2]) | (s0_lsh[2] & msk_lsh[2]); - } - - static void rsha (val_t d[], val_t s0[], int amount, int w) { - rsha_n(d, s0, amount, 3, w); - } - static void rsh (val_t d[], val_t s0[], int amount) { - rsh_n(d, s0, amount, 3); - } - static void lsh (val_t d[], val_t s0[], int amount) { - lsh_n(d, s0, amount, 3, 3); - } - static void log2 (val_t d[], val_t s0[]) { - d[0] = log2_n(s0, 3); - } - static void set (val_t d[], val_t s0[]) { - d[0] = s0[0]; - d[1] = s0[1]; - d[2] = s0[2]; - } -}; - -static val_t __rand_val(val_t* seed) { - val_t x = *seed; - *seed = (x << 1) ^ (-(sval_t(x) < 0) & 0x1B); - return x; -} - -template <int w> -class dat_t { - public: - const static int n_words = ((w - 1) / 64) + 1; - // const static int n_words = (w >> CeilLog<sizeof(val_t)*8>::v) + 1; - val_t values[n_words]; - inline int width ( void ) { return w; } - inline int n_words_of ( void ) { return n_words; } - inline bool to_bool ( void ) { return lo_word() != 0; } - inline val_t lo_word ( void ) { return values[0]; } - inline unsigned long to_ulong ( void ) { return (unsigned long)lo_word(); } - - std::string to_str () { - std::string rres, res; - int nn = (int)ceilf(w / 4.0); - for (int i = 0; i < n_words; i++) { - int n_nibs = nn < val_n_nibs() ? nn : val_n_nibs(); - for (int j = 0; j < n_nibs; j++) { - uint8_t nib = (values[i] >> (j*4))&0xf; - rres.push_back(hex_digs[nib]); - } - nn -= val_n_bits()/4; - } - res.push_back('0'); - res.push_back('x'); - for (int i = 0; i < rres.size(); i++) - res.push_back(rres[rres.size()-i-1]); - return res; - } - void randomize(val_t* seed) { - for (int i = 0; i < n_words; i++) - values[i] = __rand_val(seed); - if (val_n_word_bits(w)) - values[n_words-1] &= mask_val(val_n_word_bits(w)); - } - inline dat_t<w> () { - } - template <int sw> - inline dat_t<w> (const dat_t<sw>& src) { - bit_word_funs<n_words>::copy(values, (val_t*)src.values, src.n_words); - if (sw != w && val_n_word_bits(w)) - values[n_words-1] &= mask_val(val_n_word_bits(w)); - } - inline dat_t<w> (const dat_t<w>& src) { - bit_word_funs<n_words>::set(values, (val_t*)src.values); - } - static inline dat_t<w> from_vals(val_t val[n_words]) { - dat_t<w> res; - for (int i = 0; i < n_words; i++) - res.values[i] = val[i]; - return res; - } - inline dat_t<w> (val_t val) { - values[0] = val; - for (int i = 1; i < n_words; i++) - values[i] = 0; - } - template <int sw> - dat_t<w> mask(dat_t<sw> fill, int n) { - dat_t<w> res; - bit_word_funs<n_words>::mask(res.values, n); - return res; - } - template <int dw> - dat_t<dw> mask(int n) { - dat_t<dw> res; - return res.mask(*this, n); - } - template <int n> - inline dat_t<n> mask(void) { - dat_t<n> res = mask<n>(n); - return res; - } - val_t operator [] (size_t i) { - return values[i]; - } - dat_t<w> operator + ( dat_t<w> o ) { - dat_t<w> res; - bit_word_funs<n_words>::add(res.values, values, o.values, w); - return res; - } - dat_t<w> operator - ( dat_t<w> o ) { - dat_t<w> res; - bit_word_funs<n_words>::sub(res.values, values, o.values, w); - return res; - } - dat_t<w> operator - ( ) { - return ~(*this) + DAT<w>(1); - } - template <int w2> - dat_t<w+w2> operator * ( dat_t<w2> o ) { - dat_t<w+w2> res; - bit_word_funs<val_n_words(w+w2)>::mul(res.values, values, o.values, w, w2); - return res; - } - template <int w2> - dat_t<w+w2> fix_times_fix( dat_t<w2> o ) { - if (w+w2 <= val_n_bits()) { - sval_t a = sval_t(values[0] << (val_n_bits()-w)) >> (val_n_bits()-w); - sval_t b = sval_t(o.values[0] << (val_n_bits()-w2)) >> (val_n_bits()-w2); - return dat_t<w+w2>((a * b) & mask_val(w+w2)); - } else { - val_t sgn_a = msb(); - dat_t<w> abs_a = sgn_a ? -(*this) : (*this); - val_t sgn_b = o.msb(); - dat_t<w2> abs_b = sgn_b ? -o : o; - dat_t<w+w2> res = abs_a * abs_b; - return (sgn_a ^ sgn_b) ? -res : res; - } - } - dat_t<w> operator / ( dat_t<w> o ) { - dat_t<w> res(0); - if (o == 0) { - res.fill_bit(1); - } else if (n_words == 1) { - res.values[0] = values[0] / o.values[0]; - } else { - dat_t<2*w> p = *this, d = o; - d = d << w; - - for (int i = w-1; i >= 0; i--) { - p = p << 1; - if (p >= d) { - p = p - d; - res.values[i / val_n_bits()] |= val_t(1) << (i % val_n_bits()); - } - } - } - return res; - } - dat_t<w> operator % ( dat_t<w> o ) { - return *this - *this / o * o; - } - dat_t<w+w> ufix_times_fix( dat_t<w> o ) { - return o.fix_times_ufix(*this); - } - template<int w2> - dat_t<w+w2> fix_times_ufix( dat_t<w2> o ) { - if (w+w2 <= val_n_bits()) { - sval_t a = sval_t(values[0] << (val_n_bits()-w)) >> (val_n_bits()-w); - return dat_t<w+w2>((a * o.values[0]) & mask_val(w+w2)); - } else { - val_t sgn_a = msb(); - dat_t<w> abs_a = sgn_a ? -(*this) : (*this); - dat_t<w+w2> res = abs_a * o; - return sgn_a ? -res : res; - } - } - inline bool operator < ( dat_t<w> o ) { - return bit_word_funs<n_words>::ltu(values, o.values); - } - inline bool operator <= ( dat_t<w> o ) { - return bit_word_funs<n_words>::lteu(values, o.values); - } - inline bool operator > ( dat_t<w> o ) { - return o < *this; - } - inline bool operator >= ( dat_t<w> o ) { - return o <= *this; - } - inline bool lt ( dat_t<w> o ) { - return bit_word_funs<n_words>::lt(values, o.values, w); - } - inline bool lte ( dat_t<w> o ) { - return bit_word_funs<n_words>::lte(values, o.values, w); - } - inline bool gt ( dat_t<w> o ) { - return o.lt(*this); - } - inline bool gte ( dat_t<w> o ) { - return o.lte(*this); - } - dat_t<w> operator ^ ( dat_t<w> o ) { - dat_t<w> res; - bit_word_funs<n_words>::bit_xor(res.values, values, o.values); - return res; - } - dat_t<w> operator & ( dat_t<w> o ) { - dat_t<w> res; - bit_word_funs<n_words>::bit_and(res.values, values, o.values); - return res; - } - dat_t<w> operator | ( dat_t<w> o ) { - dat_t<w> res; - bit_word_funs<n_words>::bit_or(res.values, values, o.values); - return res; - } - dat_t<w> operator ~ ( void ) { - dat_t<w> res; - bit_word_funs<n_words>::bit_neg(res.values, values, w); - return res; - } - inline dat_t<1> operator ! ( void ) { - return DAT<1>(!lo_word()); - } - dat_t<1> operator && ( dat_t<1> o ) { - return DAT<1>(lo_word() & o.lo_word()); - } - dat_t<1> operator || ( dat_t<1> o ) { - return DAT<1>(lo_word() | o.lo_word()); - } - bool operator == ( dat_t<w> o ) { - return bit_word_funs<n_words>::eq(values, o.values); - } - bool operator == ( datz_t<w> o ) { - return o == *this; - } - bool operator != ( dat_t<w> o ) { - return bit_word_funs<n_words>::neq(values, o.values); - } - dat_t<w> operator << ( int amount ) { - dat_t<w> res; - bit_word_funs<n_words>::lsh(res.values, values, amount); - if (val_n_word_bits(w)) - res.values[n_words-1] &= mask_val(val_n_word_bits(w)); - return res; - } - inline dat_t<w> operator << ( dat_t<w> o ) { - return *this << o.lo_word(); - } - dat_t<w> operator >> ( int amount ) { - dat_t<w> res; - bit_word_funs<n_words>::rsh(res.values, values, amount); - return res; - } - inline dat_t<w> operator >> ( dat_t<w> o ) { - return *this >> o.lo_word(); - } - dat_t<w> rsha ( dat_t<w> o) { - dat_t<w> res; - int amount = o.lo_word(); - bit_word_funs<n_words>::rsha(res.values, values, amount, w); - return res; - } - dat_t<w>& operator = ( dat_t<w> o ) { - bit_word_funs<n_words>::set(values, o.values); - return *this; - } - dat_t<w> fill_bit( val_t bit ) { - dat_t<w> res; - val_t word = 0L - bit; - bit_word_funs<n_words>::fill_nb(res.values, word, w); - return res; - } - // TODO: SPEED THIS UP - dat_t<w> fill_byte( val_t byte, int nb, int n ) { - dat_t<w> res; - bit_word_funs<n_words>::fill(res.values, 0L); - for (size_t i = 0; i < n; i++) - res = (res << nb) | byte; - return res; - } - template <int dw, int n> - dat_t<dw> fill( void ) { - // TODO: GET RID OF IF'S - dat_t<dw> res; - if (w == 1) { - return res.fill_bit(lo_word()); - } else { - return res.fill_byte(lo_word(), w, n); - } - } - template <int dw, int nw> - dat_t<dw> fill( dat_t<nw> n ) { - // TODO: GET RID OF IF'S - dat_t<dw> res; - if (w == 1) { - return res.fill_bit(lo_word()&1); - } else { - return res.fill_byte(lo_word(), w, n); - } - } - template <int dw> - dat_t<dw> extract() { - dat_t<dw> res; - int i; - for (i = 0; i < val_n_full_words(dw); i++) - res.values[i] = values[i]; - if (val_n_word_bits(dw)) - res.values[i] = values[i] & mask_val(val_n_word_bits(dw)); - return res; - } - template <int dw> - dat_t<dw> extract(val_t e, val_t s) { - dat_t<w> x = (*this >> s); - return x.extract<dw>(); - } - template <int dw, int iwe, int iws> - inline dat_t<dw> extract(dat_t<iwe> e, dat_t<iws> s) { - return extract<dw>(e.lo_word(), s.lo_word()); - } - - template <int sw> - dat_t<w> inject(dat_t<sw> src, val_t e, val_t s) { - // Modify this.values in place. - dat_t<w> inject_src(src); // Enlarged if needed to match inject_dst - bit_word_funs<n_words>::inject(values, inject_src.values, e, s); - return *this; - } - - template <int sw, int iwe, int iws> - inline dat_t<w> inject(dat_t<sw> src, dat_t<iwe> e, dat_t<iws> s) { - return inject<w>(src, e.lo_word(), s.lo_word()); - } - - - template <int dw> - inline dat_t<dw> log2() { - dat_t<dw> res; - bit_word_funs<n_words>::log2(res.values, values); - return res; - } - inline val_t bit(val_t b) { - return (values[val_n_full_words(b)] >> val_n_word_bits(b)) & 1; - } - inline val_t msb() { - return values[n_words-1] >> val_n_word_bits(w-1); - } - template <int iw> - inline dat_t<1> bit(dat_t<iw> b) { - return bit(b.lo_word()); - } -}; - -template <int w> -std::string dat_to_str(const dat_t<w>& x) { - char s[w]; - s[dat_to_str(s, x)] = 0; - return s; -} - -static __inline__ int n_digits(int w, int base) { - return (int)ceil(log(2)/log(base)*w); -} - -template <int w> -int dat_to_str(char* s, dat_t<w> x, int base = 16, char pad = '0') { - int n_digs = n_digits(w, base); - int j = n_digs-1, digit; - - do { - if (ispow2(base)) { - digit = x.lo_word() & (base-1); - x = x >> log2_1(base); - } else { - digit = (x % base).lo_word(); - x = x / base; - } - s[j] = (digit >= 10 ? 'a'-10 : '0') + digit; - } while (--j >= 0 && x != 0); - - for ( ; j >= 0; j--) - s[j] = pad; - - return n_digs; -} - -static __inline__ int dat_to_str(char* s, val_t x, int base = 16, char pad = '0') { - return dat_to_str<sizeof(val_t)*8>(s, dat_t<sizeof(val_t)*8>(x), base, pad); -} - -template <int w> -int fix_to_str(char* s, dat_t<w> x, int base = 16, char pad = '0') { - bool neg = x.msb(); - s[0] = neg; - int len = dat_to_str<w>(s+1, neg ? -x : x, base, pad); - return len+1; -} - -static __inline__ int flo_digits(int m, int e) { - return 2 + n_digits(m, 10) + 2 + n_digits(e, 10); -} - -template <int w> -int flo_to_str(char* s, dat_t<w> x, char pad = ' ') { - char buf[1000]; - int n_digs = (w == 32) ? flo_digits(32, 8) : flo_digits(52, 11); - double val = (w == 32) ? toFloat(x.values[0]) : toDouble(x.values[0]); - // sprintf(buf, "%d %d%*e", w, n_digs, n_digs, val); - sprintf(buf, "%*e", n_digs, val); - assert(strlen(buf) <= n_digs); - for (int i = 0; i < n_digs; i++) - s[i] = (i < strlen(buf)) ? buf[i] : pad; - s[n_digs] = 0; - // printf("N-DIGS = %d BUF %lu PAD %lu\n", n_digs, strlen(buf), n_digs-strlen(buf)); - // return strlen(buf); - return n_digs; -} - -template <int w> -int dat_as_str(char* s, const dat_t<w>& x) { - int i, j; - for (i = 0, j = (w/8-1)*8; i < w/8; i++, j -= 8) { - char ch = x.values[j/val_n_bits()] >> (j % val_n_bits()); - if (ch == 0) break; - s[i] = ch; - } - for ( ; i < w/8; i++) - s[i] = ' '; - return w/8; -} - -static __inline__ int dat_as_str(char* s, val_t x) { - return dat_as_str(s, dat_t<sizeof(val_t)*8>(x)); -} - -#if __cplusplus >= 201103L -static void __attribute__((unused)) dat_format(char* s, const char* fmt) -{ - for (char c; (c = *fmt); fmt++) { - if (c == '%' && *++fmt != '%') - abort(); - *s++ = c; - } -} - -template <typename T, typename... Args> -static void dat_format(char* s, const char* fmt, T value, Args... args) -{ - while (*fmt) { - if (*fmt == '%') { - switch(fmt[1]) { - case 'e': s += flo_to_str(s, value, ' '); break; - case 'h': s += dat_to_str(s, value, 16, '0'); break; - case 'b': s += dat_to_str(s, value, 2, '0'); break; - case 'd': s += dat_to_str(s, value, 10, ' '); break; - case 's': s += dat_as_str(s, value); break; - case '%': *s++ = '%'; break; - default: abort(); - } - return dat_format(s, fmt + 2, args...); - } else { - *s++ = *fmt++; - } - } - abort(); -} - -template <int w, typename... Args> -static dat_t<w> dat_format(const char* fmt, Args... args) -{ -#if BYTE_ORDER != LITTLE_ENDIAN -# error dat_format assumes a little-endian architecture -#endif - char str[w/8+1]; - dat_format(str, fmt, args...); - - dat_t<w> res; - res.values[res.n_words-1] = 0; - for (int i = 0; i < w/8; i++) - ((char*)res.values)[w/8-1-i] = str[i]; - return res; -} - -template <int w, typename... Args> -static ssize_t dat_fprintf(FILE *f, const char* fmt, Args... args) -{ - char str[w/8+1]; - dat_format(str, fmt, args...); - return fwrite(str, 1, w/8, f); -} - -template <int w, typename... Args> -static ssize_t dat_prints(std::ostream& s, const char* fmt, Args... args) -{ - char str[w/8+1]; - dat_format(str, fmt, args...); - s.write(str, w/8); - ssize_t ret = s.good() ? w/8 : -1; - return ret; -} -#endif /* C++11 */ - -template <int w, int sw> inline dat_t<w> DAT(dat_t<sw> dat) { - dat_t<w> res(dat); - return res; -} - -template <int w> inline dat_t<w> LIT(val_t value) { - return DAT<w>(value); -} - -template <int w> -inline dat_t<w> mux ( dat_t<1> t, dat_t<w> c, dat_t<w> a ) { - dat_t<w> mask; - bit_word_funs<val_n_words(w)>::fill(mask.values, -t.lo_word()); - return a ^ ((a ^ c) & mask); -} - -template <int w> -class datz_t : public dat_t<w> { - public: - dat_t<w> mask; - inline bool operator == ( dat_t<w> o ) { - dat_t<w> masked = (o & mask); - return (o & mask) == (dat_t<w>)*this; - } -}; - -template <int w> datz_t<w> inline LITZ(val_t value, val_t mask) { - datz_t<w> res; res.mask.values[0] = mask; res.values[0] = value; return res; -} - -template < int w, int w1, int w2 > -inline dat_t<w> cat(dat_t<w1> d1, dat_t<w2> d2) { - if (w <= val_n_bits() && w1 + w2 == w) - return DAT<w>(d1.values[0] << (w2 & (val_n_bits()-1)) | d2.values[0]); - return DAT<w>((DAT<w>(d1) << w2) | DAT<w>(d2)); -} - -template < int w1 > -inline dat_t<1> reduction_and(dat_t<w1> d) { - return DAT<1>(d == ~DAT<w1>(0)); -} - -template < int w1 > -inline dat_t<1> reduction_or(dat_t<w1> d) { - return DAT<1>(d != DAT<w1>(0)); -} - -// I am O(n) where n is number of bits in val_t. Future optimization would be log(n). -template < int w1 > -inline dat_t<1> reduction_xor(dat_t<w1> d) { - dat_t<1> res = DAT<1>(0); - val_t word = d.values[0]; - - for (int i = 1; i < d.n_words_of(); i++) - word ^= d.values[i]; - for (int i = 0; i < sizeof(val_t)*8; i++) { - res = res ^ DAT<1>(word & 1); - word = word >> 1; - } - - return res; -} - -template <int w, int d> -class mem_t { - public: - dat_t<w> contents[d]; - val_t dummy_seed; - val_t* seedp; - - int width() { - return w; - } - int length() { - return d; - } - - template <int iw> - dat_t<w> get (dat_t<iw> idx) { - return get(idx.lo_word() & (nextpow2_1(d)-1)); - } - dat_t<w> get (val_t idx) { - if (!ispow2(d) && idx >= d) { - dat_t<w> res; - res.randomize(seedp); - return res; - } - return contents[idx]; - } - val_t get (val_t idx, int word) { - if (!ispow2(d) && idx >= d) - return __rand_val(seedp) & (word == val_n_words(w) && val_n_word_bits(w) ? mask_val(w) : -1L); - return contents[idx].values[word]; - } - - template <int iw> - void put (dat_t<iw> idx, dat_t<w> val) { - put(idx.lo_word(), val); - } - void put (val_t idx, dat_t<w> val) { - if (ispow2(d) || idx < d) - contents[idx] = val; - } - val_t put (val_t idx, int word, val_t val) { - if (ispow2(d) || idx < d) - contents[idx].values[word] = val; - } - - void print ( void ) { - for (int j = 0; j < d/4; j++) { - for (int i = 0; i < 4; i++) { - int idx = j*4+i; - printf("|%2d: %16llx| ", idx, contents[idx].lo_word()); - } - printf("\n"); - } - } - mem_t<w,d> () { - dummy_seed = 1; - seedp = &dummy_seed; - for (int i = 0; i < d; i++) - contents[i] = DAT<w>(0); - } - void randomize(val_t* seed) { - seedp = seed; - for (int i = 0; i < d; i++) - contents[i].randomize(seed); - } - size_t read_hex(const char *hexFileName) { - ifstream ifp(hexFileName); - if (ifp.fail()) { - printf("[error] Unable to open hex data file %s\n", hexFileName); - return -1; - } - std::string hex_line; - dat_t<w> hex_dat; - for (int addr = 0; addr < d && !ifp.eof();) { - getline(ifp, hex_line); - if (dat_from_hex(hex_line, hex_dat) > 0) { - contents[addr++] = hex_dat; - } - } - ifp.close(); - return 0; - } -}; - -static __attribute__((unused)) char hex_to_char[] = "0123456789abcdef"; - -static int char_to_hex[] = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, - -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; - -// dat_from_hex: Read a hex value from a std::string into a given dat_t variable. -// Author: B. Richards, for parsing data formatted for Verilog $readmemh -// Arguments: -// hex_line A string containing hex numbers with embedded x, _ characters -// res A dat_t object to fill in with a return value -// offset Starting index in hex_line -// Return value: -// Success: returns next character offset -// Fail: 0 -template <int w> -size_t dat_from_hex(std::string hex_line, dat_t<w>& res, size_t offset = 0) { - size_t first_digit, last_digit, comment; - - // Scan for the hex data bounds. - comment = hex_line.find_first_of("/", offset); - first_digit = hex_line.find_first_of("0123456789abcdefABCDEF", offset); - if (first_digit == std::string::npos) return 0; - if (comment != std::string::npos && comment < first_digit) return 0; - last_digit = hex_line.find_first_not_of("0123456789abcdefABCDEF_xX", first_digit); - if (last_digit == std::string::npos) { - last_digit = hex_line.length() - 1; - } else { - last_digit--; - } - - // Convert the hex data to a dat_t, from right to left. - int digit_val; - val_t word_accum = 0; - int digit, w_index, bit; - for (digit = last_digit, w_index = 0, bit = 0; digit >= (int)first_digit && w_index < res.n_words; digit--) { - digit_val = char_to_hex[hex_line[digit]]; - if (digit_val >= 0) { - word_accum |= ((val_t)digit_val) << bit; - bit += 4; - if (bit == 64) { - res.values[w_index] = word_accum; - word_accum = 0L; - bit = 0; - w_index++; - } - } - } - if (bit != 0) { - res.values[w_index] = word_accum; - } - // Return a pointer to the character after the converted value. - return last_digit + 1; -} - -#pragma GCC push_options -#pragma GCC optimize ("no-stack-protector") - -template <int s, int w> -void dat_dump (FILE* f, const dat_t<w>& val, val_t name) { - size_t pos = 0; - char str[1 + w + 1 + s + 1]; - - str[pos++] = 'b'; - for (int i = 0; i < w; i++) - str[pos + w-i-1] = '0' + ((val.values[i/val_n_bits()] >> (i%val_n_bits())) & 1); - pos += w; - - str[pos++] = ' '; - for (int i = 0; i < s; i++) { - str[pos++] = name; - name >>= 8; - } - str[pos++] = '\n'; - - fwrite(str, 1, sizeof(str), f); -} - -#pragma GCC pop_options - -inline std::string read_tok(FILE* f) { - std::string res; - bool is_skipping = true; - for (;;) { - char c = fgetc(f); - if (feof(f)) - return res; - if (is_skipping) { - if (char_to_hex[c] != -1) { - res.push_back(c); - is_skipping = false; - } - } else { - if (char_to_hex[c] == -1) { - ungetc(c, f); - return res; - } - res.push_back(c); - } - } -} - -template <int s, int w, int d> -void dat_dump(FILE* file, const mem_t<w,d>& val, val_t name) { -} - -template <int w, int d> mem_t<w,d> MEM( void ); - -class mod_t { - public: - mod_t(): - dumpfile(NULL), - is_stale(false), - printStream() - {} - std::vector< mod_t* > children; - virtual void init ( val_t rand_init=false ) { }; - virtual void clock_lo ( dat_t<1> reset ) { }; - virtual void clock_hi ( dat_t<1> reset ) { }; - virtual int clock ( dat_t<1> reset ) { }; - virtual void setClocks ( std::vector< int >& periods ) { }; - - // Returns a clone of this object's circuit state (both registers and wires). - // Currently, it is undefined what happens to other state (like dumpfile and - // timestep), so use with care. - virtual mod_t* clone() = 0; - // Sets this module's circuit state (registers and wires) from the src mod_t. - // For mod_t subclasses, src must be the same class. - // Returns true on success, and false on failure. Currently, no guarantees - // are made about state consistency on failure, - virtual bool set_circuit_from(mod_t* src) = 0; - - virtual void print ( FILE* f ) { }; - virtual void print ( std::ostream& s ) { }; - virtual void dump ( FILE* f, int t ) { }; - - void set_dumpfile(FILE* f) { - dumpfile = f; - } - - int timestep; - - void dump () { - if (dumpfile != NULL) dump(dumpfile, timestep); - timestep += 1; - } - - int step (bool is_reset, int n) { - int delta = 0; - dat_t<1> reset = LIT<1>(is_reset); - for (int i = 0; i < n; i++) { - if (is_reset) { - clock_lo(reset); - } - // Collect any print output. - print(printStream); - dump(); - delta += clock(reset); - } - return delta; - } - - void mark_stale (void) { - is_stale = true; - } - - void propagate_changes (void) { - if (is_stale) clock_lo(LIT<1>(false)); - is_stale = false; - } - - int has_output(void) { - return printStream.tellp(); - } - - std::string drain_output(void) { - return printStream.str(); - } - - // Since we have an element with a deleted copy constructor - printStream, - // we need to provide our own explicit copy constructor. - mod_t(const mod_t& src) { - children = src.children; - timestep = src.timestep; - is_stale = src.is_stale; - dumpfile = src.dumpfile; - } - - protected: - bool is_stale; - FILE* dumpfile; - std::basic_ostringstream< char > printStream; -}; - -#define ASSERT(cond, msg) { \ - if (!(cond)) \ - throw std::runtime_error("Assertion failed: " msg); \ -} - -#pragma GCC diagnostic pop -#endif diff --git a/src/main/resources/sim_api.h b/src/main/resources/sim_api.h deleted file mode 100644 index f7789141..00000000 --- a/src/main/resources/sim_api.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef __SIM_API_H -#define __SIM_API_H - -#include <iostream> -#include <fstream> -#include <sstream> -#include <vector> -#include <map> - -enum SIM_CMD { RESET, STEP, UPDATE, POKE, PEEK, GETID, SETCLK, FIN }; - -template<class T> struct sim_data_t { - std::vector<T> resets; - std::vector<T> inputs; - std::vector<T> outputs; - std::vector<T> signals; - std::map<std::string, size_t> signal_map; - std::map<std::string, T> clk_map; -}; - -template <class T> class sim_api_t { -public: - void tick() { - static bool is_reset = false; - // First, Generates output tokens (in hex) - generate_tokens(); - if (is_reset) { - start(); - is_reset = false; - } - - // Next, handle commands from the testers - bool exit = false; - do { - size_t cmd; - std::cin >> std::dec >> cmd; - switch ((SIM_CMD) cmd) { - case RESET: - reset(); is_reset = true; exit = true; break; - case STEP: - consume_tokens(); - step(); exit = true; break; - case UPDATE: - consume_tokens(); - update(); exit = true; break; - case POKE: poke(); break; - case PEEK: peek(); break; - case GETID: getid(); break; - case SETCLK: setclk(); break; - case FIN: finish(); exit = true; break; - default: break; - } - } while (!exit); - } -private: - virtual void reset() = 0; - virtual void start() = 0; - virtual void finish() = 0; - virtual void update() = 0; - virtual void step() = 0; - // Consumes input tokens (in hex) - virtual void put_value(T& sig) = 0; - // Generate output tokens (in hex) - virtual void get_value(T& sig) = 0; - // Find a signal of path - virtual int search(std::string& path) { return -1; } - - void poke() { - size_t id; - std::cin >> std::dec >> id; - T obj = sim_data.signals[id]; - if (obj) { - put_value(obj); - } else { - std::cout << "Cannot find the object of id = " << id << std::endl; - finish(); - exit(0); - } - } - - void peek() { - size_t id; - std::cin >> std::dec >> id; - T obj = sim_data.signals[id]; - if (obj) { - get_value(obj); - } else { - std::cout << "Cannot find the object of id = " << id << std::endl; - finish(); - exit(0); - } - } - - void getid() { - std::string wire; - std::cin >> wire; - std::map<std::string, size_t>::iterator it = sim_data.signal_map.find(wire); - if (it != sim_data.signal_map.end()) { - std::cerr << it->second << std::endl; - } else { - int id = search(wire); - if (id < 0) { - std::cout << "Cannot find the object, " << wire<< std::endl; - finish(); - exit(0); - } - std::cerr << id << std::endl; - } - } - - void setclk() { - std::string clkname; - std::cin >> clkname; - typename std::map<std::string, T>::iterator it = sim_data.clk_map.find(clkname); - if (it != sim_data.clk_map.end()) { - put_value(it->second); - } else { - std::cout << "Cannot find " << clkname << std::endl; - } - } - - void consume_tokens() { - for (size_t i = 0 ; i < sim_data.inputs.size() ; i++) { - put_value(sim_data.inputs[i]); - } - } - - void generate_tokens() { - for (size_t i = 0 ; i < sim_data.outputs.size() ; i++) { - get_value(sim_data.outputs[i]); - } - } -protected: - sim_data_t<T> sim_data; - - void read_signal_map(std::string filename) { - std::ifstream file(filename.c_str()); - if (!file) { - std::cout << "Cannot open " << filename << std::endl; - finish(); - exit(0); - } - std::string line; - size_t id = 0; - while (std::getline(file, line)) { - std::istringstream iss(line); - std::string path; - size_t width, n; - iss >> path >> width >> n; - sim_data.signal_map[path] = id; - id += n; - } - } -}; - -#endif //__SIM_API_H |
