diff --git a/libopenfpga/libarchopenfpga/arch/sample_arch.xml b/libopenfpga/libarchopenfpga/arch/sample_arch.xml index b3bd3b2e3..f75f86530 100644 --- a/libopenfpga/libarchopenfpga/arch/sample_arch.xml +++ b/libopenfpga/libarchopenfpga/arch/sample_arch.xml @@ -262,9 +262,9 @@ - - - + + + diff --git a/libopenfpga/libarchopenfpga/src/openfpga_arch.h b/libopenfpga/libarchopenfpga/src/openfpga_arch.h index c433a74a7..f7f9108f0 100644 --- a/libopenfpga/libarchopenfpga/src/openfpga_arch.h +++ b/libopenfpga/libarchopenfpga/src/openfpga_arch.h @@ -1,6 +1,8 @@ #ifndef OPENFPGA_ARCH_H #define OPENFPGA_ARCH_H +#include + #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 cb_switch2circuit; + std::map sb_switch2circuit; + + /* Mapping from the names of routing segments + * to circuit models in circuit library + */ + std::map routing_seg2circuit; }; } /* namespace openfpga ends */ diff --git a/libopenfpga/libarchopenfpga/src/read_xml_openfpga_arch.cpp b/libopenfpga/libarchopenfpga/src/read_xml_openfpga_arch.cpp index 7fac90fcd..c9cc2652b 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_openfpga_arch.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_openfpga_arch.cpp @@ -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 */ auto xml_simulation_settings = get_single_child(doc, "openfpga_simulation_setting", loc_data); diff --git a/libopenfpga/libarchopenfpga/src/read_xml_routing_circuit.cpp b/libopenfpga/libarchopenfpga/src/read_xml_routing_circuit.cpp new file mode 100644 index 000000000..366a3ca4b --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/read_xml_routing_circuit.cpp @@ -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 + +/* 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 to an object of name-to-circuit mapping + * Note: this function should be called AFTER the parsing of circuit library!!! + *******************************************************************/ +std::map read_xml_cb_switch_circuit(pugi::xml_node& Node, + const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib) { + std::map 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::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 to an object of name-to-circuit mapping + * Note: this function should be called AFTER the parsing of circuit library!!! + *******************************************************************/ +std::map read_xml_sb_switch_circuit(pugi::xml_node& Node, + const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib) { + std::map 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::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 to an object of name-to-circuit mapping + * Note: this function should be called AFTER the parsing of circuit library!!! + *******************************************************************/ +std::map read_xml_routing_segment_circuit(pugi::xml_node& Node, + const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib) { + std::map 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::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; +} diff --git a/libopenfpga/libarchopenfpga/src/read_xml_routing_circuit.h b/libopenfpga/libarchopenfpga/src/read_xml_routing_circuit.h new file mode 100644 index 000000000..4646d7e3a --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/read_xml_routing_circuit.h @@ -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 +#include + +#include "pugixml_util.hpp" +#include "pugixml.hpp" +#include "circuit_library.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +std::map read_xml_cb_switch_circuit(pugi::xml_node& Node, + const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib); + +std::map read_xml_sb_switch_circuit(pugi::xml_node& Node, + const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib); + +std::map read_xml_routing_segment_circuit(pugi::xml_node& Node, + const pugiutil::loc_data& loc_data, + const CircuitLibrary& circuit_lib); + +#endif diff --git a/libopenfpga/libarchopenfpga/src/read_xml_simulation_setting.cpp b/libopenfpga/libarchopenfpga/src/read_xml_simulation_setting.cpp index 26f40d1ac..60821e2ed 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_simulation_setting.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_simulation_setting.cpp @@ -268,4 +268,3 @@ SimulationSetting read_xml_simulation_setting(pugi::xml_node& Node, return sim_setting; } - diff --git a/libopenfpga/libarchopenfpga/src/write_xml_openfpga_arch.cpp b/libopenfpga/libarchopenfpga/src/write_xml_openfpga_arch.cpp index c5e6c7bba..444cca3cc 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_openfpga_arch.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_openfpga_arch.cpp @@ -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 << "" << "\n"; /* Write the simulation */ diff --git a/libopenfpga/libarchopenfpga/src/write_xml_routing_circuit.cpp b/libopenfpga/libarchopenfpga/src/write_xml_routing_circuit.cpp new file mode 100644 index 000000000..0d0b28446 --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/write_xml_routing_circuit.cpp @@ -0,0 +1,99 @@ +/******************************************************************** + * This file includes functions that outputs routing circuit definition + * to XML format + *******************************************************************/ +/* Headers from system goes first */ +#include +#include + +/* 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& switch2circuit) { + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + /* Iterate over the mapping */ + for (std::map::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& switch2circuit) { + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + /* Write the root node */ + fp << "\t" << "" << "\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" << "" << "\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& switch2circuit) { + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + /* Write the root node */ + fp << "\t" << "" << "\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" << "" << "\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& seg2circuit) { + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + /* Write the root node */ + fp << "\t" << "" << "\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" << "" << "\n"; +} diff --git a/libopenfpga/libarchopenfpga/src/write_xml_routing_circuit.h b/libopenfpga/libarchopenfpga/src/write_xml_routing_circuit.h new file mode 100644 index 000000000..75f4890ee --- /dev/null +++ b/libopenfpga/libarchopenfpga/src/write_xml_routing_circuit.h @@ -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 +#include +#include + +#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& switch2circuit); + +void write_xml_sb_switch_circuit(std::fstream& fp, + const char* fname, + const CircuitLibrary& circuit_lib, + const std::map& switch2circuit); + +void write_xml_routing_segment_circuit(std::fstream& fp, + const char* fname, + const CircuitLibrary& circuit_lib, + const std::map& seg2circuit); + +#endif