Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
self.cross_couple_upper_ypos)
self.add_via_center(layers=("poly", "contact", "metal1"),
offset=right_storage_contact,
directions=("H", "H"))
inverter_gate_offset_left = vector(self.inverter_nmos_left.get_pin("G").lc().x, self.cross_couple_upper_ypos)
self.add_path("poly", [left_storage_contact, inverter_gate_offset_left])
inverter_gate_offset_right = vector(self.inverter_nmos_right.get_pin("G").rc().x, self.cross_couple_upper_ypos)
self.add_path("poly", [right_storage_contact, inverter_gate_offset_right])
# add poly to metal1 contacts for gates of read-access transistors
# route from read-access contacts to inverter contacts on metal1
for k in range(self.num_r_ports):
port_contact_offset = self.read_access_nmos_left[k].get_pin("G").uc() \
+ vector(0,
self.gate_contact_yoffset - self.poly_extend_active)
self.add_via_center(layers=("poly", "contact", "metal1"),
offset=port_contact_offset)
self.add_path("poly",
[self.read_access_nmos_left[k].get_pin("G").uc(), port_contact_offset])
mid = vector(self.read_access_nmos_left[k].get_pin("G").uc().x,
self.cross_couple_upper_ypos)
self.add_path("metal1",
[port_contact_offset, mid, left_storage_contact])
port_contact_offset = self.read_access_nmos_right[k].get_pin("G").uc() \
+ vector(0,
self.gate_contact_yoffset - self.poly_extend_active)
# add pin for WWL
wwl_ypos = rwwl_ypos = self.m1_offset \
- self.num_rw_ports * self.m1_pitch \
- k * self.m1_pitch
self.wwl_positions[k] = vector(0, wwl_ypos)
self.add_layout_pin_rect_center(text=self.w_wl_names[k],
layer="metal1",
offset=self.wwl_positions[k],
width=self.width)
# add pins for WBL and WBR
wbl_xpos = left_write_transistor_xpos \
- self.bitline_offset \
+ 0.5 * self.m2_width
self.wbl_positions[k] = vector(wbl_xpos, self.center_ypos)
self.add_layout_pin_rect_center(text=self.w_bl_names[k],
layer="metal2",
offset=self.wbl_positions[k],
height=self.height)
wbr_xpos = right_write_transistor_xpos \
+ self.write_nmos.active_width \
+ self.bitline_offset \
- 0.5 * self.m2_width
self.wbr_positions[k] = vector(wbr_xpos, self.center_ypos)
self.add_layout_pin_rect_center(text=self.w_br_names[k],
layer="metal2",
offset=self.wbr_positions[k],
height=self.height)
# update furthest left and right transistor edges
[(self.inbank_inst[1].lr().x, self.reset1_off.y+self.m1_width),
(reset_xoff, self.reset1_off.y+self.m1_width),
(reset_xoff, self.reset2_off.y+self.m1_width),
(self.inbank_inst[1].lr().x, self.reset2_off.y+self.m1_width)])
# split_merge_control_inst Connections
ctrl_pin_list = ["wack", "wreq", "rreq", "rack", "ack", "rw", "w", "r",
"ack_b", "rw_merge", "pre_ack", "pre_wack", "pre_rack"]
for k in range(self.num_outbanks):
ctrl_pin_list.extend(["ack{0}".format(k), "ack_b{0}".format(k)])
for i in range(len(ctrl_pin_list)):
ctrl_off = vector(self.out_split_mrg_ctrl_inst.get_pin(ctrl_pin_list[i]).ll().x,
self.H_ctrl_bus_pos[ctrl_pin_list[i]][1]- 0.5*self.m1_width)
ctrl2_off = vector(self.out_split_mrg_ctrl_inst.get_pin(ctrl_pin_list[i]).ll().x,
self.H2_ctrl_bus_pos[ctrl_pin_list[i]][1]- 0.5*self.m1_width)
ctrl_heigh = self.out_split_mrg_ctrl_inst.get_pin(ctrl_pin_list[i]).ll().y - \
self.H_ctrl_bus_pos[ctrl_pin_list[i]][1]+ 0.5*self.m1_width
self.add_rect(layer="metal2",
offset=ctrl_off,
width=self.m2_width,
height=ctrl_heigh)
self.add_via(self.m1_stack, (ctrl_off.x, ctrl_off.y-self.via_yshift))
self.add_via(self.m1_stack, (ctrl2_off.x, ctrl2_off.y-self.via_yshift))
power_pin =["vdd", "gnd"]
for i in range(2):
power_off = vector(self.out_split_mrg_ctrl_inst.get_pin(power_pin[i]).ll().x,
self.power1_off.y + i*self.power_pitch + 0.5*self.m1_width)
# input is A pin of first inverter
a_pin = self.driver_inst_list[0].get_pin("A")
self.add_via_center(layers=("metal1","via1","metal2"),
offset=a_pin.center())
self.add_layout_pin(text="in",
layer="metal2",
offset=a_pin.ll().scale(1,0),
height=a_pin.cy())
# output is A pin of last load inverter
last_driver_inst = self.driver_inst_list[-1]
a_pin = self.rightest_load_inst[last_driver_inst].get_pin("A")
self.add_via_center(layers=("metal1","via1","metal2"),
offset=a_pin.center())
mid_point = vector(a_pin.cx()+3*self.m2_width,a_pin.cy())
self.add_path("metal2",[a_pin.center(), mid_point, mid_point.scale(1,0)])
self.add_layout_pin_segment_center(text="out",
layer="metal2",
start=mid_point,
end=mid_point.scale(1,0))
def route_en(self):
# Enable in track
track_xoff = self.get_m4_track(self.en_track)
# The en pin will be over the vdd rail
vdd_yloc = self.en_inst.get_pin("vdd").cy()
self.add_layout_pin_segment_center(text="en",
layer="m3",
start=vector(0,vdd_yloc),
end=vector(self.width,vdd_yloc))
en_loc = self.en_inst.get_pin("A").center()
en_rail = vector(en_loc.x, vdd_yloc)
self.add_via_stack("m1", "m2", en_loc)
self.add_path("m2", [en_loc, en_rail])
self.add_via_stack("m2", "m3", en_rail)
# Start point in the track on the pin rail
en_track = vector(track_xoff, vdd_yloc)
self.add_via_stack("m3", "m4", en_track)
# This is a U route to the right down then left
bl_en_loc = self.bl_inst.get_pin("en").center()
bl_en_track = vector(track_xoff, bl_en_loc.y)
self.add_via_stack("m1", "m3", bl_en_loc)
br_en_loc = self.br_inst.get_pin("en").center()
def connect_pmos_m1(self, pmos_pin, bit_pin):
"""
Connect a pmos pin to bitline pin
"""
left_pos = vector(min(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
right_pos = vector(max(pmos_pin.cx(), bit_pin.cx()), pmos_pin.cy())
self.add_path("metal1", [left_pos, right_pos] )
directions=("H", "H"))
contact_offset_right = vector(self.inverter_nmos_right.get_pin("S").lc().x \
- 0.5*contact.poly.height,
self.cross_couple_lower_ypos)
self.add_via_center(layers=("poly", "contact", "metal1"),
offset=contact_offset_right,
directions=("H", "H"))
# connect contacts to gate poly (cross couple connections)
gate_offset_right = vector(self.inverter_nmos_right.get_pin("G").lc().x,
contact_offset_left.y)
self.add_path("poly", [contact_offset_left, gate_offset_right])
gate_offset_left = vector(self.inverter_nmos_left.get_pin("G").rc().x,
contact_offset_right.y)
self.add_path("poly", [contact_offset_right, gate_offset_left])
def add_data_pattern(self):
""" Place data pattern generator """
off = self.fsm_inst.ul()+ vector(self.m_pitch("m1"), self.gap+9*self.m_pitch("m1"))
self.data_pattern_inst=self.add_inst(name="data_pattern", mod=self.data_pattern,
offset= off)
temp=[]
for i in range(self.data_size):
temp.append("din{0}".format(i))
temp.extend(["data_enable", "vdd", "gnd"])
self.connect_inst(temp)
self.add_via(self.m1_stack, (subank_dec_vdd_x_offset,self.min_point_y+self.m_pitch("m1")))
self.add_via(self.m1_stack, (row_dec_vdd_xoff,self.min_point_y+self.m_pitch("m1")))
# Route vdd for the address/ctrl splits & merge if two_level_bank to ctrl_logic vdd
if self.two_level_bank:
ctrl_mrg_vdd_off=self.wack_merge_cell_inst.get_pin("vdd").lc()
addr_spl_vdd_off=self.addr_split_ary_inst.get_pin("vdd").lc()
x_off = self.min_point_x-(self.num_subanks+8)*self.m_pitch("m1")
vdd_pos1= vector(x_off, ctrl_mrg_vdd_off.y)
vdd_pos2= vector(x_off, addr_spl_vdd_off.y)
self.add_wire(self.m1_stack, [ctrl_mrg_vdd_off, vdd_pos1])
self.add_wire(self.m1_stack, [ctrl_mrg_vdd_off, vdd_pos1, vdd_pos2, addr_spl_vdd_off])
y_off = self.ctrl_logic_inst.ll().y-(self.num_subanks+2)*self.m_pitch("m1")
vdd_pos3= vector(x_off,y_off)
vdd_pos4= vector(self.ctrl_logic_inst.get_pin("vdd").uc().x,y_off)
vdd_pos5= self.ctrl_logic_inst.get_pin("vdd").uc()
self.add_wire(self.m1_stack, [ctrl_mrg_vdd_off, vdd_pos1, vdd_pos3, vdd_pos4, vdd_pos5])
# Route vdd from ctrl logic to vdd rail
off_y_1 = self.row_dec_drv_inst.ul().y+(8+2*self.num_subanks)*self.m_pitch("m2")
ctrl_vdd_off_y = max (off_y_1,self.ctrl_logic_inst.ll().y+self.ctrl_logic.width+3*self.m_pitch("m2"))
vdd_pos1= (row_dec_vdd_xoff+0.5*contact.m1m2.height, ctrl_vdd_off_y)
vdd_pos2= (row_dec_vdd_xoff+0.5*contact.m1m2.height, off_y_1)
vdd_pos3= (self.ctrl_logic_inst.get_pin("vdd").uc().x, ctrl_vdd_off_y)
vdd_pos4= self.ctrl_logic_inst.get_pin("vdd").uc()
self.add_path("metal2",[vdd_pos1, vdd_pos2],width=contact.m1m2.height)
self.add_wire(self.m2_rev_stack,[vdd_pos2, vdd_pos3, vdd_pos4])
if (self.row_dec_drv_inst.ul().y+(5+2*self.num_subanks)*self.m_pitch("m2") >=
self.ctrl_logic_inst.ll().y + self.ctrl_logic.width):
self.add_via(self.m2_stack, (vdd_pos2[0]+0.5*contact.m2m3.height,
#add output so that it is just below the vdd or gnd rail
# since this is where the p/n devices are and there are no
# pins in the nand gates.
y_offset = (inv_num+1) * self.inv.height - 3*self.m1_space
inv_out_pos = self.in_inst[inv_num].get_pin("Z").rc()
right_pos = inv_out_pos + vector(self.inv.width - self.inv.get_pin("Z").lx(),0)
rail_pos = vector(self.decode_rails[out_pin].x,y_offset)
self.add_path("metal1", [inv_out_pos, right_pos, vector(right_pos.x, y_offset), rail_pos])
self.add_via_center(layers = ("metal1", "via1", "metal2"),
offset=rail_pos)
#route input
inv_in_pos = self.in_inst[inv_num].get_pin("A").lc()
in_pos = vector(self.input_rails[in_pin].x,inv_in_pos.y)
self.add_path("metal1", [in_pos, inv_in_pos])
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=in_pos)