[Lib] Adding XML parser for the bus group

This commit is contained in:
tangxifan 2022-02-17 15:50:44 -08:00
parent 4a78bcf5d3
commit 1edaa04715
4 changed files with 209 additions and 4 deletions

View File

@ -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] );
}

View File

@ -36,8 +36,10 @@
class BusGroup {
public: /* Types */
typedef vtr::vector<BusGroupId, BusGroupId>::const_iterator bus_group_iterator;
typedef vtr::vector<BusPinId, BusPinId>::const_iterator bus_pin_iterator;
/* Create range */
typedef vtr::Range<bus_group_iterator> bus_group_range;
typedef vtr::Range<bus_pin_iterator> 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<BusGroupId, BusGroupId> bus_ids_;
@ -68,10 +85,16 @@ class BusGroup {
vtr::vector<BusGroupId, openfpga::BasicPort> bus_ports_;
/* Indices of each pin under each bus */
vtr::vector<BusGroupId, std::vector<int>> bus_pin_indices_;
vtr::vector<BusGroupId, std::vector<BusPinId>> bus_pin_ids_;
/* Unique ids for each pin */
vtr::vector<BusPinId, BusPinId> pin_ids_;
/* Index for each pin */
vtr::vector<BusPinId, int> pin_indices_;
/* Name of each pin under each bus */
vtr::vector<BusGroupId, std::vector<std::string>> bus_pin_names_;
vtr::vector<BusPinId, std::string> pin_names_;
};
#endif

View File

@ -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 <string>
/* 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 <pin> 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 <bus> 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 <bus_group> 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;
}

View File

@ -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