/******************************************************************** * This file includes functions that outputs a circuit library to XML format *******************************************************************/ /* Headers from system goes first */ #include #include /* Headers from vtr util library */ #include "vtr_log.h" #include "openfpga_digest.h" /* Headers from readarchopenfpga library */ #include "write_xml_utils.h" #include "write_xml_circuit_library.h" /******************************************************************** * A writer to output the design technology of a circuit model to XML format *******************************************************************/ static void write_xml_design_technology(std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, const CircuitModelId& model) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); fp << "\t\t\t" << "" << "\n"; } /******************************************************************** * A writer to output a circuit port to XML format *******************************************************************/ static void write_xml_circuit_port(std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, const CircuitPortId& port) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); /* Get the parent circuit model for this port */ const CircuitModelId& model = circuit_lib.port_parent_model(port); /* Generic information about a port */ fp << "\t\t\t" << "" << "\n"; } /******************************************************************** * A writer to output wire parasitics of a circuit model to XML format *******************************************************************/ static void write_xml_wire_param(std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, const CircuitModelId& model) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); fp << "\t\t\t" << "" << "\n"; } /******************************************************************** * A writer to output delay matrices of a circuit model to XML format *******************************************************************/ static void write_xml_delay_matrix(std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, const CircuitModelId& model) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); std::vector in_ports; std::vector out_ports; /* Collect the input ports and output ports */ for (const auto& timing_edge : circuit_lib.timing_edges_by_model(model)) { /* For each input port of each edge, build a list of unique ports */ CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge); if (in_ports.end() == std::find(in_ports.begin(), in_ports.end(), src_port)) { in_ports.push_back(src_port); } /* For each input port of each edge, build a list of unique ports */ CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge); if (out_ports.end() == std::find(out_ports.begin(), out_ports.end(), sink_port)) { out_ports.push_back(sink_port); } } /* Build the string of in_port list */ std::string in_port_string; for (const CircuitPortId& in_port : in_ports) { if (!in_port_string.empty()) { in_port_string += std::string(" "); } in_port_string += circuit_lib.port_prefix(in_port); } /* Build the string of out_port list */ std::string out_port_string; for (const CircuitPortId& out_port : out_ports) { if (!out_port_string.empty()) { out_port_string += std::string(" "); } out_port_string += circuit_lib.port_prefix(out_port); } /* Output rising edges */ fp << "\t\t\t"; fp << "\n"; for (const CircuitPortId& out_port : out_ports) { for (const size_t& out_pin : circuit_lib.pins(out_port)) { fp << "\t\t\t\t"; size_t counter = 0; /* Count the numbers of delays in one line */ for (const CircuitPortId& in_port : in_ports) { for (const size_t& in_pin : circuit_lib.pins(in_port)) { for (const auto& timing_edge : circuit_lib.timing_edges_by_model(model)) { CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge); size_t src_pin = circuit_lib.timing_edge_src_pin(timing_edge); CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge); size_t sink_pin = circuit_lib.timing_edge_sink_pin(timing_edge); /* Bypass unwanted edges */ if ( (src_port != in_port) || (src_pin != in_pin) || (sink_port != out_port) || (sink_pin != out_pin) ) { continue; } /* This is the edge we want, output the rise delay */ if (0 < counter) { fp << std::string(" "); } fp << std::scientific << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_RISE); counter++; } } } /* One line of delay matrix finished here, output to the file */ fp << "\n"; } } fp << "\t\t\t"; fp << "" << "\n"; /* Output falling edges */ fp << "\t\t\t"; fp << "\n"; for (const CircuitPortId& out_port : out_ports) { for (const size_t& out_pin : circuit_lib.pins(out_port)) { fp << "\t\t\t\t"; size_t counter = 0; /* Count the numbers of delays in one line */ for (const CircuitPortId& in_port : in_ports) { for (const size_t& in_pin : circuit_lib.pins(in_port)) { for (const auto& timing_edge : circuit_lib.timing_edges_by_model(model)) { CircuitPortId src_port = circuit_lib.timing_edge_src_port(timing_edge); size_t src_pin = circuit_lib.timing_edge_src_pin(timing_edge); CircuitPortId sink_port = circuit_lib.timing_edge_sink_port(timing_edge); size_t sink_pin = circuit_lib.timing_edge_sink_pin(timing_edge); /* Bypass unwanted edges */ if ( (src_port != in_port) || (src_pin != in_pin) || (sink_port != out_port) || (sink_pin != out_pin) ) { continue; } /* This is the edge we want, output the rise delay */ if (0 < counter) { fp << std::string(" "); } fp << std::scientific << circuit_lib.timing_edge_delay(timing_edge, CIRCUIT_MODEL_DELAY_FALL); counter++; } } } /* One line of delay matrix finished here, output to the file */ fp << "\n"; } } fp << "\t\t\t"; fp << "" << "\n"; } /******************************************************************** * A writer to output a circuit model to XML format *******************************************************************/ static void write_xml_circuit_model(std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib, const CircuitModelId& model) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); /* Write the definition of circuit model */ fp << "\t\t" << "" << "\n"; /* Write the design technology of circuit model */ write_xml_design_technology(fp, fname, circuit_lib, model); /* Write the input buffer information of circuit model, * only applicable when this circuit model is neither inverter nor buffer */ if (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) { if (true == circuit_lib.is_input_buffered(model)) { fp << "\t\t\t" << "" << "\n"; } } /* Write the output buffer information of circuit model */ if (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) { if (true == circuit_lib.is_output_buffered(model)) { fp << "\t\t\t" << "" << "\n"; } } if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) { /* Write the lut input buffer information of circuit model * This is a mandatory attribute for LUT, so it must exist */ fp << "\t\t\t" << "" << "\n"; /* Write the lut input inverter information of circuit model * This is a mandatory attribute for LUT, so it must exist */ fp << "\t\t\t" << "" << "\n"; /* Write the lut intermediate buffer information of circuit model */ if (true == circuit_lib.is_lut_intermediate_buffered(model)) { fp << "\t\t\t" << "" << "\n"; } } /* Write the pass-gate-logic information of circuit model */ if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) || (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model)) ) { fp << "\t\t\t" << "" << "\n"; } /* Write the ports of circuit model */ for (const CircuitPortId& port : circuit_lib.model_ports(model)) { write_xml_circuit_port(fp, fname, circuit_lib, port); } /* Write the wire parasticis of circuit model */ if ( (CIRCUIT_MODEL_WIRE == circuit_lib.model_type(model)) || (CIRCUIT_MODEL_CHAN_WIRE == circuit_lib.model_type(model)) ) { write_xml_wire_param(fp, fname, circuit_lib, model); } /* Write the delay matrix of circuit model * Skip circuit models without delay matrices */ if (0 < circuit_lib.num_delay_info(model)) { write_xml_delay_matrix(fp, fname, circuit_lib, model); } /* Put an end to the XML definition of this circuit model */ fp << "\t\t" << "\n"; } /******************************************************************** * A writer to output a circuit library to XML format * Note: * This function should be run after that the following methods of * CircuitLibrary are executed * 1. build_model_links(); * 2. build_timing_graph(); *******************************************************************/ void write_xml_circuit_library(std::fstream& fp, const char* fname, const CircuitLibrary& circuit_lib) { /* Validate the file stream */ openfpga::check_file_stream(fname, fp); /* Write the root node for circuit_library, * we apply a tab becuase circuit library is a subnode * under the root node */ fp << "\t" << "" << "\n"; /* Write circuit model one by one */ for (const CircuitModelId& model : circuit_lib.models()) { write_xml_circuit_model(fp, fname, circuit_lib, model); } /* Write the root node for circuit_library */ fp << "\t" << "" << "\n"; }