mirror of https://github.com/KLayout/klayout.git
Implemented #444 (double-height standard-cell support).
This commit is contained in:
parent
412fe2bbf9
commit
d0e6efa484
|
|
@ -1103,6 +1103,9 @@ private:
|
|||
// ------------------------------------------------------------------------------
|
||||
// hier_clusters implementation
|
||||
|
||||
template <class T>
|
||||
const db::cell_index_type hier_clusters<T>::top_cell_index = std::numeric_limits<db::cell_index_type>::max ();
|
||||
|
||||
template <class T>
|
||||
hier_clusters<T>::hier_clusters ()
|
||||
: m_base_verbosity (20)
|
||||
|
|
@ -1124,7 +1127,7 @@ void hier_clusters<T>::clear ()
|
|||
|
||||
template <class T>
|
||||
void
|
||||
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
|
||||
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<unsigned int> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
|
||||
{
|
||||
clear ();
|
||||
cell_clusters_box_converter<T> cbc (layout, *this);
|
||||
|
|
@ -1903,7 +1906,7 @@ hier_clusters<T>::propagate_cluster_inst (const db::Layout &layout, const db::Ce
|
|||
|
||||
template <class T>
|
||||
void
|
||||
hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
|
||||
hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<unsigned int> > *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
|
||||
{
|
||||
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity, tl::to_string (tr ("Computing shape clusters")));
|
||||
|
||||
|
|
@ -1918,8 +1921,30 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
|
|||
tl::RelativeProgress progress (tl::to_string (tr ("Computing local clusters")), called.size (), 1);
|
||||
|
||||
for (std::set<db::cell_index_type>::const_iterator c = called.begin (); c != called.end (); ++c) {
|
||||
build_local_cluster (layout, layout.cell (*c), shape_flags, conn, *c == cell.cell_index () ? attr_equivalence : 0);
|
||||
|
||||
// look for the net label joining spec - for the top cell the "top_cell_index" entry is looked for.
|
||||
// If there is no such entry or the cell is not the top cell, look for the entry by cell index.
|
||||
std::map<db::cell_index_type, tl::equivalence_clusters<unsigned int> >::const_iterator ae;
|
||||
const tl::equivalence_clusters<unsigned int> *ec = 0;
|
||||
if (attr_equivalence) {
|
||||
if (*c == cell.cell_index ()) {
|
||||
ae = attr_equivalence->find (top_cell_index);
|
||||
if (ae != attr_equivalence->end ()) {
|
||||
ec = &ae->second;
|
||||
}
|
||||
}
|
||||
if (! ec) {
|
||||
ae = attr_equivalence->find (*c);
|
||||
if (ae != attr_equivalence->end ()) {
|
||||
ec = &ae->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
build_local_cluster (layout, layout.cell (*c), shape_flags, conn, ec);
|
||||
|
||||
++progress;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -986,10 +986,15 @@ public:
|
|||
*/
|
||||
void set_base_verbosity (int bv);
|
||||
|
||||
/**
|
||||
* @brief A constant indicating the top cell for the equivalence cluster key
|
||||
*/
|
||||
static const db::cell_index_type top_cell_index;
|
||||
|
||||
/**
|
||||
* @brief Builds a hierarchy of clusters from a cell hierarchy and given connectivity
|
||||
*/
|
||||
void build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence = 0, const std::set<cell_index_type> *breakout_cells = 0);
|
||||
void build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<unsigned int> > *attr_equivalence = 0, const std::set<cell_index_type> *breakout_cells = 0);
|
||||
|
||||
/**
|
||||
* @brief Gets the connected clusters for a given cell
|
||||
|
|
@ -1030,7 +1035,7 @@ private:
|
|||
void build_local_cluster (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence);
|
||||
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, instance_interaction_cache_type &instance_interaction_cache);
|
||||
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, tl::RelativeProgress &progress, instance_interaction_cache_type &instance_interaction_cache);
|
||||
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence, const std::set<cell_index_type> *breakout_cells);
|
||||
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const std::map<db::cell_index_type, tl::equivalence_clusters<unsigned int> > *attr_equivalence, const std::set<cell_index_type> *breakout_cells);
|
||||
|
||||
std::map<db::cell_index_type, connected_clusters<T> > m_per_cell_clusters;
|
||||
int m_base_verbosity;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "dbLayoutVsSchematic.h"
|
||||
#include "dbLayoutToNetlistFormatDefs.h"
|
||||
#include "dbLayoutVsSchematicFormatDefs.h"
|
||||
#include "tlGlobPattern.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -295,6 +296,11 @@ size_t LayoutToNetlist::global_net_id (const std::string &name)
|
|||
}
|
||||
|
||||
void LayoutToNetlist::extract_netlist (const std::string &joined_net_names, bool include_floating_subcircuits)
|
||||
{
|
||||
extract_netlist (joined_net_names, std::map<std::string, std::string> (), include_floating_subcircuits);
|
||||
}
|
||||
|
||||
void LayoutToNetlist::extract_netlist (const std::string &joined_net_names, const std::map<std::string, std::string> &joined_net_names_per_cell, bool include_floating_subcircuits)
|
||||
{
|
||||
if (m_netlist_extracted) {
|
||||
throw tl::Exception (tl::to_string (tr ("The netlist has already been extracted")));
|
||||
|
|
@ -302,7 +308,23 @@ void LayoutToNetlist::extract_netlist (const std::string &joined_net_names, bool
|
|||
ensure_netlist ();
|
||||
|
||||
db::NetlistExtractor netex;
|
||||
|
||||
netex.set_joined_net_names (joined_net_names);
|
||||
|
||||
const db::Layout &layout = dss ().layout (m_layout_index);
|
||||
for (std::map<std::string, std::string>::const_iterator j = joined_net_names_per_cell.begin (); j != joined_net_names_per_cell.end (); ++j) {
|
||||
tl::GlobPattern pat (j->first);
|
||||
if (pat.is_const ()) {
|
||||
netex.set_joined_net_names (j->first, j->second);
|
||||
} else {
|
||||
for (db::Layout::const_iterator c = layout.begin (); c != layout.end (); ++c) {
|
||||
if (pat.match (layout.cell_name (c->cell_index ()))) {
|
||||
netex.set_joined_net_names (layout.cell_name (c->cell_index ()), j->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
netex.set_include_floating_subcircuits (include_floating_subcircuits);
|
||||
netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters);
|
||||
|
||||
|
|
|
|||
|
|
@ -391,6 +391,16 @@ public:
|
|||
*/
|
||||
void extract_netlist (const std::string &joined_net_names = std::string (), bool include_floating_subcircuits = false);
|
||||
|
||||
/**
|
||||
* @brief Runs the netlist extraction
|
||||
* In addition to the previous version, this extraction method allows specification of a per-cell list of
|
||||
* joined (labelled) net names.
|
||||
* The key of the "joined_net_names_per_cell" is a cell name or a glob expression for cells. On all matching cells,
|
||||
* the value is applied as a label selector for labels that are joined together. The "joined_net_names" expressions
|
||||
* is only applied to the top cell.
|
||||
*/
|
||||
void extract_netlist (const std::string &joined_net_names, const std::map<std::string, std::string> &joined_net_names_per_cell, bool include_floating_subcircuits = false);
|
||||
|
||||
/**
|
||||
* @brief Marks the netlist as extracted
|
||||
* NOTE: this method is provided for special cases such as netlist readers. Don't
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@ void NetlistExtractor::set_joined_net_names (const std::string &jnn)
|
|||
m_joined_net_names = jnn;
|
||||
}
|
||||
|
||||
void NetlistExtractor::set_joined_net_names (const std::string &cellname, const std::string &jnn)
|
||||
{
|
||||
m_joined_net_names_per_cell.push_back (std::make_pair (cellname, jnn));
|
||||
}
|
||||
|
||||
void NetlistExtractor::set_include_floating_subcircuits (bool f)
|
||||
{
|
||||
m_include_floating_subcircuits = f;
|
||||
|
|
@ -90,9 +95,17 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
|
|||
|
||||
// the big part: actually extract the nets
|
||||
|
||||
tl::equivalence_clusters<unsigned int> net_name_equivalence;
|
||||
if (m_text_annot_name_id.first && ! m_joined_net_names.empty ()) {
|
||||
build_net_name_equivalence (mp_layout, m_text_annot_name_id.second, m_joined_net_names, net_name_equivalence);
|
||||
std::map<db::cell_index_type, tl::equivalence_clusters<unsigned int> > net_name_equivalence;
|
||||
if (m_text_annot_name_id.first) {
|
||||
if (! m_joined_net_names.empty ()) {
|
||||
build_net_name_equivalence (mp_layout, m_text_annot_name_id.second, m_joined_net_names, net_name_equivalence [hier_clusters_type::top_cell_index]);
|
||||
}
|
||||
for (std::list<std::pair<std::string, std::string> >::const_iterator m = m_joined_net_names_per_cell.begin (); m != m_joined_net_names_per_cell.end (); ++m) {
|
||||
std::pair<bool, db::cell_index_type> cp = mp_layout->cell_by_name (m->first.c_str ());
|
||||
if (cp.first) {
|
||||
build_net_name_equivalence (mp_layout, m_text_annot_name_id.second, m->second, net_name_equivalence [cp.second]);
|
||||
}
|
||||
}
|
||||
}
|
||||
mp_clusters->build (*mp_layout, *mp_cell, db::ShapeIterator::Polygons, conn, &net_name_equivalence);
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,13 @@ public:
|
|||
*/
|
||||
void set_joined_net_names (const std::string &jnn);
|
||||
|
||||
/**
|
||||
* @brief Sets the joined net names attribute for a given cell name
|
||||
* While the single-parameter set_joined_net_names only acts on the top cell, this
|
||||
* version will act on the cell with the given name.
|
||||
*/
|
||||
void set_joined_net_names (const std::string &cell_name, const std::string &jnn);
|
||||
|
||||
/**
|
||||
* @brief Gets the joined net names expression
|
||||
*/
|
||||
|
|
@ -128,6 +135,7 @@ private:
|
|||
std::pair<bool, db::property_names_id_type> m_device_annot_name_id;
|
||||
std::pair<bool, db::property_names_id_type> m_terminal_annot_name_id;
|
||||
std::string m_joined_net_names;
|
||||
std::list<std::pair<std::string, std::string> > m_joined_net_names_per_cell;
|
||||
bool m_include_floating_subcircuits;
|
||||
|
||||
bool instance_is_device (db::properties_id_type prop_id) const;
|
||||
|
|
|
|||
|
|
@ -355,6 +355,17 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
|||
"\n"
|
||||
"The 'include_floating_subcircuits' argument has been introduced in version 0.26.2."
|
||||
) +
|
||||
gsi::method ("extract_netlist", &db::LayoutToNetlist::extract_netlist, gsi::arg ("join_net_names"), gsi::arg ("join_net_names_per_cell"), gsi::arg ("include_floating_subcircuits", false),
|
||||
"@brief Runs the netlist extraction\n"
|
||||
"This method runs the netlist extraction like the two-parameter version. In addition to the latter, this method "
|
||||
"can be given a per-cell net label joining specification in 'join_net_names_per_cell'. The keys of this array "
|
||||
"are cell names or cell names or cell name match expressions (glob style). The values are lable match expressions.\n"
|
||||
"\n"
|
||||
"If not an empty string, the 'join_net_names' label match expression is applied to the top cell. For all non-top cells "
|
||||
"the per-cell label match expression is applied and determines what labels are joined into single nets. "
|
||||
"As the keys of 'join_net_names_per_cell' are glob expressions, a single cell may fall into more than one category. In this "
|
||||
"case, the label match pattern are combined. In any case, the 'join_net_names' has priority for the top cell."
|
||||
) +
|
||||
gsi::method_ext ("internal_layout", &l2n_internal_layout,
|
||||
"@brief Gets the internal layout\n"
|
||||
"Usually it should not be required to obtain the internal layout. If you need to do so, make sure not to modify the layout as\n"
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ module DRC
|
|||
@engine = engine
|
||||
@netlisted = false
|
||||
@connect_implicit = []
|
||||
@connect_implicit_per_cell = {}
|
||||
@l2n = nil
|
||||
@lnum = 0
|
||||
@device_scaling = 1.0
|
||||
|
|
@ -203,6 +204,7 @@ module DRC
|
|||
def clear_connections
|
||||
@netlisted = false
|
||||
@connect_implicit = []
|
||||
@connect_implicit_per_cell = {}
|
||||
_clear_data
|
||||
end
|
||||
|
||||
|
|
@ -210,8 +212,9 @@ module DRC
|
|||
# @name connect_implicit
|
||||
# @brief Specifies a search pattern for labels which create implicit net connections
|
||||
# @synopsis connect_implicit(label_pattern)
|
||||
# @synopsis connect_implicit(cell_pattern, label_pattern)
|
||||
# Use this method to supply label strings which create implicit net connections
|
||||
# on the top level circuit. This feature is useful to connect identically labelled nets
|
||||
# on the top level circuit in the first version. This feature is useful to connect identically labelled nets
|
||||
# while a component isn't integrated yet. If the component is integrated, nets may be connected
|
||||
# on a higher hierarchy level - e.g. by a power mesh. Inside the component this net consists
|
||||
# of individual islands. To properly perform netlist extraction and comparison, these islands
|
||||
|
|
@ -219,12 +222,26 @@ module DRC
|
|||
# achive this if these islands are labelled with the same text on the top level of the
|
||||
# component.
|
||||
#
|
||||
# In the second version, the pattern can be specified for a cell range (given by a cell name pattern or a
|
||||
# single cell name). These pattern are applied to non-top cells. The unspecific pattern
|
||||
# has priority over the cell-specific ones. As the cell selector is a pattern itself, a
|
||||
# single cell may fall into more than one category. In this case, the label filters are
|
||||
# combined.
|
||||
#
|
||||
# The implicit connections are applied on the next net extraction and cleared
|
||||
# on "clear_connections".
|
||||
|
||||
def connect_implicit(arg)
|
||||
def connect_implicit(arg1, arg2 = nil)
|
||||
cleanup
|
||||
@connect_implicit << arg
|
||||
if arg2
|
||||
(arg2.is_a?(String) && arg2 != "") || raise("The second argument of 'connect_implicit' has to be a non-empty string")
|
||||
arg1.is_a?(String) || raise("The first argument of 'connect_implicit' has to be a string")
|
||||
@connect_implicit_per_cell[arg1] ||= []
|
||||
@connect_implicit_per_cell[arg1] << arg2
|
||||
else
|
||||
arg1.is_a?(String) || raise("The argument of 'connect_implicit' has to be a string")
|
||||
@connect_implicit << arg1
|
||||
end
|
||||
end
|
||||
|
||||
# %DRC%
|
||||
|
|
@ -341,15 +358,19 @@ module DRC
|
|||
|
||||
# run extraction in a timed environment
|
||||
if ! @netlisted
|
||||
|
||||
# build a glob expression from the parts
|
||||
exprs = @connect_implicit.collect { |c| c.gsub(/\?\*\[\]\{\},\(\)\\/) { |x| "\\" + x } }
|
||||
if exprs.size > 1
|
||||
expr = "{" + exprs.join(",") + "}"
|
||||
else
|
||||
expr = exprs[0] || ""
|
||||
expr = _join_glob_pattern(@connect_implicit)
|
||||
|
||||
# build cell-pattern specific glob expressions from the parts
|
||||
per_cell_expr = {}
|
||||
@connect_implicit_per_cell.each do |cell_pattern,label_pattern|
|
||||
per_cell_expr[cell_pattern] = _join_glob_pattern(label_pattern)
|
||||
end
|
||||
@engine._cmd(@l2n, :extract_netlist, expr)
|
||||
|
||||
@engine._cmd(@l2n, :extract_netlist, expr, per_cell_expr)
|
||||
@netlisted = true
|
||||
|
||||
end
|
||||
|
||||
@l2n
|
||||
|
|
@ -401,6 +422,19 @@ module DRC
|
|||
end
|
||||
end
|
||||
|
||||
def _join_glob_pattern(pattern)
|
||||
|
||||
exprs = pattern.collect { |c| c.gsub(/\?\*\[\]\{\},\(\)\\/) { |x| "\\" + x } }
|
||||
if exprs.size > 1
|
||||
expr = "{" + exprs.join(",") + "}"
|
||||
else
|
||||
expr = exprs[0] || ""
|
||||
end
|
||||
|
||||
expr
|
||||
|
||||
end
|
||||
|
||||
def _make_data
|
||||
|
||||
if @engine._dss
|
||||
|
|
|
|||
|
|
@ -184,17 +184,24 @@ to shapes belonging to tie-down diodes.
|
|||
<a name="connect_implicit"/><p>Usage:</p>
|
||||
<ul>
|
||||
<li><tt>connect_implicit(label_pattern)</tt></li>
|
||||
<li><tt>connect_implicit(cell_pattern, label_pattern)</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
Use this method to supply label strings which create implicit net connections
|
||||
Use the first version of this method to supply label strings which create implicit net connections
|
||||
on the top level circuit. This feature is useful to connect identically labelled nets
|
||||
while a component isn't integrated yet. If the component is integrated, nets may be connected
|
||||
on a higher hierarchy level - e.g. by a power mesh. Inside the component this net consists
|
||||
of individual islands. To properly perform netlist extraction and comparison, these islands
|
||||
need to be connected even though there isn't a physical connection. "connect_implicit" can
|
||||
achive this if these islands are labelled with the same text on the top level of the
|
||||
achieve this if these islands are labelled with the same text on the top level of the
|
||||
component.
|
||||
</p><p>
|
||||
In the second version, the pattern can be specified for a cell range (given by a cell glob-style
|
||||
name pattern or a single cell name). These pattern are applied to non-top cells. An unspecific pattern
|
||||
has priority over the cell-specific ones. As the cell selector is a pattern itself, a
|
||||
single cell may fall into more than one category. In this case, the label filters are
|
||||
combined.
|
||||
</p><p>
|
||||
The implicit connections are applied on the next net extraction and cleared
|
||||
on "clear_connections".
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -165,3 +165,15 @@ TEST(18_cheats)
|
|||
run_test (_this, "invchain_cheat", "invchain_for_cheat.gds");
|
||||
}
|
||||
|
||||
// testing cell specific net joining for VSS of the double-height inverter standard cell
|
||||
TEST(19_double_height_inv)
|
||||
{
|
||||
run_test (_this, "double_height", "double_height_inv.gds");
|
||||
}
|
||||
|
||||
// testing cell specific net joining for VSS of the double-height inverter standard cell
|
||||
TEST(20_double_height2_inv)
|
||||
{
|
||||
run_test (_this, "double_height2", "double_height2_inv.gds");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
* Extracted by KLayout
|
||||
|
||||
.SUBCKT INVCHAIN IN OUT VSS VDD
|
||||
X$1 VDD IN \$1 \$1 OUT VSS INV2
|
||||
.ENDS INVCHAIN
|
||||
|
||||
.SUBCKT INV2 VDD A1 A2 Q1 Q2 VSS
|
||||
X$1 VSS VDD A2 Q2 INV
|
||||
X$2 VSS VDD A1 Q1 INV
|
||||
.ENDS INV2
|
||||
|
||||
.SUBCKT INV \$1 \$2 \$3 \$4
|
||||
M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U
|
||||
+ PD=3.45U
|
||||
M$2 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U
|
||||
+ PD=3.45U
|
||||
.ENDS INV
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
|
||||
source($lvs_test_source)
|
||||
|
||||
report_lvs($lvs_test_target_lvsdb)
|
||||
|
||||
writer = write_spice(true, false)
|
||||
target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")
|
||||
|
||||
# needs this delegate because we use MOS3 which is not available in Spice
|
||||
class SpiceReaderDelegate < RBA::NetlistSpiceReaderDelegate
|
||||
|
||||
# says we want to catch these subcircuits as devices
|
||||
def wants_subcircuit(name)
|
||||
name == "HVNMOS" || name == "HVPMOS"
|
||||
end
|
||||
|
||||
# translate the element
|
||||
def element(circuit, el, name, model, value, nets, params)
|
||||
|
||||
if el != "M"
|
||||
# all other elements are left to the standard implementation
|
||||
return super
|
||||
end
|
||||
|
||||
if nets.size != 4
|
||||
error("Device #{model} needs four nodes")
|
||||
end
|
||||
|
||||
# provide a device class
|
||||
cls = circuit.netlist.device_class_by_name(model)
|
||||
if ! cls
|
||||
cls = RBA::DeviceClassMOS3Transistor::new
|
||||
cls.name = model
|
||||
circuit.netlist.add(cls)
|
||||
end
|
||||
|
||||
# create a device
|
||||
device = circuit.create_device(cls, name)
|
||||
|
||||
# and configure the device
|
||||
[ "S", "G", "D" ].each_with_index do |t,index|
|
||||
device.connect_terminal(t, nets[index])
|
||||
end
|
||||
device.set_parameter("W", params["W"] * 1e6)
|
||||
device.set_parameter("L", params["L"] * 1e6)
|
||||
|
||||
device
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
reader = RBA::NetlistSpiceReader::new(SpiceReaderDelegate::new)
|
||||
schematic("double_height_inv.cir", reader)
|
||||
|
||||
deep
|
||||
|
||||
# Drawing layers
|
||||
|
||||
nwell = input(1, 0)
|
||||
active = input(2, 0)
|
||||
poly = input(3, 0)
|
||||
poly_lbl = input(3, 1)
|
||||
diff_cont = input(4, 0)
|
||||
poly_cont = input(5, 0)
|
||||
metal1 = input(6, 0)
|
||||
metal1_lbl = input(6, 1)
|
||||
via1 = input(7, 0)
|
||||
metal2 = input(8, 0)
|
||||
metal2_lbl = input(8, 1)
|
||||
|
||||
# Bulk layer for terminal provisioning
|
||||
|
||||
bulk = polygon_layer
|
||||
|
||||
psd = nil
|
||||
nsd = nil
|
||||
|
||||
# Computed layers
|
||||
|
||||
active_in_nwell = active & nwell
|
||||
pactive = active_in_nwell
|
||||
pgate = pactive & poly
|
||||
psd = pactive - pgate
|
||||
|
||||
active_outside_nwell = active - nwell
|
||||
nactive = active_outside_nwell
|
||||
ngate = nactive & poly
|
||||
nsd = nactive - ngate
|
||||
|
||||
# Device extraction
|
||||
|
||||
# PMOS transistor device extraction
|
||||
extract_devices(mos3("PMOS"), { "SD" => psd, "G" => pgate,
|
||||
"tS" => psd, "tD" => psd, "tG" => poly })
|
||||
|
||||
# NMOS transistor device extraction
|
||||
extract_devices(mos3("NMOS"), { "SD" => nsd, "G" => ngate,
|
||||
"tS" => nsd, "tD" => nsd, "tG" => poly })
|
||||
|
||||
# Define connectivity for netlist extraction
|
||||
|
||||
# Inter-layer
|
||||
connect(psd, diff_cont)
|
||||
connect(nsd, diff_cont)
|
||||
connect(poly, poly_cont)
|
||||
connect(diff_cont, metal1)
|
||||
connect(poly_cont, metal1)
|
||||
connect(metal1, via1)
|
||||
connect(via1, metal2)
|
||||
|
||||
# attach labels
|
||||
connect(poly, poly_lbl)
|
||||
connect(metal1, metal1_lbl)
|
||||
connect(metal2, metal2_lbl)
|
||||
|
||||
# Global
|
||||
connect_global(bulk, "SUBSTRATE")
|
||||
|
||||
# Implicit connection of the INV2
|
||||
# VSS nets
|
||||
connect_implicit("INV2", "VSS")
|
||||
|
||||
# Compare section
|
||||
|
||||
netlist.simplify
|
||||
align
|
||||
|
||||
compare
|
||||
|
||||
|
|
@ -0,0 +1,326 @@
|
|||
#%lvsdb-klayout
|
||||
J(
|
||||
W(INVCHAIN)
|
||||
U(0.001)
|
||||
L(l3 '3/0')
|
||||
L(l11 '3/1')
|
||||
L(l6 '4/0')
|
||||
L(l7 '5/0')
|
||||
L(l8 '6/0')
|
||||
L(l12 '6/1')
|
||||
L(l9 '7/0')
|
||||
L(l10 '8/0')
|
||||
L(l13 '8/1')
|
||||
L(l14)
|
||||
L(l2)
|
||||
L(l5)
|
||||
C(l3 l3 l11 l7)
|
||||
C(l11 l3 l11)
|
||||
C(l6 l6 l8 l2 l5)
|
||||
C(l7 l3 l7 l8)
|
||||
C(l8 l6 l7 l8 l12 l9)
|
||||
C(l12 l8 l12)
|
||||
C(l9 l8 l9 l10)
|
||||
C(l10 l9 l10 l13)
|
||||
C(l13 l10 l13)
|
||||
C(l14 l14)
|
||||
C(l2 l6 l2)
|
||||
C(l5 l6 l5)
|
||||
G(l14 SUBSTRATE)
|
||||
K(PMOS MOS3)
|
||||
K(NMOS MOS3)
|
||||
D(D$PMOS PMOS
|
||||
T(S
|
||||
R(l2 (-900 -475) (775 950))
|
||||
)
|
||||
T(G
|
||||
R(l3 (-125 -475) (250 950))
|
||||
)
|
||||
T(D
|
||||
R(l2 (125 -475) (775 950))
|
||||
)
|
||||
)
|
||||
D(D$NMOS NMOS
|
||||
T(S
|
||||
R(l5 (-900 -475) (775 950))
|
||||
)
|
||||
T(G
|
||||
R(l3 (-125 -475) (250 950))
|
||||
)
|
||||
T(D
|
||||
R(l5 (125 -475) (775 950))
|
||||
)
|
||||
)
|
||||
X(INV
|
||||
R((-1500 -800) (3000 4600))
|
||||
N(1
|
||||
R(l6 (290 -310) (220 220))
|
||||
R(l6 (-220 180) (220 220))
|
||||
R(l8 (-290 -690) (360 760))
|
||||
R(l9 (-305 -705) (250 250))
|
||||
R(l9 (-250 150) (250 250))
|
||||
R(l10 (-2025 -775) (3000 900))
|
||||
R(l5 (-1375 -925) (775 950))
|
||||
)
|
||||
N(2
|
||||
R(l6 (290 2490) (220 220))
|
||||
R(l6 (-220 180) (220 220))
|
||||
R(l8 (-290 -690) (360 760))
|
||||
R(l9 (-305 -705) (250 250))
|
||||
R(l9 (-250 150) (250 250))
|
||||
R(l10 (-2025 -775) (3000 900))
|
||||
R(l2 (-1375 -925) (775 950))
|
||||
)
|
||||
N(3
|
||||
R(l3 (-125 -250) (250 2500))
|
||||
R(l3 (-250 -3050) (250 1600))
|
||||
R(l3 (-250 1200) (250 1600))
|
||||
)
|
||||
N(4
|
||||
R(l6 (-510 -310) (220 220))
|
||||
R(l6 (-220 180) (220 220))
|
||||
R(l6 (-220 2180) (220 220))
|
||||
R(l6 (-220 180) (220 220))
|
||||
R(l8 (-290 -3530) (360 2840))
|
||||
R(l8 (-360 -2800) (360 760))
|
||||
R(l8 (-360 2040) (360 760))
|
||||
R(l2 (-680 -855) (775 950))
|
||||
R(l5 (-775 -3750) (775 950))
|
||||
)
|
||||
P(1)
|
||||
P(2)
|
||||
P(3)
|
||||
P(4)
|
||||
D(1 D$PMOS
|
||||
Y(0 2800)
|
||||
E(L 0.25)
|
||||
E(W 0.95)
|
||||
E(AS 0.73625)
|
||||
E(AD 0.73625)
|
||||
E(PS 3.45)
|
||||
E(PD 3.45)
|
||||
T(S 4)
|
||||
T(G 3)
|
||||
T(D 2)
|
||||
)
|
||||
D(2 D$NMOS
|
||||
Y(0 0)
|
||||
E(L 0.25)
|
||||
E(W 0.95)
|
||||
E(AS 0.73625)
|
||||
E(AD 0.73625)
|
||||
E(PS 3.45)
|
||||
E(PD 3.45)
|
||||
T(S 4)
|
||||
T(G 3)
|
||||
T(D 1)
|
||||
)
|
||||
)
|
||||
X(INV2
|
||||
R((0 0) (3000 9200))
|
||||
N(1 I(VDD)
|
||||
R(l10 (0 3150) (3000 2900))
|
||||
R(l13 (-1891 -1451) (2 2))
|
||||
)
|
||||
N(2 I(A1)
|
||||
R(l11 (1479 7109) (2 2))
|
||||
)
|
||||
N(3 I(A2)
|
||||
R(l11 (1519 1949) (2 2))
|
||||
)
|
||||
N(4 I(Q1)
|
||||
R(l12 (1919 7069) (2 2))
|
||||
)
|
||||
N(5 I(Q2)
|
||||
R(l12 (1939 1949) (2 2))
|
||||
)
|
||||
N(6 I(VSS)
|
||||
R(l13 (2679 8389) (2 2))
|
||||
R(l13 (-32 -7642) (2 2))
|
||||
)
|
||||
P(1 I(VDD))
|
||||
P(2 I(A1))
|
||||
P(3 I(A2))
|
||||
P(4 I(Q1))
|
||||
P(5 I(Q2))
|
||||
P(6 I(VSS))
|
||||
X(1 INV M O(180) Y(1500 800)
|
||||
P(0 6)
|
||||
P(1 1)
|
||||
P(2 3)
|
||||
P(3 5)
|
||||
)
|
||||
X(2 INV O(180) Y(1500 8400)
|
||||
P(0 6)
|
||||
P(1 1)
|
||||
P(2 2)
|
||||
P(3 4)
|
||||
)
|
||||
)
|
||||
X(INVCHAIN
|
||||
R((-90 0) (4475 9200))
|
||||
N(1
|
||||
R(l3 (1625 1835) (2160 250))
|
||||
R(l3 (-250 0) (250 4990))
|
||||
R(l3 (-1605 0) (1605 250))
|
||||
R(l7 (-1545 -250) (240 250))
|
||||
R(l8 (-560 -375) (690 510))
|
||||
)
|
||||
N(2 I(IN)
|
||||
R(l3 (-90 6850) (1590 650))
|
||||
R(l11 (-701 -351) (2 2))
|
||||
)
|
||||
N(3 I(OUT)
|
||||
R(l8 (-90 1720) (1890 470))
|
||||
R(l12 (-1171 -231) (2 2))
|
||||
)
|
||||
N(4 I(VSS)
|
||||
R(l10 (3000 655) (1385 250))
|
||||
R(l10 (-250 0) (250 7220))
|
||||
R(l10 (-1385 0) (1385 250))
|
||||
R(l13 (-686 -126) (2 2))
|
||||
)
|
||||
N(5 I(VDD)
|
||||
R(l13 (2299 4599) (2 2))
|
||||
)
|
||||
P(2 I(IN))
|
||||
P(3 I(OUT))
|
||||
P(4 I(VSS))
|
||||
P(5 I(VDD))
|
||||
X(1 INV2 Y(0 0)
|
||||
P(0 5)
|
||||
P(1 2)
|
||||
P(2 1)
|
||||
P(3 1)
|
||||
P(4 3)
|
||||
P(5 4)
|
||||
)
|
||||
)
|
||||
)
|
||||
H(
|
||||
K(PMOS MOS3)
|
||||
K(NMOS MOS3)
|
||||
X(INV
|
||||
N(1 I(VDD))
|
||||
N(2 I(VSS))
|
||||
N(3 I(A))
|
||||
N(4 I(Q))
|
||||
P(1 I(VDD))
|
||||
P(2 I(VSS))
|
||||
P(3 I(A))
|
||||
P(4 I(Q))
|
||||
D(1 PMOS
|
||||
I($1)
|
||||
E(L 0.25)
|
||||
E(W 0.95)
|
||||
E(AS 0)
|
||||
E(AD 0)
|
||||
E(PS 0)
|
||||
E(PD 0)
|
||||
T(S 1)
|
||||
T(G 3)
|
||||
T(D 4)
|
||||
)
|
||||
D(2 NMOS
|
||||
I($3)
|
||||
E(L 0.25)
|
||||
E(W 0.95)
|
||||
E(AS 0)
|
||||
E(AD 0)
|
||||
E(PS 0)
|
||||
E(PD 0)
|
||||
T(S 2)
|
||||
T(G 3)
|
||||
T(D 4)
|
||||
)
|
||||
)
|
||||
X(INV2
|
||||
N(1 I(VDD))
|
||||
N(2 I(VSS))
|
||||
N(3 I(A1))
|
||||
N(4 I(Q1))
|
||||
N(5 I(A2))
|
||||
N(6 I(Q2))
|
||||
P(1 I(VDD))
|
||||
P(2 I(VSS))
|
||||
P(3 I(A1))
|
||||
P(4 I(Q1))
|
||||
P(5 I(A2))
|
||||
P(6 I(Q2))
|
||||
X(1 INV I($1)
|
||||
P(0 1)
|
||||
P(1 2)
|
||||
P(2 3)
|
||||
P(3 4)
|
||||
)
|
||||
X(2 INV I($2)
|
||||
P(0 1)
|
||||
P(1 2)
|
||||
P(2 5)
|
||||
P(3 6)
|
||||
)
|
||||
)
|
||||
X(INVCHAIN
|
||||
N(1 I('1'))
|
||||
N(2 I('2'))
|
||||
N(3 I('3'))
|
||||
N(4 I('4'))
|
||||
N(5 I('5'))
|
||||
X(1 INV2 I($2)
|
||||
P(0 1)
|
||||
P(1 2)
|
||||
P(2 3)
|
||||
P(3 4)
|
||||
P(4 4)
|
||||
P(5 5)
|
||||
)
|
||||
)
|
||||
)
|
||||
Z(
|
||||
X(INV INV 1
|
||||
Z(
|
||||
N(3 3 1)
|
||||
N(4 4 1)
|
||||
N(2 1 1)
|
||||
N(1 2 1)
|
||||
P(2 2 1)
|
||||
P(3 3 1)
|
||||
P(1 0 1)
|
||||
P(0 1 1)
|
||||
D(2 2 1)
|
||||
D(1 1 1)
|
||||
)
|
||||
)
|
||||
X(INV2 INV2 1
|
||||
Z(
|
||||
N(2 3 1)
|
||||
N(3 5 1)
|
||||
N(4 4 W)
|
||||
N(5 6 W)
|
||||
N(1 1 1)
|
||||
N(6 2 1)
|
||||
P(1 2 1)
|
||||
P(2 4 1)
|
||||
P(3 3 1)
|
||||
P(4 5 1)
|
||||
P(0 0 1)
|
||||
P(5 1 1)
|
||||
X(2 1 1)
|
||||
X(1 2 1)
|
||||
)
|
||||
)
|
||||
X(INVCHAIN INVCHAIN 1
|
||||
Z(
|
||||
N(1 4 1)
|
||||
N(2 3 1)
|
||||
N(3 5 1)
|
||||
N(5 1 1)
|
||||
N(4 2 1)
|
||||
P(0 () 1)
|
||||
P(1 () 1)
|
||||
P(3 () 1)
|
||||
P(2 () 1)
|
||||
X(1 1 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
* Extracted by KLayout
|
||||
|
||||
.SUBCKT INVCHAIN ANY R ANY$1 PWR GND
|
||||
X$1 ANY R R ANY$1 PWR GND INV2
|
||||
.ENDS INVCHAIN
|
||||
|
||||
.SUBCKT INV2 A1 A2 Q1 Q2 R VSS
|
||||
X$1 VSS R A1 Q1 INV
|
||||
X$2 VSS R A2 Q2 INV
|
||||
.ENDS INV2
|
||||
|
||||
.SUBCKT INV \$1 \$2 \$3 \$4
|
||||
M$1 \$4 \$3 \$2 \$4 PMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U
|
||||
+ PD=3.45U
|
||||
M$2 \$4 \$3 \$1 \$4 NMOS L=0.25U W=0.95U AS=0.73625P AD=0.73625P PS=3.45U
|
||||
+ PD=3.45U
|
||||
.ENDS INV
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
|
||||
source($lvs_test_source)
|
||||
|
||||
report_lvs($lvs_test_target_lvsdb)
|
||||
|
||||
writer = write_spice(true, false)
|
||||
target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")
|
||||
|
||||
# needs this delegate because we use MOS3 which is not available in Spice
|
||||
class SpiceReaderDelegate < RBA::NetlistSpiceReaderDelegate
|
||||
|
||||
# says we want to catch these subcircuits as devices
|
||||
def wants_subcircuit(name)
|
||||
name == "HVNMOS" || name == "HVPMOS"
|
||||
end
|
||||
|
||||
# translate the element
|
||||
def element(circuit, el, name, model, value, nets, params)
|
||||
|
||||
if el != "M"
|
||||
# all other elements are left to the standard implementation
|
||||
return super
|
||||
end
|
||||
|
||||
if nets.size != 4
|
||||
error("Device #{model} needs four nodes")
|
||||
end
|
||||
|
||||
# provide a device class
|
||||
cls = circuit.netlist.device_class_by_name(model)
|
||||
if ! cls
|
||||
cls = RBA::DeviceClassMOS3Transistor::new
|
||||
cls.name = model
|
||||
circuit.netlist.add(cls)
|
||||
end
|
||||
|
||||
# create a device
|
||||
device = circuit.create_device(cls, name)
|
||||
|
||||
# and configure the device
|
||||
[ "S", "G", "D" ].each_with_index do |t,index|
|
||||
device.connect_terminal(t, nets[index])
|
||||
end
|
||||
device.set_parameter("W", params["W"] * 1e6)
|
||||
device.set_parameter("L", params["L"] * 1e6)
|
||||
|
||||
device
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
reader = RBA::NetlistSpiceReader::new(SpiceReaderDelegate::new)
|
||||
schematic("double_height_inv.cir", reader)
|
||||
|
||||
deep
|
||||
|
||||
# Drawing layers
|
||||
|
||||
nwell = input(1, 0)
|
||||
active = input(2, 0)
|
||||
poly = input(3, 0)
|
||||
poly_lbl = input(3, 1)
|
||||
diff_cont = input(4, 0)
|
||||
poly_cont = input(5, 0)
|
||||
metal1 = input(6, 0)
|
||||
metal1_lbl = input(6, 1)
|
||||
via1 = input(7, 0)
|
||||
metal2 = input(8, 0)
|
||||
metal2_lbl = input(8, 1)
|
||||
|
||||
# Bulk layer for terminal provisioning
|
||||
|
||||
bulk = polygon_layer
|
||||
|
||||
psd = nil
|
||||
nsd = nil
|
||||
|
||||
# Computed layers
|
||||
|
||||
active_in_nwell = active & nwell
|
||||
pactive = active_in_nwell
|
||||
pgate = pactive & poly
|
||||
psd = pactive - pgate
|
||||
|
||||
active_outside_nwell = active - nwell
|
||||
nactive = active_outside_nwell
|
||||
ngate = nactive & poly
|
||||
nsd = nactive - ngate
|
||||
|
||||
# Device extraction
|
||||
|
||||
# PMOS transistor device extraction
|
||||
extract_devices(mos3("PMOS"), { "SD" => psd, "G" => pgate,
|
||||
"tS" => psd, "tD" => psd, "tG" => poly })
|
||||
|
||||
# NMOS transistor device extraction
|
||||
extract_devices(mos3("NMOS"), { "SD" => nsd, "G" => ngate,
|
||||
"tS" => nsd, "tD" => nsd, "tG" => poly })
|
||||
|
||||
# Define connectivity for netlist extraction
|
||||
|
||||
# Inter-layer
|
||||
connect(psd, diff_cont)
|
||||
connect(nsd, diff_cont)
|
||||
connect(poly, poly_cont)
|
||||
connect(diff_cont, metal1)
|
||||
connect(poly_cont, metal1)
|
||||
connect(metal1, via1)
|
||||
connect(via1, metal2)
|
||||
|
||||
# attach labels
|
||||
connect(poly, poly_lbl)
|
||||
connect(metal1, metal1_lbl)
|
||||
connect(metal2, metal2_lbl)
|
||||
|
||||
# Global
|
||||
connect_global(bulk, "SUBSTRATE")
|
||||
|
||||
# Implicit connection of the INV2
|
||||
# VSS nets
|
||||
connect_implicit("GND")
|
||||
connect_implicit("?") # "R"
|
||||
connect_implicit("DOESNOTEXIST")
|
||||
connect_implicit("*2", "*SS")
|
||||
connect_implicit("*", "R")
|
||||
connect_implicit("DOESNOTEXIST", "DOESNOTEXIST")
|
||||
|
||||
# Compare section
|
||||
|
||||
netlist.simplify
|
||||
align
|
||||
|
||||
compare
|
||||
|
||||
|
|
@ -0,0 +1,325 @@
|
|||
#%lvsdb-klayout
|
||||
J(
|
||||
W(INVCHAIN)
|
||||
U(0.001)
|
||||
L(l3 '3/0')
|
||||
L(l11 '3/1')
|
||||
L(l6 '4/0')
|
||||
L(l7 '2/0')
|
||||
L(l8 '6/0')
|
||||
L(l12 '6/1')
|
||||
L(l9 '7/0')
|
||||
L(l10 '8/0')
|
||||
L(l13 '8/1')
|
||||
L(l14)
|
||||
L(l2)
|
||||
L(l5)
|
||||
C(l3 l3 l11 l7)
|
||||
C(l11 l3 l11)
|
||||
C(l6 l6 l8 l2 l5)
|
||||
C(l7 l3 l7 l8)
|
||||
C(l8 l6 l7 l8 l12 l9)
|
||||
C(l12 l8 l12)
|
||||
C(l9 l8 l9 l10)
|
||||
C(l10 l9 l10 l13)
|
||||
C(l13 l10 l13)
|
||||
C(l14 l14)
|
||||
C(l2 l6 l2)
|
||||
C(l5 l6 l5)
|
||||
G(l14 SUBSTRATE)
|
||||
K(PMOS MOS3)
|
||||
K(NMOS MOS3)
|
||||
D(D$PMOS PMOS
|
||||
T(S
|
||||
R(l2 (-900 -475) (775 950))
|
||||
)
|
||||
T(G
|
||||
R(l3 (-125 -475) (250 950))
|
||||
)
|
||||
T(D
|
||||
R(l2 (125 -475) (775 950))
|
||||
)
|
||||
)
|
||||
D(D$NMOS NMOS
|
||||
T(S
|
||||
R(l5 (-900 -475) (775 950))
|
||||
)
|
||||
T(G
|
||||
R(l3 (-125 -475) (250 950))
|
||||
)
|
||||
T(D
|
||||
R(l5 (125 -475) (775 950))
|
||||
)
|
||||
)
|
||||
X(INV
|
||||
R((-1500 -800) (3000 4600))
|
||||
N(1
|
||||
R(l6 (290 -310) (220 220))
|
||||
R(l6 (-220 180) (220 220))
|
||||
R(l8 (-290 -690) (360 760))
|
||||
R(l9 (-305 -705) (250 250))
|
||||
R(l9 (-250 150) (250 250))
|
||||
R(l10 (-2025 -775) (3000 900))
|
||||
R(l5 (-1375 -925) (775 950))
|
||||
)
|
||||
N(2
|
||||
R(l6 (290 2490) (220 220))
|
||||
R(l6 (-220 180) (220 220))
|
||||
R(l8 (-290 -690) (360 760))
|
||||
R(l9 (-305 -705) (250 250))
|
||||
R(l9 (-250 150) (250 250))
|
||||
R(l10 (-2025 -775) (3000 900))
|
||||
R(l2 (-1375 -925) (775 950))
|
||||
)
|
||||
N(3
|
||||
R(l3 (-125 -250) (250 2500))
|
||||
R(l3 (-250 -3050) (250 1600))
|
||||
R(l3 (-250 1200) (250 1600))
|
||||
)
|
||||
N(4
|
||||
R(l6 (-510 -310) (220 220))
|
||||
R(l6 (-220 180) (220 220))
|
||||
R(l6 (-220 2180) (220 220))
|
||||
R(l6 (-220 180) (220 220))
|
||||
R(l8 (-290 -3530) (360 2840))
|
||||
R(l8 (-360 -2800) (360 760))
|
||||
R(l8 (-360 2040) (360 760))
|
||||
R(l2 (-680 -855) (775 950))
|
||||
R(l5 (-775 -3750) (775 950))
|
||||
)
|
||||
P(1)
|
||||
P(2)
|
||||
P(3)
|
||||
P(4)
|
||||
D(1 D$PMOS
|
||||
Y(0 2800)
|
||||
E(L 0.25)
|
||||
E(W 0.95)
|
||||
E(AS 0.73625)
|
||||
E(AD 0.73625)
|
||||
E(PS 3.45)
|
||||
E(PD 3.45)
|
||||
T(S 4)
|
||||
T(G 3)
|
||||
T(D 2)
|
||||
)
|
||||
D(2 D$NMOS
|
||||
Y(0 0)
|
||||
E(L 0.25)
|
||||
E(W 0.95)
|
||||
E(AS 0.73625)
|
||||
E(AD 0.73625)
|
||||
E(PS 3.45)
|
||||
E(PD 3.45)
|
||||
T(S 4)
|
||||
T(G 3)
|
||||
T(D 1)
|
||||
)
|
||||
)
|
||||
X(INV2
|
||||
R((0 0) (3000 9200))
|
||||
N(1 I(A1)
|
||||
R(l11 (1479 7109) (2 2))
|
||||
)
|
||||
N(2 I(A2)
|
||||
R(l11 (1519 1949) (2 2))
|
||||
)
|
||||
N(3 I(Q1)
|
||||
R(l12 (1919 7069) (2 2))
|
||||
)
|
||||
N(4 I(Q2)
|
||||
R(l12 (1939 1949) (2 2))
|
||||
)
|
||||
N(5 I(R)
|
||||
R(l13 (2719 5559) (2 2))
|
||||
R(l13 (-92 -1942) (2 2))
|
||||
)
|
||||
N(6 I(VSS)
|
||||
R(l13 (2679 8389) (2 2))
|
||||
R(l13 (-32 -7642) (2 2))
|
||||
)
|
||||
P(1 I(A1))
|
||||
P(2 I(A2))
|
||||
P(3 I(Q1))
|
||||
P(4 I(Q2))
|
||||
P(5 I(R))
|
||||
P(6 I(VSS))
|
||||
X(1 INV O(180) Y(1500 8400)
|
||||
P(0 6)
|
||||
P(1 5)
|
||||
P(2 1)
|
||||
P(3 3)
|
||||
)
|
||||
X(2 INV M O(180) Y(1500 800)
|
||||
P(0 6)
|
||||
P(1 5)
|
||||
P(2 2)
|
||||
P(3 4)
|
||||
)
|
||||
)
|
||||
X(INVCHAIN
|
||||
R((-90 0) (3090 9200))
|
||||
N(1 I(ANY)
|
||||
R(l3 (-90 6850) (1590 650))
|
||||
R(l11 (-701 -351) (2 2))
|
||||
)
|
||||
N(2 I(R)
|
||||
R(l11 (1479 2369) (2 2))
|
||||
R(l8 (439 4579) (690 510))
|
||||
R(l12 (-301 -291) (2 2))
|
||||
)
|
||||
N(3 I(ANY)
|
||||
R(l8 (-90 1720) (1890 470))
|
||||
R(l12 (-1171 -231) (2 2))
|
||||
)
|
||||
N(4 I(PWR)
|
||||
R(l13 (299 5549) (2 2))
|
||||
R(l13 (-12 -1992) (2 2))
|
||||
)
|
||||
N(5 I(GND)
|
||||
R(l13 (319 8399) (2 2))
|
||||
R(l13 (-52 -7602) (2 2))
|
||||
)
|
||||
P(1 I(ANY))
|
||||
P(2 I(R))
|
||||
P(3 I(ANY))
|
||||
P(4 I(PWR))
|
||||
P(5 I(GND))
|
||||
X(1 INV2 Y(0 0)
|
||||
P(0 1)
|
||||
P(1 2)
|
||||
P(2 2)
|
||||
P(3 3)
|
||||
P(4 4)
|
||||
P(5 5)
|
||||
)
|
||||
)
|
||||
)
|
||||
H(
|
||||
K(PMOS MOS3)
|
||||
K(NMOS MOS3)
|
||||
X(INV
|
||||
N(1 I(VDD))
|
||||
N(2 I(VSS))
|
||||
N(3 I(A))
|
||||
N(4 I(Q))
|
||||
P(1 I(VDD))
|
||||
P(2 I(VSS))
|
||||
P(3 I(A))
|
||||
P(4 I(Q))
|
||||
D(1 PMOS
|
||||
I($1)
|
||||
E(L 0.25)
|
||||
E(W 0.95)
|
||||
E(AS 0)
|
||||
E(AD 0)
|
||||
E(PS 0)
|
||||
E(PD 0)
|
||||
T(S 1)
|
||||
T(G 3)
|
||||
T(D 4)
|
||||
)
|
||||
D(2 NMOS
|
||||
I($3)
|
||||
E(L 0.25)
|
||||
E(W 0.95)
|
||||
E(AS 0)
|
||||
E(AD 0)
|
||||
E(PS 0)
|
||||
E(PD 0)
|
||||
T(S 2)
|
||||
T(G 3)
|
||||
T(D 4)
|
||||
)
|
||||
)
|
||||
X(INV2
|
||||
N(1 I(VDD))
|
||||
N(2 I(VSS))
|
||||
N(3 I(A1))
|
||||
N(4 I(Q1))
|
||||
N(5 I(A2))
|
||||
N(6 I(Q2))
|
||||
P(1 I(VDD))
|
||||
P(2 I(VSS))
|
||||
P(3 I(A1))
|
||||
P(4 I(Q1))
|
||||
P(5 I(A2))
|
||||
P(6 I(Q2))
|
||||
X(1 INV I($1)
|
||||
P(0 1)
|
||||
P(1 2)
|
||||
P(2 3)
|
||||
P(3 4)
|
||||
)
|
||||
X(2 INV I($2)
|
||||
P(0 1)
|
||||
P(1 2)
|
||||
P(2 5)
|
||||
P(3 6)
|
||||
)
|
||||
)
|
||||
X(INVCHAIN
|
||||
N(1 I('1'))
|
||||
N(2 I('2'))
|
||||
N(3 I('3'))
|
||||
N(4 I('4'))
|
||||
N(5 I('5'))
|
||||
X(1 INV2 I($2)
|
||||
P(0 1)
|
||||
P(1 2)
|
||||
P(2 3)
|
||||
P(3 4)
|
||||
P(4 4)
|
||||
P(5 5)
|
||||
)
|
||||
)
|
||||
)
|
||||
Z(
|
||||
X(INV INV 1
|
||||
Z(
|
||||
N(3 3 1)
|
||||
N(4 4 1)
|
||||
N(2 1 1)
|
||||
N(1 2 1)
|
||||
P(2 2 1)
|
||||
P(3 3 1)
|
||||
P(1 0 1)
|
||||
P(0 1 1)
|
||||
D(2 2 1)
|
||||
D(1 1 1)
|
||||
)
|
||||
)
|
||||
X(INV2 INV2 1
|
||||
Z(
|
||||
N(1 3 1)
|
||||
N(2 5 1)
|
||||
N(3 4 W)
|
||||
N(4 6 W)
|
||||
N(5 1 1)
|
||||
N(6 2 1)
|
||||
P(0 2 1)
|
||||
P(1 4 1)
|
||||
P(2 3 1)
|
||||
P(3 5 1)
|
||||
P(4 0 1)
|
||||
P(5 1 1)
|
||||
X(1 1 1)
|
||||
X(2 2 1)
|
||||
)
|
||||
)
|
||||
X(INVCHAIN INVCHAIN 1
|
||||
Z(
|
||||
N(1 3 1)
|
||||
N(3 5 1)
|
||||
N(5 2 1)
|
||||
N(4 1 1)
|
||||
N(2 4 1)
|
||||
P(2 () 1)
|
||||
P(0 () 1)
|
||||
P(4 () 1)
|
||||
P(3 () 1)
|
||||
P(1 () 1)
|
||||
X(1 1 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
* cell INVCHAIN
|
||||
.SUBCKT INVCHAIN
|
||||
X$2 1 2 3 4 4 5 INV2
|
||||
.ENDS INVCHAIN
|
||||
|
||||
* cell INV2
|
||||
.SUBCKT INV2 VDD VSS A1 Q1 A2 Q2
|
||||
X$1 VDD VSS A1 Q1 INV
|
||||
X$2 VDD VSS A2 Q2 INV
|
||||
.ENDS INV2
|
||||
|
||||
* cell INV
|
||||
.SUBCKT INV VDD VSS A Q
|
||||
M$1 VDD A Q VDD PMOS L=0.25U W=0.95U
|
||||
M$3 VSS A Q VSS NMOS L=0.25U W=0.95U
|
||||
.ENDS INV
|
||||
|
||||
Binary file not shown.
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
* cell INVCHAIN
|
||||
.SUBCKT INVCHAIN
|
||||
X$2 1 2 3 4 4 5 INV2
|
||||
.ENDS INVCHAIN
|
||||
|
||||
* cell INV2
|
||||
.SUBCKT INV2 VDD VSS A1 Q1 A2 Q2
|
||||
X$1 VDD VSS A1 Q1 INV
|
||||
X$2 VDD VSS A2 Q2 INV
|
||||
.ENDS INV2
|
||||
|
||||
* cell INV
|
||||
.SUBCKT INV VDD VSS A Q
|
||||
M$1 VDD A Q VDD PMOS L=0.25U W=0.95U
|
||||
M$3 VSS A Q VSS NMOS L=0.25U W=0.95U
|
||||
.ENDS INV
|
||||
|
||||
Binary file not shown.
Loading…
Reference in New Issue