From fb4048d3173b04a9d5df97bc300a1e244538b027 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 8 Jan 2019 00:17:58 +0100 Subject: [PATCH] Added RBA tests for four-terminal MOS extraction plus global nets. --- src/db/db/dbNetlistDeviceExtractorClasses.h | 6 + src/db/db/gsiDeclDbNetlistDeviceExtractor.cc | 35 +++++ testdata/ruby/dbLayoutToNetlist.rb | 128 +++++++++++++++++++ 3 files changed, 169 insertions(+) diff --git a/src/db/db/dbNetlistDeviceExtractorClasses.h b/src/db/db/dbNetlistDeviceExtractorClasses.h index 2a2b3cb35..b779317d5 100644 --- a/src/db/db/dbNetlistDeviceExtractorClasses.h +++ b/src/db/db/dbNetlistDeviceExtractorClasses.h @@ -106,6 +106,12 @@ template<> struct type_traits : public typedef tl::false_tag has_default_constructor; }; +template<> struct type_traits : public tl::type_traits +{ + typedef tl::false_tag has_copy_constructor; + typedef tl::false_tag has_default_constructor; +}; + } #endif diff --git a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc index 45a22e247..0c8e281c8 100644 --- a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc +++ b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc @@ -415,4 +415,39 @@ Class decl_NetlistDeviceExtractorMOS3T "This class has been introduced in version 0.26." ); +db::NetlistDeviceExtractorMOS4Transistor *make_mos4_extractor (const std::string &name) +{ + return new db::NetlistDeviceExtractorMOS4Transistor (name); +} + +Class decl_NetlistDeviceExtractorMOS4Transistor (decl_dbNetlistDeviceExtractor, "db", "DeviceExtractorMOS4Transistor", + gsi::constructor ("new", &make_mos4_extractor, gsi::arg ("name"), + "@brief Creates a new device extractor with the given name." + ), + "@brief A device extractor for a four-terminal MOS transistor\n" + "\n" + "This class supplies the generic extractor for a MOS device.\n" + "The device is defined by two basic input layers: the diffusion area\n" + "(source and drain) and the gate area. It requires a third layer\n" + "(poly) to put the gate terminals on and a forth layer to put the bulk\n" + "terminal an. The separation between poly\n" + "and allows separating the device recognition layer (gate) from the\n" + "conductive layer.\n" + "\n" + "The bulk terminal layer can be an empty layer representing the substrate.\n" + "In this use mode the bulk terminal shapes will be produced there. This\n" + "layer then needs to be connected to a global net to establish the net.\n" + "\n" + "The device class produced by this extractor is \\DeviceClassMOS4Transistor.\n" + "The extractor extracts the four parameters of this class: L, W, AS and AD.\n" + "\n" + "The diffusion area is distributed on the number of gates connecting to\n" + "the particular source or drain area.\n" + "\n" + "This class is a closed one and methods cannot be reimplemented. To reimplement " + "specific methods, see \\DeviceExtractor.\n" + "\n" + "This class has been introduced in version 0.26." +); + } diff --git a/testdata/ruby/dbLayoutToNetlist.rb b/testdata/ruby/dbLayoutToNetlist.rb index 3ca02cc67..54a764c77 100644 --- a/testdata/ruby/dbLayoutToNetlist.rb +++ b/testdata/ruby/dbLayoutToNetlist.rb @@ -290,6 +290,134 @@ END end + def test_12_LayoutToNetlistExtractionWithDevicesAndGlobalNets + + ly = RBA::Layout::new + ly.read(File.join($ut_testsrc, "testdata", "algo", "device_extract_l3.gds")) + + l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, ly.top_cell, [])) + + rbulk = l2n.make_polygon_layer( ly.layer ) + rnwell = l2n.make_polygon_layer( ly.layer(1, 0) ) + ractive = l2n.make_polygon_layer( ly.layer(2, 0) ) + rpoly = l2n.make_polygon_layer( ly.layer(3, 0) ) + rpoly_lbl = l2n.make_text_layer( ly.layer(3, 1) ) + rdiff_cont = l2n.make_polygon_layer( ly.layer(4, 0) ) + rpoly_cont = l2n.make_polygon_layer( ly.layer(5, 0) ) + rmetal1 = l2n.make_polygon_layer( ly.layer(6, 0) ) + rmetal1_lbl = l2n.make_text_layer( ly.layer(6, 1) ) + rvia1 = l2n.make_polygon_layer( ly.layer(7, 0) ) + rmetal2 = l2n.make_polygon_layer( ly.layer(8, 0) ) + rmetal2_lbl = l2n.make_text_layer( ly.layer(8, 1) ) + rpplus = l2n.make_polygon_layer( ly.layer(10, 0) ) + rnplus = l2n.make_polygon_layer( ly.layer(11, 0) ) + + ractive_in_nwell = ractive & rnwell + rpactive = ractive_in_nwell & rpplus + rntie = ractive_in_nwell & rnplus + rpgate = rpactive & rpoly + rpsd = rpactive - rpgate + + ractive_outside_nwell = ractive - rnwell + rnactive = ractive_outside_nwell & rnplus + rptie = ractive_outside_nwell & rpplus + rngate = rnactive & rpoly + rnsd = rnactive - rngate + + # PMOS transistor device extraction + pmos_ex = RBA::DeviceExtractorMOS4Transistor::new("PMOS") + l2n.extract_devices(pmos_ex, { "SD" => rpsd, "G" => rpgate, "P" => rpoly, "W" => rnwell }) + + # NMOS transistor device extraction + nmos_ex = RBA::DeviceExtractorMOS4Transistor::new("NMOS") + l2n.extract_devices(nmos_ex, { "SD" => rnsd, "G" => rngate, "P" => rpoly, "W" => rbulk }) + + # Define connectivity for netlist extraction + + # Intra-layer + l2n.connect(rpsd) + l2n.connect(rnsd) + l2n.connect(rnwell) + l2n.connect(rpoly) + l2n.connect(rdiff_cont) + l2n.connect(rpoly_cont) + l2n.connect(rmetal1) + l2n.connect(rvia1) + l2n.connect(rmetal2) + l2n.connect(rptie) + l2n.connect(rntie) + + # Inter-layer + l2n.connect(rpsd, rdiff_cont) + l2n.connect(rnsd, rdiff_cont) + l2n.connect(rpoly, rpoly_cont) + l2n.connect(rpoly_cont, rmetal1) + l2n.connect(rdiff_cont, rmetal1) + l2n.connect(rdiff_cont, rntie) + l2n.connect(rdiff_cont, rptie) + l2n.connect(rnwell, rntie) + l2n.connect(rmetal1, rvia1) + l2n.connect(rvia1, rmetal2) + l2n.connect(rpoly, rpoly_lbl) # attaches labels + l2n.connect(rmetal1, rmetal1_lbl) # attaches labels + l2n.connect(rmetal2, rmetal2_lbl) # attaches labels + + # Global connections + l2n.connect_global(rptie, "BULK") + l2n.connect_global(rbulk, "BULK") + + # Perform netlist extraction + l2n.extract_netlist + + assert_equal(l2n.netlist.to_s, <