diff --git a/compiler/bank.py b/compiler/bank.py index 1d4fd0b4..92999ad3 100644 --- a/compiler/bank.py +++ b/compiler/bank.py @@ -92,10 +92,7 @@ class bank(design.design): self.add_control_pins() self.route_vdd_supply() self.route_gnd_supply() - - - - + def add_modules(self): """ Add modules. The order should not matter! """ self.add_bitcell_array() @@ -360,13 +357,13 @@ class bank(design.design): def add_row_decoder(self): """ Add the hierarchical row decoder """ - + # The address and control bus will be in between decoder and the main memory array # This bus will route address bits to the decoder input and column mux inputs. # The wires are actually routed after we placed the stuff on both sides. # The predecoder is below the x-axis and the main decoder is above the x-axis # The address flop and decoder are aligned in the x coord. - + decoder_x_offset = self.decoder.width + self.overall_central_bus_width addr_x_offset = self.msf_address.height offset = vector(max(decoder_x_offset, addr_x_offset), @@ -432,11 +429,10 @@ class bank(design.design): temp.extend(["vdd", "gnd"]) self.connect_inst(temp) - def add_column_decoder(self): """ Create a 2:4 decoder to decode column select lines if the col_addr_size = 4 """ - + if self.col_addr_size == 1: return # This is done from the FF outputs directly if self.col_addr_size == 2: @@ -590,8 +586,8 @@ class bank(design.design): gated_name, "vdd", "gnd"]) - + # Connect the logic output to inverter input pre = logic_inst.get_pin("Z").lc() out_position = logic_inst.get_pin("Z").rc() + vector(0.5*self.m1_width,0) diff --git a/compiler/sram.py b/compiler/sram.py index 5d583ddd..20521105 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -161,145 +161,45 @@ class sram(design.design): elif self.num_banks == 2: self.add_two_bank_modules() self.route_two_banks() + elif self.num_banks == 4: + self.add_four_bank_modules() + self.route_four_banks() else: - self.add_multi_bank_modules() - self.add_multi_bank_pins() - return - self.route_2or4_banks() - if self.num_banks > 2: - self.route_4_banks() - - self.route_bank_and_control() - self.route_supplies() + debug.error("Invalid number of banks.",-1) + + + def add_four_bank_modules(self): + """ Adds the modules and the buses to the top level """ + + self.compute_four_bank_offsets() + + self.add_four_banks() + + self.add_busses() + + self.add_four_bank_logic() + + self.width = self.bank_inst[1].ur().x + self.height = max(self.control_logic_inst.uy(),self.msb_decoder_inst.uy()) + def add_two_bank_modules(self): """ Adds the modules and the buses to the top level """ + self.compute_two_bank_offsets() - ######################## - # First, compute all of the offsets - ######################## - self.num_vertical_line = self.bank_addr_size + self.control_size + self.num_banks + 1 - self.num_horizontal_line = self.word_size - - self.vertical_bus_width = self.m2_pitch*self.num_vertical_line - self.data_bus_height = self.m3_pitch*self.num_horizontal_line - self.control_bus_height = self.m1_pitch*(self.control_size+2) - self.supply_bus_height = self.m1_pitch*2 # 2 for vdd/gnd placed with control bus - - # Sanity check to ensure we can fit the control logic above a single bank (0.9 is a hack really) - debug.check(self.bank.width + self.vertical_bus_width > 0.9*self.control_logic.width, "Bank is too small compared to control logic.") + self.add_two_banks() - # This depends on the bus widths, but nothing else - self.add_top_banks() - - self.vertical_bus_height = self.bank.height + self.bank_to_bus_distance + self.data_bus_height + self.control_bus_height - self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 2*self.power_rail_pitch) + self.add_busses() - self.data_bus_width = 2*(self.bank.width + self.bank_to_bus_distance) + self.vertical_bus_width - self.data_bus_offset = vector(0, 2*self.power_rail_pitch + self.bank.height + self.bank_to_bus_distance) + self.add_two_bank_logic() - self.supply_bus_width = self.data_bus_width - self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height) - - self.control_bus_width = self.bank.width + self.bank_to_bus_distance + self.vertical_bus_width - self.control_bus_offset = vector(0, self.supply_bus_offset.y + self.supply_bus_height) - - self.bank_sel_bus_offset = self.vertical_bus_offset + vector(self.m2_pitch*self.control_size,0) - - # The address bus extends down through the power rails, but control and bank_sel bus don't - self.addr_bus_height = self.vertical_bus_height + 2*self.power_rail_pitch - self.addr_bus_offset = self.bank_sel_bus_offset.scale(1,0) + vector(self.m2_pitch*self.num_banks,0) - - - - # Control is placed at the top above the control bus and everything - self.control_logic_position = vector(0, self.control_bus_offset.y + self.control_bus_height + self.m1_pitch) - - # Bank select flops get put to the right of control logic above bank1 and the buses - # Leave a pitch to get the vdd rails up to M2 - self.msb_address_position = vector(max(self.bank_inst[1].lx(),self.control_logic.width), - self.supply_bus_offset.y+self.supply_bus_height + 2*self.m1_pitch + self.msb_address.width) - - - ######################## - # Second, place the buses - ######################## - # Vertical bus - # The order of the control signals on the control bus: - self.control_bus_names = ["clk_buf", "tri_en_bar", "tri_en", "clk_bar", "w_en", "s_en"] - self.vert_control_bus_positions = self.create_bus(layer="metal2", - pitch=self.m2_pitch, - offset=self.vertical_bus_offset, - names=self.control_bus_names, - length=self.vertical_bus_height, - vertical=True) - self.addr_bus_names=[] - for i in range(self.addr_size): - self.addr_bus_names.append("ADDR[{}]".format(i)) - self.vert_control_bus_positions.update(self.create_bus(layer="metal2", - pitch=self.m2_pitch, - offset=self.addr_bus_offset, - names=self.addr_bus_names, - length=self.addr_bus_height, - vertical=True, - make_pins=True)) - - self.bank_sel_bus_names = ["bank_sel[0]","bank_sel[1]"] - self.vert_control_bus_positions.update(self.create_bus(layer="metal2", - pitch=self.m2_pitch, - offset=self.bank_sel_bus_offset, - names=self.bank_sel_bus_names, - length=self.vertical_bus_height, - vertical=True)) - - - # Horizontal data bus - self.data_bus_names = [] - for i in range(0, self.word_size): - self.data_bus_names.append("DATA[{}]".format(i)) - self.data_bus_positions = self.create_bus(layer="metal3", - pitch=self.m3_pitch, - offset=self.data_bus_offset, - names=self.data_bus_names, - length=self.data_bus_width, - vertical=False, - make_pins=True) - - # Horizontal control logic bus - # vdd/gnd in bus go along whole SRAM - # FIXME: Fatten these wires? - self.horz_control_bus_positions = self.create_bus(layer="metal1", - pitch=self.m1_pitch, - offset=self.supply_bus_offset, - names=["vdd", "gnd"], - length=self.supply_bus_width, - vertical=False) - self.horz_control_bus_positions.update(self.create_bus(layer="metal1", - pitch=self.m1_pitch, - offset=self.control_bus_offset, - names=self.control_bus_names, - length=self.control_bus_width, - vertical=False)) - - ######################## - # Third, place the other logic (banks are done first to anchor the design) - ######################## - self.add_control_logic(position=self.control_logic_position, rotate=0) - - self.msb_address_inst = self.add_inst(name="msb_address", - mod=self.msb_address, - offset=self.msb_address_position, - rotate=270) - self.msb_bank_sel_addr = "ADDR[{}]".format(self.addr_size-1) - self.connect_inst([self.msb_bank_sel_addr,"bank_sel[1]","bank_sel[0]","clk_buf", "vdd", "gnd"]) - - - self.width= self.data_bus_width + self.width = self.bank_inst[1].ur().x self.height = self.control_logic_inst.uy() - - def route_two_banks(self): - """ Route all of the signals for the two bank SRAM. """ + + + def route_shared_banks(self): + """ Route the shared signals for two and four bank configurations. """ # create the input control pins for n in self.control_logic_inputs: @@ -315,16 +215,264 @@ class sram(design.design): rail_pos = vector(pin_pos.x,self.horz_control_bus_positions[n].y) self.add_path("metal2",[pin_pos,rail_pos]) self.add_center_via(("metal1","via1","metal2"),rail_pos) - + # connect the control logic cross bar for n in self.control_logic_outputs: cross_pos = vector(self.vert_control_bus_positions[n].x,self.horz_control_bus_positions[n].y) self.add_center_via(("metal1","via1","metal2"),cross_pos) + + # connect the bank select signals to the vertical bus + for i in range(self.num_banks): + pin = self.bank_inst[i].get_pin("bank_sel") + pin_pos = pin.rc() if i==0 else pin.lc() + rail_pos = vector(self.vert_control_bus_positions["bank_sel[{}]".format(i)].x,pin_pos.y) + self.add_path("metal3",[pin_pos,rail_pos]) + self.add_center_via(("metal2","via2","metal3"),rail_pos) + + # connect the horizontal control bus to the vertical bus + + + def route_four_banks(self): + """ Route all of the signals for the four bank SRAM. """ + + self.route_shared_banks() + + # connect the data output to the data bus + for n in self.data_bus_names: + for i in [0,1]: + pin_pos = self.bank_inst[i].get_pin(n).bc() + rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y) + self.add_path("metal2",[pin_pos,rail_pos]) + self.add_center_via(("metal2","via2","metal3"),rail_pos) + + for i in [2,3]: + pin_pos = self.bank_inst[i].get_pin(n).uc() + rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y) + self.add_path("metal2",[pin_pos,rail_pos]) + self.add_center_via(("metal2","via2","metal3"),rail_pos) + + # route msb address bits + # route 2:4 decoder + self.route_double_msb_address() + + # connect the banks to the vertical address bus + # connect the banks to the vertical control bus + for n in self.addr_bus_names + self.control_bus_names: + # Skip these from the horizontal bus + if n in ["vdd", "gnd"]: continue + # This will be the bank select, so skip it + if n in self.msb_bank_sel_addr: continue + + for bank_id in [0,2]: + pin0_pos = self.bank_inst[bank_id].get_pin(n).rc() + pin1_pos = self.bank_inst[bank_id+1].get_pin(n).lc() + rail_pos = vector(self.vert_control_bus_positions[n].x,pin0_pos.y) + self.add_path("metal3",[pin0_pos,pin1_pos]) + self.add_center_via(("metal2","via2","metal3"),rail_pos) + + + self.route_bank_supply_rails(bottom_banks=[2,3]) + + + + + + def compute_bus_sizes(self): + """ Compute the independent bus widths shared between two and four bank SRAMs """ + + # address size + control signals + one-hot bank select signals + self.num_vertical_line = self.addr_size + self.control_size + log(self.num_banks,2) + 1 + # data bus size + self.num_horizontal_line = self.word_size + + self.vertical_bus_width = self.m2_pitch*self.num_vertical_line + # vertical bus height depends on 2 or 4 banks + + self.data_bus_height = self.m3_pitch*self.num_horizontal_line + self.data_bus_width = 2*(self.bank.width + self.bank_to_bus_distance) + self.vertical_bus_width + + self.control_bus_height = self.m1_pitch*(self.control_size+2) + self.control_bus_width = self.bank.width + self.bank_to_bus_distance + self.vertical_bus_width + + self.supply_bus_height = self.m1_pitch*2 # 2 for vdd/gnd placed with control bus + self.supply_bus_width = self.data_bus_width + + # Sanity check to ensure we can fit the control logic above a single bank (0.9 is a hack really) + debug.check(self.bank.width + self.vertical_bus_width > 0.9*self.control_logic.width, "Bank is too small compared to control logic.") + + + def compute_four_bank_offsets(self): + """ Compute the overall offsets for a four bank SRAM """ + + # The main difference is that the four bank SRAM has the data bus in the middle of the four banks + # as opposed to the top of the banks. + + self.compute_bus_sizes() + + # In 4 bank SRAM, the height is determined by the bank decoder and address flop + self.vertical_bus_height = 2*self.bank.height + 4*self.bank_to_bus_distance + self.data_bus_height \ + + self.supply_bus_height + self.msb_decoder.height + self.msb_address.width + # The address bus extends down through the power rails, but control and bank_sel bus don't + self.addr_bus_height = self.vertical_bus_height + 2*self.power_rail_pitch + + self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 2*self.power_rail_pitch) + self.data_bus_offset = vector(0, 2*self.power_rail_pitch + self.bank.height + self.bank_to_bus_distance) + self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height + self.bank.height + 2*self.bank_to_bus_distance) + self.control_bus_offset = vector(0, self.supply_bus_offset.y + self.supply_bus_height) + self.bank_sel_bus_offset = self.vertical_bus_offset + vector(self.m2_pitch*self.control_size,0) + self.addr_bus_offset = self.bank_sel_bus_offset.scale(1,0) + vector(self.m2_pitch*self.num_banks,0) + + # Control is placed at the top above the control bus and everything + self.control_logic_position = vector(0, self.control_bus_offset.y + self.control_bus_height + self.m1_pitch) + + # Bank select flops get put to the right of control logic above bank1 and the buses + # Leave a pitch to get the vdd rails up to M2 + self.msb_address_position = vector(max(self.bank.width + self.vertical_bus_width + 2*self.bank_to_bus_distance, self.control_logic.width), + self.supply_bus_offset.y + self.supply_bus_height + 2*self.m1_pitch + self.msb_address.width) + + # Decoder goes above the MSB address flops, and is flipped in Y + # separate the two by a bank to bus distance for nwell rules, just in case + self.msb_decoder_position = self.msb_address_position + vector(self.msb_decoder.width, self.bank_to_bus_distance) + + + def compute_two_bank_offsets(self): + """ Compute the overall offsets for a two bank SRAM """ + + self.compute_bus_sizes() + + # In 2 bank SRAM, the height is determined by the control bus which is higher than the msb address + self.vertical_bus_height = self.bank.height + 2*self.bank_to_bus_distance + self.data_bus_height + self.control_bus_height + # The address bus extends down through the power rails, but control and bank_sel bus don't + self.addr_bus_height = self.vertical_bus_height + 2*self.power_rail_pitch + + self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 2*self.power_rail_pitch) + self.data_bus_offset = vector(0, 2*self.power_rail_pitch + self.bank.height + self.bank_to_bus_distance) + self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height) + self.control_bus_offset = vector(0, self.supply_bus_offset.y + self.supply_bus_height) + self.bank_sel_bus_offset = self.vertical_bus_offset + vector(self.m2_pitch*self.control_size,0) + self.addr_bus_offset = self.bank_sel_bus_offset.scale(1,0) + vector(self.m2_pitch*self.num_banks,0) + + # Control is placed at the top above the control bus and everything + self.control_logic_position = vector(0, self.control_bus_offset.y + self.control_bus_height + self.m1_pitch) + + # Bank select flops get put to the right of control logic above bank1 and the buses + # Leave a pitch to get the vdd rails up to M2 + self.msb_address_position = vector(max(self.bank.width + self.vertical_bus_width + 2*self.bank_to_bus_distance,self.control_logic.width), + self.supply_bus_offset.y+self.supply_bus_height + 2*self.m1_pitch + self.msb_address.width) + + def add_busses(self): + """ Add the horizontal and vertical busses """ + # Vertical bus + # The order of the control signals on the control bus: + self.control_bus_names = ["clk_buf", "tri_en_bar", "tri_en", "clk_bar", "w_en", "s_en"] + self.vert_control_bus_positions = self.create_bus(layer="metal2", + pitch=self.m2_pitch, + offset=self.vertical_bus_offset, + names=self.control_bus_names, + length=self.vertical_bus_height, + vertical=True) + + self.addr_bus_names=["ADDR[{}]".format(i) for i in range(self.addr_size)] + self.vert_control_bus_positions.update(self.create_bus(layer="metal2", + pitch=self.m2_pitch, + offset=self.addr_bus_offset, + names=self.addr_bus_names, + length=self.addr_bus_height, + vertical=True, + make_pins=True)) + + + self.bank_sel_bus_names = ["bank_sel[{}]".format(i) for i in range(self.num_banks)] + self.vert_control_bus_positions.update(self.create_bus(layer="metal2", + pitch=self.m2_pitch, + offset=self.bank_sel_bus_offset, + names=self.bank_sel_bus_names, + length=self.vertical_bus_height, + vertical=True)) + + + # Horizontal data bus + self.data_bus_names = ["DATA[{}]".format(i) for i in range(self.word_size)] + self.data_bus_positions = self.create_bus(layer="metal3", + pitch=self.m3_pitch, + offset=self.data_bus_offset, + names=self.data_bus_names, + length=self.data_bus_width, + vertical=False, + make_pins=True) + + # Horizontal control logic bus + # vdd/gnd in bus go along whole SRAM + # FIXME: Fatten these wires? + self.horz_control_bus_positions = self.create_bus(layer="metal1", + pitch=self.m1_pitch, + offset=self.supply_bus_offset, + names=["vdd"], + length=self.supply_bus_width, + vertical=False) + # The gnd rail must not be the entire width since we protrude the right-most vdd rail up for + # the decoder in 4-bank SRAMs + self.horz_control_bus_positions.update(self.create_bus(layer="metal1", + pitch=self.m1_pitch, + offset=self.supply_bus_offset+vector(0,self.m1_pitch), + names=["gnd"], + length=self.supply_bus_width-2*self.power_rail_width, + vertical=False)) + self.horz_control_bus_positions.update(self.create_bus(layer="metal1", + pitch=self.m1_pitch, + offset=self.control_bus_offset, + names=self.control_bus_names, + length=self.control_bus_width, + vertical=False)) + + def add_two_bank_logic(self): + """ Add the control and MSB logic """ + + self.add_control_logic(position=self.control_logic_position, rotate=0) + + self.msb_address_inst = self.add_inst(name="msb_address", + mod=self.msb_address, + offset=self.msb_address_position, + rotate=270) + self.msb_bank_sel_addr = "ADDR[{}]".format(self.addr_size-1) + self.connect_inst([self.msb_bank_sel_addr,"bank_sel[1]","bank_sel[0]","clk_buf", "vdd", "gnd"]) + + def add_four_bank_logic(self): + """ Add the control and MSB decode/bank select logic for four banks """ + + + self.add_control_logic(position=self.control_logic_position, rotate=0) + + self.msb_address_inst = self.add_inst(name="msb_address", + mod=self.msb_address, + offset=self.msb_address_position, + rotate=270) + + self.msb_bank_sel_addr = ["ADDR[{}]".format(i) for i in range(self.addr_size-2,self.addr_size,1)] + temp = list(self.msb_bank_sel_addr) + temp.extend(["msb{0}[{1}]".format(j,i) for i in range(2) for j in ["","_bar"]]) + temp.extend(["clk_buf", "vdd", "gnd"]) + self.connect_inst(temp) + + self.msb_decoder_inst = self.add_inst(name="msb_decoder", + mod=self.msb_decoder, + offset=self.msb_decoder_position, + mirror="MY") + temp = ["msb[{}]".format(i) for i in range(2)] + temp.extend(["bank_sel[{}]".format(i) for i in range(4)]) + temp.extend(["vdd", "gnd"]) + self.connect_inst(temp) + + + def route_two_banks(self): + """ Route all of the signals for the two bank SRAM. """ + + self.route_shared_banks() # connect the horizontal control bus to the vertical bus # connect the data output to the data bus for n in self.data_bus_names: - for i in range(2): + for i in [0,1]: pin_pos = self.bank_inst[i].get_pin(n).uc() rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y) self.add_path("metal2",[pin_pos,rail_pos]) @@ -345,28 +493,127 @@ class sram(design.design): self.add_path("metal3",[pin0_pos,pin1_pos]) self.add_center_via(("metal2","via2","metal3"),rail_pos) - # connect the bank select signals to the vertical bus - for i in range(2): - pin = self.bank_inst[i].get_pin("bank_sel") - pin_pos = pin.rc() if i==0 else pin.lc() - rail_pos = vector(self.vert_control_bus_positions["bank_sel[{}]".format(i)].x,pin_pos.y) - self.add_path("metal3",[pin_pos,rail_pos]) + + self.route_bank_supply_rails(bottom_banks=[0,1]) + + + def route_double_msb_address(self): + """ Route two MSB address bits and the bank decoder for 4-bank SRAM """ + + + + # connect the MSB flops to the address input bus + for i in [0,1]: + msb_pins = self.msb_address_inst.get_pins("din[{}]".format(i)) + for msb_pin in msb_pins: + if msb_pin.layer == "metal3": + msb_pin_pos = msb_pin.lc() + break + rail_pos = vector(self.vert_control_bus_positions[self.msb_bank_sel_addr[i]].x,msb_pin_pos.y) + self.add_path("metal3",[msb_pin_pos,rail_pos]) self.add_center_via(("metal2","via2","metal3"),rail_pos) - - self.route_two_bank_supplies() + # Connect clk + clk_pin = self.msb_address_inst.get_pin("clk") + clk_pos = clk_pin.bc() + rail_pos = self.horz_control_bus_positions["clk_buf"] + bend_pos = vector(clk_pos.x,self.horz_control_bus_positions["clk_buf"].y) + self.add_path("metal1",[clk_pos,bend_pos,rail_pos]) - def route_two_bank_supplies(self): - """ Finish routing the power supplies for a 2-bank SRAM """ - # control logic supplies done with control signals - + # Connect bank decoder outputs to the bank select vertical bus wires + for i in range(self.num_banks): + msb_pin = self.msb_decoder_inst.get_pin("out[{}]".format(i)) + msb_pin_pos = msb_pin.lc() + rail_pos = vector(self.vert_control_bus_positions["bank_sel[{}]".format(i)].x,msb_pin_pos.y) + self.add_path("metal1",[msb_pin_pos,rail_pos]) + self.add_center_via(("metal1","via1","metal2"),rail_pos) - self.route_major_supply_rails() + # connect MSB flop outputs to the bank decoder inputs + msb_pin = self.msb_address_inst.get_pin("dout[0]") + msb_pin_pos = msb_pin.rc() + in_pin = self.msb_decoder_inst.get_pin("in[0]") + in_pos = in_pin.bc() + vector(0,1*self.m2_pitch,) # pin is up from bottom + out_pos = msb_pin_pos + vector(1*self.m2_pitch,0) # route out to the right + up_pos = vector(out_pos.x,in_pos.y) # and route up to the decoer + self.add_wire(("metal1","via1","metal2"),[msb_pin_pos,out_pos,up_pos,in_pos]) + self.add_center_via(("metal1","via1","metal2"),in_pos) + self.add_center_via(("metal1","via1","metal2"),msb_pin_pos,rotate=90) + msb_pin = self.msb_address_inst.get_pin("dout[1]") + msb_pin_pos = msb_pin.rc() + in_pin = self.msb_decoder_inst.get_pin("in[1]") + in_pos = in_pin.bc() + vector(0,self.bitcell.height+self.m2_pitch) # route the next row up + out_pos = msb_pin_pos + vector(2*self.m2_pitch,0) # route out to the right + up_pos = vector(out_pos.x,in_pos.y) # and route up to the decoer + self.add_wire(("metal1","via1","metal2"),[msb_pin_pos,out_pos,up_pos,in_pos]) + self.add_center_via(("metal1","via1","metal2"),in_pos) + self.add_center_via(("metal1","via1","metal2"),msb_pin_pos,rotate=90) + + # Route the right-most vdd/gnd of the right upper bank to the top of the decoder + vdd_pins = self.bank_inst[1].get_pins("vdd") + highest_x = None + for bank_vdd_pin in vdd_pins: + if highest_x == None or bank_vdd_pin.lx()>highest_x: + highest_x = bank_vdd_pin.lx() + bank_vdd_pos = bank_vdd_pin.ul() + # Route to top + self.add_rect(layer="metal1", + offset=bank_vdd_pos, + height=self.height-bank_vdd_pos.y, + width=bank_vdd_pin.width()) + gnd_pins = self.bank_inst[1].get_pins("gnd") + highest_x = None + for bank_gnd_pin in gnd_pins: + if highest_x == None or bank_gnd_pin.lx()>highest_x: + highest_x = bank_gnd_pin.lx() + bank_gnd_pos = bank_gnd_pin.ul() + # Route to top + self.add_rect(layer="metal2", + offset=bank_gnd_pos, + height=self.height-bank_gnd_pos.y, + width=bank_gnd_pin.width()) + + # Connect bank decoder vdd/gnd supplies using the previous bank_vdd_pos and bank_gnd_pos + vdd_pins = self.msb_decoder_inst.get_pins("vdd") + for vdd_pin in vdd_pins: + if vdd_pin.layer != "metal1": continue + vdd_pos = vdd_pin.rc() + rail_pos = vector(bank_vdd_pos.x+bank_vdd_pin.width(),vdd_pos.y) + self.add_path("metal1",[vdd_pos,rail_pos]) + gnd_pins = self.msb_decoder_inst.get_pins("gnd") + for gnd_pin in gnd_pins: + if gnd_pin.layer != "metal1": continue + gnd_pos = gnd_pin.rc() + rail_pos = vector(bank_gnd_pos.x+bank_gnd_pin.width(),gnd_pos.y) + self.add_path("metal1",[gnd_pos,rail_pos]) + self.add_via(("metal1","via1","metal2"),rail_pos- vector(0,0.5*self.m1_width),rotate=90,size=[1,3]) + + # connect the bank MSB flop supplies + vdd_pins = self.msb_address_inst.get_pins("vdd") + # vdd pins go down to the rail + for vdd_pin in vdd_pins: + if vdd_pin.layer != "metal1": continue + vdd_pos = vdd_pin.bc() + down_pos = vdd_pos - vector(0,self.m1_pitch) + rail_pos = vector(vdd_pos.x,self.horz_control_bus_positions["vdd"].y) + self.add_path("metal1",[vdd_pos,down_pos]) + self.add_center_via(("metal1","via1","metal2"),down_pos,rotate=90) + self.add_path("metal2",[down_pos,rail_pos]) + self.add_center_via(("metal1","via1","metal2"),rail_pos) + # gnd pins go right to the rail + gnd_pins = self.msb_address_inst.get_pins("gnd") + for gnd_pin in gnd_pins: + if gnd_pin.layer != "metal2": continue + gnd_pos = gnd_pin.rc() + rail_pos = vector(bank_gnd_pos.x+bank_gnd_pin.width(),gnd_pos.y) + self.add_path("metal1",[gnd_pos,rail_pos]) + self.add_center_via(("metal1","via1","metal2"),gnd_pos,rotate=90) + self.add_via(("metal1","via1","metal2"),rail_pos- vector(0,0.5*self.m1_width),rotate=90,size=[1,3]) + def route_single_msb_address(self): """ Route one MSB address bit for 2-bank SRAM """ - + # connect the bank MSB flop supplies vdd_pins = self.msb_address_inst.get_pins("vdd") for vdd_pin in vdd_pins: @@ -430,7 +677,8 @@ class sram(design.design): self.add_path("metal1",[clk_pos,bend_pos,rail_pos]) - def route_major_supply_rails(self): + + def route_bank_supply_rails(self, bottom_banks): """ Create rails at bottom. Connect veritcal rails to top and bottom. """ self.add_layout_pin(text="gnd", @@ -445,58 +693,45 @@ class sram(design.design): height=self.power_rail_width, width=self.width) - # route bank vertical rails to top and bottom - for i in range(2): + + # route bank vertical rails to bottom + for i in bottom_banks: vdd_pins = self.bank_inst[i].get_pins("vdd") for vdd_pin in vdd_pins: vdd_pos = vdd_pin.ul() - # Route to top - self.add_rect(layer="metal1", - offset=vdd_pos, - height=self.horz_control_bus_positions["vdd"].y-vdd_pos.y+0.5*self.m1_width, - width=vdd_pin.width()) # Route to bottom self.add_rect(layer="metal1", offset=vector(vdd_pos.x,self.power_rail_pitch), - height=self.bank_inst[0].by(), + height=self.horz_control_bus_positions["vdd"].y-self.power_rail_pitch, width=vdd_pin.width()) gnd_pins = self.bank_inst[i].get_pins("gnd") for gnd_pin in gnd_pins: - # Route to top - gnd_pos = gnd_pin.ul() + gnd_pos = gnd_pin.ul() + # Route to bottom self.add_rect(layer="metal2", - offset=gnd_pos, - height=self.horz_control_bus_positions["gnd"].y-gnd_pos.y+0.5*self.m1_width, + offset=vector(gnd_pos.x,0), + height=self.horz_control_bus_positions["gnd"].y, # route to the top bank width=gnd_pin.width()) - # Add two vias for right now, should be right size power via + # Add vias at top right_rail_pos = vector(gnd_pin.ur().x,self.horz_control_bus_positions["gnd"].y) self.add_via(layers=("metal1","via1","metal2"), offset=right_rail_pos - vector(0,0.5*self.m1_width), rotate=90, size=[1,3]) - - # Route to bottom - self.add_rect(layer="metal2", - offset=vector(gnd_pos.x,0), - height=self.bank_inst[0].by(), - width=gnd_pin.width()) - # Add two vias for right now, should be right size power via + # Add vias at bottom right_rail_pos = vector(gnd_pin.lr().x,0) self.add_via(layers=("metal2","via2","metal3"), offset=right_rail_pos, rotate=90, size=[2,3]) - # connect the vertical rails along bottom of SRAM - pass def create_multi_bank_modules(self): """ Create the multibank address flops and bank decoder """ - self.msb_address = self.mod_ms_flop_array(name="msb_address", - columns=1, + columns=self.num_banks/2, word_size=self.num_banks/2) self.add_mod(self.msb_address) @@ -673,145 +908,39 @@ class sram(design.design): self.copy_layout_pin(self.bank_inst, "gnd") - def add_top_banks(self): - # Placement of bank 0 - self.bank_position_0 = vector(self.bank.width, - self.bank.height + 2*self.power_rail_pitch) - self.bank_inst=[self.add_bank(0,self.bank_position_0, -1, -1)] + def add_two_banks(self): + # Placement of bank 0 (left) + bank_position_0 = vector(self.bank.width, + self.bank.height + 2*self.power_rail_pitch) + self.bank_inst=[self.add_bank(0, bank_position_0, -1, -1)] - # Placement of bank 1 + # Placement of bank 1 (right) x_off = self.bank.width + self.vertical_bus_width + 2*self.bank_to_bus_distance - self.bank_position_1 = vector(x_off, self.bank_position_0.y) - self.bank_inst.append(self.add_bank(1,self.bank_position_1, -1, 1)) + bank_position_1 = vector(x_off, bank_position_0.y) + self.bank_inst.append(self.add_bank(1, bank_position_1, -1, 1)) - def add_bottom_banks(self): - # Placement of bank 2 - y_off = self.bank.height + self.horizontal_bus_width + 2*self.bank_to_bus_distance + self.power_rail_pitch - bank_position_2 = vector(self.bank_position_0.x, y_off) - self.bank2=self.add_bank(bank_position_2, 1, -1) - # Placement of bank 3 - bank_position_3 = vector(self.bank_position_1.x, bank_position_2.y) - self.bank3=self.add_bank(bank_position_3, 1, 1) + def add_four_banks(self): - self.msb_decoder_position = vector(bank_position_3.x + self.power_rail_width + 4*drc["minwidth_metal3"] + self.msb_decoder.width, - self.msf_msb_address_position.y + 4*drc["minwidth_metal3"]) + # Placement of bank 0 (upper left) + bank_position_0 = vector(self.bank.width, + self.bank.height + self.data_bus_height + 2*self.bank_to_bus_distance + 2*self.power_rail_pitch) + self.bank_inst=[self.add_bank(0, bank_position_0, 1, -1)] - self.add_inst(name="msb_decoder", - mod=self.msb_decoder, - offset=self.msb_decoder_position, - mirror="MY") - temp = ["msb0", "msb1"] - for i in range(4): - temp.append("bank_sel[{}]".format(i)) - temp.extend(["vdd", "gnd"]) - self.connect_inst(temp) + # Placement of bank 1 (upper right) + x_off = self.bank.width + self.vertical_bus_width + 2*self.bank_to_bus_distance + bank_position_1 = vector(x_off, bank_position_0.y) + self.bank_inst.append(self.add_bank(1, bank_position_1, 1, 1)) + + # Placement of bank 2 (bottom left) + y_off = self.bank.height + 2*self.power_rail_pitch + bank_position_2 = vector(bank_position_0.x, y_off) + self.bank_inst.append(self.add_bank(2, bank_position_2, -1, -1)) + + # Placement of bank 3 (bottom right) + bank_position_3 = vector(bank_position_1.x, bank_position_2.y) + self.bank_inst.append(self.add_bank(3, bank_position_3, -1, 1)) - self.control_position = vector(0, self.msb_decoder_position.y + self.msb_decoder.height) - self.add_control_logic(self.control_position, 0) - - # Max point - self.max_point = self.msb_decoder_position.y + self.msb_decoder.height - - - def route_2or4_banks(self): - """ Routing of top two banks """ - return - addr_start_index = len(self.sram_property) + self.num_banks/2 - bank_select_index = addr_start_index + self.bank.addr_size - - # control, data , address and bank_select connection - for i in range(self.num_banks / 2): - left_bank_index = 2*i - right_bank_index = 2*i + 1 - - for attr_index in range(len(self.sram_property)): - bank_attr = self.sram_property[attr_index] - self.add_rect(layer="metal3", - offset=getattr(self,bank_attr)[left_bank_index], - width=getattr(self,bank_attr)[right_bank_index].x - getattr(self,bank_attr)[left_bank_index].x, - height=drc["minwidth_metal3"]) - self.add_via(layers=("metal2", "via2", "metal3"), - offset=[self.vertical_line_positions[attr_index].x, - getattr(self,bank_attr)[left_bank_index].y]) - - for addr_index in range(self.bank.addr_size): - line_index = addr_start_index + addr_index - self.add_rect(layer="metal3", - offset=self.sram_bank_adress_positions[left_bank_index][addr_index], - width=self.sram_bank_adress_positions[right_bank_index][addr_index].x \ - - self.sram_bank_adress_positions[left_bank_index][addr_index].x, - height=drc["minwidth_metal3"]) - self.add_via(layers=("metal2", "via2", "metal3"), - offset=[self.vertical_line_positions[line_index].x, - self.sram_bank_adress_positions[left_bank_index][addr_index].y]) - - # left bank_select - self.add_rect(layer="metal3", - offset=self.sram_bank_select_positions[left_bank_index], - width=self.vertical_line_positions[bank_select_index + left_bank_index].x \ - - self.sram_bank_select_positions[left_bank_index].x, - height=drc["minwidth_metal3"]) - self.add_via(layers=("metal2", "via2", "metal3"), - offset=[self.vertical_line_positions[bank_select_index + left_bank_index].x, - self.sram_bank_select_positions[left_bank_index].y]) - - # right bank select - x_off = self.vertical_line_positions[bank_select_index + right_bank_index].x - contact_offset = vector(x_off, - self.sram_bank_select_positions[right_bank_index].y) - - self.add_rect(layer="metal3", - offset=contact_offset, - width=self.sram_bank_select_positions[right_bank_index].x \ - - contact_offset.x, - height=drc["minwidth_metal3"]) - self.add_via(layers=("metal2", "via2", "metal3"), - offset=contact_offset) - - # Data connection on the horizontal bus - if self.num_banks == 4: - data_connection_top = self.sram_bank_data_positions[2][0].y + self.m2m3_via.height - else: - data_connection_top=self.horizontal_bus_offset.y - - data_connection_height = data_connection_top - self.sram_bank_data_positions[0][0].y - - for i in range(2): - lower_bank_index = i - upper_bank_index = i + 2 - - for data_index in range(self.bank.word_size): - line_index = addr_start_index + addr_index - self.add_rect(layer="metal2", - offset=self.sram_bank_data_positions[lower_bank_index][data_index], - width=drc["minwidth_metal2"], - height=data_connection_height) - self.add_via(layers=("metal2", "via2", "metal3"), - offset=[self.sram_bank_data_positions[lower_bank_index][data_index].x, - self.horizontal_line_positions[data_index].y]) - - def route_bottom_banks(self): - for i in range(2): - lower_bank_index = i - upper_bank_index = i + 2 - - # Power rail connections - self.add_rect(layer="metal1", - offset=self.sram_bank_right_vdd_positions[lower_bank_index], - width=self.power_rail_width, - height=self.sram_bank_right_vdd_positions[upper_bank_index].y \ - - self.sram_bank_right_vdd_positions[lower_bank_index].y) - self.add_rect(layer="metal1", - offset=self.sram_bank_left_vdd_positions[lower_bank_index], - width=self.power_rail_width, - height=self.sram_bank_left_vdd_positions[upper_bank_index].y \ - - self.sram_bank_left_vdd_positions[lower_bank_index].y) - self.add_rect(layer="metal2", - offset=self.sram_bank_left_gnd_positions[lower_bank_index], - width=self.power_rail_width, - height=self.sram_bank_left_gnd_positions[upper_bank_index].y \ - - self.sram_bank_left_gnd_positions[lower_bank_index].y) def connect_rail_from_left_m2m3(self, src_pin, dest_pin): """ Helper routine to connect an unrotated/mirrored oriented instance to the rails """ @@ -849,361 +978,6 @@ class sram(design.design): dest_pin = self.bank_inst.get_pin("gnd") self.connect_rail_from_left_m2m3(src_pin,dest_pin) - def route_bank_and_control(self): - """ Routing between banks and control """ - - if self.num_banks == 1: - pass - elif self.num_banks == 2 or self.num_banks == 4: - for i in range(self.control_size): - self.add_via(layers=("metal1", "via1", "metal2"), - offset=[self.vertical_line_positions[i].x + drc["minwidth_metal2"], - self.control_bus_line_positions[i].y], - rotate=90) - control_attr = self.bank_property[i] - control_side_line_position = (getattr(self.control,control_attr) - +self.control_position) - - self.add_rect(layer="metal2", - offset=[control_side_line_position.x, - self.control_bus_line_positions[i].y], - width=drc["minwidth_metal2"], - height=control_side_line_position.y - - self.control_bus_line_positions[i].y) - self.add_via(layers=("metal1", "via1", "metal2"), - offset=[control_side_line_position.x - + drc["minwidth_metal2"], - self.control_bus_line_positions[i].y], - rotate=90) - for i in range(self.num_banks/2): - # MSB line connections - msb_line = self.control_size + self.num_banks/2 - 1 - i - bank_select_start_line = msb_line + 2 + self.bank_addr_size - - msf_msb_din = (self.msf_msb_address.din_positions[i].rotate_scale(1, -1) - + self.msf_msb_address_position) - - contact_pos = vector(self.vertical_line_positions[msb_line].x, - msf_msb_din.y - 0.5*self.m2m3_via.width) - self.add_rect(layer="metal3", - offset=contact_pos, - width=msf_msb_din.x - contact_pos.x, - height=drc["minwidth_metal3"]) - self.add_via(layers=("metal2", "via2", "metal3"), - offset=contact_pos) - - # msf_msb_address clk connection - self.add_rect(layer="metal1", - offset=[self.vertical_line_positions[0].x, - self.control_bus_line_positions[0].y], - width=self.msf_msb_address_position.x - + self.msf_msb_address.clk_positions[0].y - - self.vertical_line_positions[0].x, - height=drc["minwidth_metal1"]) - - if(self.num_banks == 2): - msb_msf_dout_position = (self.msf_msb_address.dout_positions[i].rotate_scale(1, -1) - + self.msf_msb_address_position) - msb_msf_dout_bar_position = (self.msf_msb_address.dout_bar_positions[i].rotate_scale(1, -1) - + self.msf_msb_address_position) - starts = [msb_msf_dout_bar_position, - msb_msf_dout_position] - - for i in range(2): - bank_select_line = (self.control_size + 1 - + self.bank_addr_size + i) - - start = starts[i] - mid1 = vector(self.msf_msb_address_position.x - + self.msf_msb_address.height - + 4 * (i + 1) * drc["minwidth_metal2"], - start.y) - end = vector(mid1.x, self.msf_msb_address_position.y - + 4 * (i + 1) * drc["minwidth_metal2"]) - self.add_wire(("metal2", "via1", "metal1"), [start, mid1, end]) - - x_off = self.vertical_line_positions[bank_select_line].x - contact_pos = vector(x_off, - end.y - drc["minwidth_metal1"]) - self.add_rect(layer="metal1", - offset=contact_pos, - width=end.x - contact_pos.x - + 0.5 * drc["minwidth_metal1"], - height=drc["minwidth_metal1"]) - self.add_via(layers=("metal1", "via1", "metal2"), - offset=contact_pos) - - if(self.num_banks == 4): - for i in range(2): - msb_msf_out_position = (self.msf_msb_address.dout_positions[i].rotate_scale(1, -1) - + self.msf_msb_address_position) - msb_decoder_in_position =(self.msb_decoder.A_positions[i].scale(-1, 1) - + self.msb_decoder_position - + vector(0, 0.5 * drc["minwidth_metal1"])) - - start = msb_msf_out_position - mid1 = start + vector(4 * (i + 1) * drc["minwidth_metal1"], 0) - mid2 = vector(mid1.x, msb_decoder_in_position.y) - end = vector(self.msb_decoder_position.x - + 3*drc["minwidth_metal3"], - mid2.y) - - layer_stack = ("metal2", "via1", "metal1") - self.add_wire(layer_stack, [start, mid1, mid2, end]) - - self.add_rect(layer="metal1", - offset=[msb_decoder_in_position.x, - msb_decoder_in_position.y - 0.5 * drc["minwidth_metal1"]], - width=end.x - msb_decoder_in_position.x, - height=drc["minwidth_metal1"]) - self.add_via(layers=("metal1", "via1", "metal2"), - offset=end - vector(0, 0.5 * self.m1m2_via.width), - rotate=90) - for i in range(4): - bank_select_line = self.control_size + 2 + self.bank_addr_size + i - msb_decoder_out = (self.msb_decoder_position - + self.msb_decoder.decode_out_positions[i].scale(-1, 1) - + vector(0, 0.5*drc["minwidth_metal1"])) - - x_off = self.vertical_line_positions[bank_select_line].x - contact_pos = vector(x_off, - msb_decoder_out.y - 0.5*drc["minwidth_metal1"]) - self.add_rect(layer="metal1", - offset=contact_pos, - width=msf_msb_din.x - contact_pos.x, - height=drc["minwidth_metal1"]) - self.add_via(layers=("metal1", "via1", "metal2"), - offset=contact_pos) - - - def route_vdd_multi_bank(self): - """ Route the vdd for 2 and 4 bank SRAMs """ - # VDD routing between banks - self.add_rect(layer="metal1", - offset=self.vdd_position, - width=self.width, - height=self.power_rail_width) - for bank_index in range(2): - self.add_rect(layer="metal1", - offset=[self.sram_bank_right_vdd_positions[bank_index].x, - self.vdd_position.y], - width=self.power_rail_width, - height=self.sram_bank_right_vdd_positions[bank_index].y - - self.vdd_position.y) - self.add_rect(layer="metal1", - offset=[self.sram_bank_left_vdd_positions[bank_index].x, - self.vdd_position.y], - width=self.power_rail_width, - height=self.sram_bank_left_vdd_positions[bank_index].y - - self.vdd_position.y) - - # VDD routing to control - control_vdd_supply = self.control_bus_line_positions[self.control_size + 1] - control_vdd1_position = self.control_position + self.control.vdd1_position - control_vdd2_position = self.control_position + self.control.vdd2_position - - # rail extension - self.add_rect(layer="metal1", - offset=self.sram_bank_right_vdd_positions[0], - width=self.power_rail_width, - height=control_vdd_supply.y - - self.sram_bank_right_vdd_positions[0].y) - - # Control vdd1 - if (self.control.width <= self.bank.width): - self.add_rect(layer="metal2", - offset=[control_vdd1_position.x, - control_vdd_supply.y], - width=drc["minwidth_metal2"], - height=control_vdd1_position.y - - control_vdd_supply.y) - self.add_via(layers=("metal1", "via1", "metal2"), - offset=control_vdd1_position) - self.add_via(layers=("metal1", "via1", "metal2"), - offset=[control_vdd1_position.x + drc["minwidth_metal2"], - control_vdd_supply.y], - rotate=90) - - if (self.control.width > self.bank.width): - last_bank = self.num_banks - 1 - self.add_rect(layer="metal1", - offset=control_vdd1_position, - width=self.sram_bank_right_vdd_positions[last_bank].x - - control_vdd1_position.x, - height=drc["minwidth_metal2"]) - self.add_rect(layer="metal1", - offset=self.sram_bank_right_vdd_positions[last_bank], - width=10*drc["minwidth_metal2"], - height=control_vdd1_position.y - - self.sram_bank_right_vdd_positions[last_bank].y - + drc["minwidth_metal2"]) - - # Control vdd2 - self.add_via(layers=("metal1", "via1", "metal2"), - offset=[control_vdd2_position.x - + drc["minwidth_metal2"], - control_vdd_supply.y], - rotate=90) - - self.add_layout_pin(text="vdd", - layer="metal2", - offset=[control_vdd2_position.x, - control_vdd_supply.y], - width=drc["minwidth_metal2"], - height=control_vdd2_position.y - - control_vdd_supply.y) - - # msf_msb_address - start = msf_address_vdd_position = (self.msf_msb_address_position - + self.msf_msb_address.vdd_positions[0].rotate_scale(1,-1)) - mid1 = vector(start.x, - self.msf_msb_address_position.y - - self.msf_msb_address.width - - 2*drc["minwidth_metal3"]) - end = vector(self.sram_bank_left_vdd_positions[1].x, - mid1.y) - - self.add_path("metal1", [start, mid1, end]) - - # rail extension - self.add_rect(layer="metal1", - offset=self.sram_bank_left_vdd_positions[1], - width=self.power_rail_width, - height=end.y - self.sram_bank_left_vdd_positions[1].y) - - if(self.num_banks == 4): - # msf_msb and msb_decoder VDD - start = (self.msb_decoder_position - + self.msb_decoder.vdd_position.scale(-1, 1) - + vector(0, 0.5*drc["minwidth_metal1"])) - mid1 = vector(msf_address_vdd_position.x, - start.y) - end = msf_address_vdd_position - - self.add_path("metal1", [start, mid1, end]) - - # Add vdd labels to horizotal and vertical lines - self.add_label(text="vdd", - layer="metal1", - offset=self.vdd_position) - self.add_label(text="vdd", - layer="metal1", - offset=[self.sram_bank_left_vdd_positions[0].x, - self.vdd_position.y]) - self.add_label(text="vdd", - layer="metal1", - offset=[self.sram_bank_left_vdd_positions[1].x, - self.vdd_position.y]) - self.add_label(text="vdd", - layer="metal1", - offset=[self.sram_bank_right_vdd_positions[1].x, - self.vdd_position.y]) - - - - def route_gnd_multi_bank(self): - """ Route the gnd for 2 and 4 bank SRAMs """ - self.add_rect(layer="metal2", - offset=self.gnd_position, - width=self.width, - height=self.power_rail_width) - - for bank_index in range(2): - self.add_rect(layer="metal2", - offset=[self.sram_bank_left_gnd_positions[bank_index].x, - self.gnd_position.y], - width=self.power_rail_width, - height=self.sram_bank_left_gnd_positions[bank_index].y - - self.gnd_position.y) - - # gnd routing to control - control_gnd_supply = self.control_bus_line_positions[self.control_size] - control_gnd_position = self.control_position + self.control.gnd_position - - # rail extension - self.add_rect(layer="metal2", - offset=self.sram_bank_left_gnd_positions[0], - width=drc["minwidth_metal2"], - height=control_gnd_supply.y + drc["minwidth_metal1"] - - self.sram_bank_left_gnd_positions[0].y) - self.add_via(layers=("metal1", "via1", "metal2"), - offset=[self.sram_bank_left_gnd_positions[0].x - + drc["minwidth_metal2"], - control_gnd_supply.y], - rotate=90) - # Control gnd - self.add_via(layers=("metal1", "via1", "metal2"), - offset=[control_gnd_position.x + drc["minwidth_metal2"], - control_gnd_supply.y], - rotate=90) - self.add_layout_pin(text="gnd", - layer="metal2", - offset=[control_gnd_position.x, - control_gnd_supply.y], - width=drc["minwidth_metal2"], - height=control_gnd_position.y - - control_gnd_supply.y) - - # msf_msb_address , msb_decoder gnd - - # left gnd rail extension of bank3 - self.add_rect(layer="metal2", - offset=self.sram_bank_left_gnd_positions[1], - width=self.power_rail_width, - height=self.max_point - - self.sram_bank_left_gnd_positions[1].y) - - for p in self.msf_msb_address.gnd_positions: - gnd_position = vector(self.msf_msb_address_position.x - + self.msf_msb_address.height, - self.msf_msb_address_position.y - - p.x - 0.5*drc["minwidth_metal2"]) - self.add_rect(layer="metal2", - offset=gnd_position, - width=(self.sram_bank_left_gnd_positions[1].x - - gnd_position.x), - height=drc["minwidth_metal2"]) - - if(self.num_banks == 4): - # msb Decoder - msb_decoder_gnd_position = (self.msb_decoder_position - + self.msb_decoder.gnd_position.scale(-1,1)) - self.add_rect(layer="metal1", - offset=msb_decoder_gnd_position, - width=self.sram_bank_left_gnd_positions[3].x \ - - msb_decoder_gnd_position.x \ - + self.power_rail_width, - height=drc["minwidth_metal1"]) - - self.add_via(layers=("metal1", "via1", "metal2"), - offset=[self.sram_bank_left_gnd_positions[3].x, - msb_decoder_gnd_position.y + drc["minwidth_metal1"]], - mirror="MX", - size=(2,1)) - - # Add gnd labels to horizotal and vertical lines - self.add_label(text="gnd", - layer="metal2", - offset=self.gnd_position) - self.add_label(text="gnd", - layer="metal2", - offset=[self.sram_bank_left_gnd_positions[0].x, - 0]) - self.add_label(text="gnd", - layer="metal2", - offset=[self.sram_bank_left_gnd_positions[1].x, - 0]) - - def route_supplies(self): - """ vdd/gnd routing of all modules """ - return - if (self.num_banks == 1): - pass - elif (self.num_banks == 2 or self.num_banks == 4): - self.route_vdd_multi_bank() - self.route_gnd_multi_bank() - else: - debug.error("Incorrect number of banks.") def sp_write(self, sp_name): @@ -1215,10 +989,10 @@ class sram(design.design): sp.write("* OpenRAM generated memory.\n") # This causes unit test mismatch - #sp.write("* Created: {0}\n".format(datetime.datetime.now())) - sp.write("* User: {0}\n".format(getpass.getuser())) - sp.write(".global {0} {1}\n".format(spice["vdd_name"], - spice["gnd_name"])) + # sp.write("* Created: {0}\n".format(datetime.datetime.now())) + # sp.write("* User: {0}\n".format(getpass.getuser())) + # sp.write(".global {0} {1}\n".format(spice["vdd_name"], + # spice["gnd_name"])) usedMODS = list() self.sp_write_file(sp, usedMODS) del usedMODS diff --git a/compiler/tests/20_sram_4bank_test.py b/compiler/tests/20_sram_4bank_test.py index 45dda0e9..05c9df35 100644 --- a/compiler/tests/20_sram_4bank_test.py +++ b/compiler/tests/20_sram_4bank_test.py @@ -26,15 +26,15 @@ class sram_4bank_test(unittest.TestCase): import sram debug.info(1, "Four bank, no column mux with control logic") - a = sram.sram(word_size=4, num_words=32, num_banks=4, name="sram1") + a = sram.sram(word_size=16, num_words=64, num_banks=4, name="sram1") self.local_check(a) debug.info(1, "Four bank two way column mux with control logic") - a = sram.sram(word_size=4, num_words=64, num_banks=4, name="sram2") + a = sram.sram(word_size=16, num_words=128, num_banks=4, name="sram2") self.local_check(a) debug.info(1, "Four bank, four way column mux with control logic") - a = sram.sram(word_size=4, num_words=128, num_banks=4, name="sram3") + a = sram.sram(word_size=16, num_words=256, num_banks=4, name="sram3") self.local_check(a) # debug.info(1, "Four bank, eight way column mux with control logic")