Replace the SRAM structure with characterization structure.
diff --git a/doitcode/sram.py b/doitcode/sram.py index cfde4a4..bc0b657 100644 --- a/doitcode/sram.py +++ b/doitcode/sram.py
@@ -58,36 +58,31 @@ return None +io_spspecs = ( + _io_spec(sram_signal="in_shiftclk", io_type="io_in", io_number=14), + _io_spec(sram_signal="shift_in", io_type="io_in", io_number=15), + _io_spec(sram_signal="in_captureclk_l", io_type="io_out", io_number=16), + _io_spec(sram_signal="in_captureclk", io_type="io_in", io_number=17), + _io_spec(sram_signal="sramclk", io_type="io_in", io_number=18), + _io_spec(sram_signal="out_captureclk_l", io_type="io_out", io_number=13), + _io_spec(sram_signal="out_captureclk", io_type="io_in", io_number=12), + _io_spec(sram_signal="out_docapture", io_type="io_in", io_number=11), + _io_spec(sram_signal="out_shiftclk", io_type="io_in", io_number=10), + _io_spec(sram_signal="shift_out", io_type="io_out", io_number=9), +) +io_spsig2spec = { + spec.sram_signal: spec + for spec in io_spspecs +} +io_sppin2spec = { + spec.toppin_name: spec + for spec in io_spspecs +} + + io_specs = ( - _io_spec(sram_signal="a[8]", io_type="io_in", io_number=14), - _io_spec(sram_signal="a[7]", io_type="io_in", io_number=15), - _io_spec(sram_signal="a[6]", io_type="io_in", io_number=16), - _io_spec(sram_signal="a[5]", io_type="io_in", io_number=17), - _io_spec(sram_signal="a[4]", io_type="io_in", io_number=18), - _io_spec(sram_signal="a[3]", io_type="io_in", io_number=19), - _io_spec(sram_signal="a[2]", io_type="io_in", io_number=20), - _io_spec(sram_signal="a[1]", io_type="io_in", io_number=21), - _io_spec(sram_signal="a[0]", io_type="io_in", io_number=22), - _io_spec(sram_signal="clk", io_type="io_in", io_number=23), - _io_spec(sram_signal="q[7]", io_type="io_out", io_number=13), - _io_spec(sram_signal="d[7]", io_type="io_in", io_number=12), - _io_spec(sram_signal="d[6]", io_type="io_in", io_number=11), - _io_spec(sram_signal="q[6]", io_type="io_out", io_number=10), - _io_spec(sram_signal="q[5]", io_type="io_out", io_number=9), - _io_spec(sram_signal="d[5]", io_type="io_in", io_number=8), - _io_spec(sram_signal="d[4]", io_type="io_in", io_number=7), - _io_spec(sram_signal="q[4]", io_type="io_out", io_number=6), - _io_spec(sram_signal="q[3]", io_type="io_out", io_number=5), - _io_spec(sram_signal="d[3]", io_type="io_in", io_number=4), - _io_spec(sram_signal="d[2]", io_type="io_in", io_number=3), - _io_spec(sram_signal="q[2]", io_type="io_out", io_number=2), - _io_spec(sram_signal="q[1]", io_type="io_out", io_number=1), - _io_spec(sram_signal="we[0]", io_type="io_in", io_number=0), - _io_spec(sram_signal="d[1]", io_type="io_in", io_number=26), - _io_spec(sram_signal="d[0]", io_type="io_in", io_number=25), - _io_spec(sram_signal="q[0]", io_type="io_out", io_number=24), - _io_spec(sram_signal="vdd", io_type="io_analog", io_number=4), - _io_spec(sram_signal="vss", io_type="io_analog", io_number=5), + _io_spec(sram_signal="svdd", io_type="io_analog", io_number=4), + _io_spec(sram_signal="svss", io_type="io_analog", io_number=5), ) io_sig2spec = { spec.sram_signal: spec @@ -278,6 +273,10 @@ m2 = cast(_prm.MetalWire, prims.m2) assert m2.pin is not None m2pin = m2.pin[0] + via2 = cast(_prm.Via, prims.via2) + m3 = cast(_prm.MetalWire, prims.m3) + assert m3.pin is not None + m3pin = m3.pin[0] # Place the SRAM block layouter = self.new_circuitlayouter() @@ -469,6 +468,54 @@ bottom_enclosure="wide", top_enclosure="tall", ) + # Connect svss + net = nets.svss + + bbs = tuple(ms.shape.bounds for ms in sram_lay.filter_polygons( + net=net, mask=m2pin.mask, depth=1, split=True, + )) + left = max(bb.left for bb in bbs) + top = max(bb.top for bb in bbs) + bottom = min(bb.bottom for bb in bbs) + w = 10.0 + x_via2 = left + w/2.0 + right = left + w + + for bb in bbs: + y_via2 = bb.center.y + layouter.add_wire( + net=net, wire=via2, x=x_via2, y=y_via2, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + + shape = _geo.Rect(left=left, bottom=bottom, right=right, top=top) + layouter.add_wire(net=net, wire=m3, pin=m3pin, shape=shape) + + # Connect svdd + net = nets.svdd + + bbs = tuple(ms.shape.bounds for ms in sram_lay.filter_polygons( + net=net, mask=m2pin.mask, depth=1, split=True, + )) + right = min(bb.right for bb in bbs) + top = max(bb.top for bb in bbs) + bottom = min(bb.bottom for bb in bbs) + w = 10.0 + x_via2 = right - w/2.0 + left = right - w + + for bb in bbs: + y_via2 = bb.center.y + layouter.add_wire( + net=net, wire=via2, x=x_via2, y=y_via2, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + + shape = _geo.Rect(left=left, bottom=bottom, right=right, top=top) + layouter.add_wire(net=net, wire=m3, pin=m3pin, shape=shape) + # Connect sramclk net = nets.sramclk @@ -1532,6 +1579,8 @@ via2 = cast(_prm.Via, prims.via2) m3 = cast(_prm.MetalWire, prims.m3) m3pin = cast(_prm.Marker, prims["m3.pin"]) + via3 = cast(_prm.Via, prims.via3) + m4 = cast(_prm.MetalWire, prims.m4) zero_cell = stdcells.zero_x1 zero_nets = zero_cell.circuit.nets @@ -1563,6 +1612,7 @@ address_groups=(3, 4, 2), word_size=word_size, we_size=we_size, cell_name="512x8", ) + spchar_cell = SPCharacterizationWrapper(lib=lib, spcell=spsram_cell) dpsram_cell = dpmem_fab.block( address_groups=(3, 4, 2), word_size=word_size, we_size=we_size, cell_name="512x8", @@ -1585,9 +1635,12 @@ # Place the SRAM # # instantiate - spsram = ckt.instantiate(spsram_cell, name="sram") + spsram = ckt.instantiate(spchar_cell, name="sram") dpsram = ckt.instantiate(dpsram_cell, name="sram") + dvss.childports += spsram.ports.dvss + dvdd.childports += spsram.ports.dvdd + # place _spsram_lay = layouter.inst_layout(inst=spsram) _spsram_bb = _spsram_lay.boundary @@ -1597,23 +1650,16 @@ assert _dpsram_bb is not None x = sky130.tech.on_grid(_frm.boundary.center.x - _spsram_bb.center.x) - y = _frm.boundary.top - 100.0 - _spsram_bb.top + y = _frm.boundary.top - 60.0 - _spsram_bb.top spsram_lay = layouter.place(_spsram_lay, x=x, y=y) spsram_bb = spsram_lay.boundary assert spsram_bb is not None - x = spsram_bb.right + 100.0 + x = sky130.tech.on_grid(_frm.boundary.center.x - _dpsram_bb.center.x) + y = 1600.0 - _dpsram_bb.bottom dpsram_lay = layouter.place(_dpsram_lay, x=x, y=y) dpsram_bb = dpsram_lay.boundary assert dpsram_bb is not None - # Temporary add - spchar_cell = SPCharacterizationWrapper(lib=lib, spcell=spsram_cell) - spchar = ckt.instantiate(spchar_cell, name="sramchar") - x = spsram_bb.right + 700 - spchar_lay = layouter.place( - spchar, x=x, y=(y + 50), rotation=_geo.Rotation.R90, - ) - # Make three rows of to place standard cells in # dbound = 4.0 @@ -1755,132 +1801,19 @@ layouter.add_wire(net=dvdd, wire=m3, pin=m3pin, shape=dvdd_bb) - # below SRAM - rot_midrow = _geo.Rotation.R0 - _tie_rotbb = rot_midrow*_tie_bb - - y_midrow = spsram_bb.bottom - dbound - _tie_rotbb.top - - inst = ckt.instantiate(tie_cell, name="mltie") - dvss.childports += inst.ports.vss - dvdd.childports += inst.ports.vdd - - x_tie = spsram_bb.left - _tie_rotbb.left - lay = layouter.place(inst, x=x_tie, y=y_midrow, rotation=rot_midrow) - nwmbb1 = lay.bounds(mask=nwm.mask) - lipindvssbb1 = lay.bounds(mask=lipin.mask, net=dvss, depth=1) - lipindvddbb1 = lay.bounds(mask=lipin.mask, net=dvdd, depth=1) - - inst = ckt.instantiate(tie_cell, name="mrtie") - dvss.childports += inst.ports.vss - dvdd.childports += inst.ports.vdd - - x_tie = spsram_bb.right - _tie_rotbb.right - lay = layouter.place(inst, x=x_tie, y=y_midrow, rotation=rot_midrow) - nwmbb2 = lay.bounds(mask=nwm.mask) - lipindvssbb2 = lay.bounds(mask=lipin.mask, net=dvss, depth=1) - lipindvddbb2 = lay.bounds(mask=lipin.mask, net=dvdd, depth=1) - - shape = _geo.Rect.from_rect(rect=nwmbb1, right=nwmbb2.right) - layouter.add_wire(net=dvdd, wire=nwm, shape=shape) - - shape = _geo.Rect.from_rect(rect=lipindvssbb1, right=lipindvssbb2.right) - layouter.add_wire(net=dvss, wire=li, shape=shape) - w = tech.on_grid(shape.width, mult=2, rounding="floor") - h = tech.on_grid(shape.height, mult=2, rounding="floor") - o = tech.on_grid(shape.center) - lay = layouter.add_wire( - net=dvss, wire=mcon, origin=o, bottom_width=w, bottom_height=h, - ) - dvss_midrowm1bb = lay.bounds(mask=m1.mask) - - shape = _geo.Rect.from_rect(rect=lipindvddbb1, right=lipindvddbb2.right) - layouter.add_wire(net=dvdd, wire=li, shape=shape) - w = tech.on_grid(shape.width, mult=2, rounding="floor") - h = tech.on_grid(shape.height, mult=2, rounding="floor") - o = tech.on_grid(shape.center) - lay = layouter.add_wire( - net=dvdd, wire=mcon, origin=o, bottom_width=w, bottom_height=h, - ) - dvdd_midrowm1bb = lay.bounds(mask=m1.mask) - - assert dvss_leftrowm1bb.center.x > dvdd_leftrowm1bb.center.x, "Internal error" - assert dvss_rightrowm1bb.center.x > dvdd_rightrowm1bb.center.x, "Internal error" - - shape = _geo.Rect.from_rect( - rect=dvss_midrowm1bb, - left=dvss_leftrowm1bb.left, right=dvdd_rightrowm1bb.left - 1.0, - ) - layouter.add_wire(net=dvss, wire=m1, shape=shape) - - w = shape.height - _via_lay = layouter.wire_layout( - net=dvss, wire=via, bottom_width=w, bottom_height=w, - ) - _via_m1bb = _via_lay.bounds(mask=m1.mask) - - y_via = shape.center.y - x_via = shape.right - _via_m1bb.right - lay = layouter.place(_via_lay, x=x_via, y=y_via) - m2bb1 = lay.bounds(mask=m2.mask) - x_via = dvss_rightrowm1bb.center.x - lay = layouter.place(_via_lay, x=x_via, y=y_via) - m2bb2 = lay.bounds(mask=m2.mask) - - shape = _geo.Rect.from_rect(rect=m2bb1, right=m2bb2.right) - layouter.add_wire(net=dvss, wire=m2, shape=shape) - - shape = _geo.Rect.from_rect( - rect=dvdd_midrowm1bb, - left=(dvss_leftrowm1bb.right + 1.0), right=dvdd_rightrowm1bb.right, - ) - layouter.add_wire(net=dvdd, wire=m1, shape=shape) - - w = shape.height - _via_lay = layouter.wire_layout( - net=dvdd, wire=via, bottom_width=w, bottom_height=w, - ) - _via_m1bb = _via_lay.bounds(mask=m1.mask) - - y_via = shape.center.y - x_via = shape.left - _via_m1bb.left - lay = layouter.place(_via_lay, x=x_via, y=y_via) - m2bb1 = lay.bounds(mask=m2.mask) - x_via = dvdd_leftrowm1bb.center.x - lay = layouter.place(_via_lay, x=x_via, y=y_via) - m2bb2 = lay.bounds(mask=m2.mask) - - shape = _geo.Rect.from_rect(rect=m2bb1, left=m2bb2.left) - layouter.add_wire(net=dvdd, wire=m2, shape=shape) - # Connect the SRAM signals # - # vss - spec = io_sig2spec["vss"] + # svss + spec = io_sig2spec["svss"] sram_port = spsram.ports[spec.sram_signal] net = ckt.new_net(name=spec.toppin_name, external=True, childports=sram_port) toppin_bb = _frm.toppins[spec.toppin_name] - bbs = tuple(ms.shape.bounds for ms in spsram_lay.filter_polygons( - net=net, mask=m2pin.mask, depth=1, split=True, - )) - left = max(bb.left for bb in bbs) - top = max(bb.top for bb in bbs) - bottom = min(bb.bottom for bb in bbs) - w = 10.0 - x_via2 = left + w/2.0 - right = left + w + sram_m3pinbb = spsram_lay.bounds(mask=m3pin.mask, net=net, depth=1) + left = sram_m3pinbb.left + right = sram_m3pinbb.right + top = sram_m3pinbb.top - for bb in bbs: - y_via2 = bb.center.y - layouter.add_wire( - net=net, wire=via2, x=x_via2, y=y_via2, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - - shape = _geo.Rect( - left=left, bottom=bottom, right=right, top=(top + 20.0), - ) + shape = _geo.Rect.from_rect(rect=sram_m3pinbb, top=(sram_m3pinbb.top + 20.0)) layouter.add_wire(net=net, wire=m3, shape=shape) shape = _geo.Rect( left=toppin_bb.left, bottom=(top + 10.0), right=right, top=(top+20.0), @@ -1895,32 +1828,17 @@ shape = _geo.Rect.from_rect(rect=clamp_bb, bottom=(top + 10)) layouter.add_wire(net=net, wire=m3, shape=shape) - # vdd - spec = io_sig2spec["vdd"] + # svdd + spec = io_sig2spec["svdd"] sram_port = spsram.ports[spec.sram_signal] net = ckt.new_net(name=spec.toppin_name, external=True, childports=sram_port) toppin_bb = _frm.toppins[spec.toppin_name] - bbs = tuple(ms.shape.bounds for ms in spsram_lay.filter_polygons( - net=net, mask=m2pin.mask, depth=1, split=True, - )) - right = min(bb.right for bb in bbs) - top = max(bb.top for bb in bbs) - bottom = min(bb.bottom for bb in bbs) - w = 10.0 - x_via2 = right - w/2.0 - left = right - w + sram_m3pinbb = spsram_lay.bounds(mask=m3pin.mask, net=net, depth=1) + left = sram_m3pinbb.left + right = sram_m3pinbb.right + top = sram_m3pinbb.top - for bb in bbs: - y_via2 = bb.center.y - layouter.add_wire( - net=net, wire=via2, x=x_via2, y=y_via2, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - - shape = _geo.Rect( - left=left, bottom=bottom, right=right, top=(top + 20.0), - ) + shape = _geo.Rect.from_rect(rect=sram_m3pinbb, top=(sram_m3pinbb.top + 20.0)) layouter.add_wire(net=net, wire=m3, shape=shape) shape = _geo.Rect( left=left, bottom=(top + 10.0), right=toppin_bb.right, top=(top + 20.0), @@ -1941,398 +1859,768 @@ ) layouter.add_wire(net=net, wire=m3, shape=shape) - # connect the input signals - a_col = 0 - for sig_name in ( - *(f"a[{a_bit}]" for a_bit in reversed(range(a_bits))), # Reversed for a_col - "clk", "we[0]", - *(f"d[{bit}]" for bit in range(word_size)), - ): - spec = io_sig2spec[sig_name] + # + # Support functions + # + def place_ioperiph(*, spec: _io_spec, sram: _ckt._CellInstance): + sig_name = spec.sram_signal prefix = spec.prefix num = spec.io_number pin_name = spec.toppin_name oeb_name = f"io_oeb[{num}]" out_name = f"io_out[{num}]" - assert spec.io_type == "io_in", "Internal error" - assert spec.oeb, "Internal error" - sram_port = spsram.ports[sig_name] + sram_port = sram.ports[sig_name] - # instantiate cells - buf = ckt.instantiate(buf_cell, name="{prefix}buf") - one = ckt.instantiate(one_cell, name=f"{prefix}one") - zero = ckt.instantiate(zero_cell, name=f"{prefix}zero") - tie = ckt.instantiate(tie_cell, name=f"{prefix}tie") + if spec.io_type == "io_in": + assert spec.oeb, "Internal error" - # create nets - pin_net = ckt.new_net(name=pin_name, external=True, childports=buf.ports.i) - sig_net = ckt.new_net(name=sig_name, external=False, childports=( - buf.ports.q, sram_port, - )) - oeb_net = ckt.new_net( - name=oeb_name, external=True, childports=one.ports.one, - ) - out_net = ckt.new_net( - name=out_name, external=True, childports=zero.ports.zero, - ) + # instantiate cells + buf = ckt.instantiate(buf_cell, name="{prefix}buf") + one = ckt.instantiate(one_cell, name=f"{prefix}one") + zero = ckt.instantiate(zero_cell, name=f"{prefix}zero") + tie = ckt.instantiate(tie_cell, name=f"{prefix}tie") - # get bbs; SRAM m2 pin to m3 pin - toppin_bb = _frm.toppins[pin_name] - oeb_bb = _frm.toppins[oeb_name] - out_bb = _frm.toppins[out_name] - if sig_name.startswith("a["): - # Connect signal up to m2 - sram_m1pinbb = spsram_lay.bounds(mask=m1pin.mask, net=sig_net, depth=1) + # create nets + pin_net = ckt.new_net(name=pin_name, external=True, childports=buf.ports.i) + sig_net = ckt.new_net(name=sig_name, external=False, childports=( + buf.ports.q, sram_port, + )) + oeb_net = ckt.new_net( + name=oeb_name, external=True, childports=one.ports.one, + ) + out_net = ckt.new_net( + name=out_name, external=True, childports=zero.ports.zero, + ) - w = 10.0 - right = spsram_bb.left - (2*a_col + 1)*w - left = right - 1 - a_col += 1 + # get bbs + toppin_bb = _frm.toppins[pin_name] + oeb_bb = _frm.toppins[oeb_name] + out_bb = _frm.toppins[out_name] + is_leftrow = toppin_bb.center.x < _frm.boundary.center.x - x_via = right - w/2.0 - y_via = tech.on_grid(sram_m1pinbb.center.y) - via_lay = layouter.add_wire( - net=sig_net, wire=via, x=x_via, y=y_via, + rot = rot_leftrow if is_leftrow else rot_rightrow + x_row = x_leftrow if is_leftrow else x_rightrow + + # place buf + _buf_rotilipinbb = rot*_buf_ilipinbb + y_buf = tech.on_grid( + toppin_bb.top - _buf_rotilipinbb.bottom, + mult=2, + ) + buf_lay = layouter.place(buf, x=x_row, y=y_buf, rotation=rot) + pinbuf_lipinbb = buf_lay.bounds(mask=lipin.mask, net=pin_net, depth=1) + sigbuf_lipinbb = buf_lay.bounds(mask=lipin.mask, net=sig_net, depth=1) + buf_bb = buf_lay.boundary + assert buf_bb is not None + + # place tie cell + _tie_rotbb = rot*_tie_bb + if is_leftrow: + y_tie = buf_bb.top - _tie_rotbb.bottom + else: + y_tie = buf_bb.bottom - _tie_rotbb.top + layouter.place(tie, x=x_row, y=y_tie, rotation=rot) + + # place zero cell + _zero_rotbb = rot*_zero_bb + if is_leftrow: + y_zero = buf_bb.bottom - _zero_rotbb.top + else: + y_zero = buf_bb.top - _zero_rotbb.bottom + zero_lay = layouter.place(zero, x=x_row, y=y_zero, rotation=rot) + zero_bb = zero_lay.boundary + assert zero_bb is not None + zeroout_lipinbb = zero_lay.bounds(mask=lipin.mask, net=out_net, depth=1) + + # place one cell + _one_rotbb = rot*_one_bb + if is_leftrow: + y_one = zero_bb.bottom - _one_rotbb.top + else: + y_one = zero_bb.top - _one_rotbb.bottom + one_lay = layouter.place(one, x=x_row, y=y_one, rotation=rot) + oneoeb_lipinbb = one_lay.bounds(mask=lipin.mask, net=oeb_net, depth=1) + + # connect pin_net + w = tech.on_grid(pinbuf_lipinbb.width, mult=2, rounding="floor") + o_via = tech.on_grid(pinbuf_lipinbb.center) + layouter.add_wire( + net=pin_net, wire=mcon, origin=o_via, bottom_width=w, bottom_enclosure="wide", top_width=w, top_enclosure="wide", ) - via_m1bb = via_lay.bounds(mask=m1.mask) - sram_m2pinbb = via_lay.bounds(mask=m2.mask) + layouter.add_wire( + net=pin_net, wire=via, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via2_lay = layouter.add_wire( + net=pin_net, wire=via2, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via2_m3bb = via2_lay.bounds(mask=m3.mask) - shape = _geo.Rect.from_rect(rect=sram_m1pinbb, left=via_m1bb.left) - layouter.add_wire(net=sig_net, wire=m1, shape=shape) + if is_leftrow: + shape = _geo.Rect.from_rect(rect=toppin_bb, right=via2_m3bb.right) + else: + shape = _geo.Rect.from_rect(rect=toppin_bb, left=via2_m3bb.left) + layouter.add_wire(net=pin_net, wire=m3, shape=shape) + layouter.add_wire(net=pin_net, wire=m3, pin=m3pin, shape=toppin_bb) + + # connect oeb_net + w = tech.on_grid(oneoeb_lipinbb.width, mult=2, rounding="floor") + o_via = tech.on_grid(oneoeb_lipinbb.center) + layouter.add_wire( + net=oeb_net, wire=mcon, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via_lay = layouter.add_wire( + net=oeb_net, wire=via, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via_m2bb = via_lay.bounds(mask=m2.mask) + + o_via2 = _geo.Point.from_point(point=o_via, y=oeb_bb.center.y) + via2_lay = layouter.add_wire( + net=oeb_net, wire=via2, origin=o_via2, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via2_m2bb = via2_lay.bounds(mask=m2.mask) + via2_m3bb = via2_lay.bounds(mask=m3.mask) + + if is_leftrow: + shape = _geo.Rect.from_rect(rect=via_m2bb, bottom=via2_m2bb.bottom) + else: + shape = _geo.Rect.from_rect(rect=via_m2bb, top=via2_m2bb.top) + layouter.add_wire(net=oeb_net, wire=m2, shape=shape) + if is_leftrow: + shape = _geo.Rect.from_rect(rect=oeb_bb, right=via2_m3bb.right) + else: + shape = _geo.Rect.from_rect(rect=oeb_bb, left=via2_m3bb.left) + layouter.add_wire(net=oeb_net, wire=m3, shape=shape) + + layouter.add_wire(net=oeb_net, wire=m3, pin=m3pin, shape=oeb_bb) + + # connect out_net + w = tech.on_grid(zeroout_lipinbb.width, mult=2, rounding="floor") + o_via = tech.on_grid(zeroout_lipinbb.center) + layouter.add_wire( + net=out_net, wire=mcon, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + layouter.add_wire( + net=out_net, wire=via, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via2_lay = layouter.add_wire( + net=out_net, wire=via2, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via2_m3bb = via2_lay.bounds(mask=m3.mask) + + if is_leftrow: + shape = _geo.Rect.from_rect(rect=via2_m3bb, bottom=out_bb.bottom) + else: + shape = _geo.Rect.from_rect(rect=via2_m3bb, top=out_bb.top) + layouter.add_wire(net=out_net, wire=m3, shape=shape) + if is_leftrow: + shape = _geo.Rect.from_rect(rect=out_bb, right=via2_m3bb.right) + else: + shape = _geo.Rect.from_rect(rect=out_bb, left=via2_m3bb.left) + layouter.add_wire(net=out_net, wire=m3, shape=shape) + + layouter.add_wire(net=out_net, wire=m3, pin=m3pin, shape=out_bb) + + # connect sig_net + w = tech.on_grid(sigbuf_lipinbb.width, mult=2, rounding="floor") + o_via = tech.on_grid(sigbuf_lipinbb.center) + layouter.add_wire( + net=sig_net, wire=mcon, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + layouter.add_wire( + net=sig_net, wire=via, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via2_lay = layouter.add_wire( + net=sig_net, wire=via2, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via2sig_m3bb = via2_lay.bounds(mask=m3.mask) + elif spec.io_type == "io_out": + assert not spec.oeb, "Internal error" + + # instantiate cells + buf = ckt.instantiate(buf_cell, name="{prefix}buf") + zero = ckt.instantiate(zero_cell, name=f"{prefix}zero") + tie = ckt.instantiate(tie_cell, name=f"{prefix}tie") + + # create nets + sig_net = pin_net = ckt.new_net( + name=pin_name, external=True, childports=sram_port, + ) + oeb_net = ckt.new_net( + name=oeb_name, external=True, childports=zero.ports.zero, + ) + + # get bss + toppin_bb = _frm.toppins[pin_name] + oeb_bb = _frm.toppins[oeb_name] + + is_leftrow = toppin_bb.center.x < _frm.boundary.center.x + + # place zero + rot = rot_leftrow if is_leftrow else rot_rightrow + x_row = x_leftrow if is_leftrow else x_rightrow + _zero_rotzerolipinbb = rot*_zero_zerolipinbb + y_zero = oeb_bb.center.y - _zero_rotzerolipinbb.center.y + zero_lay = layouter.place(zero, x=x_row, y=y_zero, rotation=rot) + zero_zerolipinbb = zero_lay.bounds(mask=lipin.mask, net=oeb_net, depth=1) + zero_bb = zero_lay.boundary + assert zero_bb is not None + + # place tie + _tie_rotbb = rot*_tie_bb + y_tie = zero_bb.top - _tie_rotbb.bottom + layouter.place(tie, x=x_row, y=y_tie, rotation=rot) + + # connect sig_net + layouter.add_wire(net=sig_net, wire=m3, pin=m3pin, shape=toppin_bb) + via2sig_m3bb = toppin_bb + + # connect oeb_net + w = tech.on_grid(zero_zerolipinbb.width, mult=2, rounding="floor") + o_via = tech.on_grid(zero_zerolipinbb.center) + layouter.add_wire( + net=oeb_net, wire=mcon, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + layouter.add_wire( + net=oeb_net, wire=via, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via2_lay = layouter.add_wire( + net=oeb_net, wire=via2, origin=o_via, + bottom_width=w, bottom_enclosure="wide", + top_width=w, top_enclosure="wide", + ) + via2_m3bb = via2_lay.bounds(mask=m3.mask) + + if is_leftrow: + shape = _geo.Rect.from_rect(rect=oeb_bb, right=via2_m3bb.right) + else: + shape = _geo.Rect.from_rect(rect=oeb_bb, left=via2_m3bb.left) + layouter.add_wire(net=oeb_net, wire=m3, shape=shape) + layouter.add_wire(net=oeb_net, wire=m3, pin=m3pin, shape=oeb_bb) else: - sram_m2pinbb = spsram_lay.bounds(mask=m2pin.mask, net=sig_net, depth=1) - is_leftrow = toppin_bb.center.x < sram_m2pinbb.center.x + assert False, "Internal error" - rot = rot_leftrow if is_leftrow else rot_rightrow - x_row = x_leftrow if is_leftrow else x_rightrow + return sig_net, via2sig_m3bb - # place buf - _buf_rotilipinbb = rot*_buf_ilipinbb - y_buf = tech.on_grid( - toppin_bb.top - _buf_rotilipinbb.bottom, - mult=2, - ) - buf_lay = layouter.place(buf, x=x_row, y=y_buf, rotation=rot) - pinbuf_lipinbb = buf_lay.bounds(mask=lipin.mask, net=pin_net, depth=1) - sigbuf_lipinbb = buf_lay.bounds(mask=lipin.mask, net=sig_net, depth=1) - buf_bb = buf_lay.boundary - assert buf_bb is not None + # + # SP connections + # - # place tie cell - _tie_rotbb = rot*_tie_bb - if is_leftrow: - y_tie = buf_bb.top - _tie_rotbb.bottom - else: - y_tie = buf_bb.bottom - _tie_rotbb.top - layouter.place(tie, x=x_row, y=y_tie, rotation=rot) + left_col = 1 + right_col = 1 + col_width = 10.0 + col_pitch = 20.0 + col_left0 = 20.0 + col_right0 = 2890.0 - # place zero cell - _zero_rotbb = rot*_zero_bb - if is_leftrow: - y_zero = buf_bb.bottom - _zero_rotbb.top - else: - y_zero = buf_bb.top - _zero_rotbb.bottom - zero_lay = layouter.place(zero, x=x_row, y=y_zero, rotation=rot) - zero_bb = zero_lay.boundary - assert zero_bb is not None - zeroout_lipinbb = zero_lay.bounds(mask=lipin.mask, net=out_net, depth=1) + # Connect in_shiftclk + sig_net, sig_m3bb = place_ioperiph( + spec=io_spsig2spec["in_shiftclk"], sram=spsram, + ) - # place one cell - _one_rotbb = rot*_one_bb - if is_leftrow: - y_one = zero_bb.bottom - _one_rotbb.top - else: - y_one = zero_bb.top - _one_rotbb.bottom - one_lay = layouter.place(one, x=x_row, y=y_one, rotation=rot) - oneoeb_lipinbb = one_lay.bounds(mask=lipin.mask, net=oeb_net, depth=1) + sramsig_m1pinbb = spsram_lay.bounds(mask=m1pin.mask, net=sig_net, depth=1) - # connect pin_net - w = tech.on_grid(pinbuf_lipinbb.width, mult=2, rounding="floor") - o_via = tech.on_grid(pinbuf_lipinbb.center) - layouter.add_wire( - net=pin_net, wire=mcon, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - layouter.add_wire( - net=pin_net, wire=via, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via2_lay = layouter.add_wire( - net=pin_net, wire=via2, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via2_m3bb = via2_lay.bounds(mask=m3.mask) + _viasig_lay = layouter.wire_layout( + net=sig_net, wire=via, rows=10, columns=10, + ) + _viasig_m1bb = _viasig_lay.bounds(mask=m1.mask) - if is_leftrow: - shape = _geo.Rect.from_rect(rect=toppin_bb, right=via2_m3bb.right) - else: - shape = _geo.Rect.from_rect(rect=toppin_bb, left=via2_m3bb.left) - layouter.add_wire(net=pin_net, wire=m3, shape=shape) - layouter.add_wire(net=pin_net, wire=m3, pin=m3pin, shape=toppin_bb) + x = sramsig_m1pinbb.right - _viasig_m1bb.right + y = sramsig_m1pinbb.center.y + layouter.place(_viasig_lay, x=x, y=y) + via2_lay = layouter.add_wire( + net=sig_net, wire=via2, rows=10, columns=10, x=x, y=y, + ) + via2_m3bb = via2_lay.bounds(mask=m3.mask) - # connect sig_net - w = tech.on_grid(sigbuf_lipinbb.width, mult=2, rounding="floor") - o_via = tech.on_grid(sigbuf_lipinbb.center) - layouter.add_wire( - net=sig_net, wire=mcon, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - layouter.add_wire( - net=sig_net, wire=via, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via2_lay = layouter.add_wire( - net=sig_net, wire=via2, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via2_m3bb1 = via2_lay.bounds(mask=m3.mask) + col_left = col_left0 + (left_col - 1)*col_pitch + col_right = col_left + col_width + shape = _geo.Polygon.from_floats(points=( + (sig_m3bb.left, sig_m3bb.bottom), + (sig_m3bb.left, sig_m3bb.top + 1.0), + (col_left, sig_m3bb.top + 1.0), + (col_left, via2_m3bb.top), + (via2_m3bb.right, via2_m3bb.top), + (via2_m3bb.right, via2_m3bb.bottom), + (col_right, via2_m3bb.bottom), + (col_right, sig_m3bb.bottom), + (sig_m3bb.left, sig_m3bb.bottom), + )) + layouter.add_wire(net=sig_net, wire=m3, shape=shape) - _via2_lay = layouter.wire_layout( - net=sig_net, wire=via2, rows=6, columns=3, - ) - _via2_m2bb = _via2_lay.bounds(mask=m2.mask) - if is_leftrow: - x_via2 = sram_m2pinbb.right - _via2_m2bb.right - else: - x_via2 = sram_m2pinbb.left - _via2_m2bb.left - y_via2 = via2_m3bb1.center.y - via2_lay = layouter.place(_via2_lay, x=x_via2, y=y_via2) - via2_m2bb = via2_lay.bounds(mask=m2.mask) - via2_m3bb2 = via2_lay.bounds(mask=m3.mask) + left_col += 1 - shape = _geo.Rect.from_rect(rect=sram_m2pinbb, bottom=via2_m2bb.bottom) - layouter.add_wire(net=sig_net, wire=m2, shape=shape) - if is_leftrow: - shape = _geo.Rect.from_rect(rect=via2_m3bb1, right=via2_m3bb2.right) - else: - shape = _geo.Rect.from_rect(rect=via2_m3bb1, left=via2_m3bb2.left) - layouter.add_wire(net=sig_net, wire=m3, shape=shape) + # Connect shift_in + sig_net, sig_m3bb = place_ioperiph( + spec=io_spsig2spec["shift_in"], sram=spsram, + ) - # connect oeb_net - w = tech.on_grid(oneoeb_lipinbb.width, mult=2, rounding="floor") - o_via = tech.on_grid(oneoeb_lipinbb.center) - layouter.add_wire( - net=oeb_net, wire=mcon, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via_lay = layouter.add_wire( - net=oeb_net, wire=via, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via_m2bb = via_lay.bounds(mask=m2.mask) + sramsig_m1pinbb = spsram_lay.bounds(mask=m1pin.mask, net=sig_net, depth=1) - o_via2 = _geo.Point.from_point(point=o_via, y=oeb_bb.center.y) - via2_lay = layouter.add_wire( - net=oeb_net, wire=via2, origin=o_via2, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via2_m2bb = via2_lay.bounds(mask=m2.mask) - via2_m3bb = via2_lay.bounds(mask=m3.mask) + _viasig_lay = layouter.wire_layout( + net=sig_net, wire=via, rows=10, columns=10, + ) + _viasig_m1bb = _viasig_lay.bounds(mask=m1.mask) - if is_leftrow: - shape = _geo.Rect.from_rect(rect=via_m2bb, bottom=via2_m2bb.bottom) - else: - shape = _geo.Rect.from_rect(rect=via_m2bb, top=via2_m2bb.top) - layouter.add_wire(net=oeb_net, wire=m2, shape=shape) - if is_leftrow: - shape = _geo.Rect.from_rect(rect=oeb_bb, right=via2_m3bb.right) - else: - shape = _geo.Rect.from_rect(rect=oeb_bb, left=via2_m3bb.left) - layouter.add_wire(net=oeb_net, wire=m3, shape=shape) + x = sramsig_m1pinbb.right - _viasig_m1bb.right + y = sramsig_m1pinbb.center.y + layouter.place(_viasig_lay, x=x, y=y) + via2_lay = layouter.add_wire( + net=sig_net, wire=via2, rows=10, columns=10, x=x, y=y, + ) + via2_m3bb = via2_lay.bounds(mask=m3.mask) - layouter.add_wire(net=oeb_net, wire=m3, pin=m3pin, shape=oeb_bb) + col_left = col_left0 + (left_col - 1)*col_pitch + col_right = col_left + col_width + shape = _geo.Polygon.from_floats(points=( + (sig_m3bb.left, sig_m3bb.bottom), + (sig_m3bb.left, sig_m3bb.top + 1.0), + (col_left, sig_m3bb.top + 1.0), + (col_left, via2_m3bb.top), + (via2_m3bb.right, via2_m3bb.top), + (via2_m3bb.right, via2_m3bb.bottom), + (col_right, via2_m3bb.bottom), + (col_right, sig_m3bb.bottom), + (sig_m3bb.left, sig_m3bb.bottom), + )) + layouter.add_wire(net=sig_net, wire=m3, shape=shape) - # connect out_net - w = tech.on_grid(zeroout_lipinbb.width, mult=2, rounding="floor") - o_via = tech.on_grid(zeroout_lipinbb.center) - layouter.add_wire( - net=out_net, wire=mcon, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - layouter.add_wire( - net=out_net, wire=via, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via2_lay = layouter.add_wire( - net=out_net, wire=via2, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via2_m3bb = via2_lay.bounds(mask=m3.mask) + left_col += 1 - if is_leftrow: - shape = _geo.Rect.from_rect(rect=via2_m3bb, bottom=out_bb.bottom) - else: - shape = _geo.Rect.from_rect(rect=via2_m3bb, top=out_bb.top) - layouter.add_wire(net=out_net, wire=m3, shape=shape) - if is_leftrow: - shape = _geo.Rect.from_rect(rect=out_bb, right=via2_m3bb.right) - else: - shape = _geo.Rect.from_rect(rect=out_bb, left=via2_m3bb.left) - layouter.add_wire(net=out_net, wire=m3, shape=shape) + # Connect in_captureclk_l + sig_net, sig_m3bb = place_ioperiph( + spec=io_spsig2spec["in_captureclk_l"], sram=spsram, + ) - layouter.add_wire(net=out_net, wire=m3, pin=m3pin, shape=out_bb) + sramsig_m1pinbb = spsram_lay.bounds(mask=m1pin.mask, net=sig_net, depth=1) - # connect the output signals - for sig_name in ( - *(f"q[{bit}]" for bit in range(word_size)), - ): - spec = io_sig2spec[sig_name] - prefix = spec.prefix - num = spec.io_number + _viasig_lay = layouter.wire_layout( + net=sig_net, wire=via, rows=10, columns=10, + ) + _viasig_m1bb = _viasig_lay.bounds(mask=m1.mask) - pin_name = spec.toppin_name - oeb_name = f"io_oeb[{num}]" - assert spec.io_type == "io_out", "Internal error" - assert not spec.oeb, "Internal error" - sram_port = spsram.ports[spec.sram_signal] + x = sramsig_m1pinbb.right - _viasig_m1bb.right + y = sramsig_m1pinbb.center.y + layouter.place(_viasig_lay, x=x, y=y) + via2_lay = layouter.add_wire( + net=sig_net, wire=via2, rows=10, columns=10, x=x, y=y, + ) + via2_m3bb = via2_lay.bounds(mask=m3.mask) - # instantiate cells - buf = ckt.instantiate(buf_cell, name="{prefix}buf") - zero = ckt.instantiate(zero_cell, name=f"{prefix}zero") - tie = ckt.instantiate(tie_cell, name=f"{prefix}tie") + col_left = col_left0 + (left_col - 1)*col_pitch + col_right = col_left + col_width + shape = _geo.Polygon.from_floats(points=( + (sig_m3bb.left, sig_m3bb.bottom), + (sig_m3bb.left, sig_m3bb.top + 1.0), + (col_left, sig_m3bb.top + 1.0), + (col_left, via2_m3bb.top), + (via2_m3bb.right, via2_m3bb.top), + (via2_m3bb.right, via2_m3bb.bottom), + (col_right, via2_m3bb.bottom), + (col_right, sig_m3bb.bottom), + (sig_m3bb.left, sig_m3bb.bottom), + )) + layouter.add_wire(net=sig_net, wire=m3, shape=shape) - # create nets - pin_net = ckt.new_net(name=pin_name, external=True, childports=buf.ports.q) - sig_net = ckt.new_net(name=sig_name, external=False, childports=( - buf.ports.i, sram_port, - )) - oeb_net = ckt.new_net( - name=oeb_name, external=True, childports=zero.ports.zero, - ) + left_col += 1 - # get bss - toppin_bb = _frm.toppins[pin_name] - oeb_bb = _frm.toppins[oeb_name] - sram_m2pinbb = spsram_lay.bounds(mask=m2pin.mask, net=sig_net, depth=1) + # Connect in_captureclk + sig_net, sig_m3bb = place_ioperiph( + spec=io_spsig2spec["in_captureclk"], sram=spsram, + ) - is_leftrow = toppin_bb.center.x < sram_m2pinbb.center.x + sramsig_m2pinbb = spsram_lay.bounds(mask=m2pin.mask, net=sig_net, depth=1) - # place buf - rot = rot_midrow - y_row = y_midrow - _buf_rotilipinbb = rot*_buf_ilipinbb - x_buf = tech.on_grid( - sram_m2pinbb.right - _buf_rotilipinbb.left, - mult=2, rounding="ceiling", - ) - buf_lay = layouter.place(buf, x=x_buf, y=y_row, rotation=rot) - pinbuf_lipinbb = buf_lay.bounds(mask=lipin.mask, net=pin_net, depth=1) - sigbuf_lipinbb = buf_lay.bounds(mask=lipin.mask, net=sig_net, depth=1) - buf_bb = buf_lay.boundary - assert buf_bb is not None + _via2sig_lay = layouter.wire_layout( + net=sig_net, wire=via2, rows=10, columns=10, + ) + _via2sig_m2bb = _via2sig_lay.bounds(mask=m2.mask) - # place zero - rot = rot_leftrow if is_leftrow else rot_rightrow - x_row = x_leftrow if is_leftrow else x_rightrow - _zero_rotzerolipinbb = rot*_zero_zerolipinbb - y_zero = oeb_bb.center.y - _zero_rotzerolipinbb.center.y - zero_lay = layouter.place(zero, x=x_row, y=y_zero, rotation=rot) - zero_zerolipinbb = zero_lay.bounds(mask=lipin.mask, net=oeb_net, depth=1) - zero_bb = zero_lay.boundary - assert zero_bb is not None + x = sramsig_m2pinbb.right - _via2sig_m2bb.right + y = sramsig_m2pinbb.top - _via2sig_m2bb.top + via2_lay = layouter.place(_via2sig_lay, x=x, y=y) + via2_m3bb = via2_lay.bounds(mask=m3.mask) - # place tie - _tie_rotbb = rot*_tie_bb - y_tie = zero_bb.top - _tie_rotbb.bottom - layouter.place(tie, x=x_row, y=y_tie, rotation=rot) + col_left = col_left0 + (left_col - 1)*col_pitch + col_right = col_left + col_width + shape = _geo.Polygon.from_floats(points=( + (sig_m3bb.left, sig_m3bb.bottom), + (sig_m3bb.left, sig_m3bb.top + 1.0), + (col_left, sig_m3bb.top + 1.0), + (col_left, via2_m3bb.top), + (via2_m3bb.right, via2_m3bb.top), + (via2_m3bb.right, via2_m3bb.bottom), + (col_right, via2_m3bb.bottom), + (col_right, sig_m3bb.bottom), + (sig_m3bb.left, sig_m3bb.bottom), + )) + layouter.add_wire(net=sig_net, wire=m3, shape=shape) - # connect sig_net - h = tech.on_grid(sigbuf_lipinbb.height, mult=2, rounding="floor") - o_via = tech.on_grid(sigbuf_lipinbb.center) - layouter.add_wire( - net=sig_net, wire=mcon, origin=o_via, - bottom_height=h, bottom_enclosure="tall", - top_height=h, top_enclosure="tall", - ) - via_lay = layouter.add_wire( - net=sig_net, wire=via, origin=o_via, - bottom_height=h, bottom_enclosure="tall", - top_height=h, top_enclosure="tall", - ) - via_m2bb = via_lay.bounds(mask=m2.mask) + left_col += 1 - shape = _geo.Rect.from_rect(rect=sram_m2pinbb, bottom=via_m2bb.bottom) - layouter.add_wire(net=sig_net, wire=m2, shape=shape) + # Connect sramclk + sig_net, sig_m3bb = place_ioperiph( + spec=io_spsig2spec["sramclk"], sram=spsram, + ) - # connect pin_net - h = tech.on_grid(pinbuf_lipinbb.height, mult=2, rounding="floor") - o_via = tech.on_grid(pinbuf_lipinbb.center) + sramsig_m2pinbb = spsram_lay.bounds(mask=m2pin.mask, net=sig_net, depth=1) - layouter.add_wire( - net=sig_net, wire=mcon, origin=o_via, - bottom_height=h, bottom_enclosure="tall", - top_height=h, top_enclosure="tall", - ) - via_lay = layouter.add_wire( - net=sig_net, wire=via, origin=o_via, - bottom_height=h, bottom_enclosure="tall", - top_height=h, top_enclosure="tall", - ) - via_m2bb = via_lay.bounds(mask=m2.mask) + _via2sig_lay = layouter.wire_layout( + net=sig_net, wire=via2, rows=10, columns=10, + ) + _via2sig_m2bb = _via2sig_lay.bounds(mask=m2.mask) - _via2_lay = layouter.wire_layout( - net=pin_net, wire=via2, rows=6, columns=3, - ) - _via2_m2bb = _via2_lay.bounds(mask=m2.mask) - if is_leftrow: - x_via2 = via_m2bb.right - _via2_m2bb.right - else: - x_via2 = via_m2bb.left - _via2_m2bb.left - y_via2 = toppin_bb.center.y - via2_lay = layouter.place(_via2_lay, x=x_via2, y=y_via2) - via2_m2bb = via2_lay.bounds(mask=m2.mask) - via2_m3bb = via2_lay.bounds(mask=m3.mask) + x = sramsig_m2pinbb.right - _via2sig_m2bb.right + y = sramsig_m2pinbb.bottom - _via2sig_m2bb.bottom + via2_lay = layouter.place(_via2sig_lay, x=x, y=y) + via2_m3bb = via2_lay.bounds(mask=m3.mask) - shape = _geo.Rect.from_rect(rect=via_m2bb, bottom=via2_m2bb.bottom) - layouter.add_wire(net=pin_net, wire=m2, shape=shape) - if is_leftrow: - shape = _geo.Rect.from_rect(rect=toppin_bb, right=via2_m3bb.right) - else: - shape = _geo.Rect.from_rect(rect=toppin_bb, left=via2_m3bb.left) - layouter.add_wire(net=pin_net, wire=m3, shape=shape) - layouter.add_wire(net=pin_net, wire=m3, pin=m3pin, shape=toppin_bb) + col_left = col_left0 + (left_col - 1)*col_pitch + col_right = col_left + col_width + shape = _geo.Polygon.from_floats(points=( + (sig_m3bb.left, sig_m3bb.bottom), + (sig_m3bb.left, sig_m3bb.top + 1.0), + (col_left, sig_m3bb.top + 1.0), + (col_left, via2_m3bb.top), + (via2_m3bb.right, via2_m3bb.top), + (via2_m3bb.right, via2_m3bb.bottom), + (col_right, via2_m3bb.bottom), + (col_right, sig_m3bb.bottom), + (sig_m3bb.left, sig_m3bb.bottom), + )) + layouter.add_wire(net=sig_net, wire=m3, shape=shape) - # connect oeb_net - w = tech.on_grid(zero_zerolipinbb.width, mult=2, rounding="floor") - o_via = tech.on_grid(zero_zerolipinbb.center) - layouter.add_wire( - net=oeb_net, wire=mcon, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - layouter.add_wire( - net=oeb_net, wire=via, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via2_lay = layouter.add_wire( - net=oeb_net, wire=via2, origin=o_via, - bottom_width=w, bottom_enclosure="wide", - top_width=w, top_enclosure="wide", - ) - via2_m3bb = via2_lay.bounds(mask=m3.mask) + left_col += 1 - if is_leftrow: - shape = _geo.Rect.from_rect(rect=oeb_bb, right=via2_m3bb.right) - else: - shape = _geo.Rect.from_rect(rect=oeb_bb, left=via2_m3bb.left) - layouter.add_wire(net=oeb_net, wire=m3, shape=shape) - layouter.add_wire(net=oeb_net, wire=m3, pin=m3pin, shape=oeb_bb) + # Connect out_captureclk_l + sig_net, sig_m3bb = place_ioperiph( + spec=io_spsig2spec["out_captureclk_l"], sram=spsram, + ) + + sramsig_m1pinbb = spsram_lay.bounds(mask=m1pin.mask, net=sig_net, depth=1) + + _viasig_lay = layouter.wire_layout( + net=sig_net, wire=via, rows=10, columns=10, + ) + _viasig_m1bb = _viasig_lay.bounds(mask=m1.mask) + + x = sramsig_m1pinbb.right - _viasig_m1bb.right + y = sramsig_m1pinbb.center.y + layouter.place(_viasig_lay, x=x, y=y) + via2_lay = layouter.add_wire( + net=sig_net, wire=via2, rows=10, columns=10, x=x, y=y, + ) + via2_m3bb = via2_lay.bounds(mask=m3.mask) + + col_right = col_right0 - (right_col - 1)*col_pitch + col_left = col_right - col_width + shape = _geo.Polygon.from_floats(points=( + (via2_m3bb.left, via2_m3bb.bottom), + (via2_m3bb.left, via2_m3bb.top), + (col_right, via2_m3bb.top), + (col_right, sig_m3bb.top), + (sig_m3bb.right, sig_m3bb.top), + (sig_m3bb.right, sig_m3bb.bottom), + (col_left, sig_m3bb.bottom), + (col_left, via2_m3bb.bottom), + (via2_m3bb.left, via2_m3bb.bottom), + )) + layouter.add_wire(net=sig_net, wire=m3, shape=shape) + + right_col += 1 + + # Connect out_captureclk + sig_net, sig_m3bb = place_ioperiph( + spec=io_spsig2spec["out_captureclk"], sram=spsram, + ) + + sramsig_m1pinbb = spsram_lay.bounds(mask=m1pin.mask, net=sig_net, depth=1) + + _viasig_lay = layouter.wire_layout( + net=sig_net, wire=via, rows=10, columns=10, + ) + _viasig_m1bb = _viasig_lay.bounds(mask=m1.mask) + + x = sramsig_m1pinbb.left - _viasig_m1bb.left + y = sramsig_m1pinbb.center.y + layouter.place(_viasig_lay, x=x, y=y) + via2_lay = layouter.add_wire( + net=sig_net, wire=via2, rows=10, columns=10, x=x, y=y, + ) + via2_m3bb = via2_lay.bounds(mask=m3.mask) + + col_right = col_right0 - (right_col - 1)*col_pitch + col_left = col_right - col_width + shape = _geo.Polygon.from_floats(points=( + (via2_m3bb.left, via2_m3bb.bottom), + (via2_m3bb.left, via2_m3bb.top), + (col_right, via2_m3bb.top), + (col_right, sig_m3bb.top), + (sig_m3bb.right, sig_m3bb.top), + (sig_m3bb.right, sig_m3bb.bottom), + (col_left, sig_m3bb.bottom), + (col_left, via2_m3bb.bottom), + (via2_m3bb.left, via2_m3bb.bottom), + )) + layouter.add_wire(net=sig_net, wire=m3, shape=shape) + + right_col += 1 + + # Connect out_docapture + sig_net, sig_m3bb = place_ioperiph( + spec=io_spsig2spec["out_docapture"], sram=spsram, + ) + + sramsig_m1pinbb = spsram_lay.bounds(mask=m1pin.mask, net=sig_net, depth=1) + + _viasig_lay = layouter.wire_layout( + net=sig_net, wire=via, rows=10, columns=10, + ) + _viasig_m1bb = _viasig_lay.bounds(mask=m1.mask) + + x = sramsig_m1pinbb.right + 5.0 - _viasig_m1bb.left + y = sramsig_m1pinbb.center.y - 1.0 + via_lay = layouter.place(_viasig_lay, x=x, y=y) + via_m1bb = via_lay.bounds(mask=m1.mask) + via2_lay = layouter.add_wire( + net=sig_net, wire=via2, rows=10, columns=10, x=x, y=y, + ) + via2_m3bb = via2_lay.bounds(mask=m3.mask) + + shape =_geo.Rect.from_rect(rect=sramsig_m1pinbb, right=via_m1bb.right) + layouter.add_wire(net=sig_net, wire=m1, shape=shape) + + col_right = col_right0 - (right_col - 1)*col_pitch + col_left = col_right - col_width + shape = _geo.Polygon.from_floats(points=( + (via2_m3bb.left, via2_m3bb.bottom), + (via2_m3bb.left, via2_m3bb.top), + (col_right, via2_m3bb.top), + (col_right, sig_m3bb.top), + (sig_m3bb.right, sig_m3bb.top), + (sig_m3bb.right, sig_m3bb.bottom), + (col_left, sig_m3bb.bottom), + (col_left, via2_m3bb.bottom), + (via2_m3bb.left, via2_m3bb.bottom), + )) + layouter.add_wire(net=sig_net, wire=m3, shape=shape) + + right_col += 1 + + # Connect out_shiftclk + sig_net, sig_m3bb = place_ioperiph( + spec=io_spsig2spec["out_shiftclk"], sram=spsram, + ) + + sramsig_m2pinbb = spsram_lay.bounds(mask=m2pin.mask, net=sig_net, depth=1) + + _via2sig_lay = layouter.wire_layout( + net=sig_net, wire=via2, rows=10, columns=10, + ) + _via2sig_m2bb = _via2sig_lay.bounds(mask=m2.mask) + + x = sramsig_m2pinbb.left - _via2sig_m2bb.left + y = sramsig_m2pinbb.center.y - _via2sig_m2bb.top + via2_lay = layouter.place(_via2sig_lay, x=x, y=y) + via2_m3bb = via2_lay.bounds(mask=m3.mask) + + col_right = col_right0 - (right_col - 1)*col_pitch + col_left = col_right - col_width + shape = _geo.Polygon.from_floats(points=( + (via2_m3bb.left, via2_m3bb.bottom), + (via2_m3bb.left, via2_m3bb.top), + (col_right, via2_m3bb.top), + (col_right, sig_m3bb.top), + (sig_m3bb.right, sig_m3bb.top), + (sig_m3bb.right, sig_m3bb.bottom), + (col_left, sig_m3bb.bottom), + (col_left, via2_m3bb.bottom), + (via2_m3bb.left, via2_m3bb.bottom), + )) + layouter.add_wire(net=sig_net, wire=m3, shape=shape) + + right_col += 1 + + # Connect shift_out + sig_net, sig_m3bb = place_ioperiph( + spec=io_spsig2spec["shift_out"], sram=spsram, + ) + + sramsig_m1pinbb = spsram_lay.bounds(mask=m1pin.mask, net=sig_net, depth=1) + + _viasig_lay = layouter.wire_layout( + net=sig_net, wire=via, rows=10, columns=10, + ) + _viasig_m1bb = _viasig_lay.bounds(mask=m1.mask) + + x = sramsig_m1pinbb.left - _viasig_m1bb.left + y = sramsig_m1pinbb.top - _viasig_m1bb.top + layouter.place(_viasig_lay, x=x, y=y) + via2_lay = layouter.add_wire( + net=sig_net, wire=via2, rows=10, columns=10, x=x, y=y, + ) + via2_m3bb = via2_lay.bounds(mask=m3.mask) + + col_right = col_right0 - (right_col - 1)*col_pitch + col_left = col_right - col_width + shape = _geo.Polygon.from_floats(points=( + (via2_m3bb.left, via2_m3bb.bottom), + (via2_m3bb.left, via2_m3bb.top), + (col_right, via2_m3bb.top), + (col_right, sig_m3bb.top), + (sig_m3bb.right, sig_m3bb.top), + (sig_m3bb.right, sig_m3bb.bottom), + (col_left, sig_m3bb.bottom), + (col_left, via2_m3bb.bottom), + (via2_m3bb.left, via2_m3bb.bottom), + )) + layouter.add_wire(net=sig_net, wire=m3, shape=shape) + + right_col += 1 + + # Connect dvss/dvdd + dc_width = 10.0 + + sramdvss_m1pinbb = spsram_lay.bounds(mask=m1pin.mask, net=dvss, depth=1) + sramdvdd_m2pinbb = spsram_lay.bounds(mask=m2pin.mask, net=dvdd, depth=1) + + o = sramdvss_m1pinbb.center + layouter.add_wire( + net=dvss, wire=via, origin=o, rows=3, + bottom_width=sramdvss_m1pinbb.width + ) + layouter.add_wire( + net=dvss, wire=via2, origin=o, + bottom_width=sramdvss_m1pinbb.width, bottom_height=dc_width, + ) + via3dvss_lay = layouter.add_wire( + net=dvss, wire=via3, origin=o, + bottom_width=sramdvss_m1pinbb.width, bottom_height=dc_width, + ) + via3dvss_m4bb = via3dvss_lay.bounds(mask=m4.mask) + + shape = _geo.Rect.from_rect( + rect=via3dvss_m4bb, left=dvss_leftrowm1bb.left, right=dvss_rightrowm1bb.right, + ) + layouter.add_wire(net=dvss, wire=m4, shape=shape) + + shape = _geo.Rect( + left=dvss_leftrowm1bb.left, bottom=via3dvss_m4bb.bottom, + right=dvss_leftrowm1bb.right, top=via3dvss_m4bb.top, + ) + layouter.add_wire( + net=dvss, wire=via, bottom_shape=shape, top_shape=shape, + ) + layouter.add_wire( + net=dvss, wire=via2, x=shape.center.x, columns=10, + bottom_bottom=shape.bottom, bottom_top=shape.top, + top_bottom=shape.bottom, top_top=shape.top, + ) + layouter.add_wire( + net=dvss, wire=via3, x=shape.center.x, columns=10, + bottom_bottom=shape.bottom, bottom_top=shape.top, + top_bottom=shape.bottom, top_top=shape.top, + ) + + shape = _geo.Rect( + left=dvss_rightrowm1bb.left, bottom=via3dvss_m4bb.bottom, + right=dvss_rightrowm1bb.right, top=via3dvss_m4bb.top, + ) + layouter.add_wire( + net=dvss, wire=via, bottom_shape=shape, top_shape=shape, + ) + layouter.add_wire( + net=dvss, wire=via2, x=shape.center.x, columns=10, + bottom_bottom=shape.bottom, bottom_top=shape.top, + top_bottom=shape.bottom, top_top=shape.top, + ) + layouter.add_wire( + net=dvss, wire=via3, x=shape.center.x, columns=10, + bottom_bottom=shape.bottom, bottom_top=shape.top, + top_bottom=shape.bottom, top_top=shape.top, + ) + + bottom = via3dvss_m4bb.top + 1.0 + top = bottom + dc_width + right = sramdvdd_m2pinbb.right + left = right - dc_width + shape = _geo.Rect(left=left, bottom=bottom, right=right, top=top) + layouter.add_wire( + net=dvss, wire=via2, bottom_shape=shape, top_shape=shape, + ) + via3dvdd_lay = layouter.add_wire( + net=dvss, wire=via3, bottom_shape=shape, top_shape=shape, + ) + via3dvdd_m4bb = via3dvdd_lay.bounds(mask=m4.mask) + + shape = _geo.Rect.from_rect( + rect=via3dvdd_m4bb, left=dvdd_leftrowm1bb.left, right=dvdd_rightrowm1bb.right, + ) + layouter.add_wire(net=dvss, wire=m4, shape=shape) + + shape = _geo.Rect( + left=dvdd_leftrowm1bb.left, bottom=via3dvdd_m4bb.bottom, + right=dvdd_leftrowm1bb.right, top=via3dvdd_m4bb.top, + ) + layouter.add_wire( + net=dvss, wire=via, bottom_shape=shape, top_shape=shape, + ) + layouter.add_wire( + net=dvss, wire=via2, x=shape.center.x, columns=10, + bottom_bottom=shape.bottom, bottom_top=shape.top, + top_bottom=shape.bottom, top_top=shape.top, + ) + layouter.add_wire( + net=dvss, wire=via3, x=shape.center.x, columns=10, + bottom_bottom=shape.bottom, bottom_top=shape.top, + top_bottom=shape.bottom, top_top=shape.top, + ) + + shape = _geo.Rect( + left=dvdd_rightrowm1bb.left, bottom=via3dvdd_m4bb.bottom, + right=dvdd_rightrowm1bb.right, top=via3dvdd_m4bb.top, + ) + layouter.add_wire( + net=dvss, wire=via, bottom_shape=shape, top_shape=shape, + ) + layouter.add_wire( + net=dvss, wire=via2, x=shape.center.x, columns=10, + bottom_bottom=shape.bottom, bottom_top=shape.top, + top_bottom=shape.bottom, top_top=shape.top, + ) + layouter.add_wire( + net=dvss, wire=via3, x=shape.center.x, columns=10, + bottom_bottom=shape.bottom, bottom_top=shape.top, + top_bottom=shape.bottom, top_top=shape.top, + ) # boundary #
diff --git a/gds/user_analog_project_wrapper.gds.gz b/gds/user_analog_project_wrapper.gds.gz index dc51ee5..d54d89f 100644 --- a/gds/user_analog_project_wrapper.gds.gz +++ b/gds/user_analog_project_wrapper.gds.gz Binary files differ