summaryrefslogtreecommitdiff
path: root/src/main/resources/emulator_api.h
diff options
context:
space:
mode:
authorAdam Izraelevitz2015-10-01 07:41:29 -0700
committerAdam Izraelevitz2015-10-01 07:41:29 -0700
commitec8de0e596e769b916d1a87908081d9826aa1271 (patch)
tree0b008a0855e7ee444299e247eff8a3b278eae577 /src/main/resources/emulator_api.h
parent16f00d0947b9c9ebb3b30e040834eb79fcb14f46 (diff)
parenta1fdffe5ad740e1a6b496456c9011507e0d61874 (diff)
Merge pull request #11 from ucb-bar/removemu
Remove unused emulator C++ headers
Diffstat (limited to 'src/main/resources/emulator_api.h')
-rw-r--r--src/main/resources/emulator_api.h684
1 files changed, 0 insertions, 684 deletions
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