Merge pull request #580 from KLayout/drawing-performance2

Drawing performance2
This commit is contained in:
Matthias Köfferlein
2020-06-28 16:14:48 +02:00
committed by GitHub
21 changed files with 966 additions and 324 deletions
@@ -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
@@ -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
@@ -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);