[Lib] Adding XML parser for the bus group
This commit is contained in:
parent
4a78bcf5d3
commit
1edaa04715
|
@ -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] );
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
Loading…
Reference in New Issue