mirror of https://github.com/KLayout/klayout.git
Merge branch 'lefdef-enhancments'
This commit is contained in:
commit
d7af7fc5c0
|
|
@ -140,7 +140,7 @@ struct XORData
|
|||
double tile_size;
|
||||
db::Layout *output_layout;
|
||||
db::cell_index_type output_cell;
|
||||
std::map<db::LayerProperties, std::pair<int, int> > l2l_map;
|
||||
std::map<db::LayerProperties, std::pair<int, int>, db::LPLogicalLessFunc> l2l_map;
|
||||
std::map<std::pair<int, db::LayerProperties>, ResultDescriptor> *results;
|
||||
};
|
||||
|
||||
|
|
@ -299,7 +299,7 @@ BD_PUBLIC int strmxor (int argc, char *argv[])
|
|||
throw tl::Exception ("'" + top_b + "' is not a valid cell name in second layout");
|
||||
}
|
||||
|
||||
std::map<db::LayerProperties, std::pair<int, int> > l2l_map;
|
||||
std::map<db::LayerProperties, std::pair<int, int>, db::LPLogicalLessFunc> l2l_map;
|
||||
|
||||
for (db::Layout::layer_iterator l = layout_a.begin_layers (); l != layout_a.end_layers (); ++l) {
|
||||
l2l_map.insert (std::make_pair (*(*l).second, std::make_pair (-1, -1))).first->second.first = (*l).first;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace db
|
|||
*
|
||||
* This implementation will create new layers if required.
|
||||
*/
|
||||
class DirectLayerMapping
|
||||
class DB_PUBLIC DirectLayerMapping
|
||||
: public ImportLayerMapping
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include "dbReader.h"
|
||||
#include "dbStream.h"
|
||||
#include "tlClassRegistry.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlLog.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -74,5 +76,21 @@ Reader::~Reader ()
|
|||
}
|
||||
}
|
||||
|
||||
const db::LayerMap &
|
||||
Reader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading file: ")) + m_stream.source ());
|
||||
|
||||
return mp_actual_reader->read (layout, options);
|
||||
}
|
||||
|
||||
const db::LayerMap &
|
||||
Reader::read (db::Layout &layout)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading file: ")) + m_stream.source ());
|
||||
|
||||
return mp_actual_reader->read (layout);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,10 +125,7 @@ public:
|
|||
* @param layout The layout object to write to
|
||||
* @param options The LayerMap object
|
||||
*/
|
||||
const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options)
|
||||
{
|
||||
return mp_actual_reader->read (layout, options);
|
||||
}
|
||||
const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options);
|
||||
|
||||
/**
|
||||
* @brief The basic read method (without mapping)
|
||||
|
|
@ -143,10 +140,7 @@ public:
|
|||
* @param layout The layout object to write to
|
||||
* @return The LayerMap object
|
||||
*/
|
||||
const db::LayerMap &read (db::Layout &layout)
|
||||
{
|
||||
return mp_actual_reader->read (layout);
|
||||
}
|
||||
const db::LayerMap &read (db::Layout &layout);
|
||||
|
||||
/**
|
||||
* @brief Returns a format describing the file format found
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include "tlClassRegistry.h"
|
||||
#include "tlAssert.h"
|
||||
#include "tlStream.h"
|
||||
#include "tlTimer.h"
|
||||
#include "tlLog.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -54,6 +56,8 @@ Writer::~Writer ()
|
|||
void
|
||||
Writer::write (db::Layout &layout, tl::OutputStream &stream)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Writing file: ")) + stream.path ());
|
||||
|
||||
tl_assert (mp_writer != 0);
|
||||
mp_writer->write (layout, stream, m_options);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1839,10 +1839,15 @@ LayerPropertiesList::load (tl::XMLSource &stream, std::vector <lay::LayerPropert
|
|||
lay::LayerPropertiesList properties_list;
|
||||
layer_prop_list_structure.parse (stream, properties_list);
|
||||
properties_lists.push_back (properties_list);
|
||||
} catch (...) {
|
||||
// "new" way
|
||||
stream.reset ();
|
||||
layer_prop_lists_structure.parse (stream, properties_lists);
|
||||
} catch (tl::Exception &ex) {
|
||||
try {
|
||||
// "new" way
|
||||
stream.reset ();
|
||||
layer_prop_lists_structure.parse (stream, properties_lists);
|
||||
} catch (tl::Exception &) {
|
||||
// the first exception is likely to be the root cause, so let's rather throw this one
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -818,8 +818,6 @@ CIFReader::read_cell (db::Layout &layout, db::Cell &cell, double sf, int level)
|
|||
void
|
||||
CIFReader::do_read (db::Layout &layout)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + m_stream.source ());
|
||||
|
||||
try {
|
||||
|
||||
double sf = 0.01 / m_dbu;
|
||||
|
|
|
|||
|
|
@ -379,8 +379,6 @@ DXFReader::open_layer (db::Layout &layout, const std::string &n)
|
|||
void
|
||||
DXFReader::do_read (db::Layout &layout, db::cell_index_type top)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + m_stream.source ());
|
||||
|
||||
// create the zero layer - this is not mapped to GDS but can be specified in the layer mapping as
|
||||
// a layer named "0".
|
||||
std::pair<bool, unsigned int> ll = layer_map ().logical (zero_layer_name, layout);
|
||||
|
|
|
|||
|
|
@ -233,8 +233,6 @@ eq_y (const GDS2XY &a, const GDS2XY &b)
|
|||
void
|
||||
GDS2ReaderBase::do_read (db::Layout &layout)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + path ());
|
||||
|
||||
m_cellname = "";
|
||||
m_libname = "";
|
||||
m_mapped_cellnames.clear ();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -36,6 +36,8 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
struct DEFImporterGroup;
|
||||
|
||||
/**
|
||||
* @brief The DEF importer object
|
||||
*/
|
||||
|
|
@ -54,18 +56,33 @@ public:
|
|||
* This method reads the layout specified into the given layout.
|
||||
* Multiple LEF files can be read.
|
||||
*/
|
||||
void read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDelegate &ld);
|
||||
void read_lef (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state);
|
||||
|
||||
protected:
|
||||
void do_read (db::Layout &layout);
|
||||
|
||||
private:
|
||||
LEFImporter m_lef_importer;
|
||||
std::map<std::string, std::map<std::string, double> > m_nondefault_widths;
|
||||
std::map<std::string, std::map<std::string, db::Coord> > m_nondefault_widths;
|
||||
std::map<std::string, ViaDesc> m_via_desc;
|
||||
std::map<int, db::Polygon> m_styles;
|
||||
|
||||
db::FTrans get_orient (bool optional);
|
||||
void read_polygon (db::Polygon &poly, double scale);
|
||||
void read_rect (db::Polygon &poly, double scale);
|
||||
std::pair<Coord, Coord> get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu);
|
||||
std::pair<db::Coord, db::Coord> get_def_ext (const std::string &ln, const std::pair<db::Coord, db::Coord> &wxy, double dbu);
|
||||
void read_diearea (db::Layout &layout, db::Cell &design, double scale);
|
||||
void read_nondefaultrules (double scale);
|
||||
void read_regions (std::map<std::string, std::vector<db::Polygon> > ®ions, double scale);
|
||||
void read_groups (std::list<DEFImporterGroup> &groups, double scale);
|
||||
void read_blockages (db::Layout &layout, db::Cell &design, double scale);
|
||||
void read_nets (db::Layout &layout, db::Cell &design, double scale, bool specialnets);
|
||||
void read_vias (db::Layout &layout, db::Cell &design, double scale);
|
||||
void read_pins (db::Layout &layout, db::Cell &design, double scale);
|
||||
void read_styles (double scale);
|
||||
void read_components (std::list<std::pair<std::string, db::CellInstArray> > &instances, double scale);
|
||||
void read_single_net (std::string &nondefaultrule, db::Layout &layout, db::Cell &design, double scale, properties_id_type prop_id, bool specialnets);
|
||||
void produce_routing_geometry (db::Cell &design, const db::Polygon *style, unsigned int layer, properties_id_type prop_id, const std::vector<db::Point> &pts, const std::vector<std::pair<db::Coord, db::Coord> > &ext, std::pair<db::Coord, db::Coord> w);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@
|
|||
|
||||
|
||||
#include "dbLEFDEFImporter.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
|
||||
#include "tlStream.h"
|
||||
#include "tlProgress.h"
|
||||
#include "tlFileUtils.h"
|
||||
|
||||
#include <cctype>
|
||||
|
||||
|
|
@ -52,9 +54,13 @@ LEFDEFReaderOptions::LEFDEFReaderOptions ()
|
|||
m_produce_via_geometry (true),
|
||||
m_via_geometry_suffix (""),
|
||||
m_via_geometry_datatype (0),
|
||||
m_via_cellname_prefix ("VIA_"),
|
||||
m_produce_pins (true),
|
||||
m_pins_suffix (".PIN"),
|
||||
m_pins_datatype (2),
|
||||
m_produce_lef_pins (true),
|
||||
m_lef_pins_suffix (".PIN"),
|
||||
m_lef_pins_datatype (2),
|
||||
m_produce_obstructions (true),
|
||||
m_obstructions_suffix (".OBS"),
|
||||
m_obstructions_datatype (3),
|
||||
|
|
@ -66,7 +72,13 @@ LEFDEFReaderOptions::LEFDEFReaderOptions ()
|
|||
m_labels_datatype (1),
|
||||
m_produce_routing (true),
|
||||
m_routing_suffix (""),
|
||||
m_routing_datatype (0)
|
||||
m_routing_datatype (0),
|
||||
m_produce_special_routing (true),
|
||||
m_special_routing_suffix (""),
|
||||
m_special_routing_datatype (0),
|
||||
m_separate_groups (false),
|
||||
m_map_file (),
|
||||
m_macro_resolution_mode (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -99,9 +111,13 @@ LEFDEFReaderOptions &LEFDEFReaderOptions::operator= (const LEFDEFReaderOptions &
|
|||
m_produce_via_geometry = d.m_produce_via_geometry;
|
||||
m_via_geometry_suffix = d.m_via_geometry_suffix;
|
||||
m_via_geometry_datatype = d.m_via_geometry_datatype;
|
||||
m_via_cellname_prefix = d.m_via_cellname_prefix;
|
||||
m_produce_pins = d.m_produce_pins;
|
||||
m_pins_suffix = d.m_pins_suffix;
|
||||
m_pins_datatype = d.m_pins_datatype;
|
||||
m_produce_lef_pins = d.m_produce_lef_pins;
|
||||
m_lef_pins_suffix = d.m_lef_pins_suffix;
|
||||
m_lef_pins_datatype = d.m_lef_pins_datatype;
|
||||
m_produce_obstructions = d.m_produce_obstructions;
|
||||
m_obstructions_suffix = d.m_obstructions_suffix;
|
||||
m_obstructions_datatype = d.m_obstructions_datatype;
|
||||
|
|
@ -114,6 +130,12 @@ LEFDEFReaderOptions &LEFDEFReaderOptions::operator= (const LEFDEFReaderOptions &
|
|||
m_produce_routing = d.m_produce_routing;
|
||||
m_routing_suffix = d.m_routing_suffix;
|
||||
m_routing_datatype = d.m_routing_datatype;
|
||||
m_produce_special_routing = d.m_produce_special_routing;
|
||||
m_special_routing_suffix = d.m_special_routing_suffix;
|
||||
m_special_routing_datatype = d.m_special_routing_datatype;
|
||||
m_separate_groups = d.m_separate_groups;
|
||||
m_map_file = d.m_map_file;
|
||||
m_macro_resolution_mode = d.m_macro_resolution_mode;
|
||||
m_lef_files = d.m_lef_files;
|
||||
}
|
||||
return *this;
|
||||
|
|
@ -135,37 +157,194 @@ LEFDEFReaderOptions::format_name () const
|
|||
// -----------------------------------------------------------------------------------
|
||||
// LEFDEFLayerDelegate implementation
|
||||
|
||||
LEFDEFLayerDelegate::LEFDEFLayerDelegate (const LEFDEFReaderOptions *tc)
|
||||
: m_create_layers (true), m_laynum (1), mp_tech_comp (tc)
|
||||
LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout)
|
||||
: m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc)
|
||||
{
|
||||
if (tc) {
|
||||
m_layer_map = tc->layer_map ();
|
||||
m_create_layers = tc->read_all_layers ();
|
||||
}
|
||||
|
||||
m_layer_map.prepare (layout);
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFLayerDelegate::register_layer (const std::string &ln)
|
||||
LEFDEFReaderState::register_layer (const std::string &ln)
|
||||
{
|
||||
m_default_number.insert (std::make_pair (ln, m_laynum));
|
||||
++m_laynum;
|
||||
}
|
||||
|
||||
std::pair <bool, unsigned int>
|
||||
LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose)
|
||||
void
|
||||
LEFDEFReaderState::set_explicit_layer_mapping (bool f)
|
||||
{
|
||||
if (purpose == Outline || purpose == PlacementBlockage || purpose == Region) {
|
||||
m_has_explicit_layer_mapping = f;
|
||||
if (! f) {
|
||||
m_layers.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::map_layer_explicit (const std::string &n, LayerPurpose purpose, const db::LayerProperties &lp, unsigned int layer)
|
||||
{
|
||||
m_layers [std::make_pair (n, purpose)] = std::make_pair (true, layer);
|
||||
m_layer_map.map (lp, layer);
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||
{
|
||||
tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << path;
|
||||
|
||||
tl::InputFile file (path);
|
||||
tl::InputStream file_stream (file);
|
||||
tl::TextInputStream ts (file_stream);
|
||||
|
||||
std::map<std::string, LayerPurpose> purpose_translation;
|
||||
purpose_translation ["LEFPIN"] = LEFPins;
|
||||
purpose_translation ["PIN"] = Pins;
|
||||
purpose_translation ["LEFOBS"] = Obstructions;
|
||||
purpose_translation ["SPNET"] = SpecialRouting;
|
||||
purpose_translation ["NET"] = Routing;
|
||||
purpose_translation ["VIA"] = ViaGeometry;
|
||||
purpose_translation ["BLOCKAGE"] = Blockage;
|
||||
|
||||
std::map<std::pair<std::string, LayerPurpose>, db::LayerProperties> layer_map;
|
||||
|
||||
while (! ts.at_end ()) {
|
||||
|
||||
const std::string &l = ts.get_line ();
|
||||
|
||||
tl::Extractor ex (l.c_str ());
|
||||
if (ex.at_end () || ex.test ("#")) {
|
||||
|
||||
// ignore empty of comment lines
|
||||
|
||||
} else {
|
||||
|
||||
std::string w1, w2;
|
||||
int layer = 0, datatype = 0;
|
||||
|
||||
if (ex.try_read_word (w1) && ex.try_read_word (w2, "._$,/:") && ex.try_read (layer) && ex.try_read (datatype)) {
|
||||
|
||||
if (w1 == "DIEAREA") {
|
||||
|
||||
layer_map [std::make_pair (std::string (), Outline)] = db::LayerProperties (layer, datatype, "OUTLINE");
|
||||
|
||||
} else if (w1 == "REGIONS") {
|
||||
|
||||
layer_map [std::make_pair (std::string (), Regions)] = db::LayerProperties (layer, datatype, "REGIONS");
|
||||
|
||||
} else if (w1 == "BLOCKAGE") {
|
||||
|
||||
layer_map [std::make_pair (std::string (), PlacementBlockage)] = db::LayerProperties (layer, datatype, "PLACEMENT_BLK");
|
||||
|
||||
} else if (w1 == "NAME") {
|
||||
|
||||
// converts a line like
|
||||
// "NAME M1/PINS,M2/PINS ..."
|
||||
// into a canonical name mapping like
|
||||
// "(M1/LABELS): M1.LABEL"
|
||||
// "(M2/LABELS): M2.LABEL"
|
||||
|
||||
std::vector<std::string> layers;
|
||||
std::vector<std::string> purposes = tl::split (w2, ",");
|
||||
for (std::vector<std::string>::const_iterator p = purposes.begin (); p != purposes.end (); ++p) {
|
||||
layers.push_back (tl::split (*p, "/").front ());
|
||||
}
|
||||
|
||||
std::string final_name = tl::join (layers, "/") + ".LABEL";
|
||||
for (std::vector<std::string>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
||||
layer_map [std::make_pair (*l, Label)] = db::LayerProperties (layer, datatype, final_name);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// converts a line like
|
||||
// "M1 SPNET,NET,PINS,LEFPINS ..."
|
||||
// into a canonical name mapping like
|
||||
// "(M1,NET): M1.NET/PINS"
|
||||
// "(M1,PINS): M1.NET/PINS"
|
||||
// (separating, translating and recombing the purposes)
|
||||
|
||||
std::set<LayerPurpose> translated_purposes;
|
||||
std::string purpose_str;
|
||||
std::vector<std::string> purposes = tl::split (w2, ",");
|
||||
for (std::vector<std::string>::const_iterator p = purposes.begin (); p != purposes.end (); ++p) {
|
||||
|
||||
std::map<std::string, LayerPurpose>::const_iterator i = purpose_translation.find (tl::to_upper_case (*p));
|
||||
if (i != purpose_translation.end ()) {
|
||||
|
||||
translated_purposes.insert (i->second);
|
||||
|
||||
if (! purpose_str.empty ()) {
|
||||
purpose_str += "/";
|
||||
}
|
||||
purpose_str += i->first;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::string final_name = w1 + "." + purpose_str;
|
||||
|
||||
for (std::set<LayerPurpose>::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
|
||||
layer_map [std::make_pair (w1, *p)] = db::LayerProperties (layer, datatype, final_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
set_explicit_layer_mapping (true);
|
||||
|
||||
db::DirectLayerMapping lm (&layout);
|
||||
for (std::map<std::pair<std::string, LayerPurpose>, db::LayerProperties>::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) {
|
||||
map_layer_explicit (i->first.first, i->first.second, i->second, lm.map_layer (i->second).second);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair <bool, unsigned int>
|
||||
LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose)
|
||||
{
|
||||
std::map <std::pair<std::string, LayerPurpose>, std::pair<bool, unsigned int> >::const_iterator nl = m_layers.find (std::make_pair (n, purpose));
|
||||
if (nl == m_layers.end ()) {
|
||||
|
||||
std::pair <bool, unsigned int> ll (false, 0);
|
||||
|
||||
if (n.empty () || ! m_has_explicit_layer_mapping) {
|
||||
ll = open_layer_uncached (layout, n, purpose);
|
||||
}
|
||||
|
||||
m_layers.insert (std::make_pair (std::make_pair (n, purpose), ll));
|
||||
return ll;
|
||||
|
||||
} else {
|
||||
return nl->second;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair <bool, unsigned int>
|
||||
LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n, LayerPurpose purpose)
|
||||
{
|
||||
if (n.empty ()) {
|
||||
|
||||
// NOTE: the canonical name is independent from the tech component's settings
|
||||
// as is "(name)". It's used for implementing the automatic map file import
|
||||
// feature.
|
||||
std::string ld;
|
||||
bool produce;
|
||||
bool produce = false;
|
||||
|
||||
if (purpose == Outline) {
|
||||
produce = mp_tech_comp->produce_cell_outlines ();
|
||||
ld = mp_tech_comp->cell_outline_layer ();
|
||||
} else if (purpose == Region) {
|
||||
} else if (purpose == Regions) {
|
||||
produce = mp_tech_comp->produce_regions ();
|
||||
ld = mp_tech_comp->region_layer ();
|
||||
} else {
|
||||
} else if (purpose == PlacementBlockage) {
|
||||
produce = mp_tech_comp->produce_placement_blockages ();
|
||||
ld = mp_tech_comp->placement_blockage_layer ();
|
||||
}
|
||||
|
|
@ -187,11 +366,6 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer
|
|||
|
||||
if (ll.first) {
|
||||
|
||||
// create the layer if it is not part of the layout yet.
|
||||
if (! layout.is_valid_layer (ll.second)) {
|
||||
layout.insert_layer (ll.second, m_layer_map.mapping (ll.second));
|
||||
}
|
||||
|
||||
return ll;
|
||||
|
||||
} else if (! m_create_layers) {
|
||||
|
|
@ -208,67 +382,95 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer
|
|||
|
||||
} else {
|
||||
|
||||
if (mp_tech_comp) {
|
||||
bool produce = true;
|
||||
switch (purpose) {
|
||||
case Routing:
|
||||
default:
|
||||
produce = mp_tech_comp->produce_routing ();
|
||||
break;
|
||||
case SpecialRouting:
|
||||
produce = mp_tech_comp->produce_special_routing ();
|
||||
break;
|
||||
case ViaGeometry:
|
||||
produce = mp_tech_comp->produce_via_geometry ();
|
||||
break;
|
||||
case Label:
|
||||
produce = mp_tech_comp->produce_labels ();
|
||||
break;
|
||||
case Pins:
|
||||
produce = mp_tech_comp->produce_pins ();
|
||||
break;
|
||||
case LEFPins:
|
||||
produce = mp_tech_comp->produce_lef_pins ();
|
||||
break;
|
||||
case Obstructions:
|
||||
produce = mp_tech_comp->produce_obstructions ();
|
||||
break;
|
||||
case Blockage:
|
||||
produce = mp_tech_comp->produce_blockages ();
|
||||
break;
|
||||
}
|
||||
if (! produce) {
|
||||
return std::make_pair (false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: "name" is the decorated name as provided by the tech component's
|
||||
// x_suffix specifications.
|
||||
std::string name (n);
|
||||
bool produce = true;
|
||||
int dt = 0;
|
||||
|
||||
if (mp_tech_comp) {
|
||||
switch (purpose) {
|
||||
case Routing:
|
||||
default:
|
||||
produce = mp_tech_comp->produce_routing ();
|
||||
name += mp_tech_comp->routing_suffix ();
|
||||
dt += mp_tech_comp->routing_datatype ();
|
||||
break;
|
||||
case SpecialRouting:
|
||||
name += mp_tech_comp->special_routing_suffix ();
|
||||
dt += mp_tech_comp->special_routing_datatype ();
|
||||
break;
|
||||
case ViaGeometry:
|
||||
produce = mp_tech_comp->produce_via_geometry ();
|
||||
name += mp_tech_comp->via_geometry_suffix ();
|
||||
dt += mp_tech_comp->via_geometry_datatype ();
|
||||
break;
|
||||
case Label:
|
||||
produce = mp_tech_comp->produce_labels ();
|
||||
name += mp_tech_comp->labels_suffix ();
|
||||
dt += mp_tech_comp->labels_datatype ();
|
||||
break;
|
||||
case Pins:
|
||||
produce = mp_tech_comp->produce_pins ();
|
||||
name += mp_tech_comp->pins_suffix ();
|
||||
dt += mp_tech_comp->pins_datatype ();
|
||||
break;
|
||||
case LEFPins:
|
||||
name += mp_tech_comp->lef_pins_suffix ();
|
||||
dt += mp_tech_comp->lef_pins_datatype ();
|
||||
break;
|
||||
case Obstructions:
|
||||
produce = mp_tech_comp->produce_obstructions ();
|
||||
name += mp_tech_comp->obstructions_suffix ();
|
||||
dt += mp_tech_comp->obstructions_datatype ();
|
||||
break;
|
||||
case Blockage:
|
||||
produce = mp_tech_comp->produce_blockages ();
|
||||
name += mp_tech_comp->blockages_suffix ();
|
||||
dt += mp_tech_comp->blockages_datatype ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! produce) {
|
||||
return std::make_pair (false, 0);
|
||||
}
|
||||
|
||||
std::pair<bool, unsigned int> ll = m_layer_map.logical (name, layout);
|
||||
|
||||
if (ll.first) {
|
||||
|
||||
// create the layer if it is not part of the layout yet.
|
||||
if (! layout.is_valid_layer (ll.second)) {
|
||||
layout.insert_layer (ll.second, m_layer_map.mapping (ll.second));
|
||||
}
|
||||
|
||||
return ll;
|
||||
|
||||
} else {
|
||||
|
||||
std::pair<bool, unsigned int> ll_raw = m_layer_map.logical (n, layout);
|
||||
ll = m_layer_map.logical (n, layout);
|
||||
int ln = -1;
|
||||
|
||||
if (ll_raw.first && (ln = layout.get_properties (ll_raw.second).layer) >= 0) {
|
||||
if (ll.first && (ln = layout.get_properties (ll.second).layer) >= 0) {
|
||||
|
||||
m_layer_map.map (db::LayerProperties (name), layout.layers (), db::LayerProperties (ln, dt, name));
|
||||
m_layer_map.prepare (layout);
|
||||
|
|
@ -280,14 +482,14 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer
|
|||
|
||||
} else {
|
||||
|
||||
std::map <std::pair<std::string, LayerPurpose>, unsigned int>::const_iterator nl = m_layers.find (std::make_pair (n, purpose));
|
||||
if (nl == m_layers.end ()) {
|
||||
unsigned int li = layout.insert_layer (db::LayerProperties (name));
|
||||
m_layer_map.map (db::LayerProperties (name), li);
|
||||
m_layers.insert (std::make_pair (std::make_pair (n, purpose), li));
|
||||
return std::pair<bool, unsigned int> (true, li);
|
||||
std::map <std::pair<std::string, LayerPurpose>, unsigned int>::const_iterator l = m_unassigned_layers.find (std::make_pair (n, purpose));
|
||||
if (l != m_unassigned_layers.end ()) {
|
||||
return std::pair<bool, unsigned int> (true, l->second);
|
||||
} else {
|
||||
return std::pair<bool, unsigned int> (true, nl->second);
|
||||
unsigned int li = layout.insert_layer (db::LayerProperties (name));
|
||||
m_unassigned_layers.insert (std::make_pair (std::make_pair (n, purpose), li));
|
||||
m_layer_map.map (db::LayerProperties (name), li);
|
||||
return std::pair<bool, unsigned int> (true, li);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -298,13 +500,7 @@ LEFDEFLayerDelegate::open_layer (db::Layout &layout, const std::string &n, Layer
|
|||
}
|
||||
|
||||
void
|
||||
LEFDEFLayerDelegate::prepare (db::Layout &layout)
|
||||
{
|
||||
m_layer_map.prepare (layout);
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFLayerDelegate::finish (db::Layout &layout)
|
||||
LEFDEFReaderState::finish (db::Layout &layout)
|
||||
{
|
||||
int lnum = 0;
|
||||
|
||||
|
|
@ -319,7 +515,7 @@ LEFDEFLayerDelegate::finish (db::Layout &layout)
|
|||
used_numbers.insert (ln->second);
|
||||
}
|
||||
|
||||
for (std::map<std::pair<std::string, LayerPurpose>, unsigned int>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
||||
for (std::map<std::pair<std::string, LayerPurpose>, unsigned int>::const_iterator l = m_unassigned_layers.begin (); l != m_unassigned_layers.end (); ++l) {
|
||||
|
||||
int dt = 0;
|
||||
switch (l->first.second) {
|
||||
|
|
@ -327,6 +523,9 @@ LEFDEFLayerDelegate::finish (db::Layout &layout)
|
|||
default:
|
||||
dt = mp_tech_comp->routing_datatype ();
|
||||
break;
|
||||
case SpecialRouting:
|
||||
dt = mp_tech_comp->special_routing_datatype ();
|
||||
break;
|
||||
case ViaGeometry:
|
||||
dt = mp_tech_comp->via_geometry_datatype ();
|
||||
break;
|
||||
|
|
@ -336,6 +535,9 @@ LEFDEFLayerDelegate::finish (db::Layout &layout)
|
|||
case Pins:
|
||||
dt = mp_tech_comp->pins_datatype ();
|
||||
break;
|
||||
case LEFPins:
|
||||
dt = mp_tech_comp->lef_pins_datatype ();
|
||||
break;
|
||||
case Obstructions:
|
||||
dt = mp_tech_comp->obstructions_datatype ();
|
||||
break;
|
||||
|
|
@ -364,11 +566,24 @@ LEFDEFLayerDelegate::finish (db::Layout &layout)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderState::register_via_cell (const std::string &vn, db::Cell *cell)
|
||||
{
|
||||
m_via_cells [vn] = cell;
|
||||
}
|
||||
|
||||
db::Cell *
|
||||
LEFDEFReaderState::via_cell (const std::string &vn)
|
||||
{
|
||||
std::map<std::string, db::Cell *>::const_iterator i = m_via_cells.find (vn);
|
||||
return i != m_via_cells.end () ? i->second : 0;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// LEFDEFImporter implementation
|
||||
|
||||
LEFDEFImporter::LEFDEFImporter ()
|
||||
: mp_progress (0), mp_stream (0), mp_layer_delegate (0),
|
||||
: mp_progress (0), mp_stream (0), mp_reader_state (0),
|
||||
m_produce_net_props (false), m_net_prop_name_id (0),
|
||||
m_produce_inst_props (false), m_inst_prop_name_id (0),
|
||||
m_produce_pin_props (false), m_pin_prop_name_id (0)
|
||||
|
|
@ -382,7 +597,7 @@ LEFDEFImporter::~LEFDEFImporter ()
|
|||
}
|
||||
|
||||
void
|
||||
LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDelegate &ld)
|
||||
LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state)
|
||||
{
|
||||
m_fn = stream.filename ();
|
||||
|
||||
|
|
@ -391,34 +606,39 @@ LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDe
|
|||
progress.set_format_unit (1000.0);
|
||||
progress.set_unit (10000.0);
|
||||
|
||||
mp_reader_state = &state;
|
||||
|
||||
if (state.tech_comp ()) {
|
||||
m_options = *state.tech_comp ();
|
||||
}
|
||||
|
||||
m_produce_net_props = false;
|
||||
m_net_prop_name_id = 0;
|
||||
|
||||
if (ld.tech_comp () && ld.tech_comp ()->produce_net_names ()) {
|
||||
if (m_options.produce_net_names ()) {
|
||||
m_produce_net_props = true;
|
||||
m_net_prop_name_id = layout.properties_repository ().prop_name_id (ld.tech_comp ()->net_property_name ());
|
||||
m_net_prop_name_id = layout.properties_repository ().prop_name_id (m_options.net_property_name ());
|
||||
}
|
||||
|
||||
m_produce_inst_props = false;
|
||||
m_inst_prop_name_id = 0;
|
||||
|
||||
if (ld.tech_comp () && ld.tech_comp ()->produce_inst_names ()) {
|
||||
if (m_options.produce_inst_names ()) {
|
||||
m_produce_inst_props = true;
|
||||
m_inst_prop_name_id = layout.properties_repository ().prop_name_id (ld.tech_comp ()->inst_property_name ());
|
||||
m_inst_prop_name_id = layout.properties_repository ().prop_name_id (m_options.inst_property_name ());
|
||||
}
|
||||
|
||||
m_produce_pin_props = false;
|
||||
m_pin_prop_name_id = 0;
|
||||
|
||||
if (ld.tech_comp () && ld.tech_comp ()->produce_pin_names ()) {
|
||||
if (m_options.produce_pin_names ()) {
|
||||
m_produce_pin_props = true;
|
||||
m_pin_prop_name_id = layout.properties_repository ().prop_name_id (ld.tech_comp ()->pin_property_name ());
|
||||
m_pin_prop_name_id = layout.properties_repository ().prop_name_id (m_options.pin_property_name ());
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
mp_progress = &progress;
|
||||
mp_layer_delegate = &ld;
|
||||
mp_stream = new tl::TextInputStream (stream);
|
||||
|
||||
do_read (layout);
|
||||
|
|
@ -502,7 +722,23 @@ LEFDEFImporter::expect (const std::string &token)
|
|||
}
|
||||
}
|
||||
|
||||
double
|
||||
void
|
||||
LEFDEFImporter::expect (const std::string &token1, const std::string &token2)
|
||||
{
|
||||
if (! test (token1) && ! test (token2)) {
|
||||
error ("Expected token: " + token1 + " or " + token2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFImporter::expect (const std::string &token1, const std::string &token2, const std::string &token3)
|
||||
{
|
||||
if (! test (token1) && ! test (token2) && ! test (token3)) {
|
||||
error ("Expected token: " + token1 + ", " + token2 + " or " + token3);
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
LEFDEFImporter::get_double ()
|
||||
{
|
||||
if (m_last_token.empty ()) {
|
||||
|
|
@ -763,5 +999,48 @@ LEFDEFImporter::create_generated_via (std::vector<db::Polygon> &bottom,
|
|||
|
||||
}
|
||||
|
||||
db::FTrans
|
||||
LEFDEFImporter::get_orient (bool optional)
|
||||
{
|
||||
if (test ("N")) {
|
||||
return db::FTrans (db::FTrans::r0);
|
||||
} else if (test ("S")) {
|
||||
return db::FTrans (db::FTrans::r180);
|
||||
} else if (test ("W")) {
|
||||
return db::FTrans (db::FTrans::r90);
|
||||
} else if (test ("E")) {
|
||||
return db::FTrans (db::FTrans::r270);
|
||||
} else if (test ("FN")) {
|
||||
return db::FTrans (db::FTrans::m90);
|
||||
} else if (test ("FS")) {
|
||||
return db::FTrans (db::FTrans::m0);
|
||||
} else if (test ("FW")) {
|
||||
return db::FTrans (db::FTrans::m45);
|
||||
} else if (test ("FE")) {
|
||||
return db::FTrans (db::FTrans::m135);
|
||||
} else if (optional) {
|
||||
return db::FTrans (db::FTrans::r0);
|
||||
} else {
|
||||
error (tl::to_string (tr ("Invalid orientation specification: ")) + get ());
|
||||
return db::FTrans (db::FTrans::r0);
|
||||
}
|
||||
}
|
||||
|
||||
db::Point
|
||||
LEFDEFImporter::get_point (double scale)
|
||||
{
|
||||
double x = get_double ();
|
||||
double y = get_double ();
|
||||
return db::Point (db::DPoint (x * scale, y * scale));
|
||||
}
|
||||
|
||||
db::Vector
|
||||
LEFDEFImporter::get_vector (double scale)
|
||||
{
|
||||
double x = get_double ();
|
||||
double y = get_double ();
|
||||
return db::Vector (db::DVector (x * scale, y * scale));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -256,6 +256,16 @@ public:
|
|||
m_via_geometry_datatype = s;
|
||||
}
|
||||
|
||||
const std::string &via_cellname_prefix () const
|
||||
{
|
||||
return m_via_cellname_prefix;
|
||||
}
|
||||
|
||||
void set_via_cellname_prefix (const std::string &s)
|
||||
{
|
||||
m_via_cellname_prefix = s;
|
||||
}
|
||||
|
||||
bool produce_pins () const
|
||||
{
|
||||
return m_produce_pins;
|
||||
|
|
@ -286,6 +296,36 @@ public:
|
|||
m_pins_datatype = s;
|
||||
}
|
||||
|
||||
bool produce_lef_pins () const
|
||||
{
|
||||
return m_produce_lef_pins;
|
||||
}
|
||||
|
||||
void set_produce_lef_pins (bool f)
|
||||
{
|
||||
m_produce_lef_pins = f;
|
||||
}
|
||||
|
||||
const std::string &lef_pins_suffix () const
|
||||
{
|
||||
return m_lef_pins_suffix;
|
||||
}
|
||||
|
||||
void set_lef_pins_suffix (const std::string &s)
|
||||
{
|
||||
m_lef_pins_suffix = s;
|
||||
}
|
||||
|
||||
int lef_pins_datatype () const
|
||||
{
|
||||
return m_lef_pins_datatype;
|
||||
}
|
||||
|
||||
void set_lef_pins_datatype (int s)
|
||||
{
|
||||
m_lef_pins_datatype = s;
|
||||
}
|
||||
|
||||
bool produce_obstructions () const
|
||||
{
|
||||
return m_produce_obstructions;
|
||||
|
|
@ -406,6 +446,36 @@ public:
|
|||
m_routing_datatype = s;
|
||||
}
|
||||
|
||||
bool produce_special_routing () const
|
||||
{
|
||||
return m_produce_special_routing;
|
||||
}
|
||||
|
||||
void set_produce_special_routing (bool f)
|
||||
{
|
||||
m_produce_special_routing = f;
|
||||
}
|
||||
|
||||
const std::string &special_routing_suffix () const
|
||||
{
|
||||
return m_special_routing_suffix;
|
||||
}
|
||||
|
||||
void set_special_routing_suffix (const std::string &s)
|
||||
{
|
||||
m_special_routing_suffix = s;
|
||||
}
|
||||
|
||||
int special_routing_datatype () const
|
||||
{
|
||||
return m_special_routing_datatype;
|
||||
}
|
||||
|
||||
void set_special_routing_datatype (int s)
|
||||
{
|
||||
m_special_routing_datatype = s;
|
||||
}
|
||||
|
||||
void clear_lef_files ()
|
||||
{
|
||||
m_lef_files.clear ();
|
||||
|
|
@ -436,6 +506,43 @@ public:
|
|||
m_lef_files = lf;
|
||||
}
|
||||
|
||||
bool separate_groups () const
|
||||
{
|
||||
return m_separate_groups;
|
||||
}
|
||||
|
||||
void set_separate_groups (bool f)
|
||||
{
|
||||
m_separate_groups = f;
|
||||
}
|
||||
|
||||
const std::string &map_file () const
|
||||
{
|
||||
return m_map_file;
|
||||
}
|
||||
|
||||
void set_map_file (const std::string &f)
|
||||
{
|
||||
m_map_file = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specify the LEF macro resolution strategy
|
||||
* Values are:
|
||||
* 0: propduce LEF geometry unless a FOREIGN cell is specified (default)
|
||||
* 1: produce LEF geometry always and ignore FOREIGN
|
||||
* 2: produce a placeholder cell always (even if FOREIGN isn't given)
|
||||
*/
|
||||
unsigned int macro_resolution_mode () const
|
||||
{
|
||||
return m_macro_resolution_mode;
|
||||
}
|
||||
|
||||
void set_macro_resolution_mode (unsigned int m)
|
||||
{
|
||||
m_macro_resolution_mode = m;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_read_all_layers;
|
||||
db::LayerMap m_layer_map;
|
||||
|
|
@ -455,9 +562,13 @@ private:
|
|||
bool m_produce_via_geometry;
|
||||
std::string m_via_geometry_suffix;
|
||||
int m_via_geometry_datatype;
|
||||
std::string m_via_cellname_prefix;
|
||||
bool m_produce_pins;
|
||||
std::string m_pins_suffix;
|
||||
int m_pins_datatype;
|
||||
bool m_produce_lef_pins;
|
||||
std::string m_lef_pins_suffix;
|
||||
int m_lef_pins_datatype;
|
||||
bool m_produce_obstructions;
|
||||
std::string m_obstructions_suffix;
|
||||
int m_obstructions_datatype;
|
||||
|
|
@ -470,6 +581,12 @@ private:
|
|||
bool m_produce_routing;
|
||||
std::string m_routing_suffix;
|
||||
int m_routing_datatype;
|
||||
bool m_produce_special_routing;
|
||||
std::string m_special_routing_suffix;
|
||||
int m_special_routing_datatype;
|
||||
bool m_separate_groups;
|
||||
std::string m_map_file;
|
||||
unsigned int m_macro_resolution_mode;
|
||||
std::vector<std::string> m_lef_files;
|
||||
};
|
||||
|
||||
|
|
@ -478,15 +595,17 @@ private:
|
|||
*/
|
||||
enum LayerPurpose
|
||||
{
|
||||
Routing = 0,
|
||||
ViaGeometry = 1,
|
||||
Label = 2,
|
||||
Pins = 3,
|
||||
Obstructions = 4,
|
||||
Outline = 5,
|
||||
Blockage = 6,
|
||||
PlacementBlockage = 7,
|
||||
Region = 8
|
||||
Routing = 0, // from DEF only
|
||||
SpecialRouting, // from DEF only
|
||||
ViaGeometry, // from LEF+DEF
|
||||
Label, // from LEF+DEF
|
||||
Pins, // from DEF
|
||||
LEFPins, // from LEF
|
||||
Obstructions, // from LEF only
|
||||
Outline, // from LEF+DEF
|
||||
Blockage, // from DEF only
|
||||
PlacementBlockage, // from DEF only
|
||||
Regions, // from DEF only
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -494,16 +613,33 @@ enum LayerPurpose
|
|||
*
|
||||
* This class will handle the creation and management of layers in the LEF/DEF reader context
|
||||
*/
|
||||
class DB_PLUGIN_PUBLIC LEFDEFLayerDelegate
|
||||
class DB_PLUGIN_PUBLIC LEFDEFReaderState
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
LEFDEFLayerDelegate (const LEFDEFReaderOptions *tc);
|
||||
LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout);
|
||||
|
||||
/**
|
||||
* @brief Set the layer map
|
||||
* @brief Provides an explicit layer mapping
|
||||
* This method is used when reading the layer map file.
|
||||
*/
|
||||
void map_layer_explicit (const std::string &n, LayerPurpose purpose, const LayerProperties &lp, unsigned int layer);
|
||||
|
||||
/**
|
||||
* @brief Provides an explicit layer mapping
|
||||
* If this flag is set, the layer mapping specified in the reader options are ignored.
|
||||
*/
|
||||
void set_explicit_layer_mapping (bool f);
|
||||
|
||||
/**
|
||||
* @brief Reads a map file
|
||||
*/
|
||||
void read_map_file (const std::string &path, db::Layout &layout);
|
||||
|
||||
/**
|
||||
* @brief Sets the layer map
|
||||
*/
|
||||
virtual void set_layer_map (const db::LayerMap &lm, bool create_layers)
|
||||
{
|
||||
|
|
@ -512,13 +648,21 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Get the layer map
|
||||
* @brief Gets the layer map
|
||||
*/
|
||||
const db::LayerMap &layer_map () const
|
||||
{
|
||||
return m_layer_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the layer map (non-const version)
|
||||
*/
|
||||
db::LayerMap &layer_map ()
|
||||
{
|
||||
return m_layer_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new layer or return the index of the given layer
|
||||
*/
|
||||
|
|
@ -529,16 +673,21 @@ public:
|
|||
*/
|
||||
void register_layer (const std::string &l);
|
||||
|
||||
/**
|
||||
* @brief Prepare, i.e. create layers required by the layer map
|
||||
*/
|
||||
void prepare (db::Layout &layout);
|
||||
|
||||
/**
|
||||
* @brief Finish, i.e. assign GDS layer numbers to the layers
|
||||
*/
|
||||
void finish (db::Layout &layout);
|
||||
|
||||
/**
|
||||
* @brief Registers a via cell for the via with the given name
|
||||
*/
|
||||
void register_via_cell (const std::string &vn, db::Cell *cell);
|
||||
|
||||
/**
|
||||
* @brief Gets the via cell for the given via name or 0 if no such via is registered
|
||||
*/
|
||||
db::Cell *via_cell (const std::string &vn);
|
||||
|
||||
/**
|
||||
* @brief Get the technology component pointer
|
||||
*/
|
||||
|
|
@ -548,12 +697,17 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
std::map <std::pair<std::string, LayerPurpose>, unsigned int> m_layers;
|
||||
std::map <std::pair<std::string, LayerPurpose>, std::pair<bool, unsigned int> > m_layers;
|
||||
std::map <std::pair<std::string, LayerPurpose>, unsigned int> m_unassigned_layers;
|
||||
db::LayerMap m_layer_map;
|
||||
bool m_create_layers;
|
||||
bool m_has_explicit_layer_mapping;
|
||||
int m_laynum;
|
||||
std::map<std::string, int> m_default_number;
|
||||
std::map<std::string, db::Cell *> m_via_cells;
|
||||
const LEFDEFReaderOptions *mp_tech_comp;
|
||||
|
||||
std::pair <bool, unsigned int> open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -595,7 +749,7 @@ public:
|
|||
*
|
||||
* This method reads the layout specified into the given layout
|
||||
*/
|
||||
void read (tl::InputStream &stream, db::Layout &layout, LEFDEFLayerDelegate &layer_delegate);
|
||||
void read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state);
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
|
@ -635,6 +789,16 @@ protected:
|
|||
*/
|
||||
void expect (const std::string &token);
|
||||
|
||||
/**
|
||||
* @brief Test whether the next token matches one of the given ones and raise an error if it does not
|
||||
*/
|
||||
void expect (const std::string &token1, const std::string &token2);
|
||||
|
||||
/**
|
||||
* @brief Test whether the next token matches one of the given ones and raise an error if it does not
|
||||
*/
|
||||
void expect (const std::string &token, const std::string &token2, const std::string &token3);
|
||||
|
||||
/**
|
||||
* @brief Gets the next token
|
||||
*/
|
||||
|
|
@ -655,12 +819,30 @@ protected:
|
|||
*/
|
||||
long get_long ();
|
||||
|
||||
/**
|
||||
* @brief Gets an orientation code
|
||||
* The orientation code is read employing the LEF/DEF convention ("N" for r0 etc.)
|
||||
*/
|
||||
db::FTrans get_orient (bool optional);
|
||||
|
||||
/**
|
||||
* @brief Reads a point
|
||||
* A point is given by two coordinates, x and y
|
||||
*/
|
||||
db::Point get_point (double scale);
|
||||
|
||||
/**
|
||||
* @brief Reads a vector
|
||||
* A vector is given by two coordinates, x and y
|
||||
*/
|
||||
db::Vector get_vector (double scale);
|
||||
|
||||
/**
|
||||
* @brief Create a new layer or return the index of the given layer
|
||||
*/
|
||||
std::pair <bool, unsigned int> open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose)
|
||||
{
|
||||
return mp_layer_delegate->open_layer (layout, name, purpose);
|
||||
return mp_reader_state->open_layer (layout, name, purpose);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -668,7 +850,7 @@ protected:
|
|||
*/
|
||||
void register_layer (const std::string &l)
|
||||
{
|
||||
mp_layer_delegate->register_layer (l);
|
||||
mp_reader_state->register_layer (l);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -735,7 +917,22 @@ protected:
|
|||
return m_pin_prop_name_id;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Gets the reader options
|
||||
*/
|
||||
const db::LEFDEFReaderOptions &options () const
|
||||
{
|
||||
return m_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the reader state object
|
||||
*/
|
||||
db::LEFDEFReaderState *reader_state ()
|
||||
{
|
||||
return mp_reader_state;
|
||||
}
|
||||
|
||||
void create_generated_via (std::vector<db::Polygon> &bottom,
|
||||
std::vector<db::Polygon> &cut,
|
||||
std::vector<db::Polygon> &top,
|
||||
|
|
@ -750,7 +947,7 @@ protected:
|
|||
private:
|
||||
tl::AbsoluteProgress *mp_progress;
|
||||
tl::TextInputStream *mp_stream;
|
||||
LEFDEFLayerDelegate *mp_layer_delegate;
|
||||
LEFDEFReaderState *mp_reader_state;
|
||||
std::string m_cellname;
|
||||
std::string m_fn;
|
||||
std::string m_last_token;
|
||||
|
|
@ -760,6 +957,7 @@ private:
|
|||
db::property_names_id_type m_inst_prop_name_id;
|
||||
bool m_produce_pin_props;
|
||||
db::property_names_id_type m_pin_prop_name_id;
|
||||
db::LEFDEFReaderOptions m_options;
|
||||
|
||||
const std::string &next ();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
#include "dbLEFImporter.h"
|
||||
#include "dbDEFImporter.h"
|
||||
#include "dbLEFDEFImporter.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "dbTechnology.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -102,14 +104,32 @@ public:
|
|||
{
|
||||
return "LEFDEF";
|
||||
}
|
||||
|
||||
private:
|
||||
tl::InputStream &m_stream;
|
||||
db::LayerMap m_layer_map;
|
||||
|
||||
std::string correct_path (const std::string &fn)
|
||||
std::string correct_path (const std::string &fn, const db::Layout &layout)
|
||||
{
|
||||
if (! tl::is_absolute (fn)) {
|
||||
return tl::combine_path (m_stream.absolute_path (), fn);
|
||||
|
||||
// if a technology is given and the file can be found in the technology's base path, take it
|
||||
// from there.
|
||||
std::string tn = layout.meta_info_value ("technology");
|
||||
const db::Technology *tech = 0;
|
||||
if (! tn.empty ()) {
|
||||
tech = db::Technologies::instance ()->technology_by_name (tn);
|
||||
}
|
||||
|
||||
if (tech && ! tech->base_path ().empty ()) {
|
||||
std::string new_fn = tl::combine_path (tech->base_path (), fn);
|
||||
if (tl::file_exists (new_fn)) {
|
||||
return new_fn;
|
||||
}
|
||||
}
|
||||
|
||||
return tl::combine_path (tl::dirname (m_stream.absolute_path ()), fn);
|
||||
|
||||
} else {
|
||||
return fn;
|
||||
}
|
||||
|
|
@ -123,49 +143,53 @@ private:
|
|||
lefdef_options = &default_options;
|
||||
}
|
||||
|
||||
// Take the layer map and the "read all layers" flag from the reader options - hence we override the
|
||||
db::LEFDEFLayerDelegate layers (lefdef_options);
|
||||
layers.prepare (layout);
|
||||
db::LEFDEFReaderState state (lefdef_options, layout);
|
||||
|
||||
if (! lefdef_options->map_file ().empty ()) {
|
||||
state.read_map_file (correct_path (lefdef_options->map_file (), layout), layout);
|
||||
}
|
||||
|
||||
layout.dbu (lefdef_options->dbu ());
|
||||
|
||||
if (import_lef) {
|
||||
|
||||
tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (tr ("Reading LEF file")));
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file")));
|
||||
|
||||
db::LEFImporter importer;
|
||||
|
||||
for (std::vector<std::string>::const_iterator l = lefdef_options->begin_lef_files (); l != lefdef_options->end_lef_files (); ++l) {
|
||||
|
||||
std::string lp = correct_path (*l);
|
||||
std::string lp = correct_path (*l, layout);
|
||||
|
||||
tl::InputStream lef_stream (lp);
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
|
||||
importer.read (lef_stream, layout, layers);
|
||||
importer.read (lef_stream, layout, state);
|
||||
|
||||
}
|
||||
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
|
||||
importer.read (m_stream, layout, layers);
|
||||
importer.read (m_stream, layout, state);
|
||||
|
||||
} else {
|
||||
|
||||
tl::SelfTimer timer (tl::verbosity () >= 11, tl::to_string (tr ("Reading DEF file")));
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading DEF file")));
|
||||
|
||||
DEFImporter importer;
|
||||
|
||||
for (std::vector<std::string>::const_iterator l = lefdef_options->begin_lef_files (); l != lefdef_options->end_lef_files (); ++l) {
|
||||
|
||||
std::string lp = correct_path (*l);
|
||||
std::string lp = correct_path (*l, layout);
|
||||
|
||||
tl::InputStream lef_stream (lp);
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
|
||||
importer.read_lef (lef_stream, layout, layers);
|
||||
importer.read_lef (lef_stream, layout, state);
|
||||
|
||||
}
|
||||
|
||||
// Additionally read all LEF files next to the DEF file
|
||||
|
||||
std::string input_dir = tl::absolute_path (m_stream.absolute_path ());
|
||||
|
||||
if (tl::file_exists (input_dir)) {
|
||||
|
||||
std::vector<std::string> entries = tl::dir_entries (input_dir);
|
||||
|
|
@ -174,9 +198,12 @@ private:
|
|||
if (is_lef_format (*e)) {
|
||||
|
||||
std::string lp = tl::combine_path (input_dir, *e);
|
||||
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Reading LEF file: ")) + lp);
|
||||
|
||||
tl::InputStream lef_stream (lp);
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << lp;
|
||||
importer.read_lef (lef_stream, layout, layers);
|
||||
importer.read_lef (lef_stream, layout, state);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -185,17 +212,50 @@ private:
|
|||
}
|
||||
|
||||
tl::log << tl::to_string (tr ("Reading")) << " " << m_stream.source ();
|
||||
importer.read (m_stream, layout, layers);
|
||||
importer.read (m_stream, layout, state);
|
||||
|
||||
}
|
||||
|
||||
layers.finish (layout);
|
||||
state.finish (layout);
|
||||
|
||||
m_layer_map = layers.layer_map ();
|
||||
m_layer_map = state.layer_map ();
|
||||
return m_layer_map;
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
struct MacroResolutionModeConverter
|
||||
{
|
||||
public:
|
||||
MacroResolutionModeConverter ()
|
||||
{
|
||||
m_values.push_back ("default");
|
||||
m_values.push_back ("always-lef");
|
||||
m_values.push_back ("always-cellref");
|
||||
}
|
||||
|
||||
std::string to_string (unsigned int v) const
|
||||
{
|
||||
return v < m_values.size () ? m_values[v] : std::string ();
|
||||
}
|
||||
|
||||
void from_string (const std::string &s, unsigned int &v) const
|
||||
{
|
||||
v = 0;
|
||||
for (unsigned int i = 0; i < (unsigned int) m_values.size (); ++i) {
|
||||
if (m_values [i] == s) {
|
||||
v = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_values;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class LEFDEFFormatDeclaration
|
||||
: public db::StreamFormatDeclaration
|
||||
{
|
||||
|
|
@ -253,6 +313,9 @@ class LEFDEFFormatDeclaration
|
|||
tl::make_member (&LEFDEFReaderOptions::produce_pins, &LEFDEFReaderOptions::set_produce_pins, "produce-pins") +
|
||||
tl::make_member (&LEFDEFReaderOptions::pins_suffix, &LEFDEFReaderOptions::set_pins_suffix, "pins-suffix") +
|
||||
tl::make_member (&LEFDEFReaderOptions::pins_datatype, &LEFDEFReaderOptions::set_pins_datatype, "pins-datatype") +
|
||||
tl::make_member (&LEFDEFReaderOptions::produce_lef_pins, &LEFDEFReaderOptions::set_produce_lef_pins, "produce-lef-pins") +
|
||||
tl::make_member (&LEFDEFReaderOptions::lef_pins_suffix, &LEFDEFReaderOptions::set_lef_pins_suffix, "lef-pins-suffix") +
|
||||
tl::make_member (&LEFDEFReaderOptions::lef_pins_datatype, &LEFDEFReaderOptions::set_lef_pins_datatype, "lef-pins-datatype") +
|
||||
tl::make_member (&LEFDEFReaderOptions::produce_obstructions, &LEFDEFReaderOptions::set_produce_obstructions, "produce-obstructions") +
|
||||
tl::make_member (&LEFDEFReaderOptions::obstructions_suffix, &LEFDEFReaderOptions::set_obstructions_suffix, "obstructions-suffix") +
|
||||
tl::make_member (&LEFDEFReaderOptions::obstructions_datatype, &LEFDEFReaderOptions::set_obstructions_datatype, "obstructions-datatype") +
|
||||
|
|
@ -265,7 +328,13 @@ class LEFDEFFormatDeclaration
|
|||
tl::make_member (&LEFDEFReaderOptions::produce_routing, &LEFDEFReaderOptions::set_produce_routing, "produce-routing") +
|
||||
tl::make_member (&LEFDEFReaderOptions::routing_suffix, &LEFDEFReaderOptions::set_routing_suffix, "routing-suffix") +
|
||||
tl::make_member (&LEFDEFReaderOptions::routing_datatype, &LEFDEFReaderOptions::set_routing_datatype, "routing-datatype") +
|
||||
tl::make_member (&LEFDEFReaderOptions::begin_lef_files, &LEFDEFReaderOptions::end_lef_files, &LEFDEFReaderOptions::push_lef_file, "lef-files")
|
||||
tl::make_member (&LEFDEFReaderOptions::produce_special_routing, &LEFDEFReaderOptions::set_produce_special_routing, "produce-special-routing") +
|
||||
tl::make_member (&LEFDEFReaderOptions::special_routing_suffix, &LEFDEFReaderOptions::set_special_routing_suffix, "special-routing-suffix") +
|
||||
tl::make_member (&LEFDEFReaderOptions::special_routing_datatype, &LEFDEFReaderOptions::set_special_routing_datatype, "special-routing-datatype") +
|
||||
tl::make_member (&LEFDEFReaderOptions::begin_lef_files, &LEFDEFReaderOptions::end_lef_files, &LEFDEFReaderOptions::push_lef_file, "lef-files") +
|
||||
tl::make_member (&LEFDEFReaderOptions::macro_resolution_mode, &LEFDEFReaderOptions::set_macro_resolution_mode, "macro-resolution-mode", MacroResolutionModeConverter ()) +
|
||||
tl::make_member (&LEFDEFReaderOptions::separate_groups, &LEFDEFReaderOptions::set_separate_groups, "separate-groups") +
|
||||
tl::make_member (&LEFDEFReaderOptions::map_file, &LEFDEFReaderOptions::set_map_file, "map-file")
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -65,12 +65,23 @@ LEFImporter::layer_ext (const std::string &layer, double def_ext) const
|
|||
}
|
||||
}
|
||||
|
||||
double
|
||||
LEFImporter::layer_width (const std::string &layer, const std::string &nondefaultrule, double def_width) const
|
||||
std::pair<double, double>
|
||||
LEFImporter::min_layer_width (const std::string &layer) const
|
||||
{
|
||||
std::map<std::string, std::map<std::string, double> >::const_iterator nd = m_nondefault_widths.find (nondefaultrule);
|
||||
std::map<std::string, std::pair<double, double> >::const_iterator l = m_min_widths.find (layer);
|
||||
if (l != m_min_widths.end ()) {
|
||||
return l->second;
|
||||
} else {
|
||||
return std::make_pair (0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, double>::const_iterator l;
|
||||
std::pair<double, double>
|
||||
LEFImporter::layer_width (const std::string &layer, const std::string &nondefaultrule, const std::pair<double, double> &def_width) const
|
||||
{
|
||||
std::map<std::string, std::map<std::string, std::pair<double, double> > >::const_iterator nd = m_nondefault_widths.find (nondefaultrule);
|
||||
|
||||
std::map<std::string, std::pair<double, double> >::const_iterator l;
|
||||
bool has_width = false;
|
||||
|
||||
if (! nondefaultrule.empty () && nd != m_nondefault_widths.end ()) {
|
||||
|
|
@ -94,14 +105,14 @@ LEFImporter::layer_width (const std::string &layer, const std::string &nondefaul
|
|||
}
|
||||
}
|
||||
|
||||
db::Cell *
|
||||
std::pair<db::Cell *, db::Trans>
|
||||
LEFImporter::macro_by_name (const std::string &name) const
|
||||
{
|
||||
std::map<std::string, db::Cell *>::const_iterator m = m_macros_by_name.find (name);
|
||||
std::map<std::string, std::pair<db::Cell *, db::Trans> >::const_iterator m = m_macros_by_name.find (name);
|
||||
if (m != m_macros_by_name.end ()) {
|
||||
return m->second;
|
||||
} else {
|
||||
return 0;
|
||||
return std::make_pair ((db::Cell *) 0, db::Trans ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -174,9 +185,9 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||
}
|
||||
|
||||
w = 0.0;
|
||||
std::map<std::string, double>::const_iterator dw = m_default_widths.find (layer_name);
|
||||
std::map<std::string, std::pair<double, double> >::const_iterator dw = m_default_widths.find (layer_name);
|
||||
if (dw != m_default_widths.end ()) {
|
||||
w = dw->second;
|
||||
w = dw->second.first;
|
||||
}
|
||||
|
||||
while (! test (";")) {
|
||||
|
|
@ -334,20 +345,18 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||
points.push_back (db::Vector (db::DVector (x / dbu, y / dbu)));
|
||||
|
||||
std::string vn = get ();
|
||||
std::pair<bool, db::cell_index_type> cn = layout.cell_by_name (("VIA_" + vn).c_str ());
|
||||
if (! cn.first) {
|
||||
warn ("Unknown via: " + vn);
|
||||
db::Cell *vc = reader_state ()->via_cell (vn);
|
||||
if (! vc) {
|
||||
warn (tl::to_string (tr ("Unknown via: ")) + vn);
|
||||
}
|
||||
|
||||
if (iterate) {
|
||||
std::vector<db::Trans> ti = get_iteration (layout);
|
||||
if (cn.first) {
|
||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||
cell.insert (db::CellInstArray (db::CellInst (cn.second), *t * db::Trans (points [0])));
|
||||
}
|
||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||
cell.insert (db::CellInstArray (db::CellInst (vc->cell_index ()), *t * db::Trans (points [0])));
|
||||
}
|
||||
} else if (cn.first) {
|
||||
cell.insert (db::CellInstArray (db::CellInst (cn.second), db::Trans (points [0])));
|
||||
} else {
|
||||
cell.insert (db::CellInstArray (db::CellInst (vc->cell_index ()), db::Trans (points [0])));
|
||||
}
|
||||
|
||||
expect (";");
|
||||
|
|
@ -360,6 +369,568 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFImporter::read_nondefaultrule (db::Layout & /*layout*/)
|
||||
{
|
||||
// read NONDEFAULTRULE sections
|
||||
std::string n = get ();
|
||||
|
||||
while (! test ("END") || ! test (n)) {
|
||||
|
||||
if (test ("LAYER")) {
|
||||
|
||||
std::string l = get ();
|
||||
|
||||
// read the width for the layer
|
||||
while (! test ("END")) {
|
||||
if (test ("WIDTH")) {
|
||||
double w = get_double ();
|
||||
test (";");
|
||||
m_nondefault_widths[n][l] = std::make_pair (w, w);
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test (l);
|
||||
|
||||
} else if (test ("VIA")) {
|
||||
|
||||
// ignore VIA statements
|
||||
std::string v = get ();
|
||||
while (! test ("END") || ! test (v)) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFImporter::read_viadef_by_rule (Layout &layout, db::Cell &cell, ViaDesc &via_desc, const std::string & /*n*/)
|
||||
{
|
||||
db::Vector cutsize, cutspacing;
|
||||
db::Vector be, te;
|
||||
db::Vector bo, to;
|
||||
db::Point offset;
|
||||
int rows = 1, columns = 1;
|
||||
std::string pattern;
|
||||
|
||||
std::vector<std::pair<std::string, std::vector<db::Polygon> > > geometry;
|
||||
geometry.push_back (std::pair<std::string, std::vector<db::Polygon> > ());
|
||||
geometry.push_back (std::pair<std::string, std::vector<db::Polygon> > ());
|
||||
geometry.push_back (std::pair<std::string, std::vector<db::Polygon> > ());
|
||||
|
||||
while (! test ("END")) {
|
||||
|
||||
double x, y;
|
||||
|
||||
if (test ("CUTSIZE")) {
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
cutsize = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("CUTSPACING")) {
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
cutspacing = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("ORIGIN")) {
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
offset = db::Point (db::DPoint (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("ENCLOSURE")) {
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
be = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
te = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("OFFSET")) {
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
bo = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
to = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("ROWCOL")) {
|
||||
|
||||
rows = get_long ();
|
||||
columns = get_long ();
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("PATTERN")) {
|
||||
|
||||
pattern = get ();
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("LAYERS")) {
|
||||
|
||||
via_desc.m1 = geometry[0].first = get ();
|
||||
geometry[1].first = get ();
|
||||
via_desc.m2 = geometry[2].first = get ();
|
||||
|
||||
test (";");
|
||||
|
||||
} else {
|
||||
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
create_generated_via (geometry [0].second, geometry [1].second, geometry [2].second,
|
||||
cutsize, cutspacing, be, te, bo, to, offset, rows, columns, pattern);
|
||||
|
||||
for (std::vector<std::pair<std::string, std::vector<db::Polygon> > >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) {
|
||||
std::pair <bool, unsigned int> dl = open_layer (layout, g->first, ViaGeometry);
|
||||
if (dl.first) {
|
||||
for (std::vector<db::Polygon>::const_iterator p = g->second.begin (); p != g->second.end (); ++p) {
|
||||
cell.shapes (dl.second).insert (*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFImporter::read_viadef_by_geometry (Layout &layout, db::Cell &cell, ViaDesc &via_desc, const std::string &n)
|
||||
{
|
||||
// ignore resistance spec
|
||||
if (test ("RESISTANCE")) {
|
||||
get_double ();
|
||||
test (";");
|
||||
}
|
||||
|
||||
std::map<std::string, db::Box> bboxes;
|
||||
read_geometries (layout, cell, ViaGeometry, &bboxes);
|
||||
|
||||
// determine m1 and m2 layers
|
||||
|
||||
std::vector<std::string> routing_layers;
|
||||
for (std::map<std::string, db::Box>::const_iterator b = bboxes.begin (); b != bboxes.end (); ++b) {
|
||||
if (m_routing_layers.find (b->first) != m_routing_layers.end ()) {
|
||||
routing_layers.push_back (b->first);
|
||||
}
|
||||
}
|
||||
|
||||
if (routing_layers.size () == 2) {
|
||||
via_desc.m1 = routing_layers[0];
|
||||
via_desc.m2 = routing_layers[1];
|
||||
} else {
|
||||
warn (tl::to_string (tr ("Can't determine routing layers for via: ")) + n);
|
||||
}
|
||||
|
||||
reset_cellname ();
|
||||
|
||||
expect ("END");
|
||||
}
|
||||
|
||||
void
|
||||
LEFImporter::read_viadef (Layout &layout)
|
||||
{
|
||||
std::string n = get ();
|
||||
|
||||
// produce a cell for vias
|
||||
std::string cellname = options ().via_cellname_prefix () + n;
|
||||
db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ()));
|
||||
reader_state ()->register_via_cell (n, &cell);
|
||||
|
||||
ViaDesc &via_desc = m_vias[n];
|
||||
via_desc.cell = &cell;
|
||||
|
||||
while (test ("DEFAULT") || test ("TOPOFSTACKONLY"))
|
||||
;
|
||||
test (";");
|
||||
|
||||
if (test ("VIARULE")) {
|
||||
read_viadef_by_rule (layout, cell, via_desc, n);
|
||||
} else {
|
||||
read_viadef_by_geometry (layout, cell, via_desc, n);
|
||||
}
|
||||
|
||||
test ("VIA");
|
||||
expect (n);
|
||||
}
|
||||
|
||||
void
|
||||
LEFImporter::read_layer (Layout & /*layout*/)
|
||||
{
|
||||
std::string ln = get ();
|
||||
double wmin = 0.0, wmin_wrongdir = 0.0;
|
||||
double w = 0.0, w_wrongdir = 0.0;
|
||||
bool is_horizontal = false;
|
||||
|
||||
register_layer (ln);
|
||||
|
||||
// just extract the width from the layer - we need that as the default width for paths
|
||||
while (! at_end ()) {
|
||||
|
||||
if (test ("END")) {
|
||||
|
||||
expect (ln);
|
||||
break;
|
||||
|
||||
} else if (test ("TYPE")) {
|
||||
|
||||
std::string type = get ();
|
||||
|
||||
if (type == "ROUTING" || type == "MASTERSLICE") {
|
||||
m_routing_layers.insert (ln);
|
||||
} else if (type == "CUT") {
|
||||
m_cut_layers.insert (ln);
|
||||
}
|
||||
expect (";");
|
||||
|
||||
} else if (test ("WIDTH")) {
|
||||
|
||||
w = get_double ();
|
||||
expect (";");
|
||||
|
||||
} else if (test ("MINWIDTH")) {
|
||||
|
||||
wmin = get_double ();
|
||||
expect (";");
|
||||
|
||||
} else if (test ("DIRECTION")) {
|
||||
|
||||
if (test ("HORIZONTAL")) {
|
||||
is_horizontal = true;
|
||||
} else {
|
||||
expect ("VERTICAL", "DIAG45", "DIAG135");
|
||||
}
|
||||
|
||||
} else if (test ("WIREEXTENSION")) {
|
||||
|
||||
double v = get_double ();
|
||||
m_default_ext.insert (std::make_pair (ln, v));
|
||||
expect (";");
|
||||
|
||||
} else if (test ("ACCURRENTDENSITY")) {
|
||||
|
||||
// ACCURRENTDENSITY needs some special attention because it can contain nested WIDTH
|
||||
// blocks following a semicolon
|
||||
take ();
|
||||
if (test ("FREQUENCY")) {
|
||||
while (! test ("TABLEENTRIES")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("PROPERTY")) {
|
||||
|
||||
std::string name = get ();
|
||||
tl::Variant value = get ();
|
||||
|
||||
if (name == "LEF58_MINWIDTH") {
|
||||
|
||||
// Cadence extension
|
||||
tl::Extractor ex (value.to_string ());
|
||||
double v = 0.0;
|
||||
if (ex.test ("MINWIDTH") && ex.try_read (v)) {
|
||||
if (ex.test ("WRONGDIRECTION")) {
|
||||
wmin_wrongdir = v;
|
||||
} else {
|
||||
wmin = v;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (name == "LEF58_WIDTH") {
|
||||
|
||||
// Cadence extension
|
||||
tl::Extractor ex (value.to_string ());
|
||||
double v = 0.0;
|
||||
if (ex.test ("WIDTH") && ex.try_read (v)) {
|
||||
if (ex.test ("WRONGDIRECTION")) {
|
||||
w_wrongdir = v;
|
||||
} else {
|
||||
w = v;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
expect (";");
|
||||
|
||||
} else {
|
||||
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (w > 0.0 || w_wrongdir > 0.0) {
|
||||
|
||||
if (w_wrongdir == 0.0) {
|
||||
w_wrongdir = w;
|
||||
} else if (! is_horizontal) {
|
||||
std::swap (w, w_wrongdir);
|
||||
}
|
||||
|
||||
m_default_widths.insert (std::make_pair (ln, std::make_pair (w, w_wrongdir)));
|
||||
|
||||
}
|
||||
|
||||
if (wmin > 0.0 || wmin_wrongdir > 0.0) {
|
||||
|
||||
if (wmin_wrongdir == 0.0) {
|
||||
wmin_wrongdir = wmin;
|
||||
} else if (! is_horizontal) {
|
||||
std::swap (wmin, wmin_wrongdir);
|
||||
}
|
||||
|
||||
m_min_widths.insert (std::make_pair (ln, std::make_pair (wmin, wmin_wrongdir)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFImporter::read_macro (Layout &layout)
|
||||
{
|
||||
std::string mn = get ();
|
||||
|
||||
if (m_macros_by_name.find (mn) != m_macros_by_name.end ()) {
|
||||
error (tl::to_string (tr ("Duplicate MACRO name: ")) + mn);
|
||||
}
|
||||
|
||||
set_cellname (mn);
|
||||
|
||||
db::Cell &cell = layout.cell (layout.add_cell ());
|
||||
db::Cell *foreign_cell = 0;
|
||||
db::Trans foreign_trans;
|
||||
std::string foreign_name;
|
||||
|
||||
db::Point origin;
|
||||
db::Vector size;
|
||||
|
||||
// read the macro
|
||||
while (! at_end ()) {
|
||||
|
||||
if (test ("END")) {
|
||||
expect (mn);
|
||||
break;
|
||||
|
||||
} else if (test ("ORIGIN")) {
|
||||
|
||||
origin = get_point (1.0 / layout.dbu ());
|
||||
expect (";");
|
||||
|
||||
} else if (test ("SIZE")) {
|
||||
|
||||
double x = get_double ();
|
||||
test ("BY");
|
||||
double y = get_double ();
|
||||
expect (";");
|
||||
size = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
} else if (test ("PIN")) {
|
||||
|
||||
std::string pn = get ();
|
||||
std::string dir;
|
||||
|
||||
while (! at_end ()) {
|
||||
|
||||
if (test ("END")) {
|
||||
|
||||
break;
|
||||
|
||||
} else if (test ("DIRECTION")) {
|
||||
|
||||
dir = get ();
|
||||
test (";");
|
||||
|
||||
} else if (test ("PORT")) {
|
||||
|
||||
// produce pin labels
|
||||
// TODO: put a label on every single object?
|
||||
std::string label = pn;
|
||||
/* don't add the direction currently, a name is sufficient
|
||||
if (! dir.empty ()) {
|
||||
label += ":";
|
||||
label += dir;
|
||||
}
|
||||
*/
|
||||
|
||||
db::properties_id_type prop_id = 0;
|
||||
if (produce_pin_props ()) {
|
||||
db::PropertiesRepository::properties_set props;
|
||||
props.insert (std::make_pair (pin_prop_name_id (), tl::Variant (label)));
|
||||
prop_id = layout.properties_repository ().properties_id (props);
|
||||
}
|
||||
|
||||
std::map <std::string, db::Box> bboxes;
|
||||
read_geometries (layout, cell, LEFPins, &bboxes, prop_id);
|
||||
|
||||
for (std::map <std::string, db::Box>::const_iterator b = bboxes.begin (); b != bboxes.end (); ++b) {
|
||||
std::pair <bool, unsigned int> dl = open_layer (layout, b->first, Label);
|
||||
if (dl.first) {
|
||||
cell.shapes (dl.second).insert (db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ())));
|
||||
}
|
||||
}
|
||||
|
||||
expect ("END");
|
||||
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect (pn);
|
||||
|
||||
} else if (test ("FOREIGN")) {
|
||||
|
||||
if (foreign_cell) {
|
||||
error (tl::to_string (tr ("Duplicate FOREIGN definition")));
|
||||
}
|
||||
|
||||
std::string cn = get ();
|
||||
|
||||
db::Point vec;
|
||||
db::FTrans ft;
|
||||
if (! peek (";")) {
|
||||
vec = get_point (1.0 / layout.dbu ());
|
||||
ft = get_orient (true);
|
||||
}
|
||||
|
||||
expect (";");
|
||||
|
||||
if (options ().macro_resolution_mode () != 1) {
|
||||
|
||||
db::cell_index_type ci;
|
||||
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (cn.c_str ());
|
||||
if (c.first) {
|
||||
ci = c.second;
|
||||
} else {
|
||||
ci = layout.add_cell (cn.c_str ());
|
||||
layout.cell (ci).set_ghost_cell (true);
|
||||
}
|
||||
|
||||
foreign_cell = &layout.cell (ci);
|
||||
// What is the definition of the FOREIGN transformation?
|
||||
// Guessing: this transformation moves the lower-left origin to 0,0
|
||||
foreign_trans = db::Trans (db::Point () - vec) * db::Trans (ft);
|
||||
foreign_name = cn;
|
||||
|
||||
}
|
||||
|
||||
} else if (test ("OBS")) {
|
||||
|
||||
read_geometries (layout, cell, Obstructions);
|
||||
expect ("END");
|
||||
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! foreign_cell) {
|
||||
|
||||
if (options ().macro_resolution_mode () != 2) {
|
||||
|
||||
// actually implement the real cell
|
||||
|
||||
layout.rename_cell (cell.cell_index (), mn.c_str ());
|
||||
|
||||
std::pair <bool, unsigned int> dl = open_layer (layout, std::string (), Outline);
|
||||
if (dl.first) {
|
||||
cell.shapes (dl.second).insert (db::Box (-origin, -origin + size));
|
||||
}
|
||||
|
||||
m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ())));
|
||||
|
||||
} else {
|
||||
|
||||
// macro resolution mode #2 (always create a MACRO reference, no LEF geometry)
|
||||
|
||||
db::cell_index_type ci;
|
||||
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (mn.c_str ());
|
||||
if (c.first) {
|
||||
ci = c.second;
|
||||
} else {
|
||||
ci = layout.add_cell (mn.c_str ());
|
||||
layout.cell (ci).set_ghost_cell (true);
|
||||
}
|
||||
|
||||
layout.delete_cell (cell.cell_index ());
|
||||
m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&layout.cell (ci), db::Trans ())));
|
||||
|
||||
}
|
||||
|
||||
} else if (foreign_name != mn) {
|
||||
|
||||
warn (tl::to_string (tr ("FOREIGN name differs from MACRO name in macro: ")) + mn);
|
||||
|
||||
layout.rename_cell (cell.cell_index (), mn.c_str ());
|
||||
|
||||
// clear imported LEF geometry with a foreign cell, but provide a level of indirection so we have
|
||||
// both the MACRO and the FOREIGN name
|
||||
|
||||
for (unsigned int l = 0; l < layout.layers (); ++l) {
|
||||
if (layout.is_valid_layer (l)) {
|
||||
cell.clear (l);
|
||||
}
|
||||
}
|
||||
|
||||
cell.clear_insts ();
|
||||
|
||||
cell.insert (db::CellInstArray (db::CellInst (foreign_cell->cell_index ()), db::Trans (db::Point () - origin) * foreign_trans));
|
||||
m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ())));
|
||||
|
||||
} else {
|
||||
|
||||
// use FOREIGN cell instead of new one
|
||||
|
||||
layout.delete_cell (cell.cell_index ());
|
||||
m_macros_by_name.insert (std::make_pair (mn, std::make_pair (foreign_cell, db::Trans (db::Point () - origin) * foreign_trans)));
|
||||
|
||||
}
|
||||
|
||||
m_macro_bboxes_by_name.insert (std::make_pair (mn, db::Box (-origin, -origin + size)));
|
||||
|
||||
reset_cellname ();
|
||||
}
|
||||
|
||||
void
|
||||
LEFImporter::do_read (db::Layout &layout)
|
||||
{
|
||||
|
|
@ -414,45 +985,7 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
|
||||
} else if (test ("NONDEFAULTRULE")) {
|
||||
|
||||
// read NONDEFAULTRULE sections
|
||||
std::string n = get ();
|
||||
|
||||
while (! test ("END") || ! test (n)) {
|
||||
|
||||
if (test ("LAYER")) {
|
||||
|
||||
std::string l = get ();
|
||||
|
||||
// read the width for the layer
|
||||
while (! test ("END")) {
|
||||
if (test ("WIDTH")) {
|
||||
double w = get_double ();
|
||||
test (";");
|
||||
m_nondefault_widths[n][l] = w;
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test (l);
|
||||
|
||||
} else if (test ("VIA")) {
|
||||
|
||||
// ignore VIA statements
|
||||
std::string v = get ();
|
||||
while (! test ("END") || ! test (v)) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
read_nondefaultrule (layout);
|
||||
|
||||
} else if (test ("SITE")) {
|
||||
|
||||
|
|
@ -472,146 +1005,7 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
|
||||
} else if (test ("VIA")) {
|
||||
|
||||
std::string n = get ();
|
||||
|
||||
// produce a cell for vias
|
||||
std::string cellname = "VIA_" + n;
|
||||
db::Cell &cell = layout.cell (layout.add_cell (cellname.c_str ()));
|
||||
|
||||
ViaDesc &via_desc = m_vias[n];
|
||||
via_desc.cell = &cell;
|
||||
|
||||
while (test ("DEFAULT") || test ("TOPOFSTACKONLY"))
|
||||
;
|
||||
test (";");
|
||||
|
||||
if (test ("VIARULE")) {
|
||||
|
||||
db::Vector cutsize, cutspacing;
|
||||
db::Vector be, te;
|
||||
db::Vector bo, to;
|
||||
db::Point offset;
|
||||
int rows = 1, columns = 1;
|
||||
std::string pattern;
|
||||
|
||||
std::vector<std::pair<std::string, std::vector<db::Polygon> > > geometry;
|
||||
geometry.push_back (std::pair<std::string, std::vector<db::Polygon> > ());
|
||||
geometry.push_back (std::pair<std::string, std::vector<db::Polygon> > ());
|
||||
geometry.push_back (std::pair<std::string, std::vector<db::Polygon> > ());
|
||||
|
||||
while (! test ("END")) {
|
||||
|
||||
double x, y;
|
||||
|
||||
if (test ("CUTSIZE")) {
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
cutsize = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("CUTSPACING")) {
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
cutspacing = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("ORIGIN")) {
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
offset = db::Point (db::DPoint (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("ENCLOSURE")) {
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
be = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
te = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("OFFSET")) {
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
bo = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
x = get_double ();
|
||||
y = get_double ();
|
||||
to = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("ROWCOL")) {
|
||||
|
||||
rows = get_long ();
|
||||
columns = get_long ();
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("PATTERN")) {
|
||||
|
||||
pattern = get ();
|
||||
|
||||
test (";");
|
||||
|
||||
} else if (test ("LAYERS")) {
|
||||
|
||||
via_desc.m1 = geometry[0].first = get ();
|
||||
geometry[1].first = get ();
|
||||
via_desc.m2 = geometry[2].first = get ();
|
||||
|
||||
test (";");
|
||||
|
||||
} else {
|
||||
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
create_generated_via (geometry [0].second, geometry [1].second, geometry [2].second,
|
||||
cutsize, cutspacing, be, te, bo, to, offset, rows, columns, pattern);
|
||||
|
||||
for (std::vector<std::pair<std::string, std::vector<db::Polygon> > >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) {
|
||||
std::pair <bool, unsigned int> dl = open_layer (layout, g->first, ViaGeometry);
|
||||
if (dl.first) {
|
||||
for (std::vector<db::Polygon>::const_iterator p = g->second.begin (); p != g->second.end (); ++p) {
|
||||
cell.shapes (dl.second).insert (*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// ignore resistance spec
|
||||
if (test ("RESISTANCE")) {
|
||||
get_double ();
|
||||
test (";");
|
||||
}
|
||||
|
||||
read_geometries (layout, cell, ViaGeometry);
|
||||
|
||||
reset_cellname ();
|
||||
|
||||
expect ("END");
|
||||
|
||||
}
|
||||
|
||||
test ("VIA");
|
||||
expect (n);
|
||||
read_viadef (layout);
|
||||
|
||||
} else if (test ("BEGINEXT")) {
|
||||
|
||||
|
|
@ -622,148 +1016,11 @@ LEFImporter::do_read (db::Layout &layout)
|
|||
|
||||
} else if (test ("LAYER")) {
|
||||
|
||||
std::string ln = get ();
|
||||
|
||||
register_layer (ln);
|
||||
|
||||
// just extract the width from the layer - we need that as the default width for paths
|
||||
while (! at_end ()) {
|
||||
if (test ("END")) {
|
||||
expect (ln);
|
||||
break;
|
||||
} else if (test ("WIDTH")) {
|
||||
double w = get_double ();
|
||||
m_default_widths.insert (std::make_pair (ln, w));
|
||||
expect (";");
|
||||
} else if (test ("WIREEXTENSION")) {
|
||||
double w = get_double ();
|
||||
m_default_ext.insert (std::make_pair (ln, w));
|
||||
expect (";");
|
||||
} else if (test ("ACCURRENTDENSITY")) {
|
||||
// ACCURRENTDENSITY needs some special attention because it can contain nested WIDTH
|
||||
// blocks following a semicolon
|
||||
take ();
|
||||
if (test ("FREQUENCY")) {
|
||||
while (! test ("TABLEENTRIES")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
}
|
||||
read_layer (layout);
|
||||
|
||||
} else if (test ("MACRO")) {
|
||||
|
||||
std::string mn = get ();
|
||||
set_cellname (mn);
|
||||
|
||||
db::Cell &cell = layout.cell (layout.add_cell (mn.c_str ()));
|
||||
|
||||
m_macros_by_name.insert (std::make_pair (mn, &cell));
|
||||
|
||||
db::Point origin;
|
||||
db::Vector size;
|
||||
|
||||
// read the macro
|
||||
while (! at_end ()) {
|
||||
|
||||
if (test ("END")) {
|
||||
expect (mn);
|
||||
break;
|
||||
|
||||
} else if (test ("ORIGIN")) {
|
||||
|
||||
double x = get_double ();
|
||||
double y = get_double ();
|
||||
expect (";");
|
||||
origin = db::Point (db::DPoint (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
} else if (test ("SIZE")) {
|
||||
|
||||
double x = get_double ();
|
||||
test ("BY");
|
||||
double y = get_double ();
|
||||
expect (";");
|
||||
size = db::Vector (db::DVector (x / layout.dbu (), y / layout.dbu ()));
|
||||
|
||||
} else if (test ("PIN")) {
|
||||
|
||||
std::string pn = get ();
|
||||
std::string dir;
|
||||
|
||||
while (! at_end ()) {
|
||||
if (test ("END")) {
|
||||
break;
|
||||
} else if (test ("DIRECTION")) {
|
||||
dir = get ();
|
||||
test (";");
|
||||
} else if (test ("PORT")) {
|
||||
|
||||
// produce pin labels
|
||||
// TODO: put a label on every single object?
|
||||
std::string label = pn;
|
||||
/* don't add the direction currently, a name is sufficient
|
||||
if (! dir.empty ()) {
|
||||
label += ":";
|
||||
label += dir;
|
||||
}
|
||||
*/
|
||||
|
||||
db::properties_id_type prop_id = 0;
|
||||
if (produce_pin_props ()) {
|
||||
db::PropertiesRepository::properties_set props;
|
||||
props.insert (std::make_pair (pin_prop_name_id (), tl::Variant (label)));
|
||||
prop_id = layout.properties_repository ().properties_id (props);
|
||||
}
|
||||
|
||||
std::map <std::string, db::Box> bboxes;
|
||||
read_geometries (layout, cell, Pins, &bboxes, prop_id);
|
||||
|
||||
for (std::map <std::string, db::Box>::const_iterator b = bboxes.begin (); b != bboxes.end (); ++b) {
|
||||
std::pair <bool, unsigned int> dl = open_layer (layout, b->first, Label);
|
||||
if (dl.first) {
|
||||
cell.shapes (dl.second).insert (db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ())));
|
||||
}
|
||||
}
|
||||
|
||||
expect ("END");
|
||||
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect (pn);
|
||||
|
||||
} else if (test ("OBS")) {
|
||||
|
||||
read_geometries (layout, cell, Obstructions);
|
||||
expect ("END");
|
||||
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::pair <bool, unsigned int> dl = open_layer (layout, std::string (), Outline);
|
||||
if (dl.first) {
|
||||
cell.shapes (dl.second).insert (db::Box (-origin, -origin + size));
|
||||
}
|
||||
|
||||
m_macro_bboxes_by_name.insert (std::make_pair (mn, db::Box (-origin, -origin + size)));
|
||||
|
||||
reset_cellname ();
|
||||
read_macro (layout);
|
||||
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public:
|
|||
* Returns 0 if the name is not a valid macro name. Otherwise it returns the pointer
|
||||
* to the corresponding db::Cell object.
|
||||
*/
|
||||
db::Cell *macro_by_name (const std::string ¯o_name) const;
|
||||
std::pair<db::Cell *, db::Trans> macro_by_name (const std::string ¯o_name) const;
|
||||
|
||||
/**
|
||||
* @brief Get the cell bbox for the given macro name
|
||||
|
|
@ -77,7 +77,7 @@ public:
|
|||
* The nondefaultrule name gives the name of the nondefaultrule or an empty string if
|
||||
* none is requested.
|
||||
*/
|
||||
double layer_width (const std::string &layer, const std::string &nondefaultrule, double def_width = 0.0) const;
|
||||
std::pair<double, double> layer_width (const std::string &layer, const std::string &nondefaultrule, const std::pair<double, double> &def_width = std::make_pair (0.0, 0.0)) const;
|
||||
|
||||
/**
|
||||
* @brief Get the extension for a layer with the given name
|
||||
|
|
@ -86,6 +86,27 @@ public:
|
|||
*/
|
||||
double layer_ext (const std::string &layer, double def_ext = 0.0) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the minimum wire width in x and y direction for the given layer name
|
||||
*/
|
||||
std::pair<double, double> min_layer_width (const std::string &layer) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the given layer is a routing layer
|
||||
*/
|
||||
bool is_routing_layer (const std::string &layer) const
|
||||
{
|
||||
return m_routing_layers.find (layer) != m_routing_layers.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the given layer is a cut layer
|
||||
*/
|
||||
bool is_cut_layer (const std::string &layer) const
|
||||
{
|
||||
return m_cut_layers.find (layer) != m_cut_layers.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a map of the vias defined in this LEF file
|
||||
*
|
||||
|
|
@ -100,15 +121,23 @@ protected:
|
|||
void do_read (db::Layout &layout);
|
||||
|
||||
private:
|
||||
std::map<std::string, std::map<std::string, double> > m_nondefault_widths;
|
||||
std::map<std::string, double> m_default_widths;
|
||||
std::map<std::string, std::map<std::string, std::pair<double, double> > > m_nondefault_widths;
|
||||
std::map<std::string, std::pair<double, double> > m_default_widths;
|
||||
std::map<std::string, double> m_default_ext;
|
||||
std::map<std::string, db::Cell *> m_macros_by_name;
|
||||
std::map<std::string, std::pair<double, double> > m_min_widths;
|
||||
std::map<std::string, std::pair<db::Cell *, db::Trans> > m_macros_by_name;
|
||||
std::map<std::string, db::Box> m_macro_bboxes_by_name;
|
||||
std::map<std::string, ViaDesc> m_vias;
|
||||
std::set<std::string> m_routing_layers, m_cut_layers;
|
||||
|
||||
std::vector <db::Trans> get_iteration (db::Layout &layout);
|
||||
void read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes = 0, properties_id_type prop_id = 0);
|
||||
void read_nondefaultrule (Layout &layout);
|
||||
void read_viadef (Layout &layout);
|
||||
void read_viadef_by_rule (Layout &layout, db::Cell &cell, ViaDesc &desc, const std::string &n);
|
||||
void read_viadef_by_geometry (Layout &layout, db::Cell &cell, ViaDesc &desc, const std::string &n);
|
||||
void read_layer (Layout &layout);
|
||||
void read_macro (Layout &layout);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,6 +260,18 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
|
|||
"@brief Sets the via geometry layer datatype value.\n"
|
||||
"See \\produce_via_geometry for details about this property.\n"
|
||||
) +
|
||||
gsi::method ("via_cellname_prefix", &db::LEFDEFReaderOptions::via_cellname_prefix,
|
||||
"@brief Gets the via cellname prefix.\n"
|
||||
"Vias are represented by cells. The cell name is formed by combining the via cell name prefix and the via name.\n"
|
||||
"\n"
|
||||
"This property has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("via_cellname_prefix=", &db::LEFDEFReaderOptions::set_via_cellname_prefix, gsi::arg ("prefix"),
|
||||
"@brief Sets the via cellname prefix.\n"
|
||||
"See \\via_cellname_prefix for details about this property.\n"
|
||||
"\n"
|
||||
"This property has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("produce_pins", &db::LEFDEFReaderOptions::produce_pins,
|
||||
"@brief Gets a value indicating whether pin geometries shall be produced.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
|
|
@ -284,6 +296,30 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
|
|||
"@brief Sets the pin geometry layer datatype value.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
) +
|
||||
gsi::method ("produce_lef_pins", &db::LEFDEFReaderOptions::produce_lef_pins,
|
||||
"@brief Gets a value indicating whether LEF pin geometries shall be produced.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
) +
|
||||
gsi::method ("produce_lef_pins=", &db::LEFDEFReaderOptions::set_produce_lef_pins, gsi::arg ("produce"),
|
||||
"@brief Sets a value indicating whether LEF pin geometries shall be produced.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
) +
|
||||
gsi::method ("lef_pins_suffix", &db::LEFDEFReaderOptions::lef_pins_suffix,
|
||||
"@brief Gets the LEF pin geometry layer name suffix.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
) +
|
||||
gsi::method ("lef_pins_suffix=", &db::LEFDEFReaderOptions::set_lef_pins_suffix, gsi::arg ("suffix"),
|
||||
"@brief Sets the LEF pin geometry layer name suffix.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
) +
|
||||
gsi::method ("lef_pins_datatype", &db::LEFDEFReaderOptions::lef_pins_datatype,
|
||||
"@brief Gets the LEF pin geometry layer datatype value.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
) +
|
||||
gsi::method ("lef_pins_datatype=", &db::LEFDEFReaderOptions::set_lef_pins_datatype, gsi::arg ("datatype"),
|
||||
"@brief Sets the LEF pin geometry layer datatype value.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
) +
|
||||
gsi::method ("produce_obstructions", &db::LEFDEFReaderOptions::produce_obstructions,
|
||||
"@brief Gets a value indicating whether obstruction markers shall be produced.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
|
|
@ -380,6 +416,92 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
|
|||
"@brief Sets the routing layer datatype value.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
) +
|
||||
gsi::method ("produce_special_routing", &db::LEFDEFReaderOptions::produce_special_routing,
|
||||
"@brief Gets a value indicating whether special routing geometry shall be produced.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules.\n"
|
||||
"\n"
|
||||
"The differentiation between special and normal routing has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method ("produce_special_routing=", &db::LEFDEFReaderOptions::set_produce_special_routing, gsi::arg ("produce"),
|
||||
"@brief Sets a value indicating whether special routing geometry shall be produced.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
"\n"
|
||||
"The differentiation between special and normal routing has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method ("special_routing_suffix", &db::LEFDEFReaderOptions::special_routing_suffix,
|
||||
"@brief Gets the special routing layer name suffix.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
"\n"
|
||||
"The differentiation between special and normal routing has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method ("special_routing_suffix=", &db::LEFDEFReaderOptions::set_special_routing_suffix, gsi::arg ("suffix"),
|
||||
"@brief Sets the special routing layer name suffix.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
"\n"
|
||||
"The differentiation between special and normal routing has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method ("special_routing_datatype", &db::LEFDEFReaderOptions::special_routing_datatype,
|
||||
"@brief Gets the special routing layer datatype value.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
"\n"
|
||||
"The differentiation between special and normal routing has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method ("special_routing_datatype=", &db::LEFDEFReaderOptions::set_special_routing_datatype, gsi::arg ("datatype"),
|
||||
"@brief Sets the special routing layer datatype value.\n"
|
||||
"See \\produce_via_geometry for details about the layer production rules."
|
||||
"\n"
|
||||
"The differentiation between special and normal routing has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method ("separate_groups", &db::LEFDEFReaderOptions::separate_groups,
|
||||
"@brief Gets a value indicating whether to create separate parent cells for individual groups.\n"
|
||||
"If this property is set to true, instances belonging to different groups are separated by putting them into "
|
||||
"individual parent cells. These parent cells are named after the groups and are put into the master top cell.\n"
|
||||
"If this property is set to false (the default), no such group parents will be formed."
|
||||
"\n"
|
||||
"This property has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("separate_groups=", &db::LEFDEFReaderOptions::set_separate_groups, gsi::arg ("flag"),
|
||||
"@brief Sets a value indicating whether to create separate parent cells for individual groups.\n"
|
||||
"See \\seperate_groups for details about this property.\n"
|
||||
"\n"
|
||||
"This property has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("map_file", &db::LEFDEFReaderOptions::map_file,
|
||||
"@brief Gets the layer map file to use.\n"
|
||||
"If a layer map file is given, the reader will pull the layer mapping from this file. The layer mapping rules "
|
||||
"specified in the reader options are ignored in this case. These are the name suffix rules for vias, blockages, routing, "
|
||||
"special routing, pins etc. and the corresponding datatype rules. The \\layer_map attribute will also be ignored. "
|
||||
"\n"
|
||||
"The layer map file path will be resolved relative to the technology base path if the LEF/DEF reader options are "
|
||||
"used in the context of a technology.\n"
|
||||
"\n"
|
||||
"This property has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("map_file=", &db::LEFDEFReaderOptions::set_map_file, gsi::arg ("file"),
|
||||
"@brief Sets the layer map file to use.\n"
|
||||
"See \\map_file for details about this property.\n"
|
||||
"\n"
|
||||
"This property has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("macro_resolution_mode", &db::LEFDEFReaderOptions::macro_resolution_mode,
|
||||
"@brief Gets the macro resolution mode.\n"
|
||||
"This property describes the way LEF macros are turned into GDS cells. There "
|
||||
"are three modes available:\n"
|
||||
"\n"
|
||||
"@ul\n"
|
||||
" @li 0: propduce LEF geometry unless a FOREIGN cell is specified (default) @/li\n"
|
||||
" @li 1: produce LEF geometry always and ignore FOREIGN @/li\n"
|
||||
" @li 2: produce a placeholder cell always (even if FOREIGN isn't given) @/li\n"
|
||||
"@/ul\n"
|
||||
"\n"
|
||||
"This property has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("macro_resolution_mode=", &db::LEFDEFReaderOptions::set_macro_resolution_mode, gsi::arg ("mode"),
|
||||
"@brief Sets the macro resolution mode.\n"
|
||||
"See \\macro_resolution_mode for details about this property.\n"
|
||||
"\n"
|
||||
"This property has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("lef_files", &db::LEFDEFReaderOptions::lef_files,
|
||||
"@brief Gets the list technology LEF files to additionally import\n"
|
||||
"Returns a list of path names for technology LEF files to read in addition to the primary file. "
|
||||
|
|
@ -394,6 +516,21 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
|
|||
"@brief Detailed LEF/DEF reader options\n"
|
||||
"This class is a aggregate belonging to the \\LoadLayoutOptions class. It provides options for the LEF/DEF reader. "
|
||||
"These options have been placed into a separate class to account for their complexity."
|
||||
"\n"
|
||||
"This class specifically handles layer mapping. This is the process of generating layer names or GDS layer/datatypes "
|
||||
"from LEF/DEF layers and purpose combinations. There are basically two ways: to use a map file or to use pattern-based production rules.\n"
|
||||
"\n"
|
||||
"To use a layer map file, set the \\map_file attribute to the name of the layer map file. The layer map "
|
||||
"file lists the GDS layer and datatype numbers to generate for the geometry.\n"
|
||||
"\n"
|
||||
"The pattern-based approach will use the layer name and attach a purpose-dependent suffix to it. "
|
||||
"Use the ..._suffix attributes to specify this suffix. For routing, the corresponding attribute is \\routing_suffix for example. "
|
||||
"A purpose can also be mapped to a specific GDS datatype using the corresponding ..._datatype attributes.\n"
|
||||
"The decorated or undecorated names are looked up in a layer mapping table in the next step. The layer mapping table "
|
||||
"is specified using the \\layer_map attribute. This table can be used to map layer names to specific GDS layers "
|
||||
"by using entries of the form 'NAME: layer-number'.\n"
|
||||
"\n"
|
||||
"If a layer map file is present, the pattern-based attributes are ignored.\n"
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -140,8 +140,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
db::LEFDEFLayerDelegate layers (&options);
|
||||
layers.prepare (*layout);
|
||||
db::LEFDEFReaderState state (&options, *layout);
|
||||
layout->dbu (options.dbu ());
|
||||
|
||||
if (import_lef) {
|
||||
|
|
@ -153,11 +152,11 @@ public:
|
|||
for (std::vector<std::string>::const_iterator l = options.begin_lef_files (); l != options.end_lef_files (); ++l) {
|
||||
tl::InputStream lef_stream (*l);
|
||||
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l;
|
||||
importer.read (lef_stream, *layout, layers);
|
||||
importer.read (lef_stream, *layout, state);
|
||||
}
|
||||
|
||||
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << data.file;
|
||||
importer.read (stream, *layout, layers);
|
||||
importer.read (stream, *layout, state);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -177,23 +176,23 @@ public:
|
|||
if (fi.isAbsolute ()) {
|
||||
tl::InputStream lef_stream (*l);
|
||||
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l;
|
||||
importer.read_lef (lef_stream, *layout, layers);
|
||||
importer.read_lef (lef_stream, *layout, state);
|
||||
} else {
|
||||
std::string ex_l = tl::to_string (def_fi.absoluteDir ().absoluteFilePath (tl::to_qstring (*l)));
|
||||
tl::InputStream lef_stream (ex_l);
|
||||
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << *l;
|
||||
importer.read_lef (lef_stream, *layout, layers);
|
||||
importer.read_lef (lef_stream, *layout, state);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tl::log << tl::to_string (QObject::tr ("Reading")) << " " << data.file;
|
||||
|
||||
importer.read (stream, *layout, layers);
|
||||
importer.read (stream, *layout, state);
|
||||
|
||||
}
|
||||
|
||||
layers.finish (*layout);
|
||||
state.finish (*layout);
|
||||
|
||||
lay::LayoutView *view = lay::LayoutView::current ();
|
||||
if (! view || data.mode == 1) {
|
||||
|
|
|
|||
|
|
@ -353,14 +353,17 @@ LEFDEFReaderOptionsEditor::LEFDEFReaderOptionsEditor (QWidget *parent)
|
|||
connect (produce_regions, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
|
||||
connect (produce_via_geometry, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
|
||||
connect (produce_pins, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
|
||||
connect (produce_lef_pins, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
|
||||
connect (produce_obstructions, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
|
||||
connect (produce_blockages, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
|
||||
connect (produce_routing, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
|
||||
connect (produce_special_routing, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
|
||||
connect (produce_labels, SIGNAL (stateChanged (int)), this, SLOT (checkbox_changed ()));
|
||||
connect (add_lef_file, SIGNAL (clicked ()), this, SLOT (add_lef_file_clicked ()));
|
||||
connect (del_lef_files, SIGNAL (clicked ()), this, SLOT (del_lef_files_clicked ()));
|
||||
connect (move_lef_files_up, SIGNAL (clicked ()), this, SLOT (move_lef_files_up_clicked ()));
|
||||
connect (move_lef_files_down, SIGNAL (clicked ()), this, SLOT (move_lef_files_down_clicked ()));
|
||||
connect (browse_mapfile, SIGNAL (clicked ()), this, SLOT (browse_mapfile_clicked ()));
|
||||
|
||||
lay::activate_help_links (help_label);
|
||||
}
|
||||
|
|
@ -425,9 +428,13 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con
|
|||
data->set_produce_via_geometry (produce_via_geometry->isChecked ());
|
||||
data->set_via_geometry_suffix (tl::to_string (suffix_via_geometry->text ()));
|
||||
data->set_via_geometry_datatype (datatype_via_geometry->text ().toInt ());
|
||||
data->set_via_cellname_prefix (tl::to_string (prefix_via_cellname->text ()));
|
||||
data->set_produce_pins (produce_pins->isChecked ());
|
||||
data->set_pins_suffix (tl::to_string (suffix_pins->text ()));
|
||||
data->set_pins_datatype (datatype_pins->text ().toInt ());
|
||||
data->set_produce_lef_pins (produce_lef_pins->isChecked ());
|
||||
data->set_lef_pins_suffix (tl::to_string (suffix_lef_pins->text ()));
|
||||
data->set_lef_pins_datatype (datatype_lef_pins->text ().toInt ());
|
||||
data->set_produce_obstructions (produce_obstructions->isChecked ());
|
||||
data->set_obstructions_suffix (tl::to_string (suffix_obstructions->text ()));
|
||||
data->set_obstructions_datatype (datatype_obstructions->text ().toInt ());
|
||||
|
|
@ -437,9 +444,15 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con
|
|||
data->set_produce_routing (produce_routing->isChecked ());
|
||||
data->set_routing_suffix (tl::to_string (suffix_routing->text ()));
|
||||
data->set_routing_datatype (datatype_routing->text ().toInt ());
|
||||
data->set_produce_special_routing (produce_special_routing->isChecked ());
|
||||
data->set_special_routing_suffix (tl::to_string (suffix_special_routing->text ()));
|
||||
data->set_special_routing_datatype (datatype_special_routing->text ().toInt ());
|
||||
data->set_produce_labels (produce_labels->isChecked ());
|
||||
data->set_labels_suffix (tl::to_string (suffix_labels->text ()));
|
||||
data->set_labels_datatype (datatype_labels->text ().toInt ());
|
||||
data->set_separate_groups (separate_groups->isChecked ());
|
||||
data->set_map_file (tl::to_string (mapfile_path->text ()));
|
||||
data->set_macro_resolution_mode (foreign_mode->currentIndex ());
|
||||
|
||||
data->clear_lef_files ();
|
||||
for (int i = 0; i < lef_files->count (); ++i) {
|
||||
|
|
@ -477,9 +490,13 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options
|
|||
produce_via_geometry->setChecked (data->produce_via_geometry ());
|
||||
suffix_via_geometry->setText (tl::to_qstring (data->via_geometry_suffix ()));
|
||||
datatype_via_geometry->setText (QString::number (data->via_geometry_datatype ()));
|
||||
prefix_via_cellname->setText (tl::to_qstring (data->via_cellname_prefix ()));
|
||||
produce_pins->setChecked (data->produce_pins ());
|
||||
suffix_pins->setText (tl::to_qstring (data->pins_suffix ()));
|
||||
datatype_pins->setText (QString::number (data->pins_datatype ()));
|
||||
produce_lef_pins->setChecked (data->produce_lef_pins ());
|
||||
suffix_lef_pins->setText (tl::to_qstring (data->lef_pins_suffix ()));
|
||||
datatype_lef_pins->setText (QString::number (data->lef_pins_datatype ()));
|
||||
produce_obstructions->setChecked (data->produce_obstructions ());
|
||||
suffix_obstructions->setText (tl::to_qstring (data->obstructions_suffix ()));
|
||||
datatype_obstructions->setText (QString::number (data->obstructions_datatype ()));
|
||||
|
|
@ -489,9 +506,16 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options
|
|||
produce_routing->setChecked (data->produce_routing ());
|
||||
suffix_routing->setText (tl::to_qstring (data->routing_suffix ()));
|
||||
datatype_routing->setText (QString::number (data->routing_datatype ()));
|
||||
produce_special_routing->setChecked (data->produce_special_routing ());
|
||||
suffix_special_routing->setText (tl::to_qstring (data->special_routing_suffix ()));
|
||||
datatype_special_routing->setText (QString::number (data->special_routing_datatype ()));
|
||||
produce_labels->setChecked (data->produce_labels ());
|
||||
suffix_labels->setText (tl::to_qstring (data->labels_suffix ()));
|
||||
datatype_labels->setText (QString::number (data->labels_datatype ()));
|
||||
separate_groups->setChecked (data->separate_groups ());
|
||||
mapfile_path->setText (tl::to_qstring (data->map_file ()));
|
||||
layer_map_mode->setCurrentIndex (data->map_file ().empty () ? 1 : 0);
|
||||
foreign_mode->setCurrentIndex (data->macro_resolution_mode ());
|
||||
|
||||
checkbox_changed ();
|
||||
|
||||
|
|
@ -519,25 +543,51 @@ LEFDEFReaderOptionsEditor::checkbox_changed ()
|
|||
placement_blockage_layer->setEnabled (produce_placement_blockages->isChecked ());
|
||||
suffix_via_geometry->setEnabled (produce_via_geometry->isChecked ());
|
||||
suffix_pins->setEnabled (produce_pins->isChecked ());
|
||||
suffix_lef_pins->setEnabled (produce_lef_pins->isChecked ());
|
||||
suffix_obstructions->setEnabled (produce_obstructions->isChecked ());
|
||||
suffix_blockages->setEnabled (produce_blockages->isChecked ());
|
||||
suffix_routing->setEnabled (produce_routing->isChecked ());
|
||||
suffix_special_routing->setEnabled (produce_special_routing->isChecked ());
|
||||
suffix_labels->setEnabled (produce_labels->isChecked ());
|
||||
datatype_via_geometry->setEnabled (produce_via_geometry->isChecked ());
|
||||
datatype_pins->setEnabled (produce_pins->isChecked ());
|
||||
datatype_lef_pins->setEnabled (produce_lef_pins->isChecked ());
|
||||
datatype_obstructions->setEnabled (produce_obstructions->isChecked ());
|
||||
datatype_blockages->setEnabled (produce_blockages->isChecked ());
|
||||
datatype_routing->setEnabled (produce_routing->isChecked ());
|
||||
datatype_special_routing->setEnabled (produce_special_routing->isChecked ());
|
||||
datatype_labels->setEnabled (produce_labels->isChecked ());
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderOptionsEditor::browse_mapfile_clicked ()
|
||||
{
|
||||
std::string title, filters;
|
||||
title = tl::to_string (QObject::tr ("Select Layer Map File"));
|
||||
filters = tl::to_string (QObject::tr ("LEF/DEF layer map files (*.map);;All files (*)"));
|
||||
QString file = QFileDialog::getOpenFileName (this, tl::to_qstring (title), QString (), tl::to_qstring (filters));
|
||||
if (! file.isNull ()) {
|
||||
if (mp_tech) {
|
||||
mapfile_path->setText (tl::to_qstring (mp_tech->correct_path (tl::to_string (file))));
|
||||
} else {
|
||||
mapfile_path->setText (file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LEFDEFReaderOptionsEditor::add_lef_file_clicked ()
|
||||
{
|
||||
std::string title, filters;
|
||||
title = tl::to_string (QObject::tr ("Add LEF Files"));
|
||||
filters = tl::to_string (QObject::tr ("LEF files (*.lef *.LEF *.lef.gz *.LEF.gz);;All files (*)"));
|
||||
QStringList files = QFileDialog::getOpenFileNames (this, tl::to_qstring (title), QString (), tl::to_qstring (filters));
|
||||
|
||||
std::string dir;
|
||||
if (mp_tech) {
|
||||
dir = mp_tech->base_path ();
|
||||
}
|
||||
|
||||
QStringList files = QFileDialog::getOpenFileNames (this, tl::to_qstring (title), tl::to_qstring (dir), tl::to_qstring (filters));
|
||||
for (QStringList::const_iterator f = files.begin (); f != files.end (); ++f) {
|
||||
if (mp_tech) {
|
||||
lef_files->addItem (tl::to_qstring (mp_tech->correct_path (tl::to_string (*f))));
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ private slots:
|
|||
void del_lef_files_clicked ();
|
||||
void move_lef_files_up_clicked ();
|
||||
void move_lef_files_down_clicked ();
|
||||
void browse_mapfile_clicked ();
|
||||
|
||||
private:
|
||||
tl::weak_ptr<db::Technology> mp_tech;
|
||||
|
|
|
|||
|
|
@ -49,28 +49,35 @@ static db::LEFDEFReaderOptions default_options ()
|
|||
return tc;
|
||||
}
|
||||
|
||||
static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &tc, bool priv = true)
|
||||
static void run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true)
|
||||
{
|
||||
db::LEFDEFLayerDelegate ld (&tc);
|
||||
std::string fn_path (priv ? tl::testsrc_private () : tl::testsrc ());
|
||||
fn_path += "/testdata/lefdef/";
|
||||
fn_path += lef_dir;
|
||||
fn_path += "/";
|
||||
|
||||
db::Manager m (false);
|
||||
db::Layout layout (&m), layout2 (&m), layout_au (&m);
|
||||
|
||||
tl::Extractor ex (filename);
|
||||
|
||||
ld.prepare (layout);
|
||||
db::LEFDEFReaderState ld (&options, layout);
|
||||
|
||||
db::DEFImporter imp;
|
||||
|
||||
while (! ex.at_end ()) {
|
||||
|
||||
if (ex.test ("def:")) {
|
||||
if (ex.test ("map:")) {
|
||||
|
||||
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
|
||||
fn += "/testdata/lefdef/";
|
||||
fn += lef_dir;
|
||||
fn += "/";
|
||||
std::string f;
|
||||
std::string fn = fn_path, f;
|
||||
ex.read_word_or_quoted (f);
|
||||
fn += f;
|
||||
|
||||
ld.read_map_file (fn, layout);
|
||||
|
||||
} else if (ex.test ("def:")) {
|
||||
|
||||
std::string fn = fn_path, f;
|
||||
ex.read_word_or_quoted (f);
|
||||
fn += f;
|
||||
|
||||
|
|
@ -79,17 +86,35 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file
|
|||
|
||||
} else if (ex.test ("lef:")) {
|
||||
|
||||
std::string fn (priv ? tl::testsrc_private () : tl::testsrc ());
|
||||
fn += "/testdata/lefdef/";
|
||||
fn += lef_dir;
|
||||
fn += "/";
|
||||
std::string f;
|
||||
std::string fn = fn_path, f;
|
||||
ex.read_word_or_quoted (f);
|
||||
fn += f;
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
imp.read_lef (stream, layout, ld);
|
||||
|
||||
} else if (ex.test ("gds:")) {
|
||||
|
||||
std::string fn = fn_path, f;
|
||||
ex.read_word_or_quoted (f);
|
||||
fn += f;
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout, db::LoadLayoutOptions ());
|
||||
|
||||
} else if (ex.test("read:")) {
|
||||
|
||||
std::string fn = fn_path, f;
|
||||
ex.read_word_or_quoted (f);
|
||||
fn += f;
|
||||
|
||||
tl::InputStream stream (fn);
|
||||
db::Reader reader (stream);
|
||||
db::LoadLayoutOptions lo;
|
||||
lo.set_options (options);
|
||||
reader.read (layout, lo);
|
||||
|
||||
} else {
|
||||
|
||||
break;
|
||||
|
|
@ -112,6 +137,7 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file
|
|||
tl::OutputStream stream (tmp_file);
|
||||
db::SaveLayoutOptions options;
|
||||
options.set_format ("OASIS");
|
||||
options.set_option_by_name ("oasis_permissive", tl::Variant (true));
|
||||
db::Writer writer (options);
|
||||
writer.write (layout, stream);
|
||||
}
|
||||
|
|
@ -222,6 +248,7 @@ TEST(15)
|
|||
TEST(16)
|
||||
{
|
||||
run_test (_this, "def7", "lef:cells.lef+lef:tech.lef+def:in.def.gz", "au.oas.gz", default_options ());
|
||||
run_test (_this, "def7", "map:in.map+lef:cells.lef+lef:tech.lef+def:in.def.gz", "au_with_map_file.oas.gz", default_options ());
|
||||
}
|
||||
|
||||
TEST(17)
|
||||
|
|
@ -231,7 +258,11 @@ TEST(17)
|
|||
|
||||
TEST(18)
|
||||
{
|
||||
run_test (_this, "def9", "lef:tech.lef+lef:cells_modified.lef+def:in.def", "au.oas.gz", default_options ());
|
||||
db::LEFDEFReaderOptions options = default_options ();
|
||||
options.set_separate_groups (true);
|
||||
run_test (_this, "def9", "lef:tech.lef+lef:cells_modified.lef+def:in.def", "au.oas.gz", options);
|
||||
|
||||
run_test (_this, "def9", "lef:tech.lef+lef:cells_modified.lef+def:in.def", "au_nogroups.oas.gz", default_options ());
|
||||
}
|
||||
|
||||
TEST(19)
|
||||
|
|
@ -241,10 +272,20 @@ TEST(19)
|
|||
|
||||
TEST(20)
|
||||
{
|
||||
run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false);
|
||||
run_test (_this, "def11", "lef:test.lef+def:test.def", "au.oas.gz", default_options ());
|
||||
}
|
||||
|
||||
TEST(21)
|
||||
{
|
||||
run_test (_this, "def12", "lef:test.lef+def:test.def", "au.oas.gz", default_options ());
|
||||
}
|
||||
|
||||
TEST(100)
|
||||
{
|
||||
run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
||||
TEST(101)
|
||||
{
|
||||
db::LEFDEFReaderOptions opt = default_options ();
|
||||
opt.set_produce_pin_names (true);
|
||||
|
|
@ -252,7 +293,7 @@ TEST(21)
|
|||
run_test (_this, "issue-489", "lef:in.lef+def:in.def", "au.oas", opt, false);
|
||||
}
|
||||
|
||||
TEST(22)
|
||||
TEST(102)
|
||||
{
|
||||
db::LEFDEFReaderOptions opt = default_options ();
|
||||
opt.set_produce_pin_names (true);
|
||||
|
|
@ -260,8 +301,83 @@ TEST(22)
|
|||
run_test (_this, "issue-489b", "lef:in_tech.lef+lef:in.lef", "au.oas.gz", opt, false);
|
||||
}
|
||||
|
||||
TEST(23)
|
||||
TEST(103)
|
||||
{
|
||||
run_test (_this, "issue-517", "def:in.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
||||
TEST(104_doxy_vias)
|
||||
{
|
||||
run_test (_this, "doxy_vias", "def:test.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
||||
TEST(105_specialnets_geo)
|
||||
{
|
||||
run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
|
||||
|
||||
db::LEFDEFReaderOptions options = default_options ();
|
||||
options.set_produce_special_routing (false);
|
||||
run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au_no_spnet.oas.gz", options, false);
|
||||
|
||||
options.set_produce_special_routing (true);
|
||||
options.set_special_routing_datatype (10);
|
||||
options.set_special_routing_suffix (".SPNET");
|
||||
|
||||
options.set_via_geometry_datatype (11);
|
||||
options.set_via_geometry_suffix (".VIA");
|
||||
|
||||
run_test (_this, "specialnets_geo", "lef:test.lef+def:test.def", "au_spnet_mapped.oas.gz", options, false);
|
||||
}
|
||||
|
||||
TEST(106_wrongdirection)
|
||||
{
|
||||
run_test (_this, "wrongdirection", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
||||
TEST(107_specialwidths)
|
||||
{
|
||||
run_test (_this, "specialwidths", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
||||
TEST(108_scanchain)
|
||||
{
|
||||
run_test (_this, "scanchain", "def:test.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
||||
TEST(109_foreigncell)
|
||||
{
|
||||
run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef+def:in.def", "au.oas.gz", default_options (), false);
|
||||
|
||||
db::LEFDEFReaderOptions options = default_options ();
|
||||
|
||||
run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in2.lef+def:in.def", "au_default.oas.gz", options, false);
|
||||
|
||||
options.set_macro_resolution_mode (1);
|
||||
|
||||
run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in2.lef+def:in.def", "au_ignore_foreign.oas.gz", options, false);
|
||||
|
||||
options.set_macro_resolution_mode (2);
|
||||
|
||||
run_test (_this, "foreigncell", "gds:foreign.gds+lef:in_tech.lef+lef:in.lef+def:in.def", "au_always_foreign.oas.gz", options, false);
|
||||
}
|
||||
|
||||
TEST(110_lefpins)
|
||||
{
|
||||
db::LEFDEFReaderOptions options = default_options ();
|
||||
options.set_produce_lef_pins (false);
|
||||
run_test (_this, "lefpins", "lef:in_tech.lef+lef:in.lef+def:in.def", "au_no_lefpins.oas.gz", options, false);
|
||||
|
||||
options.set_produce_lef_pins (true);
|
||||
options.set_lef_pins_datatype (10);
|
||||
options.set_lef_pins_suffix (".LEFPIN");
|
||||
|
||||
run_test (_this, "lefpins", "lef:in_tech.lef+lef:in.lef+def:in.def", "au_lefpins_mapped.oas.gz", options, false);
|
||||
}
|
||||
|
||||
TEST(111_mapfile)
|
||||
{
|
||||
db::LEFDEFReaderOptions options = default_options ();
|
||||
options.set_map_file ("test.map");
|
||||
|
||||
run_test (_this, "mapfile", "read:in.def", "au.oas.gz", options, false);
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ TARGET = lefdef_tests
|
|||
include($$PWD/../../../../lib_ut.pri)
|
||||
|
||||
SOURCES = \
|
||||
dbLEFDEFImport.cc
|
||||
dbLEFDEFImportTests.cc
|
||||
|
||||
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
||||
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ MAGReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
|
|||
m_tech.clear ();
|
||||
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, "Reading MAGIC file tree");
|
||||
tl::SelfTimer timer (tl::verbosity () >= 11, "Reading MAGIC file tree");
|
||||
|
||||
// This is the seed
|
||||
do_read (layout, top_cell, m_stream);
|
||||
|
|
|
|||
|
|
@ -689,8 +689,6 @@ static const char magic_bytes[] = { "%SEMI-OASIS\015\012" };
|
|||
void
|
||||
OASISReader::do_read (db::Layout &layout)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + m_stream.source ());
|
||||
|
||||
unsigned char r;
|
||||
char *mb;
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
VERSION 5.8 ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DESIGN chip_top ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
DIEAREA ( 30000 3000 ) ( 10000000 4000 ) ;
|
||||
VIAS 1 ;
|
||||
- VIA1_dummy
|
||||
+ RECT M1 ( -200 -140 ) ( 200 140 )
|
||||
+ RECT VIA1 ( -100 -100 ) ( 100 100 )
|
||||
+ RECT M2 ( -300 -120 ) ( 300 120 ) ;
|
||||
END VIAS
|
||||
SPECIALNETS 1 ;
|
||||
- dummy
|
||||
+ ROUTED M1 150 + SHAPE IOWIRE ( 40000 3600 ) VIA1_dummy DO 16000 BY 1 STEP 700 0
|
||||
;
|
||||
END SPECIALNETS
|
||||
SCANCHAINS 77 ;
|
||||
- chain1_clock1
|
||||
+ PARTITION clock1
|
||||
+ START block1/bsr_reg_0 Q
|
||||
+ FLOATING
|
||||
block1/pgm_cgm_en_reg_reg ( IN SD ) ( OUT QZ )
|
||||
block1/start_reset_dd_reg ( IN SD ) ( OUT QZ )
|
||||
+ STOP block1/start_reset_d_reg SD ;
|
||||
END SCANCHAINS
|
||||
END DESIGN
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
VERSION 5.8 ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DESIGN foreigncells ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
|
||||
DIEAREA ( 0 0 ) ( 1000 2000 ) ;
|
||||
|
||||
COMPONENTS 3 ;
|
||||
- macro1 macro1 + PLACED ( 0 0 ) N ;
|
||||
- macro2 macro2 + PLACED ( 0 500 ) E ;
|
||||
- macro3 macro3 + PLACED ( 0 1000 ) N ;
|
||||
END COMPONENTS
|
||||
|
||||
END DESIGN
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
MACRO macro1
|
||||
CLASS CORE ;
|
||||
FOREIGN foreign1 0.13 0.5 W ;
|
||||
ORIGIN 0.035 0.235 ;
|
||||
SIZE 0.07 BY 0.47 ;
|
||||
END macro1
|
||||
|
||||
MACRO macro2
|
||||
CLASS CORE ;
|
||||
FOREIGN foreign2 -0.15 0.25 ;
|
||||
ORIGIN 0.235 0.035 ;
|
||||
SIZE 0.47 BY 0.07 ;
|
||||
END macro2
|
||||
|
||||
MACRO macro3
|
||||
CLASS CORE ;
|
||||
FOREIGN macro3 -1.0 1.0 ;
|
||||
ORIGIN 0.0 0.0 ;
|
||||
SIZE 1.0 BY 0.4 ;
|
||||
END macro3
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
MACRO macro1
|
||||
CLASS CORE ;
|
||||
ORIGIN 0.035 0.235 ;
|
||||
SIZE 0.07 BY 0.47 ;
|
||||
PIN Z
|
||||
PORT
|
||||
LAYER M1 ;
|
||||
RECT -0.02 0 0.02 0.2 ;
|
||||
RECT -0.03 -0.2 0.01 -0.1 ;
|
||||
VIA 0.0 0.2 square ;
|
||||
VIA 0.01 -0.2 square ;
|
||||
END
|
||||
END Z
|
||||
END macro1
|
||||
|
||||
MACRO macro2
|
||||
CLASS CORE ;
|
||||
FOREIGN foreign2 -0.15 0.25 ;
|
||||
ORIGIN 0.235 0.035 ;
|
||||
SIZE 0.47 BY 0.07 ;
|
||||
PIN Z
|
||||
PORT
|
||||
LAYER M1 ;
|
||||
RECT 0 -0.02 -0.2 0.02 ;
|
||||
RECT 0.2 -0.03 0.1 0.01 ;
|
||||
VIA -0.2 0.0 square ;
|
||||
VIA 0.2 0.01 square ;
|
||||
END
|
||||
END Z
|
||||
END macro2
|
||||
|
||||
MACRO macro3
|
||||
CLASS CORE ;
|
||||
FOREIGN macro3 -1.0 1.0 ;
|
||||
ORIGIN 0.0 0.0 ;
|
||||
SIZE 1.0 BY 1.0 ;
|
||||
PIN Z
|
||||
PORT
|
||||
LAYER M1 ;
|
||||
RECT 0.2 0.2 0.3 0.5 ;
|
||||
END
|
||||
END Z
|
||||
END macro3
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
LAYER OD
|
||||
TYPE IMPLANT ;
|
||||
END OD
|
||||
LAYER VTS_N
|
||||
TYPE IMPLANT ;
|
||||
END VTS_N
|
||||
LAYER VTS_P
|
||||
TYPE IMPLANT ;
|
||||
END VTS_P
|
||||
LAYER M0OD
|
||||
TYPE IMPLANT ;
|
||||
END M0OD
|
||||
LAYER M0PO
|
||||
TYPE MASTERSLICE ;
|
||||
END M0PO
|
||||
LAYER VIA0
|
||||
TYPE CUT ;
|
||||
END VIA0
|
||||
LAYER M1
|
||||
TYPE MASTERSLICE ;
|
||||
END M1
|
||||
LAYER VIA1
|
||||
TYPE CUT ;
|
||||
END VIA1
|
||||
LAYER M2
|
||||
TYPE MASTERSLICE ;
|
||||
END M2
|
||||
|
||||
VIA square
|
||||
LAYER M0PO ;
|
||||
RECT -0.006 -0.006 0.006 0.006 ;
|
||||
LAYER VIA0 ;
|
||||
RECT -0.006 -0.006 0.006 0.006 ;
|
||||
LAYER M1 ;
|
||||
RECT -0.006 -0.006 0.006 0.006 ;
|
||||
END square
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
MACRO dummy
|
||||
CLASS CORE ;
|
||||
FOREIGN dummy 0.000 0.000 ;
|
||||
ORIGIN 0.000 0.000 ;
|
||||
SIZE 0.384 BY 0.480 ;
|
||||
SYMMETRY X Y ;
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
VERSION 5.8 ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DESIGN foreigncells ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
|
||||
DIEAREA ( 0 0 ) ( 1000 2000 ) ;
|
||||
|
||||
COMPONENTS 3 ;
|
||||
- macro1 macro1 + PLACED ( 0 0 ) N ;
|
||||
END COMPONENTS
|
||||
|
||||
END DESIGN
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
MACRO macro1
|
||||
CLASS CORE ;
|
||||
ORIGIN 0.000 0.000 ;
|
||||
SIZE 0.384 BY 0.480 ;
|
||||
PIN Z
|
||||
PORT
|
||||
LAYER M1 ;
|
||||
RECT 0.306 0.357 0.318 0.403 ;
|
||||
RECT 0.318 0.115 0.352 0.403 ;
|
||||
VIA 0.336 0.167 square ;
|
||||
VIA 0.336 0.351 square ;
|
||||
END
|
||||
END Z
|
||||
END macro1
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
LAYER OD
|
||||
TYPE IMPLANT ;
|
||||
END OD
|
||||
LAYER VTS_N
|
||||
TYPE IMPLANT ;
|
||||
END VTS_N
|
||||
LAYER VTS_P
|
||||
TYPE IMPLANT ;
|
||||
END VTS_P
|
||||
LAYER M0OD
|
||||
TYPE IMPLANT ;
|
||||
END M0OD
|
||||
LAYER M0PO
|
||||
TYPE MASTERSLICE ;
|
||||
END M0PO
|
||||
LAYER VIA0
|
||||
TYPE CUT ;
|
||||
END VIA0
|
||||
LAYER M1
|
||||
TYPE MASTERSLICE ;
|
||||
END M1
|
||||
LAYER VIA1
|
||||
TYPE CUT ;
|
||||
END VIA1
|
||||
LAYER M2
|
||||
TYPE MASTERSLICE ;
|
||||
END M2
|
||||
|
||||
VIA square
|
||||
LAYER M0PO ;
|
||||
RECT -0.006 -0.006 0.006 0.006 ;
|
||||
LAYER VIA0 ;
|
||||
RECT -0.006 -0.006 0.006 0.006 ;
|
||||
LAYER M1 ;
|
||||
RECT -0.006 -0.006 0.006 0.006 ;
|
||||
END square
|
||||
Binary file not shown.
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
VERSION 5.8 ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DESIGN mapfile ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
|
||||
DIEAREA ( 0 0 ) ( 1000 2000 ) ;
|
||||
|
||||
COMPONENTS 3 ;
|
||||
- macro1 macro1 + PLACED ( 0 0 ) N ;
|
||||
END COMPONENTS
|
||||
|
||||
SPECIALNETS 1 ;
|
||||
- VDD ( * VDD )
|
||||
+ ROUTED M1 50 + SHAPE STRIPE ( 500 0 ) ( 500 500 25 ) square ( 0 500 )
|
||||
+ USE POWER ;
|
||||
END SPECIALNETS
|
||||
|
||||
PINS 1 ;
|
||||
- VDD + NET VDD + SPECIAL + DIRECTION INOUT + USE POWER
|
||||
+ LAYER M1 ( 0 0 ) ( 50 70 )
|
||||
;
|
||||
END PINS
|
||||
|
||||
NETS 1 ;
|
||||
- TOP
|
||||
+ ROUTED M1 ( 100 700 ) ( 500 * ) ;
|
||||
END NETS
|
||||
|
||||
END DESIGN
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
MACRO macro1
|
||||
CLASS CORE ;
|
||||
ORIGIN 0.035 0.235 ;
|
||||
SIZE 0.07 BY 0.47 ;
|
||||
PIN Z
|
||||
PORT
|
||||
LAYER M1 ;
|
||||
RECT -0.02 0 0.02 0.2 ;
|
||||
RECT -0.03 -0.2 0.01 -0.1 ;
|
||||
VIA 0.0 0.2 square ;
|
||||
VIA 0.01 -0.2 square ;
|
||||
END
|
||||
END Z
|
||||
OBS
|
||||
LAYER M1 ;
|
||||
RECT -0.035 -0.235 0.035 0.235 ;
|
||||
END
|
||||
END macro1
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
LAYER M0PO
|
||||
TYPE MASTERSLICE ;
|
||||
WIDTH 0.02 ;
|
||||
END M0PO
|
||||
LAYER VIA0
|
||||
TYPE CUT ;
|
||||
END VIA0
|
||||
LAYER M1
|
||||
TYPE MASTERSLICE ;
|
||||
WIDTH 0.025 ;
|
||||
END M1
|
||||
LAYER VIA1
|
||||
TYPE CUT ;
|
||||
END VIA1
|
||||
LAYER M2
|
||||
TYPE MASTERSLICE ;
|
||||
WIDTH 0.03 ;
|
||||
END M2
|
||||
|
||||
VIA square
|
||||
LAYER M0PO ;
|
||||
RECT -0.006 -0.006 0.006 0.006 ;
|
||||
LAYER VIA0 ;
|
||||
RECT -0.006 -0.006 0.006 0.006 ;
|
||||
LAYER M1 ;
|
||||
RECT -0.006 -0.006 0.006 0.006 ;
|
||||
END square
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
DIEAREA ALL 100 0
|
||||
M0PO LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 10 0
|
||||
VIA0 LEFPIN,LEFOBS,VIA,PIN,NET,SPNET 11 0
|
||||
M1 LEFPIN 12 0
|
||||
M1 LEFOBS 12 1
|
||||
M1 PIN 12 2
|
||||
M1 NET 12 3
|
||||
M1 SPNET 12 4
|
||||
M1 VIA 12 5
|
||||
M1 FILLOPC 12 100
|
||||
M1 FILLOPC:MASK:1 12 101
|
||||
M1 FILLOPC:MASK:2 12 102
|
||||
M1 BLOCKAGEFILL 12 150
|
||||
M1 BLOCKAGE 12 151
|
||||
M1 FILL 12 152
|
||||
NAME M1/PIN 12 10
|
||||
VIA1 LEFPIN,LEFOBS,VIA,PIN,NET,SPNET 13 0
|
||||
M2 LEFPIN,LEFOBS,PIN,NET,SPNET,VIA 14 0
|
||||
Binary file not shown.
|
|
@ -0,0 +1,32 @@
|
|||
VERSION 5.8 ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DESIGN chip_top ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
DIEAREA ( 0 0 ) ( 8729280 8199360 ) ;
|
||||
SCANCHAINS 9992 ;
|
||||
- chain1
|
||||
+ PARTITION part/Y_45_45_0.720000
|
||||
+ START whereever/anchor_buf_8 Y
|
||||
+ FLOATING
|
||||
dumdidum/_reg_1_reg_2_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_2_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_7_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_8_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_5_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_9_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_6_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_4_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_7_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_1_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_3_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_1_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_0_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_4_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_0_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_6_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_3_ ( IN SI ) ( OUT Q )
|
||||
dumdidum/_reg_1_reg_5_ ( IN SI ) ( OUT Q )
|
||||
+ STOP somewhere/LOCKUP D ;
|
||||
END SCANCHAINS
|
||||
END DESIGN
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
VERSION 5.8 ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DESIGN chip_top ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
DIEAREA ( 0 0 ) ( 300 300 ) ;
|
||||
STYLES 2 ;
|
||||
- STYLE 1 ( 30 10 ) ( 10 30 ) ( -10 30 ) ( -30 10 ) ( -30 -10 ) ( -10 -30 ) ( 10 -30 ) ( 30 -10 ) ;
|
||||
END STYLES
|
||||
VIAS 1 ;
|
||||
- VIA1_dummy
|
||||
+ RECT M1 ( -20 -15 ) ( 20 15 )
|
||||
+ RECT VIA1 ( -10 -10 ) ( 10 10 )
|
||||
+ RECT M2 ( -25 -25 ) ( 25 25 ) ;
|
||||
END VIAS
|
||||
SPECIALNETS 1 ;
|
||||
- dummy
|
||||
+ ROUTED + RECT M2 ( 350 0 ) ( 200 100 )
|
||||
+ POLYGON M1 ( 300 0 ) ( 300 50 ) ( 350 50 ) ( 400 100 ) ( 400 0 )
|
||||
+ ROUTED + POLYGON M2 ( 300 150 ) ( 300 200 ) ( 350 200 ) ( 400 250 ) ( 400 150 )
|
||||
+ RECT M1 ( 0 0 ) ( 100 200 )
|
||||
+ ROUTED M1 30 ( 0 0 15 ) ( 100 0 0 ) VIA1_dummy ( 100 100 10 )
|
||||
+ ROUTED M2 50 + SHAPE RING + STYLE 1 ( 0 100 ) ( 100 200 ) ( 200 200 )
|
||||
;
|
||||
END SPECIALNETS
|
||||
END DESIGN
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
VERSION 5.8 ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DIVIDERCHAR "/" ;
|
||||
|
||||
UNITS
|
||||
DATABASE MICRONS 1000 ;
|
||||
END UNITS
|
||||
|
||||
MANUFACTURINGGRID 0.001 ;
|
||||
|
||||
LAYER M1
|
||||
TYPE ROUTING ;
|
||||
END M1
|
||||
|
||||
LAYER VIA1
|
||||
TYPE CUT ;
|
||||
END VIA1
|
||||
|
||||
LAYER M2
|
||||
TYPE ROUTING ;
|
||||
WIDTH 0.05 ;
|
||||
END M2
|
||||
|
||||
END LIBRARY
|
||||
Binary file not shown.
|
|
@ -0,0 +1,19 @@
|
|||
VERSION 5.8 ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DESIGN test ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
DIEAREA ( 0 0 ) ( 10000 10000 ) ;
|
||||
NONDEFAULTRULES 1 ;
|
||||
- ndr
|
||||
+ HARDSPACING
|
||||
+ LAYER M3 WIDTH 500 SPACING 500
|
||||
;
|
||||
END NONDEFAULTRULES
|
||||
NETS 1 ;
|
||||
- net_b
|
||||
+ NONDEFAULTRULE ndr
|
||||
+ ROUTED M3 ( 0 2000 ) ( 0 0 ) ( 2000 0 ) via34 ( * 2000 ) ( 4000 * ) ( * 4000 )
|
||||
;
|
||||
END NETS
|
||||
END DESIGN
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
VERSION 5.8 ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DIVIDERCHAR "/" ;
|
||||
|
||||
UNITS
|
||||
DATABASE MICRONS 1000 ;
|
||||
END UNITS
|
||||
|
||||
MANUFACTURINGGRID 0.001 ;
|
||||
|
||||
PROPERTYDEFINITIONS
|
||||
LAYER LEF58_MINWIDTH STRING ;
|
||||
END PROPERTYDEFINITIONS
|
||||
|
||||
LAYER M3
|
||||
TYPE ROUTING ;
|
||||
DIRECTION VERTICAL ;
|
||||
WIDTH 0.4 ;
|
||||
PROPERTY LEF58_MINWIDTH "MINWIDTH 0.5 ; " ;
|
||||
PROPERTY LEF58_MINWIDTH "MINWIDTH 0.8 WRONGDIRECTION ; " ;
|
||||
END M3
|
||||
|
||||
LAYER VIA3
|
||||
TYPE CUT ;
|
||||
END VIA3
|
||||
|
||||
LAYER M4
|
||||
TYPE ROUTING ;
|
||||
DIRECTION HORIZONTAL ;
|
||||
PROPERTY LEF58_WIDTH "WIDTH 0.6 ; " ;
|
||||
PROPERTY LEF58_WIDTH "WIDTH 1.0 WRONGDIRECTION ; " ;
|
||||
END M4
|
||||
|
||||
VIA via34
|
||||
LAYER M3 ;
|
||||
RECT -0.4 -0.3 0.4 0.3 ;
|
||||
LAYER VIA3 ;
|
||||
RECT -0.3 -0.25 0.3 0.25 ;
|
||||
LAYER M4 ;
|
||||
RECT -1.00 -0.5 1.00 0.5 ;
|
||||
END via34
|
||||
|
||||
END LIBRARY
|
||||
Binary file not shown.
|
|
@ -0,0 +1,19 @@
|
|||
VERSION 5.8 ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DESIGN test ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
DIEAREA ( 0 0 ) ( 10000 10000 ) ;
|
||||
NONDEFAULTRULES 1 ;
|
||||
- ndr
|
||||
+ HARDSPACING
|
||||
+ LAYER M3 WIDTH 500 SPACING 500
|
||||
;
|
||||
END NONDEFAULTRULES
|
||||
NETS 1 ;
|
||||
- net_b
|
||||
+ NONDEFAULTRULE ndr
|
||||
+ ROUTED M3 ( 0 0 ) ( 2000 0 ) via34 ( * 2000 ) ( 4000 * ) ( * 4000 )
|
||||
;
|
||||
END NETS
|
||||
END DESIGN
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
VERSION 5.8 ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DIVIDERCHAR "/" ;
|
||||
|
||||
UNITS
|
||||
DATABASE MICRONS 1000 ;
|
||||
END UNITS
|
||||
|
||||
MANUFACTURINGGRID 0.001 ;
|
||||
|
||||
PROPERTYDEFINITIONS
|
||||
LAYER LEF58_MINWIDTH STRING ;
|
||||
END PROPERTYDEFINITIONS
|
||||
|
||||
LAYER M3
|
||||
TYPE ROUTING ;
|
||||
DIRECTION VERTICAL ;
|
||||
WIDTH 0.6 ;
|
||||
END M3
|
||||
|
||||
LAYER VIA3
|
||||
TYPE CUT ;
|
||||
END VIA3
|
||||
|
||||
LAYER M4
|
||||
TYPE ROUTING ;
|
||||
DIRECTION HORIZONTAL ;
|
||||
WIDTH 0.5 ;
|
||||
PROPERTY LEF58_MINWIDTH "MINWIDTH 1.0 WRONGDIRECTION ; " ;
|
||||
END M4
|
||||
|
||||
VIA via34
|
||||
LAYER M3 ;
|
||||
RECT -0.4 -0.3 0.4 0.3 ;
|
||||
LAYER VIA3 ;
|
||||
RECT -0.3 -0.25 0.3 0.25 ;
|
||||
LAYER M4 ;
|
||||
RECT -1.00 -0.5 1.00 0.5 ;
|
||||
END via34
|
||||
|
||||
END LIBRARY
|
||||
|
|
@ -249,6 +249,10 @@ class DBReaders_TestClass < TestBase
|
|||
conf.via_geometry_suffix = "XVIA"
|
||||
assert_equal(conf.via_geometry_suffix, "XVIA")
|
||||
|
||||
assert_equal(conf.via_cellname_prefix, "VIA_")
|
||||
conf.via_cellname_prefix = "ABC"
|
||||
assert_equal(conf.via_cellname_prefix, "ABC")
|
||||
|
||||
assert_equal(conf.via_geometry_datatype, 0)
|
||||
conf.via_geometry_datatype = 17
|
||||
assert_equal(conf.via_geometry_datatype, 17)
|
||||
|
|
@ -265,6 +269,18 @@ class DBReaders_TestClass < TestBase
|
|||
conf.pins_datatype = 18
|
||||
assert_equal(conf.pins_datatype, 18)
|
||||
|
||||
assert_equal(conf.produce_lef_pins, true)
|
||||
conf.produce_lef_pins = false
|
||||
assert_equal(conf.produce_lef_pins, false)
|
||||
|
||||
assert_equal(conf.lef_pins_suffix, ".PIN")
|
||||
conf.lef_pins_suffix = "LEFPIN"
|
||||
assert_equal(conf.lef_pins_suffix, "LEFPIN")
|
||||
|
||||
assert_equal(conf.lef_pins_datatype, 2)
|
||||
conf.lef_pins_datatype = 181
|
||||
assert_equal(conf.lef_pins_datatype, 181)
|
||||
|
||||
assert_equal(conf.produce_obstructions, true)
|
||||
conf.produce_obstructions = false
|
||||
assert_equal(conf.produce_obstructions, false)
|
||||
|
|
@ -313,6 +329,26 @@ class DBReaders_TestClass < TestBase
|
|||
conf.routing_datatype = 22
|
||||
assert_equal(conf.routing_datatype, 22)
|
||||
|
||||
assert_equal(conf.produce_special_routing, true)
|
||||
conf.produce_special_routing = false
|
||||
assert_equal(conf.produce_special_routing, false)
|
||||
|
||||
assert_equal(conf.special_routing_suffix, "")
|
||||
conf.special_routing_suffix = "SPROUT"
|
||||
assert_equal(conf.special_routing_suffix, "SPROUT")
|
||||
|
||||
assert_equal(conf.special_routing_datatype, 0)
|
||||
conf.special_routing_datatype = 23
|
||||
assert_equal(conf.special_routing_datatype, 23)
|
||||
|
||||
assert_equal(conf.separate_groups, false)
|
||||
conf.separate_groups = true
|
||||
assert_equal(conf.separate_groups, true)
|
||||
|
||||
assert_equal(conf.map_file, "")
|
||||
conf.map_file = "xyz.map"
|
||||
assert_equal(conf.map_file, "xyz.map")
|
||||
|
||||
assert_equal(conf.lef_files.join(","), "")
|
||||
conf.lef_files = [ "u.lef", "v.lef" ]
|
||||
assert_equal(conf.lef_files.join(","), "u.lef,v.lef")
|
||||
|
|
|
|||
Loading…
Reference in New Issue