Skip to content

Instantly share code, notes, and snippets.

@duck2
Created November 14, 2019 21:19
Show Gist options
  • Save duck2/758b6de52187def4d82c1d376e3a6de2 to your computer and use it in GitHub Desktop.
Save duck2/758b6de52187def4d82c1d376e3a6de2 to your computer and use it in GitHub Desktop.
[...]
/* Internal loading functions, which validate and load a PugiXML DOM tree into memory. */
inline int load_int(const char *in){
int out;
out = std::strtol(in, NULL, 10);
if(errno != 0)
throw std::runtime_error("Invalid value `" + std::string(in) + "` when loading into a int."); return out;
}
inline unsigned int load_unsignedInt(const char *in){
unsigned int out;
out = std::strtoul(in, NULL, 10);
if(errno != 0)
throw std::runtime_error("Invalid value `" + std::string(in) + "` when loading into a unsigned int."); return out;
}
inline float load_float(const char *in){
float out;
out = std::strtof(in, NULL);
if(errno != 0)
throw std::runtime_error("Invalid value `" + std::string(in) + "` when loading into a float."); return out;
}
template<class T>
void load_channel(const pugi::xml_node &root, T &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 = lex_attr_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.set_channel_chan_width_max(load_int(attr.value()));
break;
case atok_t_channel::X_MAX:
out.set_channel_x_max(load_int(attr.value()));
break;
case atok_t_channel::X_MIN:
out.set_channel_x_min(load_int(attr.value()));
break;
case atok_t_channel::Y_MAX:
out.set_channel_y_max(load_int(attr.value()));
break;
case atok_t_channel::Y_MIN:
out.set_channel_y_min(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<5> test_astate = astate | std::bitset<5>(0b00000);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_channel);
}
template<class T>
void load_x_list(const pugi::xml_node &root, T &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 = lex_attr_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.set_x_list_index(load_unsignedInt(attr.value()));
break;
case atok_t_x_list::INFO:
out.set_x_list_info(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<2> test_astate = astate | std::bitset<2>(0b00);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_x_list);
}
template<class T>
void load_y_list(const pugi::xml_node &root, T &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 = lex_attr_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.set_y_list_index(load_unsignedInt(attr.value()));
break;
case atok_t_y_list::INFO:
out.set_y_list_info(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<2> test_astate = astate | std::bitset<2>(0b00);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_y_list);
}
template<class T>
void load_timing(const pugi::xml_node &root, T &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 = lex_attr_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::CIN:
out.set_timing_Cin(load_float(attr.value()));
break;
case atok_t_timing::CINTERNAL:
out.set_timing_Cinternal(load_float(attr.value()));
break;
case atok_t_timing::COUT:
out.set_timing_Cout(load_float(attr.value()));
break;
case atok_t_timing::R:
out.set_timing_R(load_float(attr.value()));
break;
case atok_t_timing::TDEL:
out.set_timing_Tdel(load_float(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<5> test_astate = astate | std::bitset<5>(0b00000);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_timing);
}
template<class T>
void load_sizing(const pugi::xml_node &root, T &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 = lex_attr_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::BUF_SIZE:
out.set_sizing_buf_size(load_float(attr.value()));
break;
case atok_t_sizing::MUX_TRANS_SIZE:
out.set_sizing_mux_trans_size(load_float(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<2> test_astate = astate | std::bitset<2>(0b00);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_sizing);
}
template<class T>
void load_switch(const pugi::xml_node &root, T &out){
std::bitset<2> gstate = 0;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_switch in = lex_node_t_switch(node.name());
if(gstate[(int)in] == 0) gstate[(int)in] = 1;
else throw std::runtime_error("Duplicate element " + std::string(node.name()) + " in <switch>.");
switch(in){
case gtok_t_switch::TIMING:
out.init_switch_timing();
load_timing(node, out);
break;
case gtok_t_switch::SIZING:
out.init_switch_sizing();
load_sizing(node, out);
break;
default: break; /* Not possible. */
}
}
std::bitset<2> test_gstate = gstate | std::bitset<2>(0b01);
if(!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_switch);
std::bitset<3> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_switch in = lex_attr_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.set_switch_id(load_int(attr.value()));
break;
case atok_t_switch::NAME:
out.set_switch_name(attr.value());
break;
case atok_t_switch::TYPE:
out.set_switch_type(lex_switch_type(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<3> test_astate = astate | std::bitset<3>(0b100);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_switch);
}
template<class T>
void load_segment_timing(const pugi::xml_node &root, T &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 = lex_attr_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::C_PER_METER:
out.set_segment_timing_C_per_meter(load_float(attr.value()));
break;
case atok_t_segment_timing::R_PER_METER:
out.set_segment_timing_R_per_meter(load_float(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<2> test_astate = astate | std::bitset<2>(0b11);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_segment_timing);
}
template<class T>
void load_segment(const pugi::xml_node &root, T &out){
std::bitset<1> gstate = 0;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_segment in = lex_node_t_segment(node.name());
if(gstate[(int)in] == 0) gstate[(int)in] = 1;
else throw std::runtime_error("Duplicate element " + std::string(node.name()) + " in <segment>.");
switch(in){
case gtok_t_segment::TIMING:
out.init_segment_timing();
load_segment_timing(node, out);
break;
default: break; /* Not possible. */
}
}
std::bitset<1> test_gstate = gstate | std::bitset<1>(0b1);
if(!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_segment);
std::bitset<2> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_segment in = lex_attr_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.set_segment_id(load_int(attr.value()));
break;
case atok_t_segment::NAME:
out.set_segment_name(attr.value());
break;
default: break; /* Not possible. */
}
}
std::bitset<2> test_astate = astate | std::bitset<2>(0b00);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_segment);
}
template<class T>
void load_pin(const pugi::xml_node &root, T &out){
out.set_pin_value(node.child_value());
std::bitset<1> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_pin in = lex_attr_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.set_pin_ptc(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<1> test_astate = astate | std::bitset<1>(0b0);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_pin);
}
static const int NUM_T_PIN_CLASS_STATES = 2;
static const int NUM_T_PIN_CLASS_INPUTS = 1;
int gstate_t_pin_class[NUM_T_PIN_CLASS_STATES][NUM_T_PIN_CLASS_INPUTS] = {
{0},
{0},
};
template<class T>
void load_pin_class(const pugi::xml_node &root, T &out){
int next, state=1;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_pin_class in = lex_node_t_pin_class(node.name());
next = gstate_t_pin_class[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_pin_class[(int)in], gstate_t_pin_class[state], gtok_lookup_t_pin_class, 1);
state = next;
switch(in){
case gtok_t_pin_class::PIN:
out.add_pin_class_pin();
load_pin(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_pin_class[state], 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 = lex_attr_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.set_pin_class_type(lex_pin_type(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<1> test_astate = astate | std::bitset<1>(0b0);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_pin_class);
}
template<class T>
void load_meta(const pugi::xml_node &root, T &out){
out.set_meta_value(node.child_value());
std::bitset<1> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_meta in = lex_attr_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.set_meta_name(attr.value());
break;
default: break; /* Not possible. */
}
}
std::bitset<1> test_astate = astate | std::bitset<1>(0b0);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_meta);
}
static const int NUM_T_METADATA_STATES = 2;
static const int NUM_T_METADATA_INPUTS = 1;
int gstate_t_metadata[NUM_T_METADATA_STATES][NUM_T_METADATA_INPUTS] = {
{0},
{0},
};
template<class T>
void load_metadata(const pugi::xml_node &root, T &out){
int next, state=1;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_metadata in = lex_node_t_metadata(node.name());
next = gstate_t_metadata[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_metadata[(int)in], gstate_t_metadata[state], gtok_lookup_t_metadata, 1);
state = next;
switch(in){
case gtok_t_metadata::META:
out.add_metadata_meta();
load_meta(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_metadata[state], gtok_lookup_t_metadata, 1);
if(root.first_attribute())
throw std::runtime_error("Unexpected attribute in <metadata>.");
}
static const int NUM_T_BLOCK_TYPE_STATES = 1;
static const int NUM_T_BLOCK_TYPE_INPUTS = 1;
int gstate_t_block_type[NUM_T_BLOCK_TYPE_STATES][NUM_T_BLOCK_TYPE_INPUTS] = {
{0},
};
template<class T>
void load_block_type(const pugi::xml_node &root, T &out){
int next, state=0;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_block_type in = lex_node_t_block_type(node.name());
next = gstate_t_block_type[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_block_type[(int)in], gstate_t_block_type[state], gtok_lookup_t_block_type, 1);
state = next;
switch(in){
case gtok_t_block_type::PIN_CLASS:
out.add_block_type_pin_class();
load_pin_class(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_block_type[state], 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 = lex_attr_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::HEIGHT:
out.set_block_type_height(load_int(attr.value()));
break;
case atok_t_block_type::ID:
out.set_block_type_id(load_int(attr.value()));
break;
case atok_t_block_type::NAME:
out.set_block_type_name(attr.value());
break;
case atok_t_block_type::WIDTH:
out.set_block_type_width(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<4> test_astate = astate | std::bitset<4>(0b0000);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_block_type);
}
template<class T>
void load_grid_loc(const pugi::xml_node &root, T &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 = lex_attr_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::BLOCK_TYPE_ID:
out.set_grid_loc_block_type_id(load_int(attr.value()));
break;
case atok_t_grid_loc::HEIGHT_OFFSET:
out.set_grid_loc_height_offset(load_int(attr.value()));
break;
case atok_t_grid_loc::WIDTH_OFFSET:
out.set_grid_loc_width_offset(load_int(attr.value()));
break;
case atok_t_grid_loc::X:
out.set_grid_loc_x(load_int(attr.value()));
break;
case atok_t_grid_loc::Y:
out.set_grid_loc_y(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<5> test_astate = astate | std::bitset<5>(0b00000);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_grid_loc);
}
template<class T>
void load_node_loc(const pugi::xml_node &root, T &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 = lex_attr_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::PTC:
out.set_node_loc_ptc(load_int(attr.value()));
break;
case atok_t_node_loc::SIDE:
out.set_node_loc_side(lex_loc_side(attr.value()));
break;
case atok_t_node_loc::XHIGH:
out.set_node_loc_xhigh(load_int(attr.value()));
break;
case atok_t_node_loc::XLOW:
out.set_node_loc_xlow(load_int(attr.value()));
break;
case atok_t_node_loc::YHIGH:
out.set_node_loc_yhigh(load_int(attr.value()));
break;
case atok_t_node_loc::YLOW:
out.set_node_loc_ylow(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<6> test_astate = astate | std::bitset<6>(0b000010);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_loc);
}
template<class T>
void load_node_timing(const pugi::xml_node &root, T &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 = lex_attr_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::C:
out.set_node_timing_C(load_float(attr.value()));
break;
case atok_t_node_timing::R:
out.set_node_timing_R(load_float(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<2> test_astate = astate | std::bitset<2>(0b00);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_timing);
}
template<class T>
void load_node_segment(const pugi::xml_node &root, T &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 = lex_attr_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.set_node_segment_segment_id(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<1> test_astate = astate | std::bitset<1>(0b0);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_segment);
}
template<class T>
void load_node_connection_box(const pugi::xml_node &root, T &out){
if(root.first_child().type() == pugi::node_element)
throw std::runtime_error("Unexpected child element in <node_connection_box>.");
std::bitset<3> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_node_connection_box in = lex_attr_t_node_connection_box(attr.name());
if(astate[(int)in] == 0) astate[(int)in] = 1;
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node_connection_box>.");
switch(in){
case atok_t_node_connection_box::ID:
out.set_node_connection_box_id(load_int(attr.value()));
break;
case atok_t_node_connection_box::X:
out.set_node_connection_box_x(load_int(attr.value()));
break;
case atok_t_node_connection_box::Y:
out.set_node_connection_box_y(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<3> test_astate = astate | std::bitset<3>(0b000);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_connection_box);
}
template<class T>
void load_node_canonical_loc(const pugi::xml_node &root, T &out){
if(root.first_child().type() == pugi::node_element)
throw std::runtime_error("Unexpected child element in <node_canonical_loc>.");
std::bitset<2> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_node_canonical_loc in = lex_attr_t_node_canonical_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_canonical_loc>.");
switch(in){
case atok_t_node_canonical_loc::X:
out.set_node_canonical_loc_x(load_int(attr.value()));
break;
case atok_t_node_canonical_loc::Y:
out.set_node_canonical_loc_y(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<2> test_astate = astate | std::bitset<2>(0b00);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_canonical_loc);
}
template<class T>
void load_node(const pugi::xml_node &root, T &out){
std::bitset<6> gstate = 0;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_node in = lex_node_t_node(node.name());
if(gstate[(int)in] == 0) gstate[(int)in] = 1;
else throw std::runtime_error("Duplicate element " + std::string(node.name()) + " in <node>.");
switch(in){
case gtok_t_node::LOC:
out.init_node_loc();
load_node_loc(node, out);
break;
case gtok_t_node::TIMING:
out.init_node_timing();
load_node_timing(node, out);
break;
case gtok_t_node::SEGMENT:
out.init_node_segment();
load_node_segment(node, out);
break;
case gtok_t_node::CONNECTION_BOX:
out.init_node_connection_box();
load_node_connection_box(node, out);
break;
case gtok_t_node::CANONICAL_LOC:
out.init_node_canonical_loc();
load_node_canonical_loc(node, out);
break;
case gtok_t_node::METADATA:
out.init_node_metadata();
load_metadata(node, out);
break;
default: break; /* Not possible. */
}
}
std::bitset<6> test_gstate = gstate | std::bitset<6>(0b111110);
if(!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_node);
std::bitset<4> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_node in = lex_attr_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::CAPACITY:
out.set_node_capacity(load_unsignedInt(attr.value()));
break;
case atok_t_node::DIRECTION:
out.set_node_direction(lex_node_direction(attr.value()));
break;
case atok_t_node::ID:
out.set_node_id(load_unsignedInt(attr.value()));
break;
case atok_t_node::TYPE:
out.set_node_type(lex_node_type(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<4> test_astate = astate | std::bitset<4>(0b0010);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node);
}
template<class T>
void load_edge(const pugi::xml_node &root, T &out){
std::bitset<1> gstate = 0;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_edge in = lex_node_t_edge(node.name());
if(gstate[(int)in] == 0) gstate[(int)in] = 1;
else throw std::runtime_error("Duplicate element " + std::string(node.name()) + " in <edge>.");
switch(in){
case gtok_t_edge::METADATA:
out.init_edge_metadata();
load_metadata(node, out);
break;
default: break; /* Not possible. */
}
}
std::bitset<1> test_gstate = gstate | std::bitset<1>(0b1);
if(!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_edge);
std::bitset<4> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_edge in = lex_attr_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.set_edge_id(load_unsignedInt(attr.value()));
break;
case atok_t_edge::SINK_NODE:
out.set_edge_sink_node(load_unsignedInt(attr.value()));
break;
case atok_t_edge::SRC_NODE:
out.set_edge_src_node(load_unsignedInt(attr.value()));
break;
case atok_t_edge::SWITCH_ID:
out.set_edge_switch_id(load_unsignedInt(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<4> test_astate = astate | std::bitset<4>(0b0001);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_edge);
}
static const int NUM_T_CHANNELS_STATES = 4;
static const int NUM_T_CHANNELS_INPUTS = 3;
int gstate_t_channels[NUM_T_CHANNELS_STATES][NUM_T_CHANNELS_INPUTS] = {
{-1, -1, 0},
{-1, 1, 0},
{-1, 1, -1},
{2, -1, -1},
};
template<class T>
void load_channels(const pugi::xml_node &root, T &out){
int next, state=3;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_channels in = lex_node_t_channels(node.name());
next = gstate_t_channels[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_channels[(int)in], gstate_t_channels[state], gtok_lookup_t_channels, 3);
state = next;
switch(in){
case gtok_t_channels::CHANNEL:
out.init_channels_channel();
load_channel(node, out);
break;
case gtok_t_channels::X_LIST:
out.add_channels_x_list();
load_x_list(node, out);
break;
case gtok_t_channels::Y_LIST:
out.add_channels_y_list();
load_y_list(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_channels[state], gtok_lookup_t_channels, 3);
if(root.first_attribute())
throw std::runtime_error("Unexpected attribute in <channels>.");
}
static const int NUM_T_SWITCHES_STATES = 2;
static const int NUM_T_SWITCHES_INPUTS = 1;
int gstate_t_switches[NUM_T_SWITCHES_STATES][NUM_T_SWITCHES_INPUTS] = {
{0},
{0},
};
template<class T>
void load_switches(const pugi::xml_node &root, T &out){
int next, state=1;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_switches in = lex_node_t_switches(node.name());
next = gstate_t_switches[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_switches[(int)in], gstate_t_switches[state], gtok_lookup_t_switches, 1);
state = next;
switch(in){
case gtok_t_switches::SWITCH:
out.add_switches_switch();
load_switch(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_switches[state], gtok_lookup_t_switches, 1);
if(root.first_attribute())
throw std::runtime_error("Unexpected attribute in <switches>.");
}
static const int NUM_T_SEGMENTS_STATES = 2;
static const int NUM_T_SEGMENTS_INPUTS = 1;
int gstate_t_segments[NUM_T_SEGMENTS_STATES][NUM_T_SEGMENTS_INPUTS] = {
{0},
{0},
};
template<class T>
void load_segments(const pugi::xml_node &root, T &out){
int next, state=1;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_segments in = lex_node_t_segments(node.name());
next = gstate_t_segments[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_segments[(int)in], gstate_t_segments[state], gtok_lookup_t_segments, 1);
state = next;
switch(in){
case gtok_t_segments::SEGMENT:
out.add_segments_segment();
load_segment(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_segments[state], gtok_lookup_t_segments, 1);
if(root.first_attribute())
throw std::runtime_error("Unexpected attribute in <segments>.");
}
static const int NUM_T_BLOCK_TYPES_STATES = 2;
static const int NUM_T_BLOCK_TYPES_INPUTS = 1;
int gstate_t_block_types[NUM_T_BLOCK_TYPES_STATES][NUM_T_BLOCK_TYPES_INPUTS] = {
{0},
{0},
};
template<class T>
void load_block_types(const pugi::xml_node &root, T &out){
int next, state=1;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_block_types in = lex_node_t_block_types(node.name());
next = gstate_t_block_types[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_block_types[(int)in], gstate_t_block_types[state], gtok_lookup_t_block_types, 1);
state = next;
switch(in){
case gtok_t_block_types::BLOCK_TYPE:
out.add_block_types_block_type();
load_block_type(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_block_types[state], gtok_lookup_t_block_types, 1);
if(root.first_attribute())
throw std::runtime_error("Unexpected attribute in <block_types>.");
}
static const int NUM_T_GRID_LOCS_STATES = 2;
static const int NUM_T_GRID_LOCS_INPUTS = 1;
int gstate_t_grid_locs[NUM_T_GRID_LOCS_STATES][NUM_T_GRID_LOCS_INPUTS] = {
{0},
{0},
};
template<class T>
void load_grid_locs(const pugi::xml_node &root, T &out){
int next, state=1;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_grid_locs in = lex_node_t_grid_locs(node.name());
next = gstate_t_grid_locs[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_grid_locs[(int)in], gstate_t_grid_locs[state], gtok_lookup_t_grid_locs, 1);
state = next;
switch(in){
case gtok_t_grid_locs::GRID_LOC:
out.add_grid_locs_grid_loc();
load_grid_loc(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_grid_locs[state], gtok_lookup_t_grid_locs, 1);
if(root.first_attribute())
throw std::runtime_error("Unexpected attribute in <grid_locs>.");
}
static const int NUM_T_RR_NODES_STATES = 2;
static const int NUM_T_RR_NODES_INPUTS = 1;
int gstate_t_rr_nodes[NUM_T_RR_NODES_STATES][NUM_T_RR_NODES_INPUTS] = {
{0},
{0},
};
template<class T>
void load_rr_nodes(const pugi::xml_node &root, T &out){
int next, state=1;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_rr_nodes in = lex_node_t_rr_nodes(node.name());
next = gstate_t_rr_nodes[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_rr_nodes[(int)in], gstate_t_rr_nodes[state], gtok_lookup_t_rr_nodes, 1);
state = next;
switch(in){
case gtok_t_rr_nodes::NODE:
out.add_rr_nodes_node();
load_node(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_rr_nodes[state], gtok_lookup_t_rr_nodes, 1);
if(root.first_attribute())
throw std::runtime_error("Unexpected attribute in <rr_nodes>.");
}
static const int NUM_T_RR_EDGES_STATES = 2;
static const int NUM_T_RR_EDGES_INPUTS = 1;
int gstate_t_rr_edges[NUM_T_RR_EDGES_STATES][NUM_T_RR_EDGES_INPUTS] = {
{0},
{0},
};
template<class T>
void load_rr_edges(const pugi::xml_node &root, T &out){
int next, state=1;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_rr_edges in = lex_node_t_rr_edges(node.name());
next = gstate_t_rr_edges[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_rr_edges[(int)in], gstate_t_rr_edges[state], gtok_lookup_t_rr_edges, 1);
state = next;
switch(in){
case gtok_t_rr_edges::EDGE:
out.add_rr_edges_edge();
load_edge(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_rr_edges[state], gtok_lookup_t_rr_edges, 1);
if(root.first_attribute())
throw std::runtime_error("Unexpected attribute in <rr_edges>.");
}
template<class T>
void load_bin_nodes(const pugi::xml_node &root, T &out){
if(root.first_child().type() == pugi::node_element)
throw std::runtime_error("Unexpected child element in <bin_nodes>.");
std::bitset<1> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_bin_nodes in = lex_attr_t_bin_nodes(attr.name());
if(astate[(int)in] == 0) astate[(int)in] = 1;
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <bin_nodes>.");
switch(in){
case atok_t_bin_nodes::FILE:
out.set_bin_nodes_file(attr.value());
break;
default: break; /* Not possible. */
}
}
std::bitset<1> test_astate = astate | std::bitset<1>(0b1);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_bin_nodes);
}
template<class T>
void load_connection_box(const pugi::xml_node &root, T &out){
if(root.first_child().type() == pugi::node_element)
throw std::runtime_error("Unexpected child element in <connection_box>.");
std::bitset<2> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_connection_box in = lex_attr_t_connection_box(attr.name());
if(astate[(int)in] == 0) astate[(int)in] = 1;
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <connection_box>.");
switch(in){
case atok_t_connection_box::ID:
out.set_connection_box_id(load_unsignedInt(attr.value()));
break;
case atok_t_connection_box::NAME:
out.set_connection_box_name(attr.value());
break;
default: break; /* Not possible. */
}
}
std::bitset<2> test_astate = astate | std::bitset<2>(0b00);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_connection_box);
}
static const int NUM_T_CONNECTION_BOXES_STATES = 2;
static const int NUM_T_CONNECTION_BOXES_INPUTS = 1;
int gstate_t_connection_boxes[NUM_T_CONNECTION_BOXES_STATES][NUM_T_CONNECTION_BOXES_INPUTS] = {
{0},
{0},
};
template<class T>
void load_connection_boxes(const pugi::xml_node &root, T &out){
int next, state=1;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_connection_boxes in = lex_node_t_connection_boxes(node.name());
next = gstate_t_connection_boxes[state][(int)in];
if(next == -1)
dfa_error(gtok_lookup_t_connection_boxes[(int)in], gstate_t_connection_boxes[state], gtok_lookup_t_connection_boxes, 1);
state = next;
switch(in){
case gtok_t_connection_boxes::CONNECTION_BOX:
out.add_connection_boxes_connection_box();
load_connection_box(node, out);
break;
default: break; /* Not possible. */
}
}
if(state != 0) dfa_error("end of input", gstate_t_connection_boxes[state], gtok_lookup_t_connection_boxes, 1);
std::bitset<3> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_connection_boxes in = lex_attr_t_connection_boxes(attr.name());
if(astate[(int)in] == 0) astate[(int)in] = 1;
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <connection_boxes>.");
switch(in){
case atok_t_connection_boxes::NUM_BOXES:
out.set_connection_boxes_num_boxes(load_unsignedInt(attr.value()));
break;
case atok_t_connection_boxes::X_DIM:
out.set_connection_boxes_x_dim(load_int(attr.value()));
break;
case atok_t_connection_boxes::Y_DIM:
out.set_connection_boxes_y_dim(load_int(attr.value()));
break;
default: break; /* Not possible. */
}
}
std::bitset<3> test_astate = astate | std::bitset<3>(0b000);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_connection_boxes);
}
template<class T>
void load_rr_graph(const pugi::xml_node &root, T &out){
std::bitset<9> gstate = 0;
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){
gtok_t_rr_graph in = lex_node_t_rr_graph(node.name());
if(gstate[(int)in] == 0) gstate[(int)in] = 1;
else throw std::runtime_error("Duplicate element " + std::string(node.name()) + " in <rr_graph>.");
switch(in){
case gtok_t_rr_graph::BINARY_NODES_AND_EDGES:
out.init_rr_graph_binary_nodes_and_edges();
load_bin_nodes(node, out);
break;
case gtok_t_rr_graph::CONNECTION_BOXES:
out.init_rr_graph_connection_boxes();
load_connection_boxes(node, out);
break;
case gtok_t_rr_graph::CHANNELS:
out.init_rr_graph_channels();
load_channels(node, out);
break;
case gtok_t_rr_graph::SWITCHES:
out.init_rr_graph_switches();
load_switches(node, out);
break;
case gtok_t_rr_graph::SEGMENTS:
out.init_rr_graph_segments();
load_segments(node, out);
break;
case gtok_t_rr_graph::BLOCK_TYPES:
out.init_rr_graph_block_types();
load_block_types(node, out);
break;
case gtok_t_rr_graph::GRID:
out.init_rr_graph_grid();
load_grid_locs(node, out);
break;
case gtok_t_rr_graph::RR_NODES:
out.init_rr_graph_rr_nodes();
load_rr_nodes(node, out);
break;
case gtok_t_rr_graph::RR_EDGES:
out.init_rr_graph_rr_edges();
load_rr_edges(node, out);
break;
default: break; /* Not possible. */
}
}
std::bitset<9> test_gstate = gstate | std::bitset<9>(0b000000011);
if(!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_rr_graph);
std::bitset<3> astate = 0;
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){
atok_t_rr_graph in = lex_attr_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_COMMENT:
out.set_rr_graph_tool_comment(attr.value());
break;
case atok_t_rr_graph::TOOL_NAME:
out.set_rr_graph_tool_name(attr.value());
break;
case atok_t_rr_graph::TOOL_VERSION:
out.set_rr_graph_tool_version(attr.value());
break;
default: break; /* Not possible. */
}
}
std::bitset<3> test_astate = astate | std::bitset<3>(0b111);
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_rr_graph);
}
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(unsigned 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));
}
template<std::size_t N>
void all_error(std::bitset<N> gstate, const char **lookup){
std::vector<std::string> 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];
throw std::runtime_error("Didn't find required elements " + missing_and + ".");
}
template<std::size_t N>
void attr_error(std::bitset<N> astate, const char **lookup){
std::vector<std::string> 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];
throw std::runtime_error("Didn't find required attributes " + missing_and + ".");
}
} /* namespace uxsd */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment