finish XML parser and writer for pb_type annotation
This commit is contained in:
parent
1cba141dd0
commit
7d4b07421d
|
@ -31,7 +31,8 @@ std::vector<std::string> PbTypeAnnotation::operating_parent_mode_names() const {
|
|||
}
|
||||
|
||||
bool PbTypeAnnotation::is_operating_pb_type() const {
|
||||
return true == operating_pb_type_name_.empty();
|
||||
return (false == operating_pb_type_name_.empty())
|
||||
&& (false == physical_pb_type_name_.empty());
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,7 +49,8 @@ std::vector<std::string> PbTypeAnnotation::physical_parent_mode_names() const {
|
|||
}
|
||||
|
||||
bool PbTypeAnnotation::is_physical_pb_type() const {
|
||||
return true == physical_pb_type_name_.empty();
|
||||
return (true == operating_pb_type_name_.empty())
|
||||
&& (false == physical_pb_type_name_.empty());
|
||||
}
|
||||
|
||||
std::string PbTypeAnnotation::physical_mode_name() const {
|
||||
|
@ -75,7 +77,15 @@ int PbTypeAnnotation::physical_pb_type_index_offset() const {
|
|||
return physical_pb_type_index_offset_;
|
||||
}
|
||||
|
||||
BasicPort PbTypeAnnotation::physical_pb_type_ports(const std::string& port_name) const {
|
||||
std::vector<std::string> PbTypeAnnotation::port_names() const {
|
||||
std::vector<std::string> keys;
|
||||
for (auto const& element : operating_pb_type_ports_) {
|
||||
keys.push_back(element.first);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
BasicPort PbTypeAnnotation::physical_pb_type_port(const std::string& port_name) const {
|
||||
std::map<std::string, BasicPort>::const_iterator it = operating_pb_type_ports_.find(port_name);
|
||||
if (it == operating_pb_type_ports_.end()) {
|
||||
/* Return an empty port */
|
||||
|
@ -84,7 +94,7 @@ BasicPort PbTypeAnnotation::physical_pb_type_ports(const std::string& port_name)
|
|||
return operating_pb_type_ports_.at(port_name);
|
||||
}
|
||||
|
||||
int PbTypeAnnotation::physical_pin_rotate_offsets(const std::string& port_name) const {
|
||||
int PbTypeAnnotation::physical_pin_rotate_offset(const std::string& port_name) const {
|
||||
std::map<std::string, int>::const_iterator it = physical_pin_rotate_offsets_.find(port_name);
|
||||
if (it == physical_pin_rotate_offsets_.end()) {
|
||||
/* Return a zero offset which is default */
|
||||
|
@ -93,6 +103,14 @@ int PbTypeAnnotation::physical_pin_rotate_offsets(const std::string& port_name)
|
|||
return physical_pin_rotate_offsets_.at(port_name);
|
||||
}
|
||||
|
||||
std::vector<std::string> PbTypeAnnotation::interconnect_names() const {
|
||||
std::vector<std::string> keys;
|
||||
for (auto const& element : interconnect_circuit_model_names_) {
|
||||
keys.push_back(element.first);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
std::string PbTypeAnnotation::interconnect_circuit_model_name(const std::string& interc_name) const {
|
||||
std::map<std::string, std::string>::const_iterator it = interconnect_circuit_model_names_.find(interc_name);
|
||||
if (it == interconnect_circuit_model_names_.end()) {
|
||||
|
|
|
@ -47,8 +47,10 @@ class PbTypeAnnotation {
|
|||
std::string circuit_model_name() const;
|
||||
int physical_pb_type_index_factor() const;
|
||||
int physical_pb_type_index_offset() const;
|
||||
BasicPort physical_pb_type_ports(const std::string& port_name) const;
|
||||
int physical_pin_rotate_offsets(const std::string& port_name) const;
|
||||
std::vector<std::string> port_names() const;
|
||||
BasicPort physical_pb_type_port(const std::string& port_name) const;
|
||||
int physical_pin_rotate_offset(const std::string& port_name) const;
|
||||
std::vector<std::string> interconnect_names() const;
|
||||
std::string interconnect_circuit_model_name(const std::string& interc_name) const;
|
||||
public: /* Public mutators */
|
||||
void set_operating_pb_type_name(const std::string& name);
|
||||
|
|
|
@ -75,7 +75,6 @@ void read_xml_pb_type_annotation(pugi::xml_node& xml_pb_type,
|
|||
/* Find the name of pb_type */
|
||||
const std::string& name_attr = get_attribute(xml_pb_type, "name", loc_data).as_string();
|
||||
const std::string& physical_name_attr = get_attribute(xml_pb_type, "physical_pb_type_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
|
||||
const std::string& physical_mode_name_attr = get_attribute(xml_pb_type, "physical_mode_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
|
||||
|
||||
/* If both names are not empty, this is a operating pb_type */
|
||||
if ( (false == name_attr.empty())
|
||||
|
@ -122,9 +121,11 @@ void read_xml_pb_type_annotation(pugi::xml_node& xml_pb_type,
|
|||
/* Parse mode bits which are applied to both pb_types */
|
||||
pb_type_annotation.set_mode_bits(get_attribute(xml_pb_type, "mode_bits", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());
|
||||
|
||||
/* If this is a physical pb_type, circuit model name is a mandatory attribute */
|
||||
/* If this is a physical pb_type, circuit model name is an optional attribute,
|
||||
* which is applicable to leaf pb_type in the hierarchy
|
||||
*/
|
||||
if (true == pb_type_annotation.is_physical_pb_type()) {
|
||||
pb_type_annotation.set_circuit_model_name(get_attribute(xml_pb_type, "circuit_model_name", loc_data).as_string());
|
||||
pb_type_annotation.set_circuit_model_name(get_attribute(xml_pb_type, "circuit_model_name", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string());
|
||||
}
|
||||
|
||||
/* If this is an operating pb_type, index factor and offset may be optional needed */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "write_xml_simulation_setting.h"
|
||||
#include "write_xml_config_protocol.h"
|
||||
#include "write_xml_routing_circuit.h"
|
||||
#include "write_xml_pb_type_annotation.h"
|
||||
#include "write_xml_openfpga_arch.h"
|
||||
|
||||
/********************************************************************
|
||||
|
@ -57,6 +58,10 @@ void write_xml_openfpga_arch(const char* fname,
|
|||
/* Write the direct connection circuit definition */
|
||||
write_xml_direct_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.direct2circuit);
|
||||
|
||||
|
||||
/* Write the pb_type annotations */
|
||||
openfpga::write_xml_pb_type_annotations(fp, fname, openfpga_arch. pb_type_annotations);
|
||||
|
||||
fp << "</openfpga_architecture>" << "\n";
|
||||
|
||||
/* Write the simulation */
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that outputs pb_type annotations to XML format
|
||||
*******************************************************************/
|
||||
/* Headers from system goes first */
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
/* Headers from vtr util library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
/* Headers from readarchopenfpga library */
|
||||
#include "write_xml_utils.h"
|
||||
#include "write_xml_pb_type_annotation.h"
|
||||
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* Generate the full hierarchy name for a operating pb_type
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_operating_pb_type_hierarchy_name(const PbTypeAnnotation& pb_type_annotation) {
|
||||
/* Iterate over the parent_pb_type and modes names, they should well match */
|
||||
VTR_ASSERT_SAFE(pb_type_annotation.operating_parent_pb_type_names().size() == pb_type_annotation.operating_parent_mode_names().size());
|
||||
|
||||
std::string hie_name;
|
||||
|
||||
for (size_t i = 0 ; i < pb_type_annotation.operating_parent_pb_type_names().size(); ++i) {
|
||||
hie_name += pb_type_annotation.operating_parent_pb_type_names()[i];
|
||||
hie_name += std::string("[");
|
||||
hie_name += pb_type_annotation.operating_parent_mode_names()[i];
|
||||
hie_name += std::string("]");
|
||||
hie_name += std::string(".");
|
||||
}
|
||||
|
||||
/* Add the leaf pb_type */
|
||||
hie_name += pb_type_annotation.operating_pb_type_name();
|
||||
|
||||
return hie_name;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate the full hierarchy name for a operating pb_type
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_physical_pb_type_hierarchy_name(const PbTypeAnnotation& pb_type_annotation) {
|
||||
/* Iterate over the parent_pb_type and modes names, they should well match */
|
||||
VTR_ASSERT_SAFE(pb_type_annotation.physical_parent_pb_type_names().size() == pb_type_annotation.physical_parent_mode_names().size());
|
||||
|
||||
std::string hie_name;
|
||||
|
||||
for (size_t i = 0 ; i < pb_type_annotation.physical_parent_pb_type_names().size(); ++i) {
|
||||
hie_name += pb_type_annotation.physical_parent_pb_type_names()[i];
|
||||
hie_name += std::string("[");
|
||||
hie_name += pb_type_annotation.physical_parent_mode_names()[i];
|
||||
hie_name += std::string("]");
|
||||
hie_name += std::string(".");
|
||||
}
|
||||
|
||||
/* Add the leaf pb_type */
|
||||
hie_name += pb_type_annotation.physical_pb_type_name();
|
||||
|
||||
return hie_name;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Generate the full hierarchy name for a operating pb_type
|
||||
*******************************************************************/
|
||||
static
|
||||
std::string generate_physical_pb_port_name(const BasicPort& pb_port) {
|
||||
std::string port_name;
|
||||
|
||||
/* Output format: <port_name>[<LSB>:<MSB>] */
|
||||
port_name += pb_port.get_name();
|
||||
port_name += std::string("[");
|
||||
port_name += std::to_string(pb_port.get_lsb());
|
||||
port_name += std::string(":");
|
||||
port_name += std::to_string(pb_port.get_msb());
|
||||
port_name += std::string("]");
|
||||
|
||||
return port_name;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output an pb_type interconnection annotation to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_interconnect_annotation(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::PbTypeAnnotation& pb_type_annotation,
|
||||
const std::string& interc_name) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t\t" << "<interconnect";
|
||||
|
||||
write_xml_attribute(fp, "name", interc_name.c_str());
|
||||
write_xml_attribute(fp, "circuit_model_name", pb_type_annotation.interconnect_circuit_model_name(interc_name).c_str());
|
||||
|
||||
fp << "/>" << "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output an pb_type port annotation to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_pb_port_annotation(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::PbTypeAnnotation& pb_type_annotation,
|
||||
const std::string& port_name) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t\t" << "<port";
|
||||
|
||||
write_xml_attribute(fp, "name", port_name.c_str());
|
||||
write_xml_attribute(fp, "physical_mode_port", generate_physical_pb_port_name(pb_type_annotation.physical_pb_type_port(port_name)).c_str());
|
||||
write_xml_attribute(fp, "physical_mode_pin_rotate_offset", pb_type_annotation.physical_pin_rotate_offset(port_name));
|
||||
|
||||
fp << "/>" << "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a device variation in a technology library to XML format
|
||||
*******************************************************************/
|
||||
static
|
||||
void write_xml_pb_type_annotation(std::fstream& fp,
|
||||
const char* fname,
|
||||
const openfpga::PbTypeAnnotation& pb_type_annotation) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
fp << "\t\t" << "<pb_type";
|
||||
|
||||
/* Write up name of the pb_type, which is different by the type of pb_type
|
||||
* 1. operating pb_type, we output name, physical_pb_type_name
|
||||
* 1. physical pb_type, we output name
|
||||
*/
|
||||
if (true == pb_type_annotation.is_operating_pb_type()) {
|
||||
write_xml_attribute(fp, "name", generate_operating_pb_type_hierarchy_name(pb_type_annotation).c_str());
|
||||
write_xml_attribute(fp, "physical_pb_type_name", generate_physical_pb_type_hierarchy_name(pb_type_annotation).c_str());
|
||||
}
|
||||
|
||||
if (true == pb_type_annotation.is_physical_pb_type()) {
|
||||
write_xml_attribute(fp, "name", generate_physical_pb_type_hierarchy_name(pb_type_annotation).c_str());
|
||||
}
|
||||
|
||||
/* Output physical mode name */
|
||||
if (!pb_type_annotation.physical_mode_name().empty()) {
|
||||
write_xml_attribute(fp, "physical_mode_name", pb_type_annotation.physical_mode_name().c_str());
|
||||
}
|
||||
|
||||
/* Output idle mode name */
|
||||
if (!pb_type_annotation.idle_mode_name().empty()) {
|
||||
write_xml_attribute(fp, "idle_mode_name", pb_type_annotation.idle_mode_name().c_str());
|
||||
}
|
||||
|
||||
/* Output mode_bits */
|
||||
if (!pb_type_annotation.mode_bits().empty()) {
|
||||
write_xml_attribute(fp, "mode_bits", pb_type_annotation.mode_bits().c_str());
|
||||
}
|
||||
|
||||
/* Output circuit model name */
|
||||
if (!pb_type_annotation.circuit_model_name().empty()) {
|
||||
write_xml_attribute(fp, "circuit_model_name", pb_type_annotation.circuit_model_name().c_str());
|
||||
}
|
||||
|
||||
/* Output physical mode index factor and offset, only applicable to operating mode */
|
||||
if (true == pb_type_annotation.is_operating_pb_type()) {
|
||||
write_xml_attribute(fp, "physical_pb_type_index_factor", pb_type_annotation.physical_pb_type_index_factor());
|
||||
write_xml_attribute(fp, "physical_pb_type_index_offset", pb_type_annotation.physical_pb_type_index_offset());
|
||||
}
|
||||
|
||||
/* If there are interconnect definition or port definition, output them
|
||||
* Otherwise we can finish here
|
||||
*/
|
||||
if ( (0 == pb_type_annotation.interconnect_names().size())
|
||||
&& (0 == pb_type_annotation.port_names().size()) ) {
|
||||
fp << "/>" << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
fp << ">" << "\n";
|
||||
|
||||
/* Output interconnects if there are any */
|
||||
for (const std::string& interc_name : pb_type_annotation.interconnect_names()) {
|
||||
write_xml_interconnect_annotation(fp, fname, pb_type_annotation, interc_name);
|
||||
}
|
||||
|
||||
/* Output pb_type ports if there are any */
|
||||
for (const std::string& port_name : pb_type_annotation.port_names()) {
|
||||
write_xml_pb_port_annotation(fp, fname, pb_type_annotation, port_name);
|
||||
}
|
||||
|
||||
fp << "\t\t</pb_type>" << "\n";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A writer to output a number of pb_type annotations to XML format
|
||||
*******************************************************************/
|
||||
void write_xml_pb_type_annotations(std::fstream& fp,
|
||||
const char* fname,
|
||||
const std::vector<PbTypeAnnotation>& pb_type_annotations) {
|
||||
/* Validate the file stream */
|
||||
openfpga::check_file_stream(fname, fp);
|
||||
|
||||
/* Write the root node for pb_type annotations,
|
||||
* we apply a tab becuase pb_type annotations is just a subnode
|
||||
* under the root node <openfpga_arch>
|
||||
*/
|
||||
fp << "\t" << "<pb_type_annotations>" << "\n";
|
||||
|
||||
/* Write device model one by one */
|
||||
for (const PbTypeAnnotation& pb_type_annotation : pb_type_annotations) {
|
||||
write_xml_pb_type_annotation(fp, fname, pb_type_annotation);
|
||||
}
|
||||
|
||||
/* Write the root node for pb_type annotations */
|
||||
fp << "\t" << "</pb_type_annotations>" << "\n";
|
||||
}
|
||||
|
||||
} /* namespace openfpga ends */
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef WRITE_XML_PB_TYPE_ANNOTATION_H
|
||||
#define WRITE_XML_PB_TYPE_ANNOTATION_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
#include "pb_type_annotation.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
/* namespace openfpga begins */
|
||||
namespace openfpga {
|
||||
|
||||
void write_xml_pb_type_annotations(std::fstream& fp,
|
||||
const char* fname,
|
||||
const std::vector<PbTypeAnnotation>& pb_type_annotations);
|
||||
|
||||
} /* namespace openfpga ends */
|
||||
|
||||
#endif
|
|
@ -46,6 +46,21 @@ void write_xml_attribute(std::fstream& fp,
|
|||
fp << "\"";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A most utilized function to write an XML attribute to file
|
||||
* This accepts the value as a float
|
||||
*******************************************************************/
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
const int& value) {
|
||||
/* Validate the file stream */
|
||||
openfpga::valid_file_stream(fp);
|
||||
|
||||
fp << " " << attr << "=\"";
|
||||
fp << value;
|
||||
fp << "\"";
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* A most utilized function to write an XML attribute to file
|
||||
* This accepts the value as a float
|
||||
|
|
|
@ -18,6 +18,10 @@ void write_xml_attribute(std::fstream& fp,
|
|||
const char* attr,
|
||||
const bool& value);
|
||||
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
const int& value);
|
||||
|
||||
void write_xml_attribute(std::fstream& fp,
|
||||
const char* attr,
|
||||
const float& value);
|
||||
|
|
|
@ -67,6 +67,7 @@ void PbParser::parse() {
|
|||
/* The last pb is the leaf node.
|
||||
* It should NOT be empty and should NOT contain any brackets!
|
||||
*/
|
||||
VTR_ASSERT(0 < pb_tokens.size());
|
||||
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);
|
||||
|
|
|
@ -64,7 +64,7 @@ void PortParser::parse() {
|
|||
|
||||
/* If we only have one token */
|
||||
if (1 == port_tokens.size()) {
|
||||
port_.set_width(0);
|
||||
port_.set_width(1);
|
||||
return; /* We can finish here */
|
||||
}
|
||||
|
||||
|
@ -75,21 +75,22 @@ void PortParser::parse() {
|
|||
VTR_ASSERT_SAFE (1 == port_tokens.size());
|
||||
|
||||
/* Split the pin string now */
|
||||
tokenizer.set_data(port_tokens[0]);
|
||||
tokenizer.set_data(pin_tokens[0]);
|
||||
pin_tokens = tokenizer.split(delim_);
|
||||
|
||||
/* Check if we have LSB and MSB or just one */
|
||||
if ( 1 == pin_tokens.size() ) {
|
||||
/* Single pin */
|
||||
port_.set_width(stoi(pin_tokens[0]), stoi(pin_tokens[0]));
|
||||
port_.set_width(std::stoi(pin_tokens[0]), std::stoi(pin_tokens[0]));
|
||||
} else if ( 2 == pin_tokens.size() ) {
|
||||
/* A number of pin */
|
||||
port_.set_width(stoi(pin_tokens[0]), stoi(pin_tokens[1]));
|
||||
}
|
||||
|
||||
/* Re-order to ensure LSB <= MSB */
|
||||
if (false == port_.is_valid()) {
|
||||
port_.revert();
|
||||
/* A number of pins.
|
||||
* Note that we always use the LSB for token[0] and MSB for token[1]
|
||||
*/
|
||||
if (std::stoi(pin_tokens[1]) < std::stoi(pin_tokens[0])) {
|
||||
port_.set_width(std::stoi(pin_tokens[1]), std::stoi(pin_tokens[0]));
|
||||
} else {
|
||||
port_.set_width(std::stoi(pin_tokens[0]), std::stoi(pin_tokens[1]));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue