Problems encountered when changing the terminal declaration in the device class

Hi, I'm trying to manipulate a device class used by a device extractor, but I'm encountering an error when executing define_terminal “define_terminal(device, RBA::DeviceClassDiode::TERMINAL_A, 0, anode);”:

I asked you for advice on R extraction last year, and this code is a reference to your previous reply to me( All the files used for testing are in the attachment

Look forward to your advice!


  • I don't know what's wrong with the input of define_terminal, I checked the type of input and my input "define_terminal(device, RBA::DeviceClassDiode::TERMINAL_A, 0, anode);" matches "(1) Signature: void define_terminal (Device ptr device, unsigned long terminal_id, unsigned long layer_index, const Polygon shape)".

    How should i handle this error?

    Definition of device and anode:

  • edited November 2022

    Hi @Bian,

    the problem is the type of the anode and cathode variables: these are "Region" objects, not polygons. "Region" objects can consist of multiple polygons.

    For example, for a planar MOSFET, source and drain are usually derived from the same drawing layer and are commutable. Hence, there is only one input layer with (usually) two polygons. So inside the device extractor you have to separate them and assign them to different terminals.

    If in your case it is guaranteed (e.g. by layout design rules) that anode and cathode will only have a single polygon, you can extract it using "anode[0]" and "cathode[0]".

    In your code is another mistake: TERMINAL_C needs to be output to the second layer (see "define_layer" in "setup"). So you have to define the C terminal for layer index "1". The following is my functional (cleaned) version of "DiodeExtractor":

    class DiodeExtractor < RBA::GenericDeviceExtractor
      def initialize(name) = name
      def setup
        define_layer("P", "Anode")
        define_layer("N", "Cathode ")
      def get_connectivity(layout, layers)
        conn = RBA::Connectivity::new
        conn.connect(layers[0], layers[1])   # collect touching contacts
        conn.connect(layers[1], layers[1])   # combine resistor shapes into one area
      def extract_devices(layer_geometry)
        anode = layer_geometry[0]
        cathode  = layer_geometry[1]
        diode_regions= (anode & cathode).merged
        a = diode_regions.area*dbu*dbu
        p = diode_regions.perimeter*dbu
        device = create_device
        device.set_parameter(RBA::DeviceClassDiode::PARAM_A, a)
        device.set_parameter(RBA::DeviceClassDiode::PARAM_P, p) 
        define_terminal(device, RBA::DeviceClassDiode::TERMINAL_A, 0, anode[0]);
        define_terminal(device, RBA::DeviceClassDiode::TERMINAL_C, 1, cathode[0]);


  • edited November 2022


    Thanks for your detailed and perfect answer, this problem has been solved perfectly!

    And I would like to report to you a bug about the "width_check" function, when the third parameter region is entered as nil, it says that nil cannot be passed in Region, i solve this with input "RBA::Region::Metrics::Euclidian". But according to the documentation for width_check, nil could be selected as the default input for Euclidian. This problem did not exist in previous versions.

  • Very good and thanks for the hint. Honestly, I don't know why nil was working. I need to check. By "previous versions" you mean which one?



  • I just checked why nil isn't working any longer - actually, the argument became type-bound which avoids issues when you forget to specify one argument, but on the other hand, nil is no longer a valid value.

    Hence currently, the way to specify the default is to use "Euclidian" explicitly. I plan to add the option to have named parameters, but that won't happen quickly.



  • @Matthias

    I just checked the previous log and this line of code was used in KLayout version 0.26.11 when nil was still valid.


Sign In or Register to comment.