From f0958b0b118a6181705bd97dc18098f345e8719a Mon Sep 17 00:00:00 2001 From: jcirimel Date: Wed, 18 Dec 2019 03:03:13 -0800 Subject: [PATCH 01/65] squashed update of pex progress due to timezone error --- compiler/base/geometry.py | 102 +++++++++++- compiler/base/hierarchy_layout.py | 2 + compiler/bitcells/bitcell_base.py | 35 ++++- compiler/bitcells/pbitcell.py | 19 ++- compiler/characterizer/delay.py | 8 +- compiler/characterizer/stimuli.py | 5 + compiler/modules/bank.py | 5 +- compiler/modules/control_logic.py | 4 +- compiler/sram/sram_base.py | 38 +++++ compiler/verify/magic.py | 44 +++--- technology/scn4m_subm/mag_lib/cell_1rw_1r.mag | 137 ++++++++-------- technology/scn4m_subm/mag_lib/cell_1w_1r.mag | 137 ++++++++-------- technology/scn4m_subm/mag_lib/cell_6t.mag | 116 +++++++------- .../scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag | 143 +++++++++-------- .../scn4m_subm/mag_lib/dummy_cell_1w_1r.mag | 143 +++++++++-------- .../scn4m_subm/mag_lib/dummy_cell_6t.mag | 112 ++++++------- .../mag_lib/replica_cell_1rw_1r.mag | 147 +++++++++--------- .../scn4m_subm/mag_lib/replica_cell_1w_1r.mag | 147 +++++++++--------- .../scn4m_subm/mag_lib/replica_cell_6t.mag | 116 +++++++------- 19 files changed, 813 insertions(+), 647 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 74b02f5f..1c037fdf 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -12,6 +12,8 @@ import debug from vector import vector import tech import math +import copy +import numpy as np from globals import OPTS from utils import round_to_grid @@ -221,9 +223,8 @@ class instance(geometry): self.mirror = mirror self.rotate = rotate self.update_boundary() - debug.info(3, "placing instance {}".format(self)) - - + debug.info(3, "placing instance {}".format(self)) + def get_pin(self,name,index=-1): """ Return an absolute pin that is offset and transformed based on this instance location. Index will return one of several pins.""" @@ -241,20 +242,109 @@ class instance(geometry): def get_num_pins(self, name): """ Return the number of pins of a given name """ return len(self.mod.get_pins(name)) - + def get_pins(self,name): """ Return an absolute pin that is offset and transformed based on this instance location. """ - + import copy pin = copy.deepcopy(self.mod.get_pins(name)) - + new_pins = [] for p in pin: p.transform(self.offset,self.mirror,self.rotate) new_pins.append(p) return new_pins + + def reverse_bitcell_transformation(self): + path = [] + bitcell_paths = [] + pex_offsets = [] + Q_offsets = [] + Q_bar_offsets = [] + + def walk_subtree(node): + path.append(node) + + if node.mod.name == 'pbitcell': + bitcell_paths.append(copy.copy(path)) + + Q_x = node.mod.get_normalized_storage_net_offset()[0][0] + Q_y = node.mod.get_normalized_storage_net_offset()[0][1] + + Q_bar_x = node.mod.get_normalized_storage_net_offset()[1][0] + Q_bar_y = node.mod.get_normalized_storage_net_offset()[1][1] + + if node.mirror == 'MX': + Q_y = -1 * Q_y + Q_bar_y = -1 * Q_bar_y + + Q_offsets.append([Q_x, Q_y]) + Q_bar_offsets.append([Q_bar_x, Q_bar_y]) + + + elif node.mod.insts is not []: + for instance in node.mod.insts: + walk_subtree(instance) + path.pop(-1) + + def calculate_transform(node): + #set up the rotation matrix + angle = math.radians(float(node.rotate)) + mRotate = np.array([[math.cos(angle),-math.sin(angle),0.0], + [math.sin(angle),math.cos(angle),0.0], + [0.0,0.0,1.0]]) + + #set up translation matrix + translateX = float(node.offset[0]) + translateY = float(node.offset[1]) + mTranslate = np.array([[1.0,0.0,translateX], + [0.0,1.0,translateY], + [0.0,0.0,1.0]]) + + #set up the scale matrix (handles mirror X) + scaleX = 1.0 + if(node.mirror == 'MX'): + scaleY = -1.0 + else: + scaleY = 1.0 + mScale = np.array([[scaleX,0.0,0.0], + [0.0,scaleY,0.0], + [0.0,0.0,1.0]]) + + return (mRotate, mScale, mTranslate) + + def apply_transform(mtransforms, uVector, vVector, origin): + origin = np.dot(mtransforms[0], origin) #rotate + uVector = np.dot(mtransforms[0], uVector) #rotate + vVector = np.dot(mtransforms[0], vVector) #rotate + origin = np.dot(mtransforms[1], origin) #scale + uVector = np.dot(mtransforms[1], uVector) #scale + vVector = np.dot(mtransforms[1], vVector) #scale + origin = np.dot(mtransforms[2], origin) + + return(uVector, vVector, origin) + + def apply_path_transform(path): + uVector = np.array([[1.0],[0.0],[0.0]]) + vVector = np.array([[0.0],[1.0],[0.0]]) + origin = np.array([[0.0],[0.0],[1.0]]) + + while(path): + instance = path.pop(-1) + mtransforms = calculate_transform(instance) + (uVector, vVector, origin) = apply_transform(mtransforms, uVector, vVector, origin) + + return (uVector, vVector, origin) + + walk_subtree(self) + for path in bitcell_paths: + vector_spaces = apply_path_transform(path) + origin = vector_spaces[2] + pex_offsets.append([origin[0], origin[1]]) + return(pex_offsets, Q_offsets, Q_bar_offsets) + def __str__(self): """ override print function output """ return "( inst: " + self.name + " @" + str(self.offset) + " mod=" + self.mod.name + " " + self.mirror + " R=" + str(self.rotate) + ")" diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 2fea5c61..ae288d2e 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -1124,6 +1124,8 @@ class layout(): pdf.drawLayout() pdf.writeToFile(pdf_name) + + def print_attr(self): """Prints a list of attributes for the current layout object""" debug.info(0, diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 5265904b..ea394548 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -8,6 +8,7 @@ import debug import design +from globals import OPTS import logical_effort from tech import parameter, drc @@ -78,7 +79,39 @@ class bitcell_base(design.design): fmt_str = "Storage nodes={} not found in spice file." debug.info(1, fmt_str.format(self.storage_nets)) return None - + + def get_storage_net_offset(self): + """ + Gets the location of the storage net labels to add top level + labels for pex simulation. + """ + #TODO: use getTexts to support custom bitcells + # If we generated the bitcell, we already know where Q and Q_bar are + #if OPTS.bitcell is not "pbitcell": + # self.storage_net_offsets = [] + # for net in get_storage_net_names: + # if net is "Q" or "Q_bar": + # for text in self.getTexts("metal1"): + # self.storage_net_offsets.append(text.offsetInMicrons) + return(self.storage_net_offsets) + + def get_normalized_storage_net_offset(self): + """ + Convert storage net offset to be relative to the bottom left corner + of the bitcell. This is useful for making sense of offsets outside + of the bitcell. + """ + + Q_x = self.storage_net_offsets[0][0] - self.leftmost_xpos + Q_y = self.storage_net_offsets[0][1] - self.botmost_ypos + Q_bar_x = self.storage_net_offsets[1][0] - self.leftmost_xpos + Q_bar_y = self.storage_net_offsets[1][1] - self.botmost_ypos + + normalized_storage_net_offset = [[Q_x,Q_y],[Q_bar_x,Q_bar_y]] + + return normalized_storage_net_offset + + def build_graph(self, graph, inst_name, port_nets): """ By default, bitcells won't be part of the graph. diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index bbfdf942..d14a36ed 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -26,7 +26,7 @@ class pbitcell(bitcell_base.bitcell_base): self.num_w_ports = OPTS.num_w_ports self.num_r_ports = OPTS.num_r_ports self.total_ports = self.num_rw_ports + self.num_w_ports + self.num_r_ports - + self.replica_bitcell = replica_bitcell self.dummy_bitcell = dummy_bitcell @@ -152,7 +152,7 @@ class pbitcell(bitcell_base.bitcell_base): self.Q_bar = "Q_bar" self.Q = "Q" self.storage_nets = [self.Q, self.Q_bar] - + def add_modules(self): """ Determine size of transistors and add ptx modules """ # if there are any read/write ports, @@ -353,6 +353,11 @@ class pbitcell(bitcell_base.bitcell_base): self.right_building_edge = right_inverter_xpos \ + self.inverter_nmos.active_width + def add_pex_labels(self, left_inverter_offset, right_inverter_offset): + self.add_label("Q", "metal1", left_inverter_offset) + self.add_label("Q_bar", "metal1", right_inverter_offset) + self.storage_net_offsets = [left_inverter_offset, right_inverter_offset] + def route_storage(self): """ Routes inputs and outputs of inverters to cross couple them """ # connect input (gate) of inverters @@ -399,6 +404,16 @@ class pbitcell(bitcell_base.bitcell_base): contact_offset_right.y) self.add_path("poly", [contact_offset_right, gate_offset_left]) + # add labels to cross couple inverter for extracted simulation + contact_offset_left_output = vector(self.inverter_nmos_left.get_pin("D").rc().x \ + + 0.5 * contact.poly.height, + self.cross_couple_upper_ypos) + + contact_offset_right_output = vector(self.inverter_nmos_right.get_pin("S").lc().x \ + - 0.5*contact.poly.height, + self.cross_couple_lower_ypos) + self.add_pex_labels(contact_offset_left_output, contact_offset_right_output) + def route_rails(self): """ Adds gnd and vdd rails and connects them to the inverters """ # Add rails for vdd and gnd diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 2a8d5293..e64f9515 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -217,8 +217,12 @@ class delay(simulation): storage_names = cell_inst.mod.get_storage_net_names() debug.check(len(storage_names) == 2, ("Only inverting/non-inverting storage nodes" "supported for characterization. Storage nets={}").format(storage_names)) - q_name = cell_name+'.'+str(storage_names[0]) - qbar_name = cell_name+'.'+str(storage_names[1]) + if not OPTS.use_pex: + q_name = cell_name+'.'+str(storage_names[0]) + qbar_name = cell_name+'.'+str(storage_names[1]) + else: + q_name = "bitcell_Q_r{0}_c{1}".format(OPTS.num_words -1, OPTS.word_size-1) + qbar_name = "bitcell_Q_r{0}_c{1}".format(OPTS.num_words -1, OPTS.word_size-1) # Bit measures, measurements times to be defined later. The measurement names must be unique # but they is enforced externally diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 58a9e3ed..e565fb5f 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -51,6 +51,11 @@ class stimuli(): self.sf.write("X{0} ".format(model_name)) for pin in pins: self.sf.write("{0} ".format(pin)) + if OPTS.use_pex: + for row in range(0,OPTS.num_words): + for col in range(0,OPTS.word_size): + self.sf.write("bitcell_Q_r{0}_c{1} ".format(row,col)) + self.sf.write("bitcell_Q_bar_r{0}_c{1} ".format(row,col)) self.sf.write("{0}\n".format(model_name)) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 3e105d09..0fe40ea8 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -75,8 +75,7 @@ class bank(design.design): self.bank_array_ll = self.offset_all_coordinates().scale(-1,-1) self.bank_array_ur = self.bitcell_array_inst.ur() self.bank_array_ul = self.bitcell_array_inst.ul() - - + self.DRC_LVS() def add_pins(self): @@ -968,7 +967,7 @@ class bank(design.design): stage_effort_list += self.port_address.wordline_driver.determine_wordline_stage_efforts(wordline_cout,inp_is_rise) return stage_effort_list - + def get_wl_en_cin(self): """Get the relative capacitance of all the clk connections in the bank""" #wl_en only used in the wordline driver. diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 3256c9ac..354179ca 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -789,7 +789,7 @@ class control_logic(design.design): layer="metal1", start=out_pin.center(), end=right_pos) - + def route_supply(self): @@ -847,7 +847,7 @@ class control_logic(design.design): height=pin.height(), width=pin.width()) - + def get_delays_to_wl(self): """Get the delay (in delay units) of the clk to a wordline in the bitcell array""" debug.check(self.sram.all_mods_except_control_done, "Cannot calculate sense amp enable delay unless all module have been added.") diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 2a4983b6..547ba517 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -18,6 +18,7 @@ from design import design from verilog import verilog from lef import lef from sram_factory import factory +from tech import drc import logical_effort class sram_base(design, verilog, lef): @@ -85,6 +86,41 @@ class sram_base(design, verilog, lef): self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") + def add_global_pex_labels(self): + """ + Add pex labels at the sram level for spice analysis + """ + + # add pex labels for bitcell + for bank_num in range(0,len(self.bank_insts)): + bank = self.bank_insts[bank_num] + pex_offsets = bank.reverse_bitcell_transformation() + + bank_offset = pex_offsets[0] # offset bank relative to sram + Q_offset = pex_offsets[1] # offset of storage relative to bank + Q_bar_offset = pex_offsets[2] # offset of storage relative to bank + + layer = "metal1" + + for i in range(0,len(bank_offset)): + + Q = [bank_offset[i][0] + Q_offset[i][0], bank_offset[i][1] + Q_offset[i][1]] + Q_bar = [bank_offset[i][0] + Q_bar_offset[i][0], bank_offset[i][1] + Q_bar_offset[i][1]] + + self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , layer, Q) + self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), layer, Q_bar) + + # add pex labels for control logic + for i in range (0,len(self.control_logic_insts)): + control_logic_offset = self.control_logic_insts[i].offset + for output in self.control_logic_insts[i].mod.output_list: + pin = self.control_logic_insts[i].mod.get_pin(output) + offset = [control_logic_offset[0] + pin.center()[0], control_logic_offset[1] + pin.center()[1]] + self.add_layout_pin_rect_center("{0}{1}".format(pin.name,i), "metal1", offset) + + + + def create_netlist(self): """ Netlist creation """ @@ -126,6 +162,8 @@ class sram_base(design, verilog, lef): self.width = highest_coord[0] self.height = highest_coord[1] + self.add_global_pex_labels() + start_time = datetime.now() # We only enable final verification if we have routed the design self.DRC_LVS(final_verification=OPTS.route_supplies, top_level=True) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 63aeaabe..fb0bc452 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -80,12 +80,12 @@ def write_magic_script(cell_name, extract=False, final_verification=False): f.write(pre+"ext2spice renumber off\n") f.write(pre+"ext2spice scale off\n") f.write(pre+"ext2spice blackbox on\n") - f.write(pre+"ext2spice subcircuit top auto\n") + f.write(pre+"ext2spice subcircuit top on\n") f.write(pre+"ext2spice global off\n") # Can choose hspice, ngspice, or spice3, # but they all seem compatible enough. - #f.write(pre+"ext2spice format ngspice\n") + f.write(pre+"ext2spice format ngspice\n") f.write(pre+"ext2spice {}\n".format(cell_name)) f.write("quit -noprompt\n") f.write("EOF\n") @@ -309,7 +309,7 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False): out_errors = find_error(results) debug.check(os.path.isfile(output),"Couldn't find PEX extracted output.") - correct_port(name,output,sp_name) + #correct_port(name,output,sp_name) return out_errors def write_batch_pex_rule(gds_name,name,sp_name,output): @@ -375,13 +375,13 @@ def write_script_pex_rule(gds_name,cell_name,output): else: pre = "" f.write(pre+"extract\n".format(cell_name)) - #f.write(pre+"ext2spice hierarchy on\n") - #f.write(pre+"ext2spice format ngspice\n") - #f.write(pre+"ext2spice renumber off\n") - #f.write(pre+"ext2spice scale off\n") - #f.write(pre+"ext2spice blackbox on\n") + f.write(pre+"ext2spice hierarchy on\n") + f.write(pre+"ext2spice format ngspice\n") + f.write(pre+"ext2spice renumber off\n") + f.write(pre+"ext2spice scale off\n") + f.write(pre+"ext2spice blackbox on\n") f.write(pre+"ext2spice subcircuit top on\n") - #f.write(pre+"ext2spice global off\n") + f.write(pre+"ext2spice global off\n") f.write(pre+"ext2spice {}\n".format(cell_name)) f.write("quit -noprompt\n") f.write("eof\n") @@ -404,31 +404,37 @@ def correct_port(name, output_file_name, ref_file_name): pex_file = open(output_file_name, "r") contents = pex_file.read() # locate the start of circuit definition line - match = re.search(".subckt " + str(name) + ".*", contents) + match = re.search(r'^\.subckt+[^M]*', contents, re.MULTILINE) match_index_start = match.start() - pex_file.seek(match_index_start) - rest_text = pex_file.read() - # locate the end of circuit definition line - match = re.search(r'\n', rest_text) - match_index_end = match.start() + match_index_end = match.end() # store the unchanged part of pex file in memory pex_file.seek(0) part1 = pex_file.read(match_index_start) - pex_file.seek(match_index_start + match_index_end) + pex_file.seek(match_index_end) part2 = pex_file.read() + + bitcell_list = "+ " + for row in range(0,OPTS.num_words): + for col in range(0,OPTS.word_size): + bitcell_list += "bitcell_Q_r{0}_c{1} ".format(row,col) + bitcell_list += "bitcell_Q_bar_r{0}_c{1} ".format(row,col) + bitcell_list += "\n" + + + part2 = bitcell_list + part2 pex_file.close() # obtain the correct definition line from the original spice file sp_file = open(ref_file_name, "r") contents = sp_file.read() - circuit_title = re.search(".SUBCKT " + str(name) + ".*\n", contents) + circuit_title = re.search(".SUBCKT " + str(name) + ".*", contents) circuit_title = circuit_title.group() sp_file.close() # write the new pex file with info in the memory output_file = open(output_file_name, "w") output_file.write(part1) - output_file.write(circuit_title) + output_file.write(circuit_title+'\n') output_file.write(part2) output_file.close() @@ -437,4 +443,4 @@ def print_drc_stats(): def print_lvs_stats(): debug.info(1,"LVS runs: {0}".format(num_lvs_runs)) def print_pex_stats(): - debug.info(1,"PEX runs: {0}".format(num_pex_runs)) + debug.info(1,"PEX runs: {0}".format(num_pex_runs)) \ No newline at end of file diff --git a/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag index 9aec1c5d..0f2cdadb 100644 --- a/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag +++ b/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag @@ -1,22 +1,31 @@ magic tech scmos -timestamp 1542220294 -<< nwell >> -rect 0 46 54 75 +timestamp 1572948731 << pwell >> rect 0 0 54 46 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 +<< nwell >> +rect 0 46 54 75 +<< polysilicon >> +rect 22 57 24 60 +rect 30 57 32 60 +rect 22 44 24 54 +rect 30 51 32 54 +rect 31 47 32 51 +rect 14 37 16 44 +rect 22 40 23 44 +rect 22 37 24 40 +rect 30 37 32 47 +rect 38 37 40 44 +rect 14 31 16 33 +rect 38 31 40 33 +rect 14 23 16 24 +rect 22 23 24 29 +rect 30 23 32 29 +rect 38 23 40 24 +rect 14 15 16 17 +rect 22 15 24 17 +rect 30 15 32 17 +rect 38 15 40 17 << ndiffusion >> rect 13 33 14 37 rect 16 33 17 37 @@ -41,46 +50,6 @@ rect 21 54 22 57 rect 24 54 25 57 rect 29 54 30 57 rect 32 54 33 57 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 25 17 29 23 -<< pdcontact >> -rect 17 54 21 58 -rect 33 54 37 58 -<< psubstratepcontact >> -rect 25 9 29 13 -<< polysilicon >> -rect 22 57 24 60 -rect 30 57 32 60 -rect 22 44 24 54 -rect 30 51 32 54 -rect 31 47 32 51 -rect 14 37 16 44 -rect 22 40 23 44 -rect 22 37 24 40 -rect 30 37 32 47 -rect 38 37 40 44 -rect 14 31 16 33 -rect 38 31 40 33 -rect 14 23 16 24 -rect 22 23 24 29 -rect 30 23 32 29 -rect 38 23 40 24 -rect 14 15 16 17 -rect 22 15 24 17 -rect 30 15 32 17 -rect 38 15 40 17 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -102,20 +71,6 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 -<< m2contact >> -rect 2 33 6 37 -rect 48 33 52 37 -rect 16 24 20 28 -rect 34 24 38 28 -rect 16 2 20 6 -rect 34 2 38 6 -<< pdm12contact >> -rect 25 54 29 58 -<< ndm12contact >> -rect 9 17 13 21 -rect 41 17 45 21 -<< nsm12contact >> -rect 25 68 29 72 << metal2 >> rect 2 37 6 72 rect 2 0 6 33 @@ -125,11 +80,47 @@ rect 9 0 13 17 rect 16 6 20 24 rect 34 6 38 24 rect 41 21 45 72 -rect 41 0 45 17 rect 48 37 52 72 +rect 41 0 45 17 rect 48 0 52 33 -<< comment >> -rect 0 0 54 70 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 25 17 29 23 +<< pdcontact >> +rect 17 54 21 58 +rect 33 54 37 58 +<< m2contact >> +rect 2 33 6 37 +rect 48 33 52 37 +rect 16 24 20 28 +rect 34 24 38 28 +rect 16 2 20 6 +rect 34 2 38 6 +<< psubstratepcontact >> +rect 25 9 29 13 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd @@ -139,4 +130,6 @@ rlabel metal2 4 7 4 7 2 bl0 rlabel metal2 11 7 11 7 1 bl1 rlabel metal2 43 7 43 7 1 br1 rlabel metal2 50 7 50 7 8 br0 +rlabel metal1 19 49 19 49 1 Q +rlabel metal1 35 42 35 42 1 Q_bar << end >> diff --git a/technology/scn4m_subm/mag_lib/cell_1w_1r.mag b/technology/scn4m_subm/mag_lib/cell_1w_1r.mag index 9aec1c5d..91d06069 100644 --- a/technology/scn4m_subm/mag_lib/cell_1w_1r.mag +++ b/technology/scn4m_subm/mag_lib/cell_1w_1r.mag @@ -1,22 +1,31 @@ magic tech scmos -timestamp 1542220294 -<< nwell >> -rect 0 46 54 75 +timestamp 1572948787 << pwell >> rect 0 0 54 46 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 +<< nwell >> +rect 0 46 54 75 +<< polysilicon >> +rect 22 57 24 60 +rect 30 57 32 60 +rect 22 44 24 54 +rect 30 51 32 54 +rect 31 47 32 51 +rect 14 37 16 44 +rect 22 40 23 44 +rect 22 37 24 40 +rect 30 37 32 47 +rect 38 37 40 44 +rect 14 31 16 33 +rect 38 31 40 33 +rect 14 23 16 24 +rect 22 23 24 29 +rect 30 23 32 29 +rect 38 23 40 24 +rect 14 15 16 17 +rect 22 15 24 17 +rect 30 15 32 17 +rect 38 15 40 17 << ndiffusion >> rect 13 33 14 37 rect 16 33 17 37 @@ -41,46 +50,6 @@ rect 21 54 22 57 rect 24 54 25 57 rect 29 54 30 57 rect 32 54 33 57 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 25 17 29 23 -<< pdcontact >> -rect 17 54 21 58 -rect 33 54 37 58 -<< psubstratepcontact >> -rect 25 9 29 13 -<< polysilicon >> -rect 22 57 24 60 -rect 30 57 32 60 -rect 22 44 24 54 -rect 30 51 32 54 -rect 31 47 32 51 -rect 14 37 16 44 -rect 22 40 23 44 -rect 22 37 24 40 -rect 30 37 32 47 -rect 38 37 40 44 -rect 14 31 16 33 -rect 38 31 40 33 -rect 14 23 16 24 -rect 22 23 24 29 -rect 30 23 32 29 -rect 38 23 40 24 -rect 14 15 16 17 -rect 22 15 24 17 -rect 30 15 32 17 -rect 38 15 40 17 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -102,20 +71,6 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 -<< m2contact >> -rect 2 33 6 37 -rect 48 33 52 37 -rect 16 24 20 28 -rect 34 24 38 28 -rect 16 2 20 6 -rect 34 2 38 6 -<< pdm12contact >> -rect 25 54 29 58 -<< ndm12contact >> -rect 9 17 13 21 -rect 41 17 45 21 -<< nsm12contact >> -rect 25 68 29 72 << metal2 >> rect 2 37 6 72 rect 2 0 6 33 @@ -125,11 +80,47 @@ rect 9 0 13 17 rect 16 6 20 24 rect 34 6 38 24 rect 41 21 45 72 -rect 41 0 45 17 rect 48 37 52 72 +rect 41 0 45 17 rect 48 0 52 33 -<< comment >> -rect 0 0 54 70 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 25 17 29 23 +<< pdcontact >> +rect 17 54 21 58 +rect 33 54 37 58 +<< m2contact >> +rect 2 33 6 37 +rect 48 33 52 37 +rect 16 24 20 28 +rect 34 24 38 28 +rect 16 2 20 6 +rect 34 2 38 6 +<< psubstratepcontact >> +rect 25 9 29 13 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd @@ -139,4 +130,6 @@ rlabel metal2 4 7 4 7 2 bl0 rlabel metal2 11 7 11 7 1 bl1 rlabel metal2 43 7 43 7 1 br1 rlabel metal2 50 7 50 7 8 br0 +rlabel metal1 19 49 19 49 1 Q +rlabel metal1 35 42 35 42 1 Q_bar << end >> diff --git a/technology/scn4m_subm/mag_lib/cell_6t.mag b/technology/scn4m_subm/mag_lib/cell_6t.mag index bb9d943d..6b277af2 100644 --- a/technology/scn4m_subm/mag_lib/cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/cell_6t.mag @@ -1,18 +1,28 @@ magic tech scmos -timestamp 1560809302 -<< nwell >> -rect -8 35 42 57 +timestamp 1572949512 << pwell >> rect -8 -2 42 35 -<< ntransistor >> -rect 7 16 9 24 -rect 29 16 31 24 -rect 10 9 14 11 -rect 24 9 28 11 -<< ptransistor >> -rect 7 43 11 46 -rect 27 43 31 46 +<< nwell >> +rect -8 35 42 57 +<< polysilicon >> +rect 7 46 11 48 +rect 27 46 31 48 +rect 7 41 11 43 +rect 7 27 9 41 +rect 27 40 31 43 +rect 15 39 31 40 +rect 19 38 31 39 +rect 7 26 21 27 +rect 7 25 24 26 +rect 7 24 9 25 +rect 29 24 31 38 +rect 7 14 9 16 +rect 17 11 21 12 +rect 29 14 31 16 +rect -2 9 10 11 +rect 14 9 24 11 +rect 28 9 36 11 << ndiffusion >> rect -2 22 7 24 rect 2 18 7 22 @@ -33,45 +43,6 @@ rect 2 43 7 46 rect 11 43 12 46 rect 26 43 27 46 rect 31 43 32 46 -<< ndcontact >> -rect -2 18 2 22 -rect 10 20 14 24 -rect 24 20 28 24 -rect 32 18 36 22 -rect 10 4 14 8 -rect 24 4 28 8 -<< pdcontact >> -rect -2 42 2 46 -rect 12 42 16 46 -rect 22 42 26 46 -rect 32 42 36 46 -<< psubstratepcontact >> -rect -2 28 2 32 -rect 32 28 36 32 -<< nsubstratencontact >> -rect 32 50 36 54 -<< polysilicon >> -rect 7 46 11 48 -rect 27 46 31 48 -rect 7 41 11 43 -rect 7 27 9 41 -rect 27 40 31 43 -rect 15 39 31 40 -rect 19 38 31 39 -rect 7 26 21 27 -rect 7 25 24 26 -rect 7 24 9 25 -rect 29 24 31 38 -rect 7 14 9 16 -rect 17 11 21 12 -rect 29 14 31 16 -rect -2 9 10 11 -rect 14 9 24 11 -rect 28 9 36 11 -<< polycontact >> -rect 15 35 19 39 -rect 21 26 25 30 -rect 17 12 21 16 << metal1 >> rect -2 50 15 54 rect 19 50 32 54 @@ -92,12 +63,6 @@ rect 32 22 36 28 rect -2 12 17 15 rect 21 12 36 15 rect -2 11 36 12 -<< m2contact >> -rect 15 50 19 54 -rect -2 35 2 39 -rect 32 35 36 39 -rect 6 4 10 8 -rect 20 4 24 8 << metal2 >> rect -2 39 2 54 rect -2 0 2 35 @@ -106,8 +71,41 @@ rect 6 0 10 4 rect 24 0 28 54 rect 32 39 36 54 rect 32 0 36 35 -<< bb >> -rect 0 0 34 52 +<< ntransistor >> +rect 7 16 9 24 +rect 29 16 31 24 +rect 10 9 14 11 +rect 24 9 28 11 +<< ptransistor >> +rect 7 43 11 46 +rect 27 43 31 46 +<< polycontact >> +rect 15 35 19 39 +rect 21 26 25 30 +rect 17 12 21 16 +<< ndcontact >> +rect -2 18 2 22 +rect 10 20 14 24 +rect 24 20 28 24 +rect 32 18 36 22 +rect 10 4 14 8 +rect 24 4 28 8 +<< pdcontact >> +rect -2 42 2 46 +rect 12 42 16 46 +rect 22 42 26 46 +rect 32 42 36 46 +<< m2contact >> +rect 15 50 19 54 +rect -2 35 2 39 +rect 32 35 36 39 +rect 6 4 10 8 +rect 20 4 24 8 +<< psubstratepcontact >> +rect -2 28 2 32 +rect 32 28 36 32 +<< nsubstratencontact >> +rect 32 50 36 54 << labels >> rlabel metal2 0 6 0 6 1 gnd rlabel metal2 34 6 34 6 1 gnd @@ -115,4 +113,6 @@ rlabel m2contact 17 52 17 52 5 vdd rlabel metal2 8 49 8 49 1 bl rlabel metal2 26 49 26 49 1 br rlabel metal1 4 13 4 13 1 wl +rlabel polycontact 23 28 23 28 1 Q_bar +rlabel polycontact 17 37 17 37 1 Q << end >> diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag index 60e24aca..79b5daf0 100644 --- a/technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag +++ b/technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag @@ -1,63 +1,10 @@ magic tech scmos -timestamp 1562188987 -<< nwell >> -rect 0 46 54 75 +timestamp 1572949567 << pwell >> rect 0 0 54 46 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 21 14 23 -rect 13 17 14 21 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 21 45 23 -rect 40 17 41 21 -<< pdiffusion >> -rect 21 54 22 57 -rect 24 54 25 57 -rect 29 54 30 57 -rect 32 54 33 57 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 9 17 13 21 -rect 25 17 29 23 -rect 41 17 45 21 -<< pdcontact >> -rect 17 54 21 58 -rect 25 54 29 58 -rect 33 54 37 58 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratencontact >> -rect 25 68 29 72 +<< nwell >> +rect 0 46 54 75 << polysilicon >> rect 22 57 24 60 rect 30 57 32 60 @@ -79,13 +26,30 @@ rect 14 15 16 17 rect 22 15 24 17 rect 30 15 32 17 rect 38 15 40 17 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 +<< ndiffusion >> +rect 13 33 14 37 +rect 16 33 17 37 +rect 21 33 22 37 +rect 17 29 22 33 +rect 24 29 25 37 +rect 29 29 30 37 +rect 32 33 33 37 +rect 37 33 38 37 +rect 40 33 41 37 +rect 32 29 37 33 +rect 9 21 14 23 +rect 13 17 14 21 +rect 16 17 22 23 +rect 24 17 25 23 +rect 29 17 30 23 +rect 32 17 38 23 +rect 40 21 45 23 +rect 40 17 41 21 +<< pdiffusion >> +rect 25 57 29 58 +rect 21 54 22 57 +rect 24 54 30 57 +rect 32 54 33 57 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -107,13 +71,6 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 16 24 20 28 -rect 34 24 38 28 -rect 16 2 20 6 -rect 34 2 38 6 << metal2 >> rect 2 0 6 72 rect 9 0 13 72 @@ -122,8 +79,48 @@ rect 16 6 20 24 rect 34 6 38 24 rect 41 0 45 72 rect 48 0 52 72 -<< comment >> -rect 0 0 54 70 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 9 17 13 21 +rect 25 17 29 23 +rect 41 17 45 21 +<< pdcontact >> +rect 17 54 21 58 +rect 33 54 37 58 +<< m2contact >> +rect 25 68 29 72 +rect 25 54 29 58 +rect 16 24 20 28 +rect 34 24 38 28 +rect 16 2 20 6 +rect 34 2 38 6 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratendiff >> +rect 25 68 29 72 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd @@ -133,4 +130,6 @@ rlabel metal2 4 7 4 7 2 bl0 rlabel metal2 11 7 11 7 1 bl1 rlabel metal2 43 7 43 7 1 br1 rlabel metal2 50 7 50 7 8 br0 +rlabel polycontact 29 49 29 49 1 Q +rlabel polycontact 25 42 25 42 1 Q_bar << end >> diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag b/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag index 03e49f03..9166b42a 100644 --- a/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag +++ b/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag @@ -1,63 +1,10 @@ magic tech scmos -timestamp 1562189027 -<< nwell >> -rect 0 46 54 75 +timestamp 1572949619 << pwell >> rect 0 0 54 46 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 21 14 23 -rect 13 17 14 21 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 21 45 23 -rect 40 17 41 21 -<< pdiffusion >> -rect 21 54 22 57 -rect 24 54 25 57 -rect 29 54 30 57 -rect 32 54 33 57 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 9 17 13 21 -rect 25 17 29 23 -rect 41 17 45 21 -<< pdcontact >> -rect 17 54 21 58 -rect 25 54 29 58 -rect 33 54 37 58 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratencontact >> -rect 25 68 29 72 +<< nwell >> +rect 0 46 54 75 << polysilicon >> rect 22 57 24 60 rect 30 57 32 60 @@ -79,13 +26,30 @@ rect 14 15 16 17 rect 22 15 24 17 rect 30 15 32 17 rect 38 15 40 17 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 +<< ndiffusion >> +rect 13 33 14 37 +rect 16 33 17 37 +rect 21 33 22 37 +rect 17 29 22 33 +rect 24 29 25 37 +rect 29 29 30 37 +rect 32 33 33 37 +rect 37 33 38 37 +rect 40 33 41 37 +rect 32 29 37 33 +rect 9 21 14 23 +rect 13 17 14 21 +rect 16 17 22 23 +rect 24 17 25 23 +rect 29 17 30 23 +rect 32 17 38 23 +rect 40 21 45 23 +rect 40 17 41 21 +<< pdiffusion >> +rect 25 57 29 58 +rect 21 54 22 57 +rect 24 54 30 57 +rect 32 54 33 57 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -107,13 +71,6 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 16 24 20 28 -rect 34 24 38 28 -rect 16 2 20 6 -rect 34 2 38 6 << metal2 >> rect 2 0 6 72 rect 9 0 13 72 @@ -122,8 +79,48 @@ rect 16 6 20 24 rect 34 6 38 24 rect 41 0 45 72 rect 48 0 52 72 -<< comment >> -rect 0 0 54 70 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 9 17 13 21 +rect 25 17 29 23 +rect 41 17 45 21 +<< pdcontact >> +rect 17 54 21 58 +rect 33 54 37 58 +<< m2contact >> +rect 25 68 29 72 +rect 25 54 29 58 +rect 16 24 20 28 +rect 34 24 38 28 +rect 16 2 20 6 +rect 34 2 38 6 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratendiff >> +rect 25 68 29 72 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd @@ -133,4 +130,6 @@ rlabel metal2 4 7 4 7 2 bl0 rlabel metal2 11 7 11 7 1 bl1 rlabel metal2 43 7 43 7 1 br1 rlabel metal2 50 7 50 7 8 br0 +rlabel polycontact 29 49 29 49 1 Q +rlabel polycontact 25 42 25 42 1 Q_bar << end >> diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag b/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag index 74562f15..7f7591ba 100644 --- a/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag @@ -1,18 +1,28 @@ magic tech scmos -timestamp 1560809362 -<< nwell >> -rect -8 35 42 57 +timestamp 1572949665 << pwell >> rect -8 -2 42 35 -<< ntransistor >> -rect 7 16 9 24 -rect 29 16 31 24 -rect 10 9 14 11 -rect 24 9 28 11 -<< ptransistor >> -rect 7 43 11 46 -rect 27 43 31 46 +<< nwell >> +rect -8 35 42 57 +<< polysilicon >> +rect 7 46 11 48 +rect 27 46 31 48 +rect 7 41 11 43 +rect 7 27 9 41 +rect 27 40 31 43 +rect 15 39 31 40 +rect 19 38 31 39 +rect 7 26 21 27 +rect 7 25 24 26 +rect 7 24 9 25 +rect 29 24 31 38 +rect 7 14 9 16 +rect 17 11 21 12 +rect 29 14 31 16 +rect -2 9 10 11 +rect 14 9 24 11 +rect 28 9 36 11 << ndiffusion >> rect -2 22 7 24 rect 2 18 7 22 @@ -33,45 +43,6 @@ rect 2 43 7 46 rect 11 43 12 46 rect 26 43 27 46 rect 31 43 32 46 -<< ndcontact >> -rect -2 18 2 22 -rect 10 20 14 24 -rect 24 20 28 24 -rect 32 18 36 22 -rect 10 4 14 8 -rect 24 4 28 8 -<< pdcontact >> -rect -2 42 2 46 -rect 12 42 16 46 -rect 22 42 26 46 -rect 32 42 36 46 -<< psubstratepcontact >> -rect -2 28 2 32 -rect 32 28 36 32 -<< nsubstratencontact >> -rect 32 50 36 54 -<< polysilicon >> -rect 7 46 11 48 -rect 27 46 31 48 -rect 7 41 11 43 -rect 7 27 9 41 -rect 27 40 31 43 -rect 15 39 31 40 -rect 19 38 31 39 -rect 7 26 21 27 -rect 7 25 24 26 -rect 7 24 9 25 -rect 29 24 31 38 -rect 7 14 9 16 -rect 17 11 21 12 -rect 29 14 31 16 -rect -2 9 10 11 -rect 14 9 24 11 -rect 28 9 36 11 -<< polycontact >> -rect 15 35 19 39 -rect 21 26 25 30 -rect 17 12 21 16 << metal1 >> rect -2 50 15 54 rect 19 50 32 54 @@ -92,10 +63,6 @@ rect 32 22 36 28 rect -2 12 17 15 rect 21 12 36 15 rect -2 11 36 12 -<< m2contact >> -rect 15 50 19 54 -rect -2 35 2 39 -rect 32 35 36 39 << metal2 >> rect -2 39 2 54 rect -2 0 2 35 @@ -103,8 +70,39 @@ rect 6 0 10 54 rect 24 0 28 54 rect 32 39 36 54 rect 32 0 36 35 -<< bb >> -rect 0 0 34 52 +<< ntransistor >> +rect 7 16 9 24 +rect 29 16 31 24 +rect 10 9 14 11 +rect 24 9 28 11 +<< ptransistor >> +rect 7 43 11 46 +rect 27 43 31 46 +<< polycontact >> +rect 15 35 19 39 +rect 21 26 25 30 +rect 17 12 21 16 +<< ndcontact >> +rect -2 18 2 22 +rect 10 20 14 24 +rect 24 20 28 24 +rect 32 18 36 22 +rect 10 4 14 8 +rect 24 4 28 8 +<< pdcontact >> +rect -2 42 2 46 +rect 12 42 16 46 +rect 22 42 26 46 +rect 32 42 36 46 +<< m2contact >> +rect 15 50 19 54 +rect -2 35 2 39 +rect 32 35 36 39 +<< psubstratepcontact >> +rect -2 28 2 32 +rect 32 28 36 32 +<< nsubstratencontact >> +rect 32 50 36 54 << labels >> rlabel metal2 0 6 0 6 1 gnd rlabel metal2 34 6 34 6 1 gnd @@ -112,4 +110,6 @@ rlabel m2contact 17 52 17 52 5 vdd rlabel metal2 8 49 8 49 1 bl rlabel metal2 26 49 26 49 1 br rlabel metal1 4 13 4 13 1 wl +rlabel polycontact 17 37 17 37 1 Q +rlabel polycontact 23 28 23 28 1 Q_bar << end >> diff --git a/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag index f215ff04..9b6e203b 100644 --- a/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag +++ b/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag @@ -1,63 +1,10 @@ magic tech scmos -timestamp 1542221056 -<< nwell >> -rect 0 46 54 75 +timestamp 1572949704 << pwell >> rect 0 0 54 46 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 21 14 23 -rect 13 17 14 21 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 21 45 23 -rect 40 17 41 21 -<< pdiffusion >> -rect 21 54 22 57 -rect 24 54 25 57 -rect 29 54 30 57 -rect 32 54 33 57 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 9 17 13 21 -rect 25 17 29 23 -rect 41 17 45 21 -<< pdcontact >> -rect 17 54 21 58 -rect 25 54 29 58 -rect 33 54 37 58 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratencontact >> -rect 25 68 29 72 +<< nwell >> +rect 0 46 54 75 << polysilicon >> rect 22 57 24 60 rect 30 57 32 60 @@ -79,13 +26,28 @@ rect 14 15 16 17 rect 22 15 24 17 rect 30 15 32 17 rect 38 15 40 17 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 +<< ndiffusion >> +rect 13 33 14 37 +rect 16 33 17 37 +rect 21 33 22 37 +rect 17 29 22 33 +rect 24 29 25 37 +rect 29 29 30 37 +rect 32 33 33 37 +rect 37 33 38 37 +rect 40 33 41 37 +rect 32 29 37 33 +rect 9 17 14 23 +rect 16 17 22 23 +rect 24 17 25 23 +rect 29 17 30 23 +rect 32 17 38 23 +rect 40 17 45 23 +<< pdiffusion >> +rect 25 57 29 58 +rect 21 54 22 57 +rect 24 54 30 57 +rect 32 54 33 57 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -108,17 +70,6 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 2 33 6 37 -rect 48 33 52 37 -rect 16 24 20 28 -rect 34 24 38 28 -rect 9 17 13 21 -rect 41 17 45 21 -rect 16 2 20 6 -rect 34 2 38 6 << metal2 >> rect 2 37 6 72 rect 2 0 6 33 @@ -131,8 +82,50 @@ rect 41 21 45 72 rect 41 0 45 17 rect 48 37 52 72 rect 48 0 52 33 -<< comment >> -rect 0 0 54 70 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 25 17 29 23 +<< pdcontact >> +rect 17 54 21 58 +rect 33 54 37 58 +<< m2contact >> +rect 25 68 29 72 +rect 25 54 29 58 +rect 2 33 6 37 +rect 48 33 52 37 +rect 16 24 20 28 +rect 34 24 38 28 +rect 9 17 13 21 +rect 41 17 45 21 +rect 16 2 20 6 +rect 34 2 38 6 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratendiff >> +rect 25 68 29 72 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd @@ -142,4 +135,6 @@ rlabel metal2 4 7 4 7 2 bl0 rlabel metal2 11 7 11 7 1 bl1 rlabel metal2 43 7 43 7 1 br1 rlabel metal2 50 7 50 7 8 br0 +rlabel polycontact 29 49 29 49 1 Q +rlabel polycontact 25 42 25 42 1 Q_bar << end >> diff --git a/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag b/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag index f215ff04..b2a525e8 100644 --- a/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag +++ b/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag @@ -1,63 +1,10 @@ magic tech scmos -timestamp 1542221056 -<< nwell >> -rect 0 46 54 75 +timestamp 1572949741 << pwell >> rect 0 0 54 46 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 21 14 23 -rect 13 17 14 21 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 21 45 23 -rect 40 17 41 21 -<< pdiffusion >> -rect 21 54 22 57 -rect 24 54 25 57 -rect 29 54 30 57 -rect 32 54 33 57 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 9 17 13 21 -rect 25 17 29 23 -rect 41 17 45 21 -<< pdcontact >> -rect 17 54 21 58 -rect 25 54 29 58 -rect 33 54 37 58 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratencontact >> -rect 25 68 29 72 +<< nwell >> +rect 0 46 54 75 << polysilicon >> rect 22 57 24 60 rect 30 57 32 60 @@ -79,13 +26,28 @@ rect 14 15 16 17 rect 22 15 24 17 rect 30 15 32 17 rect 38 15 40 17 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 +<< ndiffusion >> +rect 13 33 14 37 +rect 16 33 17 37 +rect 21 33 22 37 +rect 17 29 22 33 +rect 24 29 25 37 +rect 29 29 30 37 +rect 32 33 33 37 +rect 37 33 38 37 +rect 40 33 41 37 +rect 32 29 37 33 +rect 9 17 14 23 +rect 16 17 22 23 +rect 24 17 25 23 +rect 29 17 30 23 +rect 32 17 38 23 +rect 40 17 45 23 +<< pdiffusion >> +rect 25 57 29 58 +rect 21 54 22 57 +rect 24 54 30 57 +rect 32 54 33 57 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -108,17 +70,6 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 2 33 6 37 -rect 48 33 52 37 -rect 16 24 20 28 -rect 34 24 38 28 -rect 9 17 13 21 -rect 41 17 45 21 -rect 16 2 20 6 -rect 34 2 38 6 << metal2 >> rect 2 37 6 72 rect 2 0 6 33 @@ -131,8 +82,50 @@ rect 41 21 45 72 rect 41 0 45 17 rect 48 37 52 72 rect 48 0 52 33 -<< comment >> -rect 0 0 54 70 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 25 17 29 23 +<< pdcontact >> +rect 17 54 21 58 +rect 33 54 37 58 +<< m2contact >> +rect 25 68 29 72 +rect 25 54 29 58 +rect 2 33 6 37 +rect 48 33 52 37 +rect 16 24 20 28 +rect 34 24 38 28 +rect 9 17 13 21 +rect 41 17 45 21 +rect 16 2 20 6 +rect 34 2 38 6 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratendiff >> +rect 25 68 29 72 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd @@ -142,4 +135,6 @@ rlabel metal2 4 7 4 7 2 bl0 rlabel metal2 11 7 11 7 1 bl1 rlabel metal2 43 7 43 7 1 br1 rlabel metal2 50 7 50 7 8 br0 +rlabel polycontact 29 49 29 49 1 Q +rlabel polycontact 25 42 25 42 1 Q_bar << end >> diff --git a/technology/scn4m_subm/mag_lib/replica_cell_6t.mag b/technology/scn4m_subm/mag_lib/replica_cell_6t.mag index b5a5f7b8..316082ca 100644 --- a/technology/scn4m_subm/mag_lib/replica_cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/replica_cell_6t.mag @@ -1,18 +1,28 @@ magic tech scmos -timestamp 1560809329 -<< nwell >> -rect -8 35 42 57 +timestamp 1572949776 << pwell >> rect -8 -2 42 35 -<< ntransistor >> -rect 7 16 9 24 -rect 29 16 31 24 -rect 10 9 14 11 -rect 24 9 28 11 -<< ptransistor >> -rect 7 43 11 46 -rect 27 43 31 46 +<< nwell >> +rect -8 35 42 57 +<< polysilicon >> +rect 7 46 11 48 +rect 27 46 31 48 +rect 7 41 11 43 +rect 7 27 9 41 +rect 27 40 31 43 +rect 15 39 31 40 +rect 19 38 31 39 +rect 7 26 21 27 +rect 7 25 24 26 +rect 7 24 9 25 +rect 29 24 31 38 +rect 7 14 9 16 +rect 17 11 21 12 +rect 29 14 31 16 +rect -2 9 10 11 +rect 14 9 24 11 +rect 28 9 36 11 << ndiffusion >> rect -2 22 7 24 rect 2 18 7 22 @@ -33,45 +43,6 @@ rect 2 43 7 46 rect 11 43 12 46 rect 26 43 27 46 rect 31 43 32 46 -<< ndcontact >> -rect -2 18 2 22 -rect 10 20 14 24 -rect 24 20 28 24 -rect 32 18 36 22 -rect 10 4 14 8 -rect 24 4 28 8 -<< pdcontact >> -rect -2 42 2 46 -rect 12 42 16 46 -rect 22 42 26 46 -rect 32 42 36 46 -<< psubstratepcontact >> -rect -2 28 2 32 -rect 32 28 36 32 -<< nsubstratencontact >> -rect 32 50 36 54 -<< polysilicon >> -rect 7 46 11 48 -rect 27 46 31 48 -rect 7 41 11 43 -rect 7 27 9 41 -rect 27 40 31 43 -rect 15 39 31 40 -rect 19 38 31 39 -rect 7 26 21 27 -rect 7 25 24 26 -rect 7 24 9 25 -rect 29 24 31 38 -rect 7 14 9 16 -rect 17 11 21 12 -rect 29 14 31 16 -rect -2 9 10 11 -rect 14 9 24 11 -rect 28 9 36 11 -<< polycontact >> -rect 15 35 19 39 -rect 21 26 25 30 -rect 17 12 21 16 << metal1 >> rect -2 50 15 54 rect 19 50 32 54 @@ -93,12 +64,6 @@ rect 32 22 36 28 rect -2 12 17 15 rect 21 12 36 15 rect -2 11 36 12 -<< m2contact >> -rect 15 50 19 54 -rect -2 35 2 39 -rect 32 35 36 39 -rect 6 4 10 8 -rect 20 4 24 8 << metal2 >> rect -2 39 2 54 rect -2 0 2 35 @@ -107,8 +72,41 @@ rect 6 0 10 4 rect 24 0 28 54 rect 32 39 36 54 rect 32 0 36 35 -<< bb >> -rect 0 0 34 52 +<< ntransistor >> +rect 7 16 9 24 +rect 29 16 31 24 +rect 10 9 14 11 +rect 24 9 28 11 +<< ptransistor >> +rect 7 43 11 46 +rect 27 43 31 46 +<< polycontact >> +rect 15 35 19 39 +rect 21 26 25 30 +rect 17 12 21 16 +<< ndcontact >> +rect -2 18 2 22 +rect 10 20 14 24 +rect 24 20 28 24 +rect 32 18 36 22 +rect 10 4 14 8 +rect 24 4 28 8 +<< pdcontact >> +rect -2 42 2 46 +rect 12 42 16 46 +rect 22 42 26 46 +rect 32 42 36 46 +<< m2contact >> +rect 15 50 19 54 +rect -2 35 2 39 +rect 32 35 36 39 +rect 6 4 10 8 +rect 20 4 24 8 +<< psubstratepcontact >> +rect -2 28 2 32 +rect 32 28 36 32 +<< nsubstratencontact >> +rect 32 50 36 54 << labels >> rlabel metal2 0 6 0 6 1 gnd rlabel metal2 34 6 34 6 1 gnd @@ -116,4 +114,6 @@ rlabel m2contact 17 52 17 52 5 vdd rlabel metal2 8 49 8 49 1 bl rlabel metal2 26 49 26 49 1 br rlabel metal1 4 13 4 13 1 wl +rlabel polycontact 17 37 17 37 1 Q +rlabel polycontact 23 28 23 28 1 Q_bar << end >> From 88d3da0b4aadf1be35af4d07fa5875ea49a71af9 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Wed, 18 Dec 2019 12:45:12 +0000 Subject: [PATCH 02/65] fix control logic pex labels with multiport --- compiler/sram/sram_base.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 547ba517..cd9fb19d 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -112,11 +112,13 @@ class sram_base(design, verilog, lef): # add pex labels for control logic for i in range (0,len(self.control_logic_insts)): - control_logic_offset = self.control_logic_insts[i].offset - for output in self.control_logic_insts[i].mod.output_list: - pin = self.control_logic_insts[i].mod.get_pin(output) - offset = [control_logic_offset[0] + pin.center()[0], control_logic_offset[1] + pin.center()[1]] - self.add_layout_pin_rect_center("{0}{1}".format(pin.name,i), "metal1", offset) + instance = self.control_logic_insts[i] + control_logic_offset = instance.offset + for output in instance.mod.output_list: + pin = instance.mod.get_pin(output) + pin.transform([0,0], instance.mirror, instance.rotate) + offset = [control_logic_offset[0] + pin.center()[0], control_logic_offset[1] + pin.center()[1]] + self.add_layout_pin_rect_center("{0}{1}".format(pin.name,i), "metal1", offset) From 5b44dce50d37e4ef30e2d3115536208dc700ae29 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Mon, 23 Dec 2019 02:22:11 +0000 Subject: [PATCH 03/65] added labels to scn4m magic libaries --- technology/scn4m_subm/mag_lib/cell_1rw_1r.mag | 141 +++++++++-------- technology/scn4m_subm/mag_lib/cell_1w_1r.mag | 141 +++++++++-------- technology/scn4m_subm/mag_lib/cell_6t.mag | 116 +++++++------- .../scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag | 141 ++++++++--------- .../scn4m_subm/mag_lib/dummy_cell_1w_1r.mag | 141 ++++++++--------- .../scn4m_subm/mag_lib/dummy_cell_6t.mag | 110 ++++++------- .../mag_lib/replica_cell_1rw_1r.mag | 145 +++++++++--------- .../scn4m_subm/mag_lib/replica_cell_1w_1r.mag | 145 +++++++++--------- .../scn4m_subm/mag_lib/replica_cell_6t.mag | 114 +++++++------- 9 files changed, 621 insertions(+), 573 deletions(-) diff --git a/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag index 0f2cdadb..0484df70 100644 --- a/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag +++ b/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag @@ -1,31 +1,22 @@ magic tech scmos -timestamp 1572948731 -<< pwell >> -rect 0 0 54 46 +timestamp 1577066542 << nwell >> rect 0 46 54 75 -<< polysilicon >> -rect 22 57 24 60 -rect 30 57 32 60 -rect 22 44 24 54 -rect 30 51 32 54 -rect 31 47 32 51 -rect 14 37 16 44 -rect 22 40 23 44 -rect 22 37 24 40 -rect 30 37 32 47 -rect 38 37 40 44 -rect 14 31 16 33 -rect 38 31 40 33 -rect 14 23 16 24 -rect 22 23 24 29 -rect 30 23 32 29 -rect 38 23 40 24 -rect 14 15 16 17 -rect 22 15 24 17 -rect 30 15 32 17 -rect 38 15 40 17 +<< pwell >> +rect 0 0 54 46 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 << ndiffusion >> rect 13 33 14 37 rect 16 33 17 37 @@ -50,6 +41,51 @@ rect 21 54 22 57 rect 24 54 25 57 rect 29 54 30 57 rect 32 54 33 57 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 9 17 13 21 +rect 25 17 29 23 +rect 41 17 45 21 +<< pdcontact >> +rect 17 54 21 58 +rect 25 54 29 58 +rect 33 54 37 58 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 25 68 29 72 +<< polysilicon >> +rect 22 57 24 60 +rect 30 57 32 60 +rect 22 44 24 54 +rect 30 51 32 54 +rect 31 47 32 51 +rect 14 37 16 44 +rect 22 40 23 44 +rect 22 37 24 40 +rect 30 37 32 47 +rect 38 37 40 44 +rect 14 31 16 33 +rect 38 31 40 33 +rect 14 23 16 24 +rect 22 23 24 29 +rect 30 23 32 29 +rect 38 23 40 24 +rect 14 15 16 17 +rect 22 15 24 17 +rect 30 15 32 17 +rect 38 15 40 17 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -71,6 +107,17 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 +<< m2contact >> +rect 25 68 29 72 +rect 25 54 29 58 +rect 2 33 6 37 +rect 48 33 52 37 +rect 16 24 20 28 +rect 34 24 38 28 +rect 9 17 13 21 +rect 41 17 45 21 +rect 16 2 20 6 +rect 34 2 38 6 << metal2 >> rect 2 37 6 72 rect 2 0 6 33 @@ -80,47 +127,11 @@ rect 9 0 13 17 rect 16 6 20 24 rect 34 6 38 24 rect 41 21 45 72 -rect 48 37 52 72 rect 41 0 45 17 +rect 48 37 52 72 rect 48 0 52 33 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 25 17 29 23 -<< pdcontact >> -rect 17 54 21 58 -rect 33 54 37 58 -<< m2contact >> -rect 2 33 6 37 -rect 48 33 52 37 -rect 16 24 20 28 -rect 34 24 38 28 -rect 16 2 20 6 -rect 34 2 38 6 -<< psubstratepcontact >> -rect 25 9 29 13 +<< comment >> +rect 0 0 54 70 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd @@ -130,6 +141,6 @@ rlabel metal2 4 7 4 7 2 bl0 rlabel metal2 11 7 11 7 1 bl1 rlabel metal2 43 7 43 7 1 br1 rlabel metal2 50 7 50 7 8 br0 -rlabel metal1 19 49 19 49 1 Q -rlabel metal1 35 42 35 42 1 Q_bar +rlabel polycontact 29 49 29 49 1 Q +rlabel polycontact 25 42 25 42 1 Q_bar << end >> diff --git a/technology/scn4m_subm/mag_lib/cell_1w_1r.mag b/technology/scn4m_subm/mag_lib/cell_1w_1r.mag index 91d06069..71a3b1bc 100644 --- a/technology/scn4m_subm/mag_lib/cell_1w_1r.mag +++ b/technology/scn4m_subm/mag_lib/cell_1w_1r.mag @@ -1,31 +1,22 @@ magic tech scmos -timestamp 1572948787 -<< pwell >> -rect 0 0 54 46 +timestamp 1577067400 << nwell >> rect 0 46 54 75 -<< polysilicon >> -rect 22 57 24 60 -rect 30 57 32 60 -rect 22 44 24 54 -rect 30 51 32 54 -rect 31 47 32 51 -rect 14 37 16 44 -rect 22 40 23 44 -rect 22 37 24 40 -rect 30 37 32 47 -rect 38 37 40 44 -rect 14 31 16 33 -rect 38 31 40 33 -rect 14 23 16 24 -rect 22 23 24 29 -rect 30 23 32 29 -rect 38 23 40 24 -rect 14 15 16 17 -rect 22 15 24 17 -rect 30 15 32 17 -rect 38 15 40 17 +<< pwell >> +rect 0 0 54 46 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 << ndiffusion >> rect 13 33 14 37 rect 16 33 17 37 @@ -50,6 +41,51 @@ rect 21 54 22 57 rect 24 54 25 57 rect 29 54 30 57 rect 32 54 33 57 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 9 17 13 21 +rect 25 17 29 23 +rect 41 17 45 21 +<< pdcontact >> +rect 17 54 21 58 +rect 25 54 29 58 +rect 33 54 37 58 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 25 68 29 72 +<< polysilicon >> +rect 22 57 24 60 +rect 30 57 32 60 +rect 22 44 24 54 +rect 30 51 32 54 +rect 31 47 32 51 +rect 14 37 16 44 +rect 22 40 23 44 +rect 22 37 24 40 +rect 30 37 32 47 +rect 38 37 40 44 +rect 14 31 16 33 +rect 38 31 40 33 +rect 14 23 16 24 +rect 22 23 24 29 +rect 30 23 32 29 +rect 38 23 40 24 +rect 14 15 16 17 +rect 22 15 24 17 +rect 30 15 32 17 +rect 38 15 40 17 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -71,6 +107,17 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 +<< m2contact >> +rect 25 68 29 72 +rect 25 54 29 58 +rect 2 33 6 37 +rect 48 33 52 37 +rect 16 24 20 28 +rect 34 24 38 28 +rect 9 17 13 21 +rect 41 17 45 21 +rect 16 2 20 6 +rect 34 2 38 6 << metal2 >> rect 2 37 6 72 rect 2 0 6 33 @@ -80,47 +127,11 @@ rect 9 0 13 17 rect 16 6 20 24 rect 34 6 38 24 rect 41 21 45 72 -rect 48 37 52 72 rect 41 0 45 17 +rect 48 37 52 72 rect 48 0 52 33 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 25 17 29 23 -<< pdcontact >> -rect 17 54 21 58 -rect 33 54 37 58 -<< m2contact >> -rect 2 33 6 37 -rect 48 33 52 37 -rect 16 24 20 28 -rect 34 24 38 28 -rect 16 2 20 6 -rect 34 2 38 6 -<< psubstratepcontact >> -rect 25 9 29 13 +<< comment >> +rect 0 0 54 70 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd @@ -130,6 +141,6 @@ rlabel metal2 4 7 4 7 2 bl0 rlabel metal2 11 7 11 7 1 bl1 rlabel metal2 43 7 43 7 1 br1 rlabel metal2 50 7 50 7 8 br0 -rlabel metal1 19 49 19 49 1 Q -rlabel metal1 35 42 35 42 1 Q_bar +rlabel polycontact 29 49 29 49 1 Q +rlabel polycontact 25 42 25 42 1 Q_bar << end >> diff --git a/technology/scn4m_subm/mag_lib/cell_6t.mag b/technology/scn4m_subm/mag_lib/cell_6t.mag index 6b277af2..17206ac6 100644 --- a/technology/scn4m_subm/mag_lib/cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/cell_6t.mag @@ -1,28 +1,18 @@ magic tech scmos -timestamp 1572949512 -<< pwell >> -rect -8 -2 42 35 +timestamp 1577066121 << nwell >> rect -8 35 42 57 -<< polysilicon >> -rect 7 46 11 48 -rect 27 46 31 48 -rect 7 41 11 43 -rect 7 27 9 41 -rect 27 40 31 43 -rect 15 39 31 40 -rect 19 38 31 39 -rect 7 26 21 27 -rect 7 25 24 26 -rect 7 24 9 25 -rect 29 24 31 38 -rect 7 14 9 16 -rect 17 11 21 12 -rect 29 14 31 16 -rect -2 9 10 11 -rect 14 9 24 11 -rect 28 9 36 11 +<< pwell >> +rect -8 -2 42 35 +<< ntransistor >> +rect 7 16 9 24 +rect 29 16 31 24 +rect 10 9 14 11 +rect 24 9 28 11 +<< ptransistor >> +rect 7 43 11 46 +rect 27 43 31 46 << ndiffusion >> rect -2 22 7 24 rect 2 18 7 22 @@ -43,6 +33,45 @@ rect 2 43 7 46 rect 11 43 12 46 rect 26 43 27 46 rect 31 43 32 46 +<< ndcontact >> +rect -2 18 2 22 +rect 10 20 14 24 +rect 24 20 28 24 +rect 32 18 36 22 +rect 10 4 14 8 +rect 24 4 28 8 +<< pdcontact >> +rect -2 42 2 46 +rect 12 42 16 46 +rect 22 42 26 46 +rect 32 42 36 46 +<< psubstratepcontact >> +rect -2 28 2 32 +rect 32 28 36 32 +<< nsubstratencontact >> +rect 32 50 36 54 +<< polysilicon >> +rect 7 46 11 48 +rect 27 46 31 48 +rect 7 41 11 43 +rect 7 27 9 41 +rect 27 40 31 43 +rect 15 39 31 40 +rect 19 38 31 39 +rect 7 26 21 27 +rect 7 25 24 26 +rect 7 24 9 25 +rect 29 24 31 38 +rect 7 14 9 16 +rect 17 11 21 12 +rect 29 14 31 16 +rect -2 9 10 11 +rect 14 9 24 11 +rect 28 9 36 11 +<< polycontact >> +rect 15 35 19 39 +rect 21 26 25 30 +rect 17 12 21 16 << metal1 >> rect -2 50 15 54 rect 19 50 32 54 @@ -63,6 +92,12 @@ rect 32 22 36 28 rect -2 12 17 15 rect 21 12 36 15 rect -2 11 36 12 +<< m2contact >> +rect 15 50 19 54 +rect -2 35 2 39 +rect 32 35 36 39 +rect 6 4 10 8 +rect 20 4 24 8 << metal2 >> rect -2 39 2 54 rect -2 0 2 35 @@ -71,41 +106,8 @@ rect 6 0 10 4 rect 24 0 28 54 rect 32 39 36 54 rect 32 0 36 35 -<< ntransistor >> -rect 7 16 9 24 -rect 29 16 31 24 -rect 10 9 14 11 -rect 24 9 28 11 -<< ptransistor >> -rect 7 43 11 46 -rect 27 43 31 46 -<< polycontact >> -rect 15 35 19 39 -rect 21 26 25 30 -rect 17 12 21 16 -<< ndcontact >> -rect -2 18 2 22 -rect 10 20 14 24 -rect 24 20 28 24 -rect 32 18 36 22 -rect 10 4 14 8 -rect 24 4 28 8 -<< pdcontact >> -rect -2 42 2 46 -rect 12 42 16 46 -rect 22 42 26 46 -rect 32 42 36 46 -<< m2contact >> -rect 15 50 19 54 -rect -2 35 2 39 -rect 32 35 36 39 -rect 6 4 10 8 -rect 20 4 24 8 -<< psubstratepcontact >> -rect -2 28 2 32 -rect 32 28 36 32 -<< nsubstratencontact >> -rect 32 50 36 54 +<< bb >> +rect 0 0 34 52 << labels >> rlabel metal2 0 6 0 6 1 gnd rlabel metal2 34 6 34 6 1 gnd @@ -113,6 +115,6 @@ rlabel m2contact 17 52 17 52 5 vdd rlabel metal2 8 49 8 49 1 bl rlabel metal2 26 49 26 49 1 br rlabel metal1 4 13 4 13 1 wl -rlabel polycontact 23 28 23 28 1 Q_bar rlabel polycontact 17 37 17 37 1 Q +rlabel polycontact 23 28 23 28 1 Q_bar << end >> diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag index 79b5daf0..1931485f 100644 --- a/technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag +++ b/technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag @@ -1,10 +1,63 @@ magic tech scmos -timestamp 1572949567 -<< pwell >> -rect 0 0 54 46 +timestamp 1577067400 << nwell >> rect 0 46 54 75 +<< pwell >> +rect 0 0 54 46 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 +<< ndiffusion >> +rect 13 33 14 37 +rect 16 33 17 37 +rect 21 33 22 37 +rect 17 29 22 33 +rect 24 29 25 37 +rect 29 29 30 37 +rect 32 33 33 37 +rect 37 33 38 37 +rect 40 33 41 37 +rect 32 29 37 33 +rect 9 21 14 23 +rect 13 17 14 21 +rect 16 17 22 23 +rect 24 17 25 23 +rect 29 17 30 23 +rect 32 17 38 23 +rect 40 21 45 23 +rect 40 17 41 21 +<< pdiffusion >> +rect 21 54 22 57 +rect 24 54 25 57 +rect 29 54 30 57 +rect 32 54 33 57 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 9 17 13 21 +rect 25 17 29 23 +rect 41 17 45 21 +<< pdcontact >> +rect 17 54 21 58 +rect 25 54 29 58 +rect 33 54 37 58 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 25 68 29 72 << polysilicon >> rect 22 57 24 60 rect 30 57 32 60 @@ -26,30 +79,13 @@ rect 14 15 16 17 rect 22 15 24 17 rect 30 15 32 17 rect 38 15 40 17 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 21 14 23 -rect 13 17 14 21 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 21 45 23 -rect 40 17 41 21 -<< pdiffusion >> -rect 25 57 29 58 -rect 21 54 22 57 -rect 24 54 30 57 -rect 32 54 33 57 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -71,6 +107,13 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 +<< m2contact >> +rect 25 68 29 72 +rect 25 54 29 58 +rect 16 24 20 28 +rect 34 24 38 28 +rect 16 2 20 6 +rect 34 2 38 6 << metal2 >> rect 2 0 6 72 rect 9 0 13 72 @@ -79,48 +122,8 @@ rect 16 6 20 24 rect 34 6 38 24 rect 41 0 45 72 rect 48 0 52 72 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 9 17 13 21 -rect 25 17 29 23 -rect 41 17 45 21 -<< pdcontact >> -rect 17 54 21 58 -rect 33 54 37 58 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 16 24 20 28 -rect 34 24 38 28 -rect 16 2 20 6 -rect 34 2 38 6 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratendiff >> -rect 25 68 29 72 +<< comment >> +rect 0 0 54 70 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag b/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag index 9166b42a..1931485f 100644 --- a/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag +++ b/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag @@ -1,10 +1,63 @@ magic tech scmos -timestamp 1572949619 -<< pwell >> -rect 0 0 54 46 +timestamp 1577067400 << nwell >> rect 0 46 54 75 +<< pwell >> +rect 0 0 54 46 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 +<< ndiffusion >> +rect 13 33 14 37 +rect 16 33 17 37 +rect 21 33 22 37 +rect 17 29 22 33 +rect 24 29 25 37 +rect 29 29 30 37 +rect 32 33 33 37 +rect 37 33 38 37 +rect 40 33 41 37 +rect 32 29 37 33 +rect 9 21 14 23 +rect 13 17 14 21 +rect 16 17 22 23 +rect 24 17 25 23 +rect 29 17 30 23 +rect 32 17 38 23 +rect 40 21 45 23 +rect 40 17 41 21 +<< pdiffusion >> +rect 21 54 22 57 +rect 24 54 25 57 +rect 29 54 30 57 +rect 32 54 33 57 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 9 17 13 21 +rect 25 17 29 23 +rect 41 17 45 21 +<< pdcontact >> +rect 17 54 21 58 +rect 25 54 29 58 +rect 33 54 37 58 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 25 68 29 72 << polysilicon >> rect 22 57 24 60 rect 30 57 32 60 @@ -26,30 +79,13 @@ rect 14 15 16 17 rect 22 15 24 17 rect 30 15 32 17 rect 38 15 40 17 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 21 14 23 -rect 13 17 14 21 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 21 45 23 -rect 40 17 41 21 -<< pdiffusion >> -rect 25 57 29 58 -rect 21 54 22 57 -rect 24 54 30 57 -rect 32 54 33 57 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -71,6 +107,13 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 +<< m2contact >> +rect 25 68 29 72 +rect 25 54 29 58 +rect 16 24 20 28 +rect 34 24 38 28 +rect 16 2 20 6 +rect 34 2 38 6 << metal2 >> rect 2 0 6 72 rect 9 0 13 72 @@ -79,48 +122,8 @@ rect 16 6 20 24 rect 34 6 38 24 rect 41 0 45 72 rect 48 0 52 72 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 9 17 13 21 -rect 25 17 29 23 -rect 41 17 45 21 -<< pdcontact >> -rect 17 54 21 58 -rect 33 54 37 58 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 16 24 20 28 -rect 34 24 38 28 -rect 16 2 20 6 -rect 34 2 38 6 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratendiff >> -rect 25 68 29 72 +<< comment >> +rect 0 0 54 70 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag b/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag index 7f7591ba..515ef682 100644 --- a/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag @@ -1,28 +1,18 @@ magic tech scmos -timestamp 1572949665 -<< pwell >> -rect -8 -2 42 35 +timestamp 1577067400 << nwell >> rect -8 35 42 57 -<< polysilicon >> -rect 7 46 11 48 -rect 27 46 31 48 -rect 7 41 11 43 -rect 7 27 9 41 -rect 27 40 31 43 -rect 15 39 31 40 -rect 19 38 31 39 -rect 7 26 21 27 -rect 7 25 24 26 -rect 7 24 9 25 -rect 29 24 31 38 -rect 7 14 9 16 -rect 17 11 21 12 -rect 29 14 31 16 -rect -2 9 10 11 -rect 14 9 24 11 -rect 28 9 36 11 +<< pwell >> +rect -8 -2 42 35 +<< ntransistor >> +rect 7 16 9 24 +rect 29 16 31 24 +rect 10 9 14 11 +rect 24 9 28 11 +<< ptransistor >> +rect 7 43 11 46 +rect 27 43 31 46 << ndiffusion >> rect -2 22 7 24 rect 2 18 7 22 @@ -43,6 +33,45 @@ rect 2 43 7 46 rect 11 43 12 46 rect 26 43 27 46 rect 31 43 32 46 +<< ndcontact >> +rect -2 18 2 22 +rect 10 20 14 24 +rect 24 20 28 24 +rect 32 18 36 22 +rect 10 4 14 8 +rect 24 4 28 8 +<< pdcontact >> +rect -2 42 2 46 +rect 12 42 16 46 +rect 22 42 26 46 +rect 32 42 36 46 +<< psubstratepcontact >> +rect -2 28 2 32 +rect 32 28 36 32 +<< nsubstratencontact >> +rect 32 50 36 54 +<< polysilicon >> +rect 7 46 11 48 +rect 27 46 31 48 +rect 7 41 11 43 +rect 7 27 9 41 +rect 27 40 31 43 +rect 15 39 31 40 +rect 19 38 31 39 +rect 7 26 21 27 +rect 7 25 24 26 +rect 7 24 9 25 +rect 29 24 31 38 +rect 7 14 9 16 +rect 17 11 21 12 +rect 29 14 31 16 +rect -2 9 10 11 +rect 14 9 24 11 +rect 28 9 36 11 +<< polycontact >> +rect 15 35 19 39 +rect 21 26 25 30 +rect 17 12 21 16 << metal1 >> rect -2 50 15 54 rect 19 50 32 54 @@ -63,6 +92,10 @@ rect 32 22 36 28 rect -2 12 17 15 rect 21 12 36 15 rect -2 11 36 12 +<< m2contact >> +rect 15 50 19 54 +rect -2 35 2 39 +rect 32 35 36 39 << metal2 >> rect -2 39 2 54 rect -2 0 2 35 @@ -70,39 +103,8 @@ rect 6 0 10 54 rect 24 0 28 54 rect 32 39 36 54 rect 32 0 36 35 -<< ntransistor >> -rect 7 16 9 24 -rect 29 16 31 24 -rect 10 9 14 11 -rect 24 9 28 11 -<< ptransistor >> -rect 7 43 11 46 -rect 27 43 31 46 -<< polycontact >> -rect 15 35 19 39 -rect 21 26 25 30 -rect 17 12 21 16 -<< ndcontact >> -rect -2 18 2 22 -rect 10 20 14 24 -rect 24 20 28 24 -rect 32 18 36 22 -rect 10 4 14 8 -rect 24 4 28 8 -<< pdcontact >> -rect -2 42 2 46 -rect 12 42 16 46 -rect 22 42 26 46 -rect 32 42 36 46 -<< m2contact >> -rect 15 50 19 54 -rect -2 35 2 39 -rect 32 35 36 39 -<< psubstratepcontact >> -rect -2 28 2 32 -rect 32 28 36 32 -<< nsubstratencontact >> -rect 32 50 36 54 +<< bb >> +rect 0 0 34 52 << labels >> rlabel metal2 0 6 0 6 1 gnd rlabel metal2 34 6 34 6 1 gnd diff --git a/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag index 9b6e203b..982e1630 100644 --- a/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag +++ b/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag @@ -1,10 +1,63 @@ magic tech scmos -timestamp 1572949704 -<< pwell >> -rect 0 0 54 46 +timestamp 1577067400 << nwell >> rect 0 46 54 75 +<< pwell >> +rect 0 0 54 46 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 +<< ndiffusion >> +rect 13 33 14 37 +rect 16 33 17 37 +rect 21 33 22 37 +rect 17 29 22 33 +rect 24 29 25 37 +rect 29 29 30 37 +rect 32 33 33 37 +rect 37 33 38 37 +rect 40 33 41 37 +rect 32 29 37 33 +rect 9 21 14 23 +rect 13 17 14 21 +rect 16 17 22 23 +rect 24 17 25 23 +rect 29 17 30 23 +rect 32 17 38 23 +rect 40 21 45 23 +rect 40 17 41 21 +<< pdiffusion >> +rect 21 54 22 57 +rect 24 54 25 57 +rect 29 54 30 57 +rect 32 54 33 57 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 9 17 13 21 +rect 25 17 29 23 +rect 41 17 45 21 +<< pdcontact >> +rect 17 54 21 58 +rect 25 54 29 58 +rect 33 54 37 58 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 25 68 29 72 << polysilicon >> rect 22 57 24 60 rect 30 57 32 60 @@ -26,28 +79,13 @@ rect 14 15 16 17 rect 22 15 24 17 rect 30 15 32 17 rect 38 15 40 17 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 17 14 23 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 17 45 23 -<< pdiffusion >> -rect 25 57 29 58 -rect 21 54 22 57 -rect 24 54 30 57 -rect 32 54 33 57 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -70,6 +108,17 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 +<< m2contact >> +rect 25 68 29 72 +rect 25 54 29 58 +rect 2 33 6 37 +rect 48 33 52 37 +rect 16 24 20 28 +rect 34 24 38 28 +rect 9 17 13 21 +rect 41 17 45 21 +rect 16 2 20 6 +rect 34 2 38 6 << metal2 >> rect 2 37 6 72 rect 2 0 6 33 @@ -82,50 +131,8 @@ rect 41 21 45 72 rect 41 0 45 17 rect 48 37 52 72 rect 48 0 52 33 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 25 17 29 23 -<< pdcontact >> -rect 17 54 21 58 -rect 33 54 37 58 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 2 33 6 37 -rect 48 33 52 37 -rect 16 24 20 28 -rect 34 24 38 28 -rect 9 17 13 21 -rect 41 17 45 21 -rect 16 2 20 6 -rect 34 2 38 6 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratendiff >> -rect 25 68 29 72 +<< comment >> +rect 0 0 54 70 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd diff --git a/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag b/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag index b2a525e8..61add325 100644 --- a/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag +++ b/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag @@ -1,10 +1,63 @@ magic tech scmos -timestamp 1572949741 -<< pwell >> -rect 0 0 54 46 +timestamp 1577067446 << nwell >> rect 0 46 54 75 +<< pwell >> +rect 0 0 54 46 +<< ntransistor >> +rect 14 33 16 37 +rect 22 29 24 37 +rect 30 29 32 37 +rect 38 33 40 37 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 54 24 57 +rect 30 54 32 57 +<< ndiffusion >> +rect 13 33 14 37 +rect 16 33 17 37 +rect 21 33 22 37 +rect 17 29 22 33 +rect 24 29 25 37 +rect 29 29 30 37 +rect 32 33 33 37 +rect 37 33 38 37 +rect 40 33 41 37 +rect 32 29 37 33 +rect 9 21 14 23 +rect 13 17 14 21 +rect 16 17 22 23 +rect 24 17 25 23 +rect 29 17 30 23 +rect 32 17 38 23 +rect 40 21 45 23 +rect 40 17 41 21 +<< pdiffusion >> +rect 21 54 22 57 +rect 24 54 25 57 +rect 29 54 30 57 +rect 32 54 33 57 +<< ndcontact >> +rect 9 33 13 37 +rect 17 33 21 37 +rect 25 29 29 37 +rect 33 33 37 37 +rect 41 33 45 37 +rect 9 17 13 21 +rect 25 17 29 23 +rect 41 17 45 21 +<< pdcontact >> +rect 17 54 21 58 +rect 25 54 29 58 +rect 33 54 37 58 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 25 68 29 72 << polysilicon >> rect 22 57 24 60 rect 30 57 32 60 @@ -26,28 +79,13 @@ rect 14 15 16 17 rect 22 15 24 17 rect 30 15 32 17 rect 38 15 40 17 -<< ndiffusion >> -rect 13 33 14 37 -rect 16 33 17 37 -rect 21 33 22 37 -rect 17 29 22 33 -rect 24 29 25 37 -rect 29 29 30 37 -rect 32 33 33 37 -rect 37 33 38 37 -rect 40 33 41 37 -rect 32 29 37 33 -rect 9 17 14 23 -rect 16 17 22 23 -rect 24 17 25 23 -rect 29 17 30 23 -rect 32 17 38 23 -rect 40 17 45 23 -<< pdiffusion >> -rect 25 57 29 58 -rect 21 54 22 57 -rect 24 54 30 57 -rect 32 54 33 57 +<< polycontact >> +rect 27 47 31 51 +rect 10 40 14 44 +rect 23 40 27 44 +rect 40 40 44 44 +rect 12 24 16 28 +rect 38 24 42 28 << metal1 >> rect 0 68 25 72 rect 29 68 54 72 @@ -70,6 +108,17 @@ rect 29 9 54 13 rect 0 2 16 6 rect 20 2 34 6 rect 38 2 54 6 +<< m2contact >> +rect 25 68 29 72 +rect 25 54 29 58 +rect 2 33 6 37 +rect 48 33 52 37 +rect 16 24 20 28 +rect 34 24 38 28 +rect 9 17 13 21 +rect 41 17 45 21 +rect 16 2 20 6 +rect 34 2 38 6 << metal2 >> rect 2 37 6 72 rect 2 0 6 33 @@ -82,50 +131,8 @@ rect 41 21 45 72 rect 41 0 45 17 rect 48 37 52 72 rect 48 0 52 33 -<< ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 -rect 14 17 16 23 -rect 22 17 24 23 -rect 30 17 32 23 -rect 38 17 40 23 -<< ptransistor >> -rect 22 54 24 57 -rect 30 54 32 57 -<< polycontact >> -rect 27 47 31 51 -rect 10 40 14 44 -rect 23 40 27 44 -rect 40 40 44 44 -rect 12 24 16 28 -rect 38 24 42 28 -<< ndcontact >> -rect 9 33 13 37 -rect 17 33 21 37 -rect 25 29 29 37 -rect 33 33 37 37 -rect 41 33 45 37 -rect 25 17 29 23 -<< pdcontact >> -rect 17 54 21 58 -rect 33 54 37 58 -<< m2contact >> -rect 25 68 29 72 -rect 25 54 29 58 -rect 2 33 6 37 -rect 48 33 52 37 -rect 16 24 20 28 -rect 34 24 38 28 -rect 9 17 13 21 -rect 41 17 45 21 -rect 16 2 20 6 -rect 34 2 38 6 -<< psubstratepcontact >> -rect 25 9 29 13 -<< nsubstratendiff >> -rect 25 68 29 72 +<< comment >> +rect 0 0 54 70 << labels >> rlabel metal1 19 63 19 63 1 wl0 rlabel metal1 19 70 19 70 5 vdd diff --git a/technology/scn4m_subm/mag_lib/replica_cell_6t.mag b/technology/scn4m_subm/mag_lib/replica_cell_6t.mag index 316082ca..61a7646e 100644 --- a/technology/scn4m_subm/mag_lib/replica_cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/replica_cell_6t.mag @@ -1,28 +1,18 @@ magic tech scmos -timestamp 1572949776 -<< pwell >> -rect -8 -2 42 35 +timestamp 1577067503 << nwell >> rect -8 35 42 57 -<< polysilicon >> -rect 7 46 11 48 -rect 27 46 31 48 -rect 7 41 11 43 -rect 7 27 9 41 -rect 27 40 31 43 -rect 15 39 31 40 -rect 19 38 31 39 -rect 7 26 21 27 -rect 7 25 24 26 -rect 7 24 9 25 -rect 29 24 31 38 -rect 7 14 9 16 -rect 17 11 21 12 -rect 29 14 31 16 -rect -2 9 10 11 -rect 14 9 24 11 -rect 28 9 36 11 +<< pwell >> +rect -8 -2 42 35 +<< ntransistor >> +rect 7 16 9 24 +rect 29 16 31 24 +rect 10 9 14 11 +rect 24 9 28 11 +<< ptransistor >> +rect 7 43 11 46 +rect 27 43 31 46 << ndiffusion >> rect -2 22 7 24 rect 2 18 7 22 @@ -43,6 +33,45 @@ rect 2 43 7 46 rect 11 43 12 46 rect 26 43 27 46 rect 31 43 32 46 +<< ndcontact >> +rect -2 18 2 22 +rect 10 20 14 24 +rect 24 20 28 24 +rect 32 18 36 22 +rect 10 4 14 8 +rect 24 4 28 8 +<< pdcontact >> +rect -2 42 2 46 +rect 12 42 16 46 +rect 22 42 26 46 +rect 32 42 36 46 +<< psubstratepcontact >> +rect -2 28 2 32 +rect 32 28 36 32 +<< nsubstratencontact >> +rect 32 50 36 54 +<< polysilicon >> +rect 7 46 11 48 +rect 27 46 31 48 +rect 7 41 11 43 +rect 7 27 9 41 +rect 27 40 31 43 +rect 15 39 31 40 +rect 19 38 31 39 +rect 7 26 21 27 +rect 7 25 24 26 +rect 7 24 9 25 +rect 29 24 31 38 +rect 7 14 9 16 +rect 17 11 21 12 +rect 29 14 31 16 +rect -2 9 10 11 +rect 14 9 24 11 +rect 28 9 36 11 +<< polycontact >> +rect 15 35 19 39 +rect 21 26 25 30 +rect 17 12 21 16 << metal1 >> rect -2 50 15 54 rect 19 50 32 54 @@ -64,6 +93,12 @@ rect 32 22 36 28 rect -2 12 17 15 rect 21 12 36 15 rect -2 11 36 12 +<< m2contact >> +rect 15 50 19 54 +rect -2 35 2 39 +rect 32 35 36 39 +rect 6 4 10 8 +rect 20 4 24 8 << metal2 >> rect -2 39 2 54 rect -2 0 2 35 @@ -72,41 +107,8 @@ rect 6 0 10 4 rect 24 0 28 54 rect 32 39 36 54 rect 32 0 36 35 -<< ntransistor >> -rect 7 16 9 24 -rect 29 16 31 24 -rect 10 9 14 11 -rect 24 9 28 11 -<< ptransistor >> -rect 7 43 11 46 -rect 27 43 31 46 -<< polycontact >> -rect 15 35 19 39 -rect 21 26 25 30 -rect 17 12 21 16 -<< ndcontact >> -rect -2 18 2 22 -rect 10 20 14 24 -rect 24 20 28 24 -rect 32 18 36 22 -rect 10 4 14 8 -rect 24 4 28 8 -<< pdcontact >> -rect -2 42 2 46 -rect 12 42 16 46 -rect 22 42 26 46 -rect 32 42 36 46 -<< m2contact >> -rect 15 50 19 54 -rect -2 35 2 39 -rect 32 35 36 39 -rect 6 4 10 8 -rect 20 4 24 8 -<< psubstratepcontact >> -rect -2 28 2 32 -rect 32 28 36 32 -<< nsubstratencontact >> -rect 32 50 36 54 +<< bb >> +rect 0 0 34 52 << labels >> rlabel metal2 0 6 0 6 1 gnd rlabel metal2 34 6 34 6 1 gnd From 3ab99d7f9c3225672fa48af66477ef8ca985cdb4 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Tue, 24 Dec 2019 05:01:55 +0000 Subject: [PATCH 04/65] update gds library, generalize geometry reverse transform function --- compiler/base/geometry.py | 13 +++++---- compiler/bitcells/bitcell_base.py | 27 +++++++++--------- compiler/sram/sram_base.py | 8 +++--- technology/scn4m_subm/gds_lib/cell_6t.gds | Bin 5788 -> 5868 bytes technology/scn4m_subm/gds_lib/dff.gds | Bin 16622 -> 16622 bytes .../scn4m_subm/gds_lib/replica_cell_6t.gds | Bin 5868 -> 5948 bytes technology/scn4m_subm/gds_lib/sense_amp.gds | Bin 8312 -> 8312 bytes technology/scn4m_subm/gds_lib/tri_gate.gds | Bin 4576 -> 4576 bytes .../scn4m_subm/gds_lib/write_driver.gds | Bin 10204 -> 10204 bytes technology/scn4m_subm/mag_lib/cell_6t.mag | 2 +- 10 files changed, 26 insertions(+), 24 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 1c037fdf..46a7bd6e 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -256,18 +256,19 @@ class instance(geometry): new_pins.append(p) return new_pins - def reverse_bitcell_transformation(self): + def reverse_transformation(self, cell_name): path = [] - bitcell_paths = [] + cell_paths = [] pex_offsets = [] Q_offsets = [] Q_bar_offsets = [] def walk_subtree(node): path.append(node) - - if node.mod.name == 'pbitcell': - bitcell_paths.append(copy.copy(path)) + + if node.mod.name == cell_name: + print("bitcell found") + cell_paths.append(copy.copy(path)) Q_x = node.mod.get_normalized_storage_net_offset()[0][0] Q_y = node.mod.get_normalized_storage_net_offset()[0][1] @@ -338,7 +339,7 @@ class instance(geometry): return (uVector, vVector, origin) walk_subtree(self) - for path in bitcell_paths: + for path in cell_paths: vector_spaces = apply_path_transform(path) origin = vector_spaces[2] pex_offsets.append([origin[0], origin[1]]) diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index ea394548..3661abf7 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -10,7 +10,7 @@ import debug import design from globals import OPTS import logical_effort -from tech import parameter, drc +from tech import parameter, drc, layer class bitcell_base(design.design): @@ -85,14 +85,15 @@ class bitcell_base(design.design): Gets the location of the storage net labels to add top level labels for pex simulation. """ - #TODO: use getTexts to support custom bitcells # If we generated the bitcell, we already know where Q and Q_bar are - #if OPTS.bitcell is not "pbitcell": - # self.storage_net_offsets = [] - # for net in get_storage_net_names: - # if net is "Q" or "Q_bar": - # for text in self.getTexts("metal1"): - # self.storage_net_offsets.append(text.offsetInMicrons) + if OPTS.bitcell is not "pbitcell": + self.storage_net_offsets = [] + for i in range(0, len(self.get_storage_net_names())): + for text in self.gds.getTexts(layer["metal1"]): + if self.storage_nets[i] == text: + print(text) + + return(self.storage_net_offsets) def get_normalized_storage_net_offset(self): @@ -101,11 +102,11 @@ class bitcell_base(design.design): of the bitcell. This is useful for making sense of offsets outside of the bitcell. """ - - Q_x = self.storage_net_offsets[0][0] - self.leftmost_xpos - Q_y = self.storage_net_offsets[0][1] - self.botmost_ypos - Q_bar_x = self.storage_net_offsets[1][0] - self.leftmost_xpos - Q_bar_y = self.storage_net_offsets[1][1] - self.botmost_ypos + print("get normalized") + Q_x = self.get_storage_net_offset()[0][0] - self.leftmost_xpos + Q_y = self.get_storage_net_offset()[0][1] - self.botmost_ypos + Q_bar_x = self.get_storage_net_offset()[1][0] - self.leftmost_xpos + Q_bar_y = self.get_storage_net_offset()[1][1] - self.botmost_ypos normalized_storage_net_offset = [[Q_x,Q_y],[Q_bar_x,Q_bar_y]] diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index cd9fb19d..6a7e996e 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -94,21 +94,21 @@ class sram_base(design, verilog, lef): # add pex labels for bitcell for bank_num in range(0,len(self.bank_insts)): bank = self.bank_insts[bank_num] - pex_offsets = bank.reverse_bitcell_transformation() + pex_offsets = bank.reverse_transformation(bank.mod.bitcell.name) bank_offset = pex_offsets[0] # offset bank relative to sram Q_offset = pex_offsets[1] # offset of storage relative to bank Q_bar_offset = pex_offsets[2] # offset of storage relative to bank - layer = "metal1" + layer_name = "metal1" for i in range(0,len(bank_offset)): Q = [bank_offset[i][0] + Q_offset[i][0], bank_offset[i][1] + Q_offset[i][1]] Q_bar = [bank_offset[i][0] + Q_bar_offset[i][0], bank_offset[i][1] + Q_bar_offset[i][1]] - self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , layer, Q) - self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), layer, Q_bar) + self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , layer_name, Q) + self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), layer_name, Q_bar) # add pex labels for control logic for i in range (0,len(self.control_logic_insts)): diff --git a/technology/scn4m_subm/gds_lib/cell_6t.gds b/technology/scn4m_subm/gds_lib/cell_6t.gds index 14d6ab7e9697c2a197b595db62ac8c2e7db6d325..6bfc44317b701b019ff7e4dadbefdf591068e370 100644 GIT binary patch delta 118 zcmbQE`$kuZfsKKQftf*uk%^(4frmkYfrY`GK?u&aVBnjmq%Mk8Vq=_z*yI8+5guL- s1_qfI3~Z8Yfee$g#H3^de=snJK49Pi3dAQR7BMie2m&!X5VJ4<0F8_gBLDyZ delta 75 zcmaE(J4aWEfsKKQftf*uk%^%k$QESaXW(EEgR?mqq$Vn7D delta 88 zcmaE${6JZWfsKKQftf*uk%^&n*vXG#}WER0Y02G@KKmY&$ diff --git a/technology/scn4m_subm/gds_lib/write_driver.gds b/technology/scn4m_subm/gds_lib/write_driver.gds index 8223c795bae070e4d734e567c739a4440f0194ac..9e201f2402bc21fcd17da3b25c62a80d3ffc20b1 100644 GIT binary patch delta 64 zcmccPf5%^mfsKKQftf*uk%^(4fddG|7&I9~fovWIaiEL@1M@^BeL)PtjY(DN01eIu A=Kufz delta 64 vcmccPf5%^mfsKKQftf*uk%^(4fddHn88jJ0;cP7izKKfuf*67uld9AK4w?uD diff --git a/technology/scn4m_subm/mag_lib/cell_6t.mag b/technology/scn4m_subm/mag_lib/cell_6t.mag index 17206ac6..e8c16eff 100644 --- a/technology/scn4m_subm/mag_lib/cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/cell_6t.mag @@ -1,6 +1,6 @@ magic tech scmos -timestamp 1577066121 +timestamp 1577163318 << nwell >> rect -8 35 42 57 << pwell >> From 05ab018ffc31ce90a7fa04e801a4b2d2c0c63387 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Tue, 7 Jan 2020 00:01:32 +0000 Subject: [PATCH 05/65] strip padding character from gds reading --- compiler/bitcells/bitcell_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 3661abf7..62bcf1bb 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -90,8 +90,8 @@ class bitcell_base(design.design): self.storage_net_offsets = [] for i in range(0, len(self.get_storage_net_names())): for text in self.gds.getTexts(layer["metal1"]): - if self.storage_nets[i] == text: - print(text) + if self.storage_nets[i] == text.textString.rstrip('\x00'): + print(text.textString + "sucess") return(self.storage_net_offsets) From 2733c3bf3fe2acd23b6d89f9a8e7ca2c27b8e326 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Wed, 15 Jan 2020 09:00:02 +0000 Subject: [PATCH 06/65] fix custom bitcell labeling; fix gds scaling in labeling --- compiler/base/geometry.py | 11 ++++---- compiler/bitcells/bitcell.py | 4 +-- compiler/bitcells/bitcell_base.py | 25 ++++++++++++------- technology/scn4m_subm/sp_lib/cell_6t.sp | 10 ++++---- technology/scn4m_subm/sp_lib/dummy_cell_6t.sp | 10 ++++---- 5 files changed, 34 insertions(+), 26 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 46a7bd6e..885b139a 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -267,14 +267,15 @@ class instance(geometry): path.append(node) if node.mod.name == cell_name: - print("bitcell found") cell_paths.append(copy.copy(path)) + + normalized_storage_nets = node.mod.get_normalized_storage_nets_offset() - Q_x = node.mod.get_normalized_storage_net_offset()[0][0] - Q_y = node.mod.get_normalized_storage_net_offset()[0][1] + Q_x = normalized_storage_nets[0][0] + Q_y = normalized_storage_nets[0][1] - Q_bar_x = node.mod.get_normalized_storage_net_offset()[1][0] - Q_bar_y = node.mod.get_normalized_storage_net_offset()[1][1] + Q_bar_x = normalized_storage_nets[1][0] + Q_bar_y = normalized_storage_nets[1][1] if node.mirror == 'MX': Q_y = -1 * Q_y diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index b22c9a46..52552413 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -18,9 +18,9 @@ class bitcell(bitcell_base.bitcell_base): the layout and netlist should be available in the technology library. """ - + pin_names = ["bl", "br", "wl", "vdd", "gnd"] - storage_nets = ['Q', 'Qbar'] + storage_nets = ['Q', 'Q_bar'] type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] (width, height) = utils.get_libcell_size("cell_6t", GDS["unit"], diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 62bcf1bb..0a5624bd 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -88,27 +88,34 @@ class bitcell_base(design.design): # If we generated the bitcell, we already know where Q and Q_bar are if OPTS.bitcell is not "pbitcell": self.storage_net_offsets = [] - for i in range(0, len(self.get_storage_net_names())): + for i in range(len(self.get_storage_net_names())): for text in self.gds.getTexts(layer["metal1"]): if self.storage_nets[i] == text.textString.rstrip('\x00'): - print(text.textString + "sucess") + self.storage_net_offsets.append(text.coordinates[0]) + for i in range(len(self.storage_net_offsets)): + self.storage_net_offsets[i] = tuple([self.gds.info["units"][0] * x for x in self.storage_net_offsets[i]]) + return(self.storage_net_offsets) - def get_normalized_storage_net_offset(self): + def get_normalized_storage_nets_offset(self): """ Convert storage net offset to be relative to the bottom left corner of the bitcell. This is useful for making sense of offsets outside of the bitcell. """ - print("get normalized") - Q_x = self.get_storage_net_offset()[0][0] - self.leftmost_xpos - Q_y = self.get_storage_net_offset()[0][1] - self.botmost_ypos - Q_bar_x = self.get_storage_net_offset()[1][0] - self.leftmost_xpos - Q_bar_y = self.get_storage_net_offset()[1][1] - self.botmost_ypos + if OPTS.bitcell is not "pbitcell": + normalized_storage_net_offset = self.get_storage_net_offset() - normalized_storage_net_offset = [[Q_x,Q_y],[Q_bar_x,Q_bar_y]] + else: + net_offset = self.get_storage_net_offset() + Q_x = net_offset[0][0] - self.leftmost_xpos + Q_y = net_offset[0][1] - self.botmost_ypos + Q_bar_x = net_offset[1][0] - self.leftmost_xpos + Q_bar_y = net_offset[1][1] - self.botmost_ypos + + normalized_storage_net_offset = [[Q_x,Q_y],[Q_bar_x,Q_bar_y]] return normalized_storage_net_offset diff --git a/technology/scn4m_subm/sp_lib/cell_6t.sp b/technology/scn4m_subm/sp_lib/cell_6t.sp index bb430893..dc724007 100644 --- a/technology/scn4m_subm/sp_lib/cell_6t.sp +++ b/technology/scn4m_subm/sp_lib/cell_6t.sp @@ -4,15 +4,15 @@ * SPICE3 file created from cell_6t.ext - technology: scmos * Inverter 1 -M1000 Q Qbar vdd vdd p w=0.6u l=0.8u -M1002 Q Qbar gnd gnd n w=1.6u l=0.4u +M1000 Q Q_bar vdd vdd p w=0.6u l=0.8u +M1002 Q Q_bar gnd gnd n w=1.6u l=0.4u * Inverter 2 -M1001 vdd Q Qbar vdd p w=0.6u l=0.8u -M1003 gnd Q Qbar gnd n w=1.6u l=0.4u +M1001 vdd Q Q_bar vdd p w=0.6u l=0.8u +M1003 gnd Q Q_bar gnd n w=1.6u l=0.4u * Access transistors M1004 Q wl bl gnd n w=0.8u l=0.4u -M1005 Qbar wl br gnd n w=0.8u l=0.4u +M1005 Q_bar wl br gnd n w=0.8u l=0.4u .ENDS diff --git a/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp b/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp index 3b0584df..c5b6ff9d 100644 --- a/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp +++ b/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp @@ -3,15 +3,15 @@ .SUBCKT dummy_cell_6t bl br wl vdd gnd * Inverter 1 -M1000 Q Qbar vdd vdd p w=0.6u l=0.8u -M1002 Q Qbar gnd gnd n w=1.6u l=0.4u +M1000 Q Q_bar vdd vdd p w=0.6u l=0.8u +M1002 Q Q_bar gnd gnd n w=1.6u l=0.4u * Inverter 2 -M1001 vdd Q Qbar vdd p w=0.6u l=0.8u -M1003 gnd Q Qbar gnd n w=1.6u l=0.4u +M1001 vdd Q Q_bar vdd p w=0.6u l=0.8u +M1003 gnd Q Q_bar gnd n w=1.6u l=0.4u * Access transistors M1004 Q wl bl_noconn gnd n w=0.8u l=0.4u -M1005 Qbar wl br_noconn gnd n w=0.8u l=0.4u +M1005 Q_bar wl br_noconn gnd n w=0.8u l=0.4u .ENDS From 075bf0d841c2c8413fe114d732941baba5e1785c Mon Sep 17 00:00:00 2001 From: jcirimel Date: Thu, 16 Jan 2020 03:51:29 -0800 Subject: [PATCH 07/65] label bitcell in stim, add s_en top level to stim --- compiler/characterizer/delay.py | 7 +++++-- compiler/characterizer/stimuli.py | 10 ++++++---- compiler/sram/sram_1bank.py | 3 +++ compiler/verify/magic.py | 20 +++++++++++++------- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index e64f9515..60039f89 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -221,8 +221,9 @@ class delay(simulation): q_name = cell_name+'.'+str(storage_names[0]) qbar_name = cell_name+'.'+str(storage_names[1]) else: - q_name = "bitcell_Q_r{0}_c{1}".format(OPTS.num_words -1, OPTS.word_size-1) - qbar_name = "bitcell_Q_r{0}_c{1}".format(OPTS.num_words -1, OPTS.word_size-1) + bank_num = self.sram.get_bank_num(self.sram.name, bit_row, bit_col) + q_name = "bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, bit_row, bit_col) + qbar_name = "bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, bit_row, bit_col) # Bit measures, measurements times to be defined later. The measurement names must be unique # but they is enforced externally @@ -284,6 +285,8 @@ class delay(simulation): debug.check(len(sa_mods) == 1, "Only expected one type of Sense Amp. Cannot perform s_en checks.") enable_name = sa_mods[0].get_enable_name() sen_name = self.get_alias_in_path(paths, enable_name, sa_mods[0]) + if OPTS.use_pex: + #get sense amp multi bank return sen_name def get_bl_name(self, paths, port): diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index e565fb5f..5d08fbf9 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -52,10 +52,12 @@ class stimuli(): for pin in pins: self.sf.write("{0} ".format(pin)) if OPTS.use_pex: - for row in range(0,OPTS.num_words): - for col in range(0,OPTS.word_size): - self.sf.write("bitcell_Q_r{0}_c{1} ".format(row,col)) - self.sf.write("bitcell_Q_bar_r{0}_c{1} ".format(row,col)) + for bank in range(OPTS.num_banks): + for row in range(OPTS.num_words): + for col in range(OPTS.word_size): + self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) + self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) + self.sf.write("s_en{0} ".format(bank)) self.sf.write("{0}\n".format(model_name)) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 9e578c7c..c07b43e5 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -489,3 +489,6 @@ class sram_1bank(sram_base): if inst_name.find('x') != 0: inst_name = 'x'+inst_name return self.bank_inst.mod.get_cell_name(inst_name+'.x'+self.bank_inst.name, row, col) + + def get_bank_num(self, inst_name, row, col): + return 0; diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index fb0bc452..fa219e77 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -309,7 +309,7 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False): out_errors = find_error(results) debug.check(os.path.isfile(output),"Couldn't find PEX extracted output.") - #correct_port(name,output,sp_name) + correct_port(name,output,sp_name) return out_errors def write_batch_pex_rule(gds_name,name,sp_name,output): @@ -375,7 +375,7 @@ def write_script_pex_rule(gds_name,cell_name,output): else: pre = "" f.write(pre+"extract\n".format(cell_name)) - f.write(pre+"ext2spice hierarchy on\n") + f.write(pre+"ext2spice hierarchy off\n") f.write(pre+"ext2spice format ngspice\n") f.write(pre+"ext2spice renumber off\n") f.write(pre+"ext2spice scale off\n") @@ -414,14 +414,20 @@ def correct_port(name, output_file_name, ref_file_name): part2 = pex_file.read() bitcell_list = "+ " - for row in range(0,OPTS.num_words): - for col in range(0,OPTS.word_size): - bitcell_list += "bitcell_Q_r{0}_c{1} ".format(row,col) - bitcell_list += "bitcell_Q_bar_r{0}_c{1} ".format(row,col) + for bank in range(OPTS.num_banks): + for row in range(OPTS.num_words): + for col in range(OPTS.word_size): + bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank, row,col) + bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank, row,col) bitcell_list += "\n" + control_list = "+ " + for bank in range(OPTS.num_banks): + control_list += "s_en{0}".format(bank) + control_list += '\n' + + part2 = bitcell_list + control_list + part2 - part2 = bitcell_list + part2 pex_file.close() # obtain the correct definition line from the original spice file From 364842569a0dec098bdb51bd64dedfa630d6317e Mon Sep 17 00:00:00 2001 From: jcirimel Date: Thu, 16 Jan 2020 12:16:49 -0800 Subject: [PATCH 08/65] fix s_en in stim --- compiler/characterizer/delay.py | 2 +- compiler/sram/sram_1bank.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 60039f89..f53e91a6 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -286,7 +286,7 @@ class delay(simulation): enable_name = sa_mods[0].get_enable_name() sen_name = self.get_alias_in_path(paths, enable_name, sa_mods[0]) if OPTS.use_pex: - #get sense amp multi bank + sen_name = sen_name.split('.')[-1] return sen_name def get_bl_name(self, paths, port): diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index c07b43e5..a141765b 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -480,7 +480,7 @@ class sram_1bank(sram_base): debug.error("Signal={} not contained in control logic connections={}"\ .format(sen_name, control_conns)) if sen_name in self.pins: - debug.error("Internal signal={} contained in port list. Name defined by the parent.") + debug.error("Internal signal={} contained in port list. Name defined by the parent.") return "X{}.{}".format(sram_name, sen_name) def get_cell_name(self, inst_name, row, col): From 5778901cfe84219f722879ae09aa79f6476b1024 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Mon, 20 Jan 2020 12:16:30 +0000 Subject: [PATCH 09/65] pull bitline labels to top level spice --- compiler/base/geometry.py | 122 ++++++++++++++++-------------- compiler/bitcells/bitcell_base.py | 15 ++++ compiler/sram/sram_base.py | 27 +++++-- 3 files changed, 101 insertions(+), 63 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 885b139a..0fef7b72 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -255,13 +255,64 @@ class instance(geometry): p.transform(self.offset,self.mirror,self.rotate) new_pins.append(p) return new_pins + + def calculate_transform(self, node): + #set up the rotation matrix + angle = math.radians(float(node.rotate)) + mRotate = np.array([[math.cos(angle),-math.sin(angle),0.0], + [math.sin(angle),math.cos(angle),0.0], + [0.0,0.0,1.0]]) - def reverse_transformation(self, cell_name): + #set up translation matrix + translateX = float(node.offset[0]) + translateY = float(node.offset[1]) + mTranslate = np.array([[1.0,0.0,translateX], + [0.0,1.0,translateY], + [0.0,0.0,1.0]]) + + #set up the scale matrix (handles mirror X) + scaleX = 1.0 + if(node.mirror == 'MX'): + scaleY = -1.0 + else: + scaleY = 1.0 + mScale = np.array([[scaleX,0.0,0.0], + [0.0,scaleY,0.0], + [0.0,0.0,1.0]]) + + return (mRotate, mScale, mTranslate) + + def apply_transform(self, mtransforms, uVector, vVector, origin): + origin = np.dot(mtransforms[0], origin) #rotate + uVector = np.dot(mtransforms[0], uVector) #rotate + vVector = np.dot(mtransforms[0], vVector) #rotate + origin = np.dot(mtransforms[1], origin) #scale + uVector = np.dot(mtransforms[1], uVector) #scale + vVector = np.dot(mtransforms[1], vVector) #scale + origin = np.dot(mtransforms[2], origin) + + return(uVector, vVector, origin) + + def apply_path_transform(self, path): + uVector = np.array([[1.0],[0.0],[0.0]]) + vVector = np.array([[0.0],[1.0],[0.0]]) + origin = np.array([[0.0],[0.0],[1.0]]) + + while(path): + instance = path.pop(-1) + mtransforms = self.calculate_transform(instance) + (uVector, vVector, origin) = self.apply_transform(mtransforms, uVector, vVector, origin) + + return (uVector, vVector, origin) + + def reverse_transformation_bitcell(self, cell_name): path = [] cell_paths = [] - pex_offsets = [] + origin_offsets = [] Q_offsets = [] Q_bar_offsets = [] + bl_offsets = [] + br_offsets = [] def walk_subtree(node): path.append(node) @@ -270,6 +321,7 @@ class instance(geometry): cell_paths.append(copy.copy(path)) normalized_storage_nets = node.mod.get_normalized_storage_nets_offset() + normalized_bitline_nets = node.mod.get_normalized_bitline_offset() Q_x = normalized_storage_nets[0][0] Q_y = normalized_storage_nets[0][1] @@ -277,75 +329,35 @@ class instance(geometry): Q_bar_x = normalized_storage_nets[1][0] Q_bar_y = normalized_storage_nets[1][1] + bl_x = normalized_bitline_nets[0][0] + bl_y = normalized_bitline_nets[0][1] + + br_x = normalized_bitline_nets[1][0] + br_y = normalized_bitline_nets[1][1] + if node.mirror == 'MX': Q_y = -1 * Q_y Q_bar_y = -1 * Q_bar_y + bl_y = -1 * bl_y + br_y = -1 * br_y Q_offsets.append([Q_x, Q_y]) Q_bar_offsets.append([Q_bar_x, Q_bar_y]) - + bl_offsets.append([bl_x, bl_y]) + br_offsets.append([br_x, br_y]) elif node.mod.insts is not []: for instance in node.mod.insts: walk_subtree(instance) path.pop(-1) - def calculate_transform(node): - #set up the rotation matrix - angle = math.radians(float(node.rotate)) - mRotate = np.array([[math.cos(angle),-math.sin(angle),0.0], - [math.sin(angle),math.cos(angle),0.0], - [0.0,0.0,1.0]]) - - #set up translation matrix - translateX = float(node.offset[0]) - translateY = float(node.offset[1]) - mTranslate = np.array([[1.0,0.0,translateX], - [0.0,1.0,translateY], - [0.0,0.0,1.0]]) - - #set up the scale matrix (handles mirror X) - scaleX = 1.0 - if(node.mirror == 'MX'): - scaleY = -1.0 - else: - scaleY = 1.0 - mScale = np.array([[scaleX,0.0,0.0], - [0.0,scaleY,0.0], - [0.0,0.0,1.0]]) - - return (mRotate, mScale, mTranslate) - - def apply_transform(mtransforms, uVector, vVector, origin): - origin = np.dot(mtransforms[0], origin) #rotate - uVector = np.dot(mtransforms[0], uVector) #rotate - vVector = np.dot(mtransforms[0], vVector) #rotate - origin = np.dot(mtransforms[1], origin) #scale - uVector = np.dot(mtransforms[1], uVector) #scale - vVector = np.dot(mtransforms[1], vVector) #scale - origin = np.dot(mtransforms[2], origin) - - return(uVector, vVector, origin) - - def apply_path_transform(path): - uVector = np.array([[1.0],[0.0],[0.0]]) - vVector = np.array([[0.0],[1.0],[0.0]]) - origin = np.array([[0.0],[0.0],[1.0]]) - - while(path): - instance = path.pop(-1) - mtransforms = calculate_transform(instance) - (uVector, vVector, origin) = apply_transform(mtransforms, uVector, vVector, origin) - - return (uVector, vVector, origin) - walk_subtree(self) for path in cell_paths: - vector_spaces = apply_path_transform(path) + vector_spaces = self.apply_path_transform(path) origin = vector_spaces[2] - pex_offsets.append([origin[0], origin[1]]) + origin_offsets.append([origin[0], origin[1]]) - return(pex_offsets, Q_offsets, Q_bar_offsets) + return(origin_offsets, Q_offsets, Q_bar_offsets, bl_offsets, br_offsets) def __str__(self): """ override print function output """ diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 0a5624bd..56c36b66 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -99,6 +99,19 @@ class bitcell_base(design.design): return(self.storage_net_offsets) + def get_bitline_offset(self): + self.bitline_names = ["bl", "br"] + self.bitline_offsets = [] + for i in range(len(self.bitline_names)): + for text in self.gds.getTexts(layer["metal2"]): + if self.bitline_names[i] == text.textString.rstrip('\x00'): + self.bitline_offsets.append(text.coordinates[0]) + + for i in range(len(self.bitline_offsets)): + self.bitline_offsets[i] = tuple([self.gds.info["units"][0] * x for x in self.bitline_offsets[i]]) + + return(self.bitline_offsets) + def get_normalized_storage_nets_offset(self): """ Convert storage net offset to be relative to the bottom left corner @@ -119,6 +132,8 @@ class bitcell_base(design.design): return normalized_storage_net_offset + def get_normalized_bitline_offset(self): + return self.get_bitline_offset() def build_graph(self, graph, inst_name, port_nets): """ diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 6a7e996e..1a8d220b 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -91,34 +91,45 @@ class sram_base(design, verilog, lef): Add pex labels at the sram level for spice analysis """ - # add pex labels for bitcell - for bank_num in range(0,len(self.bank_insts)): + # add pex labels for bitcells + for bank_num in range(len(self.bank_insts)): bank = self.bank_insts[bank_num] - pex_offsets = bank.reverse_transformation(bank.mod.bitcell.name) + pex_offsets = bank.reverse_transformation_bitcell(bank.mod.bitcell.name) bank_offset = pex_offsets[0] # offset bank relative to sram Q_offset = pex_offsets[1] # offset of storage relative to bank Q_bar_offset = pex_offsets[2] # offset of storage relative to bank + bl_offsets = pex_offsets[3] + br_offsets = pex_offsets[4] - layer_name = "metal1" + storage_layer_name = "metal1" + bitline_layer_name = "metal2" for i in range(0,len(bank_offset)): Q = [bank_offset[i][0] + Q_offset[i][0], bank_offset[i][1] + Q_offset[i][1]] Q_bar = [bank_offset[i][0] + Q_bar_offset[i][0], bank_offset[i][1] + Q_bar_offset[i][1]] + bl = [bank_offset[i][0] + bl_offsets[i][0], bank_offset[i][1] + bl_offsets[i][1]] + br = [bank_offset[i][0] + br_offsets[i][0], bank_offset[i][1] + br_offsets[i][1]] - self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , layer_name, Q) - self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), layer_name, Q_bar) + self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , storage_layer_name, Q) + self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), storage_layer_name, Q_bar) + + self.add_layout_pin_rect_center("bitcell_bl_b{0}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) + self.add_layout_pin_rect_center("bitcell_br_b{0}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) + + + # add pex labels for control logic - for i in range (0,len(self.control_logic_insts)): + for i in range (len(self.control_logic_insts)): instance = self.control_logic_insts[i] control_logic_offset = instance.offset for output in instance.mod.output_list: pin = instance.mod.get_pin(output) pin.transform([0,0], instance.mirror, instance.rotate) offset = [control_logic_offset[0] + pin.center()[0], control_logic_offset[1] + pin.center()[1]] - self.add_layout_pin_rect_center("{0}{1}".format(pin.name,i), "metal1", offset) + self.add_layout_pin_rect_center("{0}{1}".format(pin.name,i), storage_layer_name, offset) From 73691f60548d87791d70c3224f664c1c6d5a792c Mon Sep 17 00:00:00 2001 From: jcirimel Date: Tue, 21 Jan 2020 00:20:52 -0800 Subject: [PATCH 10/65] fix bug in top level bitline label placement --- compiler/bitcells/bitcell_base.py | 8 ++++++-- compiler/characterizer/delay.py | 5 ++++- compiler/characterizer/stimuli.py | 3 +++ compiler/sram/sram_base.py | 4 ++-- compiler/verify/magic.py | 3 +++ 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 56c36b66..f0f562c6 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -101,11 +101,15 @@ class bitcell_base(design.design): def get_bitline_offset(self): self.bitline_names = ["bl", "br"] + found_bitlines = [] self.bitline_offsets = [] for i in range(len(self.bitline_names)): for text in self.gds.getTexts(layer["metal2"]): - if self.bitline_names[i] == text.textString.rstrip('\x00'): - self.bitline_offsets.append(text.coordinates[0]) + if not self.bitline_names[i] in found_bitlines: + if self.bitline_names[i] == text.textString.rstrip('\x00'): + self.bitline_offsets.append(text.coordinates[0]) + found_bitlines.append(self.bitline_names[i]) + continue for i in range(len(self.bitline_offsets)): self.bitline_offsets[i] = tuple([self.gds.info["units"][0] * x for x in self.bitline_offsets[i]]) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index f53e91a6..3aa2765a 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -302,7 +302,10 @@ class delay(simulation): exclude_set = self.get_bl_name_search_exclusions() for int_net in [cell_bl, cell_br]: bl_names.append(self.get_alias_in_path(paths, int_net, cell_mod, exclude_set)) - + #if OPTS.use_pex: + # bank_num = 0 + # bl_names[0] = "bl_b{0}_{1}".format(bank_num, ) + # bl_names[1] = "br_b{0}_{1}".format(bank_num, ) return bl_names[0], bl_names[1] diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 5d08fbf9..28a02472 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -57,6 +57,9 @@ class stimuli(): for col in range(OPTS.word_size): self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) + for col in range(OPTS.word_size): + self.sf.write("bl_b{0}_c{2} ".format(bank, row,col)) + self.sf.write("br_b{0}_c{2} ".format(bank, row,col)) self.sf.write("s_en{0} ".format(bank)) self.sf.write("{0}\n".format(model_name)) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 1a8d220b..5fc510b7 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -115,8 +115,8 @@ class sram_base(design, verilog, lef): self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , storage_layer_name, Q) self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), storage_layer_name, Q_bar) - self.add_layout_pin_rect_center("bitcell_bl_b{0}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) - self.add_layout_pin_rect_center("bitcell_br_b{0}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) + self.add_layout_pin_rect_center("bl_b{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) + self.add_layout_pin_rect_center("br_b{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index fa219e77..29014797 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -419,6 +419,9 @@ def correct_port(name, output_file_name, ref_file_name): for col in range(OPTS.word_size): bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank, row,col) bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank, row,col) + for col in range(OPTS.word_size): + bitcell_list += "bl_b{0}_c{2} ".format(bank, row,col) + bitcell_list += "br_b{0}_c{2} ".format(bank, row,col) bitcell_list += "\n" control_list = "+ " From 40c01dab855bb651c0504f02503f02649743096a Mon Sep 17 00:00:00 2001 From: jcirimel Date: Tue, 21 Jan 2020 01:44:15 -0800 Subject: [PATCH 11/65] fix bl in stim file --- compiler/characterizer/delay.py | 16 ++++++++++------ compiler/characterizer/stimuli.py | 29 +++++++++++++++++++---------- compiler/sram/sram_base.py | 8 ++++++-- compiler/verify/magic.py | 8 ++++++-- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 3aa2765a..6ec3ae8a 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -302,10 +302,9 @@ class delay(simulation): exclude_set = self.get_bl_name_search_exclusions() for int_net in [cell_bl, cell_br]: bl_names.append(self.get_alias_in_path(paths, int_net, cell_mod, exclude_set)) - #if OPTS.use_pex: - # bank_num = 0 - # bl_names[0] = "bl_b{0}_{1}".format(bank_num, ) - # bl_names[1] = "br_b{0}_{1}".format(bank_num, ) + if OPTS.use_pex: + for i in range(len(bl_names)): + bl_names[i] = bl_names[i].split('.')[-1] return bl_names[0], bl_names[1] @@ -396,8 +395,13 @@ class delay(simulation): # instantiate the sram self.sf.write("\n* Instantiation of the SRAM\n") - self.stim.inst_model(pins=self.pins, - model_name=self.sram.name) + if not OPTS.use_pex: + self.stim.inst_model(pins=self.pins, + model_name=self.sram.name) + else: + self.stim.inst_sram_pex(pins=self.pins, + model_name=self.sram.name) + self.sf.write("\n* SRAM output loads\n") for port in self.read_ports: for i in range(self.word_size): diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 28a02472..f413d97b 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -51,18 +51,27 @@ class stimuli(): self.sf.write("X{0} ".format(model_name)) for pin in pins: self.sf.write("{0} ".format(pin)) - if OPTS.use_pex: - for bank in range(OPTS.num_banks): - for row in range(OPTS.num_words): - for col in range(OPTS.word_size): - self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) - self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) - for col in range(OPTS.word_size): - self.sf.write("bl_b{0}_c{2} ".format(bank, row,col)) - self.sf.write("br_b{0}_c{2} ".format(bank, row,col)) - self.sf.write("s_en{0} ".format(bank)) self.sf.write("{0}\n".format(model_name)) + + def inst_sram_pex(self, pins, model_name): + self.sf.write("X{0} ".format(model_name)) + for pin in pins: + self.sf.write("{0} ".format(pin)) + for bank in range(OPTS.num_banks): + for row in range(OPTS.num_words): + for col in range(OPTS.word_size): + self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) + self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) + for col in range(OPTS.word_size): + if OPTS.num_banks == 1: + self.sf.write("bl_{2} ".format(bank, row,col)) + self.sf.write("br_{2} ".format(bank, row,col)) + else: + self.sf.write("bl{0}_{2} ".format(bank, row,col)) + self.sf.write("br{0}_{2} ".format(bank, row,col)) + self.sf.write("s_en{0} ".format(bank)) + self.sf.write("{0}\n".format(model_name)) def create_inverter(self, size=1, beta=2.5): """ Generates inverter for the top level signals (only for sim purposes) """ diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 5fc510b7..dfe96697 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -115,8 +115,12 @@ class sram_base(design, verilog, lef): self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , storage_layer_name, Q) self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), storage_layer_name, Q_bar) - self.add_layout_pin_rect_center("bl_b{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) - self.add_layout_pin_rect_center("br_b{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) + if OPTS.num_banks == 1: + self.add_layout_pin_rect_center("bl_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) + self.add_layout_pin_rect_center("br_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) + else: + self.add_layout_pin_rect_center("bl{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) + self.add_layout_pin_rect_center("br{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 29014797..16f37bdc 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -420,8 +420,12 @@ def correct_port(name, output_file_name, ref_file_name): bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank, row,col) bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank, row,col) for col in range(OPTS.word_size): - bitcell_list += "bl_b{0}_c{2} ".format(bank, row,col) - bitcell_list += "br_b{0}_c{2} ".format(bank, row,col) + if OPTS.num_banks == 1: + bitcell_list += "bl_{2} ".format(bank, row,col) + bitcell_list += "br_{2} ".format(bank, row,col) + else: + bitcell_list += "bl{0}_{2} ".format(bank, row,col) + bitcell_list += "br{0}_{2} ".format(bank, row,col) bitcell_list += "\n" control_list = "+ " From 1062cbfd7f6f01d75d42f65116a0ef05cc527f1c Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Fri, 24 Jan 2020 10:24:29 +0000 Subject: [PATCH 12/65] begin fixes to pbitcell, prepare multibank pex --- compiler/base/geometry.py | 24 ++++++++++------- compiler/bitcells/bitcell_base.py | 44 ++++++++++++++++++++++--------- compiler/sram/sram_base.py | 36 +++++++++++++++---------- 3 files changed, 67 insertions(+), 37 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 0fef7b72..175ec0d3 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -321,7 +321,7 @@ class instance(geometry): cell_paths.append(copy.copy(path)) normalized_storage_nets = node.mod.get_normalized_storage_nets_offset() - normalized_bitline_nets = node.mod.get_normalized_bitline_offset() + (normalized_bl_offsets, normalized_br_offsets) = node.mod.get_normalized_bitline_offset() Q_x = normalized_storage_nets[0][0] Q_y = normalized_storage_nets[0][1] @@ -329,22 +329,26 @@ class instance(geometry): Q_bar_x = normalized_storage_nets[1][0] Q_bar_y = normalized_storage_nets[1][1] - bl_x = normalized_bitline_nets[0][0] - bl_y = normalized_bitline_nets[0][1] - - br_x = normalized_bitline_nets[1][0] - br_y = normalized_bitline_nets[1][1] if node.mirror == 'MX': Q_y = -1 * Q_y Q_bar_y = -1 * Q_bar_y - bl_y = -1 * bl_y - br_y = -1 * br_y + for pair in range(len(normalized_bl_offsets)): + for offset in range(len(offset)): + normalized_bl_offsets[pair][offset] = -1 * normalized_bl_offsets[pair][offset] + + for pair in range(len(normalized_br_offsets)): + for offset in range(len(offset)): + normalized_br_offsets[pair][offset] = -1 * normalized_br_offsets[pair][offset] + Q_offsets.append([Q_x, Q_y]) Q_bar_offsets.append([Q_bar_x, Q_bar_y]) - bl_offsets.append([bl_x, bl_y]) - br_offsets.append([br_x, br_y]) + + for offset in bl_offset: + bl_offsets.append(offset) + for offset in br.offset: + br_offsets.append(offset) elif node.mod.insts is not []: for instance in node.mod.insts: diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index f0f562c6..069f8f6c 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -100,21 +100,39 @@ class bitcell_base(design.design): return(self.storage_net_offsets) def get_bitline_offset(self): - self.bitline_names = ["bl", "br"] - found_bitlines = [] - self.bitline_offsets = [] - for i in range(len(self.bitline_names)): + + bl_names = self.get_all_bl_names() + br_names = self.get_all_br_names() + + found_bl = [] + found_br = [] + + self.bl_offsets = [] + self.br_offsets = [] + + for i in range(len(bl_names)): for text in self.gds.getTexts(layer["metal2"]): - if not self.bitline_names[i] in found_bitlines: - if self.bitline_names[i] == text.textString.rstrip('\x00'): - self.bitline_offsets.append(text.coordinates[0]) - found_bitlines.append(self.bitline_names[i]) + if not bl_names[i] in found_bl: + if bl_names[i] == text.textString.rstrip('\x00'): + self.bl_offsets.append(text.coordinates[0]) + found_bl.append(bl_names[i]) continue - - for i in range(len(self.bitline_offsets)): - self.bitline_offsets[i] = tuple([self.gds.info["units"][0] * x for x in self.bitline_offsets[i]]) - - return(self.bitline_offsets) + + for i in range(len(br_names)): + for text in self.gds.getTexts(layer["metal2"]): + if not br_names[i] in found_br: + if br_names[i] == text.textString.rstrip('\x00'): + self.br_offsets.append(text.coordinates[0]) + found_br.append(br_names[i]) + continue + + for i in range(len(self.bl_offsets)): + self.bl_offsets[i] = tuple([self.gds.info["units"][0] * x for x in self.bl_offsets[i]]) + + for i in range(len(self.br_offsets)): + self.br_offsets[i] = tuple([self.gds.info["units"][0] * x for x in self.br_offsets[i]]) + + return(self.bl_offsets, self.br_offsets) def get_normalized_storage_nets_offset(self): """ diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index dfe96697..762295d4 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -104,23 +104,31 @@ class sram_base(design, verilog, lef): storage_layer_name = "metal1" bitline_layer_name = "metal2" - - for i in range(0,len(bank_offset)): - Q = [bank_offset[i][0] + Q_offset[i][0], bank_offset[i][1] + Q_offset[i][1]] - Q_bar = [bank_offset[i][0] + Q_bar_offset[i][0], bank_offset[i][1] + Q_bar_offset[i][1]] - bl = [bank_offset[i][0] + bl_offsets[i][0], bank_offset[i][1] + bl_offsets[i][1]] - br = [bank_offset[i][0] + br_offsets[i][0], bank_offset[i][1] + br_offsets[i][1]] + Q = [bank_offset[bank_num][0] + Q_offset[bank_num][0], bank_offset[bank_num][1] + Q_offset[bank_num][1]] + Q_bar = [bank_offset[bank_num][0] + Q_bar_offset[bank_num][0], bank_offset[bank_num][1] + Q_bar_offset[bank_num][1]] + + bl = [] + br = [] - self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , storage_layer_name, Q) - self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), storage_layer_name, Q_bar) + for i in range(len(bl_offsets)): + bl.append([bank_offset[bank_num][1] + bl_offsets[bank_num][2*(i)], bank_offset[bank_num][1] + bl_offsets[bank_num][2*(i)+1]]) - if OPTS.num_banks == 1: + for i in range(len(br_offsets)): + br.append([bank_offset[bank_num][1] + br_offsets[bank_num][2*(i)], bank_offset[bank_num][1] + br_offsets[bank_num][2*(i)+1]]) + + self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , storage_layer_name, Q) + self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), storage_layer_name, Q_bar) + + if OPTS.num_banks == 1: + for i in range(len(bl_offsets)): self.add_layout_pin_rect_center("bl_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) + + for i in range(len(br_offsets)): self.add_layout_pin_rect_center("br_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) - else: - self.add_layout_pin_rect_center("bl{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) - self.add_layout_pin_rect_center("br{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) + else: + self.add_layout_pin_rect_center("bl{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) + self.add_layout_pin_rect_center("br{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) @@ -178,8 +186,8 @@ class sram_base(design, verilog, lef): highest_coord = self.find_highest_coords() self.width = highest_coord[0] self.height = highest_coord[1] - - self.add_global_pex_labels() + if OPTS.use_pex: + self.add_global_pex_labels() start_time = datetime.now() # We only enable final verification if we have routed the design From d42cd9a281f0f1f96f3dc9a5979e882d1343c2be Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Mon, 27 Jan 2020 10:03:31 +0000 Subject: [PATCH 13/65] pbitcell working with bitline adjustments --- compiler/base/geometry.py | 18 ++++++------ compiler/characterizer/stimuli.py | 4 --- compiler/sram/sram_base.py | 48 +++++++++++++++++-------------- compiler/verify/magic.py | 6 +--- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 175ec0d3..3b2eb2d3 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -333,22 +333,22 @@ class instance(geometry): if node.mirror == 'MX': Q_y = -1 * Q_y Q_bar_y = -1 * Q_bar_y + for pair in range(len(normalized_bl_offsets)): - for offset in range(len(offset)): - normalized_bl_offsets[pair][offset] = -1 * normalized_bl_offsets[pair][offset] + normalized_bl_offsets[pair] = (normalized_bl_offsets[pair][0], + -1 * normalized_bl_offsets[pair][1]) for pair in range(len(normalized_br_offsets)): - for offset in range(len(offset)): - normalized_br_offsets[pair][offset] = -1 * normalized_br_offsets[pair][offset] + normalized_br_offsets[pair] = (normalized_br_offsets[pair][0], + -1 * normalized_br_offsets[pair][1]) Q_offsets.append([Q_x, Q_y]) Q_bar_offsets.append([Q_bar_x, Q_bar_y]) - for offset in bl_offset: - bl_offsets.append(offset) - for offset in br.offset: - br_offsets.append(offset) + + bl_offsets.append(normalized_bl_offsets) + br_offsets.append(normalized_br_offsets) elif node.mod.insts is not []: for instance in node.mod.insts: @@ -360,7 +360,7 @@ class instance(geometry): vector_spaces = self.apply_path_transform(path) origin = vector_spaces[2] origin_offsets.append([origin[0], origin[1]]) - + return(origin_offsets, Q_offsets, Q_bar_offsets, bl_offsets, br_offsets) def __str__(self): diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index f413d97b..b4cd00f4 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -63,10 +63,6 @@ class stimuli(): self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) for col in range(OPTS.word_size): - if OPTS.num_banks == 1: - self.sf.write("bl_{2} ".format(bank, row,col)) - self.sf.write("br_{2} ".format(bank, row,col)) - else: self.sf.write("bl{0}_{2} ".format(bank, row,col)) self.sf.write("br{0}_{2} ".format(bank, row,col)) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 762295d4..2c66924a 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -19,6 +19,7 @@ from verilog import verilog from lef import lef from sram_factory import factory from tech import drc +import numpy as np import logical_effort class sram_base(design, verilog, lef): @@ -102,33 +103,38 @@ class sram_base(design, verilog, lef): bl_offsets = pex_offsets[3] br_offsets = pex_offsets[4] - storage_layer_name = "metal1" - bitline_layer_name = "metal2" - - Q = [bank_offset[bank_num][0] + Q_offset[bank_num][0], bank_offset[bank_num][1] + Q_offset[bank_num][1]] - Q_bar = [bank_offset[bank_num][0] + Q_bar_offset[bank_num][0], bank_offset[bank_num][1] + Q_bar_offset[bank_num][1]] - bl = [] br = [] - for i in range(len(bl_offsets)): - bl.append([bank_offset[bank_num][1] + bl_offsets[bank_num][2*(i)], bank_offset[bank_num][1] + bl_offsets[bank_num][2*(i)+1]]) + storage_layer_name = "metal1" + bitline_layer_name = "metal2" + + for cell in range(len(bank_offset)): + Q = [bank_offset[cell][0] + Q_offset[cell][0], bank_offset[cell][1] + Q_offset[cell][1]] + Q_bar = [bank_offset[cell][0] + Q_bar_offset[cell][0], bank_offset[cell][1] + Q_bar_offset[cell][1]] - for i in range(len(br_offsets)): - br.append([bank_offset[bank_num][1] + br_offsets[bank_num][2*(i)], bank_offset[bank_num][1] + br_offsets[bank_num][2*(i)+1]]) + self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, cell % OPTS.num_words, int(cell / OPTS.num_words)) , storage_layer_name, Q) + self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, cell % OPTS.num_words, int(cell / OPTS.num_words)), storage_layer_name, Q_bar) + + for bitline in range(len(bl_offsets[cell])): + bitline_location = [float(bank_offset[cell][0]) + bl_offsets[cell][bitline][0], float(bank_offset[cell][1]) + bl_offsets[cell][bitline][1]] + bl.append(bitline_location) - self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , storage_layer_name, Q) - self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), storage_layer_name, Q_bar) + for bitline in range(len(br_offsets[0])): + bitline_location = [float(bank_offset[cell][0]) + br_offsets[cell][bitline][0], float(bank_offset[cell][1]) + br_offsets[cell][bitline][1]] + br.append(bitline_location) + + for col in range(len(bl)): + if OPTS.num_banks == 1: + self.add_layout_pin_rect_center("bl0_{0}".format(int(col / OPTS.num_words)), bitline_layer_name, bl[col]) + else: + self.add_layout_pin_rect_center("bl{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) - if OPTS.num_banks == 1: - for i in range(len(bl_offsets)): - self.add_layout_pin_rect_center("bl_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) - - for i in range(len(br_offsets)): - self.add_layout_pin_rect_center("br_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) - else: - self.add_layout_pin_rect_center("bl{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) - self.add_layout_pin_rect_center("br{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)), bitline_layer_name, br) + for col in range(len(br)): + if OPTS.num_banks == 1: + self.add_layout_pin_rect_center("br0_{0}".format(int(col / OPTS.num_words)), bitline_layer_name, br[col]) + else: + self.add_layout_pin_rect_center("br{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, br) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 16f37bdc..d81255b6 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -420,12 +420,8 @@ def correct_port(name, output_file_name, ref_file_name): bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank, row,col) bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank, row,col) for col in range(OPTS.word_size): - if OPTS.num_banks == 1: - bitcell_list += "bl_{2} ".format(bank, row,col) - bitcell_list += "br_{2} ".format(bank, row,col) - else: bitcell_list += "bl{0}_{2} ".format(bank, row,col) - bitcell_list += "br{0}_{2} ".format(bank, row,col) + bitcell_list += "br{0}_{2} ".format(bank, row,col) bitcell_list += "\n" control_list = "+ " From 1a97dfc63e29b52db7ebf579c1c1c2eefaea97c0 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Mon, 27 Jan 2020 11:50:43 +0000 Subject: [PATCH 14/65] syncronize bitline naming convention betwen bitcell and pbitcell --- compiler/characterizer/delay.py | 37 ++++++++++++++++++++----------- compiler/characterizer/stimuli.py | 5 +++-- compiler/sram/sram_base.py | 11 +++------ compiler/verify/magic.py | 8 +++---- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 6ec3ae8a..36965f4d 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -130,19 +130,18 @@ class delay(simulation): """ self.bitline_volt_meas = [] - self.bitline_volt_meas.append(voltage_at_measure("v_bl_READ_ZERO", - self.bl_name)) + self.bl_name)) self.bitline_volt_meas[-1].meta_str = sram_op.READ_ZERO self.bitline_volt_meas.append(voltage_at_measure("v_br_READ_ZERO", - self.br_name)) + self.br_name)) self.bitline_volt_meas[-1].meta_str = sram_op.READ_ZERO self.bitline_volt_meas.append(voltage_at_measure("v_bl_READ_ONE", - self.bl_name)) + self.bl_name)) self.bitline_volt_meas[-1].meta_str = sram_op.READ_ONE self.bitline_volt_meas.append(voltage_at_measure("v_br_READ_ONE", - self.br_name)) + self.br_name)) self.bitline_volt_meas[-1].meta_str = sram_op.READ_ONE return self.bitline_volt_meas @@ -264,14 +263,26 @@ class delay(simulation): """Sets important names for characterization such as Sense amp enable and internal bit nets.""" port = self.read_ports[0] - self.graph.get_all_paths('{}{}'.format("clk", port), - '{}{}_{}'.format(self.dout_name, port, self.probe_data)) - - self.sen_name = self.get_sen_name(self.graph.all_paths) - debug.info(2,"s_en name = {}".format(self.sen_name)) - - self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths, port) - debug.info(2,"bl name={}, br name={}".format(self.bl_name,self.br_name)) + if not OPTS.use_pex: + self.graph.get_all_paths('{}{}'.format("clk", port), + '{}{}_{}'.format(self.dout_name, port, self.probe_data)) + + self.sen_name = self.get_sen_name(self.graph.all_paths) + debug.info(2,"s_en name = {}".format(self.sen_name)) + + self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths, port) + debug.info(2,"bl name={}, br name={}".format(self.bl_name,self.br_name)) + else: + self.graph.get_all_paths('{}{}'.format("clk", port), + '{}{}_{}'.format(self.dout_name, port, self.probe_data)) + + self.sen_name = self.get_sen_name(self.graph.all_paths) + debug.info(2,"s_en name = {}".format(self.sen_name)) + + + self.bl_name = "bl{0}_{1}".format(port, OPTS.word_size-1) + self.br_name = "br{0}_{1}".format(port, OPTS.word_size-1) + debug.info(2,"bl name={}, br name={}".format(self.bl_name,self.br_name)) def get_sen_name(self, paths): """ diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index b4cd00f4..198dacdd 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -63,8 +63,9 @@ class stimuli(): self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) for col in range(OPTS.word_size): - self.sf.write("bl{0}_{2} ".format(bank, row,col)) - self.sf.write("br{0}_{2} ".format(bank, row,col)) + self.sf.write("bl{0}_{2} ".format(bank, row, col)) + self.sf.write("br{0}_{2} ".format(bank, row, col)) + self.sf.write("s_en{0} ".format(bank)) self.sf.write("{0}\n".format(model_name)) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 2c66924a..3479957b 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -125,16 +125,11 @@ class sram_base(design, verilog, lef): br.append(bitline_location) for col in range(len(bl)): - if OPTS.num_banks == 1: - self.add_layout_pin_rect_center("bl0_{0}".format(int(col / OPTS.num_words)), bitline_layer_name, bl[col]) - else: - self.add_layout_pin_rect_center("bl{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, bl) + self.add_layout_pin_rect_center("bl{0}_{1}".format(bank_num, int(col / OPTS.num_words)), bitline_layer_name, bl[col]) for col in range(len(br)): - if OPTS.num_banks == 1: - self.add_layout_pin_rect_center("br0_{0}".format(int(col / OPTS.num_words)), bitline_layer_name, br[col]) - else: - self.add_layout_pin_rect_center("br{0}_{2}".format(bank_num, i % OPTS.num_words, int(i / OPTS.num_words)) , bitline_layer_name, br) + self.add_layout_pin_rect_center("br{0}_{1}".format(bank_num, int(col / OPTS.num_words)), bitline_layer_name, br[col]) + diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index d81255b6..93472e2a 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -417,11 +417,11 @@ def correct_port(name, output_file_name, ref_file_name): for bank in range(OPTS.num_banks): for row in range(OPTS.num_words): for col in range(OPTS.word_size): - bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank, row,col) - bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank, row,col) + bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank, row, col) + bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank, row, col) for col in range(OPTS.word_size): - bitcell_list += "bl{0}_{2} ".format(bank, row,col) - bitcell_list += "br{0}_{2} ".format(bank, row,col) + bitcell_list += "bl{0}_{2} ".format(bank, row, col) + bitcell_list += "br{0}_{2} ".format(bank, row, col) bitcell_list += "\n" control_list = "+ " From 30604fb093dc752479d03124031ad8ef2874833e Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Tue, 28 Jan 2020 00:28:55 +0000 Subject: [PATCH 15/65] add multiport support for pex labels --- compiler/base/geometry.py | 44 +++++++++++++----- compiler/bitcells/bitcell_base.py | 3 +- .../example_config_1w_1r_scn4m_subm.py | 4 +- compiler/sram/sram_base.py | 38 +++++++++------ technology/scn4m_subm/gds_lib/cell_1w_1r.gds | Bin 8192 -> 6406 bytes 5 files changed, 59 insertions(+), 30 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 3b2eb2d3..02b100ad 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -136,8 +136,7 @@ class geometry: def cy(self): """ Return the center y """ return 0.5 * (self.boundary[0].y + self.boundary[1].y) - - + class instance(geometry): """ An instance of an instance/module with a specified location and @@ -306,29 +305,47 @@ class instance(geometry): return (uVector, vVector, origin) def reverse_transformation_bitcell(self, cell_name): - path = [] - cell_paths = [] - origin_offsets = [] - Q_offsets = [] - Q_bar_offsets = [] - bl_offsets = [] - br_offsets = [] + path = [] # path currently follwed in bitcell search + cell_paths = [] # saved paths to bitcells + origin_offsets = [] # cell to bank offset + Q_offsets = [] # Q to cell offet + Q_bar_offsets = [] # Q_bar to cell offset + bl_offsets = [] # bl to cell offset + br_offsets = [] # br to cell offset + bl_meta = [] # bl offset metadata (row,col,name) + br_meta = [] #br offset metadata (row,col,name) def walk_subtree(node): path.append(node) if node.mod.name == cell_name: cell_paths.append(copy.copy(path)) + + inst_name = path[-1].name + # get the row and col names from the path + row = int(path[-1].name.split('_')[-2][1:]) + col = int(path[-1].name.split('_')[-1][1:]) + + cell_bl_meta = [] + cell_br_meta = [] + normalized_storage_nets = node.mod.get_normalized_storage_nets_offset() - (normalized_bl_offsets, normalized_br_offsets) = node.mod.get_normalized_bitline_offset() + (normalized_bl_offsets, normalized_br_offsets, bl_names, br_names) = node.mod.get_normalized_bitline_offset() + + for offset in range(len(normalized_bl_offsets)): + for port in range(len(bl_names)): + cell_bl_meta.append([bl_names[offset], row, col, port]) + + for offset in range(len(normalized_br_offsets)): + for port in range(len(br_names)): + cell_br_meta.append([br_names[offset], row, col, port]) Q_x = normalized_storage_nets[0][0] Q_y = normalized_storage_nets[0][1] Q_bar_x = normalized_storage_nets[1][0] Q_bar_y = normalized_storage_nets[1][1] - if node.mirror == 'MX': Q_y = -1 * Q_y @@ -350,6 +367,9 @@ class instance(geometry): bl_offsets.append(normalized_bl_offsets) br_offsets.append(normalized_br_offsets) + bl_meta.append(cell_bl_meta) + br_meta.append(cell_br_meta) + elif node.mod.insts is not []: for instance in node.mod.insts: walk_subtree(instance) @@ -361,7 +381,7 @@ class instance(geometry): origin = vector_spaces[2] origin_offsets.append([origin[0], origin[1]]) - return(origin_offsets, Q_offsets, Q_bar_offsets, bl_offsets, br_offsets) + return(origin_offsets, Q_offsets, Q_bar_offsets, bl_offsets, br_offsets, bl_meta, br_meta) def __str__(self): """ override print function output """ diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 069f8f6c..58f7bdcb 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -116,6 +116,7 @@ class bitcell_base(design.design): if bl_names[i] == text.textString.rstrip('\x00'): self.bl_offsets.append(text.coordinates[0]) found_bl.append(bl_names[i]) + continue for i in range(len(br_names)): @@ -132,7 +133,7 @@ class bitcell_base(design.design): for i in range(len(self.br_offsets)): self.br_offsets[i] = tuple([self.gds.info["units"][0] * x for x in self.br_offsets[i]]) - return(self.bl_offsets, self.br_offsets) + return(self.bl_offsets, self.br_offsets, found_bl, found_br) def get_normalized_storage_nets_offset(self): """ diff --git a/compiler/example_configs/example_config_1w_1r_scn4m_subm.py b/compiler/example_configs/example_config_1w_1r_scn4m_subm.py index 4b6584d4..fde94de0 100644 --- a/compiler/example_configs/example_config_1w_1r_scn4m_subm.py +++ b/compiler/example_configs/example_config_1w_1r_scn4m_subm.py @@ -1,9 +1,9 @@ word_size = 2 num_words = 16 -num_rw_ports = 1 +num_rw_ports = 0 num_r_ports = 1 -num_w_ports = 0 +num_w_ports = 1 tech_name = "scn4m_subm" process_corners = ["TT"] diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 3479957b..8d4bc330 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -95,13 +95,15 @@ class sram_base(design, verilog, lef): # add pex labels for bitcells for bank_num in range(len(self.bank_insts)): bank = self.bank_insts[bank_num] - pex_offsets = bank.reverse_transformation_bitcell(bank.mod.bitcell.name) + pex_data = bank.reverse_transformation_bitcell(bank.mod.bitcell.name) - bank_offset = pex_offsets[0] # offset bank relative to sram - Q_offset = pex_offsets[1] # offset of storage relative to bank - Q_bar_offset = pex_offsets[2] # offset of storage relative to bank - bl_offsets = pex_offsets[3] - br_offsets = pex_offsets[4] + bank_offset = pex_data[0] # offset bank relative to sram + Q_offset = pex_data[1] # offset of storage relative to bank + Q_bar_offset = pex_data[2] # offset of storage relative to bank + bl_offsets = pex_data[3] + br_offsets = pex_data[4] + bl_meta = pex_data[5] + br_meta = pex_data[6] bl = [] br = [] @@ -116,20 +118,26 @@ class sram_base(design, verilog, lef): self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, cell % OPTS.num_words, int(cell / OPTS.num_words)) , storage_layer_name, Q) self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, cell % OPTS.num_words, int(cell / OPTS.num_words)), storage_layer_name, Q_bar) + for cell in range(len(bl_offsets)): + col = bl_meta[cell][0][2] for bitline in range(len(bl_offsets[cell])): bitline_location = [float(bank_offset[cell][0]) + bl_offsets[cell][bitline][0], float(bank_offset[cell][1]) + bl_offsets[cell][bitline][1]] - bl.append(bitline_location) + bl.append([bitline_location, bl_meta[cell][bitline][3], col]) - for bitline in range(len(br_offsets[0])): + for cell in range(len(br_offsets)): + col = br_meta[cell][0][2] + for bitline in range(len(br_offsets[cell])): bitline_location = [float(bank_offset[cell][0]) + br_offsets[cell][bitline][0], float(bank_offset[cell][1]) + br_offsets[cell][bitline][1]] - br.append(bitline_location) - - for col in range(len(bl)): - self.add_layout_pin_rect_center("bl{0}_{1}".format(bank_num, int(col / OPTS.num_words)), bitline_layer_name, bl[col]) + br.append([bitline_location, br_meta[cell][bitline][3], col]) - for col in range(len(br)): - self.add_layout_pin_rect_center("br{0}_{1}".format(bank_num, int(col / OPTS.num_words)), bitline_layer_name, br[col]) - + + + + for i in range(len(bl)): + self.add_layout_pin_rect_center("bl{0}_{1}".format(bl[i][1], bl[i][2]), bitline_layer_name, bl[i][0]) + + for i in range(len(br)): + self.add_layout_pin_rect_center("br{0}_{1}".format(br[i][1], br[i][2]), bitline_layer_name, br[i][0]) diff --git a/technology/scn4m_subm/gds_lib/cell_1w_1r.gds b/technology/scn4m_subm/gds_lib/cell_1w_1r.gds index 782c43dc67499f61fd6df7d7481bc6a0311a0b32..06f79ba5d4a3d86bf948a0040ea1f6fd7fbefb55 100644 GIT binary patch literal 6406 zcmbW5J&aXF7=}OYE_WAPmW%SYvdSudEAq1oLBK*Wu^^$*#DdtcB1Q^g%oZ-?mfBI0 z*lZ^yC8d?2q_ni8q_p&X?wmJg?!|9RJjvbX?mP3&H}lP$nR9LoV-Pd3ylW6!u@Fb} z-zZk&VeE=yL*|z8ME+c7O8OFIR8<@!PBGpFg{}^Xu1N#q#ck zdsw??=Oc#u25~lqi-U+bH=5C3T_;{eoL%er@#CVKDxWEo4^h{I2MUb|8HZmK-> z@4Kmmq&7zPd!GLy0^L-3>L)&a;+y!;&6a=ZdGRg3?1>NEZ29RYYZt#sKRm9kJnjG7 ze2H~pwI^+%o9avIr+vmwU6a0}o6=K1ai~jtletGXrKf)KOkHA|dsj>TP3g6NtzJI| zmFp`nBMxcJnpYo2pqtWD|J;j+w;x69+32~f^@wh&JoPV*if{i;PkiWR%TH`R)HUnx zU3nURh&i4Wau`H4fWiEr-N zDDh3{b^kBa_s@Z~lDjv5@5#Q8ZYsB_|HzLKXEcAT9TOkADLwTcI$F*y{G4HK2c7o1 z^3>0mkKc$`*zU<%KsQyM`uDyn=PZ8CTepKwyIpzeCr{L)pC)mg*RDMEGe_i}xF&On zZc0!6^pA5Ezezjjru5WL|L{@QWE>t>SDyNrXMD_?$vmQ)(o_FCPfOm&8F3*WbW?iM z&%EI^`R;b1^roM&vtO9x9iJ(^>1W);G-(IFIW_)^_5DYTQ`;q9=9y86ZA!1>Px$8_ ztMBug@712~NkcbPp8CgQmY;oub|5}@S`-~@dJPSbXC3I7I>gO37 zA8|~4=;oCFQk{Rs>*og3&kg3(^TTU?_HE|T^uBLS?cWpr!R@lw&%Erpyb^(K>MW?o zKjA-pv-sF6IWr(WbhG8>nT@=0_L}4k-E8IW*zMxu`4KVtn?PwBvTW@}{4@6W^pAw+p4Ge(rhBNxUZg zM>nOXe%{eEzhl2iJLqO>{_*gkuF1OLyQ%MKeELb>>knRZvo-!*s>fV&UYN9nZc0z% zlV5zSUlU)K_c2?3_ASmz=Fj9TKsTkQ@pd%#<^D10Ke{PB^)qHZ z)HUnxU3u!~+@%h`9hvyiP3fthc_weu&tK@|uPaae#366>?+@e+-E8GAbdhWB6_Y%2 znbOnv)MKsTH)o%sMwrrT|K)oB$5YqE!@iGhsyy}6XD;^@;zKu8ocjN5|HX%HYHX>0 zVY~E|^-rH6^M-D=#?SoX<9XTiyqhgQ^UTHkoAevql%Dqg)HbfNeocJnru5qXX+3{< zxR`(QBaMa2)Yq|pq5S@>^Ybvje=qR+H_sjG*J6HYxb;9yH0!B7)%)q*y+%Erxn@>M zd+YyEPwxn7@B1I7+SB^%`=_?}eOLAFPWNx39`75jHx+lH9`6QSz0FoV-hEuJl^6EC e(>G(dH2ktLT2`}mn7yiX=k7O~UClXhHvR$Vczuxo literal 8192 zcmeI0J8T_A6o!u-=lT)HvGZ`8V2H_s7?b#sD8!)vBT+=6p+qzZ;6Mrsp$JGym(Wp0 zqH#w`moBML%9JT7T~MT?uBn!mFP|Oy2L&x|sUOOB}>c ze$#rJ|IE|khxlf9d&J*dPxI4mYUO_5#|N#8segE+?O(3P&q>w%#;&G@c=J)jsXuzOE~ftBXAx(A zRvW}wjl``sp8eAbIJ(X}v8!F$)^Eka>sK zv@WLkX+LogAN4b>xB00xaS$KR(6rv>Coi>!qv|{PP3vOa{;T!;VXj_RZg@-gnOW`8 zx|sS8KPn#hhR%ySJ#w$+dg?!-c;-GNo_m|6-kgYPpPANZ#YW^~hLmuBZOf-$q=19s%()XHDy3>OVD8 zY6gkNZ(iKdcq-RZKV$6NS{Z}1cYL$-2U-_X|JaLCGf2FBkXkm^Q$O{==Q`3}+5xS% zw$n)a)nbzC_JL|Ym_8)P&3oI zn6{twk~oNuoTl|Y|4Lo|&~amqzva81Z(jBR(7IUXf62e}q-&3BPm9mAE~fr^{UV-u zY%+$L>#3h_Tz{wc??0@Ish=7V2fgnwt+)C4RwoYj??0@!`Ds7vz58)&tK1J-7t{9R zW4-ZxnDh9cb+OgYp2PPcFFt5pO#OT}v1WC@qf`ex^cz|iQ$O!*o--ugK4@J`{lxfW z+;9)mdYhkilM52>ywJLs<{yxcXAg;I9-G$1)KA@sgZTLNHm$e$N7Y}}F34KSb2F`r zX@2&2^)qk0hSBcnC#C(+x|sUuqfh+xX}zugtarpgynHj7*4z9%cj^TF z-ZQPY)sMW?2~s!q|EBe}`h^Z^&q2MIJEnCptsg$d9>>sj@tfAgu7AAz{-pJLn%|!~ zrw90ZmcQft7R7#VWi>|5bRKS~8T=TX`C zJ?&ckKI8rE-yQb(d&EnA_I=#P`$*Gz-+pk9fAG^Xmf-B1`nlU9W30JeKhHh>w{90d z#Lrr8;%}~}e#RVg5>jWLscBtI{jaIr#6f(_CDVGFpZ7I;dB|GCx@1}x)BOMA_k=z5 zqu#3h-#2Nzof6uiprvCBG(njd_h)LU<>#3hHN}ShI?<=5nG4->KazNV8dTLr1Q~#w+ zqRO5EAMXRxy4dwM>!IrZ@9Uw~D1KYen)5~fdYF3HhuG7%wxu5S42|c(em(4w>{;Gh rj}PkcNS}RZo$ihe)4JHL$FMk5i3k54RN$Zj2NgJ|z(ECG%?kVt)Hin7 From 6e070925b642691f412d5fc0fcce563edef9cd3f Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Tue, 28 Jan 2020 02:32:34 +0000 Subject: [PATCH 16/65] update magic for multiport --- compiler/characterizer/stimuli.py | 5 +++-- compiler/sram/sram_base.py | 10 ++-------- compiler/verify/magic.py | 1 + 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 198dacdd..5e0bd52e 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -63,8 +63,9 @@ class stimuli(): self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) for col in range(OPTS.word_size): - self.sf.write("bl{0}_{2} ".format(bank, row, col)) - self.sf.write("br{0}_{2} ".format(bank, row, col)) + for port in range(OPTS.num_r_ports + OPTS.num_w_ports + OPTS.num_rw_ports): + self.sf.write("bl{0}_{2} ".format(port, row, col)) + self.sf.write("br{0}_{2} ".format(port, row, col)) self.sf.write("s_en{0} ".format(bank)) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 8d4bc330..bdb84b97 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -128,19 +128,13 @@ class sram_base(design, verilog, lef): col = br_meta[cell][0][2] for bitline in range(len(br_offsets[cell])): bitline_location = [float(bank_offset[cell][0]) + br_offsets[cell][bitline][0], float(bank_offset[cell][1]) + br_offsets[cell][bitline][1]] - br.append([bitline_location, br_meta[cell][bitline][3], col]) - - - + br.append([bitline_location, br_meta[cell][bitline][3], col]) for i in range(len(bl)): self.add_layout_pin_rect_center("bl{0}_{1}".format(bl[i][1], bl[i][2]), bitline_layer_name, bl[i][0]) for i in range(len(br)): - self.add_layout_pin_rect_center("br{0}_{1}".format(br[i][1], br[i][2]), bitline_layer_name, br[i][0]) - - - + self.add_layout_pin_rect_center("br{0}_{1}".format(br[i][1], br[i][2]), bitline_layer_name, br[i][0]) # add pex labels for control logic for i in range (len(self.control_logic_insts)): diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 93472e2a..432325ea 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -420,6 +420,7 @@ def correct_port(name, output_file_name, ref_file_name): bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank, row, col) bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank, row, col) for col in range(OPTS.word_size): + for port in range(OPTS.num_r_ports + OPTS.num_w_ports + OPTS.num_rw_ports): bitcell_list += "bl{0}_{2} ".format(bank, row, col) bitcell_list += "br{0}_{2} ".format(bank, row, col) bitcell_list += "\n" From 89688f8ea9a696fc418db45a7c322940de8b17d0 Mon Sep 17 00:00:00 2001 From: jcirimel Date: Mon, 4 May 2020 01:31:51 -0700 Subject: [PATCH 17/65] fix pex for larger memories --- compiler/sram/sram_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index bdb84b97..652615dd 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -115,8 +115,8 @@ class sram_base(design, verilog, lef): Q = [bank_offset[cell][0] + Q_offset[cell][0], bank_offset[cell][1] + Q_offset[cell][1]] Q_bar = [bank_offset[cell][0] + Q_bar_offset[cell][0], bank_offset[cell][1] + Q_bar_offset[cell][1]] - self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, cell % OPTS.num_words, int(cell / OPTS.num_words)) , storage_layer_name, Q) - self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, cell % OPTS.num_words, int(cell / OPTS.num_words)), storage_layer_name, Q_bar) + self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, cell % (OPTS.num_words * self.words_per_row), int(cell / (OPTS.num_words / self.words_per_row))) , storage_layer_name, Q) + self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, cell % (OPTS.num_words * self.words_per_row), int(cell / (OPTS.num_words / self.words_per_row))), storage_layer_name, Q_bar) for cell in range(len(bl_offsets)): col = bl_meta[cell][0][2] From 0f9e38881c5736e732df1c8ea83db0b0cd4beaa2 Mon Sep 17 00:00:00 2001 From: jcirimel Date: Mon, 4 May 2020 03:05:33 -0700 Subject: [PATCH 18/65] update stim for large pex layouts --- compiler/characterizer/stimuli.py | 6 +++--- compiler/sram/sram_base.py | 6 +++--- compiler/verify/magic.py | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 5e0bd52e..c8ee0492 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -58,11 +58,11 @@ class stimuli(): for pin in pins: self.sf.write("{0} ".format(pin)) for bank in range(OPTS.num_banks): - for row in range(OPTS.num_words): - for col in range(OPTS.word_size): + for row in range(int(OPTS.num_words / OPTS.words_per_row)): + for col in range(int(OPTS.word_size * OPTS.words_per_row)): self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) - for col in range(OPTS.word_size): + for col in range(OPTS.word_size * OPTS.words_per_row): for port in range(OPTS.num_r_ports + OPTS.num_w_ports + OPTS.num_rw_ports): self.sf.write("bl{0}_{2} ".format(port, row, col)) self.sf.write("br{0}_{2} ".format(port, row, col)) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 652615dd..3cace3d6 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -114,9 +114,9 @@ class sram_base(design, verilog, lef): for cell in range(len(bank_offset)): Q = [bank_offset[cell][0] + Q_offset[cell][0], bank_offset[cell][1] + Q_offset[cell][1]] Q_bar = [bank_offset[cell][0] + Q_bar_offset[cell][0], bank_offset[cell][1] + Q_bar_offset[cell][1]] - - self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, cell % (OPTS.num_words * self.words_per_row), int(cell / (OPTS.num_words / self.words_per_row))) , storage_layer_name, Q) - self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, cell % (OPTS.num_words * self.words_per_row), int(cell / (OPTS.num_words / self.words_per_row))), storage_layer_name, Q_bar) + OPTS.words_per_row = self.words_per_row + self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, int(cell % (OPTS.num_words / self.words_per_row)), int(cell / (OPTS.word_size * self.words_per_row))) , storage_layer_name, Q) + self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, int(cell % (OPTS.num_words / self.words_per_row)), int(cell / (OPTS.word_size * self.words_per_row))), storage_layer_name, Q_bar) for cell in range(len(bl_offsets)): col = bl_meta[cell][0][2] diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 432325ea..de206b87 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -415,11 +415,11 @@ def correct_port(name, output_file_name, ref_file_name): bitcell_list = "+ " for bank in range(OPTS.num_banks): - for row in range(OPTS.num_words): - for col in range(OPTS.word_size): + for row in range(int(OPTS.num_words / OPTS.words_per_row)): + for col in range(int(OPTS.word_size * OPTS.words_per_row)): bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank, row, col) bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank, row, col) - for col in range(OPTS.word_size): + for col in range(OPTS.word_size * OPTS.words_per_row): for port in range(OPTS.num_r_ports + OPTS.num_w_ports + OPTS.num_rw_ports): bitcell_list += "bl{0}_{2} ".format(bank, row, col) bitcell_list += "br{0}_{2} ".format(bank, row, col) From 575278998d42648acc089aa94fa9d7d5b5036bed Mon Sep 17 00:00:00 2001 From: jcirimel Date: Thu, 28 May 2020 23:56:15 -0700 Subject: [PATCH 19/65] write only used bitcells to top level in stim and pex output --- compiler/characterizer/stimuli.py | 18 ++++++++++++------ compiler/verify/magic.py | 13 +++++++------ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index c8ee0492..fb2e261d 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -58,14 +58,20 @@ class stimuli(): for pin in pins: self.sf.write("{0} ".format(pin)) for bank in range(OPTS.num_banks): - for row in range(int(OPTS.num_words / OPTS.words_per_row)): - for col in range(int(OPTS.word_size * OPTS.words_per_row)): - self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) - self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) + row = int(OPTS.num_words / OPTS.words_per_row) - 1 + col = int(OPTS.word_size * OPTS.words_per_row) - 1 + self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) + self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) + # can't add all bitcells to top level due to ngspice max port count of 1005 + # for row in range(int(OPTS.num_words / OPTS.words_per_row)): + # for col in range(int(OPTS.word_size * OPTS.words_per_row)): + # self.sf.write("bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)) + # self.sf.write("bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)) + for bank in range(OPTS.num_banks): for col in range(OPTS.word_size * OPTS.words_per_row): for port in range(OPTS.num_r_ports + OPTS.num_w_ports + OPTS.num_rw_ports): - self.sf.write("bl{0}_{2} ".format(port, row, col)) - self.sf.write("br{0}_{2} ".format(port, row, col)) + self.sf.write("bl{0}_{1} ".format(port, col)) + self.sf.write("br{0}_{1} ".format(port, col)) self.sf.write("s_en{0} ".format(bank)) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index de206b87..c2960aa6 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -415,14 +415,15 @@ def correct_port(name, output_file_name, ref_file_name): bitcell_list = "+ " for bank in range(OPTS.num_banks): - for row in range(int(OPTS.num_words / OPTS.words_per_row)): - for col in range(int(OPTS.word_size * OPTS.words_per_row)): - bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank, row, col) - bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank, row, col) + for bank in range(OPTS.num_banks): + row = int(OPTS.num_words / OPTS.words_per_row) - 1 + col = int(OPTS.word_size * OPTS.words_per_row) - 1 + bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col) + bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col) for col in range(OPTS.word_size * OPTS.words_per_row): for port in range(OPTS.num_r_ports + OPTS.num_w_ports + OPTS.num_rw_ports): - bitcell_list += "bl{0}_{2} ".format(bank, row, col) - bitcell_list += "br{0}_{2} ".format(bank, row, col) + bitcell_list += "bl{0}_{1} ".format(bank, col) + bitcell_list += "br{0}_{1} ".format(bank, col) bitcell_list += "\n" control_list = "+ " From 3a0939c40299a1a65a78b4147a8c91979d571de7 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Tue, 23 Jun 2020 11:50:02 +0100 Subject: [PATCH 20/65] Update minimum required Magic version --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 82fe75ed..d6b948ef 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The OpenRAM compiler has very few dependencies: If you want to perform DRC and LVS, you will need either: + Calibre (for [FreePDK45]) -+ [Magic] 8.2.79 or higher (for [SCMOS]) ++ [Magic] 8.3.27 or higher (for [SCMOS]) + [Netgen] 1.5 (for [SCMOS]) You must set two environment variables: @@ -81,6 +81,8 @@ We have included the most recent SCN4M_SUBM design rules from [Qflow]. ## Docker Image +**WARNING! Some OpenRAM dependency tools installed in the Docker image are out-of-date.** + We have a pre-configured Ubuntu [Docker](https://www.docker.com/) image available that has all tools installed for the [SCMOS] process. It is available at [docker hub](https://hub.docker.com/r/vlsida/openram-ubuntu). From ed9d32c7bc105db2a438d36d4b2d852152a79e3b Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 13 Jul 2020 16:26:25 -0700 Subject: [PATCH 21/65] OpenRAM 1.1.6 --- compiler/globals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/globals.py b/compiler/globals.py index a192ebc9..dd4ac177 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -19,7 +19,7 @@ import re import copy import importlib -VERSION = "1.1.5" +VERSION = "1.1.6" NAME = "OpenRAM v{}".format(VERSION) USAGE = "openram.py [options] \nUse -h for help.\n" From ee3da912321b87369e3aa742cc6ba607d17ce759 Mon Sep 17 00:00:00 2001 From: Bob Vanhoof Date: Wed, 15 Jul 2020 11:50:21 +0200 Subject: [PATCH 22/65] calibrepex: file copy fix --- compiler/sram/sram.py | 1 + compiler/verify/calibre.py | 27 ++++++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index 1ec7d636..b2ab1124 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -101,6 +101,7 @@ class sram(): start_time = datetime.datetime.now() # Output the extracted design if requested sp_file = OPTS.output_path + "temp_pex.sp" + spname = OPTS.output_path + self.s.name + ".sp" verify.run_pex(self.s.name, gdsname, spname, output=sp_file) print_time("Extraction", datetime.datetime.now(), start_time) else: diff --git a/compiler/verify/calibre.py b/compiler/verify/calibre.py index 443c91ca..6d1786c9 100644 --- a/compiler/verify/calibre.py +++ b/compiler/verify/calibre.py @@ -135,11 +135,11 @@ def write_calibre_lvs_script(cell_name, final_verification): def write_calibre_pex_script(cell_name, extract, output, final_verification): """ Write a pex script that can either just extract the netlist or the netlist+parasitics """ if output == None: - output = name + ".pex.netlist" + output = cell_name + ".pex.netlist" # check if lvs report has been done # if not run drc and lvs - if not os.path.isfile(cell_name + ".lvs.report"): + if not os.path.isfile(OPTS.openram_temp + cell_name + ".lvs.report"): gds_name = OPTS.openram_temp +"/"+ cell_name + ".gds" sp_name = OPTS.openram_temp +"/"+ cell_name + ".sp" run_drc(cell_name, gds_name) @@ -155,7 +155,7 @@ def write_calibre_pex_script(cell_name, extract, output, final_verification): 'pexSourcePath': cell_name + ".sp", 'pexSourcePrimary': cell_name, 'pexReportFile': cell_name + ".pex.report", - 'pexPexNetlistFile': cell_name + ".pex.netlist", + 'pexPexNetlistFile': output, 'pexPexReportFile': cell_name + ".pex.report", 'pexMaskDBFile': cell_name + ".maskdb", 'cmnFDIDEFLayoutPath': cell_name + ".def", @@ -195,8 +195,8 @@ def run_drc(cell_name, gds_name, extract=False, final_verification=False): filter_gds(cell_name, OPTS.openram_temp + "temp.gds", OPTS.openram_temp + cell_name + ".gds") else: # Copy file to local dir if it isn't already - if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): - shutil.copy(gds_name, OPTS.openram_temp) + if not os.path.isfile(gds_name): + shutil.copy(OPTS.output_path+os.path.basename(gds_name),gds_name) drc_runset = write_calibre_drc_script(cell_name, extract, final_verification) @@ -241,10 +241,14 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): lvs_runset = write_calibre_lvs_script(cell_name, final_verification) # Copy file to local dir if it isn't already - if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): - shutil.copy(gds_name, OPTS.openram_temp) - if os.path.dirname(sp_name)!=OPTS.openram_temp.rstrip('/'): - shutil.copy(sp_name, OPTS.openram_temp) +# if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): +# shutil.copy(gds_name, OPTS.openram_temp) +# if os.path.dirname(sp_name)!=OPTS.openram_temp.rstrip('/'): +# shutil.copy(sp_name, OPTS.openram_temp) + if not os.path.isfile(gds_name): + shutil.copy(OPTS.output_path+os.path.basename(gds_name), gds_name) + if not os.path.isfile(sp_name): + shutil.copy(OPTS.output_path+os.path.basename(sp_name), sp_name) (outfile, errfile, resultsfile) = run_script(cell_name, "lvs") @@ -327,6 +331,11 @@ def run_pex(cell_name, gds_name, sp_name, output=None, final_verification=False) write_calibre_pex_script(cell_name,True,output,final_verification) + if not os.path.isfile(OPTS.openram_temp + os.path.basename(gds_name)): + shutil.copy(gds_name, OPTS.openram_temp + os.path.basename(gds_name)) + if not os.path.isfile(OPTS.openram_temp + os.path.basename(sp_name)): + shutil.copy(sp_name, OPTS.openram_temp + os.path.basename(sp_name)) + (outfile, errfile, resultsfile) = run_script(cell_name, "pex") From 1d9296ceb1ab9b5a1d7472657691d66d20535228 Mon Sep 17 00:00:00 2001 From: jcirimel Date: Tue, 21 Jul 2020 11:50:25 -0700 Subject: [PATCH 23/65] fix magic.py conflict --- compiler/verify/magic.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 9695591d..1be2f2cd 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -107,7 +107,6 @@ def write_magic_script(cell_name, extract=False, final_verification=False): # f.write(pre + "ext2spice hierarchy on\n") # f.write(pre + "ext2spice scale off\n") # lvs exists in 8.2.79, but be backword compatible for now -<<<<<<< HEAD #f.write(pre+"ext2spice lvs\n") f.write(pre+"ext2spice hierarchy on\n") f.write(pre+"ext2spice format ngspice\n") @@ -123,23 +122,6 @@ def write_magic_script(cell_name, extract=False, final_verification=False): # but they all seem compatible enough. f.write(pre+"ext2spice format ngspice\n") f.write(pre+"ext2spice {}\n".format(cell_name)) -======= - # f.write(pre + "ext2spice lvs\n") - f.write(pre + "ext2spice hierarchy on\n") - f.write(pre + "ext2spice format ngspice\n") - f.write(pre + "ext2spice cthresh infinite\n") - f.write(pre + "ext2spice rthresh infinite\n") - f.write(pre + "ext2spice renumber off\n") - f.write(pre + "ext2spice scale off\n") - f.write(pre + "ext2spice blackbox on\n") - f.write(pre + "ext2spice subcircuit top auto\n") - f.write(pre + "ext2spice global off\n") - - # Can choose hspice, ngspice, or spice3, - # but they all seem compatible enough. - #f.write(pre + "ext2spice format ngspice\n") - f.write(pre + "ext2spice {}\n".format(cell_name)) ->>>>>>> dev f.write("quit -noprompt\n") f.write("EOF\n") From b7c43ae674bb1876e6136e3d4bc55b6886860fb6 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 23 Jul 2020 14:17:13 -0700 Subject: [PATCH 24/65] Fix 1w/1r example --- compiler/example_configs/example_config_1w_1r_scn4m_subm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/example_configs/example_config_1w_1r_scn4m_subm.py b/compiler/example_configs/example_config_1w_1r_scn4m_subm.py index 55ac4016..7698f1a3 100644 --- a/compiler/example_configs/example_config_1w_1r_scn4m_subm.py +++ b/compiler/example_configs/example_config_1w_1r_scn4m_subm.py @@ -1,9 +1,9 @@ word_size = 2 num_words = 16 -num_rw_ports = 1 +num_rw_ports = 0 num_r_ports = 1 -num_w_ports = 0 +num_w_ports = 1 tech_name = "scn4m_subm" nominal_corners_only = False From e1967dc548d82a79161918e26dcd0d195e8d4a61 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 23 Jul 2020 14:43:14 -0700 Subject: [PATCH 25/65] Draft local and global arrays. Ensure rows before cols in usage. --- compiler/modules/bitcell_array.py | 8 +- compiler/modules/bitcell_base_array.py | 4 +- compiler/modules/col_cap_array.py | 4 +- compiler/modules/dummy_array.py | 6 +- compiler/modules/global_bitcell_array.py | 66 +++++++++ compiler/modules/local_bitcell_array.py | 66 +++++++++ compiler/modules/replica_bitcell_array.py | 2 +- compiler/modules/replica_column.py | 14 +- compiler/modules/row_cap_array.py | 4 +- compiler/modules/wordline_buffer_array.py | 137 ++++++++++++++++++ compiler/modules/wordline_driver_array.py | 1 + .../tests/08_wordline_buffer_array_test.py | 37 +++++ 12 files changed, 328 insertions(+), 21 deletions(-) create mode 100644 compiler/modules/global_bitcell_array.py create mode 100644 compiler/modules/local_bitcell_array.py create mode 100644 compiler/modules/wordline_buffer_array.py create mode 100755 compiler/tests/08_wordline_buffer_array_test.py diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 97b681e9..ce72b137 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -17,8 +17,8 @@ class bitcell_array(bitcell_base_array): and word line is connected by abutment. Connects the word lines and bit lines. """ - def __init__(self, cols, rows, name, column_offset=0): - super().__init__(cols, rows, name, column_offset) + def __init__(self, rows, cols, column_offset=0, name=""): + super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name) self.create_netlist() if not OPTS.netlist_only: @@ -57,8 +57,8 @@ class bitcell_array(bitcell_base_array): name = "bit_r{0}_c{1}".format(row, col) self.cell_inst[row, col]=self.add_inst(name=name, mod=self.cell) - self.connect_inst(self.get_bitcell_pins(col, row)) - + self.connect_inst(self.get_bitcell_pins(row, col)) + def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" diff --git a/compiler/modules/bitcell_base_array.py b/compiler/modules/bitcell_base_array.py index 7d241b4d..793cfc34 100644 --- a/compiler/modules/bitcell_base_array.py +++ b/compiler/modules/bitcell_base_array.py @@ -14,7 +14,7 @@ class bitcell_base_array(design.design): """ Abstract base class for bitcell-arrays -- bitcell, dummy """ - def __init__(self, cols, rows, name, column_offset): + def __init__(self, name, rows, cols, column_offset): design.design.__init__(self, name) debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) self.add_comment("rows: {0} cols: {1}".format(rows, cols)) @@ -61,7 +61,7 @@ class bitcell_base_array(design.design): self.add_pin("vdd", "POWER") self.add_pin("gnd", "GROUND") - def get_bitcell_pins(self, col, row): + def get_bitcell_pins(self, row, col): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ diff --git a/compiler/modules/col_cap_array.py b/compiler/modules/col_cap_array.py index ee9302d8..d9fe78b5 100644 --- a/compiler/modules/col_cap_array.py +++ b/compiler/modules/col_cap_array.py @@ -50,9 +50,9 @@ class col_cap_array(bitcell_base_array): name = "bit_r{0}_c{1}".format(row, col) self.cell_inst[row, col]=self.add_inst(name=name, mod=self.dummy_cell) - self.connect_inst(self.get_bitcell_pins(col, row)) + self.connect_inst(self.get_bitcell_pins(row, col)) - def get_bitcell_pins(self, col, row): + def get_bitcell_pins(self, row, col): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py index f4b240da..9004994b 100644 --- a/compiler/modules/dummy_array.py +++ b/compiler/modules/dummy_array.py @@ -12,8 +12,8 @@ class dummy_array(bitcell_base_array): """ Generate a dummy row/column for the replica array. """ - def __init__(self, cols, rows, column_offset=0, mirror=0, name=""): - super().__init__(cols, rows, name, column_offset) + def __init__(self, rows, cols, column_offset=0, mirror=0, name=""): + super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name) self.mirror = mirror self.create_netlist() @@ -51,7 +51,7 @@ class dummy_array(bitcell_base_array): name = "bit_r{0}_c{1}".format(row, col) self.cell_inst[row, col]=self.add_inst(name=name, mod=self.dummy_cell) - self.connect_inst(self.get_bitcell_pins(col, row)) + self.connect_inst(self.get_bitcell_pins(row, col)) def input_load(self): wl_wire = self.gen_wl_wire() diff --git a/compiler/modules/global_bitcell_array.py b/compiler/modules/global_bitcell_array.py new file mode 100644 index 00000000..728f170f --- /dev/null +++ b/compiler/modules/global_bitcell_array.py @@ -0,0 +1,66 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +from bitcell_base_array import bitcell_base_array +from tech import drc, spice +from globals import OPTS +from sram_factory import factory +import debug + +class global_bitcell_array(bitcell_base_array): + """ + Creates a global bitcell array with a number + of local arrays of a sizes given by a tuple in the list. + """ + def __init__(self, sizes, name=""): + # Each bank will have the same number of rows + self.rows = sizes[0][0] + for (r, c) in sizes: + debug.check(r[0] == self.rows, "Cannot have non-uniform number of rows in global array.") + # The total of all columns will be the number of columns + self.cols = sum(x[1] for x in sizes) + self.sizes = sizes + super().__init__(rows=self.rows, cols=self.cols, name=name) + + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() + + def create_netlist(self): + """ Create and connect the netlist """ + self.add_modules() + self.add_pins() + self.create_instances() + + def create_layout(self): + + self.place() + + self.add_layout_pins() + + self.add_boundary() + + self.DRC_LVS() + + def add_modules(self): + """ Add the modules used in this design """ + self.local_mods = [] + for (row, col) in self.sizes: + la = factory.create(module_type="local_bitcell_array", rows=row, cols=col) + self.add_mod(la) + self.local_mods.append(la) + + def create_instances(self): + """ Create the module instances used in this design """ + self.local_inst = {} + for i in range(self.sizes): + name = "local_array_{0}".format(i) + self.local_inst.append(self.add_inst(name=name, + mod=self.local_mods[i]) + self.connect_inst(self.get_bitcell_pins(row, col)) + + diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py new file mode 100644 index 00000000..fc3137c6 --- /dev/null +++ b/compiler/modules/local_bitcell_array.py @@ -0,0 +1,66 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +from bitcell_base_array import bitcell_base_array +from tech import drc, spice +from globals import OPTS +from sram_factory import factory + + +class local_bitcell_array(bitcell_base_array): + """ + A local wordline array is a bitcell array with a wordline driver. + This can either be a single aray on its own if there is no hierarchical WL + or it can be combined into a larger array with hierarchical WL. + """ + def __init__(self, name, rows, cols): + super().__init__(name, rows, cols) + + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() + + # We don't offset this because we need to align + # the replica bitcell in the control logic + # self.offset_all_coordinates() + + def create_netlist(self): + """ Create and connect the netlist """ + self.add_modules() + self.add_pins() + self.create_instances() + + def create_layout(self): + + self.place_array("bit_r{0}_c{1}") + + self.add_layout_pins() + + self.add_boundary() + + self.DRC_LVS() + + def add_modules(self): + """ Add the modules used in this design """ + self.bit_array = factory.create(module_type="bitcell_array", + rows=self.rows, + cols=self.cols, + column_offset=self.column_offset) + self.add_mod(self.bit_array) + + self.wl_array = factory.create(module_type="wordline_driver_array", + rows=self.rows, + cols=self.cols) + self.add_mod(self.wl_array) + + def create_instances(self): + """ Create the module instances used in this design """ + self.bitcell_inst = self.add_inst(mod=self.bitcell_array) + self.connect_inst(self.get_bitcell_pins(row, col)) + self.wl_inst = self.add_inst(mod=self.wl_array) + self.connect_inst(self.get_bitcell_pins(row, col)) + diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 0c7e412e..0c08cd56 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -21,7 +21,7 @@ class replica_bitcell_array(design.design): Requires a regular bitcell array, replica bitcell, and dummy bitcell (Bl/BR disconnected). """ - def __init__(self, cols, rows, left_rbl, right_rbl, bitcell_ports, name): + def __init__(self, rows, cols, left_rbl, right_rbl, bitcell_ports, name): design.design.__init__(self, name) debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) self.add_comment("rows: {0} cols: {1}".format(rows, cols)) diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 9613e6fa..c75bc9ee 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -102,22 +102,22 @@ class replica_column(design.design): if (row > self.left_rbl and row < self.total_size - self.right_rbl - 1): self.cell_inst[row]=self.add_inst(name=name, mod=self.replica_cell) - self.connect_inst(self.get_bitcell_pins(0, row)) + self.connect_inst(self.get_bitcell_pins(row, 0)) elif row==self.replica_bit: self.cell_inst[row]=self.add_inst(name=name, mod=self.replica_cell) - self.connect_inst(self.get_bitcell_pins(0, row)) + self.connect_inst(self.get_bitcell_pins(row, 0)) elif (row == 0 or row == self.total_size - 1): self.cell_inst[row]=self.add_inst(name=name, mod=self.edge_cell) if end_caps_enabled: - self.connect_inst(self.get_bitcell_pins_col_cap(0, row)) + self.connect_inst(self.get_bitcell_pins_col_cap(row, 0)) else: - self.connect_inst(self.get_bitcell_pins(0, row)) + self.connect_inst(self.get_bitcell_pins(row, 0)) else: self.cell_inst[row]=self.add_inst(name=name, mod=self.dummy_cell) - self.connect_inst(self.get_bitcell_pins(0, row)) + self.connect_inst(self.get_bitcell_pins(row, 0)) def place_instances(self): from tech import cell_properties @@ -191,7 +191,7 @@ class replica_column(design.design): else: self.copy_layout_pin(inst, pin_name) - def get_bitcell_pins(self, col, row): + def get_bitcell_pins(self, row, col): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ @@ -208,7 +208,7 @@ class replica_column(design.design): return bitcell_pins - def get_bitcell_pins_col_cap(self, col, row): + def get_bitcell_pins_col_cap(self, row, col): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ diff --git a/compiler/modules/row_cap_array.py b/compiler/modules/row_cap_array.py index f108d86e..bfbd035c 100644 --- a/compiler/modules/row_cap_array.py +++ b/compiler/modules/row_cap_array.py @@ -49,9 +49,9 @@ class row_cap_array(bitcell_base_array): name = "bit_r{0}_c{1}".format(row, col) self.cell_inst[row, col]=self.add_inst(name=name, mod=self.dummy_cell) - self.connect_inst(self.get_bitcell_pins(col, row)) + self.connect_inst(self.get_bitcell_pins(row, col)) - def get_bitcell_pins(self, col, row): + def get_bitcell_pins(self, row, col): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array diff --git a/compiler/modules/wordline_buffer_array.py b/compiler/modules/wordline_buffer_array.py new file mode 100644 index 00000000..7dad327d --- /dev/null +++ b/compiler/modules/wordline_buffer_array.py @@ -0,0 +1,137 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import debug +import design +from tech import drc, layer +from vector import vector +from sram_factory import factory +from globals import OPTS + + +class wordline_buffer_array(design.design): + """ + Creates a Wordline Buffer/Inverter array + """ + + def __init__(self, name, rows, cols): + design.design.__init__(self, name) + debug.info(1, "Creating {0}".format(self.name)) + self.add_comment("rows: {0} cols: {1}".format(rows, cols)) + + self.rows = rows + self.cols = cols + + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() + + def create_netlist(self): + self.add_modules() + self.add_pins() + self.create_drivers() + + def create_layout(self): + if "li" in layer: + self.route_layer = "li" + else: + self.route_layer = "m1" + self.place_drivers() + self.route_layout() + self.route_vdd_gnd() + self.offset_all_coordinates() + self.add_boundary() + self.DRC_LVS() + + def add_pins(self): + # inputs to wordline_driver. + for i in range(self.rows): + self.add_pin("in_{0}".format(i), "INPUT") + # Outputs from wordline_driver. + for i in range(self.rows): + self.add_pin("wl_{0}".format(i), "OUTPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + def add_modules(self): + self.wl_driver = factory.create(module_type="inv_dec", + size=self.cols) + self.add_mod(self.wl_driver) + + def route_vdd_gnd(self): + """ + Add a pin for each row of vdd/gnd which + are must-connects next level up. + """ + if OPTS.tech_name == "sky130": + for name in ["vdd", "gnd"]: + supply_pins = self.wld_inst[0].get_pins(name) + for pin in supply_pins: + self.add_layout_pin_segment_center(text=name, + layer=pin.layer, + start=pin.bc(), + end=vector(pin.cx(), self.height)) + else: + # Find the x offsets for where the vias/pins should be placed + xoffset_list = [self.wld_inst[0].rx()] + for num in range(self.rows): + # this will result in duplicate polygons for rails, but who cares + + # use the inverter offset even though it will be the and's too + (gate_offset, y_dir) = self.get_gate_offset(0, + self.wl_driver.height, + num) + # Route both supplies + for name in ["vdd", "gnd"]: + supply_pin = self.wld_inst[num].get_pin(name) + + # Add pins in two locations + for xoffset in xoffset_list: + pin_pos = vector(xoffset, supply_pin.cy()) + self.add_power_pin(name, pin_pos) + + def create_drivers(self): + self.wld_inst = [] + for row in range(self.rows): + self.wld_inst.append(self.add_inst(name="wld{0}".format(row), + mod=self.wl_driver)) + self.connect_inst(["in_{0}".format(row), + "wl_{0}".format(row), + "vdd", "gnd"]) + + def place_drivers(self): + + for row in range(self.rows): + if (row % 2): + y_offset = self.wl_driver.height * (row + 1) + inst_mirror = "MX" + else: + y_offset = self.wl_driver.height * row + inst_mirror = "R0" + + offset = [0, y_offset] + + self.wld_inst[row].place(offset=offset, + mirror=inst_mirror) + + self.width = self.wl_driver.width + self.height = self.wl_driver.height * self.rows + + def route_layout(self): + """ Route all of the signals """ + + for row in range(self.rows): + inst = self.wld_inst[row] + + self.copy_layout_pin(inst, "A", "in_{0}".format(row)) + + # output each WL on the right + wl_offset = inst.get_pin("Z").rc() + self.add_layout_pin_segment_center(text="wl_{0}".format(row), + layer=self.route_layer, + start=wl_offset, + end=wl_offset - vector(self.m1_width, 0)) diff --git a/compiler/modules/wordline_driver_array.py b/compiler/modules/wordline_driver_array.py index e8a3c110..f5f8e639 100644 --- a/compiler/modules/wordline_driver_array.py +++ b/compiler/modules/wordline_driver_array.py @@ -12,6 +12,7 @@ from vector import vector from sram_factory import factory from globals import OPTS + class wordline_driver_array(design.design): """ Creates a Wordline Driver diff --git a/compiler/tests/08_wordline_buffer_array_test.py b/compiler/tests/08_wordline_buffer_array_test.py new file mode 100755 index 00000000..a753a21a --- /dev/null +++ b/compiler/tests/08_wordline_buffer_array_test.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import unittest +from testutils import * +import sys,os +sys.path.append(os.getenv("OPENRAM_HOME")) +import globals +from globals import OPTS +from sram_factory import factory +import debug + + +class wordline_buffer_array_test(openram_test): + + def runTest(self): + config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + + # check wordline driver for single port + debug.info(2, "Checking driver") + tx = factory.create(module_type="wordline_buffer_array", rows=8, cols=32) + self.local_check(tx) + + globals.end_openram() + +# run the test from the command line +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) From 2991534d3f2de86e6986cec02daa22523172de7b Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 23 Jul 2020 17:15:39 -0700 Subject: [PATCH 26/65] Drafting local bitline stuff. --- compiler/modules/local_bitcell_array.py | 33 +++++++++-------- compiler/modules/wordline_buffer_array.py | 6 ++-- compiler/tests/05_local_bitcell_array_test.py | 36 +++++++++++++++++++ 3 files changed, 58 insertions(+), 17 deletions(-) create mode 100755 compiler/tests/05_local_bitcell_array_test.py diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index fc3137c6..8b56ea19 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -13,12 +13,12 @@ from sram_factory import factory class local_bitcell_array(bitcell_base_array): """ - A local wordline array is a bitcell array with a wordline driver. + A local bitcell array is a bitcell array with a wordline driver. This can either be a single aray on its own if there is no hierarchical WL or it can be combined into a larger array with hierarchical WL. """ def __init__(self, name, rows, cols): - super().__init__(name, rows, cols) + super().__init__(name=name, rows=rows, cols=cols, column_offset=0) self.create_netlist() if not OPTS.netlist_only: @@ -36,7 +36,7 @@ class local_bitcell_array(bitcell_base_array): def create_layout(self): - self.place_array("bit_r{0}_c{1}") + self.place() self.add_layout_pins() @@ -46,21 +46,26 @@ class local_bitcell_array(bitcell_base_array): def add_modules(self): """ Add the modules used in this design """ - self.bit_array = factory.create(module_type="bitcell_array", - rows=self.rows, - cols=self.cols, - column_offset=self.column_offset) - self.add_mod(self.bit_array) + # This is just used for names + self.cell = factory.create(module_type="bitcell") + + self.bitcell_array = factory.create(module_type="bitcell_array", + rows=self.row_size, + cols=self.column_size) + self.add_mod(self.bitcell_array) - self.wl_array = factory.create(module_type="wordline_driver_array", - rows=self.rows, - cols=self.cols) + self.wl_array = factory.create(module_type="wordline_buffer_array", + rows=self.row_size, + cols=self.column_size) self.add_mod(self.wl_array) def create_instances(self): """ Create the module instances used in this design """ - self.bitcell_inst = self.add_inst(mod=self.bitcell_array) - self.connect_inst(self.get_bitcell_pins(row, col)) - self.wl_inst = self.add_inst(mod=self.wl_array) + self.array_inst = self.add_inst(mod=self.bitcell_array) + self.connect_inst(self.pins) + + #wl_names = self.get_ + self.wl_inst = self.add_inst(mod=self.wl_array, + offset=self.bitcell_inst.lr()) self.connect_inst(self.get_bitcell_pins(row, col)) diff --git a/compiler/modules/wordline_buffer_array.py b/compiler/modules/wordline_buffer_array.py index 7dad327d..be0fe1f7 100644 --- a/compiler/modules/wordline_buffer_array.py +++ b/compiler/modules/wordline_buffer_array.py @@ -53,7 +53,7 @@ class wordline_buffer_array(design.design): self.add_pin("in_{0}".format(i), "INPUT") # Outputs from wordline_driver. for i in range(self.rows): - self.add_pin("wl_{0}".format(i), "OUTPUT") + self.add_pin("out_{0}".format(i), "OUTPUT") self.add_pin("vdd", "POWER") self.add_pin("gnd", "GROUND") @@ -100,7 +100,7 @@ class wordline_buffer_array(design.design): self.wld_inst.append(self.add_inst(name="wld{0}".format(row), mod=self.wl_driver)) self.connect_inst(["in_{0}".format(row), - "wl_{0}".format(row), + "out_{0}".format(row), "vdd", "gnd"]) def place_drivers(self): @@ -131,7 +131,7 @@ class wordline_buffer_array(design.design): # output each WL on the right wl_offset = inst.get_pin("Z").rc() - self.add_layout_pin_segment_center(text="wl_{0}".format(row), + self.add_layout_pin_segment_center(text="out_{0}".format(row), layer=self.route_layer, start=wl_offset, end=wl_offset - vector(self.m1_width, 0)) diff --git a/compiler/tests/05_local_bitcell_array_test.py b/compiler/tests/05_local_bitcell_array_test.py new file mode 100755 index 00000000..1a717fb2 --- /dev/null +++ b/compiler/tests/05_local_bitcell_array_test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import unittest +from testutils import * +import sys,os +sys.path.append(os.getenv("OPENRAM_HOME")) +import globals +from globals import OPTS +from sram_factory import factory +import debug + + +class local_bitcell_array_test(openram_test): + + def runTest(self): + config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + + debug.info(2, "Testing 4x4 local bitcell array for 6t_cell") + a = factory.create(module_type="local_bitcell_array", cols=4, rows=4) + self.local_check(a) + + globals.end_openram() + +# run the test from the command line +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) From 26b01e37c6514100eb8f0e68641b301295a8e289 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 27 Jul 2020 13:59:35 -0700 Subject: [PATCH 27/65] Fix pbuf test info --- compiler/tests/04_pbuf_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/04_pbuf_test.py b/compiler/tests/04_pbuf_test.py index ffd06962..7ed92ab8 100755 --- a/compiler/tests/04_pbuf_test.py +++ b/compiler/tests/04_pbuf_test.py @@ -21,7 +21,7 @@ class pbuf_test(openram_test): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) - debug.info(2, "Testing inverter/buffer 4x 8x") + debug.info(2, "Testing buffer 8x") a = factory.create(module_type="pbuf", size=8) self.local_check(a) From 69cab426760def426a363934bb66a4e818ac15b2 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 27 Jul 2020 13:59:55 -0700 Subject: [PATCH 28/65] Add pbuf_dec gate --- compiler/pgates/pbuf_dec.py | 125 ++++++++++++++++++++++++++ compiler/tests/04_pbuf_dec_8x_test.py | 40 +++++++++ 2 files changed, 165 insertions(+) create mode 100644 compiler/pgates/pbuf_dec.py create mode 100755 compiler/tests/04_pbuf_dec_8x_test.py diff --git a/compiler/pgates/pbuf_dec.py b/compiler/pgates/pbuf_dec.py new file mode 100644 index 00000000..e5018b62 --- /dev/null +++ b/compiler/pgates/pbuf_dec.py @@ -0,0 +1,125 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import debug +from vector import vector +import pgate +from sram_factory import factory + + +class pbuf_dec(pgate.pgate): + """ + This is a simple buffer used for driving wordlines. + """ + def __init__(self, name, size=4, height=None): + + debug.info(1, "creating {0} with size of {1}".format(name, size)) + self.add_comment("size: {}".format(size)) + + self.stage_effort = 4 + self.size = size + self.height = height + + # Creates the netlist and layout + pgate.pgate.__init__(self, name, height) + + def create_netlist(self): + self.add_pins() + self.create_modules() + self.create_insts() + + def create_layout(self): + self.width = self.inv1.width + self.inv2.width + self.place_insts() + self.add_wires() + self.add_layout_pins() + self.route_supply_rails() + self.add_boundary() + + def add_pins(self): + self.add_pin("A", "INPUT") + self.add_pin("Z", "OUTPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + def create_modules(self): + # Shield the cap, but have at least a stage effort of 4 + input_size = max(1, int(self.size / self.stage_effort)) + self.inv1 = factory.create(module_type="pinv_dec", + size=input_size, + height=self.height) + self.add_mod(self.inv1) + + self.inv2 = factory.create(module_type="pinv_dec", + size=self.size, + height=self.height) + self.add_mod(self.inv2) + + def create_insts(self): + self.inv1_inst = self.add_inst(name="buf_inv1", + mod=self.inv1) + self.connect_inst(["A", "zb_int", "vdd", "gnd"]) + + self.inv2_inst = self.add_inst(name="buf_inv2", + mod=self.inv2) + self.connect_inst(["zb_int", "Z", "vdd", "gnd"]) + + def place_insts(self): + # Add INV1 to the right + self.inv1_inst.place(vector(0, 0)) + + # Add INV2 to the right + self.inv2_inst.place(vector(self.inv1_inst.rx(), 0)) + + def add_wires(self): + # inv1 Z to inv2 A + z1_pin = self.inv1_inst.get_pin("Z") + a2_pin = self.inv2_inst.get_pin("A") + mid_loc = vector(a2_pin.cx(), z1_pin.cy()) + self.add_path(self.route_layer, + [z1_pin.rc(), mid_loc, a2_pin.lc()], + width=a2_pin.width()) + + def route_supply_rails(self): + """ Add vdd/gnd rails to the top, (middle), and bottom. """ + self.copy_layout_pin(self.inv1_inst, "vdd") + self.copy_layout_pin(self.inv1_inst, "gnd") + self.copy_layout_pin(self.inv2_inst, "vdd") + self.copy_layout_pin(self.inv2_inst, "gnd") + + def add_layout_pins(self): + z_pin = self.inv2_inst.get_pin("Z") + self.add_layout_pin_rect_center(text="Z", + layer=z_pin.layer, + offset=z_pin.center(), + width=z_pin.width(), + height=z_pin.height()) + + a_pin = self.inv1_inst.get_pin("A") + self.add_layout_pin_rect_center(text="A", + layer=a_pin.layer, + offset=a_pin.center(), + width=a_pin.width(), + height=a_pin.height()) + + def get_stage_efforts(self, external_cout, inp_is_rise=False): + """Get the stage efforts of the A -> Z path""" + stage_effort_list = [] + stage1_cout = self.inv2.get_cin() + stage1 = self.inv1.get_stage_effort(stage1_cout, inp_is_rise) + stage_effort_list.append(stage1) + last_stage_is_rise = stage1.is_rise + + stage2 = self.inv2.get_stage_effort(external_cout, last_stage_is_rise) + stage_effort_list.append(stage2) + + return stage_effort_list + + def get_cin(self): + """Returns the relative capacitance of the input""" + input_cin = self.inv1.get_cin() + return input_cin diff --git a/compiler/tests/04_pbuf_dec_8x_test.py b/compiler/tests/04_pbuf_dec_8x_test.py new file mode 100755 index 00000000..ad1665fe --- /dev/null +++ b/compiler/tests/04_pbuf_dec_8x_test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import unittest +from testutils import * +import sys,os +sys.path.append(os.getenv("OPENRAM_HOME")) +import globals +from globals import OPTS +from sram_factory import factory +import debug + +class pbuf_dec_test(openram_test): + + def runTest(self): + config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) + globals.init_openram(config_file) + + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 0 + globals.setup_bitcell() + + debug.info(2, "Checking 8x size decoder buffer") + a = factory.create(module_type="pbuf_dec", size=8) + self.local_check(a) + + globals.end_openram() + +# instantiate a copdsay of the class to actually run the test +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main(testRunner=debugTestRunner()) From c65178f86c14cbbef87293019a7030fa232ffa94 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Mon, 27 Jul 2020 15:43:50 -0700 Subject: [PATCH 29/65] Fixed issue with sen delay measure getting mixed with voltage checks --- compiler/characterizer/delay.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index b7faaec3..9d36fce7 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -185,8 +185,7 @@ class delay(simulation): self.sen_meas = delay_measure("delay_sen", self.clk_frmt, self.sen_name+"{}", "FALL", "RISE", measure_scale=1e9) self.sen_meas.meta_str = sram_op.READ_ZERO self.sen_meas.meta_add_delay = True - self.dout_volt_meas.append(self.sen_meas) - + return self.dout_volt_meas def create_read_bit_measures(self): From 9ea3616260820c2010316047a29916235d5ad0b8 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Mon, 27 Jul 2020 15:47:02 -0700 Subject: [PATCH 30/65] Changed multiport characterization warning to better fit --- compiler/characterizer/delay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 9d36fce7..1fcd86f4 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -1350,7 +1350,7 @@ class delay(simulation): Return the analytical model results for the SRAM. """ if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0: - debug.warning("Analytical characterization results are not supported for multiport.") + debug.warning("Analytical characterization for multiple read ports may be inaccurate.") # Probe set to 0th bit, does not matter for analytical delay. self.set_probe('0'*self.addr_size, 0) From c260297366f5724e9cdab51e493b175beb8d8358 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 27 Jul 2020 16:22:21 -0700 Subject: [PATCH 31/65] Allow replica_bitcell_array without the replica columns for local wordlines. --- compiler/modules/col_cap_array.py | 4 +- compiler/modules/local_bitcell_array.py | 1 - compiler/modules/replica_bitcell_array.py | 172 ++++++++++++------ compiler/modules/row_cap_array.py | 4 +- .../14_replica_bitcell_array_1rw_1r_test.py | 27 ++- 5 files changed, 141 insertions(+), 67 deletions(-) diff --git a/compiler/modules/col_cap_array.py b/compiler/modules/col_cap_array.py index d9fe78b5..a2bf8379 100644 --- a/compiler/modules/col_cap_array.py +++ b/compiler/modules/col_cap_array.py @@ -13,8 +13,8 @@ class col_cap_array(bitcell_base_array): """ Generate a dummy row/column for the replica array. """ - def __init__(self, cols, rows, column_offset=0, mirror=0, name=""): - super().__init__(cols, rows, name, column_offset) + def __init__(self, rows, cols, column_offset=0, mirror=0, name=""): + super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name) self.mirror = mirror self.no_instances = True diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index 8b56ea19..d446d29c 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -6,7 +6,6 @@ # All rights reserved. # from bitcell_base_array import bitcell_base_array -from tech import drc, spice from globals import OPTS from sram_factory import factory diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 0c08cd56..a0ce8e6e 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -21,7 +21,7 @@ class replica_bitcell_array(design.design): Requires a regular bitcell array, replica bitcell, and dummy bitcell (Bl/BR disconnected). """ - def __init__(self, rows, cols, left_rbl, right_rbl, bitcell_ports, name): + def __init__(self, rows, cols, left_rbl, right_rbl, bitcell_ports, name, add_replica=True): design.design.__init__(self, name) debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) self.add_comment("rows: {0} cols: {1}".format(rows, cols)) @@ -31,15 +31,26 @@ class replica_bitcell_array(design.design): self.left_rbl = left_rbl self.right_rbl = right_rbl self.bitcell_ports = bitcell_ports + # If set to false, we increase the height for the replica wordline row, but don't + # actually add the column to this array. This is so the height matches other + # banks that have the replica columns. + # Number of replica columns to actually add + if add_replica: + self.add_left_rbl = self.left_rbl + self.add_right_rbl = self.right_rbl + else: + self.add_left_rbl = 0 + self.add_right_rbl = 0 debug.check(left_rbl + right_rbl == len(self.all_ports), "Invalid number of RBLs for port configuration.") debug.check(left_rbl + right_rbl == len(self.bitcell_ports), "Bitcell ports must match total RBLs.") - # Two dummy rows/cols plus replica for each port - self.extra_rows = 2 + left_rbl + right_rbl - self.extra_cols = 2 + left_rbl + right_rbl + # Two dummy rows plus replica even if we don't add the column + self.extra_rows = 2 + self.left_rbl + self.right_rbl + # Two dummy cols plus replica if we add the column + self.extra_cols = 2 + self.add_left_rbl + self.add_right_rbl self.create_netlist() if not OPTS.netlist_only: @@ -84,28 +95,28 @@ class replica_bitcell_array(design.design): # Bitcell array self.bitcell_array = factory.create(module_type="bitcell_array", - column_offset=1 + self.left_rbl, + column_offset=1 + self.add_left_rbl, cols=self.column_size, rows=self.row_size) self.add_mod(self.bitcell_array) # Replica bitlines self.replica_columns = {} - for bit in range(self.left_rbl + self.right_rbl): + for bit in range(self.add_left_rbl + self.add_right_rbl): # Creating left_rbl - if bit1 port) - for port in range(self.left_rbl): + for port in range(self.add_left_rbl): # Make names for all RBLs wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] # Keep track of the pin that is the RBL @@ -184,7 +195,7 @@ class replica_bitcell_array(design.design): # Regular WLs self.replica_col_wl_names.extend(self.bitcell_array_wl_names) # Right port WLs (one dummy for each port when we allow >1 port) - for port in range(self.left_rbl, self.left_rbl + self.right_rbl): + for port in range(self.add_left_rbl, self.add_left_rbl + self.add_right_rbl): # Make names for all RBLs wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] # Keep track of the pin that is the RBL @@ -192,14 +203,33 @@ class replica_bitcell_array(design.design): self.replica_col_wl_names.extend(wl_names) self.replica_col_wl_names.extend(["{0}_top".format(x) for x in self.dummy_cell_wl_names]) + # Create the full WL names include dummy, replica, and regular bit cells # Left/right dummy columns are connected identically to the replica column - self.dummy_col_wl_names = self.replica_col_wl_names + self.dummy_col_wl_names = [] + self.dummy_col_wl_names.extend(["{0}_bot".format(x) for x in self.dummy_cell_wl_names]) + # Left port WLs (one dummy for each port when we allow >1 port) + for port in range(self.left_rbl): + # Make names for all RBLs + wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] + # Keep track of the pin that is the RBL + self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] + self.dummy_col_wl_names.extend(wl_names) + # Regular WLs + self.dummy_col_wl_names.extend(self.bitcell_array_wl_names) + # Right port WLs (one dummy for each port when we allow >1 port) + for port in range(self.left_rbl, self.left_rbl + self.right_rbl): + # Make names for all RBLs + wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] + # Keep track of the pin that is the RBL + self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] + self.dummy_col_wl_names.extend(wl_names) + self.dummy_col_wl_names.extend(["{0}_top".format(x) for x in self.dummy_cell_wl_names]) # Per port bitline names self.replica_bl_names = {} self.replica_wl_names = {} # Array of all port bitline names - for port in range(self.left_rbl + self.right_rbl): + for port in range(self.add_left_rbl + self.add_right_rbl): left_names=["rbl_{0}_{1}".format(self.cell.get_bl_name(x), port) for x in range(len(self.all_ports))] right_names=["rbl_{0}_{1}".format(self.cell.get_br_name(x), port) for x in range(len(self.all_ports))] # Keep track of the left pins that are the RBL @@ -209,6 +239,8 @@ class replica_bitcell_array(design.design): bl_names = [x for t in zip(left_names, right_names) for x in t] self.replica_bl_names[port] = bl_names + # Array of all port wl names + for port in range(self.left_rbl + self.right_rbl): wl_names = ["rbl_{0}_{1}".format(x, port) for x in self.cell.get_all_wl_names()] self.replica_wl_names[port] = wl_names @@ -243,13 +275,14 @@ class replica_bitcell_array(design.design): # Replica columns self.replica_col_inst = {} - for port in range(self.left_rbl + self.right_rbl): + for port in range(self.add_left_rbl + self.add_right_rbl): self.replica_col_inst[port]=self.add_inst(name="replica_col_{}".format(port), mod=self.replica_columns[port]) self.connect_inst(self.replica_bl_names[port] + self.replica_col_wl_names + supplies) - + # Dummy rows under the bitcell array (connected with with the replica cell wl) self.dummy_row_replica_inst = {} + # Note, this is the number of left and right even if we aren't adding the columns to this bitcell array! for port in range(self.left_rbl + self.right_rbl): self.dummy_row_replica_inst[port]=self.add_inst(name="dummy_row_{}".format(port), mod=self.dummy_row) @@ -277,41 +310,18 @@ class replica_bitcell_array(design.design): self.width = (self.column_size + self.extra_cols) * self.cell.width # This is a bitcell x bitcell offset to scale - offset = vector(self.cell.width, self.cell.height) + self.bitcell_offset = vector(self.cell.width, self.cell.height) + # Everything is computed with the main array at (0, 0) to start self.bitcell_array_inst.place(offset=[0, 0]) - # To the left of the bitcell array - for bit in range(self.left_rbl): - self.replica_col_inst[bit].place(offset=offset.scale(-bit - 1, -self.left_rbl - 1)) - # To the right of the bitcell array - for bit in range(self.right_rbl): - self.replica_col_inst[self.left_rbl + bit].place(offset=offset.scale(bit, -self.left_rbl - 1) + self.bitcell_array_inst.lr()) + self.add_replica_columns() + + self.add_end_caps() - # FIXME: These depend on the array size itself - # Far top dummy row (first row above array is NOT flipped) - flip_dummy = self.right_rbl % 2 - self.dummy_row_top_inst.place(offset=offset.scale(0, self.right_rbl + flip_dummy) + self.bitcell_array_inst.ul(), - mirror="MX" if flip_dummy else "R0") - # FIXME: These depend on the array size itself - # Far bottom dummy row (first row below array IS flipped) - flip_dummy = (self.left_rbl + 1) % 2 - self.dummy_row_bot_inst.place(offset=offset.scale(0, -self.left_rbl - 1 + flip_dummy), - mirror="MX" if flip_dummy else "R0") - # Far left dummy col - self.dummy_col_left_inst.place(offset=offset.scale(-self.left_rbl - 1, -self.left_rbl - 1)) - # Far right dummy col - self.dummy_col_right_inst.place(offset=offset.scale(self.right_rbl, -self.left_rbl - 1) + self.bitcell_array_inst.lr()) - - # Replica dummy rows - for bit in range(self.left_rbl): - self.dummy_row_replica_inst[bit].place(offset=offset.scale(0, -bit - bit % 2), - mirror="R0" if bit % 2 else "MX") - for bit in range(self.right_rbl): - self.dummy_row_replica_inst[self.left_rbl + bit].place(offset=offset.scale(0, bit + bit % 2) + self.bitcell_array_inst.ul(), - mirror="MX" if bit % 2 else "R0") - - self.translate_all(offset.scale(-1 - self.left_rbl, -1 - self.left_rbl)) + # Array was at (0, 0) but move everything so it is at the lower left + # We move DOWN the number of left RBL even if we didn't add the column to this bitcell array + self.translate_all(self.bitcell_offset.scale(-1 - self.add_left_rbl, -1 - self.left_rbl)) self.add_layout_pins() @@ -319,6 +329,49 @@ class replica_bitcell_array(design.design): self.DRC_LVS() + def add_replica_columns(self): + """ Add replica columns on left and right of array """ + + # To the left of the bitcell array + for bit in range(self.add_left_rbl): + self.replica_col_inst[bit].place(offset=self.bitcell_offset.scale(-bit - 1, -self.add_left_rbl - 1)) + # To the right of the bitcell array + for bit in range(self.add_right_rbl): + self.replica_col_inst[self.add_left_rbl + bit].place(offset=self.bitcell_offset.scale(bit, -self.add_left_rbl - 1) + self.bitcell_array_inst.lr()) + + # Replica dummy rows + # Add the dummy rows even if we aren't adding the replica column to this bitcell array + for bit in range(self.left_rbl): + self.dummy_row_replica_inst[bit].place(offset=self.bitcell_offset.scale(0, -bit - bit % 2), + mirror="R0" if bit % 2 else "MX") + for bit in range(self.right_rbl): + self.dummy_row_replica_inst[self.left_rbl + bit].place(offset=self.bitcell_offset.scale(0, bit + bit % 2) + self.bitcell_array_inst.ul(), + mirror="MX" if bit % 2 else "R0") + + def add_end_caps(self): + """ Add dummy cells or end caps around the array """ + + # FIXME: These depend on the array size itself + # Far top dummy row (first row above array is NOT flipped) + flip_dummy = self.right_rbl % 2 + dummy_row_offset = self.bitcell_offset.scale(0, self.right_rbl + flip_dummy) + self.bitcell_array_inst.ul() + self.dummy_row_top_inst.place(offset=dummy_row_offset, + mirror="MX" if flip_dummy else "R0") + # FIXME: These depend on the array size itself + # Far bottom dummy row (first row below array IS flipped) + flip_dummy = (self.left_rbl + 1) % 2 + dummy_row_offset = self.bitcell_offset.scale(0, -self.left_rbl - 1 + flip_dummy) + self.dummy_row_bot_inst.place(offset=dummy_row_offset, + mirror="MX" if flip_dummy else "R0") + # Far left dummy col + # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array + dummy_col_offset = self.bitcell_offset.scale(-self.add_left_rbl - 1, -self.left_rbl - 1) + self.dummy_col_left_inst.place(offset=dummy_col_offset) + # Far right dummy col + # Shifted down by the number of left RBLs even if we aren't adding replica column to this bitcell array + dummy_col_offset = self.bitcell_offset.scale(self.add_right_rbl, -self.left_rbl - 1) + self.bitcell_array_inst.lr() + self.dummy_col_right_inst.place(offset=dummy_col_offset) + def add_layout_pins(self): """ Add the layout pins """ @@ -345,13 +398,13 @@ class replica_bitcell_array(design.design): height=self.height) # Replica wordlines - for port in range(self.left_rbl + self.right_rbl): + for port in range(self.add_left_rbl + self.add_right_rbl): inst = self.replica_col_inst[port] for (pin_name, wl_name) in zip(self.cell.get_all_wl_names(), self.replica_wl_names[port]): # +1 for dummy row pin_bit = port + 1 # +row_size if above the array - if port>=self.left_rbl: + if port>=self.add_left_rbl: pin_bit += self.row_size pin_name += "_{}".format(pin_bit) @@ -362,12 +415,13 @@ class replica_bitcell_array(design.design): offset=pin.ll().scale(0, 1), width=self.width, height=pin.height()) - + # Replica bitlines - for port in range(self.left_rbl + self.right_rbl): + for port in range(self.add_left_rbl + self.add_right_rbl): inst = self.replica_col_inst[port] for (pin_name, bl_name) in zip(self.cell.get_all_bitline_names(), self.replica_bl_names[port]): pin = inst.get_pin(pin_name) + if bl_name in self.rbl_bl_names or bl_name in self.rbl_br_names: name = bl_name else: diff --git a/compiler/modules/row_cap_array.py b/compiler/modules/row_cap_array.py index bfbd035c..58b33c89 100644 --- a/compiler/modules/row_cap_array.py +++ b/compiler/modules/row_cap_array.py @@ -13,8 +13,8 @@ class row_cap_array(bitcell_base_array): """ Generate a dummy row/column for the replica array. """ - def __init__(self, cols, rows, column_offset=0, mirror=0, name=""): - super().__init__(cols, rows, name, column_offset) + def __init__(self, rows, cols, column_offset=0, mirror=0, name=""): + super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name) self.mirror = mirror self.no_instances = True self.create_netlist() diff --git a/compiler/tests/14_replica_bitcell_array_1rw_1r_test.py b/compiler/tests/14_replica_bitcell_array_1rw_1r_test.py index 626725c4..bfb35cd7 100755 --- a/compiler/tests/14_replica_bitcell_array_1rw_1r_test.py +++ b/compiler/tests/14_replica_bitcell_array_1rw_1r_test.py @@ -24,14 +24,35 @@ class replica_bitcell_array_1rw_1r_test(openram_test): OPTS.num_w_ports = 0 globals.setup_bitcell() - debug.info(2, "Testing 4x4 array for cell_1rw_1r") - a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=1, right_rbl=1, bitcell_ports=[0, 1]) + debug.info(2, "Testing 4x4 non-replica array for cell_1rw_1r") + a = factory.create(module_type="replica_bitcell_array", + cols=4, + rows=4, + left_rbl=1, + right_rbl=1, + bitcell_ports=[0, 1], + add_replica=False) self.local_check(a) + debug.info(2, "Testing 4x4 array for cell_1rw_1r") + a = factory.create(module_type="replica_bitcell_array", + cols=4, + rows=4, + left_rbl=1, + right_rbl=1, + bitcell_ports=[0, 1]) + self.local_check(a) + + # Sky 130 has restrictions on the symmetries if OPTS.tech_name != "sky130": debug.info(2, "Testing 4x4 array for cell_1rw_1r") - a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=2, right_rbl=0, bitcell_ports=[0, 1]) + a = factory.create(module_type="replica_bitcell_array", + cols=4, + rows=4, + left_rbl=2, + right_rbl=0, + bitcell_ports=[0, 1]) self.local_check(a) globals.end_openram() From b4dafac489d4f618bcb3fc080a97f5688e5f1fac Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Mon, 27 Jul 2020 23:55:03 -0700 Subject: [PATCH 32/65] Fixed issue with sen measurement not being added --- compiler/characterizer/delay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 1fcd86f4..afb9c7f6 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -186,7 +186,7 @@ class delay(simulation): self.sen_meas.meta_str = sram_op.READ_ZERO self.sen_meas.meta_add_delay = True - return self.dout_volt_meas + return self.dout_volt_meas + [self.sen_meas] def create_read_bit_measures(self): """ Adds bit measurements for read0 and read1 cycles """ From 2fa561f98f5aee68ba26f611da370439c4e979d8 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 29 Jul 2020 10:08:13 -0700 Subject: [PATCH 33/65] Local bitcell array edits. Skip test by default. --- compiler/modules/bitcell_base_array.py | 2 +- compiler/modules/local_bitcell_array.py | 40 ++++++++++++------- compiler/tests/05_local_bitcell_array_test.py | 2 +- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/compiler/modules/bitcell_base_array.py b/compiler/modules/bitcell_base_array.py index 793cfc34..2ef710e3 100644 --- a/compiler/modules/bitcell_base_array.py +++ b/compiler/modules/bitcell_base_array.py @@ -12,7 +12,7 @@ from tech import cell_properties class bitcell_base_array(design.design): """ - Abstract base class for bitcell-arrays -- bitcell, dummy + Abstract base class for bitcell-arrays -- bitcell, dummy, replica """ def __init__(self, name, rows, cols, column_offset): design.design.__init__(self, name) diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index d446d29c..a9b98490 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -5,20 +5,28 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -from bitcell_base_array import bitcell_base_array +import design from globals import OPTS from sram_factory import factory -class local_bitcell_array(bitcell_base_array): +class local_bitcell_array(design.design): """ A local bitcell array is a bitcell array with a wordline driver. This can either be a single aray on its own if there is no hierarchical WL or it can be combined into a larger array with hierarchical WL. """ - def __init__(self, name, rows, cols): - super().__init__(name=name, rows=rows, cols=cols, column_offset=0) + def __init__(self, rows, cols, ports, left_rbl=0, right_rbl=0, name=""): + design.design.__init__(self, name) + debug.info(2, "create sram of size {0} with {1} words".format(self.word_size, + self.num_words)) + self.rows = rows + self.cols = cols + self.left_rbl = left_rbl + self.right_rbl = right_rbl + self.all_ports = ports + self.create_netlist() if not OPTS.netlist_only: self.create_layout() @@ -48,23 +56,27 @@ class local_bitcell_array(bitcell_base_array): # This is just used for names self.cell = factory.create(module_type="bitcell") - self.bitcell_array = factory.create(module_type="bitcell_array", - rows=self.row_size, - cols=self.column_size) + self.bitcell_array = factory.create(module_type="replica_bitcell_array", + cols=self.cols, + rows=self.rows, + left_rbl=self.left_rbl, + right_rbl=self.right_rbl, + bitcell_ports=self.all_ports) self.add_mod(self.bitcell_array) self.wl_array = factory.create(module_type="wordline_buffer_array", - rows=self.row_size, - cols=self.column_size) + rows=self.rows, + cols=self.cols) self.add_mod(self.wl_array) def create_instances(self): """ Create the module instances used in this design """ - self.array_inst = self.add_inst(mod=self.bitcell_array) + + self.wl_inst = self.add_inst(mod=self.wl_array) + self.connect_inst(self.pins) + + self.array_inst = self.add_inst(mod=self.bitcell_array, + offset=self.wl_inst.lr()) self.connect_inst(self.pins) - #wl_names = self.get_ - self.wl_inst = self.add_inst(mod=self.wl_array, - offset=self.bitcell_inst.lr()) - self.connect_inst(self.get_bitcell_pins(row, col)) diff --git a/compiler/tests/05_local_bitcell_array_test.py b/compiler/tests/05_local_bitcell_array_test.py index 1a717fb2..c5b26b06 100755 --- a/compiler/tests/05_local_bitcell_array_test.py +++ b/compiler/tests/05_local_bitcell_array_test.py @@ -15,7 +15,7 @@ from globals import OPTS from sram_factory import factory import debug - +@unittest.skip("SKIPPING 05_local_bitcell_array_test") class local_bitcell_array_test(openram_test): def runTest(self): From f23d2e36a798685c3d0795f6c4c711da0229afd7 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 29 Jul 2020 10:31:18 -0700 Subject: [PATCH 34/65] Don't obstruct control logic signals with dffs when no column mux. --- compiler/sram/sram_1bank.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index a5dfb0e5..fc390f37 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -160,7 +160,10 @@ class sram_1bank(sram_base): port = 0 # Add the col address flops below the bank to the right of the control logic x_offset = self.control_logic_insts[port].rx() + self.dff.width - y_offset = - self.data_bus_size[port] - self.dff.height + # Place it a data bus below the x-axis, but at least as low as the control logic to not block + # the control logic signals + y_offset = min(-self.data_bus_size[port] - self.dff.height, + self.control_logic_insts[port].by()) if self.col_addr_dff: self.col_addr_pos[port] = vector(x_offset, y_offset) @@ -201,7 +204,10 @@ class sram_1bank(sram_base): # Add the col address flops below the bank to the right of the control logic x_offset = self.control_logic_insts[port].lx() - 2 * self.dff.width - y_offset = self.bank.height + self.data_bus_size[port] + self.dff.height + # Place it a data bus below the x-axis, but at least as high as the control logic to not block + # the control logic signals + y_offset = max(self.bank.height + self.data_bus_size[port] + self.dff.height, + self.control_logic_insts[port].uy() - self.dff.height) if self.col_addr_dff: self.col_addr_pos[port] = vector(x_offset, y_offset) From c6f2edc20d03f292ff19b1f709761f84d6a6eba6 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Wed, 29 Jul 2020 19:50:06 -0700 Subject: [PATCH 35/65] Changed warning message for multiport analytical characterization. --- compiler/characterizer/delay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index afb9c7f6..3f5d61af 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -1350,7 +1350,7 @@ class delay(simulation): Return the analytical model results for the SRAM. """ if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0: - debug.warning("Analytical characterization for multiple read ports may be inaccurate.") + debug.warning("In analytical mode, all ports have the timing of the first read port.") # Probe set to 0th bit, does not matter for analytical delay. self.set_probe('0'*self.addr_size, 0) From 8fa0065aafb8e98f3b275d2508fb51ee13059cb7 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 30 Jul 2020 11:09:19 -0700 Subject: [PATCH 36/65] Undo PR 82 changes -- broke unit test. --- compiler/verify/calibre.py | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/compiler/verify/calibre.py b/compiler/verify/calibre.py index 6d1786c9..443c91ca 100644 --- a/compiler/verify/calibre.py +++ b/compiler/verify/calibre.py @@ -135,11 +135,11 @@ def write_calibre_lvs_script(cell_name, final_verification): def write_calibre_pex_script(cell_name, extract, output, final_verification): """ Write a pex script that can either just extract the netlist or the netlist+parasitics """ if output == None: - output = cell_name + ".pex.netlist" + output = name + ".pex.netlist" # check if lvs report has been done # if not run drc and lvs - if not os.path.isfile(OPTS.openram_temp + cell_name + ".lvs.report"): + if not os.path.isfile(cell_name + ".lvs.report"): gds_name = OPTS.openram_temp +"/"+ cell_name + ".gds" sp_name = OPTS.openram_temp +"/"+ cell_name + ".sp" run_drc(cell_name, gds_name) @@ -155,7 +155,7 @@ def write_calibre_pex_script(cell_name, extract, output, final_verification): 'pexSourcePath': cell_name + ".sp", 'pexSourcePrimary': cell_name, 'pexReportFile': cell_name + ".pex.report", - 'pexPexNetlistFile': output, + 'pexPexNetlistFile': cell_name + ".pex.netlist", 'pexPexReportFile': cell_name + ".pex.report", 'pexMaskDBFile': cell_name + ".maskdb", 'cmnFDIDEFLayoutPath': cell_name + ".def", @@ -195,8 +195,8 @@ def run_drc(cell_name, gds_name, extract=False, final_verification=False): filter_gds(cell_name, OPTS.openram_temp + "temp.gds", OPTS.openram_temp + cell_name + ".gds") else: # Copy file to local dir if it isn't already - if not os.path.isfile(gds_name): - shutil.copy(OPTS.output_path+os.path.basename(gds_name),gds_name) + if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): + shutil.copy(gds_name, OPTS.openram_temp) drc_runset = write_calibre_drc_script(cell_name, extract, final_verification) @@ -241,14 +241,10 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): lvs_runset = write_calibre_lvs_script(cell_name, final_verification) # Copy file to local dir if it isn't already -# if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): -# shutil.copy(gds_name, OPTS.openram_temp) -# if os.path.dirname(sp_name)!=OPTS.openram_temp.rstrip('/'): -# shutil.copy(sp_name, OPTS.openram_temp) - if not os.path.isfile(gds_name): - shutil.copy(OPTS.output_path+os.path.basename(gds_name), gds_name) - if not os.path.isfile(sp_name): - shutil.copy(OPTS.output_path+os.path.basename(sp_name), sp_name) + if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): + shutil.copy(gds_name, OPTS.openram_temp) + if os.path.dirname(sp_name)!=OPTS.openram_temp.rstrip('/'): + shutil.copy(sp_name, OPTS.openram_temp) (outfile, errfile, resultsfile) = run_script(cell_name, "lvs") @@ -331,11 +327,6 @@ def run_pex(cell_name, gds_name, sp_name, output=None, final_verification=False) write_calibre_pex_script(cell_name,True,output,final_verification) - if not os.path.isfile(OPTS.openram_temp + os.path.basename(gds_name)): - shutil.copy(gds_name, OPTS.openram_temp + os.path.basename(gds_name)) - if not os.path.isfile(OPTS.openram_temp + os.path.basename(sp_name)): - shutil.copy(sp_name, OPTS.openram_temp + os.path.basename(sp_name)) - (outfile, errfile, resultsfile) = run_script(cell_name, "pex") From 487027a9f2694f364cf1f2d498dc63c2b2d6aae2 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 30 Jul 2020 11:35:13 -0700 Subject: [PATCH 37/65] Fix pex file names --- compiler/sram/sram.py | 4 ++-- compiler/verify/calibre.py | 23 ++++++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index b2ab1124..686877da 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -100,9 +100,9 @@ class sram(): import verify start_time = datetime.datetime.now() # Output the extracted design if requested - sp_file = OPTS.output_path + "temp_pex.sp" + pexname = OPTS.output_path + self.s.name + ".pex.sp" spname = OPTS.output_path + self.s.name + ".sp" - verify.run_pex(self.s.name, gdsname, spname, output=sp_file) + verify.run_pex(self.s.name, gdsname, spname, output=pexname) print_time("Extraction", datetime.datetime.now(), start_time) else: # Use generated spice file for characterization diff --git a/compiler/verify/calibre.py b/compiler/verify/calibre.py index 443c91ca..1c13103d 100644 --- a/compiler/verify/calibre.py +++ b/compiler/verify/calibre.py @@ -135,11 +135,11 @@ def write_calibre_lvs_script(cell_name, final_verification): def write_calibre_pex_script(cell_name, extract, output, final_verification): """ Write a pex script that can either just extract the netlist or the netlist+parasitics """ if output == None: - output = name + ".pex.netlist" + output = cell_name + ".pex.sp" # check if lvs report has been done # if not run drc and lvs - if not os.path.isfile(cell_name + ".lvs.report"): + if not os.path.isfile(OPTS.openram_temp + cell_name + ".lvs.report"): gds_name = OPTS.openram_temp +"/"+ cell_name + ".gds" sp_name = OPTS.openram_temp +"/"+ cell_name + ".sp" run_drc(cell_name, gds_name) @@ -155,7 +155,7 @@ def write_calibre_pex_script(cell_name, extract, output, final_verification): 'pexSourcePath': cell_name + ".sp", 'pexSourcePrimary': cell_name, 'pexReportFile': cell_name + ".pex.report", - 'pexPexNetlistFile': cell_name + ".pex.netlist", + 'pexPexNetlistFile': output, 'pexPexReportFile': cell_name + ".pex.report", 'pexMaskDBFile': cell_name + ".maskdb", 'cmnFDIDEFLayoutPath': cell_name + ".def", @@ -195,11 +195,14 @@ def run_drc(cell_name, gds_name, extract=False, final_verification=False): filter_gds(cell_name, OPTS.openram_temp + "temp.gds", OPTS.openram_temp + cell_name + ".gds") else: # Copy file to local dir if it isn't already - if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): + if not os.path.isfile(OPTS.openram_temp + os.path.basename(gds_name)): shutil.copy(gds_name, OPTS.openram_temp) drc_runset = write_calibre_drc_script(cell_name, extract, final_verification) + if not os.path.isfile(OPTS.openram_temp + os.path.basename(gds_name)): + shutil.copy(gds_name, OPTS.openram_temp + os.path.basename(gds_name)) + (outfile, errfile, resultsfile) = run_script(cell_name, "drc") # check the result for these lines in the summary: @@ -241,9 +244,9 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): lvs_runset = write_calibre_lvs_script(cell_name, final_verification) # Copy file to local dir if it isn't already - if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): + if not os.path.isfile(OPTS.openram_temp + os.path.basename(gds_name)): shutil.copy(gds_name, OPTS.openram_temp) - if os.path.dirname(sp_name)!=OPTS.openram_temp.rstrip('/'): + if not os.path.isfile(OPTS.openram_temp + os.path.basename(sp_name)): shutil.copy(sp_name, OPTS.openram_temp) (outfile, errfile, resultsfile) = run_script(cell_name, "lvs") @@ -325,8 +328,14 @@ def run_pex(cell_name, gds_name, sp_name, output=None, final_verification=False) global num_pex_runs num_pex_runs += 1 - write_calibre_pex_script(cell_name,True,output,final_verification) + write_calibre_pex_script(cell_name, True, output, final_verification) + # Copy file to local dir if it isn't already + if not os.path.isfile(OPTS.openram_temp + os.path.basename(gds_name)): + shutil.copy(gds_name, OPTS.openram_temp) + if not os.path.isfile(OPTS.openram_temp + os.path.basename(sp_name)): + shutil.copy(sp_name, OPTS.openram_temp) + (outfile, errfile, resultsfile) = run_script(cell_name, "pex") From dc55ededc1bb93e84b62877f95065d4411226e48 Mon Sep 17 00:00:00 2001 From: Bob Vanhoof Date: Fri, 31 Jul 2020 12:51:34 +0200 Subject: [PATCH 38/65] fix regession tests after calibre fix --- compiler/verify/calibre.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/verify/calibre.py b/compiler/verify/calibre.py index 6d1786c9..6ee41e5f 100644 --- a/compiler/verify/calibre.py +++ b/compiler/verify/calibre.py @@ -30,7 +30,7 @@ num_lvs_runs = 0 num_pex_runs = 0 -def write_calibre_drc_script(cell_name, extract, final_verification): +def write_calibre_drc_script(cell_name, extract, final_verification, gds_name): """ Write a Calibre runset file and script to run DRC """ # the runset file contains all the options to run calibre from tech import drc @@ -39,7 +39,7 @@ def write_calibre_drc_script(cell_name, extract, final_verification): drc_runset = { 'drcRulesFile': drc_rules, 'drcRunDir': OPTS.openram_temp, - 'drcLayoutPaths': cell_name + ".gds", + 'drcLayoutPaths': gds_name, 'drcLayoutPrimary': cell_name, 'drcLayoutSystem': 'GDSII', 'drcResultsformat': 'ASCII', @@ -68,7 +68,7 @@ def write_calibre_drc_script(cell_name, extract, final_verification): return drc_runset -def write_calibre_lvs_script(cell_name, final_verification): +def write_calibre_lvs_script(cell_name, final_verification, gds_name, sp_name): """ Write a Calibre runset file and script to run LVS """ from tech import drc @@ -76,9 +76,9 @@ def write_calibre_lvs_script(cell_name, final_verification): lvs_runset = { 'lvsRulesFile': lvs_rules, 'lvsRunDir': OPTS.openram_temp, - 'lvsLayoutPaths': cell_name + ".gds", + 'lvsLayoutPaths': gds_name, 'lvsLayoutPrimary': cell_name, - 'lvsSourcePath': cell_name + ".sp", + 'lvsSourcePath': sp_name, 'lvsSourcePrimary': cell_name, 'lvsSourceSystem': 'SPICE', 'lvsSpiceFile': "{}.spice".format(cell_name), @@ -198,7 +198,7 @@ def run_drc(cell_name, gds_name, extract=False, final_verification=False): if not os.path.isfile(gds_name): shutil.copy(OPTS.output_path+os.path.basename(gds_name),gds_name) - drc_runset = write_calibre_drc_script(cell_name, extract, final_verification) + drc_runset = write_calibre_drc_script(cell_name, extract, final_verification, gds_name) (outfile, errfile, resultsfile) = run_script(cell_name, "drc") @@ -238,7 +238,7 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): global num_lvs_runs num_lvs_runs += 1 - lvs_runset = write_calibre_lvs_script(cell_name, final_verification) + lvs_runset = write_calibre_lvs_script(cell_name, final_verification, gds_name, sp_name) # Copy file to local dir if it isn't already # if os.path.dirname(gds_name)!=OPTS.openram_temp.rstrip('/'): From 3221b4ec5724c50419784723bb0e0588118e3503 Mon Sep 17 00:00:00 2001 From: jcirimel Date: Fri, 31 Jul 2020 05:27:19 -0700 Subject: [PATCH 39/65] update to new metal stack names --- compiler/bitcells/bitcell.py | 4 ++-- compiler/bitcells/bitcell_base.py | 6 +++--- compiler/bitcells/pbitcell.py | 18 +++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index e91d8c2f..814d9308 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -33,7 +33,7 @@ class bitcell(bitcell_base.bitcell_base): props.bitcell.cell_6t.pin.vdd, props.bitcell.cell_6t.pin.gnd] type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] - storage_nets = ['Q', 'Qbar'] + storage_nets = ['Q', 'Q_bar'] (width, height) = utils.get_libcell_size("cell_6t", GDS["unit"], @@ -51,7 +51,7 @@ class bitcell(bitcell_base.bitcell_base): self.add_pin_types(self.type_list) self.nets_match = self.do_nets_exist(self.storage_nets) - debug.check(OPTS.tech_name != "sky130", "sky130 does not yet support single port cells") +# debug.check(OPTS.tech_name != "sky130", "sky130 does not yet support single port cells") def get_all_wl_names(self): """ Creates a list of all wordline pin names """ diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 58f7bdcb..690e98fa 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -89,7 +89,7 @@ class bitcell_base(design.design): if OPTS.bitcell is not "pbitcell": self.storage_net_offsets = [] for i in range(len(self.get_storage_net_names())): - for text in self.gds.getTexts(layer["metal1"]): + for text in self.gds.getTexts(layer["m1"]): if self.storage_nets[i] == text.textString.rstrip('\x00'): self.storage_net_offsets.append(text.coordinates[0]) @@ -111,7 +111,7 @@ class bitcell_base(design.design): self.br_offsets = [] for i in range(len(bl_names)): - for text in self.gds.getTexts(layer["metal2"]): + for text in self.gds.getTexts(layer["m2"]): if not bl_names[i] in found_bl: if bl_names[i] == text.textString.rstrip('\x00'): self.bl_offsets.append(text.coordinates[0]) @@ -120,7 +120,7 @@ class bitcell_base(design.design): continue for i in range(len(br_names)): - for text in self.gds.getTexts(layer["metal2"]): + for text in self.gds.getTexts(layer["m2"]): if not br_names[i] in found_br: if br_names[i] == text.textString.rstrip('\x00'): self.br_offsets.append(text.coordinates[0]) diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 98e477d8..25868df5 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -401,16 +401,16 @@ class pbitcell(bitcell_base.bitcell_base): 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]) - + if OPTS.use_pex: # add labels to cross couple inverter for extracted simulation - contact_offset_left_output = vector(self.inverter_nmos_left.get_pin("D").rc().x \ - + 0.5 * contact.poly.height, - self.cross_couple_upper_ypos) - - contact_offset_right_output = vector(self.inverter_nmos_right.get_pin("S").lc().x \ - - 0.5*contact.poly.height, - self.cross_couple_lower_ypos) - self.add_pex_labels(contact_offset_left_output, contact_offset_right_output) + contact_offset_left_output = vector(self.inverter_nmos_left.get_pin("D").rc().x \ + + 0.5 * contact.poly.height, + self.cross_couple_upper_ypos) + + contact_offset_right_output = vector(self.inverter_nmos_right.get_pin("S").lc().x \ + - 0.5*contact.poly.height, + self.cross_couple_lower_ypos) + self.add_pex_labels(contact_offset_left_output, contact_offset_right_output) def route_rails(self): """ Adds gnd and vdd rails and connects them to the inverters """ From 9b8ef5ef57cce9e89b60bca7ec5651ba04baaa43 Mon Sep 17 00:00:00 2001 From: Bob Vanhoof Date: Mon, 3 Aug 2020 10:16:12 +0200 Subject: [PATCH 40/65] fix: generated pex file was not passed correctly to lib characterizer --- compiler/sram/sram.py | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index 686877da..ed09fbe0 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -103,6 +103,7 @@ class sram(): pexname = OPTS.output_path + self.s.name + ".pex.sp" spname = OPTS.output_path + self.s.name + ".sp" verify.run_pex(self.s.name, gdsname, spname, output=pexname) + sp_file = pexname print_time("Extraction", datetime.datetime.now(), start_time) else: # Use generated spice file for characterization From 02e65a00efffeabddd67dc887a971b70c6ae85b7 Mon Sep 17 00:00:00 2001 From: jcirimel Date: Mon, 3 Aug 2020 17:14:34 -0700 Subject: [PATCH 41/65] update pex to work with dev changes --- compiler/characterizer/delay.py | 8 ++++++-- compiler/sram/sram_base.py | 10 +++++----- compiler/verify/magic.py | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 21355b0e..f5a57324 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -180,8 +180,12 @@ class delay(simulation): self.dout_volt_meas.append(voltage_at_measure("v_{}".format(meas.name), meas.targ_name_no_port)) self.dout_volt_meas[-1].meta_str = meas.meta_str - - self.sen_meas = delay_measure("delay_sen", self.clk_frmt, self.sen_name+"{}", "FALL", "RISE", measure_scale=1e9) + + if not OPTS.use_pex: + self.sen_meas = delay_measure("delay_sen", self.clk_frmt, self.sen_name+"{}", "FALL", "RISE", measure_scale=1e9) + else: + self.sen_meas = delay_measure("delay_sen", self.clk_frmt, self.sen_name, "FALL", "RISE", measure_scale=1e9) + self.sen_meas.meta_str = sram_op.READ_ZERO self.sen_meas.meta_add_delay = True self.dout_volt_meas.append(self.sen_meas) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 6dc98835..ffaca694 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -111,16 +111,16 @@ class sram_base(design, verilog, lef): bl = [] br = [] - storage_layer_name = "metal1" - bitline_layer_name = "metal2" + storage_layer_name = "m1" + bitline_layer_name = "m2" for cell in range(len(bank_offset)): Q = [bank_offset[cell][0] + Q_offset[cell][0], bank_offset[cell][1] + Q_offset[cell][1]] Q_bar = [bank_offset[cell][0] + Q_bar_offset[cell][0], bank_offset[cell][1] + Q_bar_offset[cell][1]] OPTS.words_per_row = self.words_per_row - self.add_layout_pin_rect_center("bitcell_Q_b{0}_r{1}_c{2}".format(bank_num, int(cell % (OPTS.num_words / self.words_per_row)), int(cell / (OPTS.word_size * self.words_per_row))) , storage_layer_name, Q) - self.add_layout_pin_rect_center("bitcell_Q_bar_b{0}_r{1}_c{2}".format(bank_num, int(cell % (OPTS.num_words / self.words_per_row)), int(cell / (OPTS.word_size * self.words_per_row))), storage_layer_name, Q_bar) - + self.add_layout_pin_rect_center("bitcell_Q_b{}_r{}_c{}".format(bank_num, int(cell % (OPTS.num_words / self.words_per_row)), int(cell / (OPTS.num_words))) , storage_layer_name, Q) + self.add_layout_pin_rect_center("bitcell_Q_bar_b{}_r{}_c{}".format(bank_num, int(cell % (OPTS.num_words / self.words_per_row)), int(cell / (OPTS.num_words))), storage_layer_name, Q_bar) + for cell in range(len(bl_offsets)): col = bl_meta[cell][0][2] for bitline in range(len(bl_offsets[cell])): diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 1be2f2cd..dcdf6951 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -464,7 +464,7 @@ def correct_port(name, output_file_name, ref_file_name): control_list = "+ " for bank in range(OPTS.num_banks): - control_list += "s_en{0}".format(bank) + control_list += "bank_{}/s_en0".format(bank) control_list += '\n' part2 = bitcell_list + control_list + part2 From 38648027d0e4cc4cabb45877aaf36e3f3ccc289d Mon Sep 17 00:00:00 2001 From: jcirimel Date: Tue, 4 Aug 2020 04:40:20 -0700 Subject: [PATCH 42/65] fix pinv unit test --- compiler/verify/magic.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index dcdf6951..25d36a5e 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -450,21 +450,22 @@ def correct_port(name, output_file_name, ref_file_name): part2 = pex_file.read() bitcell_list = "+ " - for bank in range(OPTS.num_banks): + if OPTS.words_per_row: for bank in range(OPTS.num_banks): - row = int(OPTS.num_words / OPTS.words_per_row) - 1 - col = int(OPTS.word_size * OPTS.words_per_row) - 1 - bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col) - bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col) - for col in range(OPTS.word_size * OPTS.words_per_row): - for port in range(OPTS.num_r_ports + OPTS.num_w_ports + OPTS.num_rw_ports): - bitcell_list += "bl{0}_{1} ".format(bank, col) - bitcell_list += "br{0}_{1} ".format(bank, col) + for bank in range(OPTS.num_banks): + row = int(OPTS.num_words / OPTS.words_per_row) - 1 + col = int(OPTS.word_size * OPTS.words_per_row) - 1 + bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col) + bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col) + for col in range(OPTS.word_size * OPTS.words_per_row): + for port in range(OPTS.num_r_ports + OPTS.num_w_ports + OPTS.num_rw_ports): + bitcell_list += "bl{0}_{1} ".format(bank, col) + bitcell_list += "br{0}_{1} ".format(bank, col) bitcell_list += "\n" - control_list = "+ " - for bank in range(OPTS.num_banks): - control_list += "bank_{}/s_en0".format(bank) + if OPTS.words_per_row: + for bank in range(OPTS.num_banks): + control_list += "bank_{}/s_en0".format(bank) control_list += '\n' part2 = bitcell_list + control_list + part2 @@ -490,4 +491,4 @@ def print_drc_stats(): def print_lvs_stats(): debug.info(1,"LVS runs: {0}".format(num_lvs_runs)) def print_pex_stats(): - debug.info(1,"PEX runs: {0}".format(num_pex_runs)) \ No newline at end of file + debug.info(1,"PEX runs: {0}".format(num_pex_runs)) From 19f4e30989f3291ba8150617db7a55bf643a14ec Mon Sep 17 00:00:00 2001 From: jcirimel Date: Tue, 4 Aug 2020 15:21:54 -0700 Subject: [PATCH 43/65] change Qbar to Q_bar in freepdk45 bitcells --- technology/freepdk45/sp_lib/cell_6t.sp | 6 +++--- technology/freepdk45/sp_lib/dummy_cell_6t.sp | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/technology/freepdk45/sp_lib/cell_6t.sp b/technology/freepdk45/sp_lib/cell_6t.sp index e1e4936d..3a66fc9a 100644 --- a/technology/freepdk45/sp_lib/cell_6t.sp +++ b/technology/freepdk45/sp_lib/cell_6t.sp @@ -5,11 +5,11 @@ MM0 Qbar Q gnd gnd NMOS_VTG W=205.00n L=50n MM4 Qbar Q vdd vdd PMOS_VTG W=90n L=50n * Inverer 2 -MM1 Q Qbar gnd gnd NMOS_VTG W=205.00n L=50n -MM5 Q Qbar vdd vdd PMOS_VTG W=90n L=50n +MM1 Q Q_bar gnd gnd NMOS_VTG W=205.00n L=50n +MM5 Q Q_bar vdd vdd PMOS_VTG W=90n L=50n * Access transistors MM3 bl wl Q gnd NMOS_VTG W=135.00n L=50n -MM2 br wl Qbar gnd NMOS_VTG W=135.00n L=50n +MM2 br wl Q_bar gnd NMOS_VTG W=135.00n L=50n .ENDS cell_6t diff --git a/technology/freepdk45/sp_lib/dummy_cell_6t.sp b/technology/freepdk45/sp_lib/dummy_cell_6t.sp index ab862ec5..6e192049 100644 --- a/technology/freepdk45/sp_lib/dummy_cell_6t.sp +++ b/technology/freepdk45/sp_lib/dummy_cell_6t.sp @@ -1,15 +1,15 @@ .SUBCKT dummy_cell_6t bl br wl vdd gnd * Inverter 1 -MM0 Qbar Q gnd gnd NMOS_VTG W=205.00n L=50n -MM4 Qbar Q vdd vdd PMOS_VTG W=90n L=50n +MM0 Q_bar Q gnd gnd NMOS_VTG W=205.00n L=50n +MM4 Q_bar Q vdd vdd PMOS_VTG W=90n L=50n * Inverer 2 -MM1 Q Qbar gnd gnd NMOS_VTG W=205.00n L=50n -MM5 Q Qbar vdd vdd PMOS_VTG W=90n L=50n +MM1 Q Q_bar gnd gnd NMOS_VTG W=205.00n L=50n +MM5 Q Q_bar vdd vdd PMOS_VTG W=90n L=50n * Access transistors MM3 bl_noconn wl Q gnd NMOS_VTG W=135.00n L=50n -MM2 br_noconn wl Qbar gnd NMOS_VTG W=135.00n L=50n +MM2 br_noconn wl Q_bar gnd NMOS_VTG W=135.00n L=50n .ENDS cell_6t From eef97ff21547f62ff8290885ec0037149b286c14 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 6 Aug 2020 11:17:49 -0700 Subject: [PATCH 44/65] Reabstracting bit and word line names. --- compiler/modules/bitcell_array.py | 27 +++--- compiler/modules/bitcell_base_array.py | 82 +++++++++---------- compiler/modules/local_bitcell_array.py | 13 ++- compiler/modules/replica_bitcell_array.py | 9 +- compiler/tests/05_local_bitcell_array_test.py | 9 +- 5 files changed, 67 insertions(+), 73 deletions(-) diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index ce72b137..81f1062f 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -13,9 +13,8 @@ from sram_factory import factory class bitcell_array(bitcell_base_array): """ - Creates a rows x cols array of memory cells. Assumes bit-lines - and word line is connected by abutment. - Connects the word lines and bit lines. + Creates a rows x cols array of memory cells. + Assumes bit-lines and word lines are connected by abutment. """ def __init__(self, rows, cols, column_offset=0, name=""): super().__init__(rows=rows, cols=cols, column_offset=column_offset, name=name) @@ -27,7 +26,7 @@ class bitcell_array(bitcell_base_array): # We don't offset this because we need to align # the replica bitcell in the control logic # self.offset_all_coordinates() - + def create_netlist(self): """ Create and connect the netlist """ self.add_modules() @@ -41,7 +40,7 @@ class bitcell_array(bitcell_base_array): self.add_layout_pins() self.add_boundary() - + self.DRC_LVS() def add_modules(self): @@ -58,20 +57,20 @@ class bitcell_array(bitcell_base_array): self.cell_inst[row, col]=self.add_inst(name=name, mod=self.cell) self.connect_inst(self.get_bitcell_pins(row, col)) - + def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" - + # Dynamic Power from Bitline bl_wire = self.gen_bl_wire() cell_load = 2 * bl_wire.return_input_cap() bl_swing = OPTS.rbl_delay_percentage freq = spice["default_event_frequency"] bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing) - + # Calculate the bitcell power which currently only includes leakage cell_power = self.cell.analytical_power(corner, load) - + # Leakage power grows with entire array and bitlines. total_power = self.return_power(cell_power.dynamic + bitline_dynamic * self.column_size, cell_power.leakage * self.column_size * self.row_size) @@ -83,7 +82,8 @@ class bitcell_array(bitcell_base_array): else: width = self.width wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_m1")) - wl_wire.wire_c = 2 * spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell + # 2 access tx gate per cell + wl_wire.wire_c = 2 * spice["min_tx_gate_c"] + wl_wire.wire_c return wl_wire def gen_bl_wire(self): @@ -93,7 +93,8 @@ class bitcell_array(bitcell_base_array): height = self.height bl_pos = 0 bl_wire = self.generate_rc_net(int(self.row_size - bl_pos), height, drc("minwidth_m1")) - bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell + # 1 access tx d/s per cell + bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c return bl_wire def get_wordline_cin(self): @@ -102,7 +103,7 @@ class bitcell_array(bitcell_base_array): bitcell_wl_cin = self.cell.get_wl_cin() total_cin = bitcell_wl_cin * self.column_size return total_cin - + def graph_exclude_bits(self, targ_row, targ_col): """Excludes bits in column from being added to graph except target""" # Function is not robust with column mux configurations @@ -111,7 +112,7 @@ class bitcell_array(bitcell_base_array): if row == targ_row and col == targ_col: continue self.graph_inst_exclude.add(self.cell_inst[row, col]) - + def get_cell_name(self, inst_name, row, col): """Gets the spice name of the target bitcell.""" return inst_name + '.x' + self.cell_inst[row, col].name, self.cell_inst[row, col] diff --git a/compiler/modules/bitcell_base_array.py b/compiler/modules/bitcell_base_array.py index 2ef710e3..292831b5 100644 --- a/compiler/modules/bitcell_base_array.py +++ b/compiler/modules/bitcell_base_array.py @@ -8,6 +8,7 @@ import debug import design from tech import cell_properties +from sram_factory import factory class bitcell_base_array(design.design): @@ -15,7 +16,7 @@ class bitcell_base_array(design.design): Abstract base class for bitcell-arrays -- bitcell, dummy, replica """ def __init__(self, name, rows, cols, column_offset): - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) self.add_comment("rows: {0} cols: {1}".format(rows, cols)) @@ -23,41 +24,40 @@ class bitcell_base_array(design.design): self.row_size = rows self.column_offset = column_offset - def get_all_bitline_names(self): + # Bitcell for port names only + self.cell = factory.create(module_type="bitcell") + + self.create_all_bitline_names() + self.create_all_wordline_names() - res = list() + def get_all_bitline_names(self, prefix=""): + return [prefix + x for x in self.bitline_names] + + def create_all_bitline_names(self): + self.bitline_names = list() bitline_names = self.cell.get_all_bitline_names() - # We have to keep the order of self.pins, otherwise we connect - # it wrong in the spice netlist - for pin in self.pins: - for bl_name in bitline_names: - if bl_name in pin: - res.append(pin) - return res + for col in range(self.column_size): + for cell_column in bitline_names: + self.bitline_names.append("{0}_{1}".format(cell_column, col)) - def get_all_wordline_names(self): + def get_all_wordline_names(self, prefix=""): + return [prefix + x for x in self.wordline_names] - res = list() + def create_all_wordline_names(self): + + self.wordline_names = list() wordline_names = self.cell.get_all_wl_names() - # We have to keep the order of self.pins, otherwise we connect - # it wrong in the spice netlist - for pin in self.pins: - for wl_name in wordline_names: - if wl_name in pin: - res.append(pin) - return res + for row in range(self.row_size): + for cell_row in wordline_names: + self.wordline_names.append("{0}_{1}".format(cell_row, row)) def add_pins(self): - row_list = self.cell.get_all_wl_names() - column_list = self.cell.get_all_bitline_names() - for col in range(self.column_size): - for cell_column in column_list: - self.add_pin(cell_column+"_{0}".format(col), "INOUT") - for row in range(self.row_size): - for cell_row in row_list: - self.add_pin(cell_row+"_{0}".format(row), "INPUT") + for bl_name in self.bitline_names: + self.add_pin(bl_name, "INOUT") + for wl_name in self.wordline_names: + self.add_pin(wl_name, "INPUT") self.add_pin("vdd", "POWER") self.add_pin("gnd", "GROUND") @@ -66,13 +66,10 @@ class bitcell_base_array(design.design): indexed by column and row, for instance use in bitcell_array """ bitcell_pins = [] - - pin_names = self.cell.get_all_bitline_names() - for pin in pin_names: - bitcell_pins.append(pin + "_{0}".format(col)) - pin_names = self.cell.get_all_wl_names() - for pin in pin_names: - bitcell_pins.append(pin + "_{0}".format(row)) + # bitlines + bitcell_pins.extend([x for x in self.bitline_names if x.endswith("_{0}".format(col))]) + # wordlines + bitcell_pins.extend([x for x in self.wordline_names if x.endswith("_{0}".format(row))]) bitcell_pins.append("vdd") bitcell_pins.append("gnd") @@ -81,22 +78,21 @@ class bitcell_base_array(design.design): def add_layout_pins(self): """ Add the layout pins """ - row_list = self.cell.get_all_wl_names() - column_list = self.cell.get_all_bitline_names() - + bitline_names = self.cell.get_all_bitline_names() for col in range(self.column_size): - for cell_column in column_list: - bl_pin = self.cell_inst[0, col].get_pin(cell_column) - self.add_layout_pin(text=cell_column + "_{0}".format(col), + for bl_name in bitline_names: + bl_pin = self.cell_inst[0, col].get_pin(bl_name) + self.add_layout_pin(text="{0}_{1}".format(bl_name, col), layer=bl_pin.layer, offset=bl_pin.ll().scale(1, 0), width=bl_pin.width(), height=self.height) + wl_names = self.cell.get_all_wl_names() for row in range(self.row_size): - for cell_row in row_list: - wl_pin = self.cell_inst[row, 0].get_pin(cell_row) - self.add_layout_pin(text=cell_row + "_{0}".format(row), + for wl_name in wl_names: + wl_pin = self.cell_inst[row, 0].get_pin(wl_name) + self.add_layout_pin(text="{0}_{1}".format(wl_name, row), layer=wl_pin.layer, offset=wl_pin.ll().scale(0, 1), width=self.width, diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index a9b98490..ba19ad5e 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -8,6 +8,7 @@ import design from globals import OPTS from sram_factory import factory +import debug class local_bitcell_array(design.design): @@ -26,7 +27,7 @@ class local_bitcell_array(design.design): self.left_rbl = left_rbl self.right_rbl = right_rbl self.all_ports = ports - + self.create_netlist() if not OPTS.netlist_only: self.create_layout() @@ -34,7 +35,7 @@ class local_bitcell_array(design.design): # We don't offset this because we need to align # the replica bitcell in the control logic # self.offset_all_coordinates() - + def create_netlist(self): """ Create and connect the netlist """ self.add_modules() @@ -48,14 +49,14 @@ class local_bitcell_array(design.design): self.add_layout_pins() self.add_boundary() - + self.DRC_LVS() def add_modules(self): """ Add the modules used in this design """ # This is just used for names self.cell = factory.create(module_type="bitcell") - + self.bitcell_array = factory.create(module_type="replica_bitcell_array", cols=self.cols, rows=self.rows, @@ -68,7 +69,7 @@ class local_bitcell_array(design.design): rows=self.rows, cols=self.cols) self.add_mod(self.wl_array) - + def create_instances(self): """ Create the module instances used in this design """ @@ -78,5 +79,3 @@ class local_bitcell_array(design.design): self.array_inst = self.add_inst(mod=self.bitcell_array, offset=self.wl_inst.lr()) self.connect_inst(self.pins) - - diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index a0ce8e6e..d035f7b4 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -5,14 +5,14 @@ # import debug -import design +import bitcell_base_array from tech import drc, spice, cell_properties from vector import vector from globals import OPTS from sram_factory import factory -class replica_bitcell_array(design.design): +class replica_bitcell_array(bitcell_base_array.bitcell_base_array): """ Creates a bitcell arrow of cols x rows and then adds the replica and dummy columns and rows. Replica columns are on the left and @@ -22,7 +22,7 @@ class replica_bitcell_array(design.design): bitcell (Bl/BR disconnected). """ def __init__(self, rows, cols, left_rbl, right_rbl, bitcell_ports, name, add_replica=True): - design.design.__init__(self, name) + super().__init__(name, rows, cols, column_offset=0) debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) self.add_comment("rows: {0} cols: {1}".format(rows, cols)) @@ -90,9 +90,6 @@ class replica_bitcell_array(design.design): 1 x (rows + 4) """ - # Bitcell for port names only - self.cell = factory.create(module_type="bitcell") - # Bitcell array self.bitcell_array = factory.create(module_type="bitcell_array", column_offset=1 + self.add_left_rbl, diff --git a/compiler/tests/05_local_bitcell_array_test.py b/compiler/tests/05_local_bitcell_array_test.py index c5b26b06..99227694 100755 --- a/compiler/tests/05_local_bitcell_array_test.py +++ b/compiler/tests/05_local_bitcell_array_test.py @@ -8,14 +8,14 @@ # import unittest from testutils import * -import sys,os +import sys, os sys.path.append(os.getenv("OPENRAM_HOME")) import globals -from globals import OPTS from sram_factory import factory import debug -@unittest.skip("SKIPPING 05_local_bitcell_array_test") + +#@unittest.skip("SKIPPING 05_local_bitcell_array_test") class local_bitcell_array_test(openram_test): def runTest(self): @@ -25,9 +25,10 @@ class local_bitcell_array_test(openram_test): debug.info(2, "Testing 4x4 local bitcell array for 6t_cell") a = factory.create(module_type="local_bitcell_array", cols=4, rows=4) self.local_check(a) - + globals.end_openram() + # run the test from the command line if __name__ == "__main__": (OPTS, args) = globals.parse_args() From 30976df48f2f3346831f7b71c8d98f42977a144d Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 6 Aug 2020 11:33:26 -0700 Subject: [PATCH 45/65] Change inheritance inits to use super --- compiler/base/channel_route.py | 2 +- compiler/base/contact.py | 2 +- compiler/base/design.py | 2 +- compiler/base/geometry.py | 8 ++++---- compiler/base/route.py | 2 +- compiler/characterizer/delay.py | 2 +- compiler/characterizer/functional.py | 2 +- compiler/characterizer/measurements.py | 12 ++++++------ compiler/characterizer/model_check.py | 4 ++-- compiler/modules/bank.py | 2 +- compiler/modules/bank_select.py | 2 +- compiler/modules/control_logic.py | 2 +- compiler/modules/delay_chain.py | 2 +- compiler/modules/dff_array.py | 2 +- compiler/modules/dff_buf.py | 2 +- compiler/modules/dff_buf_array.py | 2 +- compiler/modules/dff_inv.py | 2 +- compiler/modules/dff_inv_array.py | 2 +- compiler/modules/hierarchical_decoder.py | 2 +- compiler/modules/hierarchical_predecode.py | 2 +- compiler/modules/hierarchical_predecode2x4.py | 2 +- compiler/modules/hierarchical_predecode3x8.py | 2 +- compiler/modules/hierarchical_predecode4x16.py | 2 +- compiler/modules/multibank.py | 2 +- compiler/modules/port_address.py | 2 +- compiler/modules/port_data.py | 2 +- compiler/modules/precharge_array.py | 2 +- compiler/modules/replica_column.py | 2 +- compiler/modules/sense_amp.py | 2 +- compiler/modules/sense_amp_array.py | 2 +- compiler/modules/single_level_column_mux_array.py | 2 +- compiler/modules/tri_gate_array.py | 2 +- compiler/modules/wordline_driver_array.py | 2 +- compiler/modules/write_driver_array.py | 2 +- compiler/modules/write_mask_and_array.py | 2 +- compiler/pgates/pand2.py | 2 +- compiler/pgates/pand3.py | 2 +- compiler/pgates/pbuf.py | 2 +- compiler/pgates/pdriver.py | 2 +- compiler/pgates/pgate.py | 2 +- compiler/pgates/pinv.py | 2 +- compiler/pgates/pinv_dec.py | 2 +- compiler/pgates/pinvbuf.py | 2 +- compiler/pgates/pnand2.py | 2 +- compiler/pgates/pnand3.py | 2 +- compiler/pgates/pnor2.py | 2 +- compiler/pgates/precharge.py | 2 +- compiler/pgates/ptristate_inv.py | 2 +- compiler/pgates/ptx.py | 2 +- compiler/pgates/pwrite_driver.py | 2 +- compiler/pgates/single_level_column_mux.py | 2 +- compiler/pgates/wordline_driver.py | 2 +- 52 files changed, 61 insertions(+), 61 deletions(-) diff --git a/compiler/base/channel_route.py b/compiler/base/channel_route.py index 00ad6e37..5ec955c1 100644 --- a/compiler/base/channel_route.py +++ b/compiler/base/channel_route.py @@ -97,7 +97,7 @@ class channel_route(design.design): """ name = "cr_{0}".format(channel_route.unique_id) channel_route.unique_id += 1 - design.design.__init__(self, name) + super().__init__(name) self.netlist = netlist self.offset = offset diff --git a/compiler/base/contact.py b/compiler/base/contact.py index cc1ca27a..16c671d4 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -34,7 +34,7 @@ class contact(hierarchy_design.hierarchy_design): # This will ignore the name parameter since # we can guarantee a unique name here - hierarchy_design.hierarchy_design.__init__(self, name) + super().__init__(name) debug.info(4, "create contact object {0}".format(name)) self.add_comment("layers: {0}".format(layer_stack)) diff --git a/compiler/base/design.py b/compiler/base/design.py index 2b2d7711..2a79120d 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -20,7 +20,7 @@ class design(hierarchy_design): """ def __init__(self, name): - hierarchy_design.__init__(self, name) + super().__init__(name) self.setup_drc_constants() self.setup_layer_constants() diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 32af7ee9..171210ad 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -160,7 +160,7 @@ class instance(geometry): """ def __init__(self, name, mod, offset=[0, 0], mirror="R0", rotate=0): """Initializes an instance to represent a module""" - geometry.__init__(self) + super().__init__() debug.check(mirror not in ["R90", "R180", "R270"], "Please use rotation and not mirroring during instantiation.") @@ -284,7 +284,7 @@ class path(geometry): def __init__(self, lpp, coordinates, path_width): """Initializes a path for the specified layer""" - geometry.__init__(self) + super().__init__() self.name = "path" self.layerNumber = lpp[0] self.layerPurpose = lpp[1] @@ -322,7 +322,7 @@ class label(geometry): def __init__(self, text, lpp, offset, zoom=-1): """Initializes a text label for specified layer""" - geometry.__init__(self) + super().__init__() self.name = "label" self.text = text self.layerNumber = lpp[0] @@ -366,7 +366,7 @@ class rectangle(geometry): def __init__(self, lpp, offset, width, height): """Initializes a rectangular shape for specified layer""" - geometry.__init__(self) + super().__init__() self.name = "rect" self.layerNumber = lpp[0] self.layerPurpose = lpp[1] diff --git a/compiler/base/route.py b/compiler/base/route.py index c3e446a3..4e3d8a60 100644 --- a/compiler/base/route.py +++ b/compiler/base/route.py @@ -30,7 +30,7 @@ class route(design): def __init__(self, obj, layer_stack, path, layer_widths=[None,1,None]): name = "route_{0}".format(route.unique_route_id) route.unique_route_id += 1 - design.__init__(self, name) + super().__init__(name) debug.info(3, "create route obj {0}".format(name)) self.obj = obj diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 3f5d61af..54d6217c 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -41,7 +41,7 @@ class delay(simulation): """ def __init__(self, sram, spfile, corner): - simulation.__init__(self, sram, spfile, corner) + super().__init__(sram, spfile, corner) self.targ_read_ports = [] self.targ_write_ports = [] diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 2c391e38..8574c4f6 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -24,7 +24,7 @@ class functional(simulation): """ def __init__(self, sram, spfile, corner): - simulation.__init__(self, sram, spfile, corner) + super().__init__(sram, spfile, corner) # Seed the characterizer with a constant seed for unit tests if OPTS.is_unit_test: diff --git a/compiler/characterizer/measurements.py b/compiler/characterizer/measurements.py index 54f9973f..7d32c4f7 100644 --- a/compiler/characterizer/measurements.py +++ b/compiler/characterizer/measurements.py @@ -58,7 +58,7 @@ class delay_measure(spice_measurement): def __init__(self, measure_name, trig_name, targ_name, trig_dir_str, targ_dir_str,\ trig_vdd=0.5, targ_vdd=0.5, measure_scale=None, has_port=True): - spice_measurement.__init__(self, measure_name, measure_scale, has_port) + super().__init__(measure_name, measure_scale, has_port) self.set_meas_constants(trig_name, targ_name, trig_dir_str, targ_dir_str, trig_vdd, targ_vdd) def get_measure_function(self): @@ -95,7 +95,7 @@ class delay_measure(spice_measurement): class slew_measure(delay_measure): def __init__(self, measure_name, signal_name, slew_dir_str, measure_scale=None, has_port=True): - spice_measurement.__init__(self, measure_name, measure_scale, has_port) + super().__init__(measure_name, measure_scale, has_port) self.set_meas_constants(signal_name, slew_dir_str) def set_meas_constants(self, signal_name, slew_dir_str): @@ -120,7 +120,7 @@ class power_measure(spice_measurement): """Generates a spice measurement for the average power between two time points.""" def __init__(self, measure_name, power_type="", measure_scale=None, has_port=True): - spice_measurement.__init__(self, measure_name, measure_scale, has_port) + super().__init__(measure_name, measure_scale, has_port) self.set_meas_constants(power_type) def get_measure_function(self): @@ -144,7 +144,7 @@ class voltage_when_measure(spice_measurement): """Generates a spice measurement to measure the voltage of a signal based on the voltage of another.""" def __init__(self, measure_name, trig_name, targ_name, trig_dir_str, trig_vdd, measure_scale=None, has_port=True): - spice_measurement.__init__(self, measure_name, measure_scale, has_port) + super().__init__(measure_name, measure_scale, has_port) self.set_meas_constants(trig_name, targ_name, trig_dir_str, trig_vdd) def get_measure_function(self): @@ -177,7 +177,7 @@ class voltage_at_measure(spice_measurement): The time is considered variant with different periods.""" def __init__(self, measure_name, targ_name, measure_scale=None, has_port=True): - spice_measurement.__init__(self, measure_name, measure_scale, has_port) + super().__init__(measure_name, measure_scale, has_port) self.set_meas_constants(targ_name) def get_measure_function(self): @@ -198,4 +198,4 @@ class voltage_at_measure(spice_measurement): meas_name = self.name targ_name = self.targ_name_no_port return (meas_name,targ_name,time_at) - \ No newline at end of file + diff --git a/compiler/characterizer/model_check.py b/compiler/characterizer/model_check.py index b35c3c47..52100001 100644 --- a/compiler/characterizer/model_check.py +++ b/compiler/characterizer/model_check.py @@ -26,7 +26,7 @@ class model_check(delay): """ def __init__(self, sram, spfile, corner, custom_delaychain=False): - delay.__init__(self,sram,spfile,corner) + super().__init__(sram, spfile, corner) self.period = tech.spice["feasible_period"] self.create_data_names() self.custom_delaychain=custom_delaychain @@ -446,4 +446,4 @@ class model_check(delay): return name_dict - \ No newline at end of file + diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index b0707edb..cac1e278 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -36,7 +36,7 @@ class bank(design.design): if name == "": name = "bank_{0}_{1}".format(self.word_size, self.num_words) - design.design.__init__(self, name) + super().__init__(name) debug.info(2, "create sram of size {0} with {1} words".format(self.word_size, self.num_words)) diff --git a/compiler/modules/bank_select.py b/compiler/modules/bank_select.py index b6246268..8a776d30 100644 --- a/compiler/modules/bank_select.py +++ b/compiler/modules/bank_select.py @@ -24,7 +24,7 @@ class bank_select(design.design): """ def __init__(self, name="bank_select", port="rw"): - design.design.__init__(self, name) + super().__init__(name) self.port = port diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index a4e26a6f..a17f5aa7 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -23,7 +23,7 @@ class control_logic(design.design): def __init__(self, num_rows, words_per_row, word_size, spare_columns=None, sram=None, port_type="rw", name=""): """ Constructor """ name = "control_logic_" + port_type - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {}".format(name)) self.add_comment("num_rows: {0}".format(num_rows)) self.add_comment("words_per_row: {0}".format(words_per_row)) diff --git a/compiler/modules/delay_chain.py b/compiler/modules/delay_chain.py index c261138a..246299c1 100644 --- a/compiler/modules/delay_chain.py +++ b/compiler/modules/delay_chain.py @@ -21,7 +21,7 @@ class delay_chain(design.design): def __init__(self, name, fanout_list): """init function""" - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "creating delay chain {0}".format(str(fanout_list))) self.add_comment("fanouts: {0}".format(str(fanout_list))) diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index d3f9b68e..c4f85a6d 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -24,7 +24,7 @@ class dff_array(design.design): if name=="": name = "dff_array_{0}x{1}".format(rows, columns) - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {0} rows={1} cols={2}".format(self.name, self.rows, self.columns)) self.add_comment("rows: {0} cols: {1}".format(rows, columns)) diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index a1e54a4d..1657d7a8 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -27,7 +27,7 @@ class dff_buf(design.design): if name=="": name = "dff_buf_{0}".format(dff_buf.unique_id) dff_buf.unique_id += 1 - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {}".format(self.name)) self.add_comment("inv1: {0} inv2: {1}".format(inv1_size, inv2_size)) diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index 1cbd9284..88852d45 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -27,7 +27,7 @@ class dff_buf_array(design.design): if name=="": name = "dff_buf_array_{0}x{1}_{2}".format(rows, columns, dff_buf_array.unique_id) dff_buf_array.unique_id += 1 - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {}".format(self.name)) self.add_comment("rows: {0} cols: {1}".format(rows, columns)) self.add_comment("inv1: {0} inv2: {1}".format(inv1_size, inv2_size)) diff --git a/compiler/modules/dff_inv.py b/compiler/modules/dff_inv.py index 9dcb84c5..033312ef 100644 --- a/compiler/modules/dff_inv.py +++ b/compiler/modules/dff_inv.py @@ -25,7 +25,7 @@ class dff_inv(design.design): if name=="": name = "dff_inv_{0}".format(dff_inv.unique_id) dff_inv.unique_id += 1 - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {}".format(self.name)) self.add_comment("inv: {0}".format(inv_size)) diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py index aadb4257..6b08bcce 100644 --- a/compiler/modules/dff_inv_array.py +++ b/compiler/modules/dff_inv_array.py @@ -27,7 +27,7 @@ class dff_inv_array(design.design): if name=="": name = "dff_inv_array_{0}x{1}_{2}".format(rows, columns, dff_inv_array.unique_id) dff_inv_array.unique_id += 1 - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {}".format(self.name)) self.add_comment("rows: {0} cols: {1}".format(rows, columns)) self.add_comment("inv1: {0}".format(inv1_size)) diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index dbacd051..e32fe1c6 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -18,7 +18,7 @@ class hierarchical_decoder(design.design): Dynamically generated hierarchical decoder. """ def __init__(self, name, num_outputs): - design.design.__init__(self, name) + super().__init__(name) self.AND_FORMAT = "DEC_AND_{0}" diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index a89f5fa6..9c34735d 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -31,7 +31,7 @@ class hierarchical_predecode(design.design): self.column_decoder = (height != b.height) self.number_of_outputs = int(math.pow(2, self.number_of_inputs)) - design.design.__init__(self, name) + super().__init__(name) def add_pins(self): for k in range(self.number_of_inputs): diff --git a/compiler/modules/hierarchical_predecode2x4.py b/compiler/modules/hierarchical_predecode2x4.py index 9c7ddfa3..3c1daa6a 100644 --- a/compiler/modules/hierarchical_predecode2x4.py +++ b/compiler/modules/hierarchical_predecode2x4.py @@ -14,7 +14,7 @@ class hierarchical_predecode2x4(hierarchical_predecode): Pre 2x4 decoder used in hierarchical_decoder. """ def __init__(self, name, height=None): - hierarchical_predecode.__init__(self, name, 2, height) + super().__init__( name, 2, height) self.create_netlist() if not OPTS.netlist_only: diff --git a/compiler/modules/hierarchical_predecode3x8.py b/compiler/modules/hierarchical_predecode3x8.py index e8c44e48..7513ed7c 100644 --- a/compiler/modules/hierarchical_predecode3x8.py +++ b/compiler/modules/hierarchical_predecode3x8.py @@ -14,7 +14,7 @@ class hierarchical_predecode3x8(hierarchical_predecode): Pre 3x8 decoder used in hierarchical_decoder. """ def __init__(self, name, height=None): - hierarchical_predecode.__init__(self, name, 3, height) + super().__init__(name, 3, height) self.create_netlist() if not OPTS.netlist_only: diff --git a/compiler/modules/hierarchical_predecode4x16.py b/compiler/modules/hierarchical_predecode4x16.py index 4a258bfb..3b423fde 100644 --- a/compiler/modules/hierarchical_predecode4x16.py +++ b/compiler/modules/hierarchical_predecode4x16.py @@ -14,7 +14,7 @@ class hierarchical_predecode4x16(hierarchical_predecode): Pre 4x16 decoder used in hierarchical_decoder. """ def __init__(self, name, height=None): - hierarchical_predecode.__init__(self, name, 4, height) + super().__init__(name, 4, height) self.create_netlist() if not OPTS.netlist_only: diff --git a/compiler/modules/multibank.py b/compiler/modules/multibank.py index bf19954b..48bf5f1f 100644 --- a/compiler/modules/multibank.py +++ b/compiler/modules/multibank.py @@ -26,7 +26,7 @@ class multibank(design.design): def __init__(self, name, word_size, num_words, words_per_row, num_banks=1): - design.design.__init__(self, name) + super().__init__(name) debug.info(2, "create sram of size {0} with {1} words".format(word_size,num_words)) self.word_size = word_size diff --git a/compiler/modules/port_address.py b/compiler/modules/port_address.py index 980c9d96..532463a7 100644 --- a/compiler/modules/port_address.py +++ b/compiler/modules/port_address.py @@ -25,7 +25,7 @@ class port_address(design.design): if name == "": name = "port_address_{0}_{1}".format(cols, rows) - design.design.__init__(self, name) + super().__init__(name) debug.info(2, "create data port of cols {0} rows {1}".format(cols, rows)) self.create_netlist() diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index bd6b39e2..eb827f2f 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -32,7 +32,7 @@ class port_data(design.design): if name == "": name = "port_data_{0}".format(self.port) - design.design.__init__(self, name) + super().__init__(name) debug.info(2, "create data port of size {0} with {1} words per row".format(self.word_size, self.words_per_row)) diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index d37de64f..c2d3d986 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -20,7 +20,7 @@ class precharge_array(design.design): """ def __init__(self, name, columns, size=1, bitcell_bl="bl", bitcell_br="br", column_offset=0): - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {0}".format(self.name)) self.add_comment("cols: {0} size: {1} bl: {2} br: {3}".format(columns, size, bitcell_bl, bitcell_br)) diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 9613e6fa..31ca4180 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -22,7 +22,7 @@ class replica_column(design.design): def __init__(self, name, rows, left_rbl, right_rbl, replica_bit, column_offset=0): - design.design.__init__(self, name) + super().__init__(name) self.rows = rows self.left_rbl = left_rbl diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index 35fbdf42..67703903 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -50,7 +50,7 @@ class sense_amp(design.design): return props.sense_amp.pin.en def __init__(self, name): - design.design.__init__(self, name) + super().__init__(name) debug.info(2, "Create sense_amp") self.width = sense_amp.width diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 98cbee66..20f6e06f 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -22,7 +22,7 @@ class sense_amp_array(design.design): def __init__(self, name, word_size, words_per_row, num_spare_cols=None, column_offset=0): - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {0}".format(self.name)) self.add_comment("word_size {0}".format(word_size)) self.add_comment("words_per_row: {0}".format(words_per_row)) diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 8b01d111..f57bbb20 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -21,7 +21,7 @@ class single_level_column_mux_array(design.design): """ def __init__(self, name, columns, word_size, bitcell_bl="bl", bitcell_br="br", column_offset=0): - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {0}".format(self.name)) self.add_comment("cols: {0} word_size: {1} bl: {2} br: {3}".format(columns, word_size, bitcell_bl, bitcell_br)) diff --git a/compiler/modules/tri_gate_array.py b/compiler/modules/tri_gate_array.py index e7ebd802..c329a04b 100644 --- a/compiler/modules/tri_gate_array.py +++ b/compiler/modules/tri_gate_array.py @@ -19,7 +19,7 @@ class tri_gate_array(design.design): def __init__(self, columns, word_size, name): """Intial function of tri gate array """ - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {0}".format(self.name)) self.columns = columns diff --git a/compiler/modules/wordline_driver_array.py b/compiler/modules/wordline_driver_array.py index e8a3c110..61f51404 100644 --- a/compiler/modules/wordline_driver_array.py +++ b/compiler/modules/wordline_driver_array.py @@ -19,7 +19,7 @@ class wordline_driver_array(design.design): """ def __init__(self, name, rows, cols): - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {0}".format(self.name)) self.add_comment("rows: {0} cols: {1}".format(rows, cols)) diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index a6eb1384..665142ec 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -21,7 +21,7 @@ class write_driver_array(design.design): def __init__(self, name, columns, word_size, num_spare_cols=None, write_size=None, column_offset=0): - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {0}".format(self.name)) self.add_comment("columns: {0}".format(columns)) self.add_comment("word_size {0}".format(word_size)) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index d48aefef..9b083512 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -19,7 +19,7 @@ class write_mask_and_array(design.design): """ def __init__(self, name, columns, word_size, write_size, column_offset=0): - design.design.__init__(self, name) + super().__init__(name) debug.info(1, "Creating {0}".format(self.name)) self.add_comment("columns: {0}".format(columns)) self.add_comment("word_size {0}".format(word_size)) diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index 435ace1f..a46485d0 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -22,7 +22,7 @@ class pand2(pgate.pgate): self.vertical = vertical self.size = size - pgate.pgate.__init__(self, name, height, add_wells) + super().__init__(name, height, add_wells) def create_netlist(self): self.add_pins() diff --git a/compiler/pgates/pand3.py b/compiler/pgates/pand3.py index 92429921..72a57f74 100644 --- a/compiler/pgates/pand3.py +++ b/compiler/pgates/pand3.py @@ -23,7 +23,7 @@ class pand3(pgate.pgate): self.size = size # Creates the netlist and layout - pgate.pgate.__init__(self, name, height, add_wells) + super().__init__(name, height, add_wells) def create_netlist(self): self.add_pins() diff --git a/compiler/pgates/pbuf.py b/compiler/pgates/pbuf.py index 8b9c4eab..d82e2091 100644 --- a/compiler/pgates/pbuf.py +++ b/compiler/pgates/pbuf.py @@ -25,7 +25,7 @@ class pbuf(pgate.pgate): self.height = height # Creates the netlist and layout - pgate.pgate.__init__(self, name, height) + super().__init__(name, height) def create_netlist(self): self.add_pins() diff --git a/compiler/pgates/pdriver.py b/compiler/pgates/pdriver.py index 578a11c4..8916f0fa 100644 --- a/compiler/pgates/pdriver.py +++ b/compiler/pgates/pdriver.py @@ -35,7 +35,7 @@ class pdriver(pgate.pgate): debug.error("Cannot specify both size_list and inverting.", -1) # Creates the netlist and layout - pgate.pgate.__init__(self, name, height, add_wells) + super().__init__(name, height, add_wells) def compute_sizes(self): # size_list specified diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index 1e55d5fb..57d93e6f 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -26,7 +26,7 @@ class pgate(design.design): def __init__(self, name, height=None, add_wells=True): """ Creates a generic cell """ - design.design.__init__(self, name) + super().__init__(, name) if height: self.height = height diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 4caf2a18..db46b6b1 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -44,7 +44,7 @@ class pinv(pgate.pgate): self.pmos_size = beta * size self.beta = beta - pgate.pgate.__init__(self, name, height, add_wells) + super().__init__(name, height, add_wells) def create_netlist(self): """ Calls all functions related to the generation of the netlist """ diff --git a/compiler/pgates/pinv_dec.py b/compiler/pgates/pinv_dec.py index 672bde2d..90c8e579 100644 --- a/compiler/pgates/pinv_dec.py +++ b/compiler/pgates/pinv_dec.py @@ -38,7 +38,7 @@ class pinv_dec(pinv.pinv): else: self.supply_layer = "m2" - pinv.pinv.__init__(self, name, size, beta, self.cell_height, add_wells) + super().__init__(, name, size, beta, self.cell_height, add_wells) def determine_tx_mults(self): """ diff --git a/compiler/pgates/pinvbuf.py b/compiler/pgates/pinvbuf.py index 5b286e9b..f746736c 100644 --- a/compiler/pgates/pinvbuf.py +++ b/compiler/pgates/pinvbuf.py @@ -32,7 +32,7 @@ class pinvbuf(pgate.pgate): self.predriver_size = max(int(self.size / (self.stage_effort / 2)), 1) # Creates the netlist and layout - pgate.pgate.__init__(self, name) + super().__init__(name) def create_netlist(self): self.add_pins() diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index fb6bb210..c1295a1b 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -43,7 +43,7 @@ class pnand2(pgate.pgate): self.pmos_width = self.nearest_bin("pmos", self.pmos_width) # Creates the netlist and layout - pgate.pgate.__init__(self, name, height, add_wells) + super().__init__(name, height, add_wells) def create_netlist(self): self.add_pins() diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index e4e71e61..efcbe369 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -46,7 +46,7 @@ class pnand3(pgate.pgate): self.pmos_width = self.nearest_bin("pmos", self.pmos_width) # Creates the netlist and layout - pgate.pgate.__init__(self, name, height, add_wells) + super().__init__(name, height, add_wells) def add_pins(self): """ Adds pins for spice netlist """ diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index aad405e8..331a0745 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -42,7 +42,7 @@ class pnor2(pgate.pgate): self.pmos_width = self.nearest_bin("pmos", self.pmos_width) # Creates the netlist and layout - pgate.pgate.__init__(self, name, height, add_wells) + super().__init__(name, height, add_wells) def create_netlist(self): self.add_pins() diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index 52d24390..d948056d 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -23,7 +23,7 @@ class precharge(design.design): def __init__(self, name, size=1, bitcell_bl="bl", bitcell_br="br"): debug.info(2, "creating precharge cell {0}".format(name)) - design.design.__init__(self, name) + super().__init__(, name) self.bitcell = factory.create(module_type="bitcell") self.beta = parameter["beta"] diff --git a/compiler/pgates/ptristate_inv.py b/compiler/pgates/ptristate_inv.py index 9fd5f8b6..affc157e 100644 --- a/compiler/pgates/ptristate_inv.py +++ b/compiler/pgates/ptristate_inv.py @@ -38,7 +38,7 @@ class ptristate_inv(pgate.pgate): self.pmos_width = self.pmos_size * drc("minwidth_tx") # Creates the netlist and layout - pgate.pgate.__init__(self, name, height) + super().__init__(name, height) def create_netlist(self): """ Calls all functions related to the generation of the netlist """ diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index b6f839f3..6de86346 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -75,7 +75,7 @@ class ptx(design.design): # replace periods with underscore for newer spice compatibility name = name.replace('.', '_') debug.info(3, "creating ptx {0}".format(name)) - design.design.__init__(self, name) + super().__init__(, name) self.tx_type = tx_type self.mults = mults diff --git a/compiler/pgates/pwrite_driver.py b/compiler/pgates/pwrite_driver.py index 87db7b20..2d091fd0 100644 --- a/compiler/pgates/pwrite_driver.py +++ b/compiler/pgates/pwrite_driver.py @@ -22,7 +22,7 @@ class pwrite_driver(design.design): def __init__(self, name, size=0): debug.error("pwrite_driver not implemented yet.", -1) debug.info(1, "creating pwrite_driver {}".format(name)) - design.design.__init__(self, name) + super().__init__(, name) self.size = size self.beta = parameter["beta"] self.pmos_width = self.beta*self.size*parameter["min_tx_size"] diff --git a/compiler/pgates/single_level_column_mux.py b/compiler/pgates/single_level_column_mux.py index d2dbacc1..cd9be887 100644 --- a/compiler/pgates/single_level_column_mux.py +++ b/compiler/pgates/single_level_column_mux.py @@ -30,7 +30,7 @@ class single_level_column_mux(pgate.pgate): self.bitcell_bl = bitcell_bl self.bitcell_br = bitcell_br - pgate.pgate.__init__(self, name) + super().__init__(name) def get_bl_names(self): return "bl" diff --git a/compiler/pgates/wordline_driver.py b/compiler/pgates/wordline_driver.py index c8cf1326..b8fa4631 100644 --- a/compiler/pgates/wordline_driver.py +++ b/compiler/pgates/wordline_driver.py @@ -21,7 +21,7 @@ class wordline_driver(design.design): def __init__(self, name, size=1, height=None): debug.info(1, "Creating wordline_driver {}".format(name)) self.add_comment("size: {}".format(size)) - design.design.__init__(self, name) + super().__init__(, name) if height is None: b = factory.create(module_type="bitcell") From 8e890c2014476ad26bf97d2605841888051383a7 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 11 Aug 2020 15:00:29 -0700 Subject: [PATCH 46/65] Replica bitcell with all the fixings --- compiler/modules/bank.py | 2 +- compiler/modules/local_bitcell_array.py | 55 +++- compiler/modules/replica_bitcell_array.py | 273 +++++++++--------- compiler/modules/replica_column.py | 2 - compiler/modules/wordline_buffer_array.py | 5 +- compiler/tests/05_local_bitcell_array_test.py | 8 +- 6 files changed, 197 insertions(+), 148 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index b0707edb..4d0b09fb 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -392,7 +392,7 @@ class bank(design.design): def create_bitcell_array(self): """ Creating Bitcell Array """ - + import pdb; pdb.set_trace() self.bitcell_array_inst=self.add_inst(name="replica_bitcell_array", mod=self.bitcell_array) diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index ba19ad5e..da203de7 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -5,22 +5,22 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -import design +import bitcell_base_array from globals import OPTS from sram_factory import factory +from vector import vector import debug - -class local_bitcell_array(design.design): +class local_bitcell_array(bitcell_base_array.bitcell_base_array): """ A local bitcell array is a bitcell array with a wordline driver. This can either be a single aray on its own if there is no hierarchical WL or it can be combined into a larger array with hierarchical WL. """ - def __init__(self, rows, cols, ports, left_rbl=0, right_rbl=0, name=""): - design.design.__init__(self, name) - debug.info(2, "create sram of size {0} with {1} words".format(self.word_size, - self.num_words)) + def __init__(self, rows, cols, ports, left_rbl=0, right_rbl=0, add_replica=True, name=""): + super().__init__(name, rows, cols, 0) + debug.info(2, "create local array of size {} rows x {} cols words".format(rows, + cols + left_rbl + right_rbl)) self.rows = rows self.cols = cols @@ -66,16 +66,47 @@ class local_bitcell_array(design.design): self.add_mod(self.bitcell_array) self.wl_array = factory.create(module_type="wordline_buffer_array", - rows=self.rows, + rows=self.rows + len(self.all_ports), cols=self.cols) self.add_mod(self.wl_array) + def add_pins(self): + + self.bitline_names = self.bitcell_array.get_all_bitline_names() + self.add_pin_list(self.bitline_names, "INOUT") + self.wordline_names = self.bitcell_array.get_all_wordline_names() + self.add_pin_list(self.wordline_names, "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + def create_instances(self): """ Create the module instances used in this design """ - self.wl_inst = self.add_inst(mod=self.wl_array) - self.connect_inst(self.pins) + internal_wl_names = [x + "i" for x in self.wordline_names] + self.wl_inst = self.add_inst(name="wl_driver", + mod=self.wl_array) + self.connect_inst(self.wordline_names + internal_wl_names + ["vdd", "gnd"]) - self.array_inst = self.add_inst(mod=self.bitcell_array, + self.array_inst = self.add_inst(name="array", + mod=self.bitcell_array, offset=self.wl_inst.lr()) - self.connect_inst(self.pins) + self.connect_inst(self.bitline_names + internal_wl_names + ["vdd", "gnd"]) + + def place(self): + """ Place the bitcelll array to the right of the wl driver. """ + + self.wl_inst.place(vector(0, 0)) + self.array_inst.place(self.wl_inst.lr()) + + self.height = self.bitcell_array.height + self.width = self.array_inst.rx() + + def add_layout_pins(self): + + for (x, y) in zip(self.bitline_names, self.bitcell_array.get_inouts()): + self.copy_layout_pin(self.array_inst, y, x) + + for (x, y) in zip(self.wordline_names, self.wl_array.get_inputs()): + self.copy_layout_pin(self.wl_inst, y, x) + + diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index d035f7b4..2511ea80 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -42,9 +42,9 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): self.add_left_rbl = 0 self.add_right_rbl = 0 - debug.check(left_rbl + right_rbl == len(self.all_ports), + debug.check(left_rbl + right_rbl <= len(self.all_ports), "Invalid number of RBLs for port configuration.") - debug.check(left_rbl + right_rbl == len(self.bitcell_ports), + debug.check(left_rbl + right_rbl <= len(self.bitcell_ports), "Bitcell ports must match total RBLs.") # Two dummy rows plus replica even if we don't add the column @@ -134,27 +134,26 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): end_caps_enabled = False # Dummy Row or Col Cap, depending on bitcell array properties - edge_row_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array") - - self.edge_row = factory.create(module_type=edge_row_module_type, + col_cap_module_type = ("col_cap_array" if end_caps_enabled else "dummy_array") + self.col_cap = factory.create(module_type=col_cap_module_type, cols=self.column_size, rows=1, # dummy column + left replica column(s) column_offset=1 + self.add_left_rbl, mirror=0) - self.add_mod(self.edge_row) + self.add_mod(self.col_cap) # Dummy Col or Row Cap, depending on bitcell array properties - edge_col_module_type = ("row_cap_array" if end_caps_enabled else "dummy_array") + row_cap_module_type = ("row_cap_array" if end_caps_enabled else "dummy_array") - self.edge_col_left = factory.create(module_type=edge_col_module_type, + self.row_cap_left = factory.create(module_type=row_cap_module_type, cols=1, column_offset=0, rows=self.row_size + self.extra_rows, mirror=(self.left_rbl + 1) % 2) - self.add_mod(self.edge_col_left) + self.add_mod(self.row_cap_left) - self.edge_col_right = factory.create(module_type=edge_col_module_type, + self.row_cap_right = factory.create(module_type=row_cap_module_type, cols=1, # dummy column # + left replica column(s) @@ -163,100 +162,111 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): column_offset = 1 + self.add_left_rbl + self.column_size + self.add_right_rbl, rows=self.row_size + self.extra_rows, mirror=(self.left_rbl + 1) %2) - self.add_mod(self.edge_col_right) + self.add_mod(self.row_cap_right) def add_pins(self): - self.bitcell_array_wl_names = self.bitcell_array.get_all_wordline_names() - self.bitcell_array_bl_names = self.bitcell_array.get_all_bitline_names() + + self.add_bitline_pins() + self.add_wordline_pins() + + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + def add_bitline_pins(self): + + # All bitline names for all ports + self.bitline_names = [] + # Bitline names for each port + self.bitline_names_by_port = [[] for x in self.all_ports] + # Replica wordlines by port + self.replica_bitline_names = [[] for x in self.all_ports] + # Replica wordlines by port (bl only) + self.replica_bl_names = [[] for x in self.all_ports] + # Dummy wordlines by port + self.dummy_bitline_names = [] + + # Regular array bitline names + self.bitcell_array_bitline_names = self.bitcell_array.get_all_bitline_names() # These are the non-indexed names - self.dummy_cell_wl_names = ["dummy_" + x for x in self.cell.get_all_wl_names()] - self.dummy_cell_bl_names = ["dummy_" + x for x in self.cell.get_all_bitline_names()] - self.dummy_row_bl_names = self.bitcell_array_bl_names + dummy_bitline_names = ["dummy_" + x for x in self.cell.get_all_bitline_names()] + self.dummy_bitline_names.append([x+"_left" for x in dummy_bitline_names]) + self.dummy_bitline_names.append([x+"_right" for x in dummy_bitline_names]) - # A dictionary because some ports may have nothing - self.rbl_bl_names = {} - self.rbl_br_names = {} - self.rbl_wl_names = {} - - # Create the full WL names include dummy, replica, and regular bit cells - self.replica_col_wl_names = [] - self.replica_col_wl_names.extend(["{0}_bot".format(x) for x in self.dummy_cell_wl_names]) - # Left port WLs (one dummy for each port when we allow >1 port) - for port in range(self.add_left_rbl): - # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] - # Keep track of the pin that is the RBL - self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] - self.replica_col_wl_names.extend(wl_names) - # Regular WLs - self.replica_col_wl_names.extend(self.bitcell_array_wl_names) - # Right port WLs (one dummy for each port when we allow >1 port) - for port in range(self.add_left_rbl, self.add_left_rbl + self.add_right_rbl): - # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] - # Keep track of the pin that is the RBL - self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] - self.replica_col_wl_names.extend(wl_names) - self.replica_col_wl_names.extend(["{0}_top".format(x) for x in self.dummy_cell_wl_names]) - - # Create the full WL names include dummy, replica, and regular bit cells - # Left/right dummy columns are connected identically to the replica column - self.dummy_col_wl_names = [] - self.dummy_col_wl_names.extend(["{0}_bot".format(x) for x in self.dummy_cell_wl_names]) - # Left port WLs (one dummy for each port when we allow >1 port) - for port in range(self.left_rbl): - # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] - # Keep track of the pin that is the RBL - self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] - self.dummy_col_wl_names.extend(wl_names) - # Regular WLs - self.dummy_col_wl_names.extend(self.bitcell_array_wl_names) - # Right port WLs (one dummy for each port when we allow >1 port) - for port in range(self.left_rbl, self.left_rbl + self.right_rbl): - # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] - # Keep track of the pin that is the RBL - self.rbl_wl_names[port]=wl_names[self.bitcell_ports[port]] - self.dummy_col_wl_names.extend(wl_names) - self.dummy_col_wl_names.extend(["{0}_top".format(x) for x in self.dummy_cell_wl_names]) - - # Per port bitline names - self.replica_bl_names = {} - self.replica_wl_names = {} # Array of all port bitline names for port in range(self.add_left_rbl + self.add_right_rbl): left_names=["rbl_{0}_{1}".format(self.cell.get_bl_name(x), port) for x in range(len(self.all_ports))] right_names=["rbl_{0}_{1}".format(self.cell.get_br_name(x), port) for x in range(len(self.all_ports))] # Keep track of the left pins that are the RBL - self.rbl_bl_names[port]=left_names[self.bitcell_ports[port]] - self.rbl_br_names[port]=right_names[self.bitcell_ports[port]] + self.replica_bl_names[port]=left_names[self.bitcell_ports[port]] # Interleave the left and right lists - bl_names = [x for t in zip(left_names, right_names) for x in t] - self.replica_bl_names[port] = bl_names + bitline_names = [x for t in zip(left_names, right_names) for x in t] + self.replica_bitline_names[port] = bitline_names + + # Dummy bitlines are not connected to anything + # br pins are not connected to anything + for port in range(self.add_left_rbl): + self.bitline_names.extend(self.replica_bitline_names[port]) + self.bitline_names.extend(self.bitcell_array_bitline_names) + # br pins are not connected to anything + for port in range(self.left_rbl, self.left_rbl + self.right_rbl): + self.bitline_names.extend(self.replica_bitline_names[port]) + + self.add_pin_list(self.bitline_names, "INOUT") + + def add_wordline_pins(self): + + # All wordline names for all ports + self.wordline_names = [] + # Wordline names for each port + self.wordline_names_by_port = [[] for x in self.all_ports] + # Replica wordlines by port + self.replica_wordline_names = [[] for x in self.all_ports] + # Dummy wordlines + self.dummy_wordline_names = {} + + # Regular array wordline names + self.bitcell_array_wordline_names = self.bitcell_array.get_all_wordline_names() + + # These are the non-indexed names + dummy_cell_wl_names = ["dummy_" + x for x in self.cell.get_all_wl_names()] + + # Create the full WL names include dummy, replica, and regular bit cells + self.wordline_names = [] + + self.dummy_wordline_names["bot"] = ["{0}_bot".format(x) for x in dummy_cell_wl_names] + self.wordline_names.extend(self.dummy_wordline_names["bot"]) + + # Left port WLs + for port in range(self.left_rbl): + # Make names for all RBLs + wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] + # Keep track of the pin that is the RBL + self.replica_wordline_names[port] = wl_names + self.wordline_names.extend(wl_names) + + # Regular WLs + self.wordline_names.extend(self.bitcell_array_wordline_names) + + # Right port WLs + for port in range(self.left_rbl, self.left_rbl + self.right_rbl): + # Make names for all RBLs + wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] + # Keep track of the pin that is the RBL + self.replica_wordline_names[port] = wl_names + self.wordline_names.extend(wl_names) + + + self.dummy_wordline_names["top"] = ["{0}_top".format(x) for x in dummy_cell_wl_names] + self.wordline_names.extend(self.dummy_wordline_names["top"]) # Array of all port wl names for port in range(self.left_rbl + self.right_rbl): wl_names = ["rbl_{0}_{1}".format(x, port) for x in self.cell.get_all_wl_names()] - self.replica_wl_names[port] = wl_names - - # External pins - self.add_pin_list(self.bitcell_array_bl_names, "INOUT") - # Need to sort by port order since dictionary values may not be in order - bl_names = [self.rbl_bl_names[x] for x in sorted(self.rbl_bl_names.keys())] - br_names = [self.rbl_br_names[x] for x in sorted(self.rbl_br_names.keys())] - for (bl_name, br_name) in zip(bl_names, br_names): - self.add_pin(bl_name, "OUTPUT") - self.add_pin(br_name, "OUTPUT") - self.add_pin_list(self.bitcell_array_wl_names, "INPUT") - # Need to sort by port order since dictionary values may not be in order - wl_names = [self.rbl_wl_names[x] for x in sorted(self.rbl_wl_names.keys())] - for pin_name in wl_names: - self.add_pin(pin_name, "INPUT") - self.add_pin("vdd", "POWER") - self.add_pin("gnd", "GROUND") + self.replica_wordline_names[port] = wl_names + self.add_pin_list(self.wordline_names, "INPUT") + def create_instances(self): """ Create the module instances used in this design """ @@ -268,14 +278,14 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): # Main array self.bitcell_array_inst=self.add_inst(name="bitcell_array", mod=self.bitcell_array) - self.connect_inst(self.bitcell_array_bl_names + self.bitcell_array_wl_names + supplies) + self.connect_inst(self.bitcell_array_bitline_names + self.bitcell_array_wordline_names + supplies) # Replica columns self.replica_col_inst = {} for port in range(self.add_left_rbl + self.add_right_rbl): self.replica_col_inst[port]=self.add_inst(name="replica_col_{}".format(port), mod=self.replica_columns[port]) - self.connect_inst(self.replica_bl_names[port] + self.replica_col_wl_names + supplies) + self.connect_inst(self.replica_bitline_names[port] + self.wordline_names + supplies) # Dummy rows under the bitcell array (connected with with the replica cell wl) self.dummy_row_replica_inst = {} @@ -283,23 +293,27 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): for port in range(self.left_rbl + self.right_rbl): self.dummy_row_replica_inst[port]=self.add_inst(name="dummy_row_{}".format(port), mod=self.dummy_row) - self.connect_inst(self.dummy_row_bl_names + self.replica_wl_names[port] + supplies) + self.connect_inst(self.bitcell_array_bitline_names + self.replica_wordline_names[port] + supplies) # Top/bottom dummy rows or col caps self.dummy_row_bot_inst=self.add_inst(name="dummy_row_bot", - mod=self.edge_row) - self.connect_inst(self.dummy_row_bl_names + [x + "_bot" for x in self.dummy_cell_wl_names] + supplies) + mod=self.col_cap) + self.connect_inst(self.bitcell_array_bitline_names + + self.dummy_wordline_names["bot"] + + supplies) self.dummy_row_top_inst=self.add_inst(name="dummy_row_top", - mod=self.edge_row) - self.connect_inst(self.dummy_row_bl_names + [x + "_top" for x in self.dummy_cell_wl_names] + supplies) + mod=self.col_cap) + self.connect_inst(self.bitcell_array_bitline_names + + self.dummy_wordline_names["top"] + + supplies) # Left/right Dummy columns self.dummy_col_left_inst=self.add_inst(name="dummy_col_left", - mod=self.edge_col_left) - self.connect_inst([x + "_left" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies) + mod=self.row_cap_left) + self.connect_inst(self.dummy_bitline_names[0] + self.wordline_names + supplies) self.dummy_col_right_inst=self.add_inst(name="dummy_col_right", - mod=self.edge_col_right) - self.connect_inst([x + "_right" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies) + mod=self.row_cap_right) + self.connect_inst(self.dummy_bitline_names[-1] + self.wordline_names + supplies) def create_layout(self): @@ -372,19 +386,20 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): def add_layout_pins(self): """ Add the layout pins """ + # All wordlines # Main array wl and bl/br pin_names = self.bitcell_array.get_pin_names() for pin_name in pin_names: - for wl in self.bitcell_array_wl_names: + for wl in self.bitcell_array_wordline_names: if wl in pin_name: pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: self.add_layout_pin(text=pin_name, - layer=pin.layer, + layer=pin.layer, offset=pin.ll().scale(0, 1), width=self.width, height=pin.height()) - for bitline in self.bitcell_array_bl_names: + for bitline in self.bitcell_array_bitline_names: if bitline in pin_name: pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: @@ -394,32 +409,35 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): width=pin.width(), height=self.height) - # Replica wordlines - for port in range(self.add_left_rbl + self.add_right_rbl): - inst = self.replica_col_inst[port] - for (pin_name, wl_name) in zip(self.cell.get_all_wl_names(), self.replica_wl_names[port]): - # +1 for dummy row - pin_bit = port + 1 - # +row_size if above the array - if port>=self.add_left_rbl: - pin_bit += self.row_size + # Dummy wordlines + for (name, inst) in [("bot", self.dummy_row_bot_inst), ("top", self.dummy_row_top_inst)]: + for (pin_name, wl_name) in zip(self.cell.get_all_wl_names(), self.dummy_wordline_names[name]): + # It's always a single row + pin = inst.get_pin(pin_name + "_0") + self.add_layout_pin(text=wl_name, + layer=pin.layer, + offset=pin.ll().scale(0, 1), + width=self.width, + height=pin.height()) + + # Replica wordlines (go by the row instead of replica column because we may have to add a pin + # even though the column is in another local bitcell array) + for (port, inst) in list(self.dummy_row_replica_inst.items()): + for (pin_name, wl_name) in zip(self.cell.get_all_wl_names(), self.replica_wordline_names[port]): + pin = inst.get_pin(pin_name + "_0") + self.add_layout_pin(text=wl_name, + layer=pin.layer, + offset=pin.ll().scale(0, 1), + width=self.width, + height=pin.height()) - pin_name += "_{}".format(pin_bit) - pin = inst.get_pin(pin_name) - if wl_name in self.rbl_wl_names.values(): - self.add_layout_pin(text=wl_name, - layer=pin.layer, - offset=pin.ll().scale(0, 1), - width=self.width, - height=pin.height()) - # Replica bitlines for port in range(self.add_left_rbl + self.add_right_rbl): inst = self.replica_col_inst[port] - for (pin_name, bl_name) in zip(self.cell.get_all_bitline_names(), self.replica_bl_names[port]): + for (pin_name, bl_name) in zip(self.cell.get_all_bitline_names(), self.replica_bitline_names[port]): pin = inst.get_pin(pin_name) - if bl_name in self.rbl_bl_names or bl_name in self.rbl_br_names: + if bl_name in self.replica_bl_names: name = bl_name else: name = "rbl_{0}_{1}".format(pin_name, port) @@ -441,22 +459,17 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): loc=pin.center(), directions=("V", "V"), start_layer=pin.layer) - + for inst in list(self.replica_col_inst.values()): self.copy_layout_pin(inst, pin_name) - self.copy_layout_pin(inst, pin_name) def get_rbl_wl_name(self, port): """ Return the WL for the given RBL port """ - return self.rbl_wl_names[port] + return self.replica_wordline_names[port] def get_rbl_bl_name(self, port): """ Return the BL for the given RBL port """ - return self.rbl_bl_names[port] - - def get_rbl_br_name(self, port): - """ Return the BR for the given RBL port """ - return self.rbl_br_names[port] + return self.replica_bl_names[port] def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index c75bc9ee..eb3116d3 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -188,8 +188,6 @@ class replica_column(design.design): for pin_name in ["vdd", "gnd"]: if inst in [self.cell_inst[0], self.cell_inst[self.total_size - 1]]: self.copy_power_pins(inst, pin_name) - else: - self.copy_layout_pin(inst, pin_name) def get_bitcell_pins(self, row, col): """ Creates a list of connections in the bitcell, diff --git a/compiler/modules/wordline_buffer_array.py b/compiler/modules/wordline_buffer_array.py index be0fe1f7..7a1bf8d1 100644 --- a/compiler/modules/wordline_buffer_array.py +++ b/compiler/modules/wordline_buffer_array.py @@ -58,8 +58,11 @@ class wordline_buffer_array(design.design): self.add_pin("gnd", "GROUND") def add_modules(self): + b = factory.create(module_type="bitcell") + self.wl_driver = factory.create(module_type="inv_dec", - size=self.cols) + size=self.cols, + height=b.height) self.add_mod(self.wl_driver) def route_vdd_gnd(self): diff --git a/compiler/tests/05_local_bitcell_array_test.py b/compiler/tests/05_local_bitcell_array_test.py index 99227694..664d9ef8 100755 --- a/compiler/tests/05_local_bitcell_array_test.py +++ b/compiler/tests/05_local_bitcell_array_test.py @@ -22,10 +22,14 @@ class local_bitcell_array_test(openram_test): config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME")) globals.init_openram(config_file) - debug.info(2, "Testing 4x4 local bitcell array for 6t_cell") - a = factory.create(module_type="local_bitcell_array", cols=4, rows=4) + debug.info(2, "Testing 4x4 local bitcell array for 6t_cell without replica") + a = factory.create(module_type="local_bitcell_array", cols=4, rows=4, ports=[0], add_replica=False) self.local_check(a) + debug.info(2, "Testing 4x4 local bitcell array for 6t_cell with replica column") + a = factory.create(module_type="local_bitcell_array", cols=4, left_rbl=1, rows=4, ports=[0]) + self.local_check(a) + globals.end_openram() From a55909930f1d57ff20d79d92a239a6db3cb8f2f2 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 12 Aug 2020 09:49:14 -0700 Subject: [PATCH 47/65] Replace replcia_bitcell_array with new one in bank --- compiler/modules/bank.py | 42 ++++++++--------------- compiler/modules/replica_bitcell_array.py | 14 ++++++-- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 4d0b09fb..cd06a969 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -83,7 +83,7 @@ class bank(design.design): for bit in range(self.word_size + self.num_spare_cols): self.add_pin("dout{0}_{1}".format(port, bit), "OUTPUT") for port in self.all_ports: - self.add_pin(self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]), "OUTPUT") + self.add_pin_list(self.bitcell_array.get_rbl_bitline_names(self.port_rbl_map[port]), "OUTPUT") for port in self.write_ports: for bit in range(self.word_size + self.num_spare_cols): self.add_pin("din{0}_{1}".format(port, bit), "INPUT") @@ -392,24 +392,14 @@ class bank(design.design): def create_bitcell_array(self): """ Creating Bitcell Array """ - import pdb; pdb.set_trace() self.bitcell_array_inst=self.add_inst(name="replica_bitcell_array", mod=self.bitcell_array) - temp = [] - for col in range(self.num_cols + self.num_spare_cols): - for bitline in self.bitline_names: - temp.append("{0}_{1}".format(bitline, col)) - for rbl in range(self.num_rbl): - rbl_bl_name=self.bitcell_array.get_rbl_bl_name(rbl) - temp.append(rbl_bl_name) - rbl_br_name=self.bitcell_array.get_rbl_br_name(rbl) - temp.append(rbl_br_name) - for row in range(self.num_rows): - for wordline in self.wl_names: - temp.append("{0}_{1}".format(wordline, row)) - for port in self.all_ports: - temp.append("wl_en{0}".format(port)) + bitline_names = self.bitcell_array.get_bitline_names() + temp.extend(bitline_names) + # Replace RBL wordline with wl_en# + wordline_names = [x.replace("rbl_wl_", "wl_en") for x in self.bitcell_array.get_wordline_names()] + temp.extend(wordline_names) temp.append("vdd") temp.append("gnd") self.connect_inst(temp) @@ -427,10 +417,8 @@ class bank(design.design): mod=self.port_data[port]) temp = [] - rbl_bl_name=self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]) - rbl_br_name=self.bitcell_array.get_rbl_br_name(self.port_rbl_map[port]) - temp.append(rbl_bl_name) - temp.append(rbl_br_name) + rbl_bl_names=self.bitcell_array.get_rbl_bitline_names(self.port_rbl_map[port]) + temp.extend(rbl_bl_names) for col in range(self.num_cols + self.num_spare_cols): temp.append("{0}_{1}".format(self.bl_names[port], col)) temp.append("{0}_{1}".format(self.br_names[port], col)) @@ -718,10 +706,9 @@ class bank(design.design): self.connect_bitline(inst1, inst2, inst1_br_name.format(self.num_cols+i), "spare" + inst2_br_name.format(i)) # Connect the replica bitlines - rbl_bl_name=self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]) - rbl_br_name=self.bitcell_array.get_rbl_br_name(self.port_rbl_map[port]) - self.connect_bitline(inst1, inst2, rbl_bl_name, "rbl_bl") - self.connect_bitline(inst1, inst2, rbl_br_name, "rbl_br") + rbl_bl_names=self.bitcell_array.get_rbl_bitline_names(self.port_rbl_map[port]) + for (array_name, data_name) in zip(rbl_bl_names, ["rbl_bl", "rbl_br"]): + self.connect_bitline(inst1, inst2, array_name, data_name) def route_port_data_out(self, port): """ Add pins for the port data out """ @@ -974,9 +961,10 @@ class bank(design.design): connection.append((self.prefix + "p_en_bar{}".format(port), self.port_data_inst[port].get_pin("p_en_bar"))) - rbl_wl_name = self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]) - connection.append((self.prefix + "wl_en{}".format(port), - self.bitcell_array_inst.get_pin(rbl_wl_name))) + rbl_wl_names = self.bitcell_array.get_rbl_wordline_names(self.port_rbl_map[port]) + for rbl_wl_name in rbl_wl_names: + connection.append((self.prefix + "wl_en{}".format(port), + self.bitcell_array_inst.get_pin(rbl_wl_name))) if port in self.write_ports: connection.append((self.prefix + "w_en{}".format(port), diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 2511ea80..1119d546 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -463,13 +463,21 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): for inst in list(self.replica_col_inst.values()): self.copy_layout_pin(inst, pin_name) - def get_rbl_wl_name(self, port): + def get_rbl_wordline_names(self, port): """ Return the WL for the given RBL port """ return self.replica_wordline_names[port] - def get_rbl_bl_name(self, port): + def get_rbl_bitline_names(self, port): """ Return the BL for the given RBL port """ - return self.replica_bl_names[port] + return self.replica_bitline_names[port] + + def get_wordline_names(self): + """ Return the wordline names """ + return self.wordline_names + + def get_bitline_names(self): + """ Return the bitline names """ + return self.bitline_names def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" From 0bec6f0439b02362a786e88969826b9b9f6b0240 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 12 Aug 2020 10:41:21 -0700 Subject: [PATCH 48/65] Fix SRAM to use simulation spice instead of LVS spice --- compiler/sram/sram.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index ed09fbe0..8cf926c6 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -90,9 +90,9 @@ class sram(): # Save the LVS file start_time = datetime.datetime.now() - spname = OPTS.output_path + self.s.name + ".lvs" - debug.print_raw("LVS: Writing to {0}".format(spname)) - self.lvs_write(spname) + lvsname = OPTS.output_path + self.s.name + ".lvs.sp" + debug.print_raw("LVS: Writing to {0}".format(lvsname)) + self.lvs_write(lvsname) print_time("LVS writing", datetime.datetime.now(), start_time) # Save the extracted spice file From 55814a8f74b43f3a7fe806da0718fd961f0929bb Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 12 Aug 2020 11:15:32 -0700 Subject: [PATCH 49/65] Fix syntax errors in pgates for super edits --- compiler/pgates/pgate.py | 2 +- compiler/pgates/precharge.py | 2 +- compiler/pgates/ptx.py | 2 +- compiler/pgates/pwrite_driver.py | 2 +- compiler/pgates/wordline_driver.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index 57d93e6f..082ef7b8 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -26,7 +26,7 @@ class pgate(design.design): def __init__(self, name, height=None, add_wells=True): """ Creates a generic cell """ - super().__init__(, name) + super().__init__(name) if height: self.height = height diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index d948056d..aefdbb86 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -23,7 +23,7 @@ class precharge(design.design): def __init__(self, name, size=1, bitcell_bl="bl", bitcell_br="br"): debug.info(2, "creating precharge cell {0}".format(name)) - super().__init__(, name) + super().__init__(name) self.bitcell = factory.create(module_type="bitcell") self.beta = parameter["beta"] diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index 6de86346..1e4393e7 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -75,7 +75,7 @@ class ptx(design.design): # replace periods with underscore for newer spice compatibility name = name.replace('.', '_') debug.info(3, "creating ptx {0}".format(name)) - super().__init__(, name) + super().__init__(name) self.tx_type = tx_type self.mults = mults diff --git a/compiler/pgates/pwrite_driver.py b/compiler/pgates/pwrite_driver.py index 2d091fd0..6ae448f9 100644 --- a/compiler/pgates/pwrite_driver.py +++ b/compiler/pgates/pwrite_driver.py @@ -22,7 +22,7 @@ class pwrite_driver(design.design): def __init__(self, name, size=0): debug.error("pwrite_driver not implemented yet.", -1) debug.info(1, "creating pwrite_driver {}".format(name)) - super().__init__(, name) + super().__init__(name) self.size = size self.beta = parameter["beta"] self.pmos_width = self.beta*self.size*parameter["min_tx_size"] diff --git a/compiler/pgates/wordline_driver.py b/compiler/pgates/wordline_driver.py index b8fa4631..a8ca76f8 100644 --- a/compiler/pgates/wordline_driver.py +++ b/compiler/pgates/wordline_driver.py @@ -21,7 +21,7 @@ class wordline_driver(design.design): def __init__(self, name, size=1, height=None): debug.info(1, "Creating wordline_driver {}".format(name)) self.add_comment("size: {}".format(size)) - super().__init__(, name) + super().__init__(name) if height is None: b = factory.create(module_type="bitcell") From 15c8c200f3c2e3a0655d9ec11769818ba592c44d Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 12 Aug 2020 12:10:12 -0700 Subject: [PATCH 50/65] Undo super() in measurement abstract class --- compiler/characterizer/measurements.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/characterizer/measurements.py b/compiler/characterizer/measurements.py index 7d32c4f7..31da8ac5 100644 --- a/compiler/characterizer/measurements.py +++ b/compiler/characterizer/measurements.py @@ -58,7 +58,7 @@ class delay_measure(spice_measurement): def __init__(self, measure_name, trig_name, targ_name, trig_dir_str, targ_dir_str,\ trig_vdd=0.5, targ_vdd=0.5, measure_scale=None, has_port=True): - super().__init__(measure_name, measure_scale, has_port) + spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(trig_name, targ_name, trig_dir_str, targ_dir_str, trig_vdd, targ_vdd) def get_measure_function(self): @@ -95,7 +95,7 @@ class delay_measure(spice_measurement): class slew_measure(delay_measure): def __init__(self, measure_name, signal_name, slew_dir_str, measure_scale=None, has_port=True): - super().__init__(measure_name, measure_scale, has_port) + spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(signal_name, slew_dir_str) def set_meas_constants(self, signal_name, slew_dir_str): @@ -120,7 +120,7 @@ class power_measure(spice_measurement): """Generates a spice measurement for the average power between two time points.""" def __init__(self, measure_name, power_type="", measure_scale=None, has_port=True): - super().__init__(measure_name, measure_scale, has_port) + spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(power_type) def get_measure_function(self): @@ -144,7 +144,7 @@ class voltage_when_measure(spice_measurement): """Generates a spice measurement to measure the voltage of a signal based on the voltage of another.""" def __init__(self, measure_name, trig_name, targ_name, trig_dir_str, trig_vdd, measure_scale=None, has_port=True): - super().__init__(measure_name, measure_scale, has_port) + spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(trig_name, targ_name, trig_dir_str, trig_vdd) def get_measure_function(self): @@ -177,7 +177,7 @@ class voltage_at_measure(spice_measurement): The time is considered variant with different periods.""" def __init__(self, measure_name, targ_name, measure_scale=None, has_port=True): - super().__init__(measure_name, measure_scale, has_port) + spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(targ_name) def get_measure_function(self): From 5fc643855365bcb157e8bfd06087ba30055c6d33 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 12 Aug 2020 13:22:28 -0700 Subject: [PATCH 51/65] Fix pinv_dec super call --- compiler/pgates/pinv_dec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/pgates/pinv_dec.py b/compiler/pgates/pinv_dec.py index 90c8e579..458ce187 100644 --- a/compiler/pgates/pinv_dec.py +++ b/compiler/pgates/pinv_dec.py @@ -38,7 +38,7 @@ class pinv_dec(pinv.pinv): else: self.supply_layer = "m2" - super().__init__(, name, size, beta, self.cell_height, add_wells) + super().__init__(name, size, beta, self.cell_height, add_wells) def determine_tx_mults(self): """ From 7ac4574e4f2bbc97310e2906e09009b84877ae5b Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 12 Aug 2020 13:54:55 -0700 Subject: [PATCH 52/65] Use micron units for all simulation in sky130 --- compiler/pgates/ptx.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index b6f839f3..1d9a9361 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -129,7 +129,7 @@ class ptx(design.design): # be decided in the layout later. area_sd = 2.5 * self.poly_width * self.tx_width perimeter_sd = 2 * self.poly_width + 2 * self.tx_width - if OPTS.tech_name == "sky130" and OPTS.lvs_exe and OPTS.lvs_exe[0] == "calibre": + if OPTS.tech_name == "sky130": # sky130 simulation cannot use the mult parameter in simulation (self.tx_width, self.mults) = pgate.best_bin(self.tx_type, self.tx_width) main_str = "M{{0}} {{1}} {0} m={1} w={2} l={3} ".format(spice[self.tx_type], @@ -148,20 +148,19 @@ class ptx(design.design): area_str = "pd={0:.2f}u ps={0:.2f}u as={1:.2f}p ad={1:.2f}p".format(perimeter_sd, area_sd) self.spice_device = main_str + area_str - self.spice.append("\n* ptx " + self.spice_device) + self.spice.append("\n* spice ptx " + self.spice_device) if OPTS.tech_name == "sky130" and OPTS.lvs_exe and OPTS.lvs_exe[0] == "calibre": # sky130 requires mult parameter too self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2} l={3} mult={1}".format(spice[self.tx_type], - self.mults, - self.tx_width, - drc("minwidth_poly")) + self.mults, + self.tx_width, + drc("minwidth_poly")) else: self.lvs_device = "M{{0}} {{1}} {0} m={1} w={2}u l={3}u ".format(spice[self.tx_type], - self.mults, - self.tx_width, - drc("minwidth_poly")) - + self.mults, + self.tx_width, + drc("minwidth_poly")) def setup_layout_constants(self): """ Pre-compute some handy layout parameters. From 50525e70f40bbbbff50bcd91bd2b49b552550f64 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 13 Aug 2020 14:29:10 -0700 Subject: [PATCH 53/65] Fix up to SRAM level with new replica bitcell array ports. --- compiler/modules/bank.py | 78 +++++++++++++++++------ compiler/modules/replica_bitcell_array.py | 48 ++++++++------ compiler/sram/sram_base.py | 1 + 3 files changed, 90 insertions(+), 37 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index cd06a969..4b9c3990 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -83,7 +83,7 @@ class bank(design.design): for bit in range(self.word_size + self.num_spare_cols): self.add_pin("dout{0}_{1}".format(port, bit), "OUTPUT") for port in self.all_ports: - self.add_pin_list(self.bitcell_array.get_rbl_bitline_names(self.port_rbl_map[port]), "OUTPUT") + self.add_pin_list(self.bitcell_array.get_rbl_bitline_names(port), "OUTPUT") for port in self.write_ports: for bit in range(self.word_size + self.num_spare_cols): self.add_pin("din{0}_{1}".format(port, bit), "INPUT") @@ -114,6 +114,8 @@ class bank(design.design): def route_layout(self): """ Create routing amoung the modules """ self.route_central_bus() + + self.route_unused_wordlines() for port in self.all_ports: self.route_bitlines(port) @@ -375,7 +377,6 @@ class bank(design.design): rows=self.num_rows) self.add_mod(self.port_address) - self.port_rbl_map = self.all_ports self.num_rbl = len(self.all_ports) self.bitcell_array = factory.create(module_type="replica_bitcell_array", @@ -395,10 +396,24 @@ class bank(design.design): self.bitcell_array_inst=self.add_inst(name="replica_bitcell_array", mod=self.bitcell_array) temp = [] + rbl_names = self.bitcell_array.get_rbl_bitline_names() + temp.extend(rbl_names) bitline_names = self.bitcell_array.get_bitline_names() temp.extend(bitline_names) # Replace RBL wordline with wl_en# - wordline_names = [x.replace("rbl_wl_", "wl_en") for x in self.bitcell_array.get_wordline_names()] + wordline_names = self.bitcell_array.get_wordline_names() + + rbl_wl_names = [] + for port in self.all_ports: + rbl_wl_names.append(self.bitcell_array.get_rbl_wordline_names(port)) + + # Rename the RBL WL to the enable name + for port in self.all_ports: + wordline_names = [x.replace(rbl_wl_names[port], "wl_en{0}".format(port)) for x in wordline_names] + # Connect the other RBL WL to gnd + wordline_names = ["gnd" if x.startswith("rbl_wl") else x for x in wordline_names] + # Connect the dummy WL to gnd + wordline_names = ["gnd" if x.startswith("dummy") else x for x in wordline_names] temp.extend(wordline_names) temp.append("vdd") temp.append("gnd") @@ -410,14 +425,13 @@ class bank(design.design): def create_port_data(self): """ Creating Port Data """ - self.port_data_inst = [None] * len(self.all_ports) for port in self.all_ports: self.port_data_inst[port]=self.add_inst(name="port_data{}".format(port), mod=self.port_data[port]) temp = [] - rbl_bl_names=self.bitcell_array.get_rbl_bitline_names(self.port_rbl_map[port]) + rbl_bl_names = self.bitcell_array.get_rbl_bitline_names(port) temp.extend(rbl_bl_names) for col in range(self.num_cols + self.num_spare_cols): temp.append("{0}_{1}".format(self.bl_names[port], col)) @@ -441,7 +455,6 @@ class bank(design.design): for bit in range(self.num_spare_cols): temp.append("bank_spare_wen{0}_{1}".format(port, bit)) temp.extend(["vdd", "gnd"]) - self.connect_inst(temp) def place_port_data(self, offsets): @@ -466,7 +479,7 @@ class bank(design.design): temp = [] for bit in range(self.row_addr_size): temp.append("addr{0}_{1}".format(port, bit + self.col_addr_size)) - temp.append("wl_en{0}".format(port)) + temp.append("wl_en{}".format(port)) for row in range(self.num_rows): temp.append("{0}_{1}".format(self.wl_names[port], row)) temp.extend(["vdd", "gnd"]) @@ -654,7 +667,7 @@ class bank(design.design): # Port 0 # The bank is at (0,0), so this is to the left of the y-axis. # 2 pitches on the right for vias/jogs to access the inputs - control_bus_offset = vector(-self.m3_pitch * self.num_control_lines[0] - self.m3_pitch, self.min_y_offset) + control_bus_offset = vector(-self.m3_pitch * self.num_control_lines[0] - 2 * self.m3_pitch, self.min_y_offset) # The control bus is routed up to two pitches below the bitcell array control_bus_length = self.main_bitcell_array_bottom - self.min_y_offset - 2 * self.m1_pitch self.bus_pins[0] = self.create_bus(layer="m2", @@ -669,7 +682,7 @@ class bank(design.design): if len(self.all_ports)==2: # The other control bus is routed up to two pitches above the bitcell array control_bus_length = self.max_y_offset - self.main_bitcell_array_top - 2 * self.m1_pitch - control_bus_offset = vector(self.bitcell_array_right + self.m3_pitch, + control_bus_offset = vector(self.bitcell_array_right + 2 * self.m3_pitch, self.max_y_offset - control_bus_length) # The bus for the right port is reversed so that the rbl_wl is closest to the array self.bus_pins[1] = self.create_bus(layer="m2", @@ -702,11 +715,11 @@ class bank(design.design): # connect spare bitlines for i in range(self.num_spare_cols): - self.connect_bitline(inst1, inst2, inst1_bl_name.format(self.num_cols+i), "spare" + inst2_bl_name.format(i)) - self.connect_bitline(inst1, inst2, inst1_br_name.format(self.num_cols+i), "spare" + inst2_br_name.format(i)) + self.connect_bitline(inst1, inst2, inst1_bl_name.format(self.num_cols + i), "spare" + inst2_bl_name.format(i)) + self.connect_bitline(inst1, inst2, inst1_br_name.format(self.num_cols + i), "spare" + inst2_br_name.format(i)) # Connect the replica bitlines - rbl_bl_names=self.bitcell_array.get_rbl_bitline_names(self.port_rbl_map[port]) + rbl_bl_names = self.bitcell_array.get_rbl_bitline_names(port) for (array_name, data_name) in zip(rbl_bl_names, ["rbl_bl", "rbl_br"]): self.connect_bitline(inst1, inst2, array_name, data_name) @@ -949,7 +962,35 @@ class bank(design.design): self.add_label(text=data_name, layer="m1", offset=data_pin.center()) - + + def route_unused_wordlines(self): + """ Connect the unused RBL and dummy wordlines to gnd """ + gnd_wl_names = [] + + # Connect unused RBL WL to gnd + array_rbl_names = set([x for x in self.bitcell_array.get_all_wordline_names() if x.startswith("rbl")]) + dummy_rbl_names = set([x for x in self.bitcell_array.get_all_wordline_names() if x.startswith("dummy")]) + rbl_wl_names = set([self.bitcell_array.get_rbl_wordline_names(x) for x in self.all_ports]) + + gnd_wl_names = list((array_rbl_names - rbl_wl_names) | dummy_rbl_names) + + for wl_name in gnd_wl_names: + pin = self.bitcell_array_inst.get_pin(wl_name) + pin_layer = pin.layer + layer_pitch = getattr(self, "{}_pitch".format(pin_layer)) + left_pin_loc = pin.lc() + right_pin_loc = pin.rc() + + # Place the pins a track outside of the array + left_loc = left_pin_loc - vector(layer_pitch, 0) + right_loc = right_pin_loc + vector(layer_pitch, 0) + self.add_power_pin("gnd", left_loc) + self.add_power_pin("gnd", right_loc) + + # Add a path to connect to the array + self.add_path(pin_layer, [left_loc, left_pin_loc]) + self.add_path(pin_layer, [right_loc, right_pin_loc]) + def route_control_lines(self, port): """ Route the control lines of the entire bank """ @@ -961,11 +1002,10 @@ class bank(design.design): connection.append((self.prefix + "p_en_bar{}".format(port), self.port_data_inst[port].get_pin("p_en_bar"))) - rbl_wl_names = self.bitcell_array.get_rbl_wordline_names(self.port_rbl_map[port]) - for rbl_wl_name in rbl_wl_names: - connection.append((self.prefix + "wl_en{}".format(port), - self.bitcell_array_inst.get_pin(rbl_wl_name))) - + rbl_wl_name = self.bitcell_array.get_rbl_wordline_names(port) + connection.append((self.prefix + "wl_en{}".format(port), + self.bitcell_array_inst.get_pin(rbl_wl_name))) + if port in self.write_ports: connection.append((self.prefix + "w_en{}".format(port), self.port_data_inst[port].get_pin("w_en"))) @@ -1000,7 +1040,7 @@ class bank(design.design): self.add_wire(self.m1_stack, [pin_pos, mid_pos, control_pos]) self.add_via_center(layers=self.m1_stack, offset=control_pos) - + def determine_wordline_stage_efforts(self, external_cout, inp_is_rise=True): """Get the all the stage efforts for each stage in the path within the bank clk_buf to a wordline""" # Decoder is assumed to have settled before the negative edge of the clock. diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 1119d546..48da3630 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -174,7 +174,7 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): def add_bitline_pins(self): - # All bitline names for all ports + # Regular bitline names for all ports self.bitline_names = [] # Bitline names for each port self.bitline_names_by_port = [[] for x in self.all_ports] @@ -183,15 +183,15 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): # Replica wordlines by port (bl only) self.replica_bl_names = [[] for x in self.all_ports] # Dummy wordlines by port - self.dummy_bitline_names = [] + self.dummy_bitline_names = [] # Regular array bitline names self.bitcell_array_bitline_names = self.bitcell_array.get_all_bitline_names() # These are the non-indexed names dummy_bitline_names = ["dummy_" + x for x in self.cell.get_all_bitline_names()] - self.dummy_bitline_names.append([x+"_left" for x in dummy_bitline_names]) - self.dummy_bitline_names.append([x+"_right" for x in dummy_bitline_names]) + self.dummy_bitline_names.append([x + "_left" for x in dummy_bitline_names]) + self.dummy_bitline_names.append([x + "_right" for x in dummy_bitline_names]) # Array of all port bitline names for port in range(self.add_left_rbl + self.add_right_rbl): @@ -204,14 +204,10 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): self.replica_bitline_names[port] = bitline_names # Dummy bitlines are not connected to anything - # br pins are not connected to anything - for port in range(self.add_left_rbl): - self.bitline_names.extend(self.replica_bitline_names[port]) self.bitline_names.extend(self.bitcell_array_bitline_names) - # br pins are not connected to anything - for port in range(self.left_rbl, self.left_rbl + self.right_rbl): - self.bitline_names.extend(self.replica_bitline_names[port]) + for port in self.all_ports: + self.add_pin_list(self.replica_bitline_names[port], "INOUT") self.add_pin_list(self.bitline_names, "INOUT") def add_wordline_pins(self): @@ -240,7 +236,7 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): # Left port WLs for port in range(self.left_rbl): # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] + wl_names=["rbl_{0}_{1}".format(x, port) for x in self.cell.get_all_wl_names()] # Keep track of the pin that is the RBL self.replica_wordline_names[port] = wl_names self.wordline_names.extend(wl_names) @@ -251,11 +247,10 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): # Right port WLs for port in range(self.left_rbl, self.left_rbl + self.right_rbl): # Make names for all RBLs - wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x), port) for x in range(len(self.cell.get_all_wl_names()))] + wl_names=["rbl_{0}_{1}".format(x, port) for x in self.cell.get_all_wl_names()] # Keep track of the pin that is the RBL self.replica_wordline_names[port] = wl_names self.wordline_names.extend(wl_names) - self.dummy_wordline_names["top"] = ["{0}_top".format(x) for x in dummy_cell_wl_names] self.wordline_names.extend(self.dummy_wordline_names["top"]) @@ -463,13 +458,30 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): for inst in list(self.replica_col_inst.values()): self.copy_layout_pin(inst, pin_name) - def get_rbl_wordline_names(self, port): - """ Return the WL for the given RBL port """ - return self.replica_wordline_names[port] + def get_rbl_wordline_names(self, port=None): + """ + Return the ACTIVE WL for the given RBL port. + Inactive will be set to gnd. + """ + if port == None: + temp = [] + for port in self.all_ports: + temp.extend(self.replica_wordline_names[port]) + return temp + else: + wl_names = self.replica_wordline_names[port] + return wl_names[port] - def get_rbl_bitline_names(self, port): + def get_rbl_bitline_names(self, port=None): """ Return the BL for the given RBL port """ - return self.replica_bitline_names[port] + if port == None: + temp = [] + for port in self.all_ports: + temp.extend(self.replica_bitline_names[port]) + return temp + else: + bl_names = self.replica_bitline_names[port] + return bl_names[2 * port:2 * port + 2] def get_wordline_names(self): """ Return the wordline names """ diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 12af7cf6..23c05dbf 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -346,6 +346,7 @@ class sram_base(design, verilog, lef): temp.append("dout{0}[{1}]".format(port, bit)) for port in self.all_ports: temp.append("rbl_bl{0}".format(port)) + temp.append("rbl_br{0}".format(port)) for port in self.write_ports: for bit in range(self.word_size + self.num_spare_cols): temp.append("bank_din{0}[{1}]".format(port, bit)) From 797c41c75011d7506c19cd9bbbc06e442822bff1 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 13 Aug 2020 14:36:39 -0700 Subject: [PATCH 54/65] Skip local bitcell array test --- compiler/tests/05_local_bitcell_array_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/05_local_bitcell_array_test.py b/compiler/tests/05_local_bitcell_array_test.py index 664d9ef8..29b3b1de 100755 --- a/compiler/tests/05_local_bitcell_array_test.py +++ b/compiler/tests/05_local_bitcell_array_test.py @@ -15,7 +15,7 @@ from sram_factory import factory import debug -#@unittest.skip("SKIPPING 05_local_bitcell_array_test") +@unittest.skip("SKIPPING 05_local_bitcell_array_test") class local_bitcell_array_test(openram_test): def runTest(self): From 2ac04efe2e466e0653dfadbf4520fc5a6d2c4239 Mon Sep 17 00:00:00 2001 From: mrg Date: Thu, 13 Aug 2020 16:26:19 -0700 Subject: [PATCH 55/65] Must connect for replica cells other than top/bottom --- compiler/modules/replica_column.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index eb3116d3..c75bc9ee 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -188,6 +188,8 @@ class replica_column(design.design): for pin_name in ["vdd", "gnd"]: if inst in [self.cell_inst[0], self.cell_inst[self.total_size - 1]]: self.copy_power_pins(inst, pin_name) + else: + self.copy_layout_pin(inst, pin_name) def get_bitcell_pins(self, row, col): """ Creates a list of connections in the bitcell, From dfb593e9b4d1a19a1fefea8c7fefdfd22dc22f4d Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 14 Aug 2020 10:38:22 -0700 Subject: [PATCH 56/65] Add draft lyt file -- connectivity not working --- technology/scn4m_subm/tf/mosis.lyt | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 technology/scn4m_subm/tf/mosis.lyt diff --git a/technology/scn4m_subm/tf/mosis.lyt b/technology/scn4m_subm/tf/mosis.lyt new file mode 100644 index 00000000..8673627e --- /dev/null +++ b/technology/scn4m_subm/tf/mosis.lyt @@ -0,0 +1,27 @@ + + + SCMOS + + 0.001 + + mosis.lyp + true + + Active,ActX,Metal1 + Poly1,P1Con,Metal1 + Metal1,Via,Metal2 + Metal2,Via2,Metal3 + Metal3,Via3,Metal4 + Active='43/0' + Poly1='46/0' + P1Con='47/0' + ActX='48/0' + Metal1='49/0' + Via='50/0' + Metal2='51/0' + Via2='61/0' + Metal3.='62/0' + Via3='30/0' + Metal4='31/0' + + From 604e433e22a688413b0df46342569cad9b4da556 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 14 Aug 2020 10:40:31 -0700 Subject: [PATCH 57/65] Add readonly true for Magic scripts --- compiler/verify/magic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index ef98a09b..75bd53f0 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -77,6 +77,7 @@ def write_magic_script(cell_name, extract=False, final_verification=False): f.write("{} -dnull -noconsole << EOF\n".format(OPTS.drc_exe[1])) f.write("gds polygon subcell true\n") f.write("gds warning default\n") + f.write("gds readonly true\n") f.write("gds read {}.gds\n".format(cell_name)) f.write("load {}\n".format(cell_name)) # Flatten the cell to get rid of DRCs spanning multiple layers From 170e3feb7dddb0512b02a1aef6caba94987944ec Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 14 Aug 2020 14:14:49 -0700 Subject: [PATCH 58/65] Fix order of replica wordlines and bitlines --- compiler/modules/replica_bitcell_array.py | 30 +++++++++++++---------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 48da3630..1abd5553 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -101,15 +101,15 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array): self.replica_columns = {} for bit in range(self.add_left_rbl + self.add_right_rbl): # Creating left_rbl - if bit Date: Fri, 14 Aug 2020 14:23:40 -0700 Subject: [PATCH 59/65] Extra space for unused wl contacts --- compiler/modules/bank.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 4b9c3990..2ed003ab 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -977,7 +977,7 @@ class bank(design.design): for wl_name in gnd_wl_names: pin = self.bitcell_array_inst.get_pin(wl_name) pin_layer = pin.layer - layer_pitch = getattr(self, "{}_pitch".format(pin_layer)) + layer_pitch = 1.5 * getattr(self, "{}_pitch".format(pin_layer)) left_pin_loc = pin.lc() right_pin_loc = pin.rc() From 2c43d315db02b63306d27dbcf98430a9caf8c44a Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 17 Aug 2020 12:19:23 -0700 Subject: [PATCH 60/65] Revert gds readonly true --- compiler/verify/magic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 75bd53f0..cb0efeff 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -77,7 +77,8 @@ def write_magic_script(cell_name, extract=False, final_verification=False): f.write("{} -dnull -noconsole << EOF\n".format(OPTS.drc_exe[1])) f.write("gds polygon subcell true\n") f.write("gds warning default\n") - f.write("gds readonly true\n") + # This causes substrate contacts to not be extracted + f.write("# gds readonly true\n") f.write("gds read {}.gds\n".format(cell_name)) f.write("load {}\n".format(cell_name)) # Flatten the cell to get rid of DRCs spanning multiple layers From bddb251a845e9b810f40f1b8687fbd797e68dbe4 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 17 Aug 2020 12:32:44 -0700 Subject: [PATCH 61/65] More room for power contacts --- compiler/modules/bank.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 2ed003ab..59b8faa7 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -257,7 +257,7 @@ class bank(design.design): self.port_data_offsets[port] = vector(self.main_bitcell_array_left, self.bitcell_array_top) # LOWER RIGHT QUADRANT - # To the left of the bitcell array + # To the right of the bitcell array x_offset = self.bitcell_array_right + self.port_address.width + self.m2_gap self.port_address_offsets[port] = vector(x_offset, self.main_bitcell_array_bottom) @@ -682,7 +682,7 @@ class bank(design.design): if len(self.all_ports)==2: # The other control bus is routed up to two pitches above the bitcell array control_bus_length = self.max_y_offset - self.main_bitcell_array_top - 2 * self.m1_pitch - control_bus_offset = vector(self.bitcell_array_right + 2 * self.m3_pitch, + control_bus_offset = vector(self.bitcell_array_right + 2.5 * self.m3_pitch, self.max_y_offset - control_bus_length) # The bus for the right port is reversed so that the rbl_wl is closest to the array self.bus_pins[1] = self.create_bus(layer="m2", From 94bfad4113ac16807efa68a1b9edaeabc5fad286 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 17 Aug 2020 13:24:34 -0700 Subject: [PATCH 62/65] Horizontal gnd vias for unused array inputs --- compiler/modules/bank.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 59b8faa7..ea39fac4 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -984,8 +984,8 @@ class bank(design.design): # Place the pins a track outside of the array left_loc = left_pin_loc - vector(layer_pitch, 0) right_loc = right_pin_loc + vector(layer_pitch, 0) - self.add_power_pin("gnd", left_loc) - self.add_power_pin("gnd", right_loc) + self.add_power_pin("gnd", left_loc, directions=("H", "H")) + self.add_power_pin("gnd", right_loc, directions=("H", "H")) # Add a path to connect to the array self.add_path(pin_layer, [left_loc, left_pin_loc]) From 3a692e28469ef130f8c58440422ac8faf4275d74 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 17 Aug 2020 14:35:39 -0700 Subject: [PATCH 63/65] Comment updates --- compiler/base/design.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/base/design.py b/compiler/base/design.py index 2a79120d..ee985fec 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -230,13 +230,14 @@ class design(hierarchy_design): self.write_ports = [] # These are the write-only port indices. self.writeonly_ports = [] - # These are teh read/write and read-only port indice + # These are the read/write and read-only port indices self.read_ports = [] # These are the read-only port indices. self.readonly_ports = [] # These are all the ports self.all_ports = list(range(total_ports)) - + + # The order is always fixed as RW, W, R port_number = 0 for port in range(OPTS.num_rw_ports): self.readwrite_ports.append(port_number) From b1e55f9072b26679fe6330260a83bba315389eeb Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 17 Aug 2020 15:14:42 -0700 Subject: [PATCH 64/65] Add local bitcell array --- compiler/modules/local_bitcell_array.py | 94 +++++++++++++++---- compiler/tests/05_local_bitcell_array_test.py | 2 +- 2 files changed, 76 insertions(+), 20 deletions(-) diff --git a/compiler/modules/local_bitcell_array.py b/compiler/modules/local_bitcell_array.py index da203de7..cf5fbdee 100644 --- a/compiler/modules/local_bitcell_array.py +++ b/compiler/modules/local_bitcell_array.py @@ -9,6 +9,7 @@ import bitcell_base_array from globals import OPTS from sram_factory import factory from vector import vector +from tech import drc import debug class local_bitcell_array(bitcell_base_array.bitcell_base_array): @@ -24,10 +25,9 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array): self.rows = rows self.cols = cols - self.left_rbl = left_rbl - self.right_rbl = right_rbl + self.add_replica=add_replica self.all_ports = ports - + self.create_netlist() if not OPTS.netlist_only: self.create_layout() @@ -48,6 +48,8 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array): self.add_layout_pins() + self.route() + self.add_boundary() self.DRC_LVS() @@ -60,9 +62,10 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array): self.bitcell_array = factory.create(module_type="replica_bitcell_array", cols=self.cols, rows=self.rows, - left_rbl=self.left_rbl, - right_rbl=self.right_rbl, - bitcell_ports=self.all_ports) + left_rbl=1, + right_rbl=1 if len(self.all_ports)>1 else 0, + bitcell_ports=self.all_ports, + add_replica=self.add_replica) self.add_mod(self.bitcell_array) self.wl_array = factory.create(module_type="wordline_buffer_array", @@ -74,39 +77,92 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array): self.bitline_names = self.bitcell_array.get_all_bitline_names() self.add_pin_list(self.bitline_names, "INOUT") - self.wordline_names = self.bitcell_array.get_all_wordline_names() + self.driver_wordline_inputs = [x for x in self.bitcell_array.get_all_wordline_names() if not x.startswith("dummy")] + self.driver_wordline_outputs = [x + "i" for x in self.driver_wordline_inputs] + self.array_wordline_inputs = [x + "i" if not x.startswith("dummy") else "gnd" for x in self.bitcell_array.get_all_wordline_names()] self.add_pin_list(self.wordline_names, "INPUT") + self.replica_names = self.bitcell_array.get_rbl_wordline_names() + self.add_pin_list(self.replica_names, "INPUT") + self.bitline_names = self.bitcell_array.get_inouts() self.add_pin("vdd", "POWER") self.add_pin("gnd", "GROUND") def create_instances(self): """ Create the module instances used in this design """ - - internal_wl_names = [x + "i" for x in self.wordline_names] + self.wl_inst = self.add_inst(name="wl_driver", mod=self.wl_array) - self.connect_inst(self.wordline_names + internal_wl_names + ["vdd", "gnd"]) + self.connect_inst(self.driver_wordline_inputs + self.driver_wordline_outputs + ["vdd", "gnd"]) - self.array_inst = self.add_inst(name="array", - mod=self.bitcell_array, - offset=self.wl_inst.lr()) - self.connect_inst(self.bitline_names + internal_wl_names + ["vdd", "gnd"]) + self.bitcell_array_inst = self.add_inst(name="array", + mod=self.bitcell_array, + offset=self.wl_inst.lr()) + self.connect_inst(self.bitline_names + self.array_wordline_inputs + ["vdd", "gnd"]) def place(self): """ Place the bitcelll array to the right of the wl driver. """ - self.wl_inst.place(vector(0, 0)) - self.array_inst.place(self.wl_inst.lr()) + self.wl_inst.place(vector(0, self.cell.height)) + # FIXME: Replace this with a tech specific paramter + driver_to_array_spacing = 3 * self.m3_pitch + self.bitcell_array_inst.place(vector(self.wl_inst.rx() + driver_to_array_spacing, + 0)) self.height = self.bitcell_array.height - self.width = self.array_inst.rx() + self.width = self.bitcell_array_inst.rx() + def route_unused_wordlines(self): + """ Connect the unused RBL and dummy wordlines to gnd """ + gnd_wl_names = [] + + # Connect unused RBL WL to gnd + array_rbl_names = set([x for x in self.bitcell_array.get_all_wordline_names() if x.startswith("rbl")]) + dummy_rbl_names = set([x for x in self.bitcell_array.get_all_wordline_names() if x.startswith("dummy")]) + rbl_wl_names = set([self.bitcell_array.get_rbl_wordline_names(x) for x in self.all_ports]) + + gnd_wl_names = list((array_rbl_names - rbl_wl_names) | dummy_rbl_names) + + for wl_name in gnd_wl_names: + pin = self.bitcell_array_inst.get_pin(wl_name) + pin_layer = pin.layer + layer_pitch = 1.5 * getattr(self, "{}_pitch".format(pin_layer)) + left_pin_loc = pin.lc() + right_pin_loc = pin.rc() + + # Place the pins a track outside of the array + left_loc = left_pin_loc - vector(layer_pitch, 0) + right_loc = right_pin_loc + vector(layer_pitch, 0) + self.add_power_pin("gnd", left_loc, directions=("H", "H")) + self.add_power_pin("gnd", right_loc, directions=("H", "H")) + + # Add a path to connect to the array + self.add_path(pin_layer, [left_loc, left_pin_loc]) + self.add_path(pin_layer, [right_loc, right_pin_loc]) + def add_layout_pins(self): for (x, y) in zip(self.bitline_names, self.bitcell_array.get_inouts()): - self.copy_layout_pin(self.array_inst, y, x) + self.copy_layout_pin(self.bitcell_array_inst, y, x) - for (x, y) in zip(self.wordline_names, self.wl_array.get_inputs()): + for (x, y) in zip(self.driver_wordline_inputs, self.wl_array.get_inputs()): self.copy_layout_pin(self.wl_inst, y, x) + supply_insts = [self.wl_inst, self.bitcell_array_inst] + for pin_name in ["vdd", "gnd"]: + for inst in supply_insts: + pin_list = inst.get_pins(pin_name) + for pin in pin_list: + self.add_power_pin(name=pin_name, + loc=pin.center(), + start_layer=pin.layer) + + def route(self): + array_names = [x for x in self.bitcell_array.get_all_wordline_names() if not x.startswith("dummy")] + for (driver_name, array_name) in zip(self.wl_array.get_outputs(), array_names): + out_pin = self.wl_inst.get_pin(driver_name) + in_pin = self.bitcell_array_inst.get_pin(array_name) + mid_loc = self.wl_inst.rx() + 1.5 * self.m3_pitch + self.add_path(out_pin.layer, [out_pin.rc(), vector(mid_loc, out_pin.cy()), in_pin.lc()]) + + self.route_unused_wordlines() diff --git a/compiler/tests/05_local_bitcell_array_test.py b/compiler/tests/05_local_bitcell_array_test.py index 29b3b1de..664d9ef8 100755 --- a/compiler/tests/05_local_bitcell_array_test.py +++ b/compiler/tests/05_local_bitcell_array_test.py @@ -15,7 +15,7 @@ from sram_factory import factory import debug -@unittest.skip("SKIPPING 05_local_bitcell_array_test") +#@unittest.skip("SKIPPING 05_local_bitcell_array_test") class local_bitcell_array_test(openram_test): def runTest(self): From 35eac54c0d7c3f93944808da62ff624771387417 Mon Sep 17 00:00:00 2001 From: jcirimel Date: Mon, 17 Aug 2020 17:47:43 -0700 Subject: [PATCH 65/65] update freepdk bitcell for pex --- technology/freepdk45/sp_lib/cell_6t.sp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/technology/freepdk45/sp_lib/cell_6t.sp b/technology/freepdk45/sp_lib/cell_6t.sp index 3a66fc9a..b39427d7 100644 --- a/technology/freepdk45/sp_lib/cell_6t.sp +++ b/technology/freepdk45/sp_lib/cell_6t.sp @@ -1,8 +1,8 @@ .SUBCKT cell_6t bl br wl vdd gnd * Inverter 1 -MM0 Qbar Q gnd gnd NMOS_VTG W=205.00n L=50n -MM4 Qbar Q vdd vdd PMOS_VTG W=90n L=50n +MM0 Q_bar Q gnd gnd NMOS_VTG W=205.00n L=50n +MM4 Q_bar Q vdd vdd PMOS_VTG W=90n L=50n * Inverer 2 MM1 Q Q_bar gnd gnd NMOS_VTG W=205.00n L=50n