mirror of https://github.com/KLayout/klayout.git
680 lines
20 KiB
C++
680 lines
20 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2017 Matthias Koefferlein
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
#ifndef HDR_dbTilingProcessor
|
|
#define HDR_dbTilingProcessor
|
|
|
|
#include "dbLayout.h"
|
|
#include "dbEdgePairs.h"
|
|
#include "dbRegion.h"
|
|
#include "dbEdges.h"
|
|
#include "dbLayoutUtils.h"
|
|
#include "dbPolygonTools.h"
|
|
#include "dbClip.h"
|
|
|
|
#include "gsiObject.h"
|
|
|
|
#include "tlExpression.h"
|
|
#include "tlTypeTraits.h"
|
|
|
|
namespace db
|
|
{
|
|
|
|
class TilingProcessor;
|
|
|
|
/**
|
|
* @brief A receiver for the output data
|
|
*/
|
|
class DB_PUBLIC TileOutputReceiver
|
|
: public gsi::ObjectBase
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Constructor
|
|
*/
|
|
TileOutputReceiver ()
|
|
: mp_proc (0)
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
/**
|
|
* @brief Destructor
|
|
*/
|
|
virtual ~TileOutputReceiver ()
|
|
{
|
|
// .. nothing yet ..
|
|
}
|
|
|
|
/**
|
|
* @brief Initiate the deliver
|
|
*
|
|
* This method is called before the first tile delivers it's data.
|
|
*
|
|
* @param nx The number of tiles in x direction
|
|
* @param ny The number of tiles in y direction
|
|
* @param p0 The initial point
|
|
* @param dx The tile's x dimension
|
|
* @param dy The tile's y dimension
|
|
* @param frame The overall frame covered
|
|
*
|
|
* The tile's coordinates will be p0+(ix*dx,iy*dy),p0+((ix+1)*dx,(iy+1)*dy)
|
|
* where ix=0..nx-1, iy=0..ny-1.
|
|
*
|
|
* All coordinates are given in micron. If tiles are not used, nx and ny are 0.
|
|
*/
|
|
virtual void begin (size_t /*nx*/, size_t /*ny*/, const db::DPoint &/*p0*/, double /*dx*/, double /*dy*/, const db::DBox & /*frame*/) { }
|
|
|
|
/**
|
|
* @brief Deliver an object for one tile
|
|
*
|
|
* Delivery is protected by a mutex - only one thread will access the
|
|
* receiver at one time.
|
|
*
|
|
* The interpretation of the object remains subject to the implementation.
|
|
*
|
|
* @param ix The x index of the tile
|
|
* @param iy The y index of the tile
|
|
* @param tile The tile's box
|
|
* @param id The output id specified in the "output" method
|
|
* @param obj The object which is delivered
|
|
* @param dbu The database unit
|
|
* @param trans The transformation
|
|
* @param clip If true, clipping at the tile box is requested
|
|
*/
|
|
virtual void put (size_t /*ix*/, size_t /*iy*/, const db::Box &/*tile*/, size_t /*id*/, const tl::Variant & /*obj*/, double /*dbu*/, const db::ICplxTrans & /*trans*/, bool /*clip*/) { }
|
|
|
|
/**
|
|
* @brief Indicate the end of the execution
|
|
* @param sucess Will be true if all tiles executed successfully
|
|
*/
|
|
virtual void finish (bool /*success*/) { }
|
|
|
|
/**
|
|
* @brief Gets the tiling processor the receiver is attached to
|
|
*
|
|
* The returned value is a null pointer if no processor is attached.
|
|
*/
|
|
TilingProcessor *processor () const
|
|
{
|
|
return mp_proc;
|
|
}
|
|
|
|
private:
|
|
friend class TilingProcessor;
|
|
|
|
/**
|
|
* @brief Sets the tiling processor
|
|
*/
|
|
void set_processor (TilingProcessor *proc)
|
|
{
|
|
mp_proc = proc;
|
|
}
|
|
|
|
TilingProcessor *mp_proc;
|
|
};
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
void insert (X &inserter, const db::Polygon &o, const db::Box &tile, bool clip)
|
|
{
|
|
if (clip && ! o.box ().inside (tile)) {
|
|
// apply clipping
|
|
if (o.box ().touches (tile)) {
|
|
std::vector <db::Polygon> clipped_poly;
|
|
db::clip_poly (o, tile, clipped_poly);
|
|
for (std::vector <db::Polygon>::const_iterator cp = clipped_poly.begin (); cp != clipped_poly.end (); ++cp) {
|
|
inserter (*cp);
|
|
}
|
|
}
|
|
} else {
|
|
// no clipping
|
|
inserter (o);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
void insert (X &inserter, const db::SimplePolygon &o, const db::Box &tile, bool clip)
|
|
{
|
|
if (clip && ! o.box ().inside (tile)) {
|
|
// apply clipping
|
|
if (o.box ().touches (tile)) {
|
|
std::vector <db::SimplePolygon> clipped_poly;
|
|
db::clip_poly (o, tile, clipped_poly);
|
|
for (std::vector <db::SimplePolygon>::const_iterator cp = clipped_poly.begin (); cp != clipped_poly.end (); ++cp) {
|
|
inserter (*cp);
|
|
}
|
|
}
|
|
} else {
|
|
// no clipping
|
|
inserter (o);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
void insert (X &inserter, const db::Path &o, const db::Box &tile, bool clip)
|
|
{
|
|
if (clip && ! o.box ().inside (tile)) {
|
|
// apply clipping
|
|
if (o.box ().touches (tile)) {
|
|
insert (inserter, o.polygon (), tile, clip);
|
|
}
|
|
} else {
|
|
// no clipping
|
|
inserter (o);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
void insert (X &inserter, const db::EdgePair &o, const db::Box &tile, bool clip)
|
|
{
|
|
if (clip) {
|
|
// no real clipping for edge pairs - just select the ones that touch the clip rectangle
|
|
if (o.first ().clipped (tile).first || o.second ().clipped (tile).first) {
|
|
inserter (o);
|
|
}
|
|
} else {
|
|
inserter (o);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
void insert (X &inserter, const db::Text &o, const db::Box &tile, bool clip)
|
|
{
|
|
if (clip) {
|
|
// clipping
|
|
if (o.box ().inside (tile)) {
|
|
inserter (o);
|
|
}
|
|
} else {
|
|
// no clipping
|
|
inserter (o);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
void insert (X &inserter, const db::Box &o, const db::Box &tile, bool clip)
|
|
{
|
|
if (clip) {
|
|
// clipping
|
|
db::Box oc = o & tile;
|
|
if (! oc.empty ()) {
|
|
inserter (oc);
|
|
}
|
|
} else {
|
|
// no clipping
|
|
inserter (o);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
void insert (X &inserter, const db::Edge &o, const db::Box &tile, bool clip)
|
|
{
|
|
if (clip) {
|
|
// apply clipping. To ensure an edge is just added once, clipping is applied in a
|
|
// somewhat special way: edges coincident with the clip box are only taken if their
|
|
// inside side is towards the clip box (see Region::perimeter implementation).
|
|
if (o.bbox ().touches (tile)) {
|
|
|
|
std::pair<bool, db::Edge> ce = o.clipped (tile);
|
|
if (ce.first) {
|
|
|
|
db::Coord dx = ce.second.dx ();
|
|
db::Coord dy = ce.second.dy ();
|
|
db::Coord x = ce.second.p1 ().x ();
|
|
db::Coord y = ce.second.p1 ().y ();
|
|
if ((dx == 0 && x == tile.left () && dy < 0) ||
|
|
(dx == 0 && x == tile.right () && dy > 0) ||
|
|
(dy == 0 && y == tile.top () && dx < 0) ||
|
|
(dy == 0 && y == tile.bottom () && dx > 0)) {
|
|
// not counted -> box is at outside side of the edge
|
|
} else {
|
|
inserter (ce.second);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
// no clipping
|
|
inserter (o);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
void insert (X &inserter, const db::Region &data, const db::Box &tile, bool clip)
|
|
{
|
|
for (db::Region::const_iterator o = data.begin (); ! o.at_end (); ++o) {
|
|
insert (inserter, *o, tile, clip);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
void insert (X &inserter, const db::Edges &data, const db::Box &tile, bool clip)
|
|
{
|
|
for (db::Edges::const_iterator o = data.begin (); ! o.at_end (); ++o) {
|
|
insert (inserter, *o, tile, clip);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
void insert (X &inserter, const db::EdgePairs &data, const db::Box &tile, bool clip)
|
|
{
|
|
for (db::EdgePairs::const_iterator o = data.begin (); o != data.end (); ++o) {
|
|
insert (inserter, *o, tile, clip);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Delivery of tiling processor output
|
|
* This utility is put between the container and the receiver.
|
|
* The inserter is an object having an operator() that takes the object.
|
|
* This function is responsible for preparing (i.e. clipping) and delivering the output.
|
|
*/
|
|
template <class X>
|
|
bool insert_var (X &inserter, const tl::Variant &obj, const db::Box &tile, bool clip)
|
|
{
|
|
if (obj.is_user<db::Region> ()) {
|
|
insert (inserter, obj.to_user<db::Region> (), tile, clip);
|
|
return true;
|
|
} else if (obj.is_user<db::EdgePairs> ()) {
|
|
insert (inserter, obj.to_user<db::EdgePairs> (), tile, clip);
|
|
return true;
|
|
} else if (obj.is_user<db::Edges> ()) {
|
|
insert (inserter, obj.to_user<db::Edges> (), tile, clip);
|
|
return true;
|
|
} else if (obj.is_user<db::Box> ()) {
|
|
insert (inserter, obj.to_user<db::Box> (), tile, clip);
|
|
return true;
|
|
} else if (obj.is_user<db::Path> ()) {
|
|
insert (inserter, obj.to_user<db::Path> (), tile, clip);
|
|
return true;
|
|
} else if (obj.is_user<db::Text> ()) {
|
|
insert (inserter, obj.to_user<db::Text> (), tile, clip);
|
|
return true;
|
|
} else if (obj.is_user<db::Polygon> ()) {
|
|
insert (inserter, obj.to_user<db::Polygon> (), tile, clip);
|
|
return true;
|
|
} else if (obj.is_user<db::SimplePolygon> ()) {
|
|
insert (inserter, obj.to_user<db::SimplePolygon> (), tile, clip);
|
|
return true;
|
|
} else if (obj.is_user<db::EdgePair> ()) {
|
|
insert (inserter, obj.to_user<db::EdgePair> (), tile, clip);
|
|
return true;
|
|
} else if (obj.is_user<db::Edge> ()) {
|
|
insert (inserter, obj.to_user<db::Edge> (), tile, clip);
|
|
return true;
|
|
} else if (obj.is_nil ()) {
|
|
// .. ignore nil
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief A processor for executing scripts on tiles of a layout
|
|
*
|
|
* The idea of the tiling processor is to offer a way to execute scripts
|
|
* (written in tl::Expressions language) on tiles of a layout. Multiple
|
|
* scripts can be registered per tile.
|
|
*
|
|
* Multiple inputs can be specified. Custom functions can be registered to
|
|
* implement additional functionality.
|
|
* Multiple outputs can also be specified. Each output channel is assigned a name
|
|
* which will be available to the script through a variable. To output an object
|
|
* use _output(name, object).
|
|
*
|
|
* Inside the scripts provided, the following variables and functions are
|
|
* available:
|
|
* _tile a function, delivers the region describing the current tile or nil if tiling is not enabled
|
|
* _dbu the database unit used for the data
|
|
* _output output the data: _output(name, object)
|
|
* _count report a count for a specific output for display during execution
|
|
* <name> fetch the input <name> as specified in the "input" method
|
|
*/
|
|
class DB_PUBLIC TilingProcessor
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Constructor
|
|
*/
|
|
TilingProcessor ();
|
|
|
|
/**
|
|
* @brief Destructor
|
|
*/
|
|
~TilingProcessor ();
|
|
|
|
/**
|
|
* @brief Specifies a variable
|
|
*
|
|
* The name is the variable name which will receive the given value in the script.
|
|
*/
|
|
void var (const std::string &name, const tl::Variant &var);
|
|
|
|
/**
|
|
* @brief Specifies an input
|
|
*
|
|
* The name is the variable name which will receive the shapes for the individual tile.
|
|
* The transformation can be used to convert between database units.
|
|
* If "as_region" is false, the input is taken as edge input.
|
|
*/
|
|
void input (const std::string &name, const db::RecursiveShapeIterator &iter, const db::ICplxTrans &trans = db::ICplxTrans (), bool as_region = true, bool merged_semantics = true);
|
|
|
|
/**
|
|
* @brief Specifies the output
|
|
*
|
|
* The name is the variable which carries the context information.
|
|
* In the script, the output given by this specification can be referred to as
|
|
* _output(name, object).
|
|
*
|
|
* This version will employ the output receiver given by "rec". "id" will be passed
|
|
* to the "id" parameter of the receiver's "put" implementation.
|
|
*
|
|
* The ownership of the receiver object will be passed over to the processor.
|
|
*/
|
|
void output (const std::string &name, size_t id, TileOutputReceiver *rec, const db::ICplxTrans &trans);
|
|
|
|
/**
|
|
* @brief Specifies output to a layout
|
|
*
|
|
* This version will specify output to a layout object to the specified cell and layer.
|
|
* The ep_ext parameter specifies what extension to apply when converting edge pairs to polygons.
|
|
*/
|
|
void output (const std::string &name, db::Layout &layout, db::cell_index_type cell, const db::LayerProperties &lp, db::Coord ep_ext = 1);
|
|
|
|
/**
|
|
* @brief Specifies output to a layout
|
|
*
|
|
* This version will specify output to a layout object to the specified cell and layer.
|
|
* The ep_ext parameter specifies what extension to apply when converting edge pairs to polygons.
|
|
*/
|
|
void output (const std::string &name, db::Layout &layout, db::cell_index_type cell, unsigned int layer, db::Coord ep_ext = 1);
|
|
|
|
/**
|
|
* @brief Specifies output to a region
|
|
*
|
|
* This version will specify output to a region object.
|
|
* The ep_ext parameter specifies what extension to apply when converting edge pairs to polygons.
|
|
*/
|
|
void output (const std::string &name, db::Region ®ion, db::Coord ep_ext = 1);
|
|
|
|
/**
|
|
* @brief Specifies output to an edge pair collection
|
|
*
|
|
* This version will specify output to a EdgePairs object.
|
|
* Only edge pairs will be stored.
|
|
*/
|
|
void output (const std::string &name, db::EdgePairs &edge_pairs);
|
|
|
|
/**
|
|
* @brief Specifies output to an edge collection
|
|
*
|
|
* This version will specify output to a Edges object.
|
|
*/
|
|
void output (const std::string &name, db::Edges &edges);
|
|
|
|
/**
|
|
* @brief Gets the database unit under which the computation will be done
|
|
*/
|
|
double dbu () const
|
|
{
|
|
return m_dbu_specific_set ? m_dbu_specific : m_dbu;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the database unit under which the computation will be done
|
|
*
|
|
* Using this method will establish the given database unit as the target unit.
|
|
* Otherwise, the first input's database unit will be used.
|
|
*/
|
|
void set_dbu (double dbu)
|
|
{
|
|
m_dbu_specific_set = true;
|
|
m_dbu_specific = dbu;
|
|
}
|
|
|
|
/**
|
|
* @brief Disables or enables automatic scaling to database unit
|
|
*
|
|
* If enabled, all inputs are automatically scaled to the database unit.
|
|
* The default is "enabled".
|
|
*/
|
|
void set_scale_to_dbu (bool sdbu)
|
|
{
|
|
m_scale_to_dbu = sdbu;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns a value indicating whether automatic scaling to database unit is enabled
|
|
*/
|
|
bool scale_to_dbu () const
|
|
{
|
|
return m_scale_to_dbu;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the layout frame
|
|
*
|
|
* The layout frame is the box (in micron units) taken into account for computing
|
|
* the tiles if the tile counts are not given. If the layout frame is not set or
|
|
* set to an empty box, the processor will try to derive the frame from the given
|
|
* inputs.
|
|
*/
|
|
void set_frame (const db::DBox &frame);
|
|
|
|
/**
|
|
* @brief Gets the layout frame
|
|
*
|
|
* This is the value set by "set_frame".
|
|
*/
|
|
const db::DBox &frame () const
|
|
{
|
|
return m_frame;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the tile size
|
|
*
|
|
* The tile size is given in micron units.
|
|
* Alternatively, the tiling can be specified in terms of tile number (tiles method).
|
|
* The tiles method will override the tile size specified in tile_size.
|
|
*/
|
|
void tile_size (double w, double h);
|
|
|
|
/**
|
|
* @brief Sets the tile number
|
|
*
|
|
* Specifies how many tiles to use.
|
|
* Alternatively, the tiling can be specified in terms of tile size (tile_size method).
|
|
* The tile_size method will override the tile count specified in tiles.
|
|
*/
|
|
void tiles (size_t nx, size_t ny);
|
|
|
|
/**
|
|
* @brief Sets the tile border
|
|
*
|
|
* The tile border specifies the amount by which the tiles overlap.
|
|
* The tile border is given in micron units.
|
|
*/
|
|
void tile_border (double bx, double by);
|
|
|
|
/**
|
|
* @brief Sets the tile origin
|
|
*
|
|
* If the tile origin is specified, the lower left corner of the
|
|
* lower left tile is fixed and will not be moved.
|
|
*/
|
|
void tile_origin (double xo, double yo);
|
|
|
|
/**
|
|
* @brief Specifies the number of threads to use
|
|
*/
|
|
void set_threads (size_t n);
|
|
|
|
/**
|
|
* @brief Gets the number of threads used
|
|
*/
|
|
size_t threads () const
|
|
{
|
|
return m_threads;
|
|
}
|
|
|
|
/**
|
|
* @brief Queue a script for execution with "execute"
|
|
*
|
|
* Multiple scripts can be installed. They will be executed in parallel (if the number
|
|
* of threads allows).
|
|
*/
|
|
void queue (const std::string &script);
|
|
|
|
/**
|
|
* @brief Execute the job
|
|
*
|
|
* The description (desc) is shown in the progress bar.
|
|
*/
|
|
void execute (const std::string &desc);
|
|
|
|
private:
|
|
friend class TilingProcessorWorker;
|
|
friend class TilingProcessorOutputFunction;
|
|
friend class TilingProcessorReceiverFunction;
|
|
|
|
struct InputSpec
|
|
{
|
|
std::string name;
|
|
db::RecursiveShapeIterator iter;
|
|
db::ICplxTrans trans;
|
|
bool region;
|
|
bool merged_semantics;
|
|
};
|
|
|
|
struct OutputSpec
|
|
{
|
|
std::string name;
|
|
size_t id;
|
|
db::TileOutputReceiver *receiver;
|
|
db::ICplxTrans trans;
|
|
};
|
|
|
|
std::vector<InputSpec>::const_iterator begin_inputs () const { return m_inputs.begin (); }
|
|
std::vector<InputSpec>::const_iterator end_inputs () const { return m_inputs.end (); }
|
|
|
|
void put (size_t ix, size_t iy, const db::Box &tile, const std::vector<tl::Variant> &args);
|
|
tl::Variant receiver (const std::vector<tl::Variant> &args);
|
|
tl::Eval &top_eval () { return m_top_eval; }
|
|
|
|
std::vector<InputSpec> m_inputs;
|
|
std::vector<OutputSpec> m_outputs;
|
|
db::DBox m_frame;
|
|
double m_tile_width, m_tile_height;
|
|
size_t m_ntiles_w, m_ntiles_h;
|
|
bool m_tile_size_given, m_tile_count_given;
|
|
double m_tile_origin_x, m_tile_origin_y;
|
|
bool m_tile_origin_given;
|
|
double m_tile_bx, m_tile_by;
|
|
size_t m_threads;
|
|
double m_dbu, m_dbu_specific;
|
|
bool m_dbu_specific_set;
|
|
bool m_scale_to_dbu;
|
|
std::vector<std::string> m_scripts;
|
|
QMutex m_output_mutex;
|
|
tl::Eval m_top_eval;
|
|
};
|
|
|
|
}
|
|
|
|
namespace tl
|
|
{
|
|
template <>
|
|
struct type_traits<db::TilingProcessor> : public type_traits<void>
|
|
{
|
|
typedef tl::true_tag has_default_constructor;
|
|
typedef tl::false_tag has_copy_constructor;
|
|
};
|
|
}
|
|
|
|
#endif
|
|
|