mirror of https://github.com/KLayout/klayout.git
WIP: refactoring, added first tests for LVS
This commit is contained in:
parent
15022709b4
commit
2f6aae7204
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<klayout-macro>
|
||||
<description/>
|
||||
<version/>
|
||||
<category/>
|
||||
<prolog/>
|
||||
<epilog/>
|
||||
<doc/>
|
||||
<autorun>true</autorun>
|
||||
<autorun-early>false</autorun-early>
|
||||
<shortcut/>
|
||||
<show-in-menu>false</show-in-menu>
|
||||
<group-name/>
|
||||
<menu-path/>
|
||||
<interpreter>ruby</interpreter>
|
||||
<dsl-interpreter-name/>
|
||||
<text>
|
||||
# Installs the home menu entries (needs to be done on autorun, not autorun-early)
|
||||
|
||||
if RBA::Application::instance && RBA::Application::instance.main_window
|
||||
|
||||
cat = "drc"
|
||||
|
||||
name = cat.upcase
|
||||
|
||||
mw = RBA::Application::instance.main_window
|
||||
mw.menu.insert_menu("tools_menu.verification_group+", cat, name)
|
||||
|
||||
new_action = RBA::Action::new
|
||||
new_action.title = "New #{name} Script"
|
||||
new_action.on_triggered do
|
||||
mw.show_macro_editor(cat, true)
|
||||
end
|
||||
|
||||
mw.menu.insert_item("tools_menu.#{cat}.end", "new_script", new_action)
|
||||
|
||||
edit_action = RBA::Action::new
|
||||
edit_action.title = "Edit #{name} Script"
|
||||
edit_action.on_triggered do
|
||||
mw.show_macro_editor(cat, false)
|
||||
end
|
||||
|
||||
mw.menu.insert_item("tools_menu.#{cat}.end", "edit_script", edit_action)
|
||||
|
||||
end
|
||||
</text>
|
||||
</klayout-macro>
|
||||
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<klayout-macro>
|
||||
<description/>
|
||||
<version/>
|
||||
<category/>
|
||||
<prolog/>
|
||||
<epilog/>
|
||||
<doc/>
|
||||
<autorun>true</autorun>
|
||||
<autorun-early>false</autorun-early>
|
||||
<shortcut/>
|
||||
<show-in-menu>false</show-in-menu>
|
||||
<group-name/>
|
||||
<menu-path/>
|
||||
<interpreter>ruby</interpreter>
|
||||
<dsl-interpreter-name/>
|
||||
<text>
|
||||
# Installs the home menu entries (needs to be done on autorun, not autorun-early)
|
||||
|
||||
if RBA::Application::instance && RBA::Application::instance.main_window
|
||||
|
||||
[ "drc", "lvs" ].each do |cat|
|
||||
|
||||
name = cat.upcase
|
||||
|
||||
mw = RBA::Application::instance.main_window
|
||||
mw.menu.insert_menu("tools_menu.verification_group+", cat, name)
|
||||
|
||||
new_action = RBA::Action::new
|
||||
new_action.title = "New #{name} Script"
|
||||
new_action.on_triggered do
|
||||
mw.show_macro_editor(cat, true)
|
||||
end
|
||||
|
||||
mw.menu.insert_item("tools_menu.#{cat}.end", "new_script", new_action)
|
||||
|
||||
edit_action = RBA::Action::new
|
||||
edit_action.title = "Edit #{name} Script"
|
||||
edit_action.on_triggered do
|
||||
mw.show_macro_editor(cat, false)
|
||||
end
|
||||
|
||||
mw.menu.insert_item("tools_menu.#{cat}.end", "edit_script", edit_action)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
</text>
|
||||
</klayout-macro>
|
||||
|
||||
|
|
@ -7,9 +7,6 @@
|
|||
<file alias="_drc_source.rb">built-in-macros/_drc_source.rb</file>
|
||||
<file alias="_drc_tags.rb">built-in-macros/_drc_tags.rb</file>
|
||||
<file alias="drc_interpreters.lym">built-in-macros/drc_interpreters.lym</file>
|
||||
<file alias="_lvs_netter.rb">built-in-macros/_lvs_netter.rb</file>
|
||||
<file alias="_lvs_engine.rb">built-in-macros/_lvs_engine.rb</file>
|
||||
<file alias="lvs_interpreters.lym">built-in-macros/lvs_interpreters.lym</file>
|
||||
<file alias="install.lym">built-in-macros/install.lym</file>
|
||||
<file alias="drc_install.lym">built-in-macros/drc_install.lym</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
|||
|
|
@ -69,9 +69,10 @@ plugins.depends += lib rdb db
|
|||
}
|
||||
|
||||
equals(HAVE_RUBY, "1") {
|
||||
SUBDIRS += drc
|
||||
MAIN_DEPENDS += drc
|
||||
SUBDIRS += drc lvs
|
||||
MAIN_DEPENDS += drc lvs
|
||||
drc.depends += rdb lym
|
||||
lvs.depends += drc
|
||||
}
|
||||
|
||||
equals(HAVE_QTBINDINGS, "1") {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = lvs unit_tests
|
||||
|
||||
unit_tests.depends += lvs
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<klayout-macro>
|
||||
<description/>
|
||||
<version/>
|
||||
<category/>
|
||||
<prolog/>
|
||||
<epilog/>
|
||||
<doc/>
|
||||
<autorun>true</autorun>
|
||||
<autorun-early>false</autorun-early>
|
||||
<shortcut/>
|
||||
<show-in-menu>false</show-in-menu>
|
||||
<group-name/>
|
||||
<menu-path/>
|
||||
<interpreter>ruby</interpreter>
|
||||
<dsl-interpreter-name/>
|
||||
<text>
|
||||
# Installs the home menu entries (needs to be done on autorun, not autorun-early)
|
||||
|
||||
if RBA::Application::instance && RBA::Application::instance.main_window
|
||||
|
||||
cat = "lvs"
|
||||
|
||||
name = cat.upcase
|
||||
|
||||
mw = RBA::Application::instance.main_window
|
||||
mw.menu.insert_menu("tools_menu.verification_group+", cat, name)
|
||||
|
||||
new_action = RBA::Action::new
|
||||
new_action.title = "New #{name} Script"
|
||||
new_action.on_triggered do
|
||||
mw.show_macro_editor(cat, true)
|
||||
end
|
||||
|
||||
mw.menu.insert_item("tools_menu.#{cat}.end", "new_script", new_action)
|
||||
|
||||
edit_action = RBA::Action::new
|
||||
edit_action.title = "Edit #{name} Script"
|
||||
edit_action.on_triggered do
|
||||
mw.show_macro_editor(cat, false)
|
||||
end
|
||||
|
||||
mw.menu.insert_item("tools_menu.#{cat}.end", "edit_script", edit_action)
|
||||
|
||||
end
|
||||
</text>
|
||||
</klayout-macro>
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
DESTDIR = $$OUT_PWD/../..
|
||||
TARGET = klayout_lvs
|
||||
|
||||
include($$PWD/../../lib.pri)
|
||||
|
||||
DEFINES += MAKE_LVS_LIBRARY
|
||||
|
||||
SOURCES = \
|
||||
lvsForceLink.cc \
|
||||
|
||||
HEADERS = \
|
||||
lvsCommon.h \
|
||||
lvsForceLink.h \
|
||||
|
||||
RESOURCES = \
|
||||
lvsResources.qrc
|
||||
|
||||
INCLUDEPATH += $$TL_INC $$DB_INC $$GSI_INC $$LYM_INC $$RDB_INC
|
||||
DEPENDPATH += $$TL_INC $$DB_INC $$GSI_INC $$LYM_INC $$RDB_INC
|
||||
LIBS += -L$$DESTDIR -lklayout_tl -lklayout_db -lklayout_gsi -lklayout_lym -lklayout_rdb -lklayout_drc
|
||||
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(HDR_lvsCommon_h)
|
||||
# define HDR_lvsCommon_h
|
||||
|
||||
# if defined _WIN32 || defined __CYGWIN__
|
||||
|
||||
# ifdef MAKE_LVS_LIBRARY
|
||||
# define LVS_PUBLIC __declspec(dllexport)
|
||||
# else
|
||||
# define LVS_PUBLIC __declspec(dllimport)
|
||||
# endif
|
||||
# define LVS_LOCAL
|
||||
# define LVS_PUBLIC_TEMPLATE
|
||||
|
||||
# else
|
||||
|
||||
# if __GNUC__ >= 4 || defined(__clang__)
|
||||
# define LVS_PUBLIC __attribute__ ((visibility ("default")))
|
||||
# define LVS_PUBLIC_TEMPLATE __attribute__ ((visibility ("default")))
|
||||
# define LVS_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
# else
|
||||
# define LVS_PUBLIC
|
||||
# define LVS_PUBLIC_TEMPLATE
|
||||
# define LVS_LOCAL
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 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 "lvsForceLink.h"
|
||||
#include "rdbForceLink.h"
|
||||
|
||||
namespace lvs
|
||||
{
|
||||
int _force_link_f ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 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_lvsForceLink
|
||||
#define HDR_lvsForceLink
|
||||
|
||||
#include "lvsCommon.h"
|
||||
|
||||
/**
|
||||
* @file Include this function to force linking of the lvs module
|
||||
*/
|
||||
|
||||
namespace lvs
|
||||
{
|
||||
LVS_PUBLIC int _force_link_f ();
|
||||
int _force_link_target = _force_link_f ();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<RCC>
|
||||
<qresource prefix="/built-in-macros">
|
||||
<file alias="_lvs_netter.rb">built-in-macros/_lvs_netter.rb</file>
|
||||
<file alias="_lvs_engine.rb">built-in-macros/_lvs_engine.rb</file>
|
||||
<file alias="lvs_interpreters.lym">built-in-macros/lvs_interpreters.lym</file>
|
||||
<file alias="lvs_install.lym">built-in-macros/lvs_install.lym</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 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 "tlUnitTest.h"
|
||||
#include "dbReader.h"
|
||||
#include "dbTestSupport.h"
|
||||
#include "lymMacro.h"
|
||||
|
||||
TEST(1)
|
||||
{
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/inv.oas";
|
||||
std::string schematic = "inv.cir"; // relative to inv.oas
|
||||
std::string au_cir = tl::testsrc ();
|
||||
au_cir += "/testdata/lvs/inv_layout.cir";
|
||||
std::string au_lvsdb = tl::testsrc ();
|
||||
au_lvsdb += "/testdata/lvs/inv.lvsdb";
|
||||
|
||||
std::string output_cir = this->tmp_file ("tmp.cir");
|
||||
std::string output_lvsdb = this->tmp_file ("tmp.lvsdb");
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.set_text (tl::sprintf (
|
||||
"source('%s', 'INVERTER')\n"
|
||||
"\n"
|
||||
"deep\n"
|
||||
"\n"
|
||||
"# Reports generated\n"
|
||||
"\n"
|
||||
"# LVS report to inv.lvsdb\n"
|
||||
"report_lvs('%s')\n"
|
||||
"\n"
|
||||
"# Write extracted netlist to inv_extracted.cir\n"
|
||||
"target_netlist('%s', write_spice, 'Extracted by KLayout')\n"
|
||||
"\n"
|
||||
"# Drawing layers\n"
|
||||
"\n"
|
||||
"nwell = input(1, 0)\n"
|
||||
"active = input(2, 0)\n"
|
||||
"pplus = input(3, 0)\n"
|
||||
"nplus = input(4, 0)\n"
|
||||
"poly = input(5, 0)\n"
|
||||
"contact = input(6, 0)\n"
|
||||
"metal1 = input(7, 0)\n"
|
||||
"metal1_lbl = labels(7, 1)\n"
|
||||
"via1 = input(8, 0)\n"
|
||||
"metal2 = input(9, 0)\n"
|
||||
"metal2_lbl = labels(9, 1)\n"
|
||||
"\n"
|
||||
"# Bulk layer for terminal provisioning\n"
|
||||
"\n"
|
||||
"bulk = polygon_layer\n"
|
||||
"\n"
|
||||
"# Computed layers\n"
|
||||
"\n"
|
||||
"active_in_nwell = active & nwell\n"
|
||||
"pactive = active_in_nwell & pplus\n"
|
||||
"pgate = pactive & poly\n"
|
||||
"psd = pactive - pgate\n"
|
||||
"\n"
|
||||
"active_outside_nwell = active - nwell\n"
|
||||
"nactive = active_outside_nwell & nplus\n"
|
||||
"ngate = nactive & poly\n"
|
||||
"nsd = nactive - ngate\n"
|
||||
"\n"
|
||||
"# Device extraction\n"
|
||||
"\n"
|
||||
"# PMOS transistor device extraction\n"
|
||||
"extract_devices(mos4('PMOS'), { 'SD' => psd, 'G' => pgate, 'W' => nwell, \n"
|
||||
" 'tS' => psd, 'tD' => psd, 'tG' => poly, 'tW' => nwell })\n"
|
||||
"\n"
|
||||
"# NMOS transistor device extraction\n"
|
||||
"extract_devices(mos4('NMOS'), { 'SD' => nsd, 'G' => ngate, 'W' => bulk, \n"
|
||||
" 'tS' => nsd, 'tD' => nsd, 'tG' => poly, 'tW' => bulk })\n"
|
||||
"\n"
|
||||
"# Define connectivity for netlist extraction\n"
|
||||
"\n"
|
||||
"# Inter-layer\n"
|
||||
"connect(psd, contact)\n"
|
||||
"connect(nsd, contact)\n"
|
||||
"connect(poly, contact)\n"
|
||||
"connect(contact, metal1)\n"
|
||||
"connect(metal1, metal1_lbl) # attaches labels\n"
|
||||
"connect(metal1, via1)\n"
|
||||
"connect(via1, metal2)\n"
|
||||
"connect(metal2, metal2_lbl) # attaches labels\n"
|
||||
"\n"
|
||||
"# Global\n"
|
||||
"connect_global(bulk, 'SUBSTRATE')\n"
|
||||
"connect_global(nwell, 'NWELL')\n"
|
||||
"\n"
|
||||
"# Compare section\n"
|
||||
"\n"
|
||||
"schematic('%s')\n"
|
||||
"\n"
|
||||
"compare\n"
|
||||
, input, output_lvsdb, output_cir, schematic)
|
||||
);
|
||||
lvs.set_interpreter (lym::Macro::DSLInterpreter);
|
||||
lvs.set_dsl_interpreter ("lvs-dsl");
|
||||
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
compare_text_files (output_cir, au_cir);
|
||||
compare_text_files (output_lvsdb, au_lvsdb);
|
||||
}
|
||||
|
||||
#if 0
|
||||
TEST(2)
|
||||
{
|
||||
lym::Macro lvs;
|
||||
lvs.set_text (
|
||||
"dbu 0.001\n"
|
||||
"def compare(a, b, ex)\n"
|
||||
" a = a.to_s\n"
|
||||
" b = b.to_s\n"
|
||||
" if a != b\n"
|
||||
" raise(ex + \" (actual=#{a}, ref=#{b})\")\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
"compare(0.1.um, 0.1, \"unexpected value when converting um\")\n"
|
||||
"compare(0.1.micron, 0.1, \"unexpected value when converting micron\")\n"
|
||||
"compare(0.1.um2, 0.1, \"unexpected value when converting um2\")\n"
|
||||
"compare(0.1.mm2, 100000.0, \"unexpected value when converting mm2\")\n"
|
||||
"compare(120.dbu, 0.12, \"unexpected value when converting dbu\")\n"
|
||||
"compare((0.1.um + 120.dbu), 0.22, \"unexpected value when adding values\")\n"
|
||||
"compare(0.1.mm, 100.0, \"unexpected value when converting mm\")\n"
|
||||
"compare(1e-6.m, 1.0, \"unexpected value when converting m\")\n"
|
||||
"compare(1.um, 1.0, \"unexpected value when converting integer um\")\n"
|
||||
"compare(1.micron, 1.0, \"unexpected value when convering integer micron\")\n"
|
||||
"compare(1.um2, 1.0, \"unexpected value when converting integer um2\")\n"
|
||||
"compare(1.mm2, 1000000.0, \"unexpected value when converting integer mm2\")\n"
|
||||
"compare((1.um + 120.dbu), 1.12, \"unexpected value when adding integer values\")\n"
|
||||
"compare(1.mm, 1000.0, \"unexpected value when converting integer mm\")\n"
|
||||
"compare(1.m, 1000000.0, \"unexpected value when converting integer m\")\n"
|
||||
);
|
||||
lvs.set_interpreter (lym::Macro::DSLInterpreter);
|
||||
lvs.set_dsl_interpreter ("lvs-dsl");
|
||||
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,623 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2019 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 "tlUnitTest.h"
|
||||
#include "dbReader.h"
|
||||
#include "dbTestSupport.h"
|
||||
#include "dbNetlist.h"
|
||||
#include "dbNetlistSpiceReader.h"
|
||||
#include "lymMacro.h"
|
||||
#include "tlFileUtils.h"
|
||||
|
||||
#if 0 // @@@
|
||||
TEST(1)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_1.lvs";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au1.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = nil\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
||||
TEST(2)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_2.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/lvstest.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au2.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
||||
TEST(3_Flat)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_3.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/lvstest.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au3.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
||||
TEST(4_Hierarchical)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_4.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/lvstest.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au4.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
||||
TEST(5_FlatAntenna)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_5.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/antenna_l1.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au5.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
||||
TEST(6_HierarchicalAntenna)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_6.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/antenna_l1.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au6.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
||||
TEST(7_AntennaWithDiodes)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_7.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/antenna_l1.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au7.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
||||
TEST(8_TextsAndPolygons)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_8.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/texts.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au8.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
||||
static void compare_netlists (tl::TestBase *_this, const std::string &cir, const std::string &cir_au)
|
||||
{
|
||||
db::Netlist nl, nl_au;
|
||||
|
||||
db::NetlistSpiceReader reader;
|
||||
|
||||
{
|
||||
tl::info << "Output: " << cir;
|
||||
tl::InputStream is (cir);
|
||||
reader.read (is, nl);
|
||||
}
|
||||
|
||||
{
|
||||
tl::info << "Golden: " << cir_au;
|
||||
tl::InputStream is (cir_au);
|
||||
reader.read (is, nl_au);
|
||||
}
|
||||
|
||||
db::compare_netlist (_this, nl, nl_au);
|
||||
}
|
||||
|
||||
TEST(9_NetlistExtraction)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_9.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/ringo.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au9a.cir";
|
||||
|
||||
std::string au_simplified = tl::testsrc ();
|
||||
au_simplified += "/testdata/lvs/lvsSimpleTests_au9b.cir";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.cir");
|
||||
std::string output_simplified = this->tmp_file ("tmp_simplified.cir");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
"$lvs_test_target_simplified = '%s'\n"
|
||||
, input, output, output_simplified)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
|
||||
// verify
|
||||
|
||||
CHECKPOINT ();
|
||||
compare_netlists (_this, output, au);
|
||||
|
||||
CHECKPOINT ();
|
||||
compare_netlists (_this, output_simplified, au_simplified);
|
||||
}
|
||||
|
||||
TEST(10_NetlistExtractionFlat)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_10.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/ringo.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au10a.cir";
|
||||
|
||||
std::string au_simplified = tl::testsrc ();
|
||||
au_simplified += "/testdata/lvs/lvsSimpleTests_au10b.cir";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.cir");
|
||||
std::string output_simplified = this->tmp_file ("tmp_simplified.cir");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
"$lvs_test_target_simplified = '%s'\n"
|
||||
, input, output, output_simplified)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
|
||||
// verify
|
||||
|
||||
CHECKPOINT ();
|
||||
compare_netlists (_this, output, au);
|
||||
|
||||
CHECKPOINT ();
|
||||
compare_netlists (_this, output_simplified, au_simplified);
|
||||
}
|
||||
|
||||
TEST(11_CustomDevices)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_11.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/vdiv.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au11a.cir";
|
||||
|
||||
std::string au_simplified = tl::testsrc ();
|
||||
au_simplified += "/testdata/lvs/lvsSimpleTests_au11b.cir";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.cir");
|
||||
std::string output_simplified = this->tmp_file ("tmp_simplified.cir");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
"$lvs_test_target_simplified = '%s'\n"
|
||||
, input, output, output_simplified)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
|
||||
// verify
|
||||
|
||||
CHECKPOINT ();
|
||||
compare_netlists (_this, output, au);
|
||||
|
||||
CHECKPOINT ();
|
||||
compare_netlists (_this, output_simplified, au_simplified);
|
||||
}
|
||||
|
||||
TEST(12_NetlistJoinLabels)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_12.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/implicit_nets.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au12a.cir";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.cir");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
"$lvs_test_target_simplified = nil\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
// verify
|
||||
|
||||
CHECKPOINT ();
|
||||
compare_netlists (_this, output, au);
|
||||
}
|
||||
|
||||
TEST(13a_KissingCorners)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_13a.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/kissing_corners.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au13a.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
// verify
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
CHECKPOINT ();
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
|
||||
TEST(13b_KissingCornersDeep)
|
||||
{
|
||||
std::string rs = tl::testsrc ();
|
||||
rs += "/testdata/lvs/lvsSimpleTests_13b.lvs";
|
||||
|
||||
std::string input = tl::testsrc ();
|
||||
input += "/testdata/lvs/kissing_corners.gds";
|
||||
|
||||
std::string au = tl::testsrc ();
|
||||
au += "/testdata/lvs/lvsSimpleTests_au13b.gds";
|
||||
|
||||
std::string output = this->tmp_file ("tmp.gds");
|
||||
|
||||
{
|
||||
// Set some variables
|
||||
lym::Macro config;
|
||||
config.set_text (tl::sprintf (
|
||||
"$lvs_test_source = '%s'\n"
|
||||
"$lvs_test_target = '%s'\n"
|
||||
, input, output)
|
||||
);
|
||||
config.set_interpreter (lym::Macro::Ruby);
|
||||
EXPECT_EQ (config.run (), 0);
|
||||
}
|
||||
|
||||
lym::Macro lvs;
|
||||
lvs.load_from (rs);
|
||||
EXPECT_EQ (lvs.run (), 0);
|
||||
|
||||
// verify
|
||||
|
||||
db::Layout layout;
|
||||
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout);
|
||||
}
|
||||
|
||||
CHECKPOINT ();
|
||||
db::compare_layouts (_this, layout, au, db::NoNormalization);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
DESTDIR_UT = $$OUT_PWD/../..
|
||||
DESTDIR = $$OUT_PWD/..
|
||||
|
||||
TARGET = lvs_tests
|
||||
|
||||
include($$PWD/../../lib_ut.pri)
|
||||
|
||||
SOURCES = \
|
||||
lvsBasicTests.cc \
|
||||
lvsSimpleTests.cc \
|
||||
|
||||
INCLUDEPATH += $$DRC_INC $$TL_INC $$RDB_INC $$DB_INC $$GSI_INC $$LYM_INC
|
||||
DEPENDPATH += $$DRC_INC $$TL_INC $$RDB_INC $$DB_INC $$GSI_INC $$LYM_INC
|
||||
|
||||
LIBS += -L$$DESTDIR_UT -lklayout_lvs -lklayout_drc -lklayout_rdb -lklayout_db -lklayout_tl -lklayout_gsi -lklayout_lym
|
||||
|
|
@ -0,0 +1,239 @@
|
|||
#%lvsdb-klayout
|
||||
|
||||
# Layout
|
||||
layout(
|
||||
top(INVERTER)
|
||||
unit(0.001)
|
||||
|
||||
# Layer section
|
||||
# This section lists the mask layers (drawing or derived) and their connections.
|
||||
|
||||
# Mask layers
|
||||
layer(l3 'NWELL (1/0)')
|
||||
layer(l8 'POLY (5/0)')
|
||||
layer(l9 'CONTACT (6/0)')
|
||||
layer(l10 'METAL1 (7/0)')
|
||||
layer(l11 'METAL1_LABEL (7/1)')
|
||||
layer(l12 'VIA1 (8/0)')
|
||||
layer(l13 'METAL2 (9/0)')
|
||||
layer(l14 'METAL2_LABEL (9/1)')
|
||||
layer(l15)
|
||||
layer(l23)
|
||||
layer(l31)
|
||||
|
||||
# Mask layer connectivity
|
||||
connect(l3 l3)
|
||||
connect(l8 l8 l9)
|
||||
connect(l9 l8 l9 l10 l23 l31)
|
||||
connect(l10 l9 l10 l11 l12)
|
||||
connect(l11 l10 l11)
|
||||
connect(l12 l10 l12 l13)
|
||||
connect(l13 l12 l13 l14)
|
||||
connect(l14 l13 l14)
|
||||
connect(l15 l15)
|
||||
connect(l23 l9 l23)
|
||||
connect(l31 l9 l31)
|
||||
|
||||
# Global nets and connectivity
|
||||
global(l3 NWELL)
|
||||
global(l15 SUBSTRATE)
|
||||
|
||||
# Device class section
|
||||
class(PMOS MOS4)
|
||||
class(NMOS MOS4)
|
||||
|
||||
# Device abstracts section
|
||||
# Device abstracts list the pin shapes of the devices.
|
||||
device(D$PMOS PMOS
|
||||
terminal(S
|
||||
rect(l23 (-575 -750) (450 1500))
|
||||
)
|
||||
terminal(G
|
||||
rect(l8 (-125 -750) (250 1500))
|
||||
)
|
||||
terminal(D
|
||||
rect(l23 (125 -750) (450 1500))
|
||||
)
|
||||
terminal(B
|
||||
rect(l3 (-125 -750) (250 1500))
|
||||
)
|
||||
)
|
||||
device(D$NMOS NMOS
|
||||
terminal(S
|
||||
rect(l31 (-575 -450) (450 900))
|
||||
)
|
||||
terminal(G
|
||||
rect(l8 (-125 -450) (250 900))
|
||||
)
|
||||
terminal(D
|
||||
rect(l31 (125 -450) (450 900))
|
||||
)
|
||||
terminal(B
|
||||
rect(l15 (-125 -450) (250 900))
|
||||
)
|
||||
)
|
||||
|
||||
# Circuit section
|
||||
# Circuits are the hierarchical building blocks of the netlist.
|
||||
circuit(INVERTER
|
||||
|
||||
# Nets with their geometries
|
||||
net(1 name(IN)
|
||||
rect(l8 (900 50) (250 1050))
|
||||
rect(l8 (-250 0) (250 3100))
|
||||
rect(l8 (-250 0) (250 1650))
|
||||
rect(l8 (-800 -3100) (550 400))
|
||||
rect(l9 (-450 -300) (200 200))
|
||||
rect(l10 (-300 -300) (400 400))
|
||||
rect(l11 (-201 -201) (2 2))
|
||||
)
|
||||
net(2 name(VSS)
|
||||
rect(l9 (550 300) (200 200))
|
||||
rect(l9 (-200 300) (200 200))
|
||||
rect(l10 (-250 -950) (300 1050))
|
||||
rect(l12 (-250 -950) (200 200))
|
||||
rect(l12 (-200 300) (200 200))
|
||||
rect(l13 (-750 -850) (2000 1000))
|
||||
rect(l14 (-101 -851) (2 2))
|
||||
rect(l31 (-1451 49) (450 900))
|
||||
)
|
||||
net(3 name(VDD)
|
||||
rect(l9 (550 4350) (200 200))
|
||||
rect(l9 (-200 300) (200 200))
|
||||
rect(l9 (-200 300) (200 200))
|
||||
rect(l10 (-250 -1300) (300 1600))
|
||||
rect(l12 (-250 -800) (200 200))
|
||||
rect(l12 (-200 300) (200 200))
|
||||
rect(l13 (-750 -850) (2000 1000))
|
||||
rect(l14 (-151 -851) (2 2))
|
||||
rect(l23 (-1401 -851) (450 1500))
|
||||
)
|
||||
net(4 name(OUT)
|
||||
rect(l9 (1300 4350) (200 200))
|
||||
rect(l9 (-200 300) (200 200))
|
||||
rect(l9 (-200 300) (200 200))
|
||||
rect(l9 (-200 -5250) (200 200))
|
||||
rect(l9 (-200 300) (200 200))
|
||||
rect(l10 (-250 3250) (300 1400))
|
||||
rect(l10 (-300 -4600) (300 3200))
|
||||
rect(l10 (-300 -2900) (450 400))
|
||||
rect(l10 (-450 -1550) (300 850))
|
||||
rect(l11 (-51 499) (2 2))
|
||||
rect(l23 (-351 2649) (450 1500))
|
||||
rect(l31 (-450 -5500) (450 900))
|
||||
)
|
||||
net(5 name(NWELL)
|
||||
rect(l3 (0 2950) (2000 3200))
|
||||
)
|
||||
net(6 name(SUBSTRATE))
|
||||
|
||||
# Devices and their connections
|
||||
device(1 D$PMOS
|
||||
location(1025 4950)
|
||||
param(L 0.25)
|
||||
param(W 1.5)
|
||||
param(AS 0.675)
|
||||
param(AD 0.675)
|
||||
param(PS 3.9)
|
||||
param(PD 3.9)
|
||||
terminal(S 3)
|
||||
terminal(G 1)
|
||||
terminal(D 4)
|
||||
terminal(B 5)
|
||||
)
|
||||
device(2 D$NMOS
|
||||
location(1025 650)
|
||||
param(L 0.25)
|
||||
param(W 0.9)
|
||||
param(AS 0.405)
|
||||
param(AD 0.405)
|
||||
param(PS 2.7)
|
||||
param(PD 2.7)
|
||||
terminal(S 2)
|
||||
terminal(G 1)
|
||||
terminal(D 4)
|
||||
terminal(B 6)
|
||||
)
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
# Reference netlist
|
||||
reference(
|
||||
|
||||
# Device class section
|
||||
class(PMOS MOS4)
|
||||
class(NMOS MOS4)
|
||||
|
||||
# Circuit section
|
||||
# Circuits are the hierarchical building blocks of the netlist.
|
||||
circuit(INVERTER
|
||||
|
||||
# Nets
|
||||
net(1 name(VSS))
|
||||
net(2 name(IN))
|
||||
net(3 name(OUT))
|
||||
net(4 name(NWELL))
|
||||
net(5 name(SUBSTRATE))
|
||||
net(6 name(VDD))
|
||||
|
||||
# Outgoing pins and their connections to nets
|
||||
pin(1)
|
||||
pin(2)
|
||||
pin(3)
|
||||
pin(4)
|
||||
pin(5)
|
||||
pin(6)
|
||||
|
||||
# Devices and their connections
|
||||
device(1 PMOS
|
||||
name(P)
|
||||
param(L 0.25)
|
||||
param(W 1.5)
|
||||
param(AS 0)
|
||||
param(AD 0)
|
||||
param(PS 0)
|
||||
param(PD 0)
|
||||
terminal(S 6)
|
||||
terminal(G 2)
|
||||
terminal(D 3)
|
||||
terminal(B 4)
|
||||
)
|
||||
device(2 NMOS
|
||||
name(N)
|
||||
param(L 0.25)
|
||||
param(W 0.9)
|
||||
param(AS 0)
|
||||
param(AD 0)
|
||||
param(PS 0)
|
||||
param(PD 0)
|
||||
terminal(S 3)
|
||||
terminal(G 2)
|
||||
terminal(D 1)
|
||||
terminal(B 5)
|
||||
)
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
# Cross reference
|
||||
xref(
|
||||
circuit(INVERTER INVERTER match
|
||||
xref(
|
||||
net(1 2 match)
|
||||
net(5 4 match)
|
||||
net(4 3 match)
|
||||
net(6 5 match)
|
||||
net(3 6 match)
|
||||
net(2 1 match)
|
||||
pin(() 0 match)
|
||||
pin(() 1 match)
|
||||
pin(() 2 match)
|
||||
pin(() 3 match)
|
||||
pin(() 4 match)
|
||||
pin(() 5 match)
|
||||
device(2 2 match)
|
||||
device(1 1 match)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
* Extracted by KLayout
|
||||
|
||||
* cell INVERTER
|
||||
.SUBCKT INVERTER
|
||||
* net 1 IN
|
||||
* net 2 VSS
|
||||
* net 3 VDD
|
||||
* net 4 OUT
|
||||
* net 5 NWELL
|
||||
* net 6 SUBSTRATE
|
||||
* device instance $1 r0 *1 1.025,4.95 PMOS
|
||||
M$1 3 1 4 5 PMOS L=0.25U W=1.5U AS=0.675P AD=0.675P PS=3.9U PD=3.9U
|
||||
* device instance $2 r0 *1 1.025,0.65 NMOS
|
||||
M$2 2 1 4 6 NMOS L=0.25U W=0.9U AS=0.405P AD=0.405P PS=2.7U PD=2.7U
|
||||
.ENDS INVERTER
|
||||
Loading…
Reference in New Issue