Home Forums Nazca How to pass down pcell arguments in the replaceCells function ?

This topic contains 3 replies, has 2 voices, and was last updated by  Ronald 2 weeks, 1 day ago.

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #6016

    Cecil
    Member

    Hello Nazca team,

    I am trying to use the replaceCells function using the PcellFunctionMap argument to convert blackboxes into pcells with the desired parameters.

    It looks like this:

    def blackbox(width_wg, offset, radius):
        with nd.Cell(name='blackbox', cnt=True) as C:
            length = some_calculation(offset, radius)
            nd.Pin('a0').put(0,0,180)
            nd.Pin('b0').put(length, offset)
            nd.put_stub()
            nd.put_boundingbox(length, offset, (0,0,0))
        return C
    
    def white_pcell(width_wg=2, offset=100, radius=500, layer=1):
        with nd.Cell(name='white_pcell', cnt=True) as C:
            length = some_calculation(offset, radius)
            # do some stuff to create the pattern
            # same pin placement as above
        return C
    
    nd.strt(width=2, length=200, layer=1).put(0)
    blackbox(width_wg=2, offset=150, radius=1000).put()
    blackbox(width_wg=2, offset=20, radius=500).put()
    nd.export_gds('test')
    
    # Import and conversion black to white:
    
    d = {'blackbox': white_pcell}
    nd.replaceCells(gdsin='test.gds', gdsout='testwhite', PcellFunctionMap=d)
    

    The replacement of the cell in the gds file works, however only default parameters are used for white_pcell generation. I haven’t found a way to pass down custom parameters to the replaceCells function to use for the white_pcell function. Is there a way to do it ?

    Best regards,

    Cecil

    #6025

    Ronald
    Keymaster

    Dear Cecil,

    Your approach is correct. What is missing is that you need to fill the cell’s ‘parameter’ attribute with a dict like {parametername : value}. The parametername is expressed as a string.

    This parameter attribute is automatically filled by the @hashme decorator, which I added in the example below to your ‘blackbox’ in combination with an autobbox=True. To give the autobbox dimension in your case with only two pins, I added the userbbox. The autobbox finds the boundaries and calls the correct put_boundingbox() function internally, so that explicit call can be deleted.

    In all it adds a boundingbox and all the blackbox function parameters as annotation to the gds. Those parameters are read back in during the pcell replacement to generate the parametric white cell. I also added some keywords to your calls to make the code more robust. Additionally, I added version info to your cell via the ‘version’ attribute of the cell, which adds a extra information to the black cell, again as annotation.

    This pcell flow can be used for IP protection and there are several more elements to this flow to make this pcell IP-replacement work in basically any situation. If you know your pcell names you can simply look for them in the gds, but Nazca can also detect “unknown” pcells, as well as tempering with black boxes to make the whole process 100% reliable. All these features require a somewhat longer tutorial.

    import nazca as nd
    version = {'owner': 'cecil'}
    
    def some_calculation(offset, radius):
        return 2.0 + offset + 0.5*radius
    
    @nd.bb_util.hashme('blackbox')
    def blackbox(width_wg, offset, radius):
        with nd.Cell() as C:
            C.version = version
            length = some_calculation(offset, radius)
            C.userbbox = [(0, -1.5*offset), (length, -1.5*offset), (length, 1.5*offset), (0, 1.5*offset)]
            C.autobbox = True
            nd.Pin('a0').put(0, 0, 180)
            nd.Pin('b0').put(length, offset)
            nd.put_stub()
        return C
    
    def white_pcell(width_wg=2, offset=100, radius=500, layer=1):
        with nd.Cell(name='white_pcell', cnt=True) as C:
            length = some_calculation(offset, radius)
            nd.strt(length=length, width=width_wg).put(0)
            # do some stuff to create the pattern
            # same pin placement as above
        return C
    
    nd.strt(width=2, length=200, layer=1).put(0)
    blackbox(width_wg=2, offset=150, radius=1000).put()
    blackbox(width_wg=2, offset=20, radius=500).put()
    nd.export_gds(filename='test')
    
    # Import and conversion black to white:
    d = {'blackbox': white_pcell}
    nd.replaceCells(gdsin='test.gds', gdsout='testwhite.gds', PcellFunctionMap=d)

    Ronald

    #6031

    Cecil
    Member

    Dear Ronald,

    I found a similar solution in the meantime by manually adding an annotation using nd.Annotation and a formatted string, however your solution seems more robust and elegant.

    I have one more question though, how would you pass down arguments that are not present in the blackbox (“hidden” from the user but necessary on my side), but needed in the pcell ? In the following example, I would like to pass down the “width_output” argument without the user having to interact with it :

     

     

    def blackbox(width_wg, offset, radius):
        # do things
    def white_pcell(width_wg, offset, radius, width_output):
        # do other things

    Thanks a lot for your answers,

    Cecil

    #6042

    Ronald
    Keymaster

    Dear Cecil,

    If I understand your question correctly you want to add an extra parameter, here width_output, on your side to the whitebox in addition to the blackbox parameters. Such a parameter should not affect any pin positions or bbox size. I can not image a direct use case, unless you do something like porting the same black box to two different processes internally. You can probably use the partial method from Pythons functools module. It basically applies, in the example below, the width_output parameter before feeding the white_pcell into the replacement dictionary. After partial(white_pcell, width_output) only the blackbox parameters are left:

    from functools import partial
    
    ...
    def white_pcell(width_wg, offset, radius, width_output):
        # do other things
    ...
    
    d = {'blackbox': partial(white_pcell, width_output)}

    Ronald

Viewing 4 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic.