mirror of https://github.com/KLayout/klayout.git
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:
parent
fd4fe5ce62
commit
9cb77d6222
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> > ®ions, double scale)
|
||||
DEFImporter::read_regions (std::map<std::string, std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > > > ®ions, 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 (";")) {
|
||||
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 ()) {
|
||||
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 ()) {
|
||||
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::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) {
|
||||
for (std::vector<db::Polygon>::const_iterator p = r->second.begin (); p != r->second.end (); ++p) {
|
||||
group_cell->shapes (*l).insert (*p);
|
||||
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 ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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> > ®ions, double scale);
|
||||
void read_regions (std::map<std::string, std::vector<std::pair<LayerPurpose, std::vector<db::Polygon> > > > ®ions, double scale);
|
||||
void read_groups (std::list<DEFImporterGroup> &groups, double scale);
|
||||
void read_blockages (db::Layout &layout, db::Cell &design, double scale);
|
||||
void read_nets (db::Layout &layout, db::Cell &design, double scale, bool specialnets);
|
||||
|
|
|
|||
|
|
@ -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,10 +149,10 @@ static std::string purpose_to_name (LayerPurpose purpose)
|
|||
return "BLK";
|
||||
case All:
|
||||
return "ALL";
|
||||
}
|
||||
|
||||
default:
|
||||
return std::string ();
|
||||
}
|
||||
}
|
||||
|
||||
static std::string
|
||||
layer_spec_to_name (const std::string &layer_name, LayerPurpose purpose, unsigned int mask, const db::DVector &via_size)
|
||||
|
|
@ -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 ()) {
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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")) {
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,4 @@
|
|||
DIEAREA ALL 100 0
|
||||
M1 ALL 12 0
|
||||
VIA1 ALL 13 0
|
||||
M2 ALL 14 0
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
DESIGN sub ;
|
||||
DIEAREA ( 0 0 ) ( 200 200 ) ;
|
||||
END DESIGN
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
MACRO sub
|
||||
SIZE .1 BY .1 ;
|
||||
END sub
|
||||
END LIBRARY
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
DESIGN top ;
|
||||
DIEAREA ( 0 0 ) ( 1000 1000 ) ;
|
||||
COMPONENTS 1 ;
|
||||
- sub sub + PLACED ( 0 0 ) N ;
|
||||
END COMPONENTS
|
||||
END DESIGN
|
||||
Binary file not shown.
|
|
@ -0,0 +1,5 @@
|
|||
BLOCKAGE ALL 20 0
|
||||
REGION ALL 1 0
|
||||
REGION FENCE 2 0
|
||||
REGION GUIDE 3 0
|
||||
REGION NONE 4 0
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
UNITS
|
||||
DATABASE MICRONS 1000 ;
|
||||
END UNITS
|
||||
END LIBRARY
|
||||
|
|
@ -0,0 +1 @@
|
|||
DIEAREA ALL 10 0
|
||||
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
|||
v:
|
||||
time strm2oas \
|
||||
--lefdef-map v.map \
|
||||
--lefdef-lefs v.lef \
|
||||
v.def v.oas
|
||||
|
||||
Binary file not shown.
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
M1 ALL 31 0
|
||||
M2 ALL 32 0
|
||||
VIA1 ALL 51 0
|
||||
Binary file not shown.
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue