2020-01-12 22:33:28 -06:00
|
|
|
/********************************************************************
|
|
|
|
* This file includes the top-level function of this library
|
|
|
|
* which reads an XML modeling OpenFPGA architecture to the associated
|
|
|
|
* data structures
|
|
|
|
*******************************************************************/
|
2020-01-12 23:39:38 -06:00
|
|
|
#include <string>
|
2020-01-12 22:33:28 -06:00
|
|
|
|
|
|
|
/* Headers from pugi XML library */
|
|
|
|
#include "pugixml.hpp"
|
|
|
|
#include "pugixml_util.hpp"
|
|
|
|
|
2020-01-14 17:24:27 -06:00
|
|
|
/* Headers from vtr util library */
|
|
|
|
#include "vtr_assert.h"
|
|
|
|
|
2020-01-12 22:33:28 -06:00
|
|
|
/* Headers from libarchfpga */
|
|
|
|
#include "arch_error.h"
|
|
|
|
#include "read_xml_util.h"
|
|
|
|
|
2020-01-14 09:33:48 -06:00
|
|
|
#include "read_xml_circuit_library.h"
|
2020-01-12 22:33:28 -06:00
|
|
|
|
2020-01-12 23:39:38 -06:00
|
|
|
/********************************************************************
|
|
|
|
* Convert string to the enumerate of model type
|
|
|
|
*******************************************************************/
|
|
|
|
static
|
|
|
|
e_circuit_model_type string_to_circuit_model_type(const std::string& type_string) {
|
|
|
|
if (std::string("chan_wire") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_CHAN_WIRE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("wire") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_WIRE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("mux") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_MUX;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("lut") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_LUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("ff") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_FF;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("sram") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_SRAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("hard_logic") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_HARDLOGIC;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("ccff") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_CCFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("iopad") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_IOPAD;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("inv_buf") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_INVBUF;
|
|
|
|
}
|
|
|
|
|
2020-01-13 22:52:13 -06:00
|
|
|
if (std::string("pass_gate") == type_string) {
|
2020-01-12 23:39:38 -06:00
|
|
|
return CIRCUIT_MODEL_PASSGATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("gate") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_GATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reach here, we have an invalid value, error out */
|
|
|
|
return NUM_CIRCUIT_MODEL_TYPES;
|
|
|
|
}
|
|
|
|
|
2020-01-14 15:10:00 -06:00
|
|
|
/********************************************************************
|
|
|
|
* Convert string to the enumerate of model type
|
|
|
|
*******************************************************************/
|
|
|
|
static
|
|
|
|
e_circuit_model_design_tech string_to_design_tech_type(const std::string& type_string) {
|
|
|
|
if (std::string("cmos") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_DESIGN_CMOS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("rram") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_DESIGN_RRAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES;
|
|
|
|
}
|
|
|
|
|
2020-01-14 16:44:24 -06:00
|
|
|
/********************************************************************
|
|
|
|
* Convert string to the enumerate of buffer type
|
|
|
|
*******************************************************************/
|
|
|
|
static
|
|
|
|
e_circuit_model_buffer_type string_to_buffer_type(const std::string& type_string) {
|
|
|
|
if (std::string("inverter") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_BUF_INV;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("buffer") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_BUF_BUF;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NUM_CIRCUIT_MODEL_BUF_TYPES;
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* Convert string to the enumerate of pass-gate-logic type
|
|
|
|
*******************************************************************/
|
|
|
|
static
|
|
|
|
e_circuit_model_pass_gate_logic_type string_to_passgate_type(const std::string& type_string) {
|
|
|
|
if (std::string("transmission_gate") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_PASS_GATE_TRANSMISSION;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("pass_transistor") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_PASS_GATE_TRANSISTOR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NUM_CIRCUIT_MODEL_PASS_GATE_TYPES;
|
|
|
|
}
|
|
|
|
|
2020-01-14 17:24:27 -06:00
|
|
|
/********************************************************************
|
|
|
|
* Convert string to the enumerate of multiplexer structure
|
|
|
|
*******************************************************************/
|
|
|
|
static
|
|
|
|
e_circuit_model_structure string_to_mux_structure_type(const std::string& type_string) {
|
|
|
|
if (std::string("tree") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_STRUCTURE_TREE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("one-level") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_STRUCTURE_ONELEVEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("multi-level") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_STRUCTURE_MULTILEVEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NUM_CIRCUIT_MODEL_STRUCTURE_TYPES;
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* Convert string to the enumerate of logic gate type
|
|
|
|
*******************************************************************/
|
|
|
|
static
|
|
|
|
e_circuit_model_gate_type string_to_gate_type(const std::string& type_string) {
|
|
|
|
if (std::string("AND") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_GATE_AND;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("OR") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_GATE_OR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (std::string("MUX2") == type_string) {
|
|
|
|
return CIRCUIT_MODEL_GATE_MUX2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NUM_CIRCUIT_MODEL_GATE_TYPES;
|
|
|
|
}
|
|
|
|
|
2020-01-14 15:10:00 -06:00
|
|
|
/********************************************************************
|
|
|
|
* Parse XML codes of design technology of a circuit model to circuit library
|
|
|
|
*******************************************************************/
|
|
|
|
static
|
|
|
|
void read_xml_model_design_technology(pugi::xml_node& xml_model,
|
|
|
|
const pugiutil::loc_data& loc_data,
|
|
|
|
CircuitLibrary& circuit_lib, const CircuitModelId& model) {
|
|
|
|
|
|
|
|
auto xml_design_tech = get_single_child(xml_model, "design_technology", loc_data);
|
|
|
|
|
|
|
|
/* Identify if the circuit model power-gated */
|
|
|
|
circuit_lib.set_model_is_power_gated(model, get_attribute(xml_design_tech, "power_gated", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
|
|
|
|
|
|
|
|
/* Identify the type of design technology */
|
|
|
|
const char* type_attr = get_attribute(xml_design_tech, "type", loc_data).value();
|
|
|
|
/* Translate the type of design technology to enumerate */
|
|
|
|
e_circuit_model_design_tech design_tech_type = string_to_design_tech_type(std::string(type_attr));
|
|
|
|
|
|
|
|
if (NUM_CIRCUIT_MODEL_DESIGN_TECH_TYPES == design_tech_type) {
|
|
|
|
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_design_tech),
|
|
|
|
"Invalid 'type' attribute '%s'\n",
|
|
|
|
type_attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
circuit_lib.set_model_design_tech_type(model, design_tech_type);
|
|
|
|
|
|
|
|
/* Parse exclusive attributes for inverters and buffers */
|
2020-01-14 16:44:24 -06:00
|
|
|
if (CIRCUIT_MODEL_INVBUF == circuit_lib.model_type(model)) {
|
|
|
|
/* Identify the topology of the buffer */
|
|
|
|
const char* topology_attr = get_attribute(xml_design_tech, "topology", loc_data).value();
|
|
|
|
/* Translate the type of buffer to enumerate */
|
|
|
|
e_circuit_model_buffer_type buf_type = string_to_buffer_type(std::string(topology_attr));
|
|
|
|
|
|
|
|
if (NUM_CIRCUIT_MODEL_BUF_TYPES == buf_type) {
|
|
|
|
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_design_tech),
|
|
|
|
"Invalid 'topology' attribute '%s'\n",
|
|
|
|
topology_attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
circuit_lib.set_buffer_type(model, buf_type);
|
|
|
|
|
|
|
|
/* Parse the others options:
|
|
|
|
* 1. size of buffer in the first stage
|
|
|
|
* 2. number of levels
|
|
|
|
* 3. driving strength per stage
|
|
|
|
*/
|
|
|
|
circuit_lib.set_buffer_size(model, get_attribute(xml_design_tech, "size", loc_data).as_float(0.));
|
|
|
|
circuit_lib.set_buffer_num_levels(model, get_attribute(xml_design_tech, "tap_drive_level", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(0));
|
|
|
|
circuit_lib.set_buffer_f_per_stage(model, get_attribute(xml_design_tech, "f_per_stage", loc_data, pugiutil::ReqOpt::OPTIONAL).as_int(4));
|
|
|
|
}
|
2020-01-14 15:10:00 -06:00
|
|
|
|
2020-01-14 16:44:24 -06:00
|
|
|
/* Parse exclusive attributes for pass-gate logics */
|
|
|
|
if (CIRCUIT_MODEL_PASSGATE == circuit_lib.model_type(model)) {
|
|
|
|
/* Identify the topology of the pass-gate logic */
|
|
|
|
const char* topology_attr = get_attribute(xml_design_tech, "topology", loc_data).value();
|
|
|
|
/* Translate the type of pass-gate logic to enumerate */
|
|
|
|
e_circuit_model_pass_gate_logic_type passgate_type = string_to_passgate_type(std::string(topology_attr));
|
|
|
|
|
|
|
|
if (NUM_CIRCUIT_MODEL_PASS_GATE_TYPES == passgate_type) {
|
|
|
|
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_design_tech),
|
|
|
|
"Invalid 'topology' attribute '%s'\n",
|
|
|
|
topology_attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
circuit_lib.set_pass_gate_logic_type(model, passgate_type);
|
|
|
|
/* Parse the others options:
|
|
|
|
* 1. pmos size to be used in the pass gate logic
|
|
|
|
* 2. nmos size to be used in the pass gate logic
|
|
|
|
*/
|
|
|
|
circuit_lib.set_pass_gate_logic_pmos_size(model, get_attribute(xml_design_tech, "pmos_size", loc_data).as_float(0.));
|
|
|
|
circuit_lib.set_pass_gate_logic_nmos_size(model, get_attribute(xml_design_tech, "nmos_size", loc_data).as_float(0.));
|
|
|
|
}
|
|
|
|
|
2020-01-14 17:24:27 -06:00
|
|
|
/* Parse exclusive attributes for Look-Up Tables (LUTs) */
|
|
|
|
if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) {
|
|
|
|
/* Identify if this is a fracturable LUT */
|
|
|
|
circuit_lib.set_lut_is_fracturable(model, get_attribute(xml_design_tech, "fracturable_lut", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
|
|
|
|
/* Set default MUX-relate attributes as LUT contains a tree-like MUX */
|
|
|
|
circuit_lib.set_mux_structure(model, CIRCUIT_MODEL_STRUCTURE_TREE);
|
|
|
|
circuit_lib.set_mux_use_local_encoder(model, false);
|
|
|
|
circuit_lib.set_mux_use_advanced_rram_design(model, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse exclusive attributes for multiplexers */
|
|
|
|
if (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model)) {
|
|
|
|
/* Set default values for multiplexer structure */
|
|
|
|
if (CIRCUIT_MODEL_DESIGN_CMOS == circuit_lib.design_tech_type(model)) {
|
|
|
|
circuit_lib.set_mux_structure(model, CIRCUIT_MODEL_STRUCTURE_TREE);
|
|
|
|
} else {
|
|
|
|
VTR_ASSERT_SAFE(CIRCUIT_MODEL_DESIGN_RRAM == circuit_lib.design_tech_type(model));
|
|
|
|
circuit_lib.set_mux_structure(model, CIRCUIT_MODEL_STRUCTURE_ONELEVEL);
|
|
|
|
}
|
|
|
|
/* Identify the topology of the multiplexer structure */
|
|
|
|
const char* structure_attr = get_attribute(xml_design_tech, "structure", loc_data).value();
|
|
|
|
/* Translate the type of multiplexer structure to enumerate */
|
|
|
|
e_circuit_model_structure mux_structure = string_to_mux_structure_type(std::string(structure_attr));
|
|
|
|
|
|
|
|
if (NUM_CIRCUIT_MODEL_STRUCTURE_TYPES == mux_structure) {
|
|
|
|
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_design_tech),
|
|
|
|
"Invalid 'structure' attribute '%s'\n",
|
|
|
|
structure_attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
circuit_lib.set_mux_structure(model, mux_structure);
|
|
|
|
|
|
|
|
/* Parse the others options:
|
|
|
|
* 1. constant input values
|
|
|
|
* 2. number of levels if multi-level multiplexer structure is selected
|
|
|
|
* 3. if advanced ReRAM design is used
|
|
|
|
* 4. if local encoder is to be used
|
|
|
|
*/
|
|
|
|
if (true == get_attribute(xml_design_tech, "add_const_input", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)) {
|
|
|
|
circuit_lib.set_mux_const_input_value(model, get_attribute(xml_design_tech, "const_input_val", loc_data).as_int(0));
|
|
|
|
}
|
|
|
|
if (CIRCUIT_MODEL_STRUCTURE_MULTILEVEL == circuit_lib.mux_structure(model)) {
|
|
|
|
circuit_lib.set_mux_num_levels(model, get_attribute(xml_design_tech, "num_level", loc_data).as_int(1));
|
|
|
|
}
|
|
|
|
circuit_lib.set_mux_use_advanced_rram_design(model, get_attribute(xml_design_tech, "advanced_rram_design", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
|
|
|
|
circuit_lib.set_mux_use_local_encoder(model, get_attribute(xml_design_tech, "local_encoder", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse exclusive attributes for logic gates */
|
|
|
|
if (CIRCUIT_MODEL_GATE == circuit_lib.model_type(model)) {
|
|
|
|
/* Identify the topology of the logic gate */
|
|
|
|
const char* topology_attr = get_attribute(xml_design_tech, "topology", loc_data).value();
|
|
|
|
/* Translate the type of logic gate to enumerate */
|
|
|
|
e_circuit_model_gate_type gate_type = string_to_gate_type(std::string(topology_attr));
|
|
|
|
|
|
|
|
if (NUM_CIRCUIT_MODEL_GATE_TYPES == gate_type) {
|
|
|
|
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_design_tech),
|
|
|
|
"Invalid 'topology' attribute '%s'\n",
|
|
|
|
topology_attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
circuit_lib.set_gate_type(model, gate_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse exclusive attributes for RRAM */
|
|
|
|
if (CIRCUIT_MODEL_DESIGN_RRAM == circuit_lib.design_tech_type(model)) {
|
|
|
|
circuit_lib.set_rram_rlrs(model, get_attribute(xml_design_tech, "ron", loc_data).as_float(0.));
|
|
|
|
circuit_lib.set_rram_rhrs(model, get_attribute(xml_design_tech, "roff", loc_data).as_float(0.));
|
|
|
|
circuit_lib.set_rram_wprog_set_pmos(model, get_attribute(xml_design_tech, "wprog_set_pmos", loc_data).as_float(0.));
|
|
|
|
circuit_lib.set_rram_wprog_set_nmos(model, get_attribute(xml_design_tech, "wprog_set_nmos", loc_data).as_float(0.));
|
|
|
|
circuit_lib.set_rram_wprog_reset_pmos(model, get_attribute(xml_design_tech, "wprog_reset_pmos", loc_data).as_float(0.));
|
|
|
|
circuit_lib.set_rram_wprog_reset_nmos(model, get_attribute(xml_design_tech, "wprog_reset_nmos", loc_data).as_float(0.));
|
|
|
|
}
|
2020-01-15 16:27:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* This is a generic function to parse XML codes that describe
|
|
|
|
* a buffer of a circuit model to circuit library
|
|
|
|
* This function will return a string with the circuit model name
|
|
|
|
* linked to the buffer
|
|
|
|
* If the return is empty, it means that buffer does NOT exist
|
|
|
|
*******************************************************************/
|
|
|
|
static
|
|
|
|
std::string read_xml_buffer(pugi::xml_node& xml_buffer,
|
|
|
|
const pugiutil::loc_data& loc_data) {
|
|
|
|
bool buffer_existence = get_attribute(xml_buffer, "exist", loc_data).as_bool(false);
|
|
|
|
std::string buffer_circuit_model_name("");
|
|
|
|
|
|
|
|
if (true == buffer_existence) {
|
|
|
|
buffer_circuit_model_name = get_attribute(xml_buffer, "circuit_model_name", loc_data).as_string();
|
|
|
|
}
|
2020-01-14 17:24:27 -06:00
|
|
|
|
2020-01-15 16:27:49 -06:00
|
|
|
return buffer_circuit_model_name;
|
2020-01-14 15:10:00 -06:00
|
|
|
}
|
|
|
|
|
2020-01-13 22:05:58 -06:00
|
|
|
/********************************************************************
|
|
|
|
* Parse XML codes of a circuit model to circuit library
|
|
|
|
*******************************************************************/
|
|
|
|
static
|
2020-01-14 15:10:00 -06:00
|
|
|
void read_xml_circuit_model(pugi::xml_node& xml_model,
|
2020-01-13 22:05:58 -06:00
|
|
|
const pugiutil::loc_data& loc_data,
|
|
|
|
CircuitLibrary& circuit_lib) {
|
|
|
|
/* Find the type of the circuit model
|
|
|
|
* so that we can add a new circuit model to circuit library
|
|
|
|
*/
|
2020-01-14 15:10:00 -06:00
|
|
|
const char* type_attr = get_attribute(xml_model, "type", loc_data).value();
|
2020-01-13 22:05:58 -06:00
|
|
|
|
|
|
|
/* Translate the type of circuit model to enumerate */
|
|
|
|
e_circuit_model_type model_type = string_to_circuit_model_type(std::string(type_attr));
|
|
|
|
|
|
|
|
if (NUM_CIRCUIT_MODEL_TYPES == model_type) {
|
2020-01-14 15:10:00 -06:00
|
|
|
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_model),
|
2020-01-13 22:05:58 -06:00
|
|
|
"Invalid 'type' attribute '%s'\n",
|
|
|
|
type_attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
CircuitModelId model = circuit_lib.add_model(model_type);
|
|
|
|
|
|
|
|
/* Find the name of the circuit model */
|
2020-01-14 15:10:00 -06:00
|
|
|
const char* name_attr = get_attribute(xml_model, "name", loc_data).value();
|
2020-01-13 22:05:58 -06:00
|
|
|
circuit_lib.set_model_name(model, std::string(name_attr));
|
2020-01-14 09:45:27 -06:00
|
|
|
|
|
|
|
/* TODO: This attribute is going to be DEPRECATED
|
|
|
|
* Find the prefix of the circuit model
|
|
|
|
*/
|
2020-01-14 15:10:00 -06:00
|
|
|
const char* prefix_attr = get_attribute(xml_model, "prefix", loc_data).value();
|
2020-01-14 09:45:27 -06:00
|
|
|
circuit_lib.set_model_prefix(model, std::string(prefix_attr));
|
|
|
|
|
|
|
|
/* Find a SPICE netlist which is an optional attribute*/
|
2020-01-14 15:10:00 -06:00
|
|
|
circuit_lib.set_model_circuit_netlist(model, get_attribute(xml_model, "spice_netlist", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(""));
|
2020-01-14 09:45:27 -06:00
|
|
|
|
|
|
|
/* Find a Verilog netlist which is an optional attribute*/
|
2020-01-14 15:10:00 -06:00
|
|
|
circuit_lib.set_model_verilog_netlist(model, get_attribute(xml_model, "verilog_netlist", loc_data, pugiutil::ReqOpt::OPTIONAL).as_string(""));
|
|
|
|
|
|
|
|
/* Find if the circuit model is default in its type */
|
|
|
|
circuit_lib.set_model_is_default(model, get_attribute(xml_model, "is_default", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
|
|
|
|
|
|
|
|
/* Find if the circuit model is should be dumped in structural verilog */
|
|
|
|
circuit_lib.set_model_dump_structural_verilog(model, get_attribute(xml_model, "dump_structural_verilog", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false));
|
|
|
|
|
|
|
|
/* Parse attributes under the <circuit_model> */
|
|
|
|
/* Design technology -related attributes */
|
|
|
|
read_xml_model_design_technology(xml_model, loc_data, circuit_lib, model);
|
|
|
|
|
2020-01-15 16:27:49 -06:00
|
|
|
/* Parse special buffer attributes required by LUTs only */
|
|
|
|
if (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model)) {
|
|
|
|
/* Input buffer of LUTs */
|
|
|
|
auto xml_input_buffer = get_single_child(xml_model, "lut_input_buffer", loc_data);
|
|
|
|
std::string input_buffer_circuit_model_name = read_xml_buffer(xml_input_buffer, loc_data);
|
|
|
|
circuit_lib.set_model_lut_input_buffer(model,
|
|
|
|
true != input_buffer_circuit_model_name.empty(),
|
|
|
|
input_buffer_circuit_model_name);
|
|
|
|
|
|
|
|
/* Input inverter of LUTs */
|
|
|
|
auto xml_input_inverter = get_single_child(xml_model, "lut_input_inverter", loc_data);
|
|
|
|
std::string input_inverter_circuit_model_name = read_xml_buffer(xml_input_inverter, loc_data);
|
|
|
|
circuit_lib.set_model_lut_input_inverter(model,
|
|
|
|
true != input_inverter_circuit_model_name.empty(),
|
|
|
|
input_inverter_circuit_model_name);
|
|
|
|
|
|
|
|
/* Intermediate buffer of LUTs */
|
|
|
|
auto xml_intermediate_buffer = get_single_child(xml_model, "lut_intermediate_buffer", loc_data, pugiutil::ReqOpt::OPTIONAL);
|
|
|
|
if (xml_intermediate_buffer) {
|
|
|
|
std::string intermediate_buffer_circuit_model_name = read_xml_buffer(xml_intermediate_buffer, loc_data);
|
|
|
|
circuit_lib.set_model_lut_intermediate_buffer(model,
|
|
|
|
true != intermediate_buffer_circuit_model_name.empty(),
|
|
|
|
intermediate_buffer_circuit_model_name);
|
|
|
|
/* If intermediate buffer is defined, try to find the location map */
|
|
|
|
if (true != intermediate_buffer_circuit_model_name.empty()) {
|
|
|
|
circuit_lib.set_model_lut_intermediate_buffer_location_map(model, get_attribute(xml_intermediate_buffer, "location_map", loc_data).as_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Input buffer attributes, NOT required for circuit models which are inverters or buffers */
|
|
|
|
if (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) {
|
|
|
|
auto xml_input_buffer = get_single_child(xml_model, "input_buffer", loc_data);
|
|
|
|
std::string input_buffer_circuit_model_name = read_xml_buffer(xml_input_buffer, loc_data);
|
|
|
|
circuit_lib.set_model_input_buffer(model,
|
|
|
|
true != input_buffer_circuit_model_name.empty(),
|
|
|
|
input_buffer_circuit_model_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output buffer attributes, NOT required for circuit models which are inverters or buffers */
|
|
|
|
if (CIRCUIT_MODEL_INVBUF != circuit_lib.model_type(model)) {
|
|
|
|
auto xml_output_buffer = get_single_child(xml_model, "output_buffer", loc_data);
|
|
|
|
std::string output_buffer_circuit_model_name = read_xml_buffer(xml_output_buffer, loc_data);
|
|
|
|
circuit_lib.set_model_output_buffer(model,
|
|
|
|
true != output_buffer_circuit_model_name.empty(),
|
|
|
|
output_buffer_circuit_model_name);
|
|
|
|
}
|
2020-01-15 16:49:02 -06:00
|
|
|
|
|
|
|
/* Pass-gate-logic attributes, required by LUT and MUX */
|
|
|
|
if ( (CIRCUIT_MODEL_LUT == circuit_lib.model_type(model))
|
|
|
|
|| (CIRCUIT_MODEL_MUX == circuit_lib.model_type(model)) ) {
|
|
|
|
auto xml_pass_gate_logic = get_single_child(xml_model, "pass_gate_logic", loc_data);
|
|
|
|
circuit_lib.set_model_pass_gate_logic(model, get_attribute(xml_pass_gate_logic, "circuit_model_name", loc_data).as_string());
|
|
|
|
}
|
2020-01-13 22:05:58 -06:00
|
|
|
}
|
|
|
|
|
2020-01-12 22:33:28 -06:00
|
|
|
/********************************************************************
|
|
|
|
* Parse XML codes about circuit models to circuit library
|
|
|
|
*******************************************************************/
|
2020-01-14 09:33:48 -06:00
|
|
|
CircuitLibrary read_xml_circuit_library(pugi::xml_node& Node,
|
|
|
|
const pugiutil::loc_data& loc_data) {
|
2020-01-12 23:39:38 -06:00
|
|
|
CircuitLibrary circuit_lib;
|
2020-01-14 09:33:48 -06:00
|
|
|
|
2020-01-12 22:33:28 -06:00
|
|
|
/* Iterate over the children under this node,
|
|
|
|
* each child should be named after circuit_model
|
|
|
|
*/
|
2020-01-14 15:10:00 -06:00
|
|
|
for (pugi::xml_node xml_model : Node.children()) {
|
2020-01-12 22:33:28 -06:00
|
|
|
/* Error out if the XML child has an invalid name! */
|
2020-01-14 15:10:00 -06:00
|
|
|
if (xml_model.name() != std::string("circuit_model")) {
|
|
|
|
bad_tag(xml_model, loc_data, Node, {"circuit_model"});
|
2020-01-12 22:33:28 -06:00
|
|
|
}
|
2020-01-14 15:10:00 -06:00
|
|
|
read_xml_circuit_model(xml_model, loc_data, circuit_lib);
|
2020-01-12 22:33:28 -06:00
|
|
|
}
|
2020-01-12 23:39:38 -06:00
|
|
|
|
|
|
|
return circuit_lib;
|
2020-01-12 22:33:28 -06:00
|
|
|
}
|
|
|
|
|