diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index fb8db22654b..57d57bc2809 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -93,6 +93,7 @@ void SetupVPR(const t_options* Options, FileNameOpts->PowerFile = Options->PowerFile; FileNameOpts->CmosTechFile = Options->CmosTechFile; FileNameOpts->out_file_prefix = Options->out_file_prefix; + FileNameOpts->read_vpr_constraints_file = Options->read_vpr_constraints_file; FileNameOpts->verify_file_digests = Options->verify_file_digests; diff --git a/vpr/src/base/ShowSetup.cpp b/vpr/src/base/ShowSetup.cpp index 62702376bfc..6b487ca94c6 100644 --- a/vpr/src/base/ShowSetup.cpp +++ b/vpr/src/base/ShowSetup.cpp @@ -31,6 +31,7 @@ void ShowSetup(const t_vpr_setup& vpr_setup) { VTR_LOG("Circuit placement file: %s\n", vpr_setup.FileNameOpts.PlaceFile.c_str()); VTR_LOG("Circuit routing file: %s\n", vpr_setup.FileNameOpts.RouteFile.c_str()); VTR_LOG("Circuit SDC file: %s\n", vpr_setup.Timing.SDCFile.c_str()); + VTR_LOG("Vpr Constraints file: %s\n", vpr_setup.FileNameOpts.read_vpr_constraints_file.c_str()); VTR_LOG("\n"); VTR_LOG("Packer: %s\n", (vpr_setup.PackerOpts.doPacking ? "ENABLED" : "DISABLED")); diff --git a/vpr/src/base/constraints_load.cpp b/vpr/src/base/constraints_load.cpp new file mode 100644 index 00000000000..4cdf5b1d579 --- /dev/null +++ b/vpr/src/base/constraints_load.cpp @@ -0,0 +1,81 @@ +#include "constraints_load.h" + +static void print_region(FILE* fp, Region region); +static void print_partition(FILE* fp, Partition part); +static void print_partition_region(FILE* fp, PartitionRegion pr); +static void print_constraints(FILE* fp, VprConstraints constraints, int num_parts); + +void print_region(FILE* fp, Region region) { + vtr::Rect rect = region.get_region_rect(); + int xmin = rect.xmin(); + int xmax = rect.xmax(); + int ymin = rect.ymin(); + int ymax = rect.ymax(); + int subtile = region.get_sub_tile(); + + fprintf(fp, "\tRegion: \n"); + fprintf(fp, "\txmin: %d\n", xmin); + fprintf(fp, "\txmax: %d\n", xmax); + fprintf(fp, "\tymin: %d\n", ymin); + fprintf(fp, "\tymax: %d\n", ymax); + fprintf(fp, "\tsubtile: %d\n\n", subtile); +} + +void print_partition(FILE* fp, Partition part) { + std::string name = part.get_name(); + fprintf(fp, "\npartition_name: %s\n", name.c_str()); + + PartitionRegion pr = part.get_part_region(); + + print_partition_region(fp, pr); +} + +void print_partition_region(FILE* fp, PartitionRegion pr) { + std::vector part_region = pr.get_partition_region(); + + int pr_size = part_region.size(); + + fprintf(fp, "\tNumber of regions in partition is: %d\n", pr_size); + + for (unsigned int i = 0; i < part_region.size(); i++) { + print_region(fp, part_region[i]); + } +} + +void print_constraints(FILE* fp, VprConstraints constraints, int num_parts) { + Partition temp_part; + std::vector atoms; + + for (int i = 0; i < num_parts; i++) { + PartitionId part_id(i); + + temp_part = constraints.get_partition(part_id); + + print_partition(fp, temp_part); + + atoms = constraints.get_part_atoms(part_id); + + int atoms_size = atoms.size(); + + fprintf(fp, "\tAtom vector size is %d\n", atoms_size); + fprintf(fp, "\tIds of atoms in partition: \n"); + for (unsigned int j = 0; j < atoms.size(); j++) { + AtomBlockId atom_id = atoms[j]; + fprintf(fp, "\t#%zu\n", size_t(atom_id)); + } + } +} + +void echo_constraints(char* filename, VprConstraints constraints, int num_parts) { + FILE* fp; + fp = vtr::fopen(filename, "w"); + + fprintf(fp, "--------------------------------------------------------------\n"); + fprintf(fp, "Constraints\n"); + fprintf(fp, "--------------------------------------------------------------\n"); + fprintf(fp, "\n"); + fprintf(fp, "\n Number of partitions is %d \n", num_parts); + print_constraints(fp, constraints, num_parts); + + fclose(fp); +} diff --git a/vpr/src/base/constraints_load.h b/vpr/src/base/constraints_load.h new file mode 100644 index 00000000000..f95fbe40c0d --- /dev/null +++ b/vpr/src/base/constraints_load.h @@ -0,0 +1,12 @@ +#ifndef CONSTRAINTS_LOAD_H_ +#define CONSTRAINTS_LOAD_H_ + +#include "region.h" +#include "partition.h" +#include "partition_region.h" +#include "vpr_constraints.h" +#include "vtr_vector.h" + +void echo_constraints(char* filename, VprConstraints constraints, int num_parts); + +#endif diff --git a/vpr/src/base/echo_files.cpp b/vpr/src/base/echo_files.cpp index ca628c24cb8..b294af97874 100644 --- a/vpr/src/base/echo_files.cpp +++ b/vpr/src/base/echo_files.cpp @@ -71,6 +71,9 @@ void alloc_and_load_echo_file_info() { setEchoFileName(E_ECHO_ATOM_NETLIST_ORIG, "atom_netlist.orig.echo.blif"); setEchoFileName(E_ECHO_ATOM_NETLIST_CLEANED, "atom_netlist.cleaned.echo.blif"); + //Vpr constraints + setEchoFileName(E_ECHO_VPR_CONSTRAINTS, "vpr_constraints.echo"); + //Intra-block routing setEchoFileName(E_ECHO_INTRA_LB_FAILED_ROUTE, "intra_lb_failed_route.echo"); diff --git a/vpr/src/base/echo_files.h b/vpr/src/base/echo_files.h index 799d06a88e9..6c4e548ab76 100644 --- a/vpr/src/base/echo_files.h +++ b/vpr/src/base/echo_files.h @@ -10,6 +10,7 @@ enum e_echo_files { E_ECHO_PRE_PACKING_SLACK, E_ECHO_PRE_PACKING_CRITICALITY, E_ECHO_PRE_PACKING_MOLECULES_AND_PATTERNS, + E_ECHO_VPR_CONSTRAINTS, // Intra-block routing E_ECHO_INTRA_LB_FAILED_ROUTE, diff --git a/vpr/src/base/gen/README.gen.md b/vpr/src/base/gen/README.gen.md new file mode 100644 index 00000000000..a237dba3ec7 --- /dev/null +++ b/vpr/src/base/gen/README.gen.md @@ -0,0 +1,3 @@ +`vpr_constraints_uxsdcxx.h`and +`vpr_constraints_uxsdcxx_interface.h` are generated via uxsdcxx and are checked in to +avoid requiring python3 and the uxsdcxx depedencies to build VPR. diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h new file mode 100644 index 00000000000..7f3bf755295 --- /dev/null +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx.h @@ -0,0 +1,857 @@ +#pragma once +/* + * This file is generated by uxsdcxx 0.1.0. + * https://github.com/duck2/uxsdcxx + * Modify only if your build process doesn't involve regenerating this file. + * + * Cmdline: uxsdcxx.py ../vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * Input file: /home/khalid88/Documents/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * md5sum of input file: 3e1f2692931484aa45dce794ba723aa9 + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "pugixml.hpp" + +#include "vpr_constraints_uxsdcxx_interface.h" +/* All uxsdcxx functions and structs live in this namespace. */ +namespace uxsd { + +/** + * Internal function for getting line and column number from file based on + * byte offset. + */ +inline void get_line_number(const char* filename, std::ptrdiff_t offset, int* line, int* col); + +[[noreturn]] inline void noreturn_report(const std::function* report_error, const char* msg) { + (*report_error)(msg); + throw std::runtime_error("Unreachable!"); +} + +/* Declarations for internal load functions for the complex types. */ +template +inline void load_add_atom(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_add_region(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +inline void load_add_region_required_attributes(const pugi::xml_node& root, int* x_high, int* x_low, int* y_high, int* y_low, const std::function* report_error); +template +inline void load_partition(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_partition_list(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); +template +inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug); + +/* Declarations for internal write functions for the complex types. */ +template +inline void write_partition(T& in, std::ostream& os, const void* data, void* iter); +template +inline void write_partition_list(T& in, std::ostream& os, const void* data, void* iter); +template +inline void write_vpr_constraints(T& in, std::ostream& os, const void* data, void* iter); + +/* Load function for the root element. */ +template +inline void load_vpr_constraints_xml(T& out, Context& context, const char* filename, std::istream& is) { + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load(is); + if (!result) { + int line, col; + get_line_number(filename, result.offset, &line, &col); + std::stringstream msg; + msg << "Unable to load XML file '" << filename << "', "; + msg << result.description() << " (line: " << line; + msg << " col: " << col << ")"; + out.error_encountered(filename, line, msg.str().c_str()); + } + ptrdiff_t offset_debug = 0; + std::function report_error = [filename, &out, &offset_debug](const char* message) { + int line, col; + get_line_number(filename, offset_debug, &line, &col); + out.error_encountered(filename, line, message); + // If error_encountered didn't throw, throw now to unwind. + throw std::runtime_error(message); + }; + out.start_load(&report_error); + + for (pugi::xml_node node = doc.first_child(); node; node = node.next_sibling()) { + if (std::strcmp(node.name(), "vpr_constraints") == 0) { + /* If errno is set up to this point, it messes with strtol errno checking. */ + errno = 0; + load_vpr_constraints(node, out, context, &report_error, &offset_debug); + } else { + offset_debug = node.offset_debug(); + report_error(("Invalid root-level element " + std::string(node.name())).c_str()); + } + } + out.finish_load(); +} + +/* Write function for the root element. */ +template +inline void write_vpr_constraints_xml(T& in, Context& context, std::ostream& os) { + in.start_write(); + os << "\n"; + write_vpr_constraints(in, os, context); + os << "\n"; + in.finish_write(); +} + +typedef const uint32_t __attribute__((aligned(1))) triehash_uu32; +typedef const uint64_t __attribute__((aligned(1))) triehash_uu64; +static_assert(alignof(triehash_uu32) == 1, "Unaligned 32-bit access not found."); +static_assert(alignof(triehash_uu64) == 1, "Unaligned 64-bit access not found."); +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define onechar(c, s, l) (((uint64_t)(c)) << (s)) +#else +# define onechar(c, s, l) (((uint64_t)(c)) << (l - 8 - s)) +#endif + +/* Tokens for attribute and node names. */ + +enum class atok_t_add_atom { NAME_PATTERN }; +constexpr const char* atok_lookup_t_add_atom[] = {"name_pattern"}; + +enum class atok_t_add_region { SUBTILE, + X_HIGH, + X_LOW, + Y_HIGH, + Y_LOW }; +constexpr const char* atok_lookup_t_add_region[] = {"subtile", "x_high", "x_low", "y_high", "y_low"}; + +enum class gtok_t_partition { ADD_ATOM, + ADD_REGION }; +constexpr const char* gtok_lookup_t_partition[] = {"add_atom", "add_region"}; +enum class atok_t_partition { NAME }; +constexpr const char* atok_lookup_t_partition[] = {"name"}; + +enum class gtok_t_partition_list { PARTITION }; +constexpr const char* gtok_lookup_t_partition_list[] = {"partition"}; +enum class gtok_t_vpr_constraints { PARTITION_LIST }; +constexpr const char* gtok_lookup_t_vpr_constraints[] = {"partition_list"}; +enum class atok_t_vpr_constraints { TOOL_NAME }; +constexpr const char* atok_lookup_t_vpr_constraints[] = {"tool_name"}; + +/* Internal lexers. These convert the PugiXML node names to input tokens. */ +inline atok_t_add_atom lex_attr_t_add_atom(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 12: + switch (*((triehash_uu64*)&in[0])) { + case onechar('n', 0, 64) | onechar('a', 8, 64) | onechar('m', 16, 64) | onechar('e', 24, 64) | onechar('_', 32, 64) | onechar('p', 40, 64) | onechar('a', 48, 64) | onechar('t', 56, 64): + switch (*((triehash_uu32*)&in[8])) { + case onechar('t', 0, 32) | onechar('e', 8, 32) | onechar('r', 16, 32) | onechar('n', 24, 32): + return atok_t_add_atom::NAME_PATTERN; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +} + +inline atok_t_add_region lex_attr_t_add_region(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 5: + switch (*((triehash_uu32*)&in[0])) { + case onechar('x', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('o', 24, 32): + switch (in[4]) { + case onechar('w', 0, 8): + return atok_t_add_region::X_LOW; + break; + default: + break; + } + break; + case onechar('y', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('o', 24, 32): + switch (in[4]) { + case onechar('w', 0, 8): + return atok_t_add_region::Y_LOW; + break; + default: + break; + } + break; + default: + break; + } + break; + case 6: + switch (*((triehash_uu32*)&in[0])) { + case onechar('x', 0, 32) | onechar('_', 8, 32) | onechar('h', 16, 32) | onechar('i', 24, 32): + switch (in[4]) { + case onechar('g', 0, 8): + switch (in[5]) { + case onechar('h', 0, 8): + return atok_t_add_region::X_HIGH; + break; + default: + break; + } + break; + default: + break; + } + break; + case onechar('y', 0, 32) | onechar('_', 8, 32) | onechar('h', 16, 32) | onechar('i', 24, 32): + switch (in[4]) { + case onechar('g', 0, 8): + switch (in[5]) { + case onechar('h', 0, 8): + return atok_t_add_region::Y_HIGH; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + case 7: + switch (*((triehash_uu32*)&in[0])) { + case onechar('s', 0, 32) | onechar('u', 8, 32) | onechar('b', 16, 32) | onechar('t', 24, 32): + switch (in[4]) { + case onechar('i', 0, 8): + switch (in[5]) { + case onechar('l', 0, 8): + switch (in[6]) { + case onechar('e', 0, 8): + return atok_t_add_region::SUBTILE; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +} + +inline gtok_t_partition lex_node_t_partition(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 8: + switch (*((triehash_uu64*)&in[0])) { + case onechar('a', 0, 64) | onechar('d', 8, 64) | onechar('d', 16, 64) | onechar('_', 24, 64) | onechar('a', 32, 64) | onechar('t', 40, 64) | onechar('o', 48, 64) | onechar('m', 56, 64): + return gtok_t_partition::ADD_ATOM; + break; + default: + break; + } + break; + case 10: + switch (*((triehash_uu64*)&in[0])) { + case onechar('a', 0, 64) | onechar('d', 8, 64) | onechar('d', 16, 64) | onechar('_', 24, 64) | onechar('r', 32, 64) | onechar('e', 40, 64) | onechar('g', 48, 64) | onechar('i', 56, 64): + switch (in[8]) { + case onechar('o', 0, 8): + switch (in[9]) { + case onechar('n', 0, 8): + return gtok_t_partition::ADD_REGION; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +} +inline atok_t_partition lex_attr_t_partition(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 4: + switch (*((triehash_uu32*)&in[0])) { + case onechar('n', 0, 32) | onechar('a', 8, 32) | onechar('m', 16, 32) | onechar('e', 24, 32): + return atok_t_partition::NAME; + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +} + +inline gtok_t_partition_list lex_node_t_partition_list(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 9: + switch (*((triehash_uu64*)&in[0])) { + case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('r', 16, 64) | onechar('t', 24, 64) | onechar('i', 32, 64) | onechar('t', 40, 64) | onechar('i', 48, 64) | onechar('o', 56, 64): + switch (in[8]) { + case onechar('n', 0, 8): + return gtok_t_partition_list::PARTITION; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +} + +inline gtok_t_vpr_constraints lex_node_t_vpr_constraints(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 14: + switch (*((triehash_uu64*)&in[0])) { + case onechar('p', 0, 64) | onechar('a', 8, 64) | onechar('r', 16, 64) | onechar('t', 24, 64) | onechar('i', 32, 64) | onechar('t', 40, 64) | onechar('i', 48, 64) | onechar('o', 56, 64): + switch (*((triehash_uu32*)&in[8])) { + case onechar('n', 0, 32) | onechar('_', 8, 32) | onechar('l', 16, 32) | onechar('i', 24, 32): + switch (in[12]) { + case onechar('s', 0, 8): + switch (in[13]) { + case onechar('t', 0, 8): + return gtok_t_vpr_constraints::PARTITION_LIST; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized child " + std::string(in) + " of .").c_str()); +} +inline atok_t_vpr_constraints lex_attr_t_vpr_constraints(const char* in, const std::function* report_error) { + unsigned int len = strlen(in); + switch (len) { + case 9: + switch (*((triehash_uu64*)&in[0])) { + case onechar('t', 0, 64) | onechar('o', 8, 64) | onechar('o', 16, 64) | onechar('l', 24, 64) | onechar('_', 32, 64) | onechar('n', 40, 64) | onechar('a', 48, 64) | onechar('m', 56, 64): + switch (in[8]) { + case onechar('e', 0, 8): + return atok_t_vpr_constraints::TOOL_NAME; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + noreturn_report(report_error, ("Found unrecognized attribute " + std::string(in) + " of .").c_str()); +} + +/** + * Internal error function for xs:choice and xs:sequence validators. + */ +[[noreturn]] inline void dfa_error(const char* wrong, const int* states, const char* const* lookup, int len, const std::function* report_error); + +/** + * Internal error function for xs:all validators. + */ +template +[[noreturn]] inline void all_error(std::bitset gstate, const char* const* lookup, const std::function* report_error); + +/** + * Internal error function for attribute validators. + */ +template +[[noreturn]] inline void attr_error(std::bitset astate, const char* const* lookup, const std::function* report_error); + +/* Internal loading functions, which validate and load a PugiXML DOM tree into memory. */ +inline int load_int(const char* in, const std::function* report_error) { + int out; + out = std::strtol(in, NULL, 10); + if (errno != 0) + noreturn_report(report_error, ("Invalid value `" + std::string(in) + "` when loading into a int.").c_str()); + return out; +} +inline void load_add_region_required_attributes(const pugi::xml_node& root, int* x_high, int* x_low, int* y_high, int* y_low, const std::function* report_error) { + std::bitset<5> astate = 0; + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_add_region in = lex_attr_t_add_region(attr.name(), report_error); + if (astate[(int)in] == 0) + astate[(int)in] = 1; + else + noreturn_report(report_error, ("Duplicate attribute " + std::string(attr.name()) + " in .").c_str()); + switch (in) { + case atok_t_add_region::SUBTILE: + /* Attribute subtile set after element init */ + break; + case atok_t_add_region::X_HIGH: + *x_high = load_int(attr.value(), report_error); + break; + case atok_t_add_region::X_LOW: + *x_low = load_int(attr.value(), report_error); + break; + case atok_t_add_region::Y_HIGH: + *y_high = load_int(attr.value(), report_error); + break; + case atok_t_add_region::Y_LOW: + *y_low = load_int(attr.value(), report_error); + break; + default: + break; /* Not possible. */ + } + } + std::bitset<5> test_astate = astate | std::bitset<5>(0b00001); + if (!test_astate.all()) attr_error(test_astate, atok_lookup_t_add_region, report_error); +} +template +inline void load_add_atom(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_add_atom in = lex_attr_t_add_atom(attr.name(), report_error); + switch (in) { + case atok_t_add_atom::NAME_PATTERN: + out.set_add_atom_name_pattern(attr.value(), context); + break; + default: + break; /* Not possible. */ + } + } + + if (root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); +} + +template +inline void load_add_region(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_add_region in = lex_attr_t_add_region(attr.name(), report_error); + switch (in) { + case atok_t_add_region::SUBTILE: + out.set_add_region_subtile(load_int(attr.value(), report_error), context); + break; + case atok_t_add_region::X_HIGH: + /* Attribute x_high is already set */ + break; + case atok_t_add_region::X_LOW: + /* Attribute x_low is already set */ + break; + case atok_t_add_region::Y_HIGH: + /* Attribute y_high is already set */ + break; + case atok_t_add_region::Y_LOW: + /* Attribute y_low is already set */ + break; + default: + break; /* Not possible. */ + } + } + + if (root.first_child().type() == pugi::node_element) + noreturn_report(report_error, "Unexpected child element in ."); +} + +constexpr int NUM_T_PARTITION_STATES = 3; +constexpr const int NUM_T_PARTITION_INPUTS = 2; +constexpr int gstate_t_partition[NUM_T_PARTITION_STATES][NUM_T_PARTITION_INPUTS] = { + {-1, 0}, + {1, 0}, + {1, -1}, +}; +template +inline void load_partition(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_partition in = lex_attr_t_partition(attr.name(), report_error); + switch (in) { + case atok_t_partition::NAME: + out.set_partition_name(attr.value(), context); + break; + default: + break; /* Not possible. */ + } + } + + // Preallocate arrays by counting child nodes (if any) + size_t add_atom_count = 0; + size_t add_region_count = 0; + { + int next, state = 2; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_partition in = lex_node_t_partition(node.name(), report_error); + next = gstate_t_partition[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_partition[(int)in], gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); + state = next; + switch (in) { + case gtok_t_partition::ADD_ATOM: + add_atom_count += 1; + break; + case gtok_t_partition::ADD_REGION: + add_region_count += 1; + break; + default: + break; /* Not possible. */ + } + } + + out.preallocate_partition_add_atom(context, add_atom_count); + out.preallocate_partition_add_region(context, add_region_count); + } + int next, state = 2; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_partition in = lex_node_t_partition(node.name(), report_error); + next = gstate_t_partition[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_partition[(int)in], gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); + state = next; + switch (in) { + case gtok_t_partition::ADD_ATOM: { + auto child_context = out.add_partition_add_atom(context); + load_add_atom(node, out, child_context, report_error, offset_debug); + out.finish_partition_add_atom(child_context); + } break; + case gtok_t_partition::ADD_REGION: { + int add_region_x_high; + memset(&add_region_x_high, 0, sizeof(add_region_x_high)); + int add_region_x_low; + memset(&add_region_x_low, 0, sizeof(add_region_x_low)); + int add_region_y_high; + memset(&add_region_y_high, 0, sizeof(add_region_y_high)); + int add_region_y_low; + memset(&add_region_y_low, 0, sizeof(add_region_y_low)); + load_add_region_required_attributes(node, &add_region_x_high, &add_region_x_low, &add_region_y_high, &add_region_y_low, report_error); + auto child_context = out.add_partition_add_region(context, add_region_x_high, add_region_x_low, add_region_y_high, add_region_y_low); + load_add_region(node, out, child_context, report_error, offset_debug); + out.finish_partition_add_region(child_context); + } break; + default: + break; /* Not possible. */ + } + } + if (state != 0) dfa_error("end of input", gstate_t_partition[state], gtok_lookup_t_partition, 2, report_error); +} + +constexpr int NUM_T_PARTITION_LIST_STATES = 2; +constexpr const int NUM_T_PARTITION_LIST_INPUTS = 1; +constexpr int gstate_t_partition_list[NUM_T_PARTITION_LIST_STATES][NUM_T_PARTITION_LIST_INPUTS] = { + {0}, + {0}, +}; +template +inline void load_partition_list(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + if (root.first_attribute()) + noreturn_report(report_error, "Unexpected attribute in ."); + + // Preallocate arrays by counting child nodes (if any) + size_t partition_count = 0; + { + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_partition_list in = lex_node_t_partition_list(node.name(), report_error); + next = gstate_t_partition_list[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_partition_list[(int)in], gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); + state = next; + switch (in) { + case gtok_t_partition_list::PARTITION: + partition_count += 1; + break; + default: + break; /* Not possible. */ + } + } + + out.preallocate_partition_list_partition(context, partition_count); + } + int next, state = 1; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_partition_list in = lex_node_t_partition_list(node.name(), report_error); + next = gstate_t_partition_list[state][(int)in]; + if (next == -1) + dfa_error(gtok_lookup_t_partition_list[(int)in], gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); + state = next; + switch (in) { + case gtok_t_partition_list::PARTITION: { + auto child_context = out.add_partition_list_partition(context); + load_partition(node, out, child_context, report_error, offset_debug); + out.finish_partition_list_partition(child_context); + } break; + default: + break; /* Not possible. */ + } + } + if (state != 0) dfa_error("end of input", gstate_t_partition_list[state], gtok_lookup_t_partition_list, 1, report_error); +} + +template +inline void load_vpr_constraints(const pugi::xml_node& root, T& out, Context& context, const std::function* report_error, ptrdiff_t* offset_debug) { + (void)root; + (void)out; + (void)context; + (void)report_error; + // Update current file offset in case an error is encountered. + *offset_debug = root.offset_debug(); + + for (pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()) { + atok_t_vpr_constraints in = lex_attr_t_vpr_constraints(attr.name(), report_error); + switch (in) { + case atok_t_vpr_constraints::TOOL_NAME: + out.set_vpr_constraints_tool_name(attr.value(), context); + break; + default: + break; /* Not possible. */ + } + } + + std::bitset<1> gstate = 0; + for (pugi::xml_node node = root.first_child(); node; node = node.next_sibling()) { + *offset_debug = node.offset_debug(); + gtok_t_vpr_constraints in = lex_node_t_vpr_constraints(node.name(), report_error); + if (gstate[(int)in] == 0) + gstate[(int)in] = 1; + else + noreturn_report(report_error, ("Duplicate element " + std::string(node.name()) + " in .").c_str()); + switch (in) { + case gtok_t_vpr_constraints::PARTITION_LIST: { + auto child_context = out.init_vpr_constraints_partition_list(context); + load_partition_list(node, out, child_context, report_error, offset_debug); + out.finish_vpr_constraints_partition_list(child_context); + } break; + default: + break; /* Not possible. */ + } + } + std::bitset<1> test_gstate = gstate | std::bitset<1>(0b0); + if (!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_vpr_constraints, report_error); +} + +/* Internal writing functions, which uxsdcxx uses to write out a class. */ +template +inline void write_partition(T& in, std::ostream& os, Context& context) { + (void)in; + (void)os; + (void)context; + { + for (size_t i = 0, n = in.num_partition_add_atom(context); i < n; i++) { + auto child_context = in.get_partition_add_atom(i, context); + os << "\n"; + } + } + { + for (size_t i = 0, n = in.num_partition_add_region(context); i < n; i++) { + auto child_context = in.get_partition_add_region(i, context); + os << "\n"; + } + } +} + +template +inline void write_partition_list(T& in, std::ostream& os, Context& context) { + (void)in; + (void)os; + (void)context; + { + for (size_t i = 0, n = in.num_partition_list_partition(context); i < n; i++) { + auto child_context = in.get_partition_list_partition(i, context); + os << ""; + write_partition(in, os, child_context); + os << "\n"; + } + } +} + +template +inline void write_vpr_constraints(T& in, std::ostream& os, Context& context) { + (void)in; + (void)os; + (void)context; + { + auto child_context = in.get_vpr_constraints_partition_list(context); + os << "\n"; + write_partition_list(in, os, child_context); + os << "\n"; + } +} + +inline void dfa_error(const char* wrong, const int* states, const char* const* lookup, int len, const std::function* report_error) { + std::vector expected; + for (int i = 0; i < len; i++) { + if (states[i] != -1) expected.push_back(lookup[i]); + } + + std::string expected_or = expected[0]; + for (unsigned int i = 1; i < expected.size(); i++) + expected_or += std::string(" or ") + expected[i]; + + noreturn_report(report_error, ("Expected " + expected_or + ", found " + std::string(wrong)).c_str()); +} + +template +inline void all_error(std::bitset gstate, const char* const* lookup, const std::function* report_error) { + std::vector missing; + for (unsigned int i = 0; i < N; i++) { + if (gstate[i] == 0) missing.push_back(lookup[i]); + } + + std::string missing_and = missing[0]; + for (unsigned int i = 1; i < missing.size(); i++) + missing_and += std::string(", ") + missing[i]; + + noreturn_report(report_error, ("Didn't find required elements " + missing_and + ".").c_str()); +} + +template +inline void attr_error(std::bitset astate, const char* const* lookup, const std::function* report_error) { + std::vector missing; + for (unsigned int i = 0; i < N; i++) { + if (astate[i] == 0) missing.push_back(lookup[i]); + } + + std::string missing_and = missing[0]; + for (unsigned int i = 1; i < missing.size(); i++) + missing_and += std::string(", ") + missing[i]; + + noreturn_report(report_error, ("Didn't find required attributes " + missing_and + ".").c_str()); +} + +inline void get_line_number(const char* filename, std::ptrdiff_t target_offset, int* line, int* col) { + std::unique_ptr f(fopen(filename, "rb"), fclose); + + if (!f) { + throw std::runtime_error(std::string("Failed to open file") + filename); + } + + int current_line = 1; + std::ptrdiff_t offset = 0; + std::ptrdiff_t last_line_offset = 0; + std::ptrdiff_t current_line_offset = 0; + + char buffer[1024]; + std::size_t size; + + while ((size = fread(buffer, 1, sizeof(buffer), f.get())) > 0) { + for (std::size_t i = 0; i < size; ++i) { + if (buffer[i] == '\n') { + current_line += 1; + last_line_offset = current_line_offset; + current_line_offset = offset + i; + + if (target_offset < current_line_offset) { + if (target_offset < last_line_offset) { + throw std::runtime_error("Assertion violation"); + } + + *line = current_line - 1; + *col = target_offset - last_line_offset; + return; + } + } + } + + offset += size; + } + + *line = current_line; + *col = target_offset - current_line_offset; +} + +} /* namespace uxsd */ diff --git a/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h b/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h new file mode 100644 index 00000000000..f47fa5063d4 --- /dev/null +++ b/vpr/src/base/gen/vpr_constraints_uxsdcxx_interface.h @@ -0,0 +1,118 @@ +#pragma once +/* + * This file is generated by uxsdcxx 0.1.0. + * https://github.com/duck2/uxsdcxx + * Modify only if your build process doesn't involve regenerating this file. + * + * Cmdline: uxsdcxx.py ../vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * Input file: /home/khalid88/Documents/vtr-verilog-to-routing/vpr/src/base/vpr_constraints.xsd + * md5sum of input file: 3e1f2692931484aa45dce794ba723aa9 + */ + +#include + +/* All uxsdcxx functions and structs live in this namespace. */ + +#include +#include + +namespace uxsd { + +/* Base class for the schema. */ +struct DefaultVprConstraintsContextTypes { + using AddAtomReadContext = void*; + using AddRegionReadContext = void*; + using PartitionReadContext = void*; + using PartitionListReadContext = void*; + using VprConstraintsReadContext = void*; + using AddAtomWriteContext = void*; + using AddRegionWriteContext = void*; + using PartitionWriteContext = void*; + using PartitionListWriteContext = void*; + using VprConstraintsWriteContext = void*; +}; + +template +class VprConstraintsBase { + public: + virtual ~VprConstraintsBase() {} + virtual void start_load(const std::function* report_error) = 0; + virtual void finish_load() = 0; + virtual void start_write() = 0; + virtual void finish_write() = 0; + virtual void error_encountered(const char* file, int line, const char* message) = 0; + /** Generated for complex type "add_atom": + * + * + * + */ + virtual inline const char* get_add_atom_name_pattern(typename ContextTypes::AddAtomReadContext& ctx) = 0; + virtual inline void set_add_atom_name_pattern(const char* name_pattern, typename ContextTypes::AddAtomWriteContext& ctx) = 0; + + /** Generated for complex type "add_region": + * + * + * + * + * + * + * + */ + virtual inline int get_add_region_subtile(typename ContextTypes::AddRegionReadContext& ctx) = 0; + virtual inline void set_add_region_subtile(int subtile, typename ContextTypes::AddRegionWriteContext& ctx) = 0; + virtual inline int get_add_region_x_high(typename ContextTypes::AddRegionReadContext& ctx) = 0; + virtual inline int get_add_region_x_low(typename ContextTypes::AddRegionReadContext& ctx) = 0; + virtual inline int get_add_region_y_high(typename ContextTypes::AddRegionReadContext& ctx) = 0; + virtual inline int get_add_region_y_low(typename ContextTypes::AddRegionReadContext& ctx) = 0; + + /** Generated for complex type "partition": + * + * + * + * + * + * + * + */ + virtual inline const char* get_partition_name(typename ContextTypes::PartitionReadContext& ctx) = 0; + virtual inline void set_partition_name(const char* name, typename ContextTypes::PartitionWriteContext& ctx) = 0; + virtual inline void preallocate_partition_add_atom(typename ContextTypes::PartitionWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::AddAtomWriteContext add_partition_add_atom(typename ContextTypes::PartitionWriteContext& ctx) = 0; + virtual inline void finish_partition_add_atom(typename ContextTypes::AddAtomWriteContext& ctx) = 0; + virtual inline size_t num_partition_add_atom(typename ContextTypes::PartitionReadContext& ctx) = 0; + virtual inline typename ContextTypes::AddAtomReadContext get_partition_add_atom(int n, typename ContextTypes::PartitionReadContext& ctx) = 0; + virtual inline void preallocate_partition_add_region(typename ContextTypes::PartitionWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::AddRegionWriteContext add_partition_add_region(typename ContextTypes::PartitionWriteContext& ctx, int x_high, int x_low, int y_high, int y_low) = 0; + virtual inline void finish_partition_add_region(typename ContextTypes::AddRegionWriteContext& ctx) = 0; + virtual inline size_t num_partition_add_region(typename ContextTypes::PartitionReadContext& ctx) = 0; + virtual inline typename ContextTypes::AddRegionReadContext get_partition_add_region(int n, typename ContextTypes::PartitionReadContext& ctx) = 0; + + /** Generated for complex type "partition_list": + * + * + * + * + * + */ + virtual inline void preallocate_partition_list_partition(typename ContextTypes::PartitionListWriteContext& ctx, size_t size) = 0; + virtual inline typename ContextTypes::PartitionWriteContext add_partition_list_partition(typename ContextTypes::PartitionListWriteContext& ctx) = 0; + virtual inline void finish_partition_list_partition(typename ContextTypes::PartitionWriteContext& ctx) = 0; + virtual inline size_t num_partition_list_partition(typename ContextTypes::PartitionListReadContext& ctx) = 0; + virtual inline typename ContextTypes::PartitionReadContext get_partition_list_partition(int n, typename ContextTypes::PartitionListReadContext& ctx) = 0; + + /** Generated for complex type "vpr_constraints": + * + * + * + * + * + * + */ + virtual inline const char* get_vpr_constraints_tool_name(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; + virtual inline void set_vpr_constraints_tool_name(const char* tool_name, typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; + virtual inline typename ContextTypes::PartitionListWriteContext init_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsWriteContext& ctx) = 0; + virtual inline void finish_vpr_constraints_partition_list(typename ContextTypes::PartitionListWriteContext& ctx) = 0; + virtual inline typename ContextTypes::PartitionListReadContext get_vpr_constraints_partition_list(typename ContextTypes::VprConstraintsReadContext& ctx) = 0; +}; + +} /* namespace uxsd */ diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 5a7157ecf2f..6868715884c 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -1381,6 +1381,10 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg .metavar("RR_GRAPH_FILE") .show_in(argparse::ShowIn::HELP_ONLY); + file_grp.add_argument(args.read_vpr_constraints_file, "--read_vpr_constraints") + .help("Reads the constraints data from the constraints file.") + .show_in(argparse::ShowIn::HELP_ONLY); + file_grp.add_argument(args.read_router_lookahead, "--read_router_lookahead") .help( "Reads the lookahead data from the specified file instead of computing it.") diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index fdda9d6287c..9294647ec34 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -26,6 +26,7 @@ struct t_options { argparse::ArgValue constraints_file; argparse::ArgValue write_rr_graph_file; argparse::ArgValue read_rr_graph_file; + argparse::ArgValue read_vpr_constraints_file; argparse::ArgValue write_placement_delay_lookup; argparse::ArgValue read_placement_delay_lookup; diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index b533673cfa5..6e18819ca1b 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -68,6 +68,7 @@ #include "atom_netlist_utils.h" #include "cluster.h" #include "output_clustering.h" +#include "vpr_constraints_reader.h" #include "pack_report.h" #include "overuse_report.h" @@ -346,6 +347,12 @@ void vpr_init_with_options(const t_options* options, t_vpr_setup* vpr_setup, t_a } } + //Initialize vpr floorplanning constraints + auto& filename_opts = vpr_setup->FileNameOpts; + if (!filename_opts.read_vpr_constraints_file.empty()) { + load_vpr_constraints_file(filename_opts.read_vpr_constraints_file.c_str()); + } + fflush(stdout); ShowSetup(*vpr_setup); diff --git a/vpr/src/base/vpr_constraints.xsd b/vpr/src/base/vpr_constraints.xsd new file mode 100644 index 00000000000..d251b321eec --- /dev/null +++ b/vpr/src/base/vpr_constraints.xsd @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vpr/src/base/vpr_constraints_reader.cpp b/vpr/src/base/vpr_constraints_reader.cpp new file mode 100644 index 00000000000..8c3bfb0f6ce --- /dev/null +++ b/vpr/src/base/vpr_constraints_reader.cpp @@ -0,0 +1,40 @@ +#include "vpr_constraints_serializer.h" +#include "vpr_constraints_uxsdcxx.h" + +#include "vtr_time.h" + +#include "globals.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" +#include "echo_files.h" + +#include +#include "vpr_constraints_reader.h" + +void load_vpr_constraints_file(const char* read_vpr_constraints_name) { + vtr::ScopedStartFinishTimer timer("Loading VPR constraints file"); + + VprConstraintsSerializer reader; + + if (vtr::check_file_name_extension(read_vpr_constraints_name, ".xml")) { + try { + std::ifstream file(read_vpr_constraints_name); + void* context; + uxsd::load_vpr_constraints_xml(reader, context, read_vpr_constraints_name, file); + } catch (pugiutil::XmlError& e) { + vpr_throw(VPR_ERROR_ROUTE, read_vpr_constraints_name, e.line(), "%s", e.what()); + } + } else { + VTR_LOG_WARN( + "VPR constraints file '%s' may be in incorrect format. " + "Expecting .xml format\n", + read_vpr_constraints_name); + } + + VprConstraints constraints = reader.constraints_; + int num_parts = reader.num_partitions_; + + if (getEchoEnabled() && isEchoFileEnabled(E_ECHO_VPR_CONSTRAINTS)) { + echo_constraints(getEchoFileName(E_ECHO_VPR_CONSTRAINTS), constraints, num_parts); + } +} diff --git a/vpr/src/base/vpr_constraints_reader.h b/vpr/src/base/vpr_constraints_reader.h new file mode 100644 index 00000000000..cd4b031675d --- /dev/null +++ b/vpr/src/base/vpr_constraints_reader.h @@ -0,0 +1,8 @@ +/* Defines the function used to load a vpr constraints file written in xml format into vpr*/ + +#ifndef VPR_CONSTRAINTS_READER_H_ +#define VPR_CONSTRAINTS_READER_H_ + +void load_vpr_constraints_file(const char* read_vpr_constraints_name); + +#endif /* VPR_CONSTRAINTS_READER_H_ */ diff --git a/vpr/src/base/vpr_constraints_serializer.h b/vpr/src/base/vpr_constraints_serializer.h new file mode 100644 index 00000000000..1c9823a75af --- /dev/null +++ b/vpr/src/base/vpr_constraints_serializer.h @@ -0,0 +1,239 @@ +#ifndef VPR_CONSTRAINTS_SERIALIZER_H_ +#define VPR_CONSTRAINTS_SERIALIZER_H_ + +#include "region.h" +#include "vpr_constraints.h" +#include "partition.h" +#include "partition_region.h" +#include "echo_files.h" +#include "constraints_load.h" +#include "vtr_log.h" +#include "globals.h" //for the g_vpr_ctx + +#include "vpr_constraints_uxsdcxx_interface.h" + +struct VprConstraintsContextTypes : public uxsd::DefaultVprConstraintsContextTypes { + using AddAtomReadContext = void*; + using AddRegionReadContext = void*; + using PartitionReadContext = void*; + using PartitionListReadContext = void*; + using VprConstraintsReadContext = void*; + using AddAtomWriteContext = void*; + using AddRegionWriteContext = void*; + using PartitionWriteContext = void*; + using PartitionListWriteContext = void*; + using VprConstraintsWriteContext = void*; +}; + +class VprConstraintsSerializer final : public uxsd::VprConstraintsBase { + public: + void start_load(const std::function* report_error_in) final { + // report_error_in should be invoked if VprConstraintsSerializer encounters + // an error during the read. + report_error_ = report_error_in; + } + + virtual void start_write() final {} + virtual void finish_write() final {} + + // error_encountered will be invoked by the reader implementation whenever + // any error is encountered. + // + // This method should **not** be invoked from within VprConstraintsSerializer, + // instead the error should be reported via report_error. This enables + // the reader implementation to add context (e.g. file and line number). + void error_encountered(const char* file, int line, const char* message) final { + vpr_throw(VPR_ERROR_OTHER, file, line, "%s", message); + } + + /** Generated for complex type "add_atom": + * + * + * + */ + virtual inline const char* get_add_atom_name_pattern(void*& /*ctx*/) final { + return temp_.c_str(); + } + + virtual inline void set_add_atom_name_pattern(const char* name_pattern, void*& /*ctx*/) final { + auto& atom_ctx = g_vpr_ctx.atom(); + std::string atom_name = name_pattern; + atom_id_ = atom_ctx.nlist.find_block(name_pattern); + + if (atom_id_ == AtomBlockId::INVALID()) { + VTR_LOG_WARN("Atom %s was not found, skipping atom.\n", name_pattern); + } + } + + /** Generated for complex type "add_region": + * + * + * + * + * + * + * + */ + virtual inline int get_add_region_subtile(void*& /*ctx*/) final { + int i = 0; + return i; + } + + virtual inline void set_add_region_subtile(int subtile, void*& /*ctx*/) final { + loaded_region.set_sub_tile(subtile); + } + + virtual inline int get_add_region_x_high(void*& /*ctx*/) final { + int i = 0; + return i; + } + + virtual inline int get_add_region_x_low(void*& /*ctx*/) final { + int i = 0; + return i; + } + + virtual inline int get_add_region_y_high(void*& /*ctx*/) final { + int i = 0; + return i; + } + + virtual inline int get_add_region_y_low(void*& /*ctx*/) final { + int i = 0; + return i; + } + + /** Generated for complex type "partition": + * + * + * + * + * + * + * + */ + virtual inline const char* get_partition_name(void*& /*ctx*/) final { + return temp_.c_str(); + } + virtual inline void set_partition_name(const char* name, void*& /*ctx*/) final { + loaded_partition.set_name(name); + } + + virtual inline void preallocate_partition_add_atom(void*& /*ctx*/, size_t /*size*/) final {} + + virtual inline void* add_partition_add_atom(void*& /*ctx*/) final { + return nullptr; + } + + virtual inline void finish_partition_add_atom(void*& /*ctx*/) final { + PartitionId part_id(num_partitions_); + + if (atom_id_ != AtomBlockId::INVALID()) { + constraints_.add_constrained_atom(atom_id_, part_id); + } + } + + virtual inline size_t num_partition_add_atom(void*& /*ctx*/) final { + int i = 0; + return i; + } + virtual inline void* get_partition_add_atom(int /*n*/, void*& /*ctx*/) final { + return nullptr; + } + + virtual inline void preallocate_partition_add_region(void*& /*ctx*/, size_t /*size*/) final {} + + virtual inline void* add_partition_add_region(void*& /*ctx*/, int x_high, int x_low, int y_high, int y_low) final { + loaded_region.set_region_rect(x_low, y_low, x_high, y_high); + + return nullptr; + } + + virtual inline void finish_partition_add_region(void*& /*ctx*/) final { + loaded_part_region.add_to_part_region(loaded_region); + + Region clear_region; + loaded_region = clear_region; + } + + virtual inline size_t num_partition_add_region(void*& /*ctx*/) final { + int i = 0; + return i; + } + virtual inline void* get_partition_add_region(int /*n*/, void*& /*ctx*/) final { + return nullptr; + } + + /** Generated for complex type "partition_list": + * + * + * + * + * + */ + virtual inline void preallocate_partition_list_partition(void*& /*ctx*/, size_t /*size*/) final {} + + virtual inline void* add_partition_list_partition(void*& /*ctx*/) final { + return nullptr; + } + + virtual inline void finish_partition_list_partition(void*& /*ctx*/) final { + loaded_partition.set_part_region(loaded_part_region); + + //clear loaded_part_region + PartitionRegion clear_pr; + loaded_part_region = clear_pr; + + constraints_.add_partition(loaded_partition); + + num_partitions_++; + } + virtual inline size_t num_partition_list_partition(void*& /*ctx*/) final { + int i = 0; + return i; + } + + virtual inline void* get_partition_list_partition(int /*n*/, void*& /*ctx*/) final { + return nullptr; + } + + /** Generated for complex type "vpr_constraints": + * + * + * + * + * + * + */ + virtual inline const char* get_vpr_constraints_tool_name(void*& /*ctx*/) final { + return temp_.c_str(); + } + + virtual inline void set_vpr_constraints_tool_name(const char* /*tool_name*/, void*& /*ctx*/) final {} + + virtual inline void* init_vpr_constraints_partition_list(void*& /*ctx*/) final { + return nullptr; + } + + virtual inline void finish_vpr_constraints_partition_list(void*& /*ctx*/) final { + } + + virtual inline void* get_vpr_constraints_partition_list(void*& /*ctx*/) final { + return nullptr; + } + + virtual void finish_load() final { + } + + //temp data for loads + const std::function* report_error_; + Region loaded_region; + Partition loaded_partition; + PartitionRegion loaded_part_region; + VprConstraints constraints_; + std::string temp_; + int num_partitions_ = 0; + AtomBlockId atom_id_; +}; + +#endif /* VPR_CONSTRAINTS_SERIALIZER_H_ */ diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 78161c013fe..e9e1f63d25f 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -746,6 +746,7 @@ struct t_file_name_opts { std::string PowerFile; std::string CmosTechFile; std::string out_file_prefix; + std::string read_vpr_constraints_file; bool verify_file_digests; };