#ifndef HALIDE_TRACE_CONFIG_H #define HALIDE_TRACE_CONFIG_H #include #include #include #include #include #include #include #include "HalideRuntime.h" namespace Halide { namespace Trace { using ErrorFunc = std::function; inline void default_error(const std::string &err) { std::cerr << "Error: " << err << "\n"; exit(1); } inline std::string replace_all(const std::string &str, const std::string &find, const std::string &replace) { size_t pos = 0; std::string result = str; while ((pos = result.find(find, pos)) != std::string::npos) { result.replace(pos, find.length(), replace); pos += replace.length(); } return result; } inline std::string escape_spaces(const std::string &str) { // Note: if the source string already contains '\x20', we'll // end up unescaping that back into a space. That's acceptable. return replace_all(str, " ", "\\x20"); } inline std::string unescape_spaces(const std::string &str) { // Note: if the source string already contains '\x20', we'll // end up unescaping that back into a space. That's acceptable. return replace_all(str, "\\x20", " "); } inline std::ostream &operator<<(std::ostream &os, const halide_type_t &t) { os << (int)t.code << " " << (int)t.bits << " " << t.lanes; return os; } inline std::istream &operator>>(std::istream &is, halide_type_t &t) { // type.code is an enum; type.bits is a uint8 and might be read as char. int type_code, type_bits; is >> type_code >> type_bits >> t.lanes; t.code = (halide_type_code_t)type_code; t.bits = (uint8_t)type_bits; return is; } template std::ostream &operator<<(std::ostream &os, const std::vector &v) { os << v.size() << " "; for (const T &t : v) { os << t << " "; } return os; } template std::istream &operator>>(std::istream &is, std::vector &v) { v.clear(); size_t size; is >> size; for (size_t i = 0; i < size; ++i) { T tmp; is >> tmp; v.push_back(tmp); } return is; } struct Point { int x = 0, y = 0; Point() = default; Point(int x, int y) : x(x), y(y) { } friend std::ostream &operator<<(std::ostream &os, const Point &pt) { os << pt.x << " " << pt.y; return os; } friend std::istream &operator>>(std::istream &is, Point &pt) { is >> pt.x >> pt.y; return is; } }; // A struct specifying a text label that will appear on the screen at some point. struct Label { std::string text; Point pos; int fade_in_frames = 0; float h_scale = 1.0f; Label() = default; Label(const std::string &text, const Point &pos = {0, 0}, int fade_in_frames = 0, float h_scale = 1.f) : text(text), pos(pos), fade_in_frames(fade_in_frames), h_scale(h_scale) { } friend std::ostream &operator<<(std::ostream &os, const Label &label) { os << escape_spaces(label.text) << " " << label.pos << " " << label.fade_in_frames << " " << label.h_scale; return os; } friend std::istream &operator>>(std::istream &is, Label &label) { is >> label.text >> label.pos >> label.fade_in_frames >> label.h_scale; label.text = unescape_spaces(label.text); return is; } }; // Configuration for how a func should be rendered in HalideTraceViz. struct FuncConfig { // Note that every field in this struct is initialized to a value which // means "no value specified"; this is allows us to merge configs // from several sources (auto-layout, embedded trace-tags, and command-line) // in a way that we can selectively add or override some-but-not-all configuration // values (e.g., use auto-layout's positioning, but customizing labels // and changing rgb vs gray rendering). In all cases, if a field is // the initial "no value specified" value at rendering time, HalideTraceViz // will choose a reasonable value for that field. // Each value of a Func will draw as a zoom x zoom // box in the output. Fractional values are allowed. // // Valid values: 0.0 < zoom <= HUGEVAL or so float zoom = -1.f; // Each load from a Func costs the given number of ticks. // Legal values are 0.0 < zoom <= 1000 or so // // Valid values: load_cost >= 0 int load_cost = -1; // Each store to a Func costs the given number of ticks. // // Valid values: store_cost >= 0 int store_cost = -1; // The position on the screen corresponding to the Func's 0, 0 coordinate. // // Valid values: pos.x and pos.y > std::numeric_limits::lowest() Point pos = {std::numeric_limits::lowest(), std::numeric_limits::lowest()}; // Specifies the matrix that maps the coordinates of the // Func to screen pixels. Specified column major. For example, // { {1, 0}, {0, 1}, {0, 0} } specifies that the Func has three // dimensions where the first one maps to screen-space x // coordinates, the second one maps to screen-space y coordinates, // and the third one does not affect screen-space coordinates. // // Valid values: strize.size() > 0 std::vector strides; // Specify the dimension to use for rendering the color channels of the Func. // // Valid values: color_dim == -1 -> render as grayscale // color_dim >= 0 -> render as RGB using that dimension as color channel int color_dim = -2; // The minimum value taken on by a Func; maps to black. // TODO: this doesn't give enough range to allow for the full range of int64 or uint64. Do we care? // // Valid values: min-of-type <= min <= max-of-type double min = std::numeric_limits::quiet_NaN(); // The maximum value taken on by a Func; maps to white. // TODO: this doesn't give enough range to allow for the full range of int64 or uint64. Do we care? // // Valid values: min-of-type <= min <= max-of-type double max = std::numeric_limits::quiet_NaN(); // Label(s) to be rendered with the Func. The Label's position // is an offset from the Func's position, so (0, 0) means render // at the top-left of the Func itself. // // Valid values: Any std::vector