OpenFPGA/libopenfpga/libarchopenfpga/src/read_xml_technology_library...

280 lines
13 KiB
C++
Raw Normal View History

/********************************************************************
* This file includes the top-level function of this library
* which reads an XML modeling OpenFPGA architecture to the associated
* data structures
*******************************************************************/
#include <string>
/* Headers from pugi XML library */
#include "pugixml.hpp"
#include "pugixml_util.hpp"
/* Headers from vtr util library */
#include "vtr_assert.h"
/* Headers from libarchfpga */
#include "arch_error.h"
#include "read_xml_util.h"
#include "read_xml_technology_library.h"
/********************************************************************
* Convert string to the enumerate of device model type
*******************************************************************/
static
e_tech_lib_model_type string_to_device_model_type(const std::string& type_string) {
if (std::string("transistor") == type_string) {
return TECH_LIB_MODEL_TRANSISTOR;
}
if (std::string("rram") == type_string) {
return TECH_LIB_MODEL_RRAM;
}
return NUM_TECH_LIB_MODEL_TYPES;
}
/********************************************************************
* Convert string to the enumerate of technology library type
*******************************************************************/
static
e_tech_lib_type string_to_tech_lib_type(const std::string& type_string) {
if (std::string("industry") == type_string) {
return TECH_LIB_INDUSTRY;
}
if (std::string("academia") == type_string) {
return TECH_LIB_ACADEMIA;
}
return NUM_TECH_LIB_TYPES;
}
/********************************************************************
* Parse XML codes of a <lib> under a device model definiton
* to an object of technology library
*******************************************************************/
static
void read_xml_device_model_lib_settings(pugi::xml_node& xml_device_model_lib,
const pugiutil::loc_data& loc_data,
TechnologyLibrary& tech_lib,
TechnologyModelId& device_model) {
/* Parse the type of model library */
const char* type_attr = get_attribute(xml_device_model_lib, "type", loc_data).value();
/* Translate the type of design technology to enumerate */
e_tech_lib_type device_model_lib_type = string_to_tech_lib_type(std::string(type_attr));
if (NUM_TECH_LIB_TYPES == device_model_lib_type) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_device_model_lib),
"Invalid 'type' attribute '%s'\n",
type_attr);
}
tech_lib.set_model_lib_type(device_model, device_model_lib_type);
/* Parse the type of process corner, this is ONLY applicable to industry library */
if (TECH_LIB_INDUSTRY == tech_lib.model_lib_type(device_model)) {
tech_lib.set_model_corner(device_model, get_attribute(xml_device_model_lib, "corner", loc_data).as_string());
}
/* Parse the model reference */
tech_lib.set_model_ref(device_model, get_attribute(xml_device_model_lib, "ref", loc_data).as_string());
/* Parse the lib path */
tech_lib.set_model_lib_path(device_model, get_attribute(xml_device_model_lib, "path", loc_data).as_string());
}
/********************************************************************
* Parse XML codes of design parameters under a device model
* to an object of technology library
*******************************************************************/
static
void read_xml_device_model_design_settings(pugi::xml_node& xml_device_model_design,
const pugiutil::loc_data& loc_data,
TechnologyLibrary& tech_lib,
TechnologyModelId& device_model) {
/* Parse the vdd to be used in circuit design */
tech_lib.set_model_vdd(device_model, get_attribute(xml_device_model_design, "vdd", loc_data).as_float(0.));
/* Parse the width ratio between PMOS and NMOS transistor */
tech_lib.set_model_pn_ratio(device_model, get_attribute(xml_device_model_design, "pn_ratio", loc_data).as_float(0.));
}
/********************************************************************
* Parse XML codes of transistor models under a device model
* to an object of technology library
*******************************************************************/
static
void read_xml_device_transistor(pugi::xml_node& xml_device_transistor,
const pugiutil::loc_data& loc_data,
TechnologyLibrary& tech_lib,
TechnologyModelId& device_model,
const e_tech_lib_transistor_type& transistor_type) {
/* Parse the transistor model name */
tech_lib.set_transistor_model_name(device_model, transistor_type,
get_attribute(xml_device_transistor, "name", loc_data).as_string());
/* Parse the transistor channel length */
tech_lib.set_transistor_model_chan_length(device_model, transistor_type,
get_attribute(xml_device_transistor, "chan_length", loc_data).as_float(0.));
/* Parse the transistor minimum width */
tech_lib.set_transistor_model_min_width(device_model, transistor_type,
get_attribute(xml_device_transistor, "min_width", loc_data).as_float(0.));
/* Parse the transistor variation name */
tech_lib.set_transistor_model_variation_name(device_model, transistor_type,
get_attribute(xml_device_transistor, "variation", loc_data).as_string());
}
/********************************************************************
* Parse XML codes of RRAM models under a device model
* to an object of technology library
*******************************************************************/
static
void read_xml_device_rram(pugi::xml_node& xml_device_rram,
const pugiutil::loc_data& loc_data,
TechnologyLibrary& tech_lib,
TechnologyModelId& device_model) {
/* Parse the LRS and HRS resistance */
tech_lib.set_rram_rlrs(device_model, get_attribute(xml_device_rram, "rlrs", loc_data).as_float(0.));
tech_lib.set_rram_rhrs(device_model, get_attribute(xml_device_rram, "rhrs", loc_data).as_float(0.));
/* Parse the RRAM variation name */
tech_lib.set_rram_variation_name(device_model, get_attribute(xml_device_rram, "variation", loc_data).as_string());
}
/********************************************************************
* Parse XML codes of a <device> to an object of technology library
*******************************************************************/
static
void read_xml_device_model(pugi::xml_node& xml_device_model,
const pugiutil::loc_data& loc_data,
TechnologyLibrary& tech_lib) {
/* Get the name of this device_model node and add a device to the technology library */
TechnologyModelId device_model = tech_lib.add_model(get_attribute(xml_device_model, "name", loc_data).as_string());
/* Find the type of device model*/
const char* type_attr = get_attribute(xml_device_model, "type", loc_data).value();
/* Translate the type of design technology to enumerate */
e_tech_lib_model_type device_model_type = string_to_device_model_type(std::string(type_attr));
if (NUM_TECH_LIB_MODEL_TYPES == device_model_type) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_device_model),
"Invalid 'type' attribute '%s'\n",
type_attr);
}
tech_lib.set_model_type(device_model, device_model_type);
/* Model library -relate attributes */
auto xml_device_model_lib = get_single_child(xml_device_model, "lib", loc_data);
read_xml_device_model_lib_settings(xml_device_model_lib, loc_data, tech_lib, device_model);
/* Model design -relate attributes, this is ONLY applicable to transistor models */
if (TECH_LIB_MODEL_TRANSISTOR == tech_lib.model_type(device_model)) {
auto xml_device_model_design = get_single_child(xml_device_model, "design", loc_data);
read_xml_device_model_design_settings(xml_device_model_design, loc_data, tech_lib, device_model);
}
/* Transistor -relate attributes, this is ONLY applicable to transistor models */
if (TECH_LIB_MODEL_TRANSISTOR == tech_lib.model_type(device_model)) {
auto xml_device_model_pmos = get_single_child(xml_device_model, "pmos", loc_data);
read_xml_device_transistor(xml_device_model_pmos, loc_data, tech_lib, device_model, TECH_LIB_TRANSISTOR_PMOS);
auto xml_device_model_nmos = get_single_child(xml_device_model, "nmos", loc_data);
read_xml_device_transistor(xml_device_model_nmos, loc_data, tech_lib, device_model, TECH_LIB_TRANSISTOR_NMOS);
}
/* RRAM -relate attributes, this is ONLY applicable to RRAM models */
if (TECH_LIB_MODEL_RRAM == tech_lib.model_type(device_model)) {
auto xml_device_rram = get_single_child(xml_device_model, "rram", loc_data);
read_xml_device_rram(xml_device_rram, loc_data, tech_lib, device_model);
}
}
/********************************************************************
* Parse XML codes of a <variation> to an object of technology library
*******************************************************************/
static
void read_xml_device_variation(pugi::xml_node& xml_device_variation,
const pugiutil::loc_data& loc_data,
TechnologyLibrary& tech_lib) {
/* Get the name of this variation and add it to the technology library */
TechnologyVariationId variation = tech_lib.add_variation(get_attribute(xml_device_variation, "name", loc_data).as_string());
tech_lib.set_variation_abs_value(variation, get_attribute(xml_device_variation, "abs_deviation", loc_data).as_float(0.));
tech_lib.set_variation_num_sigma(variation, get_attribute(xml_device_variation, "num_sigma", loc_data).as_int(0.));
}
/********************************************************************
* Parse XML codes of a <device_library> to an object of technology library
*******************************************************************/
static
void read_xml_device_lib(pugi::xml_node& xml_device_lib,
const pugiutil::loc_data& loc_data,
TechnologyLibrary& tech_lib) {
/* Iterate over the children under this node,
* each child should be named after <device>
*/
for (pugi::xml_node xml_device_model : xml_device_lib.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_device_model.name() != std::string("device_model")) {
bad_tag(xml_device_model, loc_data, xml_device_lib, {"device_model"});
}
read_xml_device_model(xml_device_model, loc_data, tech_lib);
}
}
/********************************************************************
* Parse XML codes of a <variation_library> to an object of technology library
*******************************************************************/
static
void read_xml_variation_lib(pugi::xml_node& xml_variation_lib,
const pugiutil::loc_data& loc_data,
TechnologyLibrary& tech_lib) {
/* Iterate over the children under this node,
* each child should be named after <variation>
*/
for (pugi::xml_node xml_device_variation : xml_variation_lib.children()) {
/* Error out if the XML child has an invalid name! */
if (xml_device_variation.name() != std::string("variation")) {
bad_tag(xml_device_variation, loc_data, xml_variation_lib, {"variation"});
}
read_xml_device_variation(xml_device_variation, loc_data, tech_lib);
}
}
/********************************************************************
* Parse XML codes about <technology_library> to an object of technology library
*******************************************************************/
TechnologyLibrary read_xml_technology_library(pugi::xml_node& Node,
const pugiutil::loc_data& loc_data) {
TechnologyLibrary tech_lib;
/* Iterate over the children under this node,
* There should be only two child nodes
* 1. device_library
* 2. variation_library
*/
size_t num_device_lib = count_children(Node, "device_library", loc_data);
if (1 != num_device_lib) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node),
"Expect only 1 <device_library> defined under <technology_library>");
}
pugi::xml_node xml_device_lib = get_first_child(Node, "device_library", loc_data);
read_xml_device_lib(xml_device_lib, loc_data, tech_lib);
size_t num_variation_lib = count_children(Node, "variation_library", loc_data);
if (1 != num_variation_lib) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(Node),
"Expect only 1 <variation_library> defined under <technology_library>");
}
pugi::xml_node xml_variation_lib = get_first_child(Node, "variation_library", loc_data);
read_xml_variation_lib(xml_variation_lib, loc_data, tech_lib);
return tech_lib;
}