add XML writer for circuit ports
This commit is contained in:
parent
0304d723c0
commit
9ba42cd540
|
@ -16,6 +16,7 @@
|
||||||
<io_nmos model_name="nch_25" chan_length="270e-9" min_width="320e-9"/>
|
<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"/>
|
<io_pmos model_name="pch_25" chan_length="270e-9" min_width="320e-9"/>
|
||||||
</transistors>
|
</transistors>
|
||||||
|
<rram model_name="rram" rlrs="5e3" rhrs="20e6"/>
|
||||||
</technology>
|
</technology>
|
||||||
<circuit_library>
|
<circuit_library>
|
||||||
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">
|
<circuit_model type="inv_buf" name="INVTX1" prefix="INVTX1" is_default="true">
|
||||||
|
|
|
@ -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 */
|
/* 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 */
|
/* validate the circuit_port_id */
|
||||||
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
|
VTR_ASSERT(valid_circuit_port_id(circuit_port_id));
|
||||||
return port_lut_output_masks_[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 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
|
* Public Accessors : Methods to visit timing graphs
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
|
@ -265,12 +265,13 @@ class CircuitLibrary {
|
||||||
bool port_is_config_enable(const CircuitPortId& circuit_port_id) const;
|
bool port_is_config_enable(const CircuitPortId& circuit_port_id) const;
|
||||||
bool port_is_prog(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;
|
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;
|
std::string port_tri_state_map(const CircuitPortId& circuit_port_id) const;
|
||||||
CircuitModelId port_tri_state_model(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;
|
std::string port_tri_state_model_name(const CircuitPortId& circuit_port_id) const;
|
||||||
CircuitModelId port_parent_model(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 model_name(const CircuitPortId& port_id) const;
|
||||||
|
std::string port_inv_model_name(const CircuitPortId& circuit_port_id) const;
|
||||||
public: /* Public Accessors: Timing graph */
|
public: /* Public Accessors: Timing graph */
|
||||||
/* Get source/sink nodes and delay of edges */
|
/* Get source/sink nodes and delay of edges */
|
||||||
std::vector<CircuitEdgeId> timing_edges_by_model(const CircuitModelId& model_id) const;
|
std::vector<CircuitEdgeId> timing_edges_by_model(const CircuitModelId& model_id) const;
|
||||||
|
|
|
@ -426,9 +426,9 @@ static
|
||||||
void read_xml_output_mask(pugi::xml_node& xml_port,
|
void read_xml_output_mask(pugi::xml_node& xml_port,
|
||||||
const pugiutil::loc_data& loc_data,
|
const pugiutil::loc_data& loc_data,
|
||||||
CircuitLibrary& circuit_lib, const CircuitPortId& port) {
|
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;
|
std::vector<size_t> mask_vector;
|
||||||
if (nullptr != output_mask_attr) {
|
if (!output_mask_attr.empty()) {
|
||||||
/* Split the string with token ',' */
|
/* Split the string with token ',' */
|
||||||
openfpga::StringToken string_tokenizer(get_attribute(xml_port, "lut_output_mask", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(nullptr));
|
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(',')) {
|
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
|
* 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);
|
size_t num_ports = count_children(xml_model, "port", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
||||||
for (size_t iport = 0; iport < num_ports; ++iport) {
|
if (0 < num_ports) {
|
||||||
auto xml_port = get_first_child(xml_model, "port", loc_data);
|
pugi::xml_node xml_port = get_first_child(xml_model, "port", loc_data);
|
||||||
read_xml_circuit_port(xml_port, loc_data, circuit_lib, model);
|
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 */
|
/* 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 */
|
/* Parse all the delay matrix if defined */
|
||||||
size_t num_delay_matrix = count_children(xml_model, "delay_matrix", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
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) {
|
if (0 < num_delay_matrix) {
|
||||||
auto xml_delay_matrix = get_first_child(xml_model, "delay_matrix", loc_data);
|
pugi::xml_node xml_delay_matrix = get_first_child(xml_model, "delay_matrix", loc_data);
|
||||||
read_xml_delay_matrix(xml_delay_matrix, loc_data, circuit_lib, model);
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,123 @@ void write_xml_design_technology(std::fstream& fp,
|
||||||
|
|
||||||
/* Finish all the attributes, we can return here */
|
/* Finish all the attributes, we can return here */
|
||||||
fp << "/>" << "\n";
|
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 the design technology of circuit model */
|
||||||
write_xml_design_technology(fp, fname, circuit_lib, 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 */
|
/* TODO: Write the wire parasticis of circuit model */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue