add XML writer for circuit ports

This commit is contained in:
tangxifan 2020-01-16 16:05:11 -07:00
parent 0304d723c0
commit 9ba42cd540
5 changed files with 154 additions and 12 deletions

View File

@ -16,6 +16,7 @@
<io_nmos model_name="nch_25" chan_length="270e-9" min_width="320e-9"/>
<io_pmos model_name="pch_25" chan_length="270e-9" min_width="320e-9"/>
</transistors>
<rram model_name="rram" rlrs="5e3" rhrs="20e6"/>
</technology>
<circuit_library>
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">

View File

@ -886,7 +886,7 @@ size_t CircuitLibrary::port_lut_frac_level(const CircuitPortId& circuit_port_id)
}
/* Return indices of internal nodes in a LUT multiplexing structure to which the output port is wired to */
std::vector<size_t> CircuitLibrary::port_lut_output_masks(const CircuitPortId& circuit_port_id) const {
std::vector<size_t> CircuitLibrary::port_lut_output_mask(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
return port_lut_output_masks_[circuit_port_id];
@ -927,6 +927,13 @@ std::string CircuitLibrary::model_name(const CircuitPortId& port_id) const {
return model_names_[port_parent_model(port_id)];
}
/* Return the name of inverter circuit model linked to a circuit port */
std::string CircuitLibrary::port_inv_model_name(const CircuitPortId& circuit_port_id) const {
/* validate the circuit_port_id */
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
return port_inv_model_names_[circuit_port_id];
}
/************************************************************************
* Public Accessors : Methods to visit timing graphs
***********************************************************************/

View File

@ -265,12 +265,13 @@ class CircuitLibrary {
bool port_is_config_enable(const CircuitPortId& circuit_port_id) const;
bool port_is_prog(const CircuitPortId& circuit_port_id) const;
size_t port_lut_frac_level(const CircuitPortId& circuit_port_id) const;
std::vector<size_t> port_lut_output_masks(const CircuitPortId& circuit_port_id) const;
std::vector<size_t> port_lut_output_mask(const CircuitPortId& circuit_port_id) const;
std::string port_tri_state_map(const CircuitPortId& circuit_port_id) const;
CircuitModelId port_tri_state_model(const CircuitPortId& circuit_port_id) const;
std::string port_tri_state_model_name(const CircuitPortId& circuit_port_id) const;
CircuitModelId port_parent_model(const CircuitPortId& circuit_port_id) const;
std::string model_name(const CircuitPortId& port_id) const;
std::string port_inv_model_name(const CircuitPortId& circuit_port_id) const;
public: /* Public Accessors: Timing graph */
/* Get source/sink nodes and delay of edges */
std::vector<CircuitEdgeId> timing_edges_by_model(const CircuitModelId& model_id) const;

View File

@ -426,9 +426,9 @@ static
void read_xml_output_mask(pugi::xml_node& xml_port,
const pugiutil::loc_data& loc_data,
CircuitLibrary& circuit_lib, const CircuitPortId& port) {
const char* output_mask_attr = get_attribute(xml_port, "lut_output_mask", loc_data, pugiutil::ReqOpt::OPTIONAL).value();
std::string output_mask_attr = get_attribute(xml_port, "lut_output_mask", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string();
std::vector<size_t> mask_vector;
if (nullptr != output_mask_attr) {
if (!output_mask_attr.empty()) {
/* Split the string with token ',' */
openfpga::StringToken string_tokenizer(get_attribute(xml_port, "lut_output_mask", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(nullptr));
for (const std::string& mask_token : string_tokenizer.split(',')) {
@ -722,9 +722,12 @@ void read_xml_circuit_model(pugi::xml_node& xml_model,
* We count the number of ports in total and then add one by one
*/
size_t num_ports = count_children(xml_model, "port", loc_data, pugiutil::ReqOpt::OPTIONAL);
for (size_t iport = 0; iport < num_ports; ++iport) {
auto xml_port = get_first_child(xml_model, "port", loc_data);
if (0 < num_ports) {
pugi::xml_node xml_port = get_first_child(xml_model, "port", loc_data);
while (xml_port) {
read_xml_circuit_port(xml_port, loc_data, circuit_lib, model);
xml_port = xml_port.next_sibling(xml_port.name());
}
}
/* Parse the parasitics of wires */
@ -736,9 +739,12 @@ void read_xml_circuit_model(pugi::xml_node& xml_model,
/* Parse all the delay matrix if defined */
size_t num_delay_matrix = count_children(xml_model, "delay_matrix", loc_data, pugiutil::ReqOpt::OPTIONAL);
for (size_t idelay_matrix = 0; idelay_matrix < num_delay_matrix; ++idelay_matrix) {
auto xml_delay_matrix = get_first_child(xml_model, "delay_matrix", loc_data);
if (0 < num_delay_matrix) {
pugi::xml_node xml_delay_matrix = get_first_child(xml_model, "delay_matrix", loc_data);
while (xml_delay_matrix) {
read_xml_delay_matrix(xml_delay_matrix, loc_data, circuit_lib, model);
xml_delay_matrix = xml_delay_matrix.next_sibling(xml_delay_matrix.name());
}
}
}

View File

@ -89,7 +89,123 @@ void write_xml_design_technology(std::fstream& fp,
/* Finish all the attributes, we can return here */
fp << "/>" << "\n";
return;
}
/********************************************************************
* 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" << "<port";
write_xml_attribute(fp, "type", CIRCUIT_MODEL_PORT_TYPE_STRING[circuit_lib.port_type(port)]);
write_xml_attribute(fp, "prefix", circuit_lib.port_prefix(port).c_str());
/* Output the lib_name when it is different than prefix */
if (circuit_lib.port_prefix(port) != circuit_lib.port_lib_name(port)) {
write_xml_attribute(fp, "lib_name", circuit_lib.port_lib_name(port).c_str());
}
write_xml_attribute(fp, "size", std::to_string(circuit_lib.port_size(port)).c_str());
/* Output the default value only when this is a global port */
if (true == circuit_lib.port_is_global(port)) {
write_xml_attribute(fp, "default_val", std::to_string(circuit_lib.port_default_value(port)).c_str());
}
/* SRAM port may be for mode selection. Output it only when it is true */
if (CIRCUIT_MODEL_PORT_SRAM == circuit_lib.port_type(port)) {
if (true == circuit_lib.port_is_mode_select(port)) {
write_xml_attribute(fp, "mode_select", "true");
}
}
/* Output the tri-state map of the port
* This is only applicable to input ports of a LUT
*/
if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model))
&& (CIRCUIT_MODEL_PORT_INPUT == circuit_lib.port_type(port)) ) {
if (!circuit_lib.port_tri_state_map(port).empty()) {
write_xml_attribute(fp, "tri_state_map", circuit_lib.port_tri_state_map(port).c_str());
}
}
/* Identify the fracturable-level of the port in LUTs, by default it will be -1
* This is only applicable to output ports of a LUT
*/
if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model))
&& (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) ) {
if (size_t(-1) != circuit_lib.port_lut_frac_level(port)) {
write_xml_attribute(fp, "lut_frac_level", std::to_string(circuit_lib.port_lut_frac_level(port)).c_str());
}
}
/* Output the output mask of the port
* This is only applicable to output ports of a LUT
*/
if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model))
&& (CIRCUIT_MODEL_PORT_OUTPUT == circuit_lib.port_type(port)) ) {
std::string output_mask_string;
for (const size_t& mask : circuit_lib.port_lut_output_mask(port)) {
if (!output_mask_string.empty()) {
output_mask_string += std::string(",");
}
output_mask_string += std::to_string(mask);
}
if (!output_mask_string.empty()) {
write_xml_attribute(fp, "lut_output_mask", output_mask_string.c_str());
}
}
/* Global, reset, set port attributes */
if (true == circuit_lib.port_is_global(port)) {
write_xml_attribute(fp, "is_global", "true");
}
if (true == circuit_lib.port_is_reset(port)) {
write_xml_attribute(fp, "is_reset", "true");
}
if (true == circuit_lib.port_is_set(port)) {
write_xml_attribute(fp, "is_set", "true");
}
if (true == circuit_lib.port_is_prog(port)) {
write_xml_attribute(fp, "is_prog", "true");
}
if (true == circuit_lib.port_is_config_enable(port)) {
write_xml_attribute(fp, "is_config_enable", "true");
}
/* Output the name of circuit model that this port is linked to */
if (!circuit_lib.port_tri_state_model_name(port).empty()) {
write_xml_attribute(fp, "circuit_model_name", circuit_lib.port_tri_state_model_name(port).c_str());
}
/* Find the name of circuit model that port is used for inversion of signals,
* This is only applicable to BL/WL/BLB/WLB ports
*/
if ( (CIRCUIT_MODEL_PORT_BL == circuit_lib.port_type(port))
|| (CIRCUIT_MODEL_PORT_WL == circuit_lib.port_type(port))
|| (CIRCUIT_MODEL_PORT_BLB == circuit_lib.port_type(port))
|| (CIRCUIT_MODEL_PORT_WLB == circuit_lib.port_type(port)) ) {
if (!circuit_lib.port_inv_model_name(port).empty()) {
write_xml_attribute(fp, "inv_circuit_model_name", circuit_lib.port_inv_model_name(port).c_str());
}
}
/* Finish all the attributes, we can return here */
fp << "/>" << "\n";
}
/********************************************************************
@ -125,7 +241,18 @@ void write_xml_circuit_model(std::fstream& fp,
/* Write the design technology of circuit model */
write_xml_design_technology(fp, fname, circuit_lib, model);
/* TODO: Write the ports of circuit model */
/* TODO: Write the input buffer information of circuit model */
/* TODO: Write the output buffer information of circuit model */
/* TODO: Write the lut input buffer information of circuit model */
/* TODO: Write the lut input inverter information of circuit model */
/* TODO: Write the lut intermediate buffer information of circuit model */
/* TODO: Write the pass-gate-logic information of circuit model */
/* Write the ports of circuit model */
for (const CircuitPortId& port : circuit_lib.model_ports(model)) {
write_xml_circuit_port(fp, fname, circuit_lib, port);
}
/* TODO: Write the wire parasticis of circuit model */