WIP: refactoring of map file reading.

This commit is contained in:
Matthias Koefferlein 2020-04-19 16:54:41 +02:00
parent e51f15b116
commit 040af426dc
10 changed files with 444 additions and 249 deletions

View File

@ -42,7 +42,7 @@ namespace db
*
* This implementation will create new layers if required.
*/
class DirectLayerMapping
class DB_PUBLIC DirectLayerMapping
: public ImportLayerMapping
{
public:

View File

@ -22,9 +22,11 @@
#include "dbLEFDEFImporter.h"
#include "dbLayoutUtils.h"
#include "tlStream.h"
#include "tlProgress.h"
#include "tlFileUtils.h"
#include <cctype>
@ -74,7 +76,8 @@ LEFDEFReaderOptions::LEFDEFReaderOptions ()
m_produce_special_routing (true),
m_special_routing_suffix (""),
m_special_routing_datatype (0),
m_separate_groups (false)
m_separate_groups (false),
m_consider_map_file (true)
{
// .. nothing yet ..
}
@ -121,6 +124,7 @@ LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d)
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_consider_map_file (d.m_consider_map_file),
m_lef_files (d.m_lef_files)
{
// .. nothing yet ..
@ -142,8 +146,20 @@ LEFDEFReaderOptions::format_name () const
// -----------------------------------------------------------------------------------
// LEFDEFLayerDelegate implementation
static db::LayerProperties lp_from_string (const std::string &ld)
{
db::LayerProperties lp;
tl::Extractor ex (ld.c_str ());
try {
ex.read (lp);
return lp;
} catch (...) {
return db::LayerProperties (0, 0);
}
}
LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc)
: m_create_layers (true), m_laynum (1), mp_tech_comp (tc)
: 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 ();
@ -158,8 +174,208 @@ LEFDEFReaderState::register_layer (const std::string &ln)
++m_laynum;
}
std::pair <bool, unsigned int>
void
LEFDEFReaderState::set_explicit_layer_mapping (bool f)
{
m_has_explicit_layer_mapping = f;
if (! f) {
m_layers.clear ();
}
}
void
LEFDEFReaderState::map_layer_explicit (const std::string &n, LayerPurpose purpose, unsigned int layer)
{
m_layers [std::make_pair (n, purpose)] = std::make_pair (true, 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;
if (tech_comp ()) {
const db::LEFDEFReaderOptions &options = *tech_comp ();
if (options.produce_placement_blockages ()) {
layer_map [std::make_pair (std::string (), Blockage)] = lp_from_string (options.placement_blockage_layer ());
}
if (options.produce_cell_outlines ()) {
layer_map [std::make_pair (std::string (), Outline)] = lp_from_string (options.cell_outline_layer ());
}
if (options.produce_regions ()) {
layer_map [std::make_pair (std::string (), Region)] = lp_from_string (options.region_layer ());
}
}
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 == "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, lm.map_layer (i->second).second);
}
// @@@ TODO: need to assign layer/datatype for all layers present.
}
void
LEFDEFReaderState::import_map_file_heuristics (const std::string &main_path, db::Layout &layout)
{
std::string input_dir = tl::absolute_path (main_path);
if (! tl::file_exists (input_dir)) {
return;
}
std::string bn = tl::basename (tl::filename (main_path));
std::vector<std::string> map_files;
std::string map_file_exact;
std::vector<std::string> entries = tl::dir_entries (input_dir);
for (std::vector<std::string>::const_iterator e = entries.begin (); e != entries.end (); ++e) {
if (tl::to_lower_case (tl::extension (*e)) == "map") {
if (tl::basename (*e) == bn) {
map_file_exact = *e;
} else {
map_files.push_back (*e);
}
}
}
try {
if (! map_file_exact.empty ()) {
read_map_file (tl::combine_path (input_dir, map_file_exact), layout);
} else if (map_files.size () == 1) {
read_map_file (tl::combine_path (input_dir, map_files.front ()), layout);
}
} catch (tl::Exception &ex) {
// ignore read errors on map file (this is a heuristics!)
tl::error << ex.msg ();
}
}
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 (! 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 (purpose == Outline || purpose == PlacementBlockage || purpose == Region) {
@ -167,21 +383,17 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu
// as is "(name)". It's used for implementing the automatic map file import
// feature.
std::string ld;
std::string canonical_name;
bool produce;
if (purpose == Outline) {
produce = mp_tech_comp->produce_cell_outlines ();
ld = mp_tech_comp->cell_outline_layer ();
canonical_name = "(OUTLINE)";
} else if (purpose == Region) {
produce = mp_tech_comp->produce_regions ();
ld = mp_tech_comp->region_layer ();
canonical_name = "(REGION)";
} else {
produce = mp_tech_comp->produce_placement_blockages ();
ld = mp_tech_comp->placement_blockage_layer ();
canonical_name = "(BLK)";
}
if (! produce) {
@ -203,10 +415,6 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu
return ll;
} else if ((ll = m_layer_map.logical (db::LayerProperties (canonical_name), layout)).first) {
return ll;
} else if (! m_create_layers) {
return std::pair<bool, unsigned int> (false, 0);
@ -256,74 +464,54 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu
}
// Note: "name" is the decorated name as provided by the tech component's
// x_suffix specifications. As this is a variable entity, we also provide
// a canonical name of the form "(layer,purpose)" where purpose is a
// predefined suffix. The canonical name is the last fallback. Hence this
// allows importing layer mapping files as canonical name mapping.
// x_suffix specifications.
std::string name (n);
int dt = 0;
std::string canonical_purpose;
if (mp_tech_comp) {
switch (purpose) {
case Routing:
default:
name += mp_tech_comp->routing_suffix ();
canonical_purpose = "NET";
dt += mp_tech_comp->routing_datatype ();
break;
case SpecialRouting:
name += mp_tech_comp->special_routing_suffix ();
canonical_purpose = "SPNET";
dt += mp_tech_comp->special_routing_datatype ();
break;
case ViaGeometry:
name += mp_tech_comp->via_geometry_suffix ();
dt += mp_tech_comp->via_geometry_datatype ();
canonical_purpose = "VIA";
break;
case Label:
name += mp_tech_comp->labels_suffix ();
dt += mp_tech_comp->labels_datatype ();
canonical_purpose = "LABEL";
break;
case Pins:
name += mp_tech_comp->pins_suffix ();
dt += mp_tech_comp->pins_datatype ();
canonical_purpose = "PIN";
break;
case LEFPins:
name += mp_tech_comp->lef_pins_suffix ();
dt += mp_tech_comp->lef_pins_datatype ();
canonical_purpose = "LEFPIN";
break;
case Obstructions:
name += mp_tech_comp->obstructions_suffix ();
dt += mp_tech_comp->obstructions_datatype ();
canonical_purpose = "OBS";
break;
case Blockage:
name += mp_tech_comp->blockages_suffix ();
dt += mp_tech_comp->blockages_datatype ();
canonical_purpose = "BLK";
break;
}
}
std::string canonical_name = std::string ("(") + n + "," + canonical_purpose + ")";
std::pair<bool, unsigned int> ll = m_layer_map.logical (name, layout);
if (ll.first) {
return ll;
} else if ((ll = m_layer_map.logical (db::LayerProperties (canonical_name), layout)).first) {
// final fallback: try canonical name
return ll;
} else {
ll = m_layer_map.logical (n, layout);
@ -341,14 +529,14 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu
} 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);
}
}
@ -380,7 +568,7 @@ LEFDEFReaderState::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) {

View File

@ -515,6 +515,16 @@ public:
m_separate_groups = f;
}
bool consider_map_file () const
{
return m_consider_map_file;
}
void set_consider_map_file (bool f)
{
m_consider_map_file = f;
}
private:
bool m_read_all_layers;
db::LayerMap m_layer_map;
@ -557,6 +567,7 @@ private:
std::string m_special_routing_suffix;
int m_special_routing_datatype;
bool m_separate_groups;
bool m_consider_map_file;
std::vector<std::string> m_lef_files;
};
@ -592,7 +603,32 @@ public:
LEFDEFReaderState (const LEFDEFReaderOptions *tc);
/**
* @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, 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 Imports a .map file present next to the input files
* "main_path" path of an input file (DEF). If a suitable .map file is found at this path,
* it is loaded into the reader state object. This will eventually disable any other layer
* mapping except for the global layers (region, outline, placement blockage).
*/
void import_map_file_heuristics (const std::string &main_path, db::Layout &layout);
/**
* @brief Sets the layer map
*/
virtual void set_layer_map (const db::LayerMap &lm, bool create_layers)
{
@ -601,7 +637,7 @@ public:
}
/**
* @brief Get the layer map
* @brief Gets the layer map
*/
const db::LayerMap &layer_map () const
{
@ -609,7 +645,7 @@ public:
}
/**
* @brief Get the layer map (non-const version)
* @brief Gets the layer map (non-const version)
*/
db::LayerMap &layer_map ()
{
@ -655,13 +691,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);
};
/**

View File

@ -30,6 +30,7 @@
#include "dbLEFImporter.h"
#include "dbDEFImporter.h"
#include "dbLEFDEFImporter.h"
#include "dbLayoutUtils.h"
namespace db
{
@ -77,156 +78,6 @@ static bool is_def_format (const std::string &fn)
return false;
}
/**
* @brief Reads a map file
*
* NOTE: this is rather experimental ... no idea what is the specification of
* the map file.
*/
static void
read_map_file (const std::string &path, db::LEFDEFReaderState &layers)
{
tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << path;
db::LayerMap &lm = layers.layer_map ();
unsigned int n = lm.next_index ();
tl::InputFile file (path);
tl::InputStream file_stream (file);
tl::TextInputStream ts (file_stream);
std::map<std::string, std::string> purpose_translation;
purpose_translation ["LEFPIN"] = "LEFPIN";
purpose_translation ["PIN"] = "PIN";
purpose_translation ["LEFOBS"] = "OBS";
purpose_translation ["SPNET"] = "SPNET";
purpose_translation ["NET"] = "NET";
purpose_translation ["VIA"] = "VIA";
purpose_translation ["BLOCKAGE"] = "BLK";
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") {
std::string canonical_name = "OUTLINE";
lm.map (db::LayerProperties (canonical_name), n++, db::LayerProperties (layer, datatype));
} 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) {
std::string canonical_name = std::string ("(") + *l + ",LABEL)";
lm.map (db::LayerProperties (canonical_name), n, db::LayerProperties (layer, datatype, final_name));
}
++n;
} 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::vector<std::string> translated_purposes;
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, std::string>::const_iterator i = purpose_translation.find (tl::to_upper_case (*p));
if (i != purpose_translation.end ()) {
translated_purposes.push_back (i->second);
}
}
std::sort (translated_purposes.begin (), translated_purposes.end ());
translated_purposes.erase (std::unique (translated_purposes.begin (), translated_purposes.end ()), translated_purposes.end ());
std::string final_name = w1 + "." + tl::join (translated_purposes, "/");
for (std::vector<std::string>::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
std::string canonical_name = std::string ("(") + w1 + "," + *p + ")";
lm.map (db::LayerProperties (canonical_name), n, db::LayerProperties (layer, datatype, final_name));
}
++n;
}
}
}
}
}
/**
* @brief Imports a .map file present next to the input files
*/
static void
import_map_file_heuristics (const std::string &main_path, db::LEFDEFReaderState &layers)
{
std::string input_dir = tl::absolute_path (main_path);
if (! tl::file_exists (input_dir)) {
return;
}
std::string bn = tl::basename (tl::filename (main_path));
std::vector<std::string> map_files;
std::string map_file_exact;
std::vector<std::string> entries = tl::dir_entries (input_dir);
for (std::vector<std::string>::const_iterator e = entries.begin (); e != entries.end (); ++e) {
if (tl::to_lower_case (tl::extension (*e)) == "map") {
if (tl::basename (*e) == bn) {
map_file_exact = *e;
} else {
map_files.push_back (*e);
}
}
}
try {
if (! map_file_exact.empty ()) {
read_map_file (tl::combine_path (input_dir, map_file_exact), layers);
tl::log << layers.layer_map ().to_string_file_format (); // @@@
} else if (map_files.size () == 1) {
read_map_file (tl::combine_path (input_dir, map_files.front ()), layers);
tl::log << layers.layer_map ().to_string_file_format (); // @@@
}
} catch (tl::Exception &ex) {
// ignore read errors on map file (this is a heuristics!)
tl::error << ex.msg ();
}
}
class LEFDEFReader
: public db::ReaderBase
{
@ -275,7 +126,9 @@ private:
db::LEFDEFReaderState state (lefdef_options);
import_map_file_heuristics (m_stream.absolute_path (), state);
if (lefdef_options->consider_map_file ()) {
state.import_map_file_heuristics (m_stream.absolute_path (), layout);
}
state.prepare (layout);
layout.dbu (lefdef_options->dbu ());

View File

@ -461,11 +461,25 @@ gsi::Class<db::LEFDEFReaderOptions> decl_lefdef_config ("db", "LEFDEFReaderConfi
"This property has been added in version 0.26.5.\n"
) +
gsi::method ("separate_groups=", &db::LEFDEFReaderOptions::set_separate_groups, gsi::arg ("flag"),
"@brief Gets a value indicating whether to create separate parent cells for individual groups.\n"
"@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.26.5.\n"
) +
gsi::method ("consider_map_file", &db::LEFDEFReaderOptions::consider_map_file,
"@brief Gets a value indicating whether to consider reading .map files next to DEF files.\n"
"If this property is set to true (the default), the DEF reader will look for .map files next to the "
"DEF file. If such a file is found, it will be used to map DEF layers to layout layers. The layer mapping "
"settings specified in the reader options are ignored in this case.\n"
"\n"
"This property has been added in version 0.26.5.\n"
) +
gsi::method ("consider_map_file=", &db::LEFDEFReaderOptions::set_consider_map_file, gsi::arg ("flag"),
"@brief Sets a value indicating whether to consider reading .map files next to DEF files.\n"
"See \\consider_map_file for details about this property.\n"
"\n"
"This property has been added in version 0.26.5.\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. "

View File

@ -207,17 +207,13 @@
<property name="bottomMargin">
<number>4</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Layout database unit</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Via cell name prefix</string>
<item row="0" column="4">
<widget class="QLineEdit" name="prefix_via_cellname">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
@ -234,6 +230,34 @@
</property>
</widget>
</item>
<item row="1" column="1" colspan="4">
<widget class="QCheckBox" name="separate_groups">
<property name="text">
<string>Produce a parent cell for each group</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Via cell name prefix</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Layout database unit</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Separate groups</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="dbu">
<property name="sizePolicy">
@ -244,27 +268,20 @@
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLineEdit" name="prefix_via_cellname">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="2" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>Consider map files</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QCheckBox" name="separate_groups">
<item row="2" column="1" colspan="4">
<widget class="QCheckBox" name="consider_map_file">
<property name="text">
<string>Produce a parent cell for each group</string>
<string>Look for .map files next to DEF files and use them to map layers</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Separate groups</string>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
@ -517,13 +534,6 @@
</property>
</widget>
</item>
<item row="0" column="5" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Produce ...</string>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QCheckBox" name="produce_pins">
<property name="text">
@ -764,6 +774,56 @@
</property>
</widget>
</item>
<item row="0" column="5" colspan="2">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="warn1">
<property name="toolTip">
<string>Layer assignment is not used if a .map file is present for DEF layer mapping</string>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../lay/lay/layResources.qrc">:/warn_16.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_26">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Produce ...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
@ -781,10 +841,7 @@
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>9</number>
</property>
@ -797,21 +854,14 @@
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<item row="0" column="1">
<widget class="QCheckBox" name="read_all_cbx">
<property name="text">
<string>Read all layers (additionally to the ones in the mapping table)</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<item row="2" column="1">
<widget class="lay::LayerMappingWidget" name="layer_map">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
@ -833,6 +883,32 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="warn2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>This table is not used if a .map file is present for DEF layer mapping</string>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../../lay/lay/layResources.qrc">:/warn_16.png</pixmap>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -881,12 +957,12 @@
<slot>setChecked(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>186</x>
<y>598</y>
<x>229</x>
<y>838</y>
</hint>
<hint type="destinationlabel">
<x>155</x>
<y>553</y>
<x>198</x>
<y>701</y>
</hint>
</hints>
</connection>

View File

@ -363,6 +363,7 @@ LEFDEFReaderOptionsEditor::LEFDEFReaderOptionsEditor (QWidget *parent)
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 (consider_map_file, SIGNAL (stateChanged (int)), this, SLOT (consider_map_file_state_changed ()));
lay::activate_help_links (help_label);
}
@ -450,6 +451,7 @@ LEFDEFReaderOptionsEditor::commit (db::FormatSpecificReaderOptions *options, con
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_consider_map_file (consider_map_file->isChecked ());
data->clear_lef_files ();
for (int i = 0; i < lef_files->count (); ++i) {
@ -510,6 +512,7 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options
suffix_labels->setText (tl::to_qstring (data->labels_suffix ()));
datatype_labels->setText (QString::number (data->labels_datatype ()));
separate_groups->setChecked (data->separate_groups ());
consider_map_file->setChecked (data->consider_map_file ());
checkbox_changed ();
@ -526,6 +529,13 @@ LEFDEFReaderOptionsEditor::setup (const db::FormatSpecificReaderOptions *options
}
}
void
LEFDEFReaderOptionsEditor::consider_map_file_state_changed ()
{
warn1->setVisible (consider_map_file->isChecked ());
warn2->setVisible (consider_map_file->isChecked ());
}
void
LEFDEFReaderOptionsEditor::checkbox_changed ()
{

View File

@ -98,6 +98,7 @@ private slots:
void del_lef_files_clicked ();
void move_lef_files_up_clicked ();
void move_lef_files_down_clicked ();
void consider_map_file_state_changed ();
private:
tl::weak_ptr<db::Technology> mp_tech;

View File

@ -69,7 +69,15 @@ static void run_test (tl::TestBase *_this, const char *lef_dir, const char *file
while (! ex.at_end ()) {
if (ex.test ("def:")) {
if (ex.test ("map:")) {
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);
@ -230,6 +238,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)

View File

@ -345,6 +345,10 @@ class DBReaders_TestClass < TestBase
conf.separate_groups = true
assert_equal(conf.separate_groups, true)
assert_equal(conf.consider_map_file, true)
conf.consider_map_file = false
assert_equal(conf.consider_map_file, false)
assert_equal(conf.lef_files.join(","), "")
conf.lef_files = [ "u.lef", "v.lef" ]
assert_equal(conf.lef_files.join(","), "u.lef,v.lef")