diff --git a/libopenfpga/libarchopenfpga/src/circuit_library.cpp b/libopenfpga/libarchopenfpga/src/circuit_library.cpp index f9c101aff..177e61b93 100644 --- a/libopenfpga/libarchopenfpga/src/circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/circuit_library.cpp @@ -439,6 +439,45 @@ size_t CircuitLibrary::num_delay_info(const CircuitModelId& model_id) const { return delay_types_[model_id].size(); } +/* Return the type of a wire model, this is ONLY applicable to wires and channel wires */ +e_wire_model_type CircuitLibrary::wire_type(const CircuitModelId& model_id) const { + /* validate the model_id */ + VTR_ASSERT(valid_model_id(model_id)); + VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) + || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); + return wire_types_[model_id]; +} + +/* Return the resistance value of a wire model, + * this is ONLY applicable to wires and channel wires + */ +float CircuitLibrary::wire_r(const CircuitModelId& model_id) const { + /* validate the model_id */ + VTR_ASSERT(valid_model_id(model_id)); + /* validate that the type of this model should be WIRE or CHAN_WIRE */ + VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) + || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); + return wire_rc_[model_id].x(); +} + +float CircuitLibrary::wire_c(const CircuitModelId& model_id) const { + /* validate the model_id */ + VTR_ASSERT(valid_model_id(model_id)); + /* validate that the type of this model should be WIRE or CHAN_WIRE */ + VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) + || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); + return wire_rc_[model_id].y(); +} + +size_t CircuitLibrary::wire_num_level(const CircuitModelId& model_id) const { + /* validate the model_id */ + VTR_ASSERT(valid_model_id(model_id)); + /* validate that the type of this model should be WIRE or CHAN_WIRE */ + VTR_ASSERT( (CIRCUIT_MODEL_WIRE == model_type(model_id)) + || (CIRCUIT_MODEL_CHAN_WIRE == model_type(model_id)) ); + return wire_num_levels_[model_id]; +} + /* Return the Low Resistance State Resistance of a RRAM model */ float CircuitLibrary::rram_rlrs(const CircuitModelId& model_id) const { /* validate the model_id */ @@ -1810,8 +1849,8 @@ void CircuitLibrary::set_wire_c(const CircuitModelId& model_id, return; } -void CircuitLibrary::set_wire_num_levels(const CircuitModelId& model_id, - const size_t& num_level) { +void CircuitLibrary::set_wire_num_level(const CircuitModelId& model_id, + const size_t& num_level) { /* validate the model_id */ VTR_ASSERT(valid_model_id(model_id)); /* validate that the type of this model should be WIRE or CHAN_WIRE */ diff --git a/libopenfpga/libarchopenfpga/src/circuit_library.h b/libopenfpga/libarchopenfpga/src/circuit_library.h index 130b08c4e..885867252 100644 --- a/libopenfpga/libarchopenfpga/src/circuit_library.h +++ b/libopenfpga/libarchopenfpga/src/circuit_library.h @@ -228,6 +228,11 @@ class CircuitLibrary { CircuitModelId output_buffer_model(const CircuitModelId& model_id) const; /* Delay information */ size_t num_delay_info(const CircuitModelId& model_id) const; + /* Wire parameters */ + e_wire_model_type wire_type(const CircuitModelId& model_id) const; + float wire_r(const CircuitModelId& model_id) const; + float wire_c(const CircuitModelId& model_id) const; + size_t wire_num_level(const CircuitModelId& model_id) const; /* RRAM information */ float rram_rlrs(const CircuitModelId& model_id) const; float rram_rhrs(const CircuitModelId& model_id) const; @@ -432,8 +437,8 @@ class CircuitLibrary { const float& r_val); void set_wire_c(const CircuitModelId& model_id, const float& c_val); - void set_wire_num_levels(const CircuitModelId& model_id, - const size_t& num_level); + void set_wire_num_level(const CircuitModelId& model_id, + const size_t& num_level); private: /* Private Mutators: builders */ void set_model_buffer(const CircuitModelId& model_id, const enum e_buffer_type buffer_type, const bool& existence, const std::string& model_name); void link_port_tri_state_model(); diff --git a/libopenfpga/libarchopenfpga/src/circuit_types.h b/libopenfpga/libarchopenfpga/src/circuit_types.h index 151ca397a..0124a9bdc 100644 --- a/libopenfpga/libarchopenfpga/src/circuit_types.h +++ b/libopenfpga/libarchopenfpga/src/circuit_types.h @@ -85,6 +85,8 @@ enum e_wire_model_type { WIRE_MODEL_T, NUM_WIRE_MODEL_TYPES }; +/* Strings correspond to each type of logic gate */ +constexpr std::array WIRE_MODEL_TYPE_STRING = {{"pi", "t"}}; enum e_circuit_model_port_type { CIRCUIT_MODEL_PORT_INPUT, @@ -106,6 +108,8 @@ enum e_circuit_model_delay_type { CIRCUIT_MODEL_DELAY_FALL, NUM_CIRCUIT_MODEL_DELAY_TYPES }; +/* Strings correspond to each delay type */ +constexpr std::array CIRCUIT_MODEL_DELAY_TYPE_STRING = {{"rise", "fall"}}; /* For SRAM */ enum e_sram_orgz { diff --git a/libopenfpga/libarchopenfpga/src/read_xml_circuit_library.cpp b/libopenfpga/libarchopenfpga/src/read_xml_circuit_library.cpp index b4cce468c..af12297d1 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_circuit_library.cpp @@ -579,7 +579,7 @@ void read_xml_wire_param(pugi::xml_node& xml_wire_param, circuit_lib.set_wire_c(model, get_attribute(xml_wire_param, "C", loc_data).as_float(0.)); /* Parse the number of levels for the wire model */ - circuit_lib.set_wire_num_levels(model, get_attribute(xml_wire_param, "num_level", loc_data).as_int(0)); + circuit_lib.set_wire_num_level(model, get_attribute(xml_wire_param, "num_level", loc_data).as_int(0)); } /******************************************************************** diff --git a/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp b/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp index a162838a4..88fc0d3b2 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_circuit_library.cpp @@ -3,6 +3,7 @@ *******************************************************************/ /* Headers from system goes first */ #include +#include /* Headers from vtr util library */ #include "vtr_log.h" @@ -208,6 +209,165 @@ void write_xml_circuit_port(std::fstream& fp, fp << "/>" << "\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 *******************************************************************/ @@ -305,9 +465,18 @@ void write_xml_circuit_model(std::fstream& fp, write_xml_circuit_port(fp, fname, circuit_lib, port); } - /* TODO: Write the wire parasticis of circuit model */ + /* 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); + } - /* TODO: Write the delay matrix of circuit 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";