mirror of https://github.com/KLayout/klayout.git
Added tests and two convenience methods
The two convenience methods are Library#library_from_file Library#library_from_files Both create and register a Library object tied to a file. This object supports proper reloading and re-mapping on "refresh".
This commit is contained in:
parent
ca3505b872
commit
f501f039c0
|
|
@ -34,6 +34,7 @@ SOURCES = \
|
|||
dbEdgeProcessor.cc \
|
||||
dbEdges.cc \
|
||||
dbEdgesLocalOperations.cc \
|
||||
dbFileBasedLibrary.cc \
|
||||
dbFillTool.cc \
|
||||
dbFuzzyCellMapping.cc \
|
||||
dbGenericShapeIterator.cc \
|
||||
|
|
@ -274,6 +275,7 @@ HEADERS = \
|
|||
dbEdges.h \
|
||||
dbEdgesLocalOperations.h \
|
||||
dbEdgesToContours.h \
|
||||
dbFileBasedLibrary.h \
|
||||
dbFillTool.h \
|
||||
dbFuzzyCellMapping.h \
|
||||
dbGenericShapeIterator.h \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2026 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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "dbFileBasedLibrary.h"
|
||||
#include "dbReader.h"
|
||||
#include "dbCellMapping.h"
|
||||
|
||||
#include "tlFileUtils.h"
|
||||
#include "tlStream.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
FileBasedLibrary::FileBasedLibrary (const std::string &path, const std::string &name)
|
||||
: db::Library (), m_name (name), m_path (path), m_is_loaded (false)
|
||||
{
|
||||
set_description (tl::filename (path));
|
||||
}
|
||||
|
||||
void
|
||||
FileBasedLibrary::merge_with_other_layout (const std::string &path)
|
||||
{
|
||||
m_other_paths.push_back (path);
|
||||
if (m_is_loaded) {
|
||||
merge_impl (path);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
FileBasedLibrary::load ()
|
||||
{
|
||||
if (! m_is_loaded) {
|
||||
return reload ();
|
||||
} else {
|
||||
return get_name ();
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
FileBasedLibrary::reload ()
|
||||
{
|
||||
std::string name = m_name.empty () ? tl::basename (m_path) : m_name;
|
||||
|
||||
layout ().clear ();
|
||||
|
||||
tl::InputStream stream (m_path);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout ());
|
||||
|
||||
// Use the libname if there is one
|
||||
if (m_name.empty ()) {
|
||||
db::Layout::meta_info_name_id_type libname_name_id = layout ().meta_info_name_id ("libname");
|
||||
for (db::Layout::meta_info_iterator m = layout ().begin_meta (); m != layout ().end_meta (); ++m) {
|
||||
if (m->first == libname_name_id && ! m->second.value.is_nil ()) {
|
||||
name = m->second.value.to_string ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto p = m_other_paths.begin (); p != m_other_paths.end (); ++p) {
|
||||
merge_impl (*p);
|
||||
}
|
||||
|
||||
m_is_loaded = true;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
void
|
||||
FileBasedLibrary::merge_impl (const std::string &path)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
tl::InputStream stream (path);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
|
||||
std::vector<db::cell_index_type> target_cells, source_cells;
|
||||
|
||||
// collect the cells to pull in (all top cells of the library layout)
|
||||
// NOTE: cells are not overwritten - the first layout wins, in terms
|
||||
// of cell names and also in terms of database unit.
|
||||
for (auto c = ly.begin_top_down (); c != ly.end_top_cells (); ++c) {
|
||||
std::string cn = ly.cell_name (*c);
|
||||
if (! layout ().has_cell (cn.c_str ())) {
|
||||
source_cells.push_back (*c);
|
||||
target_cells.push_back (layout ().add_cell (cn.c_str ()));
|
||||
}
|
||||
}
|
||||
|
||||
db::CellMapping cm;
|
||||
cm.create_multi_mapping_full (layout (), target_cells, ly, source_cells);
|
||||
layout ().copy_tree_shapes (ly, cm);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2026 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_dbFileBasedLibrary
|
||||
#define HDR_dbFileBasedLibrary
|
||||
|
||||
#include "dbLibrary.h"
|
||||
#include "dbCommon.h"
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A Library specialization that ties a library to a file
|
||||
*
|
||||
* This object supports loading a library from multiple files and merging them into
|
||||
* a single library (e.g. for loading a directory of cell files).
|
||||
*/
|
||||
class DB_PUBLIC FileBasedLibrary
|
||||
: public db::Library
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a file-based library object
|
||||
*
|
||||
* @param path The file path
|
||||
* @param name The library name
|
||||
*
|
||||
* If the library name is an empty string, the library name is taken from
|
||||
* a GDS LIBNAME or from the file name in the path.
|
||||
*
|
||||
* Note that you need to call "load" in order to actually load the file.
|
||||
*/
|
||||
FileBasedLibrary (const std::string &path, const std::string &name = std::string ());
|
||||
|
||||
/**
|
||||
* @brief Merges another file into this library
|
||||
*
|
||||
* If the library was not loaded already, the merge requests are postponed
|
||||
* until "load" is called.
|
||||
*/
|
||||
void merge_with_other_layout (const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Loads the files
|
||||
*
|
||||
* If the files are already loaded, this method does nothing.
|
||||
* It returns the name of the library derived from the first file
|
||||
* or the name given in the constructor. The constructor name has
|
||||
* priority.
|
||||
*/
|
||||
std::string load ();
|
||||
|
||||
/**
|
||||
* @brief Implements the reload feature
|
||||
*/
|
||||
virtual std::string reload ();
|
||||
|
||||
/**
|
||||
* @brief Set the paths
|
||||
* This method is provided for test purposes only.
|
||||
*/
|
||||
void set_paths (const std::string &path, const std::list<std::string> &other_paths = std::list<std::string> ())
|
||||
{
|
||||
m_path = path;
|
||||
m_other_paths = other_paths;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
std::string m_path;
|
||||
std::list<std::string> m_other_paths;
|
||||
bool m_is_loaded;
|
||||
|
||||
void merge_impl (const std::string &path);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -177,8 +177,6 @@ Library::refresh ()
|
|||
void
|
||||
Library::remap_to (db::Library *other, db::Layout *original_layout)
|
||||
{
|
||||
tl_assert (other != this || original_layout != 0);
|
||||
|
||||
if (! original_layout) {
|
||||
original_layout = &layout ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "dbPCellDeclaration.h"
|
||||
#include "dbLibrary.h"
|
||||
#include "dbLibraryManager.h"
|
||||
#include "dbFileBasedLibrary.h"
|
||||
#include "tlLog.h"
|
||||
|
||||
namespace gsi
|
||||
|
|
@ -156,11 +157,63 @@ static LibraryImpl *new_lib ()
|
|||
return new LibraryImpl ();
|
||||
}
|
||||
|
||||
static db::Library *library_from_file (const std::string &path, const std::string &name)
|
||||
{
|
||||
std::unique_ptr<db::FileBasedLibrary> lib (new db::FileBasedLibrary (path, name));
|
||||
|
||||
std::string n = lib->load ();
|
||||
db::Library *ret = lib.get ();
|
||||
register_lib (lib.release (), n);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static db::Library *library_from_files (const std::vector<std::string> &paths, const std::string &name)
|
||||
{
|
||||
if (paths.empty ()) {
|
||||
throw tl::Exception (tl::to_string (tr ("At least one path must be given")));
|
||||
}
|
||||
|
||||
std::unique_ptr<db::FileBasedLibrary> lib (new db::FileBasedLibrary (paths.front (), name));
|
||||
for (auto i = paths.begin () + 1; i != paths.end (); ++i) {
|
||||
lib->merge_with_other_layout (*i);
|
||||
}
|
||||
|
||||
std::string n = lib->load ();
|
||||
db::Library *ret = lib.get ();
|
||||
register_lib (lib.release (), n);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A basic implementation of the library
|
||||
*/
|
||||
|
||||
LibraryClass<db::Library> decl_Library ("db", "LibraryBase",
|
||||
gsi::method ("library_from_file", &library_from_file, gsi::arg ("path"), gsi::arg ("name", std::string (), "auto"),
|
||||
"@brief Creates a library from a file\n"
|
||||
"@param path The path to the file from which to create the library from.\n"
|
||||
"@param name The name of the library. If empty, the name will be derived from the GDS LIBNAME or the file name.\n"
|
||||
"@return The library object created. It is already registered with the name given or derived from the file.\n"
|
||||
"\n"
|
||||
"This method will create a \\Library object which is tied to a specific file. This object supports "
|
||||
"automatic reloading when the \\Library#refresh method is called.\n"
|
||||
"\n"
|
||||
"This convenience method has been added in version 0.30.8.\n"
|
||||
) +
|
||||
gsi::method ("library_from_files", &library_from_files, gsi::arg ("paths"), gsi::arg ("name", std::string (), "auto"),
|
||||
"@brief Creates a library from a set of files\n"
|
||||
"@param paths The paths to the files from which to create the library from. At least one file needs to be given.\n"
|
||||
"@param name The name of the library. If empty, the name will be derived from the GDS LIBNAME or the file name.\n"
|
||||
"@return The library object created. It is already registered with the name given or derived from the file.\n"
|
||||
"\n"
|
||||
"This method will create a \\Library object which is tied to several files. This object supports "
|
||||
"automatic reloading when the \\Library#refresh method is called. The content of the files is merged "
|
||||
"into the library. This is useful for example to create one library from a collection of files.\n"
|
||||
"\n"
|
||||
"This convenience method has been added in version 0.30.8.\n"
|
||||
) +
|
||||
gsi::method ("library_by_name", &library_by_name, gsi::arg ("name"), gsi::arg ("for_technology", std::string (), "unspecific"),
|
||||
"@brief Gets a library by name\n"
|
||||
"Returns the library object for the given name. If the name is not a valid library name, nil is returned.\n"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2026 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
|
||||
|
||||
*/
|
||||
|
||||
#include "dbLibraryManager.h"
|
||||
#include "dbLibrary.h"
|
||||
#include "dbFileBasedLibrary.h"
|
||||
#include "tlUnitTest.h"
|
||||
#include "tlFileUtils.h"
|
||||
|
||||
// map library to different file (aka reload/refresh)
|
||||
TEST(1)
|
||||
{
|
||||
std::string pa = tl::testsrc () + "/testdata/gds/lib_a.gds";
|
||||
std::string pb = tl::testsrc () + "/testdata/gds/lib_b.gds";
|
||||
|
||||
db::FileBasedLibrary *lib = new db::FileBasedLibrary (pa);
|
||||
lib->load ();
|
||||
lib->set_name ("LIB");
|
||||
db::LibraryManager::instance ().register_lib (lib);
|
||||
|
||||
db::Layout l;
|
||||
auto top_cell_index = l.add_cell ("TOP");
|
||||
auto lib_proxy = l.get_lib_proxy (lib, lib->layout ().cell_by_name ("A").second);
|
||||
|
||||
l.cell (top_cell_index).insert (db::CellInstArray (db::CellInst (lib_proxy), db::Trans ()));
|
||||
|
||||
EXPECT_EQ (l.cell (top_cell_index).bbox ().to_string (), "(0,0;2000,2000)");
|
||||
|
||||
// switch to a different file and refresh
|
||||
lib->set_paths (pb);
|
||||
lib->refresh ();
|
||||
|
||||
EXPECT_EQ (l.cell (top_cell_index).bbox ().to_string (), "(-1000,-1000;1000,1000)");
|
||||
|
||||
db::LibraryManager::instance ().delete_lib (lib);
|
||||
}
|
||||
|
||||
// merge multiple files into one library
|
||||
TEST(2)
|
||||
{
|
||||
std::string pa = tl::testsrc () + "/testdata/gds/lib_a.gds";
|
||||
std::string pb = tl::testsrc () + "/testdata/gds/lib_b.gds";
|
||||
|
||||
db::FileBasedLibrary *lib = new db::FileBasedLibrary (pa);
|
||||
lib->merge_with_other_layout (pb);
|
||||
lib->load ();
|
||||
lib->set_name ("LIB");
|
||||
db::LibraryManager::instance ().register_lib (lib);
|
||||
|
||||
{
|
||||
db::Layout l;
|
||||
auto top_cell_index = l.add_cell ("TOP");
|
||||
auto lib_proxy = l.get_lib_proxy (lib, lib->layout ().cell_by_name ("A").second);
|
||||
|
||||
l.cell (top_cell_index).insert (db::CellInstArray (db::CellInst (lib_proxy), db::Trans ()));
|
||||
|
||||
// A comes from the first layout
|
||||
EXPECT_EQ (l.cell (top_cell_index).bbox ().to_string (), "(0,0;2000,2000)");
|
||||
}
|
||||
|
||||
{
|
||||
db::Layout l;
|
||||
auto top_cell_index = l.add_cell ("TOP");
|
||||
auto lib_proxy = l.get_lib_proxy (lib, lib->layout ().cell_by_name ("Z").second);
|
||||
|
||||
l.cell (top_cell_index).insert (db::CellInstArray (db::CellInst (lib_proxy), db::Trans ()));
|
||||
|
||||
// Z comes from the second layout
|
||||
EXPECT_EQ (l.cell (top_cell_index).bbox ().to_string (), "(0,0;100,100)");
|
||||
}
|
||||
|
||||
db::LibraryManager::instance ().delete_lib (lib);
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ SOURCES = \
|
|||
dbCompoundOperationTests.cc \
|
||||
dbEdgeNeighborhoodTests.cc \
|
||||
dbFillToolTests.cc \
|
||||
dbLibraryTests.cc \
|
||||
dbLogTests.cc \
|
||||
dbObjectWithPropertiesTests.cc \
|
||||
dbPLCConvexDecompositionTests.cc \
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@
|
|||
#include "layQtTools.h"
|
||||
#include "dbLibraryManager.h"
|
||||
#include "dbLibrary.h"
|
||||
#include "dbReader.h"
|
||||
#include "dbCellMapping.h"
|
||||
#include "dbFileBasedLibrary.h"
|
||||
#include "tlLog.h"
|
||||
#include "tlStream.h"
|
||||
#include "tlFileUtils.h"
|
||||
|
|
@ -42,81 +41,6 @@ namespace lay
|
|||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
class FileBasedLibrary
|
||||
: public db::Library
|
||||
{
|
||||
public:
|
||||
FileBasedLibrary (const std::string &path)
|
||||
: db::Library (), m_path (path)
|
||||
{
|
||||
set_description (tl::filename (path));
|
||||
}
|
||||
|
||||
void merge_with_other_layout (const std::string &path)
|
||||
{
|
||||
m_other_paths.push_back (path);
|
||||
merge_impl (path);
|
||||
}
|
||||
|
||||
virtual std::string reload ()
|
||||
{
|
||||
std::string name = tl::basename (m_path);
|
||||
|
||||
layout ().clear ();
|
||||
|
||||
tl::InputStream stream (m_path);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout ());
|
||||
|
||||
// Use the libname if there is one
|
||||
db::Layout::meta_info_name_id_type libname_name_id = layout ().meta_info_name_id ("libname");
|
||||
for (db::Layout::meta_info_iterator m = layout ().begin_meta (); m != layout ().end_meta (); ++m) {
|
||||
if (m->first == libname_name_id && ! m->second.value.is_nil ()) {
|
||||
name = m->second.value.to_string ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto p = m_other_paths.begin (); p != m_other_paths.end (); ++p) {
|
||||
merge_impl (*p);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_path;
|
||||
std::list<std::string> m_other_paths;
|
||||
|
||||
void merge_impl (const std::string &path)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
||||
tl::InputStream stream (path);
|
||||
db::Reader reader (stream);
|
||||
reader.read (ly);
|
||||
|
||||
std::vector<db::cell_index_type> target_cells, source_cells;
|
||||
|
||||
// collect the cells to pull in (all top cells of the library layout)
|
||||
// NOTE: cells are not overwritten - the first layout wins, in terms
|
||||
// of cell names and also in terms of database unit.
|
||||
for (auto c = ly.begin_top_down (); c != ly.end_top_cells (); ++c) {
|
||||
std::string cn = ly.cell_name (*c);
|
||||
if (! layout ().has_cell (cn.c_str ())) {
|
||||
source_cells.push_back (*c);
|
||||
target_cells.push_back (layout ().add_cell (cn.c_str ()));
|
||||
}
|
||||
}
|
||||
|
||||
db::CellMapping cm;
|
||||
cm.create_multi_mapping_full (layout (), target_cells, ly, source_cells);
|
||||
layout ().copy_tree_shapes (ly, cm);
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
LibraryController::LibraryController ()
|
||||
: m_file_watcher (0),
|
||||
dm_sync_files (this, &LibraryController::sync_files)
|
||||
|
|
@ -279,7 +203,7 @@ LibraryController::sync_files ()
|
|||
|
||||
} else {
|
||||
|
||||
std::map<std::string, FileBasedLibrary *> libs_by_name_here;
|
||||
std::map<std::string, db::FileBasedLibrary *> libs_by_name_here;
|
||||
|
||||
// Reload all files
|
||||
for (QStringList::const_iterator im = libs.begin (); im != libs.end (); ++im) {
|
||||
|
|
@ -289,13 +213,13 @@ LibraryController::sync_files ()
|
|||
|
||||
try {
|
||||
|
||||
std::unique_ptr<FileBasedLibrary> lib (new FileBasedLibrary (lib_path));
|
||||
std::unique_ptr<db::FileBasedLibrary> lib (new db::FileBasedLibrary (lib_path));
|
||||
if (! p->second.empty ()) {
|
||||
lib->set_technology (p->second);
|
||||
}
|
||||
|
||||
tl::log << "Reading library '" << lib_path << "'";
|
||||
std::string libname = lib->reload ();
|
||||
std::string libname = lib->load ();
|
||||
|
||||
// merge with existing lib if there is already one in this folder with the right name
|
||||
auto il = libs_by_name_here.find (libname);
|
||||
|
|
|
|||
|
|
@ -265,6 +265,70 @@ class DBLibrary_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
def test_8_file_based_library
|
||||
|
||||
# clean up before
|
||||
[ "RBA-unit-test" ].each do |name|
|
||||
l = RBA::Library::library_by_name(name)
|
||||
l && l.unregister
|
||||
end
|
||||
|
||||
lylib = RBA::Layout::new
|
||||
lylib.read(File.join($ut_testsrc, "testdata", "gds", "lib_a.gds"))
|
||||
|
||||
tmp = File::join($ut_testtmp, "rba_dbLibrary_8.gds")
|
||||
lylib.write(tmp)
|
||||
|
||||
lib = RBA::Library::library_from_file(tmp, "RBA-unit-test")
|
||||
|
||||
ly = RBA::Layout::new
|
||||
top = ly.create_cell("TOP")
|
||||
a = ly.create_cell("A", "RBA-unit-test")
|
||||
top.insert(RBA::CellInstArray::new(a, RBA::Trans::new))
|
||||
|
||||
assert_equal(top.dbbox.to_s, "(0,0;2,2)")
|
||||
|
||||
lylib.clear
|
||||
lylib.read(File.join($ut_testsrc, "testdata", "gds", "lib_b.gds"))
|
||||
lylib.write(tmp)
|
||||
|
||||
lib.refresh
|
||||
|
||||
assert_equal(top.dbbox.to_s, "(-1,-1;1,1)")
|
||||
|
||||
end
|
||||
|
||||
def test_9_file_based_library_multiple_files
|
||||
|
||||
# clean up before
|
||||
[ "RBA-unit-test" ].each do |name|
|
||||
l = RBA::Library::library_by_name(name)
|
||||
l && l.unregister
|
||||
end
|
||||
|
||||
files = [
|
||||
File.join($ut_testsrc, "testdata", "gds", "lib_a.gds"),
|
||||
File.join($ut_testsrc, "testdata", "gds", "lib_b.gds")
|
||||
]
|
||||
|
||||
lib = RBA::Library::library_from_files(files, "RBA-unit-test")
|
||||
|
||||
ly = RBA::Layout::new
|
||||
top = ly.create_cell("TOP")
|
||||
a = ly.create_cell("A", "RBA-unit-test")
|
||||
top.insert(RBA::CellInstArray::new(a, RBA::Trans::new))
|
||||
|
||||
assert_equal(top.dbbox.to_s, "(0,0;2,2)")
|
||||
|
||||
ly = RBA::Layout::new
|
||||
top = ly.create_cell("TOP")
|
||||
z = ly.create_cell("Z", "RBA-unit-test")
|
||||
top.insert(RBA::CellInstArray::new(z, RBA::Trans::new))
|
||||
|
||||
assert_equal(top.dbbox.to_s, "(0,0;0.1,0.1)")
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue