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 ()); 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_via_cellname_prefix = std::string ();
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_produce_cell_outlines = load_options.get_option_by_name ("lefdef_config.produce_cell_outlines").to_bool (); 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 (); 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_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_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_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_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_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 (); 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]"); std::string group ("[" + m_group_prefix + " options - LEF/DEF specific]");
cmd << tl::arg (group + 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", "#--" + 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" "This option gives the name of the shape property used to annotate net names. For 'spec' use:\n"
"\n" "\n"
"* \"#n\" for property number \"n\" (compatible with GDS2)\n" "* \"#n\" for property number \"n\" (compatible with GDS2)\n"
"* A plain word for a named property (not compatible with GDS2)\n" "* A plain word for a named property (not compatible with GDS2)\n"
"\n" "\n"
"Producing net name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-net-names'." "By default, net names are not produced."
)
<< 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."
) )
<< tl::arg (group + << 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", "#--" + 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. " "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'." "For the 'spec' format see '--" + m_long_prefix + "lefdef-net-property-name'."
"\n" "\n"
"Producing instance name annotation properties can be turned off with '--" + m_long_prefix + "lefdef-dont-produce-instance-names'." "By default, instance names are not produced."
)
<< 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."
) )
<< tl::arg (group + << 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", "#--" + 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. " "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'." "For the 'spec' format see '--" + m_long_prefix + "lefdef-net-property-name'."
"\n" "\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 + << tl::arg (group +
"#!--" + m_long_prefix + "lefdef-dont-produce-cell-outlines", &m_lefdef_produce_cell_outlines, "Disables producing cell outlines", "#!--" + 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" "layers need to specified individually for different layer/purpose combinations.\n"
"\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 ...) " "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" "layer name and using layer/purpose in the purpose column allows mapping labels to specific layers.\n"
"\n" "\n"
"This is an example for a layer map file:\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" "VIA1 LEFPIN,VIA,PIN,NET,SPNET 13 0\n"
"M2 LEFPIN,PIN,NET,SPNET,VIA 14 0\n" "M2 LEFPIN,PIN,NET,SPNET,VIA 14 0\n"
"\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 + << tl::arg (group +
"!--" + m_long_prefix + "lefdef-macro-resolution-mode", &m_lefdef_macro_resolution_mode, "Specify how to generate layout from LEF macros", "!--" + 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.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.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.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.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_produce_inst_names ? tl::Variant (m_lefdef_inst_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_produce_pin_names ? tl::Variant (m_lefdef_pin_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.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.cell_outline_layer", m_lefdef_cell_outline_layer);
load_options.set_option_by_name ("lefdef_config.produce_placement_blockages", m_lefdef_produce_placement_blockages); 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); void set_read_named_layers (bool f);
// LEFDEF // LEFDEF
bool m_lefdef_produce_net_names;
std::string m_lefdef_net_property_name; std::string m_lefdef_net_property_name;
bool m_lefdef_produce_inst_names;
std::string m_lefdef_inst_property_name; std::string m_lefdef_inst_property_name;
bool m_lefdef_produce_pin_names;
std::string m_lefdef_pin_property_name; std::string m_lefdef_pin_property_name;
bool m_lefdef_produce_cell_outlines; bool m_lefdef_produce_cell_outlines;
std::string m_lefdef_cell_outline_layer; 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 (); static const size_t null_id = std::numeric_limits<size_t>::max ();
CommonReader::CommonReader () CommonReaderBase::CommonReaderBase ()
: m_cc_resolution (AddToCell), m_create_layers (false) : m_cc_resolution (AddToCell), m_create_layers (false)
{ {
// .. nothing yet .. // .. nothing yet ..
} }
db::cell_index_type 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 ()); tl_assert (! cn.empty ());
@ -69,13 +69,13 @@ CommonReader::make_cell (db::Layout &layout, const std::string &cn)
} }
bool 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 (); return m_name_map.find (cn) != m_name_map.end ();
} }
std::pair<bool, db::cell_index_type> 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); 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 ()) { if (iname != m_name_map.end ()) {
@ -86,7 +86,7 @@ CommonReader::cell_by_name (const std::string &cn) const
} }
db::cell_index_type 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); tl_assert (id != null_id);
@ -114,13 +114,13 @@ CommonReader::make_cell (db::Layout &layout, size_t id)
} }
bool 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 (); return m_id_map.find (id) != m_id_map.end ();
} }
std::pair<bool, db::cell_index_type> 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); 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 ()) { if (iid != m_id_map.end ()) {
@ -131,7 +131,7 @@ CommonReader::cell_by_id (size_t id) const
} }
const std::string & 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); std::map<size_t, std::string>::const_iterator n = m_name_for_id.find (id);
if (n != m_name_for_id.end ()) { if (n != m_name_for_id.end ()) {
@ -143,7 +143,7 @@ CommonReader::name_for_id (size_t id) const
} }
void 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)); 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 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); tl_assert (id != null_id);
@ -213,7 +213,7 @@ CommonReader::cell_for_instance (db::Layout &layout, size_t id)
} }
db::cell_index_type 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 ()); tl_assert (! cn.empty ());
@ -235,7 +235,7 @@ CommonReader::cell_for_instance (db::Layout &layout, const std::string &cn)
} }
void 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); const db::Cell &src_cell = layout.cell (src_cell_index);
db::Cell &target_cell = layout.cell (target_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 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); const db::Cell &src_cell = layout.cell (src_cell_index);
db::Cell &target_cell = layout.cell (target_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 ()); 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 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_layer_map_out.clear ();
m_multi_mapping_placeholders.clear (); m_multi_mapping_placeholders.clear ();
m_layer_cache.clear (); m_layer_cache.clear ();
@ -329,7 +292,7 @@ CommonReader::init (const LoadLayoutOptions &options)
} }
void void
CommonReader::finish (db::Layout &layout) CommonReaderBase::finish (db::Layout &layout)
{ {
bool any_missing = false; bool any_missing = false;
@ -492,7 +455,7 @@ CommonReader::finish (db::Layout &layout)
} }
std::pair <bool, unsigned int> 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); std::map<db::LDPair, std::pair <bool, unsigned int> >::const_iterator lc = m_layer_cache.find (dl);
if (lc != m_layer_cache.end ()) { if (lc != m_layer_cache.end ()) {
@ -505,9 +468,9 @@ CommonReader::open_dl (db::Layout &layout, const LDPair &dl)
} }
std::pair <bool, unsigned int> 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 (li.empty ()) {
if (! m_create_layers) { 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 // 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 * @brief A common reader base for GDS2 and OASIS providing common services for both readers
*/ */
class DB_PUBLIC CommonReader class DB_PUBLIC CommonReaderBase
: public ReaderBase
{ {
public: public:
typedef tl::interval_map <db::ld_type, tl::interval_map <db::ld_type, std::string> > layer_name_map; 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 * @brief Constructor
*/ */
CommonReader (); CommonReaderBase ();
/** /**
* @brief Make a cell from a name * @brief Make a cell from a name
@ -205,17 +204,40 @@ public:
*/ */
void finish (db::Layout &layout); void finish (db::Layout &layout);
// Reimplementation of the ReaderBase interace /**
virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions &options); * @brief Re-initialize: clears the tables and caches
virtual const db::LayerMap &read (db::Layout &layout); */
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: protected:
friend class CommonReaderLayerMapping; friend class CommonReaderLayerMapping;
virtual void common_reader_error (const std::string &msg) = 0; virtual void common_reader_error (const std::string &msg) = 0;
virtual void common_reader_warn (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 * @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; 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 * @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); 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; std::map<size_t, std::string> m_name_for_id;
CellConflictResolution m_cc_resolution; CellConflictResolution m_cc_resolution;
bool m_create_layers; bool m_create_layers;
db::CommonReaderOptions m_common_options; db::LayerMap m_layer_map;
db::LayerMap m_layer_map_out; db::LayerMap m_layer_map_out;
tl::interval_map <db::ld_type, tl::interval_map <db::ld_type, std::string> > m_layer_names; 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; 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); 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 * @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); 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> (); 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_allow_multi_xy_records = gds2_options.allow_multi_xy_records;
m_box_mode = gds2_options.box_mode; 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 // 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 // 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. // 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); 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); 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 void
@ -205,22 +212,39 @@ DEFImporter::read_nondefaultrules (double scale)
} }
void 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 ("-")) { while (test ("-")) {
std::string n = get (); 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 (";")) { while (! peek (";")) {
if (test ("+")) { if (test ("+")) {
// ignore other options for now if (test ("TYPE")) {
while (! peek (";")) {
take (); 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 { } else {
@ -379,7 +403,11 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u
// compute begin extension // compute begin extension
db::Coord be = 0; db::Coord be = 0;
if (pt0 == pts.begin ()) { 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) { } else if (was_path_before) {
// provides the overlap to the previous segment // provides the overlap to the previous segment
be = wxy_perp / 2; be = wxy_perp / 2;
@ -388,15 +416,32 @@ DEFImporter::produce_routing_geometry (db::Cell &design, const Polygon *style, u
// compute end extension // compute end extension
db::Coord ee = 0; db::Coord ee = 0;
if (pt + 1 == pts.end ()) { 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); db::Path p (pt0, pt + 1, wxy, be, ee, false);
if (prop_id != 0) { if (prop_id != 0) {
design.shapes (layer).insert (db::object_with_properties<db::Path> (p, prop_id)); design.shapes (layer).insert (db::object_with_properties<db::Path> (p, prop_id));
} else { } else {
design.shapes (layer).insert (p); 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; 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_cut = (mask / 10) % 10;
unsigned int mask_bottom = mask % 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 (cell) {
if (nx <= 1 && ny <= 1) { if (nx <= 1 && ny <= 1) {
design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), db::Vector (pts.back ())))); 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); std::map<std::string, ViaDesc>::const_iterator vd = m_via_desc.find (vn);
if (vd != m_via_desc.end ()) { if (vd != m_via_desc.end ()) {
// TODO: no mask specification here? // 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) { if (cell) {
design.insert (db::CellInstArray (db::CellInst (cell->cell_index ()), db::Trans (ft.rot (), pt))); 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::set<std::string> seen_layers;
std::vector<std::string> routing_layers; std::vector<std::string> routing_layers;
bool has_cut_geometry = false;
bool has_patternname = false;
while (test ("+")) { while (test ("+")) {
bool is_polygon = false; 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_rows (get_long ());
rule_based_vg->set_columns (get_long ()); rule_based_vg->set_columns (get_long ());
} else if (test ("PATTERNNAME")) {
get (); // ignore
has_patternname = true;
} else if (test ("PATTERN")) { } else if (test ("PATTERN")) {
if (! rule_based_vg.get ()) { 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)) { } else if (m_lef_importer.is_cut_layer (ln)) {
geo_based_vg->set_maskshift_layer (1, 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 ()) { if (vd.m1.empty () && vd.m2.empty ()) {
// analyze the layers to find the metals // 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.m1 = routing_layers[0];
vd.m2 = routing_layers[1]; vd.m2 = routing_layers[1];
} else { } 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 ()) { 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"))); 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 ()) { } 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 ()) { } 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 { } else {
error (tl::to_string (tr ("Too little information to generate a via"))); 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 dbu_mic = 1000.0;
double scale = 1.0 / (dbu_mic * layout.dbu ()); 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<DEFImporterGroup> groups;
std::list<std::pair<std::string, db::CellInstArray> > instances; std::list<std::pair<std::string, db::CellInstArray> > instances;
m_via_desc = m_lef_importer.vias (); m_via_desc = m_lef_importer.vias ();
m_styles.clear (); 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 ()) { while (! at_end ()) {
@ -1465,7 +1524,7 @@ DEFImporter::do_read (db::Layout &layout)
} else if (test ("DESIGN")) { } else if (test ("DESIGN")) {
std::string cn = get (); 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 (";"); expect (";");
@ -1651,7 +1710,7 @@ DEFImporter::do_read (db::Layout &layout)
if (! groups.empty () && options ().separate_groups ()) { 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 ())); design.insert (db::CellInstArray (others_cell->cell_index (), db::Trans ()));
// Walk through the groups, create a group container cell and put all instances // 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) { 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 ())); design.insert (db::CellInstArray (group_cell->cell_index (), db::Trans ()));
if (! g->region_name.empty ()) { 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 ()) { 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)); 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 { } else {
std::set<unsigned int> dl = open_layer (layout, std::string (), Regions, 0); for (std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > >::const_iterator rr = r->second.begin (); rr != r->second.end (); ++rr) {
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) { std::set<unsigned int> dl = open_layer (layout, std::string (), rr->first, 0);
group_cell->shapes (*l).insert (*p); 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); regions.erase (r);
} }
@ -1714,12 +1784,19 @@ DEFImporter::do_read (db::Layout &layout)
if (! regions.empty ()) { if (! regions.empty ()) {
std::set<unsigned int> dl = open_layer (layout, std::string (), Regions, 0); LayerPurpose lps [] = { Regions, RegionsNone, RegionsGuide, RegionsFence };
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
for (std::map<std::string, std::vector<db::Polygon> >::const_iterator r = regions.begin (); r != regions.end (); ++r) { for (unsigned int i = 0; i < sizeof (lps) / sizeof (lps[0]); ++i) {
for (std::vector<db::Polygon>::const_iterator p = r->second.begin (); p != r->second.end (); ++p) {
others_cell->shapes (*l).insert (*p); 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); 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_diearea (db::Layout &layout, db::Cell &design, double scale);
void read_nondefaultrules (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_groups (std::list<DEFImporterGroup> &groups, double scale);
void read_blockages (db::Layout &layout, db::Cell &design, double scale); void read_blockages (db::Layout &layout, db::Cell &design, double scale);
void read_nets (db::Layout &layout, db::Cell &design, double scale, bool specialnets); void read_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"; return "OUTLINE";
case Regions: case Regions:
return "REGION"; return "REGION";
case RegionsGuide:
return "REGIONGUIDE";
case RegionsFence:
return "REGIONFENCE";
case RegionsNone:
return "REGIONNONE";
case PlacementBlockage: case PlacementBlockage:
return "BLOCKAGE"; return "BLOCKAGE";
case Routing: case Routing:
@ -143,9 +149,9 @@ static std::string purpose_to_name (LayerPurpose purpose)
return "BLK"; return "BLK";
case All: case All:
return "ALL"; return "ALL";
default:
return std::string ();
} }
return std::string ();
} }
static 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)); 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) { 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 (); 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) { 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) { if (! g) {
continue; continue;
} }
@ -401,7 +407,7 @@ GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &la
unsigned mshift_cut = get_maskshift (msl [1], ext_msl, masks); unsigned mshift_cut = get_maskshift (msl [1], ext_msl, masks);
unsigned mshift_top = get_maskshift (msl [2], 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 [0], v->bottom_mask, mshift_bottom, nm),
combine_maskshifts (msl [1], v->cut_mask, mshift_cut, nm), combine_maskshifts (msl [1], v->cut_mask, mshift_cut, nm),
combine_maskshifts (msl [2], v->top_mask, mshift_top, nm), combine_maskshifts (msl [2], v->top_mask, mshift_top, nm),
@ -868,11 +874,11 @@ LEFDEFReaderOptions::special_routing_datatype_str () const
// LEFDEFLayerDelegate implementation // LEFDEFLayerDelegate implementation
LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout &layout, const std::string &base_path) 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 ()) { 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 { } else {
@ -886,7 +892,7 @@ LEFDEFReaderState::LEFDEFReaderState (const LEFDEFReaderOptions *tc, db::Layout
LEFDEFReaderState::~LEFDEFReaderState () 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; delete i->second;
} }
@ -899,6 +905,22 @@ LEFDEFReaderState::~LEFDEFReaderState ()
m_macro_generators.clear (); 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 void
LEFDEFReaderState::register_layer (const std::string &ln) 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; 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 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; 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::InputFile file (path);
tl::InputStream file_stream (file); tl::InputStream file_stream (file);
tl::TextInputStream ts (file_stream); 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; std::map<std::string, LayerPurpose> purpose_translation;
purpose_translation ["LEFPIN"] = LEFPins; purpose_translation ["LEFPIN"] = LEFPins;
purpose_translation ["PIN"] = Pins; 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 ["BLOCKAGE"] = Blockage;
purpose_translation ["ALL"] = All; purpose_translation ["ALL"] = All;
std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> > layer_map;
while (! ts.at_end ()) { while (! ts.at_end ()) {
const std::string &l = ts.get_line (); 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 l = layers.begin (); l != layers.end (); ++l) {
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) { 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) { } else if (i->second == All) {
for (std::map<std::string, LayerPurpose>::const_iterator p = purpose_translation.begin (); p != purpose_translation.end (); ++p) { 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)); 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. /**
* @brief Returns true, if the layer purpose has a fallback
tl_assert (m_has_explicit_layer_mapping); */
m_layers.clear (); static bool has_fallback (LayerPurpose p)
m_layer_map.clear (); {
return p == RegionsFence || p == RegionsGuide || p == RegionsNone;
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);
}
}
} }
std::set <unsigned int> std::set <unsigned int>
@ -1201,14 +1283,18 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu
std::set <unsigned int> ll; 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); ll = open_layer_uncached (layout, n, purpose, mask);
} }
m_layers.insert (std::make_pair (std::make_pair (n, LayerDetailsKey (purpose, mask)), ll)); m_layers.insert (std::make_pair (std::make_pair (n, LayerDetailsKey (purpose, mask)), ll));
if (ll.empty ()) { if (ll.empty () && ! has_fallback (purpose)) {
tl::warn << tl::to_string (tr ("No mapping for layer")) << " '" << n << "', purpose '" << purpose_to_name (purpose) << "'" << tl::noendl; 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) { if (mask > 0) {
tl::warn << tl::to_string (tr (" Mask ")) << mask << tl::noendl; 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 void
LEFDEFReaderState::finish (db::Layout &layout) LEFDEFReaderState::finish (db::Layout &layout)
{ {
CommonReaderBase::finish (layout);
int lnum = 0; int lnum = 0;
std::set<int> used_numbers; std::set<int> used_numbers;
@ -1606,18 +1694,22 @@ LEFDEFReaderState::finish (db::Layout &layout)
} }
void 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 ()) { if (m_via_generators.find (std::make_pair (vn, nondefaultrule)) != m_via_generators.end ()) {
delete m_via_generators [vn]; delete m_via_generators [std::make_pair (vn, nondefaultrule)];
} }
m_via_generators [vn] = generator; m_via_generators [std::make_pair (vn, nondefaultrule)] = generator;
} }
LEFDEFLayoutGenerator * 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 ()) { if (g != m_via_generators.end ()) {
return g->second; return g->second;
} else { } else {
@ -1626,31 +1718,45 @@ LEFDEFReaderState::via_generator (const std::string &vn)
} }
db::Cell * 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); std::map<ViaKey, db::Cell *>::const_iterator i = m_via_cells.find (vk);
if (i == m_via_cells.end ()) { if (i == m_via_cells.end ()) {
db::Cell *cell = 0; db::Cell *cell = 0;
std::map<std::string, LEFDEFLayoutGenerator *>::const_iterator g = m_via_generators.find (vn);
if (g != m_via_generators.end ()) { if (g != m_via_generators.end ()) {
LEFDEFLayoutGenerator *vg = g->second; LEFDEFLayoutGenerator *vg = g->second;
std::string mask_suffix; std::string n = vn;
if (mask_bottom > 0 || mask_cut > 0 || mask_top > 0) {
mask_suffix += "_"; if (! vk.nondefaultrule.empty ()) {
mask_suffix += tl::to_string (mask_bottom); n += "_";
mask_suffix += "_"; n += vk.nondefaultrule;
mask_suffix += tl::to_string (mask_cut);
mask_suffix += "_";
mask_suffix += tl::to_string (mask_top);
} }
std::string cn = mp_tech_comp->via_cellname_prefix () + vn + mask_suffix; if (mask_bottom > 0 || mask_cut > 0 || mask_top > 0) {
cell = &layout.cell (layout.add_cell (cn.c_str ())); 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; std::vector<unsigned int> masks;
masks.reserve (3); masks.reserve (3);
@ -1705,7 +1811,7 @@ LEFDEFReaderState::foreign_cell (Layout &layout, const std::string &name)
if (cc.first) { if (cc.first) {
ci = cc.second; ci = cc.second;
} else { } else {
ci = layout.add_cell (name.c_str ()); ci = make_cell (layout, name.c_str ());
layout.cell (ci).set_ghost_cell (true); 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) { if (macro_desc.foreign_name != mn) {
// create an indirection for renaming the cell // 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)); cell->insert (db::CellInstArray (db::CellInst (foreign_cell->cell_index ()), db::Trans (db::Point () - macro_desc.origin) * macro_desc.foreign_trans));
} else { } else {
@ -1779,7 +1885,7 @@ LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std:
std::string cn = mn + mask_suffix; 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 ()) { if (mg->is_fixedmask ()) {
mg->create_cell (*this, layout, *cell, 0, std::vector<unsigned int> (), nm); mg->create_cell (*this, layout, *cell, 0, std::vector<unsigned int> (), nm);
@ -1819,6 +1925,8 @@ LEFDEFImporter::get_mask (long m)
void void
LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderState &state) 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 (); m_fn = stream.filename ();
tl::AbsoluteProgress progress (tl::to_string (tr ("Reading ")) + m_fn, 1000); 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); progress.set_unit (10000.0);
mp_reader_state = &state; mp_reader_state = &state;
mp_reader_state->attach_reader (this);
if (state.tech_comp ()) { if (state.tech_comp ()) {
m_options = *state.tech_comp (); m_options = *state.tech_comp ();
@ -1863,11 +1972,13 @@ LEFDEFImporter::read (tl::InputStream &stream, db::Layout &layout, LEFDEFReaderS
do_read (layout); do_read (layout);
mp_reader_state->attach_reader (0);
delete mp_stream; delete mp_stream;
mp_stream = 0; mp_stream = 0;
mp_progress = 0; mp_progress = 0;
} catch (...) { } catch (...) {
mp_reader_state->attach_reader (0);
delete mp_stream; delete mp_stream;
mp_stream = 0; mp_stream = 0;
mp_progress = 0; mp_progress = 0;

View File

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

View File

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

View File

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

View File

@ -50,7 +50,7 @@ static db::LEFDEFReaderOptions default_options ()
return tc; 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 ()); std::string fn_path (priv ? tl::testdata_private () : tl::testdata ());
fn_path += "/lefdef/"; 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); tl::Extractor ex (filename);
db::LEFDEFReaderState ld (&options, layout, fn_path); db::LEFDEFReaderState ld (&options, layout, fn_path);
ld.set_conflict_resolution_mode (cc_mode);
db::DEFImporter imp; db::DEFImporter imp;
bool any_def = false; 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:")) { if (ex.test ("map:")) {
std::string fn = fn_path, f; std::string f;
ex.read_word_or_quoted (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:")) { } 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 (); 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::Manager m (false);
db::Layout layout (&m), layout2 (&m), layout_au (&m); 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 .. // 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; 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) TEST(1)
{ {
run_test (_this, "lef1", "lef:in.lef", 0, default_options ()); run_test (_this, "lef1", "lef:in.lef", 0, default_options ());
@ -252,7 +319,7 @@ TEST(7)
TEST(10) 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) TEST(11)
@ -271,7 +338,7 @@ TEST(12)
TEST(13) 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) 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); 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) TEST(100)
{ {
run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false); 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.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.SPNET : \\'M1.NET/SPNET\\' (16/0)';"
"'+M1.NET : M1.NET (18/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.PIN:1\\';\\'M1.SPNET:1\\';\\'M1.VIA:1\\' : \\'M1.NET:1/PIN:1/...\\' (6/0)';"
"'+\\'M1.NET:1\\' : \\'M1.NET:1\\' (7/0)';" "'+\\'M1.NET:1\\' : \\'M1.NET:1\\' (7/0)';"
"'+M1.PIN : M1.PIN (3/0)';" "'+M1.PIN : M1.PIN (3/0)';"
@ -736,7 +810,7 @@ TEST(117_mapfile_all)
"'M1.LABEL : M1.LABEL (26/0)';" "'M1.LABEL : M1.LABEL (26/0)';"
// NAME M1/NET not supported: "'+M1.LABEL : M1.LABEL (27/0)';" // NAME M1/NET not supported: "'+M1.LABEL : M1.LABEL (27/0)';"
// NAME M1/SPNET not supported: "'+M1.LABEL : M1.LABEL (28/1)';" // 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)'" "'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); 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) TEST(200_lefdef_plugin)
{ {
db::Layout ly; 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); 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); CommonReader::init (options);
m_read_texts = common_options ().enable_text_objects; db::CommonReaderOptions common_options = options.get_options<db::CommonReaderOptions> ();
m_read_properties = common_options ().enable_properties; m_read_texts = common_options.enable_text_objects;
m_read_properties = common_options.enable_properties;
db::OASISReaderOptions oasis_options = options.get_options<db::OASISReaderOptions> (); db::OASISReaderOptions oasis_options = options.get_options<db::OASISReaderOptions> ();
m_read_all_properties = oasis_options.read_all_properties; 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