Lefdef enhancements (#1053)

* Implementated patch as suggested by issue-1047

* Implementing blend-mode for LEF/DEF for a first solution for issue-1048

* Added testcase, fixed other tests

* Issue-1050 fixed - now REGION, BLOCKAGE and DIEAREA are relevant from mapping file, nothing else

* Bug fixes

* Experimental: DEF multipart paths

* Experimental: ignore LEF wire extension, ignore PATTERNNAME

* Implemented PATTERNNAME in DEF instead of LEF ..

* Implemented nondefaultrule vias

* LEF/DEF: non-defaultrule vias need a name suffix.

* Refined solution for NDR via names, updated test data

* Updated test data

* Multiple map files and 'REGIONS FENCE' + 'REGIONS GUIDE' layer mapping entries.

* Added test data, updated doc.

* Some enhancements and feedback

REGIONS in map files -> REGION
REGION NONE for map files (maps REGIONs which are neither GUIDE or FENCE)
Bugfix: VIA with ORIGIN
No via cell name prefix by default for buddy tools

* Simplified buddy tool options for LEF/DEF property names

Dropped --lefdef-dont-produce-instance-names,
--lefdef-dont-produce-pin-names and --lefdef-dont-produce-net-names
options. Instead, these options have to be enabled by giving
the respective property names.

Writing the property names takes some space and these
options are simply confusing and redundant.

* Issue a warning about missing cut geometry for a DEF via with PATTERNNAME (which is ignored)

* Fixed issue-1065
This commit is contained in:
Matthias Köfferlein 2022-04-23 22:26:37 +02:00 committed by GitHub
parent fd4fe5ce62
commit 9cb77d6222
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 778 additions and 231 deletions

View File

@ -68,19 +68,11 @@ GenericReaderOptions::GenericReaderOptions ()
m_magic_lib_path.push_back (i->to_string ());
}
tl::Variant v;
m_lefdef_net_property_name = std::string ();
m_lefdef_inst_property_name = std::string ();
m_lefdef_pin_property_name = std::string ();
v = load_options.get_option_by_name ("lefdef_config.net_property_name");
m_lefdef_produce_net_names = ! v.is_nil ();
m_lefdef_net_property_name = v .to_parsable_string ();
v = load_options.get_option_by_name ("lefdef_config.instance_property_name");
m_lefdef_produce_inst_names = ! v.is_nil ();
m_lefdef_inst_property_name = v .to_parsable_string ();
v = load_options.get_option_by_name ("lefdef_config.pin_property_name");
m_lefdef_produce_pin_names = ! v.is_nil ();
m_lefdef_pin_property_name = v .to_parsable_string ();
m_lefdef_via_cellname_prefix = std::string ();
m_lefdef_produce_cell_outlines = load_options.get_option_by_name ("lefdef_config.produce_cell_outlines").to_bool ();
m_lefdef_cell_outline_layer = load_options.get_option_by_name ("lefdef_config.cell_outline_layer").to_string ();
@ -91,7 +83,6 @@ GenericReaderOptions::GenericReaderOptions ()
m_lefdef_produce_via_geometry = load_options.get_option_by_name ("lefdef_config.produce_via_geometry").to_bool ();
m_lefdef_via_geometry_suffix = load_options.get_option_by_name ("lefdef_config.via_geometry_suffix_str").to_string ();
m_lefdef_via_geometry_datatype = load_options.get_option_by_name ("lefdef_config.via_geometry_datatype_str").to_string ();
m_lefdef_via_cellname_prefix = load_options.get_option_by_name ("lefdef_config.via_cellname_prefix").to_string ();
m_lefdef_produce_pins = load_options.get_option_by_name ("lefdef_config.produce_pins").to_bool ();
m_lefdef_pins_suffix = load_options.get_option_by_name ("lefdef_config.pins_suffix_str").to_string ();
m_lefdef_pins_datatype = load_options.get_option_by_name ("lefdef_config.pins_datatype_str").to_string ();
@ -383,39 +374,27 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
std::string group ("[" + m_group_prefix + " options - LEF/DEF specific]");
cmd << tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-net-names", &m_lefdef_produce_net_names, "Disables producing net names as shape properties",
"If this option is present, net names will not be emitted as shape properties."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-net-property-name=spec", &m_lefdef_net_property_name, "Specifies which property name to use for net names",
"This option gives the name of the shape property used to annotate net names. For 'spec' use:\n"
"\n"
"* \"#n\" for property number \"n\" (compatible with GDS2)\n"
"* A plain word for a named property (not compatible with GDS2)\n"
"\n"
"Producing net name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-net-names'."
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-instance-names", &m_lefdef_produce_inst_names, "Disables producing DEF macro instance names as instance properties",
"If this option is present, DEF macro instance names will not be emitted as instance properties."
"By default, net names are not produced."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-instance-property-name=spec", &m_lefdef_inst_property_name, "Specifies which property name to use for DEF macro instance names",
"This option gives the name of the instance property used to annotate DEF macro instance names. "
"For the 'spec' format see '--" + m_long_prefix + "lefdef-net-property-name'."
"\n"
"Producing instance name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-instance-names'."
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-pin-names", &m_lefdef_produce_pin_names, "Disables producing pin names as shape or instance properties",
"If this option is present, Pin names will not be emitted as shape or instance properties."
"By default, instance names are not produced."
)
<< tl::arg (group +
"#--" + m_long_prefix + "lefdef-pin-property-name=spec", &m_lefdef_pin_property_name, "Specifies which property name to use for pin names",
"This option gives the name of the shape or instance property used to annotate pin names. "
"For the 'spec' format see '--" + m_long_prefix + "lefdef-net-property-name'."
"\n"
"Producing pin name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-pin-names'."
"By default, pin names are not produced."
)
<< tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-cell-outlines", &m_lefdef_produce_cell_outlines, "Disables producing cell outlines",
@ -623,7 +602,10 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
"layers need to specified individually for different layer/purpose combinations.\n"
"\n"
"The mapping file is one layer mapping entry per line. Each line is a layer name, followed by a list of purposes (VIA, PIN ...) "
"and a layer and datatype number. In addition, 'DIEAREA' can be used to map the design outline to a layer. 'NAME' in place of the "
"and a layer and datatype number. In addition, 'DIEAREA', 'REGION' and 'BLOCKAGE' can be used to map the design outline, regions and blockages to a layer. "
"'REGION' can have a detailed specifier which is 'FENCE', 'GUIDE' or 'NONE' for fence, guide or other type regions (e.g. 'REGION FENCE 99/0').\n"
"\n"
"'NAME' in place of the "
"layer name and using layer/purpose in the purpose column allows mapping labels to specific layers.\n"
"\n"
"This is an example for a layer map file:\n"
@ -639,7 +621,9 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
"VIA1 LEFPIN,VIA,PIN,NET,SPNET 13 0\n"
"M2 LEFPIN,PIN,NET,SPNET,VIA 14 0\n"
"\n"
"If a map file is used, only the layers present in the map file are generated. No other layers are produced."
"If a map file is used, only the layers present in the map file are generated. No other layers are produced.\n"
"\n"
"Multiple map files can be given, separated by '+' or ','. In that case, these files are concatenated."
)
<< tl::arg (group +
"!--" + m_long_prefix + "lefdef-macro-resolution-mode", &m_lefdef_macro_resolution_mode, "Specify how to generate layout from LEF macros",
@ -760,9 +744,9 @@ GenericReaderOptions::configure (db::LoadLayoutOptions &load_options)
load_options.set_option_by_name ("lefdef_config.layer_map", tl::Variant::make_variant (m_layer_map));
load_options.set_option_by_name ("lefdef_config.create_other_layers", m_create_other_layers);
load_options.set_option_by_name ("lefdef_config.dbu", m_dbu);
load_options.set_option_by_name ("lefdef_config.net_property_name", m_lefdef_produce_net_names ? tl::Variant (m_lefdef_net_property_name) : tl::Variant ());
load_options.set_option_by_name ("lefdef_config.instance_property_name", m_lefdef_produce_inst_names ? tl::Variant (m_lefdef_inst_property_name) : tl::Variant ());
load_options.set_option_by_name ("lefdef_config.pin_property_name", m_lefdef_produce_pin_names ? tl::Variant (m_lefdef_pin_property_name) : tl::Variant ());
load_options.set_option_by_name ("lefdef_config.net_property_name", !m_lefdef_net_property_name.empty () ? tl::Variant (m_lefdef_net_property_name) : tl::Variant ());
load_options.set_option_by_name ("lefdef_config.instance_property_name", !m_lefdef_inst_property_name.empty () ? tl::Variant (m_lefdef_inst_property_name) : tl::Variant ());
load_options.set_option_by_name ("lefdef_config.pin_property_name", !m_lefdef_pin_property_name.empty () ? tl::Variant (m_lefdef_pin_property_name) : tl::Variant ());
load_options.set_option_by_name ("lefdef_config.produce_cell_outlines", m_lefdef_produce_cell_outlines);
load_options.set_option_by_name ("lefdef_config.cell_outline_layer", m_lefdef_cell_outline_layer);
load_options.set_option_by_name ("lefdef_config.produce_placement_blockages", m_lefdef_produce_placement_blockages);

View File

@ -142,11 +142,8 @@ private:
void set_read_named_layers (bool f);
// LEFDEF
bool m_lefdef_produce_net_names;
std::string m_lefdef_net_property_name;
bool m_lefdef_produce_inst_names;
std::string m_lefdef_inst_property_name;
bool m_lefdef_produce_pin_names;
std::string m_lefdef_pin_property_name;
bool m_lefdef_produce_cell_outlines;
std::string m_lefdef_cell_outline_layer;

View File

@ -30,18 +30,18 @@ namespace db
{
// ---------------------------------------------------------------
// Common reader implementation
// Common reader basic feature implementation
static const size_t null_id = std::numeric_limits<size_t>::max ();
CommonReader::CommonReader ()
CommonReaderBase::CommonReaderBase ()
: m_cc_resolution (AddToCell), m_create_layers (false)
{
// .. nothing yet ..
}
db::cell_index_type
CommonReader::make_cell (db::Layout &layout, const std::string &cn)
CommonReaderBase::make_cell (db::Layout &layout, const std::string &cn)
{
tl_assert (! cn.empty ());
@ -69,13 +69,13 @@ CommonReader::make_cell (db::Layout &layout, const std::string &cn)
}
bool
CommonReader::has_cell (const std::string &cn) const
CommonReaderBase::has_cell (const std::string &cn) const
{
return m_name_map.find (cn) != m_name_map.end ();
}
std::pair<bool, db::cell_index_type>
CommonReader::cell_by_name (const std::string &cn) const
CommonReaderBase::cell_by_name (const std::string &cn) const
{
std::map<std::string, std::pair<size_t, db::cell_index_type> >::const_iterator iname = m_name_map.find (cn);
if (iname != m_name_map.end ()) {
@ -86,7 +86,7 @@ CommonReader::cell_by_name (const std::string &cn) const
}
db::cell_index_type
CommonReader::make_cell (db::Layout &layout, size_t id)
CommonReaderBase::make_cell (db::Layout &layout, size_t id)
{
tl_assert (id != null_id);
@ -114,13 +114,13 @@ CommonReader::make_cell (db::Layout &layout, size_t id)
}
bool
CommonReader::has_cell (size_t id) const
CommonReaderBase::has_cell (size_t id) const
{
return m_id_map.find (id) != m_id_map.end ();
}
std::pair<bool, db::cell_index_type>
CommonReader::cell_by_id (size_t id) const
CommonReaderBase::cell_by_id (size_t id) const
{
std::map<size_t, std::pair<std::string, db::cell_index_type> >::const_iterator iid = m_id_map.find (id);
if (iid != m_id_map.end ()) {
@ -131,7 +131,7 @@ CommonReader::cell_by_id (size_t id) const
}
const std::string &
CommonReader::name_for_id (size_t id) const
CommonReaderBase::name_for_id (size_t id) const
{
std::map<size_t, std::string>::const_iterator n = m_name_for_id.find (id);
if (n != m_name_for_id.end ()) {
@ -143,7 +143,7 @@ CommonReader::name_for_id (size_t id) const
}
void
CommonReader::rename_cell (db::Layout &layout, size_t id, const std::string &cn)
CommonReaderBase::rename_cell (db::Layout &layout, size_t id, const std::string &cn)
{
m_name_for_id.insert (std::make_pair (id, cn));
@ -191,7 +191,7 @@ CommonReader::rename_cell (db::Layout &layout, size_t id, const std::string &cn)
}
db::cell_index_type
CommonReader::cell_for_instance (db::Layout &layout, size_t id)
CommonReaderBase::cell_for_instance (db::Layout &layout, size_t id)
{
tl_assert (id != null_id);
@ -213,7 +213,7 @@ CommonReader::cell_for_instance (db::Layout &layout, size_t id)
}
db::cell_index_type
CommonReader::cell_for_instance (db::Layout &layout, const std::string &cn)
CommonReaderBase::cell_for_instance (db::Layout &layout, const std::string &cn)
{
tl_assert (! cn.empty ());
@ -235,7 +235,7 @@ CommonReader::cell_for_instance (db::Layout &layout, const std::string &cn)
}
void
CommonReader::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const
CommonReaderBase::merge_cell (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const
{
const db::Cell &src_cell = layout.cell (src_cell_index);
db::Cell &target_cell = layout.cell (target_cell_index);
@ -253,7 +253,7 @@ CommonReader::merge_cell (db::Layout &layout, db::cell_index_type target_cell_in
}
void
CommonReader::merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const
CommonReaderBase::merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const
{
const db::Cell &src_cell = layout.cell (src_cell_index);
db::Cell &target_cell = layout.cell (target_cell_index);
@ -281,46 +281,9 @@ CommonReader::merge_cell_without_instances (db::Layout &layout, db::cell_index_t
layout.delete_cell (src_cell.cell_index ());
}
const db::LayerMap &
CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
init (options);
tl_assert (!layout.under_construction ());
m_common_options.layer_map.prepare (layout);
layout.start_changes ();
try {
do_read (layout);
finish (layout);
layout.end_changes ();
} catch (...) {
layout.end_changes ();
throw;
}
// A cleanup may be necessary because of the following scenario: if library proxies contain subcells
// which are proxies itself, the proxy update may make them orphans (the proxies are regenerated).
// The cleanup will removed these.
layout.cleanup ();
return m_layer_map_out;
}
const db::LayerMap &
CommonReader::read (db::Layout &layout)
{
return read (layout, db::LoadLayoutOptions ());
}
void
CommonReader::init (const LoadLayoutOptions &options)
CommonReaderBase::init ()
{
m_common_options = options.get_options<db::CommonReaderOptions> ();
m_cc_resolution = m_common_options.cell_conflict_resolution;
m_create_layers = m_common_options.create_other_layers;
m_layer_map_out.clear ();
m_multi_mapping_placeholders.clear ();
m_layer_cache.clear ();
@ -329,7 +292,7 @@ CommonReader::init (const LoadLayoutOptions &options)
}
void
CommonReader::finish (db::Layout &layout)
CommonReaderBase::finish (db::Layout &layout)
{
bool any_missing = false;
@ -492,7 +455,7 @@ CommonReader::finish (db::Layout &layout)
}
std::pair <bool, unsigned int>
CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
CommonReaderBase::open_dl (db::Layout &layout, const LDPair &dl)
{
std::map<db::LDPair, std::pair <bool, unsigned int> >::const_iterator lc = m_layer_cache.find (dl);
if (lc != m_layer_cache.end ()) {
@ -505,9 +468,9 @@ CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
}
std::pair <bool, unsigned int>
CommonReader::open_dl_uncached (db::Layout &layout, const LDPair &dl)
CommonReaderBase::open_dl_uncached (db::Layout &layout, const LDPair &dl)
{
const std::set<unsigned int> &li = common_options ().layer_map.logical (dl, layout);
std::set<unsigned int> li = m_layer_map.logical (dl, layout);
if (li.empty ()) {
if (! m_create_layers) {
@ -558,6 +521,58 @@ CommonReader::open_dl_uncached (db::Layout &layout, const LDPair &dl)
}
}
// ---------------------------------------------------------------
// Common reader implementation
CommonReader::CommonReader ()
{
// .. nothing yet ..
}
const db::LayerMap &
CommonReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
init (options);
tl_assert (!layout.under_construction ());
layer_map ().prepare (layout);
layout.start_changes ();
try {
do_read (layout);
finish (layout);
layout.end_changes ();
} catch (...) {
layout.end_changes ();
throw;
}
// A cleanup may be necessary because of the following scenario: if library proxies contain subcells
// which are proxies itself, the proxy update may make them orphans (the proxies are regenerated).
// The cleanup will removed these.
layout.cleanup ();
return layer_map_out ();
}
const db::LayerMap &
CommonReader::read (db::Layout &layout)
{
return read (layout, db::LoadLayoutOptions ());
}
void
CommonReader::init (const LoadLayoutOptions &options)
{
CommonReaderBase::init ();
db::CommonReaderOptions common_options = options.get_options<db::CommonReaderOptions> ();
set_conflict_resolution_mode (common_options.cell_conflict_resolution);
set_create_layers (common_options.create_other_layers);
set_layer_map (common_options.layer_map);
}
// ---------------------------------------------------------------
// Common format declaration

View File

@ -132,8 +132,7 @@ public:
/**
* @brief A common reader base for GDS2 and OASIS providing common services for both readers
*/
class DB_PUBLIC CommonReader
: public ReaderBase
class DB_PUBLIC CommonReaderBase
{
public:
typedef tl::interval_map <db::ld_type, tl::interval_map <db::ld_type, std::string> > layer_name_map;
@ -141,7 +140,7 @@ public:
/**
* @brief Constructor
*/
CommonReader ();
CommonReaderBase ();
/**
* @brief Make a cell from a name
@ -205,17 +204,40 @@ public:
*/
void finish (db::Layout &layout);
// Reimplementation of the ReaderBase interace
virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options);
virtual const db::LayerMap &read (db::Layout &layout);
/**
* @brief Re-initialize: clears the tables and caches
*/
void init ();
/**
* @brief Sets a value indicating whether to create layers
*/
void set_create_layers (bool f)
{
m_create_layers = f;
}
/**
* @brief Sets the conflict resolution mode
*/
void set_conflict_resolution_mode (CellConflictResolution cc_resolution)
{
m_cc_resolution = cc_resolution;
}
/**
* @brief Sets the input layer map
*/
void set_layer_map (const db::LayerMap &lm)
{
m_layer_map = lm;
}
protected:
friend class CommonReaderLayerMapping;
virtual void common_reader_error (const std::string &msg) = 0;
virtual void common_reader_warn (const std::string &msg) = 0;
virtual void do_read (db::Layout &layout) = 0;
virtual void init (const LoadLayoutOptions &options);
/**
* @brief Merge (and delete) the src_cell into target_cell
@ -227,14 +249,6 @@ protected:
*/
void merge_cell_without_instances (db::Layout &layout, db::cell_index_type target_cell_index, db::cell_index_type src_cell_index) const;
/**
* @brief Gets the common options
*/
db::CommonReaderOptions &common_options ()
{
return m_common_options;
}
/**
* @brief Gets the layer name map
*/
@ -244,7 +258,23 @@ protected:
}
/**
* @brief Enters the a layer with a given layer/datatype
* @brief Gets the input layer name
*/
db::LayerMap &layer_map ()
{
return m_layer_map;
}
/**
* @brief Gets the output layer name map
*/
const db::LayerMap &layer_map_out () const
{
return m_layer_map_out;
}
/**
* @brief Enters the layer with a given layer/datatype
*/
std::pair <bool, unsigned int> open_dl (db::Layout &layout, const LDPair &dl);
@ -255,7 +285,7 @@ private:
std::map<size_t, std::string> m_name_for_id;
CellConflictResolution m_cc_resolution;
bool m_create_layers;
db::CommonReaderOptions m_common_options;
db::LayerMap m_layer_map;
db::LayerMap m_layer_map_out;
tl::interval_map <db::ld_type, tl::interval_map <db::ld_type, std::string> > m_layer_names;
std::map<db::LDPair, std::pair <bool, unsigned int> > m_layer_cache;
@ -265,6 +295,33 @@ private:
std::pair <bool, unsigned int> open_dl_uncached (db::Layout &layout, const LDPair &dl);
};
/**
* @brief A common reader base for GDS2 and OASIS providing common services for both readers
*/
class DB_PUBLIC CommonReader
: public ReaderBase, public CommonReaderBase
{
public:
typedef tl::interval_map <db::ld_type, tl::interval_map <db::ld_type, std::string> > layer_name_map;
/**
* @brief Constructor
*/
CommonReader ();
// Reimplementation of the ReaderBase interace
virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options);
virtual const db::LayerMap &read (db::Layout &layout);
protected:
friend class CommonReaderLayerMapping;
virtual void init (const LoadLayoutOptions &options);
virtual void do_read (db::Layout &layout) = 0;
};
/**
* @brief A utility class that maps the layers for the proxy cell recovery
*/

View File

@ -59,11 +59,11 @@ GDS2ReaderBase::init (const db::LoadLayoutOptions &options)
{
CommonReader::init (options);
db::CommonReaderOptions common_options = options.get_options<db::CommonReaderOptions> ();
m_read_texts = common_options.enable_text_objects;
m_read_properties = common_options.enable_properties;
db::GDS2ReaderOptions gds2_options = options.get_options<db::GDS2ReaderOptions> ();
m_read_texts = common_options ().enable_text_objects;
m_read_properties = common_options ().enable_properties;
m_allow_multi_xy_records = gds2_options.allow_multi_xy_records;
m_box_mode = gds2_options.box_mode;
}

View File

@ -139,8 +139,15 @@ DEFImporter::get_def_ext (const std::string &ln, const std::pair<db::Coord, db::
// This implementation assumes the "preferred width" is controlling the default extension and it is
// identical to the minimum effective width. This is true if "LEF58_MINWIDTH" with "WRONGDIRECTION" is
// used in the proposed way. Which is to specify a larger width for the "wrong" direction.
#if 0
// This implementation tries to use LEF wire extension if given
db::Coord de = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, std::min (wxy.first, wxy.second) * 0.5 * dbu) / dbu);
return std::make_pair (de, de);
#else
// This implementation follows the LEFDEF 5.8 spec saying the "default extension is half the wire width":
db::Coord de = std::min (wxy.first, wxy.second) / 2;
return std::make_pair (de, de);
#endif
}
void
@ -205,22 +212,39 @@ DEFImporter::read_nondefaultrules (double scale)
}
void
DEFImporter::read_regions (std::map<std::string, std::vector<db::Polygon> > &regions, double scale)
DEFImporter::read_regions (std::map<std::string, std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > > > &regions, double scale)
{
while (test ("-")) {
std::string n = get ();
std::vector<db::Polygon> &polygons = regions [n];
std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > > &rg = regions[n];
rg.push_back (std::pair<LayerPurpose, std::vector<db::Polygon> > (RegionsNone, std::vector<db::Polygon> ()));
LayerPurpose &p = rg.back ().first;
std::vector<db::Polygon> &polygons = rg.back ().second;
while (! peek (";")) {
if (test ("+")) {
// ignore other options for now
while (! peek (";")) {
take ();
if (test ("TYPE")) {
if (test ("GUIDE")) {
p = RegionsGuide;
} else if (test ("FENCE")) {
p = RegionsFence;
} else {
error (tl::to_string (tr ("REGION type needs to be GUIDE or FENCE")));
}
} else {
// ignore other options for now (i.e. PROPERTY)
while (! peek (";") && ! peek ("+")) {
take ();
}
}
break;
} else {
@ -379,7 +403,11 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u
// compute begin extension
db::Coord be = 0;
if (pt0 == pts.begin ()) {
be = ext.front ().first;
if (pt0->x () == pt0 [1].x ()) {
be = ext.front ().second;
} else {
be = ext.front ().first;
}
} else if (was_path_before) {
// provides the overlap to the previous segment
be = wxy_perp / 2;
@ -388,15 +416,32 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u
// compute end extension
db::Coord ee = 0;
if (pt + 1 == pts.end ()) {
ee = ext.back ().first;
if (pt [-1].x () == pt->x ()) {
ee = ext.back ().second;
} else {
ee = ext.back ().first;
}
}
#if 0
// single path
db::Path p (pt0, pt + 1, wxy, be, ee, false);
if (prop_id != 0) {
design.shapes (layer).insert (db::object_with_properties<db::Path> (p, prop_id));
} else {
design.shapes (layer).insert (p);
}
#else
// multipart paths
for (std::vector<db::Point>::const_iterator i = pt0; i != pt; ++i) {
db::Path p (i, i + 2, wxy, i == pt0 ? be : wxy / 2, i + 1 != pt ? wxy / 2 : ee, false);
if (prop_id != 0) {
design.shapes (layer).insert (db::object_with_properties<db::Path> (p, prop_id));
} else {
design.shapes (layer).insert (p);
}
}
#endif
was_path_before = true;
@ -667,7 +712,7 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
unsigned int mask_cut = (mask / 10) % 10;
unsigned int mask_bottom = mask % 10;
db::Cell *cell = reader_state ()->via_cell (vn, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer);
db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, mask_bottom, mask_cut, mask_top, &m_lef_importer);
if (cell) {
if (nx <= 1 && ny <= 1) {
design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ()))));
@ -846,7 +891,7 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool
std::map<std::string, ViaDesc>::const_iterator vd = m_via_desc.find (vn);
if (vd != m_via_desc.end ()) {
// TODO: no mask specification here?
db::Cell *cell = reader_state ()->via_cell (vn, layout, 0, 0, 0, &m_lef_importer);
db::Cell *cell = reader_state ()->via_cell (vn, nondefaultrule, layout, 0, 0, 0, &m_lef_importer);
if (cell) {
design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), pt)));
}
@ -917,6 +962,9 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale)
std::set<std::string> seen_layers;
std::vector<std::string> routing_layers;
bool has_cut_geometry = false;
bool has_patternname = false;
while (test ("+")) {
bool is_polygon = false;
@ -980,6 +1028,11 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale)
rule_based_vg->set_rows (get_long ());
rule_based_vg->set_columns (get_long ());
} else if (test ("PATTERNNAME")) {
get (); // ignore
has_patternname = true;
} else if (test ("PATTERN")) {
if (! rule_based_vg.get ()) {
@ -1031,6 +1084,7 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale)
} else if (m_lef_importer.is_cut_layer (ln)) {
geo_based_vg->set_maskshift_layer (1, ln);
has_cut_geometry = true;
}
@ -1058,6 +1112,10 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale)
}
if (has_patternname && ! has_cut_geometry) {
warn (tl::sprintf (tl::to_string (tr ("Via %s uses legacy PATTERNAME and no cut geometry - no via shapes are generated")), n));
}
if (vd.m1.empty () && vd.m2.empty ()) {
// analyze the layers to find the metals
@ -1065,7 +1123,7 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale)
vd.m1 = routing_layers[0];
vd.m2 = routing_layers[1];
} else {
warn ("Can't determine routing layers for via: " + n);
warn (tl::to_string (tr ("Cannot determine routing layers for via: ")) + n);
}
}
@ -1073,9 +1131,9 @@ DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale)
if (rule_based_vg.get () && geo_based_vg.get ()) {
error (tl::to_string (tr ("A via can only be defined through a VIARULE or geometry, not both ways")));
} else if (rule_based_vg.get ()) {
reader_state ()->register_via_cell (n, rule_based_vg.release ());
reader_state ()->register_via_cell (n, std::string (), rule_based_vg.release ());
} else if (geo_based_vg.get ()) {
reader_state ()->register_via_cell (n, geo_based_vg.release ());
reader_state ()->register_via_cell (n, std::string (), geo_based_vg.release ());
} else {
error (tl::to_string (tr ("Too little information to generate a via")));
}
@ -1442,15 +1500,16 @@ DEFImporter::do_read (db::Layout &layout)
double dbu_mic = 1000.0;
double scale = 1.0 / (dbu_mic * layout.dbu ());
size_t top_id = 0;
std::map<std::string, std::vector<db::Polygon> > regions;
std::map<std::string, std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > > > regions;
std::list<DEFImporterGroup> groups;
std::list<std::pair<std::string, db::CellInstArray> > instances;
m_via_desc = m_lef_importer.vias ();
m_styles.clear ();
db::Cell &design = layout.cell (layout.add_cell ("TOP"));
db::Cell &design = layout.cell (reader_state ()->make_cell (layout, top_id));
while (! at_end ()) {
@ -1465,7 +1524,7 @@ DEFImporter::do_read (db::Layout &layout)
} else if (test ("DESIGN")) {
std::string cn = get ();
layout.rename_cell (design.cell_index (), layout.uniquify_cell_name (cn.c_str ()).c_str ());
reader_state ()->rename_cell (layout, top_id, cn);
expect (";");
@ -1651,7 +1710,7 @@ DEFImporter::do_read (db::Layout &layout)
if (! groups.empty () && options ().separate_groups ()) {
others_cell = &layout.cell (layout.add_cell ("NOGROUP"));
others_cell = &layout.cell (reader_state ()->make_cell (layout, "NOGROUP"));
design.insert (db::CellInstArray (others_cell->cell_index (), db::Trans ()));
// Walk through the groups, create a group container cell and put all instances
@ -1659,24 +1718,35 @@ DEFImporter::do_read (db::Layout &layout)
for (std::list<DEFImporterGroup>::const_iterator g = groups.begin (); g != groups.end (); ++g) {
db::Cell *group_cell = &layout.cell (layout.add_cell (("GROUP_" + g->name).c_str ()));
db::Cell *group_cell = &layout.cell (reader_state ()->make_cell (layout, ("GROUP_" + g->name).c_str ()));
design.insert (db::CellInstArray (group_cell->cell_index (), db::Trans ()));
if (! g->region_name.empty ()) {
std::map<std::string, std::vector<db::Polygon> >::iterator r = regions.find (g->region_name);
std::map<std::string, std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > > >::iterator r = regions.find (g->region_name);
if (r == regions.end ()) {
warn (tl::sprintf (tl::to_string (tr ("Not a valid region name or region is already used: %s in group %s")), g->region_name, g->name));
} else {
std::set<unsigned int> dl = open_layer (layout, std::string (), Regions, 0);
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
for (std::vector<db::Polygon>::const_iterator p = r->second.begin (); p != r->second.end (); ++p) {
group_cell->shapes (*l).insert (*p);
for (std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > >::const_iterator rr = r->second.begin (); rr != r->second.end (); ++rr) {
std::set<unsigned int> dl = open_layer (layout, std::string (), rr->first, 0);
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
group_cell->shapes (*l).insert (rr->second.begin (), rr->second.end ());
}
if (rr->first != Regions) {
// try the "ALL" slot too for FENCE and GUIDE regions
dl = open_layer (layout, std::string (), Regions, 0);
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
group_cell->shapes (*l).insert (rr->second.begin (), rr->second.end ());
}
}
}
regions.erase (r);
}
@ -1714,12 +1784,19 @@ DEFImporter::do_read (db::Layout &layout)
if (! regions.empty ()) {
std::set<unsigned int> dl = open_layer (layout, std::string (), Regions, 0);
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
LayerPurpose lps [] = { Regions, RegionsNone, RegionsGuide, RegionsFence };
for (std::map<std::string, std::vector<db::Polygon> >::const_iterator r = regions.begin (); r != regions.end (); ++r) {
for (std::vector<db::Polygon>::const_iterator p = r->second.begin (); p != r->second.end (); ++p) {
others_cell->shapes (*l).insert (*p);
for (unsigned int i = 0; i < sizeof (lps) / sizeof (lps[0]); ++i) {
std::set<unsigned int> dl = open_layer (layout, std::string (), lps[i], 0);
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
for (std::map<std::string, std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > > >::const_iterator r = regions.begin (); r != regions.end (); ++r) {
for (std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > >::const_iterator rr = r->second.begin (); rr != r->second.end (); ++rr) {
if (lps [i] == Regions || rr->first == lps [i]) {
others_cell->shapes (*l).insert (rr->second.begin (), rr->second.end ());
}
}
}
}

View File

@ -79,7 +79,7 @@ private:
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> > &regions, double scale);
void read_regions (std::map<std::string, std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > > > &regions, 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);

View File

@ -117,6 +117,12 @@ static std::string purpose_to_name (LayerPurpose purpose)
return "OUTLINE";
case Regions:
return "REGION";
case RegionsGuide:
return "REGIONGUIDE";
case RegionsFence:
return "REGIONFENCE";
case RegionsNone:
return "REGIONNONE";
case PlacementBlockage:
return "BLOCKAGE";
case Routing:
@ -143,9 +149,9 @@ static std::string purpose_to_name (LayerPurpose purpose)
return "BLK";
case All:
return "ALL";
default:
return std::string ();
}
return std::string ();
}
static std::string
@ -213,7 +219,7 @@ RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, d
dl = reader.open_layer (layout, m_top_layer, ViaGeometry, mask_top, via_box.enlarged (m_te));
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
cell.shapes (*l).insert (db::Polygon (via_box.enlarged (m_te).moved (m_bo)));
cell.shapes (*l).insert (db::Polygon (via_box.enlarged (m_te).moved (m_to)));
}
const char *p = m_pattern.c_str ();
@ -389,7 +395,7 @@ GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &la
for (std::list<Via>::const_iterator v = m_vias.begin (); v != m_vias.end (); ++v) {
LEFDEFLayoutGenerator *g = reader.via_generator (v->name);
LEFDEFLayoutGenerator *g = reader.via_generator (v->name, v->nondefaultrule);
if (! g) {
continue;
}
@ -401,7 +407,7 @@ GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &la
unsigned mshift_cut = get_maskshift (msl [1], ext_msl, masks);
unsigned mshift_top = get_maskshift (msl [2], ext_msl, masks);
db::Cell *vc = reader.via_cell (v->name, layout,
db::Cell *vc = reader.via_cell (v->name, v->nondefaultrule, layout,
combine_maskshifts (msl [0], v->bottom_mask, mshift_bottom, nm),
combine_maskshifts (msl [1], v->cut_mask, mshift_cut, nm),
combine_maskshifts (msl [2], v->top_mask, mshift_top, nm),
@ -868,11 +874,11 @@ LEFDEFReaderOptions::special_routing_datatype_str () const
// LEFDEFLayerDelegate implementation
LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout, const std::string &base_path)
: m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc)
: mp_importer (0), m_create_layers (true), m_has_explicit_layer_mapping (false), m_laynum (1), mp_tech_comp (tc)
{
if (! tc->map_file ().empty ()) {
read_map_file (correct_path (tc->map_file (), layout, base_path), layout);
read_map_file (tc->map_file (), layout, base_path);
} else {
@ -886,7 +892,7 @@ LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout
LEFDEFReaderState::~LEFDEFReaderState ()
{
for (std::map<std::string, LEFDEFLayoutGenerator *>::const_iterator i = m_via_generators.begin (); i != m_via_generators.end (); ++i) {
for (std::map<std::pair<std::string, std::string>, LEFDEFLayoutGenerator *>::const_iterator i = m_via_generators.begin (); i != m_via_generators.end (); ++i) {
delete i->second;
}
@ -899,6 +905,22 @@ LEFDEFReaderState::~LEFDEFReaderState ()
m_macro_generators.clear ();
}
void
LEFDEFReaderState::common_reader_error (const std::string &msg)
{
if (mp_importer) {
mp_importer->error (msg);
}
}
void
LEFDEFReaderState::common_reader_warn (const std::string &msg)
{
if (mp_importer) {
mp_importer->warn (msg);
}
}
void
LEFDEFReaderState::register_layer (const std::string &ln)
{
@ -926,17 +948,71 @@ static bool try_read_layers (tl::Extractor &ex, std::vector<int> &layers)
return true;
}
static std::string::size_type find_file_sep (const std::string &s, std::string::size_type from)
{
std::string::size_type p1 = s.find ("+", from);
std::string::size_type p2 = s.find (",", from);
if (p1 == std::string::npos) {
return p2;
} else if (p2 == std::string::npos) {
return p1;
} else {
return p1 < p2 ? p1 : p2;
}
}
static std::vector<std::string> split_file_list (const std::string &infile)
{
std::vector<std::string> files;
size_t p = 0;
for (size_t pp = 0; (pp = find_file_sep (infile, p)) != std::string::npos; p = pp + 1) {
files.push_back (std::string (infile, p, pp - p));
}
files.push_back (std::string (infile, p));
return files;
}
void
LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
LEFDEFReaderState::read_map_file (const std::string &filename, db::Layout &layout, const std::string &base_path)
{
m_has_explicit_layer_mapping = true;
tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << path;
std::vector<std::string> paths = split_file_list (filename);
std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> > layer_map;
for (std::vector<std::string>::const_iterator p = paths.begin (); p != paths.end (); ++p) {
read_single_map_file (correct_path (*p, layout, base_path), layer_map);
}
// build an explicit layer mapping now.
tl_assert (m_has_explicit_layer_mapping);
m_layers.clear ();
m_layer_map.clear ();
db::DirectLayerMapping lm (&layout);
for (std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> >::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) {
for (std::vector<db::LayerProperties>::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
unsigned int layer = lm.map_layer (*j).second;
m_layers [i->first].insert (layer);
m_layer_map.mmap (*j, layer);
}
}
}
void
LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> > &layer_map)
{
tl::InputFile file (path);
tl::InputStream file_stream (file);
tl::TextInputStream ts (file_stream);
tl::log << tl::to_string (tr ("Reading LEF/DEF map file")) << " " << file_stream.absolute_path ();
std::map<std::string, LayerPurpose> purpose_translation;
purpose_translation ["LEFPIN"] = LEFPins;
purpose_translation ["PIN"] = Pins;
@ -949,8 +1025,6 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
purpose_translation ["BLOCKAGE"] = Blockage;
purpose_translation ["ALL"] = All;
std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> > layer_map;
while (! ts.at_end ()) {
const std::string &l = ts.get_line ();
@ -979,11 +1053,26 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
}
}
} else if (w1 == "REGIONS") {
} else if (w1 == "REGION") {
std::string name = "REGIONS";
LayerPurpose lp = Regions;
if (w2 == "FENCE") {
name = "REGIONS_FENCE";
lp = RegionsFence;
} else if (w2 == "GUIDE") {
name = "REGIONS_GUIDE";
lp = RegionsGuide;
} else if (w2 == "NONE") {
name = "REGIONS_NONE";
lp = RegionsNone;
} else if (w2 != "ALL") {
tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d - ignoring unknowns REGION purpose %s (use FENCE, GUIDE or ALL)")), path, ts.line_number (), w2);
}
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
layer_map [std::make_pair (std::string (), LayerDetailsKey (Regions))].push_back (db::LayerProperties (*l, *d, "REGIONS"));
layer_map [std::make_pair (std::string (), LayerDetailsKey (lp))].push_back (db::LayerProperties (*l, *d, name));
}
}
@ -1124,7 +1213,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
} else if (i->second == All) {
for (std::map<std::string, LayerPurpose>::const_iterator p = purpose_translation.begin (); p != purpose_translation.end (); ++p) {
if (p->second != All) {
if (p->second != All && p->second != Blockage) {
translated_purposes.insert (LayerDetailsKey (p->second, mask, via_size));
}
}
@ -1172,21 +1261,14 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
}
}
}
// build an explicit layer mapping now.
tl_assert (m_has_explicit_layer_mapping);
m_layers.clear ();
m_layer_map.clear ();
db::DirectLayerMapping lm (&layout);
for (std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> >::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) {
for (std::vector<db::LayerProperties>::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
unsigned int layer = lm.map_layer (*j).second;
m_layers [i->first].insert (layer);
m_layer_map.mmap (*j, layer);
}
}
/**
* @brief Returns true, if the layer purpose has a fallback
*/
static bool has_fallback (LayerPurpose p)
{
return p == RegionsFence || p == RegionsGuide || p == RegionsNone;
}
std::set <unsigned int>
@ -1201,14 +1283,18 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu
std::set <unsigned int> ll;
if (n.empty () || ! m_has_explicit_layer_mapping) {
if (! m_has_explicit_layer_mapping) {
ll = open_layer_uncached (layout, n, purpose, mask);
}
m_layers.insert (std::make_pair (std::make_pair (n, LayerDetailsKey (purpose, mask)), ll));
if (ll.empty ()) {
tl::warn << tl::to_string (tr ("No mapping for layer")) << " '" << n << "', purpose '" << purpose_to_name (purpose) << "'" << tl::noendl;
if (ll.empty () && ! has_fallback (purpose)) {
if (n.empty ()) {
tl::warn << tl::to_string (tr ("No mapping for purpose")) << " '" << purpose_to_name (purpose) << "'" << tl::noendl;
} else {
tl::warn << tl::to_string (tr ("No mapping for layer")) << " '" << n << "', purpose '" << purpose_to_name (purpose) << "'" << tl::noendl;
}
if (mask > 0) {
tl::warn << tl::to_string (tr (" Mask ")) << mask << tl::noendl;
}
@ -1538,6 +1624,8 @@ std::set<unsigned int> LEFDEFReaderState::open_layer_uncached(db::Layout &layout
void
LEFDEFReaderState::finish (db::Layout &layout)
{
CommonReaderBase::finish (layout);
int lnum = 0;
std::set<int> used_numbers;
@ -1606,18 +1694,22 @@ LEFDEFReaderState::finish (db::Layout &layout)
}
void
LEFDEFReaderState::register_via_cell (const std::string &vn, LEFDEFLayoutGenerator *generator)
LEFDEFReaderState::register_via_cell (const std::string &vn, const std::string &nondefaultrule, LEFDEFLayoutGenerator *generator)
{
if (m_via_generators.find (vn) != m_via_generators.end ()) {
delete m_via_generators [vn];
if (m_via_generators.find (std::make_pair (vn, nondefaultrule)) != m_via_generators.end ()) {
delete m_via_generators [std::make_pair (vn, nondefaultrule)];
}
m_via_generators [vn] = generator;
m_via_generators [std::make_pair (vn, nondefaultrule)] = generator;
}
LEFDEFLayoutGenerator *
LEFDEFReaderState::via_generator (const std::string &vn)
LEFDEFReaderState::via_generator (const std::string &vn, const std::string &nondefaultrule)
{
std::map<std::string, LEFDEFLayoutGenerator *>::const_iterator g = m_via_generators.find (vn);
std::map<std::pair<std::string, std::string>, LEFDEFLayoutGenerator *>::const_iterator g = m_via_generators.find (std::make_pair (vn, nondefaultrule));
if (g == m_via_generators.end () && ! nondefaultrule.empty ()) {
// default rule is fallback
g = m_via_generators.find (std::make_pair (vn, std::string ()));
}
if (g != m_via_generators.end ()) {
return g->second;
} else {
@ -1626,31 +1718,45 @@ LEFDEFReaderState::via_generator (const std::string &vn)
}
db::Cell *
LEFDEFReaderState::via_cell (const std::string &vn, db::Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm)
LEFDEFReaderState::via_cell (const std::string &vn, const std::string &nondefaultrule, db::Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm)
{
ViaKey vk (vn, mask_bottom, mask_cut, mask_top);
ViaKey vk (vn, nondefaultrule, mask_bottom, mask_cut, mask_top);
std::map<std::pair<std::string, std::string>, LEFDEFLayoutGenerator *>::const_iterator g = m_via_generators.find (std::make_pair (vn, nondefaultrule));
if (g == m_via_generators.end () && ! vk.nondefaultrule.empty ()) {
// default rule is fallback
g = m_via_generators.find (std::make_pair (vn, std::string ()));
vk.nondefaultrule.clear ();
}
std::map<ViaKey, db::Cell *>::const_iterator i = m_via_cells.find (vk);
if (i == m_via_cells.end ()) {
db::Cell *cell = 0;
std::map<std::string, LEFDEFLayoutGenerator *>::const_iterator g = m_via_generators.find (vn);
if (g != m_via_generators.end ()) {
LEFDEFLayoutGenerator *vg = g->second;
std::string mask_suffix;
if (mask_bottom > 0 || mask_cut > 0 || mask_top > 0) {
mask_suffix += "_";
mask_suffix += tl::to_string (mask_bottom);
mask_suffix += "_";
mask_suffix += tl::to_string (mask_cut);
mask_suffix += "_";
mask_suffix += tl::to_string (mask_top);
std::string n = vn;
if (! vk.nondefaultrule.empty ()) {
n += "_";
n += vk.nondefaultrule;
}
std::string cn = mp_tech_comp->via_cellname_prefix () + vn + mask_suffix;
cell = &layout.cell (layout.add_cell (cn.c_str ()));
if (mask_bottom > 0 || mask_cut > 0 || mask_top > 0) {
n += "_";
n += tl::to_string (mask_bottom);
n += "_";
n += tl::to_string (mask_cut);
n += "_";
n += tl::to_string (mask_top);
}
std::string cn = mp_tech_comp->via_cellname_prefix () + n;
cell = &layout.cell (make_cell (layout, cn.c_str ()));
std::vector<unsigned int> masks;
masks.reserve (3);
@ -1705,7 +1811,7 @@ LEFDEFReaderState::foreign_cell (Layout &layout, const std::string &name)
if (cc.first) {
ci = cc.second;
} else {
ci = layout.add_cell (name.c_str ());
ci = make_cell (layout, name.c_str ());
layout.cell (ci).set_ghost_cell (true);
}
@ -1747,7 +1853,7 @@ LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std:
if (macro_desc.foreign_name != mn) {
// create an indirection for renaming the cell
cell = &layout.cell (layout.add_cell (mn.c_str ()));
cell = &layout.cell (make_cell (layout, mn.c_str ()));
cell->insert (db::CellInstArray (db::CellInst (foreign_cell->cell_index ()), db::Trans (db::Point () - macro_desc.origin) * macro_desc.foreign_trans));
} else {
@ -1779,7 +1885,7 @@ LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std:
std::string cn = mn + mask_suffix;
cell = &layout.cell (layout.add_cell (cn.c_str ()));
cell = &layout.cell (make_cell (layout, cn.c_str ()));
if (mg->is_fixedmask ()) {
mg->create_cell (*this, layout, *cell, 0, std::vector<unsigned int> (), nm);
@ -1819,6 +1925,8 @@ LEFDEFImporter::get_mask (long m)
void
LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state)
{
tl::log << tl::to_string (tr ("Reading LEF/DEF file")) << " " << stream.absolute_path ();
m_fn = stream.filename ();
tl::AbsoluteProgress progress (tl::to_string (tr ("Reading ")) + m_fn, 1000);
@ -1827,6 +1935,7 @@ LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderS
progress.set_unit (10000.0);
mp_reader_state = &state;
mp_reader_state->attach_reader (this);
if (state.tech_comp ()) {
m_options = *state.tech_comp ();
@ -1863,11 +1972,13 @@ LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderS
do_read (layout);
mp_reader_state->attach_reader (0);
delete mp_stream;
mp_stream = 0;
mp_progress = 0;
} catch (...) {
mp_reader_state->attach_reader (0);
delete mp_stream;
mp_stream = 0;
mp_progress = 0;

View File

@ -27,6 +27,7 @@
#include "dbPluginCommon.h"
#include "dbLayout.h"
#include "dbReader.h"
#include "dbCommonReader.h"
#include "dbStreamLayers.h"
#include "tlStream.h"
#include "tlVariant.h"
@ -44,6 +45,7 @@ namespace db
{
class LEFDEFReaderState;
class LEFDEFImporter;
struct MacroDesc;
/**
@ -1021,7 +1023,8 @@ private:
*/
enum LayerPurpose
{
Routing = 0, // from DEF only
None = 0,
Routing, // from DEF only
Pins, // from DEF
Fills, // from DEF
FillsOPC, // from DEF
@ -1035,6 +1038,9 @@ enum LayerPurpose
Blockage, // from DEF only
PlacementBlockage, // from DEF only
Regions, // from DEF only
RegionsNone, // from DEF only
RegionsFence, // from DEF only
RegionsGuide, // from DEF only
All // from DEF only
};
@ -1049,7 +1055,12 @@ struct LayerDetailsKey
LayerDetailsKey (LayerPurpose _purpose, unsigned int _mask = 0, const db::DVector &_via_size = db::DVector ())
: purpose (_purpose), mask (_mask), via_size (_via_size)
{ }
{
// normalize the via size such that x is smaller than y size (issue-1065)
if (via_size.y () < via_size.x ()) {
via_size = db::DVector (via_size.y (), via_size.x ());
}
}
bool operator< (const LayerDetailsKey &other) const
{
@ -1195,6 +1206,7 @@ private:
struct Via {
Via () : bottom_mask (0), cut_mask (0), top_mask (0) { }
std::string name;
std::string nondefaultrule;
unsigned int bottom_mask, cut_mask, top_mask;
db::Trans trans;
};
@ -1215,6 +1227,7 @@ private:
* This class will handle the creation and management of layers in the LEF/DEF reader context
*/
class DB_PLUGIN_PUBLIC LEFDEFReaderState
: public db::CommonReaderBase
{
public:
/**
@ -1227,12 +1240,22 @@ public:
*/
~LEFDEFReaderState ();
/**
* @brief Attaches to or detaches from an importer
*/
void attach_reader (LEFDEFImporter *importer)
{
mp_importer = importer;
}
/**
* @brief Reads the given map file
*
* Usually this file is read by the constructor. This method is provided for test purposes.
* The filename can be a list of files, separated by "+" or ",". They are loaded together into
* the same map like they were concatenated.
*/
void read_map_file (const std::string &path, db::Layout &layout);
void read_map_file (const std::string &filename, db::Layout &layout, const std::string &base_path);
/**
* @brief Gets the layer map
@ -1272,17 +1295,17 @@ public:
*
* The generator is capable of creating a via for a specific mask configuration
*/
void register_via_cell (const std::string &vn, LEFDEFLayoutGenerator *generator);
void register_via_cell (const std::string &vn, const std::string &nondefaultrule, LEFDEFLayoutGenerator *generator);
/**
* @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, Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm);
db::Cell *via_cell (const std::string &vn, const std::string &nondefaultrule, Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm);
/**
* @brief Gets the via generator for a given via name or 0 if there is no such generator
*/
LEFDEFLayoutGenerator *via_generator (const std::string &vn);
LEFDEFLayoutGenerator *via_generator (const std::string &vn, const std::string &nondefaultrule);
/**
* @brief Registers a macro generator for the macro with the given name
@ -1317,19 +1340,23 @@ public:
return m_foreign_cells;
}
protected:
virtual void common_reader_error (const std::string &msg);
virtual void common_reader_warn (const std::string &msg);
private:
/**
* @brief A key for the via cache
*/
struct ViaKey
{
ViaKey (const std::string &n, unsigned int mb, unsigned int mc, unsigned int mt)
: name (n), mask_bottom (mb), mask_cut (mc), mask_top (mt)
ViaKey (const std::string &n, const std::string &ndr, unsigned int mb, unsigned int mc, unsigned int mt)
: name (n), nondefaultrule (ndr), mask_bottom (mb), mask_cut (mc), mask_top (mt)
{ }
bool operator== (const ViaKey &other) const
{
return name == other.name && mask_bottom == other.mask_bottom && mask_cut == other.mask_cut && mask_top == other.mask_top;
return name == other.name && nondefaultrule == other.nondefaultrule && mask_bottom == other.mask_bottom && mask_cut == other.mask_cut && mask_top == other.mask_top;
}
bool operator< (const ViaKey &other) const
@ -1337,6 +1364,9 @@ private:
if (name != other.name) {
return name < other.name;
}
if (nondefaultrule != other.nondefaultrule) {
return nondefaultrule < other.nondefaultrule;
}
if (mask_bottom != other.mask_bottom) {
return mask_bottom < other.mask_bottom;
}
@ -1349,7 +1379,7 @@ private:
return false;
}
std::string name;
std::string name, nondefaultrule;
unsigned int mask_bottom, mask_cut, mask_top;
};
@ -1389,6 +1419,7 @@ private:
LEFDEFReaderState (const LEFDEFReaderState &);
LEFDEFReaderState &operator= (const LEFDEFReaderState &);
LEFDEFImporter *mp_importer;
std::map <std::pair<std::string, LayerDetailsKey>, std::set<unsigned int> > m_layers;
db::LayerMap m_layer_map;
bool m_create_layers;
@ -1397,13 +1428,14 @@ private:
std::map<std::string, int> m_default_number;
const LEFDEFReaderOptions *mp_tech_comp;
std::map<ViaKey, db::Cell *> m_via_cells;
std::map<std::string, LEFDEFLayoutGenerator *> m_via_generators;
std::map<std::pair<std::string, std::string>, LEFDEFLayoutGenerator *> m_via_generators;
std::map<MacroKey, std::pair<db::Cell *, db::Trans> > m_macro_cells;
std::map<std::string, LEFDEFLayoutGenerator *> m_macro_generators;
std::map<std::string, db::cell_index_type> m_foreign_cells;
std::set<unsigned int> open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
db::cell_index_type foreign_cell(Layout &layout, const std::string &name);
void read_single_map_file (const std::string &path, std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> > &layer_map);
};
/**
@ -1453,6 +1485,8 @@ struct DB_PLUGIN_PUBLIC MacroDesc
class DB_PLUGIN_PUBLIC LEFDEFImporter
{
public:
friend class LEFDEFReaderState;
/**
* @brief Default constructor
*/

View File

@ -123,6 +123,9 @@ LEFDEFReader::read_lefdef (db::Layout &layout, const db::LoadLayoutOptions &opti
db::LEFDEFReaderState state (&effective_options, layout, base_path);
db::CommonReaderOptions common_options = options.get_options<db::CommonReaderOptions> ();
state.set_conflict_resolution_mode (common_options.cell_conflict_resolution);
layout.dbu (effective_options.dbu ());
if (import_lef) {

View File

@ -380,7 +380,7 @@ LEFImporter::read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, Laye
}
void
LEFImporter::read_nondefaultrule (db::Layout & /*layout*/)
LEFImporter::read_nondefaultrule (db::Layout &layout)
{
// read NONDEFAULTRULE sections
std::string n = get ();
@ -408,11 +408,7 @@ LEFImporter::read_nondefaultrule (db::Layout & /*layout*/)
} else if (test ("VIA")) {
// ignore VIA statements
std::string v = get ();
while (! test ("END") || ! test (v)) {
take ();
}
read_viadef (layout, n);
} else {
while (! at_end () && ! test (";")) {
@ -640,7 +636,7 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc
}
void
LEFImporter::read_viadef (Layout &layout)
LEFImporter::read_viadef (Layout &layout, const std::string &nondefaultrule)
{
std::string n = get ();
@ -653,11 +649,11 @@ LEFImporter::read_viadef (Layout &layout)
if (test ("VIARULE")) {
std::unique_ptr<RuleBasedViaGenerator> vg (new RuleBasedViaGenerator ());
read_viadef_by_rule (vg.get (), via_desc, n, layout.dbu ());
reader_state ()->register_via_cell (n, vg.release ());
reader_state ()->register_via_cell (n, nondefaultrule, vg.release ());
} else {
std::unique_ptr<GeometryBasedLayoutGenerator> vg (new GeometryBasedLayoutGenerator ());
read_viadef_by_geometry (vg.get (), via_desc, n, layout.dbu ());
reader_state ()->register_via_cell (n, vg.release ());
reader_state ()->register_via_cell (n, nondefaultrule, vg.release ());
}
test ("VIA");
@ -1064,7 +1060,7 @@ LEFImporter::do_read (db::Layout &layout)
} else if (test ("VIA")) {
read_viadef (layout);
read_viadef (layout, std::string ());
} else if (test ("BEGINEXT")) {

View File

@ -147,7 +147,7 @@ private:
std::vector <db::Trans> get_iteration (double dbu);
void read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, 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 (Layout &layout, const std::string &nondefaultrule);
void read_viadef_by_rule (RuleBasedViaGenerator *vg, ViaDesc &desc, const std::string &n, double dbu);
void read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc &desc, const std::string &n, double dbu);
void read_layer (Layout &layout);

View File

@ -50,7 +50,7 @@ static db::LEFDEFReaderOptions default_options ()
return tc;
}
static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *filename, const db::LEFDEFReaderOptions &options, bool priv = true)
static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *filename, const db::LEFDEFReaderOptions &options, bool priv = true, db::CellConflictResolution cc_mode = db::RenameCell)
{
std::string fn_path (priv ? tl::testdata_private () : tl::testdata ());
fn_path += "/lefdef/";
@ -60,6 +60,7 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f
tl::Extractor ex (filename);
db::LEFDEFReaderState ld (&options, layout, fn_path);
ld.set_conflict_resolution_mode (cc_mode);
db::DEFImporter imp;
bool any_def = false;
@ -69,11 +70,10 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f
if (ex.test ("map:")) {
std::string fn = fn_path, f;
std::string f;
ex.read_word_or_quoted (f);
fn += f;
ld.read_map_file (fn, layout);
ld.read_map_file (f, layout, fn_path);
} else if (ex.test ("def:")) {
@ -142,12 +142,12 @@ static db::LayerMap read (db::Layout &layout, const char *lef_dir, const char *f
return ld.layer_map ();
}
static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true)
static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true, db::CellConflictResolution cc_mode = db::RenameCell)
{
db::Manager m (false);
db::Layout layout (&m), layout2 (&m), layout_au (&m);
db::LayerMap lm = read (layout, lef_dir, filename, options, priv);
db::LayerMap lm = read (layout, lef_dir, filename, options, priv, cc_mode);
// normalize the layout by writing to OASIS and reading from ..
@ -210,6 +210,73 @@ static db::LayerMap run_test (tl::TestBase *_this, const char *lef_dir, const ch
return lm;
}
static void run_test2 (tl::TestBase *_this, const char *lef_dir, const char *filename, const char *filename2, const char *au, const db::LEFDEFReaderOptions &options, bool priv = true, db::CellConflictResolution cc_mode = db::RenameCell)
{
db::Manager m (false);
db::Layout layout (&m), layout2 (&m), layout_au (&m);
read (layout, lef_dir, filename, options, priv, cc_mode);
read (layout, lef_dir, filename2, options, priv, cc_mode);
// normalize the layout by writing to OASIS and reading from ..
// generate a "unique" name ...
unsigned int hash = 0;
if (au) {
for (const char *cp = au; *cp; ++cp) {
hash = (hash << 4) ^ (hash >> 4) ^ ((unsigned int) *cp);
}
}
std::string tmp_file = _this->tmp_file (tl::sprintf ("tmp_%x.oas", hash));
{
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);
}
{
tl::InputStream stream (tmp_file);
db::Reader reader (stream);
reader.read (layout2);
}
if (au) {
std::string fn (priv ? tl::testdata_private () : tl::testdata ());
fn += "/lefdef/";
fn += lef_dir;
fn += "/";
fn += au;
try {
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (layout_au);
} catch (...) {
_this->raise (tl::sprintf ("Compare failed - see %s vs %s (not existing or not readable)\n", tmp_file, fn));
throw;
}
bool equal = db::compare_layouts (layout2, layout_au, db::layout_diff::f_verbose | db::layout_diff::f_flatten_array_insts, 0);
if (! equal) {
_this->raise (tl::sprintf ("Compare failed - see %s vs %s\n", tmp_file, fn));
}
} else {
bool equal = db::compare_layouts (layout2, layout_au, db::layout_diff::f_verbose | db::layout_diff::f_flatten_array_insts, 0);
if (! equal) {
_this->raise (tl::sprintf ("Compare failed - see %s vs empty file\n", tmp_file));
}
}
}
TEST(1)
{
run_test (_this, "lef1", "lef:in.lef", 0, default_options ());
@ -252,7 +319,7 @@ TEST(7)
TEST(10)
{
run_test (_this, "def1", "lef:in.lef+def:in.def", "au.oas.gz", default_options ());
run_test (_this, "def1", "lef:in.lef+def:in.def", "au2.oas.gz", default_options ());
}
TEST(11)
@ -271,7 +338,7 @@ TEST(12)
TEST(13)
{
run_test (_this, "def4", "lef:in.lef+def:in.def", "au.oas.gz", default_options ());
run_test (_this, "def4", "lef:in.lef+def:in.def", "au2.oas.gz", default_options ());
}
TEST(14)
@ -342,6 +409,13 @@ TEST(23)
run_test (_this, "def14", "map:test.map+lef:tech.lef+lef:stdlib.lef+def:test.def", "au.oas.gz", opt);
}
TEST(24)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_macro_resolution_mode (1);
run_test (_this, "def15", "map:test.map+lef:tech.lef+def:test.def", "au2.oas.gz", opt);
}
TEST(100)
{
run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false);
@ -720,7 +794,7 @@ TEST(117_mapfile_all)
"'+M1.LEFOBS;M1.LEFPIN;M1.NET;M1.PIN;M1.SPNET;M1.VIA : \\'M1.NET/PIN/SPNET/...\\' (1/5)';"
"'+M1.NET;M1.SPNET : \\'M1.NET/SPNET\\' (16/0)';"
"'+M1.NET : M1.NET (18/0)';"
"'+M1.BLK;M1.FILL;M1.FILLOPC;M1.LEFOBS;M1.LEFPIN;M1.NET;M1.PIN;M1.SPNET;M1.VIA : \\'M1.NET/PIN/FILL/...\\' (22/2)';"
"'+M1.FILL;M1.FILLOPC;M1.LEFOBS;M1.LEFPIN;M1.NET;M1.PIN;M1.SPNET;M1.VIA : \\'M1.NET/PIN/FILL/...\\' (22/2)';"
"'+\\'M1.NET:1\\';\\'M1.PIN:1\\';\\'M1.SPNET:1\\';\\'M1.VIA:1\\' : \\'M1.NET:1/PIN:1/...\\' (6/0)';"
"'+\\'M1.NET:1\\' : \\'M1.NET:1\\' (7/0)';"
"'+M1.PIN : M1.PIN (3/0)';"
@ -736,7 +810,7 @@ TEST(117_mapfile_all)
"'M1.LABEL : M1.LABEL (26/0)';"
// NAME M1/NET not supported: "'+M1.LABEL : M1.LABEL (27/0)';"
// NAME M1/SPNET not supported: "'+M1.LABEL : M1.LABEL (28/1)';"
"'+M1.BLK : M1.BLK (13/0)';"
"'M1.BLK : M1.BLK (13/0)';"
"'M1_TEXT.LABEL;M1_TEXT.LEFLABEL : \\'M1_TEXT.LABEL/M1_TEXT.LEFLABEL\\' (29/0)'"
")"
)
@ -780,6 +854,18 @@ TEST(130_viasize)
run_test (_this, "viasize", "map:test.map+lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
}
// issue-1065
TEST(130_viasize2)
{
run_test (_this, "viasize2", "map:test_ok.map+lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
run_test (_this, "viasize2", "map:test_fail.map+lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
}
TEST(131_patternname)
{
run_test (_this, "patternname", "map:v.map+lef:v.lef+def:v.def", "au.oas.gz", default_options (), false);
}
TEST(200_lefdef_plugin)
{
db::Layout ly;
@ -826,3 +912,21 @@ TEST(201_lefdef_plugin_explicit_lef)
db::compare_layouts (_this, ly, fn_path + "au_plugin_alt_lef.oas.gz", db::WriteOAS);
}
TEST(202_lefdef_blend_mode)
{
db::LEFDEFReaderOptions lefdef_opt = default_options ();
run_test2 (_this, "blend_mode", "map:layers.map+lef:sub.lef+def:top.def", "map:layers.map+def:sub.def", "au1.oas.gz", lefdef_opt, false);
run_test2 (_this, "blend_mode", "map:layers.map+lef:sub.lef+def:top.def", "map:layers.map+def:sub.def", "au2.oas.gz", lefdef_opt, false, db::AddToCell);
lefdef_opt.set_macro_resolution_mode (2);
run_test2 (_this, "blend_mode", "map:layers.map+lef:sub.lef+def:top.def", "map:layers.map+def:sub.def", "au3.oas.gz", lefdef_opt, false);
}
TEST(203_regionsAndMapfileConcat)
{
db::LEFDEFReaderOptions lefdef_opt = default_options ();
run_test (_this, "map_regions", "map:'test.map,test.add.map'+lef:test.lef+def:test.def", "au.oas.gz", lefdef_opt, false);
}

View File

@ -104,8 +104,9 @@ OASISReader::init (const db::LoadLayoutOptions &options)
{
CommonReader::init (options);
m_read_texts = common_options ().enable_text_objects;
m_read_properties = common_options ().enable_properties;
db::CommonReaderOptions common_options = options.get_options<db::CommonReaderOptions> ();
m_read_texts = common_options.enable_text_objects;
m_read_properties = common_options.enable_properties;
db::OASISReaderOptions oasis_options = options.get_options<db::OASISReaderOptions> ();
m_read_all_properties = oasis_options.read_all_properties;

BIN
testdata/lefdef/blend_mode/au1.oas.gz vendored Normal file

Binary file not shown.

BIN
testdata/lefdef/blend_mode/au2.oas.gz vendored Normal file

Binary file not shown.

BIN
testdata/lefdef/blend_mode/au3.oas.gz vendored Normal file

Binary file not shown.

4
testdata/lefdef/blend_mode/layers.map vendored Normal file
View File

@ -0,0 +1,4 @@
DIEAREA ALL 100 0
M1 ALL 12 0
VIA1 ALL 13 0
M2 ALL 14 0

3
testdata/lefdef/blend_mode/sub.def vendored Normal file
View File

@ -0,0 +1,3 @@
DESIGN sub ;
DIEAREA ( 0 0 ) ( 200 200 ) ;
END DESIGN

4
testdata/lefdef/blend_mode/sub.lef vendored Normal file
View File

@ -0,0 +1,4 @@
MACRO sub
SIZE .1 BY .1 ;
END sub
END LIBRARY

6
testdata/lefdef/blend_mode/top.def vendored Normal file
View File

@ -0,0 +1,6 @@
DESIGN top ;
DIEAREA ( 0 0 ) ( 1000 1000 ) ;
COMPONENTS 1 ;
- sub sub + PLACED ( 0 0 ) N ;
END COMPONENTS
END DESIGN

BIN
testdata/lefdef/map_regions/au.oas.gz vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,5 @@
BLOCKAGE ALL 20 0
REGION ALL 1 0
REGION FENCE 2 0
REGION GUIDE 3 0
REGION NONE 4 0

12
testdata/lefdef/map_regions/test.def vendored Normal file
View File

@ -0,0 +1,12 @@
DESIGN test ;
DIEAREA ( 0 0 ) ( 1000 1000 ) ;
UNITS DISTANCE MICRONS 1000 ;
REGIONS 3 ;
- a ( 100 700 ) ( 300 900 ) ;
- b ( 700 700 ) ( 900 900 ) + TYPE GUIDE ;
- c ( 100 100 ) ( 900 200 ) ( 100 200 ) ( 200 300 ) ( 800 200 ) ( 900 300 ) + TYPE FENCE ;
END REGIONS
BLOCKAGES 51 ;
- PLACEMENT RECT ( 450 450 ) ( 550 550 ) ;
END BLOCKAGES
END DESIGN

4
testdata/lefdef/map_regions/test.lef vendored Normal file
View File

@ -0,0 +1,4 @@
UNITS
DATABASE MICRONS 1000 ;
END UNITS
END LIBRARY

1
testdata/lefdef/map_regions/test.map vendored Normal file
View File

@ -0,0 +1 @@
DIEAREA ALL 10 0

Binary file not shown.

6
testdata/lefdef/patternname/Makefile vendored Normal file
View File

@ -0,0 +1,6 @@
v:
time strm2oas \
--lefdef-map v.map \
--lefdef-lefs v.lef \
v.def v.oas

BIN
testdata/lefdef/patternname/au.oas.gz vendored Normal file

Binary file not shown.

15
testdata/lefdef/patternname/v.def vendored Normal file
View File

@ -0,0 +1,15 @@
DESIGN top ;
VIAS 1 ;
- M1H_M2V-1400-1400-ALL-2-2 + PATTERNNAME M1H_M2V-1400-1400-I3
+ RECT M1 ( -700 -620 ) ( 700 620 )
+ RECT M2 ( -610 -700 ) ( 610 700 )
+ RECT VIA1 ( -600 -600 ) ( -220 -220 )
+ RECT VIA1 ( 220 -600 ) ( 600 -220 )
+ RECT VIA1 ( -600 220 ) ( -220 600 )
+ RECT VIA1 ( 220 220 ) ( 600 600 ) ;
END VIAS
NETS 1 ;
- dummy + ROUTED M1 ( 0 0 ) M1H_M2V-1400-1400-ALL-2-2 ;
END NETS
END DESIGN

26
testdata/lefdef/patternname/v.lef vendored Normal file
View File

@ -0,0 +1,26 @@
VERSION 5.4 ;
NAMESCASESENSITIVE ON ;
BUSBITCHARS "[]" ;
DIVIDERCHAR "/" ;
NOWIREEXTENSIONATPIN OFF ;
UNITS
DATABASE MICRONS 2000 ;
END UNITS
MANUFACTURINGGRID 0.005 ;
LAYER M1
TYPE ROUTING ;
END M1
LAYER VIA1
TYPE CUT ;
END VIA1
LAYER M2
TYPE ROUTING ;
END M2
END LIBRARY

3
testdata/lefdef/patternname/v.map vendored Normal file
View File

@ -0,0 +1,3 @@
M1 ALL 31 0
M2 ALL 32 0
VIA1 ALL 51 0

BIN
testdata/lefdef/viasize2/au.oas.gz vendored Normal file

Binary file not shown.

37
testdata/lefdef/viasize2/test.def vendored Executable file
View File

@ -0,0 +1,37 @@
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_small
+ RECT M1 ( -20 -15 ) ( 20 15 )
+ RECT VIA1 ( -10 -10 ) ( 10 10 )
+ RECT M2 ( -25 -25 ) ( 25 25 ) ;
- VIA1_bar
+ RECT M1 ( -20 -15 ) ( 20 15 )
+ RECT VIA1 ( -12 -10 ) ( 12 10 )
+ RECT M2 ( -25 -25 ) ( 25 25 ) ;
- VIA1_large
+ RECT M1 ( -20 -15 ) ( 20 15 )
+ RECT VIA1 ( -12 -12 ) ( 12 12 )
+ RECT M2 ( -25 -25 ) ( 25 25 ) ;
END VIAS
SPECIALNETS 1 ;
- dummy
+ ROUTED + RECT M2 ( 350 0 ) ( 250 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 ) + VIA VIA1_bar E ( 100 200 )
+ ROUTED M1 30 + MASK 2 ( 0 0 15 ) ( 100 0 0 ) VIA1_small ( 100 100 10 )
+ ROUTED M2 50 + SHAPE RING + STYLE 1 ( 0 100 ) ( 100 200 ) ( 200 200 )
+ ROUTED + MASK 2 + RECT M2 ( 250 0 ) ( 150 100 )
+ ROUTED + SHAPE RING + MASK 1 + VIA VIA1_large E ( 200 200 )
;
END SPECIALNETS
END DESIGN

24
testdata/lefdef/viasize2/test.lef vendored Executable file
View File

@ -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

9
testdata/lefdef/viasize2/test_fail.map vendored Executable file
View File

@ -0,0 +1,9 @@
# some variations of map file entries
DIEAREA ALL 1 0
COMP ALL 2 0
M1 NET,SPNET 7 0
M2 NET,SPNET 9 0
VIA1 VIA 8 0
VIA1 VIA:SIZE:0.02x0.02 8 1
VIA1 VIA:SIZE:0.02x0.024 8 2
VIA1 VIA:SIZE:0.024x0.024 8 3

9
testdata/lefdef/viasize2/test_ok.map vendored Executable file
View File

@ -0,0 +1,9 @@
# some variations of map file entries
DIEAREA ALL 1 0
COMP ALL 2 0
M1 NET,SPNET 7 0
M2 NET,SPNET 9 0
VIA1 VIA 8 0
VIA1 VIA:SIZE:0.02x0.02 8 1
VIA1 VIA:SIZE:0.024x0.02 8 2
VIA1 VIA:SIZE:0.024x0.024 8 3