add XML parser and writer for routing circuit definition for OpenFPGA architecture

This commit is contained in:
tangxifan 2020-01-19 14:44:27 -07:00
parent ebe46d15a9
commit 10336cbe67
9 changed files with 400 additions and 4 deletions

View File

@ -262,9 +262,9 @@
<switch_block>
<switch name="sb_mux_L4" circuit_model_name="mux_2level_tapbuf"/>
</switch_block>
<routing_segement>
<switch name="L4" circuit_model_name="chan_segment"/>
</routing_segement>
<routing_segment>
<segment name="L4" circuit_model_name="chan_segment"/>
</routing_segment>
<complex_blocks>
<pb_type name="io" idle_mode_name="inpad" physical_mode_name="io_phy"/>
<mode name="io[io_phy]" disable_in_packing="true"/>

View File

@ -1,6 +1,8 @@
#ifndef OPENFPGA_ARCH_H
#define OPENFPGA_ARCH_H
#include <map>
#include "circuit_library.h"
#include "technology_library.h"
#include "simulation_setting.h"
@ -11,12 +13,35 @@ namespace openfpga {
/* A unified data structure to store circuit-level settings,
* including circuit library, technology library and simulation parameters
*
* Note:
* Once this struct is built by function read_xml_openfpga_arch()
* It should be READ-ONLY! Any modification should not be applied later
* This is to keep everything well modularized
*/
struct Arch {
/* Circuit models */
CircuitLibrary circuit_lib;
/* Technology devices */
TechnologyLibrary tech_lib;
/* Simulation settings */
SimulationSetting sim_setting;
/* Configuration protocol settings */
ConfigProtocol config_protocol;
/* Mapping from the names of routing switches
* to circuit models in circuit library
*/
std::map<std::string, CircuitModelId> cb_switch2circuit;
std::map<std::string, CircuitModelId> sb_switch2circuit;
/* Mapping from the names of routing segments
* to circuit models in circuit library
*/
std::map<std::string, CircuitModelId> routing_seg2circuit;
};
} /* namespace openfpga ends */

View File

@ -17,6 +17,7 @@
#include "read_xml_circuit_library.h"
#include "read_xml_simulation_setting.h"
#include "read_xml_config_protocol.h"
#include "read_xml_routing_circuit.h"
#include "read_xml_openfpga_arch.h"
#include "openfpga_arch_linker.h"
@ -63,6 +64,22 @@ openfpga::Arch read_xml_openfpga_arch(const char* arch_file_name) {
/* Build the internal link between configuration protocol and circuit library */
link_config_protocol_to_circuit_library(openfpga_arch);
/* Parse the connection block circuit definition */
openfpga_arch.cb_switch2circuit = read_xml_cb_switch_circuit(xml_openfpga_arch, loc_data,
openfpga_arch.circuit_lib);
/* Parse the connection block circuit definition */
openfpga_arch.cb_switch2circuit = read_xml_cb_switch_circuit(xml_openfpga_arch, loc_data,
openfpga_arch.circuit_lib);
/* Parse the switch block circuit definition */
openfpga_arch.sb_switch2circuit = read_xml_sb_switch_circuit(xml_openfpga_arch, loc_data,
openfpga_arch.circuit_lib);
/* Parse the routing segment circuit definition */
openfpga_arch.routing_seg2circuit = read_xml_routing_segment_circuit(xml_openfpga_arch, loc_data,
openfpga_arch.circuit_lib);
/* Second node should be <openfpga_simulation_setting> */
auto xml_simulation_settings = get_single_child(doc, "openfpga_simulation_setting", loc_data);

View File

@ -0,0 +1,186 @@
/********************************************************************
* This file includes the top-level function of this library
* which reads an XML modeling OpenFPGA architecture 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"
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
#include "read_xml_routing_circuit.h"
/********************************************************************
* Find the circuit model id for a routing switch as defined in XML
*******************************************************************/
static
CircuitModelId find_routing_circuit_model(pugi::xml_node& xml_switch,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib,
const std::string& switch_model_name,
const e_circuit_model_type& expected_circuit_model_type) {
/* Find the circuit model id in circuit library */
CircuitModelId switch_model = circuit_lib.model(switch_model_name);
/* Ensure we have a valid circuit model id! */
if (CircuitModelId::INVALID() == switch_model) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch),
"Invalid circuit model name '%s'! Unable to find it in circuit library\n",
switch_model_name.c_str());
}
/* Check the type of switch model, it must be a specific type!!!
* For CB/SB switches, the type must be a multiplexer
* For routing segments, the type must be a channel wire
* TODO: decide where to put these checking codes
* This can be done here or in the function check_arch()
*/
if (expected_circuit_model_type != circuit_lib.model_type(switch_model)) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch),
"Circuit model '%s' must be a type of '%s'\n",
switch_model_name.c_str(), CIRCUIT_MODEL_TYPE_STRING[expected_circuit_model_type]);
}
return switch_model;
}
/********************************************************************
* Parse XML codes about <connection_block> to an object of name-to-circuit mapping
* Note: this function should be called AFTER the parsing of circuit library!!!
*******************************************************************/
std::map<std::string, CircuitModelId> read_xml_cb_switch_circuit(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib) {
std::map<std::string, CircuitModelId> cb_switch2circuit;
/* Parse cb switch list */
pugi::xml_node xml_cb_switch = get_single_child(Node, "connection_block", loc_data);
/* Iterate over the children under this node,
* each child should be named after switch
*/
for (pugi::xml_node xml_switch : xml_cb_switch.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_switch.name() != std::string("switch")) {
bad_tag(xml_switch, loc_data, xml_cb_switch, {"switch"});
}
/* Get the switch name */
std::string switch_name = get_attribute(xml_switch, "name", loc_data).as_string();
/* Get the switch circuit model name */
std::string switch_model_name = get_attribute(xml_switch, "circuit_model_name", loc_data).as_string();
CircuitModelId switch_model = find_routing_circuit_model(xml_switch, loc_data,
circuit_lib, switch_model_name,
CIRCUIT_MODEL_MUX);
/* Ensure that there is no duplicated switch names defined here */
std::map<std::string, CircuitModelId>::const_iterator it = cb_switch2circuit.find(switch_name);
if (it != cb_switch2circuit.end()) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch),
"Switch name '%s' has been defined more than once!\n",
switch_name.c_str());
}
/* Pass all the check, we can add it to the map */
cb_switch2circuit[switch_name] = switch_model;
}
return cb_switch2circuit;
}
/********************************************************************
* Parse XML codes about <switch_block> to an object of name-to-circuit mapping
* Note: this function should be called AFTER the parsing of circuit library!!!
*******************************************************************/
std::map<std::string, CircuitModelId> read_xml_sb_switch_circuit(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib) {
std::map<std::string, CircuitModelId> sb_switch2circuit;
/* Parse cb switch list */
pugi::xml_node xml_sb_switch = get_single_child(Node, "switch_block", loc_data);
/* Iterate over the children under this node,
* each child should be named after switch
*/
for (pugi::xml_node xml_switch : xml_sb_switch.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_switch.name() != std::string("switch")) {
bad_tag(xml_switch, loc_data, xml_sb_switch, {"switch"});
}
/* Get the switch name */
std::string switch_name = get_attribute(xml_switch, "name", loc_data).as_string();
/* Get the switch circuit model name */
std::string switch_model_name = get_attribute(xml_switch, "circuit_model_name", loc_data).as_string();
CircuitModelId switch_model = find_routing_circuit_model(xml_switch, loc_data,
circuit_lib, switch_model_name,
CIRCUIT_MODEL_MUX);
/* Ensure that there is no duplicated switch names defined here */
std::map<std::string, CircuitModelId>::const_iterator it = sb_switch2circuit.find(switch_name);
if (it != sb_switch2circuit.end()) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_switch),
"Switch name '%s' has been defined more than once!\n",
switch_name.c_str());
}
/* Pass all the check, we can add it to the map */
sb_switch2circuit[switch_name] = switch_model;
}
return sb_switch2circuit;
}
/********************************************************************
* Parse XML codes about <routing_segment> to an object of name-to-circuit mapping
* Note: this function should be called AFTER the parsing of circuit library!!!
*******************************************************************/
std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib) {
std::map<std::string, CircuitModelId> seg2circuit;
/* Parse cb switch list */
pugi::xml_node xml_segments= get_single_child(Node, "routing_segment", loc_data);
/* Iterate over the children under this node,
* each child should be named after switch
*/
for (pugi::xml_node xml_seg : xml_segments.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_seg.name() != std::string("segment")) {
bad_tag(xml_seg, loc_data, xml_segments, {"segment"});
}
/* Get the switch name */
std::string seg_name = get_attribute(xml_seg, "name", loc_data).as_string();
/* Get the routing segment circuit model name */
std::string seg_model_name = get_attribute(xml_seg, "circuit_model_name", loc_data).as_string();
CircuitModelId seg_model = find_routing_circuit_model(xml_seg, loc_data,
circuit_lib, seg_model_name,
CIRCUIT_MODEL_CHAN_WIRE);
/* Ensure that there is no duplicated seg names defined here */
std::map<std::string, CircuitModelId>::const_iterator it = seg2circuit.find(seg_name);
if (it != seg2circuit.end()) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_seg),
"Segment name '%s' has been defined more than once!\n",
seg_name.c_str());
}
/* Pass all the check, we can add it to the map */
seg2circuit[seg_name] = seg_model;
}
return seg2circuit;
}

View File

@ -0,0 +1,29 @@
#ifndef READ_XML_ROUTING_CIRCUIT_H
#define READ_XML_ROUTING_CIRCUIT_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include <map>
#include "pugixml_util.hpp"
#include "pugixml.hpp"
#include "circuit_library.h"
/********************************************************************
* Function declaration
*******************************************************************/
std::map<std::string, CircuitModelId> read_xml_cb_switch_circuit(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib);
std::map<std::string, CircuitModelId> read_xml_sb_switch_circuit(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib);
std::map<std::string, CircuitModelId> read_xml_routing_segment_circuit(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data,
const CircuitLibrary& circuit_lib);
#endif

View File

@ -268,4 +268,3 @@ SimulationSetting read_xml_simulation_setting(pugi::xml_node& Node,
return sim_setting;
}

View File

@ -12,6 +12,7 @@
#include "write_xml_technology_library.h"
#include "write_xml_simulation_setting.h"
#include "write_xml_config_protocol.h"
#include "write_xml_routing_circuit.h"
#include "write_xml_openfpga_arch.h"
/********************************************************************
@ -39,6 +40,15 @@ void write_xml_openfpga_arch(const char* fname,
/* Write the configuration protocol */
write_xml_config_protocol(fp, fname, openfpga_arch.config_protocol, openfpga_arch.circuit_lib);
/* Write the connection block circuit definition */
write_xml_cb_switch_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.cb_switch2circuit);
/* Write the switch block circuit definition */
write_xml_sb_switch_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.sb_switch2circuit);
/* Write the routing segment circuit definition */
write_xml_routing_segment_circuit(fp, fname, openfpga_arch.circuit_lib, openfpga_arch.routing_seg2circuit);
fp << "</openfpga_architecture>" << "\n";
/* Write the simulation */

View File

@ -0,0 +1,99 @@
/********************************************************************
* This file includes functions that outputs routing circuit definition
* 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_routing_circuit.h"
/********************************************************************
* Write switch circuit model definition in XML format
*******************************************************************/
static
void write_xml_routing_component_circuit(std::fstream& fp,
const char* fname,
const std::string& routing_component_name,
const CircuitLibrary& circuit_lib,
const std::map<std::string, CircuitModelId>& switch2circuit) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Iterate over the mapping */
for (std::map<std::string, CircuitModelId>::const_iterator it = switch2circuit.begin();
it != switch2circuit.end();
++it) {
fp << "\t\t" << "<" << routing_component_name;
write_xml_attribute(fp, "name", it->first.c_str());
write_xml_attribute(fp, "circuit_model_name", circuit_lib.model_name(it->second).c_str());
fp << "/>" << "\n";
}
}
/********************************************************************
* Write Connection block circuit models in XML format
*******************************************************************/
void write_xml_cb_switch_circuit(std::fstream& fp,
const char* fname,
const CircuitLibrary& circuit_lib,
const std::map<std::string, CircuitModelId>& switch2circuit) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Write the root node */
fp << "\t" << "<connection_block>" << "\n";
/* Write each switch circuit definition */
write_xml_routing_component_circuit(fp, fname, std::string("switch"), circuit_lib, switch2circuit);
/* Finish writing the root node */
fp << "\t" << "</connection_block>" << "\n";
}
/********************************************************************
* Write Switch block circuit models in XML format
*******************************************************************/
void write_xml_sb_switch_circuit(std::fstream& fp,
const char* fname,
const CircuitLibrary& circuit_lib,
const std::map<std::string, CircuitModelId>& switch2circuit) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Write the root node */
fp << "\t" << "<switch_block>" << "\n";
/* Write each switch circuit definition */
write_xml_routing_component_circuit(fp, fname, std::string("switch"), circuit_lib, switch2circuit);
/* Finish writing the root node */
fp << "\t" << "</switch_block>" << "\n";
}
/********************************************************************
* Write routing segment circuit models in XML format
*******************************************************************/
void write_xml_routing_segment_circuit(std::fstream& fp,
const char* fname,
const CircuitLibrary& circuit_lib,
const std::map<std::string, CircuitModelId>& seg2circuit) {
/* Validate the file stream */
openfpga::check_file_stream(fname, fp);
/* Write the root node */
fp << "\t" << "<routing_segment>" << "\n";
/* Write each routing segment circuit definition */
write_xml_routing_component_circuit(fp, fname, std::string("segment"), circuit_lib, seg2circuit);
/* Finish writing the root node */
fp << "\t" << "</routing_segment>" << "\n";
}

View File

@ -0,0 +1,31 @@
#ifndef WRITE_XML_ROUTING_CIRCUIT_H
#define WRITE_XML_ROUTING_CIRCUIT_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <fstream>
#include <map>
#include <string>
#include "circuit_library.h"
/********************************************************************
* Function declaration
*******************************************************************/
void write_xml_cb_switch_circuit(std::fstream& fp,
const char* fname,
const CircuitLibrary& circuit_lib,
const std::map<std::string, CircuitModelId>& switch2circuit);
void write_xml_sb_switch_circuit(std::fstream& fp,
const char* fname,
const CircuitLibrary& circuit_lib,
const std::map<std::string, CircuitModelId>& switch2circuit);
void write_xml_routing_segment_circuit(std::fstream& fp,
const char* fname,
const CircuitLibrary& circuit_lib,
const std::map<std::string, CircuitModelId>& seg2circuit);
#endif