Created
July 7, 2019 03:12
-
-
Save duck2/ebd6f51e8d8494e1885d6a8a35629556 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bitset> | |
#include <cstring> | |
#include <memory> | |
#include <string> | |
#include <vector> | |
#include "pugixml.hpp" | |
struct t_channel; | |
struct t_x_list; | |
struct t_y_list; | |
struct t_timing; | |
struct t_sizing; | |
struct t_switch; | |
struct t_segment_timing; | |
struct t_segment; | |
struct t_pin; | |
struct t_pin_class; | |
struct t_meta; | |
struct t_metadata; | |
struct t_block_type; | |
struct t_grid_loc; | |
struct t_node_loc; | |
struct t_node_timing; | |
struct t_node_segment; | |
struct t_node; | |
struct t_edge; | |
struct t_channels; | |
struct t_switches; | |
struct t_segments; | |
struct t_block_types; | |
struct t_grid_locs; | |
struct t_rr_nodes; | |
struct t_rr_edges; | |
struct t_rr_graph; | |
enum class enum_switch_type {MUX, TRISTATE, PASS_GATE, SHORT, BUFFER}; | |
enum class enum_node_direction {INC_DIR, DEC_DIR, BI_DIR}; | |
enum class enum_node_type {CHANX, CHANY, SOURCE, SINK, OPIN, IPIN}; | |
enum class enum_pin_type {OPEN, OUTPUT, INPUT}; | |
enum class enum_loc_side {LEFT, RIGHT, TOP, BOTTOM}; | |
enum_switch_type lex_switch_type(const char *in){ | |
if(strcmp(in, "mux") == 0){ | |
return enum_switch_type::MUX; | |
} | |
else if(strcmp(in, "tristate") == 0){ | |
return enum_switch_type::TRISTATE; | |
} | |
else if(strcmp(in, "pass_gate") == 0){ | |
return enum_switch_type::PASS_GATE; | |
} | |
else if(strcmp(in, "short") == 0){ | |
return enum_switch_type::SHORT; | |
} | |
else if(strcmp(in, "buffer") == 0){ | |
return enum_switch_type::BUFFER; | |
} | |
else throw std::runtime_error("Found unrecognized enum value " + std::string(in) + "of enum_switch_type."); | |
} | |
enum_node_direction lex_node_direction(const char *in){ | |
if(strcmp(in, "INC_DIR") == 0){ | |
return enum_node_direction::INC_DIR; | |
} | |
else if(strcmp(in, "DEC_DIR") == 0){ | |
return enum_node_direction::DEC_DIR; | |
} | |
else if(strcmp(in, "BI_DIR") == 0){ | |
return enum_node_direction::BI_DIR; | |
} | |
else throw std::runtime_error("Found unrecognized enum value " + std::string(in) + "of enum_node_direction."); | |
} | |
enum_node_type lex_node_type(const char *in){ | |
if(strcmp(in, "CHANX") == 0){ | |
return enum_node_type::CHANX; | |
} | |
else if(strcmp(in, "CHANY") == 0){ | |
return enum_node_type::CHANY; | |
} | |
else if(strcmp(in, "SOURCE") == 0){ | |
return enum_node_type::SOURCE; | |
} | |
else if(strcmp(in, "SINK") == 0){ | |
return enum_node_type::SINK; | |
} | |
else if(strcmp(in, "OPIN") == 0){ | |
return enum_node_type::OPIN; | |
} | |
else if(strcmp(in, "IPIN") == 0){ | |
return enum_node_type::IPIN; | |
} | |
else throw std::runtime_error("Found unrecognized enum value " + std::string(in) + "of enum_node_type."); | |
} | |
enum_pin_type lex_pin_type(const char *in){ | |
if(strcmp(in, "OPEN") == 0){ | |
return enum_pin_type::OPEN; | |
} | |
else if(strcmp(in, "OUTPUT") == 0){ | |
return enum_pin_type::OUTPUT; | |
} | |
else if(strcmp(in, "INPUT") == 0){ | |
return enum_pin_type::INPUT; | |
} | |
else throw std::runtime_error("Found unrecognized enum value " + std::string(in) + "of enum_pin_type."); | |
} | |
enum_loc_side lex_loc_side(const char *in){ | |
if(strcmp(in, "LEFT") == 0){ | |
return enum_loc_side::LEFT; | |
} | |
else if(strcmp(in, "RIGHT") == 0){ | |
return enum_loc_side::RIGHT; | |
} | |
else if(strcmp(in, "TOP") == 0){ | |
return enum_loc_side::TOP; | |
} | |
else if(strcmp(in, "BOTTOM") == 0){ | |
return enum_loc_side::BOTTOM; | |
} | |
else throw std::runtime_error("Found unrecognized enum value " + std::string(in) + "of enum_loc_side."); | |
} | |
struct t_channel { | |
int chan_width_max; | |
int x_min; | |
int y_min; | |
int x_max; | |
int y_max; | |
}; | |
struct t_x_list { | |
int index; | |
int info; | |
}; | |
struct t_y_list { | |
int index; | |
int info; | |
}; | |
struct t_timing { | |
double R; | |
double Cin; | |
double Cinternal; | |
double Cout; | |
double Tdel; | |
}; | |
struct t_sizing { | |
double mux_trans_size; | |
double buf_size; | |
}; | |
struct t_switch { | |
int id; | |
std::string name; | |
enum_switch_type type; | |
std::vector<t_timing> timing_list; | |
std::vector<t_sizing> sizing_list; | |
}; | |
struct t_segment_timing { | |
double R_per_meter; | |
double C_per_meter; | |
}; | |
struct t_segment { | |
int id; | |
std::string name; | |
std::vector<t_segment_timing> timing_list; | |
}; | |
struct t_pin { | |
int ptc; | |
std::string value; | |
}; | |
struct t_pin_class { | |
enum_pin_type type; | |
std::vector<t_pin> pin_list; | |
}; | |
struct t_meta { | |
std::string name; | |
int x_offset; | |
int y_offset; | |
std::string value; | |
}; | |
struct t_metadata { | |
std::vector<t_meta> meta_list; | |
}; | |
struct t_block_type { | |
int id; | |
std::string name; | |
int width; | |
int height; | |
std::vector<t_pin_class> pin_class_list; | |
}; | |
struct t_grid_loc { | |
int x; | |
int y; | |
int block_type_id; | |
int width_offset; | |
int height_offset; | |
}; | |
struct t_node_loc { | |
int xlow; | |
int ylow; | |
int xhigh; | |
int yhigh; | |
enum_loc_side side; | |
int ptc; | |
}; | |
struct t_node_timing { | |
double R; | |
double C; | |
}; | |
struct t_node_segment { | |
int segment_id; | |
}; | |
struct t_node { | |
int id; | |
enum_node_type type; | |
enum_node_direction direction; | |
int capacity; | |
std::vector<t_node_loc> loc_list; | |
std::vector<t_node_timing> timing_list; | |
std::vector<t_node_segment> segment_list; | |
std::vector<t_metadata> metadata_list; | |
}; | |
struct t_edge { | |
int id; | |
int src_node; | |
int sink_node; | |
int switch_id; | |
std::vector<t_metadata> metadata_list; | |
}; | |
struct t_channels { | |
std::vector<t_channel> channel_list; | |
std::vector<t_x_list> x_list_list; | |
std::vector<t_y_list> y_list_list; | |
}; | |
struct t_switches { | |
std::vector<t_switch> switch_list; | |
}; | |
struct t_segments { | |
std::vector<t_segment> segment_list; | |
}; | |
struct t_block_types { | |
std::vector<t_block_type> block_type_list; | |
}; | |
struct t_grid_locs { | |
std::vector<t_grid_loc> grid_loc_list; | |
}; | |
struct t_rr_nodes { | |
std::vector<t_node> node_list; | |
}; | |
struct t_rr_edges { | |
std::vector<t_edge> edge_list; | |
}; | |
struct t_rr_graph { | |
std::string tool_name; | |
std::string tool_version; | |
std::string tool_comment; | |
std::vector<t_channels> channels_list; | |
std::vector<t_switches> switches_list; | |
std::vector<t_segments> segments_list; | |
std::vector<t_block_types> block_types_list; | |
std::vector<t_grid_locs> grid_list; | |
std::vector<t_rr_nodes> rr_nodes_list; | |
std::vector<t_rr_edges> rr_edges_list; | |
}; | |
std::unique_ptr<t_rr_graph> rr_graph; | |
void read_t_channel(pugi::xml_node &root, t_channel &out); | |
void read_t_x_list(pugi::xml_node &root, t_x_list &out); | |
void read_t_y_list(pugi::xml_node &root, t_y_list &out); | |
void read_t_timing(pugi::xml_node &root, t_timing &out); | |
void read_t_sizing(pugi::xml_node &root, t_sizing &out); | |
void read_t_switch(pugi::xml_node &root, t_switch &out); | |
void read_t_segment_timing(pugi::xml_node &root, t_segment_timing &out); | |
void read_t_segment(pugi::xml_node &root, t_segment &out); | |
void read_t_pin(pugi::xml_node &root, t_pin &out); | |
void read_t_pin_class(pugi::xml_node &root, t_pin_class &out); | |
void read_t_meta(pugi::xml_node &root, t_meta &out); | |
void read_t_metadata(pugi::xml_node &root, t_metadata &out); | |
void read_t_block_type(pugi::xml_node &root, t_block_type &out); | |
void read_t_grid_loc(pugi::xml_node &root, t_grid_loc &out); | |
void read_t_node_loc(pugi::xml_node &root, t_node_loc &out); | |
void read_t_node_timing(pugi::xml_node &root, t_node_timing &out); | |
void read_t_node_segment(pugi::xml_node &root, t_node_segment &out); | |
void read_t_node(pugi::xml_node &root, t_node &out); | |
void read_t_edge(pugi::xml_node &root, t_edge &out); | |
void read_t_channels(pugi::xml_node &root, t_channels &out); | |
void read_t_switches(pugi::xml_node &root, t_switches &out); | |
void read_t_segments(pugi::xml_node &root, t_segments &out); | |
void read_t_block_types(pugi::xml_node &root, t_block_types &out); | |
void read_t_grid_locs(pugi::xml_node &root, t_grid_locs &out); | |
void read_t_rr_nodes(pugi::xml_node &root, t_rr_nodes &out); | |
void read_t_rr_edges(pugi::xml_node &root, t_rr_edges &out); | |
void read_t_rr_graph(pugi::xml_node &root, t_rr_graph &out); | |
/* runtime error for state machines */ | |
void dfa_error(const char *wrong, int *states, const char **lookup, int len){ | |
std::vector<std::string> expected; | |
for(int i=0; i<len; i++){ | |
if(states[i] != -1) expected.push_back(lookup[i]); | |
} | |
std::string expected_or = expected[0]; | |
for(int i=1; i<expected.size(); i++) | |
expected_or += std::string(" or ") + expected[i]; | |
throw std::runtime_error("Expected " + expected_or + ", found " + std::string(wrong)); | |
} | |
/* runtime error for attributes */ | |
template<std::size_t N> | |
void attr_error(std::bitset<N> astate, const char **lookup){ | |
std::vector<std::string> missing; | |
for(int i=0; i<astate.size(); i++){ | |
if(astate[i] == 0) missing.push_back(lookup[i]); | |
} | |
std::string missing_and = missing[0]; | |
for(int i=1; i<missing.size(); i++) | |
missing_and += std::string(" and ") + missing[i]; | |
throw std::runtime_error("Didn't find required attributes " + missing_and + "."); | |
} | |
enum class atok_t_channel {CHAN_WIDTH_MAX, X_MIN, Y_MIN, X_MAX, Y_MAX}; | |
const char *atok_lookup_t_channel[] = {"chan_width_max", "x_min", "y_min", "x_max", "y_max"}; | |
atok_t_channel alex_t_channel(const char *in){ | |
if(strcmp(in, "chan_width_max") == 0){ | |
return atok_t_channel::CHAN_WIDTH_MAX; | |
} | |
else if(strcmp(in, "x_min") == 0){ | |
return atok_t_channel::X_MIN; | |
} | |
else if(strcmp(in, "y_min") == 0){ | |
return atok_t_channel::Y_MIN; | |
} | |
else if(strcmp(in, "x_max") == 0){ | |
return atok_t_channel::X_MAX; | |
} | |
else if(strcmp(in, "y_max") == 0){ | |
return atok_t_channel::Y_MAX; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <channel>."); | |
} | |
void read_t_channel(pugi::xml_node &root, t_channel &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <channel>."); | |
std::bitset<5> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_channel in = alex_t_channel(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <channel>."); | |
switch(in){ | |
case atok_t_channel::CHAN_WIDTH_MAX: | |
out.chan_width_max = std::stoi(attr.value()); | |
break; | |
case atok_t_channel::X_MIN: | |
out.x_min = std::stoi(attr.value()); | |
break; | |
case atok_t_channel::Y_MIN: | |
out.y_min = std::stoi(attr.value()); | |
break; | |
case atok_t_channel::X_MAX: | |
out.x_max = std::stoi(attr.value()); | |
break; | |
case atok_t_channel::Y_MAX: | |
out.y_max = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<5> test_state = astate | std::bitset<5>(0b00000); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_channel); | |
} | |
enum class atok_t_x_list {INDEX, INFO}; | |
const char *atok_lookup_t_x_list[] = {"index", "info"}; | |
atok_t_x_list alex_t_x_list(const char *in){ | |
if(strcmp(in, "index") == 0){ | |
return atok_t_x_list::INDEX; | |
} | |
else if(strcmp(in, "info") == 0){ | |
return atok_t_x_list::INFO; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <x_list>."); | |
} | |
void read_t_x_list(pugi::xml_node &root, t_x_list &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <x_list>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_x_list in = alex_t_x_list(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <x_list>."); | |
switch(in){ | |
case atok_t_x_list::INDEX: | |
out.index = std::stoi(attr.value()); | |
break; | |
case atok_t_x_list::INFO: | |
out.info = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<2> test_state = astate | std::bitset<2>(0b00); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_x_list); | |
} | |
enum class atok_t_y_list {INDEX, INFO}; | |
const char *atok_lookup_t_y_list[] = {"index", "info"}; | |
atok_t_y_list alex_t_y_list(const char *in){ | |
if(strcmp(in, "index") == 0){ | |
return atok_t_y_list::INDEX; | |
} | |
else if(strcmp(in, "info") == 0){ | |
return atok_t_y_list::INFO; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <y_list>."); | |
} | |
void read_t_y_list(pugi::xml_node &root, t_y_list &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <y_list>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_y_list in = alex_t_y_list(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <y_list>."); | |
switch(in){ | |
case atok_t_y_list::INDEX: | |
out.index = std::stoi(attr.value()); | |
break; | |
case atok_t_y_list::INFO: | |
out.info = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<2> test_state = astate | std::bitset<2>(0b00); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_y_list); | |
} | |
enum class atok_t_timing {R, CIN, CINTERNAL, COUT, TDEL}; | |
const char *atok_lookup_t_timing[] = {"R", "Cin", "Cinternal", "Cout", "Tdel"}; | |
atok_t_timing alex_t_timing(const char *in){ | |
if(strcmp(in, "R") == 0){ | |
return atok_t_timing::R; | |
} | |
else if(strcmp(in, "Cin") == 0){ | |
return atok_t_timing::CIN; | |
} | |
else if(strcmp(in, "Cinternal") == 0){ | |
return atok_t_timing::CINTERNAL; | |
} | |
else if(strcmp(in, "Cout") == 0){ | |
return atok_t_timing::COUT; | |
} | |
else if(strcmp(in, "Tdel") == 0){ | |
return atok_t_timing::TDEL; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <timing>."); | |
} | |
void read_t_timing(pugi::xml_node &root, t_timing &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <timing>."); | |
std::bitset<5> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_timing in = alex_t_timing(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <timing>."); | |
switch(in){ | |
case atok_t_timing::R: | |
out.R = std::stod(attr.value()); | |
break; | |
case atok_t_timing::CIN: | |
out.Cin = std::stod(attr.value()); | |
break; | |
case atok_t_timing::CINTERNAL: | |
out.Cinternal = std::stod(attr.value()); | |
break; | |
case atok_t_timing::COUT: | |
out.Cout = std::stod(attr.value()); | |
break; | |
case atok_t_timing::TDEL: | |
out.Tdel = std::stod(attr.value()); | |
break; | |
} | |
} | |
std::bitset<5> test_state = astate | std::bitset<5>(0b11111); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_timing); | |
} | |
enum class atok_t_sizing {MUX_TRANS_SIZE, BUF_SIZE}; | |
const char *atok_lookup_t_sizing[] = {"mux_trans_size", "buf_size"}; | |
atok_t_sizing alex_t_sizing(const char *in){ | |
if(strcmp(in, "mux_trans_size") == 0){ | |
return atok_t_sizing::MUX_TRANS_SIZE; | |
} | |
else if(strcmp(in, "buf_size") == 0){ | |
return atok_t_sizing::BUF_SIZE; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <sizing>."); | |
} | |
void read_t_sizing(pugi::xml_node &root, t_sizing &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <sizing>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_sizing in = alex_t_sizing(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <sizing>."); | |
switch(in){ | |
case atok_t_sizing::MUX_TRANS_SIZE: | |
out.mux_trans_size = std::stod(attr.value()); | |
break; | |
case atok_t_sizing::BUF_SIZE: | |
out.buf_size = std::stod(attr.value()); | |
break; | |
} | |
} | |
std::bitset<2> test_state = astate | std::bitset<2>(0b00); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_sizing); | |
} | |
enum class gtok_t_switch {SIZING, TIMING}; | |
const char *gtok_lookup_t_switch[] = {"timing", "sizing"}; | |
enum class atok_t_switch {ID, NAME, TYPE}; | |
const char *atok_lookup_t_switch[] = {"id", "name", "type"}; | |
gtok_t_switch glex_t_switch(const char *in){ | |
if(strcmp(in, "sizing") == 0){ | |
return gtok_t_switch::SIZING; | |
} | |
else if(strcmp(in, "timing") == 0){ | |
return gtok_t_switch::TIMING; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <switch>."); | |
} | |
atok_t_switch alex_t_switch(const char *in){ | |
if(strcmp(in, "id") == 0){ | |
return atok_t_switch::ID; | |
} | |
else if(strcmp(in, "name") == 0){ | |
return atok_t_switch::NAME; | |
} | |
else if(strcmp(in, "type") == 0){ | |
return atok_t_switch::TYPE; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <switch>."); | |
} | |
int gstates0_t_switch[2][2] = { | |
{0, 0}, | |
{0, 0}, | |
}; | |
void read_t_switch(pugi::xml_node &root, t_switch &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_switch in = glex_t_switch(node.name()); | |
next = gstates0_t_switch[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_switch[(int)in], gstates0_t_switch[state0], gtok_lookup_t_switch, 2); | |
state0 = next; | |
switch(in){ | |
case gtok_t_switch::TIMING: | |
out.timing_list.push_back(t_timing()); | |
read_t_timing(node, out.timing_list.back()); | |
break; | |
case gtok_t_switch::SIZING: | |
out.sizing_list.push_back(t_sizing()); | |
read_t_sizing(node, out.sizing_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_switch[state0], gtok_lookup_t_switch, 2); | |
std::bitset<3> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_switch in = alex_t_switch(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <switch>."); | |
switch(in){ | |
case atok_t_switch::ID: | |
out.id = std::stoi(attr.value()); | |
break; | |
case atok_t_switch::NAME: | |
out.name = attr.value(); | |
break; | |
case atok_t_switch::TYPE: | |
out.type = lex_switch_type(attr.value()); | |
break; | |
} | |
} | |
std::bitset<3> test_state = astate | std::bitset<3>(0b100); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_switch); | |
} | |
enum class atok_t_segment_timing {R_PER_METER, C_PER_METER}; | |
const char *atok_lookup_t_segment_timing[] = {"R_per_meter", "C_per_meter"}; | |
atok_t_segment_timing alex_t_segment_timing(const char *in){ | |
if(strcmp(in, "R_per_meter") == 0){ | |
return atok_t_segment_timing::R_PER_METER; | |
} | |
else if(strcmp(in, "C_per_meter") == 0){ | |
return atok_t_segment_timing::C_PER_METER; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <segment_timing>."); | |
} | |
void read_t_segment_timing(pugi::xml_node &root, t_segment_timing &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <segment_timing>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_segment_timing in = alex_t_segment_timing(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <segment_timing>."); | |
switch(in){ | |
case atok_t_segment_timing::R_PER_METER: | |
out.R_per_meter = std::stod(attr.value()); | |
break; | |
case atok_t_segment_timing::C_PER_METER: | |
out.C_per_meter = std::stod(attr.value()); | |
break; | |
} | |
} | |
std::bitset<2> test_state = astate | std::bitset<2>(0b11); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_segment_timing); | |
} | |
enum class gtok_t_segment {TIMING}; | |
const char *gtok_lookup_t_segment[] = {"timing"}; | |
enum class atok_t_segment {ID, NAME}; | |
const char *atok_lookup_t_segment[] = {"id", "name"}; | |
gtok_t_segment glex_t_segment(const char *in){ | |
if(strcmp(in, "timing") == 0){ | |
return gtok_t_segment::TIMING; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <segment>."); | |
} | |
atok_t_segment alex_t_segment(const char *in){ | |
if(strcmp(in, "id") == 0){ | |
return atok_t_segment::ID; | |
} | |
else if(strcmp(in, "name") == 0){ | |
return atok_t_segment::NAME; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <segment>."); | |
} | |
int gstates0_t_segment[2][1] = { | |
{0}, | |
{0}, | |
}; | |
void read_t_segment(pugi::xml_node &root, t_segment &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_segment in = glex_t_segment(node.name()); | |
next = gstates0_t_segment[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_segment[(int)in], gstates0_t_segment[state0], gtok_lookup_t_segment, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_segment::TIMING: | |
out.timing_list.push_back(t_segment_timing()); | |
read_t_segment_timing(node, out.timing_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_segment[state0], gtok_lookup_t_segment, 1); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_segment in = alex_t_segment(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <segment>."); | |
switch(in){ | |
case atok_t_segment::ID: | |
out.id = std::stoi(attr.value()); | |
break; | |
case atok_t_segment::NAME: | |
out.name = attr.value(); | |
break; | |
} | |
} | |
std::bitset<2> test_state = astate | std::bitset<2>(0b00); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_segment); | |
} | |
enum class atok_t_pin {PTC}; | |
const char *atok_lookup_t_pin[] = {"ptc"}; | |
atok_t_pin alex_t_pin(const char *in){ | |
if(strcmp(in, "ptc") == 0){ | |
return atok_t_pin::PTC; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <pin>."); | |
} | |
void read_t_pin(pugi::xml_node &root, t_pin &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <pin>."); | |
out.value = root.child_value(); | |
std::bitset<1> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_pin in = alex_t_pin(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <pin>."); | |
switch(in){ | |
case atok_t_pin::PTC: | |
out.ptc = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<1> test_state = astate | std::bitset<1>(0b0); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_pin); | |
} | |
enum class gtok_t_pin_class {PIN}; | |
const char *gtok_lookup_t_pin_class[] = {"pin"}; | |
enum class atok_t_pin_class {TYPE}; | |
const char *atok_lookup_t_pin_class[] = {"type"}; | |
gtok_t_pin_class glex_t_pin_class(const char *in){ | |
if(strcmp(in, "pin") == 0){ | |
return gtok_t_pin_class::PIN; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <pin_class>."); | |
} | |
atok_t_pin_class alex_t_pin_class(const char *in){ | |
if(strcmp(in, "type") == 0){ | |
return atok_t_pin_class::TYPE; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <pin_class>."); | |
} | |
int gstates0_t_pin_class[2][1] = { | |
{0}, | |
{0}, | |
}; | |
void read_t_pin_class(pugi::xml_node &root, t_pin_class &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_pin_class in = glex_t_pin_class(node.name()); | |
next = gstates0_t_pin_class[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_pin_class[(int)in], gstates0_t_pin_class[state0], gtok_lookup_t_pin_class, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_pin_class::PIN: | |
out.pin_list.push_back(t_pin()); | |
read_t_pin(node, out.pin_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_pin_class[state0], gtok_lookup_t_pin_class, 1); | |
std::bitset<1> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_pin_class in = alex_t_pin_class(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <pin_class>."); | |
switch(in){ | |
case atok_t_pin_class::TYPE: | |
out.type = lex_pin_type(attr.value()); | |
break; | |
} | |
} | |
std::bitset<1> test_state = astate | std::bitset<1>(0b0); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_pin_class); | |
} | |
enum class atok_t_meta {NAME, X_OFFSET, Y_OFFSET}; | |
const char *atok_lookup_t_meta[] = {"name", "x_offset", "y_offset"}; | |
atok_t_meta alex_t_meta(const char *in){ | |
if(strcmp(in, "name") == 0){ | |
return atok_t_meta::NAME; | |
} | |
else if(strcmp(in, "x_offset") == 0){ | |
return atok_t_meta::X_OFFSET; | |
} | |
else if(strcmp(in, "y_offset") == 0){ | |
return atok_t_meta::Y_OFFSET; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <meta>."); | |
} | |
void read_t_meta(pugi::xml_node &root, t_meta &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <meta>."); | |
out.value = root.child_value(); | |
std::bitset<3> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_meta in = alex_t_meta(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <meta>."); | |
switch(in){ | |
case atok_t_meta::NAME: | |
out.name = attr.value(); | |
break; | |
case atok_t_meta::X_OFFSET: | |
out.x_offset = std::stoi(attr.value()); | |
break; | |
case atok_t_meta::Y_OFFSET: | |
out.y_offset = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<3> test_state = astate | std::bitset<3>(0b110); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_meta); | |
} | |
enum class gtok_t_metadata {META}; | |
const char *gtok_lookup_t_metadata[] = {"meta"}; | |
gtok_t_metadata glex_t_metadata(const char *in){ | |
if(strcmp(in, "meta") == 0){ | |
return gtok_t_metadata::META; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <metadata>."); | |
} | |
int gstates0_t_metadata[2][1] = { | |
{0}, | |
{0}, | |
}; | |
void read_t_metadata(pugi::xml_node &root, t_metadata &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_metadata in = glex_t_metadata(node.name()); | |
next = gstates0_t_metadata[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_metadata[(int)in], gstates0_t_metadata[state0], gtok_lookup_t_metadata, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_metadata::META: | |
out.meta_list.push_back(t_meta()); | |
read_t_meta(node, out.meta_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_metadata[state0], gtok_lookup_t_metadata, 1); | |
if(root.first_attribute()) std::runtime_error("Unexpected attribute in <metadata>."); | |
} | |
enum class gtok_t_block_type {PIN_CLASS}; | |
const char *gtok_lookup_t_block_type[] = {"pin_class"}; | |
enum class atok_t_block_type {ID, NAME, WIDTH, HEIGHT}; | |
const char *atok_lookup_t_block_type[] = {"id", "name", "width", "height"}; | |
gtok_t_block_type glex_t_block_type(const char *in){ | |
if(strcmp(in, "pin_class") == 0){ | |
return gtok_t_block_type::PIN_CLASS; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <block_type>."); | |
} | |
atok_t_block_type alex_t_block_type(const char *in){ | |
if(strcmp(in, "id") == 0){ | |
return atok_t_block_type::ID; | |
} | |
else if(strcmp(in, "name") == 0){ | |
return atok_t_block_type::NAME; | |
} | |
else if(strcmp(in, "width") == 0){ | |
return atok_t_block_type::WIDTH; | |
} | |
else if(strcmp(in, "height") == 0){ | |
return atok_t_block_type::HEIGHT; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <block_type>."); | |
} | |
int gstates0_t_block_type[1][1] = { | |
{0}, | |
}; | |
void read_t_block_type(pugi::xml_node &root, t_block_type &out){ | |
int next, state0 = 0; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_block_type in = glex_t_block_type(node.name()); | |
next = gstates0_t_block_type[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_block_type[(int)in], gstates0_t_block_type[state0], gtok_lookup_t_block_type, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_block_type::PIN_CLASS: | |
out.pin_class_list.push_back(t_pin_class()); | |
read_t_pin_class(node, out.pin_class_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_block_type[state0], gtok_lookup_t_block_type, 1); | |
std::bitset<4> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_block_type in = alex_t_block_type(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <block_type>."); | |
switch(in){ | |
case atok_t_block_type::ID: | |
out.id = std::stoi(attr.value()); | |
break; | |
case atok_t_block_type::NAME: | |
out.name = attr.value(); | |
break; | |
case atok_t_block_type::WIDTH: | |
out.width = std::stoi(attr.value()); | |
break; | |
case atok_t_block_type::HEIGHT: | |
out.height = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<4> test_state = astate | std::bitset<4>(0b0000); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_block_type); | |
} | |
enum class atok_t_grid_loc {X, Y, BLOCK_TYPE_ID, WIDTH_OFFSET, HEIGHT_OFFSET}; | |
const char *atok_lookup_t_grid_loc[] = {"x", "y", "block_type_id", "width_offset", "height_offset"}; | |
atok_t_grid_loc alex_t_grid_loc(const char *in){ | |
if(strcmp(in, "x") == 0){ | |
return atok_t_grid_loc::X; | |
} | |
else if(strcmp(in, "y") == 0){ | |
return atok_t_grid_loc::Y; | |
} | |
else if(strcmp(in, "block_type_id") == 0){ | |
return atok_t_grid_loc::BLOCK_TYPE_ID; | |
} | |
else if(strcmp(in, "width_offset") == 0){ | |
return atok_t_grid_loc::WIDTH_OFFSET; | |
} | |
else if(strcmp(in, "height_offset") == 0){ | |
return atok_t_grid_loc::HEIGHT_OFFSET; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <grid_loc>."); | |
} | |
void read_t_grid_loc(pugi::xml_node &root, t_grid_loc &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <grid_loc>."); | |
std::bitset<5> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_grid_loc in = alex_t_grid_loc(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <grid_loc>."); | |
switch(in){ | |
case atok_t_grid_loc::X: | |
out.x = std::stoi(attr.value()); | |
break; | |
case atok_t_grid_loc::Y: | |
out.y = std::stoi(attr.value()); | |
break; | |
case atok_t_grid_loc::BLOCK_TYPE_ID: | |
out.block_type_id = std::stoi(attr.value()); | |
break; | |
case atok_t_grid_loc::WIDTH_OFFSET: | |
out.width_offset = std::stoi(attr.value()); | |
break; | |
case atok_t_grid_loc::HEIGHT_OFFSET: | |
out.height_offset = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<5> test_state = astate | std::bitset<5>(0b00000); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_grid_loc); | |
} | |
enum class atok_t_node_loc {XLOW, YLOW, XHIGH, YHIGH, SIDE, PTC}; | |
const char *atok_lookup_t_node_loc[] = {"xlow", "ylow", "xhigh", "yhigh", "side", "ptc"}; | |
atok_t_node_loc alex_t_node_loc(const char *in){ | |
if(strcmp(in, "xlow") == 0){ | |
return atok_t_node_loc::XLOW; | |
} | |
else if(strcmp(in, "ylow") == 0){ | |
return atok_t_node_loc::YLOW; | |
} | |
else if(strcmp(in, "xhigh") == 0){ | |
return atok_t_node_loc::XHIGH; | |
} | |
else if(strcmp(in, "yhigh") == 0){ | |
return atok_t_node_loc::YHIGH; | |
} | |
else if(strcmp(in, "side") == 0){ | |
return atok_t_node_loc::SIDE; | |
} | |
else if(strcmp(in, "ptc") == 0){ | |
return atok_t_node_loc::PTC; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <node_loc>."); | |
} | |
void read_t_node_loc(pugi::xml_node &root, t_node_loc &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <node_loc>."); | |
std::bitset<6> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_node_loc in = alex_t_node_loc(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node_loc>."); | |
switch(in){ | |
case atok_t_node_loc::XLOW: | |
out.xlow = std::stoi(attr.value()); | |
break; | |
case atok_t_node_loc::YLOW: | |
out.ylow = std::stoi(attr.value()); | |
break; | |
case atok_t_node_loc::XHIGH: | |
out.xhigh = std::stoi(attr.value()); | |
break; | |
case atok_t_node_loc::YHIGH: | |
out.yhigh = std::stoi(attr.value()); | |
break; | |
case atok_t_node_loc::SIDE: | |
out.side = lex_loc_side(attr.value()); | |
break; | |
case atok_t_node_loc::PTC: | |
out.ptc = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<6> test_state = astate | std::bitset<6>(0b010000); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_node_loc); | |
} | |
enum class atok_t_node_timing {R, C}; | |
const char *atok_lookup_t_node_timing[] = {"R", "C"}; | |
atok_t_node_timing alex_t_node_timing(const char *in){ | |
if(strcmp(in, "R") == 0){ | |
return atok_t_node_timing::R; | |
} | |
else if(strcmp(in, "C") == 0){ | |
return atok_t_node_timing::C; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <node_timing>."); | |
} | |
void read_t_node_timing(pugi::xml_node &root, t_node_timing &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <node_timing>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_node_timing in = alex_t_node_timing(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node_timing>."); | |
switch(in){ | |
case atok_t_node_timing::R: | |
out.R = std::stod(attr.value()); | |
break; | |
case atok_t_node_timing::C: | |
out.C = std::stod(attr.value()); | |
break; | |
} | |
} | |
std::bitset<2> test_state = astate | std::bitset<2>(0b00); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_node_timing); | |
} | |
enum class atok_t_node_segment {SEGMENT_ID}; | |
const char *atok_lookup_t_node_segment[] = {"segment_id"}; | |
atok_t_node_segment alex_t_node_segment(const char *in){ | |
if(strcmp(in, "segment_id") == 0){ | |
return atok_t_node_segment::SEGMENT_ID; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <node_segment>."); | |
} | |
void read_t_node_segment(pugi::xml_node &root, t_node_segment &out){ | |
if(root.first_child().type() == pugi::node_element) throw std::runtime_error("Unexpected child element in <node_segment>."); | |
std::bitset<1> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_node_segment in = alex_t_node_segment(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node_segment>."); | |
switch(in){ | |
case atok_t_node_segment::SEGMENT_ID: | |
out.segment_id = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<1> test_state = astate | std::bitset<1>(0b0); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_node_segment); | |
} | |
enum class gtok_t_node {SEGMENT, LOC, TIMING, METADATA}; | |
const char *gtok_lookup_t_node[] = {"metadata", "loc", "segment", "timing"}; | |
enum class atok_t_node {ID, TYPE, DIRECTION, CAPACITY}; | |
const char *atok_lookup_t_node[] = {"id", "type", "direction", "capacity"}; | |
gtok_t_node glex_t_node(const char *in){ | |
if(strcmp(in, "metadata") == 0){ | |
return gtok_t_node::METADATA; | |
} | |
else if(strcmp(in, "loc") == 0){ | |
return gtok_t_node::LOC; | |
} | |
else if(strcmp(in, "timing") == 0){ | |
return gtok_t_node::TIMING; | |
} | |
else if(strcmp(in, "segment") == 0){ | |
return gtok_t_node::SEGMENT; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <node>."); | |
} | |
atok_t_node alex_t_node(const char *in){ | |
if(strcmp(in, "id") == 0){ | |
return atok_t_node::ID; | |
} | |
else if(strcmp(in, "type") == 0){ | |
return atok_t_node::TYPE; | |
} | |
else if(strcmp(in, "direction") == 0){ | |
return atok_t_node::DIRECTION; | |
} | |
else if(strcmp(in, "capacity") == 0){ | |
return atok_t_node::CAPACITY; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <node>."); | |
} | |
int gstates0_t_node[2][4] = { | |
{0, 0, 0, 0}, | |
{0, 0, 0, 0}, | |
}; | |
void read_t_node(pugi::xml_node &root, t_node &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_node in = glex_t_node(node.name()); | |
next = gstates0_t_node[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_node[(int)in], gstates0_t_node[state0], gtok_lookup_t_node, 4); | |
state0 = next; | |
switch(in){ | |
case gtok_t_node::LOC: | |
out.loc_list.push_back(t_node_loc()); | |
read_t_node_loc(node, out.loc_list.back()); | |
break; | |
case gtok_t_node::TIMING: | |
out.timing_list.push_back(t_node_timing()); | |
read_t_node_timing(node, out.timing_list.back()); | |
break; | |
case gtok_t_node::SEGMENT: | |
out.segment_list.push_back(t_node_segment()); | |
read_t_node_segment(node, out.segment_list.back()); | |
break; | |
case gtok_t_node::METADATA: | |
out.metadata_list.push_back(t_metadata()); | |
read_t_metadata(node, out.metadata_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_node[state0], gtok_lookup_t_node, 4); | |
std::bitset<4> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_node in = alex_t_node(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node>."); | |
switch(in){ | |
case atok_t_node::ID: | |
out.id = std::stoi(attr.value()); | |
break; | |
case atok_t_node::TYPE: | |
out.type = lex_node_type(attr.value()); | |
break; | |
case atok_t_node::DIRECTION: | |
out.direction = lex_node_direction(attr.value()); | |
break; | |
case atok_t_node::CAPACITY: | |
out.capacity = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<4> test_state = astate | std::bitset<4>(0b0100); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_node); | |
} | |
enum class gtok_t_edge {METADATA}; | |
const char *gtok_lookup_t_edge[] = {"metadata"}; | |
enum class atok_t_edge {ID, SRC_NODE, SINK_NODE, SWITCH_ID}; | |
const char *atok_lookup_t_edge[] = {"id", "src_node", "sink_node", "switch_id"}; | |
gtok_t_edge glex_t_edge(const char *in){ | |
if(strcmp(in, "metadata") == 0){ | |
return gtok_t_edge::METADATA; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <edge>."); | |
} | |
atok_t_edge alex_t_edge(const char *in){ | |
if(strcmp(in, "id") == 0){ | |
return atok_t_edge::ID; | |
} | |
else if(strcmp(in, "src_node") == 0){ | |
return atok_t_edge::SRC_NODE; | |
} | |
else if(strcmp(in, "sink_node") == 0){ | |
return atok_t_edge::SINK_NODE; | |
} | |
else if(strcmp(in, "switch_id") == 0){ | |
return atok_t_edge::SWITCH_ID; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <edge>."); | |
} | |
int gstates0_t_edge[1][1] = { | |
{0}, | |
}; | |
void read_t_edge(pugi::xml_node &root, t_edge &out){ | |
int next, state0 = 0; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_edge in = glex_t_edge(node.name()); | |
next = gstates0_t_edge[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_edge[(int)in], gstates0_t_edge[state0], gtok_lookup_t_edge, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_edge::METADATA: | |
out.metadata_list.push_back(t_metadata()); | |
read_t_metadata(node, out.metadata_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_edge[state0], gtok_lookup_t_edge, 1); | |
std::bitset<4> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_edge in = alex_t_edge(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <edge>."); | |
switch(in){ | |
case atok_t_edge::ID: | |
out.id = std::stoi(attr.value()); | |
break; | |
case atok_t_edge::SRC_NODE: | |
out.src_node = std::stoi(attr.value()); | |
break; | |
case atok_t_edge::SINK_NODE: | |
out.sink_node = std::stoi(attr.value()); | |
break; | |
case atok_t_edge::SWITCH_ID: | |
out.switch_id = std::stoi(attr.value()); | |
break; | |
} | |
} | |
std::bitset<4> test_state = astate | std::bitset<4>(0b0001); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_edge); | |
} | |
enum class gtok_t_channels {CHANNEL, Y_LIST, X_LIST}; | |
const char *gtok_lookup_t_channels[] = {"channel", "y_list", "x_list"}; | |
gtok_t_channels glex_t_channels(const char *in){ | |
if(strcmp(in, "x_list") == 0){ | |
return gtok_t_channels::X_LIST; | |
} | |
else if(strcmp(in, "y_list") == 0){ | |
return gtok_t_channels::Y_LIST; | |
} | |
else if(strcmp(in, "channel") == 0){ | |
return gtok_t_channels::CHANNEL; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <channels>."); | |
} | |
int gstates0_t_channels[2][3] = { | |
{0, 0, 0}, | |
{0, 0, 0}, | |
}; | |
void read_t_channels(pugi::xml_node &root, t_channels &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_channels in = glex_t_channels(node.name()); | |
next = gstates0_t_channels[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_channels[(int)in], gstates0_t_channels[state0], gtok_lookup_t_channels, 3); | |
state0 = next; | |
switch(in){ | |
case gtok_t_channels::CHANNEL: | |
out.channel_list.push_back(t_channel()); | |
read_t_channel(node, out.channel_list.back()); | |
break; | |
case gtok_t_channels::X_LIST: | |
out.x_list_list.push_back(t_x_list()); | |
read_t_x_list(node, out.x_list_list.back()); | |
break; | |
case gtok_t_channels::Y_LIST: | |
out.y_list_list.push_back(t_y_list()); | |
read_t_y_list(node, out.y_list_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_channels[state0], gtok_lookup_t_channels, 3); | |
if(root.first_attribute()) std::runtime_error("Unexpected attribute in <channels>."); | |
} | |
enum class gtok_t_switches {SWITCH}; | |
const char *gtok_lookup_t_switches[] = {"switch"}; | |
gtok_t_switches glex_t_switches(const char *in){ | |
if(strcmp(in, "switch") == 0){ | |
return gtok_t_switches::SWITCH; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <switches>."); | |
} | |
int gstates0_t_switches[2][1] = { | |
{0}, | |
{0}, | |
}; | |
void read_t_switches(pugi::xml_node &root, t_switches &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_switches in = glex_t_switches(node.name()); | |
next = gstates0_t_switches[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_switches[(int)in], gstates0_t_switches[state0], gtok_lookup_t_switches, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_switches::SWITCH: | |
out.switch_list.push_back(t_switch()); | |
read_t_switch(node, out.switch_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_switches[state0], gtok_lookup_t_switches, 1); | |
if(root.first_attribute()) std::runtime_error("Unexpected attribute in <switches>."); | |
} | |
enum class gtok_t_segments {SEGMENT}; | |
const char *gtok_lookup_t_segments[] = {"segment"}; | |
gtok_t_segments glex_t_segments(const char *in){ | |
if(strcmp(in, "segment") == 0){ | |
return gtok_t_segments::SEGMENT; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <segments>."); | |
} | |
int gstates0_t_segments[2][1] = { | |
{0}, | |
{0}, | |
}; | |
void read_t_segments(pugi::xml_node &root, t_segments &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_segments in = glex_t_segments(node.name()); | |
next = gstates0_t_segments[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_segments[(int)in], gstates0_t_segments[state0], gtok_lookup_t_segments, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_segments::SEGMENT: | |
out.segment_list.push_back(t_segment()); | |
read_t_segment(node, out.segment_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_segments[state0], gtok_lookup_t_segments, 1); | |
if(root.first_attribute()) std::runtime_error("Unexpected attribute in <segments>."); | |
} | |
enum class gtok_t_block_types {BLOCK_TYPE}; | |
const char *gtok_lookup_t_block_types[] = {"block_type"}; | |
gtok_t_block_types glex_t_block_types(const char *in){ | |
if(strcmp(in, "block_type") == 0){ | |
return gtok_t_block_types::BLOCK_TYPE; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <block_types>."); | |
} | |
int gstates0_t_block_types[2][1] = { | |
{0}, | |
{0}, | |
}; | |
void read_t_block_types(pugi::xml_node &root, t_block_types &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_block_types in = glex_t_block_types(node.name()); | |
next = gstates0_t_block_types[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_block_types[(int)in], gstates0_t_block_types[state0], gtok_lookup_t_block_types, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_block_types::BLOCK_TYPE: | |
out.block_type_list.push_back(t_block_type()); | |
read_t_block_type(node, out.block_type_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_block_types[state0], gtok_lookup_t_block_types, 1); | |
if(root.first_attribute()) std::runtime_error("Unexpected attribute in <block_types>."); | |
} | |
enum class gtok_t_grid_locs {GRID_LOC}; | |
const char *gtok_lookup_t_grid_locs[] = {"grid_loc"}; | |
gtok_t_grid_locs glex_t_grid_locs(const char *in){ | |
if(strcmp(in, "grid_loc") == 0){ | |
return gtok_t_grid_locs::GRID_LOC; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <grid_locs>."); | |
} | |
int gstates0_t_grid_locs[2][1] = { | |
{0}, | |
{0}, | |
}; | |
void read_t_grid_locs(pugi::xml_node &root, t_grid_locs &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_grid_locs in = glex_t_grid_locs(node.name()); | |
next = gstates0_t_grid_locs[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_grid_locs[(int)in], gstates0_t_grid_locs[state0], gtok_lookup_t_grid_locs, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_grid_locs::GRID_LOC: | |
out.grid_loc_list.push_back(t_grid_loc()); | |
read_t_grid_loc(node, out.grid_loc_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_grid_locs[state0], gtok_lookup_t_grid_locs, 1); | |
if(root.first_attribute()) std::runtime_error("Unexpected attribute in <grid_locs>."); | |
} | |
enum class gtok_t_rr_nodes {NODE}; | |
const char *gtok_lookup_t_rr_nodes[] = {"node"}; | |
gtok_t_rr_nodes glex_t_rr_nodes(const char *in){ | |
if(strcmp(in, "node") == 0){ | |
return gtok_t_rr_nodes::NODE; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <rr_nodes>."); | |
} | |
int gstates0_t_rr_nodes[2][1] = { | |
{0}, | |
{0}, | |
}; | |
void read_t_rr_nodes(pugi::xml_node &root, t_rr_nodes &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_rr_nodes in = glex_t_rr_nodes(node.name()); | |
next = gstates0_t_rr_nodes[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_rr_nodes[(int)in], gstates0_t_rr_nodes[state0], gtok_lookup_t_rr_nodes, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_rr_nodes::NODE: | |
out.node_list.push_back(t_node()); | |
read_t_node(node, out.node_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_rr_nodes[state0], gtok_lookup_t_rr_nodes, 1); | |
if(root.first_attribute()) std::runtime_error("Unexpected attribute in <rr_nodes>."); | |
} | |
enum class gtok_t_rr_edges {EDGE}; | |
const char *gtok_lookup_t_rr_edges[] = {"edge"}; | |
gtok_t_rr_edges glex_t_rr_edges(const char *in){ | |
if(strcmp(in, "edge") == 0){ | |
return gtok_t_rr_edges::EDGE; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <rr_edges>."); | |
} | |
int gstates0_t_rr_edges[2][1] = { | |
{0}, | |
{0}, | |
}; | |
void read_t_rr_edges(pugi::xml_node &root, t_rr_edges &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_rr_edges in = glex_t_rr_edges(node.name()); | |
next = gstates0_t_rr_edges[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_rr_edges[(int)in], gstates0_t_rr_edges[state0], gtok_lookup_t_rr_edges, 1); | |
state0 = next; | |
switch(in){ | |
case gtok_t_rr_edges::EDGE: | |
out.edge_list.push_back(t_edge()); | |
read_t_edge(node, out.edge_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_rr_edges[state0], gtok_lookup_t_rr_edges, 1); | |
if(root.first_attribute()) std::runtime_error("Unexpected attribute in <rr_edges>."); | |
} | |
enum class gtok_t_rr_graph {GRID, CHANNELS, SEGMENTS, BLOCK_TYPES, RR_NODES, RR_EDGES, SWITCHES}; | |
const char *gtok_lookup_t_rr_graph[] = {"grid", "segments", "channels", "switches", "rr_edges", "block_types", "rr_nodes"}; | |
enum class atok_t_rr_graph {TOOL_NAME, TOOL_VERSION, TOOL_COMMENT}; | |
const char *atok_lookup_t_rr_graph[] = {"tool_name", "tool_version", "tool_comment"}; | |
gtok_t_rr_graph glex_t_rr_graph(const char *in){ | |
if(strcmp(in, "grid") == 0){ | |
return gtok_t_rr_graph::GRID; | |
} | |
else if(strcmp(in, "channels") == 0){ | |
return gtok_t_rr_graph::CHANNELS; | |
} | |
else if(strcmp(in, "switches") == 0){ | |
return gtok_t_rr_graph::SWITCHES; | |
} | |
else if(strcmp(in, "rr_nodes") == 0){ | |
return gtok_t_rr_graph::RR_NODES; | |
} | |
else if(strcmp(in, "segments") == 0){ | |
return gtok_t_rr_graph::SEGMENTS; | |
} | |
else if(strcmp(in, "block_types") == 0){ | |
return gtok_t_rr_graph::BLOCK_TYPES; | |
} | |
else if(strcmp(in, "rr_edges") == 0){ | |
return gtok_t_rr_graph::RR_EDGES; | |
} | |
else throw std::runtime_error("Found unrecognized child " + std::string(in) + " of <rr_graph>."); | |
} | |
atok_t_rr_graph alex_t_rr_graph(const char *in){ | |
if(strcmp(in, "tool_name") == 0){ | |
return atok_t_rr_graph::TOOL_NAME; | |
} | |
else if(strcmp(in, "tool_version") == 0){ | |
return atok_t_rr_graph::TOOL_VERSION; | |
} | |
else if(strcmp(in, "tool_comment") == 0){ | |
return atok_t_rr_graph::TOOL_COMMENT; | |
} | |
else throw std::runtime_error("Found unrecognized attribute " + std::string(in) + " of <rr_graph>."); | |
} | |
int gstates0_t_rr_graph[2][7] = { | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
}; | |
void read_t_rr_graph(pugi::xml_node &root, t_rr_graph &out){ | |
int next, state0 = 1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_rr_graph in = glex_t_rr_graph(node.name()); | |
next = gstates0_t_rr_graph[state0][(int)in]; | |
if(next == -1) dfa_error(gtok_lookup_t_rr_graph[(int)in], gstates0_t_rr_graph[state0], gtok_lookup_t_rr_graph, 7); | |
state0 = next; | |
switch(in){ | |
case gtok_t_rr_graph::CHANNELS: | |
out.channels_list.push_back(t_channels()); | |
read_t_channels(node, out.channels_list.back()); | |
break; | |
case gtok_t_rr_graph::SWITCHES: | |
out.switches_list.push_back(t_switches()); | |
read_t_switches(node, out.switches_list.back()); | |
break; | |
case gtok_t_rr_graph::SEGMENTS: | |
out.segments_list.push_back(t_segments()); | |
read_t_segments(node, out.segments_list.back()); | |
break; | |
case gtok_t_rr_graph::BLOCK_TYPES: | |
out.block_types_list.push_back(t_block_types()); | |
read_t_block_types(node, out.block_types_list.back()); | |
break; | |
case gtok_t_rr_graph::GRID: | |
out.grid_list.push_back(t_grid_locs()); | |
read_t_grid_locs(node, out.grid_list.back()); | |
break; | |
case gtok_t_rr_graph::RR_NODES: | |
out.rr_nodes_list.push_back(t_rr_nodes()); | |
read_t_rr_nodes(node, out.rr_nodes_list.back()); | |
break; | |
case gtok_t_rr_graph::RR_EDGES: | |
out.rr_edges_list.push_back(t_rr_edges()); | |
read_t_rr_edges(node, out.rr_edges_list.back()); | |
break; | |
} | |
} | |
if((state0 != 0)) dfa_error("end of input", gstates0_t_rr_graph[state0], gtok_lookup_t_rr_graph, 7); | |
std::bitset<3> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_rr_graph in = alex_t_rr_graph(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <rr_graph>."); | |
switch(in){ | |
case atok_t_rr_graph::TOOL_NAME: | |
out.tool_name = attr.value(); | |
break; | |
case atok_t_rr_graph::TOOL_VERSION: | |
out.tool_version = attr.value(); | |
break; | |
case atok_t_rr_graph::TOOL_COMMENT: | |
out.tool_comment = attr.value(); | |
break; | |
} | |
} | |
std::bitset<3> test_state = astate | std::bitset<3>(0b111); | |
if(!test_state.all()) attr_error(test_state, atok_lookup_t_rr_graph); | |
} | |
void read(const char *filename){ | |
pugi::xml_document doc; | |
pugi::xml_parse_result result = doc.load_file(filename); | |
if(!result){ | |
throw std::runtime_error("Could not load XML file " + std::string(filename) + "."); | |
} | |
pugi::xml_node node = doc.first_child(); | |
for(; node; node = node.next_sibling()){ | |
if(std::strcmp(node.name(), "rr_graph") == 0){ | |
rr_graph = std::unique_ptr<t_rr_graph>(new t_rr_graph); | |
read_t_rr_graph(node, *rr_graph); | |
} | |
else throw std::runtime_error("Invalid root-level element " + std::string(node.name())); | |
} | |
} | |
/* not generated- driver */ | |
#include <iostream> | |
int main(int argc, char **argv){ | |
read(argv[1]); | |
std::cout << rr_graph->tool_name << "\n"; | |
std::cout << rr_graph->tool_version << "\n"; | |
std::cout << rr_graph->tool_comment << "\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://gist.github.com/duck2/ebd6f51e8d8494e1885d6a8a35629556#file-rr_graph-cpp-L37-L41 - I think it would be helpful to generate helper functions for these enums which converts an enum value to a string. Useful in debugging....