# Design rule deck for the Coherent RX SOI technology of the PhotonForge coherent transceiver series.
# PhotonForge runs it with pf.drc_check, which passes the layout as $gdsfile and the report as $resultsfile.

source($gdsfile)
report("Coherent RX SOI DRC", $resultsfile)

# Drawing layers, as numbered in the technology
si = input(1, 0)
slab = input(2, 0)
implant_p = input(3, 0)
implant_n = input(4, 0)
implant_pp = input(5, 0)
implant_nn = input(6, 0)
ge = input(7, 0)
poly = input(8, 0)
contact = input(10, 0)
ge_contact = input(11, 0)
heater = input(12, 0)
via = input(13, 0)
m1 = input(14, 0)
pad_open = input(15, 0)
trench = input(16, 0)
floorplan = input(99, 0)

# Silicon: 100 nm lines and spaces, the smallest feature of the subwavelength edge coupler
si.width(0.1.um).output("Si.W.1", "Si width below 0.10 um")
si.space(0.1.um).output("Si.S.1", "Si space below 0.10 um")
slab.width(0.2.um).output("Slab.W.1", "Si Slab width below 0.20 um")
slab.space(0.2.um).output("Slab.S.1", "Si Slab space below 0.20 um")

# Germanium and polysilicon grow on silicon only
ge.width(0.4.um).output("Ge.W.1", "Ge width below 0.40 um")
ge.not(si).output("Ge.E.1", "Ge not on Si")
poly.not(si).output("Poly.E.1", "Poly Si not on Si")

# Implants
(implant_p + implant_n).width(0.3.um).output("Imp.W.1", "P or N implant width below 0.30 um")
(implant_pp + implant_nn).width(0.3.um).output("Imp.W.2", "P++ or N++ implant width below 0.30 um")
implant_pp.and(implant_nn).output("Imp.X.1", "P++ overlaps N++")

# Contacts land on a contact implant and are covered by M1
contact.not(implant_pp + implant_nn).output("Ct.E.1", "Contact outside a P++ or N++ implant")
m1.enclosing(contact, 0.2.um).output("Ct.E.2", "M1 enclosure of Contact below 0.20 um")
contact.not(m1).output("Ct.E.3", "Contact not covered by M1")
ge_contact.not(ge).output("Ct.E.4", "Ge Contact outside Ge")
contact.not(si).output("Ct.E.5", "Contact outside full-thickness silicon")

# Heater, via and metal
heater.width(0.5.um).output("Ht.W.1", "Heater width below 0.50 um")
via.not(heater).output("Via.E.1", "Via not on a heater")
via.not(m1).output("Via.E.2", "Via not covered by M1")
m1.width(1.0.um).output("M1.W.1", "M1 width below 1.0 um")
m1.space(1.0.um).output("M1.S.1", "M1 space below 1.0 um")

# Pad openings sit inside M1 with a 2 um margin
pad_open.not(m1).output("Pad.E.1", "Pad opening outside M1")
m1.enclosing(pad_open, 2.0.um).output("Pad.E.2", "M1 enclosure of a pad opening below 2.0 um")
pad_open.width(50.um).output("Pad.W.1", "Pad opening below 50 um")

# Everything on a mask lies inside the chip area; the facet trench runs out over the die edge
(si + slab + ge + poly + contact + ge_contact + heater + via + m1 + pad_open).not(floorplan).output("FP.1", "Shape outside the chip area")
