mirror of
https://github.com/KLayout/klayout.git
synced 2026-09-02 02:47:48 +02:00
Merge branch 'master' into 2.5d-view-devel
This commit is contained in:
@@ -581,7 +581,7 @@ CIFReader::read_cell (db::Layout &layout, db::Cell &cell, double sf, int level)
|
||||
|
||||
if (rx >= 0 && ry == 0) {
|
||||
|
||||
cell.shapes ((unsigned int) layer).insert (db::Box (sf * (x - 0.5 * w), sf * (y - 0.5 * h), sf * (x + 0.5 * w), sf * (y + 0.5 * h)));
|
||||
cell.shapes ((unsigned int) layer).insert (db::Box (db::Point (sf * (x - 0.5 * w), sf * (y - 0.5 * h)), db::Point (sf * (x + 0.5 * w), sf * (y + 0.5 * h))));
|
||||
|
||||
} else {
|
||||
|
||||
@@ -818,7 +818,7 @@ CIFReader::read_cell (db::Layout &layout, db::Cell &cell, double sf, int level)
|
||||
void
|
||||
CIFReader::do_read (db::Layout &layout)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, "File read");
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + m_stream.source ());
|
||||
|
||||
try {
|
||||
|
||||
|
||||
@@ -165,26 +165,21 @@ CIFWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa
|
||||
}
|
||||
|
||||
double a = t.angle();
|
||||
while (a < 0) {
|
||||
a += 360.0;
|
||||
}
|
||||
double ya = 0.0, xa = 0.0;
|
||||
if (a < 45 || a > 315) {
|
||||
xa = 1.0;
|
||||
ya = tan(a / 180.0 * M_PI);
|
||||
} else if (a < 135) {
|
||||
xa = 1.0 / tan(a / 180.0 * M_PI);
|
||||
ya = 1.0;
|
||||
} else if (a < 225) {
|
||||
xa = -1.0;
|
||||
ya = tan(a / 180.0 * M_PI);
|
||||
double xa = cos(a / 180.0 * M_PI);
|
||||
double ya = sin(a / 180.0 * M_PI);
|
||||
|
||||
// normalize xa or ya whichever is better
|
||||
double n;
|
||||
if (fabs (xa) >= M_SQRT1_2) {
|
||||
n = 1.0 / fabs (xa);
|
||||
} else {
|
||||
xa = 1.0 / tan(a / 180.0 * M_PI);
|
||||
ya = -1.0;
|
||||
}
|
||||
n = 1.0 / fabs (ya);
|
||||
}
|
||||
xa *= n;
|
||||
ya *= n;
|
||||
|
||||
// TODO: that can be done smarter ...
|
||||
while (fabs (xa - floor (0.5 + xa)) > 1e-3 || fabs (ya - floor (0.5 + ya)) > 1e-3) {
|
||||
for (int n = 0; n < 20 && (fabs (xa - floor (0.5 + xa)) > 1e-3 || fabs (ya - floor (0.5 + ya)) > 1e-3); ++n) {
|
||||
xa *= 2.0;
|
||||
ya *= 2.0;
|
||||
}
|
||||
|
||||
@@ -194,3 +194,15 @@ TEST(rot_boxes)
|
||||
{
|
||||
run_test (_this, tl::testsrc (), "issue_305.cif", "issue_305_au.gds");
|
||||
}
|
||||
|
||||
// Issue #568
|
||||
TEST(rot_instances)
|
||||
{
|
||||
run_test (_this, tl::testsrc (), "issue_568.cif", "issue_568_au.gds");
|
||||
}
|
||||
|
||||
// Issue #578
|
||||
TEST(rot_instances2)
|
||||
{
|
||||
run_test (_this, tl::testsrc (), "issue_578.cif", "issue_578_au.gds");
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ DXFReader::open_layer (db::Layout &layout, const std::string &n)
|
||||
void
|
||||
DXFReader::do_read (db::Layout &layout, db::cell_index_type top)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, "File read");
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + m_stream.source ());
|
||||
|
||||
// create the zero layer - this is not mapped to GDS but can be specified in the layer mapping as
|
||||
// a layer named "0".
|
||||
@@ -1406,7 +1406,6 @@ DXFReader::read_entities (db::Layout &layout, db::Cell &cell, const db::DVector
|
||||
std::string layer;
|
||||
int flags = 0;
|
||||
double width1 = 0.0, width2 = 0.0;
|
||||
unsigned int got_width = 0;
|
||||
double common_width1 = 0.0, common_width2 = 0.0;
|
||||
unsigned int common_width_set = 0;
|
||||
double ex = 0.0, ey = 0.0, ez = 1.0;
|
||||
@@ -1417,6 +1416,7 @@ DXFReader::read_entities (db::Layout &layout, db::Cell &cell, const db::DVector
|
||||
|
||||
unsigned int xy_flags = 0;
|
||||
double x = 0.0, y = 0.0;
|
||||
unsigned int got_width = 0;
|
||||
|
||||
while ((g = read_group_code ()) != 0) {
|
||||
|
||||
@@ -1445,7 +1445,6 @@ DXFReader::read_entities (db::Layout &layout, db::Cell &cell, const db::DVector
|
||||
if (got_width == 3) {
|
||||
widths.push_back (std::make_pair (seg_start, width1));
|
||||
widths.push_back (std::make_pair (points.size () - 1, width2));
|
||||
got_width = 0;
|
||||
}
|
||||
|
||||
got_width = 0;
|
||||
@@ -1516,7 +1515,7 @@ DXFReader::read_entities (db::Layout &layout, db::Cell &cell, const db::DVector
|
||||
const std::string &e = read_string (true);
|
||||
if (e == "VERTEX") {
|
||||
|
||||
got_width = 0;
|
||||
unsigned int got_width = 0;
|
||||
|
||||
double x = 0.0, y = 0.0;
|
||||
double bnew = 0.0;
|
||||
@@ -1551,7 +1550,6 @@ DXFReader::read_entities (db::Layout &layout, db::Cell &cell, const db::DVector
|
||||
if (got_width == 3) {
|
||||
widths.push_back (std::make_pair (seg_start, width1));
|
||||
widths.push_back (std::make_pair (points.size () - 1, width2));
|
||||
got_width = 0;
|
||||
}
|
||||
|
||||
} else if (e == "SEQEND") {
|
||||
@@ -2303,7 +2301,6 @@ DXFReader::read_entities (db::Layout &layout, db::Cell &cell, const db::DVector
|
||||
|
||||
// close previous loop if necessary
|
||||
finish_loop (loop_start, iedges.size (), iedges);
|
||||
loop_start = iedges.size ();
|
||||
|
||||
// create the polygons
|
||||
std::pair <bool, unsigned int> ll = open_layer (layout, layer);
|
||||
|
||||
@@ -383,4 +383,5 @@ gsi::ClassExt<db::SaveLayoutOptions> dxf_writer_options (
|
||||
""
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -301,6 +301,12 @@ GDS2ReaderText::get_ushort ()
|
||||
return x;
|
||||
}
|
||||
|
||||
std::string
|
||||
GDS2ReaderText::path () const
|
||||
{
|
||||
return sStream.source ();
|
||||
}
|
||||
|
||||
void
|
||||
GDS2ReaderText::error (const std::string &msg)
|
||||
{
|
||||
|
||||
@@ -110,6 +110,7 @@ private:
|
||||
tl::Extractor reader;
|
||||
std::vector<GDS2XY> xyData;
|
||||
|
||||
virtual std::string path () const;
|
||||
const char *get_string ();
|
||||
void get_string (tl::string &s) const;
|
||||
int get_int ();
|
||||
|
||||
@@ -256,6 +256,12 @@ GDS2Reader::progress_checkpoint ()
|
||||
m_progress.set (m_stream.pos ());
|
||||
}
|
||||
|
||||
std::string
|
||||
GDS2Reader::path () const
|
||||
{
|
||||
return m_stream.source ();
|
||||
}
|
||||
|
||||
void
|
||||
GDS2Reader::error (const std::string &msg)
|
||||
{
|
||||
|
||||
@@ -124,6 +124,7 @@ private:
|
||||
virtual void error (const std::string &txt);
|
||||
virtual void warn (const std::string &txt);
|
||||
|
||||
virtual std::string path () const;
|
||||
virtual const char *get_string ();
|
||||
virtual void get_string (tl::string &s) const;
|
||||
virtual int get_int ();
|
||||
|
||||
@@ -233,7 +233,7 @@ eq_y (const GDS2XY &a, const GDS2XY &b)
|
||||
void
|
||||
GDS2ReaderBase::do_read (db::Layout &layout)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, "File read");
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + path ());
|
||||
|
||||
m_cellname = "";
|
||||
m_libname = "";
|
||||
|
||||
@@ -128,6 +128,7 @@ private:
|
||||
virtual void error (const std::string &txt) = 0;
|
||||
virtual void warn (const std::string &txt) = 0;
|
||||
|
||||
virtual std::string path () const = 0;
|
||||
virtual const char *get_string () = 0;
|
||||
virtual void get_string (tl::string &s) const = 0;
|
||||
virtual int get_int () = 0;
|
||||
|
||||
@@ -354,120 +354,130 @@ GDS2WriterBase::write_inst (double sf, const db::Instance &instance, bool normal
|
||||
|
||||
bool is_reg = instance.is_regular_array (a, b, amax, bmax);
|
||||
|
||||
db::Trans t = instance.front ();
|
||||
for (db::CellInstArray::iterator ii = instance.begin (); ! ii.at_end (); ++ii) {
|
||||
|
||||
if (normalize) {
|
||||
db::Trans t = *ii;
|
||||
|
||||
// try to normalize orthogonal arrays into "Cadence notation", that is
|
||||
// column and row vectors are positive in the coordinate system of the
|
||||
// rotated array.
|
||||
|
||||
if (is_reg) {
|
||||
if (normalize) {
|
||||
|
||||
if (amax < 2) {
|
||||
a = db::Vector ();
|
||||
}
|
||||
if (bmax < 2) {
|
||||
b = db::Vector ();
|
||||
}
|
||||
// try to normalize orthogonal arrays into "Cadence notation", that is
|
||||
// column and row vectors are positive in the coordinate system of the
|
||||
// rotated array.
|
||||
|
||||
// normalisation only works for orthogonal vectors, parallel to x or y axis, which are not parallel
|
||||
if ((a.x () == 0 || a.y () == 0) && (b.x () == 0 || b.y () == 0) && !((a.x () != 0 && b.x () != 0) || (a.y () != 0 && b.y () != 0))) {
|
||||
|
||||
db::FTrans fp = db::FTrans(t.rot ()).inverted ();
|
||||
|
||||
a.transform (fp);
|
||||
b.transform (fp);
|
||||
if (is_reg) {
|
||||
|
||||
db::Vector p;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (amax < 2) {
|
||||
a = db::Vector ();
|
||||
}
|
||||
if (bmax < 2) {
|
||||
b = db::Vector ();
|
||||
}
|
||||
|
||||
db::Vector *q = (i == 0) ? &a : &b;
|
||||
unsigned long n = (i == 0) ? amax : bmax;
|
||||
// normalisation only works for orthogonal vectors, parallel to x or y axis, which are not parallel
|
||||
if ((a.x () == 0 || a.y () == 0) && (b.x () == 0 || b.y () == 0) && !((a.x () != 0 && b.x () != 0) || (a.y () != 0 && b.y () != 0))) {
|
||||
|
||||
db::FTrans fp = db::FTrans(t.rot ()).inverted ();
|
||||
|
||||
a.transform (fp);
|
||||
b.transform (fp);
|
||||
|
||||
db::Vector p;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
|
||||
db::Vector *q = (i == 0) ? &a : &b;
|
||||
unsigned long n = (i == 0) ? amax : bmax;
|
||||
|
||||
if (n == 0) {
|
||||
*q = db::Vector ();
|
||||
} else {
|
||||
if (q->x () < 0) {
|
||||
p += db::Vector ((n - 1) * q->x (), 0);
|
||||
q->set_x (-q->x ());
|
||||
}
|
||||
if (q->y () < 0) {
|
||||
p += db::Vector (0, (n - 1) * q->y ());
|
||||
q->set_y (-q->y ());
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
*q = db::Vector ();
|
||||
} else {
|
||||
if (q->x () < 0) {
|
||||
p += db::Vector ((n - 1) * q->x (), 0);
|
||||
q->set_x (-q->x ());
|
||||
}
|
||||
if (q->y () < 0) {
|
||||
p += db::Vector (0, (n - 1) * q->y ());
|
||||
q->set_y (-q->y ());
|
||||
}
|
||||
}
|
||||
|
||||
if (a.x () != 0 || b.y () != 0) {
|
||||
std::swap (a, b);
|
||||
std::swap (amax, bmax);
|
||||
}
|
||||
|
||||
fp = db::FTrans (t.rot ());
|
||||
a.transform (fp);
|
||||
b.transform (fp);
|
||||
|
||||
t = t * db::Trans (p);
|
||||
|
||||
}
|
||||
|
||||
if (a.x () != 0 || b.y () != 0) {
|
||||
std::swap (a, b);
|
||||
std::swap (amax, bmax);
|
||||
}
|
||||
|
||||
fp = db::FTrans (t.rot ());
|
||||
a.transform (fp);
|
||||
b.transform (fp);
|
||||
|
||||
t = t * db::Trans (p);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
write_record_size (4);
|
||||
write_record (is_reg ? sAREF : sSREF);
|
||||
|
||||
write_record_size (4);
|
||||
write_record (is_reg ? sAREF : sSREF);
|
||||
write_string_record (sSNAME, m_cell_name_map.cell_name (instance.cell_index ()));
|
||||
|
||||
write_string_record (sSNAME, m_cell_name_map.cell_name (instance.cell_index ()));
|
||||
if (t.rot () != 0 || instance.is_complex ()) {
|
||||
|
||||
if (t.rot () != 0 || instance.is_complex ()) {
|
||||
write_record_size (6);
|
||||
write_record (sSTRANS);
|
||||
write_short (t.is_mirror () ? 0x8000 : 0);
|
||||
|
||||
write_record_size (6);
|
||||
write_record (sSTRANS);
|
||||
write_short (t.is_mirror () ? 0x8000 : 0);
|
||||
|
||||
if (instance.is_complex ()) {
|
||||
write_record_size (4 + 8);
|
||||
write_record (sMAG);
|
||||
write_double (instance.complex_trans ().mag ());
|
||||
write_record_size (4 + 8);
|
||||
write_record (sANGLE);
|
||||
write_double (instance.complex_trans ().angle ());
|
||||
} else {
|
||||
if ((t.rot () % 4) != 0) {
|
||||
if (instance.is_complex ()) {
|
||||
db::CellInstArray::complex_trans_type ct = instance.complex_trans (t);
|
||||
write_record_size (4 + 8);
|
||||
write_record (sMAG);
|
||||
write_double (ct.mag ());
|
||||
write_record_size (4 + 8);
|
||||
write_record (sANGLE);
|
||||
write_double ((t.rot () % 4) * 90.0);
|
||||
write_double (ct.angle ());
|
||||
} else {
|
||||
if ((t.rot () % 4) != 0) {
|
||||
write_record_size (4 + 8);
|
||||
write_record (sANGLE);
|
||||
write_double ((t.rot () % 4) * 90.0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (is_reg) {
|
||||
write_record_size (4 + 2 * 2);
|
||||
write_record (sCOLROW);
|
||||
if (amax > 32767 || bmax > 32767) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cannot write array references with more than 32767 columns or rows to GDS2 streams")));
|
||||
}
|
||||
write_short (std::max ((unsigned long) 1, bmax));
|
||||
write_short (std::max ((unsigned long) 1, amax));
|
||||
}
|
||||
|
||||
write_record_size (4 + (is_reg ? 3 : 1) * 2 * 4);
|
||||
write_record (sXY);
|
||||
write_int (scale (sf, t.disp ().x ()));
|
||||
write_int (scale (sf, t.disp ().y ()));
|
||||
|
||||
if (is_reg) {
|
||||
write_int (scale (sf, t.disp ().x () + b.x () * bmax));
|
||||
write_int (scale (sf, t.disp ().y () + b.y () * bmax));
|
||||
write_int (scale (sf, t.disp ().x () + a.x () * amax));
|
||||
write_int (scale (sf, t.disp ().y () + a.y () * amax));
|
||||
}
|
||||
|
||||
finish (layout, prop_id);
|
||||
|
||||
if (is_reg) {
|
||||
// we have already written all instances
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (is_reg) {
|
||||
write_record_size (4 + 2 * 2);
|
||||
write_record (sCOLROW);
|
||||
if (amax > 32767 || bmax > 32767) {
|
||||
throw tl::Exception (tl::to_string (tr ("Cannot write array references with more than 32767 columns or rows to GDS2 streams")));
|
||||
}
|
||||
write_short (std::max ((unsigned long) 1, bmax));
|
||||
write_short (std::max ((unsigned long) 1, amax));
|
||||
}
|
||||
|
||||
write_record_size (4 + (is_reg ? 3 : 1) * 2 * 4);
|
||||
write_record (sXY);
|
||||
write_int (scale (sf, t.disp ().x ()));
|
||||
write_int (scale (sf, t.disp ().y ()));
|
||||
|
||||
if (is_reg) {
|
||||
write_int (scale (sf, t.disp ().x () + b.x () * bmax));
|
||||
write_int (scale (sf, t.disp ().y () + b.y () * bmax));
|
||||
write_int (scale (sf, t.disp ().x () + a.x () * amax));
|
||||
write_int (scale (sf, t.disp ().y () + a.y () * amax));
|
||||
}
|
||||
|
||||
finish (layout, prop_id);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1129,6 +1129,40 @@ TEST(117)
|
||||
EXPECT_EQ (pp == poly, true);
|
||||
}
|
||||
|
||||
// error on duplicate cell name
|
||||
TEST(118)
|
||||
{
|
||||
db::Manager m (false);
|
||||
db::Layout layout_org (&m);
|
||||
|
||||
db::cell_index_type cid1 = layout_org.add_cell ("A");
|
||||
db::cell_index_type cid2 = layout_org.add_cell ("B");
|
||||
layout_org.rename_cell (cid2, "A"); // creates a duplicate cell
|
||||
|
||||
db::LayerProperties lp;
|
||||
lp.layer = 1;
|
||||
lp.datatype = 0;
|
||||
unsigned int lid = layout_org.insert_layer (lp);
|
||||
|
||||
layout_org.cell (cid1).shapes (lid).insert (db::Box (0, 0, 1000, 2000));
|
||||
layout_org.cell (cid2).shapes (lid).insert (db::Box (0, 0, 1000, 2000));
|
||||
|
||||
std::string tmp_file = tl::TestBase::tmp_file ("tmp_GDS2Writer_117.gds");
|
||||
|
||||
bool error = false;
|
||||
try {
|
||||
tl::OutputStream stream (tmp_file);
|
||||
db::SaveLayoutOptions options;
|
||||
db::Writer writer (options);
|
||||
writer.write (layout_org, stream);
|
||||
} catch (tl::Exception &ex) {
|
||||
tl::warn << ex.msg ();
|
||||
error = true;
|
||||
}
|
||||
|
||||
EXPECT_EQ (error, true);
|
||||
}
|
||||
|
||||
// Extreme fracturing by max. points
|
||||
TEST(120)
|
||||
{
|
||||
@@ -1153,3 +1187,4 @@ TEST(166)
|
||||
opt.max_vertex_count = 4;
|
||||
run_test (_this, "t166.oas.gz", "t166_au.gds.gz", false, opt);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,42 +72,51 @@ LEFDEFReaderOptions::LEFDEFReaderOptions ()
|
||||
}
|
||||
|
||||
LEFDEFReaderOptions::LEFDEFReaderOptions (const LEFDEFReaderOptions &d)
|
||||
: db::FormatSpecificReaderOptions (d),
|
||||
m_read_all_layers (d.m_read_all_layers), m_layer_map (d.m_layer_map),
|
||||
m_dbu (d.m_dbu),
|
||||
m_produce_net_names (d.m_produce_net_names),
|
||||
m_net_property_name (d.m_net_property_name),
|
||||
m_produce_inst_names (d.m_produce_inst_names),
|
||||
m_inst_property_name (d.m_inst_property_name),
|
||||
m_produce_pin_names (d.m_produce_pin_names),
|
||||
m_pin_property_name (d.m_pin_property_name),
|
||||
m_produce_cell_outlines (d.m_produce_cell_outlines),
|
||||
m_cell_outline_layer (d.m_cell_outline_layer),
|
||||
m_produce_placement_blockages (d.m_produce_placement_blockages),
|
||||
m_placement_blockage_layer (d.m_placement_blockage_layer),
|
||||
m_produce_regions (d.m_produce_regions),
|
||||
m_region_layer (d.m_region_layer),
|
||||
m_produce_via_geometry (d.m_produce_via_geometry),
|
||||
m_via_geometry_suffix (d.m_via_geometry_suffix),
|
||||
m_via_geometry_datatype (d.m_via_geometry_datatype),
|
||||
m_produce_pins (d.m_produce_pins),
|
||||
m_pins_suffix (d.m_pins_suffix),
|
||||
m_pins_datatype (d.m_pins_datatype),
|
||||
m_produce_obstructions (d.m_produce_obstructions),
|
||||
m_obstructions_suffix (d.m_obstructions_suffix),
|
||||
m_obstructions_datatype (d.m_obstructions_datatype),
|
||||
m_produce_blockages (d.m_produce_blockages),
|
||||
m_blockages_suffix (d.m_blockages_suffix),
|
||||
m_blockages_datatype (d.m_blockages_datatype),
|
||||
m_produce_labels (d.m_produce_labels),
|
||||
m_labels_suffix (d.m_labels_suffix),
|
||||
m_labels_datatype (d.m_labels_datatype),
|
||||
m_produce_routing (d.m_produce_routing),
|
||||
m_routing_suffix (d.m_routing_suffix),
|
||||
m_routing_datatype (d.m_routing_datatype),
|
||||
m_lef_files (d.m_lef_files)
|
||||
: db::FormatSpecificReaderOptions ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
operator= (d);
|
||||
}
|
||||
|
||||
LEFDEFReaderOptions &LEFDEFReaderOptions::operator= (const LEFDEFReaderOptions &d)
|
||||
{
|
||||
if (this != &d) {
|
||||
db::FormatSpecificReaderOptions::operator= (d);
|
||||
m_read_all_layers = d.m_read_all_layers;
|
||||
m_layer_map = d.m_layer_map;
|
||||
m_dbu = d.m_dbu;
|
||||
m_produce_net_names = d.m_produce_net_names;
|
||||
m_net_property_name = d.m_net_property_name;
|
||||
m_produce_inst_names = d.m_produce_inst_names;
|
||||
m_inst_property_name = d.m_inst_property_name;
|
||||
m_produce_pin_names = d.m_produce_pin_names;
|
||||
m_pin_property_name = d.m_pin_property_name;
|
||||
m_produce_cell_outlines = d.m_produce_cell_outlines;
|
||||
m_cell_outline_layer = d.m_cell_outline_layer;
|
||||
m_produce_placement_blockages = d.m_produce_placement_blockages;
|
||||
m_placement_blockage_layer = d.m_placement_blockage_layer;
|
||||
m_produce_regions = d.m_produce_regions;
|
||||
m_region_layer = d.m_region_layer;
|
||||
m_produce_via_geometry = d.m_produce_via_geometry;
|
||||
m_via_geometry_suffix = d.m_via_geometry_suffix;
|
||||
m_via_geometry_datatype = d.m_via_geometry_datatype;
|
||||
m_produce_pins = d.m_produce_pins;
|
||||
m_pins_suffix = d.m_pins_suffix;
|
||||
m_pins_datatype = d.m_pins_datatype;
|
||||
m_produce_obstructions = d.m_produce_obstructions;
|
||||
m_obstructions_suffix = d.m_obstructions_suffix;
|
||||
m_obstructions_datatype = d.m_obstructions_datatype;
|
||||
m_produce_blockages = d.m_produce_blockages;
|
||||
m_blockages_suffix = d.m_blockages_suffix;
|
||||
m_blockages_datatype = d.m_blockages_datatype;
|
||||
m_produce_labels = d.m_produce_labels;
|
||||
m_labels_suffix = d.m_labels_suffix;
|
||||
m_labels_datatype = d.m_labels_datatype;
|
||||
m_produce_routing = d.m_produce_routing;
|
||||
m_routing_suffix = d.m_routing_suffix;
|
||||
m_routing_datatype = d.m_routing_datatype;
|
||||
m_lef_files = d.m_lef_files;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
db::FormatSpecificReaderOptions *
|
||||
|
||||
@@ -66,6 +66,7 @@ class DB_PLUGIN_PUBLIC LEFDEFReaderOptions
|
||||
public:
|
||||
LEFDEFReaderOptions ();
|
||||
LEFDEFReaderOptions (const LEFDEFReaderOptions &d);
|
||||
LEFDEFReaderOptions &operator= (const LEFDEFReaderOptions &d);
|
||||
|
||||
db::FormatSpecificReaderOptions *clone () const;
|
||||
virtual const std::string &format_name () const;
|
||||
|
||||
@@ -303,7 +303,7 @@ MAGReader::do_read (db::Layout &layout, db::cell_index_type cell_index, tl::Text
|
||||
void
|
||||
MAGReader::do_read_part (db::Layout &layout, db::cell_index_type cell_index, tl::TextInputStream &stream)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 31, "File read");
|
||||
tl::SelfTimer timer (tl::verbosity () >= 31, tl::to_string (tr ("File read: ")) + m_stream.source ());
|
||||
|
||||
if (tl::verbosity () >= 30) {
|
||||
tl::log << "Reading layout file: " << stream.source ();
|
||||
|
||||
@@ -689,7 +689,7 @@ static const char magic_bytes[] = { "%SEMI-OASIS\015\012" };
|
||||
void
|
||||
OASISReader::do_read (db::Layout &layout)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, "File read");
|
||||
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("File read: ")) + m_stream.source ());
|
||||
|
||||
unsigned char r;
|
||||
char *mb;
|
||||
@@ -2018,6 +2018,8 @@ OASISReader::do_read_placement (unsigned char r,
|
||||
|
||||
db::Vector pos (mm_placement_x.get (), mm_placement_y.get ());
|
||||
|
||||
const std::vector<db::Vector> *points = 0;
|
||||
|
||||
if ((m & 0x8) && read_repetition ()) {
|
||||
|
||||
std::pair<bool, db::properties_id_type> pp = read_element_properties (layout.properties_repository (), false);
|
||||
@@ -2042,6 +2044,42 @@ OASISReader::do_read_placement (unsigned char r,
|
||||
instances.push_back (inst);
|
||||
}
|
||||
|
||||
} else if (! layout.is_editable () && (points = mm_repetition.get ().is_iterated ()) != 0) {
|
||||
|
||||
db::CellInstArray inst;
|
||||
|
||||
if (mag_set || angle < 0) {
|
||||
|
||||
db::ICplxTrans ct (mag, angle_deg, mirror, pos);
|
||||
|
||||
db::CellInstArray::iterated_complex_array_type array (ct.rcos (), ct.mag ());
|
||||
array.reserve (points->size () + 1);
|
||||
array.insert (db::Vector ());
|
||||
array.insert (points->begin (), points->end ());
|
||||
array.sort ();
|
||||
|
||||
inst = db::CellInstArray (db::CellInst (mm_placement_cell.get ()),
|
||||
db::Trans (ct), layout.array_repository ().insert (array));
|
||||
|
||||
} else {
|
||||
|
||||
db::CellInstArray::iterated_array_type array;
|
||||
array.reserve (points->size () + 1);
|
||||
array.insert (db::Vector ());
|
||||
array.insert (points->begin (), points->end ());
|
||||
array.sort ();
|
||||
|
||||
inst = db::CellInstArray (db::CellInst (mm_placement_cell.get ()),
|
||||
db::Trans (angle, mirror, pos), layout.array_repository ().insert (array));
|
||||
|
||||
}
|
||||
|
||||
if (pp.first) {
|
||||
instances_with_props.push_back (db::CellInstArrayWithProperties (inst, pp.second));
|
||||
} else {
|
||||
instances.push_back (inst);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
RepetitionIterator p = mm_repetition.get ().begin ();
|
||||
|
||||
@@ -1965,11 +1965,35 @@ OASISWriter::write (const db::CellInstArray &inst, db::properties_id_type prop_i
|
||||
{
|
||||
m_progress.set (mp_stream->pos ());
|
||||
|
||||
std::vector<db::Vector> pts;
|
||||
db::Vector a, b;
|
||||
unsigned long amax, bmax;
|
||||
bool is_reg = inst.is_regular_array (a, b, amax, bmax);
|
||||
|
||||
if (is_reg && (amax > 1 || bmax > 1)) {
|
||||
if (inst.is_iterated_array (&pts) && pts.size () > 1) {
|
||||
|
||||
// Remove the first point which is implicitly contained in the repetition
|
||||
// Note: we can do so because below we instantiate the shape at the front of the array which includes
|
||||
// the first transformation already.
|
||||
db::Vector po = pts.front ();
|
||||
std::vector<db::Vector>::iterator pw = pts.begin();
|
||||
for (std::vector<db::Vector>::iterator p = pw + 1; p != pts.end (); ++p) {
|
||||
*pw++ = *p - po;
|
||||
}
|
||||
pts.erase (pw, pts.end ());
|
||||
|
||||
db::IrregularRepetition *rep_base = new db::IrregularRepetition ();
|
||||
rep_base->points ().swap (pts);
|
||||
db::Repetition array_rep (rep_base);
|
||||
|
||||
if (rep != db::Repetition ()) {
|
||||
for (db::RepetitionIterator r = rep.begin (); ! r.at_end (); ++r) {
|
||||
write_inst_with_rep (inst, prop_id, *r, array_rep);
|
||||
}
|
||||
} else {
|
||||
write_inst_with_rep (inst, prop_id, db::Vector (), array_rep);
|
||||
}
|
||||
|
||||
} else if (inst.is_regular_array (a, b, amax, bmax) && (amax > 1 || bmax > 1)) {
|
||||
|
||||
// we cannot use the repetition - instead we write every single instance and use the repetition
|
||||
// for the array information
|
||||
|
||||
@@ -292,4 +292,5 @@ gsi::ClassExt<db::SaveLayoutOptions> oasis_writer_options (
|
||||
""
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_layDialogs
|
||||
#define HDR_layDialogs
|
||||
#ifndef HDR_layBooleanOperationsDialogs
|
||||
#define HDR_layBooleanOperationsDialogs
|
||||
|
||||
#include "ui_BooleanOptionsDialog.h"
|
||||
#include "ui_SizingOptionsDialog.h"
|
||||
|
||||
@@ -224,6 +224,10 @@ RdbDifferenceReceiver::produce_cell_inst (const db::CellInstArrayWithProperties
|
||||
unsigned long amax, bmax;
|
||||
if (ci.is_regular_array (a, b, amax, bmax)) {
|
||||
r += tl::sprintf (" [a=%s, b=%s, na=%ld, nb=%ld]", a.to_string (), b.to_string (), amax, bmax);
|
||||
} else if (ci.size () > 1) {
|
||||
r += " (+";
|
||||
r += tl::to_string (ci.size () - 1);
|
||||
r += " irregular placements)";
|
||||
}
|
||||
|
||||
item->add_value (r);
|
||||
|
||||
@@ -501,6 +501,13 @@ NetTracerTechnologyComponent::NetTracerTechnologyComponent (const NetTracerTechn
|
||||
m_symbols = d.m_symbols;
|
||||
}
|
||||
|
||||
NetTracerTechnologyComponent &NetTracerTechnologyComponent::operator= (const NetTracerTechnologyComponent &d)
|
||||
{
|
||||
m_connections = d.m_connections;
|
||||
m_symbols = d.m_symbols;
|
||||
return *this;
|
||||
}
|
||||
|
||||
NetTracerData
|
||||
NetTracerTechnologyComponent::get_tracer_data (const db::Layout &layout) const
|
||||
{
|
||||
|
||||
@@ -375,6 +375,7 @@ public:
|
||||
|
||||
NetTracerTechnologyComponent ();
|
||||
NetTracerTechnologyComponent (const NetTracerTechnologyComponent &d);
|
||||
NetTracerTechnologyComponent &operator= (const NetTracerTechnologyComponent &d);
|
||||
|
||||
const_iterator begin () const
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
|
||||
Reference in New Issue
Block a user