From 1edaa04715a02e3cac79cd148048b56b9ab47b41 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Thu, 17 Feb 2022 15:50:44 -0800 Subject: [PATCH] [Lib] Adding XML parser for the bus group --- libopenfpga/libbusgroup/src/bus_group.cpp | 37 ++++- libopenfpga/libbusgroup/src/bus_group.h | 29 +++- .../libbusgroup/src/read_xml_bus_group.cpp | 131 ++++++++++++++++++ .../libbusgroup/src/read_xml_bus_group.h | 16 +++ 4 files changed, 209 insertions(+), 4 deletions(-) create mode 100644 libopenfpga/libbusgroup/src/read_xml_bus_group.cpp create mode 100644 libopenfpga/libbusgroup/src/read_xml_bus_group.h diff --git a/libopenfpga/libbusgroup/src/bus_group.cpp b/libopenfpga/libbusgroup/src/bus_group.cpp index b4c05b7b4..3d6682a08 100644 --- a/libopenfpga/libbusgroup/src/bus_group.cpp +++ b/libopenfpga/libbusgroup/src/bus_group.cpp @@ -46,6 +46,12 @@ void BusGroup::reserve_buses(const size_t& num_buses) { bus_pin_names_.reserve(num_buses); } +void BusGroup::reserve_pins(const size_t& num_pins) { + pin_ids_.reserve(num_pins); + pin_indices_.reserve(num_pins); + pin_names_.reserve(num_pins); +} + BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) { /* Create a new id */ BusGroupId bus_id = BusGroupId(bus_ids_.size()); @@ -58,11 +64,40 @@ BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) { return bus_id; } +BusPinId BasicGroup::create_pin(const BusGroupId& bus_id) { + /* Create a new id */ + BusPinId pin_id = BusPinId(pin_ids_.size()); + + pin_ids_.push_back(pin_id); + + pin_indices_.emplace_back(); + pin_names_.emplace_back(); + + /* Register the pin to the bus */ + VTR_ASSERT(valid_bus_id(bus_id)); + bus_pin_ids_[bus_id].push_back(pin_id); + + return bus_id; +} + +void BusGroup::set_pin_index(const BusPinId& pin_id, const int& index) { + VTR_ASSERT(valid_pin_id(pin_id)); + pin_indices_[pin_id] = index; +} + +void BusGroup::set_pin_name(const BusPinId& pin_id, const std::string& name) { + VTR_ASSERT(valid_pin_id(pin_id)); + pin_names_[pin_id] = name; +} + /************************************************************************ * Internal invalidators/validators ***********************************************************************/ -/* Validators */ bool BusGroup::valid_bus_id(const BusGroupId& bus_id) const { return ( size_t(bus_id) < bus_ids_.size() ) && ( bus_id == bus_ids_[bus_id] ); } +bool BusGroup::valid_pin_id(const BusPinId& pin_id) const { + return ( size_t(pin_id) < pin_ids_.size() ) && ( pin_id == pin_ids_[pin_id] ); +} + diff --git a/libopenfpga/libbusgroup/src/bus_group.h b/libopenfpga/libbusgroup/src/bus_group.h index 6f8517fd0..ad2393be2 100644 --- a/libopenfpga/libbusgroup/src/bus_group.h +++ b/libopenfpga/libbusgroup/src/bus_group.h @@ -36,8 +36,10 @@ class BusGroup { public: /* Types */ typedef vtr::vector::const_iterator bus_group_iterator; + typedef vtr::vector::const_iterator bus_pin_iterator; /* Create range */ typedef vtr::Range bus_group_range; + typedef vtr::Range bus_pin_range; public: /* Constructors */ BusGroup(); public: /* Accessors: aggregates */ @@ -53,13 +55,28 @@ class BusGroup { /* Reserve a number of buses to be memory efficent */ void reserve_buses(const size_t& num_buses); + /* Reserve a number of pins to be memory efficent */ + void reserve_pins(const size_t& num_pins); + /* Add a bus to storage */ BusGroupId create_bus(const openfpga::BasicPort& bus_port); + /* Add a pin to a bus */ + BusPinId create_pin(const BusGroupId& bus_id); + + /* Set the index for a pin */ + void set_pin_index(const BusPinId& pin_id, const int& index); + + /* Set the name for a pin */ + void set_pin_index(const BusPinId& pin_id, const std::string& name); + public: /* Public invalidators/validators */ - /* Show if the pin constraint id is a valid for data queries */ + /* Show if the bus id is a valid for data queries */ bool valid_bus_id(const BusGroupId& bus_id) const; + /* Show if the pin id is a valid for data queries */ + bool valid_pin_id(const BusPinId& pin_id) const; + private: /* Internal data */ /* Unique ids for each bus */ vtr::vector bus_ids_; @@ -68,10 +85,16 @@ class BusGroup { vtr::vector bus_ports_; /* Indices of each pin under each bus */ - vtr::vector> bus_pin_indices_; + vtr::vector> bus_pin_ids_; + + /* Unique ids for each pin */ + vtr::vector pin_ids_; + + /* Index for each pin */ + vtr::vector pin_indices_; /* Name of each pin under each bus */ - vtr::vector> bus_pin_names_; + vtr::vector pin_names_; }; #endif diff --git a/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp b/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp new file mode 100644 index 000000000..f904e5206 --- /dev/null +++ b/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp @@ -0,0 +1,131 @@ +/******************************************************************** + * This file includes the top-level function of this library + * which reads an XML of bus group file to the associated + * data structures + *******************************************************************/ +#include + +/* Headers from pugi XML library */ +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_time.h" + +/* Headers from libopenfpga util library */ +#include "openfpga_port_parser.h" + +/* Headers from libarchfpga */ +#include "arch_error.h" +#include "read_xml_util.h" + +#include "read_xml_bus_group.h" + +/******************************************************************** + * Parse XML codes of a to an object of BusGroup + *******************************************************************/ +static +void read_xml_pin(pugi::xml_node& xml_pin, + const pugiutil::loc_data& loc_data, + BusGroup& bus_group, + const BusGroupId& bus_id) { + if (false == bus_group.valid_bus_id(bus_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin), + "Invalid id of a bus group!\n"); + } + + int pin_index = get_attribute(xml_pin, "id", loc_data).as_int(); + std::string pin_name = get_attribute(xml_pin, "name", loc_data).as_string(); + + /* Before update storage, check if the pin index is in the range */ + BasicPort pin_port(bus_group.bus_port(bus_id).get_name(), pin_index, pin_index); + if (!bus_group.bus_port(bus_id).contained(pin_port)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin), + "Pin index is out of range of the bus port width!\n"); + } + + BusPinId pin_id = bus_group.create_pin(bus_id); + bus_group.set_pin_index(pin_id, pin_index); + bus_group.set_pin_name(pin_id, pin_name); +} + +/******************************************************************** + * Parse XML codes of a to an object of BusGroup + *******************************************************************/ +static +void read_xml_bus(pugi::xml_node& xml_bus, + const pugiutil::loc_data& loc_data, + BusGroup& bus_group) { + + openfpga::PortParser port_parser(get_attribute(xml_bus, "name", loc_data).as_string()); + + /* Create a new bus in the storage */ + BusGroupId bus_id = bus_group.create_bus(port_parser.port()); + + if (false == bus_group.valid_bus_id(bus_id)) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_bus), + "Fail to create a bus group!\n"); + } + + /* Ensure the bus port is valid */ + if (!bus_group.bus_port(bus_id).is_valid()) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_pin), + "Bus port is invalid, check LSB and MSB!\n"); + } + + for (pugi::xml_node xml_pin : xml_bus.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_pin.name() != std::string("pin")) { + bad_tag(xml_pin, loc_data, xml_root, {"pin"}); + } + read_xml_pin(xml_pin, loc_data, bus_group, bus_id); + } +} + +/******************************************************************** + * Parse XML codes about to an object of BusGroup + *******************************************************************/ +BusGroup read_xml_bus_group(const char* fname) { + + vtr::ScopedStartFinishTimer timer("Read Bus Group"); + + BusGroup bus_group; + + /* Parse the file */ + pugi::xml_document doc; + pugiutil::loc_data loc_data; + + try { + loc_data = pugiutil::load_xml(doc, fname); + + pugi::xml_node xml_root = get_single_child(doc, "bus_group", loc_data); + + size_t num_buses = std::distance(xml_root.children().begin(), xml_root.children().end()); + + /* Count the total number of pins */ + size_t num_pins = 0; + for (pugi::xml_node xml_bus : xml_root.children()) { + num_pins += std::distance(xml_bus.children().begin(), xml_bus.children().end()); + } + + /* Reserve memory space for the buses */ + bus_group.reserve_buses(num_buses); + /* Reserve memory space for the pins */ + bus_group.reserve_pins(num_pins); + + for (pugi::xml_node xml_bus : xml_root.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_bus.name() != std::string("bus")) { + bad_tag(xml_bus, loc_data, xml_root, {"bus"}); + } + read_xml_bus(xml_bus, loc_data, bus_group); + } + } catch (pugiutil::XmlError& e) { + archfpga_throw(fname, e.line(), + "%s", e.what()); + } + + return bus_group; +} + diff --git a/libopenfpga/libbusgroup/src/read_xml_bus_group.h b/libopenfpga/libbusgroup/src/read_xml_bus_group.h new file mode 100644 index 000000000..8be1fa04d --- /dev/null +++ b/libopenfpga/libbusgroup/src/read_xml_bus_group.h @@ -0,0 +1,16 @@ +#ifndef READ_XML_BUS_GROUP_H +#define READ_XML_BUS_GROUP_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "pugixml_util.hpp" +#include "pugixml.hpp" +#include "bus_group.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +BusGroup read_xml_bus_group(const char* fname); + +#endif