mirror of https://github.com/VLSIDA/OpenRAM.git
added row of nmos to end of array for precharge
This commit is contained in:
parent
f847721500
commit
89c7d50bd1
|
|
@ -65,13 +65,6 @@ class rom_base_array(bitcell_base_array):
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def add_boundary(self):
|
||||
ll = self.find_lowest_coords()
|
||||
bottom_offset = - self.zero_cell.nmos.end_to_contact + self.precharge_inst.offset.y
|
||||
|
|
@ -134,7 +127,7 @@ class rom_base_array(bitcell_base_array):
|
|||
#list of current bitline interconnect nets, starts as the same as the bitline list and is updated when new insts of cells are added
|
||||
self.int_bl_list = self.bitline_names[0].copy()
|
||||
#When rotated correctly rows are word lines
|
||||
for row in range(self.row_size):
|
||||
for row in range(self.row_size + 1):
|
||||
row_list = []
|
||||
|
||||
# for each new strap placed, offset the column index refrenced to get correct bit in the data array
|
||||
|
|
@ -153,6 +146,7 @@ class rom_base_array(bitcell_base_array):
|
|||
row_list.append(new_inst)
|
||||
|
||||
|
||||
|
||||
name = "tap_r{0}_c{1}".format(row, self.array_col_size)
|
||||
new_tap = self.add_inst(name=name, mod=self.poly_tap)
|
||||
self.tap_inst[row, self.column_size] = new_tap
|
||||
|
|
@ -160,6 +154,9 @@ class rom_base_array(bitcell_base_array):
|
|||
self.connect_inst([])
|
||||
|
||||
self.cell_list.append(row_list)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def create_poly_tap(self, row, col):
|
||||
|
|
@ -173,13 +170,12 @@ class rom_base_array(bitcell_base_array):
|
|||
def create_cell(self, row, col):
|
||||
name = "bit_r{0}_c{1}".format(row, col)
|
||||
|
||||
|
||||
# when col = 0, bl_h is connected to vdd, otherwise connect to previous bl connection
|
||||
# when col = 0, bl_h is connected to precharge, otherwise connect to previous bl connection
|
||||
# when col = col_size - 1 connected column_sizeto gnd otherwise create new bl connection
|
||||
if row == self.row_size - 1 or self.get_next_cell_in_bl(row, col) == -1:
|
||||
if row == self.row_size :
|
||||
|
||||
bl_l = self.int_bl_list[col]
|
||||
bl_h = "gnd"
|
||||
bl_h = "gnd"
|
||||
else:
|
||||
bl_l = self.int_bl_list[col]
|
||||
|
||||
|
|
@ -187,8 +183,12 @@ class rom_base_array(bitcell_base_array):
|
|||
self.int_bl_list[col] = "bl_int_{0}_{1}".format(row, col)
|
||||
|
||||
bl_h = self.int_bl_list[col]
|
||||
# Final row of dummy nmos that contains only 1s, acts to prevent shorting bl to ground when precharging
|
||||
|
||||
if self.data[row][col] == 1:
|
||||
if row == self.row_size:
|
||||
new_inst = self.add_inst(name=name, mod=self.one_cell)
|
||||
self.connect_inst([bl_h, bl_l, "precharge", "gnd"])
|
||||
elif self.data[row][col] == 1:
|
||||
new_inst = self.add_inst(name=name, mod=self.one_cell)
|
||||
self.connect_inst([bl_h, bl_l, self.wordline_names[0][row], "gnd"])
|
||||
else:
|
||||
|
|
@ -228,7 +228,7 @@ class rom_base_array(bitcell_base_array):
|
|||
pitch = drc["{0}_to_{0}".format(self.wordline_layer)]
|
||||
|
||||
for i in range(self.column_size):
|
||||
drain = self.cell_list[self.row_size - 1][i].get_pin("D")
|
||||
drain = self.cell_list[self.row_size][i].get_pin("D")
|
||||
|
||||
gnd_pos = drain.center() + vector(0, pitch + via_width + self.route_pitch)
|
||||
self.add_layout_pin_rect_center(text="gnd", layer=self.bitline_layer, offset=gnd_pos)
|
||||
|
|
@ -244,11 +244,10 @@ class rom_base_array(bitcell_base_array):
|
|||
self.cell_pos = {}
|
||||
self.strap_pos = {}
|
||||
# rows are wordlines
|
||||
col_offset = 0
|
||||
pitch_offset = 0
|
||||
for row in range(self.row_size):
|
||||
for row in range(self.row_size + 1):
|
||||
|
||||
if row % self.tap_spacing == 0 and self.pitch_match:
|
||||
if row % self.tap_spacing == 0 and self.pitch_match and row != self.row_size:
|
||||
pitch_offset += self.active_contact.width + self.active_space
|
||||
|
||||
cell_y = row * (self.zero_cell.height) + pitch_offset
|
||||
|
|
@ -376,6 +375,22 @@ class rom_base_array(bitcell_base_array):
|
|||
bl_end = vector(bl_start.x, pre_out_pin.cy())
|
||||
|
||||
self.add_segment_center(self.bitline_layer, bl_start, bl_end)
|
||||
|
||||
upper_precharge = self.precharge_inst.get_pin("precharge_r")
|
||||
lower_precharge = self.tap_inst[self.row_size, self.column_size ].get_pin("poly_tap")
|
||||
|
||||
if self.pitch_match:
|
||||
wire_offset = 2 * self.m1_pitch
|
||||
else:
|
||||
wire_offset = 3 * self.m1_pitch
|
||||
start = upper_precharge.center()
|
||||
end = lower_precharge.center()
|
||||
mid1 = start + vector(wire_offset, 0)
|
||||
mid2 = end + vector(wire_offset, 0)
|
||||
|
||||
self.add_path(layer="m1", coordinates=[start, mid1, mid2, end])
|
||||
|
||||
|
||||
def connect_taps(self):
|
||||
array_pins = [self.tap_list[i].get_pin("poly_tap") for i in range(len(self.tap_list))]
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ class rom_base_bank(design):
|
|||
self.route_array_outputs()
|
||||
self.place_top_level_pins()
|
||||
self.route_supplies()
|
||||
self.route_output_buffers()
|
||||
self.height = self.array_inst.height
|
||||
self.width = self.array_inst.width
|
||||
self.add_boundary()
|
||||
|
|
@ -185,7 +186,8 @@ class rom_base_bank(design):
|
|||
clk_fanout=(self.col_bits + self.row_bits) * 2,
|
||||
height=self.column_decode.height )
|
||||
|
||||
self.output_buffer = factory.create(module_type="rom_wordline_driver_array",
|
||||
self.output_buffer = factory.create(module_type="rom_wordline_driver_array",
|
||||
module_name="rom_output_buffer",
|
||||
rows=self.word_size,
|
||||
cols=4)
|
||||
|
||||
|
|
@ -280,10 +282,10 @@ class rom_base_bank(design):
|
|||
self.mux_inst.place(offset=self.mux_offset)
|
||||
|
||||
def place_output_buffer(self):
|
||||
output_x = self.col_decode_inst.rx()
|
||||
output_y = 0
|
||||
output_x = self.col_decode_inst.rx() + self.output_buf_inst.height
|
||||
output_y = self.col_decode_inst.by() + self.output_buf_inst.width
|
||||
self.output_buf_offset = vector(output_x, output_y)
|
||||
self.output_buf_inst.place(offset=self.output_buf_offset, rotate=90)
|
||||
self.output_buf_inst.place(offset=self.output_buf_offset, rotate=270)
|
||||
|
||||
# def create_wl_bus(self):
|
||||
# bus_x = self.decode_inst.width + ( drc["minwidth_{}".format(self.bus_layer)] + 1.5 * drc["{0}_to_{0}".format(self.bus_layer)] )
|
||||
|
|
@ -396,14 +398,38 @@ class rom_base_bank(design):
|
|||
def route_array_outputs(self):
|
||||
for i in range(self.cols):
|
||||
bl_out = self.array_inst.get_pin("bl_0_{}".format(i)).center()
|
||||
|
||||
bl_mux = self.mux_inst.get_pin("bl_{}".format(i)).center()
|
||||
|
||||
self.add_path(self.array.bitline_layer, [bl_out, bl_mux])
|
||||
|
||||
|
||||
def route_output_buffers(self):
|
||||
mux = self.mux_inst
|
||||
buf = self.output_buf_inst
|
||||
route_nets = [ [mux.get_pin("bl_out_{}".format(bit)), buf.get_pin("in_{}".format(bit))] for bit in range(self.word_size)]
|
||||
|
||||
channel_ll = vector( route_nets[0][0].cx(), route_nets[0][1].cy() + self.m1_pitch * 3)
|
||||
self.create_horizontal_channel_route(netlist=route_nets, offset=channel_ll, layer_stack=self.m1_stack)
|
||||
# for bit in range(self.word_size):
|
||||
# mux_pin = self.mux_inst.get_pin("bl_out_{}".format(bit))
|
||||
# buf_pin = self.output_buf_inst.get_pin("in_{}".format(bit))
|
||||
# mux_out = vector(mux_pin.cx(), mux_pin.by())
|
||||
# buf_in = buf_pin.center()
|
||||
|
||||
# mid1 = vector(mux_out.x, buf_in.y + bit * self.m2_pitch)
|
||||
# mid2 = vector(buf_in.x, mid1.y)
|
||||
# print("start: {0}, mid: {1}, stop: {2}".format(mux_out, mid1, buf_in))
|
||||
# self.add_path(layer="m2", coordinates=[mux_out, mid1, mid2, buf_in])
|
||||
|
||||
|
||||
|
||||
def place_top_level_pins(self):
|
||||
self.copy_layout_pin(self.control_inst, "CS", "CS")
|
||||
self.copy_layout_pin(self.control_inst, "CS")
|
||||
self.copy_layout_pin(self.control_inst, "clk_in", "clk")
|
||||
|
||||
for i in range(self.word_size):
|
||||
self.copy_layout_pin(self.mux_inst, "bl_out_{}".format(i), "rom_out_{}".format(i))
|
||||
self.copy_layout_pin(self.output_buf_inst, "out_{}".format(i), "rom_out_{}".format(i))
|
||||
for lsb in range(self.col_bits):
|
||||
name = "addr_{}".format(lsb)
|
||||
self.copy_layout_pin(self.col_decode_inst, "A{}".format(lsb), name)
|
||||
|
|
|
|||
|
|
@ -123,8 +123,8 @@ class rom_base_cell(design):
|
|||
|
||||
def place_tx(self):
|
||||
|
||||
|
||||
tx_offset = vector(self.poly_extend_active + self.cell_inst.height + (self.poly_size) ,- 0.5 * self.contact_width - self.active_enclose_contact)
|
||||
# sizing_offset = self.cell_inst.height - drc["minwidth_tx"]
|
||||
tx_offset = vector(self.poly_extend_active + self.cell_inst.height + self.poly_size,- 0.5 * self.contact_width - self.active_enclose_contact)
|
||||
# add rect of poly to account for offset from drc spacing
|
||||
# self.add_rect_center("poly", poly_offset, self.poly_extend_active_spacing, self.poly_width)
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class rom_control_logic(design):
|
|||
self.connect_inst(["clk_in", "clk_bar", "clk_out", "vdd", "gnd"])
|
||||
|
||||
self.nand_inst = self.add_inst(name="control_nand", mod=self.nand_mod)
|
||||
self.connect_inst(["CS", "clk_bar", "pre_drive", "vdd", "gnd"])
|
||||
self.connect_inst(["CS", "clk_out", "pre_drive", "vdd", "gnd"])
|
||||
|
||||
self.driver_inst = self.add_inst(name="driver_inst", mod=self.driver_mod)
|
||||
self.connect_inst(["pre_drive", "prechrg", "vdd", "gnd"])
|
||||
|
|
|
|||
|
|
@ -25,21 +25,23 @@ class rom_poly_tap(design):
|
|||
|
||||
def create_netlist(self):
|
||||
#for layout constants
|
||||
if self.tx_type == "nmos":
|
||||
self.dummy = factory.create(module_type="rom_base_cell")
|
||||
else:
|
||||
self.dummy = factory.create(module_type="rom_precharge_cell")
|
||||
self.dummy = factory.create(module_type="rom_base_cell")
|
||||
|
||||
# if self.tx_type == "nmos":
|
||||
# self.dummy = factory.create(module_type="rom_base_cell")
|
||||
# else:
|
||||
# self.dummy = factory.create(module_type="rom_precharge_cell")
|
||||
|
||||
self.pmos = factory.create(module_type="ptx", tx_type="pmos")
|
||||
|
||||
def create_layout(self):
|
||||
|
||||
self.place_via()
|
||||
|
||||
self.add_boundary()
|
||||
if self.add_tap:
|
||||
self.place_active_tap()
|
||||
self.extend_poly()
|
||||
self.add_boundary()
|
||||
|
||||
|
||||
# if self.length != 0:
|
||||
# self.place_strap()
|
||||
|
|
@ -94,9 +96,13 @@ class rom_poly_tap(design):
|
|||
# self.strap = self.add_path(self.strap_layer, (strap_start, strap_end))
|
||||
|
||||
def extend_poly(self):
|
||||
|
||||
self.add_segment_center("poly", self.via.center(), vector(self.via.cx() + self.pitch_offset, self.via.cy()))
|
||||
self.add_segment_center("poly", self.via.center(), vector(0, self.via.cy()))
|
||||
y_offset = 0
|
||||
if self.tx_type == "pmos":
|
||||
y_offset = -self.height
|
||||
start = self.via.center() + vector(0, y_offset)
|
||||
|
||||
self.add_segment_center("poly", start, vector(self.via.cx() + self.pitch_offset, self.via.cy() + y_offset))
|
||||
self.add_segment_center("poly", start, vector(0, self.via.cy() + y_offset))
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -126,17 +126,16 @@ class rom_precharge_array(design):
|
|||
self.add_label("ZERO", self.route_layer)
|
||||
|
||||
self.array_pos = []
|
||||
strap_num = 1
|
||||
strap_num = 0
|
||||
cell_y = 0
|
||||
# columns are bit lines4
|
||||
# columns are bit lines
|
||||
cell_x = 0
|
||||
|
||||
self.tap_insts[0].place(vector(cell_x, cell_y))
|
||||
|
||||
|
||||
for col in range(self.cols):
|
||||
|
||||
if col % self.strap_spacing == 0:
|
||||
self.tap_insts[strap_num].place(vector(cell_x, cell_y))
|
||||
self.tap_insts[strap_num].place(vector(cell_x, cell_y + self.poly_tap.height))
|
||||
strap_num += 1
|
||||
|
||||
if self.tap_direction == "col":
|
||||
|
|
@ -151,10 +150,14 @@ class rom_precharge_array(design):
|
|||
self.pmos_insts[col].place(vector(cell_x, cell_y))
|
||||
self.add_label("debug", "li", vector(cell_x, cell_y))
|
||||
cell_x += self.pmos.width
|
||||
print(self.tap_insts)
|
||||
|
||||
self.tap_insts[strap_num].place(vector(cell_x, cell_y + self.poly_tap.height))
|
||||
|
||||
|
||||
def create_layout_pins(self):
|
||||
self.copy_layout_pin(self.tap_insts[0], "poly_tap", "gate")
|
||||
self.copy_layout_pin(self.tap_insts[-1], "poly_tap", "precharge_r")
|
||||
for col in range(self.cols):
|
||||
source_pin = self.pmos_insts[col].get_pin("D")
|
||||
bl = "pre_bl{0}_out".format(col)
|
||||
|
|
@ -175,6 +178,19 @@ class rom_precharge_array(design):
|
|||
|
||||
self.connect_row_pins(layer=self.strap_layer, pins=array_pins, name=None, round=False)
|
||||
|
||||
for tap in self.tap_insts:
|
||||
tap_pin = tap.get_pin("poly_tap")
|
||||
start = vector(tap_pin.cx(), tap_pin.by())
|
||||
end = vector(start.x, tap.mod.get_pin("poly_tap").cy())
|
||||
self.add_segment_center(layer="poly", start=start, end=end)
|
||||
print(end)
|
||||
offset_start = vector(end.x - self.poly_tap.width + self.poly_extend_active, end.y)
|
||||
offset_end = end + vector(0.5*self.poly_width, 0)
|
||||
print(self.poly_tap.width)
|
||||
print(end)
|
||||
print(offset_start)
|
||||
self.add_segment_center(layer="poly", start=offset_start, end=offset_end)
|
||||
|
||||
def extend_well(self):
|
||||
self.well_offset = self.pmos.tap_offset
|
||||
well_y = self.pmos_insts[0].get_pin("vdd").cy() - 0.5 * self.nwell_width
|
||||
|
|
|
|||
|
|
@ -99,3 +99,5 @@ class rom_precharge_cell(rom_base_cell):
|
|||
self.add_path(self.supply_layer, [self.get_pin("vdd").center(), pos, self.get_pin("S").center()])
|
||||
|
||||
self.remove_layout_pin("S")
|
||||
def place_bitline(self):
|
||||
pass
|
||||
|
|
|
|||
Loading…
Reference in New Issue