diff --git a/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp b/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp index 160c3183a..25e1e12f8 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_pb_type_annotation.cpp @@ -14,6 +14,7 @@ /* Headers from openfpga util library */ #include "openfpga_port_parser.h" +#include "openfpga_pb_parser.h" /* Headers from libarchfpga */ #include "arch_error.h" @@ -80,14 +81,36 @@ void read_xml_pb_type_annotation(pugi::xml_node& xml_pb_type, if ( (false == name_attr.empty()) && (false == physical_name_attr.empty()) ) { /* Parse the attributes for operating pb_type */ - pb_type_annotation.set_operating_pb_type_name(name_attr); - pb_type_annotation.set_physical_pb_type_name(physical_name_attr); + openfpga::PbParser operating_pb_parser(name_attr); + pb_type_annotation.set_operating_pb_type_name(operating_pb_parser.leaf()); + if (0 < operating_pb_parser.parents().size()) { + pb_type_annotation.set_operating_parent_pb_type_names(operating_pb_parser.parents()); + } + if (0 < operating_pb_parser.modes().size()) { + pb_type_annotation.set_operating_parent_mode_names(operating_pb_parser.modes()); + } + + openfpga::PbParser physical_pb_parser(physical_name_attr); + pb_type_annotation.set_physical_pb_type_name(physical_pb_parser.leaf()); + if (0 < physical_pb_parser.parents().size()) { + pb_type_annotation.set_physical_parent_pb_type_names(physical_pb_parser.parents()); + } + if (0 < physical_pb_parser.modes().size()) { + pb_type_annotation.set_physical_parent_mode_names(physical_pb_parser.modes()); + } } /* If there is only a name, this is a physical pb_type */ if ( (false == name_attr.empty()) && (true == physical_name_attr.empty()) ) { - pb_type_annotation.set_physical_pb_type_name(name_attr); + openfpga::PbParser physical_pb_parser(name_attr); + pb_type_annotation.set_physical_pb_type_name(physical_pb_parser.leaf()); + if (0 < physical_pb_parser.parents().size()) { + pb_type_annotation.set_physical_parent_pb_type_names(physical_pb_parser.parents()); + } + if (0 < physical_pb_parser.modes().size()) { + pb_type_annotation.set_physical_parent_mode_names(physical_pb_parser.modes()); + } } /* Parse physical mode name which are applied to both pb_types */ diff --git a/libopenfpga/libopenfpgautil/src/openfpga_pb_parser.cpp b/libopenfpga/libopenfpgautil/src/openfpga_pb_parser.cpp new file mode 100644 index 000000000..ee674b928 --- /dev/null +++ b/libopenfpga/libopenfpgautil/src/openfpga_pb_parser.cpp @@ -0,0 +1,117 @@ +/************************************************************************ + * Member functions for Pb parsers + ***********************************************************************/ +#include + +#include "vtr_assert.h" + +#include "openfpga_tokenizer.h" + +#include "openfpga_pb_parser.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/************************************************************************ + * Member functions for PbParser class + ***********************************************************************/ + +/************************************************************************ + * Constructors + ***********************************************************************/ +PbParser::PbParser (const std::string& data) { + set_default_bracket(); + set_default_delim(); + set_data(data); +} + +/************************************************************************ + * Public Accessors + ***********************************************************************/ +/* Get the data string */ +std::string PbParser::data() const { + return data_; +} + +std::string PbParser::leaf() const { + return leaf_; +} + +std::vector PbParser::parents() const { + return parents_; +} + +std::vector PbParser::modes() const { + return modes_; +} + +/************************************************************************ + * Public Mutators + ***********************************************************************/ +void PbParser::set_data(const std::string& data) { + data_ = data; + parse(); +} + +/************************************************************************ + * Internal Mutators + ***********************************************************************/ +/* Parse the data */ +void PbParser::parse() { + /* Create a tokenizer */ + StringToken tokenizer(data_); + + /* Split the data into [] */ + std::vector pb_tokens = tokenizer.split(delim_); + + /* The last pb is the leaf node. + * It should NOT be empty and should NOT contain any brackets! + */ + VTR_ASSERT(false == pb_tokens.back().empty()); + VTR_ASSERT(pb_tokens.back().find(bracket_.x()) == std::string::npos); + VTR_ASSERT(pb_tokens.back().find(bracket_.y()) == std::string::npos); + /* Pass the check, we assign the value */ + leaf_ = pb_tokens.back(); + + /* Split the rest of pb_tokens, split the pb_type and mode_name */ + for (size_t itok = 0; itok < pb_tokens.size() - 1; ++itok) { + /* Create a tokenizer */ + StringToken pb_tokenizer(pb_tokens[itok]); + std::vector tokens = pb_tokenizer.split(bracket_.x()); + /* Make sure we have a port name! */ + VTR_ASSERT_SAFE ((1 == tokens.size()) || (2 == tokens.size())); + /* Store the pb_type name */ + parents_.push_back(tokens[0]); + + /* If we only have one token, the mode name is the default mode + * Here we use the default keyword 'default' + * from VPR function ProcessMode() in libarchfpga + */ + if (1 == tokens.size()) { + modes_.push_back(std::string("default")); + continue; /* We can finish here */ + } + + /* If there is a mode name, extract it */ + VTR_ASSERT_SAFE (2 == tokens.size()); + + /* Chomp the ']' */ + pb_tokenizer.set_data(tokens[1]); + std::vector mode_tokens = pb_tokenizer.split(bracket_.y()); + + /* Make sure we have only one mode name inside */ + VTR_ASSERT(1 == mode_tokens.size()); + modes_.push_back(mode_tokens[0]); + } +} + +void PbParser::set_default_bracket() { + bracket_.set_x('['); + bracket_.set_y(']'); +} + +void PbParser::set_default_delim() { + delim_ = '.'; +} + +} /* namespace openfpga ends */ diff --git a/libopenfpga/libopenfpgautil/src/openfpga_pb_parser.h b/libopenfpga/libopenfpgautil/src/openfpga_pb_parser.h new file mode 100644 index 000000000..d59286136 --- /dev/null +++ b/libopenfpga/libopenfpgautil/src/openfpga_pb_parser.h @@ -0,0 +1,56 @@ +#ifndef OPENFPGA_PB_PARSER_H +#define OPENFPGA_PB_PARSER_H + +/******************************************************************** + * Include header files that are required by data structure declaration + *******************************************************************/ +#include +#include + +#include "vtr_geometry.h" + +#include "openfpga_tokenizer.h" + +/************************************************************************ + * This file includes parsers for pb_type definition in the architecture XML + * language. + ***********************************************************************/ + +/* namespace openfpga begins */ +namespace openfpga { + +/************************************************************************ + * Class PbParser: pb_type name with full hierarchy parser + * Supported pb_type definition: + * 1. [].[] ... . + * 2. . ... . + * where each pb_type may be specified by a mode or use the default mode + * (mode name not given) + ***********************************************************************/ +class PbParser{ + public : /* Constructors*/ + PbParser (const std::string& data); + public : /* Public Accessors */ + std::string data() const; + std::string leaf() const; + std::vector parents() const; + std::vector modes() const; + public : /* Public Mutators */ + void set_data(const std::string& data); + private : /* Private Mutators */ + void parse(); + void set_default_bracket(); + void set_default_delim(); + private: /* Internal data */ + std::string data_; /* Lines to be splited */ + vtr::Point bracket_; + char delim_; + std::vector parents_; + std::vector modes_; + std::string leaf_; +}; + +} /* namespace openfpga ends */ + +#endif +