via overlapped check with DRC

edited November 2023 in Verification

Hello,

I’m doing my best to explain this as clearly as possible. I want to verify the overlap of metal layers over a passivation layer. However, I only have one passivation layer that can connect one metal to other metals.

The Design Rule Check (DRC) should work as follows:

1- Verify that the top metal layer TM, which is the common metal and can connect to all other metals through passivation, is larger (e.g., 2um) than the passivation layer (Layer PL). If this is not the case, an error should be returned. (I know how to write this part.)

2- Verify that the gate metal layer (GM) is 2um larger than PL. If this condition is not met, check the second metal, SDM. If this condition is still not met, check the third metal, BGM. If none of these conditions are met, then an error should be returned.

My problem lies in the output, which should be like this:

layer["PL"].output("Error_no_metal")

However, the error is being applied to all vias that have PL on them! I only want the error to be applied to the specific via with the problem.

Comments

  • Hi ashkan,
    you can use interaction check to filter vias-metal relation layer by layer to generate DRC check result.


    gm  = input(1, 0)
    sdm = input(2, 0)
    bgm = input(3, 0)
    tm  = input(4, 0)
    pl  = input(5, 0)
    
    enc_val       = 2.um
    ext_pl        = pl.sized(enc_val, enc_val)
    
    tm_pl_none    = ext_pl.inside(tm) 
    tm_pl_err     = ext_pl.not_inside(tm) 
    
    tm_pl_bgm     = tm_pl_none.inside(bgm)
    tm_pl_bgm_err = tm_pl_none.interacting(bgm).not_interacting(tm_pl_bgm)
    tm_pl_none    = tm_pl_none.not_inside(bgm)   
    
    tm_pl_sdm     = tm_pl_none.inside(sdm)
    tm_pl_sdm_err = tm_pl_none.interacting(sdm).not_interacting(tm_pl_sdm)
    tm_pl_none    = tm_pl_none.not_inside(sdm)   
    
    tm_pl_gm      = tm_pl_none.inside(gm)
    tm_pl_gm_err  = tm_pl_none.interacting(gm).not_interacting(tm_pl_gm)
    tm_pl_none    = tm_pl_none.not_inside(gm)   
    
    (tm_pl_err                ).sized(-enc_val, -enc_val).output("tm_pl_err")
    (tm_pl_bgm_err            ).sized(-enc_val, -enc_val).output("tm_pl_bgm_err")
    (tm_pl_sdm_err            ).sized(-enc_val, -enc_val).output("tm_pl_sdm_err")
    (tm_pl_gm_err + tm_pl_none).sized(-enc_val, -enc_val).output("tm_pl_gm_err")
    
  • @RawrRanger Many thanks for this script.

    A slight performance improvement is possible by using the "split_..." functions which deliver both the match/non-match versions in one step, e.g.

    (inside, not_inside) = l1.split_inside(l2)
    

    But I guess for a RDL application (which I assume we have here) performance should not be an issue.

    Matthias

Sign In or Register to comment.