From 4f28295e20fc24f74c5f4432e69594d84388243f Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Fri, 19 Apr 2019 01:27:06 -0700 Subject: [PATCH 001/234] Added initial graph for correct naming --- compiler/base/design.py | 6 +-- compiler/base/graph_util.py | 66 +++++++++++++++++++++++++++++++ compiler/base/hierarchy_design.py | 34 ++++++++++++++++ compiler/pgates/pinv.py | 1 - compiler/pgates/ptx.py | 13 ++++++ 5 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 compiler/base/graph_util.py diff --git a/compiler/base/design.py b/compiler/base/design.py index 4e76b40a..243304fe 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -18,7 +18,7 @@ class design(hierarchy_design): self.setup_drc_constants() self.setup_multiport_constants() - + self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space, self.m2_space) self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space, self.m3_space) self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space) @@ -86,8 +86,8 @@ class design(hierarchy_design): for port in range(OPTS.num_r_ports): self.read_ports.append(port_number) self.readonly_ports.append(port_number) - port_number += 1 - + port_number += 1 + def analytical_power(self, corner, load): """ Get total power of a module """ total_module_power = self.return_power() diff --git a/compiler/base/graph_util.py b/compiler/base/graph_util.py new file mode 100644 index 00000000..b795e67f --- /dev/null +++ b/compiler/base/graph_util.py @@ -0,0 +1,66 @@ +import os +from collections import defaultdict + +import gdsMill +import tech +import math +import globals +import debug +from vector import vector +from pin_layout import pin_layout + +class graph(): + """Implements a directed graph""" + + def __init__(self): + self.graph = defaultdict(list) + + def add_edge(self, u, v): + """Adds edge to graph. Nodes added as well if they do not exist.""" + if v not in self.graph[u]: + self.graph[u].append(v) + + def add_node(self, u): + """Add node to graph with no edges""" + if not u in self.graph: + self.graph[u] = [] + + def remove_edges(self, node): + """Helper function to remove edges, useful for removing vdd/gnd""" + self.graph[node] = [] + + def printAllPaths(self,s, d): + + # Mark all the vertices as not visited + visited = set() + + # Create an array to store paths + path = [] + + # Call the recursive helper function to print all paths + self.printAllPathsUtil(s, d,visited, path) + + def printAllPathsUtil(self, u, d, visited, path): + + # Mark the current node as visited and store in path + visited.add(u) + path.append(u) + + # If current vertex is same as destination, then print + # current path[] + if u == d: + debug.info(1,"{}".format(path)) + else: + # If current vertex is not destination + #Recur for all the vertices adjacent to this vertex + for i in self.graph[u]: + if i not in visited: + self.printAllPathsUtil(i, d, visited, path) + + # Remove current vertex from path[] and mark it as unvisited + path.pop() + visited.remove(u) + + def __str__(self): + """ override print function output """ + return "Nodes: {}\nEdges:{} ".format(list(self.graph), self.graph) \ No newline at end of file diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index 6a6003a2..607859a4 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -5,6 +5,7 @@ import verify import debug import os from globals import OPTS +import graph_util total_drc_errors = 0 total_lvs_errors = 0 @@ -98,6 +99,39 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): os.remove(tempspice) os.remove(tempgds) + #Example graph run + # graph = graph_util.graph() + # pins = ['A','Z','vdd','gnd'] + # d.build_graph(graph,"Xpdriver",pins) + # graph.remove_edges('vdd') + # graph.remove_edges('gnd') + # debug.info(1,"{}".format(graph)) + # graph.printAllPaths('A', 'Z') + + def build_graph(self, graph, inst_name, port_nets): + """Recursively create graph from instances in module.""" + + #Translate port names to external nets + if len(port_nets) != len(self.pins): + debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,self.pins),1) + port_dict = {i:j for i,j in zip(self.pins, port_nets)} + debug.info(1, "Instance name={}".format(inst_name)) + for subinst, conns in zip(self.insts, self.conns): + debug.info(1, "Sub-Instance={}".format(subinst)) + subinst_name = inst_name+'.X'+subinst.name + subinst_ports = self.translate_nets(conns, port_dict, inst_name) + subinst.mod.build_graph(graph, subinst_name, subinst_ports) + + def translate_nets(self, subinst_ports, port_dict, inst_name): + """Converts connection names to their spice hierarchy equivalent""" + converted_conns = [] + for conn in subinst_ports: + if conn in port_dict: + converted_conns.append(port_dict[conn]) + else: + converted_conns.append("{}.{}".format(inst_name, conn)) + return converted_conns + def __str__(self): """ override print function output """ return "design: " + self.name diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index f00e9af7..c66c944c 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -38,7 +38,6 @@ class pinv(pgate.pgate): self.create_netlist() if not OPTS.netlist_only: self.create_layout() - # for run-time, we won't check every transitor DRC/LVS independently # but this may be uncommented for debug purposes #self.DRC_LVS() diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index 3a127454..7e80a7c9 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -356,3 +356,16 @@ class ptx(design.design): def get_cin(self): """Returns the relative gate cin of the tx""" return self.tx_width/drc("minwidth_tx") + + def build_graph(self, graph, inst_name, port_nets): + """Adds ptx edges to graph. Lowest graph level.""" + #The ptx has four connections: (S)ource, (G)ate, (D)rain, (B)ody. The positions in spice + #are hardcoded which is represented here as well. + #Edges are connected as follows: G->S, G->D, D<->S. Body not represented in graph. + if len(port_nets) != 4: + debug.error("Transistor has non-standard connections.",1) + graph.add_edge(port_nets[1],port_nets[0]) + graph.add_edge(port_nets[1],port_nets[2]) + graph.add_edge(port_nets[0],port_nets[2]) + graph.add_edge(port_nets[2],port_nets[0]) + \ No newline at end of file From e292767166b7f44a41b4dfe0d93d58dc91d59acc Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Wed, 24 Apr 2019 14:23:22 -0700 Subject: [PATCH 002/234] Added graph creation and functions in base class and lower level modules. --- compiler/base/hierarchy_design.py | 13 ++++++++++--- compiler/bitcells/bitcell.py | 11 ++++++++++- compiler/bitcells/bitcell_1rw_1r.py | 12 ++++++++++++ compiler/bitcells/bitcell_1w_1r.py | 11 +++++++++++ compiler/bitcells/pbitcell.py | 12 ++++++++++++ compiler/bitcells/replica_bitcell.py | 9 +++++++++ compiler/bitcells/replica_bitcell_1rw_1r.py | 11 +++++++++++ compiler/bitcells/replica_bitcell_1w_1r.py | 11 +++++++++++ compiler/{base => characterizer}/graph_util.py | 5 ++++- compiler/modules/bank.py | 6 ++++++ compiler/modules/bitcell_array.py | 10 ++++++++++ compiler/modules/dff.py | 8 ++++++++ compiler/modules/hierarchical_decoder.py | 1 + compiler/modules/precharge_array.py | 1 + compiler/modules/sense_amp.py | 13 ++++++++++++- compiler/modules/tri_gate.py | 12 +++++++++++- compiler/modules/write_driver.py | 12 ++++++++++++ compiler/pgates/pnand2.py | 9 +++++++++ compiler/sram_1bank.py | 16 ++++++++++++++++ compiler/tests/05_bitcell_1rw_1r_array_test.py | 2 +- compiler/tests/05_bitcell_array_test.py | 2 +- compiler/tests/12_tri_gate_array_test.py | 2 +- compiler/tests/21_hspice_delay_test.py | 17 +++++++++++++++++ 23 files changed, 196 insertions(+), 10 deletions(-) rename compiler/{base => characterizer}/graph_util.py (90%) diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index 607859a4..a8d0f5bf 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -24,7 +24,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): self.name = name hierarchy_layout.layout.__init__(self, name) hierarchy_spice.spice.__init__(self, name) - + self.init_graph_params() def get_layout_pins(self,inst): """ Return a map of pin locations of the instance offset """ @@ -100,6 +100,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): os.remove(tempgds) #Example graph run + # import graph_util # graph = graph_util.graph() # pins = ['A','Z','vdd','gnd'] # d.build_graph(graph,"Xpdriver",pins) @@ -108,6 +109,11 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): # debug.info(1,"{}".format(graph)) # graph.printAllPaths('A', 'Z') + def init_graph_params(self): + """Initializes parameters relevant to the graph creation""" + #Only initializes a set for checking instances which should not be added + self.graph_inst_exclude = set() + def build_graph(self, graph, inst_name, port_nets): """Recursively create graph from instances in module.""" @@ -115,9 +121,10 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): if len(port_nets) != len(self.pins): debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,self.pins),1) port_dict = {i:j for i,j in zip(self.pins, port_nets)} - debug.info(1, "Instance name={}".format(inst_name)) + debug.info(3, "Instance name={}".format(inst_name)) for subinst, conns in zip(self.insts, self.conns): - debug.info(1, "Sub-Instance={}".format(subinst)) + if subinst in self.graph_inst_exclude: + continue subinst_name = inst_name+'.X'+subinst.name subinst_ports = self.translate_nets(conns, port_dict, inst_name) subinst.mod.build_graph(graph, subinst_name, subinst_ports) diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 3f1d02d3..798ee3f9 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -24,7 +24,7 @@ class bitcell(design.design): self.width = bitcell.width self.height = bitcell.height self.pin_map = bitcell.pin_map - + def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 size = 0.5 #This accounts for bitline being drained thought the access TX and internal node @@ -74,3 +74,12 @@ class bitcell(design.design): #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 5 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl->bl, wl->br. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[2],port_nets[0]) + graph.add_edge(port_nets[2],port_nets[1]) \ No newline at end of file diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index e597167f..58b0ca98 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -99,3 +99,15 @@ class bitcell_1rw_1r(design.design): #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 8 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[4],port_nets[0]) + graph.add_edge(port_nets[4],port_nets[1]) + graph.add_edge(port_nets[5],port_nets[2]) + graph.add_edge(port_nets[5],port_nets[3]) + diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index cf487fba..3d1febdd 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -99,3 +99,14 @@ class bitcell_1w_1r(design.design): #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 8 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[4],port_nets[0]) + graph.add_edge(port_nets[4],port_nets[1]) + graph.add_edge(port_nets[5],port_nets[2]) + graph.add_edge(port_nets[5],port_nets[3]) diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 94c294db..cff7b5cf 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -893,3 +893,15 @@ class pbitcell(design.design): access_tx_cin = self.readwrite_nmos.get_cin() return 2*access_tx_cin + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Done manually to make the graph acyclic.""" + #The base graph function can make this but it would contain loops and path + #searches would essentially be useless. + # Edges added wl->bl, wl->br for every port + + num_wl = len(self.rw_wl_names) + len(self.w_wl_names) + len(self.r_wl_names) + wl_pos = 2*num_wl #there are this many bitlines nets before the wls in the port list + for i in range(num_wl): + bl_pos = i*2 + graph.add_edge(port_nets[wl_pos+i],port_nets[bl_pos]) + graph.add_edge(port_nets[wl_pos+i],port_nets[bl_pos+1]) diff --git a/compiler/bitcells/replica_bitcell.py b/compiler/bitcells/replica_bitcell.py index d8b8b76e..8d77ff7b 100644 --- a/compiler/bitcells/replica_bitcell.py +++ b/compiler/bitcells/replica_bitcell.py @@ -29,3 +29,12 @@ class replica_bitcell(design.design): #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 5 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl->bl, wl->br. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[2],port_nets[0]) + graph.add_edge(port_nets[2],port_nets[1]) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1rw_1r.py b/compiler/bitcells/replica_bitcell_1rw_1r.py index 8f7b3b38..67871525 100644 --- a/compiler/bitcells/replica_bitcell_1rw_1r.py +++ b/compiler/bitcells/replica_bitcell_1rw_1r.py @@ -30,3 +30,14 @@ class replica_bitcell_1rw_1r(design.design): #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 8 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[4],port_nets[0]) + graph.add_edge(port_nets[4],port_nets[1]) + graph.add_edge(port_nets[5],port_nets[2]) + graph.add_edge(port_nets[5],port_nets[3]) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1w_1r.py b/compiler/bitcells/replica_bitcell_1w_1r.py index 6f59adec..1f5c3266 100644 --- a/compiler/bitcells/replica_bitcell_1w_1r.py +++ b/compiler/bitcells/replica_bitcell_1w_1r.py @@ -30,3 +30,14 @@ class replica_bitcell_1w_1r(design.design): #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The bitcell has 8 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[4],port_nets[0]) + graph.add_edge(port_nets[4],port_nets[1]) + graph.add_edge(port_nets[5],port_nets[2]) + graph.add_edge(port_nets[5],port_nets[3]) \ No newline at end of file diff --git a/compiler/base/graph_util.py b/compiler/characterizer/graph_util.py similarity index 90% rename from compiler/base/graph_util.py rename to compiler/characterizer/graph_util.py index b795e67f..c20f3c91 100644 --- a/compiler/base/graph_util.py +++ b/compiler/characterizer/graph_util.py @@ -36,9 +36,11 @@ class graph(): # Create an array to store paths path = [] + self.path_count = 0 # Call the recursive helper function to print all paths - self.printAllPathsUtil(s, d,visited, path) + self.printAllPathsUtil(s, d,visited, path) + debug.info(1, "Paths found={}".format(self.path_count)) def printAllPathsUtil(self, u, d, visited, path): @@ -50,6 +52,7 @@ class graph(): # current path[] if u == d: debug.info(1,"{}".format(path)) + self.path_count+=1 else: # If current vertex is not destination #Recur for all the vertices adjacent to this vertex diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 5b556660..aaa44b08 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -1279,3 +1279,9 @@ class bank(design.design): """Get the relative capacitance of all the sense amp enable connections in the bank""" #Current bank only uses sen as an enable for the sense amps. return self.sense_amp_array.get_en_cin() + + def graph_exclude_precharge(self): + """Precharge adds a loop between bitlines, can be excluded to reduce complexity""" + for inst in self.precharge_array_inst: + if inst != None: + self.graph_inst_exclude.add(inst) \ No newline at end of file diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 79c68241..a06a7e90 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -193,3 +193,13 @@ class bitcell_array(design.design): 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 + for row in range(self.row_size): + if row == targ_row: + continue + self.graph_inst_exclude.add(self.cell_inst[row,targ_col]) + + \ No newline at end of file diff --git a/compiler/modules/dff.py b/compiler/modules/dff.py index 753ae41a..9b9dd0fe 100644 --- a/compiler/modules/dff.py +++ b/compiler/modules/dff.py @@ -50,3 +50,11 @@ class dff(design.design): #Calculated in the tech file by summing the widths of all the gates and dividing by the minimum width. return parameter["dff_clk_cin"] + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The cell has 5 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: clk->Q. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[2],port_nets[1]) + \ No newline at end of file diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index bd17b37e..6b5e6050 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -621,3 +621,4 @@ class hierarchical_decoder(design.design): else: pre = self.pre3_8 return pre.input_load() + diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index 67581e1a..04f212fb 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -107,3 +107,4 @@ class precharge_array(design.design): #Assume single port precharge_en_cin = self.pc_cell.get_en_cin() return precharge_en_cin*self.columns + \ No newline at end of file diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index 8d739041..431fc1b5 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -51,4 +51,15 @@ class sense_amp(design.design): pmos_cin = parameter["sa_en_pmos_size"]/drc("minwidth_tx") nmos_cin = parameter["sa_en_nmos_size"]/drc("minwidth_tx") #sen is connected to 2 pmos isolation TX and 1 nmos per sense amp. - return 2*pmos_cin + nmos_cin \ No newline at end of file + return 2*pmos_cin + nmos_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The cell has 6 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: en->dout, bl->dout + # br->dout not included to reduce complexity + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[0],port_nets[2]) + graph.add_edge(port_nets[3],port_nets[2]) + \ No newline at end of file diff --git a/compiler/modules/tri_gate.py b/compiler/modules/tri_gate.py index 688b3644..6a1efdea 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -10,7 +10,7 @@ class tri_gate(design.design): netlist should be available in the technology library. """ - pin_names = ["in", "en", "en_bar", "out", "gnd", "vdd"] + pin_names = ["in", "out", "en", "en_bar", "gnd", "vdd"] (width,height) = utils.get_libcell_size("tri_gate", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "tri_gate", GDS["unit"]) @@ -42,3 +42,13 @@ class tri_gate(design.design): def input_load(self): return 9*spice["min_tx_gate_c"] + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The cell has 6 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: en->out, en_bar->out, in->out. + # A liberal amount of edges were added, may be reduced later for complexity. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[0],port_nets[1]) + graph.add_edge(port_nets[2],port_nets[1]) + graph.add_edge(port_nets[3],port_nets[1]) \ No newline at end of file diff --git a/compiler/modules/write_driver.py b/compiler/modules/write_driver.py index 34c51245..d20a0135 100644 --- a/compiler/modules/write_driver.py +++ b/compiler/modules/write_driver.py @@ -28,3 +28,15 @@ class write_driver(design.design): """Get the relative capacitance of a single input""" # This is approximated from SCMOS. It has roughly 5 3x transistor gates. return 5*3 + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Handmade cells must implement this manually.""" + #The cell has 6 net ports hard-coded in self.pin_names. The edges + #are based on the hard-coded name positions. + # The edges added are: din->bl, din->br, en->bl, en->br + # A liberal amount of edges were added, may be reduced later for complexity. + # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. + graph.add_edge(port_nets[0],port_nets[1]) + graph.add_edge(port_nets[0],port_nets[2]) + graph.add_edge(port_nets[3],port_nets[1]) + graph.add_edge(port_nets[3],port_nets[2]) \ No newline at end of file diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 95a9bc28..eb2484af 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -32,6 +32,8 @@ class pnand2(pgate.pgate): if not OPTS.netlist_only: self.create_layout() + #For characterization purposes only + self.exclude_nmos_from_graph() def create_netlist(self): self.add_pins() @@ -259,3 +261,10 @@ class pnand2(pgate.pgate): """ parasitic_delay = 2 return logical_effort.logical_effort(self.name, self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise) + + def exclude_nmos_from_graph(self): + """Exclude the nmos TXs from the graph to reduce complexity""" + #The pull-down network has an internal net which causes 2 different in->out paths + #Removing them simplifies generic path searching. + self.graph_inst_exclude.add(self.nmos1_inst) + self.graph_inst_exclude.add(self.nmos2_inst) diff --git a/compiler/sram_1bank.py b/compiler/sram_1bank.py index cbfec653..abe08f40 100644 --- a/compiler/sram_1bank.py +++ b/compiler/sram_1bank.py @@ -305,3 +305,19 @@ class sram_1bank(sram_base): self.add_label(text=n, layer=pin.layer, offset=pin.center()) + + def graph_exclude_data_dff(self): + """Removes data dff from search graph. """ + #Data dffs are only for writing so are not useful for evaluating read delay. + for inst in self.data_dff_insts: + self.graph_inst_exclude.add(inst) + + def graph_exclude_addr_dff(self): + """Removes data dff from search graph. """ + #Address is considered not part of the critical path, subjectively removed + for inst in self.row_addr_dff_insts: + self.graph_inst_exclude.add(inst) + + if self.col_addr_dff: + for inst in self.col_addr_dff_insts: + self.graph_inst_exclude.add(inst) diff --git a/compiler/tests/05_bitcell_1rw_1r_array_test.py b/compiler/tests/05_bitcell_1rw_1r_array_test.py index 9ea0cc32..865b10b9 100755 --- a/compiler/tests/05_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/05_bitcell_1rw_1r_array_test.py @@ -26,7 +26,7 @@ class bitcell_1rw_1r_array_test(openram_test): OPTS.num_w_ports = 0 a = factory.create(module_type="bitcell_array", cols=4, rows=4) self.local_check(a) - + globals.end_openram() # run the test from the command line diff --git a/compiler/tests/05_bitcell_array_test.py b/compiler/tests/05_bitcell_array_test.py index 82eaf256..eef69fd6 100755 --- a/compiler/tests/05_bitcell_array_test.py +++ b/compiler/tests/05_bitcell_array_test.py @@ -22,7 +22,7 @@ class array_test(openram_test): debug.info(2, "Testing 4x4 array for 6t_cell") a = factory.create(module_type="bitcell_array", cols=4, rows=4) self.local_check(a) - + globals.end_openram() # run the test from the command line diff --git a/compiler/tests/12_tri_gate_array_test.py b/compiler/tests/12_tri_gate_array_test.py index 04ef1369..cff8595a 100755 --- a/compiler/tests/12_tri_gate_array_test.py +++ b/compiler/tests/12_tri_gate_array_test.py @@ -20,7 +20,7 @@ class tri_gate_array_test(openram_test): debug.info(1, "Testing tri_gate_array for columns=8, word_size=8") a = factory.create(module_type="tri_gate_array", columns=8, word_size=8) self.local_check(a) - + debug.info(1, "Testing tri_gate_array for columns=16, word_size=8") a = factory.create(module_type="tri_gate_array", columns=16, word_size=8) self.local_check(a) diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index abe65b02..fe9c4951 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -33,6 +33,23 @@ class timing_sram_test(openram_test): c.recompute_sizes() debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") s = factory.create(module_type="sram", sram_config=c) + + #Exclude things known not to be in critical path. + #Intended for characterizing read paths. Somewhat hacky implementation + s.s.bank.bitcell_array.graph_exclude_bits(15,0) + s.s.bank.graph_exclude_precharge() + s.s.graph_exclude_addr_dff() + s.s.graph_exclude_data_dff() + + debug.info(1,'pins={}'.format(s.s.pins)) + import graph_util + graph = graph_util.graph() + pins=['DIN0[0]', 'ADDR0[0]', 'ADDR0[1]', 'ADDR0[2]', 'ADDR0[3]', 'csb0', 'web0', 'clk0', 'DOUT0[0]', 'vdd', 'gnd'] + s.s.build_graph(graph,"Xsram",pins) + graph.remove_edges('vdd') + graph.remove_edges('gnd') + debug.info(1,"{}".format(graph)) + graph.printAllPaths('clk0', 'DOUT0[0]') tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) From f35385f42ac6c440a618828b2459d6e73ef84e83 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Wed, 24 Apr 2019 23:51:09 -0700 Subject: [PATCH 003/234] Cleaned up names, added exclusions to narrow paths for analysis. --- compiler/{characterizer => base}/graph_util.py | 8 ++++---- compiler/base/hierarchy_design.py | 2 +- compiler/modules/control_logic.py | 6 +++++- compiler/sram_1bank.py | 8 +++++++- compiler/tests/21_hspice_delay_test.py | 5 +++-- 5 files changed, 20 insertions(+), 9 deletions(-) rename compiler/{characterizer => base}/graph_util.py (89%) diff --git a/compiler/characterizer/graph_util.py b/compiler/base/graph_util.py similarity index 89% rename from compiler/characterizer/graph_util.py rename to compiler/base/graph_util.py index c20f3c91..eb40d55b 100644 --- a/compiler/characterizer/graph_util.py +++ b/compiler/base/graph_util.py @@ -29,7 +29,7 @@ class graph(): """Helper function to remove edges, useful for removing vdd/gnd""" self.graph[node] = [] - def printAllPaths(self,s, d): + def print_all_paths(self,s, d): # Mark all the vertices as not visited visited = set() @@ -39,10 +39,10 @@ class graph(): self.path_count = 0 # Call the recursive helper function to print all paths - self.printAllPathsUtil(s, d,visited, path) + self.print_all_paths_util(s, d,visited, path) debug.info(1, "Paths found={}".format(self.path_count)) - def printAllPathsUtil(self, u, d, visited, path): + def print_all_paths_util(self, u, d, visited, path): # Mark the current node as visited and store in path visited.add(u) @@ -58,7 +58,7 @@ class graph(): #Recur for all the vertices adjacent to this vertex for i in self.graph[u]: if i not in visited: - self.printAllPathsUtil(i, d, visited, path) + self.print_all_paths_util(i, d, visited, path) # Remove current vertex from path[] and mark it as unvisited path.pop() diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index a8d0f5bf..6d9de53c 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -107,7 +107,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): # graph.remove_edges('vdd') # graph.remove_edges('gnd') # debug.info(1,"{}".format(graph)) - # graph.printAllPaths('A', 'Z') + # graph.print_all_paths('A', 'Z') def init_graph_params(self): """Initializes parameters relevant to the graph creation""" diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 4f654c5f..80537f2a 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -965,4 +965,8 @@ class control_logic(design.design): total_cin += self.wl_en_driver.get_cin() if self.port_type == 'rw': total_cin +=self.and2.get_cin() - return total_cin \ No newline at end of file + return total_cin + + def graph_exclude_dffs(self): + """Exclude dffs from graph as they do not represent critical path""" + self.graph_inst_exclude.add(self.ctrl_dff_inst) \ No newline at end of file diff --git a/compiler/sram_1bank.py b/compiler/sram_1bank.py index abe08f40..ca10d827 100644 --- a/compiler/sram_1bank.py +++ b/compiler/sram_1bank.py @@ -320,4 +320,10 @@ class sram_1bank(sram_base): if self.col_addr_dff: for inst in self.col_addr_dff_insts: - self.graph_inst_exclude.add(inst) + self.graph_inst_exclude.add(inst) + + def graph_exclude_ctrl_dffs(self): + """Exclude dffs for CSB, WEB, etc from graph""" + #Insts located in control logic, exclusion function called here + for inst in self.control_logic_insts: + inst.mod.graph_exclude_dffs() diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index fe9c4951..7ca8c4b5 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -40,6 +40,7 @@ class timing_sram_test(openram_test): s.s.bank.graph_exclude_precharge() s.s.graph_exclude_addr_dff() s.s.graph_exclude_data_dff() + s.s.graph_exclude_ctrl_dffs() debug.info(1,'pins={}'.format(s.s.pins)) import graph_util @@ -48,8 +49,8 @@ class timing_sram_test(openram_test): s.s.build_graph(graph,"Xsram",pins) graph.remove_edges('vdd') graph.remove_edges('gnd') - debug.info(1,"{}".format(graph)) - graph.printAllPaths('clk0', 'DOUT0[0]') + #debug.info(1,"{}".format(graph)) + graph.print_all_paths('clk0', 'DOUT0[0]') tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) From 5bfc42fdbb1fc4ecc970012ffff199658cc352bc Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Mon, 29 Apr 2019 23:57:25 -0700 Subject: [PATCH 004/234] Added quality improvements to graph: improved naming, auto vdd/gnd removal --- compiler/base/graph_util.py | 59 ++++++++++++++++---------- compiler/tests/21_hspice_delay_test.py | 6 +-- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/compiler/base/graph_util.py b/compiler/base/graph_util.py index eb40d55b..d2759930 100644 --- a/compiler/base/graph_util.py +++ b/compiler/base/graph_util.py @@ -9,28 +9,43 @@ import debug from vector import vector from pin_layout import pin_layout -class graph(): - """Implements a directed graph""" +class timing_graph(): + """Implements a directed graph + Nodes are currently just Strings. + """ def __init__(self): - self.graph = defaultdict(list) + self.graph = defaultdict(set) - def add_edge(self, u, v): + def add_edge(self, src_node, dest_node): """Adds edge to graph. Nodes added as well if they do not exist.""" - if v not in self.graph[u]: - self.graph[u].append(v) + src_node = src_node.lower() + dest_node = dest_node.lower() + self.graph[src_node].add(dest_node) - def add_node(self, u): + def add_node(self, node): """Add node to graph with no edges""" - if not u in self.graph: - self.graph[u] = [] + node = node.lower() + if not node in self.graph: + self.graph[node] = set() def remove_edges(self, node): """Helper function to remove edges, useful for removing vdd/gnd""" - self.graph[node] = [] + node = node.lower() + self.graph[node] = set() - def print_all_paths(self,s, d): - + def print_all_paths(self, src_node, dest_node, rmv_rail_nodes=True): + """Traverse all paths from source to destination""" + src_node = src_node.lower() + dest_node = dest_node.lower() + + #Remove vdd and gnd by default + #Will require edits if separate supplies are implemented. + if rmv_rail_nodes: + #Names are also assumed. + self.remove_edges('vdd') + self.remove_edges('gnd') + # Mark all the vertices as not visited visited = set() @@ -39,30 +54,30 @@ class graph(): self.path_count = 0 # Call the recursive helper function to print all paths - self.print_all_paths_util(s, d,visited, path) + self.print_all_paths_util(src_node, dest_node, visited, path) debug.info(1, "Paths found={}".format(self.path_count)) - def print_all_paths_util(self, u, d, visited, path): - + def print_all_paths_util(self, cur_node, dest_node, visited, path): + """Recursive function to find all paths in a Depth First Search manner""" # Mark the current node as visited and store in path - visited.add(u) - path.append(u) + visited.add(cur_node) + path.append(cur_node) # If current vertex is same as destination, then print # current path[] - if u == d: + if cur_node == dest_node: debug.info(1,"{}".format(path)) self.path_count+=1 else: # If current vertex is not destination #Recur for all the vertices adjacent to this vertex - for i in self.graph[u]: - if i not in visited: - self.print_all_paths_util(i, d, visited, path) + for node in self.graph[cur_node]: + if node not in visited: + self.print_all_paths_util(node, dest_node, visited, path) # Remove current vertex from path[] and mark it as unvisited path.pop() - visited.remove(u) + visited.remove(cur_node) def __str__(self): """ override print function output """ diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 7ca8c4b5..b7ccd72c 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -44,13 +44,13 @@ class timing_sram_test(openram_test): debug.info(1,'pins={}'.format(s.s.pins)) import graph_util - graph = graph_util.graph() + graph = graph_util.timing_graph() pins=['DIN0[0]', 'ADDR0[0]', 'ADDR0[1]', 'ADDR0[2]', 'ADDR0[3]', 'csb0', 'web0', 'clk0', 'DOUT0[0]', 'vdd', 'gnd'] s.s.build_graph(graph,"Xsram",pins) - graph.remove_edges('vdd') - graph.remove_edges('gnd') #debug.info(1,"{}".format(graph)) graph.print_all_paths('clk0', 'DOUT0[0]') + # import sys + # sys.exit(1) tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) From d54074d68ef021237e2a1638e7ac83192efbf04c Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 7 May 2019 00:52:27 -0700 Subject: [PATCH 005/234] Made timing graph more gate-level. Changed edges to be defined by inputs/ouputs and name based. --- compiler/base/hierarchy_design.py | 16 +++++- compiler/base/hierarchy_spice.py | 19 +++++++ compiler/bitcells/bitcell.py | 11 ++--- compiler/bitcells/bitcell_1rw_1r.py | 24 ++++----- compiler/bitcells/bitcell_1w_1r.py | 19 +++---- compiler/bitcells/pbitcell.py | 43 ++++++++-------- compiler/bitcells/replica_bitcell.py | 11 ++--- compiler/bitcells/replica_bitcell_1rw_1r.py | 21 ++++---- compiler/bitcells/replica_bitcell_1w_1r.py | 19 +++---- compiler/characterizer/model_check.py | 55 +++++++++++++-------- compiler/modules/dff.py | 10 ++-- compiler/modules/sense_amp.py | 14 ++---- compiler/modules/tri_gate.py | 13 ++--- compiler/modules/write_driver.py | 17 ++----- compiler/pgates/pgate.py | 1 - compiler/pgates/pinv.py | 18 +++++-- compiler/pgates/pnand2.py | 10 +++- compiler/pgates/pnand3.py | 8 ++- compiler/pgates/pnor2.py | 7 ++- compiler/pgates/ptx.py | 20 ++++---- 20 files changed, 205 insertions(+), 151 deletions(-) diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index 6d9de53c..898ac918 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -120,7 +120,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): #Translate port names to external nets if len(port_nets) != len(self.pins): debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,self.pins),1) - port_dict = {i:j for i,j in zip(self.pins, port_nets)} + port_dict = {pin:port for pin,port in zip(self.pins, port_nets)} debug.info(3, "Instance name={}".format(inst_name)) for subinst, conns in zip(self.insts, self.conns): if subinst in self.graph_inst_exclude: @@ -139,6 +139,20 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): converted_conns.append("{}.{}".format(inst_name, conn)) return converted_conns + def add_graph_edges(self, graph, port_nets): + """For every input, adds an edge to every output. + Only intended to be used for gates and other simple modules.""" + #The final pin names will depend on the spice hierarchy, so + #they are passed as an input. + pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} + input_pins = self.get_inputs() + output_pins = self.get_outputs() + inout_pins = self.get_inouts() + for inp in input_pins+inout_pins: + for out in output_pins+inout_pins: + if inp != out: #do not add self loops + graph.add_edge(pin_dict[inp], pin_dict[out]) + def __str__(self): """ override print function output """ return "design: " + self.name diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index cb2799f3..f2535f86 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -58,6 +58,17 @@ class spice(): else: debug.error("Mismatch in type and pin list lengths.", -1) + def add_pin_types(self, type_list): + """Add pin types for all the cell's pins. + Typically, should only be used for handmade cells.""" + #This only works if self.pins == bitcell.pin_names + if self.pin_names != self.pins: + debug.error("{} spice subcircuit port names do not match pin_names\ + \n SPICE names={}\ + \n Module names={}\ + ".format(self.name, self.pin_names, self.pins),1) + self.pin_type = {pin:type for pin,type in zip(self.pin_names, type_list)} + def get_pin_type(self, name): """ Returns the type of the signal pin. """ return self.pin_type[name] @@ -87,6 +98,14 @@ class spice(): output_list.append(pin) return output_list + def get_inouts(self): + """ These use pin types to determine pin lists. These + may be over-ridden by submodules that didn't use pin directions yet.""" + inout_list = [] + for pin in self.pins: + if self.pin_type[pin]=="INOUT": + inout_list.append(pin) + return inout_list def add_mod(self, mod): """Adds a subckt/submodule to the subckt hierarchy""" diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 798ee3f9..76ecfb0a 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -13,6 +13,7 @@ class bitcell(design.design): """ pin_names = ["bl", "br", "wl", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("cell_6t", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "cell_6t", GDS["unit"]) @@ -24,6 +25,7 @@ class bitcell(design.design): self.width = bitcell.width self.height = bitcell.height self.pin_map = bitcell.pin_map + self.add_pin_types(self.type_list) def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 @@ -76,10 +78,5 @@ class bitcell(design.design): return 2*access_tx_cin def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Handmade cells must implement this manually.""" - #The bitcell has 5 net ports hard-coded in self.pin_names. The edges - #are based on the hard-coded name positions. - # The edges added are: wl->bl, wl->br. - # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. - graph.add_edge(port_nets[2],port_nets[0]) - graph.add_edge(port_nets[2],port_nets[1]) \ No newline at end of file + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index 58b0ca98..d10d03b6 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -13,6 +13,7 @@ class bitcell_1rw_1r(design.design): """ pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("cell_1rw_1r", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "cell_1rw_1r", GDS["unit"]) @@ -24,7 +25,8 @@ class bitcell_1rw_1r(design.design): self.width = bitcell_1rw_1r.width self.height = bitcell_1rw_1r.height self.pin_map = bitcell_1rw_1r.pin_map - + self.add_pin_types(self.type_list) + def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 size = 0.5 #This accounts for bitline being drained thought the access TX and internal node @@ -101,13 +103,13 @@ class bitcell_1rw_1r(design.design): return 2*access_tx_cin def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Handmade cells must implement this manually.""" - #The bitcell has 8 net ports hard-coded in self.pin_names. The edges - #are based on the hard-coded name positions. - # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. - # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. - graph.add_edge(port_nets[4],port_nets[0]) - graph.add_edge(port_nets[4],port_nets[1]) - graph.add_edge(port_nets[5],port_nets[2]) - graph.add_edge(port_nets[5],port_nets[3]) - + """Adds edges to graph. Multiport bitcell timing graph is too complex + to use the add_graph_edges function.""" + pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} + #Edges hardcoded here. Essentially wl->bl/br for both ports. + # Port 0 edges + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) + # Port 1 edges + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index 3d1febdd..e8865dcf 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -13,6 +13,7 @@ class bitcell_1w_1r(design.design): """ pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "INPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("cell_1w_1r", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "cell_1w_1r", GDS["unit"]) @@ -24,6 +25,7 @@ class bitcell_1w_1r(design.design): self.width = bitcell_1w_1r.width self.height = bitcell_1w_1r.height self.pin_map = bitcell_1w_1r.pin_map + self.add_pin_types(self.type_list) def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 @@ -101,12 +103,11 @@ class bitcell_1w_1r(design.design): return 2*access_tx_cin def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Handmade cells must implement this manually.""" - #The bitcell has 8 net ports hard-coded in self.pin_names. The edges - #are based on the hard-coded name positions. - # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. - # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. - graph.add_edge(port_nets[4],port_nets[0]) - graph.add_edge(port_nets[4],port_nets[1]) - graph.add_edge(port_nets[5],port_nets[2]) - graph.add_edge(port_nets[5],port_nets[3]) + """Adds edges to graph. Multiport bitcell timing graph is too complex + to use the add_graph_edges function.""" + pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} + #Edges hardcoded here. Essentially wl->bl/br for both ports. + # Port 0 edges + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) + # Port 1 is a write port, so its timing is not considered here. diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index cff7b5cf..f9c49709 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -91,40 +91,40 @@ class pbitcell(design.design): port = 0 for k in range(self.num_rw_ports): - self.add_pin("bl{}".format(port)) - self.add_pin("br{}".format(port)) + self.add_pin("bl{}".format(port), "OUTPUT") + self.add_pin("br{}".format(port), "OUTPUT") self.rw_bl_names.append("bl{}".format(port)) self.rw_br_names.append("br{}".format(port)) port += 1 for k in range(self.num_w_ports): - self.add_pin("bl{}".format(port)) - self.add_pin("br{}".format(port)) + self.add_pin("bl{}".format(port), "INPUT") + self.add_pin("br{}".format(port), "INPUT") self.w_bl_names.append("bl{}".format(port)) self.w_br_names.append("br{}".format(port)) port += 1 for k in range(self.num_r_ports): - self.add_pin("bl{}".format(port)) - self.add_pin("br{}".format(port)) + self.add_pin("bl{}".format(port), "OUTPUT") + self.add_pin("br{}".format(port), "OUTPUT") self.r_bl_names.append("bl{}".format(port)) self.r_br_names.append("br{}".format(port)) port += 1 port = 0 for k in range(self.num_rw_ports): - self.add_pin("wl{}".format(port)) + self.add_pin("wl{}".format(port), "INPUT") self.rw_wl_names.append("wl{}".format(port)) port += 1 for k in range(self.num_w_ports): - self.add_pin("wl{}".format(port)) + self.add_pin("wl{}".format(port), "INPUT") self.w_wl_names.append("wl{}".format(port)) port += 1 for k in range(self.num_r_ports): - self.add_pin("wl{}".format(port)) + self.add_pin("wl{}".format(port), "INPUT") self.r_wl_names.append("wl{}".format(port)) port += 1 - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") # if this is a replica bitcell, replace the instances of Q_bar with vdd if self.replica_bitcell: @@ -894,14 +894,13 @@ class pbitcell(design.design): return 2*access_tx_cin def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Done manually to make the graph acyclic.""" - #The base graph function can make this but it would contain loops and path - #searches would essentially be useless. - # Edges added wl->bl, wl->br for every port - - num_wl = len(self.rw_wl_names) + len(self.w_wl_names) + len(self.r_wl_names) - wl_pos = 2*num_wl #there are this many bitlines nets before the wls in the port list - for i in range(num_wl): - bl_pos = i*2 - graph.add_edge(port_nets[wl_pos+i],port_nets[bl_pos]) - graph.add_edge(port_nets[wl_pos+i],port_nets[bl_pos+1]) + """Adds edges to graph for pbitcell. Only readwrite and read ports.""" + pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} + # Edges added wl->bl, wl->br for every port except write ports + rw_pin_names = zip(self.r_wl_names, self.r_bl_names, self.r_br_names) + r_pin_names = zip(self.rw_wl_names, self.rw_bl_names, self.rw_br_names) + for pin_zip in zip(rw_pin_names, r_pin_names): + for wl,bl,br in pin_zip: + graph.add_edge(pin_dict[wl],pin_dict[bl]) + graph.add_edge(pin_dict[wl],pin_dict[br]) + diff --git a/compiler/bitcells/replica_bitcell.py b/compiler/bitcells/replica_bitcell.py index 8d77ff7b..deb71e40 100644 --- a/compiler/bitcells/replica_bitcell.py +++ b/compiler/bitcells/replica_bitcell.py @@ -11,6 +11,7 @@ class replica_bitcell(design.design): the technology library. """ pin_names = ["bl", "br", "wl", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("replica_cell_6t", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "replica_cell_6t", GDS["unit"]) @@ -22,6 +23,7 @@ class replica_bitcell(design.design): self.width = replica_bitcell.width self.height = replica_bitcell.height self.pin_map = replica_bitcell.pin_map + self.add_pin_types(self.type_list) def get_wl_cin(self): """Return the relative capacitance of the access transistor gates""" @@ -31,10 +33,5 @@ class replica_bitcell(design.design): return 2*access_tx_cin def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Handmade cells must implement this manually.""" - #The bitcell has 5 net ports hard-coded in self.pin_names. The edges - #are based on the hard-coded name positions. - # The edges added are: wl->bl, wl->br. - # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. - graph.add_edge(port_nets[2],port_nets[0]) - graph.add_edge(port_nets[2],port_nets[1]) \ No newline at end of file + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1rw_1r.py b/compiler/bitcells/replica_bitcell_1rw_1r.py index 67871525..14e10ee6 100644 --- a/compiler/bitcells/replica_bitcell_1rw_1r.py +++ b/compiler/bitcells/replica_bitcell_1rw_1r.py @@ -11,6 +11,7 @@ class replica_bitcell_1rw_1r(design.design): the technology library. """ pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("replica_cell_1rw_1r", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "replica_cell_1rw_1r", GDS["unit"]) @@ -22,6 +23,7 @@ class replica_bitcell_1rw_1r(design.design): self.width = replica_bitcell_1rw_1r.width self.height = replica_bitcell_1rw_1r.height self.pin_map = replica_bitcell_1rw_1r.pin_map + self.add_pin_types(self.type_list) def get_wl_cin(self): """Return the relative capacitance of the access transistor gates""" @@ -32,12 +34,13 @@ class replica_bitcell_1rw_1r(design.design): return 2*access_tx_cin def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Handmade cells must implement this manually.""" - #The bitcell has 8 net ports hard-coded in self.pin_names. The edges - #are based on the hard-coded name positions. - # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. - # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. - graph.add_edge(port_nets[4],port_nets[0]) - graph.add_edge(port_nets[4],port_nets[1]) - graph.add_edge(port_nets[5],port_nets[2]) - graph.add_edge(port_nets[5],port_nets[3]) \ No newline at end of file + """Adds edges to graph. Multiport bitcell timing graph is too complex + to use the add_graph_edges function.""" + pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} + #Edges hardcoded here. Essentially wl->bl/br for both ports. + # Port 0 edges + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) + # Port 1 edges + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1w_1r.py b/compiler/bitcells/replica_bitcell_1w_1r.py index 1f5c3266..0b1b598f 100644 --- a/compiler/bitcells/replica_bitcell_1w_1r.py +++ b/compiler/bitcells/replica_bitcell_1w_1r.py @@ -11,6 +11,7 @@ class replica_bitcell_1w_1r(design.design): the technology library. """ pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "INPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("replica_cell_1w_1r", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "replica_cell_1w_1r", GDS["unit"]) @@ -22,6 +23,7 @@ class replica_bitcell_1w_1r(design.design): self.width = replica_bitcell_1w_1r.width self.height = replica_bitcell_1w_1r.height self.pin_map = replica_bitcell_1w_1r.pin_map + self.add_pin_types(self.type_list) def get_wl_cin(self): """Return the relative capacitance of the access transistor gates""" @@ -32,12 +34,11 @@ class replica_bitcell_1w_1r(design.design): return 2*access_tx_cin def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Handmade cells must implement this manually.""" - #The bitcell has 8 net ports hard-coded in self.pin_names. The edges - #are based on the hard-coded name positions. - # The edges added are: wl0->bl0, wl0->br0, wl1->bl1, wl1->br1. - # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. - graph.add_edge(port_nets[4],port_nets[0]) - graph.add_edge(port_nets[4],port_nets[1]) - graph.add_edge(port_nets[5],port_nets[2]) - graph.add_edge(port_nets[5],port_nets[3]) \ No newline at end of file + """Adds edges to graph. Multiport bitcell timing graph is too complex + to use the add_graph_edges function.""" + pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} + #Edges hardcoded here. Essentially wl->bl/br for both ports. + # Port 0 edges + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) + # Port 1 is a write port, so its timing is not considered here. \ No newline at end of file diff --git a/compiler/characterizer/model_check.py b/compiler/characterizer/model_check.py index ff8bbdfa..b9446639 100644 --- a/compiler/characterizer/model_check.py +++ b/compiler/characterizer/model_check.py @@ -31,7 +31,7 @@ class model_check(delay): self.bl_meas_name, self.bl_slew_name = "bl_measures", "bl_slews" self.power_name = "total_power" - def create_measurement_names(self): + def create_measurement_names(self, port): """Create measurement names. The names themselves currently define the type of measurement""" #Create delay measurement names wl_en_driver_delay_names = ["delay_wl_en_dvr_{}".format(stage) for stage in range(1,self.get_num_wl_en_driver_stages())] @@ -42,7 +42,10 @@ class model_check(delay): else: dc_delay_names = ["delay_delay_chain_stage_{}".format(stage) for stage in range(1,self.get_num_delay_stages()+1)] self.wl_delay_meas_names = wl_en_driver_delay_names+["delay_wl_en", "delay_wl_bar"]+wl_driver_delay_names+["delay_wl"] - self.rbl_delay_meas_names = ["delay_gated_clk_nand", "delay_delay_chain_in"]+dc_delay_names + if port not in self.sram.readonly_ports: + self.rbl_delay_meas_names = ["delay_gated_clk_nand", "delay_delay_chain_in"]+dc_delay_names + else: + self.rbl_delay_meas_names = ["delay_gated_clk_nand"]+dc_delay_names self.sae_delay_meas_names = ["delay_pre_sen"]+sen_driver_delay_names+["delay_sen"] # if self.custom_delaychain: @@ -58,45 +61,54 @@ class model_check(delay): else: dc_slew_names = ["slew_delay_chain_stage_{}".format(stage) for stage in range(1,self.get_num_delay_stages()+1)] self.wl_slew_meas_names = ["slew_wl_gated_clk_bar"]+wl_en_driver_slew_names+["slew_wl_en", "slew_wl_bar"]+wl_driver_slew_names+["slew_wl"] - self.rbl_slew_meas_names = ["slew_rbl_gated_clk_bar","slew_gated_clk_nand", "slew_delay_chain_in"]+dc_slew_names + if port not in self.sram.readonly_ports: + self.rbl_slew_meas_names = ["slew_rbl_gated_clk_bar","slew_gated_clk_nand", "slew_delay_chain_in"]+dc_slew_names + else: + self.rbl_slew_meas_names = ["slew_rbl_gated_clk_bar"]+dc_slew_names self.sae_slew_meas_names = ["slew_replica_bl0", "slew_pre_sen"]+sen_driver_slew_names+["slew_sen"] self.bitline_meas_names = ["delay_wl_to_bl", "delay_bl_to_dout"] self.power_meas_names = ['read0_power'] - def create_signal_names(self): + def create_signal_names(self, port): """Creates list of the signal names used in the spice file along the wl and sen paths. Names are re-harded coded here; i.e. the names are hardcoded in most of OpenRAM and are replicated here. """ delay.create_signal_names(self) #Signal names are all hardcoded, need to update to make it work for probe address and different configurations. - wl_en_driver_signals = ["Xsram.Xcontrol0.Xbuf_wl_en.Zb{}_int".format(stage) for stage in range(1,self.get_num_wl_en_driver_stages())] - wl_driver_signals = ["Xsram.Xbank0.Xwordline_driver0.Xwl_driver_inv{}.Zb{}_int".format(self.wordline_row, stage) for stage in range(1,self.get_num_wl_driver_stages())] - sen_driver_signals = ["Xsram.Xcontrol0.Xbuf_s_en.Zb{}_int".format(stage) for stage in range(1,self.get_num_sen_driver_stages())] + wl_en_driver_signals = ["Xsram.Xcontrol{}.Xbuf_wl_en.Zb{}_int".format('{}', stage) for stage in range(1,self.get_num_wl_en_driver_stages())] + wl_driver_signals = ["Xsram.Xbank0.Xwordline_driver{}.Xwl_driver_inv{}.Zb{}_int".format('{}', self.wordline_row, stage) for stage in range(1,self.get_num_wl_driver_stages())] + sen_driver_signals = ["Xsram.Xcontrol{}.Xbuf_s_en.Zb{}_int".format('{}',stage) for stage in range(1,self.get_num_sen_driver_stages())] if self.custom_delaychain: delay_chain_signal_names = [] else: - delay_chain_signal_names = ["Xsram.Xcontrol0.Xreplica_bitline.Xdelay_chain.dout_{}".format(stage) for stage in range(1,self.get_num_delay_stages())] - - self.wl_signal_names = ["Xsram.Xcontrol0.gated_clk_bar"]+\ + delay_chain_signal_names = ["Xsram.Xcontrol{}.Xreplica_bitline.Xdelay_chain.dout_{}".format('{}', stage) for stage in range(1,self.get_num_delay_stages())] + if len(self.sram.all_ports) > 1: + port_format = '{}' + else: + port_format = '' + self.wl_signal_names = ["Xsram.Xcontrol{}.gated_clk_bar".format('{}')]+\ wl_en_driver_signals+\ - ["Xsram.wl_en0", "Xsram.Xbank0.Xwordline_driver0.wl_bar_{}".format(self.wordline_row)]+\ + ["Xsram.wl_en{}".format('{}'), "Xsram.Xbank0.Xwordline_driver{}.wl_bar_{}".format('{}',self.wordline_row)]+\ wl_driver_signals+\ - ["Xsram.Xbank0.wl_{}".format(self.wordline_row)] - pre_delay_chain_names = ["Xsram.Xcontrol0.gated_clk_bar", "Xsram.Xcontrol0.Xand2_rbl_in.zb_int", "Xsram.Xcontrol0.rbl_in"] + ["Xsram.Xbank0.wl{}_{}".format(port_format, self.wordline_row)] + pre_delay_chain_names = ["Xsram.Xcontrol{}.gated_clk_bar".format('{}')] + if port not in self.sram.readonly_ports: + pre_delay_chain_names+= ["Xsram.Xcontrol{}.Xand2_rbl_in.zb_int".format('{}'), "Xsram.Xcontrol{}.rbl_in".format('{}')] + self.rbl_en_signal_names = pre_delay_chain_names+\ delay_chain_signal_names+\ - ["Xsram.Xcontrol0.Xreplica_bitline.delayed_en"] + ["Xsram.Xcontrol{}.Xreplica_bitline.delayed_en".format('{}')] - self.sae_signal_names = ["Xsram.Xcontrol0.Xreplica_bitline.bl0_0", "Xsram.Xcontrol0.pre_s_en"]+\ + self.sae_signal_names = ["Xsram.Xcontrol{}.Xreplica_bitline.bl0_0".format('{}'), "Xsram.Xcontrol{}.pre_s_en".format('{}')]+\ sen_driver_signals+\ - ["Xsram.s_en0"] + ["Xsram.s_en{}".format('{}')] dout_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit - self.bl_signal_names = ["Xsram.Xbank0.wl_{}".format(self.wordline_row),\ - "Xsram.Xbank0.bl_{}".format(self.bitline_column),\ + self.bl_signal_names = ["Xsram.Xbank0.wl{}_{}".format(port_format, self.wordline_row),\ + "Xsram.Xbank0.bl{}_{}".format(port_format, self.bitline_column),\ dout_name] def create_measurement_objects(self): @@ -362,17 +374,18 @@ class model_check(delay): errors = self.calculate_error_l2_norm(scaled_meas, scaled_model) debug.info(1, "Errors:\n{}\n".format(errors)) - def analyze(self, probe_address, probe_data, slews, loads): + def analyze(self, probe_address, probe_data, slews, loads, port): """Measures entire delay path along the wordline and sense amp enable and compare it to the model delays.""" self.load=max(loads) self.slew=max(slews) self.set_probe(probe_address, probe_data) - self.create_signal_names() - self.create_measurement_names() + self.create_signal_names(port) + self.create_measurement_names(port) self.create_measurement_objects() data_dict = {} read_port = self.read_ports[0] #only test the first read port + read_port = port self.targ_read_ports = [read_port] self.targ_write_ports = [self.write_ports[0]] debug.info(1,"Model test: corner {}".format(self.corner)) diff --git a/compiler/modules/dff.py b/compiler/modules/dff.py index 9b9dd0fe..3ba3f5c8 100644 --- a/compiler/modules/dff.py +++ b/compiler/modules/dff.py @@ -11,6 +11,7 @@ class dff(design.design): """ pin_names = ["D", "Q", "clk", "vdd", "gnd"] + type_list = ["INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("dff", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "dff", GDS["unit"]) @@ -20,6 +21,7 @@ class dff(design.design): self.width = dff.width self.height = dff.height self.pin_map = dff.pin_map + self.add_pin_types(self.type_list) def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" @@ -51,10 +53,6 @@ class dff(design.design): return parameter["dff_clk_cin"] def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Handmade cells must implement this manually.""" - #The cell has 5 net ports hard-coded in self.pin_names. The edges - #are based on the hard-coded name positions. - # The edges added are: clk->Q. - # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. - graph.add_edge(port_nets[2],port_nets[1]) + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index 431fc1b5..5ee208cd 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -13,6 +13,7 @@ class sense_amp(design.design): """ pin_names = ["bl", "br", "dout", "en", "vdd", "gnd"] + type_list = ["INPUT", "INPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("sense_amp", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "sense_amp", GDS["unit"]) @@ -23,7 +24,8 @@ class sense_amp(design.design): self.width = sense_amp.width self.height = sense_amp.height self.pin_map = sense_amp.pin_map - + self.add_pin_types(self.type_list) + def input_load(self): #Input load for the bitlines which are connected to the source/drain of a TX. Not the selects. from tech import spice, parameter @@ -54,12 +56,6 @@ class sense_amp(design.design): return 2*pmos_cin + nmos_cin def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Handmade cells must implement this manually.""" - #The cell has 6 net ports hard-coded in self.pin_names. The edges - #are based on the hard-coded name positions. - # The edges added are: en->dout, bl->dout - # br->dout not included to reduce complexity - # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. - graph.add_edge(port_nets[0],port_nets[2]) - graph.add_edge(port_nets[3],port_nets[2]) + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/modules/tri_gate.py b/compiler/modules/tri_gate.py index 6a1efdea..4b7501dd 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -11,6 +11,7 @@ class tri_gate(design.design): """ pin_names = ["in", "out", "en", "en_bar", "gnd", "vdd"] + type_list = ["INPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("tri_gate", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "tri_gate", GDS["unit"]) @@ -26,6 +27,7 @@ class tri_gate(design.design): self.width = tri_gate.width self.height = tri_gate.height self.pin_map = tri_gate.pin_map + self.add_pin_types(self.type_list) def analytical_delay(self, corner, slew, load=0.0): from tech import spice @@ -43,12 +45,5 @@ class tri_gate(design.design): return 9*spice["min_tx_gate_c"] def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Handmade cells must implement this manually.""" - #The cell has 6 net ports hard-coded in self.pin_names. The edges - #are based on the hard-coded name positions. - # The edges added are: en->out, en_bar->out, in->out. - # A liberal amount of edges were added, may be reduced later for complexity. - # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. - graph.add_edge(port_nets[0],port_nets[1]) - graph.add_edge(port_nets[2],port_nets[1]) - graph.add_edge(port_nets[3],port_nets[1]) \ No newline at end of file + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/modules/write_driver.py b/compiler/modules/write_driver.py index d20a0135..c31e8a4b 100644 --- a/compiler/modules/write_driver.py +++ b/compiler/modules/write_driver.py @@ -11,7 +11,8 @@ class write_driver(design.design): the technology library. """ - pin_names = ["din", "bl", "br", "en", "gnd", "vdd"] + pin_names = ["din", "bl", "br", "en", "vdd", "gnd"] + type_list = ["INPUT", "OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("write_driver", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "write_driver", GDS["unit"]) @@ -22,7 +23,7 @@ class write_driver(design.design): self.width = write_driver.width self.height = write_driver.height self.pin_map = write_driver.pin_map - + self.add_pin_types(self.type_list) def get_w_en_cin(self): """Get the relative capacitance of a single input""" @@ -30,13 +31,5 @@ class write_driver(design.design): return 5*3 def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Handmade cells must implement this manually.""" - #The cell has 6 net ports hard-coded in self.pin_names. The edges - #are based on the hard-coded name positions. - # The edges added are: din->bl, din->br, en->bl, en->br - # A liberal amount of edges were added, may be reduced later for complexity. - # Internal nodes of the handmade cell not considered, only ports. vdd/gnd ignored for graph. - graph.add_edge(port_nets[0],port_nets[1]) - graph.add_edge(port_nets[0],port_nets[2]) - graph.add_edge(port_nets[3],port_nets[1]) - graph.add_edge(port_nets[3],port_nets[2]) \ No newline at end of file + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index 2f641da9..eaabdfe5 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -216,4 +216,3 @@ class pgate(design.design): # offset=implant_offset, # width=implant_width, # height=implant_height) - diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index c66c944c..4a7e0820 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -62,7 +62,9 @@ class pinv(pgate.pgate): def add_pins(self): """ Adds pins for spice netlist """ - self.add_pin_list(["A", "Z", "vdd", "gnd"]) + pin_list = ["A", "Z", "vdd", "gnd"] + dir_list = ['INPUT', 'OUTPUT', 'POWER', 'GROUND'] + self.add_pin_list(pin_list, dir_list) def determine_tx_mults(self): @@ -283,7 +285,8 @@ class pinv(pgate.pgate): return transition_prob*(c_load + c_para) def get_cin(self): - """Return the capacitance of the gate connection in generic capacitive units relative to the minimum width of a transistor""" + """Return the capacitance of the gate connection in generic capacitive + units relative to the minimum width of a transistor""" return self.nmos_size + self.pmos_size def get_stage_effort(self, cout, inp_is_rise=True): @@ -291,4 +294,13 @@ class pinv(pgate.pgate): Optional is_rise refers to the input direction rise/fall. Input inverted by this stage. """ parasitic_delay = 1 - return logical_effort.logical_effort(self.name, self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise) + return logical_effort.logical_effort(self.name, + self.size, + self.get_cin(), + cout, + parasitic_delay, + not inp_is_rise) + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index eb2484af..e1dccf7e 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -33,7 +33,7 @@ class pnand2(pgate.pgate): self.create_layout() #For characterization purposes only - self.exclude_nmos_from_graph() + #self.exclude_nmos_from_graph() def create_netlist(self): self.add_pins() @@ -54,7 +54,9 @@ class pnand2(pgate.pgate): def add_pins(self): """ Adds pins for spice netlist """ - self.add_pin_list(["A", "B", "Z", "vdd", "gnd"]) + pin_list = ["A", "B", "Z", "vdd", "gnd"] + dir_list = ['INPUT', 'INPUT', 'OUTPUT', 'POWER', 'GROUND'] + self.add_pin_list(pin_list, dir_list) def add_ptx(self): @@ -268,3 +270,7 @@ class pnand2(pgate.pgate): #Removing them simplifies generic path searching. self.graph_inst_exclude.add(self.nmos1_inst) self.graph_inst_exclude.add(self.nmos2_inst) + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index d0c37b55..18fc2ed0 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -37,7 +37,9 @@ class pnand3(pgate.pgate): def add_pins(self): """ Adds pins for spice netlist """ - self.add_pin_list(["A", "B", "C", "Z", "vdd", "gnd"]) + pin_list = ["A", "B", "C", "Z", "vdd", "gnd"] + dir_list = ['INPUT', 'INPUT', 'INPUT', 'OUTPUT', 'POWER', 'GROUND'] + self.add_pin_list(pin_list, dir_list) def create_netlist(self): self.add_pins() @@ -272,3 +274,7 @@ class pnand3(pgate.pgate): """ parasitic_delay = 3 return logical_effort.logical_effort(self.name, self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise) + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index 8a5c80d4..64a75b44 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -34,7 +34,9 @@ class pnor2(pgate.pgate): def add_pins(self): """ Adds pins for spice netlist """ - self.add_pin_list(["A", "B", "Z", "vdd", "gnd"]) + pin_list = ["A", "B", "Z", "vdd", "gnd"] + dir_list = ['INPUT', 'INPUT', 'OUTPUT', 'INOUT', 'INOUT'] + self.add_pin_list(pin_list, dir_list) def create_netlist(self): self.add_pins() @@ -234,3 +236,6 @@ class pnor2(pgate.pgate): transition_prob = spice["nor2_transition_prob"] return transition_prob*(c_load + c_para) + def build_graph(self, graph, inst_name, port_nets): + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index 7e80a7c9..81ff54a3 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -60,7 +60,13 @@ class ptx(design.design): #self.DRC() def create_netlist(self): - self.add_pin_list(["D", "G", "S", "B"]) + pin_list = ["D", "G", "S", "B"] + if self.tx_type=="nmos": + body_dir = 'GROUND' + else: #Assumed that the check for either pmos or nmos is done elsewhere. + body_dir = 'POWER' + dir_list = ['INOUT', 'INPUT', 'INOUT', body_dir] + self.add_pin_list(pin_list, dir_list) # self.spice.append("\n.SUBCKT {0} {1}".format(self.name, # " ".join(self.pins))) @@ -358,14 +364,6 @@ class ptx(design.design): return self.tx_width/drc("minwidth_tx") def build_graph(self, graph, inst_name, port_nets): - """Adds ptx edges to graph. Lowest graph level.""" - #The ptx has four connections: (S)ource, (G)ate, (D)rain, (B)ody. The positions in spice - #are hardcoded which is represented here as well. - #Edges are connected as follows: G->S, G->D, D<->S. Body not represented in graph. - if len(port_nets) != 4: - debug.error("Transistor has non-standard connections.",1) - graph.add_edge(port_nets[1],port_nets[0]) - graph.add_edge(port_nets[1],port_nets[2]) - graph.add_edge(port_nets[0],port_nets[2]) - graph.add_edge(port_nets[2],port_nets[0]) + """Adds edges based on inputs/outputs. Overrides base class function.""" + self.add_graph_edges(graph, port_nets) \ No newline at end of file From c24879162aec2c7f1d0096f1ec9e882927267b1d Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 8 May 2019 16:06:21 -0700 Subject: [PATCH 006/234] Add back scn3me_subm tech files --- compiler/base/contact.py | 7 +- compiler/tests/config_scn3me_subm.py | 22 + compiler/tests/config_scn3me_subm_back_end.py | 22 + .../tests/config_scn3me_subm_front_end.py | 19 + technology/scn3me_subm/__init__.py | 43 + .../scn3me_subm/gds_lib/cell_1rw_1r.gds | Bin 0 -> 6330 bytes technology/scn3me_subm/gds_lib/cell_1w_1r.gds | Bin 0 -> 8192 bytes technology/scn3me_subm/gds_lib/cell_6t.gds | Bin 0 -> 5916 bytes technology/scn3me_subm/gds_lib/dff.gds | Bin 0 -> 16622 bytes technology/scn3me_subm/gds_lib/ms_flop.gds | Bin 0 -> 18934 bytes .../gds_lib/replica_cell_1rw_1r.gds | Bin 0 -> 6282 bytes .../gds_lib/replica_cell_1w_1r.gds | Bin 0 -> 8192 bytes .../scn3me_subm/gds_lib/replica_cell_6t.gds | Bin 0 -> 6060 bytes technology/scn3me_subm/gds_lib/sense_amp.gds | Bin 0 -> 8312 bytes technology/scn3me_subm/gds_lib/tri_gate.gds | Bin 0 -> 4576 bytes .../scn3me_subm/gds_lib/write_driver.gds | Bin 0 -> 11804 bytes technology/scn3me_subm/mag_lib/.magicrc | 5 + .../scn3me_subm/mag_lib/cell_1rw_1r.gds | Bin 0 -> 6330 bytes .../scn3me_subm/mag_lib/cell_1rw_1r.mag | 142 + technology/scn3me_subm/mag_lib/cell_6t.mag | 117 + technology/scn3me_subm/mag_lib/convertall.sh | 14 + technology/scn3me_subm/mag_lib/dff.mag | 279 + technology/scn3me_subm/mag_lib/ms_flop.mag | 294 + .../mag_lib/replica_cell_1rw_1r.gds | Bin 0 -> 6282 bytes .../mag_lib/replica_cell_1rw_1r.mag | 145 + .../scn3me_subm/mag_lib/replica_cell_6t.mag | 118 + technology/scn3me_subm/mag_lib/sense_amp.mag | 136 + technology/scn3me_subm/mag_lib/setup.tcl | 15 + technology/scn3me_subm/mag_lib/tri_gate.mag | 98 + .../scn3me_subm/mag_lib/write_driver.mag | 224 + technology/scn3me_subm/models/ff/nmos.sp | 10 + technology/scn3me_subm/models/ff/pmos.sp | 9 + technology/scn3me_subm/models/nom/nmos.sp | 9 + technology/scn3me_subm/models/nom/pmos.sp | 9 + technology/scn3me_subm/models/ss/nmos.sp | 10 + technology/scn3me_subm/models/ss/pmos.sp | 9 + technology/scn3me_subm/sp_lib/cell_6t.sp | 10 + technology/scn3me_subm/sp_lib/dff.sp | 27 + technology/scn3me_subm/sp_lib/ms_flop.sp | 29 + .../scn3me_subm/sp_lib/replica_cell_6t.sp | 10 + technology/scn3me_subm/sp_lib/sense_amp.sp | 12 + technology/scn3me_subm/sp_lib/tri_gate.sp | 13 + technology/scn3me_subm/sp_lib/write_driver.sp | 38 + technology/scn3me_subm/sue_lib/cell_6t.sue | 46 + technology/scn3me_subm/sue_lib/ms_flop.sue | 84 + .../scn3me_subm/sue_lib/replica_cell_6t.sue | 49 + technology/scn3me_subm/sue_lib/sense_amp.sue | 52 + technology/scn3me_subm/sue_lib/tri_gate.sue | 37 + .../scn3me_subm/sue_lib/write_driver.sue | 44 + technology/scn3me_subm/tech/README | 10 + .../scn3me_subm/tech/SCN3ME_SUBM.30.tech | 7891 +++++++++++++++++ technology/scn3me_subm/tech/__init__.py | 6 + .../tech/calibreDRC_scn3me_subm.rul | 225 + .../tech/calibreLVS_scn3me_subm.rul | 123 + technology/scn3me_subm/tech/tech.py | 311 + technology/scn3me_subm/tf/README | 19 + technology/scn3me_subm/tf/display.drf | 714 ++ .../scn3me_subm/tf/glade_scn3me_subm.py | 7 + technology/scn3me_subm/tf/layers.map | 16 + technology/scn3me_subm/tf/mosis.tf | 848 ++ technology/scn4m_subm/tech/tech.py | 2 +- 61 files changed, 12376 insertions(+), 3 deletions(-) create mode 100644 compiler/tests/config_scn3me_subm.py create mode 100644 compiler/tests/config_scn3me_subm_back_end.py create mode 100644 compiler/tests/config_scn3me_subm_front_end.py create mode 100644 technology/scn3me_subm/__init__.py create mode 100644 technology/scn3me_subm/gds_lib/cell_1rw_1r.gds create mode 100644 technology/scn3me_subm/gds_lib/cell_1w_1r.gds create mode 100644 technology/scn3me_subm/gds_lib/cell_6t.gds create mode 100644 technology/scn3me_subm/gds_lib/dff.gds create mode 100644 technology/scn3me_subm/gds_lib/ms_flop.gds create mode 100644 technology/scn3me_subm/gds_lib/replica_cell_1rw_1r.gds create mode 100644 technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds create mode 100644 technology/scn3me_subm/gds_lib/replica_cell_6t.gds create mode 100644 technology/scn3me_subm/gds_lib/sense_amp.gds create mode 100644 technology/scn3me_subm/gds_lib/tri_gate.gds create mode 100644 technology/scn3me_subm/gds_lib/write_driver.gds create mode 100644 technology/scn3me_subm/mag_lib/.magicrc create mode 100644 technology/scn3me_subm/mag_lib/cell_1rw_1r.gds create mode 100644 technology/scn3me_subm/mag_lib/cell_1rw_1r.mag create mode 100644 technology/scn3me_subm/mag_lib/cell_6t.mag create mode 100755 technology/scn3me_subm/mag_lib/convertall.sh create mode 100644 technology/scn3me_subm/mag_lib/dff.mag create mode 100644 technology/scn3me_subm/mag_lib/ms_flop.mag create mode 100644 technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.gds create mode 100644 technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag create mode 100644 technology/scn3me_subm/mag_lib/replica_cell_6t.mag create mode 100644 technology/scn3me_subm/mag_lib/sense_amp.mag create mode 100644 technology/scn3me_subm/mag_lib/setup.tcl create mode 100644 technology/scn3me_subm/mag_lib/tri_gate.mag create mode 100644 technology/scn3me_subm/mag_lib/write_driver.mag create mode 100644 technology/scn3me_subm/models/ff/nmos.sp create mode 100644 technology/scn3me_subm/models/ff/pmos.sp create mode 100644 technology/scn3me_subm/models/nom/nmos.sp create mode 100644 technology/scn3me_subm/models/nom/pmos.sp create mode 100644 technology/scn3me_subm/models/ss/nmos.sp create mode 100644 technology/scn3me_subm/models/ss/pmos.sp create mode 100644 technology/scn3me_subm/sp_lib/cell_6t.sp create mode 100644 technology/scn3me_subm/sp_lib/dff.sp create mode 100644 technology/scn3me_subm/sp_lib/ms_flop.sp create mode 100644 technology/scn3me_subm/sp_lib/replica_cell_6t.sp create mode 100644 technology/scn3me_subm/sp_lib/sense_amp.sp create mode 100644 technology/scn3me_subm/sp_lib/tri_gate.sp create mode 100644 technology/scn3me_subm/sp_lib/write_driver.sp create mode 100644 technology/scn3me_subm/sue_lib/cell_6t.sue create mode 100644 technology/scn3me_subm/sue_lib/ms_flop.sue create mode 100644 technology/scn3me_subm/sue_lib/replica_cell_6t.sue create mode 100644 technology/scn3me_subm/sue_lib/sense_amp.sue create mode 100644 technology/scn3me_subm/sue_lib/tri_gate.sue create mode 100644 technology/scn3me_subm/sue_lib/write_driver.sue create mode 100644 technology/scn3me_subm/tech/README create mode 100644 technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech create mode 100755 technology/scn3me_subm/tech/__init__.py create mode 100755 technology/scn3me_subm/tech/calibreDRC_scn3me_subm.rul create mode 100755 technology/scn3me_subm/tech/calibreLVS_scn3me_subm.rul create mode 100755 technology/scn3me_subm/tech/tech.py create mode 100644 technology/scn3me_subm/tf/README create mode 100644 technology/scn3me_subm/tf/display.drf create mode 100644 technology/scn3me_subm/tf/glade_scn3me_subm.py create mode 100644 technology/scn3me_subm/tf/layers.map create mode 100644 technology/scn3me_subm/tf/mosis.tf diff --git a/compiler/base/contact.py b/compiler/base/contact.py index de1afec6..396b2a6d 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -8,7 +8,7 @@ import hierarchy_design import debug import utils -from tech import drc +from tech import drc,layer from vector import vector @@ -196,5 +196,8 @@ active = factory.create(module_type="contact", layer_stack=("active", "contact", poly = factory.create(module_type="contact", layer_stack=("poly", "contact", "metal1"), directions=("V","H")) m1m2 = factory.create(module_type="contact", layer_stack=("metal1", "via1", "metal2"), directions=("H","V")) m2m3 = factory.create(module_type="contact", layer_stack=("metal2", "via2", "metal3"), directions=("V","H")) -m3m4 = factory.create(module_type="contact", layer_stack=("metal3", "via3", "metal4"), directions=("H","V")) +if "metal4" in layer.keys(): + m3m4 = factory.create(module_type="contact", layer_stack=("metal3", "via3", "metal4"), directions=("H","V")) +else: + m3m4 = None diff --git a/compiler/tests/config_scn3me_subm.py b/compiler/tests/config_scn3me_subm.py new file mode 100644 index 00000000..2cd02b5e --- /dev/null +++ b/compiler/tests/config_scn3me_subm.py @@ -0,0 +1,22 @@ +# 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. +# +word_size = 1 +num_words = 16 + +tech_name = "scn3me_subm" +process_corners = ["TT"] +supply_voltages = [5.0] +temperatures = [25] + +route_supplies = True +check_lvsdrc = True + +drc_name = "magic" +lvs_name = "netgen" +pex_name = "magic" + diff --git a/compiler/tests/config_scn3me_subm_back_end.py b/compiler/tests/config_scn3me_subm_back_end.py new file mode 100644 index 00000000..5586ebca --- /dev/null +++ b/compiler/tests/config_scn3me_subm_back_end.py @@ -0,0 +1,22 @@ +# 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. +# +word_size = 1 +num_words = 16 + +tech_name = "scn3me_subm" +process_corners = ["TT"] +supply_voltages = [5.0] +temperatures = [25] + +route_supplies = True +check_lvsdrc = True +inline_lvsdrc = True + +drc_name = "magic" +lvs_name = "netgen" +pex_name = "magic" diff --git a/compiler/tests/config_scn3me_subm_front_end.py b/compiler/tests/config_scn3me_subm_front_end.py new file mode 100644 index 00000000..7b39e46d --- /dev/null +++ b/compiler/tests/config_scn3me_subm_front_end.py @@ -0,0 +1,19 @@ +# 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. +# +word_size = 1 +num_words = 16 + +tech_name = "scn3me_subm" +process_corners = ["TT"] +supply_voltages = [5.0] +temperatures = [25] + +drc_name = "magic" +lvs_name = "netgen" +pex_name = "magic" + diff --git a/technology/scn3me_subm/__init__.py b/technology/scn3me_subm/__init__.py new file mode 100644 index 00000000..87b26056 --- /dev/null +++ b/technology/scn3me_subm/__init__.py @@ -0,0 +1,43 @@ +# 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. +# +#!/usr/bin/python +""" +This type of setup script should be placed in the setup_scripts directory in the trunk +""" + +import sys +import os + +TECHNOLOGY = "scn3me_subm" + + +########################## +# CDK paths + +# os.environ["CDK_DIR"] = CDK_DIR #PDK path +# os.environ["SYSTEM_CDS_LIB_DIR"] = "{0}/cdssetup".format(CDK_DIR) +# os.environ["CDS_SITE"] = CDK_DIR +os.environ["MGC_TMPDIR"] = "/tmp" + +########################### +# OpenRAM Paths + + +try: + DRCLVS_HOME = os.path.abspath(os.environ.get("DRCLVS_HOME")) +except: + OPENRAM_TECH=os.path.abspath(os.environ.get("OPENRAM_TECH")) + DRCLVS_HOME=OPENRAM_TECH+"/scn3me_subm/tech" +os.environ["DRCLVS_HOME"] = DRCLVS_HOME + +# try: +# SPICE_MODEL_DIR = os.path.abspath(os.environ.get("SPICE_MODEL_DIR")) +# except: +OPENRAM_TECH=os.path.abspath(os.environ.get("OPENRAM_TECH")) +os.environ["SPICE_MODEL_DIR"] = "{0}/{1}/models".format(OPENRAM_TECH, TECHNOLOGY) + diff --git a/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds b/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..2d12b8eea9b4107adacb23f749aeeec1f17ef784 GIT binary patch literal 6330 zcmbW5J&aXF7=~Z==dyuySr8Bm3jPZ$unTJdC4x%)i5Q7)lo%6@uF+y+3^A;Qg@uJC z78VvJT3DFaSWsAOVL@Sxg@uKMg@px$g$0F$g@xb4oHu9g#czn73mYDOEhTeoXflbX^dZPPlwTh5gDX6Utlt{y+06IV)n^U<@VEi?4gPoA6ulQz-K&};wx zIzD}T`l58(-#wRJme9>8PyILkAwB$~wBz%hkNhQ}n^B(niG!c`CO&kt<-hyu;@kgX zPkiWR%TGU9yZBA|;c<24Y5zBTRAMcD+mp7?&FD+&r+vmwU6a0}o1v$E;!v0PCUcK& zhMxM#Gj)k=ZaPu&Z-!p`=j-)z>pRlfU!^@i^?Y_wLN}v4^>190?)gQUneDl6UP3pc zJoRteQG7SO)e|4O+42*c4|UD@cUPXqUpQ8LM?UU}AKi>LQa^dR>%EdclbGmc=&7GP zF;?Yw|d1XUbFHG`|&kVikXWYazX$QYKGX6vL z{YQ*rr%Jxe`#&wQ&Cu)kL;mT@()_fDj{kq`|3mp>oaCDEo6G^a8G0I@apGg#CO&j?#J^ClKgGrS4`+Xq z_Z}{D?aG^e`c8b4cHAxu zJ@s?XvrpnR=|8#|dg|vLjlB!MNjvCfYyR=@p{~ig;kOyT)A;n0*!2f5x*27uf9zbD zYxWD~9MTrL8G7m`zxY_cCcZB3SK0FW{KovTXF~RZ#`$gN{^6aMSoGVZFX(3IY5%!T z@N)l{^dH>}J@qqYKGZeq-(7j?XWyj`{~ek5(aq3PKl4o9M$cd9fdsy^p$l_pS}LknZK?)^)tWtI4_%?cQf?V&pdN6|0exLH$zYT zoVmGJza~C(GxXYjvYtOYT+F}uOgH~#=vV#GCI0`8`+qzCe^2xOH|LHge%92^!RpHV zb?QZXQSZX?a-$w+u8E7Ky@l)4i+6-*@AWrF+Kcts_b=Mw|J|tf%4q+F>hZqedLwa% X>hW&S)jQv+$GeZ~IWOyDJQMl{QEIs5 literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/gds_lib/cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/cell_1w_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..080a29e3340ca246cceb29908585c6eb92868b87 GIT binary patch literal 8192 zcmeI0Ka3Ss6o(IQcONgXF3W9ocjjP&1z}hB(vY<%>Cxv zduHyPnP+WlS=;7TwQR=L+LW!aZFaY9unFtfI-9ixn{2h0&%gT8+x@r9HjYg^a`dAE zPyX=rjYG#T@B8xe=a+15B6g?R?N`qC`{#NW&-E_Yc*m@LTg!G?d#Yt-^V4Jg*S80M zOMLFS*^$T1M8%!s>+NrUXVXu1IuAY`%(mR$o%?s3G&^<444!$>?5;m+D((#Z4L8gl z{mBd-`@?L@7c~`khCX>|2l2@-DqiyM`zHAiZ}$r|@vGxue)>(VG!A?`sJJuq*L<9E zK%B+zYLdG;9{S{E%#ik+LsZ-u`kWsZZoQfEi;6o#pSt71b%#@5M8%!C-_7rzJKr@s zea#F$vuL*cYE8wRp}+RB+5Nwm!ChUmsp*=EJ465WEy;)Yo8PR7UmXv9+Gxkmcg3Bd z-#eImh`axjn)uc6(5G%Y-cR+TJ@pe6cZNQ7V~mioQ$JC0XXulE)A5v_xl4XgacAf= zKJq~FGJa9!Si;6pQe?A{SZ4UpQ&T-;&$}cMJ41MZHZpgXlyQsJ`_xI-cXMarhEF|yT z_L|(w)$!23=K-^azc+*U%vn)!XXsO7Y6fYKFDmW~eeSWnzovVT{?1%Ud5~IG$3vg`;Hi#`gML88OZk~A)Le6hyv!k}xHHU8|G3_e_VS?O&d{gdw9_~^ z2mOYMmwc`}?I72S>nAE+^5;KH`5<-6cluEs5Btw?u9MD#qg`=l(Pymq)SY!)RNPtg z87DsNRXeD7WBmK_`A4pUODX3=pQSpAiaYcCL;mD-v+krBTv$%;Frwnl(5KI|gLtgt zqT(f=Hrny>UGb97yO!R)m^0K&RNNW%pY@t{5RaUq;tju-*WY~OJ)e#Df8KdT#T)Pc zxA>2}H_+|meDX!boq7L<{CxeQJ@Z)P9;%LqKJU1CPj7yIDBgH~AIeXSXb1J(Au3+- zc~_?$Y<_%GRo`wt#e+*uqy>y6ICoX3NTJBvQw9Qd>+uc){)^m%V$&4TnB zM^xMy`aHL}&XD%_qT*8(dNGl25XOVlNIv)De zopun9cW+T~XXrPdpIkrIRLGiE9S?oJ@yHFyP5(v3ouSXX(Hcg-`DPUrcZNP=)Q*?$ zikHUEdPh5m%R8f}c**CwQzxkBo~XDp>_2&_6Qpi@|BH&3>Sw-Ddp7FD+z}ObhWYWh z$JkbPk}oRm9QfWvet+`yZxg>iwKuQg?^ga!@>>+&dr$mqo!R!qe%Ds+Jl(;0XL)&r z4$r6YODRw9UpW4Z_dKt?p*%iZ#UijL&oL(^CiiaSGp=XmlV9&<^=ua1X4 z&uhNrA!`upkEpma^#8-}2}AW`+|(FSd&Vy+?hNxYKH5P%#xE+~@b~BUUpD6k?@`P} z-lrg2bv(~MO8=yQ!&Lm(dOv8cE+^k=T5K0-Z5MEYJG4}I=Y+G#!2 zcLh}38TzcFY>m;Skaf7Cs`A`(Y&VefnCKU(|EW)Da1h0klg@@43vw=MB^yT89> zw&h*3iH(|jE{869dE&p>;U~X{A6?A-F+SvA{KT0Dp^L7k{U;ATts6)m z(8U4&k$V2k4qh`mdBbdespiV*&_ypV^B4YZ_s?(4j$DlWBQ8D)U39(CPwv)*XahWQ zQE`J_p7_mnjD?T=OB_f$(8VS{`-FOU#l=Ul|3uf*{P^+izgm+xid&VZe#Rev`N5Aa zdRgL+@gWD}Chor)y6Af1k33Zydw%tW{PYRt{>Z}~9lI2J74Di0UG(xa|F-q0J9bHo zIK+%kPfz{RGf|IrQy+4Mpo>lUr)MHBdyTcso*|CnR^?^>rE>oqx@)%lUF>!7)J`*W z(e>0n`q*szrr9&E)qM6BGj!3*Q~$nm;X81rCO&jA_jkL0{TR77Ez}&p8M^3gOY_rD z+Rj-g(jRoO$v^s7Z4k|93;hrF^fdpzbKyI1M+_hR$6u8v{_wERs4E`57rN+r;*UP# zqp#x8d!dU>{=HAaM|<%@eCT46pK->=_>1_^#oQnLBp3Y`HKwBLY5&QCkNhHiKoR^s@|M}w>t-Tx6c@Ul`q?);x1T>>lf3BS!1KE=Kl9ER ziC-ihy6AeEpL*P%cb}gU;A&NcJEK13G>=D#mL`O3Ls?wAX7 z(aX#HCkETkbC3EW&pp~N4m|$~f1E$`oAXCJcrA2sp#OzG&KZ2{d69AB{1Kb{Bg>I% z>vb{O!kEyesyyxgn8ulz6`=wg$fb~4wTlOnOuMc0%5$N2DD zf$SvF$=NWgAexr-7r+(Hcdmg_? zobpU@J@s?Oa_6W0BK<%YT~GbAlX~PAX$QLKdZVAb+}lOsC@yTu&pKn?87qYny$)|{ETt< z%illv8T(+by!4;!Kfl7?x*(eA+zK}N>-Ot+AY;aR2ihNO_OtFdC%7|+_|QeyllI4+ zp`WZD5g&U%bUpR|zwu+8#kkEciIJCeNB*k3mwzS%hzz-2i|@8^VVa1 LTE*Jzy=dFtRZEf{ literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/gds_lib/dff.gds b/technology/scn3me_subm/gds_lib/dff.gds new file mode 100644 index 0000000000000000000000000000000000000000..07c37298b1293dad95cbcfb12e4c3222dddffa7f GIT binary patch literal 16622 zcmaLeJIrNO8OHI&%rJ~P;&73R85JTbmjQ;$1W*Euj*0;zoG4EySD8-^2j5tUAX=1I}ZNomV5sB zw|8$l^y>8||9by@ZSUCw-_FUmV^?cCKfbNq*>;}0t+lpq&-VK7{O^yiO<(YL`={?= z{ojuB>NESV-t^ykS8IIXu~#O4So+d`)w=(K58gk{A5Q(~L4U2C(U<;fmwsdX<$JCD z;rSJRbKjIhSnXZ^j+a~euLG5N#NhyME>Z0&&;S_}1)ezEkS|MqvM^B3x8_MKtrUH?N{t?|h} z6rUcB{5fx~znFOLo~ggE^kw{Omgn!BD(WA;+S;9WulVGZt&cKp^ApLoADdRXmUzc|K!|LrR}cNy2*-u25rq<%84xxE|T`E`u= zAwNAVz3X?K`HtVZ;>TW{u79}U-@mM1bL_89*+F-BIc_j3MNc ze>n1AUUMDa6*b&G$bC*)T@ zVd-7JI^k14As;;)`PB)Z`U&~y;mEH}_|#9xM-NASb;759LOyyp@~aa*brbT@!;xQ| z@R@%?K6*Ivs}nx;6Y|l+k)Ox<<=D`=MGr^ompb|NOH=)X_D%G#^kMyotA0Xp)lWEz zf8&wKck^p2^3lVQU!91nenLKaIP$9#KJ^pw(Zi8no$#rjkdGdY{OW{H{e*n3;;R!r^%L^Z z!;xQ|@Ts4Wj~V!}IgnaaHL=u*ha~mfpSo>gVV0O!X7~;?Okzgr#@=>O@@i6N*a@NAcAOpZW>;=;6q(PWaSM z$VU%Hes#j9enLKaIP$9#KJ^pw(ZiA7HRe-4As;;)`PB)Z`U&~y;mEH}jNSSbdKRaL zrFXBt`uWM8seZzr*8YngmfrQN6LHl~C@wu5#aAbM>L=u*haa z3Hj*Z$gfWLmLEQPIP$9#UiB05(Zi8no$#rjkdGdY{OaWJuBm=P@6YIA>D}wEPQG8q zTE9ZM)5FrcetC*3|4>|dIEpV%KKX}y^l;>t=e_%;{KIcQJLMmi-W|U@zxCrO|L{96 zPx*(Xcm47dSN@^6^l%hko_z8T`RL)uFaNK9cgjD!`|nf!Vd>rR%iq1@`iI~A_mqEF zde<*capfP1OAkl!<;f@ikdGdY{PMr+sVV>PEB~7E4@>WkU;YPAPWgx4z0t$cyMB3! zEB{bjdN_(NPd@pFeDrYS_nyu<@cu5eme9k}m*c-~`TlSB+pS&mKx?0YO9Qi+eZ~Y+cxz;}W(u&R-J*@U_d}H+9{Hh%*^3lU;@A|F#U;4}B z5A{b6OYi!P^NVjy`-M)!s| zD>`rVaAW;jyMG*Kp0?i!t)uC8Ztuo7PIcpF4WT@e*WBLq>;F^lwPyUGab#R`d)I%< zh10x$+Y>8pRsQsFWBy;u-x^_`VC@R|=wa#I_-f4g;t%yh4@c+UzSBHu{GoM>9+uvX z|G6utdsY3oXVH12hoyJ@>eO}P3-v<}OYi#KD~?k?p}6$0^r2te>;5yvNByK<9L0B? z`JKPed8CIUzkR!Ub8P53(!XH_ne|mjX#tRJuJQJ_p??$;|-029*+FtEMtkOpNwm6 z@5a}z*7-u~Ele!$#~^0phq4|g&mfnr8 zZq1wgp?>J$X#SKRpYezCpob&BHPSepztDN4hoyJNuTJbYT(8jiPhHLJUB5W;RDYpy zWL$H5*ROwh^N0GOhok)6r+mgA%7Y$`{OX)f{f6q89&Y%rUp_xsZ(S>U{m`|fhovv` zU-R4N@Ett4A|E{*`CWI<$>xdho;KA(Sb8_UXKo+faQS_1@A?m%o}QEauAS#)^-lK;b^XJ<6Qzv4opU`syJuJN&-|sEidtJP>qIruRR(sd)XFjgI zpY?=(7EBLI@A^Gw%GvXGc=i72`7-XGX@9B31L+dU*EWPV@jl^}$LviWhD8BP9 zws+m3y)!*5y&K8L-QUzEWPV@pYb{OAs;>5@ZY$+f900@wedSo)(Ph?v~JSF z(!23pC$U|>(E3LYOYi#S$tVAij~;ILZ&=oEtA9sNO}{@K9(#p4y#vJ3m+{y9es|FC z&3a!J=J!^^jo+VL^ZOm2yPlfn%g{LJVd>rY<_v3>`92hv9+uwqyT?82@Q3=LhoyJ@ z<_$iz8X7k}9QoZNeAesGxar}@@1Ex~|Ayky!;xQ|@X0k4mmZG%&eP#t(|Qr=C+Br; z@18$-ie;_|`Ey?8_O9PNVgKX(L8u>kxUv6Pt3PA*5i?wVpWBD=J*S&%LgUD|u=K89 z-h9jVAN=%ieBR%LeDrYS7vI>I@6Ys;an0@B_~s19d)^6s zr-!5Xj&tvrJ3{@W-?_aTe||r4CYJ9Rhwu8C+q-@><~-RihMwi4ht2~%EWPVDe_QwYL;Yl4pWC~B^Nw0|&xG=zhoyJ@_PNICcdtV87CkJz z>o-1gguQDhkK{GC5B+M_+8^pC{bK1|zxSgDPEYfF=)DO&EWPW$;GJpiuwIx$P(Spr z^r4?;`SUORq+hJ|uHU}HKHpv?G z{g<`c-a&li%XyvKyW{tqB))Yjd1E5ZC=5x_0z%6yN$QuJt!G7t_O0{Q2*z*Z%%mKmJYpzrVk}Y5D%b zn9b8-h09u)+n48m&2OI1x)WNz=;6lvyXMb*BDU*}?nQc7dN;m3R`z{i_KjibU4QCq zdH?%P4@dD`XK`Hr(7uNrmVPFF-ID%(zw*Dx-|z4C_xtnvvt5_&eE5mSTmLwFi`v)h zymaTG!BJZ$&g{19sPC;GRcpp7rn#oZTQQ$La%6Cv{m)tZ9QWvxIqsY~enpphaKic+YtXalHK zt08EV2!@&zsj+CIAXSf{C_zL5#9$0<{9OjGW)O@rIZC@Gvj{;|GfK! z`~!StRsLDV{~I|x{vG&Fney-7|KII-?pu$U;w!6Cmp%WlSNM3XqM~3si zXV`!2lchX5Qp!6|n&Q7sC6f85{a+bP zzx?jg>6f85{gw|K&$wJn+lVtNugcS|72u zl(EPux%TKX^s1jc_{cBcwIlP(mjB>6r5rYv`6Y4CW$45C7Yxt8k)1hjXg~7@GVjo3 zZ~k=r&btMh(+`<{=(6P}5A%+^l6i+Nd-Jc8pYxb^_$BiWUH0bRG(YnOzr1C0`ekqa zbo}%aAN`ihJ9OFd(@y3c`6crXUH0Z*CqL&g&+tp;4Y~}ydHtCu&SU4Taba)%ojN>! zm}gIo=NyzT#Q3Aj(1-JP{PX6Q^8CC~=07(@eCRTcH~r79E#)2CN|D4fE)2ctr`_b2 z#2NS|*lIuheB|})zkFge`!7Rp=6`Hu=9l=$FGFwo$9H7^C2{b}(3^hReafQj2P6)D z*=j%iziVUmU;cb=_FsnH%zyuq?7zfEei?exzjaIYUlIqu487^U=f%t~iGyE;-t_-y zLFSjl!7oE^`WZLopCk@`*&08_|JKzx{_;CF<@n3coB6--c;=V*$S*^0`focj`!9)u zUxwcF({B1NiGyFZ+E4$liF5hwlj~y+qs!2n`PXgA{1PAeW#~=+bD*G?5T9^Hop*Qn?W_RY7_{c9qZ~8AC%l=E^;FqB{{j{69BZ-4w zw%SksPhFY)mmhjM`!7Rp=0AI0_Fv*7zYM+UKWlCFUlIqu487@JJf8U_aq!E~oBl7k~sKfYy24hqn73P%M(`Q_{-3n`MGz6bq&>6f85{omY|e);X?>6f85{a?K^{c_XG>6f85{WtDNzr1NA{WA2Xe@)Ca z?iKm@_%riQhTimlc5nLSl`;SE%g~$tPi{%S{Paudm!UWP=frr^etGWJ^vlqj{`bXr zF3!Gzhn=H{>#vt{^8n39QFe6%Q)WjAH6Q~OZF7-%h0R-Lu2d@|3N9E zFHJF?_X@g<<5fR(j=J@xT~nlPq03hN;ymgWe)-JO^vhQL!cX18FR5GTvQ@u0kGh3l zQn%1$tA6o}jgMz{i4R@2{N$nTkzZ2x&}FOsabDE73BRQ7q07*l*N?hKeo5WKFI)AG z^Qe3HC3O#7w(1|}QTOmm>K?jm)j!Uo?%|izJ#-m*v;WjR{F1tdU$*KW=TZ0YOX?oF zY}G%`qwe9C)ID_Bs(;Kge9S+I4_&tWHS^2Ro8w2_r2Ue*NnF{gpPWbC z#4o9v=rZ(Xe(EQFN!`RRTlJIksGImDbrW6o>gU4Y_1nnKQl7iJl;dBY;@|g`iTyVj z$A{bB@l#{jcRFg>6p4o}d;3ov|J>cVPej|hgD!i&pPl^7&#S|WUlIphhF;B2`!8FP?UyT~@8~l0s-HZc+Liew zanNPxRX=rV`Sv_tUQn`r$6gSom!Vhv)G2(_FNqIbw*2II z`-U8UNgUfXI9|=qxbe*b`6YgI8G6+}H|ooYo6;|dgDyjF`dKGYza(*t3q!B^=^uM# zv{y0?j?3V9)ldB4cbB}wBo4al?Vok(2X&6M8}&vK4_$^nod2}p^&9i+FK4D-{xz;Y zx(vPQr@cJqF@BPD54sG!>Zgsryf^zRcfOi!m!Vhvw3GKV^k4Gc8(oH8_0NrQ{@Qr9 zSMuHkU4~xu)6dm$uh4(Vdkl0LdehHy3Vuo5#VZw?`zOp-$-W7??Cqa){QPeI`JvpamOKZb z%g`(N_wWDT^ZB0lpaoNWbR=~--hF=V1{z%rL=(4x}((%uYdCGS)jF;p+EV}G{KhyCuPB*X2@sk@K z%JGw-H~YUTa?^i#Rg6FVm!VhvwEGj$2Clzk9|T>7UiCB2E_yNNpCk^t487_n4|Rw9 zlDdN~d-Z49_=x6>*w5_i zlAHPq{ccJ2>hCl^-y4xn634hO^lE0sg=rZ(bey%UysqyR~S%;v@(5rsxAL|V2wRGQ8hF^UTo`)Q&-mjbzr>F&TYloRZo)6OZpr+zw|?qeKm2@WNBbplj5|19 zZ9jDfANeJIbQyZpPkh#G_$A-%q08R-ZCd;9+L-N^#4#=my_%nP;v>Jrk1kt&>LbsM zoG;z?l)dN2Y3*m-Nq$Kj+AVwQ&uM0fnBUO!13{3US)z6pk2 z^&cI%;{E=_{E_(4W$0Bu{U$H-PZ9@R*7N7}<-1whFE1VQx=$Xj>mb%%;uvGrFY@v=smsu-e(n?IE%Qe*kI-dn{xVK}H!O*RE<>;8XPx))ota+} z2VI6<^)pZSPMG>9&yU|@bQyZp&-#z&e8x}u-bjXC^^@nEg<4r%`DKmd0 zaf}N?ulgBhe9T{oA6>Tm#E<=n3BTmKXLK2QH9zMq9?$km;uv>uyz1vZ#Yg)kesmdn z)lYo(J@8Aun?{$t{f|!l9) zMl$rOpZ3xB;eUyPF5_6!&o_^>LlVolF!ZXQd4>;<<=q2*dF+$c<;mmK{PdG+NBbpt(PijOKY1A|NgU(C(5rsFlj0o= z?U%$sm!Vhv?ECTFgmWcv&}Hxa$G;Y2V6?Tre}m5c&ER;o{p?#m5Z4&LBp$j9z3ONEux%{;k~rux z^roNZ^tmyAByo%jL$CU&4_mk7xJ#}Bx(vPQKXKC=-hb2U0 z*T(cq_HFRX(5vmI?y>K{_({eQUH0}LI{9Zs+t)9e{``#2^Yh?%H9yB$XHxql@r*k- zUiDL7{7y^q9T~a|z3QiCU%MgepCk^t487_9*d1BxC2@=kL$CUoXFMlz{Uz5CU4~xu zbDeq4!Y_$~E<>;SxxX)t8iHT)9T~a|z3Qibtn-;al5rUHdxD`?{aoJ8{C>zqqp8c@`m;0t$;8=RE#l{U?cI+`;i-|JlRqH`a)JW5#$%)*$FI z^a+0qD}R4btRIi!?++UF?+=Q0&N+7W)oZUC+-HOHBG1%$gZ9LEtFOJjdtS`vsq~MXoq2rv`1*CT$Ns4~_nsNL=;fjRp})+Y|JiKv`G(8ZFUezJD)i}XX|s>;LuulhR0n*E_BZJ~?am(Wl9jGek7 zeMc8v5B*tZr%ufAow(XaiZ_b*bi(Vf3 zS1*}8{hQhNM9m%3X6T}qhyIO|$@lR2n)uMglAqXos4M2*tMV}Z%z@qS5FhF9df+J&wc{fwRcLL~3_ zMAwUc#!XC-cJPa>@$bohf5bR&JmpI~bScFaUC-k;{A0JxrpL@UE5*I@X6T~pp`SkD zW4{pbp^GIy9zN6+^Y2x87++^Rx#KPX`7NP~u7`f^*!YMe;zJi({=Iqr8TWs@KP>aJ zZ!?dg_IeOiU!=W$)bB9t`H-^!U35Jkf5U%pn0)M&_#r-YvE=8@M&3AkMe>F& zmh!i~n|$0K@k4y*V#&`w%~{KSC+glHx*m@If1Lk~{4q{)&G<#;09|xFjL$gnF>Vnb zy4dp1}J~V)Bb82gxtGp7+1u*ZG;BceH~pw)WqKpFGib z?rI|MJ?NtAVSLsMKJq8xLl;Ya;;`mfD`-$-my4)@QbvAE|%sG4tz_enkA}qU)ibc_we|`x82Otja?_amZW# z{{!-dE|&6V{*Y^aD!E-B&D2-cJ$=^tM`!-3^3c!x;^V$6YTiZHLqGG(!~Bc% z8(nlg^mAwCVf~8u&_&mC|FL}j@bHj3@eQ9t9?`$v^Lv;0|F!@AH}U`LG5&wez2TK# zt-raqIGlb!J#WwJU6`LQ)Z@<7y`I{ec|bkC<9mA_e$r~s*Js^7Z;SuWdc66=H!hrCy0FskFZC`h^;T`XZC2dYvb|PJwalzD zJ?4LXd*JuP7p|L~c+yN%+&RA4{`L3N{bZ-};N!t;%l&=1f5&OFXD*w;voD+7^>;IFx&NWMa7+=zwwIMeZQK)y57UwL;v>e$%pvcE>^@ZkB2^O zwBzTy;?B_T9Zf#OJ^V>U{PK9{Q@4BGPxYfc^%E6$hCX#;jF7QYKT&aK=#zi;WXjLn zCBLY+GxQlBc_4Wizo>Xqe%dVh5(}AkxT50DFhBjL9mJ#mqT)?HwWb}!;~I*JH~HkH z_K@0>UsT+g_kVvrf0(OJpG$N1c|XtHXU#;#ouS`eNDkcpt=W;S6**UVJoGnzYPRz$ zGe~>RAu8?+ea?>ySwqM#D(=kvPCkCx9RDMoaNL26kZ4}I!`r#dnY`T-Sh%FkS(=9)9)We!2bone0Z$MuG^mj@Mh zhCcnKoyNgA=r>fn$>+M$4syM?exl+{e&@rK4^p>$ryu3TzAI_W$(+7)*;`ivEy zy0eapiaQ&9#)(gR)eb6N8~?$4{*mkGV#@j8XQ_^&;?6w(kUx3dtUGB24=ty67*TO& z=+kG~K|I!RQSm09Hrny>UGXNLcP+hpF=wcmsJJuiKkGH^ARakI#cO^qufO@mdp;ZQ z|Ge{xir3!%Z}OjbZ=l=hPVz;?oq7L<{CxeQJ@Z)P9x9KAKJU1CPp^M}C|-MiAIeXS zXb0=x4~jSWqS#UsT)~`rP+ggXlNkoTB2+&}WR=@$y~q zrt!00(GKGB&L=9~Ox-^7Q_LzBE{XW%@zCda z%eOdW4PyNf6?caI|M)#%sD6x_8bfN&_(jE?VSdI(JBY{lMa66W;r#x~=G@>th`Gr7 z5M(Ql=lO^HY|aln)&hLURvr(1t`Tbp#A7`c6?caI%+=IKsON}C-^=5n&pk>zt*81f zfQmaqpLLWC(r?yNQE_MJ^Ulu(@pvAHiaQ6sr(pf?`rmpz^fij#27JwVrM@194&M=S zYHM5Q@XlX4t7~=m#*xz18Y%(}75JQ4WiI_B|AqE*495i8I zU@(z^fkX!e2Zjy~9gJaQaByH?U~q77ATEAfpWl7nzwfzkJ+FgJZhp7_bNx)xw z|M2y%ubkODardit&)H;OO^nv|7|j8**6xPAX|17#=bRfRbMg1$Pw@r5^mBX{{lDgj ze+vIh>2J4xyKDCRA7)FdC13kKbkWOG|8%!M>MpH{#8F(>`JVdcOTXEX}Pvp^ILg@#BfQqg!IcA!d9!de%SjFzV5M>cjmTX6RyF z{)vZ?_sDTE;wWxWp5~t`$1gn7O|!k@W+HRJxQMRT`dKs0Z_UK%rs4)&&-l%DZHABh z_|*<{+EbKg{frUy7&no%h%V;aAN9yP^(gW~;wUbxYd`A`Klw%c=wjX<<3kR{Pn>!b zy6Aeg|K!1^bpz=Gx>)hgmh*3R^oH5;Ewh=$lB=gf7ri{qpZMGDKff`Xy%76HTzC?? z=z6W6+>P_m1~_{`af4o-@tX||hmZYB97sFR#X3LxgnD?zg(tE9MAx(V@#8&oy(DoI zw=e&@zC|qMb|U_$Wyej<5yqEPoH4kA9>iL!&hRj!oB06 zi(a11ziTt<4qp)?4l(1?(X;-^si;T0sSi0r(8ap^lT(qGy~bK*&k#p(i}E!8V!D5h z-8WnLF7~>3YRn8>bUo`Id}=mw+icJ4C7=7n3|;i{tpDKI@EyKa5+Ayl_qW@B{TR7> z=1Pv-4qf!NW%JWd+Rj-g(jRoO&Oi86Z4k|93;hpv^lbivXTx{+o)|v*kH09-_`}0K zqpmprAav37j6eE}kG_iY4?-8~{0E+ekM`n+_|U~VKjVy#@fY!-i+O+alU(#))R>B{ zXZueceB>AD1G-r8FQoftU?sfFH!&d3ZFJG~H2*gL_#LyIH_b%iC@yq8>u2Ba+G&-&>zAI4hb?BcuV-?M(khx-G5 z5pOYW9aioSUHzvXZ6}vV9K|ilYx8sOW&T9sC@!qrf4lN?#`Qgp{)(L6=%VY{{ER($ znLm;7M;G(?Sv+^dzQ>`9uBZ7=r0ailEADDMtGKg4@}i5bXZ<|8)466I*oWw1 zW&XSJlP{es=8m~Q7ri{qf3n(so_o|6dG67EvGV*&{Bi!!Z_Xd_=#9|DO8*mooHO{? z^CIKM`6Jf(2Ua52&YNPig)yN`MR~UW<9EV$;F%ac<^+FHp8A){@r!k`{r(;L>gj*V zYyI4L();uBE%}08p7FHYcG{m?}(&-f!x_57wCY8UkKT0i+|zev2o*I`|L_BeZs?!`i^pB<7la7=}OE+e^_amRf;gMHH1ED?gpEKcX@ZZ8; zd^LZ`g>c|&`{QrX|5x=F)qOrE52|0$w^#kUtA5W5W}kQm^B0!i%NbcgFsbClAGVMBkqD zsgr)FU)<&UkX-aU={LOg8)us>URLs+-+aP67kzuxzpGk*?}XXm&1Um{Df!h!Gjh?l zC;dD2njJqF{fq23a?$go-|chv_D5#7oG5uHkGhL~zP;Lio6m8M&pe2Dek&8KhU|x80UoVMAF6Mmdd}loB7vJrR`bE#P_2W^uh)4Zm z&Zka1>KF0I#hlN&@#t`@cj99QV?7Z)Pu9=6%W<}-QSwAjtjD5nPx{Q?i+=2||HU1b zWBx?XlRoo=$NY(SJ&gVL@tYvo1!IDFxas3c| zd$Rr+hr(kWq#cMyF6R6>e}u<+hY#_{#hlM|3yto~hWPu9;kId>Sp$eK!?m544 zpY>8a#};=F{h=gVC2rJLID0NxyTS*`Z&<7iouF^gQdY?2G3mk#^KB^gQWL z?=k!E&$#avKi+6YE_$Bzd2Zu*RiquY3v17BZS%)GZ#*CO`y$V+xT1K`wfp^+yKHu3v2?(vI4No@f2FK3}bi zW+Lqr-XuLw`pgsFf^#LA2XZmz)6acBM*Sk~k&B)u`{%hIkN!nGaxv#~d=HOD|03r> zaokVR^JM?b8_$l+zeqdeqUTAU=Qcd*6?yMKF6MmtVeP~hX-9Px+pGOAt*&3JGvE5L z$66;_rc9^zKgt1A{RZ+`l~O6FRoc1zUX<< zpTE!ykKn6up z??g$CUvjZ_{I>b*cYLm&A|APz^LbCk8qNC}k-o`A&#U8KUe4c@D}SGg>m2usvS#qU5Yi60=y|e#?(;ZKS!YDOcN9HO`rPO7 z{*r!0JaV!2{<3ZUIZnCGvJQ!O??@g&+9NQc9i?#Qs z|EV93`bFwcT`=d<{}UJE`Cp_R)m3cI*1u^>-0zCCqjsU^NuT|%`wo%gK*vR~J?S%U z)_v}`Md~0IYwLg8{BfVaI?eT0)O~~Kd9r`jE$$oeMcN@3YxfUr{r`{qk2YWLxfuuV zt93u5x{B?|`l%a_YrnW^ZH!0sJn7Ru#~9aJk#>mSdVT)#xFU%D<9+mrosp07U@ z^DXjy61nJk(r28^bN%=yXFSFBq|Z39c?MVgHG&ndGA9NuT=oVgHHL zp>Y-4lRowF!~Ww3;%i*R_DR1L-+%l1Gn4PXo3p0y?;QSZ-PE=AuOs{%x0b#a_xrA9 ze{G{yU>DidH48!zA_*}9k^l)ICV<%u*@OTgE3vSk zpwMJX3ll9UOti3|prD|5g)x>C6cm&e78Dj177{!^&i%OaE}7va@OykS-^@94XU<%n zb*yDWHnyZ?*KL`#t!tZY=K1$2+h^TYXW`oXxr-MT=4{Q-@PR|$&V2g&&wuYde0TS) zAI_e#vEhQZQ+wMZW}Ou+`^Y*gTV^(~YRLbtKJPq?FYxqYd>8#+?bZIL^6#wuPoF;d z#ccYX5B5#X(~F^t-k$n*H2utmU!1{#~`-?3KG_pFA*IyP@XE>Ci=Q&-z#2Vtou7XDeha@yJm{k9SwHc=_Bi4fi3449J@t>L^RHZGc67q5 z*ROfvkr}$^?OA{Ow%LI(v#mF39{JiA+;!30i~cu%3ctAJRQN^Lvwq@ScR1n~U;iiK z7hO;NlWG31?l(K;YrXornxA>>=%Tl0{lkyUHr+QHnXdWvb~AL*+p~V=!O#36K6J6< z-|%Dj$Q3`thc1@dHKoKepCj&@DXBf8kAKLh^di)J5w zZ`S>@CgY)t-kzPGejof5@rsP6ajW*CpIDh+WE_nPUC;WdSyOxB42#5#F1nueGbeSE z+9BdY7aR3+VEuaixI1`u+#!%S&_&m?^Ajg?QF}zjK^I-m`tdLq@r&FW=%VXIKQ)m3 zDl(47g|27)%(3iz>_3rpLl<4o`l%U9N5U^M4!Y=i(a&AM{UI`r#)Yn@{@v;M;hvjW z6S<3fFU9>Qx}Np(oOa!b=O<2f${6=#Py(^`&BO{?0oex4gOl=>rbm!ONT zr~dcS{Kq!My~RA-V~~3bU2NQ61O8q=){ple)(^67=wf622K>xN?IM41{PT!IbUhnC z`;#-r{uim6=%VYXe=5zNJx`s)FY3KTbUo`Ix*6{+>{Z@lAnz^cV&nbgh57NZULtWQ zE?DxDGd`Y|$h_!c$VXMPbsy6Ae=Pn^t)Ut}C~ z(eh){lM;E<4>(`lO|1v+shc3FF^|L?mk-vx!T`c*D zlRZa&k$jX_)t;T-{6n9elQnyN)L0Yf?L|NL7JiXu!AES|U+<^&i&#~+MCum0*r;Cv ze(o5ZJCXB;F1nt^|AJrpOl05U7hNy<$(6Mi83(`Ude+Z=(Q^~Y9bI(&nZFyqKY0CE z$L|ka{r=$3r!(4_yIk(&PhmN|&V6y=+CWcVk9xdb-)zZ*jf{4#e7R7?UCletk9*Jm kkKz3;UY;%VqYfOuNx$o}rGC7J>^Vpt^Hm;8ebl!74|A~u>Hq)$ literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/gds_lib/write_driver.gds b/technology/scn3me_subm/gds_lib/write_driver.gds new file mode 100644 index 0000000000000000000000000000000000000000..fdd3ad883b0f7ba91571eb508c5a78e27876802e GIT binary patch literal 11804 zcmai)Z>*PP8OJXVha=d@@I(TR%qIEw6lg3dU0GStq+-R2i0qVy3Fg>|;mHQpXYns z*L~mD{XF;cJii!=k(d)p&l!o?m>;7t9+$@X|NHw|X$wZiKEG|t_D!Ff-nM0S)3#VR zXYSkI`IYN#e)0#W-+I%b<@>+0VO=bp+whNd{iE|D#$GuR?})MUM@89Jo z^AC9HQ2uS||BYUt|9bwb`u>+*dT~d@?8bUimYh5G*Z@${R-LpP(mGHcKwZRN^klA!J%#B0|?n8b5jD81>YcFxOzEYc_|ysQo5VpkrI&u@_lx6M zKPL5vZb~oxuDdtv%=&}3U6S$4q5A8Lzv~Vk_2)R~)M4*<**^7g)rzb?^SXsO|EBb& zpE_~fK;k$q)bT<8)r0jj`f$V_?}%8cKAV5tp$oQjQ+nyY;QokTsPBxU`Q&&6x+%T% zpT8jDr>cMaCUMYB=}rG5%ALA5iQ~9Xdg-U12jr#y=0h{te^YwX{|${7e)HRkNnBHU z=_kM4t22L-IOwMI(m(f^h%Zg&^~bztUj(`-z3Hb;xqg|O^*4TVsQx?k!+BF$yO&1UsTkM(BaLpNLg#otXIHOXPkiWR%fIAU`nZ3P2gHYNw*1^@-t+U!*IYf3_a9SwnLqa#eB^85LpNLgMKkFm zU;Gdsy4mtyay;UFJM#WvzW+o7x+%TPpZ>GwV!lkCfzeIrrJp+a$(pPmll?EcDZTWw ze!h8ot{?MTPvrVBrI&u%!N>YB@u8b7KkEb^>&L{0Znpf4+s+SX{hN3HD96*3Ugl5T z;G_OceCTG&Prcxy?oE8?X3NjM@zc6q@C;?%s=lL}(#!m*ljXD7U-OzjWc`@ZOF!!b zAN@7)p_?r~>jWSDHSwXFEkEl7ANwy8AG$f@f79UpUXf z^ZsP~xqN>DiQ~9%=>18@|LRi_zq?QOKh2@Zdlz(5df7hxJo!}SZ_+-xDZS}Gu{5t8 zCUG1WN-zDapWm*^{7w3SZc1i1Wp={JdkZb~oxTxWRC#QP8P z$cnuFn9@r>^ZWI+IsYc_5ztNPrJwf)Joi&KCUMZsq38dX)eq-UKPK%`Kc@7uea@p@ z=Gi0;y4h-vIP3fhd``*mX^qa&%H>H>U z3FWs%Z7rJVlYXF^I$rvjr;YdLdNG+t&ui~^>8CzEvNHD%CUxYx>K!lrtQ&l+W0O44 zP3fhdI^jI}Z!#X}ru3$NgWBePYZAwCq4d(vJkekLCUMYB>7{?!y6iXCFZ%E67&_Op z-tp4UIIVpqeI{`{uD#<;{|9&F_?yIWTqwQt&!37|GnsyqIOwMIrk`sUb!HOBaiR3m zKcPCm;dIWI$$M{fQ+nxV--eI%YT`pTTYlPk+rIRh#BpA|<7NB2Z=o&5*<>8hP3fhd z`0U-NQ9exespu_{cY#|#lD}pIwO`#1Kze_ow+ zZvJI|?uSk3rJv^)?(>Y7$@>s=Q+nyApP$p(qyOgi(d@q|z3Kn>g7ll8Q2&W*N-zD~ zch^nje#!i(#uMF?Uiw)dy!&MAO|C`gru5QJoltw!kIA(d-IPA)zjko`@cgs4{>|rh zWh_&A>E}7`ZwK;vY5pVf`OlPI`Wfd(HFwOP$#+9^Q+nxVpTv6?>euAG3%WV<{-x7@ z#(2~7S+6GVozYF{W&7N>xZd&nWOCg^H;1mDo%T78_XhaQ%TK1?lwP*aJhOI~f0Mm0 zx+#6of6d_hv(A_&*1E}a7rH6E>E}BQ^=cBwaiR3m&pP3|4}R0%eaxZnKb`#9x8kF} zCO&kt(#`M zZVtUa>$J~2^ScA)-+V|Kx;gawgN~o~9{8AllX^fmTYlQn?@P}3P2xDO-tn^kj33V_ zjGxJOKXg-i=_fvQL;p?ka9+LRrJr_oug>#L@^D_gEfIGdpwrn8a~hD82MEZrmrSca!HfbW?iiXP)Rc^JfwV-8@_W@zK7C zkG##6-_L(Mr}6v;d45DUho1jB^}}~op4Yhdn#4gjrI-EZ{>OJ_{3dbGP3fhdcKF>H ze$(HrP3fhd{U6`0+3%b9(9NOm*PZ^e@50A;nIBT_=w{1L{;O`x_D%ZXe)W!*`E#7# zpU{7E<>Bu4^P%6Lbn>U4llNx(CV8Nn(#!VgC+*UIllIZgR{PwyXqUP(sT*{&)js{l zOZz5ycwBnN%ltLfXRiG`J8}}mLCN-zD?4eyBQuj%JTQ~IF)&4c?-o_oCSG*3xG zH;4A09si=4{=UuoH+<;k(EhFCXWYDRFuiXuhxQL0|HP61fB!?@`$FEAcXywEJAR&f zrjOYepG;%S$t^Jb@8@pzKkv;XYpaff~E!EU?fD$mjQ EFZKmEzW@LL literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/mag_lib/.magicrc b/technology/scn3me_subm/mag_lib/.magicrc new file mode 100644 index 00000000..f52d0592 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/.magicrc @@ -0,0 +1,5 @@ +path sys +$::env(OPENRAM_TECH)/scn3me_subm/tech +tech load SCN3ME_SUBM.30 -noprompt +scalegrid 1 4 +set GND gnd +set VDD vdd diff --git a/technology/scn3me_subm/mag_lib/cell_1rw_1r.gds b/technology/scn3me_subm/mag_lib/cell_1rw_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..2d12b8eea9b4107adacb23f749aeeec1f17ef784 GIT binary patch literal 6330 zcmbW5J&aXF7=~Z==dyuySr8Bm3jPZ$unTJdC4x%)i5Q7)lo%6@uF+y+3^A;Qg@uJC z78VvJT3DFaSWsAOVL@Sxg@uKMg@px$g$0F$g@xb4oHu9g#czn73mYDOEhTeoXflbX^dZPPlwTh5gDX6Utlt{y+06IV)n^U<@VEi?4gPoA6ulQz-K&};wx zIzD}T`l58(-#wRJme9>8PyILkAwB$~wBz%hkNhQ}n^B(niG!c`CO&kt<-hyu;@kgX zPkiWR%TGU9yZBA|;c<24Y5zBTRAMcD+mp7?&FD+&r+vmwU6a0}o1v$E;!v0PCUcK& zhMxM#Gj)k=ZaPu&Z-!p`=j-)z>pRlfU!^@i^?Y_wLN}v4^>190?)gQUneDl6UP3pc zJoRteQG7SO)e|4O+42*c4|UD@cUPXqUpQ8LM?UU}AKi>LQa^dR>%EdclbGmc=&7GP zF;?Yw|d1XUbFHG`|&kVikXWYazX$QYKGX6vL z{YQ*rr%Jxe`#&wQ&Cu)kL;mT@()_fDj{kq`|3mp>oaCDEo6G^a8G0I@apGg#CO&j?#J^ClKgGrS4`+Xq z_Z}{D?aG^e`c8b4cHAxu zJ@s?XvrpnR=|8#|dg|vLjlB!MNjvCfYyR=@p{~ig;kOyT)A;n0*!2f5x*27uf9zbD zYxWD~9MTrL8G7m`zxY_cCcZB3SK0FW{KovTXF~RZ#`$gN{^6aMSoGVZFX(3IY5%!T z@N)l{^dH>}J@qqYKGZeq-(7j?XWyj`{~ek5(aq3PKl4o9M$cd9fdsy^p$l_pS}LknZK?)^)tWtI4_%?cQf?V&pdN6|0exLH$zYT zoVmGJza~C(GxXYjvYtOYT+F}uOgH~#=vV#GCI0`8`+qzCe^2xOH|LHge%92^!RpHV zb?QZXQSZX?a-$w+u8E7Ky@l)4i+6-*@AWrF+Kcts_b=Mw|J|tf%4q+F>hZqedLwa% X>hW&S)jQv+$GeZ~IWOyDJQMl{QEIs5 literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/mag_lib/cell_1rw_1r.mag b/technology/scn3me_subm/mag_lib/cell_1rw_1r.mag new file mode 100644 index 00000000..9aec1c5d --- /dev/null +++ b/technology/scn3me_subm/mag_lib/cell_1rw_1r.mag @@ -0,0 +1,142 @@ +magic +tech scmos +timestamp 1542220294 +<< 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 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 +rect 0 61 54 65 +rect 10 44 14 61 +rect 17 51 20 54 +rect 17 47 27 51 +rect 17 37 20 47 +rect 34 44 37 54 +rect 27 40 37 44 +rect 40 44 44 61 +rect 34 37 37 40 +rect 6 33 9 37 +rect 45 33 48 37 +rect 25 23 29 29 +rect 25 13 29 17 +rect 0 9 25 13 +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 +rect 9 21 13 72 +rect 25 58 29 68 +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 48 0 52 33 +<< comment >> +rect 0 0 54 70 +<< labels >> +rlabel metal1 19 63 19 63 1 wl0 +rlabel metal1 19 70 19 70 5 vdd +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +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 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/cell_6t.mag b/technology/scn3me_subm/mag_lib/cell_6t.mag new file mode 100644 index 00000000..f2e9906a --- /dev/null +++ b/technology/scn3me_subm/mag_lib/cell_6t.mag @@ -0,0 +1,117 @@ +magic +tech scmos +timestamp 1536091415 +<< nwell >> +rect -8 29 42 51 +<< pwell >> +rect -8 -8 42 29 +<< ntransistor >> +rect 7 10 9 18 +rect 29 10 31 18 +rect 10 3 14 5 +rect 24 3 28 5 +<< ptransistor >> +rect 7 37 11 40 +rect 27 37 31 40 +<< ndiffusion >> +rect -2 16 7 18 +rect 2 12 7 16 +rect -2 10 7 12 +rect 9 14 10 18 +rect 9 10 14 14 +rect 28 14 29 18 +rect 24 10 29 14 +rect 31 16 36 18 +rect 31 12 32 16 +rect 31 10 36 12 +rect 10 5 14 10 +rect 24 5 28 10 +rect 10 2 14 3 +rect 24 2 28 3 +<< pdiffusion >> +rect 2 37 7 40 +rect 11 37 12 40 +rect 26 37 27 40 +rect 31 37 32 40 +<< ndcontact >> +rect -2 12 2 16 +rect 10 14 14 18 +rect 24 14 28 18 +rect 32 12 36 16 +rect 10 -2 14 2 +rect 24 -2 28 2 +<< pdcontact >> +rect -2 36 2 40 +rect 12 36 16 40 +rect 22 36 26 40 +rect 32 36 36 40 +<< psubstratepcontact >> +rect -2 22 2 26 +rect 32 22 36 26 +<< nsubstratencontact >> +rect 32 44 36 48 +<< polysilicon >> +rect 7 40 11 42 +rect 27 40 31 42 +rect 7 35 11 37 +rect 7 21 9 35 +rect 27 34 31 37 +rect 15 33 31 34 +rect 19 32 31 33 +rect 7 20 21 21 +rect 7 19 24 20 +rect 7 18 9 19 +rect 29 18 31 32 +rect 7 8 9 10 +rect 17 5 21 6 +rect 29 8 31 10 +rect -2 3 10 5 +rect 14 3 24 5 +rect 28 3 36 5 +<< polycontact >> +rect 15 29 19 33 +rect 21 20 25 24 +rect 17 6 21 10 +<< metal1 >> +rect -2 44 15 48 +rect 19 44 32 48 +rect -2 40 2 44 +rect 32 40 36 44 +rect 11 36 12 40 +rect 26 36 27 40 +rect -2 26 2 29 +rect -2 16 2 22 +rect 11 18 15 36 +rect 23 24 27 36 +rect 25 20 27 24 +rect 14 14 15 18 +rect 23 18 27 20 +rect 32 26 36 29 +rect 23 14 24 18 +rect 32 16 36 22 +rect -2 6 17 9 +rect 21 6 36 9 +rect -2 5 36 6 +<< m2contact >> +rect 15 44 19 48 +rect -2 29 2 33 +rect 32 29 36 33 +rect 6 -2 10 2 +rect 20 -2 24 2 +<< metal2 >> +rect -2 33 2 48 +rect -2 -2 2 29 +rect 6 2 10 48 +rect 24 -2 28 48 +rect 32 33 36 48 +rect 32 -2 36 29 +<< bb >> +rect 0 0 34 46 +<< labels >> +rlabel metal2 0 0 0 0 1 gnd +rlabel metal2 34 0 34 0 1 gnd +rlabel m2contact 17 46 17 46 5 vdd +rlabel metal2 8 43 8 43 1 bl +rlabel metal2 26 43 26 43 1 br +rlabel metal1 4 7 4 7 1 wl +<< end >> diff --git a/technology/scn3me_subm/mag_lib/convertall.sh b/technology/scn3me_subm/mag_lib/convertall.sh new file mode 100755 index 00000000..f5e2482c --- /dev/null +++ b/technology/scn3me_subm/mag_lib/convertall.sh @@ -0,0 +1,14 @@ +magic -dnull -noconsole << EOF +load dff +gds write dff.gds +load cell_6t +gds write cell_6t.gds +load replica_cell_6t +gds write replica_cell_6t.gds +load sense_amp +gds write sense_amp.gds +load tri_gate +gds write tri_gate.gds +load write_driver +gds write write_driver.gds +EOF diff --git a/technology/scn3me_subm/mag_lib/dff.mag b/technology/scn3me_subm/mag_lib/dff.mag new file mode 100644 index 00000000..46d22c84 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/dff.mag @@ -0,0 +1,279 @@ +magic +tech scmos +timestamp 1536089597 +<< nwell >> +rect 0 48 109 103 +<< pwell >> +rect 0 -3 109 48 +<< ntransistor >> +rect 11 6 13 26 +rect 19 6 21 16 +rect 24 6 26 16 +rect 33 6 35 16 +rect 38 6 40 16 +rect 47 6 49 16 +rect 63 6 65 16 +rect 68 6 70 16 +rect 78 6 80 16 +rect 83 6 85 16 +rect 91 6 93 26 +<< ptransistor >> +rect 11 54 13 94 +rect 19 74 21 94 +rect 25 74 27 94 +rect 33 74 35 94 +rect 39 74 41 94 +rect 47 74 49 94 +rect 63 74 65 94 +rect 68 74 70 94 +rect 78 84 80 94 +rect 83 84 85 94 +rect 91 54 93 94 +<< ndiffusion >> +rect 6 25 11 26 +rect 10 6 11 25 +rect 13 25 18 26 +rect 13 6 14 25 +rect 86 25 91 26 +rect 18 6 19 16 +rect 21 6 24 16 +rect 26 15 33 16 +rect 26 6 28 15 +rect 32 6 33 15 +rect 35 6 38 16 +rect 40 15 47 16 +rect 40 6 41 15 +rect 45 6 47 15 +rect 49 15 54 16 +rect 49 6 50 15 +rect 58 15 63 16 +rect 62 6 63 15 +rect 65 6 68 16 +rect 70 15 78 16 +rect 70 6 72 15 +rect 76 6 78 15 +rect 80 6 83 16 +rect 85 6 86 16 +rect 90 6 91 25 +rect 93 25 98 26 +rect 93 6 94 25 +<< pdiffusion >> +rect 6 93 11 94 +rect 10 54 11 93 +rect 13 55 14 94 +rect 18 74 19 94 +rect 21 74 25 94 +rect 27 93 33 94 +rect 27 74 28 93 +rect 32 74 33 93 +rect 35 74 39 94 +rect 41 93 47 94 +rect 41 74 42 93 +rect 46 74 47 93 +rect 49 93 54 94 +rect 49 74 50 93 +rect 58 93 63 94 +rect 62 74 63 93 +rect 65 74 68 94 +rect 70 93 78 94 +rect 70 74 72 93 +rect 76 84 78 93 +rect 80 84 83 94 +rect 85 93 91 94 +rect 85 84 86 93 +rect 76 74 77 84 +rect 13 54 18 55 +rect 90 54 91 93 +rect 93 93 98 94 +rect 93 54 94 93 +<< ndcontact >> +rect 6 6 10 25 +rect 14 6 18 25 +rect 28 6 32 15 +rect 41 6 45 15 +rect 50 6 54 15 +rect 58 6 62 15 +rect 72 6 76 15 +rect 86 6 90 25 +rect 94 6 98 25 +<< pdcontact >> +rect 6 54 10 93 +rect 14 55 18 94 +rect 28 74 32 93 +rect 42 74 46 93 +rect 50 74 54 93 +rect 58 74 62 93 +rect 72 74 76 93 +rect 86 54 90 93 +rect 94 54 98 93 +<< psubstratepcontact >> +rect 102 6 106 10 +<< nsubstratencontact >> +rect 102 89 106 93 +<< polysilicon >> +rect 11 94 13 96 +rect 19 94 21 96 +rect 25 94 27 96 +rect 33 94 35 96 +rect 39 94 41 96 +rect 47 94 49 96 +rect 63 94 65 96 +rect 68 94 70 96 +rect 78 94 80 96 +rect 83 94 85 96 +rect 91 94 93 96 +rect 11 37 13 54 +rect 19 46 21 74 +rect 11 26 13 33 +rect 19 16 21 42 +rect 25 38 27 74 +rect 33 54 35 74 +rect 33 29 35 50 +rect 24 27 35 29 +rect 39 71 41 74 +rect 24 16 26 27 +rect 39 23 41 67 +rect 47 61 49 74 +rect 63 73 65 74 +rect 54 71 65 73 +rect 34 19 35 23 +rect 33 16 35 19 +rect 38 19 39 23 +rect 38 16 40 19 +rect 47 16 49 57 +rect 53 19 55 67 +rect 68 63 70 74 +rect 78 67 80 84 +rect 76 65 80 67 +rect 63 61 70 63 +rect 61 24 63 33 +rect 68 31 70 61 +rect 83 53 85 84 +rect 79 51 85 53 +rect 78 31 80 47 +rect 91 45 93 54 +rect 89 41 93 45 +rect 68 29 75 31 +rect 61 22 70 24 +rect 53 17 65 19 +rect 63 16 65 17 +rect 68 16 70 22 +rect 73 19 75 29 +rect 78 27 79 31 +rect 73 17 80 19 +rect 78 16 80 17 +rect 83 16 85 31 +rect 91 26 93 41 +rect 11 4 13 6 +rect 19 4 21 6 +rect 24 4 26 6 +rect 33 4 35 6 +rect 38 4 40 6 +rect 47 4 49 6 +rect 63 4 65 6 +rect 68 4 70 6 +rect 78 4 80 6 +rect 83 4 85 6 +rect 91 4 93 6 +<< polycontact >> +rect 17 42 21 46 +rect 10 33 14 37 +rect 31 50 35 54 +rect 25 34 29 38 +rect 39 67 43 71 +rect 45 57 49 61 +rect 30 19 34 23 +rect 39 19 43 23 +rect 53 67 57 71 +rect 59 59 63 63 +rect 74 61 78 65 +rect 59 33 63 37 +rect 77 47 81 51 +rect 85 41 89 45 +rect 79 27 83 31 +<< metal1 >> +rect 0 97 109 103 +rect 14 94 18 97 +rect 6 93 10 94 +rect 28 93 32 94 +rect 22 74 28 77 +rect 42 93 46 97 +rect 50 93 54 94 +rect 58 93 62 97 +rect 71 93 77 94 +rect 71 74 72 93 +rect 76 74 77 93 +rect 86 93 90 97 +rect 50 71 53 74 +rect 43 68 53 71 +rect 26 57 45 60 +rect 52 60 59 63 +rect 52 54 55 60 +rect 71 56 74 65 +rect 10 50 31 52 +rect 35 51 55 54 +rect 62 53 74 56 +rect 94 93 98 94 +rect 102 93 106 97 +rect 6 49 34 50 +rect 21 43 38 46 +rect 18 34 25 37 +rect 62 37 65 53 +rect 94 51 98 54 +rect 81 48 94 51 +rect 74 41 85 44 +rect 29 34 59 37 +rect 6 25 10 26 +rect 14 25 18 26 +rect 31 23 34 34 +rect 63 34 65 37 +rect 94 31 98 47 +rect 83 28 98 31 +rect 94 25 98 28 +rect 43 19 53 22 +rect 50 16 53 19 +rect 22 15 32 16 +rect 22 13 28 15 +rect 41 15 46 16 +rect 45 6 46 15 +rect 50 15 54 16 +rect 58 15 62 16 +rect 70 15 77 16 +rect 70 13 72 15 +rect 71 6 72 13 +rect 76 6 77 15 +rect 14 3 18 6 +rect 41 3 46 6 +rect 58 3 62 6 +rect 86 3 90 6 +rect 102 3 106 6 +rect 0 -3 109 3 +<< m2contact >> +rect 22 70 26 74 +rect 70 70 74 74 +rect 22 57 26 61 +rect 6 50 10 54 +rect 38 43 42 47 +rect 14 33 18 37 +rect 94 47 98 51 +rect 70 40 74 44 +rect 6 26 10 30 +rect 22 16 26 20 +rect 70 16 74 20 +<< metal2 >> +rect 22 61 26 70 +rect 6 30 10 50 +rect 22 20 26 57 +rect 70 44 74 70 +rect 70 20 74 40 +<< bb >> +rect 0 0 109 100 +<< labels >> +rlabel m2contact 15 34 15 34 4 clk +rlabel m2contact 40 45 40 45 4 D +rlabel m2contact 96 49 96 49 4 Q +rlabel metal1 32 98 32 98 4 vdd +rlabel metal1 44 1 44 1 4 gnd +<< properties >> +string path 0.000 0.000 900.000 0.000 900.000 900.000 0.000 900.000 0.000 0.000 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/ms_flop.mag b/technology/scn3me_subm/mag_lib/ms_flop.mag new file mode 100644 index 00000000..713d264f --- /dev/null +++ b/technology/scn3me_subm/mag_lib/ms_flop.mag @@ -0,0 +1,294 @@ +magic +tech scmos +timestamp 1536089622 +<< nwell >> +rect -2 0 18 200 +<< pwell >> +rect 18 0 40 200 +<< ntransistor >> +rect 24 178 27 180 +rect 24 162 27 164 +rect 24 138 27 140 +rect 24 130 27 132 +rect 24 112 27 114 +rect 24 93 27 95 +rect 24 77 27 79 +rect 24 50 27 52 +rect 24 42 27 44 +rect 24 24 27 26 +<< ptransistor >> +rect 6 178 12 180 +rect 6 162 12 164 +rect 6 138 12 140 +rect 6 130 12 132 +rect 6 112 12 114 +rect 6 93 12 95 +rect 6 77 12 79 +rect 6 50 12 52 +rect 6 42 12 44 +rect 6 24 12 26 +<< ndiffusion >> +rect 24 180 27 181 +rect 24 177 27 178 +rect 24 164 27 165 +rect 24 161 27 162 +rect 28 157 32 161 +rect 24 140 27 141 +rect 24 137 27 138 +rect 24 132 27 133 +rect 24 129 27 130 +rect 24 114 27 115 +rect 24 111 27 112 +rect 24 95 27 96 +rect 24 92 27 93 +rect 24 79 27 80 +rect 24 76 27 77 +rect 28 72 32 76 +rect 24 52 27 53 +rect 24 49 27 50 +rect 24 44 27 45 +rect 24 41 27 42 +rect 24 26 27 27 +rect 24 23 27 24 +<< pdiffusion >> +rect 6 180 12 181 +rect 6 177 12 178 +rect 6 164 12 165 +rect 6 161 12 162 +rect 6 140 12 141 +rect 6 137 12 138 +rect 6 132 12 133 +rect 6 129 12 130 +rect 6 114 12 115 +rect 6 111 12 112 +rect 6 95 12 96 +rect 6 92 12 93 +rect 6 79 12 80 +rect 6 76 12 77 +rect 6 52 12 53 +rect 6 49 12 50 +rect 6 44 12 45 +rect 6 41 12 42 +rect 6 26 12 27 +rect 6 23 12 24 +rect 8 18 12 19 +<< ndcontact >> +rect 24 181 28 185 +rect 24 173 28 177 +rect 24 165 28 169 +rect 24 157 28 161 +rect 24 141 28 145 +rect 24 133 28 137 +rect 24 125 28 129 +rect 24 115 28 119 +rect 24 107 28 111 +rect 24 96 28 100 +rect 24 88 28 92 +rect 24 80 28 84 +rect 24 72 28 76 +rect 24 53 28 57 +rect 24 45 28 49 +rect 24 37 28 41 +rect 24 27 28 31 +rect 24 19 28 23 +<< pdcontact >> +rect 6 181 12 185 +rect 6 173 12 177 +rect 6 165 12 169 +rect 6 157 12 161 +rect 6 141 12 145 +rect 6 133 12 137 +rect 6 125 12 129 +rect 6 115 12 119 +rect 6 107 12 111 +rect 6 96 12 100 +rect 6 88 12 92 +rect 6 80 12 84 +rect 6 72 12 76 +rect 6 53 12 57 +rect 6 45 12 49 +rect 6 37 12 41 +rect 6 27 12 31 +rect 6 19 12 23 +<< psubstratepcontact >> +rect 32 157 36 161 +rect 32 72 36 76 +<< nsubstratencontact >> +rect 8 14 12 18 +<< polysilicon >> +rect 4 178 6 180 +rect 12 178 24 180 +rect 27 178 29 180 +rect 17 173 19 178 +rect 4 162 6 164 +rect 12 163 24 164 +rect 12 162 17 163 +rect 21 162 24 163 +rect 27 162 29 164 +rect 3 148 13 150 +rect 3 140 5 148 +rect 3 138 6 140 +rect 12 138 14 140 +rect 17 138 24 140 +rect 27 138 29 140 +rect 17 132 19 138 +rect 3 130 6 132 +rect 12 130 19 132 +rect 22 130 24 132 +rect 27 130 31 132 +rect 3 114 5 130 +rect 29 122 31 130 +rect 20 120 31 122 +rect 3 112 6 114 +rect 12 112 24 114 +rect 27 112 29 114 +rect 4 93 6 95 +rect 12 93 24 95 +rect 27 93 29 95 +rect 19 89 21 93 +rect 4 77 6 79 +rect 12 78 24 79 +rect 12 77 17 78 +rect 21 77 24 78 +rect 27 77 29 79 +rect 3 60 13 62 +rect 3 52 5 60 +rect 3 50 6 52 +rect 12 50 14 52 +rect 17 50 24 52 +rect 27 50 29 52 +rect 17 44 19 50 +rect 3 42 6 44 +rect 12 42 19 44 +rect 22 42 24 44 +rect 27 42 31 44 +rect 3 26 5 42 +rect 29 34 31 42 +rect 20 32 31 34 +rect 3 24 6 26 +rect 12 24 24 26 +rect 27 24 29 26 +rect 16 14 18 24 +<< polycontact >> +rect 16 169 20 173 +rect 17 159 21 163 +rect 13 148 17 152 +rect 16 118 20 122 +rect 15 108 19 112 +rect 17 85 21 89 +rect 17 74 21 78 +rect 13 60 17 64 +rect 16 30 20 34 +rect 15 10 19 14 +<< metal1 >> +rect 16 182 24 185 +rect -2 173 6 177 +rect 28 173 36 177 +rect -2 164 2 173 +rect 12 166 20 169 +rect 2 160 6 161 +rect -2 157 6 160 +rect 33 161 36 173 +rect -2 111 2 157 +rect 28 157 32 161 +rect 12 142 24 145 +rect 12 134 20 137 +rect 12 126 20 129 +rect 20 118 24 119 +rect 16 116 24 118 +rect -2 107 6 111 +rect 33 111 36 153 +rect -2 92 2 107 +rect 28 107 36 111 +rect 12 97 24 100 +rect 33 92 36 107 +rect -2 88 6 92 +rect -2 76 2 88 +rect 28 88 36 92 +rect 6 84 20 85 +rect 12 82 20 84 +rect -2 72 6 76 +rect 33 76 36 88 +rect -2 41 2 72 +rect 28 72 32 76 +rect 12 54 24 57 +rect 12 46 20 49 +rect 12 38 20 41 +rect -2 22 2 37 +rect 20 30 24 31 +rect 16 28 24 30 +rect 33 23 36 68 +rect -2 19 6 22 +rect 28 20 36 23 +rect 8 18 12 19 +rect -2 10 15 11 +rect 19 10 36 11 +rect -2 8 36 10 +<< m2contact >> +rect 12 181 16 185 +rect 20 166 24 170 +rect -2 160 2 164 +rect 17 155 21 159 +rect 32 153 36 157 +rect 6 145 10 149 +rect 17 148 21 152 +rect 20 133 24 137 +rect 20 125 24 129 +rect 12 115 16 119 +rect 15 104 19 108 +rect 6 100 10 104 +rect 20 81 24 85 +rect 17 70 21 74 +rect 32 68 36 72 +rect 6 57 10 61 +rect 17 60 21 64 +rect 20 45 24 49 +rect -2 37 2 41 +rect 20 37 24 41 +rect 12 27 16 31 +<< metal2 >> +rect 6 185 10 200 +rect 15 196 19 200 +rect 15 192 24 196 +rect 6 181 12 185 +rect 6 149 9 181 +rect 20 170 24 192 +rect 21 155 27 159 +rect 18 143 21 148 +rect 13 140 21 143 +rect 13 119 16 140 +rect 24 133 27 155 +rect 5 100 6 104 +rect 5 61 8 100 +rect 15 93 19 104 +rect 11 90 19 93 +rect 11 67 14 90 +rect 24 81 27 129 +rect 21 70 27 74 +rect 11 64 16 67 +rect 5 57 6 61 +rect 13 60 17 64 +rect 13 31 16 60 +rect 24 45 27 70 +rect 24 8 27 41 +rect 19 4 27 8 +rect 15 0 19 4 +<< m3contact >> +rect 15 4 19 8 +<< metal3 >> +rect 14 8 20 9 +rect 14 4 15 8 +rect 19 4 20 8 +rect 14 3 20 4 +<< bb >> +rect 0 0 34 200 +<< labels >> +rlabel metal1 0 8 0 8 2 clk +rlabel metal3 15 4 15 4 1 din +rlabel metal2 6 196 6 196 5 dout_bar +rlabel metal2 15 196 15 196 5 dout +rlabel m2contact 34 70 34 70 1 gnd +rlabel m2contact 34 154 34 154 1 gnd +rlabel m2contact 0 162 0 162 3 vdd +rlabel m2contact 0 38 0 38 3 vdd +<< end >> diff --git a/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.gds b/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..7e79ef75c1b506e9ff63e91e1509fefb2054bd75 GIT binary patch literal 6282 zcmbW5J&aXF7=}OY-o4zwvMdO=kVP^60vFhYHT(upi9Zn|(Tx&gg31y#xiMs8SPKdZ z3r#F6EJ(DVAfch4pxDBK!Waq*3kwSi3knMh3JMDgzlS+*&YZJ+L-ZtfpPP5)op0uw zxifRtde*TKn_AJa3%1(EZIumd!WM1R`nJ|K+6tTO^cK#YAAWrH{WE9J4TooD78d~MXoq2rv`1*CT$Ns4~_nsNL=;fjRp})+Y|JiKv`G(8ZFUezJD)i}XX|s>;LuulhR0n*E_BZJ~?am(Wl9jGek7 zeMc8v5B*tZr%ufAow(XaiZ_b*bi(Vf3 zS1*}8{hQhNM9m%3X6T}qhyIO|$@lR2n)uMglAqXos4M2*tMV}Z%z@qS5FhF9df+J&wc{fwRcLL~3_ zMAwUc#!XC-cJPa>@$bohf5bR&JmpI~bScFaUC-k;{A0JxrpL@UE5*I@X6T~pp`SkD zW4{pbp^GIy9zN6+^Y2x87++^Rx#KPX`7NP~u7`f^*!YMe;zJi({=Iqr8TWs@KP>aJ zZ!?dg_IeOiU!=W$)bB9t`H-^!U35Jkf5U%pn0)M&_#r-YvE=8@M&3AkMe>F& zmh!i~n|$0K@k4y*V#&`w%~{KSC+glHx*m@If1Lk~{4q{)&G<#;09|xFjL$gnF>Vnb zy4dp1}J~V)Bb82gxtGp7+1u*ZG;BceH~pw)WqKpFGib z?rI|MJ?NtAVSLsMKJq8xLl;Ya;;`mfD`-$-my4)@QbvAE|%sG4tz_enkA}qU)ibc_we|`x82Otja?_amZW# z{{!-dE|&6V{*Y^aD!E-B&D2-cJ$=^tM`!-3^3c!x;^V$6YTiZHLqGG(!~Bc% z8(nlg^mAwCVf~8u&_&mC|FL}j@bHj3@eQ9t9?`$v^Lv;0|F!@AH}U`LG5&wez2TK# zt-raqIGlb!J#WwJU6`LQ)Z@<7y`I{ec|bkC<9mA_e$r~s*Js^7Z;SuWdc6> +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 +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 +rect 0 61 54 65 +rect 10 44 14 61 +rect 29 54 33 58 +rect 17 51 20 54 +rect 17 47 27 51 +rect 17 37 20 47 +rect 34 44 37 54 +rect 27 40 37 44 +rect 40 44 44 61 +rect 34 37 37 40 +rect 6 33 9 37 +rect 45 33 48 37 +rect 25 23 29 29 +rect 25 13 29 17 +rect 0 9 25 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 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 +rect 9 21 13 72 +rect 25 58 29 68 +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 48 0 52 33 +<< comment >> +rect 0 0 54 70 +<< labels >> +rlabel metal1 19 63 19 63 1 wl0 +rlabel metal1 19 70 19 70 5 vdd +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +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 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/replica_cell_6t.mag b/technology/scn3me_subm/mag_lib/replica_cell_6t.mag new file mode 100644 index 00000000..d0dc472f --- /dev/null +++ b/technology/scn3me_subm/mag_lib/replica_cell_6t.mag @@ -0,0 +1,118 @@ +magic +tech scmos +timestamp 1536091380 +<< nwell >> +rect -8 29 42 51 +<< pwell >> +rect -8 -8 42 29 +<< ntransistor >> +rect 7 10 9 18 +rect 29 10 31 18 +rect 10 3 14 5 +rect 24 3 28 5 +<< ptransistor >> +rect 7 37 11 40 +rect 27 37 31 40 +<< ndiffusion >> +rect -2 16 7 18 +rect 2 12 7 16 +rect -2 10 7 12 +rect 9 14 10 18 +rect 9 10 14 14 +rect 28 14 29 18 +rect 24 10 29 14 +rect 31 16 36 18 +rect 31 12 32 16 +rect 31 10 36 12 +rect 10 5 14 10 +rect 24 5 28 10 +rect 10 2 14 3 +rect 24 2 28 3 +<< pdiffusion >> +rect 2 37 7 40 +rect 11 37 12 40 +rect 26 37 27 40 +rect 31 37 32 40 +<< ndcontact >> +rect -2 12 2 16 +rect 10 14 14 18 +rect 24 14 28 18 +rect 32 12 36 16 +rect 10 -2 14 2 +rect 24 -2 28 2 +<< pdcontact >> +rect -2 36 2 40 +rect 12 36 16 40 +rect 22 36 26 40 +rect 32 36 36 40 +<< psubstratepcontact >> +rect -2 22 2 26 +rect 32 22 36 26 +<< nsubstratencontact >> +rect 32 44 36 48 +<< polysilicon >> +rect 7 40 11 42 +rect 27 40 31 42 +rect 7 35 11 37 +rect 7 21 9 35 +rect 27 34 31 37 +rect 15 33 31 34 +rect 19 32 31 33 +rect 7 20 21 21 +rect 7 19 24 20 +rect 7 18 9 19 +rect 29 18 31 32 +rect 7 8 9 10 +rect 17 5 21 6 +rect 29 8 31 10 +rect -2 3 10 5 +rect 14 3 24 5 +rect 28 3 36 5 +<< polycontact >> +rect 15 29 19 33 +rect 21 20 25 24 +rect 17 6 21 10 +<< metal1 >> +rect -2 44 15 48 +rect 19 44 32 48 +rect -2 40 2 44 +rect 32 40 36 44 +rect 11 36 12 40 +rect 26 36 27 40 +rect -2 26 2 29 +rect 11 22 15 36 +rect 23 24 27 36 +rect -2 18 15 22 +rect 25 20 27 24 +rect -2 16 2 18 +rect 14 14 15 18 +rect 23 18 27 20 +rect 32 26 36 29 +rect 23 14 24 18 +rect 32 16 36 22 +rect -2 6 17 9 +rect 21 6 36 9 +rect -2 5 36 6 +<< m2contact >> +rect 15 44 19 48 +rect -2 29 2 33 +rect 32 29 36 33 +rect 6 -2 10 2 +rect 20 -2 24 2 +<< metal2 >> +rect -2 33 2 48 +rect -2 -2 2 29 +rect 6 2 10 48 +rect 24 -2 28 48 +rect 32 33 36 48 +rect 32 -2 36 29 +<< bb >> +rect 0 0 34 46 +<< labels >> +rlabel metal2 0 0 0 0 1 gnd +rlabel metal2 34 0 34 0 1 gnd +rlabel m2contact 17 46 17 46 5 vdd +rlabel metal2 8 43 8 43 1 bl +rlabel metal2 26 43 26 43 1 br +rlabel metal1 4 7 4 7 1 wl +<< end >> diff --git a/technology/scn3me_subm/mag_lib/sense_amp.mag b/technology/scn3me_subm/mag_lib/sense_amp.mag new file mode 100644 index 00000000..e5fa4373 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/sense_amp.mag @@ -0,0 +1,136 @@ +magic +tech scmos +timestamp 1536089670 +<< nwell >> +rect 0 0 40 102 +<< pwell >> +rect 0 102 40 163 +<< ntransistor >> +rect 21 130 23 139 +rect 12 108 14 117 +rect 20 108 22 117 +<< ptransistor >> +rect 12 78 14 96 +rect 20 78 22 96 +rect 11 20 13 44 +rect 27 20 29 44 +<< ndiffusion >> +rect 20 130 21 139 +rect 23 130 24 139 +rect 11 108 12 117 +rect 14 108 15 117 +rect 19 108 20 117 +rect 22 108 23 117 +<< pdiffusion >> +rect 7 94 12 96 +rect 11 80 12 94 +rect 7 78 12 80 +rect 14 94 20 96 +rect 14 80 15 94 +rect 19 80 20 94 +rect 14 78 20 80 +rect 22 94 27 96 +rect 22 80 23 94 +rect 22 78 27 80 +rect 10 20 11 44 +rect 13 20 14 44 +rect 26 20 27 44 +rect 29 20 30 44 +<< ndcontact >> +rect 16 130 20 139 +rect 24 130 28 139 +rect 7 108 11 117 +rect 15 108 19 117 +rect 23 108 27 117 +<< pdcontact >> +rect 7 80 11 94 +rect 15 80 19 94 +rect 23 80 27 94 +rect 6 20 10 44 +rect 14 20 18 44 +rect 22 20 26 44 +rect 30 20 34 44 +<< psubstratepcontact >> +rect 32 137 36 141 +<< nsubstratencontact >> +rect 27 70 31 74 +<< polysilicon >> +rect 21 139 23 149 +rect 21 129 23 130 +rect 3 127 23 129 +rect 3 47 5 127 +rect 12 122 34 124 +rect 12 117 14 122 +rect 20 117 22 119 +rect 12 96 14 108 +rect 20 96 22 108 +rect 32 105 34 122 +rect 30 101 34 105 +rect 12 76 14 78 +rect 20 69 22 78 +rect 13 67 22 69 +rect 9 55 11 65 +rect 32 55 34 101 +rect 33 51 34 55 +rect 3 45 13 47 +rect 11 44 13 45 +rect 27 44 29 46 +rect 11 19 13 20 +rect 27 19 29 20 +rect 11 17 29 19 +<< polycontact >> +rect 20 149 24 153 +rect 26 101 30 105 +rect 9 65 13 69 +rect 9 51 13 55 +rect 29 51 33 55 +<< metal1 >> +rect -2 149 20 153 +rect 24 149 36 153 +rect 28 133 32 137 +rect 16 117 19 130 +rect 7 94 11 108 +rect 23 105 27 108 +rect 23 101 26 105 +rect 7 69 11 80 +rect 15 94 19 96 +rect 15 78 19 80 +rect 23 94 27 101 +rect 23 78 27 80 +rect 15 75 18 78 +rect 15 74 31 75 +rect 15 72 27 74 +rect 7 65 9 69 +rect 6 44 9 54 +rect 33 51 34 55 +rect 31 44 34 51 +rect 3 20 6 23 +rect 3 15 7 20 +<< m2contact >> +rect 32 133 36 137 +rect 27 66 31 70 +rect 13 44 17 48 +rect 22 44 26 48 +rect 3 11 7 15 +<< metal2 >> +rect 10 48 14 163 +rect 20 48 24 163 +rect 32 129 36 133 +rect 27 62 31 66 +rect 10 44 13 48 +rect 20 44 22 48 +rect 3 0 7 11 +rect 10 0 14 44 +rect 20 0 24 44 +<< bb >> +rect 0 0 34 163 +<< labels >> +flabel metal1 0 149 0 149 4 FreeSans 26 0 0 0 en +rlabel metal2 34 131 34 131 1 gnd +rlabel metal2 29 64 29 64 1 vdd +rlabel metal2 12 161 12 161 5 bl +rlabel metal2 22 161 22 161 5 br +rlabel metal2 5 3 5 3 1 dout +<< properties >> +string path 270.000 468.000 270.000 486.000 288.000 486.000 288.000 468.000 270.000 468.000 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/setup.tcl b/technology/scn3me_subm/mag_lib/setup.tcl new file mode 100644 index 00000000..af55a416 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/setup.tcl @@ -0,0 +1,15 @@ +# Setup file for netgen +ignore class c +equate class {-circuit1 nfet} {-circuit2 n} +equate class {-circuit1 pfet} {-circuit2 p} +# This circuit has symmetries and needs to be flattened to resolve them +# or the banks won't pass +flatten class {-circuit1 precharge_array_1} +flatten class {-circuit1 precharge_array_2} +flatten class {-circuit1 precharge_array_3} +flatten class {-circuit1 precharge_array_4} +property {-circuit1 nfet} remove as ad ps pd +property {-circuit1 pfet} remove as ad ps pd +property {-circuit2 n} remove as ad ps pd +property {-circuit2 p} remove as ad ps pd +permute transistors diff --git a/technology/scn3me_subm/mag_lib/tri_gate.mag b/technology/scn3me_subm/mag_lib/tri_gate.mag new file mode 100644 index 00000000..bda635c7 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/tri_gate.mag @@ -0,0 +1,98 @@ +magic +tech scmos +timestamp 1536089695 +<< nwell >> +rect -2 45 38 73 +<< pwell >> +rect -2 0 38 45 +<< ntransistor >> +rect 9 27 11 31 +rect 17 27 19 31 +rect 25 27 27 31 +<< ptransistor >> +rect 9 53 11 61 +rect 17 53 19 61 +rect 25 53 27 61 +<< ndiffusion >> +rect 8 27 9 31 +rect 11 27 12 31 +rect 16 27 17 31 +rect 19 27 20 31 +rect 24 27 25 31 +rect 27 27 28 31 +<< pdiffusion >> +rect 8 53 9 61 +rect 11 53 12 61 +rect 16 53 17 61 +rect 19 53 20 61 +rect 24 53 25 61 +rect 27 53 28 61 +<< ndcontact >> +rect 4 27 8 31 +rect 12 27 16 31 +rect 20 27 24 31 +rect 28 27 32 31 +<< pdcontact >> +rect 4 53 8 61 +rect 12 53 16 61 +rect 20 53 24 61 +rect 28 53 32 61 +<< psubstratepcontact >> +rect 12 19 16 23 +<< nsubstratencontact >> +rect 12 65 16 69 +<< polysilicon >> +rect 25 63 35 65 +rect 9 61 11 63 +rect 17 61 19 63 +rect 25 61 27 63 +rect 9 50 11 53 +rect 9 31 11 46 +rect 17 42 19 53 +rect 25 51 27 53 +rect 17 31 19 38 +rect 25 31 27 33 +rect 9 25 11 27 +rect 17 25 19 27 +rect 25 16 27 27 +rect 33 8 35 63 +rect 32 6 35 8 +<< polycontact >> +rect 9 46 13 50 +rect 16 38 20 42 +rect 25 12 29 16 +rect 28 4 32 8 +<< metal1 >> +rect 16 65 23 69 +rect 12 61 16 65 +rect 3 53 4 61 +rect 3 42 6 53 +rect 13 46 15 50 +rect 3 38 16 42 +rect 3 31 6 38 +rect 29 31 32 53 +rect 3 27 4 31 +rect 12 23 16 27 +rect 16 19 24 23 +rect 0 12 25 16 +rect 29 12 36 16 +rect 0 4 28 8 +rect 32 4 36 8 +<< m2contact >> +rect 23 65 27 69 +rect 15 46 19 50 +rect 25 34 29 38 +rect 24 19 28 23 +<< metal2 >> +rect 15 34 25 38 +rect 15 0 19 34 +<< bb >> +rect 0 0 34 73 +<< labels >> +rlabel metal1 0 12 0 12 3 en +rlabel metal1 0 4 0 4 2 en_bar +rlabel metal2 16 1 16 1 1 out +rlabel m2contact 26 21 26 21 1 gnd +rlabel m2contact 25 67 25 67 1 vdd +rlabel m2contact 17 48 17 48 1 in +<< end >> diff --git a/technology/scn3me_subm/mag_lib/write_driver.mag b/technology/scn3me_subm/mag_lib/write_driver.mag new file mode 100644 index 00000000..ab2014aa --- /dev/null +++ b/technology/scn3me_subm/mag_lib/write_driver.mag @@ -0,0 +1,224 @@ +magic +tech scmos +timestamp 1536089714 +<< nwell >> +rect -3 101 37 138 +rect -3 0 37 51 +<< pwell >> +rect -3 138 37 202 +rect -3 51 37 101 +<< ntransistor >> +rect 9 177 11 189 +rect 17 177 19 189 +rect 15 162 27 164 +rect 9 144 11 148 +rect 17 144 19 148 +rect 10 82 12 89 +rect 18 82 20 89 +rect 8 57 10 64 +rect 16 57 18 64 +rect 24 60 26 64 +<< ptransistor >> +rect 9 125 11 132 +rect 17 125 19 132 +rect 10 107 12 114 +rect 18 107 20 114 +rect 8 38 10 45 +rect 16 38 18 45 +rect 24 38 26 45 +<< ndiffusion >> +rect 8 177 9 189 +rect 11 177 12 189 +rect 16 177 17 189 +rect 19 177 20 189 +rect 15 164 27 165 +rect 15 161 27 162 +rect 12 157 15 160 +rect 12 156 16 157 +rect 8 144 9 148 +rect 11 144 12 148 +rect 16 144 17 148 +rect 19 144 20 148 +rect 9 82 10 89 +rect 12 82 13 89 +rect 17 82 18 89 +rect 20 82 21 89 +rect 25 82 26 86 +rect 7 57 8 64 +rect 10 57 11 64 +rect 15 57 16 64 +rect 18 57 19 64 +rect 23 60 24 64 +rect 26 60 27 64 +<< pdiffusion >> +rect 8 125 9 132 +rect 11 125 12 132 +rect 16 125 17 132 +rect 19 125 20 132 +rect 12 122 16 125 +rect 9 107 10 114 +rect 12 107 13 114 +rect 17 107 18 114 +rect 20 107 21 114 +rect 7 38 8 45 +rect 10 38 11 45 +rect 15 38 16 45 +rect 18 38 19 45 +rect 23 38 24 45 +rect 26 38 27 45 +rect 3 35 7 38 +<< ndcontact >> +rect 4 177 8 189 +rect 12 177 16 189 +rect 20 177 24 189 +rect 15 165 27 169 +rect 15 157 27 161 +rect 4 144 8 148 +rect 12 144 16 148 +rect 20 144 24 148 +rect 5 82 9 89 +rect 13 82 17 89 +rect 21 82 25 89 +rect 3 57 7 64 +rect 11 57 15 64 +rect 19 57 23 64 +rect 27 60 31 64 +<< pdcontact >> +rect 4 125 8 132 +rect 12 125 16 132 +rect 20 125 24 132 +rect 5 107 9 114 +rect 13 107 17 114 +rect 21 107 25 114 +rect 3 38 7 45 +rect 11 38 15 45 +rect 19 38 23 45 +rect 27 38 31 45 +<< psubstratepcontact >> +rect 12 152 16 156 +rect 26 82 30 86 +<< nsubstratencontact >> +rect 12 118 16 122 +rect 3 31 7 35 +<< polysilicon >> +rect 9 194 30 196 +rect 9 189 11 194 +rect 17 189 19 191 +rect 28 185 30 194 +rect 9 175 11 177 +rect 17 172 19 177 +rect 6 170 19 172 +rect 6 167 8 170 +rect 13 162 15 164 +rect 27 162 33 164 +rect 9 148 11 150 +rect 17 148 19 150 +rect 9 132 11 144 +rect 17 132 19 144 +rect 9 124 11 125 +rect 2 122 11 124 +rect 17 124 19 125 +rect 17 122 28 124 +rect 2 75 4 122 +rect 10 114 12 116 +rect 18 114 20 116 +rect 10 89 12 107 +rect 18 106 20 107 +rect 16 104 20 106 +rect 16 92 18 104 +rect 26 100 28 122 +rect 27 96 28 100 +rect 16 90 20 92 +rect 18 89 20 90 +rect 10 81 12 82 +rect 10 79 13 81 +rect 2 71 3 75 +rect 11 71 13 79 +rect 18 79 20 82 +rect 18 77 23 79 +rect 31 71 33 162 +rect 11 69 33 71 +rect 11 67 13 69 +rect 8 65 13 67 +rect 8 64 10 65 +rect 16 64 18 66 +rect 24 64 26 66 +rect 8 45 10 57 +rect 16 52 18 57 +rect 24 52 26 60 +rect 16 50 26 52 +rect 16 45 18 50 +rect 24 45 26 50 +rect 8 28 10 38 +rect 16 14 18 38 +rect 24 36 26 38 +<< polycontact >> +rect 28 181 32 185 +rect 4 163 8 167 +rect 23 96 27 100 +rect 3 71 7 75 +rect 23 75 27 79 +rect 7 24 11 28 +rect 15 10 19 14 +<< metal1 >> +rect 5 192 10 196 +rect 5 189 8 192 +rect 32 181 33 185 +rect 13 169 16 177 +rect 13 165 15 169 +rect 4 148 8 163 +rect 12 157 15 161 +rect 12 156 16 157 +rect 12 148 16 152 +rect 4 132 8 144 +rect 20 142 24 144 +rect 30 142 33 181 +rect 20 138 33 142 +rect 20 132 24 138 +rect 12 122 16 125 +rect 13 114 17 118 +rect 5 104 9 107 +rect 21 104 25 107 +rect 5 101 25 104 +rect 5 89 9 101 +rect 21 100 25 101 +rect 21 96 23 100 +rect 25 82 26 90 +rect 4 64 7 71 +rect 27 64 31 79 +rect 3 51 7 57 +rect 3 48 15 51 +rect 11 45 15 48 +rect 27 45 31 60 +rect 3 35 7 38 +rect 19 35 23 38 +rect 7 31 19 35 +rect 0 24 7 28 +rect 11 24 36 28 +<< m2contact >> +rect 10 192 14 196 +rect 20 189 24 193 +rect 23 153 27 157 +rect 16 118 20 122 +rect 26 86 30 90 +rect 19 64 23 68 +rect 19 31 23 35 +rect 15 6 19 10 +<< metal2 >> +rect 10 196 14 202 +rect 20 193 24 202 +rect 20 177 24 189 +rect 15 0 19 6 +<< bb >> +rect 0 0 34 202 +<< labels >> +rlabel metal2 15 1 15 1 1 din +rlabel metal1 2 25 2 25 3 en +rlabel metal2 12 200 12 200 5 bl +rlabel metal2 22 200 22 200 5 br +rlabel m2contact 21 66 21 66 1 gnd +rlabel m2contact 28 88 28 88 1 gnd +rlabel m2contact 21 33 21 33 1 vdd +rlabel m2contact 18 120 18 120 1 vdd +rlabel m2contact 25 155 25 155 1 gnd +<< end >> diff --git a/technology/scn3me_subm/models/ff/nmos.sp b/technology/scn3me_subm/models/ff/nmos.sp new file mode 100644 index 00000000..9711c533 --- /dev/null +++ b/technology/scn3me_subm/models/ff/nmos.sp @@ -0,0 +1,10 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL n NMOS (LEVEL=49 VTHO=0.669845 ++ NSUB=6E16 U0=461 K1=0.5705 TOX=13.9n VERSION=3.3.0) + diff --git a/technology/scn3me_subm/models/ff/pmos.sp b/technology/scn3me_subm/models/ff/pmos.sp new file mode 100644 index 00000000..e08967e4 --- /dev/null +++ b/technology/scn3me_subm/models/ff/pmos.sp @@ -0,0 +1,9 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 ++ NSUB=6E16 U0=212 K1=0.0821 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/nom/nmos.sp b/technology/scn3me_subm/models/nom/nmos.sp new file mode 100644 index 00000000..59f88cfd --- /dev/null +++ b/technology/scn3me_subm/models/nom/nmos.sp @@ -0,0 +1,9 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL n NMOS (LEVEL=49 VTHO=0.669845 ++ NSUB=6E16 U0=458 K1=0.5705 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/nom/pmos.sp b/technology/scn3me_subm/models/nom/pmos.sp new file mode 100644 index 00000000..69f3aacd --- /dev/null +++ b/technology/scn3me_subm/models/nom/pmos.sp @@ -0,0 +1,9 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 ++ NSUB=6E16 U0=212 K1=0.0821 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/ss/nmos.sp b/technology/scn3me_subm/models/ss/nmos.sp new file mode 100644 index 00000000..4e8a531f --- /dev/null +++ b/technology/scn3me_subm/models/ss/nmos.sp @@ -0,0 +1,10 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL n NMOS (LEVEL=49 VTHO=0.669845 ++ NSUB=6E16 U0=460 K1=0.5705 TOX=13.9n VERSION=3.3.0) + diff --git a/technology/scn3me_subm/models/ss/pmos.sp b/technology/scn3me_subm/models/ss/pmos.sp new file mode 100644 index 00000000..e08967e4 --- /dev/null +++ b/technology/scn3me_subm/models/ss/pmos.sp @@ -0,0 +1,9 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 ++ NSUB=6E16 U0=212 K1=0.0821 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/sp_lib/cell_6t.sp b/technology/scn3me_subm/sp_lib/cell_6t.sp new file mode 100644 index 00000000..76c40f31 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/cell_6t.sp @@ -0,0 +1,10 @@ + +*********************** "cell_6t" ****************************** +.SUBCKT cell_6t bl br wl vdd gnd +M_1 Q Qb vdd vdd p W='0.9u' L=1.2u +M_2 Qb Q vdd vdd p W='0.9u' L=1.2u +M_3 br wl Qb gnd n W='1.2u' L=0.6u +M_4 bl wl Q gnd n W='1.2u' L=0.6u +M_5 Qb Q gnd gnd n W='2.4u' L=0.6u +M_6 Q Qb gnd gnd n W='2.4u' L=0.6u +.ENDS $ cell_6t diff --git a/technology/scn3me_subm/sp_lib/dff.sp b/technology/scn3me_subm/sp_lib/dff.sp new file mode 100644 index 00000000..d3fa7635 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/dff.sp @@ -0,0 +1,27 @@ +*********************** "dff" ****************************** +* Positive edge-triggered FF +.SUBCKT dff D Q clk vdd gnd +M0 vdd clk a_2_6# vdd p w=12u l=0.6u +M1 a_17_74# D vdd vdd p w=6u l=0.6u +M2 a_22_6# clk a_17_74# vdd p w=6u l=0.6u +M3 a_31_74# a_2_6# a_22_6# vdd p w=6u l=0.6u +M4 vdd a_34_4# a_31_74# vdd p w=6u l=0.6u +M5 a_34_4# a_22_6# vdd vdd p w=6u l=0.6u +M6 a_61_74# a_34_4# vdd vdd p w=6u l=0.6u +M7 a_66_6# a_2_6# a_61_74# vdd p w=6u l=0.6u +M8 a_76_84# clk a_66_6# vdd p w=3u l=0.6u +M9 vdd Q a_76_84# vdd p w=3u l=0.6u +M10 gnd clk a_2_6# gnd n w=6u l=0.6u +M11 Q a_66_6# vdd vdd p w=12u l=0.6u +M12 a_17_6# D gnd gnd n w=3u l=0.6u +M13 a_22_6# a_2_6# a_17_6# gnd n w=3u l=0.6u +M14 a_31_6# clk a_22_6# gnd n w=3u l=0.6u +M15 gnd a_34_4# a_31_6# gnd n w=3u l=0.6u +M16 a_34_4# a_22_6# gnd gnd n w=3u l=0.6u +M17 a_61_6# a_34_4# gnd gnd n w=3u l=0.6u +M18 a_66_6# clk a_61_6# gnd n w=3u l=0.6u +M19 a_76_6# a_2_6# a_66_6# gnd n w=3u l=0.6u +M20 gnd Q a_76_6# gnd n w=3u l=0.6u +M21 Q a_66_6# gnd gnd n w=6u l=0.6u + +.ENDS dff diff --git a/technology/scn3me_subm/sp_lib/ms_flop.sp b/technology/scn3me_subm/sp_lib/ms_flop.sp new file mode 100644 index 00000000..abf664e7 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/ms_flop.sp @@ -0,0 +1,29 @@ +*master-slave flip-flop with both output and inverted ouput + +.subckt dlatch din dout dout_bar clk clk_bar vdd gnd +*clk inverter +mPff1 clk_bar clk vdd vdd p W=1.8u L=0.6u m=1 +mNff1 clk_bar clk gnd gnd n W=0.9u L=0.6u m=1 + +*transmission gate 1 +mtmP1 din clk int1 vdd p W=1.8u L=0.6u m=1 +mtmN1 din clk_bar int1 gnd n W=0.9u L=0.6u m=1 + +*foward inverter +mPff3 dout_bar int1 vdd vdd p W=1.8u L=0.6u m=1 +mNff3 dout_bar int1 gnd gnd n W=0.9u L=0.6u m=1 + +*backward inverter +mPff4 dout dout_bar vdd vdd p W=1.8u L=0.6u m=1 +mNf4 dout dout_bar gnd gnd n W=0.9u L=0.6u m=1 + +*transmission gate 2 +mtmP2 int1 clk_bar dout vdd p W=1.8u L=0.6u m=1 +mtmN2 int1 clk dout gnd n W=0.9u L=0.6u m=1 +.ends dlatch + +.subckt ms_flop din dout dout_bar clk vdd gnd +xmaster din mout mout_bar clk clk_bar vdd gnd dlatch +xslave mout_bar dout_bar dout clk_bar clk_nn vdd gnd dlatch +.ends flop + diff --git a/technology/scn3me_subm/sp_lib/replica_cell_6t.sp b/technology/scn3me_subm/sp_lib/replica_cell_6t.sp new file mode 100644 index 00000000..1fa75a55 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/replica_cell_6t.sp @@ -0,0 +1,10 @@ + +*********************** "cell_6t" ****************************** +.SUBCKT replica_cell_6t bl br wl vdd gnd +M_1 gnd net_2 vdd vdd p W='0.9u' L=1.2u +M_2 net_2 gnd vdd vdd p W='0.9u' L=1.2u +M_3 br wl net_2 gnd n W='1.2u' L=0.6u +M_4 bl wl gnd gnd n W='1.2u' L=0.6u +M_5 net_2 gnd gnd gnd n W='2.4u' L=0.6u +M_6 gnd net_2 gnd gnd n W='2.4u' L=0.6u +.ENDS $ replica_cell_6t diff --git a/technology/scn3me_subm/sp_lib/sense_amp.sp b/technology/scn3me_subm/sp_lib/sense_amp.sp new file mode 100644 index 00000000..1399228d --- /dev/null +++ b/technology/scn3me_subm/sp_lib/sense_amp.sp @@ -0,0 +1,12 @@ +*********************** "sense_amp" ****************************** + +.SUBCKT sense_amp bl br dout en vdd gnd +M_1 dout net_1 vdd vdd p W='5.4*1u' L=0.6u +M_2 dout net_1 net_2 gnd n W='2.7*1u' L=0.6u +M_3 net_1 dout vdd vdd p W='5.4*1u' L=0.6u +M_4 net_1 dout net_2 gnd n W='2.7*1u' L=0.6u +M_5 bl en dout vdd p W='7.2*1u' L=0.6u +M_6 br en net_1 vdd p W='7.2*1u' L=0.6u +M_7 net_2 en gnd gnd n W='2.7*1u' L=0.6u +.ENDS sense_amp + diff --git a/technology/scn3me_subm/sp_lib/tri_gate.sp b/technology/scn3me_subm/sp_lib/tri_gate.sp new file mode 100644 index 00000000..0d298172 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/tri_gate.sp @@ -0,0 +1,13 @@ +*********************** tri_gate ****************************** + +.SUBCKT tri_gate in out en en_bar vdd gnd + +M_1 net_2 in_inv gnd gnd n W='1.2*1u' L=0.6u +M_2 net_3 in_inv vdd vdd p W='2.4*1u' L=0.6u +M_3 out en_bar net_3 vdd p W='2.4*1u' L=0.6u +M_4 out en net_2 gnd n W='1.2*1u' L=0.6u +M_5 in_inv in vdd vdd p W='2.4*1u' L=0.6u +M_6 in_inv in gnd gnd n W='1.2*1u' L=0.6u + + +.ENDS diff --git a/technology/scn3me_subm/sp_lib/write_driver.sp b/technology/scn3me_subm/sp_lib/write_driver.sp new file mode 100644 index 00000000..88f80361 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/write_driver.sp @@ -0,0 +1,38 @@ +*********************** Write_Driver ****************************** +.SUBCKT write_driver din bl br en vdd gnd + +**** Inverter to conver Data_in to data_in_bar ****** +* din_bar = inv(din) +M_1 din_bar din gnd gnd n W=1.2u L=0.6u +M_2 din_bar din vdd vdd p W=2.1u L=0.6u + +**** 2input nand gate follwed by inverter to drive BL ****** +* din_bar_gated = nand(en, din) +M_3 din_bar_gated en net_7 gnd n W=2.1u L=0.6u +M_4 net_7 din gnd gnd n W=2.1u L=0.6u +M_5 din_bar_gated en vdd vdd p W=2.1u L=0.6u +M_6 din_bar_gated din vdd vdd p W=2.1u L=0.6u +* din_bar_gated_bar = inv(din_bar_gated) +M_7 din_bar_gated_bar din_bar_gated vdd vdd p W=2.1u L=0.6u +M_8 din_bar_gated_bar din_bar_gated gnd gnd n W=1.2u L=0.6u + +**** 2input nand gate follwed by inverter to drive BR****** +* din_gated = nand(en, din_bar) +M_9 din_gated en vdd vdd p W=2.1u L=0.6u +M_10 din_gated en net_8 gnd n W=2.1u L=0.6u +M_11 net_8 din_bar gnd gnd n W=2.1u L=0.6u +M_12 din_gated din_bar vdd vdd p W=2.1u L=0.6u +* din_gated_bar = inv(din_gated) +M_13 din_gated_bar din_gated vdd vdd p W=2.1u L=0.6u +M_14 din_gated_bar din_gated gnd gnd n W=1.2u L=0.6u + +************************************************ +* pull down with en enable +M_15 bl din_gated_bar net_5 gnd n W=3.6u L=0.6u +M_16 br din_bar_gated_bar net_5 gnd n W=3.6u L=0.6u +M_17 net_5 en gnd gnd n W=3.6u L=0.6u + + + +.ENDS $ write_driver + diff --git a/technology/scn3me_subm/sue_lib/cell_6t.sue b/technology/scn3me_subm/sue_lib/cell_6t.sue new file mode 100644 index 00000000..427b1d05 --- /dev/null +++ b/technology/scn3me_subm/sue_lib/cell_6t.sue @@ -0,0 +1,46 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_cell_6t {} { + make inout -name BL -origin {190 360} + make inout -name BR -origin {830 360} + make input -name WL -origin {240 120} + make global -orient RXY -name vdd -origin {520 160} + make global -name gnd -origin {510 600} + make pmos -orient RY -W 0.9u -L 1.2u -origin {630 230} + make pmos -orient RXY -W 0.9u -L 1.2u -origin {400 230} + make nmos -orient R90 -W 1.2 -L 0.6u -origin {740 360} + make nmos -orient R90X -W 1.2 -L 0.6u -origin {270 360} + make nmos -W 2.4u -L 0.6u -origin {630 490} + make nmos -orient RX -W 2.4u -L 0.6u -origin {400 490} + make_wire 630 550 630 530 + make_wire 400 530 400 550 + make_wire 400 190 400 170 + make_wire 630 170 630 190 + make_wire 400 360 400 270 + make_wire 310 360 400 360 + make_wire 630 360 630 450 + make_wire 630 360 700 360 + make_wire 270 300 270 120 + make_wire 270 120 740 120 + make_wire 740 120 740 300 + make_wire 230 360 190 360 + make_wire 780 360 830 360 + make_wire 510 550 400 550 + make_wire 510 550 630 550 + make_wire 510 550 510 600 + make_wire 520 170 400 170 + make_wire 520 170 630 170 + make_wire 520 160 520 170 + make_wire 240 120 270 120 + make_wire 460 290 630 290 + make_wire 460 290 460 490 + make_wire 460 290 460 230 + make_wire 630 290 630 360 + make_wire 630 290 630 270 + make_wire 570 420 400 420 + make_wire 570 420 570 490 + make_wire 570 420 570 230 + make_wire 400 420 400 360 + make_wire 400 420 400 450 +} + diff --git a/technology/scn3me_subm/sue_lib/ms_flop.sue b/technology/scn3me_subm/sue_lib/ms_flop.sue new file mode 100644 index 00000000..85cc8e03 --- /dev/null +++ b/technology/scn3me_subm/sue_lib/ms_flop.sue @@ -0,0 +1,84 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_ms_flop {} { + make pmos -orient R90X -W 1.8u -L 0.6u -origin {40 250} + make nmos -orient R270 -W 0.9u -L 0.6u -origin {40 380} + make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {-270 540} + make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {310 310} + make inverter -orient RX -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {430 730} + make pmos -orient R90X -W 1.8u -L 0.6u -origin {190 670} + make nmos -orient R270 -W 0.9u -L 0.6u -origin {190 780} + make input -name clk -origin {-380 540} + make input -name din -origin {-370 320} + make pmos -orient R90X -W 1.8u -L 0.6u -origin {720 250} + make nmos -orient R270 -W 0.9u -L 0.6u -origin {720 380} + make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {990 310} + make pmos -orient R90X -W 1.8u -L 0.6u -origin {870 670} + make nmos -orient R270 -W 0.9u -L 0.6u -origin {870 780} + make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {620 540} + make output -name dout -origin {1410 310} + make output -name dout_bar -origin {1430 930} + make inverter -orient RX -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {1110 730} + make_wire -330 160 40 160 + make_wire 40 160 40 190 + make_wire -370 320 0 320 + make_wire 360 310 480 310 + make_wire 460 730 480 730 + make_wire 230 730 380 730 + make_wire 100 310 100 720 + make_wire 100 720 150 720 + make_wire 100 310 80 310 + make_wire 100 310 280 310 + make_wire 0 250 0 320 + make_wire 0 320 0 380 + make_wire 80 250 80 310 + make_wire 80 310 80 380 + make_wire 40 440 40 540 + make_wire -330 840 190 840 + make_wire 230 670 230 730 + make_wire 230 730 230 780 + make_wire 150 670 150 720 + make_wire 150 720 150 780 + make_wire 190 540 190 610 + make_wire -330 540 -330 840 + make_wire -220 540 40 540 + make_wire 40 540 190 540 + make_wire -380 540 -330 540 + make_wire -330 540 -300 540 + make_wire -330 540 -330 160 + make_wire 720 160 720 190 + make_wire 1140 730 1160 730 + make_wire 780 310 780 720 + make_wire 780 720 830 720 + make_wire 780 310 760 310 + make_wire 780 310 960 310 + make_wire 680 320 680 380 + make_wire 760 250 760 310 + make_wire 760 310 760 380 + make_wire 720 440 720 540 + make_wire 910 670 910 730 + make_wire 910 730 910 780 + make_wire 830 670 830 720 + make_wire 830 720 830 780 + make_wire 870 540 870 610 + make_wire 720 540 870 540 + make_wire 670 540 720 540 + make_wire 480 310 480 730 + make_wire 1160 310 1160 730 + make_wire 530 540 530 160 + make_wire 530 160 720 160 + make_wire 530 540 190 540 + make_wire 530 540 590 540 + make_wire 530 540 530 840 + make_wire 530 840 870 840 + make_wire 680 310 480 310 + make_wire 680 310 680 250 + make_wire 680 310 680 320 + make_wire 950 730 910 730 + make_wire 950 730 1060 730 + make_wire 1040 310 1160 310 + make_wire 1160 310 1410 310 + make_wire 950 930 1430 930 + make_wire 950 730 950 930 +} + diff --git a/technology/scn3me_subm/sue_lib/replica_cell_6t.sue b/technology/scn3me_subm/sue_lib/replica_cell_6t.sue new file mode 100644 index 00000000..56e72056 --- /dev/null +++ b/technology/scn3me_subm/sue_lib/replica_cell_6t.sue @@ -0,0 +1,49 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_replica_cell_6t {} { + make inout -name BL -origin {190 360} + make inout -name BR -origin {830 360} + make input -name WL -origin {240 120} + make global -orient RXY -name vdd -origin {520 160} + make global -name gnd -origin {510 600} + make pmos -orient RY -W 0.9u -L 1.2u -origin {630 230} + make pmos -orient RXY -W 0.9u -L 1.2u -origin {400 230} + make nmos -orient R90 -W 1.2 -L 0.6u -origin {740 360} + make nmos -orient R90X -W 1.2 -L 0.6u -origin {270 360} + make nmos -W 2.4u -L 0.6u -origin {630 490} + make nmos -orient RX -W 2.4u -L 0.6u -origin {400 490} + make_wire 630 550 630 530 + make_wire 400 530 400 550 + make_wire 400 190 400 170 + make_wire 630 170 630 190 + make_wire 400 360 400 270 + make_wire 630 360 630 450 + make_wire 630 360 700 360 + make_wire 270 300 270 120 + make_wire 270 120 740 120 + make_wire 740 120 740 300 + make_wire 230 360 190 360 + make_wire 780 360 830 360 + make_wire 510 550 400 550 + make_wire 510 550 630 550 + make_wire 510 550 510 600 + make_wire 520 170 400 170 + make_wire 520 170 630 170 + make_wire 520 160 520 170 + make_wire 240 120 270 120 + make_wire 460 290 630 290 + make_wire 460 290 460 490 + make_wire 460 290 460 230 + make_wire 630 290 630 360 + make_wire 630 290 630 270 + make_wire 570 420 400 420 + make_wire 570 420 570 490 + make_wire 570 420 570 230 + make_wire 400 420 400 360 + make_wire 400 420 400 450 + make_wire 320 360 320 550 + make_wire 320 550 400 550 + make_wire 320 360 310 360 + make_wire 320 360 400 360 +} + diff --git a/technology/scn3me_subm/sue_lib/sense_amp.sue b/technology/scn3me_subm/sue_lib/sense_amp.sue new file mode 100644 index 00000000..4d29e11a --- /dev/null +++ b/technology/scn3me_subm/sue_lib/sense_amp.sue @@ -0,0 +1,52 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_sense_amp {} { + make inout -name BL -origin {260 10} + make global -orient RXY -name vdd -origin {490 170} + make global -name gnd -origin {480 660} + make input -name sclk -origin {180 610} + make nmos -W 3.9u -L 0.6u -origin {600 500} + make nmos -orient RX -W 3.9u -L 0.6u -origin {370 500} + make pmos -orient RY -W 3u -L 0.6u -origin {600 240} + make pmos -orient RXY -W 3u -L 0.6u -origin {370 240} + make nmos -W 3.9u -L 0.6u -origin {480 610} + make inout -name BR -origin {710 20} + make pmos -W 3.9u -L 0.6u -origin {710 90} + make pmos -orient RX -W 3.9u -L 0.6u -origin {260 90} + make output -orient RXY -name dout -origin {110 370} + make_wire 600 560 600 540 + make_wire 370 540 370 560 + make_wire 370 200 370 180 + make_wire 600 180 600 200 + make_wire 490 180 370 180 + make_wire 490 180 600 180 + make_wire 490 170 490 180 + make_wire 430 300 600 300 + make_wire 430 300 430 500 + make_wire 430 300 430 240 + make_wire 600 300 600 280 + make_wire 540 430 370 430 + make_wire 540 430 540 500 + make_wire 540 430 540 240 + make_wire 370 430 370 460 + make_wire 480 560 600 560 + make_wire 480 560 370 560 + make_wire 480 560 480 570 + make_wire 480 650 480 660 + make_wire 420 610 180 610 + make_wire 650 90 320 90 + make_wire 600 360 710 360 + make_wire 710 360 710 130 + make_wire 600 360 600 300 + make_wire 600 360 600 460 + make_wire 370 370 260 370 + make_wire 260 370 260 130 + make_wire 370 370 370 430 + make_wire 370 370 370 280 + make_wire 260 10 260 50 + make_wire 710 20 710 50 + make_wire 320 90 180 90 + make_wire 180 90 180 610 + make_wire 110 370 260 370 +} + diff --git a/technology/scn3me_subm/sue_lib/tri_gate.sue b/technology/scn3me_subm/sue_lib/tri_gate.sue new file mode 100644 index 00000000..d296171f --- /dev/null +++ b/technology/scn3me_subm/sue_lib/tri_gate.sue @@ -0,0 +1,37 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_tri_gate {} { + make global -orient RXY -name vdd -origin {630 150} + make global -name gnd -origin {630 570} + make input -name tri_in -origin {320 340} + make output -name tri_out -origin {690 360} + make input -name en -origin {570 410} + make input -name en_bar -origin {570 310} + make nmos -W 1.2u -L 0.6u -origin {630 490} + make nmos -W 1.2u -L 0.6u -origin {630 410} + make pmos -orient RY -W 2.4u -L 0.6u -origin {630 310} + make pmos -orient RY -W 2.4u -L 0.6u -origin {630 230} + make pmos -orient RY -W 2.4u -L 0.6u -origin {380 290} + make nmos -W 1.2u -L 0.6u -origin {380 400} + make_wire 570 490 470 490 + make_wire 470 230 570 230 + make_wire 630 550 380 550 + make_wire 380 550 380 440 + make_wire 630 550 630 570 + make_wire 630 550 630 530 + make_wire 630 170 380 170 + make_wire 380 170 380 250 + make_wire 630 170 630 190 + make_wire 630 170 630 150 + make_wire 320 340 320 400 + make_wire 320 340 320 290 + make_wire 380 340 470 340 + make_wire 380 340 380 330 + make_wire 380 340 380 360 + make_wire 470 340 470 490 + make_wire 470 340 470 230 + make_wire 630 360 630 350 + make_wire 630 360 630 370 + make_wire 630 360 690 360 +} + diff --git a/technology/scn3me_subm/sue_lib/write_driver.sue b/technology/scn3me_subm/sue_lib/write_driver.sue new file mode 100644 index 00000000..de3909a7 --- /dev/null +++ b/technology/scn3me_subm/sue_lib/write_driver.sue @@ -0,0 +1,44 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_write_driver {} { + make inout -name BL -origin {550 260} + make inout -name BR -origin {830 250} + make inverter -WP 2.1u -LP 0.6u -WN 1.2u -LN 0.6u -origin {280 520} + make nand2 -WP 2.1u -WN 2.1u -origin {90 360} + make inverter -WP 2.1u -LP 0.6u -WN 1.2u -LN 0.6u -origin {270 360} + make nmos -W 3.6u -L 0.6u -origin {830 410} + make nmos -W 3.6u -L 0.6u -origin {710 610} + make global -name gnd -origin {710 690} + make nand2 -WP 2.1u -WN 2.1u -origin {90 520} + make nmos -W 3.6u -L 0.6u -origin {550 410} + make input -name wen -origin {-290 340} + make input -name din -origin {-290 380} + make inverter -WP 2.1u -LP 0.6u -WN 1.2u -LN 0.6u -origin {-80 540} + make_wire 160 360 240 360 + make_wire 830 250 830 370 + make_wire 550 260 550 370 + make_wire 550 450 550 560 + make_wire 550 560 710 560 + make_wire 710 560 710 570 + make_wire 710 560 830 560 + make_wire 830 560 830 450 + make_wire 710 650 710 690 + make_wire 250 520 160 520 + make_wire 770 410 770 520 + make_wire 770 520 330 520 + make_wire 320 360 490 360 + make_wire 490 360 490 410 + make_wire -180 380 -290 380 + make_wire -180 380 70 380 + make_wire -180 540 -110 540 + make_wire -180 380 -180 540 + make_wire -30 540 70 540 + make_wire 20 340 20 500 + make_wire 20 500 70 500 + make_wire 20 340 70 340 + make_wire -240 340 -240 610 + make_wire -240 610 650 610 + make_wire -240 340 20 340 + make_wire -240 340 -290 340 +} + diff --git a/technology/scn3me_subm/tech/README b/technology/scn3me_subm/tech/README new file mode 100644 index 00000000..0d923fcb --- /dev/null +++ b/technology/scn3me_subm/tech/README @@ -0,0 +1,10 @@ +The file SCN3ME_SUBM.30.tech is from qflow 1.2 and has the following +license information: +--------------------------------------------------------------- +Tim Edwards +Open Circuit Design +v1.0 April 2013 +v1.1 May 2015 +v1.2 April 2017 +--------------------------------------------------------------- +GPL Copyright (c) 2017 diff --git a/technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech b/technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech new file mode 100644 index 00000000..be511001 --- /dev/null +++ b/technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech @@ -0,0 +1,7891 @@ +tech + format 32 + scmos +end + +version + version 2002a + description "SCMOS: Submit as technology.lambda: SCN3ME_SUBM.30 [to process: AMIc5]" +end + +planes + well,w + implant,i + select,s + cap,c + active,a + metal1,m1 + metal2,m2 + metal3,m3 + oxide,ox + comment + xp + contact + via1,v1 + via2,v2 + fill +end + +types + well nwell,nw + well pwell,pw + implant n_field_implant,nfi + implant p_field_implant,pfi + select nselect,ns + select pselect,ps + cap electrode,poly2,el,p2 + cap electrodecontact,poly2contact,poly2c,p2c,elc + cap p2m12contact,p2m12c + cap electrodecap,ecap,poly2cap,p2cap,pcap + contact genericpoly2contact,gc2 + active ntransistor,nfet + active ptransistor,pfet + active diffusion,diff + active transistor,fet + active ndiffusion,ndif,green + active pdiffusion,pdif,brown + active ndcontact,ndc + active pdcontact,pdc + active psubstratepdiff,pohmicdiff,pod,ppdiff,ppd,psd + active nsubstratendiff,nohmicdiff,nod,nndiff,nnd,nsd + active psubstratepcontact,pohmiccontact,poc,pwcontact,pwc,psc + active nsubstratencontact,nohmiccontact,noc,nwcontact,nwc,nsc + active polysilicon,red,poly,p + active polycontact,pcontact,polycut,pc + contact genericcontact,gcontact,gc + metal1 metal1,m1,blue + metal1 pseudo_rmetal1,prm1 + metal1 rmetal1,rm1 + metal1 fillm1,fm1 + metal1 m2contact,m2cut,m2c,via1,v1 + metal2 metal2,m2,purple + metal2 pseudo_rmetal2,prm2 + metal2 rmetal2,rm2 + metal2 fillm2,fm2 + via1 gv1 + metal2 m3contact,m3cut,m3c,via2,v2 + metal3 metal3,m3,cyan + metal3 pseudo_rmetal3,prm3 + metal3 rmetal3,rm3 + metal3 fillm3,fm3 + via2 gv2 + metal3 pad + oxide glass + cap high_resist,hr + cap poly2_high_resist,phr + active pseudo_rpoly,prp + active rpoly,rp + cap pseudo_rpoly2,prp2 + cap rpoly2,rp2 + active pseudo_rndiffusion,prnd + active rndiffusion,rndiff,rnd + active pseudo_rpdiffusion,prpd + active rpdiffusion,rpdiff,rpd + active pseudo_rnwell,prnwell,prnw + active rnwell,rnw + implant filln,fn + fill filla,fa + fill fillb,fb + active fillp,fp + active fillapm,fapm + xp xp + xp m1p + xp m2p + xp m3p + comment comment + comment bb +end + +contact + pc poly metal1 + ndc ndiff metal1 + pdc pdiff metal1 + nsc nsd metal1 + psc psd metal1 + m2c metal1 metal2 + m3c metal2 metal3 + stackable pc m2c pm12contact,pm12c + stackable pdc m2c pdm12contact,pdm12c + stackable psc m2c psm12contact,psm12c,pom12c,pwm12c + stackable ndc m2c ndm12contact,ndm12c + stackable nsc m2c nsm12contact,nsm12c,nom12c,nwm12c + stackable m2c m3c m123contact,m123c +end + +styles + styletype mos + nwell 12 + pwell 13 + nfi 53 + pfi 54 + nselect 43 + pselect 44 + diff 25 + tran 2 4 + ndiff 2 + pdiff 4 + nsd 3 + psd 5 + nfet 6 7 + pfet 8 9 + ndc 2 20 32 + pdc 4 20 32 + nsc 3 20 32 + psc 5 20 32 + poly 1 + pcontact 1 20 32 + gc 32 + metal1 20 + rm1 20 48 + prm1 48 + m1p 20 34 + fm1 20 34 + fp 1 34 + fa 32 + fb 45 34 + fn 45 34 + fapm 1 20 21 34 + gv1 55 + m2contact 20 21 55 + p2m12contact 14 20 21 32 55 + metal2 21 + rm2 21 48 + prm2 48 + m2p 21 34 + fm2 21 34 + gv2 56 + m3contact 21 22 56 + metal3 22 + rm3 22 48 + prm3 48 + m3p 22 34 + fm3 22 34 + pad 22 23 34 38 + glass 34 + xp 25 34 + ecap 10 14 + poly2 14 + p2c 14 20 32 + gc2 19 + hr 10 + phr 14 48 + rp 47 48 + prp 48 + rp2 14 48 + prp2 48 + rnd 2 48 + prnd 48 + rpd 4 53 + prpd 53 + rnw 12 53 + prnw 54 + comment 45 + bb 32 + error_p 42 + error_s 42 + error_ps 42 + magnet 54 + rotate 57 + fence 59 +end + +compose + compose nfet poly ndiff + compose pfet poly pdiff + paint diff nselect ndiff + paint diff pselect pdiff + compose tran poly diff + paint tran nselect nfet + paint tran pselect pfet + paint psd ns ndiff + paint nsd ps pdiff + paint ndiff ps psd + paint pdiff ns nsd + paint pad m1 pad + paint pad m2 pad + paint pad m2c pad + paint pfi nwell nfi + paint nfi pwell pfi + paint ndc nwell pdc + paint nfet nwell pfet + paint ndiff nwell pdiff + paint psd nwell nsd + paint psc nwell nsc + paint pdc pwell ndc + paint pfet pwell nfet + paint pdiff pwell ndiff + paint nsd pwell psd + paint nsc pwell psc + paint poly2 poly ecap + erase ecap poly poly2 + paint p2c poly2 p2c + paint p2c ecap p2c + paint p2m12c poly2 p2m12c + paint p2m12c ecap p2m12c + paint pad m3 pad + compose phr poly2 hr + paint hr poly2 phr + paint poly2 hr phr + erase phr hr poly2 +#CRE/CRM + compose rm1 prm1 m1 + compose rm2 prm2 m2 + compose rm3 prm3 m3 + compose rp prp poly + compose rp2 prp2 poly2 + compose rnd prnd ndiff + compose rpd prpd pdiff + paint nwell rnw space + paint nwell prnw space + paint poly fp fp + paint m1 fm1 fm1 + paint m2 fm2 fm2 + paint m3 fm3 fm3 +end + +connect + nwell,nsc/a,nsd nwell,nsc/a,nsd + pwell,psc/a,psd pwell,psc/a,psd + m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 + m2,fm2,fapm,m2c/m2,m3c/m2,m3c/m2 m2,fm2,fapm,m2c/m2,m3c/m2,m3c/m2 + m3,fm3,fapm,m3c/m3 m3,fm3,fapm,m3c/m3 + ndiff,ndc/a,pdiff,pdc/a ndiff,ndc/a,pdiff,pdc/a + poly,fp,nfet,pfet,fet,fapm,pc/a poly,fp,nfet,pfet,fet,fapm,pc/a + gc2 poly2,ecap,metal1 + p2c poly2,ecap,m1,fm1,fapm,m2c/m1 + p2m12c poly2,ecap,m1,fm1,fapm,m2c/m1,m2,fm2,fapm,m2c/m2,m3c/m2 + poly2,ecap,p2c,p2m12c poly2,ecap,p2c,p2m12c + gc2 poly2,ecap,m1,fm1,fapm,m2c/m1 + gc poly,fp,ndiff,pdiff,nsd,psd,m1,fm1,fapm,m2c/m1 + gv1 m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2,fm2,fapm,m3c/m2 + gv2 m2,fm2,fapm,m2c/m2,m3c/m2,m3,fm3,fapm + pad m1,fm1,m2,fm2,m3,fm3 + rm1 prm1 + rm2 prm2 + rm3 prm3 + rnw prnw + rp prp + rp2 prp2 + rnd prnd + rpd prpd + phr hr +end + +cifoutput + +style lambda=0.30(p) + scalefactor 30 15 + + # This is a custom section to add bounding boxes in OpenRAM + layer BB bb + labels bb + calma 63 0 + + layer CWN nwell,rnw + bloat-or pdiff,rpd,pdc/a,pfet * 180 + bloat-or nsd,nsc/a * 90 + bloat-or nfi * 120 + grow 90 + shrink 90 + labels nwell,rnw + calma 42 0 + + layer CWP pwell + bloat-or ndiff,rnd,ndc/a,nfet * 180 + bloat-or psd,psc/a * 90 + bloat-or pfi * 120 + grow 90 + shrink 90 + and-not CWN + labels pwell + calma 41 0 + + templayer TNS ns + + templayer TPS ps + +#we give priority to selects autogenerated around diffusions (vrs. ohmics) +#XDP = (pdiff*60) Or ps +#XDN = (ndiff*60) Or ns +#FSP = ((pdiff*60,psc*60) Or XDP And-Not XDN Or ps shrink-grow +#FSN = ((ndiff*60,nsc*60) Or XDN And-Not FDP Or ns shrink-grow +#CSN = FSN +#CSP = FSP + +#diffusion auto-nselect (will have priority) + templayer XDN + bloat-or ndiff,rnd,ndc/a * 60 psd,psc/a 0 + or TNS + +#diffusion auto-pselect (will have priority) + templayer XDP + bloat-or pdiff,rpd,pdc/a * 60 nsd,nsc/a 0 + or TPS + +#final pselect + templayer FSP + bloat-or pdiff,rpd,pfet,psd,pdc/a,psc/a,pfet * 60 ndiff,rnd,ndc/a,nsd,nsc/a,nfet 0 + or XDP +#give diff nselect priority + and-not XDN + or TPS + shrink 15 + grow 15 + grow 15 + shrink 15 + +#final nselect + templayer FSN + bloat-or ndiff,rnd,nfet,nsd,ndc/a,nsc/a,nfet * 60 pdiff,rpd,pdc/a,psd,psc/a,pfet 0 + or XDN +#never conflict with final pselect + and-not FSP +#drawn select always goes + or TNS + shrink 15 + grow 15 + grow 15 + shrink 15 + + layer CSN FSN + calma 45 0 + + layer CSP FSP + calma 44 0 + + layer CAA diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + labels diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + calma 43 0 + + layer CCA ndc/m1,nsc/m1 + squares 30 60 90 + calma 48 0 + + layer CCA pdc/m1,psc/m1 + squares 30 60 90 + calma 48 0 + + layer CPG poly,rp,nfet,pfet,fet,pc/a + labels poly,rp,nfet,pfet,fet,pc/a + calma 46 0 + + layer CCP pc/m1 + squares 30 60 90 + calma 47 0 + + layer CCE gc2 + squares 0 60 90 + calma 55 0 + + layer CCE p2c,p2m12c + squares 30 60 90 + calma 55 0 + + layer CCE gc2 + squares 0 60 90 + calma 55 0 + + layer CCC gc + squares 0 60 90 + calma 25 0 + + layer CV1 m2c/m1,p2m12c + squares 30 60 90 + calma 50 0 + + layer CV1 gv1 + squares 0 60 90 + calma 50 0 + + layer CV2 m3c/m2 + squares 30 60 90 + calma 61 0 + + layer CV2 gv2 + squares 0 60 90 + calma 61 0 + + + templayer XPAD1 pad + shrink 180 + + templayer XPAD2 XPAD1 + shrink 180 + + layer CM3 pad + labels pad + calma 62 0 + + layer CV2 XPAD2 + squares 240 60 300 + calma 61 0 + + layer CM2 pad + labels pad + calma 51 0 + + layer CV1 XPAD2 + squares 60 60 300 + calma 50 0 + + layer CM1 pad + calma 49 0 + + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + calma 49 0 + + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + calma 51 0 + + layer CMFP m1p + labels m1p + calma 81 0 + + layer CMSP m2p + labels m2p + calma 82 0 + + layer 100 fp + labels fp + calma 100 0 + + layer 101 fm1 + labels fm1 + calma 101 0 + + layer 102 fm2 + labels fm2 + calma 102 0 + + layer 103 fm3 + labels fm3 + calma 103 0 + + layer 109 fa + or fb + squares 0 210 120 + labels fa + calma 109 0 + + layer 119 fn + calma 119 0 + + layer 110 fapm + labels fapm + calma 110 0 + +# layer CPG fp + layer CPG fp,fapm + squares 0 210 120 + labels fp + calma 46 0 + +# layer CM1 fm1 + layer CM1 fm1,fapm + squares 0 210 120 + labels fm1 + calma 49 0 + +# layer CM2 fm2 + layer CM2 fm2,fapm + + squares 0 210 120 + labels fm2 + calma 51 0 + +# layer CM3 fm3 + layer CM3 fm3,fapm + + squares 0 210 120 + labels fm3 + calma 62 0 + + layer CM3 m3,rm3,m3c/m3 + labels m3,rm3,m3c/m3 + calma 62 0 + + layer CMTP m3p + labels m3p + calma 83 0 + + layer COG pad + shrink 600 + labels pad + calma 52 0 + + layer COG glass + labels glass + calma 52 0 + + layer CFI nfi,pfi + labels nfi,pfi + calma 27 0 + + layer CHR hr,phr + labels hr,phr + calma 34 0 + + layer CEL poly2,ecap,phr,p2c,p2m12c + labels poly2,ecap,phr,p2c,p2m12c + calma 56 0 + +#CRE/CRM + layer CRW rnw,prnw + labels rnw,prnw + calma 65 0 + layer CRG rp,prp + labels rp,prp + calma 67 0 + layer CRD rnd,rpd,prnd,prpd + labels rnd,rpd,prnd,prpd + calma 66 0 + layer CRE rnw,rp,rnd,rpd,rp2 + labels rnw,rp,rnd,rpd,rp2 + calma 64 0 + layer CRF rm1,prm1 + labels rm1,prm1 + calma 71 0 + layer CRS rm2,prm2 + labels rm2,prm2 + calma 72 0 + layer CRG2 rp2,prp2 + labels rp2,prp2 + calma 68 0 + layer CRT rm3,prm3 + labels rm3,prm3 + calma 73 0 +#CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 +#CRE/CRM calma 70 0 + + layer CX comment + labels comment + calma 63 0 + + layer XP pad,xp + labels pad,xp + calma 26 0 + +style fill-only + scalefactor 30 15 + + layer 100 fp + calma 100 0 + + layer 101 fm1 + calma 101 0 + + layer 102 fm2 + calma 102 0 + + layer 103 fm3 + calma 103 0 + + layer 109 fa + or fb + calma 109 0 + + layer 119 fn + calma 119 0 + +style fapm-boxes + +# this output style creates fill boxes automatically (to meet minimum +# density requirements for poly and metal layers) 5 microns outside of +# drawn layout IF: 1. you have a flattened version of your chip +# 2. over which you paint the special fill layer 'fa', preferably with +# a size that is a multiple of 7 + n * (7 + 4), 3. set 'cif +# ostype fapm-boxes' and cif out to a file (this actually creates the +# fill boxes on cif/strm layer '110' using the magic 'squares' +# command), 4. cif in the resulting file (which creates boxes on magic +# layer 'fapm') and place this cell onto your chip (and verify absence +# of drc errors or shorts), then 5. cif out under your regular cif out +# style, where the 'fapm' layer creates fill boxes on poly and all +# metal layers. + + scalefactor 30 15 + + templayer CRIT fapm,fn,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet,poly,rp,nfet,pfet,fet,pc/a,poly2,ecap,phr,p2c,p2m12c + or fm1,m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + or fm2,m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + or fm3,m3,rm3,m3c/m3 + or glass,pad + grow 510 + and fa + + layer 110 fa + squares 0 210 120 + and-not CRIT + shrink 90 + grow 90 + or fapm + labels fapm + calma 110 0 + +style fapm-stripes + scalefactor 30 15 + +# this output style creates the above layer 110 as stripes for reduced size +# HOWEVER it requires each 'fa' box to first be an exact multiple as above +# and then *replacing* the left side (1-lambda wide) stripe of each 'fa' box +# to be a 1-lambda wide layer 'fb' box -- else you won't get strips! + + templayer CRIT fapm,fn,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet,poly,rp,nfet,pfet,fet,pc/a,poly2,ecap,phr,p2c,p2m12c + or fm1,m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + or fm2,m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + or fm3,m3,rm3,m3c/m3 + or glass,pad + grow 510 + and fa + + templayer FB fa + or fb + squares 0 210 120 + and-not CRIT + + layer 110 fa + squares 0 210 120 + and-not CRIT + or FB + shrink 90 + grow 90 + or fapm + labels fapm + calma 110 0 + + +style lambda=0.30(cp) + scalefactor 30 15 + + layer CWN nwell,rnw + bloat-or pdiff,rpd,pdc/a,pfet * 180 + bloat-or nsd,nsc/a * 90 + bloat-or nfi * 120 + grow 90 + shrink 90 + labels nwell,rnw + calma 42 0 + + layer CWP pwell + bloat-or ndiff,rnd,ndc/a,nfet * 180 + bloat-or psd,psc/a * 90 + bloat-or pfi * 120 + grow 90 + shrink 90 + and-not CWN + labels pwell + calma 41 0 + + templayer TNS ns + + templayer TPS ps + +#we give priority to selects autogenerated around diffusions (vrs. ohmics) +#XDP = (pdiff*60) Or ps +#XDN = (ndiff*60) Or ns +#FSP = ((pdiff*60,psc*60) Or XDP And-Not XDN Or ps shrink-grow +#FSN = ((ndiff*60,nsc*60) Or XDN And-Not FDP Or ns shrink-grow +#CSN = FSN +#CSP = FSP + +#diffusion auto-nselect (will have priority) + templayer XDN + bloat-or ndiff,rnd,ndc/a * 60 psd,psc/a 0 + or TNS + +#diffusion auto-pselect (will have priority) + templayer XDP + bloat-or pdiff,rpd,pdc/a * 60 nsd,nsc/a 0 + or TPS + +#final pselect + templayer FSP + bloat-or pdiff,rpd,pfet,psd,pdc/a,psc/a,pfet * 60 ndiff,rnd,ndc/a,nsd,nsc/a,nfet 0 + or XDP +#give diff nselect priority + and-not XDN + or TPS + shrink 15 + grow 15 + grow 15 + shrink 15 + +#final nselect + templayer FSN + bloat-or ndiff,rnd,nfet,nsd,ndc/a,nsc/a,nfet * 60 pdiff,rpd,pdc/a,psd,psc/a,pfet 0 + or XDN +#never conflict with final pselect + and-not FSP +#drawn select always goes + or TNS + shrink 15 + grow 15 + grow 15 + shrink 15 + + layer CSN FSN + calma 45 0 + + layer CSP FSP + calma 44 0 + + layer CAA diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + labels diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + calma 43 0 + + layer CCC ndc/m1,nsc/m1 + squares 30 60 90 + calma 25 0 + + layer CCC pdc/m1,psc/m1 + squares 30 60 90 + calma 25 0 + + layer CPG poly,rp,nfet,pfet,fet,pc/a + labels poly,rp,nfet,pfet,fet,pc/a + calma 46 0 + + layer CCC pc/m1 + squares 30 60 90 + calma 25 0 + + layer CCC gc2 + squares 0 60 90 + calma 25 0 + + layer CCC p2c,p2m12c + squares 30 60 90 + calma 25 0 + + layer CCC gc2 + squares 0 60 90 + calma 25 0 + + layer CCC gc + squares 0 60 90 + calma 25 0 + + layer CV1 m2c/m1,p2m12c + squares 30 60 90 + calma 50 0 + + layer CV1 gv1 + squares 0 60 90 + calma 50 0 + + layer CV2 m3c/m2 + squares 30 60 90 + calma 61 0 + + layer CV2 gv2 + squares 0 60 90 + calma 61 0 + + + templayer XPAD1 pad + shrink 180 + + templayer XPAD2 XPAD1 + shrink 180 + + layer CM3 pad + labels pad + calma 62 0 + + layer CV2 XPAD2 + squares 240 60 300 + calma 61 0 + + layer CM2 pad + labels pad + calma 51 0 + + layer CV1 XPAD2 + squares 60 60 300 + calma 50 0 + + layer CM1 pad + calma 49 0 + + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + calma 49 0 + + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + calma 51 0 + + layer CMFP m1p + labels m1p + calma 81 0 + + layer CMSP m2p + labels m2p + calma 82 0 + + layer 100 fp + labels fp + calma 100 0 + + layer 101 fm1 + labels fm1 + calma 101 0 + + layer 102 fm2 + labels fm2 + calma 102 0 + + layer 103 fm3 + labels fm3 + calma 103 0 + + layer 109 fa + or fb + squares 0 210 120 + labels fa + calma 109 0 + + layer 119 fn + calma 119 0 + + layer 110 fapm + labels fapm + calma 110 0 + +# layer CPG fp + layer CPG fp,fapm + squares 0 210 120 + labels fp + calma 46 0 + +# layer CM1 fm1 + layer CM1 fm1,fapm + squares 0 210 120 + labels fm1 + calma 49 0 + +# layer CM2 fm2 + layer CM2 fm2,fapm + + squares 0 210 120 + labels fm2 + calma 51 0 + +# layer CM3 fm3 + layer CM3 fm3,fapm + + squares 0 210 120 + labels fm3 + calma 62 0 + + layer CM3 m3,rm3,m3c/m3 + labels m3,rm3,m3c/m3 + calma 62 0 + + layer CMTP m3p + labels m3p + calma 83 0 + + layer COG pad + shrink 600 + labels pad + calma 52 0 + + layer COG glass + labels glass + calma 52 0 + + layer CFI nfi,pfi + labels nfi,pfi + calma 27 0 + + layer CHR hr,phr + labels hr,phr + calma 34 0 + + layer CEL poly2,ecap,phr,p2c,p2m12c + labels poly2,ecap,phr,p2c,p2m12c + calma 56 0 + +#CRE/CRM + layer CRW rnw,prnw + labels rnw,prnw + calma 65 0 + layer CRG rp,prp + labels rp,prp + calma 67 0 + layer CRD rnd,rpd,prnd,prpd + labels rnd,rpd,prnd,prpd + calma 66 0 + layer CRE rnw,rp,rnd,rpd,rp2 + labels rnw,rp,rnd,rpd,rp2 + calma 64 0 + layer CRF rm1,prm1 + labels rm1,prm1 + calma 71 0 + layer CRS rm2,prm2 + labels rm2,prm2 + calma 72 0 + layer CRG2 rp2,prp2 + labels rp2,prp2 + calma 68 0 + layer CRT rm3,prm3 + labels rm3,prm3 + calma 73 0 +#CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 +#CRE/CRM calma 70 0 + + layer CX comment + labels comment + calma 63 0 + + layer XP pad,xp + labels pad,xp + calma 26 0 + + +style lambda=0.30(c) + scalefactor 30 15 + + layer CWN nwell,rnw + bloat-or pdiff,rpd,pdc/a,pfet * 180 + bloat-or nsd,nsc/a * 90 + bloat-or nfi * 120 + grow 90 + shrink 90 + labels nwell,rnw + calma 42 0 + + templayer TNS ns + + templayer TPS ps + +#we give priority to selects autogenerated around diffusions (vrs. ohmics) +#XDP = (pdiff*60) Or ps +#XDN = (ndiff*60) Or ns +#FSP = ((pdiff*60,psc*60) Or XDP And-Not XDN Or ps shrink-grow +#FSN = ((ndiff*60,nsc*60) Or XDN And-Not FDP Or ns shrink-grow +#CSN = FSN +#CSP = FSP + +#diffusion auto-nselect (will have priority) + templayer XDN + bloat-or ndiff,rnd,ndc/a * 60 psd,psc/a 0 + or TNS + +#diffusion auto-pselect (will have priority) + templayer XDP + bloat-or pdiff,rpd,pdc/a * 60 nsd,nsc/a 0 + or TPS + +#final pselect + templayer FSP + bloat-or pdiff,rpd,pfet,psd,pdc/a,psc/a,pfet * 60 ndiff,rnd,ndc/a,nsd,nsc/a,nfet 0 + or XDP +#give diff nselect priority + and-not XDN + or TPS + shrink 15 + grow 15 + grow 15 + shrink 15 + +#final nselect + templayer FSN + bloat-or ndiff,rnd,nfet,nsd,ndc/a,nsc/a,nfet * 60 pdiff,rpd,pdc/a,psd,psc/a,pfet 0 + or XDN +#never conflict with final pselect + and-not FSP +#drawn select always goes + or TNS + shrink 15 + grow 15 + grow 15 + shrink 15 + + layer CSN FSN + calma 45 0 + + layer CSP FSP + calma 44 0 + + layer CAA diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + labels diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + calma 43 0 + + layer CCC ndc/m1,nsc/m1 + squares 30 60 90 + calma 25 0 + + layer CCC pdc/m1,psc/m1 + squares 30 60 90 + calma 25 0 + + layer CPG poly,rp,nfet,pfet,fet,pc/a + labels poly,rp,nfet,pfet,fet,pc/a + calma 46 0 + + layer CCC pc/m1 + squares 30 60 90 + calma 25 0 + + layer CCC gc2 + squares 0 60 90 + calma 25 0 + + layer CCC p2c,p2m12c + squares 30 60 90 + calma 25 0 + + layer CCC gc2 + squares 0 60 90 + calma 25 0 + + layer CCC gc + squares 0 60 90 + calma 25 0 + + layer CV1 m2c/m1,p2m12c + squares 30 60 90 + calma 50 0 + + layer CV1 gv1 + squares 0 60 90 + calma 50 0 + + layer CV2 m3c/m2 + squares 30 60 90 + calma 61 0 + + layer CV2 gv2 + squares 0 60 90 + calma 61 0 + + + templayer XPAD1 pad + shrink 180 + + templayer XPAD2 XPAD1 + shrink 180 + + layer CM3 pad + labels pad + calma 62 0 + + layer CV2 XPAD2 + squares 240 60 300 + calma 61 0 + + layer CM2 pad + labels pad + calma 51 0 + + layer CV1 XPAD2 + squares 60 60 300 + calma 50 0 + + layer CM1 pad + calma 49 0 + + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + calma 49 0 + + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + calma 51 0 + + layer CMFP m1p + labels m1p + calma 81 0 + + layer CMSP m2p + labels m2p + calma 82 0 + + layer 100 fp + labels fp + calma 100 0 + + layer 101 fm1 + labels fm1 + calma 101 0 + + layer 102 fm2 + labels fm2 + calma 102 0 + + layer 103 fm3 + labels fm3 + calma 103 0 + + layer 109 fa + or fb + squares 0 210 120 + labels fa + calma 109 0 + + layer 119 fn + calma 119 0 + + layer 110 fapm + labels fapm + calma 110 0 + +# layer CPG fp + layer CPG fp,fapm + squares 0 210 120 + labels fp + calma 46 0 + +# layer CM1 fm1 + layer CM1 fm1,fapm + squares 0 210 120 + labels fm1 + calma 49 0 + +# layer CM2 fm2 + layer CM2 fm2,fapm + + squares 0 210 120 + labels fm2 + calma 51 0 + +# layer CM3 fm3 + layer CM3 fm3,fapm + + squares 0 210 120 + labels fm3 + calma 62 0 + + layer CM3 m3,rm3,m3c/m3 + labels m3,rm3,m3c/m3 + calma 62 0 + + layer CMTP m3p + labels m3p + calma 83 0 + + layer COG pad + shrink 600 + labels pad + calma 52 0 + + layer COG glass + labels glass + calma 52 0 + + layer CFI nfi,pfi + labels nfi,pfi + calma 27 0 + + layer CHR hr,phr + labels hr,phr + calma 34 0 + + layer CEL poly2,ecap,phr,p2c,p2m12c + labels poly2,ecap,phr,p2c,p2m12c + calma 56 0 + +#CRE/CRM + layer CRW rnw,prnw + labels rnw,prnw + calma 65 0 + layer CRG rp,prp + labels rp,prp + calma 67 0 + layer CRD rnd,rpd,prnd,prpd + labels rnd,rpd,prnd,prpd + calma 66 0 + layer CRE rnw,rp,rnd,rpd,rp2 + labels rnw,rp,rnd,rpd,rp2 + calma 64 0 + layer CRF rm1,prm1 + labels rm1,prm1 + calma 71 0 + layer CRS rm2,prm2 + labels rm2,prm2 + calma 72 0 + layer CRG2 rp2,prp2 + labels rp2,prp2 + calma 68 0 + layer CRT rm3,prm3 + labels rm3,prm3 + calma 73 0 +#CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 +#CRE/CRM calma 70 0 + + layer CX comment + labels comment + calma 63 0 + + layer XP pad,xp + labels pad,xp + calma 26 0 + + +style lambda=0.30() + scalefactor 30 15 + + layer CWN nwell,rnw + bloat-or pdiff,rpd,pdc/a,pfet * 180 + bloat-or nsd,nsc/a * 90 + bloat-or nfi * 120 + grow 90 + shrink 90 + labels nwell,rnw + calma 42 0 + + templayer TNS ns + + templayer TPS ps + +#we give priority to selects autogenerated around diffusions (vrs. ohmics) +#XDP = (pdiff*60) Or ps +#XDN = (ndiff*60) Or ns +#FSP = ((pdiff*60,psc*60) Or XDP And-Not XDN Or ps shrink-grow +#FSN = ((ndiff*60,nsc*60) Or XDN And-Not FDP Or ns shrink-grow +#CSN = FSN +#CSP = FSP + +#diffusion auto-nselect (will have priority) + templayer XDN + bloat-or ndiff,rnd,ndc/a * 60 psd,psc/a 0 + or TNS + +#diffusion auto-pselect (will have priority) + templayer XDP + bloat-or pdiff,rpd,pdc/a * 60 nsd,nsc/a 0 + or TPS + +#final pselect + templayer FSP + bloat-or pdiff,rpd,pfet,psd,pdc/a,psc/a,pfet * 60 ndiff,rnd,ndc/a,nsd,nsc/a,nfet 0 + or XDP +#give diff nselect priority + and-not XDN + or TPS + shrink 15 + grow 15 + grow 15 + shrink 15 + +#final nselect + templayer FSN + bloat-or ndiff,rnd,nfet,nsd,ndc/a,nsc/a,nfet * 60 pdiff,rpd,pdc/a,psd,psc/a,pfet 0 + or XDN +#never conflict with final pselect + and-not FSP +#drawn select always goes + or TNS + shrink 15 + grow 15 + grow 15 + shrink 15 + + layer CSN FSN + calma 45 0 + + layer CSP FSP + calma 44 0 + + layer CAA diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + labels diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + calma 43 0 + + layer CCA ndc/m1,nsc/m1 + squares 30 60 90 + calma 48 0 + + layer CCA pdc/m1,psc/m1 + squares 30 60 90 + calma 48 0 + + layer CPG poly,rp,nfet,pfet,fet,pc/a + labels poly,rp,nfet,pfet,fet,pc/a + calma 46 0 + + layer CCP pc/m1 + squares 30 60 90 + calma 47 0 + + layer CCE gc2 + squares 0 60 90 + calma 55 0 + + layer CCE p2c,p2m12c + squares 30 60 90 + calma 55 0 + + layer CCE gc2 + squares 0 60 90 + calma 55 0 + + layer CCC gc + squares 0 60 90 + calma 25 0 + + layer CV1 m2c/m1,p2m12c + squares 30 60 90 + calma 50 0 + + layer CV1 gv1 + squares 0 60 90 + calma 50 0 + + layer CV2 m3c/m2 + squares 30 60 90 + calma 61 0 + + layer CV2 gv2 + squares 0 60 90 + calma 61 0 + + + templayer XPAD1 pad + shrink 180 + + templayer XPAD2 XPAD1 + shrink 180 + + layer CM3 pad + labels pad + calma 62 0 + + layer CV2 XPAD2 + squares 240 60 300 + calma 61 0 + + layer CM2 pad + labels pad + calma 51 0 + + layer CV1 XPAD2 + squares 60 60 300 + calma 50 0 + + layer CM1 pad + calma 49 0 + + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + calma 49 0 + + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + calma 51 0 + + layer CMFP m1p + labels m1p + calma 81 0 + + layer CMSP m2p + labels m2p + calma 82 0 + + layer 100 fp + labels fp + calma 100 0 + + layer 101 fm1 + labels fm1 + calma 101 0 + + layer 102 fm2 + labels fm2 + calma 102 0 + + layer 103 fm3 + labels fm3 + calma 103 0 + + layer 109 fa + or fb + squares 0 210 120 + labels fa + calma 109 0 + + layer 119 fn + calma 119 0 + + layer 110 fapm + labels fapm + calma 110 0 + +# layer CPG fp + layer CPG fp,fapm + squares 0 210 120 + labels fp + calma 46 0 + +# layer CM1 fm1 + layer CM1 fm1,fapm + squares 0 210 120 + labels fm1 + calma 49 0 + +# layer CM2 fm2 + layer CM2 fm2,fapm + + squares 0 210 120 + labels fm2 + calma 51 0 + +# layer CM3 fm3 + layer CM3 fm3,fapm + + squares 0 210 120 + labels fm3 + calma 62 0 + + layer CM3 m3,rm3,m3c/m3 + labels m3,rm3,m3c/m3 + calma 62 0 + + layer CMTP m3p + labels m3p + calma 83 0 + + layer COG pad + shrink 600 + labels pad + calma 52 0 + + layer COG glass + labels glass + calma 52 0 + + layer CFI nfi,pfi + labels nfi,pfi + calma 27 0 + + layer CHR hr,phr + labels hr,phr + calma 34 0 + + layer CEL poly2,ecap,phr,p2c,p2m12c + labels poly2,ecap,phr,p2c,p2m12c + calma 56 0 + +#CRE/CRM + layer CRW rnw,prnw + labels rnw,prnw + calma 65 0 + layer CRG rp,prp + labels rp,prp + calma 67 0 + layer CRD rnd,rpd,prnd,prpd + labels rnd,rpd,prnd,prpd + calma 66 0 + layer CRE rnw,rp,rnd,rpd,rp2 + labels rnw,rp,rnd,rpd,rp2 + calma 64 0 + layer CRF rm1,prm1 + labels rm1,prm1 + calma 71 0 + layer CRS rm2,prm2 + labels rm2,prm2 + calma 72 0 + layer CRG2 rp2,prp2 + labels rp2,prp2 + calma 68 0 + layer CRT rm3,prm3 + labels rm3,prm3 + calma 73 0 +#CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 +#CRE/CRM calma 70 0 + + layer CX comment + labels comment + calma 63 0 + + layer XP pad,xp + labels pad,xp + calma 26 0 + +end + +cifinput + +style lambda=0.30(p) + scalefactor 30 + + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma 63 0 + +layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + layer pwell CWP + and-not CTA + labels CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + calma CSN 45 * + + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer ndc CAA + and CSN + and CCA + and-not CV1 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and-not CV1 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and-not CV1 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and-not CV1 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and-not CV1 + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer ndc CAA + and CSN + and CCA + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and CV1 + and CV2 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and CV1 + and CV2 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and CV1 + and CV2 + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer pc CCP + and-not CV1 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and-not CV1 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer pc CCP + and CV1 + and CV2 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and CV1 + and CV2 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer p2c CCE + and-not CV1 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCE 55 * + + layer p2c CCC + and-not CV1 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer p2c CCE + and CV1 + and CV2 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCE 55 * + + layer p2c CCC + and CV1 + and CV2 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer gc CCP + and-not CPG + and-not CPC + calma CCP 47 * + + layer gc CCP + and-not CM1 + calma CCP 47 * + + layer gc CCA + and-not COP + and-not CAA + and-not CBA + calma CCA 48 * + + layer gc CCA + and-not COP + and-not CM1 + calma CCA 48 * + + layer gc CCC + and-not COP + and-not CPG + and-not CPC + and-not CEL + and-not CAA + and-not CBA + calma CCC 25 * + + layer gc CCC + and-not COP + and-not CM1 + calma CCC 25 * + + layer gc2 CCE + and-not CPC + and-not CEL + calma CCE 55 * + + layer gc2 CCE + and-not CM1 + calma CCE 55 * + + layer gv1 CV1 + and-not COP + and-not CM1 + calma CV1 50 * + + layer gv1 CV1 + and-not COP + and-not CM2 + calma CV1 50 * + + layer gv2 CV2 + and-not COP + and-not CM2 + calma CV2 61 * + + layer gv2 CV2 + and-not COP + and-not CM3 + calma CV2 61 * + + layer m2c CV1 + and-not CV2 + and-not CCC + and-not CCE + and-not CCP + and-not CCA + and-not XP + grow 30 + and CM2 + and CM1 + grow 15 + shrink 15 + calma CV1 50 * + + + + layer p2m12c CV1 + and-not CV2 + and CCE + grow 30 + and CM2 + and CM1 + and CPG + and CEL + grow 15 + shrink 15 + calma CV1 50 * + + layer p2m12c CV1 + and-not CV2 + and CCC + grow 30 + and CM2 + and CM1 + and CPG + and CEL + grow 15 + shrink 15 + calma CV1 50 * + + layer m1 CM1 + and-not CRM + and-not CRF + and-not XP + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer m2 CM2 + and-not CRM + and-not CRS + and-not XP + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + + + + + + + + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer m3c CV2 + + and-not CV1 + and-not XP + grow 30 + and CM3 + and CM2 + grow 15 + shrink 15 + calma CV2 61 * + + + layer m3 CM3 + and-not CRM + and-not CRT + and-not XP + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer pad XP + labels pad + calma XP 26 * + + layer glass COG + and-not COP + and-not XP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(s) + scalefactor 30 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + + ignore CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer nselect CSN + calma CSN 45 * + + layer pselect CSP + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer ndc CAA + and CSN + and CCA + and-not CV1 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and-not CV1 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and-not CV1 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and-not CV1 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and-not CV1 + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer ndc CAA + and CSN + and CCA + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and CV1 + and CV2 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and CV1 + and CV2 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and CV1 + and CV2 + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer pc CCP + and-not CV1 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and-not CV1 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer pc CCP + and CV1 + and CV2 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and CV1 + and CV2 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer p2c CCE + and-not CV1 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCE 55 * + + layer p2c CCC + and-not CV1 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer p2c CCE + and CV1 + and CV2 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCE 55 * + + layer p2c CCC + and CV1 + and CV2 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer gc CCP + and-not CPG + and-not CPC + calma CCP 47 * + + layer gc CCP + and-not CM1 + calma CCP 47 * + + layer gc CCA + and-not COP + and-not CAA + and-not CBA + calma CCA 48 * + + layer gc CCA + and-not COP + and-not CM1 + calma CCA 48 * + + layer gc CCC + and-not COP + and-not CPG + and-not CPC + and-not CEL + and-not CAA + and-not CBA + calma CCC 25 * + + layer gc CCC + and-not COP + and-not CM1 + calma CCC 25 * + + layer gc2 CCE + and-not CPC + and-not CEL + calma CCE 55 * + + layer gc2 CCE + and-not CM1 + calma CCE 55 * + + layer gv1 CV1 + and-not COP + and-not CM1 + calma CV1 50 * + + layer gv1 CV1 + and-not COP + and-not CM2 + calma CV1 50 * + + layer gv2 CV2 + and-not COP + and-not CM2 + calma CV2 61 * + + layer gv2 CV2 + and-not COP + and-not CM3 + calma CV2 61 * + + layer m2c CV1 + and-not CV2 + and-not CCC + and-not CCE + and-not CCP + and-not CCA + and-not XP + grow 30 + and CM2 + and CM1 + grow 15 + shrink 15 + calma CV1 50 * + + + + layer p2m12c CV1 + and-not CV2 + and CCE + grow 30 + and CM2 + and CM1 + and CPG + and CEL + grow 15 + shrink 15 + calma CV1 50 * + + layer p2m12c CV1 + and-not CV2 + and CCC + grow 30 + and CM2 + and CM1 + and CPG + and CEL + grow 15 + shrink 15 + calma CV1 50 * + + layer m1 CM1 + and-not CRM + and-not CRF + and-not XP + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer m2 CM2 + and-not CRM + and-not CRS + and-not XP + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + + + + + + + + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer m3c CV2 + + and-not CV1 + and-not XP + grow 30 + and CM3 + and CM2 + grow 15 + shrink 15 + calma CV2 61 * + + + layer m3 CM3 + and-not CRM + and-not CRT + and-not XP + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer pad XP + labels pad + calma XP 26 * + + layer glass COG + and-not COP + and-not XP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(ps) + scalefactor 30 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + layer pwell CWP + and-not CTA + labels CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer nselect CSN + calma CSN 45 * + + layer pselect CSP + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer ndc CAA + and CSN + and CCA + and-not CV1 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and-not CV1 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and-not CV1 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and-not CV1 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and-not CV1 + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer ndc CAA + and CSN + and CCA + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and CV1 + and CV2 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and CV1 + and CV2 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and CV1 + and CV2 + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer pc CCP + and-not CV1 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and-not CV1 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer pc CCP + and CV1 + and CV2 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and CV1 + and CV2 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer p2c CCE + and-not CV1 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCE 55 * + + layer p2c CCC + and-not CV1 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer p2c CCE + and CV1 + and CV2 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCE 55 * + + layer p2c CCC + and CV1 + and CV2 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer gc CCP + and-not CPG + and-not CPC + calma CCP 47 * + + layer gc CCP + and-not CM1 + calma CCP 47 * + + layer gc CCA + and-not COP + and-not CAA + and-not CBA + calma CCA 48 * + + layer gc CCA + and-not COP + and-not CM1 + calma CCA 48 * + + layer gc CCC + and-not COP + and-not CPG + and-not CPC + and-not CEL + and-not CAA + and-not CBA + calma CCC 25 * + + layer gc CCC + and-not COP + and-not CM1 + calma CCC 25 * + + layer gc2 CCE + and-not CPC + and-not CEL + calma CCE 55 * + + layer gc2 CCE + and-not CM1 + calma CCE 55 * + + layer gv1 CV1 + and-not COP + and-not CM1 + calma CV1 50 * + + layer gv1 CV1 + and-not COP + and-not CM2 + calma CV1 50 * + + layer gv2 CV2 + and-not COP + and-not CM2 + calma CV2 61 * + + layer gv2 CV2 + and-not COP + and-not CM3 + calma CV2 61 * + + layer m2c CV1 + and-not CV2 + and-not CCC + and-not CCE + and-not CCP + and-not CCA + and-not XP + grow 30 + and CM2 + and CM1 + grow 15 + shrink 15 + calma CV1 50 * + + + + layer p2m12c CV1 + and-not CV2 + and CCE + grow 30 + and CM2 + and CM1 + and CPG + and CEL + grow 15 + shrink 15 + calma CV1 50 * + + layer p2m12c CV1 + and-not CV2 + and CCC + grow 30 + and CM2 + and CM1 + and CPG + and CEL + grow 15 + shrink 15 + calma CV1 50 * + + layer m1 CM1 + and-not CRM + and-not CRF + and-not XP + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer m2 CM2 + and-not CRM + and-not CRS + and-not XP + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + + + + + + + + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer m3c CV2 + + and-not CV1 + and-not XP + grow 30 + and CM3 + and CM2 + grow 15 + shrink 15 + calma CV2 61 * + + + layer m3 CM3 + and-not CRM + and-not CRT + and-not XP + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer pad XP + labels pad + calma XP 26 * + + layer glass COG + and-not COP + and-not XP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30() + scalefactor 30 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + + ignore CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + calma CSN 45 * + + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer ndc CAA + and CSN + and CCA + and-not CV1 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and-not CV1 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and-not CV1 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and-not CV1 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and-not CV1 + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and-not CV1 + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer ndc CAA + and CSN + and CCA + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and CV1 + and CV2 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and CV1 + and CV2 + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and CV1 + and CV2 + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and CV1 + and CV2 + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer pc CCP + and-not CV1 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and-not CV1 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer pc CCP + and CV1 + and CV2 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and CV1 + and CV2 + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer p2c CCE + and-not CV1 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCE 55 * + + layer p2c CCC + and-not CV1 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer p2c CCE + and CV1 + and CV2 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCE 55 * + + layer p2c CCC + and CV1 + and CV2 + and CPG + and CEL + and-not CPC + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer gc CCP + and-not CPG + and-not CPC + calma CCP 47 * + + layer gc CCP + and-not CM1 + calma CCP 47 * + + layer gc CCA + and-not COP + and-not CAA + and-not CBA + calma CCA 48 * + + layer gc CCA + and-not COP + and-not CM1 + calma CCA 48 * + + layer gc CCC + and-not COP + and-not CPG + and-not CPC + and-not CEL + and-not CAA + and-not CBA + calma CCC 25 * + + layer gc CCC + and-not COP + and-not CM1 + calma CCC 25 * + + layer gc2 CCE + and-not CPC + and-not CEL + calma CCE 55 * + + layer gc2 CCE + and-not CM1 + calma CCE 55 * + + layer gv1 CV1 + and-not COP + and-not CM1 + calma CV1 50 * + + layer gv1 CV1 + and-not COP + and-not CM2 + calma CV1 50 * + + layer gv2 CV2 + and-not COP + and-not CM2 + calma CV2 61 * + + layer gv2 CV2 + and-not COP + and-not CM3 + calma CV2 61 * + + layer m2c CV1 + and-not CV2 + and-not CCC + and-not CCE + and-not CCP + and-not CCA + and-not XP + grow 30 + and CM2 + and CM1 + grow 15 + shrink 15 + calma CV1 50 * + + + + layer p2m12c CV1 + and-not CV2 + and CCE + grow 30 + and CM2 + and CM1 + and CPG + and CEL + grow 15 + shrink 15 + calma CV1 50 * + + layer p2m12c CV1 + and-not CV2 + and CCC + grow 30 + and CM2 + and CM1 + and CPG + and CEL + grow 15 + shrink 15 + calma CV1 50 * + + layer m1 CM1 + and-not CRM + and-not CRF + and-not XP + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer m2 CM2 + and-not CRM + and-not CRS + and-not XP + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + + + + + + + + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer m3c CV2 + + and-not CV1 + and-not XP + grow 30 + and CM3 + and CM2 + grow 15 + shrink 15 + calma CV2 61 * + + + layer m3 CM3 + and-not CRM + and-not CRT + and-not XP + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer pad XP + labels pad + calma XP 26 * + + layer glass COG + and-not COP + and-not XP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(c) + scalefactor 30 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + + ignore CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + calma CSN 45 * + + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer gc2 CCA + and CEL + calma CCA 48 * + + layer gc2 CCP + and CEL + calma CCP 47 * + + layer gc2 CCC + and CEL + calma CCC 25 * + + layer gc2 CCE + and CEL + calma CCE 55 * + + layer gc2 CCA + and CPC + and-not CPG + calma CCA 48 * + + layer gc2 CCP + and CPC + and-not CPG + calma CCP 47 * + + layer gc2 CCC + and CPC + and-not CPG + calma CCC 25 * + + layer gc2 CCE + and CPC + and-not CPG + calma CCE 55 * + + layer gc CCA + and CPG + and-not CEL + calma CCA 48 * + + layer gc CCP + and CPG + and-not CEL + calma CCP 47 * + + layer gc CCC + and CPG + and-not CEL + calma CCC 25 * + + layer gc CCE + and CPG + and-not CEL + calma CCE 55 * + + layer gc CCA + and-not COP + and-not CPC + and-not CEL + calma CCA 48 * + + layer gc CCP + and-not COP + and-not CPC + and-not CEL + calma CCP 47 * + + layer gc CCC + and-not COP + and-not CPC + and-not CEL + calma CCC 25 * + + layer gc CCE + and-not COP + and-not CPC + and-not CEL + calma CCE 55 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer m1 CM1 + and-not CRM + and-not CRF + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer gv1 CV1 + calma CV1 50 * + + layer m2 CM2 + and-not CRM + and-not CRS + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer gv2 CV2 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer xp XP + calma XP 26 * + + layer glass COG + and-not COP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(cs) + scalefactor 30 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + + ignore CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer nselect CSN + calma CSN 45 * + + layer pselect CSP + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer gc2 CCA + and CEL + calma CCA 48 * + + layer gc2 CCP + and CEL + calma CCP 47 * + + layer gc2 CCC + and CEL + calma CCC 25 * + + layer gc2 CCE + and CEL + calma CCE 55 * + + layer gc2 CCA + and CPC + and-not CPG + calma CCA 48 * + + layer gc2 CCP + and CPC + and-not CPG + calma CCP 47 * + + layer gc2 CCC + and CPC + and-not CPG + calma CCC 25 * + + layer gc2 CCE + and CPC + and-not CPG + calma CCE 55 * + + layer gc CCA + and CPG + and-not CEL + calma CCA 48 * + + layer gc CCP + and CPG + and-not CEL + calma CCP 47 * + + layer gc CCC + and CPG + and-not CEL + calma CCC 25 * + + layer gc CCE + and CPG + and-not CEL + calma CCE 55 * + + layer gc CCA + and-not COP + and-not CPC + and-not CEL + calma CCA 48 * + + layer gc CCP + and-not COP + and-not CPC + and-not CEL + calma CCP 47 * + + layer gc CCC + and-not COP + and-not CPC + and-not CEL + calma CCC 25 * + + layer gc CCE + and-not COP + and-not CPC + and-not CEL + calma CCE 55 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer m1 CM1 + and-not CRM + and-not CRF + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer gv1 CV1 + calma CV1 50 * + + layer m2 CM2 + and-not CRM + and-not CRS + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer gv2 CV2 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer xp XP + calma XP 26 * + + layer glass COG + and-not COP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(cps) + scalefactor 30 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + layer pwell CWP + and-not CTA + labels CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer nselect CSN + calma CSN 45 * + + layer pselect CSP + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer gc2 CCA + and CEL + calma CCA 48 * + + layer gc2 CCP + and CEL + calma CCP 47 * + + layer gc2 CCC + and CEL + calma CCC 25 * + + layer gc2 CCE + and CEL + calma CCE 55 * + + layer gc2 CCA + and CPC + and-not CPG + calma CCA 48 * + + layer gc2 CCP + and CPC + and-not CPG + calma CCP 47 * + + layer gc2 CCC + and CPC + and-not CPG + calma CCC 25 * + + layer gc2 CCE + and CPC + and-not CPG + calma CCE 55 * + + layer gc CCA + and CPG + and-not CEL + calma CCA 48 * + + layer gc CCP + and CPG + and-not CEL + calma CCP 47 * + + layer gc CCC + and CPG + and-not CEL + calma CCC 25 * + + layer gc CCE + and CPG + and-not CEL + calma CCE 55 * + + layer gc CCA + and-not COP + and-not CPC + and-not CEL + calma CCA 48 * + + layer gc CCP + and-not COP + and-not CPC + and-not CEL + calma CCP 47 * + + layer gc CCC + and-not COP + and-not CPC + and-not CEL + calma CCC 25 * + + layer gc CCE + and-not COP + and-not CPC + and-not CEL + calma CCE 55 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer m1 CM1 + and-not CRM + and-not CRF + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer gv1 CV1 + calma CV1 50 * + + layer m2 CM2 + and-not CRM + and-not CRS + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer gv2 CV2 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer xp XP + calma XP 26 * + + layer glass COG + and-not COP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(cp) + scalefactor 30 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + layer pwell CWP + and-not CTA + labels CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + calma CSN 45 * + + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer gc2 CCA + and CEL + calma CCA 48 * + + layer gc2 CCP + and CEL + calma CCP 47 * + + layer gc2 CCC + and CEL + calma CCC 25 * + + layer gc2 CCE + and CEL + calma CCE 55 * + + layer gc2 CCA + and CPC + and-not CPG + calma CCA 48 * + + layer gc2 CCP + and CPC + and-not CPG + calma CCP 47 * + + layer gc2 CCC + and CPC + and-not CPG + calma CCC 25 * + + layer gc2 CCE + and CPC + and-not CPG + calma CCE 55 * + + layer gc CCA + and CPG + and-not CEL + calma CCA 48 * + + layer gc CCP + and CPG + and-not CEL + calma CCP 47 * + + layer gc CCC + and CPG + and-not CEL + calma CCC 25 * + + layer gc CCE + and CPG + and-not CEL + calma CCE 55 * + + layer gc CCA + and-not COP + and-not CPC + and-not CEL + calma CCA 48 * + + layer gc CCP + and-not COP + and-not CPC + and-not CEL + calma CCP 47 * + + layer gc CCC + and-not COP + and-not CPC + and-not CEL + calma CCC 25 * + + layer gc CCE + and-not COP + and-not CPC + and-not CEL + calma CCE 55 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer m1 CM1 + and-not CRM + and-not CRF + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer gv1 CV1 + calma CV1 50 * + + layer m2 CM2 + and-not CRM + and-not CRS + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer gv2 CV2 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer xp XP + calma XP 26 * + + layer glass COG + and-not COP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + +style fill-only + scalefactor 30 +# scalefactor 100 + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + or fb + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + +end + +mzrouter + style irouter +# layer hCost vCost jogCost hintCost + layer metal3 1 2 2 1 + layer metal2 2 1 2 1 + layer metal1 2 3 2 1 + layer poly 10 10 11 1 + contact m3contact metal3 metal2 5 + contact m2contact metal2 metal1 6 + contact pcontact metal1 poly 7 + notactive poly pcontact + +style garouter + layer m2 32 64 256 1 + layer m1 64 32 256 1 + contact m2contact metal1 metal2 1024 + +end + +drc + width nwell 12 \ + "N-well width < 12 (Mosis #1.1)" + + width rnw 12 \ + "rnwell (for resistor L/W extraction) width < 12 (Mosis #1.1)" + + width pwell 12 \ + "P-well width < 12 (Mosis #1.1)" + + width diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a 3 \ + "Diffusion width < 3 (Mosis #2.1)" + + width poly,fp,rp,pc/a,nfet,pfet,fet 2 \ + "Poly width < 2 (Mosis #3.1)" + + width nselect 2 \ + "N-Select width < 2 (Mosis #4.4)" + + width pselect 2 \ + "P-Select width < 2 (Mosis #4.4)" + + width pc/m1 4 \ + "Poly contact width < 4 (Mosis #5.1)" + + + width gc 2 \ + "GC contact width < 2 (Mosis #6.1)" + + width ndc/m1 4 \ + "Diffusion contact width < 4 (Mosis #6.1)" + + + width nsc/m1 4 \ + "Diffusion contact width < 4 (Mosis #6.1)" + + + width pdc/m1 4 \ + "Diffusion contact width < 4 (Mosis #6.1)" + + + width psc/m1 4 \ + "Diffusion contact width < 4 (Mosis #6.1)" + + + width m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 3 \ + "Metal1 width < 3 (Mosis #7.1)" + + width gv1 2 \ + "GV1 via width < 2 (Mosis #8.1)" + + width m2c/m1 4 \ + "Metal2 contact width < 4 (Mosis #8.1)" + + + + + + + + width p2m12c 4 \ + "Metal2 contact width < 4 (Mosis #8.1)" + + width p2m12c 4 \ + "stacked p2m12c width < 4 (Mosis #8.1)" + + width m2,fm2,rm2,m2c/m2,m3c/m2 3 \ + "Metal2 width < 3 (Mosis #9.1)" + + width poly2,ecap,phr,p2c,p2m12c,p2c,p2m12c 5 \ + "Poly2 width < 5 (Mosis #11.1)" + + width gc2 2 \ + "Generic contact2 width < 2 (Mosis #13.1)" + + width p2c 4 \ + "Poly2 contact width < 4 (Mosis #13.1)" + + width p2m12c 4 \ + "Poly2 contact width < 4 (Mosis #13.1)" + + width gv2 2 \ + "GV2 via width < 2 (Mosis #14.1)" + + width m3c/m2 4 \ + "Metal3 contact width < 4 (Mosis #14.1)" + + + width m3,fm3,rm3,m3c/m3,pad 5 \ + "Metal3 width < 5 (Mosis #15.1)" + + width hr,phr 4 \ + "High-Resist width < 4 (Mosis #27.1)" + + width phr 5 \ + "High-Resist poly2R width < 5 (Mosis #27.7)" + + width nfi,pfi 4 \ + "N/P_field-implant width < 4 (Mosis #29.1)" + + spacing nwell nwell 6 touching_ok \ + "N-well(at-same-potential) spacing < 6 (Mosis #1.3)" + + spacing pwell pwell 6 touching_ok \ + "P-well(at-same-potential) spacing < 6 (Mosis #1.3)" + + spacing rnw nwell 18 touching_illegal \ + "rnw (for resistor L/W extraction) spacing to N-well < 18 (Mosis #2.3)" + + edge4way ~(pwell)/well pwell 1 ~(rnw)/active 0 0 \ + "P-well cannot touch rnw (for resistor L/W extraction) (Mosis #1.4)" active + + spacing diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a 3 touching_ok \ + "Diffusion spacing < 3 (Mosis #2.2)" + + spacing nwell ndiff,rnd,nfet,ndc/a 6 touching_illegal \ + "N-well spacing to N-Diffusion < 6 (Mosis #2.3)" + + spacing pwell pdiff,rpd,pfet,pdc/a 6 touching_illegal \ + "P-well spacing to P-Diffusion < 6 (Mosis #2.3)" + + spacing ndiff,rnd,nfet,ndc/a pdiff,rpd,pfet,pdc/a 12 touching_illegal \ + "N-Diffusion spacing to P-Diffusion < 12 (Mosis #2.3+2.3)" + + edge4way ~(nwell)/well nwell 6 ~(pdiff,rpd,pfet,pdc/a)/active nwell 6 \ + "N-well overlap of P-Diffusion < 6 (Mosis #2.4)" active + + edge4way ~(pwell)/well pwell 6 ~(ndiff,rnd,nfet,ndc/a)/active pwell 6 \ + "P-well overlap of N-Diffusion < 6 (Mosis #2.4)" active + + edge4way ~(nwell)/well nwell 3 ~(nsd,nsc/a)/active nwell 3 \ + "N-well overlap of N-Ohmic < 3 (Mosis #2.4)" active + + edge4way ~(pwell)/well pwell 3 ~(psd,psc/a)/active pwell 3 \ + "P-well overlap of P-Ohmic < 3 (Mosis #2.4)" active + + spacing ndiff,rnd,ndc/a nsd,nsc/a 9 touching_illegal \ + "N-Diffusion spacing to N-Ohmic < 9 (Mosis #2.3+2.4)" + + spacing pdiff,rpd,pdc/a psd,psc/a 9 touching_illegal \ + "P-Diffusion spacing to P-Ohmic < 9 (Mosis #2.3+2.4)" + + spacing nwell psd,psc/a 3 touching_illegal \ + "N-well spacing to P-Ohmic < 3 (Mosis #2.4)" + + spacing pwell nsd,nsc/a 3 touching_illegal \ + "P-well spacing to N-Ohmic < 3 (Mosis #2.4)" + + spacing psd,psc/a rnw,prnw 3 touching_illegal \ + "P-Ohmic spacing to rnw,prnw < 3 (Mosis #2.4)" + + spacing nsd,nsc/a psd,psc/a 6 touching_illegal \ + "N-Ohmic spacing to P-Ohmic < 6 (Mosis #2.4+2.4)" + + spacing ndiff,rnd,nfet,ndc/a,nfet psd,psc/a 4 touching_ok \ + "N-Diffusion spacing to P-Ohmic < 4 (Mosis #2.5)" + + spacing pdiff,rpd,pfet,pdc/a,pfet nsd,nsc/a 4 touching_ok \ + "P-Diffusion spacing to N-Ohmic < 4 (Mosis #2.5)" + + spacing poly,rp,pc/a,nfet,pfet,fet poly,rp,pc/a,nfet,pfet,fet 3 touching_ok \ + "Poly spacing < 3 (Mosis #3.2)" + + spacing poly,rp,pc/a,nfet,pfet,fet fp,fapm 3 touching_illegal \ + "Poly spacing to fill layer (fp) < 3 (Mosis #3.2)" + + spacing fp fp 4 touching_ok \ + "Poly fill layer (fp) spacing < 4 (Mosis #0)" + + edge4way nfet,pfet,fet space/active,poly,fp,rp,pc/a 2 poly,fp,rp,pc/a 0 0 \ + "Poly overhang of Transistor < 2 (Mosis #3.3)" active + + edge4way nfet,pfet,fet space/active,ndiff,rnd,ndc/a,pdiff,rpd,pdc/a 3 ndiff,rnd,ndc/a,pdiff,rpd,pdc/a,nfet,pfet,fet 0 0 \ + "N-Diffusion,P-Diffusion overhang of Transistor < 3 (Mosis #3.4)" active + + edge4way poly,fp,rp,pc/a ~(poly,fp,rp,pc/a,nfet,pfet,fet,prp)/active 1 space space 1 \ + "Poly spacing to Diffusion < 1 (Mosis #3.5)" + + edge4way nfet ~(nfet)/active 3 ~(pselect)/select ~(nfet)/active 3 \ + "N-Transistor space to P-Select < 3 (Mosis #4.1)" select + + edge4way pfet ~(pfet)/active 3 ~(nselect)/select ~(pfet)/active 3 \ + "P-Transistor space to N-Select < 3 (Mosis #4.1)" select + + edge4way nfet ~(nfet)/active 3 ~(psd,psc/a)/active ~(nfet)/active 2 \ + "N-Transistor space to P-Ohmic < 3 (Mosis #4.1)" active + + edge4way pfet ~(pfet)/active 3 ~(nsd,nsc/a)/active ~(pfet)/active 2 \ + "P-Transistor space to N-Ohmic < 3 (Mosis #4.1)" active + +#PEZ edge4way psd,psc/a space ~(nfet)/active space \ +#PEZ "P-Ohmic space to N-Transistor < (Mosis #4.1)" active + +#PEZ edge4way nsd,nsc/a space ~(pfet)/active space \ +#PEZ "N-Ohmic space to P-Transistor < (Mosis #4.1)" active + + edge4way ~(nselect,pselect)/select nselect,pselect 2 ~(diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a)/active nselect,pselect 2 \ + "N-Select,P-Select overlap of Diffusion < 2 (Mosis #4.2_)" active + + edge4way space nselect,pselect 2 ~(ndiff,rnd,nfet,ndc/a)/active nselect 2 \ + "N-Select space to N-Diffusion < 2 (Mosis #4.2a)" active + + edge4way nselect,pselect space 2 ~(ndiff,rnd,nfet,ndc/a)/active nselect 2 \ + "N-Select space to N-Diffusion < 2 (Mosis #4.2b)" active + + edge4way nselect,pselect space 2 ~(ndiff,rnd,nfet,ndc/a)/active space,nselect,pselect 2 \ + "N-Select space to N-Diffusion < 2 (Mosis #4.2c)" active + + edge4way space nselect,pselect 2 ~(pdiff,rpd,pfet,pdc/a)/active pselect 2 \ + "P-Select space to P-Diffusion < 2 (Mosis #4.2aa)" active + + edge4way nselect,pselect space 2 ~(pdiff,rpd,pfet,pdc/a)/active pselect 2 \ + "P-Select space to P-Diffusion < 2 (Mosis #4.2bb)" active + + edge4way nselect,pselect space 2 ~(pdiff,rpd,pfet,pdc/a)/active space,nselect,pselect 2 \ + "P-Select space to P-Diffusion < 2 (Mosis #4.2cc)" active + + edge4way diff space 2 nselect space 2 \ + "N-Select must overlap Diffusion by 2 (Mosis #4.2)" select + + edge4way diff space 2 pselect space 2 \ + "P-Select must overlap Diffusion by 2 (Mosis #4.2)" select + + edge4way ndiff,rnd,nfet,ndc/a space 2 ~(pselect)/select space 2 \ + "P-Select space to N-Diffusion < 2 (Mosis #4.2e)" select + + edge4way pdiff,rpd,pfet,pdc/a space 2 ~(nselect)/select space 2 \ + "N-Select space to P-Diffusion < 2 (Mosis #4.2e)" select + + edge4way ~(pdiff,rpd,pfet,pdc/a,psd,psc/a)/active pdiff,rpd,pfet,pdc/a,psd,psc/a 1 ~(nselect)/select 0 0 \ + "N-Select cannot touch P-Diffusion,P-Ohmic (Mosis #4.2f)" select + + edge4way ~(ndiff,rnd,nfet,ndc/a,nsd,nsc/a)/active ndiff,rnd,nfet,ndc/a,nsd,nsc/a 1 ~(pselect)/select 0 0 \ + "P-Select cannot touch N-Diffusion,N-Ohmic (Mosis #4.2f)" select + + width nsd,nsc/a,psd,psc/a 2 \ + "N-Ohmic,P-Ohmic width < 2 (Mosis #4.1)" + + spacing nselect nselect 2 touching_ok \ + "N-Select spacing < 2 (Mosis #4.4)" + + spacing pselect pselect 2 touching_ok \ + "P-Select spacing < 2 (Mosis #4.4)" + + edge4way ndiff,rnd,ndc/a psd,psc/a 2 ~(ndiff,rnd,ndc/a)/active 0 0 \ + "P-Ohmic(that touches N-Diffusion) width < 2 (Mosis #4.4)" + + edge4way pdiff,rpd,pdc/a nsd,nsc/a 2 ~(pdiff,rpd,pdc/a)/active 0 0 \ + "N-Ohmic(that touches P-Diffusion) width < 2 (Mosis #4.4)" + + edge4way gc ~(gc)/contact 1 poly,fp,rp,pc/a,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a ~(gc)/contact 1 \ + "Poly,Diffusion overlap of GC contact < 1 (Mosis #5.2)" active + + edge4way gc space 1 poly,fp,rp,pc/a,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a space 1 \ + "one of: Poly,Diffusion must overlap GC contact by 1 (Mosis #5.2a,6.2a)" active + + edge4way ~(poly,fp,rp,pc/a,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a)/active poly,fp,rp,pc/a,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a 1 ~(gc)/contact 0 0 \ + "Edge to one of: Poly,Diffusion cannot touch GC contact (Mosis #5.2a,6.2a)" contact + + spacing gc gc 3 touching_ok \ + "Generic contact spacing < 3 (Mosis #5.3)" + + edge4way ~(gc)/contact gc 1 ~(ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1)/metal1 0 0 \ + "GC contact cannot touch Metal1 contacts (Mosis #0)" metal1 + + edge4way ~(gc2)/contact gc2 1 ~(ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1)/metal1 0 0 \ + "Generic contact2 cannot touch Metal1 contacts (Mosis #0)" metal1 + + spacing gv1 m2c/m2 2 touching_illegal \ + "GV1 via spacing to Metal2 contacts < 2 (Mosis #14.2)" + + spacing poly,fp,rp,pc/a pc/a 4 touching_ok \ + "Poly spacing to Poly contact < 4 (Mosis #5.5.b)" + + edge4way gc ~(gc)/contact 1 diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,poly,fp,rp,pc/a ~(gc)/contact 1 \ + "Diffusion,Poly overlap of GC contact < 1 (Mosis #6.2)" active + + spacing gc pc/a,ndc/a,pdc/a,psc/a,nsc/a 2 touching_illegal \ + "Generic contact spacing to Poly contact,Diffusion contact < 2 (Mosis #5.3)" + + spacing nsc/m1 pdc/m1 1 touching_illegal \ + "nsc spacing to pdc < 1 (Mosis #6.3)" + + spacing psc/m1 ndc/m1 1 touching_illegal \ + "psc spacing to ndc < 1 (Mosis #6.3)" + + + + + + + + spacing nfet,pfet ndc/a,pdc/a,psc/a,nsc/a 1 touching_illegal \ + "N-Transistor,P-Transistor spacing to Diffusion contact < 1 (Mosis #6.4)" + + spacing nfet,pfet gc 2 touching_illegal \ + "N-Transistor,P-Transistor spacing to Generic contact < 2 (Mosis #6.4)" + + spacing diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a pc/a 1 touching_illegal \ + "Diffusion spacing to Poly contact < 1 (Mosis #6.5.b)" + + spacing diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,nfet,pfet ndc/a,pdc/a,psc/a,nsc/a 4 touching_ok \ + "Diffusion spacing to Diffusion contact < 4 (Mosis #6.5.b)" + + spacing pc/a ndc/a,pdc/a,psc/a,nsc/a 2 touching_illegal \ + "pc/a,pm12c/a spacing to ndc/a,pdc/a,psc/a,nsc/a < 2 (Mosis #6.7)" + + spacing m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 3 touching_ok \ + "Metal1 spacing < 3 (Mosis #7.2)" + + spacing m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 fm1,fapm 3 touching_illegal \ + "Metal1 spacing to fill layer (fm1) < 3 (Mosis #7.2)" + + spacing fm1 fm1 4 touching_ok \ + "Metal1 fill layer (fm1) spacing < 4 (Mosis #0)" + + edge4way gc space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 space 1 \ + "Metal1 must overlap GC contact by 1 (Mosis #7.3,7.4)" metal1 + + edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 1 ~(gc)/contact 0 0 \ + "Metal1(edge) cannot touch GC contact (Mosis #7.3+7.4)" contact + + spacing gv1 gv1 3 touching_ok \ + "GV1 via spacing < 3 (Mosis #8.2)" + + edge4way gv1 ~(gv1)/via1 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 ~(gv1)/via1 1 \ + "Metal1 overlap of GV1 via < 1 (Mosis #8.3)" metal1 + + edge4way gv1 space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 space 1 \ + "Metal1 must overlap GV1 via by 1 (Mosis #8.3)" metal1 + + edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 1 ~(gv1)/via1 0 0 \ + "Metal1(edge) cannot touch GV1 via (Mosis #8.3)" via1 + + spacing m2,rm2,m2c/m2,m3c/m2 m2,rm2,m2c/m2,m3c/m2 3 touching_ok \ + "Metal2 spacing < 3 (Mosis #9.2)" + + spacing m2,rm2,m2c/m2,m3c/m2 fm2,fapm 3 touching_illegal \ + "Metal2 spacing to fill layer (fm2) < 3 (Mosis #9.2)" + + spacing fm2 fm2 4 touching_ok \ + "Metal2 fill layer (fm2) spacing < 4 (Mosis #0)" + + edge4way gv1 space 1 m2,fm2,rm2,m2c/m2,m3c/m2 space 1 \ + "Metal2 must overlap GV1 via by 1 (Mosis #9.3)" metal2 + + edge4way ~(m2,fm2,rm2,m2c/m2,m3c/m2)/metal2 m2,fm2,rm2,m2c/m2,m3c/m2 1 ~(gv1)/via1 0 0 \ + "Metal2(edge) cannot touch GV1 via (Mosis #9.3)" via1 + + width glass 10 \ + "COG width < 10 (Mosis #10.2)" + + edge4way ~(pad)/metal3 pad 20 ~(glass)/oxide pad 20 \ + "pad overlap of COG < 20 (Mosis #10.3)" oxide + + spacing ecap ecap 3 touching_ok \ + "Ecap spacing < 3 (Mosis #11.2)" + + edge4way ecap ~(ecap)/cap 5 poly,fp,rp,pc/a ~(ecap)/cap 5 \ + "Poly overlap of Ecap < 5 (Mosis #11.3)" active + + edge4way ~(ecap)/cap ecap 1 poly,fp,rp,pc/a 0 0 \ + "Ecap must touch Poly (Mosis #11.3x)" active + + edge4way poly2,phr,p2c,p2m12c space 5 ~(poly,fp,rp,pc/a)/active space 5 \ + "Poly2 spacing to Poly < 5 (Mosis #11.3c)" active + + spacing ecap pc/a 2 touching_illegal \ + "Ecap spacing to Poly contact < 2 (Mosis #11.5)" + + spacing ecap gc 3 touching_illegal \ + "Ecap spacing to Generic contact < 3 (Mosis #11.5)" + + spacing poly2,ecap,phr,p2c,p2m12c poly2,ecap,phr,p2c,p2m12c 3 touching_ok \ + "Poly2 spacing < 3 (Mosis #11.2)" + + spacing poly2,ecap,phr,p2c,p2m12c pc/a,ndc/a,pdc/a,psc/a,nsc/a 2 touching_illegal \ + "Poly2 spacing to Poly contact,Diffusion contact < 2 (Mosis #11.5)" + + spacing poly2,ecap,phr,p2c,p2m12c gc,gc 3 touching_illegal \ + "Poly2 spacing to GC contact < 3 (Mosis #11.5)" + + spacing gc2 gc2 3 touching_ok \ + "Generic contact2 spacing < 3 (Mosis #13.2)" + + edge4way ~(ecap)/cap ecap 3 ~(gc2)/contact ecap 3 \ + "Ecap overlap of Generic contact2 < 3 (Mosis #13.3)" contact + + edge4way ~(ecap)/cap ecap 2 ~(p2c,p2m12c)/cap ecap 2 \ + "Ecap overlap of Poly2 contact < 2 (Mosis #13.3)" cap + + edge4way gc2 space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 space 1 \ + "Metal1 must overlap Generic contact2 by 1 (Mosis #13.4)" metal1 + + edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 1 ~(gc2)/contact 0 0 \ + "Metal1(edge) cannot touch Generic contact2 (Mosis #13.4)" contact + + edge4way ~(poly2,ecap,phr,p2c,p2m12c)/cap poly2,ecap,phr,p2c,p2m12c 1 ~(p2c,p2m12c)/cap poly2,ecap,phr,p2c,p2m12c 1 \ + "Poly2 overlap of Poly2 contact < 1 (Mosis #13.4)" cap + + spacing gv2 gv2 3 touching_ok \ + "GV2 via spacing < 3 (Mosis #14.2)" + + spacing gv2 m3c/m2 2 touching_illegal \ + "GV2 via spacing to Metal3 contact < 2 (Mosis #14.2)" + + edge4way gv2 space 1 m2,fm2,rm2,m2c/m2,m3c/m2 space 1 \ + "Metal2 must overlap GV2 via by 1 (Mosis #14.3)" metal2 + + edge4way ~(m2,fm2,rm2,m2c/m2,m3c/m2)/metal2 m2,fm2,rm2,m2c/m2,m3c/m2 1 ~(gv2)/via2 0 0 \ + "Metal2(edge) cannot touch GV2 via (Mosis #14.3)" via2 + + spacing m3,rm3,m3c/m3,pad m3,rm3,m3c/m3,pad 3 touching_ok \ + "Metal3 spacing < 3 (Mosis #15.2)" + + spacing m3,rm3,m3c/m3,pad fm3,fapm 3 touching_illegal \ + "Metal3 spacing to fill layer (fm3) < 3 (Mosis #15.2)" + + spacing fm3 fm3 4 touching_ok \ + "Metal3 fill layer (fm3) spacing < 4 (Mosis #0)" + + edge4way m3c/m2 ~(m3c/m2)/metal2 1 m3,fm3,rm3,m3c/m3,pad ~(m3c/m2)/metal2 1 \ + "Metal3 overlap of Metal3 contact < 1 (Mosis #15.3)" metal3 + + edge4way gv2 space 2 m3,fm3,rm3,m3c/m3,pad space 2 \ + "Metal3 must overlap GV2 via by 2 (Mosis #15.3)" metal3 + + edge4way ~(m3,fm3,rm3,m3c/m3,pad)/metal3 m3,fm3,rm3,m3c/m3,pad 1 ~(gv2)/via2 0 0 \ + "Metal3(edge) cannot touch GV2 via (Mosis #15.3)" via2 + + spacing hr,phr hr,phr 4 touching_ok \ + "High-Resist spacing < 4 (Mosis #27.2)" + + spacing hr,phr,phr p2c,p2m12c 2 touching_illegal \ + "High-Resist spacing to Poly2 contact < 2 (Mosis #27.3)" + + spacing hr,phr,phr gc 2 touching_illegal \ + "High-Resist spacing to GC contact < 2 (Mosis #27.3)" + + edge4way hr,phr space 2 ~(ndiff,rnd,ndc/a,pdiff,rpd,pdc/a)/active 0 2 \ + "High-Resist space to Diffusion < 2 (Mosis #27.4)" active + + spacing hr,phr,phr poly2,ecap,phr,p2c,p2m12c 2 touching_ok \ + "High-Resist spacing to other Poly2 < 2 (Mosis #27.5)" + + edge4way hr,phr space 2 ~(poly2,ecap,phr,p2c,p2m12c)/contact hr,phr 2 \ + "High-Resist space to Poly2 < 2 (Mosis #27.5x)" contact + + spacing nwell phr 4 touching_illegal \ + "N-well spacing to Silicide-Block poly2R < 4 (Mosis #27.6)" + + spacing phr phr 7 touching_ok \ + "High-Resist poly2R spacing < 7 (Mosis #27.13)" + + edge4way phr space/active,hr 2 hr hr 2 \ + "High-Resist overlap of High-Resist poly2R < 2 (Mosis #27.15)" + + spacing nfi nfi 4 touching_ok \ + "N_field-implant spacing < 4 (Mosis #35.2)" + + spacing pfi pfi 4 touching_ok \ + "P_field-implant spacing < 4 (Mosis #35.2)" + + spacing nfi pfi 4 touching_illegal \ + "N_field-implant spacing to P_field-implant < 4 (Mosis #35.2)" + + spacing nwell,pdiff,rpd,pfet,pdc/a pfi 4 touching_illegal \ + "N-well,P-Diffusion spacing to P_field-implant < 4 (Mosis #2.1)" + + spacing pwell,ndiff,rnd,nfet,ndc/a nfi 4 touching_illegal \ + "P-well,N-Diffusion spacing to N_field-implant < 4 (Mosis #2.1)" + + edge4way ~(nwell)/well nwell 4 ~(nfi)/implant nwell 4 \ + "N-well overlap of N_field-implant < 4 (Mosis #21.2)" implant + + edge4way ~(pwell)/well pwell 4 ~(pfi)/implant pwell 4 \ + "P-well overlap of P_field-implant < 4 (Mosis #21.2)" implant + + spacing fa fapm 4 touching_illegal \ + "fill layer fa spacing to fill layer fapm < 4 (Mosis #0)" + + width fa 7 \ + "filla width < 7 (Mosis #0)" + + width fapm 7 \ + "fillapm width < 7 (Mosis #0)" + + width fp 7 \ + "fillp width < 7 (Mosis #0)" + + width fm1 7 \ + "fillm1 width < 7 (Mosis #0)" + + width fm2 7 \ + "fillm2 width < 7 (Mosis #0)" + + width fm3 7 \ + "fillm3 width < 7 (Mosis #0)" + + edge4way fa ~(fa)/fill 1 ~(fa)/fill (~(fa),fa)/fill 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fb ~(fb)/fill 1 ~(fb)/fill (~(fb),fb)/fill 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fapm ~(fapm)/active 1 ~(fapm)/active (~(fapm),fapm)/active 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fp ~(fp)/active 1 ~(fp)/active (~(fp),fp)/active 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fm1 ~(fm1)/metal1 1 ~(fm1)/metal1 (~(fm1),fm1)/metal1 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fm2 ~(fm2)/metal2 1 ~(fm2)/metal2 (~(fm2),fm2)/metal2 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fm3 ~(fm3)/metal3 1 ~(fm3)/metal3 (~(fm3),fm3)/metal3 1 \ + "Contact not rectangular (Magic rule)" + + edge4way rp space/active 1 prp 0 0 \ + "prp overhang of rpoly (for resistor L/W extraction) < 1 (Mosis #0)" active + + edge4way rp2 space/cap 1 prp2 0 0 \ + "prp2 overhang of rpoly2 (for resistor L/W extraction) < 1 (Mosis #0)" cap + + edge4way rnw space/active 1 prnw 0 0 \ + "prnw overhang of rnwell (for resistor L/W extraction) < 1 (Mosis #0)" active + + edge4way rpd space/active 1 prpd 0 0 \ + "prpd overhang of rpdiff (for resistor L/W extraction) < 1 (Mosis #0)" active + + edge4way rnd space/active 1 prnd 0 0 \ + "prnd overhang of rndiff (for resistor L/W extraction) < 1 (Mosis #0)" active + + edge4way rm1 space/metal1 1 prm1 0 0 \ + "prm1 overhang of rmetal1 (for resistor L/W extraction) < 1 (Mosis #0)" metal1 + + edge4way rm2 space/metal2 1 prm2 0 0 \ + "prm2 overhang of rmetal2 (for resistor L/W extraction) < 1 (Mosis #0)" metal2 + + edge4way rm3 space/metal3 1 prm3 0 0 \ + "prm3 overhang of rmetal3 (for resistor L/W extraction) < 1 (Mosis #0)" metal3 + + edge4way ndc/a,nsc/a ~(ndc/a,nsc/a)/active 1 ~(ndc/a,nsc/a)/active (~(ndc/a,nsc/a),ndc/a,nsc/a)/active 1 \ + "Contact not rectangular (Magic rule)" + + edge4way pdc/a,psc/a ~(pdc/a,psc/a)/active 1 ~(pdc/a,psc/a)/active (~(pdc/a,psc/a),pdc/a,psc/a)/active 1 \ + "Contact not rectangular (Magic rule)" + + edge4way pc/a ~(pc/a)/active 1 ~(pc/a)/active (~(pc/a),pc/a)/active 1 \ + "Contact not rectangular (Magic rule)" + + edge4way gc2 ~(gc2)/contact 1 ~(gc2)/contact (~(gc2),gc2)/contact 1 \ + "Contact not rectangular (Magic rule)" + + edge4way p2c,p2m12c ~(p2c,p2m12c)/cap 1 ~(p2c,p2m12c)/cap (~(p2c,p2m12c),p2c,p2m12c)/cap 1 \ + "Contact not rectangular (Magic rule)" + + edge4way gc ~(gc)/contact 1 ~(gc)/contact (~(gc),gc)/contact 1 \ + "Contact not rectangular (Magic rule)" + + edge4way gv1 ~(gv1)/via1 1 ~(gv1)/via1 (~(gv1),gv1)/via1 1 \ + "Contact not rectangular (Magic rule)" + + edge4way m2c/m1 ~(m2c/m1)/metal1 1 ~(m2c/m1)/metal1 (~(m2c/m1),m2c/m1)/metal1 1 \ + "Contact not rectangular (Magic rule)" + + edge4way gv2 ~(gv2)/via2 1 ~(gv2)/via2 (~(gv2),gv2)/via2 1 \ + "Contact not rectangular (Magic rule)" + + edge4way m3c/m2 ~(m3c/m2)/metal2 1 ~(m3c/m2)/metal2 (~(m3c/m2),m3c/m2)/metal2 1 \ + "Contact not rectangular (Magic rule)" + + exact_overlap gc,ndc/a,pdc/a,psc/a,nsc/a,gc,pc/a,gc + + exact_overlap gc2,p2c,p2m12c + + edge4way pad ~(pad)/m3 1 ~(pad)/m3 (~(pad),pad)/m3 1 \ + "Contact not rectangular (Magic rule)" + + exact_overlap ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1 + + exact_overlap m2c/m2 + + exact_overlap m3c/m3 + + exact_overlap gv1 + + exact_overlap gv2 + + + width m1p 4 \ + "Metal1 PIN width < 4 (do_pins)" + + spacing m1p m1p 4 touching_ok \ + "Metal1 PIN spacing < 4 (do_pins)" + + width m2p 4 \ + "Metal2 PIN width < 4 (do_pins)" + + spacing m2p m2p 4 touching_ok \ + "Metal2 PIN spacing < 4 (do_pins)" + + width m3p 6 \ + "Metal3 PIN width < 6 (do_pins)" + + spacing m3p m3p 4 touching_ok \ + "Metal3 PIN spacing < 4 (do_pins)" + +#CC cifstyle lambda=0.30(p) +#CC cifwidth CWN 360 \ +#CC "generated CIF layer CWN width will be < 12 (';cif see CWN')" +#CC cifspacing CWN CWN 180 touching_ok \ +#CC "generated CIF layer CWN spacing will be < 6 (';cif see CWN')" +#CC cifwidth CWP 360 \ +#CC "generated CIF layer CWP width will be < 12 (';cif see CWP')" +#CC cifspacing CWP CWP 180 touching_ok \ +#CC "generated CIF layer CWP spacing will be < 6 (';cif see CWP')" +#CC cifwidth CSN 60 \ +#CC "generated CIF layer CSN width will be < 2 (';cif see CSN')" +#CC cifspacing CSN CSN 60 touching_ok \ +#CC "generated CIF layer CSN spacing will be < 2 (';cif see CSN')" +#CC cifwidth CSP 60 \ +#CC "generated CIF layer CSP width will be < 2 (';cif see CSP')" +#CC cifspacing CSP CSP 60 touching_ok \ +#CC "generated CIF layer CSP spacing will be < 2 (';cif see CSP')" + + stepsize 400 + +end + +#--------------------------------------------------- +# LEF format definitions +#--------------------------------------------------- + +lef + +ignore PC +ignore CA + +routing m1 M1 m1 met1 +routing m2 M2 m2 met2 +routing m3 M3 m3 met3 + +contact m2c via via1 V1 v1 +contact m3c via2 V2 v2 + +end + +extract + style AMI0.5um(amic5)from:T24H + cscale 1 + lambda 30 + step 100 + sidehalo 8 + planeorder well 0 + planeorder implant 1 + planeorder select 2 + planeorder cap 3 + planeorder active 4 + planeorder metal1 5 + planeorder metal2 6 + planeorder metal3 7 + planeorder oxide 8 + planeorder xp 9 + planeorder comment 10 + planeorder contact 11 + planeorder via1 12 + planeorder via2 13 + planeorder fill 14 + + resist (ndiff,rnd,ndc,nsd,nsc)/active 82200 + resist (pdiff,rpd,pdc,psd,psc)/active 105200 + resist (nwell)/well 808000 + resist (rnw)/active 808000 + resist (pwell)/well 1 + resist (poly,fp,rp,pc,pc,nfet,pfet,fet)/active 22000 + resist (poly2,ecap,p2c,p2m12c,p2c,p2m12c)/cap 40300 + resist (phr)/cap 40300 + resist (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c,m2c)/metal1 90 + resist (m2,fm2,rm2,m2c,m3c,m3c)/metal2 90 + resist (m3,fm3,rm3,m3c,pad)/metal3 50 + + contact ndc 4 62700 + contact pdc 4 160000 + contact pc 4 15600 + contact p2c 4 26100 + contact m2c 4 910 + contact m3c 4 830 + + +#poly2 + overlap (poly,fp,rp,pc,pc)/active (poly2,ecap,phr,p2c,p2m12c,p2c,p2m12c)/cap 84.960 + +#nwell,cwell,pwell + areacap (nwell)/well 3.600 + +#rnw + areacap (rnw)/active 3.600 + +#ndiff +# MODEL HANDLES THIS: areacap (ndiff,ndc)/active 38.430 +# MODEL HANDLES THIS: overlap (ndiff,ndc)/active ~space/w 38.430 +# MODEL HANDLES THIS: perimc (ndiff,ndc)/active ~(ndiff,ndc,nfet,pfet,fet)/active 94.800 +# MODEL HANDLES THIS: sideoverlap (ndiff,ndc)/active ~(ndiff,ndc,nfet,pfet,fet)/active ~space/w 94.800 + + areacap (rnd)/active 38.430 + overlap (rnd)/active ~space/w 38.430 + perimc (rnd)/active ~(rnd)/active 94.800 + sideoverlap (rnd)/active ~(rnd)/active ~space/w 94.800 + +#pdiff +# MODEL HANDLES THIS: areacap (pdiff,pdc)/active 65.880 +# MODEL HANDLES THIS: overlap (pdiff,pdc)/active ~space/w 65.880 +# MODEL HANDLES THIS: perimc (pdiff,pdc)/active ~(pdiff,pdc,nfet,pfet,fet)/active 75.300 +# MODEL HANDLES THIS: sideoverlap (pdiff,pdc)/active ~(pdiff,pdc,nfet,pfet,fet)/active ~space/w 75.300 + + areacap (rpd)/active 65.880 + overlap (rpd)/active ~space/w 65.880 + perimc (rpd)/active ~(rpd)/active 75.300 + sideoverlap (rpd)/active ~(rpd)/active ~space/w 75.300 + +#rnw + +#poly +# MODEL HANDLES THIS: overlap (nfet)/active (ndiff,rnd,ndc)/active 221.670 +# MODEL HANDLES THIS: sideoverlap (nfet)/active ~(nfet)/active (ndiff,rnd,ndc)/active 58.500 +# MODEL HANDLES THIS: overlap (pfet)/active (pdiff,rpd,pdc)/active 213.480 +# MODEL HANDLES THIS: sideoverlap (pfet)/active ~(pfet)/active (pdiff,rpd,pdc)/active 82.800 + + areacap (poly,fp,rp,pc)/active 7.740 + overlap (poly,fp,rp,pc)/active ~space/w 7.740 + +#poly2 + +#rnw + +#metal1 + areacap (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 2.700 + +#metal1-sub blocked by ~space/a,~space/c + overlap (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 ~space/w 2.700 ~space/a,~space/c + perimc (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 20.700 + sideoverlap (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 ~space/w 20.700 ~space/a,~space/c + +#rnw + overlap (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 rnw/active 2.700 ~space/c + sideoverlap (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 rnw/active 20.700 ~space/c + +#metal1-diff blocked by ~space/c + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (ndiff,rnd,ndc)/active 3.150 ~space/c + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (ndiff,rnd,ndc)/active 20.700 ~space/c + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (pdiff,rpd,pdc)/active 3.150 ~space/c + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (pdiff,rpd,pdc)/active 20.700 ~space/c + +#metal1-poly blocked by ~space/c + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (poly,fp,rp,pc,nfet,pfet,fet)/active 4.590 ~space/c + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (poly,fp,rp,pc,nfet,pfet,fet)/active 15.900 ~space/c + sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 15.900 ~space/c + +#metal1-poly2 not blocked + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (poly2,ecap,phr,p2c,p2m12c)/cap 3.960 + +#metal2 + areacap (m2,fm2,rm2,m3c)/metal2 1.350 + +#metal2-sub blocked by + overlap (m2,fm2,rm2,m3c)/metal2 ~space/w 1.350 ~space/a,~space/m1,~space/c + perimc (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 15.900 + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 ~space/w 15.900 ~space/a,~space/m1,~space/c + overlap (m2,fm2,rm2,m3c)/metal2 rnw/active 1.350 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 rnw/active 15.900 ~space/m1,~space/c + +#metal2-*diff blocked by ~space/m1,~space/c + overlap (m2,fm2,rm2,m3c)/metal2 (ndiff,rnd,ndc)/active 1.350 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (ndiff,rnd,ndc)/active 15.900 ~space/m1,~space/c + overlap (m2,fm2,rm2,m2c,m3c)/metal2 (pdiff,rpd,pdc)/active 1.350 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (pdiff,rpd,pdc)/active 15.900 ~space/m1,~space/c + +#metal2-poly blocked by ~space/m1,~space/c + overlap (m2,fm2,rm2,m3c)/metal2 (poly,fp,rp,pc,nfet,pfet,fet)/active 1.350 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (poly,fp,rp,pc,nfet,pfet,fet)/active 10.800 ~space/m1,~space/c + sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m2,fm2,rm2,m2c,m3c)/metal2 10.800 ~space/m1,~space/c + +#metal2-poly2 blocked by ~space/m1 + +#M2->M1 + overlap (m2,fm2,rm2,m3c)/metal2 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 2.520 + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 14.700 + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (m2,fm2,rm2,m2c,m3c)/metal2 14.700 + +#metal3 + areacap (m3,fm3,rm3,pad)/metal3 0.900 + +#metal3-sub blocked by ~space/a,~space/m1,~space/m2,~space/c + overlap (m3,fm3,rm3,pad)/metal3 ~space/w 0.900 ~space/a,~space/m1,~space/m2,~space/c + perimc (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 10.500 + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 ~space/w 10.500 ~space/a,~space/m1,~space/m2,~space/c + +#rnw + overlap (m3,fm3,rm3,pad)/metal3 rnw/active 0.900 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 rnw/active 10.500 ~space/m1,~space/m2,~space/c + +#metal3-*diff blocked by ~space/m1,~space/m2,~space/c + overlap (m3,fm3,rm3,pad)/metal3 (ndiff,rnd,ndc)/active 0.990 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (ndiff,rnd,ndc)/active 10.500 ~space/m1,~space/m2,~space/c + overlap (m3,fm3,rm3,pad)/metal3 (pdiff,rpd,pdc)/active 0.990 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (pdiff,rpd,pdc)/active 10.500 ~space/m1,~space/m2,~space/c + +#metal3-poly blocked by ~space/m1,~space/m2,~space/c + overlap (m3,fm3,rm3,pad)/metal3 (poly,fp,rp,pc,nfet,pfet,fet)/active 0.810 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (poly,fp,rp,pc,nfet,pfet,fet)/active 8.100 ~space/m1,~space/m2,~space/c + sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m3,fm3,rm3,m3c,pad)/metal3 8.100 ~space/m1,~space/m2,~space/c + +#metal3-poly2 blocked by ~space/m1,~space/m2 + +#M3->M1 + overlap (m3,fm3,rm3,pad)/metal3 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 1.080 ~space/m2 + +#metal3-metal1 blocked by ~space/m2 + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 9.900 ~space/m2 + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (m3,fm3,rm3,m3c,pad)/metal3 9.900 ~space/m2 + +#M3->M2 + overlap (m3,fm3,rm3,pad)/metal3 (m2,fm2,rm2,m2c,m3c)/metal2 3.060 + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (m2,fm2,rm2,m2c,m3c)/metal2 16.800 + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (m3,fm3,rm3,m3c,pad)/metal3 16.800 + +#metal4 + +#metal5 + +#metal6 + +#metal7 + +#metali + +#fets + +# fet pfet pdiff,pdc 2 pfet Vdd! nwell 83 213 +# fet pfet pdiff,pdc 1 pfet Vdd! nwell 83 213 + + device mosfet pfet pfet pdiff,pdc nwell $VDD 83 213 + +# fet nfet ndiff,ndc 2 nfet Gnd! pwell 59 222 +# fet nfet ndiff,ndc 1 nfet Gnd! pwell 59 222 + + device mosfet nfet nfet ndiff,ndc pwell $GND 59 222 + + fetresis pfet linear 20996 + fetresis pfet saturation 20996 + fetresis nfet linear 6144 + fetresis nfet saturation 6144 + +# fet rnwell nsd,nsc 2 nwellResistor Gnd! nwell,pwell 0 0 +# fet rpoly poly,pc 2 polyResistor Gnd! nwell,pwell 0 0 +# fet rpoly2 poly2,p2c 2 poly2Resistor Gnd! nwell,pwell 0 0 +# fet rndiff ndiff,ndc 2 ndiffResistor Gnd! nwell,pwell 0 0 +# fet rpdiff pdiff,pdc 2 pdiffResistor Gnd! nwell,pwell 0 0 + + device resistor None rnwell nsd,nsc + device resistor None rpoly poly,pc + device resistor None rpoly2 poly2,p2c + device resistor None rndiff ndiff,ndc + device resistor None rpdiff pdiff,pdc + +# fet rmetal1 metal1 2 metal1Resistor Gnd! nwell,pwell 0 0 +# fet rmetal2 metal2 2 metal2Resistor Gnd! nwell,pwell 0 0 +# fet rmetal3 metal3 2 metal3Resistor Gnd! nwell,pwell 0 0 +# fet phr poly2,p2c 2 phrResistor Gnd! nwell,pwell 0 0 + + device resistor None rmetal1 *metal1 + device resistor None rmetal2 *metal2 + device resistor None rmetal3 *metal3 + device resistor None phr poly2,p2c + +end + +wiring + contact pdcontact 4 metal1 0 pdiff 0 + contact ndcontact 4 metal1 0 ndiff 0 + contact pcontact 4 metal1 0 poly 0 + contact m2contact 4 metal1 0 metal2 0 + contact m3contact 5 metal2 0 metal3 1 + +end + +router + layer2 metal2 3 m2,fm2,rm2,m2c/m2,m3c/m2,m3c/m2 4 poly,fp,rp,ndiff,rnd,nsd,pdiff,rpd,psd,m1,fm1,rm1 1 + layer1 metal1 3 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 3 + contacts m2contact 4 + gridspacing 8 + +end + +plowing + fixed nfet,pfet,glass,pad + covered nfet,pfet + drag nfet,pfet + +end + +plot +style colorversatec + ndiff,rnd,ndc/a yellow \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA + ndiff,rnd,ndc/a cyan \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 + nsd,nsc/a yellow \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 + nsd,nsc/a cyan \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 + pdiff,rpd,pdc/a yellow \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA + pdiff,rpd,pdc/a cyan \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 + pdiff,rpd,pdc/a magenta \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 + psd,psc/a yellow \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 + psd,psc/a cyan \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 + psd,psc/a magenta \ + 2A2A 0000 A2A2 0000 \ + 2A2A 0000 A2A2 0000 \ + 2A2A 0000 A2A2 0000 \ + 2A2A 0000 A2A2 0000 + poly,fp,rp,pc/a magenta \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA + nfet yellow \ + 0505 8282 1414 0A0A \ + 5050 2828 4141 A0A0 \ + 0505 8282 1414 0A0A \ + 5050 2828 4141 A0A0 + nfet cyan \ + 0000 0505 0000 1414 \ + 0000 5050 0000 4141 \ + 0000 0505 0000 1414 \ + 0000 5050 0000 4141 + nfet magenta \ + 5050 2828 4141 A0A0 \ + 0505 8282 1414 0A0A \ + 5050 2828 4141 A0A0 \ + 0505 8282 1414 0A0A + pfet yellow \ + 6363 A0A0 5050 2828 \ + 3636 0A0A 0505 8282 \ + 6363 A0A0 5050 2828 \ + 3636 0A0A 0505 8282 + pfet cyan \ + 0000 5151 0000 5454 \ + 0000 1515 0000 1515 \ + 0000 5151 0000 5454 \ + 0000 1515 0000 1515 + pfet magenta \ + 9494 0A0A 2525 8282 \ + 4949 A0A0 5252 2828 \ + 9494 0A0A 2525 8282 \ + 4949 A0A0 5252 2828 + poly2,ecap,phr,p2c,p2m12c yellow \ + FFFF FFFF FFFF FFFF \ + FFFF FFFF FFFF FFFF \ + FFFF FFFF FFFF FFFF \ + FFFF FFFF FFFF FFFF + m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 cyan \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 + m2,fm2,rm2,m2c/m2,m3c/m2 cyan \ + 0000 1111 0000 4444 \ + 0000 1111 0000 4444 \ + 0000 1111 0000 4444 \ + 0000 1111 0000 4444 + m2,fm2,rm2,m2c/m2,m3c/m2 magenta \ + 0000 4444 0000 1111 \ + 0000 4444 0000 1111 \ + 0000 4444 0000 1111 \ + 0000 4444 0000 1111 + m2c/m1,gv1 black \ + 0000 6666 6666 0000 \ + 0000 9999 9999 0000 \ + 0000 6666 6666 0000 \ + 0000 9999 9999 0000 + pad,glass black \ + 0300 0700 0E00 1C00 \ + 3800 7000 E000 C000 \ + 00C0 00E0 0070 0038 \ + 001C 000E 0007 0003 + nwell yellow \ + 0800 1000 2000 4000 \ + 8000 0001 0002 0004 \ + 0008 0010 0020 0040 \ + 0080 0010 0200 0400 + nwell cyan \ + 1000 2000 4000 8000 \ + 0001 0002 0004 0008 \ + 0010 0020 0040 0080 \ + 0100 0200 0400 0800 + pwell yellow \ + 1000 0400 0400 0100 \ + 0100 0040 0040 0010 \ + 0010 0004 0004 0001 \ + 0001 4000 4000 1000 + pwell cyan \ + 0000 0800 0000 0200 \ + 0000 0080 0000 0020 \ + 0000 0008 0000 0002 \ + 0000 8000 0000 2000 + pwell magenta \ + 0800 0000 0200 0000 \ + 0080 0000 0020 0000 \ + 0008 0000 0002 0000 \ + 8000 0000 2000 0000 + m3c/m2,gv2 black \ + 0100 0000 0000 0000 \ + 1010 0000 0000 0000 \ + 0001 0000 0000 0000 \ + 1010 0000 0000 0000 + m3c/m2,gv2 cyan \ + 0280 0000 0820 0000 \ + 2008 0000 8002 0000 \ + 8002 0000 2008 0000 \ + 0820 0000 0280 0000 + m3c/m2,gv2 magenta \ + 0100 06C0 0440 1830 \ + 1010 600C 4004 8003 \ + 0001 C006 4004 3018 \ + 1010 0C60 0440 0380 + m3c/m2,gv2 black \ + 0820 0820 0820 0FE0 \ + E00F 2008 2008 2008 \ + 2008 2008 2008 E00F \ + 0000 0FE0 0820 0820 + error_p,error_s,error_ps black \ + 0000 3C3C 4646 4A4A \ + 5252 6262 3C3C 0000 \ + 0000 3C3C 4646 4A4A \ + 5252 6262 3C3C 0000 + magnet yellow \ + AAAA 0000 5555 0000 \ + AAAA 0000 5555 0000 \ + AAAA 0000 5555 0000 \ + AAAA 0000 5555 0000 + fence magenta \ + FFFF 0000 0000 0000 \ + 0000 0000 0000 0000 \ + FFFF 0000 0000 0000 \ + 0000 0000 0000 0000 + rotate cyan \ + 0000 E0E0 E0E0 E0E0 \ + 0000 0000 0000 0000 \ + 0000 E0E0 E0E0 E0E0 \ + 0000 0000 0000 0000 + pc/a,ndc/a,pdc/a,psc/a,nsc/a,gc,gc,gc X + +style versatec + pfet \ + 07c0 0f80 1f00 3e00 \ + 7c00 f800 f001 e003 \ + c007 800f 001f 003e \ + 00c7 00f8 01f0 03e0 + nfet \ + 1f00 0f80 07c0 03e0 \ + 01f0 00f8 007c 003e \ + 001f 800f c007 e003 \ + f001 f800 7c00 3e00 + gv1 \ + c3c3 c3c3 0000 0000 \ + 0000 0000 c3c3 c3c3 \ + c3c3 c3c3 0000 0000 \ + 0000 0000 c3c3 c3c3 + pwell \ + 2020 2020 2020 2020 \ + 2020 2020 2020 2020 \ + 0000 0000 0000 0000 \ + 0000 0000 0000 0000 + nwell \ + 0808 0404 0202 0101 \ + 0000 0000 0000 0000 \ + 0808 0404 0202 0101 \ + 0000 0000 0000 0000 + poly,fp,rp,pc/a,nfet,pfet \ + 0808 0400 0202 0101 \ + 8080 4000 2020 1010 \ + 0808 0004 0202 0101 \ + 8080 0040 2020 1010 + m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 \ + 8080 0000 0000 0000 \ + 0808 0000 0000 0000 \ + 8080 0000 0000 0000 \ + 0808 0000 0000 0000 + pad,glass \ + 0000 0000 1c1c 3e3e \ + 3636 3e3e 1c1c 0000 \ + 0000 0000 1c1c 3e3e \ + 3636 3e3e 1c1c 0000 + nsd,nsc/a \ + 0808 1414 2222 4141 \ + 8080 4040 2020 1010 \ + 0808 1414 2222 4141 \ + 8080 4040 2020 1010 + m2,fm2,rm2,m2c/m2,m3c/m2 \ + 0000 1111 0000 0000 \ + 0000 1111 0000 0000 \ + 0000 1111 0000 0000 \ + 0000 1111 0000 0000 + pdiff,rpd,pdc/a,pfet \ + 0000 0808 5555 8080 \ + 0000 8080 5555 0808 \ + 0000 0808 5555 8080 \ + 0000 8080 5555 0808 + psd,psc/a \ + 1414 2222 0000 2222 \ + 4141 2222 0000 2222 \ + 1414 2222 0000 2222 \ + 4141 2222 0000 2222 + ndiff,rnd,ndc/a,nfet \ + 0808 1010 2020 4040 \ + 8080 4141 2222 1414 \ + 0808 1010 2020 4040 \ + 8080 4141 2222 1414 + pc/a,ndc/a,pdc/a,psc/a,nsc/a,gc,gc,gc X + +style gremlin + pfet 9 + nfet 10 + gv1 11 + pwell 15 + nwell 16 + poly,fp,rp,pc/a,nfet,pfet 19 + pc/a,ndc/a,pdc/a,psc/a,nsc/a,gc,gc,gc 22 + pad,glass 23 + nsd,nsc/a 24 + gv1 28 + pdiff,rpd,pdc/a,pfet 29 + psd,psc/a 30 + ndiff,rnd,ndc/a,nfet 31 + pc/a,ndc/a,pdc/a,psc/a,nsc/a,gc,gc,gc,gv1 X + +end + diff --git a/technology/scn3me_subm/tech/__init__.py b/technology/scn3me_subm/tech/__init__.py new file mode 100755 index 00000000..2573d2c2 --- /dev/null +++ b/technology/scn3me_subm/tech/__init__.py @@ -0,0 +1,6 @@ +""" +Import tech specific modules. +""" + +from .tech import * + diff --git a/technology/scn3me_subm/tech/calibreDRC_scn3me_subm.rul b/technology/scn3me_subm/tech/calibreDRC_scn3me_subm.rul new file mode 100755 index 00000000..91d35fb4 --- /dev/null +++ b/technology/scn3me_subm/tech/calibreDRC_scn3me_subm.rul @@ -0,0 +1,225 @@ +//////////////////////////////////////////////////////////// +// DEFINE BOOLEAN LAYERS +//////////////////////////////////////////////////////////// +LAYOUT USE DATABASE PRECISION YES + +layer pwell 41 +layer nwell 42 +layer active 43 +layer poly 46 +layer nimplant 45 +layer pimplant 44 +layer contact 25 +layer active_contact 48 +layer poly_contact 47 +layer metal1 49 +layer via1 50 +layer metal2 51 +layer via2 61 +layer metal3 62 +layer glass 52 +layer pad 26 + +//Enabling incremental connectivity for antenna rule checks +DRC Incremental Connect Yes + +well = nwell OR pwell +gate = poly AND active +implant = nimplant OR pimplant +fieldpoly = poly NOT active + +contactenc1 = active OR poly +contactenc = contactenc1 AND metal1 +diode = contact AND active +act_poly = interact poly active + +GROUP mask_check +//Well.2 Well.4 +Poly.1 Poly.2 Poly.3 Poly.4 Poly.5 +Active.1 Active.2 // Active.3 +Contact.1 Contact.2 Contact.3 Contact.4 +Contact.5 Contact.6 Metal1.1 Metal1.2 Metal1.3 + + + +//Well.1 { +//@Nwell and Pwell must not overlap +//AND nwell pwell +//} + +//Well.2 { +//@Min spacing of pwell to nwell = 0.00 +//EXTERNAL nwell pwell < 0.00 +//} + +//Well.4 { +//@Min width of nwell = 3.6 +//INTERNAL nwell < 3.6 +//} + +Poly.1 { +@Min width of poly = 0.6 +INTERNAL poly < 0.6 +} + +Poly.2 { +@Min spacing of gate poly = 0.9 +EXTERNAL gate < 0.9 +} + +Poly.3 { +@Min extension of poly past active = 0.6 +ENCLOSURE active poly < 0.6 +} + +Poly.4 { +@Minimum active enclosure of gate =0.6 +ENCLOSURE poly active < 0.6 +} + +Poly.5 { +@Minimum spacing of poly to active = 0.3 +EXTERNAL act_poly active < 0.3 +} + +Active.1 { +@Minimum width of active = 0.9 +INTERNAL active < 0.9 +} + +Active.2 { +@Minimum spacing of active areas = 0.9 +EXTERNAL active < 0.9 +} + +//Active.3 { +//@Minimum well enclosure of active = 1.8 +//ENCLOSURE active well < 1.8 +//} + +Contact.1 { +@Minimum width of contact = 0.6 +INTERNAL contact < 0.6 +} + +Contact.2 { +@Minimum spacing of contact = 0.9 +EXTERNAL contact < 0.9 +} + +Contact.3 { +@Contact must be inside metal1 and active or poly +NOT contact contactenc +} + +Contact.4 { +@Minimum active enclosure of contact = 0.3 +ENCLOSURE contact active < 0.3 +} + +Contact.5 { +@Minimum poly enclosure of contact = 0.3 +ENCLOSURE contact poly < 0.3 +} + +Contact.6 { +@Minimum spacing of contact to poly = 0.6 +EXTERNAL poly contact < 0.6 +} + +Metal1.1 { +@Minimum width of metal1 = 0.9 +INTERNAL metal1 < 0.9 +} + +Metal1.2 { +@Minimum spacing of metal1 = 0.9 +EXTERNAL metal1 < 0.9 +} + +Metal1.3 { +@Metal1 must extend past contact by 0.3 on two opposite sides +RECTANGLE ENCLOSURE contact metal1 +GOOD 0.00 0.3 OPPOSITE 0.00 0.3 OPPOSITE +} + +Metal1.4 { +@Metal1 must extend past via1 by 0.3 on two opposite sides +RECTANGLE ENCLOSURE via1 metal1 +GOOD 0.00 0.3 OPPOSITE 0.00 0.3 OPPOSITE +} + +Via1.1 { +@Minimum width of via1 = 0.6 +INTERNAL via1 < 0.6 +} + +Via1.2 { +@Minimum spacing of via1 = 0.6 +EXTERNAL via1 < 0.6 +} + +Via1.3 { +@Via1 must be inside metal1 +NOT via1 metal1 +} + + +Metal2.1 { +@Minimum width of metal2 = 0.9 +INTERNAL metal2 < 0.9 +} + +Metal2.2 { +@Minimum spacing of metal2 = 0.9 +EXTERNAL metal2 < 0.9 +} + +Metal2.3 { +@Metal2 must extend past via1 by 0.3 on two opposite sides +RECTANGLE ENCLOSURE via1 metal2 +GOOD 0.00 0.3 OPPOSITE 0.00 0.3 OPPOSITE +} + +Metal2.4 { +@Metal2 must extend past via2 by 0.3 on two opposite sides +RECTANGLE ENCLOSURE via2 metal2 +GOOD 0.00 0.3 OPPOSITE 0.00 0.3 OPPOSITE +} + +Via2.1 { +@Minimum width of via2 = 0.6 +INTERNAL via2 < 0.6 +} + +Via2.2 { +@Minimum spacing of via2 = 0.9 +EXTERNAL via2 < 0.9 +} + +Via2.3 { +@Via2 must be inside metal2 +NOT via2 metal2 +} + +Via2.4 { +@Via2 must be inside metal3 +NOT via2 metal3 +} + +Metal3.1 { +@Minimum width of metal3 = 1.5 +INTERNAL metal3 < 1.5 +} + +Metal3.2 { +@Minimum spacing of metal3 = 0.9 +EXTERNAL metal3 < 0.9 +} + +Metal3.3 { +@Metal3 must extend past via2 by 0.6 on two opposite sides +RECTANGLE ENCLOSURE via2 metal3 +GOOD 0.00 0.6 OPPOSITE 0.00 0.6 OPPOSITE +} + diff --git a/technology/scn3me_subm/tech/calibreLVS_scn3me_subm.rul b/technology/scn3me_subm/tech/calibreLVS_scn3me_subm.rul new file mode 100755 index 00000000..5d3516a6 --- /dev/null +++ b/technology/scn3me_subm/tech/calibreLVS_scn3me_subm.rul @@ -0,0 +1,123 @@ +TITLE "LVS Rule File for scn3me_subm" + +LVS POWER NAME vdd +LVS GROUND NAME gnd GROUND +LVS REDUCE PARALLEL MOS yes +LVS REDUCE SERIES MOS yes +LVS REDUCE SEMI SERIES MOS yes +LVS FILTER UNUSED MOS no +LVS RECOGNIZE GATES all +LVS COMPONENT TYPE PROPERTY element +LVS COMPONENT SUBTYPE PROPERTY model +LVS IGNORE PORTS no + +LVS REPORT mask.lvs.rep +LVS REPORT OPTION N +LVS REPORT MAXIMUM 50 +MASK RESULTS DATABASE maskdb + +precision 1000 +resolution 250 + +TEXT LAYER metal1 metal2 metal3 +PORT LAYER TEXT metal1 metal2 metal3 + + +layer pwell 41 +layer nwell 42 +layer active 43 +layer poly 46 +layer nimplant 45 +layer pimplant 44 +layer contact 25 +layer active_contact 48 +layer poly_contact 47 +layer metal1 49 +layer via1 50 +layer metal2 51 +layer via2 61 +layer metal3 62 +layer glass 52 +layer pad 26 + +connect metal1 metal2 by via1 +connect metal2 metal3 by via2 + +pdif = active and pimplant // P-diffusion +ndif = active and nimplant // N-diffusion + +ngate = poly and ndif // N-Transistor +pgate = poly and pdif // P-transistor + +nsrcdrn = ndif not ngate // N-tansistor Source and Drain contacts diffusion region +psrcdrn = pdif not pgate // P-tansistor Source and Drain contacts diffusion region + +pcont = psrcdrn and pwell + +ntapcont = active not interact pimplant +ptapcont = active not interact nimplant + +bulk = extent +nsub = (bulk not pwell) and nwell +ncont = nsrcdrn and nsub + +connect metal1 poly psrcdrn nsrcdrn by contact mask +connect psrcdrn pwell by pcont mask +connect nsrcdrn nsub by ncont mask + +ncont1= ntapcont and nsub +pcont1= ptapcont and pwell +connect metal1 ncont1 by contact mask +connect metal1 pcont1 by contact mask +connect ncont1 nsub +connect pcont1 pwell + +connect psrcdrn metal1 by contact +connect nsrcdrn metal1 by contact + +connect psrcdrn metal1 by active_contact +connect nsrcdrn metal1 by active_contact + +connect poly metal1 by contact + +connect poly metal1 by poly_contact + +device mp (p) pgate poly (G) psrcdrn (S) psrcdrn (D) nsub CMACRO FET_PROPERTIES pgate nsub +device mn (n) ngate poly (G) nsrcdrn (S) nsrcdrn (D) pwell CMACRO FET_PROPERTIES ngate pwell + +VARIABLE trace_delta 4e-9 + +DMACRO FET_TRACE device_type device_name { +TRACE PROPERTY device_type(device_name) l l trace_delta ABSOLUTE +TRACE PROPERTY device_type(device_name) w w trace_delta ABSOLUTE + +} + +CMACRO FET_TRACE MN n +CMACRO FET_TRACE MP p + +DMACRO FET_PROPERTIES seed well{ +[ +PROPERTY W, L, AS, AD, PS, PD + + AS = area(S) + AD = area(D) + PS = perimeter(S) + PD = perimeter(D) + if ( AS == 0 ) { + AD = area(D) / 2 + AS = AD + PD = perimeter(D) / 2 + PS = PD + } + if ( AD == 0 ) { + AS = area(S) / 2 + AD = AS + PS = perimeter(S) / 2 + PD = PS + } + W = (perim_co(seed,S) + perim_co(seed,D) ) * 0.5 + L = (perim(seed) - perim_co(seed,S) - perim_in(seed,S) - perim_co(seed,D) - perim_in(seed,D) ) * 0.5 + +] +} diff --git a/technology/scn3me_subm/tech/tech.py b/technology/scn3me_subm/tech/tech.py new file mode 100755 index 00000000..fb7524c1 --- /dev/null +++ b/technology/scn3me_subm/tech/tech.py @@ -0,0 +1,311 @@ +import os +from design_rules import * + +""" +File containing the process technology parameters for SCMOS 3me, subm, 180nm. +""" + +#GDS file info +GDS={} +# gds units +# gds units +# From http://www.cnf.cornell.edu/cnf_spie9.html: "The first +#is the size of a database unit in user units. The second is the size +#of a database unit in meters. For example, if your library was +#created with the default units (user unit = 1 m and 1000 database +#units per user unit), then the first number would be 0.001 and the +#second number would be 10-9. Typically, the first number is less than +#1, since you use more than 1 database unit per user unit. To +#calculate the size of a user unit in meters, divide the second number +#by the first." +GDS["unit"]=(0.001,1e-6) +# default label zoom +GDS["zoom"] = 0.5 + + +################################################### +##GDS Layer Map +################################################### + +# create the GDS layer map +layer={} +layer["vtg"] = -1 +layer["vth"] = -1 +layer["contact"] = 47 +layer["pwell"] = 41 +layer["nwell"] = 42 +layer["active"] = 43 +layer["pimplant"] = 44 +layer["nimplant"] = 45 +layer["poly"] = 46 +layer["active_contact"] = 48 +layer["metal1"] = 49 +layer["via1"] = 50 +layer["metal2"] = 51 +layer["via2"] = 61 +layer["metal3"] = 62 +layer["text"] = 63 +layer["boundary"] = 63 +layer["blockage"] = 83 + +################################################### +##END GDS Layer Map +################################################### + +################################################### +##DRC/LVS Rules Setup +################################################### +_lambda_ = 0.3 + +#technology parameter +parameter={} +parameter["min_tx_size"] = 4*_lambda_ +parameter["beta"] = 2 + +parameter["6T_inv_nmos_size"] = 8*_lambda_ +parameter["6T_inv_pmos_size"] = 3*_lambda_ +parameter["6T_access_size"] = 4*_lambda_ + +drclvs_home=os.environ.get("DRCLVS_HOME") + +drc = design_rules("scn3me_subm") + +drc["body_tie_down"] = 0 +drc["has_pwell"] = True +drc["has_nwell"] = True + + +#grid size is 1/2 a lambda +drc["grid"]=0.5*_lambda_ +#DRC/LVS test set_up +drc["drc_rules"]=drclvs_home+"/calibreDRC_scn3me_subm.rul" +drc["lvs_rules"]=drclvs_home+"/calibreLVS_scn3me_subm.rul" +drc["layer_map"]=os.environ.get("OPENRAM_TECH")+"/scn3me_subm/layers.map" + + +# minwidth_tx with contact (no dog bone transistors) +drc["minwidth_tx"] = 4*_lambda_ +drc["minlength_channel"] = 2*_lambda_ + +# 1.3 Minimum spacing between wells of same type (if both are drawn) +drc["well_to_well"] = 6*_lambda_ +# 1.4 Minimum spacing between wells of different type (if both are drawn) +drc["pwell_to_nwell"] = 0 +# 1.1 Minimum width +drc["minwidth_well"] = 12*_lambda_ + +# 3.1 Minimum width +drc["minwidth_poly"] = 2*_lambda_ +# 3.2 Minimum spacing over active +drc["poly_to_poly"] = 3*_lambda_ +# 3.3 Minimum gate extension of active +drc["poly_extend_active"] = 2*_lambda_ +# 5.5.b Minimum spacing between poly contact and other poly (alternative rules) +drc["poly_to_polycontact"] = 4*_lambda_ +# ?? +drc["active_enclosure_gate"] = 0.0 +# 3.5 Minimum field poly to active +drc["poly_to_active"] = _lambda_ +# 3.2.a Minimum spacing over field poly +drc["poly_to_field_poly"] = 3*_lambda_ +# Not a rule +drc["minarea_poly"] = 0.0 + +# ?? +drc["active_to_body_active"] = 4*_lambda_ # Fix me +# 2.1 Minimum width +drc["minwidth_active"] = 3*_lambda_ +# 2.2 Minimum spacing +drc["active_to_active"] = 3*_lambda_ +# 2.3 Source/drain active to well edge +drc["well_enclosure_active"] = 6*_lambda_ +# Reserved for asymmetric enclosures +drc["well_extend_active"] = 6*_lambda_ +# Not a rule +drc["minarea_active"] = 0.0 + +# 4.1 Minimum select spacing to channel of transistor to ensure adequate source/drain width +drc["implant_to_channel"] = 3*_lambda_ +# 4.2 Minimum select overlap of active +drc["implant_enclosure_active"] = 2*_lambda_ +# 4.3 Minimum select overlap of contact +drc["implant_enclosure_contact"] = _lambda_ +# Not a rule +drc["implant_to_contact"] = 0 +# Not a rule +drc["implant_to_implant"] = 0 +# Not a rule +drc["minwidth_implant"] = 0 + +# 6.1 Exact contact size +drc["minwidth_contact"] = 2*_lambda_ +# 5.3 Minimum contact spacing +drc["contact_to_contact"] = 3*_lambda_ +# 6.2.b Minimum active overlap +drc["active_enclosure_contact"] = _lambda_ +# Reserved for asymmetric enclosure +drc["active_extend_contact"] = _lambda_ +# 5.2.b Minimum poly overlap +drc["poly_enclosure_contact"] = _lambda_ +# Reserved for asymmetric enclosures +drc["poly_extend_contact"] = _lambda_ +# Reserved for other technologies +drc["contact_to_gate"] = 2*_lambda_ +# 5.4 Minimum spacing to gate of transistor +drc["contact_to_poly"] = 2*_lambda_ + +# 7.1 Minimum width +drc["minwidth_metal1"] = 3*_lambda_ +# 7.2 Minimum spacing +drc["metal1_to_metal1"] = 3*_lambda_ +# 7.3 Minimum overlap of any contact +drc["metal1_enclosure_contact"] = _lambda_ +# Reserved for asymmetric enclosure +drc["metal1_extend_contact"] = _lambda_ +# 8.3 Minimum overlap by metal1 +drc["metal1_enclosure_via1"] = _lambda_ +# Reserve for asymmetric enclosures +drc["metal1_extend_via1"] = _lambda_ +# Not a rule +drc["minarea_metal1"] = 0 + +# 8.1 Exact size +drc["minwidth_via1"] = 2*_lambda_ +# 8.2 Minimum via1 spacing +drc["via1_to_via1"] = 3*_lambda_ + +# 9.1 Minimum width +drc["minwidth_metal2"] = 3*_lambda_ +# 9.2 Minimum spacing +drc["metal2_to_metal2"] = 3*_lambda_ +# 9.3 Minimum overlap of via1 +drc["metal2_extend_via1"] = _lambda_ +# Reserved for asymmetric enclosures +drc["metal2_enclosure_via1"] = _lambda_ +# 14.3 Minimum overlap by metal2 +drc["metal2_extend_via2"] = _lambda_ +# Reserved for asymmetric enclosures +drc["metal2_enclosure_via2"] = _lambda_ +# Not a rule +drc["minarea_metal2"] = 0 + +# 14.1 Exact size +drc["minwidth_via2"] = 2*_lambda_ +# 14.2 Minimum spacing +drc["via2_to_via2"] = 3*_lambda_ + +# 15.1 Minimum width +drc["minwidth_metal3"] = 5*_lambda_ +# 15.2 Minimum spacing to metal3 +drc["metal3_to_metal3"] = 3*_lambda_ +# 15.3 Minimum overlap of via 2 +drc["metal3_extend_via2"] = 2*_lambda_ +# Reserved for asymmetric enclosures +drc["metal3_enclosure_via2"] = 2*_lambda_ +# Not a rule +drc["minarea_metal3"] = 0 + +################################################### +##END DRC/LVS Rules +################################################### + +################################################### +##Spice Simulation Parameters +################################################### + +# spice model info +spice={} +spice["nmos"]="n" +spice["pmos"]="p" +# This is a map of corners to model files +SPICE_MODEL_DIR=os.environ.get("SPICE_MODEL_DIR") +# FIXME: Uncomment when we have the new spice models +#spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"] } +spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"], + "FF" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"], + "FS" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"], + "SF" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"], + "SS" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"], + "ST" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"], + "TS" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"], + "FT" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"], + "TF" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"], + } + + +#spice stimulus related variables +spice["feasible_period"] = 10 # estimated feasible period in ns +spice["supply_voltages"] = [4.5, 5.0, 5.5] # Supply voltage corners in [Volts] +spice["nom_supply_voltage"] = 5.0 # Nominal supply voltage in [Volts] +spice["rise_time"] = 0.05 # rise time in [Nano-seconds] +spice["fall_time"] = 0.05 # fall time in [Nano-seconds] +spice["temperatures"] = [0, 25, 100] # Temperature corners (celcius) +spice["nom_temperature"] = 25 # Nominal temperature (celcius) + +#sram signal names +#FIXME: We don't use these everywhere... +spice["vdd_name"] = "vdd" +spice["gnd_name"] = "gnd" +spice["control_signals"] = ["CSB", "WEB"] +spice["data_name"] = "DATA" +spice["addr_name"] = "ADDR" +spice["minwidth_tx"] = drc["minwidth_tx"] +spice["channel"] = drc["minlength_channel"] +spice["clk"] = "clk" + +# analytical delay parameters +# FIXME: These need to be updated for SCMOS, they are copied from FreePDK45. +spice["vdd_nominal"] = 5.0 # Typical Threshold voltage in Volts +spice["temp_nominal"] = 25.0 # Typical Threshold voltage in Volts +spice["v_threshold_typical"] = 1.3 # Typical Threshold voltage in Volts +spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square +spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2 +spice["min_tx_r"] = 9250.0 # Minimum transistor on resistance in ohms +spice["min_tx_drain_c"] = 0.7 # Minimum transistor drain capacitance in ff +spice["min_tx_gate_c"] = 0.1 # Minimum transistor gate capacitance in ff +spice["msflop_setup"] = 9 # DFF setup time in ps +spice["msflop_hold"] = 1 # DFF hold time in ps +spice["msflop_delay"] = 20.5 # DFF Clk-to-q delay in ps +spice["msflop_slew"] = 13.1 # DFF output slew in ps w/ no load +spice["msflop_in_cap"] = 9.8242 # Input capacitance of ms_flop (Din) [Femto-farad] +spice["dff_setup"] = 9 # DFF setup time in ps +spice["dff_hold"] = 1 # DFF hold time in ps +spice["dff_delay"] = 20.5 # DFF Clk-to-q delay in ps +spice["dff_slew"] = 13.1 # DFF output slew in ps w/ no load +spice["dff_in_cap"] = 9.8242 # Input capacitance of ms_flop (Din) [Femto-farad] + +# analytical power parameters, many values are temporary +spice["bitcell_leakage"] = 1 # Leakage power of a single bitcell in nW +spice["inv_leakage"] = 1 # Leakage power of inverter in nW +spice["nand2_leakage"] = 1 # Leakage power of 2-input nand in nW +spice["nand3_leakage"] = 1 # Leakage power of 3-input nand in nW +spice["nor2_leakage"] = 1 # Leakage power of 2-input nor in nW +spice["msflop_leakage"] = 1 # Leakage power of flop in nW +spice["flop_para_cap"] = 2 # Parasitic Output capacitance in fF + +spice["default_event_rate"] = 100 # Default event activity of every gate. MHz +spice["flop_transition_prob"] = .5 # Transition probability of inverter. +spice["inv_transition_prob"] = .5 # Transition probability of inverter. +spice["nand2_transition_prob"] = .1875 # Transition probability of 2-input nand. +spice["nand3_transition_prob"] = .1094 # Transition probability of 3-input nand. +spice["nor2_transition_prob"] = .1875 # Transition probability of 2-input nor. + +#Logical Effort relative values for the Handmade cells +parameter['le_tau'] = 23 #In pico-seconds. +parameter["min_inv_para_delay"] = .73 #In relative delay units +parameter['cap_relative_per_ff'] = .91 #Units of Relative Capacitance/ Femto-Farad +parameter["static_delay_stages"] = 4 +parameter["static_fanout_per_stage"] = 3 +parameter["static_fanout_list"] = parameter["static_delay_stages"]*[parameter["static_fanout_per_stage"]] +parameter["dff_clk_cin"] = 27.5 #In relative capacitance units +parameter["6tcell_wl_cin"] = 2 #In relative capacitance units +parameter["sa_en_pmos_size"] = 24*_lambda_ +parameter["sa_en_nmos_size"] = 9*_lambda_ +parameter["sa_inv_pmos_size"] = 18*_lambda_ +parameter["sa_inv_nmos_size"] = 9*_lambda_ +parameter["rbl_height_percentage"] = .5 #Height of RBL compared to bitcell array +parameter['bitcell_drain_cap'] = 0.2 #In Femto-Farad, approximation of drain capacitance + +################################################### +##END Spice Simulation Parameters +################################################### diff --git a/technology/scn3me_subm/tf/README b/technology/scn3me_subm/tf/README new file mode 100644 index 00000000..400cfe98 --- /dev/null +++ b/technology/scn3me_subm/tf/README @@ -0,0 +1,19 @@ +;; NCSU CDK v. 1.6.0.beta +;; Last Modified: 2007-07-12 + +The NCSU CDK is Copyright (C) NC State University, 1998, 1999, 2004, +2006, 2007. Users are free to use or modify the NCSU CDK as appropriate as long +as this notice appears in the modified package. The NCSU CDK is +provided with NO WARRANTY. + +As of version 1.5.1, all documentation for the NCSU CDK is provided +by the NCSU EDA Wiki which can be found at: + + http://www.eda.ncsu.edu/ + +This beta release of the kit is to be used in migrating to Cadence Virtuoso 6.1 +for OpenAccess. Details of the conversion of the CDK from the CDB version can +be found in the file cdb2oa/OA_Conversion.txt. + +This kit is not yet fully supported. Please post problems and solutions at +http://www.chiptalk.org -> Forums -> NCSU CDK -> NCSU CDK 1.6.0.beta for Virtuoso 6.1 diff --git a/technology/scn3me_subm/tf/display.drf b/technology/scn3me_subm/tf/display.drf new file mode 100644 index 00000000..4bd251e8 --- /dev/null +++ b/technology/scn3me_subm/tf/display.drf @@ -0,0 +1,714 @@ +drDefineDisplay( +;( DisplayName ) + ( display ) +) +drDefineColor( +;( DisplayName ColorsName Red Green Blue ) + ( display white 255 255 255 ) + ( display yellow 255 255 0 ) + ( display silver 217 230 255 ) + ( display cream 255 255 204 ) + ( display pink 255 191 242 ) + ( display magenta 255 0 255 ) + ( display lime 0 255 0 ) + ( display tan 255 230 191 ) + ( display cyan 0 255 255 ) + ( display cadetBlue 57 191 255 ) + ( display orange 255 128 0 ) + ( display red 255 51 51 ) + ( display purple 153 0 230 ) + ( display green 0 204 102 ) + ( display brown 191 64 38 ) + ( display blue 51 77 255 ) + ( display slate 140 140 166 ) + ( display gold 217 204 0 ) + ( display maroon 230 31 13 ) + ( display violet 94 0 230 ) + ( display forest 38 140 107 ) + ( display chocolate 128 38 38 ) + ( display navy 51 51 153 ) + ( display black 0 0 0 ) + ( display gray 204 204 217 ) + ( display winColor1 166 166 166 ) + ( display winColor2 115 115 115 ) + ( display winColor3 189 204 204 ) + ( display winColor4 204 204 204 ) + ( display winColor5 199 199 199 ) + ( display blinkRed 255 0 0 t ) + ( display blinkYellow 255 255 0 t ) + ( display blinkWhite 255 255 255 t ) + ( display winBack 224 224 224 ) + ( display winFore 128 0 0 ) + ( display winText 51 51 51 ) +) +drDefineStipple( +;( DisplayName StippleName Bitmap ) + ( display dots ( ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display dots1 ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display hLine ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) ) ) + ( display vLine ( ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) ) ) + ( display cross ( ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) ) ) + ( display grid ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) ) ) + ( display slash ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) ) ) + ( display backSlash ( ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) ) ) + ( display hZigZag ( ( 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 ) + ( 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ) + ( 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 ) + ( 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 ) + ( 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 ) + ( 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ) + ( 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 ) + ( 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 ) ) ) + ( display vZigZag ( ( 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 ) + ( 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 ) + ( 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ) + ( 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 ) + ( 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 ) + ( 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 ) + ( 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 ) + ( 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 ) + ( 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 ) + ( 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 ) + ( 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ) + ( 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 ) + ( 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 ) + ( 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 ) + ( 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 ) + ( 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 ) ) ) + ( display hCurb ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display vCurb ( ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) ) ) + ( display brick ( ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) ) ) + ( display dagger ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) ) ) + ( display triangle ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 ) + ( 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display x ( ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) ) ) + ( display stipple0 ( ( 1 ) ) ) + ( display stipple1 ( ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display stipple2 ( ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) ) ) + ( display stipple3 ( ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) ) ) + ( display stipple4 ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) ) ) + ( display stipple5 ( ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) ) ) + ( display stipple6 ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) ) ) + ( display stipple7 ( ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) ) ) + ( display stipple8 ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) ) ) + ( display stipple9 ( ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) ) ) + ( display stipple10 ( ( 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display stipple11 ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) ) ) + ( display dots2 ( ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display dots4 ( ( 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 ) ) ) + ( display dats5 ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) +) +drDefineLineStyle( +;( DisplayName LineStyle Size Pattern ) + ( display solid 1 (1 ) ) + ( display dashed 1 (1 1 1 0 0 1 1 1 ) ) + ( display dots 1 (1 0 0 ) ) + ( display dashDot 1 (1 1 1 0 0 1 0 0 ) ) + ( display shortDash 1 (1 1 0 0 ) ) + ( display doubleDash 1 (1 1 1 1 0 0 1 1 0 0 ) ) + ( display hidden 1 (1 0 0 0 ) ) + ( display thickLine 3 (1 1 1 ) ) + ( display lineStyle0 1 (1 ) ) + ( display lineStyle1 1 (1 1 1 0 1 1 1 0 1 1 1 0 1 1 0 1 ) ) +) +drDefinePacket( +;( DisplayName PacketName Stipple LineStyle Fill Outline [FillStyle]) + ( display NwellNet dots4 thickLine slate slate outlineStipple) + ( display border stipple0 solid tan tan solid ) + ( display y8 stipple0 solid gold gold solid ) + ( display background stipple1 lineStyle0 black black outlineStipple) + ( display y9 stipple0 solid silver silver solid ) + ( display Metal3Net dots4 solid navy navy outlineStipple) + ( display A1 stipple0 lineStyle0 winBack winBack solid ) + ( display pin solid lineStyle0 red red solid ) + ( display XPNet blank solid yellow yellow outline ) + ( display hardFence stipple0 solid red red solid ) + ( display PbaseNet dots4 solid yellow yellow outlineStipple) + ( display designFlow3 stipple1 lineStyle0 pink pink outlineStipple) + ( display A2 stipple0 lineStyle0 winBack winBack solid ) + ( display Unrouted1 stipple0 lineStyle1 brown brown solid ) + ( display RowLbl blank solid cyan cyan outline ) + ( display edgeLayerPin stipple0 solid yellow yellow solid ) + ( display instance blank solid winBack red outline ) + ( display Nselect dots4 solid green green outlineStipple) + ( display snap stipple0 solid yellow yellow solid ) + ( display pinAnt stipple0 solid red red solid ) + ( display winAttentionText solid solid winText winText solid ) + ( display designFlow2 stipple1 lineStyle0 purple purple outlineStipple) + ( display Unrouted2 stipple0 lineStyle1 red red solid ) + ( display hilite blank solid white white outline ) + ( display P2Con solid lineStyle0 orange orange solid ) + ( display designFlow1 stipple1 lineStyle0 red red outlineStipple) + ( display grid1 stipple0 solid gray gray solid ) + ( display Unrouted3 stipple0 lineStyle1 pink pink solid ) + ( display ViaNet x solid magenta magenta outlineStipple) + ( display select stipple0 solid tan tan solid ) + ( display Poly2Net dots4 lineStyle0 orange orange outlineStipple) + ( display winText solid solid winText winText solid ) + ( display Unrouted4 stipple0 lineStyle1 orange orange solid ) + ( display wireLbl solid lineStyle0 cyan cyan solid ) + ( display designFlow7 stipple1 lineStyle0 cyan cyan outlineStipple) + ( display align stipple0 solid tan tan solid ) + ( display Poly2Pin blank solid yellow yellow outline ) + ( display Unrouted5 stipple0 lineStyle1 green green solid ) + ( display unset stipple0 solid forest forest solid ) + ( display Poly1Net dots4 lineStyle0 red red outlineStipple) + ( display Resistor dots2 lineStyle0 cyan cyan outlineStipple) + ( display DiodeNet dots4 lineStyle0 cream cream outlineStipple) + ( display designFlow6 stipple1 lineStyle0 tan tan outlineStipple) + ( display Unrouted6 stipple0 lineStyle1 blue blue solid ) + ( display resist stipple0 solid cyan cyan solid ) + ( display designFlow5 stipple1 lineStyle0 silver silver outlineStipple) + ( display CapWellNet brick solid slate slate outlineStipple) + ( display Unrouted7 stipple0 lineStyle1 purple purple solid ) + ( display CannotoccupyBnd blank solid red red outline ) + ( display winTopShadow solid solid white white solid ) + ( display designFlow4 stipple1 lineStyle0 black black outlineStipple) + ( display softFence stipple0 solid yellow yellow solid ) + ( display ResistorNet dots4 solid cyan cyan outlineStipple) + ( display winError solid solid winColor5 winColor5 solid ) + ( display changedLayerTl1 stipple0 solid yellow yellow solid ) + ( display prBoundaryLbl stipple0 solid purple purple solid ) + ( display ActXNet x solid yellow yellow outlineStipple) + ( display Pbase stipple10 lineStyle0 yellow yellow outlineStipple) + ( display Active dots2 lineStyle0 yellow yellow outlineStipple) + ( display changedLayerTl0 stipple0 solid red red solid ) + ( display spike stipple0 solid purple purple solid ) + ( display Metal3 grid solid navy violet outlineStipple) + ( display text blank solid white white outline ) + ( display Poly1Pin stipple0 lineStyle0 red red solid ) + ( display Row blank solid cyan cyan outline ) + ( display Pwell stipple9 lineStyle0 slate slate outlineStipple) + ( display Metal2 stipple5 lineStyle0 magenta magenta outlineStipple) + ( display wire solid lineStyle0 cyan cyan solid ) + ( display ActX solid solid yellow yellow solid ) + ( display Metal1 stipple6 lineStyle0 cadetBlue cadetBlue outlineStipple) + ( display Cannotoccupy blank solid red red outline ) + ( display GroupLbl stipple0 solid green green solid ) + ( display axis stipple0 solid slate slate solid ) + ( display SiBlockNet x dashed tan tan outlineStipple) + ( display edgeLayer stipple0 solid gray gray solid ) + ( display annotate2 stipple0 solid lime lime solid ) + ( display Metal1Pin stipple0 lineStyle0 blue blue solid ) + ( display Diode stipple7 lineStyle0 cream cream outlineStipple) + ( display Glass X lineStyle0 white white X ) + ( display ViaXNet x solid magenta magenta outlineStipple) + ( display annotate3 stipple0 solid cyan cyan solid ) + ( display Poly2 dots1 lineStyle0 orange orange outlineStipple) + ( display deviceAnt stipple0 solid yellow yellow solid ) + ( display winBottomShadow solid solid winColor1 winColor1 solid ) + ( display PselectNet dots4 solid brown brown outlineStipple) + ( display comment stipple0 lineStyle0 winBack winBack outlineStipple) + ( display Poly1 dots lineStyle0 red red outlineStipple) + ( display Unrouted stipple0 lineStyle1 winColor5 winColor5 solid ) + ( display stretch stipple0 solid yellow yellow solid ) + ( display XP blank lineStyle0 winBack gold outline ) + ( display annotate1 stipple0 solid pink pink solid ) + ( display Group stipple2 solid green green outlineStipple) + ( display deviceLbl stipple0 solid green green solid ) + ( display annotate6 stipple0 solid silver silver solid ) + ( display GlassNet blank solid yellow yellow outline ) + ( display Canplace blank solid cyan cyan outline ) + ( display annotate7 stipple0 solid red red solid ) + ( display Via2 solid solid navy navy solid ) + ( display Metal2Pin stipple0 lineStyle0 magenta magenta solid ) + ( display annotate4 stipple0 solid yellow yellow solid ) + ( display device1 stipple1 lineStyle0 green green outlineStipple) + ( display "90" blank solid white white outline ) + ( display markerWarn x solid yellow yellow outlineStipple) + ( display text2 stipple1 lineStyle0 white white outlineStipple) + ( display CapacitorNet dots4 lineStyle0 tan tan outlineStipple) + ( display designFlow stipple1 lineStyle0 green green outlineStipple) + ( display hilite1 stipple0 solid silver silver solid ) + ( display device blank solid green green outline ) + ( display prBoundary stipple0 solid purple purple solid ) + ( display annotate5 stipple0 solid white white solid ) + ( display text1 stipple0 dashed white white solid ) + ( display Via solid solid magenta magenta solid ) + ( display Capacitor stipple7 lineStyle0 tan tan outlineStipple) + ( display markerErr x solid white white outlineStipple) + ( display unknown stipple0 solid yellow yellow solid ) + ( display annotate stipple0 solid orange orange solid ) + ( display P1ConNet x solid red red outlineStipple) + ( display hilite3 stipple0 solid cyan cyan solid ) + ( display winActiveBanner solid solid winColor3 winColor3 solid ) + ( display pinLbl stipple0 solid red red solid ) + ( display device2 stipple0 lineStyle1 green green solid ) + ( display grid stipple0 solid slate slate solid ) + ( display winBackground solid solid winBack winBack solid ) + ( display Metal1Net dots4 lineStyle0 blue blue outlineStipple) + ( display hilite2 stipple0 solid tan tan solid ) + ( display annotate8 stipple0 solid tan tan solid ) + ( display hilite5 stipple0 solid lime lime solid ) + ( display annotate9 stipple0 solid green green solid ) + ( display Metal2Net dots4 lineStyle0 magenta magenta outlineStipple) + ( display Metal3Pin stipple0 solid navy navy solid ) + ( display hilite4 stipple0 solid gray gray solid ) + ( display y0 stipple0 solid gray gray solid ) + ( display supply stipple0 solid lime lime solid ) + ( display ActiveNet dots4 lineStyle0 yellow yellow outlineStipple) + ( display hilite7 stipple0 solid cream cream solid ) + ( display y1 stipple0 solid brown brown solid ) + ( display defaultPacket x solid chocolate winColor2 outlineStipple) + ( display Via2Net cross solid navy navy outlineStipple) + ( display NselectNet dots4 solid green green outlineStipple) + ( display Unrouted8 stipple0 lineStyle1 gold gold solid ) + ( display hilite6 stipple0 solid orange orange solid ) + ( display y2 stipple0 solid red red solid ) + ( display winBorder solid solid winColor2 winColor2 solid ) + ( display Nwell dats5 thickLine slate slate outlineStipple) + ( display Unrouted9 stipple0 lineStyle1 silver silver solid ) + ( display hilite9 stipple0 solid pink pink solid ) + ( display SiBlock blank dashed tan tan outline ) + ( display y3 stipple0 solid orange orange solid ) + ( display prBoundaryBnd stipple0 solid cyan cyan solid ) + ( display winForeground solid solid winFore winFore solid ) + ( display hilite8 stipple0 solid magenta magenta solid ) + ( display y4 stipple0 solid yellow yellow solid ) + ( display Pselect dots1 solid brown brown outlineStipple) + ( display winInactiveBanner solid solid winColor4 winColor4 solid ) + ( display designFlow9 stipple1 lineStyle0 orange orange outlineStipple) + ( display winButton solid solid winFore winFore solid ) + ( display y5 stipple0 solid green green solid ) + ( display hiz stipple0 solid orange orange solid ) + ( display drive stipple0 solid blue blue solid ) + ( display wireFlt stipple0 dashed red red solid ) + ( display instanceLbl stipple0 solid gold gold solid ) + ( display P2ConNet x lineStyle0 orange orange outlineStipple) + ( display designFlow8 stipple1 lineStyle0 navy navy outlineStipple) + ( display y6 stipple0 solid blue blue solid ) + ( display PwellNet dots4 lineStyle0 slate slate outlineStipple) + ( display P1Con solid solid red red solid ) + ( display CapWell dagger solid slate slate outlineStipple) + ( display y7 stipple0 solid purple purple solid ) + ( display ViaX solid solid magenta magenta solid ) + ( display HR x solid chocolate winColor2 outlineStipple) + ( display HRnet x solid chocolate winColor2 outlineStipple) +) diff --git a/technology/scn3me_subm/tf/glade_scn3me_subm.py b/technology/scn3me_subm/tf/glade_scn3me_subm.py new file mode 100644 index 00000000..d2f9aa7e --- /dev/null +++ b/technology/scn3me_subm/tf/glade_scn3me_subm.py @@ -0,0 +1,7 @@ +import os +CWD = os.environ.get("OPENRAM_TECH") + "/scn3me_subm/tf" +ui().importCds("default", CWD+"/display.drf", CWD+"/mosis.tf", 1000, 1, CWD+"/layers.map") + + + + diff --git a/technology/scn3me_subm/tf/layers.map b/technology/scn3me_subm/tf/layers.map new file mode 100644 index 00000000..b5440f23 --- /dev/null +++ b/technology/scn3me_subm/tf/layers.map @@ -0,0 +1,16 @@ +Pwell drawing 41 0 +Nwell drawing 42 0 +Active drawing 43 0 +Poly1 drawing 46 0 +Pselect drawing 45 0 +Nselect drawing 44 0 +contact drawing 25 0 +P1Con drawing 47 0 +ActX drawing 48 0 +Metal1 drawing 49 0 +Via drawing 50 0 +Metal2 drawing 51 0 +Via2 drawing 61 0 +Metal3 drawing 62 0 +Glass drawing 52 0 +comment drawing 63 0 diff --git a/technology/scn3me_subm/tf/mosis.tf b/technology/scn3me_subm/tf/mosis.tf new file mode 100644 index 00000000..759221f1 --- /dev/null +++ b/technology/scn3me_subm/tf/mosis.tf @@ -0,0 +1,848 @@ +; Generated on Sep 28 16:05:23 1998 +; with @(#)$CDS: icfb.exe version 4.4.1 06/17/98 23:40 (cds10067) $ +; +; Matt Clapp fixed: October 10, 2002 +; added via devices, deleted useless app-specific crap, +; added lxExtractRules so undo in layout editor doesn't +; complain. + + +;******************************** +; LAYER DEFINITION +;******************************** + +layerDefinitions( + techLayers( + ;( LayerName Layer# Abbreviation ) + ;( --------- ------ ------------ ) + ;User-Defined Layers: + ( P2Con 3 P2Con ) + ( Poly2 7 Poly2 ) + ( Pbase 10 Pbase ) + ( Resistor 16 Resisto ) + ( Capacitor 17 Capacit ) + ( Diode 18 Diode ) + ( SiBlock 29 SiBlock ) + ( HR 34 HR ) + ( Pwell 41 Pwell ) + ( Nwell 42 Nwell ) + ( Active 43 Active ) + ( Pselect 44 Pselect ) + ( Nselect 45 Nselect ) + ( Poly1 46 Poly1 ) + ( P1Con 47 P1Con ) + ( ActX 48 ActX ) + ( Metal1 49 Metal1 ) + ( Via 50 Via ) + ( Metal2 51 Metal2 ) + ( Glass 52 Glass ) + ( CapWell 59 CapWell ) + ( XP 60 XP ) + ( Via2 61 Via2 ) + ( Metal3 62 Metal3 ) + ( A1 80 A1 ) + ( A2 81 A2 ) + ( comment 117 comment ) + ;System-Reserved Layers: + ( Unrouted 200 Unroute ) + ( Row 201 Row ) + ( Group 202 Group ) + ( Cannotoccupy 203 Cannoto ) + ( Canplace 204 Canplac ) + ( hardFence 205 hardFen ) + ( softFence 206 softFen ) + ( y0 207 y0 ) + ( y1 208 y1 ) + ( y2 209 y2 ) + ( y3 210 y3 ) + ( y4 211 y4 ) + ( y5 212 y5 ) + ( y6 213 y6 ) + ( y7 214 y7 ) + ( y8 215 y8 ) + ( y9 216 y9 ) + ( designFlow 217 designF ) + ( stretch 218 stretch ) + ( edgeLayer 219 edgeLay ) + ( changedLayer 220 changed ) + ( unset 221 unset ) + ( unknown 222 unknown ) + ( spike 223 spike ) + ( hiz 224 hiz ) + ( resist 225 resist ) + ( drive 226 drive ) + ( supply 227 supply ) + ( wire 228 wire ) + ( pin 229 pin ) + ( text 230 text ) + ( device 231 device ) + ( border 232 border ) + ( snap 233 snap ) + ( align 234 align ) + ( prBoundary 235 prBound ) + ( instance 236 instanc ) + ( annotate 237 annotat ) + ( marker 238 marker ) + ( select 239 select ) + ( grid 251 grid ) + ( axis 252 axis ) + ( hilite 253 hilite ) + ( background 254 backgro ) + ) ;techLayers + + techPurposes( + ;( PurposeName Purpose# Abbreviation ) + ;( ----------- -------- ------------ ) + ;User-Defined Purposes: + ;System-Reserved Purposes: + ( warning 234 wng ) + ( tool1 235 tl1 ) + ( tool0 236 tl0 ) + ( label 237 lbl ) + ( flight 238 flt ) + ( error 239 err ) + ( annotate 240 ant ) + ( drawing1 241 dr1 ) + ( drawing2 242 dr2 ) + ( drawing3 243 dr3 ) + ( drawing4 244 dr4 ) + ( drawing5 245 dr5 ) + ( drawing6 246 dr6 ) + ( drawing7 247 dr7 ) + ( drawing8 248 dr8 ) + ( drawing9 249 dr9 ) + ( boundary 250 bnd ) + ( pin 251 pin ) + ( drawing 252 drw ) + ( net 253 net ) + ( cell 254 cel ) + ( all 255 all ) + ) ;techPurposes + + techLayerPurposePriorities( + ;layers are ordered from lowest to highest priority + ; (higher priority is drawn on top of lower priority) + ;( LayerName Purpose ) + ;( --------- ------- ) + ( background drawing ) + ( grid drawing ) + ( grid drawing1 ) + ( Nwell drawing ) + ( Pwell drawing ) + ( CapWell drawing ) + ( Pselect drawing ) + ( Nselect drawing ) + ( Active drawing ) + ( ActX drawing ) + ( SiBlock drawing ) + ( HR drawing ) + ( Poly1 drawing ) + ( P1Con drawing ) + ( Poly2 drawing ) + ( P2Con drawing ) + ( Metal1 drawing ) + ( Via drawing ) + ( Metal2 drawing ) + ( Via2 drawing ) + ( Metal3 drawing ) + ( annotate drawing ) + ( annotate drawing1 ) + ( annotate drawing2 ) + ( annotate drawing3 ) + ( annotate drawing4 ) + ( annotate drawing5 ) + ( annotate drawing6 ) + ( annotate drawing7 ) + ( annotate drawing8 ) + ( annotate drawing9 ) + ( Poly1 pin ) + ( Metal1 pin ) + ( Metal2 pin ) + ( Metal3 pin ) + ( Glass drawing ) + ( XP drawing ) + ( prBoundary drawing ) + ( prBoundary boundary ) + ( instance drawing ) + ( prBoundary label ) + ( instance label ) + ( Row drawing ) + ( Nwell net ) + ( align drawing ) + ( Pwell net ) + ( CapWell net ) + ( hardFence drawing ) + ( Active net ) + ( softFence drawing ) + ( Row label ) + ( Group drawing ) + ( Group label ) + ( Cannotoccupy drawing ) + ( Cannotoccupy boundary ) + ( Canplace drawing ) + ( ActX net ) + ( A2 drawing ) + ( A1 drawing ) + ( comment drawing ) + ( border drawing ) + ( Pselect net ) + ( Nselect net ) + ( SiBlock net ) + ( HR net ) + ( wire drawing ) + ( Poly1 net ) + ( wire label ) + ( P1Con net ) + ( wire flight ) + ( Metal1 net ) + ( device annotate ) + ( Metal2 net ) + ( device label ) + ( Via net ) + ( Metal3 net ) + ( Via2 net ) + ( pin label ) + ( text drawing ) + ( pin drawing ) + ( text drawing1 ) + ( pin annotate ) + ( device drawing ) + ( axis drawing ) + ( edgeLayer drawing ) + ( edgeLayer pin ) + ( snap drawing ) + ( stretch drawing ) + ( y0 drawing ) + ( y1 drawing ) + ( y2 drawing ) + ( y3 drawing ) + ( y4 drawing ) + ( y5 drawing ) + ( y6 drawing ) + ( y7 drawing ) + ( y8 drawing ) + ( y9 drawing ) + ( hilite drawing ) + ( hilite drawing1 ) + ( hilite drawing2 ) + ( hilite drawing3 ) + ( hilite drawing4 ) + ( hilite drawing5 ) + ( hilite drawing6 ) + ( hilite drawing7 ) + ( hilite drawing8 ) + ( hilite drawing9 ) + ( select drawing ) + ( drive drawing ) + ( hiz drawing ) + ( resist drawing ) + ( spike drawing ) + ( supply drawing ) + ( unknown drawing ) + ( unset drawing ) + ( designFlow drawing ) + ( designFlow drawing1 ) + ( designFlow drawing2 ) + ( designFlow drawing3 ) + ( designFlow drawing4 ) + ( designFlow drawing5 ) + ( designFlow drawing6 ) + ( designFlow drawing7 ) + ( designFlow drawing8 ) + ( designFlow drawing9 ) + ( changedLayer tool0 ) + ( changedLayer tool1 ) + ( marker warning ) + ( marker error ) + ( device drawing1 ) + ( Pbase drawing ) + ( Pbase net ) + ( Resistor net ) + ( Resistor drawing ) + ( Capacitor net ) + ( Capacitor drawing ) + ( Diode net ) + ( Diode drawing ) + ( Poly2 net ) + ( P2Con net ) + ( device drawing2 ) + ( Unrouted drawing ) + ( text drawing2 ) + ( Unrouted drawing1 ) + ( Unrouted drawing2 ) + ( Unrouted drawing3 ) + ( Unrouted drawing4 ) + ( Unrouted drawing5 ) + ( Unrouted drawing6 ) + ( Unrouted drawing7 ) + ( Unrouted drawing8 ) + ( Unrouted drawing9 ) + ) ;techLayerPurposePriorities + + techDisplays( + ;( LayerName Purpose Packet Vis Sel Con2ChgLy DrgEnbl Valid ) + ;( --------- ------- ------ --- --- --------- ------- ----- ) + ( background drawing background t nil nil nil nil ) + ( grid drawing grid t nil nil nil nil ) + ( grid drawing1 grid1 t nil nil nil nil ) + ( Nwell drawing Nwell t t t t t ) + ( Pwell drawing Pwell t t t t nil ) + ( Active drawing Active t t t t t ) + ( ActX drawing ActX t t t t t ) + ( Pselect drawing Pselect t t t t t ) + ( Nselect drawing Nselect t t t t t ) + ( SiBlock drawing SiBlock t t t t t ) + ( HR drawing HR t t t t t ) + ( CapWell drawing CapWell t t t t t ) + ( Poly1 drawing Poly1 t t t t t ) + ( P1Con drawing P1Con t t t t t ) + ( Metal1 drawing Metal1 t t t t t ) + ( Via drawing Via t t t t t ) + ( Metal2 drawing Metal2 t t t t t ) + ( annotate drawing annotate t t nil t nil ) + ( annotate drawing1 annotate1 t t nil t nil ) + ( annotate drawing2 annotate2 t t nil t nil ) + ( annotate drawing3 annotate3 t t nil t nil ) + ( annotate drawing4 annotate4 t t nil t nil ) + ( annotate drawing5 annotate5 t t nil t nil ) + ( annotate drawing6 annotate6 t t nil t nil ) + ( annotate drawing7 annotate7 t t nil t nil ) + ( annotate drawing8 annotate8 t t nil t nil ) + ( annotate drawing9 annotate9 t t nil t nil ) + ( Via2 drawing Via2 t t t t t ) + ( Metal3 drawing Metal3 t t t t t ) + ( Glass drawing Glass t t t nil t ) + ( XP drawing XP t t t nil t ) + ( Metal1 pin Metal1Pin t t t nil t ) + ( Metal2 pin Metal2Pin t t t nil t ) + ( Metal3 pin Metal3Pin t t t nil t ) + ( Poly1 pin Poly1Pin t t t nil t ) + ( prBoundary drawing prBoundary t t nil t nil ) + ( prBoundary boundary prBoundaryBnd t t nil t nil ) + ( instance drawing instance t t nil t t ) + ( prBoundary label prBoundaryLbl t t t t nil ) + ( instance label instanceLbl t t t t nil ) + ( Row drawing Row t t t t nil ) + ( Nwell net NwellNet t t t nil nil ) + ( align drawing align t t nil t nil ) + ( Pwell net PwellNet t t t nil nil ) + ( CapWell net CapWellNet t t t nil nil ) + ( SiBlock net SiBlockNet t t t nil nil ) + ( HR net HRnet t t t nil nil ) + ( hardFence drawing hardFence t t t t nil ) + ( Active net ActiveNet t t t nil nil ) + ( softFence drawing softFence t t t t nil ) + ( Row label RowLbl t t t t nil ) + ( Group drawing Group t t t t nil ) + ( Group label GroupLbl t t t t nil ) + ( Cannotoccupy drawing Cannotoccupy t t t t nil ) + ( Cannotoccupy boundary CannotoccupyBnd t t t t nil ) + ( Canplace drawing Canplace t t t t nil ) + ( ActX net ActXNet t t t nil nil ) + ( A2 drawing A2 t t t t nil ) + ( A1 drawing A1 t t t t nil ) + ( comment drawing comment t t t t nil ) + ( border drawing border t t t t nil ) + ( Pselect net PselectNet t t t nil nil ) + ( Nselect net NselectNet t t t nil nil ) + ( wire drawing wire t t t t nil ) + ( Poly1 net Poly1Net t t t nil nil ) + ( wire label wireLbl t t t t nil ) + ( P1Con net P1ConNet t t t nil nil ) + ( wire flight wireFlt t t t t nil ) + ( Metal1 net Metal1Net t t t nil nil ) + ( device annotate deviceAnt t t t t nil ) + ( Metal2 net Metal2Net t t t nil nil ) + ( Metal3 net Metal3Net t t t nil nil ) + ( device label deviceLbl t t t t nil ) + ( Via net ViaNet t t t nil nil ) + ( Via2 net Via2Net t t t nil nil ) + ( pin label pinLbl t t t t nil ) + ( text drawing text t t t t t ) + ( pin drawing pin t t t t nil ) + ( text drawing1 text1 t t t t nil ) + ( pin annotate pinAnt t t t t nil ) + ( device drawing device t t t t nil ) + ( axis drawing axis t t t t nil ) + ( edgeLayer drawing edgeLayer t t nil t nil ) + ( edgeLayer pin edgeLayerPin t t nil t nil ) + ( snap drawing snap t t nil t nil ) + ( stretch drawing stretch t t nil t nil ) + ( y0 drawing y0 t t nil t nil ) + ( y1 drawing y1 t t nil t nil ) + ( y2 drawing y2 t t nil t nil ) + ( y3 drawing y3 t t nil t nil ) + ( y4 drawing y4 t t nil t nil ) + ( y5 drawing y5 t t nil t nil ) + ( y6 drawing y6 t t nil t nil ) + ( y7 drawing y7 t t nil t nil ) + ( y8 drawing y8 t t nil t nil ) + ( y9 drawing y9 t t nil t nil ) + ( hilite drawing hilite t t nil t nil ) + ( hilite drawing1 hilite1 t t t t nil ) + ( hilite drawing2 hilite2 t t nil t nil ) + ( hilite drawing3 hilite3 t t t t nil ) + ( hilite drawing4 hilite4 t t t t nil ) + ( hilite drawing5 hilite5 t t t t nil ) + ( hilite drawing6 hilite6 t t t t nil ) + ( hilite drawing7 hilite7 t t t t nil ) + ( hilite drawing8 hilite8 t t t t nil ) + ( hilite drawing9 hilite9 t t t t nil ) + ( select drawing select t t nil t nil ) + ( drive drawing drive t t t t nil ) + ( hiz drawing hiz t t t t nil ) + ( resist drawing resist t t t t nil ) + ( spike drawing spike t t t t nil ) + ( supply drawing supply t t t t nil ) + ( unknown drawing unknown t t t t nil ) + ( unset drawing unset t t t t nil ) + ( designFlow drawing designFlow t t t nil nil ) + ( designFlow drawing1 designFlow1 t t t nil nil ) + ( designFlow drawing2 designFlow2 t t t nil nil ) + ( designFlow drawing3 designFlow3 t t t nil nil ) + ( designFlow drawing4 designFlow4 t t t nil nil ) + ( designFlow drawing5 designFlow5 t t t nil nil ) + ( designFlow drawing6 designFlow6 t t t nil nil ) + ( designFlow drawing7 designFlow7 t t t nil nil ) + ( designFlow drawing8 designFlow8 t t t nil nil ) + ( designFlow drawing9 designFlow9 t t t nil nil ) + ( changedLayer tool0 changedLayerTl0 nil nil nil nil nil ) + ( changedLayer tool1 changedLayerTl1 nil nil t nil nil ) + ( marker warning markerWarn t t t t nil ) + ( marker error markerErr t t t t nil ) + ( device drawing1 device1 t t t t nil ) + ( Poly2 net Poly2Net t t t nil nil ) + ( Poly2 drawing Poly2 t t t t t ) + ( P2Con net P2ConNet t t t nil nil ) + ( P2Con drawing P2Con t t t t t ) + ( Pbase net PbaseNet t t t nil nil ) + ( Pbase drawing Pbase t t t t t ) + ( Resistor net ResistorNet t t t nil nil ) + ( Resistor drawing Resistor t t t t t ) + ( Capacitor net CapacitorNet t t t nil nil ) + ( Capacitor drawing Capacitor t t t t t ) + ( Diode net DiodeNet t t t nil nil ) + ( Diode drawing Diode t t t t t ) + ( device drawing2 device2 t t t t nil ) + ( Unrouted drawing Unrouted t t t t nil ) + ( text drawing2 text2 t t t t nil ) + ( Unrouted drawing1 Unrouted1 t t t t nil ) + ( Unrouted drawing2 Unrouted2 t t t t nil ) + ( Unrouted drawing3 Unrouted3 t t t t nil ) + ( Unrouted drawing4 Unrouted4 t t t t nil ) + ( Unrouted drawing5 Unrouted5 t t t t nil ) + ( Unrouted drawing6 Unrouted6 t t t t nil ) + ( Unrouted drawing7 Unrouted7 t t t t nil ) + ( Unrouted drawing8 Unrouted8 t t t t nil ) + ( Unrouted drawing9 Unrouted9 t t t t nil ) + ) ;techDisplays + +; I don't think the following is necessary (or used!) +techLayerProperties( +;( PropName Layer1 [ Layer2 ] PropValue ) + ( contactLimit P2Con 10000 ) + ( eqPinLimit P2Con 10000 ) + ( horizontalJogLength P2Con 2147483648.000000 ) + ( routingGrid P2Con 1.000000 ) + ( verticalJogLength P2Con 2147483648.000000 ) + ( routingGrid Poly2 1.000000 ) + ( contactLimit Active 10000 ) + ( eqPinLimit Active 10000 ) + ( horizontalJogLength Active 2147483648.000000 ) + ( routingGrid Active 1.000000 ) + ( verticalJogLength Active 2147483648.000000 ) + ( routingGrid Poly1 1.000000 ) + ( contactLimit P1Con 10000 ) + ( eqPinLimit P1Con 10000 ) + ( horizontalJogLength P1Con 2147483648.000000 ) + ( routingGrid P1Con 1.000000 ) + ( verticalJogLength P1Con 2147483648.000000 ) + ( contactLimit ActX 10000 ) + ( eqPinLimit ActX 10000 ) + ( horizontalJogLength ActX 2147483648.000000 ) + ( routingGrid ActX 1.000000 ) + ( verticalJogLength ActX 2147483648.000000 ) + ( routingGrid Metal1 1.000000 ) + ( contactLimit Via 10000 ) + ( eqPinLimit Via 10000 ) + ( horizontalJogLength Via 2147483648.000000 ) + ( routingGrid Via 1.000000 ) + ( verticalJogLength Via 2147483648.000000 ) + ( routingGrid Metal2 1.000000 ) +) + +) ;layerDefinitions + + +;******************************** +; DEVICE RULES +;******************************** + +devices( + tcCreateCDSDeviceClass() + + symContactDevice( + ;( deviceName viaLayer viaPurpose + ( VIA Via drawing + + ; layer1 purpose1 [implant1] + Metal1 drawing + + ; layer2 purpose2 [implant2] + Metal2 drawing + + ; width length [( row column xPitch yPitch xBias yBias )] + ; 2 2 ( 1 1 _NA_ _NA_ _NA_ _NA_ ) + 2 2 + + ; encLayer1 encLayer2 legalRegion ) + 1 1 _NA_) + ) ;symContactDevice + + symContactDevice( + ;( deviceName viaLayer viaPurpose + ( VIA2 Via2 drawing + + ; layer1 purpose1 [implant1] + Metal2 drawing + + ; layer2 purpose2 [implant2] + Metal3 drawing + + ; width length [( row column xPitch yPitch xBias yBias )] + ; 2 2 ( 1 1 _NA_ _NA_ _NA_ _NA_ ) + 2 2 + + ; encLayer1 encLayer2 legalRegion ) + 1 2 _NA_) + ) ;symContactDevice + +) ;devices + + +;******************************** +; LAYER RULES +;******************************** + +layerRules( + streamLayers( + ;( layer streamNumber dataType translate ) + ;( ----- ------------ -------- --------- ) + ( ("background" "drawing") 0 0 nil ) + ( ("grid" "drawing") 0 0 nil ) + ( ("grid" "drawing1") 0 0 nil ) + ( ("Nwell" "drawing") 42 0 t ) + ( ("Pwell" "drawing") 41 0 t ) + ( ("Active" "drawing") 43 0 t ) + ( ("ActX" "drawing") 48 0 t ) + ( ("Pselect" "drawing") 44 0 t ) + ( ("Nselect" "drawing") 45 0 t ) + ( ("Poly1" "drawing") 46 0 t ) + ( ("P1Con" "drawing") 47 0 t ) + ( ("Metal1" "drawing") 49 0 t ) + ( ("Metal2" "drawing") 51 0 t ) + ( ("annotate" "drawing") 0 0 nil ) + ( ("annotate" "drawing1") 0 0 nil ) + ( ("annotate" "drawing2") 0 0 nil ) + ( ("annotate" "drawing3") 0 0 nil ) + ( ("annotate" "drawing4") 0 0 nil ) + ( ("annotate" "drawing5") 0 0 nil ) + ( ("annotate" "drawing6") 0 0 nil ) + ( ("annotate" "drawing7") 0 0 nil ) + ( ("annotate" "drawing8") 0 0 nil ) + ( ("annotate" "drawing9") 0 0 nil ) + ( ("Via" "drawing") 50 0 t ) + ( ("Glass" "drawing") 52 0 t ) + ( ("XP" "drawing") 60 0 t ) + ( ("Metal2" "pin") 0 0 nil ) + ( ("Poly1" "pin") 0 0 nil ) + ( ("prBoundary" "drawing") 0 0 nil ) + ( ("Metal1" "pin") 0 0 nil ) + ( ("prBoundary" "boundary") 0 0 nil ) + ( ("instance" "drawing") 246 0 nil ) + ( ("instance" "label") 0 0 nil ) + ( ("Nwell" "net") 0 0 nil ) + ( ("align" "drawing") 0 0 nil ) + ( ("Pwell" "net") 0 0 nil ) + ( ("hardFence" "drawing") 0 0 nil ) + ( ("Active" "net") 0 0 nil ) + ( ("softFence" "drawing") 0 0 nil ) + ( ("ActX" "net") 0 0 nil ) + ( ("A2" "drawing") 5 0 nil ) + ( ("A1" "drawing") 2 0 nil ) + ( ("comment" "drawing") 0 0 nil ) + ( ("border" "drawing") 0 0 nil ) + ( ("Pselect" "net") 0 0 nil ) + ( ("Nselect" "net") 0 0 nil ) + ( ("wire" "drawing") 0 0 nil ) + ( ("Poly1" "net") 0 0 nil ) + ( ("P1Con" "net") 0 0 nil ) + ( ("Metal1" "net") 0 0 nil ) + ( ("Metal2" "net") 0 0 nil ) + ( ("device" "label") 0 0 nil ) + ( ("Via" "net") 0 0 nil ) + ( ("pin" "label") 0 0 nil ) + ( ("text" "drawing") 63 0 t ) + ( ("pin" "drawing") 0 0 nil ) + ( ("device" "drawing") 0 0 nil ) + ( ("axis" "drawing") 0 0 nil ) + ( ("edgeLayer" "drawing") 0 0 nil ) + ( ("edgeLayer" "pin") 0 0 nil ) + ( ("snap" "drawing") 0 0 nil ) + ( ("stretch" "drawing") 0 0 nil ) + ( ("y0" "drawing") 0 0 nil ) + ( ("y1" "drawing") 0 0 nil ) + ( ("y2" "drawing") 0 0 nil ) + ( ("y3" "drawing") 0 0 nil ) + ( ("y4" "drawing") 0 0 nil ) + ( ("y5" "drawing") 0 0 nil ) + ( ("y6" "drawing") 0 0 nil ) + ( ("y7" "drawing") 0 0 nil ) + ( ("y8" "drawing") 0 0 nil ) + ( ("y9" "drawing") 0 0 nil ) + ( ("hilite" "drawing") 0 0 nil ) + ( ("hilite" "drawing2") 0 0 nil ) + ( ("select" "drawing") 0 0 nil ) + ( ("drive" "drawing") 0 0 nil ) + ( ("hiz" "drawing") 0 0 nil ) + ( ("resist" "drawing") 0 0 nil ) + ( ("spike" "drawing") 0 0 nil ) + ( ("supply" "drawing") 0 0 nil ) + ( ("unknown" "drawing") 0 0 nil ) + ( ("unset" "drawing") 0 0 nil ) + ( ("changedLayer" "tool0") 0 0 nil ) + ( ("Resistor" "net") 0 0 nil ) + ( ("Resistor" "drawing") 0 0 nil ) + ( ("Capacitor" "net") 0 0 nil ) + ( ("Capacitor" "drawing") 0 0 nil ) + ( ("Diode" "net") 0 0 nil ) + ( ("Diode" "drawing") 0 0 nil ) + ( ("Poly2" "net") 0 0 nil ) + ( ("Poly2" "drawing") 0 0 nil ) + ( ("P2Con" "net") 0 0 nil ) + ( ("P2Con" "drawing") 0 0 nil ) + ( ("Pbase" "drawing") 0 0 nil ) + ( ("Pbase" "net") 0 0 nil ) + ( P2Con 0 0 nil ) + ( Poly2 0 0 nil ) + ( Pwell 0 0 nil ) + ( Nwell 0 0 nil ) + ( Active 0 0 nil ) + ( Pselect 0 0 nil ) + ( Nselect 0 0 nil ) + ( Poly1 0 0 nil ) + ( P1Con 0 0 nil ) + ( ActX 0 0 nil ) + ( Metal1 0 0 nil ) + ( Via 0 0 nil ) + ( Metal2 0 0 nil ) + ( Glass 0 0 nil ) + ( XP 0 0 nil ) + ( ("Via2" "drawing") 50 0 t ) + ( ("Via2" "net") 0 0 nil ) + ( ("Metal3" "drawing") 50 0 t ) + ( ("Metal3" "net") 0 0 nil ) + ( ("Metal3" "pin") 0 0 nil ) + ( ("CapWell" "drawing") 0 0 nil ) + ( ("CapWell" "net") 0 0 nil ) + ( ("SiBlock" "drawing") 0 0 nil ) + ( ("SiBlock" "net") 0 0 nil ) + ( ("HR" "drawing") 0 0 nil ) + ( ("HR" "net") 0 0 nil ) + ) ;streamLayers + + viaLayers( + ;( layer1 viaLayer layer2 ) + ;( ------ -------- ------ ) + ( Metal2 Via2 Metal3 ) + ( Metal1 Via Metal2 ) + ( Active ActX Poly1 ) + ( Poly1 P1Con Metal1 ) + ( Poly2 P2Con Metal1 ) + ) ;viaLayers + +) ;layerRules + + +;******************************** +; PHYSICAL RULES +;******************************** + +physicalRules( + orderedSpacingRules( + ;( rule layer1 layer2 value ) + ;( ---- ------ ------ ----- ) + ( minEnclosure "prBoundary" "Metal1" 0.0 ) + ( minEnclosure "Metal2" "Via" 1.0 ) + ( minEnclosure "Metal1" "Via" 1.0 ) + ( minEnclosure "Metal1" "P1Con" 1.0 ) + ( minEnclosure "Metal1" "ActX" 1.0 ) + ( minEnclosure "Nselect" "Active" 2.0 ) + ( minEnclosure "Pselect" "Active" 2.0 ) + ( minEnclosure "Active" "ActX" 1.0 ) + ( minEnclosure "Pwell" "Active" 5.0 ) + ( minEnclosure "Nwell" "Active" 5.0 ) + ) ;orderedSpacingRules + + spacingRules( + ;( rule layer1 layer2 value ) + ;( ---- ------ ------ ----- ) + ( minSpacing "P2Con" 2.0 ) + ( minSpacing "Poly2" 3.0 ) + ( minSpacing "Pwell" 9.0 ) + ( minSpacing "Nwell" 9.0 ) + ( minSpacing "Active" 3.0 ) + ( minSpacing "Pselect" 2.0 ) + ( minSpacing "Nselect" 2.0 ) + ( minSpacing "Poly1" 2.0 ) + ( minSpacing "P1Con" 2.0 ) + ( minSpacing "ActX" 2.0 ) + ( minSpacing "Metal1" 3.0 ) + ( minSpacing "Via" 3.0 ) + ( minSpacing "Via2" 3.0 ) + ( minSpacing "Metal2" 3.0 ) + ( minSpacing "Metal3" 4.0 ) + ( minSpacing "Glass" 75.0 ) + ( minSpacing "XP" 100.0 ) + ( minSpacing "Metal2" 4.0 ) + ( minSpacing "P1Con" "Via" 2.0 ) + ( minSpacing "ActX" "Via" 2.0 ) + ( minSpacing "ActX" "P2Con" 2.0 ) + ( minSpacing "Poly2" "P2Con" 4.0 ) + ( minSpacing "Poly1" "P1Con" 4.0 ) + ( minSpacing "ActX" "P1Con" 2.0 ) + ( minSpacing "Active" "P1Con" 2.0 ) + ( minSpacing "Active" "Poly2" 2.0 ) + ( minSpacing "Poly1" "Poly2" 2.0 ) + ( minSpacing "Active" "Poly1" 2.0 ) + ( minSpacing "ActX" "Poly1" 2.0 ) + ( minSpacing "Pselect" "Nselect" 0.0 ) + ( minSpacing "Nwell" "Pwell" 9.0 ) + ( minWidth "P2Con" 2.0 ) + ( minWidth "Poly2" 3.0 ) + ( minWidth "Pwell" 10.0 ) + ( minWidth "Nwell" 10.0 ) + ( minWidth "Active" 3.0 ) + ( minWidth "Pselect" 2.0 ) + ( minWidth "Nselect" 2.0 ) + ( minWidth "Poly1" 2.0 ) + ( minWidth "P1Con" 2.0 ) + ( minWidth "ActX" 2.0 ) + ( minWidth "Metal1" 4.0 ) + ( minWidth "Via" 2.0 ) + ( minWidth "Metal2" 4.0 ) + ( minWidth "Glass" 75.0 ) + ( minWidth "XP" 100.0 ) + ( minWidth "Metal3" 6.0 ) + ) ;spacingRules + + mfgGridResolution( + ( 1.000000 ) + ) ;mfgGridResolution + +) ;physicalRules + + +;******************************** +; ELECTRICAL RULES +;******************************** + +electricalRules( + characterizationRules( + ;( rule layer1 layer2 value ) + ;( ---- ------ ------ ----- ) + ( areaCap "P2Con" 0.0 ) + ( areaCap "Poly2" 0.0 ) + ( areaCap "Active" 0.0 ) + ( areaCap "Poly1" 6e-05 ) + ( areaCap "P1Con" 0.0 ) + ( areaCap "ActX" 0.0 ) + ( areaCap "Metal1" 2.6e-05 ) + ( areaCap "Via" 0.0 ) + ( areaCap "Metal2" 1.6e-05 ) + ( edgeCapacitance "P2Con" 0.0 ) + ( edgeCapacitance "Poly2" 0.0 ) + ( edgeCapacitance "Active" 0.0 ) + ( edgeCapacitance "Poly1" 0.0 ) + ( edgeCapacitance "P1Con" 0.0 ) + ( edgeCapacitance "ActX" 0.0 ) + ( edgeCapacitance "Metal1" 0.0 ) + ( edgeCapacitance "Via" 0.0 ) + ( edgeCapacitance "Metal2" 0.0 ) + ( sheetRes "P2Con" 0.0 ) + ( sheetRes "Poly2" 0.0 ) + ( sheetRes "Active" 0.0 ) + ( sheetRes "Poly1" 23.0 ) + ( sheetRes "P1Con" 0.0 ) + ( sheetRes "ActX" 0.0 ) + ( sheetRes "Metal1" 0.04 ) + ( sheetRes "Via" 0.0 ) + ( sheetRes "Metal2" 0.07 ) + ( currentDensity "P2Con" 1.0 ) + ( currentDensity "Poly2" 1.0 ) + ( currentDensity "Active" 1.0 ) + ( currentDensity "Poly1" 1.0 ) + ( currentDensity "P1Con" 1.0 ) + ( currentDensity "ActX" 1.0 ) + ( currentDensity "Metal1" 1.0 ) + ( currentDensity "Via" 1.0 ) + ( currentDensity "Metal2" 1.0 ) + ) ;characterizationRules + +) ;electricalRules + + +;******************************** +; LAYOUT EDITOR RULES +;******************************** +; specifies the ordering of the layers in the LSW + +leRules( + leLswLayers( + ;( layer purpose ) + ; ----- ------- ) + ( Nwell drawing ) + ( Pselect drawing ) + ( Nselect drawing ) + ( Active drawing ) + ( ActX drawing ) + ( Poly1 drawing ) + ( P1Con drawing ) + ( Metal1 drawing ) + ( Via drawing ) + ( Metal2 drawing ) + ( Via2 drawing ) + ( Metal3 drawing ) + ( Poly1 pin ) + ( Metal1 pin ) + ( Metal2 pin ) + ( Metal3 pin ) + ( Poly2 drawing ) + ( P2Con drawing ) + ( instance drawing ) + ( text drawing ) + ( CapWell drawing ) + ( SiBlock drawing ) + ( HR drawing ) + ( Pbase drawing ) + ( Resistor drawing ) + ( Capacitor drawing ) + ( Diode drawing ) + ( Glass drawing ) + ( XP drawing ) + + ) ;leLswLayers +) ;leRules + + +;******************************** +; VIRTUOSO XL RULES +;******************************** +; specifies the ordering of the layers in the LSW + +lxRules( + lxExtractLayers( + (Metal1 Metal2 Metal3) + ) ;lxExtractLayers +) ;lxRules + diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 15278c7b..882e16d5 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -9,7 +9,7 @@ import os from design_rules import * """ -File containing the process technology parameters for SCMOS 3me, subm, 180nm. +File containing the process technology parameters for SCMOS 4m, 0.35um """ #GDS file info From aca46beb743489a770e3a4b30f646c76aab70171 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 8 May 2019 16:17:19 -0700 Subject: [PATCH 007/234] Add multiport bitcell spice --- technology/scn3me_subm/sp_lib/cell_1rw_1r.sp | 14 ++++++++++++++ technology/scn3me_subm/sp_lib/cell_1w_1r.sp | 14 ++++++++++++++ .../scn3me_subm/sp_lib/replica_cell_1rw_1r.sp | 14 ++++++++++++++ .../scn3me_subm/sp_lib/replica_cell_1w_1r.sp | 14 ++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 technology/scn3me_subm/sp_lib/cell_1rw_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/cell_1w_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp diff --git a/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp b/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp new file mode 100644 index 00000000..1c4c1bc3 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left Q_bar gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 Q_bar wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q Q_bar gnd gnd n w=2.4u l=0.6u +MM0 Q_bar Q gnd gnd n w=2.4u l=0.6u +MM3 Q Q_bar vdd vdd p w=1.2u l=0.6u +MM2 Q_bar Q vdd vdd p w=1.2u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/cell_1w_1r.sp b/technology/scn3me_subm/sp_lib/cell_1w_1r.sp new file mode 100644 index 00000000..aed7466b --- /dev/null +++ b/technology/scn3me_subm/sp_lib/cell_1w_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left Q_bar gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 Q_bar wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q Q_bar gnd gnd n w=2.4u l=0.6u +MM0 Q_bar Q gnd gnd n w=2.4u l=0.6u +MM3 Q Q_bar vdd vdd p w=1.2u l=0.6u +MM2 Q_bar Q vdd vdd p w=1.2u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp b/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp new file mode 100644 index 00000000..e90dd033 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT replica_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left vdd gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 vdd wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q vdd gnd gnd n w=2.4u l=0.6u +MM0 vdd Q gnd gnd n w=2.4u l=0.6u +MM3 Q vdd vdd vdd p w=1.2u l=0.6u +MM2 vdd Q vdd vdd p w=1.2u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp b/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp new file mode 100644 index 00000000..bd2e5eb5 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT replica_cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left vdd gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 vdd wl0 br0 gnd n w=0.8u l=0.6u +MM1 Q vdd gnd gnd n w=2.4u l=0.6u +MM0 vdd Q gnd gnd n w=2.4u l=0.6u +MM3 Q vdd vdd vdd p w=0.6u l=0.6u +MM2 vdd Q vdd vdd p w=0.6u l=0.6u +.ENDS + From 94e736881fdc22242ddfcf829c4edb040421597e Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 8 May 2019 16:19:48 -0700 Subject: [PATCH 008/234] Multiport scn3me_subm has drc errors --- .../gds_lib/{ => incorrect}/cell_1rw_1r.gds | Bin .../gds_lib/{ => incorrect}/cell_1w_1r.gds | Bin .../gds_lib/{ => incorrect}/replica_cell_1rw_1r.gds | Bin .../gds_lib/{ => incorrect}/replica_cell_1w_1r.gds | Bin .../sp_lib/{ => incorrect}/cell_1rw_1r.sp | 0 .../sp_lib/{ => incorrect}/cell_1w_1r.sp | 0 .../sp_lib/{ => incorrect}/replica_cell_1rw_1r.sp | 0 .../sp_lib/{ => incorrect}/replica_cell_1w_1r.sp | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename technology/scn3me_subm/gds_lib/{ => incorrect}/cell_1rw_1r.gds (100%) rename technology/scn3me_subm/gds_lib/{ => incorrect}/cell_1w_1r.gds (100%) rename technology/scn3me_subm/gds_lib/{ => incorrect}/replica_cell_1rw_1r.gds (100%) rename technology/scn3me_subm/gds_lib/{ => incorrect}/replica_cell_1w_1r.gds (100%) rename technology/scn3me_subm/sp_lib/{ => incorrect}/cell_1rw_1r.sp (100%) rename technology/scn3me_subm/sp_lib/{ => incorrect}/cell_1w_1r.sp (100%) rename technology/scn3me_subm/sp_lib/{ => incorrect}/replica_cell_1rw_1r.sp (100%) rename technology/scn3me_subm/sp_lib/{ => incorrect}/replica_cell_1w_1r.sp (100%) diff --git a/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds b/technology/scn3me_subm/gds_lib/incorrect/cell_1rw_1r.gds similarity index 100% rename from technology/scn3me_subm/gds_lib/cell_1rw_1r.gds rename to technology/scn3me_subm/gds_lib/incorrect/cell_1rw_1r.gds diff --git a/technology/scn3me_subm/gds_lib/cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/incorrect/cell_1w_1r.gds similarity index 100% rename from technology/scn3me_subm/gds_lib/cell_1w_1r.gds rename to technology/scn3me_subm/gds_lib/incorrect/cell_1w_1r.gds diff --git a/technology/scn3me_subm/gds_lib/replica_cell_1rw_1r.gds b/technology/scn3me_subm/gds_lib/incorrect/replica_cell_1rw_1r.gds similarity index 100% rename from technology/scn3me_subm/gds_lib/replica_cell_1rw_1r.gds rename to technology/scn3me_subm/gds_lib/incorrect/replica_cell_1rw_1r.gds diff --git a/technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/incorrect/replica_cell_1w_1r.gds similarity index 100% rename from technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds rename to technology/scn3me_subm/gds_lib/incorrect/replica_cell_1w_1r.gds diff --git a/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp b/technology/scn3me_subm/sp_lib/incorrect/cell_1rw_1r.sp similarity index 100% rename from technology/scn3me_subm/sp_lib/cell_1rw_1r.sp rename to technology/scn3me_subm/sp_lib/incorrect/cell_1rw_1r.sp diff --git a/technology/scn3me_subm/sp_lib/cell_1w_1r.sp b/technology/scn3me_subm/sp_lib/incorrect/cell_1w_1r.sp similarity index 100% rename from technology/scn3me_subm/sp_lib/cell_1w_1r.sp rename to technology/scn3me_subm/sp_lib/incorrect/cell_1w_1r.sp diff --git a/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp b/technology/scn3me_subm/sp_lib/incorrect/replica_cell_1rw_1r.sp similarity index 100% rename from technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp rename to technology/scn3me_subm/sp_lib/incorrect/replica_cell_1rw_1r.sp diff --git a/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp b/technology/scn3me_subm/sp_lib/incorrect/replica_cell_1w_1r.sp similarity index 100% rename from technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp rename to technology/scn3me_subm/sp_lib/incorrect/replica_cell_1w_1r.sp From a5ed9b56cdb9a0715be5146f3f38a29649a165f5 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 8 May 2019 17:51:38 -0700 Subject: [PATCH 009/234] Optional m4 in design class --- compiler/base/design.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/base/design.py b/compiler/base/design.py index 5a87dd79..516eef80 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -28,7 +28,8 @@ class design(hierarchy_design): self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space, self.m2_space) self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space, self.m3_space) - self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space) + if contact.m3m4: + self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space) def setup_drc_constants(self): """ These are some DRC constants used in many places in the compiler.""" @@ -42,8 +43,9 @@ class design(hierarchy_design): self.m2_space = drc("metal2_to_metal2") self.m3_width = drc("minwidth_metal3") self.m3_space = drc("metal3_to_metal3") - self.m4_width = drc("minwidth_metal4") - self.m4_space = drc("metal4_to_metal4") + if contact.m3m4: + self.m4_width = drc("minwidth_metal4") + self.m4_space = drc("metal4_to_metal4") self.active_width = drc("minwidth_active") self.active_space = drc("active_to_body_active") self.contact_width = drc("minwidth_contact") From b4cce6588989714f5d70f35db3722507423883c6 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Mon, 13 May 2019 19:38:46 -0700 Subject: [PATCH 010/234] Added incorrect read checking in characterizer. --- compiler/characterizer/delay.py | 193 +++++++++++++++++++------ compiler/characterizer/measurements.py | 30 +++- compiler/characterizer/stimuli.py | 7 + compiler/tests/21_hspice_delay_test.py | 25 ++-- 4 files changed, 196 insertions(+), 59 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index a80fc4dc..4b8dae7a 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -1,4 +1,4 @@ -import sys,re,shutil +import sys,re,shutil,copy import debug import tech import math @@ -48,32 +48,33 @@ class delay(simulation): def create_measurement_objects(self): """Create the measurements used for read and write ports""" - self.create_read_port_measurement_objects() - self.create_write_port_measurement_objects() + self.read_meas_lists = self.create_read_port_measurement_objects() + self.write_meas_lists = self.create_write_port_measurement_objects() def create_read_port_measurement_objects(self): """Create the measurements used for read ports: delays, slews, powers""" - self.read_meas_objs = [] + self.read_lib_meas = [] trig_delay_name = "clk{0}" targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit - self.read_meas_objs.append(delay_measure("delay_lh", trig_delay_name, targ_name, "RISE", "RISE", measure_scale=1e9)) - self.read_meas_objs[-1].meta_str = "read1" #Used to index time delay values when measurements written to spice file. - self.read_meas_objs.append(delay_measure("delay_hl", trig_delay_name, targ_name, "FALL", "FALL", measure_scale=1e9)) - self.read_meas_objs[-1].meta_str = "read0" + self.read_lib_meas.append(delay_measure("delay_lh", trig_delay_name, targ_name, "RISE", "RISE", measure_scale=1e9)) + self.read_lib_meas[-1].meta_str = "read1" #Used to index time delay values when measurements written to spice file. + self.read_lib_meas.append(delay_measure("delay_hl", trig_delay_name, targ_name, "FALL", "FALL", measure_scale=1e9)) + self.read_lib_meas[-1].meta_str = "read0" + self.delay_meas = self.read_lib_meas[:] #For debugging, kept separated - self.read_meas_objs.append(slew_measure("slew_lh", targ_name, "RISE", measure_scale=1e9)) - self.read_meas_objs[-1].meta_str = "read1" - self.read_meas_objs.append(slew_measure("slew_hl", targ_name, "FALL", measure_scale=1e9)) - self.read_meas_objs[-1].meta_str = "read0" + self.read_lib_meas.append(slew_measure("slew_lh", targ_name, "RISE", measure_scale=1e9)) + self.read_lib_meas[-1].meta_str = "read1" + self.read_lib_meas.append(slew_measure("slew_hl", targ_name, "FALL", measure_scale=1e9)) + self.read_lib_meas[-1].meta_str = "read0" - self.read_meas_objs.append(power_measure("read1_power", "RISE", measure_scale=1e3)) - self.read_meas_objs[-1].meta_str = "read1" - self.read_meas_objs.append(power_measure("read0_power", "FALL", measure_scale=1e3)) - self.read_meas_objs[-1].meta_str = "read0" + self.read_lib_meas.append(power_measure("read1_power", "RISE", measure_scale=1e3)) + self.read_lib_meas[-1].meta_str = "read1" + self.read_lib_meas.append(power_measure("read0_power", "FALL", measure_scale=1e3)) + self.read_lib_meas[-1].meta_str = "read0" #This will later add a half-period to the spice time delay. Only for reading 0. - for obj in self.read_meas_objs: + for obj in self.read_lib_meas: if obj.meta_str is "read0": obj.meta_add_delay = True @@ -85,17 +86,22 @@ class delay(simulation): bl_name = "Xsram.Xbank0.bl{}_{}".format(port_format, self.bitline_column) br_name = "Xsram.Xbank0.br{}_{}".format(port_format, self.bitline_column) - # self.read_meas_objs.append(voltage_when_measure(self.voltage_when_names[0], trig_name, bl_name, "RISE", .5)) - # self.read_meas_objs.append(voltage_when_measure(self.voltage_when_names[1], trig_name, br_name, "RISE", .5)) + # self.read_lib_meas.append(voltage_when_measure(self.voltage_when_names[0], trig_name, bl_name, "RISE", .5)) + # self.read_lib_meas.append(voltage_when_measure(self.voltage_when_names[1], trig_name, br_name, "RISE", .5)) - #These are read values but need to be separated for unique error checking. - self.create_bitline_delay_measurement_objects() + read_measures = [] + read_measures.append(self.read_lib_meas) + #Other measurements associated with the read port not included in the liberty file + read_measures.append(self.create_bitline_delay_measurement_objects()) + read_measures.append(self.create_debug_measurement_objects()) + + return read_measures def create_bitline_delay_measurement_objects(self): """Create the measurements used for bitline delay values. Due to unique error checking, these are separated from other measurements. These measurements are only associated with read values """ - self.bitline_delay_objs = [] + self.bitline_delay_meas = [] trig_name = "clk{0}" if len(self.all_ports) == 1: #special naming case for single port sram bitlines which does not include the port in name port_format = "" @@ -106,23 +112,51 @@ class delay(simulation): targ_val = (self.vdd_voltage - tech.spice["v_threshold_typical"])/self.vdd_voltage #Calculate as a percentage of vdd targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit - # self.bitline_delay_objs.append(delay_measure(self.bitline_delay_names[0], trig_name, bl_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9)) - # self.bitline_delay_objs[-1].meta_str = "read0" - # self.bitline_delay_objs.append(delay_measure(self.bitline_delay_names[1], trig_name, br_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9)) - # self.bitline_delay_objs[-1].meta_str = "read1" + # self.bitline_delay_meas.append(delay_measure(self.bitline_delay_names[0], trig_name, bl_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9)) + # self.bitline_delay_meas[-1].meta_str = "read0" + # self.bitline_delay_meas.append(delay_measure(self.bitline_delay_names[1], trig_name, br_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9)) + # self.bitline_delay_meas[-1].meta_str = "read1" #Enforces the time delay on the bitline measurements for read0 or read1 - for obj in self.bitline_delay_objs: + for obj in self.bitline_delay_meas: obj.meta_add_delay = True + return self.bitline_delay_meas + def create_write_port_measurement_objects(self): """Create the measurements used for read ports: delays, slews, powers""" - self.write_meas_objs = [] + self.write_lib_meas = [] - self.write_meas_objs.append(power_measure("write1_power", "RISE", measure_scale=1e3)) - self.write_meas_objs[-1].meta_str = "write1" - self.write_meas_objs.append(power_measure("write0_power", "FALL", measure_scale=1e3)) - self.write_meas_objs[-1].meta_str = "write0" - + self.write_lib_meas.append(power_measure("write1_power", "RISE", measure_scale=1e3)) + self.write_lib_meas[-1].meta_str = "write1" + self.write_lib_meas.append(power_measure("write0_power", "FALL", measure_scale=1e3)) + self.write_lib_meas[-1].meta_str = "write0" + + write_measures = [] + write_measures.append(self.write_lib_meas) + return write_measures + + def create_debug_measurement_objects(self): + """Create debug measurement to help identify failures.""" + + self.debug_delay_meas = [] + self.debug_volt_meas = [] + for meas in self.delay_meas: + debug_meas = copy.deepcopy(meas) + debug_meas.name = debug_meas.name+'_debug' + #This particular debugs check if output value is flipped, so TARG_DIR is flipped + if meas.targ_dir_str == 'FALL': + debug_meas.targ_dir_str = 'RISE' + else: + debug_meas.targ_dir_str = 'FALL' + #inserting debug member variable + debug_meas.parent = meas.name + self.debug_delay_meas.append(debug_meas) + + self.debug_volt_meas.append(voltage_at_measure("v_{}".format(debug_meas.meta_str), + debug_meas.targ_name_no_port)) + self.debug_volt_meas[-1].meta_str = debug_meas.meta_str + return self.debug_delay_meas+self.debug_volt_meas + def create_signal_names(self): self.addr_name = "A" self.din_name = "DIN" @@ -284,6 +318,8 @@ class delay(simulation): return self.get_power_measure_variants(port, measure_obj, "read") elif meas_type is voltage_when_measure: return self.get_volt_when_measure_variants(port, measure_obj) + elif meas_type is voltage_at_measure: + return self.get_volt_at_measure_variants(port, measure_obj) else: debug.error("Input function not defined for measurement type={}".format(meas_type)) @@ -299,6 +335,7 @@ class delay(simulation): else: debug.error("Unrecognised delay Index={}".format(delay_obj.meta_str),1) + #These measurements have there time further delayed to the neg. edge of the clock. if delay_obj.meta_add_delay: meas_cycle_delay += self.period/2 @@ -312,7 +349,21 @@ class delay(simulation): return (t_initial, t_final, port) - def get_volt_when_measure_variants(self, port, power_obj): + def get_volt_at_measure_variants(self, port, volt_meas): + """Get the measurement values that can either vary port to port (time delays)""" + #Only checking 0 value reads for now. + if volt_meas.meta_str == "read0": + #Falling delay are measured starting from neg. clk edge. Delay adjusted to that. + meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]] + elif volt_meas.meta_str == "read1": + meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]] + else: + debug.error("Unrecognised delay Index={}".format(volt_meas.meta_str),1) + #Measurement occurs at the end of the period -> current period start + period + at_time = meas_cycle+self.period + return (at_time, port) + + def get_volt_when_measure_variants(self, port, volt_meas): """Get the measurement values that can either vary port to port (time delays)""" #Only checking 0 value reads for now. t_trig = meas_cycle_delay = self.cycle_times[self.measure_cycles[port]["read0"]] @@ -324,9 +375,10 @@ class delay(simulation): Write the measure statements to quantify the delay and power results for a read port. """ # add measure statements for delays/slews - for measure in self.read_meas_objs+self.bitline_delay_objs: - measure_variant_inp_tuple = self.get_read_measure_variants(port, measure) - measure.write_measure(self.stim, measure_variant_inp_tuple) + for meas_list in self.read_meas_lists: + for measure in meas_list: + measure_variant_inp_tuple = self.get_read_measure_variants(port, measure) + measure.write_measure(self.stim, measure_variant_inp_tuple) def get_write_measure_variants(self, port, measure_obj): """Checks the measurement object and calls respective function for related measurement inputs.""" @@ -341,9 +393,10 @@ class delay(simulation): Write the measure statements to quantify the power results for a write port. """ # add measure statements for power - for measure in self.write_meas_objs: - measure_variant_inp_tuple = self.get_write_measure_variants(port, measure) - measure.write_measure(self.stim, measure_variant_inp_tuple) + for meas_list in self.write_meas_lists: + for measure in meas_list: + measure_variant_inp_tuple = self.get_write_measure_variants(port, measure) + measure.write_measure(self.stim, measure_variant_inp_tuple) def write_delay_measures(self): """ @@ -462,6 +515,7 @@ class delay(simulation): #Sanity Check debug.check(self.period > 0, "Target simulation period non-positive") + sim_passed = True result = [{} for i in self.all_ports] # Checking from not data_value to data_value self.write_delay_stimulus() @@ -471,17 +525,18 @@ class delay(simulation): #Loop through all targeted ports and collect delays and powers. #Too much duplicate code here. Try reducing for port in self.targ_read_ports: - debug.info(2, "Check delay values for port {}".format(port)) + debug.info(2, "Checking delay values for port {}".format(port)) read_port_dict = {} #Get measurements from output file - for measure in self.read_meas_objs: + for measure in self.read_lib_meas: read_port_dict[measure.name] = measure.retrieve_measure(port=port) + debug_passed = self.check_debug_measures(port, read_port_dict) #Check timing for read ports. Power is only checked if it was read correctly - if not self.check_valid_delays(read_port_dict): + if not self.check_valid_delays(read_port_dict) or not debug_passed: return (False,{}) if not check_dict_values_is_float(read_port_dict): - debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) #Printing the entire dict looks bad. + debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) #Printing the entire dict looks bad. result[port].update(read_port_dict) @@ -490,7 +545,7 @@ class delay(simulation): for port in self.targ_write_ports: write_port_dict = {} - for measure in self.write_meas_objs: + for measure in self.write_lib_meas: write_port_dict[measure.name] = measure.retrieve_measure(port=port) if not check_dict_values_is_float(write_port_dict): @@ -498,13 +553,54 @@ class delay(simulation): result[port].update(write_port_dict) # The delay is from the negative edge for our SRAM - return (True,result) + return (sim_passed,result) + def check_debug_measures(self, port, read_measures): + """Debug measures that indicate special conditions.""" + #Currently, only check if the opposite than intended value was read during + # the read cycles i.e. neither of these measurements should pass. + success = True + for meas in self.debug_delay_meas: + val = meas.retrieve_measure(port=port) + debug.info(2,"{}={}".format(meas.name, val)) + if type(val) != float: + continue + + if meas.meta_add_delay: + max_delay = self.period/2 + else: + max_delay = self.period + + #If the debug measurement occurs after the original (and passes other conditions) + #then it fails i.e. the debug value represents the final (but failing) state of the output + parent_compare = type(read_measures[meas.parent]) != float or val > read_measures[meas.parent] + if 0 < val < max_delay and parent_compare: + success = False + debug.info(1, "Debug measurement failed. Incorrect Value found on output.") + break + + for meas in self.debug_volt_meas: + val = meas.retrieve_measure(port=port) + debug.info(2,"{}={}".format(meas.name, val)) + if type(val) != float: + continue + + if meas.meta_str == 'read1' and val < tech.spice["v_threshold_typical"]: + success = False + debug.info(1, "Debug measurement failed. Value {}v was read on read 1 cycle.".format(val)) + break + elif meas.meta_str == 'read0' and val > self.vdd_voltage-tech.spice["v_threshold_typical"]: + success = False + debug.info(1, "Debug measurement failed. Value {}v was read on read 0 cycle.".format(val)) + break + + return success + def evaluate_bitline_delay(self, port): """Parse and check the bitline delay. One of the measurements is expected to fail which warrants its own function.""" bl_delay_meas_dict = {} values_added = 0 #For error checking - for measure in self.bitline_delay_objs: + for measure in self.bitline_delay_meas: bl_delay_val = measure.retrieve_measure(port=port) if type(bl_delay_val) != float or 0 > bl_delay_val or bl_delay_val > self.period/2: #Only add if value is valid, do not error. debug.error("Bitline delay measurement failed: half-period={}, {}={}".format(self.period/2, measure.name, bl_delay_val),1) @@ -556,7 +652,8 @@ class delay(simulation): delays_str = "delay_hl={0} delay_lh={1}".format(delay_hl, delay_lh) slews_str = "slew_hl={0} slew_lh={1}".format(slew_hl,slew_lh) half_period = self.period/2 #high-to-low delays start at neg. clk edge, so they need to be less than half_period - if abs(delay_hl)>half_period or abs(delay_lh)>self.period or abs(slew_hl)>half_period or abs(slew_lh)>self.period: + if abs(delay_hl)>half_period or abs(delay_lh)>self.period or abs(slew_hl)>half_period or abs(slew_lh)>self.period \ + or delay_hl<0 or delay_lh<0 or slew_hl<0 or slew_lh<0: debug.info(2,"UNsuccessful simulation (in ns):\n\t\t{0}\n\t\t{1}\n\t\t{2}".format(period_load_slew_str, delays_str, slews_str)) diff --git a/compiler/characterizer/measurements.py b/compiler/characterizer/measurements.py index e3d16584..7c568697 100644 --- a/compiler/characterizer/measurements.py +++ b/compiler/characterizer/measurements.py @@ -156,4 +156,32 @@ class voltage_when_measure(spice_measurement): trig_voltage = self.trig_val_of_vdd*vdd_voltage - return (meas_name,trig_name,targ_name,trig_voltage,self.trig_dir_str,trig_td) \ No newline at end of file + return (meas_name,trig_name,targ_name,trig_voltage,self.trig_dir_str,trig_td) + +class voltage_at_measure(spice_measurement): + """Generates a spice measurement to measure the voltage at a specific time. + The time is considered variant with different periods.""" + + def __init__(self, measure_name, targ_name, measure_scale=None): + spice_measurement.__init__(self, measure_name, measure_scale) + self.set_meas_constants(targ_name) + + def get_measure_function(self): + return stimuli.gen_meas_find_voltage_at_time + + def set_meas_constants(self, targ_name): + """Sets values useful for power simulations. This value is only meta related to the lib file (rise/fall)""" + self.targ_name_no_port = targ_name + + def get_measure_values(self, time_at, port=None): + """Constructs inputs to stimulus measurement function. Variant values are inputs here.""" + if port != None: + #For dictionary indexing reasons, the name is formatted differently than the signals + meas_name = "{}{}".format(self.name, port) + targ_name = self.targ_name_no_port.format(port) + else: + 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/stimuli.py b/compiler/characterizer/stimuli.py index 3b569b2a..01111abd 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -226,6 +226,13 @@ class stimuli(): trig_dir, trig_td)) + def gen_meas_find_voltage_at_time(self, meas_name, targ_name, time_at): + """ Creates the .meas statement for voltage at time""" + measure_string=".meas tran {0} FIND v({1}) AT={2}n \n\n" + self.sf.write(measure_string.format(meas_name, + targ_name, + time_at)) + def gen_meas_power(self, meas_name, t_initial, t_final): """ Creates the .meas statement for the measurement of avg power """ # power mea cmd is different in different spice: diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index b7ccd72c..96a8db84 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -26,10 +26,15 @@ class timing_sram_test(openram_test): reload(characterizer) from characterizer import delay from sram_config import sram_config - c = sram_config(word_size=1, - num_words=16, + # c = sram_config(word_size=1, + # num_words=16, + # num_banks=1) + # c.words_per_row=1 + c = sram_config(word_size=32, + num_words=256, num_banks=1) - c.words_per_row=1 + c.words_per_row=2 + OPTS.use_tech_delay_chain_size = True c.recompute_sizes() debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") s = factory.create(module_type="sram", sram_config=c) @@ -42,13 +47,13 @@ class timing_sram_test(openram_test): s.s.graph_exclude_data_dff() s.s.graph_exclude_ctrl_dffs() - debug.info(1,'pins={}'.format(s.s.pins)) - import graph_util - graph = graph_util.timing_graph() - pins=['DIN0[0]', 'ADDR0[0]', 'ADDR0[1]', 'ADDR0[2]', 'ADDR0[3]', 'csb0', 'web0', 'clk0', 'DOUT0[0]', 'vdd', 'gnd'] - s.s.build_graph(graph,"Xsram",pins) - #debug.info(1,"{}".format(graph)) - graph.print_all_paths('clk0', 'DOUT0[0]') + # debug.info(1,'pins={}'.format(s.s.pins)) + # import graph_util + # graph = graph_util.timing_graph() + # pins=['DIN0[0]', 'ADDR0[0]', 'ADDR0[1]', 'ADDR0[2]', 'ADDR0[3]', 'csb0', 'web0', 'clk0', 'DOUT0[0]', 'vdd', 'gnd'] + # s.s.build_graph(graph,"Xsram",pins) + # #debug.info(1,"{}".format(graph)) + # graph.print_all_paths('clk0', 'DOUT0[0]') # import sys # sys.exit(1) From b30c20ffb515754098556172b7403845f02645de Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 14 May 2019 01:15:50 -0700 Subject: [PATCH 011/234] Added graph creation to characterizer, re-arranged pin creation. --- compiler/characterizer/delay.py | 42 +++++++++++++--------- compiler/characterizer/functional.py | 15 ++------ compiler/characterizer/simulation.py | 48 +++++++++++++++++++++++++ compiler/characterizer/stimuli.py | 50 ++++---------------------- compiler/tests/21_hspice_delay_test.py | 26 +++++++------- 5 files changed, 97 insertions(+), 84 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 4b8dae7a..3939511f 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -10,6 +10,7 @@ from globals import OPTS from .simulation import simulation from .measurements import * import logical_effort +import graph_util class delay(simulation): """Functions to measure the delay and power of an SRAM at a given address and @@ -37,6 +38,8 @@ class delay(simulation): self.period = 0 self.set_load_slew(0,0) self.set_corner(corner) + self.create_signal_names() + self.add_graph_exclusions() def create_measurement_names(self): """Create measurement names. The names themselves currently define the type of measurement""" @@ -157,19 +160,31 @@ class delay(simulation): self.debug_volt_meas[-1].meta_str = debug_meas.meta_str return self.debug_delay_meas+self.debug_volt_meas - def create_signal_names(self): - self.addr_name = "A" - self.din_name = "DIN" - self.dout_name = "DOUT" - - #This is TODO once multiport control has been finalized. - #self.control_name = "CSB" - def set_load_slew(self,load,slew): """ Set the load and slew """ self.load = load self.slew = slew + def add_graph_exclusions(self): + """Exclude portions of SRAM from timing graph which are not relevant""" + #other initializations can only be done during analysis when a bit has been selected + #for testing. + self.sram.bank.graph_exclude_precharge() + self.sram.graph_exclude_addr_dff() + self.sram.graph_exclude_data_dff() + self.sram.graph_exclude_ctrl_dffs() + + def create_graph(self): + """Creates timing graph to generate the timing paths for the SRAM output.""" + self.sram.bank.bitcell_array.init_graph_params() #Removes previous bit exclusions + self.sram.bank.bitcell_array.graph_exclude_bits(self.wordline_row, self.bitline_column) + + #Generate new graph every analysis as edges might change depending on test bit + self.graph = graph_util.timing_graph() + self.sram.build_graph(self.graph,"X{}".format(self.sram.name),self.pins) + #debug.info(1,"{}".format(graph)) + #graph.print_all_paths('clk0', 'DOUT0[0]') + def check_arguments(self): """Checks if arguments given for write_stimulus() meets requirements""" try: @@ -198,12 +213,8 @@ class delay(simulation): # instantiate the sram self.sf.write("\n* Instantiation of the SRAM\n") - self.stim.inst_sram(sram=self.sram, - port_signal_names=(self.addr_name,self.din_name,self.dout_name), - port_info=(len(self.all_ports),self.write_ports,self.read_ports), - abits=self.addr_size, - dbits=self.word_size, - sram_name=self.name) + self.stim.inst_model(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): @@ -812,7 +823,7 @@ class delay(simulation): char_sram_data = {} self.set_probe(probe_address, probe_data) - self.create_signal_names() + self.create_graph() self.create_measurement_names() self.create_measurement_objects() @@ -998,7 +1009,6 @@ class delay(simulation): """ 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.") - self.create_signal_names() self.create_measurement_names() power = self.analytical_power(slews, loads) port_data = self.get_empty_measure_data_dict() diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index ca05648a..d1471d2f 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -194,12 +194,7 @@ class functional(simulation): new_value = "0" + new_value #print("Binary Conversion: {} to {}".format(value, new_value)) - return new_value - - def create_signal_names(self): - self.addr_name = "A" - self.din_name = "DIN" - self.dout_name = "DOUT" + return new_value def write_functional_stimulus(self): """ Writes SPICE stimulus. """ @@ -219,12 +214,8 @@ class functional(simulation): #Instantiate the SRAM self.sf.write("\n* Instantiation of the SRAM\n") - self.stim.inst_sram(sram=self.sram, - port_signal_names=(self.addr_name,self.din_name,self.dout_name), - port_info=(len(self.all_ports), self.write_ports, self.read_ports), - abits=self.addr_size, - dbits=self.word_size, - sram_name=self.name) + self.stim.inst_model(pins=self.pins, + model_name=self.sram.name) # Add load capacitance to each of the read ports self.sf.write("\n* SRAM output loads\n") diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index beca0502..e14ee635 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -42,6 +42,19 @@ class simulation(): self.v_low = tech.spice["v_threshold_typical"] self.gnd_voltage = 0 + def create_signal_names(self): + self.addr_name = "A" + self.din_name = "DIN" + self.dout_name = "DOUT" + self.pins = self.gen_pin_names(port_signal_names=(self.addr_name,self.din_name,self.dout_name), + port_info=(len(self.all_ports),self.write_ports,self.read_ports), + abits=self.addr_size, + dbits=self.word_size) + debug.check(len(self.sram.pins) == len(self.pins), "Number of pins generated for characterization \ + do match pins of SRAM\nsram.pins = {0}\npin_names = {1}".format(self.sram.pins,self.pins)) + #This is TODO once multiport control has been finalized. + #self.control_name = "CSB" + def set_stimulus_variables(self): # Clock signals self.cycle_times = [] @@ -223,3 +236,38 @@ class simulation(): t_current+self.period) return comment + def gen_pin_names(self, port_signal_names, port_info, abits, dbits): + """Creates the pins names of the SRAM based on the no. of ports.""" + #This may seem redundant as the pin names are already defined in the sram. However, it is difficult + #to extract the functionality from the names, so they are recreated. As the order is static, changing + #the order of the pin names will cause issues here. + pin_names = [] + (addr_name, din_name, dout_name) = port_signal_names + (total_ports, write_index, read_index) = port_info + + for write_input in write_index: + for i in range(dbits): + pin_names.append("{0}{1}_{2}".format(din_name,write_input, i)) + + for port in range(total_ports): + for i in range(abits): + pin_names.append("{0}{1}_{2}".format(addr_name,port,i)) + + #Control signals not finalized. + for port in range(total_ports): + pin_names.append("CSB{0}".format(port)) + for port in range(total_ports): + if (port in read_index) and (port in write_index): + pin_names.append("WEB{0}".format(port)) + + for port in range(total_ports): + pin_names.append("{0}{1}".format(tech.spice["clk"], port)) + + for read_output in read_index: + for i in range(dbits): + pin_names.append("{0}{1}_{2}".format(dout_name,read_output, i)) + + pin_names.append("{0}".format(tech.spice["vdd_name"])) + pin_names.append("{0}".format(tech.spice["gnd_name"])) + return pin_names + diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 01111abd..6da966cc 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -29,51 +29,15 @@ class stimuli(): (self.process, self.voltage, self.temperature) = corner self.device_models = tech.spice["fet_models"][self.process] - def inst_sram(self, sram, port_signal_names, port_info, abits, dbits, sram_name): + self.sram_name = "Xsram" + + def inst_sram(self, pins, inst_name): """ Function to instatiate an SRAM subckt. """ - pin_names = self.gen_pin_names(port_signal_names, port_info, abits, dbits) - #Only checking length. This should check functionality as well (TODO) and/or import that information from the SRAM - debug.check(len(sram.pins) == len(pin_names), "Number of pins generated for characterization do match pins of SRAM\nsram.pins = {0}\npin_names = {1}".format(sram.pins,pin_names)) - - self.sf.write("Xsram ") - for pin in pin_names: + + self.sf.write("{} ".format(self.sram_name)) + for pin in self.sram_pins: self.sf.write("{0} ".format(pin)) - self.sf.write("{0}\n".format(sram_name)) - - def gen_pin_names(self, port_signal_names, port_info, abits, dbits): - """Creates the pins names of the SRAM based on the no. of ports.""" - #This may seem redundant as the pin names are already defined in the sram. However, it is difficult to extract the - #functionality from the names, so they are recreated. As the order is static, changing the order of the pin names - #will cause issues here. - pin_names = [] - (addr_name, din_name, dout_name) = port_signal_names - (total_ports, write_index, read_index) = port_info - - for write_input in write_index: - for i in range(dbits): - pin_names.append("{0}{1}_{2}".format(din_name,write_input, i)) - - for port in range(total_ports): - for i in range(abits): - pin_names.append("{0}{1}_{2}".format(addr_name,port,i)) - - #Control signals not finalized. - for port in range(total_ports): - pin_names.append("CSB{0}".format(port)) - for port in range(total_ports): - if (port in read_index) and (port in write_index): - pin_names.append("WEB{0}".format(port)) - - for port in range(total_ports): - pin_names.append("{0}{1}".format(tech.spice["clk"], port)) - - for read_output in read_index: - for i in range(dbits): - pin_names.append("{0}{1}_{2}".format(dout_name,read_output, i)) - - pin_names.append("{0}".format(self.vdd_name)) - pin_names.append("{0}".format(self.gnd_name)) - return pin_names + self.sf.write("{0}\n".format(inst_name)) def inst_model(self, pins, model_name): """ Function to instantiate a generic model with a set of pins """ diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 96a8db84..2cdd3414 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -26,26 +26,26 @@ class timing_sram_test(openram_test): reload(characterizer) from characterizer import delay from sram_config import sram_config - # c = sram_config(word_size=1, - # num_words=16, - # num_banks=1) - # c.words_per_row=1 - c = sram_config(word_size=32, - num_words=256, + c = sram_config(word_size=1, + num_words=16, num_banks=1) - c.words_per_row=2 - OPTS.use_tech_delay_chain_size = True + c.words_per_row=1 + # c = sram_config(word_size=32, + # num_words=256, + # num_banks=1) + # c.words_per_row=2 + #OPTS.use_tech_delay_chain_size = True c.recompute_sizes() debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") s = factory.create(module_type="sram", sram_config=c) #Exclude things known not to be in critical path. #Intended for characterizing read paths. Somewhat hacky implementation - s.s.bank.bitcell_array.graph_exclude_bits(15,0) - s.s.bank.graph_exclude_precharge() - s.s.graph_exclude_addr_dff() - s.s.graph_exclude_data_dff() - s.s.graph_exclude_ctrl_dffs() + # s.s.bank.bitcell_array.graph_exclude_bits(15,0) + # s.s.bank.graph_exclude_precharge() + # s.s.graph_exclude_addr_dff() + # s.s.graph_exclude_data_dff() + # s.s.graph_exclude_ctrl_dffs() # debug.info(1,'pins={}'.format(s.s.pins)) # import graph_util From 178d3df5f5964c1e0ce54750d5fcabd8eb92b612 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 14 May 2019 14:44:49 -0700 Subject: [PATCH 012/234] Added graph to characterizer to get net names and perform s_en checks. Graph not working with column mux. --- compiler/base/graph_util.py | 33 ++++++-- compiler/base/hierarchy_spice.py | 8 +- compiler/characterizer/delay.py | 106 +++++++++++++++---------- compiler/modules/tri_gate.py | 2 +- compiler/sram_1bank.py | 18 +++++ compiler/tests/21_hspice_delay_test.py | 16 ++-- 6 files changed, 121 insertions(+), 62 deletions(-) diff --git a/compiler/base/graph_util.py b/compiler/base/graph_util.py index d2759930..25c79d3b 100644 --- a/compiler/base/graph_util.py +++ b/compiler/base/graph_util.py @@ -1,4 +1,4 @@ -import os +import os, copy from collections import defaultdict import gdsMill @@ -16,6 +16,7 @@ class timing_graph(): def __init__(self): self.graph = defaultdict(set) + self.all_paths = [] def add_edge(self, src_node, dest_node): """Adds edge to graph. Nodes added as well if they do not exist.""" @@ -34,7 +35,7 @@ class timing_graph(): node = node.lower() self.graph[node] = set() - def print_all_paths(self, src_node, dest_node, rmv_rail_nodes=True): + def get_all_paths(self, src_node, dest_node, rmv_rail_nodes=True): """Traverse all paths from source to destination""" src_node = src_node.lower() dest_node = dest_node.lower() @@ -51,13 +52,15 @@ class timing_graph(): # Create an array to store paths path = [] - self.path_count = 0 + self.all_paths = [] # Call the recursive helper function to print all paths - self.print_all_paths_util(src_node, dest_node, visited, path) - debug.info(1, "Paths found={}".format(self.path_count)) + self.get_all_paths_util(src_node, dest_node, visited, path) + debug.info(1, "Paths found={}".format(len(self.all_paths))) - def print_all_paths_util(self, cur_node, dest_node, visited, path): + return self.all_paths + + def get_all_paths_util(self, cur_node, dest_node, visited, path): """Recursive function to find all paths in a Depth First Search manner""" # Mark the current node as visited and store in path visited.add(cur_node) @@ -67,18 +70,32 @@ class timing_graph(): # current path[] if cur_node == dest_node: debug.info(1,"{}".format(path)) - self.path_count+=1 + self.all_paths.append(copy.deepcopy(path)) else: # If current vertex is not destination #Recur for all the vertices adjacent to this vertex for node in self.graph[cur_node]: if node not in visited: - self.print_all_paths_util(node, dest_node, visited, path) + self.get_all_paths_util(node, dest_node, visited, path) # Remove current vertex from path[] and mark it as unvisited path.pop() visited.remove(cur_node) + def get_path_preconvergence_point(self, path1, path2): + """Assuming the inputs paths have the same starting point and end point, the + paths should split and converge at some point before/at the last stage. Finds the + point before convergence.""" + debug.check(path1[0] == path2[0], "Paths must start from the same point.") + debug.check(path1[-1] == path2[-1], "Paths must end from the same point.") + #Paths must end at the same point, so the paths are traversed backwards to find + #point of convergence. There could be multiple points, only finds first. + for point1,point2 in zip(reversed(path1), reversed(path2)): + if point1 != point2: + return (point1,point2) + debug.info(1,"Pre-convergence point not found, paths are equals.") + return path1[0],path2[0] + def __str__(self): """ override print function output """ return "Nodes: {}\nEdges:{} ".format(list(self.graph), self.graph) \ No newline at end of file diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index f2535f86..6dddf4c5 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -140,7 +140,13 @@ class spice(): debug.error("-----") debug.error("Connections: \n"+str(conns_string),1) - + def get_conns(self, inst): + """Returns the connections of a given instance.""" + for i in range(len(self.insts)): + if inst is self.insts[i]: + return self.conns[i] + #If not found, returns None + return None def sp_read(self): """Reads the sp file (and parse the pins) from the library diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 3939511f..b7169a0d 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -81,49 +81,39 @@ class delay(simulation): if obj.meta_str is "read0": obj.meta_add_delay = True - trig_name = "Xsram.s_en{}" #Sense amp enable - if len(self.all_ports) == 1: #special naming case for single port sram bitlines which does not include the port in name - port_format = "" - else: - port_format = "{}" + # trig_name = "Xsram.s_en{}" #Sense amp enable + # if len(self.all_ports) == 1: #special naming case for single port sram bitlines which does not include the port in name + # port_format = "" + # else: + # port_format = "{}" - bl_name = "Xsram.Xbank0.bl{}_{}".format(port_format, self.bitline_column) - br_name = "Xsram.Xbank0.br{}_{}".format(port_format, self.bitline_column) + # bl_name = "Xsram.Xbank0.bl{}_{}".format(port_format, self.bitline_column) + # br_name = "Xsram.Xbank0.br{}_{}".format(port_format, self.bitline_column) # self.read_lib_meas.append(voltage_when_measure(self.voltage_when_names[0], trig_name, bl_name, "RISE", .5)) # self.read_lib_meas.append(voltage_when_measure(self.voltage_when_names[1], trig_name, br_name, "RISE", .5)) read_measures = [] read_measures.append(self.read_lib_meas) #Other measurements associated with the read port not included in the liberty file - read_measures.append(self.create_bitline_delay_measurement_objects()) + read_measures.append(self.create_bitline_measurement_objects()) read_measures.append(self.create_debug_measurement_objects()) return read_measures - def create_bitline_delay_measurement_objects(self): + def create_bitline_measurement_objects(self): """Create the measurements used for bitline delay values. Due to unique error checking, these are separated from other measurements. These measurements are only associated with read values """ - self.bitline_delay_meas = [] - trig_name = "clk{0}" - if len(self.all_ports) == 1: #special naming case for single port sram bitlines which does not include the port in name - port_format = "" - else: - port_format = "{}" - bl_name = "Xsram.Xbank0.bl{}_{}".format(port_format, self.bitline_column) - br_name = "Xsram.Xbank0.br{}_{}".format(port_format, self.bitline_column) - targ_val = (self.vdd_voltage - tech.spice["v_threshold_typical"])/self.vdd_voltage #Calculate as a percentage of vdd + self.bitline_volt_meas = [] + #Bitline voltage measures + self.bitline_volt_meas.append(voltage_at_measure("v_bl_name", + self.bl_name)) + self.bitline_volt_meas[-1].meta_str = 'read0' - targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit - # self.bitline_delay_meas.append(delay_measure(self.bitline_delay_names[0], trig_name, bl_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9)) - # self.bitline_delay_meas[-1].meta_str = "read0" - # self.bitline_delay_meas.append(delay_measure(self.bitline_delay_names[1], trig_name, br_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9)) - # self.bitline_delay_meas[-1].meta_str = "read1" - #Enforces the time delay on the bitline measurements for read0 or read1 - for obj in self.bitline_delay_meas: - obj.meta_add_delay = True - - return self.bitline_delay_meas + self.bitline_volt_meas.append(voltage_at_measure("v_br_name", + self.br_name)) + self.bitline_volt_meas[-1].meta_str = 'read1' + return self.bitline_volt_meas def create_write_port_measurement_objects(self): """Create the measurements used for read ports: delays, slews, powers""" @@ -155,9 +145,11 @@ class delay(simulation): debug_meas.parent = meas.name self.debug_delay_meas.append(debug_meas) + #Output voltage measures self.debug_volt_meas.append(voltage_at_measure("v_{}".format(debug_meas.meta_str), debug_meas.targ_name_no_port)) self.debug_volt_meas[-1].meta_str = debug_meas.meta_str + return self.debug_delay_meas+self.debug_volt_meas def set_load_slew(self,load,slew): @@ -183,7 +175,28 @@ class delay(simulation): self.graph = graph_util.timing_graph() self.sram.build_graph(self.graph,"X{}".format(self.sram.name),self.pins) #debug.info(1,"{}".format(graph)) - #graph.print_all_paths('clk0', 'DOUT0[0]') + port = 0 + self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), \ + '{}{}_{}'.format(self.dout_name, port, self.probe_data)) + sen_name = self.sram.get_sen_name(self.sram.name, port).lower() + debug.info(1, "Sen name={}".format(sen_name)) + sen_path = [] + for path in self.graph.all_paths: + if sen_name in path: + sen_path = path + break + debug.check(len(sen_path)!=0, "Could not find s_en timing path.") + preconv_names = [] + for path in self.graph.all_paths: + if not path is sen_path: + sen_preconv = self.graph.get_path_preconvergence_point(path, sen_path) + if sen_preconv not in preconv_names: + preconv_names.append(sen_preconv[0]) #only save non-sen_path names + + #Not an good way to separate inverting and non-inverting bitlines... + self.bl_name = [bl for bl in preconv_names if 'bl' in bl][0] + self.br_name = [bl for bl in preconv_names if 'br' in bl][0] + debug.info(1,"bl_name={}".format(self.bl_name)) def check_arguments(self): """Checks if arguments given for write_stimulus() meets requirements""" @@ -551,9 +564,6 @@ class delay(simulation): result[port].update(read_port_dict) - bitline_delay_dict = self.evaluate_bitline_delay(port) - result[port].update(bitline_delay_dict) - for port in self.targ_write_ports: write_port_dict = {} for measure in self.write_lib_meas: @@ -589,7 +599,14 @@ class delay(simulation): success = False debug.info(1, "Debug measurement failed. Incorrect Value found on output.") break - + + #FIXME: these checks need to be re-done to be more robust against possible errors + bitline_results = {} + for meas in self.bitline_volt_meas: + val = meas.retrieve_measure(port=port) + bitline_results[meas.meta_str] = val + + for meas in self.debug_volt_meas: val = meas.retrieve_measure(port=port) debug.info(2,"{}={}".format(meas.name, val)) @@ -604,19 +621,20 @@ class delay(simulation): success = False debug.info(1, "Debug measurement failed. Value {}v was read on read 0 cycle.".format(val)) break - + + #If the bitlines have a correct value while the output does not then that is a + #sen error. FIXME: there are other checks that can be done to solidfy this conclusion. + if not success and self.check_bitline_meas(bitline_results[meas.meta_str]): + debug.error("Sense amp enable timing error. Increase the delay chain through the configuration file.",1) + return success - def evaluate_bitline_delay(self, port): - """Parse and check the bitline delay. One of the measurements is expected to fail which warrants its own function.""" - bl_delay_meas_dict = {} - values_added = 0 #For error checking - for measure in self.bitline_delay_meas: - bl_delay_val = measure.retrieve_measure(port=port) - if type(bl_delay_val) != float or 0 > bl_delay_val or bl_delay_val > self.period/2: #Only add if value is valid, do not error. - debug.error("Bitline delay measurement failed: half-period={}, {}={}".format(self.period/2, measure.name, bl_delay_val),1) - bl_delay_meas_dict[measure.name] = bl_delay_val - return bl_delay_meas_dict + + def check_bitline_meas(self, v_bitline): + """Checks the value of the discharging bitline""" + + return v_bitline < self.vdd_voltage*0.9 + def run_power_simulation(self): """ diff --git a/compiler/modules/tri_gate.py b/compiler/modules/tri_gate.py index 4b7501dd..633715af 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -10,7 +10,7 @@ class tri_gate(design.design): netlist should be available in the technology library. """ - pin_names = ["in", "out", "en", "en_bar", "gnd", "vdd"] + pin_names = ["in", "out", "en", "en_bar", "vdd", "gnd"] type_list = ["INPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("tri_gate", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "tri_gate", GDS["unit"]) diff --git a/compiler/sram_1bank.py b/compiler/sram_1bank.py index ca10d827..cf822861 100644 --- a/compiler/sram_1bank.py +++ b/compiler/sram_1bank.py @@ -327,3 +327,21 @@ class sram_1bank(sram_base): #Insts located in control logic, exclusion function called here for inst in self.control_logic_insts: inst.mod.graph_exclude_dffs() + + def get_sen_name(self, sram_name, port=0): + """Returns the s_en spice name.""" + #Naming scheme is hardcoded using this function, should be built into the + #graph in someway. + sen_name = "s_en{}".format(port) + control_conns = self.get_conns(self.control_logic_insts[port]) + #Sanity checks + if sen_name not in control_conns: + 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.info(1,"pins={}".format(self.pins)) + debug.info(1,"cl conns={}".format(control_conns)) + return "X{}.{}".format(sram_name, sen_name) + + diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 2cdd3414..16ef6de1 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -26,15 +26,15 @@ class timing_sram_test(openram_test): reload(characterizer) from characterizer import delay from sram_config import sram_config - c = sram_config(word_size=1, - num_words=16, - num_banks=1) - c.words_per_row=1 - # c = sram_config(word_size=32, - # num_words=256, + # c = sram_config(word_size=1, + # num_words=16, # num_banks=1) - # c.words_per_row=2 - #OPTS.use_tech_delay_chain_size = True + # c.words_per_row=1 + c = sram_config(word_size=32, + num_words=256, + num_banks=1) + c.words_per_row=2 + OPTS.use_tech_delay_chain_size = True c.recompute_sizes() debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") s = factory.create(module_type="sram", sram_config=c) From a80698918b3b65eaa1a4861c214bd3dc364fcb6b Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Wed, 15 May 2019 17:17:26 -0700 Subject: [PATCH 013/234] Fixed test issues, removed all bitcells not relevant for timing graph. --- compiler/characterizer/delay.py | 33 +++++++++++-------------------- compiler/modules/bitcell_array.py | 7 ++++--- compiler/tests/testutils.py | 5 +---- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index b7169a0d..87f0259b 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -174,7 +174,7 @@ class delay(simulation): #Generate new graph every analysis as edges might change depending on test bit self.graph = graph_util.timing_graph() self.sram.build_graph(self.graph,"X{}".format(self.sram.name),self.pins) - #debug.info(1,"{}".format(graph)) + #debug.info(1,"{}".format(self.graph)) port = 0 self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), \ '{}{}_{}'.format(self.dout_name, port, self.probe_data)) @@ -605,6 +605,7 @@ class delay(simulation): for meas in self.bitline_volt_meas: val = meas.retrieve_measure(port=port) bitline_results[meas.meta_str] = val + debug.info(1,"{}={}".format(meas.name,val)) for meas in self.debug_volt_meas: @@ -616,11 +617,9 @@ class delay(simulation): if meas.meta_str == 'read1' and val < tech.spice["v_threshold_typical"]: success = False debug.info(1, "Debug measurement failed. Value {}v was read on read 1 cycle.".format(val)) - break elif meas.meta_str == 'read0' and val > self.vdd_voltage-tech.spice["v_threshold_typical"]: success = False debug.info(1, "Debug measurement failed. Value {}v was read on read 0 cycle.".format(val)) - break #If the bitlines have a correct value while the output does not then that is a #sen error. FIXME: there are other checks that can be done to solidfy this conclusion. @@ -831,31 +830,23 @@ class delay(simulation): # Make a copy in temp for debugging shutil.copy(self.sp_file, self.sim_sp_file) - - - def analyze(self,probe_address, probe_data, slews, loads): - """ - Main function to characterize an SRAM for a table. Computes both delay and power characterization. - """ - #Dict to hold all characterization values - char_sram_data = {} - + def analysis_init(self, probe_address, probe_data): + """Sets values which are dependent on the data address/bit being tested.""" self.set_probe(probe_address, probe_data) self.create_graph() self.create_measurement_names() self.create_measurement_objects() + def analyze(self, probe_address, probe_data, slews, loads): + """ + Main function to characterize an SRAM for a table. Computes both delay and power characterization. + """ + #Dict to hold all characterization values + char_sram_data = {} + self.analysis_init(probe_address, probe_data) + self.load=max(loads) self.slew=max(slews) - # This is for debugging a full simulation - # debug.info(0,"Debug simulation running...") - # target_period=50.0 - # feasible_delay_lh=0.059083183 - # feasible_delay_hl=0.17953789 - # load=1.6728 - # slew=0.04 - # self.try_period(target_period, feasible_delay_lh, feasible_delay_hl) - # sys.exit(1) # 1) Find a feasible period and it's corresponding delays using the trimmed array. feasible_delays = self.find_feasible_period() diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index a06a7e90..b049d341 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -198,8 +198,9 @@ class bitcell_array(design.design): """Excludes bits in column from being added to graph except target""" #Function is not robust with column mux configurations for row in range(self.row_size): - if row == targ_row: - continue - self.graph_inst_exclude.add(self.cell_inst[row,targ_col]) + for col in range(self.column_size): + if row == targ_row and col == targ_col: + continue + self.graph_inst_exclude.add(self.cell_inst[row,col]) \ No newline at end of file diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index 799c223e..e9e35ee6 100755 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -62,11 +62,8 @@ class openram_test(unittest.TestCase): """ debug.info(1, "Finding feasible period for current test.") delay_obj.set_load_slew(load, slew) - delay_obj.set_probe(probe_address="1"*sram.addr_size, probe_data=(sram.word_size-1)) test_port = delay_obj.read_ports[0] #Only test one port, assumes other ports have similar period. - delay_obj.create_signal_names() - delay_obj.create_measurement_names() - delay_obj.create_measurement_objects() + delay_obj.analysis_init(probe_address="1"*sram.addr_size, probe_data=(sram.word_size-1)) delay_obj.find_feasible_period_one_port(test_port) return delay_obj.period From 03a762d311e3a62d8b35179b2a955e9af57e1fce Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Thu, 16 May 2019 14:18:33 -0700 Subject: [PATCH 014/234] Replaced constant string comparisons with enums --- compiler/characterizer/charutils.py | 6 ++++ compiler/characterizer/delay.py | 50 ++++++++++++++--------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/compiler/characterizer/charutils.py b/compiler/characterizer/charutils.py index 7081ff85..87e5adbe 100644 --- a/compiler/characterizer/charutils.py +++ b/compiler/characterizer/charutils.py @@ -8,7 +8,13 @@ import re import debug from globals import OPTS +from enum import Enum +class sram_op(Enum): + READ_ZERO = 0 + READ_ONE = 1 + WRITE_ZERO = 2 + WRITE_ONE = 3 def relative_compare(value1,value2,error_tolerance=0.001): """ This is used to compare relative values for convergence. """ diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 082ef99b..98db7177 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -68,24 +68,24 @@ class delay(simulation): trig_delay_name = "clk{0}" targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit self.read_lib_meas.append(delay_measure("delay_lh", trig_delay_name, targ_name, "RISE", "RISE", measure_scale=1e9)) - self.read_lib_meas[-1].meta_str = "read1" #Used to index time delay values when measurements written to spice file. + self.read_lib_meas[-1].meta_str = sram_op.READ_ONE #Used to index time delay values when measurements written to spice file. self.read_lib_meas.append(delay_measure("delay_hl", trig_delay_name, targ_name, "FALL", "FALL", measure_scale=1e9)) - self.read_lib_meas[-1].meta_str = "read0" + self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO self.delay_meas = self.read_lib_meas[:] #For debugging, kept separated self.read_lib_meas.append(slew_measure("slew_lh", targ_name, "RISE", measure_scale=1e9)) - self.read_lib_meas[-1].meta_str = "read1" + self.read_lib_meas[-1].meta_str = sram_op.READ_ONE self.read_lib_meas.append(slew_measure("slew_hl", targ_name, "FALL", measure_scale=1e9)) - self.read_lib_meas[-1].meta_str = "read0" + self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO self.read_lib_meas.append(power_measure("read1_power", "RISE", measure_scale=1e3)) - self.read_lib_meas[-1].meta_str = "read1" + self.read_lib_meas[-1].meta_str = sram_op.READ_ONE self.read_lib_meas.append(power_measure("read0_power", "FALL", measure_scale=1e3)) - self.read_lib_meas[-1].meta_str = "read0" + self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO #This will later add a half-period to the spice time delay. Only for reading 0. for obj in self.read_lib_meas: - if obj.meta_str is "read0": + if obj.meta_str is sram_op.READ_ZERO: obj.meta_add_delay = True # trig_name = "Xsram.s_en{}" #Sense amp enable @@ -113,13 +113,13 @@ class delay(simulation): """ self.bitline_volt_meas = [] #Bitline voltage measures - self.bitline_volt_meas.append(voltage_at_measure("v_bl_name", - self.bl_name)) - self.bitline_volt_meas[-1].meta_str = 'read0' + self.bitline_volt_meas.append(voltage_at_measure("v_bl", + self.bl_name)) + self.bitline_volt_meas[-1].meta_str = sram_op.READ_ZERO - self.bitline_volt_meas.append(voltage_at_measure("v_br_name", + self.bitline_volt_meas.append(voltage_at_measure("v_br", self.br_name)) - self.bitline_volt_meas[-1].meta_str = 'read1' + self.bitline_volt_meas[-1].meta_str = sram_op.READ_ONE return self.bitline_volt_meas def create_write_port_measurement_objects(self): @@ -127,9 +127,9 @@ class delay(simulation): self.write_lib_meas = [] self.write_lib_meas.append(power_measure("write1_power", "RISE", measure_scale=1e3)) - self.write_lib_meas[-1].meta_str = "write1" + self.write_lib_meas[-1].meta_str = sram_op.WRITE_ONE self.write_lib_meas.append(power_measure("write0_power", "FALL", measure_scale=1e3)) - self.write_lib_meas[-1].meta_str = "write0" + self.write_lib_meas[-1].meta_str = sram_op.WRITE_ZERO write_measures = [] write_measures.append(self.write_lib_meas) @@ -358,10 +358,10 @@ class delay(simulation): """Get the measurement values that can either vary from simulation to simulation (vdd, address) or port to port (time delays)""" #Return value is intended to match the delay measure format: trig_td, targ_td, vdd, port #vdd is arguably constant as that is true for a single lib file. - if delay_obj.meta_str == "read0": + if delay_obj.meta_str == sram_op.READ_ZERO: #Falling delay are measured starting from neg. clk edge. Delay adjusted to that. meas_cycle_delay = self.cycle_times[self.measure_cycles[port][delay_obj.meta_str]] - elif delay_obj.meta_str == "read1": + elif delay_obj.meta_str == sram_op.READ_ONE: meas_cycle_delay = self.cycle_times[self.measure_cycles[port][delay_obj.meta_str]] else: debug.error("Unrecognised delay Index={}".format(delay_obj.meta_str),1) @@ -383,10 +383,10 @@ class delay(simulation): def get_volt_at_measure_variants(self, port, volt_meas): """Get the measurement values that can either vary port to port (time delays)""" #Only checking 0 value reads for now. - if volt_meas.meta_str == "read0": + if volt_meas.meta_str == sram_op.READ_ZERO: #Falling delay are measured starting from neg. clk edge. Delay adjusted to that. meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]] - elif volt_meas.meta_str == "read1": + elif volt_meas.meta_str == sram_op.READ_ONE: meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]] else: debug.error("Unrecognised delay Index={}".format(volt_meas.meta_str),1) @@ -397,7 +397,7 @@ class delay(simulation): def get_volt_when_measure_variants(self, port, volt_meas): """Get the measurement values that can either vary port to port (time delays)""" #Only checking 0 value reads for now. - t_trig = meas_cycle_delay = self.cycle_times[self.measure_cycles[port]["read0"]] + t_trig = meas_cycle_delay = self.cycle_times[self.measure_cycles[port][sram_op.READ_ZERO]] return (t_trig, self.vdd_voltage, port) @@ -621,10 +621,10 @@ class delay(simulation): if type(val) != float: continue - if meas.meta_str == 'read1' and val < tech.spice["v_threshold_typical"]: + if meas.meta_str == sram_op.READ_ONE and val < tech.spice["v_threshold_typical"]: success = False debug.info(1, "Debug measurement failed. Value {}v was read on read 1 cycle.".format(val)) - elif meas.meta_str == 'read0' and val > self.vdd_voltage-tech.spice["v_threshold_typical"]: + elif meas.meta_str == sram_op.READ_ZERO and val > self.vdd_voltage-tech.spice["v_threshold_typical"]: success = False debug.info(1, "Debug measurement failed. Value {}v was read on read 0 cycle.".format(val)) @@ -943,7 +943,7 @@ class delay(simulation): self.add_write("W data 0 address {} to write value".format(self.probe_address), self.probe_address,data_zeros,write_port) - self.measure_cycles[write_port]["write0"] = len(self.cycle_times)-1 + self.measure_cycles[write_port][sram_op.WRITE_ZERO] = len(self.cycle_times)-1 # This also ensures we will have a H->L transition on the next read self.add_read("R data 1 address {} to set DOUT caps".format(inverse_address), @@ -951,14 +951,14 @@ class delay(simulation): self.add_read("R data 0 address {} to check W0 worked".format(self.probe_address), self.probe_address,data_zeros,read_port) - self.measure_cycles[read_port]["read0"] = len(self.cycle_times)-1 + self.measure_cycles[read_port][sram_op.READ_ZERO] = len(self.cycle_times)-1 self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)", inverse_address,data_zeros) self.add_write("W data 1 address {} to write value".format(self.probe_address), self.probe_address,data_ones,write_port) - self.measure_cycles[write_port]["write1"] = len(self.cycle_times)-1 + self.measure_cycles[write_port][sram_op.WRITE_ONE] = len(self.cycle_times)-1 self.add_write("W data 0 address {} to clear DIN caps".format(inverse_address), inverse_address,data_zeros,write_port) @@ -969,7 +969,7 @@ class delay(simulation): self.add_read("R data 1 address {} to check W1 worked".format(self.probe_address), self.probe_address,data_zeros,read_port) - self.measure_cycles[read_port]["read1"] = len(self.cycle_times)-1 + self.measure_cycles[read_port][sram_op.READ_ONE] = len(self.cycle_times)-1 self.add_noop_all_ports("Idle cycle (if read takes >1 cycle))", self.probe_address,data_zeros) From 412f9bb4632a10550558c348af56b4d5da7578b6 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Fri, 17 May 2019 01:56:22 -0700 Subject: [PATCH 015/234] Added additional check to bitline to reduce false positives. --- compiler/characterizer/delay.py | 43 ++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 98db7177..01cb8948 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -113,11 +113,17 @@ class delay(simulation): """ self.bitline_volt_meas = [] #Bitline voltage measures - self.bitline_volt_meas.append(voltage_at_measure("v_bl", + self.bitline_volt_meas.append(voltage_at_measure("v_bl_READ_ZERO", 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.bitline_volt_meas[-1].meta_str = sram_op.READ_ZERO - self.bitline_volt_meas.append(voltage_at_measure("v_br", + self.bitline_volt_meas.append(voltage_at_measure("v_bl_READ_ONE", + 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.bitline_volt_meas[-1].meta_str = sram_op.READ_ONE return self.bitline_volt_meas @@ -608,39 +614,52 @@ class delay(simulation): break #FIXME: these checks need to be re-done to be more robust against possible errors - bitline_results = {} + bl_vals = {} + br_vals = {} for meas in self.bitline_volt_meas: val = meas.retrieve_measure(port=port) - bitline_results[meas.meta_str] = val + if self.bl_name == meas.targ_name_no_port: + bl_vals[meas.meta_str] = val + elif self.br_name == meas.targ_name_no_port: + br_vals[meas.meta_str] = val + debug.info(1,"{}={}".format(meas.name,val)) - + bl_check = False for meas in self.debug_volt_meas: val = meas.retrieve_measure(port=port) debug.info(2,"{}={}".format(meas.name, val)) if type(val) != float: continue - if meas.meta_str == sram_op.READ_ONE and val < tech.spice["v_threshold_typical"]: + if meas.meta_str == sram_op.READ_ONE and val < self.vdd_voltage*.1: success = False debug.info(1, "Debug measurement failed. Value {}v was read on read 1 cycle.".format(val)) - elif meas.meta_str == sram_op.READ_ZERO and val > self.vdd_voltage-tech.spice["v_threshold_typical"]: + bl_check = self.check_bitline_meas(bl_vals[sram_op.READ_ONE], br_vals[sram_op.READ_ONE]) + elif meas.meta_str == sram_op.READ_ZERO and val > self.vdd_voltage*.9: success = False debug.info(1, "Debug measurement failed. Value {}v was read on read 0 cycle.".format(val)) + bl_check = self.check_bitline_meas(br_vals[sram_op.READ_ONE], bl_vals[sram_op.READ_ONE]) #If the bitlines have a correct value while the output does not then that is a #sen error. FIXME: there are other checks that can be done to solidfy this conclusion. - if not success and self.check_bitline_meas(bitline_results[meas.meta_str]): + if bl_check: debug.error("Sense amp enable timing error. Increase the delay chain through the configuration file.",1) return success - def check_bitline_meas(self, v_bitline): - """Checks the value of the discharging bitline""" - - return v_bitline < self.vdd_voltage*0.9 + def check_bitline_meas(self, v_discharged_bl, v_charged_bl): + """Checks the value of the discharging bitline. Confirms s_en timing errors. + Returns true if the bitlines are at there expected value.""" + #The inputs looks at discharge/charged bitline rather than left or right (bl/br) + #Performs two checks, discharging bitline is at least 10% away from vdd and there is a + #10% vdd difference between the bitlines. Both need to fail to be considered a s_en error. + min_dicharge = v_discharged_bl < self.vdd_voltage*0.9 + min_diff = (v_charged_bl - v_discharged_bl) > self.vdd_voltage*0.1 + debug.info(1,"min_dicharge={}, min_diff={}".format(min_dicharge,min_diff)) + return (min_dicharge and min_diff) def run_power_simulation(self): """ From 099bc4e2584c9b2238e67d560dda2e4443ab02a0 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Mon, 20 May 2019 18:35:52 -0700 Subject: [PATCH 016/234] Added bitcell check to storage nodes. --- compiler/base/hierarchy_spice.py | 17 +++++ compiler/bitcells/bitcell.py | 18 +++++ compiler/characterizer/charutils.py | 7 +- compiler/characterizer/delay.py | 100 ++++++++++++++++++++++--- compiler/characterizer/measurements.py | 59 ++++++++------- compiler/modules/bank.py | 6 +- compiler/modules/bitcell_array.py | 4 +- compiler/sram_1bank.py | 11 ++- compiler/tests/21_hspice_delay_test.py | 4 +- 9 files changed, 181 insertions(+), 45 deletions(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 2efed1da..eeabb61c 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -182,6 +182,23 @@ class spice(): else: self.spice = [] + def check_net_in_spice(self, net_name): + """Checks if a net name exists in the current. Intended to be check nets in hand-made cells.""" + #Remove spaces and lower case then add spaces. Nets are separated by spaces. + net_formatted = ' '+net_name.lstrip().rstrip().lower()+' ' + for line in self.spice: + #Lowercase the line and remove any part of the line that is a comment. + line = line.lower().split('*')[0] + + #Skip .subckt or .ENDS lines + if line.find('.') == 0: + continue + if net_formatted in line: + return True + return False + + + def contains(self, mod, modlist): for x in modlist: if x.name == mod.name: diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 42b8112b..30766f06 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -20,6 +20,7 @@ class bitcell(design.design): """ pin_names = ["bl", "br", "wl", "vdd", "gnd"] + internal_nets = ['Q', 'Qbar'] type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("cell_6t", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "cell_6t", GDS["unit"]) @@ -33,6 +34,7 @@ class bitcell(design.design): self.height = bitcell.height self.pin_map = bitcell.pin_map self.add_pin_types(self.type_list) + self.nets_match = self.check_internal_nets() def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 @@ -77,6 +79,22 @@ class bitcell(design.design): total_power = self.return_power(dynamic, leakage) return total_power + def check_internal_nets(self): + """For handmade cell, checks sp file contains the storage nodes.""" + nets_match = True + for net in self.internal_nets: + nets_match = nets_match and self.check_net_in_spice(net) + return nets_match + + def get_storage_net_names(self): + """Returns names of storage nodes in bitcell in [non-inverting, inverting] format.""" + #Checks that they do exist + if self.nets_match: + return self.internal_nets + else: + debug.info(1,"Storage nodes={} not found in spice file.".format(self.internal_nets)) + return None + def get_wl_cin(self): """Return the relative capacitance of the access transistor gates""" #This is a handmade cell so the value must be entered in the tech.py file or estimated. diff --git a/compiler/characterizer/charutils.py b/compiler/characterizer/charutils.py index 87e5adbe..6b965bc1 100644 --- a/compiler/characterizer/charutils.py +++ b/compiler/characterizer/charutils.py @@ -15,7 +15,11 @@ class sram_op(Enum): READ_ONE = 1 WRITE_ZERO = 2 WRITE_ONE = 3 - + +class bit_polarity(Enum): + NONINVERTING = 0 + INVERTING = 1 + def relative_compare(value1,value2,error_tolerance=0.001): """ This is used to compare relative values for convergence. """ return (abs(value1 - value2) / abs(max(value1,value2)) <= error_tolerance) @@ -38,7 +42,6 @@ def parse_spice_list(filename, key): f.close() # val = re.search(r"{0}\s*=\s*(-?\d+.?\d*\S*)\s+.*".format(key), contents) val = re.search(r"{0}\s*=\s*(-?\d+.?\d*[e]?[-+]?[0-9]*\S*)\s+.*".format(key), contents) - if val != None: debug.info(4, "Key = " + key + " Val = " + val.group(1)) return convert_to_float(val.group(1)) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 01cb8948..e92663d9 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -60,7 +60,19 @@ class delay(simulation): """Create the measurements used for read and write ports""" self.read_meas_lists = self.create_read_port_measurement_objects() self.write_meas_lists = self.create_write_port_measurement_objects() - + self.check_meas_names(self.read_meas_lists+self.write_meas_lists) + + def check_meas_names(self, measures_lists): + """Given measurements (in 2d list), checks that their names are unique. + Spice sim will fail otherwise.""" + name_set = set() + for meas_list in measures_lists: + for meas in meas_list: + name = meas.name.lower() + debug.check(name not in name_set,("SPICE measurements must have unique names. " + "Duplicate name={}").format(name)) + name_set.add(name) + def create_read_port_measurement_objects(self): """Create the measurements used for read ports: delays, slews, powers""" @@ -104,6 +116,7 @@ class delay(simulation): #Other measurements associated with the read port not included in the liberty file read_measures.append(self.create_bitline_measurement_objects()) read_measures.append(self.create_debug_measurement_objects()) + read_measures.append(self.create_read_bit_measures()) return read_measures @@ -164,6 +177,37 @@ class delay(simulation): self.debug_volt_meas[-1].meta_str = debug_meas.meta_str return self.debug_delay_meas+self.debug_volt_meas + + def create_read_bit_measures(self): + """Adds bit measurements for read0 and read1 cycles""" + self.bit_meas = {bit_polarity.NONINVERTING:[], bit_polarity.INVERTING:[]} + meas_cycles = (sram_op.READ_ZERO, sram_op.READ_ONE) + for cycle in meas_cycles: + meas_tag = "a{}_b{}_{}".format(self.probe_address, self.probe_data, cycle.name) + single_bit_meas = self.get_bit_measures(meas_tag, self.probe_address, self.probe_data) + for polarity,meas in single_bit_meas.items(): + meas.meta_str = cycle + self.bit_meas[polarity].append(meas) + #Dictionary values are lists, reduce to a single list of measurements + return [meas for meas_list in self.bit_meas.values() for meas in meas_list] + + def get_bit_measures(self, meas_tag, probe_address, probe_data): + """Creates measurements for the q/qbar of input bit position. + meas_tag is a unique identifier for the measurement.""" + bit_col = self.get_data_bit_column_number(probe_address, probe_data) + bit_row = self.get_address_row_number(probe_address) + (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, bit_row, bit_col) + 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]) + #Bit measures, measurements times to be defined later. The measurement names must be unique + # but they is enforced externally + q_meas = voltage_at_measure("v_q_{}".format(meas_tag), q_name, has_port=False) + qbar_meas = voltage_at_measure("v_qbar_{}".format(meas_tag), qbar_name, has_port=False) + + return {bit_polarity.NONINVERTING:q_meas, bit_polarity.INVERTING:qbar_meas} def set_load_slew(self,load,slew): """ Set the load and slew """ @@ -211,6 +255,11 @@ class delay(simulation): self.br_name = [bl for bl in preconv_names if 'br' in bl][0] debug.info(1,"bl_name={}".format(self.bl_name)) + (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, self.wordline_row, self.bitline_column) + debug.info(1, "cell_name={}".format(cell_name)) + + + def check_arguments(self): """Checks if arguments given for write_stimulus() meets requirements""" try: @@ -350,16 +399,22 @@ class delay(simulation): """Checks the measurement object and calls respective function for related measurement inputs.""" meas_type = type(measure_obj) if meas_type is delay_measure or meas_type is slew_measure: - return self.get_delay_measure_variants(port, measure_obj) + variant_tuple = self.get_delay_measure_variants(port, measure_obj) elif meas_type is power_measure: - return self.get_power_measure_variants(port, measure_obj, "read") + variant_tuple = self.get_power_measure_variants(port, measure_obj, "read") elif meas_type is voltage_when_measure: - return self.get_volt_when_measure_variants(port, measure_obj) + variant_tuple = self.get_volt_when_measure_variants(port, measure_obj) elif meas_type is voltage_at_measure: - return self.get_volt_at_measure_variants(port, measure_obj) + variant_tuple = self.get_volt_at_measure_variants(port, measure_obj) else: debug.error("Input function not defined for measurement type={}".format(meas_type)) - + #Removes port input from any object which does not use it. This shorthand only works if + #the measurement has port as the last input. Could be implemented by measurement type or + #remove entirely from measurement classes. + if not measure_obj.has_port: + variant_tuple = variant_tuple[:-1] + return variant_tuple + def get_delay_measure_variants(self, port, delay_obj): """Get the measurement values that can either vary from simulation to simulation (vdd, address) or port to port (time delays)""" #Return value is intended to match the delay measure format: trig_td, targ_td, vdd, port @@ -567,10 +622,10 @@ class delay(simulation): #Get measurements from output file for measure in self.read_lib_meas: read_port_dict[measure.name] = measure.retrieve_measure(port=port) - debug_passed = self.check_debug_measures(port, read_port_dict) - + success = self.check_debug_measures(port, read_port_dict) + success = success and self.check_bit_measures() #Check timing for read ports. Power is only checked if it was read correctly - if not self.check_valid_delays(read_port_dict) or not debug_passed: + if not self.check_valid_delays(read_port_dict) or not success: return (False,{}) if not check_dict_values_is_float(read_port_dict): debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) #Printing the entire dict looks bad. @@ -648,7 +703,32 @@ class delay(simulation): return success - + + def check_bit_measures(self): + """Checks the measurements which represent the internal storage voltages + at the end of the read cycle.""" + success = True + for polarity, meas_list in self.bit_meas.items(): + for meas in meas_list: + val = meas.retrieve_measure() + debug.info(1,"{}={}".format(meas.name, val)) + if type(val) != float: + continue + meas_cycle = meas.meta_str + if (meas_cycle == sram_op.READ_ZERO and polarity == bit_polarity.NONINVERTING) or\ + (meas_cycle == sram_op.READ_ONE and polarity == bit_polarity.INVERTING): + success = val < self.vdd_voltage*.1 + elif (meas_cycle == sram_op.READ_ZERO and polarity == bit_polarity.INVERTING) or\ + (meas_cycle == sram_op.READ_ONE and polarity == bit_polarity.NONINVERTING): + success = val > self.vdd_voltage*.9 + if not success: + debug.info(1,("Wrong value detected on probe bit during read cycle. " + "Check writes and control logic for bugs.\n measure={}, op={}, " + "bit_storage={}").format(meas.name, meas_cycle.name, polarity.name)) + return success + + + def check_bitline_meas(self, v_discharged_bl, v_charged_bl): """Checks the value of the discharging bitline. Confirms s_en timing errors. Returns true if the bitlines are at there expected value.""" diff --git a/compiler/characterizer/measurements.py b/compiler/characterizer/measurements.py index 6cd03469..228f6839 100644 --- a/compiler/characterizer/measurements.py +++ b/compiler/characterizer/measurements.py @@ -13,10 +13,11 @@ from .charutils import * class spice_measurement(ABC): """Base class for spice stimulus measurements.""" - def __init__(self, measure_name, measure_scale=None): + def __init__(self, measure_name, measure_scale=None, has_port=True): #Names must be unique for correct spice simulation, but not enforced here. self.name = measure_name self.measure_scale = measure_scale + self.has_port = has_port #Needed for error checking #Some meta values used externally. variables are added here for consistency accross the objects self.meta_str = None self.meta_add_delay = False @@ -35,18 +36,29 @@ class spice_measurement(ABC): measure_vals = self.get_measure_values(*input_tuple) measure_func(stim_obj, *measure_vals) - def retrieve_measure(self, port=""): - value = parse_spice_list("timing", "{0}{1}".format(self.name.lower(), port)) + def retrieve_measure(self, port=None): + self.port_error_check(port) + if port != None: + value = parse_spice_list("timing", "{0}{1}".format(self.name.lower(), port)) + else: + value = parse_spice_list("timing", "{0}".format(self.name.lower())) if type(value)!=float or self.measure_scale == None: return value else: return value*self.measure_scale - + + def port_error_check(self, port): + if self.has_port and port == None: + debug.error("Cannot retrieve measurement, port input was expected.",1) + elif not self.has_port and port != None: + debug.error("Unexpected port input received during measure retrieval.",1) + class delay_measure(spice_measurement): """Generates a spice measurement for the delay of 50%-to-50% points of two signals.""" - 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): - spice_measurement.__init__(self, measure_name, measure_scale) + 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) self.set_meas_constants(trig_name, targ_name, trig_dir_str, targ_dir_str, trig_vdd, targ_vdd) def get_measure_function(self): @@ -56,10 +68,8 @@ class delay_measure(spice_measurement): """Set the constants for this measurement: signal names, directions, and trigger scales""" self.trig_dir_str = trig_dir_str self.targ_dir_str = targ_dir_str - self.trig_val_of_vdd = trig_vdd self.targ_val_of_vdd = targ_vdd - self.trig_name_no_port = trig_name self.targ_name_no_port = targ_name @@ -67,9 +77,10 @@ class delay_measure(spice_measurement): def get_measure_values(self, trig_td, targ_td, vdd_voltage, port=None): """Constructs inputs to stimulus measurement function. Variant values are inputs here.""" + self.port_error_check(port) trig_val = self.trig_val_of_vdd * vdd_voltage targ_val = self.targ_val_of_vdd * vdd_voltage - + if port != None: #For dictionary indexing reasons, the name is formatted differently than the signals meas_name = "{}{}".format(self.name, port) @@ -79,13 +90,12 @@ class delay_measure(spice_measurement): meas_name = self.name trig_name = self.trig_name_no_port targ_name = self.targ_name_no_port - return (meas_name,trig_name,targ_name,trig_val,targ_val,self.trig_dir_str,self.targ_dir_str,trig_td,targ_td) class slew_measure(delay_measure): - def __init__(self, measure_name, signal_name, slew_dir_str, measure_scale=None): - spice_measurement.__init__(self, measure_name, measure_scale) + 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) self.set_meas_constants(signal_name, slew_dir_str) def set_meas_constants(self, signal_name, slew_dir_str): @@ -101,7 +111,6 @@ class slew_measure(delay_measure): self.targ_val_of_vdd = 0.1 else: debug.error("Unrecognised slew measurement direction={}".format(slew_dir_str),1) - self.trig_name_no_port = signal_name self.targ_name_no_port = signal_name @@ -110,8 +119,8 @@ class slew_measure(delay_measure): 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): - spice_measurement.__init__(self, measure_name, measure_scale) + def __init__(self, measure_name, power_type="", measure_scale=None, has_port=True): + spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(power_type) def get_measure_function(self): @@ -124,6 +133,7 @@ class power_measure(spice_measurement): def get_measure_values(self, t_initial, t_final, port=None): """Constructs inputs to stimulus measurement function. Variant values are inputs here.""" + self.port_error_check(port) if port != None: meas_name = "{}{}".format(self.name, port) else: @@ -133,8 +143,8 @@ class power_measure(spice_measurement): 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): - spice_measurement.__init__(self, measure_name, measure_scale) + 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) self.set_meas_constants(trig_name, targ_name, trig_dir_str, trig_vdd) def get_measure_function(self): @@ -144,13 +154,12 @@ class voltage_when_measure(spice_measurement): """Sets values useful for power simulations. This value is only meta related to the lib file (rise/fall)""" self.trig_dir_str = trig_dir_str self.trig_val_of_vdd = trig_vdd - self.trig_name_no_port = trig_name self.targ_name_no_port = targ_name def get_measure_values(self, trig_td, vdd_voltage, port=None): """Constructs inputs to stimulus measurement function. Variant values are inputs here.""" - + self.port_error_check(port) if port != None: #For dictionary indexing reasons, the name is formatted differently than the signals meas_name = "{}{}".format(self.name, port) @@ -160,17 +169,15 @@ class voltage_when_measure(spice_measurement): meas_name = self.name trig_name = self.trig_name_no_port targ_name = self.targ_name_no_port - - trig_voltage = self.trig_val_of_vdd*vdd_voltage - + trig_voltage = self.trig_val_of_vdd*vdd_voltage return (meas_name,trig_name,targ_name,trig_voltage,self.trig_dir_str,trig_td) class voltage_at_measure(spice_measurement): """Generates a spice measurement to measure the voltage at a specific time. The time is considered variant with different periods.""" - def __init__(self, measure_name, targ_name, measure_scale=None): - spice_measurement.__init__(self, measure_name, measure_scale) + def __init__(self, measure_name, targ_name, measure_scale=None, has_port=True): + spice_measurement.__init__(self, measure_name, measure_scale, has_port) self.set_meas_constants(targ_name) def get_measure_function(self): @@ -182,13 +189,13 @@ class voltage_at_measure(spice_measurement): def get_measure_values(self, time_at, port=None): """Constructs inputs to stimulus measurement function. Variant values are inputs here.""" + self.port_error_check(port) if port != None: #For dictionary indexing reasons, the name is formatted differently than the signals meas_name = "{}{}".format(self.name, port) targ_name = self.targ_name_no_port.format(port) else: meas_name = self.name - targ_name = self.targ_name_no_port - + targ_name = self.targ_name_no_port return (meas_name,targ_name,time_at) \ No newline at end of file diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 72702069..efdf228d 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -1286,4 +1286,8 @@ class bank(design.design): """Precharge adds a loop between bitlines, can be excluded to reduce complexity""" for inst in self.precharge_array_inst: if inst != None: - self.graph_inst_exclude.add(inst) \ No newline at end of file + self.graph_inst_exclude.add(inst) + + def get_cell_name(self, inst_name, row, col): + """Gets the spice name of the target bitcell.""" + return self.bitcell_array_inst.mod.get_cell_name(inst_name+'.x'+self.bitcell_array_inst.name, row, col) \ No newline at end of file diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index e19c7636..2380ee4b 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -210,4 +210,6 @@ class bitcell_array(design.design): continue self.graph_inst_exclude.add(self.cell_inst[row,col]) - \ No newline at end of file + 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] \ No newline at end of file diff --git a/compiler/sram_1bank.py b/compiler/sram_1bank.py index fdd41e8b..8d8ff65f 100644 --- a/compiler/sram_1bank.py +++ b/compiler/sram_1bank.py @@ -343,9 +343,12 @@ 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.info(1,"pins={}".format(self.pins)) - debug.info(1,"cl conns={}".format(control_conns)) + 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): + """Gets the spice name of the target bitcell.""" + #Sanity check in case it was forgotten + 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) \ No newline at end of file diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 456dd915..d0fa88da 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -45,7 +45,9 @@ class timing_sram_test(openram_test): c.recompute_sizes() debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") s = factory.create(module_type="sram", sram_config=c) - + #import sys + #sys.exit(1) + tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) From d08181455c436aef8996a86da24fcaea5996fbe6 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Mon, 20 May 2019 22:50:03 -0700 Subject: [PATCH 017/234] Added multiport bitcell support for storage node checks --- compiler/base/hierarchy_spice.py | 7 ++++++- compiler/bitcells/bitcell.py | 17 +++++------------ compiler/bitcells/bitcell_1rw_1r.py | 13 ++++++++++++- compiler/bitcells/bitcell_1w_1r.py | 13 ++++++++++++- compiler/bitcells/pbitcell.py | 23 +++++++++++++++-------- 5 files changed, 50 insertions(+), 23 deletions(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index eeabb61c..e668f535 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -197,7 +197,12 @@ class spice(): return True return False - + def do_nets_exist(self, nets): + """For handmade cell, checks sp file contains the storage nodes.""" + nets_match = True + for net in nets: + nets_match = nets_match and self.check_net_in_spice(net) + return nets_match def contains(self, mod, modlist): for x in modlist: diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 30766f06..0de11375 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -20,7 +20,7 @@ class bitcell(design.design): """ pin_names = ["bl", "br", "wl", "vdd", "gnd"] - internal_nets = ['Q', 'Qbar'] + storage_nets = ['Q', 'Qbar'] type_list = ["OUTPUT", "OUTPUT", "INPUT", "POWER", "GROUND"] (width,height) = utils.get_libcell_size("cell_6t", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "cell_6t", GDS["unit"]) @@ -34,7 +34,7 @@ class bitcell(design.design): self.height = bitcell.height self.pin_map = bitcell.pin_map self.add_pin_types(self.type_list) - self.nets_match = self.check_internal_nets() + self.nets_match = self.do_nets_exist(self.storage_nets) def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 @@ -78,21 +78,14 @@ class bitcell(design.design): dynamic = 0 #temporary total_power = self.return_power(dynamic, leakage) return total_power - - def check_internal_nets(self): - """For handmade cell, checks sp file contains the storage nodes.""" - nets_match = True - for net in self.internal_nets: - nets_match = nets_match and self.check_net_in_spice(net) - return nets_match - + def get_storage_net_names(self): """Returns names of storage nodes in bitcell in [non-inverting, inverting] format.""" #Checks that they do exist if self.nets_match: - return self.internal_nets + return self.storage_nets else: - debug.info(1,"Storage nodes={} not found in spice file.".format(self.internal_nets)) + debug.info(1,"Storage nodes={} not found in spice file.".format(self.storage_nets)) return None def get_wl_cin(self): diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index 67373010..6a6ebd92 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -20,7 +20,8 @@ class bitcell_1rw_1r(design.design): """ pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"] - type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] + type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] + storage_nets = ['Q', 'Q_bar'] (width,height) = utils.get_libcell_size("cell_1rw_1r", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "cell_1rw_1r", GDS["unit"]) @@ -33,6 +34,7 @@ class bitcell_1rw_1r(design.design): self.height = bitcell_1rw_1r.height self.pin_map = bitcell_1rw_1r.pin_map self.add_pin_types(self.type_list) + self.nets_match = self.do_nets_exist(self.storage_nets) def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 @@ -109,6 +111,15 @@ class bitcell_1rw_1r(design.design): access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + def get_storage_net_names(self): + """Returns names of storage nodes in bitcell in [non-inverting, inverting] format.""" + #Checks that they do exist + if self.nets_match: + return self.storage_nets + else: + debug.info(1,"Storage nodes={} not found in spice file.".format(self.storage_nets)) + return None + def build_graph(self, graph, inst_name, port_nets): """Adds edges to graph. Multiport bitcell timing graph is too complex to use the add_graph_edges function.""" diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index b3c2a5bd..dded6b30 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -20,7 +20,8 @@ class bitcell_1w_1r(design.design): """ pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"] - type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "INPUT", "INPUT", "POWER", "GROUND"] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "INPUT", "INPUT", "POWER", "GROUND"] + storage_nets = ['Q', 'Q_bar'] (width,height) = utils.get_libcell_size("cell_1w_1r", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "cell_1w_1r", GDS["unit"]) @@ -33,6 +34,7 @@ class bitcell_1w_1r(design.design): self.height = bitcell_1w_1r.height self.pin_map = bitcell_1w_1r.pin_map self.add_pin_types(self.type_list) + self.nets_match = self.do_nets_exist(self.storage_nets) def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 @@ -109,6 +111,15 @@ class bitcell_1w_1r(design.design): access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin + def get_storage_net_names(self): + """Returns names of storage nodes in bitcell in [non-inverting, inverting] format.""" + #Checks that they do exist + if self.nets_match: + return self.storage_nets + else: + debug.info(1,"Storage nodes={} not found in spice file.".format(self.storage_nets)) + return None + def build_graph(self, graph, inst_name, port_nets): """Adds edges to graph. Multiport bitcell timing graph is too complex to use the add_graph_edges function.""" diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index f0f85fe6..899da398 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -138,7 +138,9 @@ class pbitcell(design.design): self.Q_bar = "vdd" else: 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, then the inverter nmos is sized based the number of read/write ports @@ -258,20 +260,20 @@ class pbitcell(design.design): # create active for nmos self.inverter_nmos_left = self.add_inst(name="inverter_nmos_left", mod=self.inverter_nmos) - self.connect_inst(["Q", self.Q_bar, "gnd", "gnd"]) + self.connect_inst([self.Q, self.Q_bar, "gnd", "gnd"]) self.inverter_nmos_right = self.add_inst(name="inverter_nmos_right", mod=self.inverter_nmos) - self.connect_inst(["gnd", "Q", self.Q_bar, "gnd"]) + self.connect_inst(["gnd", self.Q, self.Q_bar, "gnd"]) # create active for pmos self.inverter_pmos_left = self.add_inst(name="inverter_pmos_left", mod=self.inverter_pmos) - self.connect_inst(["Q", self.Q_bar, "vdd", "vdd"]) + self.connect_inst([self.Q, self.Q_bar, "vdd", "vdd"]) self.inverter_pmos_right = self.add_inst(name="inverter_pmos_right", mod=self.inverter_pmos) - self.connect_inst(["vdd", "Q", self.Q_bar, "vdd"]) + self.connect_inst(["vdd", self.Q, self.Q_bar, "vdd"]) def place_storage(self): """ Places the transistors for the crossed coupled inverters in the bitcell """ @@ -363,7 +365,7 @@ class pbitcell(design.design): # add read/write transistors self.readwrite_nmos_left[k] = self.add_inst(name="readwrite_nmos_left{}".format(k), mod=self.readwrite_nmos) - self.connect_inst([self.rw_bl_names[k], self.rw_wl_names[k], "Q", "gnd"]) + self.connect_inst([self.rw_bl_names[k], self.rw_wl_names[k], self.Q, "gnd"]) self.readwrite_nmos_right[k] = self.add_inst(name="readwrite_nmos_right{}".format(k), mod=self.readwrite_nmos) @@ -437,7 +439,7 @@ class pbitcell(design.design): # add write transistors self.write_nmos_left[k] = self.add_inst(name="write_nmos_left{}".format(k), mod=self.write_nmos) - self.connect_inst([self.w_bl_names[k], self.w_wl_names[k], "Q", "gnd"]) + self.connect_inst([self.w_bl_names[k], self.w_wl_names[k], self.Q, "gnd"]) self.write_nmos_right[k] = self.add_inst(name="write_nmos_right{}".format(k), mod=self.write_nmos) @@ -522,7 +524,7 @@ class pbitcell(design.design): self.read_access_nmos_right[k] = self.add_inst(name="read_access_nmos_right{}".format(k), mod=self.read_nmos) - self.connect_inst(["gnd", "Q", "RA_to_R_right{}".format(k), "gnd"]) + self.connect_inst(["gnd", self.Q, "RA_to_R_right{}".format(k), "gnd"]) # add read transistors self.read_nmos_left[k] = self.add_inst(name="read_nmos_left{}".format(k), @@ -866,6 +868,11 @@ class pbitcell(design.design): Q_bar_pos = self.inverter_pmos_right.get_pin("S").center() vdd_pos = self.inverter_pmos_right.get_pin("D").center() self.add_path("metal1", [Q_bar_pos, vdd_pos]) + + def get_storage_net_names(self): + """Returns names of storage nodes in bitcell in [non-inverting, inverting] format.""" + return self.storage_nets + def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 From eb40e2fdae2fa0e0f5b60377713aac4a841e6b91 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 21 May 2019 09:23:25 -0700 Subject: [PATCH 018/234] Added remaining gds/sp files for multiport in scn3m. --- .../{mag_lib => gds_lib}/cell_1rw_1r.gds | Bin 6330 -> 6330 bytes technology/scn3me_subm/gds_lib/cell_1w_1r.gds | Bin 0 -> 6326 bytes .../replica_cell_1rw_1r.gds | Bin 6282 -> 6282 bytes .../gds_lib/replica_cell_1w_1r.gds | Bin 0 -> 6278 bytes technology/scn3me_subm/sp_lib/cell_1rw_1r.sp | 14 ++++++++++++++ technology/scn3me_subm/sp_lib/cell_1w_1r.sp | 14 ++++++++++++++ .../scn3me_subm/sp_lib/replica_cell_1rw_1r.sp | 14 ++++++++++++++ .../scn3me_subm/sp_lib/replica_cell_1w_1r.sp | 14 ++++++++++++++ 8 files changed, 56 insertions(+) rename technology/scn3me_subm/{mag_lib => gds_lib}/cell_1rw_1r.gds (97%) create mode 100644 technology/scn3me_subm/gds_lib/cell_1w_1r.gds rename technology/scn3me_subm/{mag_lib => gds_lib}/replica_cell_1rw_1r.gds (97%) create mode 100644 technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds create mode 100644 technology/scn3me_subm/sp_lib/cell_1rw_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/cell_1w_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp diff --git a/technology/scn3me_subm/mag_lib/cell_1rw_1r.gds b/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds similarity index 97% rename from technology/scn3me_subm/mag_lib/cell_1rw_1r.gds rename to technology/scn3me_subm/gds_lib/cell_1rw_1r.gds index 2d12b8eea9b4107adacb23f749aeeec1f17ef784..3669049a25251d6f77c8897c81603e2d633bfa09 100644 GIT binary patch delta 29 ecmdmGxXW;YG`k3cAcF)0+e9Tx7;|G%gaiOx`2~dl delta 29 ecmdmGxXW;YG&=_aKZ7U(<3uG(7;|G%gaiOve+5|p diff --git a/technology/scn3me_subm/gds_lib/cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/cell_1w_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..bfca605897a644c469a11de81edb76a3f667fb65 GIT binary patch literal 6326 zcmbW5J&aXF7=~Z(?p`*quDiJ6Vo>m3V1Zp&11J$x;!ng#bfd(WV04WZ8)JxJEi5c7 zG_kO-Fww%o#KwZcVhaljV=OEzEG#T6C@d@}EG#Vi9_G9`a}R!p=t=HzdG73@qCLVhD!^2N~ z|JCKACpQj!@!5+j+A-1N9@g&hNojcfKzlTt9!Of48H?|@?*Cmn{zS_cE*0I3^6^>8 z{@qwTThkvX6Utlp&mb;W0y;O^Rd&VEi?4gPoA6ulQz-K&};wR zIzD}T=7Mzl-z`^Ome9>8PyILkAwBY=H2-9ZSP2@f0cIq)bhDy3EhnH)W2mzy7w1pdZy)`MG4)E z^3;FReDU4Ln(Chy1ukWAjKa||<*wvEfKDrsXP5pP?Cq4LG zSwkj1bTjnS&z{HL#o9Az2i*)k^)u%Eze!s!wqz}!n^B(nXWl6LEPnP|w}Vc*O?m1k zPt>EoCUKqDrabjCN93NkCUc2yhMxNAANwqRlXlR}&{IGC!$)0{ad=!!dFp4L@iBiU z^N4PSp86L)D0w4i#D#p&&Cq-O%o|>l-)2re_dOH69vHy?ck8zS~#&0qQ=w|3?e8!27ahv$i&5nPmUVn;<_aDyw zCht95X6OCqD*xl}7QcCFq4>?v>;8}Uy?@sG9qpi-o#*d}pFGib&T1y_J?LiWX?)fU zKFX3~zw)s(0Gr<{F`y~m^-x7(EW`sq9IP1VJ|c+t%$OZ|g0 zWvhRx@i67kzJ@qrsbiJ%?xUMgp8DxCm-`Cw zp_@^h`v2|uix1t5v8Dd47fWAR_w?E8AD#JY%2Pk{i;wfN>3KIpPyNg@7xQn@Z*(*C z)X$lli}h>bLpMXO{m1M1!^6e=o6k1$Z-#!wA6?@A@3{ZB@&ES}|9^Atc=BgWZXd3% zEncHuv={Zxudepg@u7n%`U@u7n&CbEV&mhXcI8n(F#@v{tAOQeT4+PNw diff --git a/technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..f1ebbb560f763f8c3b3d54da3f2b4f9c51ee3f68 GIT binary patch literal 6278 zcmbW5Ka5pH6vmHl-##|5uDiIbi&+)oU*G}zU=5%|Pzg%FNOYsbn5@bYAbBxlLs$z7 z3kyvwEG$g4urRT)ps?7&g2EUJ3kwSi3knJg3JMDg3(t?aU+&zyo*{aZ-QUYM^Uaw# zGjC?@vz~Qq#OChm*cIDk6SmR%HfgIiYST7lv(~ejPH*MhrQyZ1Z!euaHykbvR+k1V zHa#->%(EXKIQio@w+mv7OeN=$Ki5a>W1p^W-09 zM_#P?`i-QEUf!KDlYd9sPi_1n?eU2IG57Dz{rCTA_R<-%M;2?owq}MddU@y{TS(pm z(=~U0XNE3%+o6BzGqZ=jPIX24f-brq`iVnb;)@TQO7TV4bALY{Kc2(4Qhf3F>C~3! zdgv!l%7I9m=%VYne^(x#KE8a_Z2R9e7vC~N7ri|6-+R;Sxu4BuzpVNEUuNi{mxq4h z;3vL_4_z$zANw}>cD-2>AG%ob(@)keevy7?Tvd74|BaudSPS3Rq%CyO`x5$TpRrR{ zr0?jW>!F`G)Fr;i+@p)Ghko)*U1E#(98UQcUC;gV`TBYAJ+srln{E50=Bo>4=%Sa0 z{!MFUkN;*iF!F`GGsjYVk?%6P=z8d9oWy1PB5~2hQhYo| zFQ>X9-#>KG^)NpD#K-y*@u7<)KRL$7T#5M5#gd;m!F|ian9lwX$M_&J@nH* zeAE>ghsITvhkoW6AM+~MK8~*VdX7l4_oR#9fWixcq_0Ufr z@v&cs_|V0Y9}j=j74y$kc^F@3Jh|g80QoMVi>`-$?%4Q$h09|xFAAiGtXqbHLmG~h(bg|^;&PLuidqwhw zE|&7Qqnmu(AMrzc=wivwKFwLnekbbQAi5ro|9_nSjr=iAa?SWf<^WxEJ&eyd@iA@@ zAG+A`5AyYA{_y_8-CyLrhevF^|E%-B@P6`(r~1h+x}NvH;n(?@pLeu_F1GgHhMzpq zckXH;?>*?E>tTG>3_kKF;zJipe&Vp^St}y#s9#li7@u;^Db5a&cGPZFUi8y<;)}GS zcA@K`pYJT^9A1(Bql>PGe%`S-d+>|2gD#fl4-bFT6`6NFi~c!`Pd|yB|KUX!y)5*1 z&ZPHD_IutpA#I_Ht@qb;>kl96PsCT{{WeQ}-M^SW&OFFoUbufX;`7c*Ecz|d7j)6} zaQv)uyuAO4^dDVxJ@hkX{-`VFpR4lF&$&q*e)|#eql>PGe&(6HweL^p`mQx@tI9(^^NWxBuBdqzT@U@tGY|7G z(r Date: Tue, 21 May 2019 13:59:44 -0700 Subject: [PATCH 019/234] Add 1w 1r magic just copied --- technology/scn4m_subm/mag_lib/cell_1w_1r.mag | 142 +++++++++++++++++ .../scn4m_subm/mag_lib/replica_cell_1w_1r.mag | 145 ++++++++++++++++++ 2 files changed, 287 insertions(+) create mode 100644 technology/scn4m_subm/mag_lib/cell_1w_1r.mag create mode 100644 technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag diff --git a/technology/scn4m_subm/mag_lib/cell_1w_1r.mag b/technology/scn4m_subm/mag_lib/cell_1w_1r.mag new file mode 100644 index 00000000..9aec1c5d --- /dev/null +++ b/technology/scn4m_subm/mag_lib/cell_1w_1r.mag @@ -0,0 +1,142 @@ +magic +tech scmos +timestamp 1542220294 +<< 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 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 +rect 0 61 54 65 +rect 10 44 14 61 +rect 17 51 20 54 +rect 17 47 27 51 +rect 17 37 20 47 +rect 34 44 37 54 +rect 27 40 37 44 +rect 40 44 44 61 +rect 34 37 37 40 +rect 6 33 9 37 +rect 45 33 48 37 +rect 25 23 29 29 +rect 25 13 29 17 +rect 0 9 25 13 +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 +rect 9 21 13 72 +rect 25 58 29 68 +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 48 0 52 33 +<< comment >> +rect 0 0 54 70 +<< labels >> +rlabel metal1 19 63 19 63 1 wl0 +rlabel metal1 19 70 19 70 5 vdd +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +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 +<< 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 new file mode 100644 index 00000000..f215ff04 --- /dev/null +++ b/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag @@ -0,0 +1,145 @@ +magic +tech scmos +timestamp 1542221056 +<< 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 +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 +rect 0 61 54 65 +rect 10 44 14 61 +rect 29 54 33 58 +rect 17 51 20 54 +rect 17 47 27 51 +rect 17 37 20 47 +rect 34 44 37 54 +rect 27 40 37 44 +rect 40 44 44 61 +rect 34 37 37 40 +rect 6 33 9 37 +rect 45 33 48 37 +rect 25 23 29 29 +rect 25 13 29 17 +rect 0 9 25 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 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 +rect 9 21 13 72 +rect 25 58 29 68 +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 48 0 52 33 +<< comment >> +rect 0 0 54 70 +<< labels >> +rlabel metal1 19 63 19 63 1 wl0 +rlabel metal1 19 70 19 70 5 vdd +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +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 +<< end >> From 9bb5041d93f26f199c3782700f3a42fcb3487895 Mon Sep 17 00:00:00 2001 From: mrg Date: Sun, 26 May 2019 17:05:00 -0700 Subject: [PATCH 020/234] Fix pc to p DRC in scn3me_subm --- .../scn3me_subm/gds_lib/cell_1rw_1r.gds | Bin 6330 -> 6458 bytes technology/scn3me_subm/gds_lib/cell_1w_1r.gds | Bin 6326 -> 6454 bytes .../gds_lib/replica_cell_1rw_1r.gds | Bin 6282 -> 6410 bytes .../gds_lib/replica_cell_1w_1r.gds | Bin 6278 -> 6406 bytes .../scn3me_subm/mag_lib/cell_1rw_1r.mag | 170 +++++++++--------- technology/scn3me_subm/mag_lib/cell_1w_1r.mag | 150 ++++++++++++++++ technology/scn3me_subm/mag_lib/convertall.sh | 8 + .../mag_lib/replica_cell_1rw_1r.mag | 164 +++++++++-------- .../mag_lib/replica_cell_1w_1r.mag | 151 ++++++++++++++++ 9 files changed, 483 insertions(+), 160 deletions(-) create mode 100644 technology/scn3me_subm/mag_lib/cell_1w_1r.mag create mode 100644 technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag diff --git a/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds b/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds index 3669049a25251d6f77c8897c81603e2d633bfa09..f9cec56965719c38ebb10025fb5ffa5cf8f57f68 100644 GIT binary patch literal 6458 zcmai&J&aXF7=}OY{;*NRT|@-3Dn|SP7T5(6KsVqTG#H5*MWe(-qZlnV#!!f*g@q;- z78WL2P?%_8L195*L1B!Ag@uKMg@vUBg{6hx!#R&jOcZ_LIh zrebl!C@#iK?2Lujkbiz2#d6G#W?z3}ef^b{3m5Y*V(Zk*iM5Z8KKa8}*N&gMa`4jU z=g!9BOv67r?w_8En7w5bdt-LRB|dc7^56eW=iB%4 zKz!)3<)@!(mm=^>`r)|x@@oHY`Z(f&Un7ouH*o302y~g{RX^?D`(PJe(jK}@z3L|p zb%`&Tdvuw4)lZ(OOaA4pt6lzO>ZO0VTt9cc7xCPY?%k2kXM5-}^{W5oD-nC9BR0KUmRJ3^Z|{6}yfY9Vx@`H$G4b~<55$KqTmF?}o$v4`1M#8DmY+PaR@s9j{Xv(h zSI1AD7%Tac+T?H#{X>_jSL4%9 zeB@8!LzgW-^Nf%Am-x_S%TF9~O?=5*pv%Qz7e!$)1oI2>1BUiCB2_`It? z<`G@C;&Vn3kDN(9qs!E*@u^2l?pl&|Y_~6O`WZX>g(UCzWa>>n<0rnP9sF`){0GbT zk8|&#&$|1QT)ozvhcfjt{+OS4p1!kQBzqycOug#ojK;?~Eb*bsmLCs))RpDuzPuXW zGoIYh2YC0F5$H1Ys-Jr+KIUBFLzff&LuLMXZ@o82?+tR|{&0hzeVer+-S_3h{ypZO z`k*^!XMP*Vxs5I-&hIfl?-=Lw!`~0Yhb~)w?rh|ZvsaQgblJ)uvGEa0;zO4$KkJmU zmh~&WH^|h>`5zlU>kA)iPI~UkmY;EwYsN2`3v`)!H9q4k=ZZX(bJ>@d{*`k5MLvB0 z;k%dQdk>GC`2KT)|A}8ZzkDjk!y{9##^0E+*=LytNjvB=^{Ri%)$V%>ceS-k-JOl^ zJ?Jv^s-HE3k9|<$LzgW-cUFAtw-O(^Z29RY_YBsGq#eiAmsk5wIq#b19;6-H?aQlv z^32}FekYj+=cO;N`e~oBvwkK0v0r_8)zA7Q9$v}#(PeA?dGGM?TZ?4fpv#uudj|16 zw`m7mre5to9{z|g@$p&a=c=D^61)7vi!QUQ>L0z>-PM^t?(C4Z&}HgXKl6i+_ebLE z=j}RMe(#U0U+x>wd!wAVzl`l4+>_bs=(nUV=rZ+c|9MaG^8QNtk1kWM`guT zU8Y|3Gtc-~E7EzFEkEWEv()9q_BQ5trsE$6 CSDVKG literal 6330 zcmbW5J&aXF7=~Z(?p`*quDiJ6Vo>m3V1Zp&11J#`;!ng#bfd(WXmpJh8)JxJEi5c7 zG_kO-Fww%o#KwZcVhaljV=OEzEG#T6C@d@}EG#Vi9_G9`a}R!p=t=HzdGshFBRR4^6^>8 z{@qwTThqxX6Utlp&mb;W0y;O^U*V8PyILkAwBY=H2-&FD+&r+vmwU6a0}o1v$E;!v0PCUcK& zhMxM#Gj)k=-f*ns-weI>FV^elws)j6ze>A)YWeK4glff><-TR9)J=1c}qJ(Zn zdFsDuzW8o_t0g{kv(Ha#KGZeq-%WWMf9Xi^9s0N>esnY1Nd4sL?)OUmOk$#&p{IWG z#8}CnNiNXM&{IEgww)^RP3~oMGxXHYIEl;nP2!@Peev;}c)Qd!x&P43(9`(z6Cdl( z#D{M7`N=Up=E}r}Zua?!L#~N$G8gD(=ym`1*Z0r%A4=|a>}tt#AKi@Hrv5wclOFu8 ztRWL0x*2-vXU}8rV(pou21=G-(IF*%|+V z`u-!vkrO3f<^!LW*k5FfhP z=jS=iUd!{&^tr(dJsto5*#AfJ$2iF~<2RWDbTjlcKI6p4xJ`WMX2-u&uRq1b`wwS- zllLAjv-AFQmH)AKi{CuGQ2b`-b^k~F-aqU8j&{(^&hvM~PoC&IXEl@e9&|JGG(Kwv zALoA)AG+D+=N$zf`8V;Qn|*%z$vwkbGik@;YRc38Q_eoe-eb~^+il8w{q&vqChfRg z7<%gGo@bxLYtnyoGxXHYI~sczev@|4&A$1^!-u*i>xSQE{7&Q3Ph!^}yy#|>rT)R$ zGS}=E%sHejbTjnSPk!;SeocH$-mkFF@ADh;$DRq<3wq9PBli#Qyu_m4CVfFSLr?q9 zeS(+!$E5%0X6UJ(G4r9WS^sXzQ$PDIb@=bd#E))_tDKLPyO_n%YB9T z(9I}L{r~p-#fNUj*i!%2i>0rud;0A4kIwux<*A?f#m9Ns^t_v)r+(&{i}^R{H@X>m z>gUYO#riezp_`%C{^Rxh;o)Nb&1ahVH$%VTk1p~5cijKm`2Tx~|GznRJn^$8w-49X z7Ozn++KYPUS66%LapoGoP}*C%M!k4Pi1uE8v(sLz&$fTj7XR-?y;r*Z8>z?phU<0W Yj@0Abps9DRuO9C{uIIdLit&u=ABP^f5dZ)H diff --git a/technology/scn3me_subm/gds_lib/cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/cell_1w_1r.gds index bfca605897a644c469a11de81edb76a3f667fb65..b10f2726c7b71f099531797c8e464ad569b30c46 100644 GIT binary patch literal 6454 zcmai&J&aXF7=}OY{;*NRT|@-3Dn|SP7T5(6KnaLJf|00EG)hb`iqT?Y424))SZHEl zVPT>Lg^3mx6c!W~6vkLsSXfwCSXf$6SX%f!ob!0*-gU;4EYIbgdFPw?X3osq8?!Nr zsaRY$ipwz*+hZZt<)5ENu^bymv#-Cgx_V*d@`aU4v3Y9d_{onBKlQ^`H;$gVw*SiK z=g-CBOv61}x~JzNW^WtC?wH*;iioB8sr)yeBacO#I5Y74v72(pET3M8(7$WaPi_2? z_IPA|Ed6^+|MtHkp1B&a^W4Cf=OfT%mRJ3Ahaw($KjQG_f%|@sK$lrw^)GxHvE%26 zz26R`J#?AnRX=g4OMH3v*)G0Jz4R}Yc8X9h$nVNZ2e;3>1QL*WtLa{#KBK|i4R@2{11N9`S!dr z5Ffg1`RV7$D-rl5{cv1;dA0wyd>rx6uMvm78@Tjg1iH-fs-O1nf4GY;X%AhdUiA}) zy2O{vJ-ST2>L<_CCI9mFV_p7b>ZO0VTtD}`7xDa|?%k0uWP9i`^{W5YYZ1GqBR0+t zWG>KUmRJ3EZtZ+`y)zIWx@`H$G4XdV55$KqTmF?Jo$uf$1M#8DmY+PaR@s9j{Xv(h zSI1AD7%Tac?H#{X>_jSL4%9 zeB@8!LzgW-^Nf%Am-x_S%TF9~O?=5*pv%Qz7e!$)1oI2>1BUiCB2_`It? z<`G@C;&Vn3kDN(9qs!E*@u^2l?pl&|Y_~6O`WZX>g(UCzWa>>n<0rnP9sF`){QJxI zk8|&l&$|1QJa(fy4`u3Q{4qc8Jbh=qNcKW>nR?aF8I6x~SmHyMEk7Rqs4L6QeR(y$ zXFR#15AfbEBhY2)RX_Jue9XDThb|}l2g>~O-g`5zlU>kA)iPI~UkmY;EwYsN2`3v`)!H9q4k=ZZX(bJ>@d{*`k5MLvB0 z;k%dQdk>GC`2MrT|Ku;7Up}4V;gP9VL0z--PM^t?(C4Z&}HgXKl6i+_ebLE z=j|q2e(#U0U+x>wd!wAVzl`l4+>_bs=(nUV=rZ+c|9MaG^8QNtk1kWM`guT zU8Y|3Gtc-~E7EzFEkEm3V1Zp&11J$x;!ng#bfd(WV04WZ8)JxJEi5c7 zG_kO-Fww%o#KwZcVhaljV=OEzEG#T6C@d@}EG#Vi9_G9`a}R!p=t=HzdG73@qCLVhD!^2N~ z|JCKACpQj!@!5+j+A-1N9@g&hNojcfKzlTt9!Of48H?|@?*Cmn{zS_cE*0I3^6^>8 z{@qwTThkvX6Utlp&mb;W0y;O^Rd&VEi?4gPoA6ulQz-K&};wR zIzD}T=7Mzl-z`^Ome9>8PyILkAwBY=H2-9ZSP2@f0cIq)bhDy3EhnH)W2mzy7w1pdZy)`MG4)E z^3;FReDU4Ln(Chy1ukWAjKa||<*wvEfKDrsXP5pP?Cq4LG zSwkj1bTjnS&z{HL#o9Az2i*)k^)u%Eze!s!wqz}!n^B(nXWl6LEPnP|w}Vc*O?m1k zPt>EoCUKqDrabjCN93NkCUc2yhMxNAANwqRlXlR}&{IGC!$)0{ad=!!dFp4L@iBiU z^N4PSp86L)D0w4i#D#p&&Cq-O%o|>l-)2re_dOH69vHy?ck8zS~#&0qQ=w|3?e8!27ahv$i&5nPmUVn;<_aDyw zCht95X6OCqD*xl}7QcCFq4>?v>;8}Uy?@sG9qpi-o#*d}pFGib&T1y_J?LiWX?)fU zKFX3~zw)s(0Gr<{F`y~m^-x7(EW`sq9IP1VJ|c+t%$OZ|g0 zWvhRx@i67kzJ@qrsbiJ%?xUMgp8DxCm-`Cw zp_@^h`v2|uix1t5v8Dd47fWAR_w?E8AD#JY%2Pk{i;wfN>3KIpPyNg@7xQn@Z*(*C z)X$lli}h>bLpMXO{m1M1!^6e=o6k1$Z-#!wA6?@A@3{ZB@&ES}|9^Atc=BgWZXd3% zEncHuv={ZxudepgzZ8quuA1^-lZK~5-x_WK!(dG9pUA{UPT$){4_CK@DBcmr4zC3dN z?vMA6onAe-^4-Nnn;xyS(|d3`-7&M?qaE98y^S3+o0%B#fBiXn%IxIX%!~7DvWZ^a zoivkwPuovz{37k~i2kwk?=St^{x*B%hS~1L%(o}Z&_yo~{bO@x&wOTfWOL?$Kg`fY zFAx2b-XLu)vH6sL(e={bFW1kGPt9JROYe^OhPQ_D}*dX~u+Cdjx5B=;J{c*ERw=>y`&_yo~{SzOi*!Veb z)ebuCHszt8JW-E)i^Nr4oAS`l9FcqCii{mybUpObKh9bFBJH4yu7`g5hmX1<)n$ z;g7mv`MD_%`ou7T1 zwIXWY7hC)HkbmU!bk2_cp2@k5F1F6^AwTaJ=k)PAnfTDfnx8uxdE@LA$s4*@%OA1v z5lh5}F4p|4Q_fn}uc&*2=z2N-L*r+C;bYB-I`_qzpK+3F#xF7#=%VXke8ySM6?rJ< zvMDe9v*r3TfB62xcQ29eJv?IT`_DT6xnGlCeA&mtBf1{O-{7&?XPF0)cF;xFL;t4R z>3a)zwS|>*XXAShy6Af7XU*VazZCJIi#0!SxF;~zBJHSOO?eofa^4l4Tab3tZc`rm z$rF1I`;|x@mDi>`^wU0LXZ?xvNBwHbLqF?_cz8v|k1p2ckM{;2zmz+V- zox8MyF1jA}9}j=T7xD2~^v|K6aT2@y!;3C@S?KS)mG0WiA9rp@Tj-+ep`ZD|$NCrX zHS@N{nqT)n)-U%3sC%E-x_=D4|J-xgtLV2#U(iL@!~XN0;pHA8(tmW(_0Z3EM#fED zk$3xyY2SoCQF4po#9P-9m6UiI8Sj(UJL$2AsMe@iax*q0_ zdaO14B6|jp=z8ftT%I3z%DQ+sH_$~d5B>C+M}39(&_yo}{o21-KkPRUAG+vz=;uA5 zudI8Kc|#Xn5B;=z17mzcI6Zc_2P?(dE*AvYbCWJj}ni z_-^_v`v2Da-X(rN_xFDbzn_ou`#E>4?hPB;+FKsX{!hK}KdJY@$5)2y`FhIjd0YIB z>-F9r^egqet^ew^;tsWU$b&WQE!FDr-ADCWafimsIq7-v{(W+#HI8-lF3hC7sJ#t7 Hp0521FZP)d literal 6282 zcmbW5F^pA36owCP-##|5uDiIxVphc{D)4|^SON$URH70v5Zx#-CI~E1lNUlZhPAM; zu)xH^!ooxg3lkd(3X3f)C=8*nprEj@prD|zps=v8@O;eubLZam4AGms{a*f=f6mOA zc{6j@de*Tan_ktiOSaa=Y>oA8+?H(ECT+r|tY=f5-s1U-gOARgIeqT@U~qbNamhbs zlS9KVzVyZ3W7mJYxBtlU&hNi{ciyIl3+?p&y`AoeS?{5aZMEK5$ISZUL;lyFJ$KCx zy5Z*>WcIQU35M46NkFQ7au>K;)|~5{(e4wJO}Tk_~NT4Q(L0z zp`Sb{2O@2vi>~MXZFzk9c;c$rQ-9Z-f8PvU^zzXE$RB1e|7te%UCmeiGD8==JoFO> zKk-F;=wiwL?3Lu(_FheV=wiuFKUur@Mf#y}Rpnv-*L;~`&HY@Hw$MfIOX#P4#!g+4 zzN3q-hkoKvm-r%ck1o0%`pGkOi7h^SFy&u#J@?P#>*tA2%ufDpw&`Zgx8}^yMK2Hi zYnRQQ`^{`@yyn&!Gj!3*L;s^w$+zKRO?>EL$xm!P)D`pZRe2bHc3<-C{;DQ^bkW-g z{p4x$XDNRoG0{cWLqB<9tmIE57wDqvp`SSGkEHk_zh!jM_0Z2aiOcv!;-ZVC_;?O~ zoa&1F{?J9&!}#zYvPN{1-j^Z-v1r>?`PwUl)LFo zHQD#kMbB;MfBJc|1HYs-B;rFCT@U@7d7NFWJ&|_MMb|?=W8QJwY~8h*tOaz@%R~S8 zhv}Tf&v~nM&}p|S5B=ncdh}N$uJT%yhkoXW+!I%1F40BTLqGlFoW(EF4!Y=i=%;`9 zs4FrKjjJjT{me5y=1*iE(M8uofB$mI8#yB`ctyUeUFdqz&)C^7MDmVL zbiL?j+{6@V2fx@F|IYmPM~r=kQ@+F(zDcn~*Yo%d|L7gFnNc&&N^#eM8M^3t=%!F`JHa_Br_|V0ce^;J=#{D1f4=eoa z+svb=eP3+t-wprJ=V`AW_B#xFKIAMw7hTWC-|+7rBp-VveuxiUEcv;!kvGm>k-VXc zrTlH_CLi}l{16|ySn{(^bJnuoiMlt4u7~6QALoA~e~gn{Gk%ddKo?yP<1m$r->-@~mJK8}PTl;UrPoC&I zcQujs9(2+5Fg|MrANdpUp^GIyaai-L6_Iw-uc|zZPdVolXNO2TYPTvc`sq9IMcPrj z(Dl&IZoQ;bZ-Y_^Q0$XUVVo7xTxN2ieOD_pe5L-dTx7zeW0jF1j9$ zpLLFx_g|6zql>PGe#Xp)x?=vlDi8gfo7CZdKO%l~(e=>JJd?Nf{Ry2sR^_3eIOHw= z{{eYJ7fbmwf5!E+$wbWPEJ$=^tM`!-3^3c!x;^V$6YTiZHLqGG(!~Bc% z8(nlg^mAwCVf~8u&_&mC|Dk;T@bHj3@lBsY9?`$v_j{N4|F!@A*Yp4DQT~6;z2WFB z8`;=f8q7SPp10@qE-fq+>Tzf4UQO-IKA@i8@x8qdF0|V7^;!4N+v5MTUhizXe~o&) cFQ{HCZlfM|`>NhzsUGhxs;9iH_VIM>AD5N39smFU diff --git a/technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds index f1ebbb560f763f8c3b3d54da3f2b4f9c51ee3f68..bab19446192c461168c38b42f083fe93ddd05db9 100644 GIT binary patch literal 6406 zcmai&Ka7+`7{*`s_LhsDaEEvTITa)R0S?%OO8~uqM}S}?YVv8sllIU>FAx31p)T>ohcBe~qU)u9t{gueaz}je{5PpB(e=CJ`#baXbu)C)%R~PIf0~`$Yqs;t%yTcBp^IJ~`iX;|_#!@Z zvF3mB+vGd&Rwh1lvF4|ri)&{1Mf#y}HRWOd@BPB;sb9_Jzt5ce%nV)h^3YHFk3XH_ zi?oL>x*qz8LtWyF%ssm3dgv$5)FuDowuO{`(e={bFW1i_ADg{8pWYquHE$1HbUpOn zw{EttYqoVNles__y*%_kxHI`4x|)d(U99=ZG4c2JGx4E|HUHpv@*TaFi4R?@`N!F`<5|{Cd#6=ft@$sDgIn@<; z|IkI(!}#Zhkp8fVwn6Q?VyXUhko{q{-oLV+nMY|=%Sa0{;BstW6MaGUUx*q!JALlH7k#^8U*F!)3!$)0_acEpk zdFW@J@#(GtnMZW77N0YUc;rmvGrH({7@vB?kpUPSgnbkX(D&l!!6b6CWOF4p{b z_@k~^es0Rc_&Vds9ese0er1L(x*qzux8h^YMSSRD%YUTIKku#X4WjN1V(b2}$>{8#6R|FI%mg!%jDcf7hC7|h@W?ibNbmIGV!5{H9vPY^2XUKk~eg*mOo8lhEAmjz zWm8`I2j%)RfB62xcQ29eJv?IT`_Cr-^LLV8e9_0lBf1{O-{P^^XPF0)cF;xFL;v>M z>3a)zwZ*k`XXAShy6Af7XU*VazZCJIi#0!SxF;~zBJHSOO?eofa^4l4Tab3tZc`rm z$rF1I`;|x@mDi>`^wU0LXZ?xvNBwHbLqF?_cz8v|k1p2ckM{;2zmz+V- zox8MyF1jA}9}j=T7xD2~^v|K6aT2@y!;3C@S?KS)k?z{eA9rp@Tj-+ep`ZD|$NCrX zHS@N?nqT)n)-U%3sC%E-x_^wk|J-xgtLV2#U(iL@!~XN0;pHA8(tmW(_0Z3EM#fED zk$3xyY2SoCQF4po#9P-9m6UiI8Sj(UJL$2AsMe@iax*q0_ zdaO14B6|jp=z8ftTAm+x%DQ+sH_$~d5B>C+M}39(&_yo}{o21-KkPRUAG+vz=;uA5 zudI8Kc|#Xn5B;=z17mzcI6Zc_2P?(dE*As+>POJj}ni z^mh6z`u{fk-X(rN_xFE>-_Ixc{hT{i_m)lU>a7k3|5I=B59+=5;pNeKzMgV>-WI>( zdcAjt{YpJ=>)(2!BePI_Lve;-|Ljbl^23v($iYHy2= Hr)&QJjOmyv literal 6278 zcmbW5Ka5pH6vmHl-##|5uDiIbi&+)oU*G}zU=5%|Pzg%FNOYsbn5@bYAbBxlLs$z7 z3kyvwEG$g4urRT)ps?7&g2EUJ3kwSi3knJg3JMDg3(t?aU+&zyo*{aZ-QUYM^Uaw# zGjC?@vz~Qq#OChm*cIDk6SmR%HfgIiYST7lv(~ejPH*MhrQyZ1Z!euaHykbvR+k1V zHa#->%(EXKIQio@w+mv7OeN=$Ki5a>W1p^W-09 zM_#P?`i-QEUf!KDlYd9sPi_1n?eU2IG57Dz{rCTA_R<-%M;2?owq}MddU@y{TS(pm z(=~U0XNE3%+o6BzGqZ=jPIX24f-brq`iVnb;)@TQO7TV4bALY{Kc2(4Qhf3F>C~3! zdgv!l%7I9m=%VYne^(x#KE8a_Z2R9e7vC~N7ri|6-+R;Sxu4BuzpVNEUuNi{mxq4h z;3vL_4_z$zANw}>cD-2>AG%ob(@)keevy7?Tvd74|BaudSPS3Rq%CyO`x5$TpRrR{ zr0?jW>!F`G)Fr;i+@p)Ghko)*U1E#(98UQcUC;gV`TBYAJ+srln{E50=Bo>4=%Sa0 z{!MFUkN;*iF!F`GGsjYVk?%6P=z8d9oWy1PB5~2hQhYo| zFQ>X9-#>KG^)NpD#K-y*@u7<)KRL$7T#5M5#gd;m!F|ian9lwX$M_&J@nH* zeAE>ghsITvhkoW6AM+~MK8~*VdX7l4_oR#9fWixcq_0Ufr z@v&cs_|V0Y9}j=j74y$kc^F@3Jh|g80QoMVi>`-$?%4Q$h09|xFAAiGtXqbHLmG~h(bg|^;&PLuidqwhw zE|&7Qqnmu(AMrzc=wivwKFwLnekbbQAi5ro|9_nSjr=iAa?SWf<^WxEJ&eyd@iA@@ zAG+A`5AyYA{_y_8-CyLrhevF^|E%-B@P6`(r~1h+x}NvH;n(?@pLeu_F1GgHhMzpq zckXH;?>*?E>tTG>3_kKF;zJipe&Vp^St}y#s9#li7@u;^Db5a&cGPZFUi8y<;)}GS zcA@K`pYJT^9A1(Bql>PGe%`S-d+>|2gD#fl4-bFT6`6NFi~c!`Pd|yB|KUX!y)5*1 z&ZPHD_IutpA#I_Ht@qb;>kl96PsCT{{WeQ}-M^SW&OFFoUbufX;`7c*Ecz|d7j)6} zaQv)uyuAO4^dDVxJ@hkX{-`VFpR4lF&$&q*e)|#eql>PGe&(6HweL^p`mQx@tI9(^^NWxBuBdqzT@U@tGY|7G z(r> -rect 0 46 54 75 +rect 0 48 54 77 << pwell >> -rect 0 0 54 46 +rect 0 0 54 48 << ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 +rect 14 34 16 38 +rect 22 30 24 38 +rect 30 30 32 38 +rect 38 34 40 38 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 +rect 22 56 24 59 +rect 30 56 32 59 << 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 13 34 14 38 +rect 16 34 17 38 +rect 21 34 22 38 +rect 17 30 22 34 +rect 24 30 25 38 +rect 29 30 30 38 +rect 32 34 33 38 +rect 37 34 38 38 +rect 40 34 41 38 +rect 32 30 37 34 rect 9 21 14 23 rect 13 17 14 21 rect 16 17 22 23 @@ -37,65 +37,76 @@ 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 +rect 21 56 22 59 +rect 24 56 25 59 +rect 29 56 30 59 +rect 32 56 33 59 << 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 34 13 38 +rect 17 34 21 38 +rect 25 30 29 38 +rect 33 34 37 38 +rect 41 34 45 38 +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 +rect 17 56 21 60 +rect 25 56 29 60 +rect 33 56 37 60 << psubstratepcontact >> rect 25 9 29 13 +<< nsubstratencontact >> +rect 25 70 29 74 << 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 22 59 24 62 +rect 30 59 32 62 +rect 22 45 24 56 +rect 30 53 32 56 +rect 13 41 16 45 +rect 14 38 16 41 +rect 22 38 24 41 +rect 30 38 32 49 +rect 38 41 41 45 +rect 38 38 40 41 +rect 14 32 16 34 +rect 38 32 40 34 rect 14 23 16 24 -rect 22 23 24 29 -rect 30 23 32 29 +rect 22 23 24 30 +rect 30 23 32 30 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 28 49 32 53 +rect 9 41 13 45 +rect 22 41 26 45 +rect 41 41 45 45 rect 12 24 16 28 rect 38 24 42 28 << metal1 >> -rect 0 68 25 72 -rect 29 68 54 72 -rect 0 61 54 65 -rect 10 44 14 61 -rect 17 51 20 54 -rect 17 47 27 51 -rect 17 37 20 47 -rect 34 44 37 54 -rect 27 40 37 44 -rect 40 44 44 61 -rect 34 37 37 40 -rect 6 33 9 37 -rect 45 33 48 37 -rect 25 23 29 29 +rect 0 70 25 74 +rect 29 70 54 74 +rect 0 63 54 67 +rect 6 45 10 63 +rect 16 56 17 60 +rect 37 56 38 60 +rect 16 53 20 56 +rect 16 49 28 53 +rect 6 41 9 45 +rect 16 38 19 49 +rect 35 45 38 56 +rect 44 45 48 63 +rect 26 41 38 45 +rect 45 41 48 45 +rect 35 38 38 41 +rect 6 34 9 38 +rect 16 34 17 38 +rect 37 34 38 38 +rect 45 34 48 38 +rect 25 23 29 30 rect 25 13 29 17 rect 0 9 25 13 rect 29 9 54 13 @@ -103,40 +114,37 @@ 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 25 70 29 74 +rect 25 56 29 60 +rect 2 34 6 38 +rect 48 34 52 38 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 +rect 16 2 20 6 +rect 34 2 38 6 << metal2 >> -rect 2 37 6 72 -rect 2 0 6 33 -rect 9 21 13 72 -rect 25 58 29 68 +rect 2 38 6 74 +rect 2 0 6 34 +rect 9 21 13 74 +rect 25 60 29 70 rect 9 0 13 17 rect 16 6 20 24 rect 34 6 38 24 -rect 41 21 45 72 +rect 41 21 45 74 rect 41 0 45 17 -rect 48 37 52 72 -rect 48 0 52 33 +rect 48 38 52 74 +rect 48 0 52 34 << comment >> -rect 0 0 54 70 +rect 0 0 54 72 << labels >> -rlabel metal1 19 63 19 63 1 wl0 -rlabel metal1 19 70 19 70 5 vdd rlabel metal1 27 4 27 4 1 wl1 rlabel psubstratepcontact 27 11 27 11 1 gnd 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 72 19 72 5 vdd +rlabel metal1 19 65 19 65 1 wl0 << end >> diff --git a/technology/scn3me_subm/mag_lib/cell_1w_1r.mag b/technology/scn3me_subm/mag_lib/cell_1w_1r.mag new file mode 100644 index 00000000..e87557e9 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/cell_1w_1r.mag @@ -0,0 +1,150 @@ +magic +tech scmos +timestamp 1558915277 +<< nwell >> +rect 0 48 54 77 +<< pwell >> +rect 0 0 54 48 +<< ntransistor >> +rect 14 34 16 38 +rect 22 30 24 38 +rect 30 30 32 38 +rect 38 34 40 38 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 56 24 59 +rect 30 56 32 59 +<< ndiffusion >> +rect 13 34 14 38 +rect 16 34 17 38 +rect 21 34 22 38 +rect 17 30 22 34 +rect 24 30 25 38 +rect 29 30 30 38 +rect 32 34 33 38 +rect 37 34 38 38 +rect 40 34 41 38 +rect 32 30 37 34 +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 56 22 59 +rect 24 56 25 59 +rect 29 56 30 59 +rect 32 56 33 59 +<< ndcontact >> +rect 9 34 13 38 +rect 17 34 21 38 +rect 25 30 29 38 +rect 33 34 37 38 +rect 41 34 45 38 +rect 9 17 13 21 +rect 25 17 29 23 +rect 41 17 45 21 +<< pdcontact >> +rect 17 56 21 60 +rect 25 56 29 60 +rect 33 56 37 60 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 25 70 29 74 +<< polysilicon >> +rect 22 59 24 62 +rect 30 59 32 62 +rect 22 45 24 56 +rect 30 53 32 56 +rect 13 41 16 45 +rect 14 38 16 41 +rect 22 38 24 41 +rect 30 38 32 49 +rect 38 41 41 45 +rect 38 38 40 41 +rect 14 32 16 34 +rect 38 32 40 34 +rect 14 23 16 24 +rect 22 23 24 30 +rect 30 23 32 30 +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 28 49 32 53 +rect 9 41 13 45 +rect 22 41 26 45 +rect 41 41 45 45 +rect 12 24 16 28 +rect 38 24 42 28 +<< metal1 >> +rect 0 70 25 74 +rect 29 70 54 74 +rect 0 63 54 67 +rect 6 45 10 63 +rect 16 56 17 60 +rect 37 56 38 60 +rect 16 53 20 56 +rect 16 49 28 53 +rect 6 41 9 45 +rect 16 38 19 49 +rect 35 45 38 56 +rect 44 45 48 63 +rect 26 41 38 45 +rect 45 41 48 45 +rect 35 38 38 41 +rect 6 34 9 38 +rect 16 34 17 38 +rect 37 34 38 38 +rect 45 34 48 38 +rect 25 23 29 30 +rect 25 13 29 17 +rect 0 9 25 13 +rect 29 9 54 13 +rect 0 2 16 6 +rect 20 2 34 6 +rect 38 2 54 6 +<< m2contact >> +rect 25 70 29 74 +rect 25 56 29 60 +rect 2 34 6 38 +rect 48 34 52 38 +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 38 6 74 +rect 2 0 6 34 +rect 9 21 13 74 +rect 25 60 29 70 +rect 9 0 13 17 +rect 16 6 20 24 +rect 34 6 38 24 +rect 41 21 45 74 +rect 41 0 45 17 +rect 48 38 52 74 +rect 48 0 52 34 +<< comment >> +rect 0 0 54 72 +<< labels >> +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +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 72 19 72 5 vdd +rlabel metal1 19 65 19 65 1 wl0 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/convertall.sh b/technology/scn3me_subm/mag_lib/convertall.sh index f5e2482c..43de584f 100755 --- a/technology/scn3me_subm/mag_lib/convertall.sh +++ b/technology/scn3me_subm/mag_lib/convertall.sh @@ -11,4 +11,12 @@ load tri_gate gds write tri_gate.gds load write_driver gds write write_driver.gds +load replica_cell_1w_1r +gds write replica_cell_1w_1r +load replica_cell_1rw_1r +gds write replica_cell_1rw_1r +load cell_1rw_1r +gds write cell_1rw_1r +load cell_1w_1r +gds write cell_1w_1r EOF diff --git a/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag b/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag index f215ff04..48a3f4c1 100644 --- a/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag +++ b/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag @@ -1,33 +1,33 @@ magic tech scmos -timestamp 1542221056 +timestamp 1558915332 << nwell >> -rect 0 46 54 75 +rect 0 48 54 77 << pwell >> -rect 0 0 54 46 +rect 0 0 54 48 << ntransistor >> -rect 14 33 16 37 -rect 22 29 24 37 -rect 30 29 32 37 -rect 38 33 40 37 +rect 14 34 16 38 +rect 22 30 24 38 +rect 30 30 32 38 +rect 38 34 40 38 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 +rect 22 56 24 59 +rect 30 56 32 59 << 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 13 34 14 38 +rect 16 34 17 38 +rect 21 34 22 38 +rect 17 30 22 34 +rect 24 30 25 38 +rect 29 30 30 38 +rect 32 34 33 38 +rect 37 34 38 38 +rect 40 34 41 38 +rect 32 30 37 34 rect 9 21 14 23 rect 13 17 14 21 rect 16 17 22 23 @@ -37,71 +37,77 @@ 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 +rect 21 56 22 59 +rect 24 56 25 59 +rect 29 56 30 59 +rect 32 56 33 59 << 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 34 13 38 +rect 17 34 21 38 +rect 25 30 29 38 +rect 33 34 37 38 +rect 41 34 45 38 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 +rect 17 56 21 60 +rect 25 56 29 60 +rect 33 56 37 60 << psubstratepcontact >> rect 25 9 29 13 << nsubstratencontact >> -rect 25 68 29 72 +rect 25 70 29 74 << 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 22 59 24 62 +rect 30 59 32 62 +rect 22 45 24 56 +rect 30 53 32 56 +rect 13 41 16 45 +rect 14 38 16 41 +rect 22 38 24 41 +rect 30 38 32 49 +rect 38 41 41 45 +rect 38 38 40 41 +rect 14 32 16 34 +rect 38 32 40 34 rect 14 23 16 24 -rect 22 23 24 29 -rect 30 23 32 29 +rect 22 23 24 30 +rect 30 23 32 30 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 28 49 32 53 +rect 9 41 13 45 +rect 22 41 26 45 +rect 41 41 45 45 rect 12 24 16 28 rect 38 24 42 28 << metal1 >> -rect 0 68 25 72 -rect 29 68 54 72 -rect 0 61 54 65 -rect 10 44 14 61 -rect 29 54 33 58 -rect 17 51 20 54 -rect 17 47 27 51 -rect 17 37 20 47 -rect 34 44 37 54 -rect 27 40 37 44 -rect 40 44 44 61 -rect 34 37 37 40 -rect 6 33 9 37 -rect 45 33 48 37 -rect 25 23 29 29 +rect 0 70 25 74 +rect 29 70 54 74 +rect 0 63 54 67 +rect 6 45 10 63 +rect 16 56 17 60 +rect 29 56 33 60 +rect 37 56 38 60 +rect 16 53 20 56 +rect 16 49 28 53 +rect 6 41 9 45 +rect 16 38 19 49 +rect 35 45 38 56 +rect 44 45 48 63 +rect 26 41 38 45 +rect 45 41 48 45 +rect 35 38 38 41 +rect 6 34 9 38 +rect 16 34 17 38 +rect 37 34 38 38 +rect 45 34 48 38 +rect 25 23 29 30 rect 25 13 29 17 rect 0 9 25 13 rect 29 9 54 13 @@ -109,10 +115,10 @@ 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 25 70 29 74 +rect 25 56 29 60 +rect 2 34 6 38 +rect 48 34 52 38 rect 16 24 20 28 rect 34 24 38 28 rect 9 17 13 21 @@ -120,26 +126,26 @@ 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 -rect 9 21 13 72 -rect 25 58 29 68 +rect 2 38 6 74 +rect 2 0 6 34 +rect 9 21 13 74 +rect 25 60 29 70 rect 9 0 13 17 rect 16 6 20 24 rect 34 6 38 24 -rect 41 21 45 72 +rect 41 21 45 74 rect 41 0 45 17 -rect 48 37 52 72 -rect 48 0 52 33 +rect 48 38 52 74 +rect 48 0 52 34 << comment >> -rect 0 0 54 70 +rect 0 0 54 72 << labels >> -rlabel metal1 19 63 19 63 1 wl0 -rlabel metal1 19 70 19 70 5 vdd rlabel metal1 27 4 27 4 1 wl1 rlabel psubstratepcontact 27 11 27 11 1 gnd 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 72 19 72 5 vdd +rlabel metal1 19 65 19 65 1 wl0 << end >> diff --git a/technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag b/technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag new file mode 100644 index 00000000..48a3f4c1 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag @@ -0,0 +1,151 @@ +magic +tech scmos +timestamp 1558915332 +<< nwell >> +rect 0 48 54 77 +<< pwell >> +rect 0 0 54 48 +<< ntransistor >> +rect 14 34 16 38 +rect 22 30 24 38 +rect 30 30 32 38 +rect 38 34 40 38 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 56 24 59 +rect 30 56 32 59 +<< ndiffusion >> +rect 13 34 14 38 +rect 16 34 17 38 +rect 21 34 22 38 +rect 17 30 22 34 +rect 24 30 25 38 +rect 29 30 30 38 +rect 32 34 33 38 +rect 37 34 38 38 +rect 40 34 41 38 +rect 32 30 37 34 +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 56 22 59 +rect 24 56 25 59 +rect 29 56 30 59 +rect 32 56 33 59 +<< ndcontact >> +rect 9 34 13 38 +rect 17 34 21 38 +rect 25 30 29 38 +rect 33 34 37 38 +rect 41 34 45 38 +rect 9 17 13 21 +rect 25 17 29 23 +rect 41 17 45 21 +<< pdcontact >> +rect 17 56 21 60 +rect 25 56 29 60 +rect 33 56 37 60 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 25 70 29 74 +<< polysilicon >> +rect 22 59 24 62 +rect 30 59 32 62 +rect 22 45 24 56 +rect 30 53 32 56 +rect 13 41 16 45 +rect 14 38 16 41 +rect 22 38 24 41 +rect 30 38 32 49 +rect 38 41 41 45 +rect 38 38 40 41 +rect 14 32 16 34 +rect 38 32 40 34 +rect 14 23 16 24 +rect 22 23 24 30 +rect 30 23 32 30 +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 28 49 32 53 +rect 9 41 13 45 +rect 22 41 26 45 +rect 41 41 45 45 +rect 12 24 16 28 +rect 38 24 42 28 +<< metal1 >> +rect 0 70 25 74 +rect 29 70 54 74 +rect 0 63 54 67 +rect 6 45 10 63 +rect 16 56 17 60 +rect 29 56 33 60 +rect 37 56 38 60 +rect 16 53 20 56 +rect 16 49 28 53 +rect 6 41 9 45 +rect 16 38 19 49 +rect 35 45 38 56 +rect 44 45 48 63 +rect 26 41 38 45 +rect 45 41 48 45 +rect 35 38 38 41 +rect 6 34 9 38 +rect 16 34 17 38 +rect 37 34 38 38 +rect 45 34 48 38 +rect 25 23 29 30 +rect 25 13 29 17 +rect 0 9 25 13 +rect 29 9 54 13 +rect 0 2 16 6 +rect 20 2 34 6 +rect 38 2 54 6 +<< m2contact >> +rect 25 70 29 74 +rect 25 56 29 60 +rect 2 34 6 38 +rect 48 34 52 38 +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 38 6 74 +rect 2 0 6 34 +rect 9 21 13 74 +rect 25 60 29 70 +rect 9 0 13 17 +rect 16 6 20 24 +rect 34 6 38 24 +rect 41 21 45 74 +rect 41 0 45 17 +rect 48 38 52 74 +rect 48 0 52 34 +<< comment >> +rect 0 0 54 72 +<< labels >> +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +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 72 19 72 5 vdd +rlabel metal1 19 65 19 65 1 wl0 +<< end >> From 26146b6838881f0d5a42dddba9399bc0489607ff Mon Sep 17 00:00:00 2001 From: mrg Date: Sun, 26 May 2019 22:28:16 -0700 Subject: [PATCH 021/234] Fix SCN3ME_SUBM stuff. Update cells to be DRC clean with rule 5.5.b Allow magic for FreePDK45 but not debugged. Revert to older Magic tech file for SCN3ME_SUBM --- compiler/verify/__init__.py | 3 - .../scn3me_subm/gds_lib/cell_1rw_1r.gds | Bin 6458 -> 6394 bytes technology/scn3me_subm/gds_lib/cell_1w_1r.gds | Bin 6454 -> 6390 bytes technology/scn3me_subm/gds_lib/cell_6t.gds | Bin 5916 -> 5916 bytes technology/scn3me_subm/gds_lib/dff.gds | Bin 16622 -> 16622 bytes .../gds_lib/incorrect/cell_1rw_1r.gds | Bin 6330 -> 0 bytes .../gds_lib/incorrect/cell_1w_1r.gds | Bin 8192 -> 0 bytes .../gds_lib/incorrect/replica_cell_1rw_1r.gds | Bin 6282 -> 0 bytes .../gds_lib/incorrect/replica_cell_1w_1r.gds | Bin 8192 -> 0 bytes .../gds_lib/replica_cell_1rw_1r.gds | Bin 6410 -> 6346 bytes .../gds_lib/replica_cell_1w_1r.gds | Bin 6406 -> 6342 bytes .../scn3me_subm/gds_lib/replica_cell_6t.gds | Bin 6060 -> 6060 bytes technology/scn3me_subm/gds_lib/sense_amp.gds | Bin 8312 -> 8312 bytes technology/scn3me_subm/gds_lib/tri_gate.gds | Bin 4576 -> 4576 bytes .../scn3me_subm/gds_lib/write_driver.gds | Bin 11804 -> 11804 bytes .../scn3me_subm/mag_lib/cell_1rw_1r.mag | 56 +- technology/scn3me_subm/mag_lib/cell_1w_1r.mag | 56 +- .../mag_lib/replica_cell_1rw_1r.mag | 56 +- .../mag_lib/replica_cell_1w_1r.mag | 56 +- technology/scn3me_subm/mag_lib/setup.tcl | 10 +- technology/scn3me_subm/sp_lib/cell_1rw_1r.sp | 20 +- technology/scn3me_subm/sp_lib/cell_1w_1r.sp | 20 +- .../scn3me_subm/sp_lib/replica_cell_1rw_1r.sp | 20 +- .../scn3me_subm/sp_lib/replica_cell_1w_1r.sp | 20 +- .../scn3me_subm/tech/SCN3ME_SUBM.30.tech | 1555 ++++------------- technology/scn4m_subm/tech/SCN4M_SUBM.20.tech | 72 +- technology/scn4m_subm/tech/tech.py | 4 +- 27 files changed, 515 insertions(+), 1433 deletions(-) delete mode 100644 technology/scn3me_subm/gds_lib/incorrect/cell_1rw_1r.gds delete mode 100644 technology/scn3me_subm/gds_lib/incorrect/cell_1w_1r.gds delete mode 100644 technology/scn3me_subm/gds_lib/incorrect/replica_cell_1rw_1r.gds delete mode 100644 technology/scn3me_subm/gds_lib/incorrect/replica_cell_1w_1r.gds diff --git a/compiler/verify/__init__.py b/compiler/verify/__init__.py index 04fa9746..c7bec114 100644 --- a/compiler/verify/__init__.py +++ b/compiler/verify/__init__.py @@ -33,9 +33,6 @@ else: OPTS.lvs_exe = get_tool("LVS", ["calibre","assura","netgen"], OPTS.lvs_name) OPTS.pex_exe = get_tool("PEX", ["calibre","magic"], OPTS.pex_name) -if OPTS.check_lvsdrc and OPTS.tech_name == "freepdk45": - debug.check(OPTS.drc_exe[0]!="magic","Magic does not support FreePDK45 for DRC.") - if OPTS.drc_exe == None: from .none import run_drc,print_drc_stats elif "calibre"==OPTS.drc_exe[0]: diff --git a/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds b/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds index f9cec56965719c38ebb10025fb5ffa5cf8f57f68..a4fea073f7794ef11cbd2daa04f721b08f919b4f 100644 GIT binary patch delta 428 zcmZXOy-EW?6ot=hCUG4i?go==f>;a^P{SrJDbs0TD#1TcL?mo&scp&>X~MjLMG6ZM zrV;T0ti&P@5G+zyr_#o`4C59Sm+x{o=brnLeD6vW;30=~=HU)`)KS4Q;=f&>HI}XL zzu2G1Ee;$$0ZE$iJOD_y)Z6Te$(>8!$OqcRjAzdP>6ZGz+wf#_2po5Sc$V>W1dwj2 zzxZcPQr~LV_7Xdd1z+I4971s%24V6 delta 410 zcmexmxXVb1fsKKQftf*uk%^(4ft5juL6CtFh+%9d27`%8`hu8(Nz0U^zA!NOZ(v|h z2|>`20t^fwaR|Lxi!qK-N!EvfA&7&4LGcfQ4%@-N01}7Ln^!T(F-`8^HQxN2!+lRXR!Ts;g7CVMukaV}z<%)u=J7Sri~h;b*es<8tN1*zi(8U~|1uP`ux#9=g0 z|2lyvMzC4~9tH+}8wLg#4blTM14J9}OnxUgOUZZw#5fBF1Pw9{Bo3h`X9=Z=fuunu z!IXj6K--=Ponzqu8pg)U#9%*hj{;vv0s|O8=*g?Zr%j$9;XIjJf_JimgbpWAm_w4S SEG1>KuY^7uI|Bm?3j+WIVomY@ diff --git a/technology/scn3me_subm/gds_lib/cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/cell_1w_1r.gds index b10f2726c7b71f099531797c8e464ad569b30c46..382018a72c5508ba11ee26a0f7b90ab724a76510 100644 GIT binary patch delta 428 zcmZXOy-EW?6ot=hHgOyx?gk8#ASzQVsBw);N*};fg1;ytLADTU(bmEug^kP`1WA!f z7!V6fOR>rW$QC|=wR0K9Ei5kI<#5hD_a*z;Qm7$71&b`eEvjgviCLt7yTIn7+KB&) zgD15b0=v&ZmX|z<0MZ>z!p@mmKLhqS(5;s|dId;#G~-|?P@N&L-viRGl7|lf>5k?* zEGmln=C@rhvG)cD>+{TVJ>jV!8_8L23O-^9)ssdxPufZMw9zZ!qSR`mBXLnp=nUDY z&9gss=RLc1vlg8){T|=x`^HYwpCpopa{Z|(8lRz-Qfe-*^@r@}l~$xL<*{CtbL|BQ T91Or)wVT|28pd{J?1cCQr~yu% delta 417 zcmexnxXnn3fsKKQftf*uk%^(4ft5juL6CtFh+%9d27`%8x`LR32}_iuzA!NOZ(v|h z2|>`20t^fwaR|LxjWLcmaHQxN4A%nm~C0%6h#;7R{0Jks){Qv*} diff --git a/technology/scn3me_subm/gds_lib/incorrect/cell_1rw_1r.gds b/technology/scn3me_subm/gds_lib/incorrect/cell_1rw_1r.gds deleted file mode 100644 index 2d12b8eea9b4107adacb23f749aeeec1f17ef784..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6330 zcmbW5J&aXF7=~Z==dyuySr8Bm3jPZ$unTJdC4x%)i5Q7)lo%6@uF+y+3^A;Qg@uJC z78VvJT3DFaSWsAOVL@Sxg@uKMg@px$g$0F$g@xb4oHu9g#czn73mYDOEhTeoXflbX^dZPPlwTh5gDX6Utlt{y+06IV)n^U<@VEi?4gPoA6ulQz-K&};wx zIzD}T`l58(-#wRJme9>8PyILkAwB$~wBz%hkNhQ}n^B(niG!c`CO&kt<-hyu;@kgX zPkiWR%TGU9yZBA|;c<24Y5zBTRAMcD+mp7?&FD+&r+vmwU6a0}o1v$E;!v0PCUcK& zhMxM#Gj)k=ZaPu&Z-!p`=j-)z>pRlfU!^@i^?Y_wLN}v4^>190?)gQUneDl6UP3pc zJoRteQG7SO)e|4O+42*c4|UD@cUPXqUpQ8LM?UU}AKi>LQa^dR>%EdclbGmc=&7GP zF;?Yw|d1XUbFHG`|&kVikXWYazX$QYKGX6vL z{YQ*rr%Jxe`#&wQ&Cu)kL;mT@()_fDj{kq`|3mp>oaCDEo6G^a8G0I@apGg#CO&j?#J^ClKgGrS4`+Xq z_Z}{D?aG^e`c8b4cHAxu zJ@s?XvrpnR=|8#|dg|vLjlB!MNjvCfYyR=@p{~ig;kOyT)A;n0*!2f5x*27uf9zbD zYxWD~9MTrL8G7m`zxY_cCcZB3SK0FW{KovTXF~RZ#`$gN{^6aMSoGVZFX(3IY5%!T z@N)l{^dH>}J@qqYKGZeq-(7j?XWyj`{~ek5(aq3PKl4o9M$cd9fdsy^p$l_pS}LknZK?)^)tWtI4_%?cQf?V&pdN6|0exLH$zYT zoVmGJza~C(GxXYjvYtOYT+F}uOgH~#=vV#GCI0`8`+qzCe^2xOH|LHge%92^!RpHV zb?QZXQSZX?a-$w+u8E7Ky@l)4i+6-*@AWrF+Kcts_b=Mw|J|tf%4q+F>hZqedLwa% X>hW&S)jQv+$GeZ~IWOyDJQMl{QEIs5 diff --git a/technology/scn3me_subm/gds_lib/incorrect/cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/incorrect/cell_1w_1r.gds deleted file mode 100644 index 080a29e3340ca246cceb29908585c6eb92868b87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 zcmeI0Ka3Ss6o(IQcONgXF3W9ocjjP&1z}hB(vY<%>Cxv zduHyPnP+WlS=;7TwQR=L+LW!aZFaY9unFtfI-9ixn{2h0&%gT8+x@r9HjYg^a`dAE zPyX=rjYG#T@B8xe=a+15B6g?R?N`qC`{#NW&-E_Yc*m@LTg!G?d#Yt-^V4Jg*S80M zOMLFS*^$T1M8%!s>+NrUXVXu1IuAY`%(mR$o%?s3G&^<444!$>?5;m+D((#Z4L8gl z{mBd-`@?L@7c~`khCX>|2l2@-DqiyM`zHAiZ}$r|@vGxue)>(VG!A?`sJJuq*L<9E zK%B+zYLdG;9{S{E%#ik+LsZ-u`kWsZZoQfEi;6o#pSt71b%#@5M8%!C-_7rzJKr@s zea#F$vuL*cYE8wRp}+RB+5Nwm!ChUmsp*=EJ465WEy;)Yo8PR7UmXv9+Gxkmcg3Bd z-#eImh`axjn)uc6(5G%Y-cR+TJ@pe6cZNQ7V~mioQ$JC0XXulE)A5v_xl4XgacAf= zKJq~FGJa9!Si;6pQe?A{SZ4UpQ&T-;&$}cMJ41MZHZpgXlyQsJ`_xI-cXMarhEF|yT z_L|(w)$!23=K-^azc+*U%vn)!XXsO7Y6fYKFDmW~eeSWnzovVT{?1%Ud5~IG$3vg`;Hi#`gML88OZk~A)Le6hyv!k}xHHU8|G3_e_VS?O&d{gdw9_~^ z2mOYMmwc`}?I72S>nAE+^5;KH`5<-6cluEs5Btw?u9MD#qg`=l(Pymq)SY!)RNPtg z87DsNRXeD7WBmK_`A4pUODX3=pQSpAiaYcCL;mD-v+krBTv$%;Frwnl(5KI|gLtgt zqT(f=Hrny>UGb97yO!R)m^0K&RNNW%pY@t{5RaUq;tju-*WY~OJ)e#Df8KdT#T)Pc zxA>2}H_+|meDX!boq7L<{CxeQJ@Z)P9;%LqKJU1CPj7yIDBgH~AIeXSXb1J(Au3+- zc~_?$Y<_%GRo`wt#e+*uqy>y6ICoX3NTJBvQw9Qd>+uc){)^m%V$&4TnB zM^xMy`aHL}&XD%_qT*8(dNGl25XOVlNIv)De zopun9cW+T~XXrPdpIkrIRLGiE9S?oJ@yHFyP5(v3ouSXX(Hcg-`DPUrcZNP=)Q*?$ zikHUEdPh5m%R8f}c**CwQzxkBo~XDp>_2&_6Qpi@|BH&3>Sw-Ddp7FD+z}ObhWYWh z$JkbPk}oRm9QfWvet+`yZxg>iwKuQg?^ga!@>>+&dr$mqo!R!qe%Ds+Jl(;0XL)&r z4$r6YODRw9UpW4Z_dKt?p*%iZ#UijL&oL(^CiiaSGp=XmlV9&<^=ua1X4 z&uhNrA!`upkEpma^#8-}2}AW`+|(FSd&Vy+?hNxYKH5P%#xE+~@b~BUUpD6k?@`P} z-lrg2bv(~MO8=yQ!&Lm(dOv8cE+^k=T5K0-Z5MEYJG4}I=Y+G#!2 zcLh}38TzcFY>~MXoq2rv`1*CT$Ns4~_nsNL=;fjRp})+Y|JiKv`G(8ZFUezJD)i}XX|s>;LuulhR0n*E_BZJ~?am(Wl9jGek7 zeMc8v5B*tZr%ufAow(XaiZ_b*bi(Vf3 zS1*}8{hQhNM9m%3X6T}qhyIO|$@lR2n)uMglAqXos4M2*tMV}Z%z@qS5FhF9df+J&wc{fwRcLL~3_ zMAwUc#!XC-cJPa>@$bohf5bR&JmpI~bScFaUC-k;{A0JxrpL@UE5*I@X6T~pp`SkD zW4{pbp^GIy9zN6+^Y2x87++^Rx#KPX`7NP~u7`f^*!YMe;zJi({=Iqr8TWs@KP>aJ zZ!?dg_IeOiU!=W$)bB9t`H-^!U35Jkf5U%pn0)M&_#r-YvE=8@M&3AkMe>F& zmh!i~n|$0K@k4y*V#&`w%~{KSC+glHx*m@If1Lk~{4q{)&G<#;09|xFjL$gnF>Vnb zy4dp1}J~V)Bb82gxtGp7+1u*ZG;BceH~pw)WqKpFGib z?rI|MJ?NtAVSLsMKJq8xLl;Ya;;`mfD`-$-my4)@QbvAE|%sG4tz_enkA}qU)ibc_we|`x82Otja?_amZW# z{{!-dE|&6V{*Y^aD!E-B&D2-cJ$=^tM`!-3^3c!x;^V$6YTiZHLqGG(!~Bc% z8(nlg^mAwCVf~8u&_&mC|FL}j@bHj3@eQ9t9?`$v^Lv;0|F!@AH}U`LG5&wez2TK# zt-raqIGlb!J#WwJU6`LQ)Z@<7y`I{ec|bkC<9mA_e$r~s*Js^7Z;SuWdc66=H!hrCy0FskFZC`h^;T`XZC2dYvb|PJwalzD zJ?4LXd*JuP7p|L~c+yN%+&RA4{`L3N{bZ-};N!t;%l&=1f5&OFXD*w;voD+7^>;IFx&NWMa7+=zwwIMeZQK)y57UwL;v>e$%pvcE>^@ZkB2^O zwBzTy;?B_T9Zf#OJ^V>U{PK9{Q@4BGPxYfc^%E6$hCX#;jF7QYKT&aK=#zi;WXjLn zCBLY+GxQlBc_4Wizo>Xqe%dVh5(}AkxT50DFhBjL9mJ#mqT)?HwWb}!;~I*JH~HkH z_K@0>UsT+g_kVvrf0(OJpG$N1c|XtHXU#;#ouS`eNDkcpt=W;S6**UVJoGnzYPRz$ zGe~>RAu8?+ea?>ySwqM#D(=kvPCkCx9RDMoaNL26kZ4}I!`r#dnY`T-Sh%FkS(=9)9)We!2bone0Z$MuG^mj@Mh zhCcnKoyNgA=r>fn$>+M$4syM?exl+{e&@rK4^p>$ryu3TzAI_W$(+7)*;`ivEy zy0eapiaQ&9#)(gR)eb6N8~?$4{*mkGV#@j8XQ_^&;?6w(kUx3dtUGB24=ty67*TO& z=+kG~K|I!RQSm09Hrny>UGXNLcP+hpF=wcmsJJuiKkGH^ARakI#cO^qufO@mdp;ZQ z|Ge{xir3!%Z}OjbZ=l=hPVz;?oq7L<{CxeQJ@Z)P9x9KAKJU1CPp^M}C|-MiAIeXS zXb0=x4~jSWqS#UsT)~`rP+ggXlNkoTB2+&}WR=@$y~q zrt!00(GKGB&L=9~Ox-^7Q_LzBE{XW%@zCda z%eOdW4PyNf6?caI|M)#%sD6x_8bfN&_(jE?VSdI(JBY{lMa66W;r#x~=G@>th`Gr7 z5M(Ql=lO^HY|aln)&hLURvr(1t`Tbp#A7`c6?caI%+=IKsON}C-^=5n&pk>zt*81f zfQmaqpLLWC(r?yNQE_MJ^Ulu(@pvAHiaQ6sr(pf?`rmpz^fij#27JwVrM@194&M=S zYHM5Q@XlX4t7~=m#*xzAc$SqWqxzYWA*5N)!Dfq@IC4n`ZLOy0+##|2Ub5;jWN{EcG~qZ-J1 zkQhiAj0Ukm;xHPhwT=s-6=W+=>o%?=RyB|@AY~xiV6^8Ii19GmfM>IvfE4588G;Ry zBZNG}U`B#ykQ$Ia&nug^37un^d_=rw@&XB+$zLP{CW}ajOb(E6o_t!IS4vcZfgvP; UfkTq5ECuLN7C|6p2Vxcm0H7&Q3jhEB delta 410 zcmX?Q*kz=|z{bGDz|0`S$iz_2z{()SAPD61Ah8W5Dwzvn3TCZSlKR5H;J<-^K_vu1 zM+z`7fW#s6W-G=xMkQGv28JLG1_s4H2s&&B0|Q7LLT}#1B*!#)2CwmEZq|#;lVvys zxJ>piFmUxSFqrJwY{t2Wak2!r2v|&~10u$q#Hz*)G!&$c8)z7e_PoNt01}7MK>hm! zq!__!4R{zB_-z;%U^GY%%nT51z%zND;4CHM2@vBf91t|fIFLAmo@^zQCI*rQnFLb? zVgqg4CUlO4185i diff --git a/technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds index bab19446192c461168c38b42f083fe93ddd05db9..5d25a34fc916518a14c51f39bb09970b770e4612 100644 GIT binary patch delta 428 zcmZoOI%cTEz{bGDz|0`S$iz_2z{()SAjZH2BoS==iAtt|n1UH=lr&iw82mRdFc_sE z=tuzu29P*}-fYGg$Ec(o!@v;4!N6d^gP_B9Fff3`A@t^LOma+0IvorQ!6pn0dJhnE zXb%GeNE||M{>Ji%SqWqxzYWA*5N)!Dfq@IC4n`ZLOy0$z#|2Ub5;jWN{E1@`qZ-J1 zkQhiAj0Ukm;xHPhwTcU(6=W+=>n5%wRyB|@AY~xiV6^8Ii19GmfM>InfE458DS{1? zLxeoUU`B#ykQ$Ia&nufZ37un^{6bt}@(uBl$#W!hCV!9+m~0^tKKZ>kuau|+14Bpx U1BWDASqjjlEP_DH4#X@B0FC%iyZ`_I delta 417 zcmX?R*k+`}z{bGDz|0`S$iz_2z{()SAPD61Ah8W5Dwzsm3TCWPlKR5H;J<-^K_vu1 zM+z`7fW#s6W;4b(MkQGv28JLG1_s4H2s&&B0|Q7LLT}#2B*!#)3a{~IcGio`lO;F> zxJ>piFmUxSFqrJwY{a>Uak2=v2v|&~10u$q#Hz*)G!&$c8)z7e_PoNt01}7MK>fP} zq!__!4R{zB_-z;%U^GY%%nT51z%zN5;4CHM2@vBf91t|fIFLAmo@^$RCI*rQnFLb? zVgqg4By^62185ia*TxY delta 37 icmZ3Zzeaz8ICmKXCj$!u9|I!;|3oEAWbVc^H*o-jf(8}< diff --git a/technology/scn3me_subm/gds_lib/sense_amp.gds b/technology/scn3me_subm/gds_lib/sense_amp.gds index 0fc7eb56b105ae597059d4dca58f1a69987badd0..11081bd361edcfd05f6b8d3a5e7200e12953c4de 100644 GIT binary patch delta 37 icmez2@WWw(ICnV%D}xk+AcFvd+(ac~WbVcU2?YS80S5;F delta 37 icmez2@WWw(ICmKXCj$!u4}&3t(L^O(O diff --git a/technology/scn3me_subm/gds_lib/write_driver.gds b/technology/scn3me_subm/gds_lib/write_driver.gds index fdd3ad883b0f7ba91571eb508c5a78e27876802e..0bef7b7973766b293c75f95a3892e39ed2b0dc5f 100644 GIT binary patch delta 37 icmbOeGbd((ICnV%D}xk+AcFvd+(ac)WbVeKUAh31LI*kk delta 37 icmbOeGbd((ICmKXCj$!u4}%c{=R_q_WbVeKUAh2~vj-#q diff --git a/technology/scn3me_subm/mag_lib/cell_1rw_1r.mag b/technology/scn3me_subm/mag_lib/cell_1rw_1r.mag index e87557e9..6a6fbc86 100644 --- a/technology/scn3me_subm/mag_lib/cell_1rw_1r.mag +++ b/technology/scn3me_subm/mag_lib/cell_1rw_1r.mag @@ -1,6 +1,6 @@ magic tech scmos -timestamp 1558915277 +timestamp 1558933786 << nwell >> rect 0 48 54 77 << pwell >> @@ -22,8 +22,10 @@ rect 13 34 14 38 rect 16 34 17 38 rect 21 34 22 38 rect 17 30 22 34 -rect 24 30 25 38 -rect 29 30 30 38 +rect 24 36 30 38 +rect 24 32 25 36 +rect 29 32 30 36 +rect 24 30 30 32 rect 32 34 33 38 rect 37 34 38 38 rect 40 34 41 38 @@ -31,8 +33,10 @@ rect 32 30 37 34 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 24 22 30 23 +rect 24 18 25 22 +rect 29 18 30 22 +rect 24 17 30 18 rect 32 17 38 23 rect 40 21 45 23 rect 40 17 41 21 @@ -44,11 +48,11 @@ rect 32 56 33 59 << ndcontact >> rect 9 34 13 38 rect 17 34 21 38 -rect 25 30 29 38 +rect 25 32 29 36 rect 33 34 37 38 rect 41 34 45 38 rect 9 17 13 21 -rect 25 17 29 23 +rect 25 18 29 22 rect 41 17 45 21 << pdcontact >> rect 17 56 21 60 @@ -57,17 +61,17 @@ rect 33 56 37 60 << psubstratepcontact >> rect 25 9 29 13 << nsubstratencontact >> -rect 25 70 29 74 +rect 37 70 41 74 << polysilicon >> rect 22 59 24 62 rect 30 59 32 62 rect 22 45 24 56 rect 30 53 32 56 -rect 13 41 16 45 +rect 13 41 16 43 rect 14 38 16 41 rect 22 38 24 41 rect 30 38 32 49 -rect 38 41 41 45 +rect 38 41 41 43 rect 38 38 40 41 rect 14 32 16 34 rect 38 32 40 34 @@ -88,26 +92,26 @@ rect 12 24 16 28 rect 38 24 42 28 << metal1 >> rect 0 70 25 74 -rect 29 70 54 74 +rect 29 70 37 74 +rect 41 70 54 74 rect 0 63 54 67 -rect 6 45 10 63 +rect 9 45 13 63 rect 16 56 17 60 rect 37 56 38 60 rect 16 53 20 56 rect 16 49 28 53 -rect 6 41 9 45 rect 16 38 19 49 rect 35 45 38 56 -rect 44 45 48 63 rect 26 41 38 45 -rect 45 41 48 45 +rect 41 45 45 63 rect 35 38 38 41 rect 6 34 9 38 rect 16 34 17 38 +rect 25 36 29 38 rect 37 34 38 38 rect 45 34 48 38 -rect 25 23 29 30 -rect 25 13 29 17 +rect 25 22 29 32 +rect 25 13 29 18 rect 0 9 25 13 rect 29 9 54 13 rect 0 2 16 6 @@ -139,12 +143,14 @@ rect 48 0 52 34 << comment >> rect 0 0 54 72 << labels >> -rlabel metal1 27 4 27 4 1 wl1 -rlabel psubstratepcontact 27 11 27 11 1 gnd -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 72 19 72 5 vdd -rlabel metal1 19 65 19 65 1 wl0 +rlabel metal1 27 4 27 4 4 wl1 +rlabel psubstratepcontact 27 11 27 11 4 gnd +rlabel metal2 4 7 4 7 4 bl0 +rlabel metal2 50 7 50 7 4 br0 +rlabel metal1 19 65 19 65 4 wl0 +rlabel metal2 11 7 11 7 4 bl1 +rlabel metal2 43 7 43 7 4 br1 +rlabel metal1 18 72 18 72 1 vdd +<< properties >> +string path 0.000 0.000 243.000 0.000 243.000 324.000 0.000 324.000 0.000 0.000 << end >> diff --git a/technology/scn3me_subm/mag_lib/cell_1w_1r.mag b/technology/scn3me_subm/mag_lib/cell_1w_1r.mag index e87557e9..6a6fbc86 100644 --- a/technology/scn3me_subm/mag_lib/cell_1w_1r.mag +++ b/technology/scn3me_subm/mag_lib/cell_1w_1r.mag @@ -1,6 +1,6 @@ magic tech scmos -timestamp 1558915277 +timestamp 1558933786 << nwell >> rect 0 48 54 77 << pwell >> @@ -22,8 +22,10 @@ rect 13 34 14 38 rect 16 34 17 38 rect 21 34 22 38 rect 17 30 22 34 -rect 24 30 25 38 -rect 29 30 30 38 +rect 24 36 30 38 +rect 24 32 25 36 +rect 29 32 30 36 +rect 24 30 30 32 rect 32 34 33 38 rect 37 34 38 38 rect 40 34 41 38 @@ -31,8 +33,10 @@ rect 32 30 37 34 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 24 22 30 23 +rect 24 18 25 22 +rect 29 18 30 22 +rect 24 17 30 18 rect 32 17 38 23 rect 40 21 45 23 rect 40 17 41 21 @@ -44,11 +48,11 @@ rect 32 56 33 59 << ndcontact >> rect 9 34 13 38 rect 17 34 21 38 -rect 25 30 29 38 +rect 25 32 29 36 rect 33 34 37 38 rect 41 34 45 38 rect 9 17 13 21 -rect 25 17 29 23 +rect 25 18 29 22 rect 41 17 45 21 << pdcontact >> rect 17 56 21 60 @@ -57,17 +61,17 @@ rect 33 56 37 60 << psubstratepcontact >> rect 25 9 29 13 << nsubstratencontact >> -rect 25 70 29 74 +rect 37 70 41 74 << polysilicon >> rect 22 59 24 62 rect 30 59 32 62 rect 22 45 24 56 rect 30 53 32 56 -rect 13 41 16 45 +rect 13 41 16 43 rect 14 38 16 41 rect 22 38 24 41 rect 30 38 32 49 -rect 38 41 41 45 +rect 38 41 41 43 rect 38 38 40 41 rect 14 32 16 34 rect 38 32 40 34 @@ -88,26 +92,26 @@ rect 12 24 16 28 rect 38 24 42 28 << metal1 >> rect 0 70 25 74 -rect 29 70 54 74 +rect 29 70 37 74 +rect 41 70 54 74 rect 0 63 54 67 -rect 6 45 10 63 +rect 9 45 13 63 rect 16 56 17 60 rect 37 56 38 60 rect 16 53 20 56 rect 16 49 28 53 -rect 6 41 9 45 rect 16 38 19 49 rect 35 45 38 56 -rect 44 45 48 63 rect 26 41 38 45 -rect 45 41 48 45 +rect 41 45 45 63 rect 35 38 38 41 rect 6 34 9 38 rect 16 34 17 38 +rect 25 36 29 38 rect 37 34 38 38 rect 45 34 48 38 -rect 25 23 29 30 -rect 25 13 29 17 +rect 25 22 29 32 +rect 25 13 29 18 rect 0 9 25 13 rect 29 9 54 13 rect 0 2 16 6 @@ -139,12 +143,14 @@ rect 48 0 52 34 << comment >> rect 0 0 54 72 << labels >> -rlabel metal1 27 4 27 4 1 wl1 -rlabel psubstratepcontact 27 11 27 11 1 gnd -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 72 19 72 5 vdd -rlabel metal1 19 65 19 65 1 wl0 +rlabel metal1 27 4 27 4 4 wl1 +rlabel psubstratepcontact 27 11 27 11 4 gnd +rlabel metal2 4 7 4 7 4 bl0 +rlabel metal2 50 7 50 7 4 br0 +rlabel metal1 19 65 19 65 4 wl0 +rlabel metal2 11 7 11 7 4 bl1 +rlabel metal2 43 7 43 7 4 br1 +rlabel metal1 18 72 18 72 1 vdd +<< properties >> +string path 0.000 0.000 243.000 0.000 243.000 324.000 0.000 324.000 0.000 0.000 << end >> diff --git a/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag b/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag index 48a3f4c1..a7387b7e 100644 --- a/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag +++ b/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag @@ -1,6 +1,6 @@ magic tech scmos -timestamp 1558915332 +timestamp 1558933826 << nwell >> rect 0 48 54 77 << pwell >> @@ -22,8 +22,10 @@ rect 13 34 14 38 rect 16 34 17 38 rect 21 34 22 38 rect 17 30 22 34 -rect 24 30 25 38 -rect 29 30 30 38 +rect 24 36 30 38 +rect 24 32 25 36 +rect 29 32 30 36 +rect 24 30 30 32 rect 32 34 33 38 rect 37 34 38 38 rect 40 34 41 38 @@ -31,8 +33,10 @@ rect 32 30 37 34 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 24 22 30 23 +rect 24 18 25 22 +rect 29 18 30 22 +rect 24 17 30 18 rect 32 17 38 23 rect 40 21 45 23 rect 40 17 41 21 @@ -44,11 +48,11 @@ rect 32 56 33 59 << ndcontact >> rect 9 34 13 38 rect 17 34 21 38 -rect 25 30 29 38 +rect 25 32 29 36 rect 33 34 37 38 rect 41 34 45 38 rect 9 17 13 21 -rect 25 17 29 23 +rect 25 18 29 22 rect 41 17 45 21 << pdcontact >> rect 17 56 21 60 @@ -57,17 +61,17 @@ rect 33 56 37 60 << psubstratepcontact >> rect 25 9 29 13 << nsubstratencontact >> -rect 25 70 29 74 +rect 37 70 41 74 << polysilicon >> rect 22 59 24 62 rect 30 59 32 62 rect 22 45 24 56 rect 30 53 32 56 -rect 13 41 16 45 +rect 13 41 16 43 rect 14 38 16 41 rect 22 38 24 41 rect 30 38 32 49 -rect 38 41 41 45 +rect 38 41 41 43 rect 38 38 40 41 rect 14 32 16 34 rect 38 32 40 34 @@ -88,27 +92,27 @@ rect 12 24 16 28 rect 38 24 42 28 << metal1 >> rect 0 70 25 74 -rect 29 70 54 74 +rect 29 70 37 74 +rect 41 70 54 74 rect 0 63 54 67 -rect 6 45 10 63 +rect 9 45 13 63 rect 16 56 17 60 rect 29 56 33 60 rect 37 56 38 60 rect 16 53 20 56 rect 16 49 28 53 -rect 6 41 9 45 rect 16 38 19 49 rect 35 45 38 56 -rect 44 45 48 63 rect 26 41 38 45 -rect 45 41 48 45 +rect 41 45 45 63 rect 35 38 38 41 rect 6 34 9 38 rect 16 34 17 38 +rect 25 36 29 38 rect 37 34 38 38 rect 45 34 48 38 -rect 25 23 29 30 -rect 25 13 29 17 +rect 25 22 29 32 +rect 25 13 29 18 rect 0 9 25 13 rect 29 9 54 13 rect 0 2 16 6 @@ -140,12 +144,14 @@ rect 48 0 52 34 << comment >> rect 0 0 54 72 << labels >> -rlabel metal1 27 4 27 4 1 wl1 -rlabel psubstratepcontact 27 11 27 11 1 gnd -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 72 19 72 5 vdd -rlabel metal1 19 65 19 65 1 wl0 +rlabel metal1 27 4 27 4 4 wl1 +rlabel psubstratepcontact 27 11 27 11 4 gnd +rlabel metal2 4 7 4 7 4 bl0 +rlabel metal2 50 7 50 7 4 br0 +rlabel metal1 19 65 19 65 4 wl0 +rlabel metal2 11 7 11 7 4 bl1 +rlabel metal2 43 7 43 7 4 br1 +rlabel metal1 18 72 18 72 1 vdd +<< properties >> +string path 0.000 0.000 243.000 0.000 243.000 324.000 0.000 324.000 0.000 0.000 << end >> diff --git a/technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag b/technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag index 48a3f4c1..a7387b7e 100644 --- a/technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag +++ b/technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag @@ -1,6 +1,6 @@ magic tech scmos -timestamp 1558915332 +timestamp 1558933826 << nwell >> rect 0 48 54 77 << pwell >> @@ -22,8 +22,10 @@ rect 13 34 14 38 rect 16 34 17 38 rect 21 34 22 38 rect 17 30 22 34 -rect 24 30 25 38 -rect 29 30 30 38 +rect 24 36 30 38 +rect 24 32 25 36 +rect 29 32 30 36 +rect 24 30 30 32 rect 32 34 33 38 rect 37 34 38 38 rect 40 34 41 38 @@ -31,8 +33,10 @@ rect 32 30 37 34 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 24 22 30 23 +rect 24 18 25 22 +rect 29 18 30 22 +rect 24 17 30 18 rect 32 17 38 23 rect 40 21 45 23 rect 40 17 41 21 @@ -44,11 +48,11 @@ rect 32 56 33 59 << ndcontact >> rect 9 34 13 38 rect 17 34 21 38 -rect 25 30 29 38 +rect 25 32 29 36 rect 33 34 37 38 rect 41 34 45 38 rect 9 17 13 21 -rect 25 17 29 23 +rect 25 18 29 22 rect 41 17 45 21 << pdcontact >> rect 17 56 21 60 @@ -57,17 +61,17 @@ rect 33 56 37 60 << psubstratepcontact >> rect 25 9 29 13 << nsubstratencontact >> -rect 25 70 29 74 +rect 37 70 41 74 << polysilicon >> rect 22 59 24 62 rect 30 59 32 62 rect 22 45 24 56 rect 30 53 32 56 -rect 13 41 16 45 +rect 13 41 16 43 rect 14 38 16 41 rect 22 38 24 41 rect 30 38 32 49 -rect 38 41 41 45 +rect 38 41 41 43 rect 38 38 40 41 rect 14 32 16 34 rect 38 32 40 34 @@ -88,27 +92,27 @@ rect 12 24 16 28 rect 38 24 42 28 << metal1 >> rect 0 70 25 74 -rect 29 70 54 74 +rect 29 70 37 74 +rect 41 70 54 74 rect 0 63 54 67 -rect 6 45 10 63 +rect 9 45 13 63 rect 16 56 17 60 rect 29 56 33 60 rect 37 56 38 60 rect 16 53 20 56 rect 16 49 28 53 -rect 6 41 9 45 rect 16 38 19 49 rect 35 45 38 56 -rect 44 45 48 63 rect 26 41 38 45 -rect 45 41 48 45 +rect 41 45 45 63 rect 35 38 38 41 rect 6 34 9 38 rect 16 34 17 38 +rect 25 36 29 38 rect 37 34 38 38 rect 45 34 48 38 -rect 25 23 29 30 -rect 25 13 29 17 +rect 25 22 29 32 +rect 25 13 29 18 rect 0 9 25 13 rect 29 9 54 13 rect 0 2 16 6 @@ -140,12 +144,14 @@ rect 48 0 52 34 << comment >> rect 0 0 54 72 << labels >> -rlabel metal1 27 4 27 4 1 wl1 -rlabel psubstratepcontact 27 11 27 11 1 gnd -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 72 19 72 5 vdd -rlabel metal1 19 65 19 65 1 wl0 +rlabel metal1 27 4 27 4 4 wl1 +rlabel psubstratepcontact 27 11 27 11 4 gnd +rlabel metal2 4 7 4 7 4 bl0 +rlabel metal2 50 7 50 7 4 br0 +rlabel metal1 19 65 19 65 4 wl0 +rlabel metal2 11 7 11 7 4 bl1 +rlabel metal2 43 7 43 7 4 br1 +rlabel metal1 18 72 18 72 1 vdd +<< properties >> +string path 0.000 0.000 243.000 0.000 243.000 324.000 0.000 324.000 0.000 0.000 << end >> diff --git a/technology/scn3me_subm/mag_lib/setup.tcl b/technology/scn3me_subm/mag_lib/setup.tcl index af55a416..01639fe2 100644 --- a/technology/scn3me_subm/mag_lib/setup.tcl +++ b/technology/scn3me_subm/mag_lib/setup.tcl @@ -4,10 +4,12 @@ equate class {-circuit1 nfet} {-circuit2 n} equate class {-circuit1 pfet} {-circuit2 p} # This circuit has symmetries and needs to be flattened to resolve them # or the banks won't pass -flatten class {-circuit1 precharge_array_1} -flatten class {-circuit1 precharge_array_2} -flatten class {-circuit1 precharge_array_3} -flatten class {-circuit1 precharge_array_4} +flatten class {-circuit1 bitcell_array_0} +flatten class {-circuit1 bitcell_array_1} +#flatten class {-circuit1 precharge_array_0} +#flatten class {-circuit1 precharge_array_1} +#flatten class {-circuit1 precharge_array_2} +#flatten class {-circuit1 precharge_array_3} property {-circuit1 nfet} remove as ad ps pd property {-circuit1 pfet} remove as ad ps pd property {-circuit2 n} remove as ad ps pd diff --git a/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp b/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp index 37f25f75..f58867a7 100644 --- a/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp +++ b/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp @@ -1,14 +1,14 @@ .SUBCKT cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd -MM9 RA_to_R_right wl1 br1 gnd n w=1.2u l=0.4u -MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u -MM7 RA_to_R_left Q_bar gnd gnd n w=1.2u l=0.4u -MM6 RA_to_R_left wl1 bl1 gnd n w=1.2u l=0.4u -MM5 Q wl0 bl0 gnd n w=0.8u l=0.4u -MM4 Q_bar wl0 br0 gnd n w=0.8u l=0.4u -MM1 Q Q_bar gnd gnd n w=1.6u l=0.4u -MM0 Q_bar Q gnd gnd n w=1.6u l=0.4u -MM3 Q Q_bar vdd vdd p w=0.6u l=0.4u -MM2 Q_bar Q vdd vdd p w=0.6u l=0.4u +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left Q_bar gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 Q_bar wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q Q_bar gnd gnd n w=2.4u l=0.6u +MM0 Q_bar Q gnd gnd n w=2.4u l=0.6u +MM3 Q Q_bar vdd vdd p w=0.9u l=0.6u +MM2 Q_bar Q vdd vdd p w=0.9u l=0.6u .ENDS diff --git a/technology/scn3me_subm/sp_lib/cell_1w_1r.sp b/technology/scn3me_subm/sp_lib/cell_1w_1r.sp index b40f589a..fe981d6d 100644 --- a/technology/scn3me_subm/sp_lib/cell_1w_1r.sp +++ b/technology/scn3me_subm/sp_lib/cell_1w_1r.sp @@ -1,14 +1,14 @@ .SUBCKT cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd -MM9 RA_to_R_right wl1 br1 gnd n w=1.2u l=0.4u -MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u -MM7 RA_to_R_left Q_bar gnd gnd n w=1.2u l=0.4u -MM6 RA_to_R_left wl1 bl1 gnd n w=1.2u l=0.4u -MM5 Q wl0 bl0 gnd n w=0.8u l=0.4u -MM4 Q_bar wl0 br0 gnd n w=0.8u l=0.4u -MM1 Q Q_bar gnd gnd n w=1.6u l=0.4u -MM0 Q_bar Q gnd gnd n w=1.6u l=0.4u -MM3 Q Q_bar vdd vdd p w=0.6u l=0.4u -MM2 Q_bar Q vdd vdd p w=0.6u l=0.4u +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left Q_bar gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 Q_bar wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q Q_bar gnd gnd n w=2.4u l=0.6u +MM0 Q_bar Q gnd gnd n w=2.4u l=0.6u +MM3 Q Q_bar vdd vdd p w=0.9u l=0.6u +MM2 Q_bar Q vdd vdd p w=0.9u l=0.6u .ENDS diff --git a/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp b/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp index 94bdb75e..a8654c83 100644 --- a/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp +++ b/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp @@ -1,14 +1,14 @@ .SUBCKT replica_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd -MM9 RA_to_R_right wl1 br1 gnd n w=1.2u l=0.4u -MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u -MM7 RA_to_R_left vdd gnd gnd n w=1.2u l=0.4u -MM6 RA_to_R_left wl1 bl1 gnd n w=1.2u l=0.4u -MM5 Q wl0 bl0 gnd n w=0.8u l=0.4u -MM4 vdd wl0 br0 gnd n w=0.8u l=0.4u -MM1 Q vdd gnd gnd n w=1.6u l=0.4u -MM0 vdd Q gnd gnd n w=1.6u l=0.4u -MM3 Q vdd vdd vdd p w=0.6u l=0.4u -MM2 vdd Q vdd vdd p w=0.6u l=0.4u +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left vdd gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 vdd wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q vdd gnd gnd n w=2.4u l=0.6u +MM0 vdd Q gnd gnd n w=2.4u l=0.6u +MM3 Q vdd vdd vdd p w=0.9u l=0.6u +MM2 vdd Q vdd vdd p w=0.9u l=0.6u .ENDS diff --git a/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp b/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp index 6c2d3c1b..5b9c9b18 100644 --- a/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp +++ b/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp @@ -1,14 +1,14 @@ .SUBCKT replica_cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd -MM9 RA_to_R_right wl1 br1 gnd n w=1.2u l=0.4u -MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u -MM7 RA_to_R_left vdd gnd gnd n w=1.2u l=0.4u -MM6 RA_to_R_left wl1 bl1 gnd n w=1.2u l=0.4u -MM5 Q wl0 bl0 gnd n w=0.8u l=0.4u -MM4 vdd wl0 br0 gnd n w=0.8u l=0.4u -MM1 Q vdd gnd gnd n w=1.6u l=0.4u -MM0 vdd Q gnd gnd n w=1.6u l=0.4u -MM3 Q vdd vdd vdd p w=0.6u l=0.4u -MM2 vdd Q vdd vdd p w=0.6u l=0.4u +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left vdd gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 vdd wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q vdd gnd gnd n w=2.4u l=0.6u +MM0 vdd Q gnd gnd n w=2.4u l=0.6u +MM3 Q vdd vdd vdd p w=0.9u l=0.6u +MM2 vdd Q vdd vdd p w=0.9u l=0.6u .ENDS diff --git a/technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech b/technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech index be511001..bc447205 100644 --- a/technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech +++ b/technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech @@ -1,10 +1,10 @@ tech - format 32 + format 29 scmos end version - version 2002a + version 2001a description "SCMOS: Submit as technology.lambda: SCN3ME_SUBM.30 [to process: AMIc5]" end @@ -34,8 +34,7 @@ types select nselect,ns select pselect,ps cap electrode,poly2,el,p2 - cap electrodecontact,poly2contact,poly2c,p2c,elc - cap p2m12contact,p2m12c + metal1 electrodecontact,poly2contact,poly2c,p2c,elc cap electrodecap,ecap,poly2cap,p2cap,pcap contact genericpoly2contact,gc2 active ntransistor,nfet @@ -104,12 +103,7 @@ contact psc psd metal1 m2c metal1 metal2 m3c metal2 metal3 - stackable pc m2c pm12contact,pm12c - stackable pdc m2c pdm12contact,pdm12c - stackable psc m2c psm12contact,psm12c,pom12c,pwm12c - stackable ndc m2c ndm12contact,ndm12c - stackable nsc m2c nsm12contact,nsm12c,nom12c,nwm12c - stackable m2c m3c m123contact,m123c + stackable end styles @@ -147,7 +141,6 @@ styles fapm 1 20 21 34 gv1 55 m2contact 20 21 55 - p2m12contact 14 20 21 32 55 metal2 21 rm2 21 48 prm2 48 @@ -218,10 +211,6 @@ compose paint nsc pwell psc paint poly2 poly ecap erase ecap poly poly2 - paint p2c poly2 p2c - paint p2c ecap p2c - paint p2m12c poly2 p2m12c - paint p2m12c ecap p2m12c paint pad m3 pad compose phr poly2 hr paint hr poly2 phr @@ -246,18 +235,15 @@ end connect nwell,nsc/a,nsd nwell,nsc/a,nsd pwell,psc/a,psd pwell,psc/a,psd - m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 + m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 m2,fm2,fapm,m2c/m2,m3c/m2,m3c/m2 m2,fm2,fapm,m2c/m2,m3c/m2,m3c/m2 m3,fm3,fapm,m3c/m3 m3,fm3,fapm,m3c/m3 ndiff,ndc/a,pdiff,pdc/a ndiff,ndc/a,pdiff,pdc/a poly,fp,nfet,pfet,fet,fapm,pc/a poly,fp,nfet,pfet,fet,fapm,pc/a + poly2,ecap,p2c poly2,ecap,p2c gc2 poly2,ecap,metal1 - p2c poly2,ecap,m1,fm1,fapm,m2c/m1 - p2m12c poly2,ecap,m1,fm1,fapm,m2c/m1,m2,fm2,fapm,m2c/m2,m3c/m2 - poly2,ecap,p2c,p2m12c poly2,ecap,p2c,p2m12c - gc2 poly2,ecap,m1,fm1,fapm,m2c/m1 gc poly,fp,ndiff,pdiff,nsd,psd,m1,fm1,fapm,m2c/m1 - gv1 m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2,fm2,fapm,m3c/m2 + gv1 m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2,fm2,fapm,m3c/m2 gv2 m2,fm2,fapm,m2c/m2,m3c/m2,m3,fm3,fapm pad m1,fm1,m2,fm2,m3,fm3 rm1 prm1 @@ -275,12 +261,8 @@ cifoutput style lambda=0.30(p) scalefactor 30 15 + options calma-permissive-labels - # This is a custom section to add bounding boxes in OpenRAM - layer BB bb - labels bb - calma 63 0 - layer CWN nwell,rnw bloat-or pdiff,rpd,pdc/a,pfet * 180 bloat-or nsd,nsc/a * 90 @@ -377,7 +359,7 @@ style lambda=0.30(p) squares 0 60 90 calma 55 0 - layer CCE p2c,p2m12c + layer CCE p2c squares 30 60 90 calma 55 0 @@ -389,7 +371,7 @@ style lambda=0.30(p) squares 0 60 90 calma 25 0 - layer CV1 m2c/m1,p2m12c + layer CV1 m2c/m1 squares 30 60 90 calma 50 0 @@ -431,12 +413,12 @@ style lambda=0.30(p) layer CM1 pad calma 49 0 - layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c - labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 calma 49 0 - layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c - labels m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2 + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2 calma 51 0 layer CMFP m1p @@ -527,8 +509,8 @@ style lambda=0.30(p) labels hr,phr calma 34 0 - layer CEL poly2,ecap,phr,p2c,p2m12c - labels poly2,ecap,phr,p2c,p2m12c + layer CEL poly2,ecap,phr,p2c + labels poly2,ecap,phr,p2c calma 56 0 #CRE/CRM @@ -559,8 +541,8 @@ style lambda=0.30(p) #CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 #CRE/CRM calma 70 0 - layer CX comment - labels comment + layer CX comment,bb + labels comment,bb calma 63 0 layer XP pad,xp @@ -606,9 +588,9 @@ style fapm-boxes scalefactor 30 15 - templayer CRIT fapm,fn,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet,poly,rp,nfet,pfet,fet,pc/a,poly2,ecap,phr,p2c,p2m12c - or fm1,m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c - or fm2,m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + templayer CRIT fapm,fn,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet,poly,rp,nfet,pfet,fet,pc/a,poly2,ecap,phr,p2c + or fm1,m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + or fm2,m2,rm2,m2c/m2,m3c/m2,m3c/m2 or fm3,m3,rm3,m3c/m3 or glass,pad grow 510 @@ -631,9 +613,9 @@ style fapm-stripes # and then *replacing* the left side (1-lambda wide) stripe of each 'fa' box # to be a 1-lambda wide layer 'fb' box -- else you won't get strips! - templayer CRIT fapm,fn,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet,poly,rp,nfet,pfet,fet,pc/a,poly2,ecap,phr,p2c,p2m12c - or fm1,m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c - or fm2,m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + templayer CRIT fapm,fn,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet,poly,rp,nfet,pfet,fet,pc/a,poly2,ecap,phr,p2c + or fm1,m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + or fm2,m2,rm2,m2c/m2,m3c/m2,m3c/m2 or fm3,m3,rm3,m3c/m3 or glass,pad grow 510 @@ -754,7 +736,7 @@ style lambda=0.30(cp) squares 0 60 90 calma 25 0 - layer CCC p2c,p2m12c + layer CCC p2c squares 30 60 90 calma 25 0 @@ -766,7 +748,7 @@ style lambda=0.30(cp) squares 0 60 90 calma 25 0 - layer CV1 m2c/m1,p2m12c + layer CV1 m2c/m1 squares 30 60 90 calma 50 0 @@ -808,12 +790,12 @@ style lambda=0.30(cp) layer CM1 pad calma 49 0 - layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c - labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 calma 49 0 - layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c - labels m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2 + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2 calma 51 0 layer CMFP m1p @@ -904,8 +886,8 @@ style lambda=0.30(cp) labels hr,phr calma 34 0 - layer CEL poly2,ecap,phr,p2c,p2m12c - labels poly2,ecap,phr,p2c,p2m12c + layer CEL poly2,ecap,phr,p2c + labels poly2,ecap,phr,p2c calma 56 0 #CRE/CRM @@ -936,8 +918,8 @@ style lambda=0.30(cp) #CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 #CRE/CRM calma 70 0 - layer CX comment - labels comment + layer CX comment,bb + labels comment,bb calma 63 0 layer XP pad,xp @@ -1034,7 +1016,7 @@ style lambda=0.30(c) squares 0 60 90 calma 25 0 - layer CCC p2c,p2m12c + layer CCC p2c squares 30 60 90 calma 25 0 @@ -1046,7 +1028,7 @@ style lambda=0.30(c) squares 0 60 90 calma 25 0 - layer CV1 m2c/m1,p2m12c + layer CV1 m2c/m1 squares 30 60 90 calma 50 0 @@ -1088,12 +1070,12 @@ style lambda=0.30(c) layer CM1 pad calma 49 0 - layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c - labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 calma 49 0 - layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c - labels m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2 + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2 calma 51 0 layer CMFP m1p @@ -1184,8 +1166,8 @@ style lambda=0.30(c) labels hr,phr calma 34 0 - layer CEL poly2,ecap,phr,p2c,p2m12c - labels poly2,ecap,phr,p2c,p2m12c + layer CEL poly2,ecap,phr,p2c + labels poly2,ecap,phr,p2c calma 56 0 #CRE/CRM @@ -1216,8 +1198,8 @@ style lambda=0.30(c) #CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 #CRE/CRM calma 70 0 - layer CX comment - labels comment + layer CX comment,bb + labels comment,bb calma 63 0 layer XP pad,xp @@ -1314,7 +1296,7 @@ style lambda=0.30() squares 0 60 90 calma 55 0 - layer CCE p2c,p2m12c + layer CCE p2c squares 30 60 90 calma 55 0 @@ -1326,7 +1308,7 @@ style lambda=0.30() squares 0 60 90 calma 25 0 - layer CV1 m2c/m1,p2m12c + layer CV1 m2c/m1 squares 30 60 90 calma 50 0 @@ -1368,12 +1350,12 @@ style lambda=0.30() layer CM1 pad calma 49 0 - layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c - labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1,p2c,p2m12c + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 calma 49 0 - layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c - labels m2,rm2,m2c/m2,m3c/m2,m3c/m2,p2m12c + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2 + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2 calma 51 0 layer CMFP m1p @@ -1464,8 +1446,8 @@ style lambda=0.30() labels hr,phr calma 34 0 - layer CEL poly2,ecap,phr,p2c,p2m12c - labels poly2,ecap,phr,p2c,p2m12c + layer CEL poly2,ecap,phr,p2c + labels poly2,ecap,phr,p2c calma 56 0 #CRE/CRM @@ -1496,8 +1478,8 @@ style lambda=0.30() #CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 #CRE/CRM calma 70 0 - layer CX comment - labels comment + layer CX comment,bb + labels comment,bb calma 63 0 layer XP pad,xp @@ -1514,7 +1496,7 @@ style lambda=0.30(p) # This is a custom section to add bounding boxes in OpenRAM layer bb BB labels BB - calma 63 0 + calma BB 63 0 layer nwell CWN and-not CWNR @@ -1721,7 +1703,6 @@ layer nwell CWN layer ndc CAA and CSN and CCA - and-not CV1 and-not CWNR and-not CTA @@ -1735,7 +1716,6 @@ layer nwell CWN layer ndc CAA and CSN and CCC - and-not CV1 and-not CWNR and-not CTA @@ -1749,7 +1729,6 @@ layer nwell CWN layer nsc CAA and CSN and CCA - and-not CV1 and-not CWNR and-not CTA @@ -1763,7 +1742,6 @@ layer nwell CWN layer nsc CAA and CSN and CCC - and-not CV1 and-not CWNR and-not CTA @@ -1777,7 +1755,6 @@ layer nwell CWN layer pdc CAA and CSP and CCA - and-not CV1 and-not CTA and-not CPS @@ -1791,7 +1768,6 @@ layer nwell CWN layer pdc CAA and CSP and CCC - and-not CV1 and-not CTA and-not CPS @@ -1805,7 +1781,6 @@ layer nwell CWN layer psc CAA and CSP and CCA - and-not CV1 and-not CTA and-not CPS @@ -1819,128 +1794,6 @@ layer nwell CWN layer psc CAA and CSP and CCC - and-not CV1 - and-not CWNR - and-not CTA - - and-not CPS - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer ndc CAA - and CSN - and CCA - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer ndc CAA - and CSN - and CCC - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer nsc CAA - and CSN - and CCA - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer nsc CAA - and CSN - and CCC - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer pdc CAA - and CSP - and CCA - and CV1 - and CV2 - and-not CTA - - and-not CPS - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer pdc CAA - and CSP - and CCC - and CV1 - and CV2 - and-not CTA - - and-not CPS - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer psc CAA - and CSP - and CCA - and CV1 - and CV2 - and-not CTA - - and-not CPS - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer psc CAA - and CSP - and CCC - and CV1 - and CV2 and-not CWNR and-not CTA @@ -1971,7 +1824,6 @@ layer nwell CWN calma CRG 67 * layer pc CCP - and-not CV1 and CPG and-not CPC and-not CEL @@ -1983,7 +1835,6 @@ layer nwell CWN calma CCP 47 * layer pc CCC - and-not CV1 and CPG and-not CPC and-not CEL @@ -1994,82 +1845,6 @@ layer nwell CWN shrink 15 calma CCC 25 * - layer pc CCP - and CV1 - and CV2 - and CPG - and-not CPC - and-not CEL - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCP 47 * - - layer pc CCC - and CV1 - and CV2 - and CPG - and-not CPC - and-not CEL - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - - layer p2c CCE - and-not CV1 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCE 55 * - - layer p2c CCC - and-not CV1 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - - layer p2c CCE - and CV1 - and CV2 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCE 55 * - - layer p2c CCC - and CV1 - and CV2 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - layer gc CCP and-not CPG and-not CPC @@ -2134,11 +1909,6 @@ layer nwell CWN calma CV2 61 * layer m2c CV1 - and-not CV2 - and-not CCC - and-not CCE - and-not CCP - and-not CCA and-not XP grow 30 and CM2 @@ -2147,32 +1917,6 @@ layer nwell CWN shrink 15 calma CV1 50 * - - - layer p2m12c CV1 - and-not CV2 - and CCE - grow 30 - and CM2 - and CM1 - and CPG - and CEL - grow 15 - shrink 15 - calma CV1 50 * - - layer p2m12c CV1 - and-not CV2 - and CCC - grow 30 - and CM2 - and CM1 - and CPG - and CEL - grow 15 - shrink 15 - calma CV1 50 * - layer m1 CM1 and-not CRM and-not CRF @@ -2219,14 +1963,6 @@ layer nwell CWN labels CMSP calma CMSP 82 * - - - - - - - - layer fp 100 calma 100 100 * @@ -2249,8 +1985,6 @@ layer nwell CWN calma 110 110 * layer m3c CV2 - - and-not CV1 and-not XP grow 30 and CM3 @@ -2259,7 +1993,6 @@ layer nwell CWN shrink 15 calma CV2 61 * - layer m3 CM3 and-not CRM and-not CRT @@ -2329,6 +2062,20 @@ layer nwell CWN and-not CRE calma CRG2 68 * + layer elc CCE + grow 30 + and CM1 + and CEL + labels CM1 + calma CCE 55 * + + layer elc CCC + grow 30 + and CM1 + and CEL + labels CM1 + calma CCC 25 * + layer comment CX labels CX calma CX 63 * @@ -2348,6 +2095,11 @@ layer nwell CWN style lambda=0.30(s) scalefactor 30 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -2554,7 +2306,6 @@ style lambda=0.30(s) layer ndc CAA and CSN and CCA - and-not CV1 and-not CWNR and-not CTA @@ -2568,7 +2319,6 @@ style lambda=0.30(s) layer ndc CAA and CSN and CCC - and-not CV1 and-not CWNR and-not CTA @@ -2582,7 +2332,6 @@ style lambda=0.30(s) layer nsc CAA and CSN and CCA - and-not CV1 and-not CWNR and-not CTA @@ -2596,7 +2345,6 @@ style lambda=0.30(s) layer nsc CAA and CSN and CCC - and-not CV1 and-not CWNR and-not CTA @@ -2610,7 +2358,6 @@ style lambda=0.30(s) layer pdc CAA and CSP and CCA - and-not CV1 and-not CTA and-not CPS @@ -2624,7 +2371,6 @@ style lambda=0.30(s) layer pdc CAA and CSP and CCC - and-not CV1 and-not CTA and-not CPS @@ -2638,7 +2384,6 @@ style lambda=0.30(s) layer psc CAA and CSP and CCA - and-not CV1 and-not CTA and-not CPS @@ -2652,128 +2397,6 @@ style lambda=0.30(s) layer psc CAA and CSP and CCC - and-not CV1 - and-not CWNR - and-not CTA - - and-not CPS - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer ndc CAA - and CSN - and CCA - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer ndc CAA - and CSN - and CCC - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer nsc CAA - and CSN - and CCA - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer nsc CAA - and CSN - and CCC - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer pdc CAA - and CSP - and CCA - and CV1 - and CV2 - and-not CTA - - and-not CPS - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer pdc CAA - and CSP - and CCC - and CV1 - and CV2 - and-not CTA - - and-not CPS - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer psc CAA - and CSP - and CCA - and CV1 - and CV2 - and-not CTA - - and-not CPS - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer psc CAA - and CSP - and CCC - and CV1 - and CV2 and-not CWNR and-not CTA @@ -2804,7 +2427,6 @@ style lambda=0.30(s) calma CRG 67 * layer pc CCP - and-not CV1 and CPG and-not CPC and-not CEL @@ -2816,7 +2438,6 @@ style lambda=0.30(s) calma CCP 47 * layer pc CCC - and-not CV1 and CPG and-not CPC and-not CEL @@ -2827,82 +2448,6 @@ style lambda=0.30(s) shrink 15 calma CCC 25 * - layer pc CCP - and CV1 - and CV2 - and CPG - and-not CPC - and-not CEL - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCP 47 * - - layer pc CCC - and CV1 - and CV2 - and CPG - and-not CPC - and-not CEL - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - - layer p2c CCE - and-not CV1 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCE 55 * - - layer p2c CCC - and-not CV1 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - - layer p2c CCE - and CV1 - and CV2 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCE 55 * - - layer p2c CCC - and CV1 - and CV2 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - layer gc CCP and-not CPG and-not CPC @@ -2967,11 +2512,6 @@ style lambda=0.30(s) calma CV2 61 * layer m2c CV1 - and-not CV2 - and-not CCC - and-not CCE - and-not CCP - and-not CCA and-not XP grow 30 and CM2 @@ -2980,32 +2520,6 @@ style lambda=0.30(s) shrink 15 calma CV1 50 * - - - layer p2m12c CV1 - and-not CV2 - and CCE - grow 30 - and CM2 - and CM1 - and CPG - and CEL - grow 15 - shrink 15 - calma CV1 50 * - - layer p2m12c CV1 - and-not CV2 - and CCC - grow 30 - and CM2 - and CM1 - and CPG - and CEL - grow 15 - shrink 15 - calma CV1 50 * - layer m1 CM1 and-not CRM and-not CRF @@ -3052,14 +2566,6 @@ style lambda=0.30(s) labels CMSP calma CMSP 82 * - - - - - - - - layer fp 100 calma 100 100 * @@ -3082,8 +2588,6 @@ style lambda=0.30(s) calma 110 110 * layer m3c CV2 - - and-not CV1 and-not XP grow 30 and CM3 @@ -3092,7 +2596,6 @@ style lambda=0.30(s) shrink 15 calma CV2 61 * - layer m3 CM3 and-not CRM and-not CRT @@ -3162,6 +2665,20 @@ style lambda=0.30(s) and-not CRE calma CRG2 68 * + layer elc CCE + grow 30 + and CM1 + and CEL + labels CM1 + calma CCE 55 * + + layer elc CCC + grow 30 + and CM1 + and CEL + labels CM1 + calma CCC 25 * + layer comment CX labels CX calma CX 63 * @@ -3181,6 +2698,11 @@ style lambda=0.30(s) style lambda=0.30(ps) scalefactor 30 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -3388,7 +2910,6 @@ style lambda=0.30(ps) layer ndc CAA and CSN and CCA - and-not CV1 and-not CWNR and-not CTA @@ -3402,7 +2923,6 @@ style lambda=0.30(ps) layer ndc CAA and CSN and CCC - and-not CV1 and-not CWNR and-not CTA @@ -3416,7 +2936,6 @@ style lambda=0.30(ps) layer nsc CAA and CSN and CCA - and-not CV1 and-not CWNR and-not CTA @@ -3430,7 +2949,6 @@ style lambda=0.30(ps) layer nsc CAA and CSN and CCC - and-not CV1 and-not CWNR and-not CTA @@ -3444,7 +2962,6 @@ style lambda=0.30(ps) layer pdc CAA and CSP and CCA - and-not CV1 and-not CTA and-not CPS @@ -3458,7 +2975,6 @@ style lambda=0.30(ps) layer pdc CAA and CSP and CCC - and-not CV1 and-not CTA and-not CPS @@ -3472,7 +2988,6 @@ style lambda=0.30(ps) layer psc CAA and CSP and CCA - and-not CV1 and-not CTA and-not CPS @@ -3486,128 +3001,6 @@ style lambda=0.30(ps) layer psc CAA and CSP and CCC - and-not CV1 - and-not CWNR - and-not CTA - - and-not CPS - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer ndc CAA - and CSN - and CCA - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer ndc CAA - and CSN - and CCC - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer nsc CAA - and CSN - and CCA - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer nsc CAA - and CSN - and CCC - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer pdc CAA - and CSP - and CCA - and CV1 - and CV2 - and-not CTA - - and-not CPS - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer pdc CAA - and CSP - and CCC - and CV1 - and CV2 - and-not CTA - - and-not CPS - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer psc CAA - and CSP - and CCA - and CV1 - and CV2 - and-not CTA - - and-not CPS - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer psc CAA - and CSP - and CCC - and CV1 - and CV2 and-not CWNR and-not CTA @@ -3638,7 +3031,6 @@ style lambda=0.30(ps) calma CRG 67 * layer pc CCP - and-not CV1 and CPG and-not CPC and-not CEL @@ -3650,7 +3042,6 @@ style lambda=0.30(ps) calma CCP 47 * layer pc CCC - and-not CV1 and CPG and-not CPC and-not CEL @@ -3661,82 +3052,6 @@ style lambda=0.30(ps) shrink 15 calma CCC 25 * - layer pc CCP - and CV1 - and CV2 - and CPG - and-not CPC - and-not CEL - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCP 47 * - - layer pc CCC - and CV1 - and CV2 - and CPG - and-not CPC - and-not CEL - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - - layer p2c CCE - and-not CV1 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCE 55 * - - layer p2c CCC - and-not CV1 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - - layer p2c CCE - and CV1 - and CV2 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCE 55 * - - layer p2c CCC - and CV1 - and CV2 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - layer gc CCP and-not CPG and-not CPC @@ -3801,11 +3116,6 @@ style lambda=0.30(ps) calma CV2 61 * layer m2c CV1 - and-not CV2 - and-not CCC - and-not CCE - and-not CCP - and-not CCA and-not XP grow 30 and CM2 @@ -3814,32 +3124,6 @@ style lambda=0.30(ps) shrink 15 calma CV1 50 * - - - layer p2m12c CV1 - and-not CV2 - and CCE - grow 30 - and CM2 - and CM1 - and CPG - and CEL - grow 15 - shrink 15 - calma CV1 50 * - - layer p2m12c CV1 - and-not CV2 - and CCC - grow 30 - and CM2 - and CM1 - and CPG - and CEL - grow 15 - shrink 15 - calma CV1 50 * - layer m1 CM1 and-not CRM and-not CRF @@ -3886,14 +3170,6 @@ style lambda=0.30(ps) labels CMSP calma CMSP 82 * - - - - - - - - layer fp 100 calma 100 100 * @@ -3916,8 +3192,6 @@ style lambda=0.30(ps) calma 110 110 * layer m3c CV2 - - and-not CV1 and-not XP grow 30 and CM3 @@ -3926,7 +3200,6 @@ style lambda=0.30(ps) shrink 15 calma CV2 61 * - layer m3 CM3 and-not CRM and-not CRT @@ -3996,6 +3269,20 @@ style lambda=0.30(ps) and-not CRE calma CRG2 68 * + layer elc CCE + grow 30 + and CM1 + and CEL + labels CM1 + calma CCE 55 * + + layer elc CCC + grow 30 + and CM1 + and CEL + labels CM1 + calma CCC 25 * + layer comment CX labels CX calma CX 63 * @@ -4015,6 +3302,11 @@ style lambda=0.30(ps) style lambda=0.30() scalefactor 30 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -4219,7 +3511,6 @@ style lambda=0.30() layer ndc CAA and CSN and CCA - and-not CV1 and-not CWNR and-not CTA @@ -4233,7 +3524,6 @@ style lambda=0.30() layer ndc CAA and CSN and CCC - and-not CV1 and-not CWNR and-not CTA @@ -4247,7 +3537,6 @@ style lambda=0.30() layer nsc CAA and CSN and CCA - and-not CV1 and-not CWNR and-not CTA @@ -4261,7 +3550,6 @@ style lambda=0.30() layer nsc CAA and CSN and CCC - and-not CV1 and-not CWNR and-not CTA @@ -4275,7 +3563,6 @@ style lambda=0.30() layer pdc CAA and CSP and CCA - and-not CV1 and-not CTA and-not CPS @@ -4289,7 +3576,6 @@ style lambda=0.30() layer pdc CAA and CSP and CCC - and-not CV1 and-not CTA and-not CPS @@ -4303,7 +3589,6 @@ style lambda=0.30() layer psc CAA and CSP and CCA - and-not CV1 and-not CTA and-not CPS @@ -4317,128 +3602,6 @@ style lambda=0.30() layer psc CAA and CSP and CCC - and-not CV1 - and-not CWNR - and-not CTA - - and-not CPS - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer ndc CAA - and CSN - and CCA - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer ndc CAA - and CSN - and CCC - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer nsc CAA - and CSN - and CCA - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer nsc CAA - and CSN - and CCC - and CV1 - and CV2 - and-not CWNR - and-not CTA - - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer pdc CAA - and CSP - and CCA - and CV1 - and CV2 - and-not CTA - - and-not CPS - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer pdc CAA - and CSP - and CCC - and CV1 - and CV2 - and-not CTA - - and-not CPS - and CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCC 25 * - - layer psc CAA - and CSP - and CCA - and CV1 - and CV2 - and-not CTA - - and-not CPS - and-not CWN - and CM1 - grow 30 - grow 15 - shrink 15 - calma CCA 48 * - - layer psc CAA - and CSP - and CCC - and CV1 - and CV2 and-not CWNR and-not CTA @@ -4469,7 +3632,6 @@ style lambda=0.30() calma CRG 67 * layer pc CCP - and-not CV1 and CPG and-not CPC and-not CEL @@ -4481,7 +3643,6 @@ style lambda=0.30() calma CCP 47 * layer pc CCC - and-not CV1 and CPG and-not CPC and-not CEL @@ -4492,82 +3653,6 @@ style lambda=0.30() shrink 15 calma CCC 25 * - layer pc CCP - and CV1 - and CV2 - and CPG - and-not CPC - and-not CEL - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCP 47 * - - layer pc CCC - and CV1 - and CV2 - and CPG - and-not CPC - and-not CEL - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - - layer p2c CCE - and-not CV1 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCE 55 * - - layer p2c CCC - and-not CV1 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - - layer p2c CCE - and CV1 - and CV2 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCE 55 * - - layer p2c CCC - and CV1 - and CV2 - and CPG - and CEL - and-not CPC - and-not CAA - grow 30 - and CM1 - grow 15 - shrink 15 - calma CCC 25 * - layer gc CCP and-not CPG and-not CPC @@ -4632,11 +3717,6 @@ style lambda=0.30() calma CV2 61 * layer m2c CV1 - and-not CV2 - and-not CCC - and-not CCE - and-not CCP - and-not CCA and-not XP grow 30 and CM2 @@ -4645,32 +3725,6 @@ style lambda=0.30() shrink 15 calma CV1 50 * - - - layer p2m12c CV1 - and-not CV2 - and CCE - grow 30 - and CM2 - and CM1 - and CPG - and CEL - grow 15 - shrink 15 - calma CV1 50 * - - layer p2m12c CV1 - and-not CV2 - and CCC - grow 30 - and CM2 - and CM1 - and CPG - and CEL - grow 15 - shrink 15 - calma CV1 50 * - layer m1 CM1 and-not CRM and-not CRF @@ -4717,14 +3771,6 @@ style lambda=0.30() labels CMSP calma CMSP 82 * - - - - - - - - layer fp 100 calma 100 100 * @@ -4747,8 +3793,6 @@ style lambda=0.30() calma 110 110 * layer m3c CV2 - - and-not CV1 and-not XP grow 30 and CM3 @@ -4757,7 +3801,6 @@ style lambda=0.30() shrink 15 calma CV2 61 * - layer m3 CM3 and-not CRM and-not CRT @@ -4827,6 +3870,20 @@ style lambda=0.30() and-not CRE calma CRG2 68 * + layer elc CCE + grow 30 + and CM1 + and CEL + labels CM1 + calma CCE 55 * + + layer elc CCC + grow 30 + and CM1 + and CEL + labels CM1 + calma CCC 25 * + layer comment CX labels CX calma CX 63 * @@ -4846,6 +3903,11 @@ style lambda=0.30() style lambda=0.30(c) scalefactor 30 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -5301,6 +4363,11 @@ style lambda=0.30(c) style lambda=0.30(cs) scalefactor 30 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -5758,6 +4825,11 @@ style lambda=0.30(cs) style lambda=0.30(cps) scalefactor 30 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -6216,6 +5288,11 @@ style lambda=0.30(cps) style lambda=0.30(cp) scalefactor 30 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -6740,27 +5817,22 @@ drc width pc/m1 4 \ "Poly contact width < 4 (Mosis #5.1)" - width gc 2 \ "GC contact width < 2 (Mosis #6.1)" width ndc/m1 4 \ "Diffusion contact width < 4 (Mosis #6.1)" - width nsc/m1 4 \ "Diffusion contact width < 4 (Mosis #6.1)" - width pdc/m1 4 \ "Diffusion contact width < 4 (Mosis #6.1)" - width psc/m1 4 \ "Diffusion contact width < 4 (Mosis #6.1)" - - width m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 3 \ + width m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 3 \ "Metal1 width < 3 (Mosis #7.1)" width gv1 2 \ @@ -6769,22 +5841,13 @@ drc width m2c/m1 4 \ "Metal2 contact width < 4 (Mosis #8.1)" - - - - - - - width p2m12c 4 \ - "Metal2 contact width < 4 (Mosis #8.1)" - - width p2m12c 4 \ - "stacked p2m12c width < 4 (Mosis #8.1)" - width m2,fm2,rm2,m2c/m2,m3c/m2 3 \ "Metal2 width < 3 (Mosis #9.1)" - width poly2,ecap,phr,p2c,p2m12c,p2c,p2m12c 5 \ + width ecap 8 \ + "Ecap width < 8 (Mosis #11.1)" + + width poly2,ecap,phr 5 \ "Poly2 width < 5 (Mosis #11.1)" width gc2 2 \ @@ -6793,16 +5856,12 @@ drc width p2c 4 \ "Poly2 contact width < 4 (Mosis #13.1)" - width p2m12c 4 \ - "Poly2 contact width < 4 (Mosis #13.1)" - width gv2 2 \ "GV2 via width < 2 (Mosis #14.1)" width m3c/m2 4 \ "Metal3 contact width < 4 (Mosis #14.1)" - width m3,fm3,rm3,m3c/m3,pad 5 \ "Metal3 width < 5 (Mosis #15.1)" @@ -6890,7 +5949,7 @@ drc edge4way nfet,pfet,fet space/active,ndiff,rnd,ndc/a,pdiff,rpd,pdc/a 3 ndiff,rnd,ndc/a,pdiff,rpd,pdc/a,nfet,pfet,fet 0 0 \ "N-Diffusion,P-Diffusion overhang of Transistor < 3 (Mosis #3.4)" active - edge4way poly,fp,rp,pc/a ~(poly,fp,rp,pc/a,nfet,pfet,fet,prp)/active 1 space space 1 \ + edge4way poly,fp,rp,pc/a ~(poly,fp,rp,pc/a,nfet,pfet,fet,prp)/active 1 space/a space/a 1 \ "Poly spacing to Diffusion < 1 (Mosis #3.5)" edge4way nfet ~(nfet)/active 3 ~(pselect)/select ~(nfet)/active 3 \ @@ -6977,12 +6036,9 @@ drc spacing gc gc 3 touching_ok \ "Generic contact spacing < 3 (Mosis #5.3)" - edge4way ~(gc)/contact gc 1 ~(ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1)/metal1 0 0 \ + edge4way ~(gc)/contact gc 1 ~(ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c)/metal1 0 0 \ "GC contact cannot touch Metal1 contacts (Mosis #0)" metal1 - edge4way ~(gc2)/contact gc2 1 ~(ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1)/metal1 0 0 \ - "Generic contact2 cannot touch Metal1 contacts (Mosis #0)" metal1 - spacing gv1 m2c/m2 2 touching_illegal \ "GV1 via spacing to Metal2 contacts < 2 (Mosis #14.2)" @@ -7001,12 +6057,6 @@ drc spacing psc/m1 ndc/m1 1 touching_illegal \ "psc spacing to ndc < 1 (Mosis #6.3)" - - - - - - spacing nfet,pfet ndc/a,pdc/a,psc/a,nsc/a 1 touching_illegal \ "N-Transistor,P-Transistor spacing to Diffusion contact < 1 (Mosis #6.4)" @@ -7020,35 +6070,44 @@ drc "Diffusion spacing to Diffusion contact < 4 (Mosis #6.5.b)" spacing pc/a ndc/a,pdc/a,psc/a,nsc/a 2 touching_illegal \ - "pc/a,pm12c/a spacing to ndc/a,pdc/a,psc/a,nsc/a < 2 (Mosis #6.7)" + "pc/a spacing to ndc/a,pdc/a,psc/a,nsc/a < 2 (Mosis #6.7)" - spacing m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 3 touching_ok \ + spacing m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 3 touching_ok \ "Metal1 spacing < 3 (Mosis #7.2)" - spacing m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 fm1,fapm 3 touching_illegal \ + spacing m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 fm1,fapm 3 touching_illegal \ "Metal1 spacing to fill layer (fm1) < 3 (Mosis #7.2)" spacing fm1 fm1 4 touching_ok \ "Metal1 fill layer (fm1) spacing < 4 (Mosis #0)" - edge4way gc space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 space 1 \ + edge4way gc space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 space 1 \ "Metal1 must overlap GC contact by 1 (Mosis #7.3,7.4)" metal1 - edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 1 ~(gc)/contact 0 0 \ + edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 1 ~(gc)/contact 0 0 \ "Metal1(edge) cannot touch GC contact (Mosis #7.3+7.4)" contact spacing gv1 gv1 3 touching_ok \ "GV1 via spacing < 3 (Mosis #8.2)" - edge4way gv1 ~(gv1)/via1 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 ~(gv1)/via1 1 \ + edge4way gv1 ~(gv1)/via1 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 ~(gv1)/via1 1 \ "Metal1 overlap of GV1 via < 1 (Mosis #8.3)" metal1 - edge4way gv1 space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 space 1 \ + edge4way gv1 space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 space 1 \ "Metal1 must overlap GV1 via by 1 (Mosis #8.3)" metal1 - edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 1 ~(gv1)/via1 0 0 \ + edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 1 ~(gv1)/via1 0 0 \ "Metal1(edge) cannot touch GV1 via (Mosis #8.3)" via1 + spacing gc gv1 2 touching_illegal \ + "GC contact spacing to GV1 via < 2 (Mosis #8.4)" + + spacing gc m2c/m2 2 touching_illegal \ + " spacing to Metal2 contacts < 2 (Mosis #14.2)" + + spacing gc m2c/m2 2 touching_illegal \ + "GC contact spacing to Metal2 contacts < 2 (Mosis #8.4)" + spacing m2,rm2,m2c/m2,m3c/m2 m2,rm2,m2c/m2,m3c/m2 3 touching_ok \ "Metal2 spacing < 3 (Mosis #9.2)" @@ -7079,7 +6138,7 @@ drc edge4way ~(ecap)/cap ecap 1 poly,fp,rp,pc/a 0 0 \ "Ecap must touch Poly (Mosis #11.3x)" active - edge4way poly2,phr,p2c,p2m12c space 5 ~(poly,fp,rp,pc/a)/active space 5 \ + edge4way poly2,phr space 5 ~(poly,fp,rp,pc/a)/active space 5 \ "Poly2 spacing to Poly < 5 (Mosis #11.3c)" active spacing ecap pc/a 2 touching_illegal \ @@ -7088,13 +6147,13 @@ drc spacing ecap gc 3 touching_illegal \ "Ecap spacing to Generic contact < 3 (Mosis #11.5)" - spacing poly2,ecap,phr,p2c,p2m12c poly2,ecap,phr,p2c,p2m12c 3 touching_ok \ + spacing poly2,ecap,phr poly2,ecap,phr 3 touching_ok \ "Poly2 spacing < 3 (Mosis #11.2)" - spacing poly2,ecap,phr,p2c,p2m12c pc/a,ndc/a,pdc/a,psc/a,nsc/a 2 touching_illegal \ + spacing poly2,ecap,phr pc/a,ndc/a,pdc/a,psc/a,nsc/a 2 touching_illegal \ "Poly2 spacing to Poly contact,Diffusion contact < 2 (Mosis #11.5)" - spacing poly2,ecap,phr,p2c,p2m12c gc,gc 3 touching_illegal \ + spacing poly2,ecap,phr gc,gc 3 touching_illegal \ "Poly2 spacing to GC contact < 3 (Mosis #11.5)" spacing gc2 gc2 3 touching_ok \ @@ -7103,17 +6162,17 @@ drc edge4way ~(ecap)/cap ecap 3 ~(gc2)/contact ecap 3 \ "Ecap overlap of Generic contact2 < 3 (Mosis #13.3)" contact - edge4way ~(ecap)/cap ecap 2 ~(p2c,p2m12c)/cap ecap 2 \ - "Ecap overlap of Poly2 contact < 2 (Mosis #13.3)" cap + edge4way ~(ecap)/cap ecap 2 ~(p2c)/metal1 ecap 2 \ + "Ecap overlap of Poly2 contact < 2 (Mosis #13.3)" metal1 - edge4way gc2 space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 space 1 \ + edge4way gc2 space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 space 1 \ "Metal1 must overlap Generic contact2 by 1 (Mosis #13.4)" metal1 - edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 1 ~(gc2)/contact 0 0 \ + edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 1 ~(gc2)/contact 0 0 \ "Metal1(edge) cannot touch Generic contact2 (Mosis #13.4)" contact - edge4way ~(poly2,ecap,phr,p2c,p2m12c)/cap poly2,ecap,phr,p2c,p2m12c 1 ~(p2c,p2m12c)/cap poly2,ecap,phr,p2c,p2m12c 1 \ - "Poly2 overlap of Poly2 contact < 1 (Mosis #13.4)" cap + edge4way ~(poly2,ecap,phr)/cap poly2,ecap,phr 1 ~(p2c)/metal1 poly2,ecap,phr 1 \ + "Poly2 overlap of Poly2 contact < 1 (Mosis #13.4)" metal1 spacing gv2 gv2 3 touching_ok \ "GV2 via spacing < 3 (Mosis #14.2)" @@ -7127,6 +6186,12 @@ drc edge4way ~(m2,fm2,rm2,m2c/m2,m3c/m2)/metal2 m2,fm2,rm2,m2c/m2,m3c/m2 1 ~(gv2)/via2 0 0 \ "Metal2(edge) cannot touch GV2 via (Mosis #14.3)" via2 + spacing gv1 gv2 2 touching_illegal \ + "GV1 via spacing to GV2 via < 2 (Mosis #14.4)" + + spacing gv1 m3c/m2 1 touching_illegal \ + "GV1 via spacing to Metal3 contact < 1 (Mosis #14.4)" + spacing m3,rm3,m3c/m3,pad m3,rm3,m3c/m3,pad 3 touching_ok \ "Metal3 spacing < 3 (Mosis #15.2)" @@ -7148,7 +6213,7 @@ drc spacing hr,phr hr,phr 4 touching_ok \ "High-Resist spacing < 4 (Mosis #27.2)" - spacing hr,phr,phr p2c,p2m12c 2 touching_illegal \ + spacing hr,phr,phr p2c 2 touching_illegal \ "High-Resist spacing to Poly2 contact < 2 (Mosis #27.3)" spacing hr,phr,phr gc 2 touching_illegal \ @@ -7157,10 +6222,10 @@ drc edge4way hr,phr space 2 ~(ndiff,rnd,ndc/a,pdiff,rpd,pdc/a)/active 0 2 \ "High-Resist space to Diffusion < 2 (Mosis #27.4)" active - spacing hr,phr,phr poly2,ecap,phr,p2c,p2m12c 2 touching_ok \ + spacing hr,phr,phr poly2,ecap,phr 2 touching_ok \ "High-Resist spacing to other Poly2 < 2 (Mosis #27.5)" - edge4way hr,phr space 2 ~(poly2,ecap,phr,p2c,p2m12c)/contact hr,phr 2 \ + edge4way hr,phr space 2 ~(poly2,ecap,phr)/contact hr,phr 2 \ "High-Resist space to Poly2 < 2 (Mosis #27.5x)" contact spacing nwell phr 4 touching_illegal \ @@ -7271,7 +6336,7 @@ drc edge4way gc2 ~(gc2)/contact 1 ~(gc2)/contact (~(gc2),gc2)/contact 1 \ "Contact not rectangular (Magic rule)" - edge4way p2c,p2m12c ~(p2c,p2m12c)/cap 1 ~(p2c,p2m12c)/cap (~(p2c,p2m12c),p2c,p2m12c)/cap 1 \ + edge4way p2c ~(p2c)/metal1 1 ~(p2c)/metal1 (~(p2c),p2c)/metal1 1 \ "Contact not rectangular (Magic rule)" edge4way gc ~(gc)/contact 1 ~(gc)/contact (~(gc),gc)/contact 1 \ @@ -7291,12 +6356,12 @@ drc exact_overlap gc,ndc/a,pdc/a,psc/a,nsc/a,gc,pc/a,gc - exact_overlap gc2,p2c,p2m12c + exact_overlap gc2,p2c edge4way pad ~(pad)/m3 1 ~(pad)/m3 (~(pad),pad)/m3 1 \ "Contact not rectangular (Magic rule)" - exact_overlap ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1 + exact_overlap ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c exact_overlap m2c/m2 @@ -7356,17 +6421,17 @@ lef ignore PC ignore CA -routing m1 M1 m1 met1 -routing m2 M2 m2 met2 -routing m3 M3 m3 met3 +routing m1 metal1 M1 m1 met1 +routing m2 metal2 M2 m2 met2 +routing m3 metal3 M3 m3 met3 -contact m2c via via1 V1 v1 +contact m2c via1 via V1 v1 contact m3c via2 V2 v2 end extract - style AMI0.5um(amic5)from:T24H + style AMI0.5um(amic5)from:T11Z cscale 1 lambda 30 step 100 @@ -7387,162 +6452,164 @@ extract planeorder via2 13 planeorder fill 14 - resist (ndiff,rnd,ndc,nsd,nsc)/active 82200 - resist (pdiff,rpd,pdc,psd,psc)/active 105200 - resist (nwell)/well 808000 - resist (rnw)/active 808000 - resist (pwell)/well 1 - resist (poly,fp,rp,pc,pc,nfet,pfet,fet)/active 22000 - resist (poly2,ecap,p2c,p2m12c,p2c,p2m12c)/cap 40300 - resist (phr)/cap 40300 - resist (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c,m2c)/metal1 90 - resist (m2,fm2,rm2,m2c,m3c,m3c)/metal2 90 - resist (m3,fm3,rm3,m3c,pad)/metal3 50 + substrate *psd,space/w,pwell well - contact ndc 4 62700 - contact pdc 4 160000 - contact pc 4 15600 - contact p2c 4 26100 - contact m2c 4 910 - contact m3c 4 830 + resist (ndiff,rnd,ndc,nsd,nsc)/active 82400 + resist (pdiff,rpd,pdc,psd,psc)/active 102700 + resist (nwell)/well 816000 + resist (rnw)/active 816000 0.5 + resist (pwell)/well 1 + resist (poly,fp,rp,pc,pc,nfet,pfet,fet)/active 22300 + resist (poly2,ecap,p2c)/cap 41300 + resist (phr)/cap 41300 0.5 + resist (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c,m2c)/metal1 90 + resist (m2,fm2,rm2,m2c,m3c,m3c)/metal2 90 + resist (m3,fm3,rm3,m3c,pad)/metal3 60 + + contact ndc 4 58700 + contact pdc 4 141000 + contact pc 4 15800 + contact p2c 4 26800 + contact m2c 4 760 + contact m3c 4 730 #poly2 - overlap (poly,fp,rp,pc,pc)/active (poly2,ecap,phr,p2c,p2m12c,p2c,p2m12c)/cap 84.960 + overlap (poly,fp,rp,pc,pc)/active (poly2,ecap,phr,p2c)/cap 82.260 #nwell,cwell,pwell - areacap (nwell)/well 3.600 + areacap (nwell)/well 3.510 #rnw - areacap (rnw)/active 3.600 + areacap (rnw)/active 3.510 #ndiff -# MODEL HANDLES THIS: areacap (ndiff,ndc)/active 38.430 -# MODEL HANDLES THIS: overlap (ndiff,ndc)/active ~space/w 38.430 -# MODEL HANDLES THIS: perimc (ndiff,ndc)/active ~(ndiff,ndc,nfet,pfet,fet)/active 94.800 -# MODEL HANDLES THIS: sideoverlap (ndiff,ndc)/active ~(ndiff,ndc,nfet,pfet,fet)/active ~space/w 94.800 +# MODEL HANDLES THIS: areacap (ndiff,ndc)/active 38.070 +# MODEL HANDLES THIS: overlap (ndiff,ndc)/active ~space/w 38.070 +# MODEL HANDLES THIS: perimc (ndiff,ndc)/active ~(ndiff,ndc,nfet,pfet,fet)/active 95.700 +# MODEL HANDLES THIS: sideoverlap (ndiff,ndc)/active ~(ndiff,ndc,nfet,pfet,fet)/active ~space/w 95.700 - areacap (rnd)/active 38.430 - overlap (rnd)/active ~space/w 38.430 - perimc (rnd)/active ~(rnd)/active 94.800 - sideoverlap (rnd)/active ~(rnd)/active ~space/w 94.800 + areacap (rnd)/active 38.070 + overlap (rnd)/active ~space/w 38.070 + perimc (rnd)/active ~(rnd)/active 95.700 + sideoverlap (rnd)/active ~(rnd)/active ~space/w 95.700 #pdiff -# MODEL HANDLES THIS: areacap (pdiff,pdc)/active 65.880 -# MODEL HANDLES THIS: overlap (pdiff,pdc)/active ~space/w 65.880 -# MODEL HANDLES THIS: perimc (pdiff,pdc)/active ~(pdiff,pdc,nfet,pfet,fet)/active 75.300 -# MODEL HANDLES THIS: sideoverlap (pdiff,pdc)/active ~(pdiff,pdc,nfet,pfet,fet)/active ~space/w 75.300 +# MODEL HANDLES THIS: areacap (pdiff,pdc)/active 65.610 +# MODEL HANDLES THIS: overlap (pdiff,pdc)/active ~space/w 65.610 +# MODEL HANDLES THIS: perimc (pdiff,pdc)/active ~(pdiff,pdc,nfet,pfet,fet)/active 73.800 +# MODEL HANDLES THIS: sideoverlap (pdiff,pdc)/active ~(pdiff,pdc,nfet,pfet,fet)/active ~space/w 73.800 - areacap (rpd)/active 65.880 - overlap (rpd)/active ~space/w 65.880 - perimc (rpd)/active ~(rpd)/active 75.300 - sideoverlap (rpd)/active ~(rpd)/active ~space/w 75.300 + areacap (rpd)/active 65.610 + overlap (rpd)/active ~space/w 65.610 + perimc (rpd)/active ~(rpd)/active 73.800 + sideoverlap (rpd)/active ~(rpd)/active ~space/w 73.800 #rnw #poly -# MODEL HANDLES THIS: overlap (nfet)/active (ndiff,rnd,ndc)/active 221.670 -# MODEL HANDLES THIS: sideoverlap (nfet)/active ~(nfet)/active (ndiff,rnd,ndc)/active 58.500 -# MODEL HANDLES THIS: overlap (pfet)/active (pdiff,rpd,pdc)/active 213.480 -# MODEL HANDLES THIS: sideoverlap (pfet)/active ~(pfet)/active (pdiff,rpd,pdc)/active 82.800 +# MODEL HANDLES THIS: overlap (nfet)/active (ndiff,rnd,ndc)/active 225.450 +# MODEL HANDLES THIS: sideoverlap (nfet)/active ~(nfet)/active (ndiff,rnd,ndc)/active 65.700 +# MODEL HANDLES THIS: overlap (pfet)/active (pdiff,rpd,pdc)/active 219.060 +# MODEL HANDLES THIS: sideoverlap (pfet)/active ~(pfet)/active (pdiff,rpd,pdc)/active 69 - areacap (poly,fp,rp,pc)/active 7.740 - overlap (poly,fp,rp,pc)/active ~space/w 7.740 + areacap (poly,fp,rp,pc)/active 7.920 + overlap (poly,fp,rp,pc)/active ~space/w 7.920 #poly2 #rnw #metal1 - areacap (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 2.700 + areacap (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 2.790 #metal1-sub blocked by ~space/a,~space/c - overlap (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 ~space/w 2.700 ~space/a,~space/c - perimc (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 20.700 - sideoverlap (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 ~space/w 20.700 ~space/a,~space/c + overlap (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 ~space/w 2.790 ~space/a,~space/c + perimc (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 22.200 + sideoverlap (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 ~space/w 22.200 ~space/a,~space/c #rnw - overlap (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 rnw/active 2.700 ~space/c - sideoverlap (m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,m2c)/metal1 rnw/active 20.700 ~space/c + overlap (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 rnw/active 2.790 ~space/c + sideoverlap (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 rnw/active 22.200 ~space/c #metal1-diff blocked by ~space/c - overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (ndiff,rnd,ndc)/active 3.150 ~space/c - sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (ndiff,rnd,ndc)/active 20.700 ~space/c - overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (pdiff,rpd,pdc)/active 3.150 ~space/c - sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (pdiff,rpd,pdc)/active 20.700 ~space/c + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (ndiff,rnd,ndc)/active 3.150 ~space/c + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (ndiff,rnd,ndc)/active 22.200 ~space/c + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (pdiff,rpd,pdc)/active 3.150 ~space/c + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (pdiff,rpd,pdc)/active 22.200 ~space/c #metal1-poly blocked by ~space/c - overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (poly,fp,rp,pc,nfet,pfet,fet)/active 4.590 ~space/c - sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (poly,fp,rp,pc,nfet,pfet,fet)/active 15.900 ~space/c - sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 15.900 ~space/c + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (poly,fp,rp,pc,nfet,pfet,fet)/active 4.680 ~space/c + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (poly,fp,rp,pc,nfet,pfet,fet)/active 18 ~space/c + sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 18 ~space/c #metal1-poly2 not blocked - overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (poly2,ecap,phr,p2c,p2m12c)/cap 3.960 + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (poly2,ecap,phr)/cap 4.320 #metal2 - areacap (m2,fm2,rm2,m3c)/metal2 1.350 + areacap (m2,fm2,rm2,m3c)/metal2 1.440 #metal2-sub blocked by - overlap (m2,fm2,rm2,m3c)/metal2 ~space/w 1.350 ~space/a,~space/m1,~space/c - perimc (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 15.900 - sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 ~space/w 15.900 ~space/a,~space/m1,~space/c - overlap (m2,fm2,rm2,m3c)/metal2 rnw/active 1.350 ~space/m1,~space/c - sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 rnw/active 15.900 ~space/m1,~space/c + overlap (m2,fm2,rm2,m3c)/metal2 ~space/w 1.440 ~space/a,~space/m1,~space/c + perimc (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 17.400 + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 ~space/w 17.400 ~space/a,~space/m1,~space/c + overlap (m2,fm2,rm2,m3c)/metal2 rnw/active 1.440 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 rnw/active 17.400 ~space/m1,~space/c #metal2-*diff blocked by ~space/m1,~space/c - overlap (m2,fm2,rm2,m3c)/metal2 (ndiff,rnd,ndc)/active 1.350 ~space/m1,~space/c - sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (ndiff,rnd,ndc)/active 15.900 ~space/m1,~space/c - overlap (m2,fm2,rm2,m2c,m3c)/metal2 (pdiff,rpd,pdc)/active 1.350 ~space/m1,~space/c - sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (pdiff,rpd,pdc)/active 15.900 ~space/m1,~space/c + overlap (m2,fm2,rm2,m3c)/metal2 (ndiff,rnd,ndc)/active 1.440 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (ndiff,rnd,ndc)/active 17.400 ~space/m1,~space/c + overlap (m2,fm2,rm2,m2c,m3c)/metal2 (pdiff,rpd,pdc)/active 1.440 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (pdiff,rpd,pdc)/active 17.400 ~space/m1,~space/c #metal2-poly blocked by ~space/m1,~space/c overlap (m2,fm2,rm2,m3c)/metal2 (poly,fp,rp,pc,nfet,pfet,fet)/active 1.350 ~space/m1,~space/c - sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (poly,fp,rp,pc,nfet,pfet,fet)/active 10.800 ~space/m1,~space/c - sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m2,fm2,rm2,m2c,m3c)/metal2 10.800 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (poly,fp,rp,pc,nfet,pfet,fet)/active 11.400 ~space/m1,~space/c + sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m2,fm2,rm2,m2c,m3c)/metal2 11.400 ~space/m1,~space/c #metal2-poly2 blocked by ~space/m1 #M2->M1 - overlap (m2,fm2,rm2,m3c)/metal2 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 2.520 - sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 14.700 - sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (m2,fm2,rm2,m2c,m3c)/metal2 14.700 + overlap (m2,fm2,rm2,m3c)/metal2 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 2.700 + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 15 + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (m2,fm2,rm2,m2c,m3c)/metal2 15 #metal3 areacap (m3,fm3,rm3,pad)/metal3 0.900 #metal3-sub blocked by ~space/a,~space/m1,~space/m2,~space/c overlap (m3,fm3,rm3,pad)/metal3 ~space/w 0.900 ~space/a,~space/m1,~space/m2,~space/c - perimc (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 10.500 - sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 ~space/w 10.500 ~space/a,~space/m1,~space/m2,~space/c + perimc (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 11.400 + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 ~space/w 11.400 ~space/a,~space/m1,~space/m2,~space/c #rnw overlap (m3,fm3,rm3,pad)/metal3 rnw/active 0.900 ~space/m1,~space/m2,~space/c - sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 rnw/active 10.500 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 rnw/active 11.400 ~space/m1,~space/m2,~space/c #metal3-*diff blocked by ~space/m1,~space/m2,~space/c overlap (m3,fm3,rm3,pad)/metal3 (ndiff,rnd,ndc)/active 0.990 ~space/m1,~space/m2,~space/c - sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (ndiff,rnd,ndc)/active 10.500 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (ndiff,rnd,ndc)/active 11.400 ~space/m1,~space/m2,~space/c overlap (m3,fm3,rm3,pad)/metal3 (pdiff,rpd,pdc)/active 0.990 ~space/m1,~space/m2,~space/c - sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (pdiff,rpd,pdc)/active 10.500 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (pdiff,rpd,pdc)/active 11.400 ~space/m1,~space/m2,~space/c #metal3-poly blocked by ~space/m1,~space/m2,~space/c overlap (m3,fm3,rm3,pad)/metal3 (poly,fp,rp,pc,nfet,pfet,fet)/active 0.810 ~space/m1,~space/m2,~space/c - sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (poly,fp,rp,pc,nfet,pfet,fet)/active 8.100 ~space/m1,~space/m2,~space/c - sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m3,fm3,rm3,m3c,pad)/metal3 8.100 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (poly,fp,rp,pc,nfet,pfet,fet)/active 8.400 ~space/m1,~space/m2,~space/c + sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m3,fm3,rm3,m3c,pad)/metal3 8.400 ~space/m1,~space/m2,~space/c #metal3-poly2 blocked by ~space/m1,~space/m2 #M3->M1 - overlap (m3,fm3,rm3,pad)/metal3 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 1.080 ~space/m2 + overlap (m3,fm3,rm3,pad)/metal3 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 1.080 ~space/m2 #metal3-metal1 blocked by ~space/m2 - sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 9.900 ~space/m2 - sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,m2c)/metal1 (m3,fm3,rm3,m3c,pad)/metal3 9.900 ~space/m2 + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 9.600 ~space/m2 + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (m3,fm3,rm3,m3c,pad)/metal3 9.600 ~space/m2 #M3->M2 - overlap (m3,fm3,rm3,pad)/metal3 (m2,fm2,rm2,m2c,m3c)/metal2 3.060 - sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (m2,fm2,rm2,m2c,m3c)/metal2 16.800 - sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (m3,fm3,rm3,m3c,pad)/metal3 16.800 + overlap (m3,fm3,rm3,pad)/metal3 (m2,fm2,rm2,m2c,m3c)/metal2 2.880 + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (m2,fm2,rm2,m2c,m3c)/metal2 15.600 + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (m3,fm3,rm3,m3c,pad)/metal3 15.600 #metal4 @@ -7554,44 +6621,28 @@ extract #metali -#fets +#devices -# fet pfet pdiff,pdc 2 pfet Vdd! nwell 83 213 -# fet pfet pdiff,pdc 1 pfet Vdd! nwell 83 213 + device mosfet pfet pfet pdiff,pdc nwell ERROR 69 219 + device mosfet nfet nfet ndiff,ndc pwell,space/w ERROR 66 225 - device mosfet pfet pfet pdiff,pdc nwell $VDD 83 213 + fetresis pfet linear 21001 + fetresis pfet saturation 21001 + fetresis nfet linear 6020 + fetresis nfet saturation 6020 -# fet nfet ndiff,ndc 2 nfet Gnd! pwell 59 222 -# fet nfet ndiff,ndc 1 nfet Gnd! pwell 59 222 + device resistor nwellResistor rnwell *nsd + device resistor polyResistor rpoly *poly + device resistor poly2Resistor rpoly2 *poly2 + device resistor ndiffResistor rndiff *ndiff + device resistor pdiffResistor rpdiff *pdiff - device mosfet nfet nfet ndiff,ndc pwell $GND 59 222 + device resistor metal1Resistor rmetal1 *metal1 + device resistor metal2Resistor rmetal2 *metal2 + device resistor metal3Resistor rmetal3 *metal3 - fetresis pfet linear 20996 - fetresis pfet saturation 20996 - fetresis nfet linear 6144 - fetresis nfet saturation 6144 + device resistor presResistor phr *poly2 -# fet rnwell nsd,nsc 2 nwellResistor Gnd! nwell,pwell 0 0 -# fet rpoly poly,pc 2 polyResistor Gnd! nwell,pwell 0 0 -# fet rpoly2 poly2,p2c 2 poly2Resistor Gnd! nwell,pwell 0 0 -# fet rndiff ndiff,ndc 2 ndiffResistor Gnd! nwell,pwell 0 0 -# fet rpdiff pdiff,pdc 2 pdiffResistor Gnd! nwell,pwell 0 0 - - device resistor None rnwell nsd,nsc - device resistor None rpoly poly,pc - device resistor None rpoly2 poly2,p2c - device resistor None rndiff ndiff,ndc - device resistor None rpdiff pdiff,pdc - -# fet rmetal1 metal1 2 metal1Resistor Gnd! nwell,pwell 0 0 -# fet rmetal2 metal2 2 metal2Resistor Gnd! nwell,pwell 0 0 -# fet rmetal3 metal3 2 metal3Resistor Gnd! nwell,pwell 0 0 -# fet phr poly2,p2c 2 phrResistor Gnd! nwell,pwell 0 0 - - device resistor None rmetal1 *metal1 - device resistor None rmetal2 *metal2 - device resistor None rmetal3 *metal3 - device resistor None phr poly2,p2c end @@ -7606,7 +6657,7 @@ end router layer2 metal2 3 m2,fm2,rm2,m2c/m2,m3c/m2,m3c/m2 4 poly,fp,rp,ndiff,rnd,nsd,pdiff,rpd,psd,m1,fm1,rm1 1 - layer1 metal1 3 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 3 + layer1 metal1 3 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 3 contacts m2contact 4 gridspacing 8 @@ -7706,12 +6757,12 @@ style colorversatec 4949 A0A0 5252 2828 \ 9494 0A0A 2525 8282 \ 4949 A0A0 5252 2828 - poly2,ecap,phr,p2c,p2m12c yellow \ + poly2,ecap,phr yellow \ FFFF FFFF FFFF FFFF \ FFFF FFFF FFFF FFFF \ FFFF FFFF FFFF FFFF \ FFFF FFFF FFFF FFFF - m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 cyan \ + m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 cyan \ AAAA 0000 AAAA 0000 \ AAAA 0000 AAAA 0000 \ AAAA 0000 AAAA 0000 \ @@ -7834,7 +6885,7 @@ style versatec 8080 4000 2020 1010 \ 0808 0004 0202 0101 \ 8080 0040 2020 1010 - m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,m2c/m1 \ + m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 \ 8080 0000 0000 0000 \ 0808 0000 0000 0000 \ 8080 0000 0000 0000 \ diff --git a/technology/scn4m_subm/tech/SCN4M_SUBM.20.tech b/technology/scn4m_subm/tech/SCN4M_SUBM.20.tech index deaae865..7207f681 100644 --- a/technology/scn4m_subm/tech/SCN4M_SUBM.20.tech +++ b/technology/scn4m_subm/tech/SCN4M_SUBM.20.tech @@ -1764,6 +1764,11 @@ cifinput style lambda=0.20(p) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -2450,10 +2455,6 @@ style lambda=0.20(p) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -2470,6 +2471,11 @@ style lambda=0.20(p) style lambda=0.20(s) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -3158,10 +3164,6 @@ style lambda=0.20(s) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -3178,6 +3180,11 @@ style lambda=0.20(s) style lambda=0.20(ps) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -3810,10 +3817,6 @@ style lambda=0.20(ps) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -3830,6 +3833,11 @@ style lambda=0.20(ps) style lambda=0.20() scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -4516,10 +4524,6 @@ style lambda=0.20() and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -4536,6 +4540,11 @@ style lambda=0.20() style lambda=0.20(c) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -4989,10 +4998,6 @@ style lambda=0.20(c) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -5009,6 +5014,11 @@ style lambda=0.20(c) style lambda=0.20(cs) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -5464,10 +5474,6 @@ style lambda=0.20(cs) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -5484,6 +5490,11 @@ style lambda=0.20(cs) style lambda=0.20(cps) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -5940,10 +5951,6 @@ style lambda=0.20(cps) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -5960,6 +5967,11 @@ style lambda=0.20(cps) style lambda=0.20(cp) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -6414,10 +6426,6 @@ style lambda=0.20(cp) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 882e16d5..a5756ce3 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -86,8 +86,8 @@ drc["has_nwell"] = True drc["grid"]=0.5*_lambda_ #DRC/LVS test set_up -drc["drc_rules"]=drclvs_home+"/calibreDRC_scn3me_subm.rul" -drc["lvs_rules"]=drclvs_home+"/calibreLVS_scn3me_subm.rul" +drc["drc_rules"]=None #drclvs_home+"/calibreDRC_scn3me_subm.rul" +drc["lvs_rules"]=None #drclvs_home+"/calibreLVS_scn3me_subm.rul" drc["layer_map"]=os.environ.get("OPENRAM_TECH")+"/scn3me_subm/layers.map" # minwidth_tx with contact (no dog bone transistors) From 42c16ed739f83d050902992ceb7b8d73bc013454 Mon Sep 17 00:00:00 2001 From: mrg Date: Sun, 26 May 2019 22:30:54 -0700 Subject: [PATCH 022/234] Add boundary layer --- .../scn3me_subm/gds_lib/cell_1rw_1r.gds | Bin 6394 -> 6458 bytes technology/scn3me_subm/gds_lib/cell_1w_1r.gds | Bin 6390 -> 6454 bytes .../gds_lib/replica_cell_1rw_1r.gds | Bin 6346 -> 6410 bytes .../gds_lib/replica_cell_1w_1r.gds | Bin 6342 -> 6406 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds b/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds index a4fea073f7794ef11cbd2daa04f721b08f919b4f..f9a19873f4bff1427a2f5ceea7c33f32d9b6df44 100644 GIT binary patch delta 53 zcmexmxXWmQJhL2w`a~sL5VbKWNSuR%fq{*eiNSv29tFOT1O_mG(3@9@2QUHvN4^Tr delta 26 fcmdmG^viI9JTn)A{zN5P5VbKWNPP1baW_T)YsLq# diff --git a/technology/scn3me_subm/gds_lib/cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/cell_1w_1r.gds index 382018a72c5508ba11ee26a0f7b90ab724a76510..41cff8af7f7b4c2e2212a810a2b1d26337ea0000 100644 GIT binary patch delta 60 zcmexnxXoySJhL2w`a~sb5VbKOK%9evfq{*eiNSv24h6xG1O_mG(F~I>ipy_4A+E;= E0FgxuRsaA1 delta 30 jcmdmH^v!UBJTn)A{zN5f5VbKOKzy=`7TeWH>ph}xJXCC`7TeWH>xh}xJTA Date: Mon, 27 May 2019 13:08:59 -0700 Subject: [PATCH 023/234] Added smarter name checking for the characterizer. --- compiler/base/graph_util.py | 2 +- compiler/base/hierarchy_design.py | 79 ++++++++++++++++++++++++++----- compiler/characterizer/delay.py | 78 ++++++++++++++++++++++-------- compiler/modules/sense_amp.py | 9 +++- compiler/sram_factory.py | 10 +++- 5 files changed, 142 insertions(+), 36 deletions(-) diff --git a/compiler/base/graph_util.py b/compiler/base/graph_util.py index 25c79d3b..af4d0888 100644 --- a/compiler/base/graph_util.py +++ b/compiler/base/graph_util.py @@ -8,7 +8,7 @@ import globals import debug from vector import vector from pin_layout import pin_layout - + class timing_graph(): """Implements a directed graph Nodes are currently just Strings. diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index 1bb9f44e..f6b10530 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -104,17 +104,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): total_lvs_errors += num_errors debug.check(num_errors == 0,"LVS failed for {0} with {1} error(s)".format(self.name,num_errors)) os.remove(tempspice) - os.remove(tempgds) - - #Example graph run - # import graph_util - # graph = graph_util.graph() - # pins = ['A','Z','vdd','gnd'] - # d.build_graph(graph,"Xpdriver",pins) - # graph.remove_edges('vdd') - # graph.remove_edges('gnd') - # debug.info(1,"{}".format(graph)) - # graph.print_all_paths('A', 'Z') + os.remove(tempgds) def init_graph_params(self): """Initializes parameters relevant to the graph creation""" @@ -136,6 +126,71 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): subinst_ports = self.translate_nets(conns, port_dict, inst_name) subinst.mod.build_graph(graph, subinst_name, subinst_ports) + def build_names(self, name_dict, inst_name, port_nets): + """Collects all the nets and the parent inst of that net.""" + #Translate port names to external nets + if len(port_nets) != len(self.pins): + debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,self.pins),1) + port_dict = {pin:port for pin,port in zip(self.pins, port_nets)} + debug.info(3, "Instance name={}".format(inst_name)) + for subinst, conns in zip(self.insts, self.conns): + subinst_name = inst_name+'.X'+subinst.name + subinst_ports = self.translate_nets(conns, port_dict, inst_name) + for si_port, conn in zip(subinst_ports, conns): + #Only add for first occurrence + if si_port.lower() not in name_dict: + mod_info = {'mod':self, 'int_net':conn} + name_dict[si_port.lower()] = mod_info + subinst.mod.build_names(name_dict, subinst_name, subinst_ports) + + def find_aliases(self, inst_name, port_nets, path_nets, alias, alias_mod): + """Given a list of nets, will compare the internal alias of a mod to determine + if the nets have a connection to this mod's net (but not inst). + """ + try: + self.name_dict + except AttributeError: + self.name_dict = {} + self.build_names(self.name_dict, inst_name, port_nets) + aliases = [] + for net in path_nets: + net = net.lower() + int_net = self.name_dict[net]['int_net'] + int_mod = self.name_dict[net]['mod'] + if int_mod.is_net_alias(int_net, alias, alias_mod): + aliases.append(net) + debug.info(1,"Aliases Found={}".format(aliases)) + return aliases + + def is_net_alias(self, known_net, net_alias, mod): + """Checks if the alias_net in mod is the same as the input net.""" + #Check ports of this mod + for pin in self.pins: + if self.is_net_alias_name_check(known_net, pin, net_alias, mod): + return True + #Check connections of all other subinsts + for subinst, inst_conns in zip(self.insts, self.conns): + for inst_conn, mod_pin in zip(inst_conns, subinst.mod.pins): + if self.is_net_alias_name_check(known_net, inst_conn, net_alias, mod): + return True + elif inst_conn.lower() == known_net.lower(): + return subinst.mod.is_net_alias(mod_pin, net_alias, mod) + return False + + def is_net_alias_name_check(self, parent_net, child_net, alias_net, mod): + """Utility function for checking single net alias.""" + return self == mod and \ + child_net.lower() == alias_net.lower() and \ + parent_net.lower() == alias_net.lower() + + def get_mod_net(self, parent_net, child_inst, child_conns): + """Given an instance and net, returns the internal net in the mod + corresponding to input net.""" + for conn, pin in zip(child_conns, child_inst.mod.pins): + if parent_net.lower() == conn.lower(): + return pin + return None + def translate_nets(self, subinst_ports, port_dict, inst_name): """Converts connection names to their spice hierarchy equivalent""" converted_conns = [] @@ -159,7 +214,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): for out in output_pins+inout_pins: if inp != out: #do not add self loops graph.add_edge(pin_dict[inp], pin_dict[out]) - + def __str__(self): """ override print function output """ pins = ",".join(self.pins) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index e92663d9..3f97f885 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -18,6 +18,7 @@ from .simulation import simulation from .measurements import * import logical_effort import graph_util +from sram_factory import factory class delay(simulation): """Functions to measure the delay and power of an SRAM at a given address and @@ -99,17 +100,6 @@ class delay(simulation): for obj in self.read_lib_meas: if obj.meta_str is sram_op.READ_ZERO: obj.meta_add_delay = True - - # trig_name = "Xsram.s_en{}" #Sense amp enable - # if len(self.all_ports) == 1: #special naming case for single port sram bitlines which does not include the port in name - # port_format = "" - # else: - # port_format = "{}" - - # bl_name = "Xsram.Xbank0.bl{}_{}".format(port_format, self.bitline_column) - # br_name = "Xsram.Xbank0.br{}_{}".format(port_format, self.bitline_column) - # self.read_lib_meas.append(voltage_when_measure(self.voltage_when_names[0], trig_name, bl_name, "RISE", .5)) - # self.read_lib_meas.append(voltage_when_measure(self.voltage_when_names[1], trig_name, br_name, "RISE", .5)) read_measures = [] read_measures.append(self.read_lib_meas) @@ -230,19 +220,20 @@ class delay(simulation): #Generate new graph every analysis as edges might change depending on test bit self.graph = graph_util.timing_graph() - self.sram.build_graph(self.graph,"X{}".format(self.sram.name),self.pins) + self.sram_spc_name = "X{}".format(self.sram.name) + self.sram.build_graph(self.graph,self.sram_spc_name,self.pins) #debug.info(1,"{}".format(self.graph)) port = 0 self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), \ '{}{}_{}'.format(self.dout_name, port, self.probe_data)) - sen_name = self.sram.get_sen_name(self.sram.name, port).lower() - debug.info(1, "Sen name={}".format(sen_name)) - sen_path = [] - for path in self.graph.all_paths: - if sen_name in path: - sen_path = path - break - debug.check(len(sen_path)!=0, "Could not find s_en timing path.") + + sen_name = self.get_sen_name(self.graph.all_paths) + debug.info(1,"s_en name = {}".format(sen_name)) + + self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths) + import sys + sys.exit(1) + preconv_names = [] for path in self.graph.all_paths: if not path is sen_path: @@ -258,7 +249,52 @@ class delay(simulation): (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, self.wordline_row, self.bitline_column) debug.info(1, "cell_name={}".format(cell_name)) - + def get_sen_name(self, paths): + """Gets the signal name associated with the sense amp enable from input paths. + Only expects a single path to contain the sen signal name.""" + sa_mods = factory.get_mods(OPTS.sense_amp) + #Any sense amp instantiated should be identical, any change to that + #will require some identification to determine the mod desired. + 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_found = False + #Only a single path should contain a single s_en name. Anything else is an error. + for path in paths: + aliases = self.sram.find_aliases(self.sram_spc_name, self.pins, path, enable_name, sa_mods[0]) + if sen_found and len(aliases) >= 1: + debug.error('Found multiple paths with SA enable.',1) + elif len(aliases) > 1: + debug.error('Found multiple S_EN points in single path. Cannot distinguish between them.',1) + elif not sen_found and len(aliases) == 1: + sen_name = aliases[0] + sen_found = True + if not sen_found: + debug.error("Could not find S_EN name.",1) + + return sen_name + + def get_bl_name(self, paths): + """Gets the signal name associated with the bitlines in the bank.""" + sa_mods = factory.get_mods(OPTS.sense_amp) + #Any sense amp instantiated should be identical, any change to that + #will require some identification to determine the mod desired. + 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_found = False + #Only a single path should contain a single s_en name. Anything else is an error. + for path in paths: + aliases = self.sram.find_aliases(self.sram_spc_name, self.pins, path, enable_name, sa_mods[0]) + if sen_found and len(aliases) >= 1: + debug.error('Found multiple paths with SA enable.',1) + elif len(aliases) > 1: + debug.error('Found multiple S_EN points in single path. Cannot distinguish between them.',1) + elif not sen_found and len(aliases) == 1: + sen_name = aliases[0] + sen_found = True + if not sen_found: + debug.error("Could not find S_EN name.",1) + + return sen_name def check_arguments(self): """Checks if arguments given for write_stimulus() meets requirements""" diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index e28f3efa..8e0ff112 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -61,7 +61,14 @@ class sense_amp(design.design): nmos_cin = parameter["sa_en_nmos_size"]/drc("minwidth_tx") #sen is connected to 2 pmos isolation TX and 1 nmos per sense amp. return 2*pmos_cin + nmos_cin - + + def get_enable_name(self): + """Returns name used for enable net""" + #FIXME: A better programmatic solution to designate pins + enable_name = "en" + debug.check(enable_name in self.pin_names, "Enable name {} not found in pin list".format(enable_name)) + return enable_name + def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" self.add_graph_edges(graph, port_nets) diff --git a/compiler/sram_factory.py b/compiler/sram_factory.py index 325261a0..90478f4c 100644 --- a/compiler/sram_factory.py +++ b/compiler/sram_factory.py @@ -83,7 +83,15 @@ class sram_factory: self.objects[module_type].append((kwargs,obj)) return obj - + def get_mods(self, module_type): + """Returns list of all objects of module name's type.""" + try: + mod_tuples = self.objects[module_type] + mods = [mod for kwargs,mod in mod_tuples] + except KeyError: + mods = [] + return mods + # Make a factory factory = sram_factory() From e738353b5c68b3b272d8c200b4bd1c3a69341824 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 27 May 2019 16:19:29 -0700 Subject: [PATCH 024/234] Pbitcell updates. Fix module offset error. Add boundary for debugging. Line wrap code. --- compiler/base/design.py | 2 + compiler/bitcells/pbitcell.py | 106 ++++++++++++++++++++-------------- 2 files changed, 66 insertions(+), 42 deletions(-) diff --git a/compiler/base/design.py b/compiler/base/design.py index 516eef80..b6651dd4 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -30,6 +30,8 @@ class design(hierarchy_design): self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space, self.m3_space) if contact.m3m4: self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space) + else: + self.m3_pitch = self.m2_pitch def setup_drc_constants(self): """ These are some DRC constants used in many places in the compiler.""" diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index e045b763..c9eb3f58 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -79,9 +79,7 @@ class pbitcell(design.design): # in netlist_only mode, calling offset_all_coordinates or translate_all will not be possible # this function is not needed to calculate the dimensions of pbitcell in netlist_only mode though if not OPTS.netlist_only: - self.offset_all_coordinates() - gnd_overlap = vector(0, 0.5*contact.well.width) - self.translate_all(gnd_overlap) + self.translate_all(vector(self.leftmost_xpos, self.botmost_ypos)) def add_pins(self): @@ -141,7 +139,8 @@ class pbitcell(design.design): def add_modules(self): """ Determine size of transistors and add ptx modules """ - # if there are any read/write ports, then the inverter nmos is sized based the number of read/write ports + # if there are any read/write ports, + # then the inverter nmos is sized based the number of read/write ports if(self.num_rw_ports > 0): inverter_nmos_width = self.num_rw_ports*parameter["6T_inv_nmos_size"] inverter_pmos_width = parameter["6T_inv_pmos_size"] @@ -149,7 +148,8 @@ class pbitcell(design.design): write_nmos_width = parameter["6T_access_size"] read_nmos_width = 2*parameter["6T_inv_pmos_size"] - # if there are no read/write ports, then the inverter nmos is statically sized for the dual port case + # if there are no read/write ports, + # then the inverter nmos is statically sized for the dual port case else: inverter_nmos_width = 2*parameter["6T_inv_pmos_size"] inverter_pmos_width = parameter["6T_inv_pmos_size"] @@ -183,14 +183,21 @@ class pbitcell(design.design): def calculate_spacing(self): """ Calculate transistor spacings """ + # calculate metal contact extensions over transistor active - readwrite_nmos_contact_extension = 0.5*(self.readwrite_nmos.active_contact.height - self.readwrite_nmos.active_height) - write_nmos_contact_extension = 0.5*(self.write_nmos.active_contact.height - self.write_nmos.active_height) - read_nmos_contact_extension = 0.5*(self.read_nmos.active_contact.height - self.read_nmos.active_height) - max_contact_extension = max(readwrite_nmos_contact_extension, write_nmos_contact_extension, read_nmos_contact_extension) + readwrite_nmos_contact_extension = 0.5*(self.readwrite_nmos.active_contact.height \ + - self.readwrite_nmos.active_height) + write_nmos_contact_extension = 0.5*(self.write_nmos.active_contact.height \ + - self.write_nmos.active_height) + read_nmos_contact_extension = 0.5*(self.read_nmos.active_contact.height \ + - self.read_nmos.active_height) + max_contact_extension = max(readwrite_nmos_contact_extension, + write_nmos_contact_extension, + read_nmos_contact_extension) # y-offset for the access transistor's gate contact - self.gate_contact_yoffset = max_contact_extension + self.m2_space + 0.5*max(contact.poly.height, contact.m1m2.height) + self.gate_contact_yoffset = max_contact_extension + self.m2_space \ + + 0.5*max(contact.poly.height, contact.m1m2.height) # y-position of access transistors self.port_ypos = self.m1_space + 0.5*contact.m1m2.height + self.gate_contact_yoffset @@ -199,8 +206,10 @@ class pbitcell(design.design): self.inverter_nmos_ypos = self.port_ypos # spacing between ports (same for read/write and write ports) - self.bitline_offset = -0.5*self.readwrite_nmos.active_width + 0.5*contact.m1m2.height + self.m2_space + self.m2_width - m2_constraint = self.bitline_offset + self.m2_space + 0.5*contact.m1m2.height - 0.5*self.readwrite_nmos.active_width + self.bitline_offset = -0.5*self.readwrite_nmos.active_width + 0.5*contact.m1m2.height \ + + self.m2_space + self.m2_width + m2_constraint = self.bitline_offset + self.m2_space + 0.5*contact.m1m2.height \ + - 0.5*self.readwrite_nmos.active_width self.write_port_spacing = max(self.active_space, self.m1_space, m2_constraint) self.read_port_spacing = self.bitline_offset + self.m2_space @@ -211,7 +220,7 @@ class pbitcell(design.design): inverter_pmos_contact_extension = 0.5*(self.inverter_pmos.active_contact.height - self.inverter_pmos.active_height) inverter_nmos_contact_extension = 0.5*(self.inverter_nmos.active_contact.height - self.inverter_nmos.active_height) self.inverter_gap = max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \ - + self.poly_to_polycontact + 2*contact.poly.width \ + + self.poly_to_polycontact + 2*contact.poly.height \ + self.m1_space + inverter_pmos_contact_extension self.cross_couple_lower_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \ + max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \ @@ -222,11 +231,11 @@ class pbitcell(design.design): + 1.5*contact.poly.width # spacing between wordlines (and gnd) - self.rowline_spacing = self.m1_space + contact.m1m2.width - self.rowline_offset = -0.5*self.m1_width + self.m1_offset = -0.5*self.m1_width # spacing for vdd - implant_constraint = max(inverter_pmos_contact_extension, 0) + 2*self.implant_enclose_active + 0.5*(contact.well.width - self.m1_width) + implant_constraint = max(inverter_pmos_contact_extension, 0) + 2*self.implant_enclose_active \ + + 0.5*(contact.well.width - self.m1_width) metal1_constraint = max(inverter_pmos_contact_extension, 0) + self.m1_space self.vdd_offset = max(implant_constraint, metal1_constraint) + 0.5*self.m1_width @@ -236,8 +245,10 @@ class pbitcell(design.design): def calculate_postions(self): """ Calculate positions that describe the edges and dimensions of the cell """ - self.botmost_ypos = -0.5*self.m1_width - self.total_ports*self.rowline_spacing - self.topmost_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height + self.inverter_gap + self.inverter_pmos.active_height + self.vdd_offset + self.botmost_ypos = self.m1_offset - self.total_ports*self.m1_pitch + self.topmost_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \ + + self.inverter_gap + self.inverter_pmos.active_height \ + + self.vdd_offset self.leftmost_xpos = -0.5*self.inverter_to_inverter_spacing - self.inverter_nmos.active_width \ - self.num_rw_ports*(self.readwrite_nmos.active_width + self.write_port_spacing) \ @@ -247,9 +258,14 @@ class pbitcell(design.design): self.width = -2*self.leftmost_xpos self.height = self.topmost_ypos - self.botmost_ypos - self.center_ypos = 0.5*(self.topmost_ypos + self.botmost_ypos) - + + # Add this boundary for visual debug + self.add_rect(layer="boundary", + offset=vector(self.leftmost_xpos,self.botmost_ypos), + height=self.height, + width=self.width) + def create_storage(self): """ Creates the crossed coupled inverters that act as storage for the bitcell. @@ -307,13 +323,15 @@ class pbitcell(design.design): width=contact.active.second_layer_width) # add contacts to connect gate poly to drain/source metal1 (to connect Q to Q_bar) - contact_offset_left = vector(self.inverter_nmos_left.get_pin("D").rc().x + 0.5*contact.poly.height, self.cross_couple_upper_ypos) + contact_offset_left = vector(self.inverter_nmos_left.get_pin("D").rc().x + 0.5*contact.poly.height, + self.cross_couple_upper_ypos) self.add_via_center(layers=("poly", "contact", "metal1"), offset=contact_offset_left, directions=("H","H")) - contact_offset_right = vector(self.inverter_nmos_right.get_pin("S").lc().x - 0.5*contact.poly.height, self.cross_couple_lower_ypos) + contact_offset_right = vector(self.inverter_nmos_right.get_pin("S").lc().x - 0.5*contact.poly.height, + self.cross_couple_lower_ypos) self.add_via_center(layers=("poly", "contact", "metal1"), offset=contact_offset_right, directions=("H","H")) @@ -328,21 +346,21 @@ class pbitcell(design.design): def route_rails(self): """ Adds gnd and vdd rails and connects them to the inverters """ # Add rails for vdd and gnd - gnd_ypos = self.rowline_offset - self.total_ports*self.rowline_spacing + gnd_ypos = self.m1_offset - self.total_ports*self.m1_pitch self.gnd_position = vector(0, gnd_ypos) self.add_rect_center(layer="metal1", offset=self.gnd_position, - width=self.width, - height=self.m1_width) + width=self.width) self.add_power_pin("gnd", vector(0,gnd_ypos)) - vdd_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height + self.inverter_gap + self.inverter_pmos.active_height + self.vdd_offset + vdd_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \ + + self.inverter_gap + self.inverter_pmos.active_height \ + + self.vdd_offset self.vdd_position = vector(0, vdd_ypos) self.add_rect_center(layer="metal1", offset=self.vdd_position, - width=self.width, - height=self.m1_width) + width=self.width) self.add_power_pin("vdd", vector(0,vdd_ypos)) def create_readwrite_ports(self): @@ -393,13 +411,12 @@ class pbitcell(design.design): self.readwrite_nmos_right[k].place(offset=[right_readwrite_transistor_xpos, self.port_ypos]) # add pin for RWWL - rwwl_ypos = self.rowline_offset - k*self.rowline_spacing + rwwl_ypos = self.m1_offset - k*self.m1_pitch self.rwwl_positions[k] = vector(0, rwwl_ypos) self.add_layout_pin_rect_center(text=self.rw_wl_names[k], layer="metal1", offset=self.rwwl_positions[k], - width=self.width, - height=self.m1_width) + width=self.width) # add pins for RWBL and RWBR rwbl_xpos = left_readwrite_transistor_xpos - self.bitline_offset + 0.5*self.m2_width @@ -409,7 +426,8 @@ class pbitcell(design.design): offset=self.rwbl_positions[k], height=self.height) - rwbr_xpos = right_readwrite_transistor_xpos + self.readwrite_nmos.active_width + self.bitline_offset - 0.5*self.m2_width + rwbr_xpos = right_readwrite_transistor_xpos + self.readwrite_nmos.active_width \ + + self.bitline_offset - 0.5*self.m2_width self.rwbr_positions[k] = vector(rwbr_xpos, self.center_ypos) self.add_layout_pin_rect_center(text=self.rw_br_names[k], layer="metal2", @@ -468,13 +486,13 @@ class pbitcell(design.design): self.write_nmos_right[k].place(offset=[right_write_transistor_xpos, self.port_ypos]) # add pin for WWL - wwl_ypos = rwwl_ypos = self.rowline_offset - self.num_rw_ports*self.rowline_spacing - k*self.rowline_spacing + wwl_ypos = rwwl_ypos = self.m1_offset - self.num_rw_ports*self.m1_pitch \ + - k*self.m1_pitch self.wwl_positions[k] = vector(0, wwl_ypos) self.add_layout_pin_rect_center(text=self.w_wl_names[k], layer="metal1", offset=self.wwl_positions[k], - width=self.width, - height=self.m1_width) + width=self.width) # add pins for WBL and WBR wbl_xpos = left_write_transistor_xpos - self.bitline_offset + 0.5*self.m2_width @@ -484,7 +502,8 @@ class pbitcell(design.design): offset=self.wbl_positions[k], height=self.height) - wbr_xpos = right_write_transistor_xpos + self.write_nmos.active_width + self.bitline_offset - 0.5*self.m2_width + wbr_xpos = right_write_transistor_xpos + self.write_nmos.active_width + self.bitline_offset \ + - 0.5*self.m2_width self.wbr_positions[k] = vector(wbr_xpos, self.center_ypos) self.add_layout_pin_rect_center(text=self.w_br_names[k], layer="metal2", @@ -565,13 +584,13 @@ class pbitcell(design.design): self.read_nmos_right[k].place(offset=[right_read_transistor_xpos+overlap_offset, self.port_ypos]) # add pin for RWL - rwl_ypos = rwwl_ypos = self.rowline_offset - self.num_rw_ports*self.rowline_spacing - self.num_w_ports*self.rowline_spacing - k*self.rowline_spacing + rwl_ypos = rwwl_ypos = self.m1_offset - self.num_rw_ports*self.m1_pitch \ + - self.num_w_ports*self.m1_pitch - k*self.m1_pitch self.rwl_positions[k] = vector(0, rwl_ypos) self.add_layout_pin_rect_center(text=self.r_wl_names[k], layer="metal1", offset=self.rwl_positions[k], - width=self.width, - height=self.m1_width) + width=self.width) # add pins for RBL and RBR rbl_xpos = left_read_transistor_xpos - self.bitline_offset + 0.5*self.m2_width @@ -581,7 +600,8 @@ class pbitcell(design.design): offset=self.rbl_positions[k], height=self.height) - rbr_xpos = right_read_transistor_xpos + self.read_port_width + self.bitline_offset - 0.5*self.m2_width + rbr_xpos = right_read_transistor_xpos + self.read_port_width + self.bitline_offset \ + - 0.5*self.m2_width self.rbr_positions[k] = vector(rbr_xpos, self.center_ypos) self.add_layout_pin_rect_center(text=self.r_br_names[k], layer="metal2", @@ -739,12 +759,14 @@ class pbitcell(design.design): def route_read_access(self): """ Routes read access transistors to the storage component of the bitcell """ # add poly to metal1 contacts for gates of the inverters - left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x - self.poly_to_polycontact - 0.5*contact.poly.width, self.cross_couple_upper_ypos) + left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x - self.poly_to_polycontact - 0.5*contact.poly.width, + self.cross_couple_upper_ypos) self.add_via_center(layers=("poly", "contact", "metal1"), offset=left_storage_contact, directions=("H","H")) - right_storage_contact = vector(self.inverter_nmos_right.get_pin("G").rc().x + self.poly_to_polycontact + 0.5*contact.poly.width, self.cross_couple_upper_ypos) + right_storage_contact = vector(self.inverter_nmos_right.get_pin("G").rc().x + self.poly_to_polycontact + 0.5*contact.poly.width, + self.cross_couple_upper_ypos) self.add_via_center(layers=("poly", "contact", "metal1"), offset=right_storage_contact, directions=("H","H")) From c2cc9013007f60d63e3be32af796a96ce365ab18 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 27 May 2019 16:32:38 -0700 Subject: [PATCH 025/234] Add boundary to every module and pgate for visual debug. --- compiler/base/hierarchy_layout.py | 7 +++++++ compiler/bitcells/pbitcell.py | 6 +----- compiler/modules/bank.py | 1 + compiler/modules/bank_select.py | 1 + compiler/modules/bitcell_array.py | 2 ++ compiler/modules/control_logic.py | 3 ++- compiler/modules/delay_chain.py | 3 ++- compiler/modules/dff_array.py | 1 + compiler/modules/dff_buf.py | 1 + compiler/modules/dff_buf_array.py | 1 + compiler/modules/dff_inv.py | 1 + compiler/modules/dff_inv_array.py | 1 + compiler/modules/hierarchical_decoder.py | 1 + compiler/modules/hierarchical_predecode2x4.py | 1 + compiler/modules/hierarchical_predecode3x8.py | 1 + compiler/modules/precharge_array.py | 1 + compiler/modules/replica_bitline.py | 1 + compiler/modules/sense_amp_array.py | 1 + compiler/modules/single_level_column_mux_array.py | 1 + compiler/modules/tri_gate_array.py | 1 + compiler/modules/wordline_driver.py | 1 + compiler/modules/write_driver_array.py | 1 + compiler/pgates/pgate.py | 7 ++++--- 23 files changed, 35 insertions(+), 10 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index e8c1b0b9..2972ecf8 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -879,6 +879,13 @@ class layout(): Wrapper to create a horizontal channel route """ self.create_channel_route(netlist, offset, layer_stack, pitch, vertical=False) + + def add_boundary(self): + """ Add boundary for debugging dimensions """ + self.add_rect(layer="boundary", + offset=vector(0,0), + height=self.height, + width=self.width) def add_enclosure(self, insts, layer="nwell"): """ Add a layer that surrounds the given instances. Useful diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index c9eb3f58..3f0a6073 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -36,6 +36,7 @@ class pbitcell(design.design): self.create_netlist() # We must always create the bitcell layout because some transistor sizes in the other netlists depend on it self.create_layout() + self.add_boundary() def create_netlist(self): self.add_pins() @@ -260,11 +261,6 @@ class pbitcell(design.design): self.height = self.topmost_ypos - self.botmost_ypos self.center_ypos = 0.5*(self.topmost_ypos + self.botmost_ypos) - # Add this boundary for visual debug - self.add_rect(layer="boundary", - offset=vector(self.leftmost_xpos,self.botmost_ypos), - height=self.height, - width=self.width) def create_storage(self): """ diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index a854c40b..e7ec2967 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -47,6 +47,7 @@ class bank(design.design): if not OPTS.netlist_only: debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.") self.create_layout() + self.add_boundary() def create_netlist(self): diff --git a/compiler/modules/bank_select.py b/compiler/modules/bank_select.py index ac866456..41588e70 100644 --- a/compiler/modules/bank_select.py +++ b/compiler/modules/bank_select.py @@ -42,6 +42,7 @@ class bank_select(design.design): self.place_instances() self.route_instances() + self.add_boundary() self.DRC_LVS() diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index f2ab77ac..0bc4011c 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -68,6 +68,8 @@ class bitcell_array(design.design): self.add_layout_pins() + self.add_boundary() + self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 0bf309a6..3c6e31b4 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -67,6 +67,7 @@ class control_logic(design.design): self.place_instances() self.route_all() #self.add_lvs_correspondence_points() + self.add_boundary() self.DRC_LVS() @@ -969,4 +970,4 @@ class control_logic(design.design): total_cin += self.wl_en_driver.get_cin() if self.port_type == 'rw': total_cin +=self.and2.get_cin() - return total_cin \ No newline at end of file + return total_cin diff --git a/compiler/modules/delay_chain.py b/compiler/modules/delay_chain.py index 188efffa..99b5875b 100644 --- a/compiler/modules/delay_chain.py +++ b/compiler/modules/delay_chain.py @@ -52,8 +52,9 @@ class delay_chain(design.design): self.place_inverters() self.route_inverters() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() - + def add_pins(self): """ Add the pins of the delay chain""" self.add_pin("in") diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 8b03fe19..53e6b0ba 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -44,6 +44,7 @@ class dff_array(design.design): self.place_dff_array() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 42e86bc0..d113cd14 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -55,6 +55,7 @@ class dff_buf(design.design): self.place_instances() self.route_wires() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index dfd38760..8b107f04 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -49,6 +49,7 @@ class dff_buf_array(design.design): self.height = self.rows * self.dff.height self.place_dff_array() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/dff_inv.py b/compiler/modules/dff_inv.py index 2f831570..7eecfc68 100644 --- a/compiler/modules/dff_inv.py +++ b/compiler/modules/dff_inv.py @@ -53,6 +53,7 @@ class dff_inv(design.design): self.add_wires() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py index 3ae50a08..c8743722 100644 --- a/compiler/modules/dff_inv_array.py +++ b/compiler/modules/dff_inv_array.py @@ -49,6 +49,7 @@ class dff_inv_array(design.design): self.place_dff_array() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 1eac268d..b316e631 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -54,6 +54,7 @@ class hierarchical_decoder(design.design): self.route_predecode_rails() self.route_vdd_gnd() self.offset_all_coordinates() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/hierarchical_predecode2x4.py b/compiler/modules/hierarchical_predecode2x4.py index 938196d3..1efdae20 100644 --- a/compiler/modules/hierarchical_predecode2x4.py +++ b/compiler/modules/hierarchical_predecode2x4.py @@ -47,6 +47,7 @@ class hierarchical_predecode2x4(hierarchical_predecode): self.place_output_inverters() self.place_nand_array() self.route() + self.add_boundary() self.DRC_LVS() def get_nand_input_line_combination(self): diff --git a/compiler/modules/hierarchical_predecode3x8.py b/compiler/modules/hierarchical_predecode3x8.py index 77d9ce01..85069202 100644 --- a/compiler/modules/hierarchical_predecode3x8.py +++ b/compiler/modules/hierarchical_predecode3x8.py @@ -52,6 +52,7 @@ class hierarchical_predecode3x8(hierarchical_predecode): self.place_output_inverters() self.place_nand_array() self.route() + self.add_boundary() self.DRC_LVS() def get_nand_input_line_combination(self): diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index f88938c8..fa19d3d5 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -51,6 +51,7 @@ class precharge_array(design.design): self.place_insts() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index acd1f5d0..1371bb68 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -49,6 +49,7 @@ class replica_bitline(design.design): self.width = self.replica_column_inst.rx() - self.delay_chain_inst.lx() + self.m2_pitch self.height = max(self.replica_column_inst.uy(), self.delay_chain_inst.uy()) + self.m3_pitch + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 4dfa03ad..81b2218d 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -50,6 +50,7 @@ class sense_amp_array(design.design): self.place_sense_amp_array() self.add_layout_pins() self.route_rails() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 435f0cbe..e7a72856 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -52,6 +52,7 @@ class single_level_column_mux_array(design.design): self.add_layout_pins() self.add_enclosure(self.mux_inst, "pwell") + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/tri_gate_array.py b/compiler/modules/tri_gate_array.py index e3eb42cb..54760572 100644 --- a/compiler/modules/tri_gate_array.py +++ b/compiler/modules/tri_gate_array.py @@ -41,6 +41,7 @@ class tri_gate_array(design.design): self.place_array() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index dbef0417..f81cdd1a 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -44,6 +44,7 @@ class wordline_driver(design.design): self.route_layout() self.route_vdd_gnd() self.offset_all_coordinates() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 27da84b0..c2ceb386 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -50,6 +50,7 @@ class write_driver_array(design.design): self.place_write_array() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index 57b73a21..40c04cb6 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -31,17 +31,18 @@ class pgate(design.design): self.create_netlist() if not OPTS.netlist_only: self.create_layout() + self.add_boundary() self.DRC_LVS() - def create_netlist(): + def create_netlist(self): """ Pure virtual function """ debug.error("Must over-ride create_netlist.",-1) - def create_layout(): + def create_layout(self): """ Pure virtual function """ debug.error("Must over-ride create_layout.",-1) - + def connect_pin_to_rail(self,inst,pin,supply): """ Connects a ptx pin to a supply rail. """ source_pin = inst.get_pin(pin) From 72f4a223c3c390250b8bc3f52f08fbee22765c95 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 27 May 2019 16:38:47 -0700 Subject: [PATCH 026/234] Move power pins before no route option --- compiler/sram_base.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/sram_base.py b/compiler/sram_base.py index 192bc669..be422135 100644 --- a/compiler/sram_base.py +++ b/compiler/sram_base.py @@ -129,14 +129,15 @@ class sram_base(design, verilog, lef): def route_supplies(self): """ Route the supply grid and connect the pins to them. """ + # Copy the pins to the top level + # This will either be used to route or left unconnected. + for inst in self.insts: + self.copy_power_pins(inst,"vdd") + self.copy_power_pins(inst,"gnd") # Do not route the power supply if not OPTS.route_supplies: return - for inst in self.insts: - self.copy_power_pins(inst,"vdd") - self.copy_power_pins(inst,"gnd") - from supply_router import supply_router as router layer_stack =("metal3","via3","metal4") rtr=router(layer_stack, self) @@ -579,4 +580,4 @@ class sram_base(design, verilog, lef): total_cin += self.data_dff.get_clk_cin() if self.col_addr_size > 0: total_cin += self.col_addr_dff.get_clk_cin() - return total_cin \ No newline at end of file + return total_cin From ad229b1504b5a3d77a113cbdcd08e63610ce37c3 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 28 May 2019 16:55:09 -0700 Subject: [PATCH 027/234] Altered indexing of objects in SRAM factory to remove duplications of items using OPTS names. Added smarter bitline name checking. --- compiler/base/hierarchy_design.py | 35 +++++- compiler/bitcells/bitcell.py | 8 ++ compiler/bitcells/bitcell_1rw_1r.py | 8 ++ compiler/bitcells/bitcell_1w_1r.py | 8 ++ compiler/bitcells/pbitcell.py | 7 ++ compiler/bitcells/replica_pbitcell.py | 1 + compiler/characterizer/delay.py | 171 ++++++++++++++++---------- compiler/modules/bitcell_array.py | 1 + compiler/sram_factory.py | 18 +-- 9 files changed, 182 insertions(+), 75 deletions(-) diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index f6b10530..a75e5a3c 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -143,38 +143,61 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): name_dict[si_port.lower()] = mod_info subinst.mod.build_names(name_dict, subinst_name, subinst_ports) - def find_aliases(self, inst_name, port_nets, path_nets, alias, alias_mod): + def find_aliases(self, inst_name, port_nets, path_nets, alias, alias_mod, exclusion_set=None): """Given a list of nets, will compare the internal alias of a mod to determine if the nets have a connection to this mod's net (but not inst). """ + #path_nets = ['xsram_0.xbank0.bl0_7'] + if exclusion_set == None: + exclusion_set = set() try: self.name_dict except AttributeError: self.name_dict = {} self.build_names(self.name_dict, inst_name, port_nets) + #debug.info(1,"names={}".format(list(self.name_dict))) aliases = [] for net in path_nets: net = net.lower() int_net = self.name_dict[net]['int_net'] int_mod = self.name_dict[net]['mod'] - if int_mod.is_net_alias(int_net, alias, alias_mod): + # debug.info(1,"int_net={}".format(int_net)) + # debug.info(1,"int_mod={}".format(int_mod.name)) + # debug.info(1,"alias_net={}".format(alias)) + # debug.info(1,"alias_mod={}".format(alias_mod.name)) + # debug.info(1,"mod id={}".format(id(alias_mod))) + if int_mod.is_net_alias(int_net, alias, alias_mod, exclusion_set): aliases.append(net) + # debug.info(1,"Alias found\n") + # else: + # debug.info(1,"Alias not found\n") debug.info(1,"Aliases Found={}".format(aliases)) return aliases - def is_net_alias(self, known_net, net_alias, mod): + def is_net_alias(self, known_net, net_alias, mod, exclusion_set): """Checks if the alias_net in mod is the same as the input net.""" + # debug.info(1,"self name={}".format(self.name)) + # debug.info(1,"self mod id={}".format(id(self))) + # debug.info(1,"self pins={}".format(self.pins)) + # debug.info(1,"known_net={}".format(known_net)) + if self in exclusion_set: + return False #Check ports of this mod for pin in self.pins: if self.is_net_alias_name_check(known_net, pin, net_alias, mod): return True - #Check connections of all other subinsts + #Check connections of all other subinsts + mod_set = set() for subinst, inst_conns in zip(self.insts, self.conns): for inst_conn, mod_pin in zip(inst_conns, subinst.mod.pins): if self.is_net_alias_name_check(known_net, inst_conn, net_alias, mod): return True - elif inst_conn.lower() == known_net.lower(): - return subinst.mod.is_net_alias(mod_pin, net_alias, mod) + elif inst_conn.lower() == known_net.lower() and subinst.mod not in mod_set: + # debug.info(1,"found matching conn={}".format(inst_conn)) + # debug.info(1,"Setting known pin={}".format(mod_pin)) + if subinst.mod.is_net_alias(mod_pin, net_alias, mod, exclusion_set): + return True + mod_set.add(subinst.mod) return False def is_net_alias_name_check(self, parent_net, child_net, alias_net, mod): diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 0de11375..b3f8dea1 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -71,6 +71,14 @@ class bitcell(design.design): column_pins = ["br"] return column_pins + def get_bl_name(self): + """Get bl name""" + return "bl" + + def get_br_name(self): + """Get bl name""" + return "br" + def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" from tech import spice diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index 6a6ebd92..f5aafa21 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -95,6 +95,14 @@ class bitcell_1rw_1r(design.design): column_pins = ["br0"] return column_pins + def get_bl_name(self, port=0): + """Get bl name by port""" + return "bl{}".format(port) + + def get_br_name(self, port=0): + """Get bl name by port""" + return "br{}".format(port) + def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" from tech import spice diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index dded6b30..6046020c 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -95,6 +95,14 @@ class bitcell_1w_1r(design.design): column_pins = ["br0"] return column_pins + def get_bl_name(self, port=0): + """Get bl name by port""" + return "bl{}".format(port) + + def get_br_name(self, port=0): + """Get bl name by port""" + return "br{}".format(port) + def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" from tech import spice diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 899da398..23d019cb 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -873,6 +873,13 @@ class pbitcell(design.design): """Returns names of storage nodes in bitcell in [non-inverting, inverting] format.""" return self.storage_nets + def get_bl_name(self, port=0): + """Get bl name by port""" + return "bl{}".format(port) + + def get_br_name(self, port=0): + """Get bl name by port""" + return "br{}".format(port) def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 diff --git a/compiler/bitcells/replica_pbitcell.py b/compiler/bitcells/replica_pbitcell.py index 30898d82..d39d361a 100644 --- a/compiler/bitcells/replica_pbitcell.py +++ b/compiler/bitcells/replica_pbitcell.py @@ -54,6 +54,7 @@ class replica_pbitcell(design.design): def add_modules(self): self.prbc = factory.create(module_type="pbitcell",replica_bitcell=True) + debug.info(1,"rbl bitcell name={}".format(self.prbc.name)) self.add_mod(self.prbc) self.height = self.prbc.height diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 3f97f885..3da84ede 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -78,18 +78,21 @@ class delay(simulation): """Create the measurements used for read ports: delays, slews, powers""" self.read_lib_meas = [] - trig_delay_name = "clk{0}" + self.clk_frmt = "clk{0}" #Unformatted clock name targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit - self.read_lib_meas.append(delay_measure("delay_lh", trig_delay_name, targ_name, "RISE", "RISE", measure_scale=1e9)) - self.read_lib_meas[-1].meta_str = sram_op.READ_ONE #Used to index time delay values when measurements written to spice file. - self.read_lib_meas.append(delay_measure("delay_hl", trig_delay_name, targ_name, "FALL", "FALL", measure_scale=1e9)) - self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO - self.delay_meas = self.read_lib_meas[:] #For debugging, kept separated + self.delay_meas = [] + self.delay_meas.append(delay_measure("delay_lh", self.clk_frmt, targ_name, "RISE", "RISE", measure_scale=1e9)) + self.delay_meas[-1].meta_str = sram_op.READ_ONE #Used to index time delay values when measurements written to spice file. + self.delay_meas.append(delay_measure("delay_hl", self.clk_frmt, targ_name, "FALL", "FALL", measure_scale=1e9)) + self.delay_meas[-1].meta_str = sram_op.READ_ZERO + self.read_lib_meas+=self.delay_meas - self.read_lib_meas.append(slew_measure("slew_lh", targ_name, "RISE", measure_scale=1e9)) - self.read_lib_meas[-1].meta_str = sram_op.READ_ONE - self.read_lib_meas.append(slew_measure("slew_hl", targ_name, "FALL", measure_scale=1e9)) - self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO + self.slew_meas = [] + self.slew_meas.append(slew_measure("slew_lh", targ_name, "RISE", measure_scale=1e9)) + self.slew_meas[-1].meta_str = sram_op.READ_ONE + self.slew_meas.append(slew_measure("slew_hl", targ_name, "FALL", measure_scale=1e9)) + self.slew_meas[-1].meta_str = sram_op.READ_ZERO + self.read_lib_meas+=self.slew_meas self.read_lib_meas.append(power_measure("read1_power", "RISE", measure_scale=1e3)) self.read_lib_meas[-1].meta_str = sram_op.READ_ONE @@ -162,11 +165,15 @@ class delay(simulation): self.debug_delay_meas.append(debug_meas) #Output voltage measures - self.debug_volt_meas.append(voltage_at_measure("v_{}".format(debug_meas.meta_str), + self.debug_volt_meas.append(voltage_at_measure("v_{}".format(debug_meas.name), debug_meas.targ_name_no_port)) self.debug_volt_meas[-1].meta_str = debug_meas.meta_str - - return self.debug_delay_meas+self.debug_volt_meas + + 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 + + return self.debug_delay_meas+self.debug_volt_meas+[self.sen_meas] def create_read_bit_measures(self): """Adds bit measurements for read0 and read1 cycles""" @@ -227,27 +234,11 @@ class delay(simulation): self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), \ '{}{}_{}'.format(self.dout_name, port, self.probe_data)) - sen_name = self.get_sen_name(self.graph.all_paths) - debug.info(1,"s_en name = {}".format(sen_name)) + self.sen_name = self.get_sen_name(self.graph.all_paths) + debug.info(1,"s_en name = {}".format(self.sen_name)) self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths) - import sys - sys.exit(1) - - preconv_names = [] - for path in self.graph.all_paths: - if not path is sen_path: - sen_preconv = self.graph.get_path_preconvergence_point(path, sen_path) - if sen_preconv not in preconv_names: - preconv_names.append(sen_preconv[0]) #only save non-sen_path names - - #Not an good way to separate inverting and non-inverting bitlines... - self.bl_name = [bl for bl in preconv_names if 'bl' in bl][0] - self.br_name = [bl for bl in preconv_names if 'br' in bl][0] - debug.info(1,"bl_name={}".format(self.bl_name)) - - (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, self.wordline_row, self.bitline_column) - debug.info(1, "cell_name={}".format(cell_name)) + debug.info(1,"bl name={}, br name={}".format(self.bl_name,self.br_name)) def get_sen_name(self, paths): """Gets the signal name associated with the sense amp enable from input paths. @@ -257,44 +248,85 @@ class delay(simulation): #will require some identification to determine the mod desired. 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_found = False - #Only a single path should contain a single s_en name. Anything else is an error. - for path in paths: - aliases = self.sram.find_aliases(self.sram_spc_name, self.pins, path, enable_name, sa_mods[0]) - if sen_found and len(aliases) >= 1: - debug.error('Found multiple paths with SA enable.',1) - elif len(aliases) > 1: - debug.error('Found multiple S_EN points in single path. Cannot distinguish between them.',1) - elif not sen_found and len(aliases) == 1: - sen_name = aliases[0] - sen_found = True - if not sen_found: - debug.error("Could not find S_EN name.",1) - + sen_name = self.get_alias_in_path(paths, enable_name, sa_mods[0]) return sen_name def get_bl_name(self, paths): """Gets the signal name associated with the bitlines in the bank.""" - sa_mods = factory.get_mods(OPTS.sense_amp) + cell_mods = factory.get_mods(OPTS.bitcell) + if len(cell_mods)>=1: + cell_mod = self.get_primary_cell_mod(cell_mods) + elif len(cell_mods)==0: + debug.error("No bitcells found. Cannot determine bitline names.", 1) #Any sense amp instantiated should be identical, any change to that #will require some identification to determine the mod desired. - 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_found = False + # debug.check(self.are_mod_pins_equal(cell_mods), "Only expected one type of bitcell. Cannot perform bitline checks") + # debug.info(1,"num pbitcells={}".format(len(cell_mods))) + # debug.info(1,"cell ids={}".format([id(i) for i in cell_mods])) + + #cell_mods = cell_mods[1:] + cell_bl = cell_mod.get_bl_name() + cell_br = cell_mod.get_br_name() + + bl_found = False #Only a single path should contain a single s_en name. Anything else is an error. - for path in paths: - aliases = self.sram.find_aliases(self.sram_spc_name, self.pins, path, enable_name, sa_mods[0]) - if sen_found and len(aliases) >= 1: - debug.error('Found multiple paths with SA enable.',1) - elif len(aliases) > 1: - debug.error('Found multiple S_EN points in single path. Cannot distinguish between them.',1) - elif not sen_found and len(aliases) == 1: - sen_name = aliases[0] - sen_found = True - if not sen_found: - debug.error("Could not find S_EN name.",1) + bl_names = [] + 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)) - return sen_name + return bl_names[0], bl_names[1] + + def get_bl_name_search_exclusions(self): + """Gets the mods as a set which should be excluded while searching for name.""" + #Exclude the RBL as it contains bitcells which are not in the main bitcell array + #so it makes the search awkward + return set(factory.get_mods(OPTS.replica_bitline)) + + def get_primary_cell_mod(self, cell_mods): + """Distinguish bitcell array mod from replica bitline array. + Assume there are no replica bitcells in the primary array.""" + if len(cell_mods) == 1: + return cell_mods[0] + rbc_mods = factory.get_mods(OPTS.replica_bitcell) + non_rbc_mods = [] + for bitcell in cell_mods: + has_cell = False + for replica_cell in rbc_mods: + has_cell = has_cell or replica_cell.contains(bitcell, replica_cell.mods) + if not has_cell: + non_rbc_mods.append(bitcell) + if len(non_rbc_mods) != 1: + debug.error('Multiple bitcell mods found. Cannot distinguish for characterization',1) + return non_rbc_mods[0] + + def are_mod_pins_equal(self, mods): + """Determines if there are pins differences in the input mods""" + if len(mods) == 0: + return True + pins = mods[0].pins + for mod in mods[1:]: + if pins != mod.pins: + return False + return True + + def get_alias_in_path(self, paths, int_net, mod, exclusion_set=None): + """Finds a single alias for the int_net in given paths. + More or less hits cause an error""" + net_found = False + for path in paths: + aliases = self.sram.find_aliases(self.sram_spc_name, self.pins, path, int_net, mod, exclusion_set) + if net_found and len(aliases) >= 1: + debug.error('Found multiple paths with {} net.'.format(int_net),1) + elif len(aliases) > 1: + debug.error('Found multiple {} nets in single path.'.format(int_net),1) + elif not net_found and len(aliases) == 1: + path_net_name = aliases[0] + net_found = True + if not net_found: + debug.error("Could not find {} net in timing paths.".format(int_net),1) + + return path_net_name def check_arguments(self): """Checks if arguments given for write_stimulus() meets requirements""" @@ -658,6 +690,10 @@ class delay(simulation): #Get measurements from output file for measure in self.read_lib_meas: read_port_dict[measure.name] = measure.retrieve_measure(port=port) + + #Check sen timing, then bitlines, then general measurements. + if not self.check_sen_measure(port): + return (False,{}) success = self.check_debug_measures(port, read_port_dict) success = success and self.check_bit_measures() #Check timing for read ports. Power is only checked if it was read correctly @@ -680,6 +716,17 @@ class delay(simulation): # The delay is from the negative edge for our SRAM return (sim_passed,result) + def check_sen_measure(self, port): + """Checks that the sen occurred within a half-period""" + self.sen_meas + sen_val = self.sen_meas.retrieve_measure(port=port) + debug.info(1,"S_EN delay={} ns".format(sen_val)) + if self.sen_meas.meta_add_delay: + max_delay = self.period/2 + else: + max_delay = self.period + return not (type(sen_val) != float or sen_val > max_delay) + def check_debug_measures(self, port, read_measures): """Debug measures that indicate special conditions.""" #Currently, only check if the opposite than intended value was read during diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 2380ee4b..361b922a 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -85,6 +85,7 @@ class bitcell_array(design.design): def add_modules(self): """ Add the modules used in this design """ self.cell = factory.create(module_type="bitcell") + debug.info(1,"Cell mod created, id={}".format(id(self.cell))) self.add_mod(self.cell) def create_instances(self): diff --git a/compiler/sram_factory.py b/compiler/sram_factory.py index 90478f4c..0b079780 100644 --- a/compiler/sram_factory.py +++ b/compiler/sram_factory.py @@ -46,16 +46,14 @@ class sram_factory: if hasattr(OPTS, module_type): # Retrieve the name from OPTS if it exists, # otherwise just use the name - module_name = getattr(OPTS, module_type) - else: - module_name = module_type - + module_type = getattr(OPTS, module_type) + # Either retrieve the already loaded module or load it try: mod = self.modules[module_type] except KeyError: - c = reload(__import__(module_name)) - mod = getattr(c, module_name) + c = reload(__import__(module_type)) + mod = getattr(c, module_type) self.modules[module_type] = mod self.module_indices[module_type] = 0 self.objects[module_type] = [] @@ -75,8 +73,10 @@ class sram_factory: # This is especially for library cells so that the spice and gds files can be found. if len(kwargs)>0: # Create a unique name and increment the index - module_name = "{0}_{1}".format(module_name, self.module_indices[module_type]) + module_name = "{0}_{1}".format(module_type, self.module_indices[module_type]) self.module_indices[module_type] += 1 + else: + module_name = module_type #debug.info(0, "New module: type={0} name={1} kwargs={2}".format(module_type,module_name,str(kwargs))) obj = mod(name=module_name,**kwargs) @@ -85,6 +85,10 @@ class sram_factory: def get_mods(self, module_type): """Returns list of all objects of module name's type.""" + if hasattr(OPTS, module_type): + # Retrieve the name from OPTS if it exists, + # otherwise just use the input + module_type = getattr(OPTS, module_type) try: mod_tuples = self.objects[module_type] mods = [mod for kwargs,mod in mod_tuples] From 36214792ebfcb178b971a7e65869470260194b57 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 28 May 2019 17:04:27 -0700 Subject: [PATCH 028/234] Removed some debug measurements that were causing failures. --- compiler/characterizer/delay.py | 46 +++++---------------------------- 1 file changed, 7 insertions(+), 39 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 3da84ede..a927ef69 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -149,31 +149,18 @@ class delay(simulation): def create_debug_measurement_objects(self): """Create debug measurement to help identify failures.""" - - self.debug_delay_meas = [] self.debug_volt_meas = [] for meas in self.delay_meas: - debug_meas = copy.deepcopy(meas) - debug_meas.name = debug_meas.name+'_debug' - #This particular debugs check if output value is flipped, so TARG_DIR is flipped - if meas.targ_dir_str == 'FALL': - debug_meas.targ_dir_str = 'RISE' - else: - debug_meas.targ_dir_str = 'FALL' - #inserting debug member variable - debug_meas.parent = meas.name - self.debug_delay_meas.append(debug_meas) - #Output voltage measures - self.debug_volt_meas.append(voltage_at_measure("v_{}".format(debug_meas.name), - debug_meas.targ_name_no_port)) - self.debug_volt_meas[-1].meta_str = debug_meas.meta_str + self.debug_volt_meas.append(voltage_at_measure("v_{}".format(meas.name), + meas.targ_name_no_port)) + self.debug_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) self.sen_meas.meta_str = sram_op.READ_ZERO self.sen_meas.meta_add_delay = True - return self.debug_delay_meas+self.debug_volt_meas+[self.sen_meas] + return self.debug_volt_meas+[self.sen_meas] def create_read_bit_measures(self): """Adds bit measurements for read0 and read1 cycles""" @@ -694,7 +681,7 @@ class delay(simulation): #Check sen timing, then bitlines, then general measurements. if not self.check_sen_measure(port): return (False,{}) - success = self.check_debug_measures(port, read_port_dict) + success = self.check_debug_measures(port) success = success and self.check_bit_measures() #Check timing for read ports. Power is only checked if it was read correctly if not self.check_valid_delays(read_port_dict) or not success: @@ -727,30 +714,11 @@ class delay(simulation): max_delay = self.period return not (type(sen_val) != float or sen_val > max_delay) - def check_debug_measures(self, port, read_measures): + def check_debug_measures(self, port): """Debug measures that indicate special conditions.""" #Currently, only check if the opposite than intended value was read during # the read cycles i.e. neither of these measurements should pass. - success = True - for meas in self.debug_delay_meas: - val = meas.retrieve_measure(port=port) - debug.info(2,"{}={}".format(meas.name, val)) - if type(val) != float: - continue - - if meas.meta_add_delay: - max_delay = self.period/2 - else: - max_delay = self.period - - #If the debug measurement occurs after the original (and passes other conditions) - #then it fails i.e. the debug value represents the final (but failing) state of the output - parent_compare = type(read_measures[meas.parent]) != float or val > read_measures[meas.parent] - if 0 < val < max_delay and parent_compare: - success = False - debug.info(1, "Debug measurement failed. Incorrect Value found on output.") - break - + success = True #FIXME: these checks need to be re-done to be more robust against possible errors bl_vals = {} br_vals = {} From bf869699721d6c667fe7b39648d431bfab33a881 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 31 May 2019 08:56:24 -0700 Subject: [PATCH 029/234] Create sram subdirectory. --- compiler/{ => sram}/sram.py | 0 compiler/{ => sram}/sram_1bank.py | 0 compiler/{ => sram}/sram_2bank.py | 0 compiler/{ => sram}/sram_base.py | 0 compiler/{ => sram}/sram_config.py | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename compiler/{ => sram}/sram.py (100%) rename compiler/{ => sram}/sram_1bank.py (100%) rename compiler/{ => sram}/sram_2bank.py (100%) rename compiler/{ => sram}/sram_base.py (100%) rename compiler/{ => sram}/sram_config.py (100%) diff --git a/compiler/sram.py b/compiler/sram/sram.py similarity index 100% rename from compiler/sram.py rename to compiler/sram/sram.py diff --git a/compiler/sram_1bank.py b/compiler/sram/sram_1bank.py similarity index 100% rename from compiler/sram_1bank.py rename to compiler/sram/sram_1bank.py diff --git a/compiler/sram_2bank.py b/compiler/sram/sram_2bank.py similarity index 100% rename from compiler/sram_2bank.py rename to compiler/sram/sram_2bank.py diff --git a/compiler/sram_base.py b/compiler/sram/sram_base.py similarity index 100% rename from compiler/sram_base.py rename to compiler/sram/sram_base.py diff --git a/compiler/sram_config.py b/compiler/sram/sram_config.py similarity index 100% rename from compiler/sram_config.py rename to compiler/sram/sram_config.py From d789f937432f278413bbefcc3a6562192d52fee1 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 31 May 2019 10:51:42 -0700 Subject: [PATCH 030/234] Add debug runner during individual tests. --- compiler/modules/bank.py | 2 +- compiler/tests/00_code_format_check_test.py | 8 ++++---- compiler/tests/01_library_drc_test.py | 6 +++--- compiler/tests/02_library_lvs_test.py | 6 +++--- compiler/tests/03_contact_test.py | 6 +++--- compiler/tests/03_path_test.py | 6 +++--- compiler/tests/03_ptx_1finger_nmos_test.py | 6 +++--- compiler/tests/03_ptx_1finger_pmos_test.py | 6 +++--- compiler/tests/03_ptx_3finger_nmos_test.py | 6 +++--- compiler/tests/03_ptx_3finger_pmos_test.py | 6 +++--- compiler/tests/03_ptx_4finger_nmos_test.py | 6 +++--- compiler/tests/03_ptx_4finger_pmos_test.py | 6 +++--- compiler/tests/03_wire_test.py | 6 +++--- compiler/tests/04_pand2_test.py | 6 +++--- compiler/tests/04_pbitcell_test.py | 6 +++--- compiler/tests/04_pbuf_test.py | 6 +++--- compiler/tests/04_pdriver_test.py | 6 +++--- compiler/tests/04_pinv_10x_test.py | 6 +++--- compiler/tests/04_pinv_1x_beta_test.py | 6 +++--- compiler/tests/04_pinv_1x_test.py | 6 +++--- compiler/tests/04_pinv_2x_test.py | 6 +++--- compiler/tests/04_pinvbuf_test.py | 6 +++--- compiler/tests/04_pnand2_test.py | 6 +++--- compiler/tests/04_pnand3_test.py | 6 +++--- compiler/tests/04_pnor2_test.py | 6 +++--- compiler/tests/04_precharge_test.py | 6 +++--- compiler/tests/04_replica_pbitcell_test.py | 6 +++--- .../tests/04_single_level_column_mux_test.py | 6 +++--- .../tests/05_bitcell_1rw_1r_array_test.py | 6 +++--- compiler/tests/05_bitcell_array_test.py | 6 +++--- compiler/tests/05_pbitcell_array_test.py | 6 +++--- .../tests/06_hierarchical_decoder_test.py | 6 +++--- .../06_hierarchical_predecode2x4_test.py | 6 +++--- .../06_hierarchical_predecode3x8_test.py | 6 +++--- .../07_single_level_column_mux_array_test.py | 6 +++--- compiler/tests/08_precharge_array_test.py | 6 +++--- compiler/tests/08_wordline_driver_test.py | 6 +++--- compiler/tests/09_sense_amp_array_test.py | 6 +++--- compiler/tests/10_write_driver_array_test.py | 6 +++--- compiler/tests/11_dff_array_test.py | 6 +++--- compiler/tests/11_dff_buf_array_test.py | 6 +++--- compiler/tests/11_dff_buf_test.py | 6 +++--- compiler/tests/12_tri_gate_array_test.py | 6 +++--- compiler/tests/13_delay_chain_test.py | 6 +++--- .../14_replica_bitline_multiport_test.py | 6 +++--- compiler/tests/14_replica_bitline_test.py | 6 +++--- compiler/tests/16_control_logic_test.py | 6 +++--- compiler/tests/19_bank_select_test.py | 6 +++--- compiler/tests/19_multi_bank_test.py | 6 +++--- compiler/tests/19_pmulti_bank_test.py | 6 +++--- compiler/tests/19_psingle_bank_test.py | 6 +++--- compiler/tests/19_single_bank_1rw_1r_test.py | 6 +++--- compiler/tests/19_single_bank_test.py | 6 +++--- .../tests/20_psram_1bank_2mux_1rw_1w_test.py | 6 +++--- .../tests/20_psram_1bank_2mux_1w_1r_test.py | 6 +++--- compiler/tests/20_psram_1bank_2mux_test.py | 6 +++--- .../tests/20_psram_1bank_4mux_1rw_1r_test.py | 6 +++--- .../tests/20_sram_1bank_2mux_1rw_1r_test.py | 6 +++--- .../tests/20_sram_1bank_2mux_1w_1r_test.py | 6 +++--- compiler/tests/20_sram_1bank_2mux_test.py | 6 +++--- compiler/tests/20_sram_1bank_4mux_test.py | 6 +++--- .../tests/20_sram_1bank_8mux_1rw_1r_test.py | 6 +++--- compiler/tests/20_sram_1bank_8mux_test.py | 6 +++--- .../tests/20_sram_1bank_nomux_1rw_1r_test.py | 6 +++--- compiler/tests/20_sram_1bank_nomux_test.py | 6 +++--- compiler/tests/20_sram_2bank_test.py | 6 +++--- compiler/tests/21_hspice_delay_test.py | 6 +++--- compiler/tests/21_hspice_setuphold_test.py | 6 +++--- compiler/tests/21_model_delay_test.py | 6 +++--- compiler/tests/21_ngspice_delay_test.py | 6 +++--- compiler/tests/21_ngspice_setuphold_test.py | 6 +++--- .../tests/22_psram_1bank_2mux_func_test.py | 6 +++--- .../tests/22_psram_1bank_4mux_func_test.py | 6 +++--- .../tests/22_psram_1bank_8mux_func_test.py | 6 +++--- .../tests/22_psram_1bank_nomux_func_test.py | 6 +++--- .../tests/22_sram_1bank_2mux_func_test.py | 6 +++--- .../tests/22_sram_1bank_4mux_func_test.py | 6 +++--- .../tests/22_sram_1bank_8mux_func_test.py | 6 +++--- .../tests/22_sram_1bank_nomux_func_test.py | 6 +++--- .../22_sram_1rw_1r_1bank_nomux_func_test.py | 6 +++--- .../tests/23_lib_sram_model_corners_test.py | 6 +++--- compiler/tests/23_lib_sram_model_test.py | 6 +++--- compiler/tests/23_lib_sram_prune_test.py | 6 +++--- compiler/tests/23_lib_sram_test.py | 6 +++--- compiler/tests/24_lef_sram_test.py | 6 +++--- compiler/tests/25_verilog_sram_test.py | 6 +++--- compiler/tests/26_pex_test.py | 6 +++--- compiler/tests/30_openram_back_end_test.py | 6 +++--- compiler/tests/30_openram_front_end_test.py | 6 +++--- compiler/tests/regress.py | 4 ++-- compiler/tests/testutils.py | 19 ++++++++++++++++++- 91 files changed, 286 insertions(+), 269 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index a854c40b..ced244e9 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -352,7 +352,7 @@ class bank(design.design): self.addr_size = self.col_addr_size + self.row_addr_size debug.check(self.num_rows*self.num_cols==self.word_size*self.num_words,"Invalid bank sizes.") - debug.check(self.addr_size==self.col_addr_size + self.row_addr_size,"Invalid address break down.") + debug.check(1+self.addr_size==self.col_addr_size + self.row_addr_size,"Invalid address break down.") # Width for the vdd/gnd rails self.supply_rail_width = 4*self.m2_width diff --git a/compiler/tests/00_code_format_check_test.py b/compiler/tests/00_code_format_check_test.py index 373b1516..af5f1abc 100755 --- a/compiler/tests/00_code_format_check_test.py +++ b/compiler/tests/00_code_format_check_test.py @@ -8,9 +8,9 @@ # import unittest -from testutils import header,openram_test +from testutils import * import sys,os,re -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals import debug @@ -51,7 +51,7 @@ def setup_files(path): files = [] for (dir, _, current_files) in os.walk(path): for f in current_files: - files.append(os.path.join(dir, f)) + files.append(os.getenv("OPENRAM_HOME")) nametest = re.compile("\.py$", re.IGNORECASE) select_files = list(filter(nametest.search, files)) return select_files @@ -122,4 +122,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/01_library_drc_test.py b/compiler/tests/01_library_drc_test.py index c2052e4e..41c83e6e 100755 --- a/compiler/tests/01_library_drc_test.py +++ b/compiler/tests/01_library_drc_test.py @@ -9,9 +9,9 @@ "Run a regression test the library cells for DRC" import unittest -from testutils import header,openram_test +from testutils import * import sys,os,re -#sys.path.append(os.path.join(sys.path[0],"..")) +#sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -51,5 +51,5 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/02_library_lvs_test.py b/compiler/tests/02_library_lvs_test.py index 6775f41f..2366f148 100755 --- a/compiler/tests/02_library_lvs_test.py +++ b/compiler/tests/02_library_lvs_test.py @@ -9,9 +9,9 @@ "Run a regression test the library cells for LVS" import unittest -from testutils import header,openram_test +from testutils import * import sys,os,re -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -74,4 +74,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/03_contact_test.py b/compiler/tests/03_contact_test.py index 2aa79df6..5daebaa5 100755 --- a/compiler/tests/03_contact_test.py +++ b/compiler/tests/03_contact_test.py @@ -9,9 +9,9 @@ "Run a regression test for DRC on basic contacts of different array sizes" import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -69,4 +69,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/03_path_test.py b/compiler/tests/03_path_test.py index 4748e18d..bf24008c 100755 --- a/compiler/tests/03_path_test.py +++ b/compiler/tests/03_path_test.py @@ -9,9 +9,9 @@ "Run a regression test on a basic path" import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -96,4 +96,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/03_ptx_1finger_nmos_test.py b/compiler/tests/03_ptx_1finger_nmos_test.py index cc6d6ed6..27cf9469 100755 --- a/compiler/tests/03_ptx_1finger_nmos_test.py +++ b/compiler/tests/03_ptx_1finger_nmos_test.py @@ -9,9 +9,9 @@ "Run a regression test on a basic parameterized transistors" import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -38,4 +38,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/03_ptx_1finger_pmos_test.py b/compiler/tests/03_ptx_1finger_pmos_test.py index cd2128be..db9db687 100755 --- a/compiler/tests/03_ptx_1finger_pmos_test.py +++ b/compiler/tests/03_ptx_1finger_pmos_test.py @@ -9,9 +9,9 @@ "Run a regression test on a basic parameterized transistors" import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -38,4 +38,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/03_ptx_3finger_nmos_test.py b/compiler/tests/03_ptx_3finger_nmos_test.py index 8231f090..370c10a4 100755 --- a/compiler/tests/03_ptx_3finger_nmos_test.py +++ b/compiler/tests/03_ptx_3finger_nmos_test.py @@ -9,9 +9,9 @@ "Run a regression test on a basic parameterized transistors" import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -40,4 +40,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/03_ptx_3finger_pmos_test.py b/compiler/tests/03_ptx_3finger_pmos_test.py index 16e3730b..c67bdac3 100755 --- a/compiler/tests/03_ptx_3finger_pmos_test.py +++ b/compiler/tests/03_ptx_3finger_pmos_test.py @@ -9,9 +9,9 @@ "Run a regression test on a basic parameterized transistors" import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -40,4 +40,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/03_ptx_4finger_nmos_test.py b/compiler/tests/03_ptx_4finger_nmos_test.py index c0a54d85..7a4667bd 100755 --- a/compiler/tests/03_ptx_4finger_nmos_test.py +++ b/compiler/tests/03_ptx_4finger_nmos_test.py @@ -9,9 +9,9 @@ "Run a regression test on a basic parameterized transistors" import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -40,4 +40,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/03_ptx_4finger_pmos_test.py b/compiler/tests/03_ptx_4finger_pmos_test.py index afb874af..fe73946e 100755 --- a/compiler/tests/03_ptx_4finger_pmos_test.py +++ b/compiler/tests/03_ptx_4finger_pmos_test.py @@ -9,9 +9,9 @@ "Run a regression test on a basic parameterized transistors" import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -40,4 +40,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/03_wire_test.py b/compiler/tests/03_wire_test.py index 3b3388e9..f702c7b5 100755 --- a/compiler/tests/03_wire_test.py +++ b/compiler/tests/03_wire_test.py @@ -9,9 +9,9 @@ "Run a regression test on a basic wire" import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -133,4 +133,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pand2_test.py b/compiler/tests/04_pand2_test.py index af99f6ec..bd2297da 100755 --- a/compiler/tests/04_pand2_test.py +++ b/compiler/tests/04_pand2_test.py @@ -11,9 +11,9 @@ Run a regression test on a pand2 cell """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -39,4 +39,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pbitcell_test.py b/compiler/tests/04_pbitcell_test.py index e8b7cb55..77e4a313 100755 --- a/compiler/tests/04_pbitcell_test.py +++ b/compiler/tests/04_pbitcell_test.py @@ -11,9 +11,9 @@ Run regresion tests on a parameterized bitcell """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -114,4 +114,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pbuf_test.py b/compiler/tests/04_pbuf_test.py index 9eeaaeab..988723a1 100755 --- a/compiler/tests/04_pbuf_test.py +++ b/compiler/tests/04_pbuf_test.py @@ -11,9 +11,9 @@ Run a regression test on a 2-row buffer cell """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -35,4 +35,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pdriver_test.py b/compiler/tests/04_pdriver_test.py index ecd697c9..c08ecda9 100755 --- a/compiler/tests/04_pdriver_test.py +++ b/compiler/tests/04_pdriver_test.py @@ -11,9 +11,9 @@ Run a regression test on a 2-row buffer cell """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -51,4 +51,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pinv_10x_test.py b/compiler/tests/04_pinv_10x_test.py index 0548cbf4..51caecaf 100755 --- a/compiler/tests/04_pinv_10x_test.py +++ b/compiler/tests/04_pinv_10x_test.py @@ -11,9 +11,9 @@ Run regression tests on a parameterized inverter """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -36,4 +36,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pinv_1x_beta_test.py b/compiler/tests/04_pinv_1x_beta_test.py index 1f8aae26..5b993f8d 100755 --- a/compiler/tests/04_pinv_1x_beta_test.py +++ b/compiler/tests/04_pinv_1x_beta_test.py @@ -11,9 +11,9 @@ Run regression tests on a parameterized inverter """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -35,4 +35,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pinv_1x_test.py b/compiler/tests/04_pinv_1x_test.py index fd70d8dc..46f1ca08 100755 --- a/compiler/tests/04_pinv_1x_test.py +++ b/compiler/tests/04_pinv_1x_test.py @@ -10,9 +10,9 @@ Run regression tests on a parameterized inverter """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -34,4 +34,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pinv_2x_test.py b/compiler/tests/04_pinv_2x_test.py index 6b472f9e..cf65c2eb 100755 --- a/compiler/tests/04_pinv_2x_test.py +++ b/compiler/tests/04_pinv_2x_test.py @@ -11,9 +11,9 @@ Run regression tests on a parameterized inverter """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -36,4 +36,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pinvbuf_test.py b/compiler/tests/04_pinvbuf_test.py index ea407d0c..40db6c2b 100755 --- a/compiler/tests/04_pinvbuf_test.py +++ b/compiler/tests/04_pinvbuf_test.py @@ -11,9 +11,9 @@ Run a regression test on a 2-row buffer cell """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -35,4 +35,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pnand2_test.py b/compiler/tests/04_pnand2_test.py index 527c6204..8aa94f1f 100755 --- a/compiler/tests/04_pnand2_test.py +++ b/compiler/tests/04_pnand2_test.py @@ -13,9 +13,9 @@ size 2-input nand gate. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -38,4 +38,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pnand3_test.py b/compiler/tests/04_pnand3_test.py index 6dba468a..e0da23f9 100755 --- a/compiler/tests/04_pnand3_test.py +++ b/compiler/tests/04_pnand3_test.py @@ -13,9 +13,9 @@ It generates only a minimum size 3-input nand gate. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -38,4 +38,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_pnor2_test.py b/compiler/tests/04_pnor2_test.py index 8a66324d..6b245941 100755 --- a/compiler/tests/04_pnor2_test.py +++ b/compiler/tests/04_pnor2_test.py @@ -13,9 +13,9 @@ size 2-input nor gate. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -37,4 +37,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_precharge_test.py b/compiler/tests/04_precharge_test.py index 162f1091..11065f71 100755 --- a/compiler/tests/04_precharge_test.py +++ b/compiler/tests/04_precharge_test.py @@ -11,9 +11,9 @@ Run a regression test on a precharge cell """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -57,4 +57,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_replica_pbitcell_test.py b/compiler/tests/04_replica_pbitcell_test.py index 1e028e40..da23bbce 100755 --- a/compiler/tests/04_replica_pbitcell_test.py +++ b/compiler/tests/04_replica_pbitcell_test.py @@ -11,9 +11,9 @@ Run a regression test on a replica pbitcell """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -51,4 +51,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/04_single_level_column_mux_test.py b/compiler/tests/04_single_level_column_mux_test.py index 151f2797..81a67995 100755 --- a/compiler/tests/04_single_level_column_mux_test.py +++ b/compiler/tests/04_single_level_column_mux_test.py @@ -11,9 +11,9 @@ Run a regression test on a wordline_driver array """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -54,4 +54,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/05_bitcell_1rw_1r_array_test.py b/compiler/tests/05_bitcell_1rw_1r_array_test.py index 9df2c8c3..21b6d1d6 100755 --- a/compiler/tests/05_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/05_bitcell_1rw_1r_array_test.py @@ -11,9 +11,9 @@ Run a regression test on a basic array """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -41,4 +41,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/05_bitcell_array_test.py b/compiler/tests/05_bitcell_array_test.py index 21943a5d..9184f69d 100755 --- a/compiler/tests/05_bitcell_array_test.py +++ b/compiler/tests/05_bitcell_array_test.py @@ -11,9 +11,9 @@ Run a regression test on a basic array """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -37,4 +37,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/05_pbitcell_array_test.py b/compiler/tests/05_pbitcell_array_test.py index 45968266..05640dd7 100755 --- a/compiler/tests/05_pbitcell_array_test.py +++ b/compiler/tests/05_pbitcell_array_test.py @@ -11,9 +11,9 @@ Run a regression test on a basic array """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -56,4 +56,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/06_hierarchical_decoder_test.py b/compiler/tests/06_hierarchical_decoder_test.py index bcc22ce8..02726aeb 100755 --- a/compiler/tests/06_hierarchical_decoder_test.py +++ b/compiler/tests/06_hierarchical_decoder_test.py @@ -11,9 +11,9 @@ Run a regression test on a hierarchical_decoder. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -80,4 +80,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/06_hierarchical_predecode2x4_test.py b/compiler/tests/06_hierarchical_predecode2x4_test.py index e4687d5e..f331fadf 100755 --- a/compiler/tests/06_hierarchical_predecode2x4_test.py +++ b/compiler/tests/06_hierarchical_predecode2x4_test.py @@ -11,9 +11,9 @@ Run a regression test on a hierarchical_predecode2x4. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -46,4 +46,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/06_hierarchical_predecode3x8_test.py b/compiler/tests/06_hierarchical_predecode3x8_test.py index 12e87d06..763732c5 100755 --- a/compiler/tests/06_hierarchical_predecode3x8_test.py +++ b/compiler/tests/06_hierarchical_predecode3x8_test.py @@ -11,9 +11,9 @@ Run a regression test on a hierarchical_predecode3x8. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -46,4 +46,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/07_single_level_column_mux_array_test.py b/compiler/tests/07_single_level_column_mux_array_test.py index 8da5f252..2a919f6a 100755 --- a/compiler/tests/07_single_level_column_mux_array_test.py +++ b/compiler/tests/07_single_level_column_mux_array_test.py @@ -10,9 +10,9 @@ Run a regression test on a single transistor column_mux. """ -from testutils import header,openram_test,unittest +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -68,4 +68,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/08_precharge_array_test.py b/compiler/tests/08_precharge_array_test.py index 86f308f4..4b406a74 100755 --- a/compiler/tests/08_precharge_array_test.py +++ b/compiler/tests/08_precharge_array_test.py @@ -11,9 +11,9 @@ Run a regression test on a precharge array """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -55,4 +55,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/08_wordline_driver_test.py b/compiler/tests/08_wordline_driver_test.py index 585b85cd..595f0ab3 100755 --- a/compiler/tests/08_wordline_driver_test.py +++ b/compiler/tests/08_wordline_driver_test.py @@ -11,9 +11,9 @@ Run a regression test on a wordline_driver array """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -49,4 +49,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/09_sense_amp_array_test.py b/compiler/tests/09_sense_amp_array_test.py index 12a20e8f..7c88ab1f 100755 --- a/compiler/tests/09_sense_amp_array_test.py +++ b/compiler/tests/09_sense_amp_array_test.py @@ -11,9 +11,9 @@ Run a regression test on a sense amp array """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -55,4 +55,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/10_write_driver_array_test.py b/compiler/tests/10_write_driver_array_test.py index f5d0c23c..af7b8557 100755 --- a/compiler/tests/10_write_driver_array_test.py +++ b/compiler/tests/10_write_driver_array_test.py @@ -11,9 +11,9 @@ Run a regression test on a write driver array """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -55,4 +55,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/11_dff_array_test.py b/compiler/tests/11_dff_array_test.py index fc48adce..bd5e12ca 100755 --- a/compiler/tests/11_dff_array_test.py +++ b/compiler/tests/11_dff_array_test.py @@ -11,9 +11,9 @@ Run a regression test on a dff_array. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -43,4 +43,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/11_dff_buf_array_test.py b/compiler/tests/11_dff_buf_array_test.py index 7d614d1b..3a011258 100755 --- a/compiler/tests/11_dff_buf_array_test.py +++ b/compiler/tests/11_dff_buf_array_test.py @@ -11,9 +11,9 @@ Run a regression test on a dff_array. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -43,4 +43,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/11_dff_buf_test.py b/compiler/tests/11_dff_buf_test.py index afb1f73b..e0c20191 100755 --- a/compiler/tests/11_dff_buf_test.py +++ b/compiler/tests/11_dff_buf_test.py @@ -11,9 +11,9 @@ Run a regression test on a dff_buf. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -35,4 +35,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/12_tri_gate_array_test.py b/compiler/tests/12_tri_gate_array_test.py index 203c5f94..e3b96697 100755 --- a/compiler/tests/12_tri_gate_array_test.py +++ b/compiler/tests/12_tri_gate_array_test.py @@ -11,9 +11,9 @@ Run a regression test on a tri_gate_array. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -39,4 +39,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/13_delay_chain_test.py b/compiler/tests/13_delay_chain_test.py index 498c1005..25f2ab4c 100755 --- a/compiler/tests/13_delay_chain_test.py +++ b/compiler/tests/13_delay_chain_test.py @@ -11,9 +11,9 @@ Run a test on a delay chain """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -35,4 +35,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/14_replica_bitline_multiport_test.py b/compiler/tests/14_replica_bitline_multiport_test.py index 947f9c52..3e3827c9 100755 --- a/compiler/tests/14_replica_bitline_multiport_test.py +++ b/compiler/tests/14_replica_bitline_multiport_test.py @@ -11,9 +11,9 @@ Run a test on a multiport replica bitline """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -67,4 +67,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/14_replica_bitline_test.py b/compiler/tests/14_replica_bitline_test.py index b5830d63..546f81ea 100755 --- a/compiler/tests/14_replica_bitline_test.py +++ b/compiler/tests/14_replica_bitline_test.py @@ -11,9 +11,9 @@ Run a test on a replica bitline """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -45,4 +45,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index ed8a0088..b701a47f 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -11,9 +11,9 @@ Run a regression test on a control_logic """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -70,4 +70,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/19_bank_select_test.py b/compiler/tests/19_bank_select_test.py index 5ea16052..339e1d99 100755 --- a/compiler/tests/19_bank_select_test.py +++ b/compiler/tests/19_bank_select_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -52,4 +52,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/19_multi_bank_test.py b/compiler/tests/19_multi_bank_test.py index 3139b4eb..46a2e5c5 100755 --- a/compiler/tests/19_multi_bank_test.py +++ b/compiler/tests/19_multi_bank_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -69,4 +69,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/19_pmulti_bank_test.py b/compiler/tests/19_pmulti_bank_test.py index f31e2608..62cd63fa 100755 --- a/compiler/tests/19_pmulti_bank_test.py +++ b/compiler/tests/19_pmulti_bank_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -74,4 +74,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/19_psingle_bank_test.py b/compiler/tests/19_psingle_bank_test.py index 22c3da2f..8829a170 100755 --- a/compiler/tests/19_psingle_bank_test.py +++ b/compiler/tests/19_psingle_bank_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -161,4 +161,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/19_single_bank_1rw_1r_test.py b/compiler/tests/19_single_bank_1rw_1r_test.py index fb0e1c66..9be071f3 100755 --- a/compiler/tests/19_single_bank_1rw_1r_test.py +++ b/compiler/tests/19_single_bank_1rw_1r_test.py @@ -11,9 +11,9 @@ Run a regression test on 1rw 1r sram bank """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -72,4 +72,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/19_single_bank_test.py b/compiler/tests/19_single_bank_test.py index 72e61c0d..5cf6e326 100755 --- a/compiler/tests/19_single_bank_test.py +++ b/compiler/tests/19_single_bank_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -67,4 +67,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py b/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py index 4bdad91f..a0ec81a0 100755 --- a/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py +++ b/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -57,4 +57,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py b/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py index a0b2b242..c642c1f5 100755 --- a/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py +++ b/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -55,4 +55,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_psram_1bank_2mux_test.py b/compiler/tests/20_psram_1bank_2mux_test.py index c718daa3..f9ecaa42 100755 --- a/compiler/tests/20_psram_1bank_2mux_test.py +++ b/compiler/tests/20_psram_1bank_2mux_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -58,4 +58,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py b/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py index f415bd77..0bfe26cd 100755 --- a/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py +++ b/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -56,4 +56,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py index 46725bc5..108cd44c 100755 --- a/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank, 2 port SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -56,4 +56,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py b/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py index fec42aeb..b0ca96e2 100755 --- a/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py +++ b/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -57,4 +57,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_sram_1bank_2mux_test.py b/compiler/tests/20_sram_1bank_2mux_test.py index c61ebe4f..db67d980 100755 --- a/compiler/tests/20_sram_1bank_2mux_test.py +++ b/compiler/tests/20_sram_1bank_2mux_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -50,4 +50,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_sram_1bank_4mux_test.py b/compiler/tests/20_sram_1bank_4mux_test.py index 5d10903c..b5e2df8a 100755 --- a/compiler/tests/20_sram_1bank_4mux_test.py +++ b/compiler/tests/20_sram_1bank_4mux_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -50,4 +50,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py index 3a2c34e6..1924f674 100755 --- a/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -56,4 +56,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_sram_1bank_8mux_test.py b/compiler/tests/20_sram_1bank_8mux_test.py index 94c073f9..b1809e8a 100755 --- a/compiler/tests/20_sram_1bank_8mux_test.py +++ b/compiler/tests/20_sram_1bank_8mux_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -50,4 +50,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py index 2ce13456..ffc326af 100755 --- a/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank, 2 port SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -56,4 +56,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_sram_1bank_nomux_test.py b/compiler/tests/20_sram_1bank_nomux_test.py index 272d16ee..77d97178 100755 --- a/compiler/tests/20_sram_1bank_nomux_test.py +++ b/compiler/tests/20_sram_1bank_nomux_test.py @@ -11,9 +11,9 @@ Run a regression test on a 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -50,4 +50,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/20_sram_2bank_test.py b/compiler/tests/20_sram_2bank_test.py index b625f9ec..df68b623 100755 --- a/compiler/tests/20_sram_2bank_test.py +++ b/compiler/tests/20_sram_2bank_test.py @@ -11,9 +11,9 @@ Run a regression test on a 2 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -100,4 +100,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index aa6cbf49..2008c097 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -94,4 +94,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/21_hspice_setuphold_test.py b/compiler/tests/21_hspice_setuphold_test.py index 49c0d2cb..b8f81cf5 100755 --- a/compiler/tests/21_hspice_setuphold_test.py +++ b/compiler/tests/21_hspice_setuphold_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -65,4 +65,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/21_model_delay_test.py b/compiler/tests/21_model_delay_test.py index c54a9118..ae6d2800 100755 --- a/compiler/tests/21_model_delay_test.py +++ b/compiler/tests/21_model_delay_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -82,4 +82,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index c12d3835..24ed01ca 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -95,4 +95,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/21_ngspice_setuphold_test.py b/compiler/tests/21_ngspice_setuphold_test.py index abf64d33..91c9e220 100755 --- a/compiler/tests/21_ngspice_setuphold_test.py +++ b/compiler/tests/21_ngspice_setuphold_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -66,4 +66,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index 4a99f009..95f21297 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -71,4 +71,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index 9eaa2671..fb007c56 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -71,4 +71,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index a0d52d1b..491e2e53 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -71,4 +71,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/22_psram_1bank_nomux_func_test.py b/compiler/tests/22_psram_1bank_nomux_func_test.py index 7b76e0da..e41223fd 100755 --- a/compiler/tests/22_psram_1bank_nomux_func_test.py +++ b/compiler/tests/22_psram_1bank_nomux_func_test.py @@ -11,9 +11,9 @@ Run a functioal test on 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -71,4 +71,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/22_sram_1bank_2mux_func_test.py b/compiler/tests/22_sram_1bank_2mux_func_test.py index e5fa9280..2123f280 100755 --- a/compiler/tests/22_sram_1bank_2mux_func_test.py +++ b/compiler/tests/22_sram_1bank_2mux_func_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -63,4 +63,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/22_sram_1bank_4mux_func_test.py b/compiler/tests/22_sram_1bank_4mux_func_test.py index dc06a882..d1c2c8ea 100755 --- a/compiler/tests/22_sram_1bank_4mux_func_test.py +++ b/compiler/tests/22_sram_1bank_4mux_func_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -63,4 +63,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/22_sram_1bank_8mux_func_test.py b/compiler/tests/22_sram_1bank_8mux_func_test.py index ee3449ab..b789e416 100755 --- a/compiler/tests/22_sram_1bank_8mux_func_test.py +++ b/compiler/tests/22_sram_1bank_8mux_func_test.py @@ -11,9 +11,9 @@ Run a regression test on various srams """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -66,4 +66,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/22_sram_1bank_nomux_func_test.py b/compiler/tests/22_sram_1bank_nomux_func_test.py index bc626858..7183e2ea 100755 --- a/compiler/tests/22_sram_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1bank_nomux_func_test.py @@ -11,9 +11,9 @@ Run a functioal test on 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -60,4 +60,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py index 0b8bffcc..9742da24 100755 --- a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py @@ -11,9 +11,9 @@ Run a functioal test on 1 bank SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -68,4 +68,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/23_lib_sram_model_corners_test.py b/compiler/tests/23_lib_sram_model_corners_test.py index 85d96a73..906f1ec1 100755 --- a/compiler/tests/23_lib_sram_model_corners_test.py +++ b/compiler/tests/23_lib_sram_model_corners_test.py @@ -11,9 +11,9 @@ Check the .lib file for an SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os,re -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -70,7 +70,7 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/23_lib_sram_model_test.py b/compiler/tests/23_lib_sram_model_test.py index e1727794..56f7f2e9 100755 --- a/compiler/tests/23_lib_sram_model_test.py +++ b/compiler/tests/23_lib_sram_model_test.py @@ -11,9 +11,9 @@ Check the .lib file for an SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os,re -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -60,7 +60,7 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/23_lib_sram_prune_test.py b/compiler/tests/23_lib_sram_prune_test.py index 0d33d1af..470dfdcf 100755 --- a/compiler/tests/23_lib_sram_prune_test.py +++ b/compiler/tests/23_lib_sram_prune_test.py @@ -11,9 +11,9 @@ Check the .lib file for an SRAM with pruning """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os,re -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -71,7 +71,7 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/23_lib_sram_test.py b/compiler/tests/23_lib_sram_test.py index 6f2bf0b7..0aca746f 100755 --- a/compiler/tests/23_lib_sram_test.py +++ b/compiler/tests/23_lib_sram_test.py @@ -11,9 +11,9 @@ Check the .lib file for an SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os,re -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -70,7 +70,7 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/24_lef_sram_test.py b/compiler/tests/24_lef_sram_test.py index 362495d7..6c9c4536 100755 --- a/compiler/tests/24_lef_sram_test.py +++ b/compiler/tests/24_lef_sram_test.py @@ -11,9 +11,9 @@ Check the LEF file for an SRMA """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -54,4 +54,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/25_verilog_sram_test.py b/compiler/tests/25_verilog_sram_test.py index 0bbe45b7..30c6e5ca 100755 --- a/compiler/tests/25_verilog_sram_test.py +++ b/compiler/tests/25_verilog_sram_test.py @@ -11,9 +11,9 @@ Check the .v file for an SRAM """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS import debug @@ -51,4 +51,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/26_pex_test.py b/compiler/tests/26_pex_test.py index 5d26d26e..9541f720 100755 --- a/compiler/tests/26_pex_test.py +++ b/compiler/tests/26_pex_test.py @@ -11,9 +11,9 @@ Run a regression test on an extracted SRAM to ensure functionality. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -319,4 +319,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/30_openram_back_end_test.py b/compiler/tests/30_openram_back_end_test.py index d5cbe0af..2ebc9f15 100755 --- a/compiler/tests/30_openram_back_end_test.py +++ b/compiler/tests/30_openram_back_end_test.py @@ -13,9 +13,9 @@ check that these files are right. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os,re,shutil -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -100,4 +100,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/30_openram_front_end_test.py b/compiler/tests/30_openram_front_end_test.py index 006d1bf3..8058153f 100755 --- a/compiler/tests/30_openram_front_end_test.py +++ b/compiler/tests/30_openram_front_end_test.py @@ -6,9 +6,9 @@ check that these files are right. """ import unittest -from testutils import header,openram_test +from testutils import * import sys,os,re,shutil -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals from globals import OPTS from sram_factory import factory @@ -99,4 +99,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main() + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py index c6591cf4..a77cb86b 100755 --- a/compiler/tests/regress.py +++ b/compiler/tests/regress.py @@ -10,13 +10,13 @@ import re import unittest import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) import globals (OPTS, args) = globals.parse_args() del sys.argv[1:] -from testutils import header,openram_test +from testutils import * header(__file__, OPTS.tech_name) # get a list of all files in the tests directory diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index dfe34361..c6da0d49 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -6,9 +6,10 @@ #All rights reserved. # import unittest,warnings +import pdb,traceback import sys,os,glob,copy import shutil -sys.path.append(os.path.join(sys.path[0],"..")) +sys.path.append(os.getenv("OPENRAM_HOME")) from globals import OPTS import debug @@ -296,3 +297,19 @@ def header(filename, technology): from globals import OPTS print("|=========" + OPTS.openram_temp.center(60) + "=========|") print("|==============================================================================|") + +def debugTestRunner(post_mortem=None): + """unittest runner doing post mortem debugging on failing tests""" + if post_mortem is None: + post_mortem = pdb.post_mortem + class DebugTestResult(unittest.TextTestResult): + def addError(self, test, err): + # called before tearDown() + traceback.print_exception(*err) + post_mortem(err[2]) + super(DebugTestResult, self).addError(test, err) + def addFailure(self, test, err): + traceback.print_exception(*err) + post_mortem(err[2]) + super(DebugTestResult, self).addFailure(test, err) + return unittest.TextTestRunner(resultclass=DebugTestResult) From 301f0326198bfb8bfb7bc25c39e21ae37ab2105e Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 31 May 2019 10:55:17 -0700 Subject: [PATCH 031/234] Remove +1 to induce error. --- 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 ced244e9..a854c40b 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -352,7 +352,7 @@ class bank(design.design): self.addr_size = self.col_addr_size + self.row_addr_size debug.check(self.num_rows*self.num_cols==self.word_size*self.num_words,"Invalid bank sizes.") - debug.check(1+self.addr_size==self.col_addr_size + self.row_addr_size,"Invalid address break down.") + debug.check(self.addr_size==self.col_addr_size + self.row_addr_size,"Invalid address break down.") # Width for the vdd/gnd rails self.supply_rail_width = 4*self.m2_width From 7cca6b4f6905425b2d7439bdcef590e10ec471f8 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 8 May 2019 16:06:21 -0700 Subject: [PATCH 032/234] Add back scn3me_subm support Add back scn3me_subm tech files Update cells to be DRC clean with rule 5.5.b Allow magic for FreePDK45 but not debugged. Revert to older Magic tech file for SCN3ME_SUBM --- compiler/base/contact.py | 7 +- compiler/tests/config_scn3me_subm.py | 22 + compiler/tests/config_scn3me_subm_back_end.py | 22 + .../tests/config_scn3me_subm_front_end.py | 19 + compiler/verify/__init__.py | 3 - technology/scn3me_subm/__init__.py | 43 + .../scn3me_subm/gds_lib/cell_1rw_1r.gds | Bin 0 -> 6394 bytes technology/scn3me_subm/gds_lib/cell_1w_1r.gds | Bin 0 -> 6390 bytes technology/scn3me_subm/gds_lib/cell_6t.gds | Bin 0 -> 5916 bytes technology/scn3me_subm/gds_lib/dff.gds | Bin 0 -> 16622 bytes technology/scn3me_subm/gds_lib/ms_flop.gds | Bin 0 -> 18934 bytes .../gds_lib/replica_cell_1rw_1r.gds | Bin 0 -> 6346 bytes .../gds_lib/replica_cell_1w_1r.gds | Bin 0 -> 6342 bytes .../scn3me_subm/gds_lib/replica_cell_6t.gds | Bin 0 -> 6060 bytes technology/scn3me_subm/gds_lib/sense_amp.gds | Bin 0 -> 8312 bytes technology/scn3me_subm/gds_lib/tri_gate.gds | Bin 0 -> 4576 bytes .../scn3me_subm/gds_lib/write_driver.gds | Bin 0 -> 11804 bytes technology/scn3me_subm/mag_lib/.magicrc | 5 + .../scn3me_subm/mag_lib/cell_1rw_1r.mag | 156 + technology/scn3me_subm/mag_lib/cell_1w_1r.mag | 156 + technology/scn3me_subm/mag_lib/cell_6t.mag | 117 + technology/scn3me_subm/mag_lib/convertall.sh | 22 + technology/scn3me_subm/mag_lib/dff.mag | 279 + technology/scn3me_subm/mag_lib/ms_flop.mag | 294 + .../mag_lib/replica_cell_1rw_1r.mag | 157 + .../mag_lib/replica_cell_1w_1r.mag | 157 + .../scn3me_subm/mag_lib/replica_cell_6t.mag | 118 + technology/scn3me_subm/mag_lib/sense_amp.mag | 136 + technology/scn3me_subm/mag_lib/setup.tcl | 17 + technology/scn3me_subm/mag_lib/tri_gate.mag | 98 + .../scn3me_subm/mag_lib/write_driver.mag | 224 + technology/scn3me_subm/models/ff/nmos.sp | 10 + technology/scn3me_subm/models/ff/pmos.sp | 9 + technology/scn3me_subm/models/nom/nmos.sp | 9 + technology/scn3me_subm/models/nom/pmos.sp | 9 + technology/scn3me_subm/models/ss/nmos.sp | 10 + technology/scn3me_subm/models/ss/pmos.sp | 9 + technology/scn3me_subm/sp_lib/cell_1rw_1r.sp | 14 + technology/scn3me_subm/sp_lib/cell_1w_1r.sp | 14 + technology/scn3me_subm/sp_lib/cell_6t.sp | 10 + technology/scn3me_subm/sp_lib/dff.sp | 27 + .../sp_lib/incorrect/cell_1rw_1r.sp | 14 + .../sp_lib/incorrect/cell_1w_1r.sp | 14 + .../sp_lib/incorrect/replica_cell_1rw_1r.sp | 14 + .../sp_lib/incorrect/replica_cell_1w_1r.sp | 14 + technology/scn3me_subm/sp_lib/ms_flop.sp | 29 + .../scn3me_subm/sp_lib/replica_cell_1rw_1r.sp | 14 + .../scn3me_subm/sp_lib/replica_cell_1w_1r.sp | 14 + .../scn3me_subm/sp_lib/replica_cell_6t.sp | 10 + technology/scn3me_subm/sp_lib/sense_amp.sp | 12 + technology/scn3me_subm/sp_lib/tri_gate.sp | 13 + technology/scn3me_subm/sp_lib/write_driver.sp | 38 + technology/scn3me_subm/sue_lib/cell_6t.sue | 46 + technology/scn3me_subm/sue_lib/ms_flop.sue | 84 + .../scn3me_subm/sue_lib/replica_cell_6t.sue | 49 + technology/scn3me_subm/sue_lib/sense_amp.sue | 52 + technology/scn3me_subm/sue_lib/tri_gate.sue | 37 + .../scn3me_subm/sue_lib/write_driver.sue | 44 + technology/scn3me_subm/tech/README | 10 + .../scn3me_subm/tech/SCN3ME_SUBM.30.tech | 6942 +++++++++++++++++ technology/scn3me_subm/tech/__init__.py | 6 + .../tech/calibreDRC_scn3me_subm.rul | 225 + .../tech/calibreLVS_scn3me_subm.rul | 123 + technology/scn3me_subm/tech/tech.py | 311 + technology/scn3me_subm/tf/README | 19 + technology/scn3me_subm/tf/display.drf | 714 ++ .../scn3me_subm/tf/glade_scn3me_subm.py | 7 + technology/scn3me_subm/tf/layers.map | 16 + technology/scn3me_subm/tf/mosis.tf | 848 ++ technology/scn4m_subm/mag_lib/cell_1w_1r.mag | 142 + .../scn4m_subm/mag_lib/replica_cell_1w_1r.mag | 145 + technology/scn4m_subm/tech/SCN4M_SUBM.20.tech | 72 +- technology/scn4m_subm/tech/tech.py | 6 +- 73 files changed, 12217 insertions(+), 40 deletions(-) create mode 100644 compiler/tests/config_scn3me_subm.py create mode 100644 compiler/tests/config_scn3me_subm_back_end.py create mode 100644 compiler/tests/config_scn3me_subm_front_end.py create mode 100644 technology/scn3me_subm/__init__.py create mode 100644 technology/scn3me_subm/gds_lib/cell_1rw_1r.gds create mode 100644 technology/scn3me_subm/gds_lib/cell_1w_1r.gds create mode 100644 technology/scn3me_subm/gds_lib/cell_6t.gds create mode 100644 technology/scn3me_subm/gds_lib/dff.gds create mode 100644 technology/scn3me_subm/gds_lib/ms_flop.gds create mode 100644 technology/scn3me_subm/gds_lib/replica_cell_1rw_1r.gds create mode 100644 technology/scn3me_subm/gds_lib/replica_cell_1w_1r.gds create mode 100644 technology/scn3me_subm/gds_lib/replica_cell_6t.gds create mode 100644 technology/scn3me_subm/gds_lib/sense_amp.gds create mode 100644 technology/scn3me_subm/gds_lib/tri_gate.gds create mode 100644 technology/scn3me_subm/gds_lib/write_driver.gds create mode 100644 technology/scn3me_subm/mag_lib/.magicrc create mode 100644 technology/scn3me_subm/mag_lib/cell_1rw_1r.mag create mode 100644 technology/scn3me_subm/mag_lib/cell_1w_1r.mag create mode 100644 technology/scn3me_subm/mag_lib/cell_6t.mag create mode 100755 technology/scn3me_subm/mag_lib/convertall.sh create mode 100644 technology/scn3me_subm/mag_lib/dff.mag create mode 100644 technology/scn3me_subm/mag_lib/ms_flop.mag create mode 100644 technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag create mode 100644 technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag create mode 100644 technology/scn3me_subm/mag_lib/replica_cell_6t.mag create mode 100644 technology/scn3me_subm/mag_lib/sense_amp.mag create mode 100644 technology/scn3me_subm/mag_lib/setup.tcl create mode 100644 technology/scn3me_subm/mag_lib/tri_gate.mag create mode 100644 technology/scn3me_subm/mag_lib/write_driver.mag create mode 100644 technology/scn3me_subm/models/ff/nmos.sp create mode 100644 technology/scn3me_subm/models/ff/pmos.sp create mode 100644 technology/scn3me_subm/models/nom/nmos.sp create mode 100644 technology/scn3me_subm/models/nom/pmos.sp create mode 100644 technology/scn3me_subm/models/ss/nmos.sp create mode 100644 technology/scn3me_subm/models/ss/pmos.sp create mode 100644 technology/scn3me_subm/sp_lib/cell_1rw_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/cell_1w_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/cell_6t.sp create mode 100644 technology/scn3me_subm/sp_lib/dff.sp create mode 100644 technology/scn3me_subm/sp_lib/incorrect/cell_1rw_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/incorrect/cell_1w_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/incorrect/replica_cell_1rw_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/incorrect/replica_cell_1w_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/ms_flop.sp create mode 100644 technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp create mode 100644 technology/scn3me_subm/sp_lib/replica_cell_6t.sp create mode 100644 technology/scn3me_subm/sp_lib/sense_amp.sp create mode 100644 technology/scn3me_subm/sp_lib/tri_gate.sp create mode 100644 technology/scn3me_subm/sp_lib/write_driver.sp create mode 100644 technology/scn3me_subm/sue_lib/cell_6t.sue create mode 100644 technology/scn3me_subm/sue_lib/ms_flop.sue create mode 100644 technology/scn3me_subm/sue_lib/replica_cell_6t.sue create mode 100644 technology/scn3me_subm/sue_lib/sense_amp.sue create mode 100644 technology/scn3me_subm/sue_lib/tri_gate.sue create mode 100644 technology/scn3me_subm/sue_lib/write_driver.sue create mode 100644 technology/scn3me_subm/tech/README create mode 100644 technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech create mode 100755 technology/scn3me_subm/tech/__init__.py create mode 100755 technology/scn3me_subm/tech/calibreDRC_scn3me_subm.rul create mode 100755 technology/scn3me_subm/tech/calibreLVS_scn3me_subm.rul create mode 100755 technology/scn3me_subm/tech/tech.py create mode 100644 technology/scn3me_subm/tf/README create mode 100644 technology/scn3me_subm/tf/display.drf create mode 100644 technology/scn3me_subm/tf/glade_scn3me_subm.py create mode 100644 technology/scn3me_subm/tf/layers.map create mode 100644 technology/scn3me_subm/tf/mosis.tf create mode 100644 technology/scn4m_subm/mag_lib/cell_1w_1r.mag create mode 100644 technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag diff --git a/compiler/base/contact.py b/compiler/base/contact.py index de1afec6..396b2a6d 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -8,7 +8,7 @@ import hierarchy_design import debug import utils -from tech import drc +from tech import drc,layer from vector import vector @@ -196,5 +196,8 @@ active = factory.create(module_type="contact", layer_stack=("active", "contact", poly = factory.create(module_type="contact", layer_stack=("poly", "contact", "metal1"), directions=("V","H")) m1m2 = factory.create(module_type="contact", layer_stack=("metal1", "via1", "metal2"), directions=("H","V")) m2m3 = factory.create(module_type="contact", layer_stack=("metal2", "via2", "metal3"), directions=("V","H")) -m3m4 = factory.create(module_type="contact", layer_stack=("metal3", "via3", "metal4"), directions=("H","V")) +if "metal4" in layer.keys(): + m3m4 = factory.create(module_type="contact", layer_stack=("metal3", "via3", "metal4"), directions=("H","V")) +else: + m3m4 = None diff --git a/compiler/tests/config_scn3me_subm.py b/compiler/tests/config_scn3me_subm.py new file mode 100644 index 00000000..2cd02b5e --- /dev/null +++ b/compiler/tests/config_scn3me_subm.py @@ -0,0 +1,22 @@ +# 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. +# +word_size = 1 +num_words = 16 + +tech_name = "scn3me_subm" +process_corners = ["TT"] +supply_voltages = [5.0] +temperatures = [25] + +route_supplies = True +check_lvsdrc = True + +drc_name = "magic" +lvs_name = "netgen" +pex_name = "magic" + diff --git a/compiler/tests/config_scn3me_subm_back_end.py b/compiler/tests/config_scn3me_subm_back_end.py new file mode 100644 index 00000000..5586ebca --- /dev/null +++ b/compiler/tests/config_scn3me_subm_back_end.py @@ -0,0 +1,22 @@ +# 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. +# +word_size = 1 +num_words = 16 + +tech_name = "scn3me_subm" +process_corners = ["TT"] +supply_voltages = [5.0] +temperatures = [25] + +route_supplies = True +check_lvsdrc = True +inline_lvsdrc = True + +drc_name = "magic" +lvs_name = "netgen" +pex_name = "magic" diff --git a/compiler/tests/config_scn3me_subm_front_end.py b/compiler/tests/config_scn3me_subm_front_end.py new file mode 100644 index 00000000..7b39e46d --- /dev/null +++ b/compiler/tests/config_scn3me_subm_front_end.py @@ -0,0 +1,19 @@ +# 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. +# +word_size = 1 +num_words = 16 + +tech_name = "scn3me_subm" +process_corners = ["TT"] +supply_voltages = [5.0] +temperatures = [25] + +drc_name = "magic" +lvs_name = "netgen" +pex_name = "magic" + diff --git a/compiler/verify/__init__.py b/compiler/verify/__init__.py index 04fa9746..c7bec114 100644 --- a/compiler/verify/__init__.py +++ b/compiler/verify/__init__.py @@ -33,9 +33,6 @@ else: OPTS.lvs_exe = get_tool("LVS", ["calibre","assura","netgen"], OPTS.lvs_name) OPTS.pex_exe = get_tool("PEX", ["calibre","magic"], OPTS.pex_name) -if OPTS.check_lvsdrc and OPTS.tech_name == "freepdk45": - debug.check(OPTS.drc_exe[0]!="magic","Magic does not support FreePDK45 for DRC.") - if OPTS.drc_exe == None: from .none import run_drc,print_drc_stats elif "calibre"==OPTS.drc_exe[0]: diff --git a/technology/scn3me_subm/__init__.py b/technology/scn3me_subm/__init__.py new file mode 100644 index 00000000..87b26056 --- /dev/null +++ b/technology/scn3me_subm/__init__.py @@ -0,0 +1,43 @@ +# 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. +# +#!/usr/bin/python +""" +This type of setup script should be placed in the setup_scripts directory in the trunk +""" + +import sys +import os + +TECHNOLOGY = "scn3me_subm" + + +########################## +# CDK paths + +# os.environ["CDK_DIR"] = CDK_DIR #PDK path +# os.environ["SYSTEM_CDS_LIB_DIR"] = "{0}/cdssetup".format(CDK_DIR) +# os.environ["CDS_SITE"] = CDK_DIR +os.environ["MGC_TMPDIR"] = "/tmp" + +########################### +# OpenRAM Paths + + +try: + DRCLVS_HOME = os.path.abspath(os.environ.get("DRCLVS_HOME")) +except: + OPENRAM_TECH=os.path.abspath(os.environ.get("OPENRAM_TECH")) + DRCLVS_HOME=OPENRAM_TECH+"/scn3me_subm/tech" +os.environ["DRCLVS_HOME"] = DRCLVS_HOME + +# try: +# SPICE_MODEL_DIR = os.path.abspath(os.environ.get("SPICE_MODEL_DIR")) +# except: +OPENRAM_TECH=os.path.abspath(os.environ.get("OPENRAM_TECH")) +os.environ["SPICE_MODEL_DIR"] = "{0}/{1}/models".format(OPENRAM_TECH, TECHNOLOGY) + diff --git a/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds b/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..a4fea073f7794ef11cbd2daa04f721b08f919b4f GIT binary patch literal 6394 zcmai&J&aXF7=}OZ-o0FL#S7vJWJQel11$Rkn*h2&*MM0AQKPF-VxrMCTHF{z;aXZ) zXkuYuVWPzrCR$ifSWs9{7-L~!VL@SGK}kVjX~FmGoR^t%@EcFE`<%Qp?|kz=bFK}n zXA?GaN6$8F()QW3-Dz{T-nZMlje3K3-W`wMT)ep9e`dQUCQq+?e&XD(-`_ZO=JNdJ zHy74yX0qZRwEg{|+2HP;9k#)ao|(;#Cj7rYC!aQZYBlr1@|J9(r}uZ7$$zNpCpUhP z@_0mlE&WGJ|DnFw3zy7}t!KVIGD8SZ%@(bGf!z1Pjo9yHtYZRWEtnxTuH9{TAc{15$`i4R?@`5*l; z`KT}DKz!(8%}+g7Hj_`J9JQ-S59`1E3$w?rnl1gDIs2Izy6EYlpYk7mJjE9&4_$OU z^b?1?#1|QRbkX(DPd}5F{ul3APW>;sUiufx`9m9DUP^0Ce8tN{7hMnicllgnt?w9R zGKT1)r-%Og_9Wl^A70xU^p+F1lEYkLQ`+Q(lqvhc3Dv z#;2b6=r<7`x>)lw&iELA5g)o(^Am@@Ccem6po^}T^`9%(&)(nC+MPL&$-a*+`q~ct z>=~zL(pe?qLl<2S{nY!^IQd1&K^I*Q{p=Z>-Ru=2dl9`-$>c=^aU!)v#(e=rXm$=B_7F zp2}^~tA6^9{Yqrq@QJQh{q!I4Masc1cKUC=T>qTAPke30{Y_lHk3>q`25;;y)|neL2yccF`}hkoV^KK4NoAG%oc zb7#iKekd8Haxgt`I+SR0o^(URRrgIZgj>>J)tA6Uv{1Yipy^3Jp7SYWZv*D`g<6kdJ?<*!;3C@TIlb+mhS4zTkhLqGkCkNGR&Yx;eQHNWnE%pcBs$XQUi|FzaH>x{jIdW+NrU35LHKkEc9>qn&i z=%VYPpLIgJ$t&`XF4o%57~$itBH}|AYkoZR8~eCO|DlVnhxI28{l@$g={Iz-)_>*? zea-$W(vLi%>tTHIG1u^m+lHuSqU)vqc)9=MDf8lC-$xfcJ@iv&9@Q1%Ll-?c^#9lX ziw|A&eI)d=PN*yMUS!gD+&kD9FaA%yscYnW?}PPrKA#V{JTHsiu07w|kL4=eDjG$N{lmb&y zP=G{1L4gE?3nVBgQc$FzNP!Rq1w{%93JOY!6qFR4&vXCG+#AktCHuSjXZ|_!p1ErS z>)C|O-O;lRo3wp4Yj@hht@rJ=Xw$vHn{SQBmqr_xMptb2#N_GKPfk4h(>FIyoxQfW z`Q^nmo13h-2c^3|G#lLAv%@x+?wQ&A%!L2<=j0i)C(mbIT-lOM^z{A?Gx-m7{p7|k zQXY@!uciNJ=|9vrd;Y4~vGvT?X3Wqj z^!rT8Ll-?g^b?1?#24?skm8H3m;U*({dnj*;*00MO=XF$hyHzkr&tHqGAR>X^g5RQ zBW3&}ubaI%G+Ua=eC3)My6EYlf7f4T=MI|f`6~127tGK_PY?a{5&nn%$;5{)*8Gor zmweQhav(l*vF4|qtDDIuQjXfyq=)t2{;AocznLxnkU9Uc8M^4{p`Y>(JeJ~%l!q?5 z9{PzxUgC?4J-X<6=%=5_OaF`atfc-IT`&Dh<@}+IFD<9FCcf68 z593o$eDs@$4_&PJ8E1TqzlaZAtoeyUUlU(sEYL;Q%la>r>u2xJY3ZhkojPYMlHc<)DkMhko`9&TjS!k-Z3AbiL~5?Adueok5UtR4(-N z&_DA|syjZ;Yn6jexlMZLr=Q8kc!|_oqnSd15aCi0Fh*2bT6qRgvu&?&D;59?1lb>^-o zQl83f(yM;@j{Qnx-0+F6SN-%K@kPqPFLwHGv0VS0yN`ci#{ErPxtY#m(e*NZ%g>%e z-I;G9dojA`dg$klfRB5Ch!0(?`SI{aUa@>{(!=<=W6*ch0Y3P3+D}B+LqGRse2lq> z4_)l|kCpw;y64`)Sc}|S(8bREizwj~V zMBO{YnxA&k*R)?`EYL;Q!}zqb94q>v9LpxX^pDE-=U7u^uT0U35M4@4TMApSUZoZl*gU-(BdU>!F`HgO7bs#D^}{ z{M?!GvEPdL%J09LpL%l7VXlajqjojvVf{&Gt?Ar^l%sN+^s1k_Gyg=&Q@POf(9ith z%)~2Fe{|9H(64&}ew~|?gD%#_9}j=z6`41@i~b(Qr=G+v|L~%Vo)-Fhuco^?^Oie1 zq%3sN_0UiM;$!}b_?mv-V$HAnAM=Ov9`?tiWI%Q|DPq23~OK^I*Q>(4sD%lZ+i zKf368=x3eKZt{w}ql>lnGe-EhtBCl}#hM=v{l-2n(tqfp>tX$gL%%WqMEVU~to5Jy zLtnH1iu5Co=z18Re9Sfc;o42QL{{qWL Blb`?q literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/gds_lib/cell_6t.gds b/technology/scn3me_subm/gds_lib/cell_6t.gds new file mode 100644 index 0000000000000000000000000000000000000000..673962cc5fa27ffa3d01138eea405a0b703bc7d6 GIT binary patch literal 5916 zcmbuDJ#3X#7{?!OZ*MP9u&sQwO(``9(ob4irG7*)VUxjuffy2v*2vHpVhk`cIB3Ga zz+fT+1Bng{4h$U}IvB&q;NZZ(z~JEEKwSK|KEM0Cf8TR2p5q|N<#+o(=l?wC`#txy zmNjg^rgk*!vhB2{?eV{k*cBVJNgK5ho3`Ob>w^zBH{X5fQ?q>ogRj5&#i_S``1;qE z&upEz{nb0?Y-+IJZPngp+pM*xVQ*M#Z^O(MMh5)<>fZ}L#TWSE&+%RKznY`|sr+-b zztj2cw%K!kn60eWeD(X#MK4eNv%UVPyRt44M{!~Id+J}T{bomwNA88sYrgVj=%TkR ziW_u2<2T#A6+ZIgS3A&Y zPgS1vGe*>7+(gzQx|nZ&)FbcAgUAnwqqwlte%2p;@{9P<#k@bpha8NbIP)NM(e-Tq z$%9Yp2GR#~vCltW&%fExYi6rA%;uJBuAdHF^zt-+;_r0+{KjnlLhK)L=~3vS>qS4g z8|R}9aQ=eg2E9DvH`_ZBKK3thAniaGOMdnV_3(;Ik7ECcu4nV($2)zsCUF$ED$n{E zfBfkOKf35;8GnoqIT$x_`fBK+>luIKsoL1}t1slIPcZL~JnYeti?LVX{_)U7FVE)R zy%lvwE{YL{nDOcAS^v~b)T7n~Km1s25Y1={{SS8aZ2m)M!*}?O7(V)szbeo8!^1wKuDEzF zbkX&UKl+T1zKVHcZ2g_rpz2IRSoF1nuPf6708%WT(mGm$uo3ti9p**845pFdZVyy#-z z^SdWM^UfKGUnCy7=z2Ck^|(JDI8&22id&Uu{q&g+V=Z!a@m=)qSwG{${Qwj!J?rJ=%xU)g>qKmF){XDzVxn>^Nhv;J8{P*N1 zUpiOJ9dm&$dU=}vWPkg4?onUlxkvlOzUN=!kMoCqbN+}&uZ1r5^*`~)IfIWqFEVbN zKVr$>UW;72u8YwY#)LLi<=Os^-wNO46ES?u3I3`)^{>?97whEd`*-N;r~fH0`nmI@ z_vh6c@&&y-G z^-TX`eE6-v_=(5vhAz6E@kgHi^P6_4UC_&me)bOS7l~K-x^zA3XOFYz8F!I>ql>O* z{j5{=JbsZl>6zks*3TKsouBrL^aEXVJ?p2P)FZ!0JJ3bfi+=KQZx@N9xUiI;b;i6i zRwDDKv!g1{=I1$+-aQyMJ$FPe&-i1V@!TT6$XUd15wY+2m7E`DL+z-W{(fRD54B@W zSLK=fjB)tW-#_>n`(U>`^{@7xU*T_@7tM5T1xxjG?fgu%NV{n1X_W!h!_f-|YQ(_Bm#)Ne=(Rv-Y#z_3r)d zwbtI>_qCmETif3Dp0%w#+dk5EwB7B>c3yj~o!u@g?rE2|UE6jZdF-*)F5G_hUHAOq zw)_6^*Z1x?^xBOl|NP(sZSUCw-_FUmV^?cCKfbNq-FBY4t+lpq&-VK7{O|X#Phapi z`={?={ojuB>NESV-SppnurStoE*d$1AOU@{-mr-dgdBw<_7v!)ovPADMl|p&#UBnEYYsL;nL0xAxFWt%dqYzgYUvf9HGC`3vF*63licl}@f&otIw zzr7+KJ*-^1{^wq3?TPzaJAV6$PkqoDJ*@VwUmW9q@Xi&TyNqjY@A~B_ceNJkFXv@$ z@A{9tIr-$zpYuRBj=8<-*Z=u%O!33Zk4^Ez(z|~B^NAbs(Zi8n{5i+}Q9l{i+}@4v z{5nSbke?ow-u1iAe8+EJ@nf$|*FW6w?_buhIrbOFTKnzp6`y>oHF{X>%lK>lUAMM& z>6@*6^p7jk(lz+JAi7EfE^kM#d z#t`z!KOFh5thtWwsv2*|M-NB-o9e#dyXD0d`RL)u|HZ#gzPt9W$VU%H{;ym$`M!31 zMLv2s@_%nW?>~5F@*^KT9QoBrwV$ba3Hj*Z$j@W_a%^bbqKBjPOP&1k<*9x``zCr=`mlb)RX?G) z>L(n;=;6q(PWaSM$VU%Hes#j9enLKa zIP$9#KJ^pw(Zi8nojm%NseZ!LbXa=#`l}OrMe|Si_`H7!OYi#CiMZ+~6qg>3;;R!r z^%L^Z!;xQ|@Ts4Wj~V!}IgnaaHL=u*ha~mfpSo>gT8LPW2Q1?9ep-gr#@=>O@@i6N*a@NAcAOpZW>;=;6q( zPWaSM$VU%Hes#j9enLKaIP$9#KJ^pw(ZiA7HRe-4As;;)`PB)Z`U&~y;mEH}jNSSb zdKRaLrFXBt`uWkGseZyA*ZzwhmfrQN6LHl~C@wu5#aAbM>L=u*haa3Hj*Z$gfWLmLEQPIP$9#UiB05(Zi8no$#rjkdGdY{OaWJuBm=P@6YIA>D}wE zPQF{mTE9ZM)5FrcetC*3|4>|dIEpV%KKX}y^l;>t=l%Pp{KIcPKjj~m-W|U@zwyH< z|L|L{O!rR%iq1@`iEct z*OY%)de<*capfP1OAkl!<;f@ikdGdY{PI8e%#?rlrGHNOhoyJNFaLW^PWgx4z0t$c zyMB3!EB{bjdN_(NPd@pFeDrYS_nyu<@cu5eme9k}m*c--`TlSBJFQ*!P-~y4IVapY z(HcE0z3cam=)mdLF8RxfeDtu|yMA@&S(!i7A3ZF+>-UcHbEl?v4WT^fVd-7JJnQ}b znfycj(8JQZetGg4e<%-nIP!n${`x`M3$1 z9+uvX|Cy_&dsY3oXVH12hoyJ@>eO}P3-v<}OYi#KD~?k?p}6$0^r2te8~#1TNByK< z9L0B?`JKPed8CIUzkR!Ub8P53(!-UT#o@cj^j~wKYgmmZeh^^0YW;}7*i4@>X*U1w{R^B3~c!_vEc?^x8BcR%4)U4MF5 zde`sw9z3h^hx(z1rFZ?F@!V_P{e;VB-?_c(cirW!{zCoG!%_a;d7CS}>khXne|lJY zH@>{BJ^Z15=wazyzw2b3_Us$VBiD6q@A_S1KfiVTLv=(CH-3J*wtl%r_L}aM(0oJ> zOYg>4x8_a$P(So=G=IvE&-g=m(8H168fl!)U+6s2!_vFsS10xxu2<;%r>^Gqu3sE^ zs=v@UGOoG3>({@$`9uBC!%_b3Q$FJl$ZbE}x&Qx2~1Fe&|}# z!_t@eulenB`0hEmA|E{*`CWI<$>xdhzBbiESb8_UXKo+faQS_1@A?m%o}QEauAS#) z^-lK;b^XJ<6Qzv4opU`syJuJN&-|sEidtJP>qIruRR(sd) zXFjgIpY?=(7EBLI@A^Gw%GvXGc-XGX@9B31L+dU*EWPV@jl^}$LviWh zD8BP9ws+m3y)!*5y&K8L-QUzEWPV@pYb{OAs;>5@ZY?=f900@wedSo)(Ph? zv~JSF(!23pC$U|>(E3LYOYi#S$tVAij~;ILZ(7!GtA9sNO}{@K9($EKy#vJ3m+{y9 zes|FC&3a!J=J!^^jo+VL^ZOm2gU?L!WoR7qu=H+xbB49cd>@KS4@>X*-Q%8h_(T2B z!_vEc^9G+<4UL-~j{NQsKI?U8-1KndchB>ge?xKU;mEH}_~aUjOAkkW=jrgSX}t*b zlk+;ach8?Z#WL4~{5dakd)IHCu>bM?Ak+^%+}QuD)t@o@h#4-w&+Wtbp3}`Wp>bqf zSbEnlZ@%UG4}N+$@;krgdFyqUXPU6|ZhU(bKJRZrK6*Ivi*M}9_h4ht2~%EWPVDe_QwYL;Yl4pWC~B^Nw0|&xG=zhoyJ@_PNICcdtV8 z7CkJz>o-1gguQDhkK{GC5B+M_+8^pC{bK1|zxSgDPEYfF=)DO&EWPW$;N5BNuwIx$ zP(Spr^r4?;`SUORq+hJ|uHU}HKHpv?G{g<`c-a&li%XyvKyW{tqB))Yjd1E5ZC=5x_0z%6yN$QuJt!G7t_O0{Q2*z*Z%%mKmJYpzrVk} zW%>TXn9b8-h09u)+n48m&2OI1x)WNz=;6lvyXMb*BDU*}?nQc7dN;m3R`z{i_Kjib zU4QCqdH?%P4@dD`XK`Hr(7uNrmVPFF-ID%(zw*Dx-|z4C_xtnvvt5_&eDtX&TmLwF zi`v)hymaTG!BJZ$&g{19sPC*FRcpp7rn#oZTQQ$Ka%6Cv{m)tZ9QXLsIqsY~enpphaKic+YtXalHK zt08EV2!@&zsj+CIAXSf{C_zL5#9$0<{9OjGW)O@rIZC@Gvj{;|GfK! z`~!StRsLDV{~I|x{vG&Fney-7|KII-?pu$U;w!6Cmp%WlSNM3XqM~3si zXV`!2lchX5Qp!6|n&Q7sC6f85{a+bP zzx?jg>6f85{gw|K&$wJn+lVtNugcS|72u zl(EPux%TKX^s1jc_{cBcwIlP(mjB>6r5rYv`6Y4CW$45C7Yxt8k)1hjXg~7@GVjo3 zZ~k=r&btMh(+`<{=(6P}5A%+^l6i+Nd-Jc8pYxb^_$BiWUH0bRG(YnOzr1C0`ekqa zbo}%aAN`ihJ9OFd(@y3c`6crXUH0Z*CqL&g&+tp;4Y~}ydHtCu&SU4Taba)%ojN>! zm}gIo=NyzT#Q3Aj(1-JP{PX6Q^8CC~=07(@eCRTcH~r79E#)2CN|D4fE)2ctr`_b2 z#2NS|*lIuheB|})zkFge`!7Rp=6`Hu=9l=$FGFwo$9H7^C2{b}(3^hReafQj2P6)D z*=j%iziVUmU;cb=_FsnH%zyuq?7zfEei?exzjaIYUlIqu487^U=f%t~iGyE;-t_-y zLFSjl!7oE^`WZLopCk@`*&08_|JKzx{_;CF<@n3coB6--c;=V*$S*^0`focj`!9)u zUxwcF({B1NiGyFZ+E4$liF5hwlj~y+qs!2n`PXgA{1PAeW#~=+bD*G?5T9^Hop*Qn?W_RY7_{c9qZ~8AC%l=E^;FqB{{j{69BZ-4w zw%SksPhFY)mmhjM`!7Rp=0AI0_Fv*7zYM+UKWlCFUlIqu487@JJf8U_aq!E~oBl7k~sKfYy24hqn73P%M(`Q_{-3n`MGz6bq&>6f85{omY|e);X?>6f85{a?K^{c_XG>6f85{WtDNzr1NA{WA2Xe@)Ca z?iKm@_%riQhTimlc5nLSl`;SE%g~$tPi{%S{Paudm!UWP=frr^etGWJ^vlqj{`bXr zF3!Gzhn=H{>#vt{^8n39QFe6%Q)WjAH6Q~OZF7-%h0R-Lu2d@|3N9E zFHJF?_X@g<<5fR(j=J@xT~nlPq03hN;ymgWe)-JO^vhQL!cX18FR5GTvQ@u0kGh3l zQn%1$tA6o}jgMz{i4R@2{N$nTkzZ2x&}FOsabDE73BRQ7q07*l*N?hKeo5WKFI)AG z^Qe3HC3O#7w(1|}QTOmm>K?jm)j!Uo?%|izJ#-m*v;WjR{F1tdU$*KW=TZ0YOX?oF zY}G%`qwe9C)ID_Bs(;Kge9S+I4_&tWHS^2Ro8w2_r2Ue*NnF{gpPWbC z#4o9v=rZ(Xe(EQFN!`RRTlJIksGImDbrW6o>gU4Y_1nnKQl7iJl;dBY;@|g`iTyVj z$A{bB@l#{jcRFg>6p4o}d;3ov|J>cVPej|hgD!i&pPl^7&#S|WUlIphhF;B2`!8FP?UyT~@8~l0s-HZc+Liew zanNPxRX=rV`Sv_tUQn`r$6gSom!Vhv)G2(_FNqIbw*2II z`-U8UNgUfXI9|=qxbe*b`6YgI8G6+}H|ooYo6;|dgDyjF`dKGYza(*t3q!B^=^uM# zv{y0?j?3V9)ldB4cbB}wBo4al?Vok(2X&6M8}&vK4_$^nod2}p^&9i+FK4D-{xz;Y zx(vPQr@cJqF@BPD54sG!>Zgsryf^zRcfOi!m!Vhvw3GKV^k4Gc8(oH8_0NrQ{@Qr9 zSMuHkU4~xu)6dm$uh4(Vdkl0LdehHy3Vuo5#VZw?`zOp-$-W7??Cqa){QPeI`JvpamOKZb z%g`(N_wWDT^ZB0lpaoNWbR=~--hF=V1{z%rL=(4x}((%uYdCGS)jF;p+EV}G{KhyCuPB*X2@sk@K z%JGw-H~YUTa?^i#Rg6FVm!VhvwEGj$2Clzk9|T>7UiCB2E_yNNpCk^t487_n4|Rw9 zlDdN~d-Z49_=x6>*w5_i zlAHPq{ccJ2>hCl^-y4xn634hO^lE0sg=rZ(bey%UysqyR~S%;v@(5rsxAL|V2wRGQ8hF^UTo`)Q&-mjbzr>F&TYloRZo)6OZpr+zw|?qeKm2@WNBbplj5|19 zZ9jDfANeJIbQyZpPkh#G_$A-%q08R-ZCd;9+L-N^#4#=my_%nP;v>Jrk1kt&>LbsM zoG;z?l)dN2Y3*m-Nq$Kj+AVwQ&uM0fnBUO!13{3US)z6pk2 z^&cI%;{E=_{E_(4W$0Bu{U$H-PZ9@R*7N7}<-1whFE1VQx=$Xj>mb%%;uvGrFY@v=smsu-e(n?IE%Qe*kI-dn{xVK}H!O*RE<>;8XPx))ota+} z2VI6<^)pZSPMG>9&yU|@bQyZp&-#z&e8x}u-bjXC^^@nEg<4r%`DKmd0 zaf}N?ulgBhe9T{oA6>Tm#E<=n3BTmKXLK2QH9zMq9?$km;uv>uyz1vZ#Yg)kesmdn z)lYo(J@8Aun?{$t{f|!l9) zMl$rOpZ3xB;eUyPF5_6!&o_^>LlVolF!ZXQd4>;<<=q2*dF+$c<;mmK{PdG+NBbpt(PijOKY1A|NgU(C(5rsFlj0o= z?U%$sm!Vhv?ECTFgmWcv&}Hxa$G;Y2V6?Tre}m5c&ER;o{p?#m5Z4&LBp$j9z3ONEux%{;k~rux z^roNZ^tmyAByo%jL$CU&4_mk7xJ#}Bx(vPQKXKC=-hb2U0 z*T(cq_HFRX(5vmI?y>K{_({eQUH0}LI{9Zs+t)9e{``#2^Yh?%H9yB$XHxql@r*k- zUiDL7{7y^q9T~a|z3QiCU%MgepCk^t487_9*d1BxC2@=kL$CUoXFMlz{Uz5CU4~xu zbDeq4!Y_$~E<>;SxxX)t8iHT)9T~a|z3Qibtn-;al5rUHdxD`?{aoJ8{C>zqqp8c@`m;0t$;8=RE#l{U?cI+`;i-|JlRqH`a)JW5#$%)*$FI z^a+0qD}R4btRIi!?++UF?+=Q0&N+7W)oZUC+-HOHBG1%$gZ9LEtFOJjdtS`vsqGKQsFbM5jUgSZBLjmb z4h{|`I&?76!GXbn!GXaT2L}fS2L=X52L?w5-(S!7})F1&aC!o|_({KDG0|C#L?8$Y@H`LUON z{r=X8Q`hD;zB#vIGvk#wga41yADRvB>)8PtZ0niX?BtmL_viR?X3w6jSZ%>+`i(Vf3hl^&9Up70oEA#M8Gj!3* zL;sGi%=Z3acIc-};-QOP9{R~cUGj?$olW^g*GvCw*?&BY9r?vGKcrZq>!E+ozbV(g zl}uuyi{8f4f3VDd@Ex<)hGz2lbEE{$;lKbLQ-4X6T}qhkoKe z_EgF*5)WN;J@k`@y5tv`dvwwD(9bwim+=?3FQxGpT`&Ff<@%wIuP>%|O?<=Sp^L7E z{(F6`@vd*1%w!JHMK2Hi4@@WDgO@V#p^G&?V@&=7^O^Y2#hQQNc=8?nG7}%VSo1&p zXm`Tp$wExo%l zdo$Vh(M5l^LqB`Q$(eLkiTKb(*F!(;J~2vukvQn0>!F`LgR`5xLS!#O7hSLVIeT_q zPiGJ$j^aWu5B-xLrnckbyjC1^;x^@>pK+!h^Ci-5%}Y}r`k7UZRV~g5>IiP@~WS)W4{uaH+-V&RX^iLevvr%#m@N6mG3|2?$ckJaeot+Zl&{B zbiK^q^0VjAcGjE7UW_if9{RZ>;Nu=3;zJi}emwk9S1dm_6{sQphMRdKK z|5pE5U-(#aqV64H%}+lWYx*xT7wDqvVSf5q&K2WO&Sg_x`WMReXa4a0i|>9S-@ACk z&iAi7{4f5Q{Nl^rA0E;5Fn@EtZl2$~L%ff~K^I*Q{X4Ix?@!znmp9U#k?&pTqU)ib zHG_}+QpATY*8Jq*p2A#<#8JDN@-RQ;yem5QAaNA8DX;ozJL^Xzp5j8+LqF?-GY_vw z`_V<$L%+^>{5toDgD%$Q4-bFT6`6NFi~c#xPdmw7{^3Ozy)5+i-b#0E)*W|lNGx>G z_0Z4w;$!`Z_?mIwWX-Sp8|#Pj8nTyH?r*L4kN1SVf_96v1zmJKY(MK9FZTeE_M?lg zhkm{@(r@aDd`1^*{b!Ewan}&>p^G&?9>$G*SY-UrMc2djlZSC*{fUelx>y@O^M|o! z{}dTV9?|tMKlNB^_{A+lR5Q`_(totvzwwlH@vv{Bi(Vf3X)}-73h|+fUL5+hf3kkq zFCad2(e=>JdqP`T_agI#F1jB2nP+^g6;bmp*8I#f5A!e5ZgkQ0Fu#6dX8rO&eCVRf zn|=?;@8ACZPVxKq1iycCN9kX+;qJluXyGpPCjO@02OqDt>-l=f@jMp4J$t?PNAs0> z-1VD!Yn^(n_HnM9olWiQ)NAGSwkck>AFXb3DZSKe5?a&I7+5TV5j((R(Jao~^LqB<_OMdbG^C`dRdg-4l`;UjQBfog=n-oiQJ@oJUJLNjC zl1WT-(c4)1kCge3yk>S`Xtpqw`SJ}jbkWO0|2==1J#)Zp&zG6czGQ|jdU@z)jPO77 zPbNNevF1PcZSv7x;y`@pV$DxGmp7A7B#!#kl!xu#{)yS6znLw5pE>uD8M^4@p`Z8< zKbG=~#6uTd5B=n!F8M{~9$j=j^fS)XW&Fjvm(uu)u9yCWa{bW9i;L-96EAr@bkX(D zf2XfC-t`^Rnam-&=;fjR-aW~8-?dD9=wi*!7?c0-LMA?RvF0D0O1=}HX5vE^YyJn` zPivJuh&2mo54z}j*nh@}zA}CyV}UNZ9{R~Mb2jA_d6&^e*F!)3Brp9J$%`)5^5c2> z=TukZ{X-XB5A)Mbe2klj4_&PJnP+^=zlaZAtog~qSd(95F3?5S%l02D-=DodrFVCB zevT5g)qfdg!O!r^m@J5(iy$J@m6@aCWm-i0nn^qU%*ZXV0#i z=?sFzQC#Tdp?~`A)OLKF*NTHq+@?JAGtSgwzC_xsd1=Z+KXc67kym8w&_&lnKkeh3 z#xD{FU35M4(>{FE73qii)s%;R)(Jk{bs*~iU99CN7xTrKiF`&EYxB=JQPx!)bmBGT zVf!hk&D`}w;wf%ZUiC9}>{lZ5hEH_8>Sz4OFA@j8*cre1^8M%Bef)DX?r-AKt#lrX zu9x{+e)b&N&UzEsi_t~bLqB%}eB1*>eCT4$kB2|%isk2~Jj|~<24hDX;DcYK{X}#< z^mA{<$DE7!(8Z4bcsc&O_uN~UYms{ky4bnD+~()pz%T0D5j*Ec%Rlj9I_D>U&*a{K zE_Ut@EkExl_k<^Y$i#;(*8JQV88^;;k#R#8YvV_5eB=`Gp^G&?>y)#e^(*S$BD!AA zf2;qjFMO;yQTGn9=BJ;GHT@Tv3v|)-FhBh)=ZbMC=dvj;{iAaInLm90;=7;7_bwi> z^Zn~K|8u`4zxaaphevch%-@`^Tjw|L5bq;#&_&ln|E`pH9vW{r!dzdan!D+Jj_oy?~2YnNF2p&%Bz0b&iWCFr?}Ad(9ind%)=|v zest0G(64hIzs^14po_Kn!^0nSMdqE)qJIwa(@t`ie|XVFFAM#>SJGXZb;q3>5(`~) zJ@hla_*j1;zGmFFSo7=t#`@vBhV12)`&;Y%<2_-opxq*EK^I*Q+s``3%RNA({ph0W zp`Y)J^qaaOpV7ry|Cu9v+%-ge=wi)}hjC*c78yTu(e<$X`-$<{2MrMbx~DH9zyr!~Bc18(nlg%&*^=S-(6GAG+xB zmfu72`?tTpGyMKN#qZzTQTo?yxOcEI9{o?fsXwXr*1K!%dcGcVJdee1&tC7%@j|5@ zcm1Z`dZ%8ieVi-j=TiGR^;&toZHm|JN2?y+sg$?YU+z*Xuaoz^HT8F!_or|F0*FtL A%>V!Z literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/gds_lib/replica_cell_6t.gds b/technology/scn3me_subm/gds_lib/replica_cell_6t.gds new file mode 100644 index 0000000000000000000000000000000000000000..b26d63d432c5e131143a8a62bd56769860d67ba2 GIT binary patch literal 6060 zcmbuDJ#3X#7{?!O@4dZ1!L}A?n^I~Jq@T33O8tmp!X|?Q12H71l!!@V8e)Kv!9f!S z1_l!u7)W$raA4@*(7_l+1_uWQ1_lQQ2jb$#_4(cB{rjGK>vmOhI;KIdA>+2U@`P6Krukq&F zUz~jBhp&Hq_4MZPyI;L`)+QPiF`Cs7L#$4-agZ zp^H`d#~w!B!^gykqqs$Rnt!ewzwk`g&GwC&iOdD#BD!AbXU){VH4~@niW_u2<2T#A z89wskS3A&YPf?!rGe*>7+(gzQx|nZ&)FbcIqsR}5qqwlD{j5Ly=e= zaq3a%qU+iIlLw#H4Wtj~Vvm2eoPV<;H_VoAnawPgTs;-K=;dkt#NTfJ`Hk7^`Pe_= z!jsTN*DL+xuAPfEz}fSP8}#yw-)!$-_}IV1fwTi%tn#x@sE1cvcoO?hbUm9NKicv*}%#Eefz&-y2(q8{z0KI9BR7pwA5OhsPy8f%$7Lmb5|%G3Od z>Hax--)!Z(*z4lS5i@kr^{jv3soBtNv*+F@`TQ?t=%SZr{Rhv4@6f%H_|V0?zuo@p z$H={7uH?||&_!=sHb4EO?VNQY{XrM2`~y$b2GNYR(EngZ&*ndPCVYqPiQ%LF_>1z4 zKRoO+>WcFZLKj`n_@mGG=&LyYAat?HKmIIyv==|bhb~t68E1TqzlaZA%=@FCPm`M3E;@0jhnX(kd!aiQy3Kl_H~ z_KRmrk{4a&?eagE2(Uy<`0U35L0 zpRp$|^CvR?=wd#9JTv+}i|3BmcpSRudYb=uy8ef^;;zQCiaQ%5FS_V@*3Yv$oonWS zeTXjh%zsyY@}+ad+%XsEqL-)nPxQ8*=N|P%o_n-k?0Nnr{y2Z=H|LLdJKzki3m zdg`C@N)6> zoy;}oq)04u(e+IKV|?gCdVfB8KXlQ{Gycfadw$anwF`QArJww?UnE}P>#!<6dz?Mb zxQp}~U35K@Kl;huCBMi!1Mb42>luHXJ)9Zj7imX&Cb^#RM;?BwG5(@{H;Arh{Bg$f zn}ha?^nF+Q6jD4_E zp8A)&&(HAJ&WUC^H-lCFvitxa zx}Np_zwu+8#kkEZijkLfNB*L`lYb!IAN%<4=l$_O^8UCr*8J#`HGhr8d*Xkq$6eU} z{<9wI+21>Ry{l_g@wls^TYLgR^DI~wXSs4@-5Iy!Tkwidg;Li@N;{ D@D#a1 literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/gds_lib/sense_amp.gds b/technology/scn3me_subm/gds_lib/sense_amp.gds new file mode 100644 index 0000000000000000000000000000000000000000..11081bd361edcfd05f6b8d3a5e7200e12953c4de GIT binary patch literal 8312 zcmbW6O>7la7=}OE+e^_amWn`YMHH1EDkq9O%NI)fuia${>B^ZO)fEJBLiK!7H zF`5vCfPw}C3!+9gESlJbF)m%WV8Ma~3l}a}xX=WH-_vj2%-oT47B(qQdFMXoeCN!} znV)M->#$B6n9^aRHq9E=vO8?9?X@oJw;9&se^2jd?%BR;&-NF$y*gqxv$N}=hYzgW z@bjt553D=4^u*C;H`_p0#%@;aMz>k>h7Ma}&FLLxHrUhY{}w+B&c`3{$42}u`u`d; z{I~EIU&~)|F&wyefBY@_|Em6?y3gn2LG>&8_Nsqx)$e)P>@)9R{=$;qtTrPTeS6aH zx?uLsDzn?Kl>F#*Gjh?lC;eMDnmzWt+1+PKKGS1HF8cPWKUl4wy1yLqow2{ZBj)7kB$UBo{qT`VFuB<~e4ImzBK#cb_oNMc-ca@2S?`J7IQsi`l$iOMZRH zj9m2XN&l{WW+x6t|04U1T=YEYcl+GE`-$0YCrcg}Fe4Xzd)9x>j}?4z#QVk>GxffUXc*sT1lYZYX;d9>NLp*Y^<}a)6znlIrJHFLy z*1D2kdHv*~Z?E>>=5w6mGY=vjxtR0m=g3&}FCM)R{fnMw`^Tey5s&`GoIlNL|KPCM z^xJTVmOo%rOzSWiUHll8Oia-1z{lswrJ>#^wDlRoqJiXS`d ze{tuPm_O0;q|ZFzF@GW+xtQ~rCp_j)#3L7TKJ^d#xlaA!4tL2#&$IR8QNM^s{bJ6i zPCV)t@yNxTPn|FL8bJNxwsldz=y|q&Jn9$ms9((a)QLy^A|APz^SMqeYnfelu;lXL zxPFMfJz4*ZL*cOw(hkHU7ju69pW(6I;X^!fG3RsL!s9#=@yNxT&-l4_VEiKYGUTG? z+418sZV`|1i#eZh;xTR!k6g_8j1!OXi+JQ>&S#u_mhp?UMJ{@t9X}r97x5UsnDZGY z9^)7B$ibievz#DoAVhb9^)5r$;Fz#q35Eq9r`VNk#@*M&$Ir@nen_N(vI4N zo+th3J!T*O75ClZr<=^kMbEQ7&uu)finOD4VeR>?ZT^_&O&8*RU*x%!T=YEIKhIfj zx1xTL{>eqplRoFn==0%=v_md>p7dEa9`!lqc|~L#+EKgE^Q^zt z=c{$eOr)K{o22JSpLxPtaK0q-KrZHd`g!oDs9&T#a?$f-|2+5O(Z7gCF6MlW@1gPN zU*tR}j{8Y^p6s7_VKC&gwcair=M)ST#q;GQ3^XmBTE9dX()qhUMb&h*a zu6OY4#>mCm^|Ru~xOxA^dN1m|n^=4Q*5-5F=Di#9E#i@jwfAprKF19nb&Gm$C+2+m z;XMt$NIR;l*q)fb_#ES=evx+6F3gR;cOu>svS#qU5Yi60=y|e#?(;ZKS!YDOcN9HO z`rPO7{*r!0JaV!2{<3ZUIZnCGvJQ!O??@g&+9N8E3 zi?#Qs|EV93`bFwcT`=d<|I?S^`Cp_R)m3cI*1vgc-0zCCqjsU^NuT|%`wo%gK*vR~ zJ?S%U)_v}`Md~0IYwLg8{BfVaI?eT0)O~~Kd9r`jE$$oeMcN@3YxfUr{r`{qk2YWL zxfuuVt93u5x{B?|`l%a_YrnW^ZH!0sJn7Ru#~9aJk#>mSdVT)#xFU%D<9+mros zp07V0^DXjy61nJk(r28^bN%=yXFSFBq|Z39c?MVgHG&ndGA9NuT=o zVgHHLp>Y-4lRowF!~Ww3;%i*R_DR1L-+%l1GmG!Po3p3zZ$JOGZs}V4_Yr)LGG^U<%^kaji&0+dbF7jZe3JT_qrIsDoi#S`pQud!kO0^~sZApigX literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/gds_lib/tri_gate.gds b/technology/scn3me_subm/gds_lib/tri_gate.gds new file mode 100644 index 0000000000000000000000000000000000000000..c48fe3a1404e24a5296e010f4a2e70bf403544fa GIT binary patch literal 4576 zcmai&Ka5pH6vjW^zI`nC#N8(%OIAejAF#-xYZla?1QJ3-F%c4DOb`PhBnAyx(Za%l zLX#~mOthdd(Za&Qf`Z}|##mZdSWsG6SXfwCXz=`)`{mBNWX4V82jARp&N*{u&Rkam z^)#i0bv<3t2K6=6!&=b?n$|YWX;#}c>*V5n3_*Z`}{%icZTmP+F z|9&Ga--yXRX?c1r>1K@Q{#{)^(eRtgH#~1*=(&Gy>zD4jE*<|xx^HXC*OrrR#(2@+ zdtG|qghbuuW8X^XX6U(pF^|u4&;5}6Ci$S7p%?w+fA1eDf0I1W&CqlIo;?1hS?R>0 zG#a;j^`?Yw#(2@+|4urzAU*nV%VQtKf`@L#c-8;lSIKWaaw_@F(2IWZ+;TMKZ*Kc5 zH5x^lJV1sNcj#{btQio%pER z#D{Ly{M3n$x=noOX3bBY_rI6&H|Kv!`J18V^*@>KKh7xUd{@6E=MmlP^q&d;#x?2L z&!ypSEtwD9jPYW8o_pr^l&{Hrp0^pV`pK2}Ci8e+7<$o9&)R<=one!_(aq3{eqz!$ z=^Z9MbhFbxC)RH?PIm|IjynXB2f7)0F+O<`i{4{054st8(T|5%0>^ProdSN+@-+#e?McwQKK?%$W6AMUx8 z&8c?t;5+I5Gea->c~5)4Pw&rM8m9MWhFo?&i9=(hD%{_0XJj~FG z`LjPcbL@YUzKL#zp8NOb^|R;cllV=4x0s<9{Zm)dcME%!?-97~@qx_ZEJWcfpU@xxb#y`xm*oZ<+KhbhFdH zCj8tnK6fVP58Vts&;Jg;_nFDQ#czgQ^;0WrZ!!;lGxVaL{o?m#QaidC`fdL({r(~P z#}yCVtbP3lI2r_= literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/gds_lib/write_driver.gds b/technology/scn3me_subm/gds_lib/write_driver.gds new file mode 100644 index 0000000000000000000000000000000000000000..0bef7b7973766b293c75f95a3892e39ed2b0dc5f GIT binary patch literal 11804 zcmai)ZOoQs8OIMF9v;Dn;ECjAL^jFSr@&%K>B`EACKW4IL}X9-Fu@!nhL5&rV-A-Q zF>SV3FB@*IsNr&^Mn#K^8Esaq(PGZZ%Dyx{@WBs$aI^o9ElAe$0zyF>hq-&K+BKZvO1lj;+(1 zcf^7jGvD=|uU&i7Q$IZWjvJ4xIQZR->tpH6hJUQZbIjpKSQe>yD@2ls@Rc zayb8kYA=5COfSDFz3IR1c>2xhP41W5(eb~zpFd(`L&P5zL@c|j&wrds-PG~H{2l*m zu8;WD>4-PJ)aQw*2y|1&OaH6X_a{!K-y|NoDZTWMAB%YWq4b-?K{utBe)|7|E!ltb zCnvK1ru5QJJHL81;&qGq-2Y;>-_-HaKVwhCl=8hneK2p+ztK(UP5)=qSLV+oj^je< zrT>D7i1(?zmmTi&!y6*dO&xFgZ`c{}`n3@z@f;UQZ~Cd7i}vLl!YfD9Z|eAMk-UG^CEtx`p0h)2i=t3^gpV$Q}-ru92ZJ2{q*yYy!79EczgEWl-~4zQ{#o-{ElK0 z*OXrRY2V&8*?yBa=%)12Kl9m$uT16j$Gqo21iC4`>8DP)ewkbJZ~W#^{dekz^Cq=+ zFTJ8q;-H&4Ugl?=eqde1^7Vb*6uEv)9dG*I`*g&T7a~mJIWCmm^iSNI`OQ^F({D;| z`f2;DRT%>khrFha5BgUQu0O`<^xM;KKC?f^&y-&J*=OKmy_xvX&6a=B_tMAs;fMIp z&6c0`|9NA!-#qnbw%?TAY(GBQZ{nlA&-8ixxd?Pq z$IJFFxjB7HpXd`Gy4muR=jT^sev|7Sx+%SxA0PQmeB?JH>Dr~mA^m@kuOV02S@>8DP9x;E>_WdDn9 zN-zDapKslk>&N`|levCO>7}1M_*g$CK6JC?XPw|<{h0XB&6b~W+x@YufAj7i=XjdZ z%l1<@_^5vqAG+D{Q!n_adlMhJ+48e*{G6^AJVTkcsPE{e^s@cb$%^UhuX)WMvwlqJ zrJr?zkN%qY(9M>gb%Kxnn)uMomY;QkkNua458WK{zh!X$anZhre{V>?`JYGfdBT)F z*#B4fd4DqJ`Fwu@iQ~9%=>18@|JpMVzrRoSKh2@Zdlz(5dYPYoo_;#pZ;~I~l-~58 zTAJ4mlQ@nGrI&uz&+k@e`%U_RZc1i5^9={JdkZb~oxTxWRC z#QP8P*vh>An9@r>^LzigoPU$|2WA~FACtV)k14&( z&w1o!o=xJQo2~q`^OI^j<82bh{puYr^YfnLX652~Ve;Mr-IQMXd2h07bzUz_e1q@f zq?i72UAMpVT>4GopqtX0{x6)&d?s-m7fLVv%kGM}V`YxN$@rn0(n~-0z3scxZxRRH zlwSJB)xNFDwQzf%^aI`0@zT#cZF(Tri^)8CUVFz&KlSnPRk?pKsUz1_?|A8F-QZ&# zo3sPnlwSI&6V9XmCgXu_N^kl%DmV9AlQ@nGrI&u@iT>g@iGyxRFa68cXTQ0A(SKjZ z(7B%Vj+cJMY2CBwGl}DI?HzCWKe8vs-z1LXLg}S{_GHA`iS(PqK{us0{am}KGm|)u z3#FI-an=baUwaZRh^QzMr|{{$HpNc^qZen|A}i# zFa6wi*H7kt$^3-I6Wx?v`dJ^m`(*4*u0`mk^wLkAP)`z1`B!iK zo6qmbSf=#S&vV}259RgJ{Ac9zpDDfcGtQ4`?wCK5?}q56^wQ5hiT5tlugQBCbaUwa zOQ-*g@#Yt@UQOORqnpyp{M@&=-tqioa@|BXhpwNU{G7*o1N`RYr_*mrFY`0ctR3dx zWbcb^N+0xJGdTaOGv~Npwd4B7(pEb&ND%x+-4s=s`bNu*D!}ytg z?lPs9e)9ZgQ`WmlJKV0`@zT#Y`@5NWRAYf|4t+oC^q=z%sqggP9R7YLz0A)(jrV4( zR}(+FIrRRllb?C!cL&VB`LHx}bLjU69Y60q@G<`;^?+`+{N&N^OV0UC;<#PC<7NLD zKb}((q`(ww?{foTZdrk79o2~q`e|l5;P2#v;z2nXPPcF*-o5XQk zD82O4&O26SeiJ{sDZT06zB|{CNgT(8(n~+%#(k1{H+gPDH>H<;=81kYea!N2JZ+_rsj0--yjxJT|p;TlYMz)BbrQ8_wNR#ukrl-d0CrxAEV}&{?0qy*`U) zt=?HX>a)0m=naxucI&pOZp%77V3p{Xdgnclc-kfEyy>Y{Jf7tC9X$Ve++iPosGIjf IwR1H72j`DC)c^nh literal 0 HcmV?d00001 diff --git a/technology/scn3me_subm/mag_lib/.magicrc b/technology/scn3me_subm/mag_lib/.magicrc new file mode 100644 index 00000000..f52d0592 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/.magicrc @@ -0,0 +1,5 @@ +path sys +$::env(OPENRAM_TECH)/scn3me_subm/tech +tech load SCN3ME_SUBM.30 -noprompt +scalegrid 1 4 +set GND gnd +set VDD vdd diff --git a/technology/scn3me_subm/mag_lib/cell_1rw_1r.mag b/technology/scn3me_subm/mag_lib/cell_1rw_1r.mag new file mode 100644 index 00000000..6a6fbc86 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/cell_1rw_1r.mag @@ -0,0 +1,156 @@ +magic +tech scmos +timestamp 1558933786 +<< nwell >> +rect 0 48 54 77 +<< pwell >> +rect 0 0 54 48 +<< ntransistor >> +rect 14 34 16 38 +rect 22 30 24 38 +rect 30 30 32 38 +rect 38 34 40 38 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 56 24 59 +rect 30 56 32 59 +<< ndiffusion >> +rect 13 34 14 38 +rect 16 34 17 38 +rect 21 34 22 38 +rect 17 30 22 34 +rect 24 36 30 38 +rect 24 32 25 36 +rect 29 32 30 36 +rect 24 30 30 32 +rect 32 34 33 38 +rect 37 34 38 38 +rect 40 34 41 38 +rect 32 30 37 34 +rect 9 21 14 23 +rect 13 17 14 21 +rect 16 17 22 23 +rect 24 22 30 23 +rect 24 18 25 22 +rect 29 18 30 22 +rect 24 17 30 18 +rect 32 17 38 23 +rect 40 21 45 23 +rect 40 17 41 21 +<< pdiffusion >> +rect 21 56 22 59 +rect 24 56 25 59 +rect 29 56 30 59 +rect 32 56 33 59 +<< ndcontact >> +rect 9 34 13 38 +rect 17 34 21 38 +rect 25 32 29 36 +rect 33 34 37 38 +rect 41 34 45 38 +rect 9 17 13 21 +rect 25 18 29 22 +rect 41 17 45 21 +<< pdcontact >> +rect 17 56 21 60 +rect 25 56 29 60 +rect 33 56 37 60 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 37 70 41 74 +<< polysilicon >> +rect 22 59 24 62 +rect 30 59 32 62 +rect 22 45 24 56 +rect 30 53 32 56 +rect 13 41 16 43 +rect 14 38 16 41 +rect 22 38 24 41 +rect 30 38 32 49 +rect 38 41 41 43 +rect 38 38 40 41 +rect 14 32 16 34 +rect 38 32 40 34 +rect 14 23 16 24 +rect 22 23 24 30 +rect 30 23 32 30 +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 28 49 32 53 +rect 9 41 13 45 +rect 22 41 26 45 +rect 41 41 45 45 +rect 12 24 16 28 +rect 38 24 42 28 +<< metal1 >> +rect 0 70 25 74 +rect 29 70 37 74 +rect 41 70 54 74 +rect 0 63 54 67 +rect 9 45 13 63 +rect 16 56 17 60 +rect 37 56 38 60 +rect 16 53 20 56 +rect 16 49 28 53 +rect 16 38 19 49 +rect 35 45 38 56 +rect 26 41 38 45 +rect 41 45 45 63 +rect 35 38 38 41 +rect 6 34 9 38 +rect 16 34 17 38 +rect 25 36 29 38 +rect 37 34 38 38 +rect 45 34 48 38 +rect 25 22 29 32 +rect 25 13 29 18 +rect 0 9 25 13 +rect 29 9 54 13 +rect 0 2 16 6 +rect 20 2 34 6 +rect 38 2 54 6 +<< m2contact >> +rect 25 70 29 74 +rect 25 56 29 60 +rect 2 34 6 38 +rect 48 34 52 38 +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 38 6 74 +rect 2 0 6 34 +rect 9 21 13 74 +rect 25 60 29 70 +rect 9 0 13 17 +rect 16 6 20 24 +rect 34 6 38 24 +rect 41 21 45 74 +rect 41 0 45 17 +rect 48 38 52 74 +rect 48 0 52 34 +<< comment >> +rect 0 0 54 72 +<< labels >> +rlabel metal1 27 4 27 4 4 wl1 +rlabel psubstratepcontact 27 11 27 11 4 gnd +rlabel metal2 4 7 4 7 4 bl0 +rlabel metal2 50 7 50 7 4 br0 +rlabel metal1 19 65 19 65 4 wl0 +rlabel metal2 11 7 11 7 4 bl1 +rlabel metal2 43 7 43 7 4 br1 +rlabel metal1 18 72 18 72 1 vdd +<< properties >> +string path 0.000 0.000 243.000 0.000 243.000 324.000 0.000 324.000 0.000 0.000 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/cell_1w_1r.mag b/technology/scn3me_subm/mag_lib/cell_1w_1r.mag new file mode 100644 index 00000000..6a6fbc86 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/cell_1w_1r.mag @@ -0,0 +1,156 @@ +magic +tech scmos +timestamp 1558933786 +<< nwell >> +rect 0 48 54 77 +<< pwell >> +rect 0 0 54 48 +<< ntransistor >> +rect 14 34 16 38 +rect 22 30 24 38 +rect 30 30 32 38 +rect 38 34 40 38 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 56 24 59 +rect 30 56 32 59 +<< ndiffusion >> +rect 13 34 14 38 +rect 16 34 17 38 +rect 21 34 22 38 +rect 17 30 22 34 +rect 24 36 30 38 +rect 24 32 25 36 +rect 29 32 30 36 +rect 24 30 30 32 +rect 32 34 33 38 +rect 37 34 38 38 +rect 40 34 41 38 +rect 32 30 37 34 +rect 9 21 14 23 +rect 13 17 14 21 +rect 16 17 22 23 +rect 24 22 30 23 +rect 24 18 25 22 +rect 29 18 30 22 +rect 24 17 30 18 +rect 32 17 38 23 +rect 40 21 45 23 +rect 40 17 41 21 +<< pdiffusion >> +rect 21 56 22 59 +rect 24 56 25 59 +rect 29 56 30 59 +rect 32 56 33 59 +<< ndcontact >> +rect 9 34 13 38 +rect 17 34 21 38 +rect 25 32 29 36 +rect 33 34 37 38 +rect 41 34 45 38 +rect 9 17 13 21 +rect 25 18 29 22 +rect 41 17 45 21 +<< pdcontact >> +rect 17 56 21 60 +rect 25 56 29 60 +rect 33 56 37 60 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 37 70 41 74 +<< polysilicon >> +rect 22 59 24 62 +rect 30 59 32 62 +rect 22 45 24 56 +rect 30 53 32 56 +rect 13 41 16 43 +rect 14 38 16 41 +rect 22 38 24 41 +rect 30 38 32 49 +rect 38 41 41 43 +rect 38 38 40 41 +rect 14 32 16 34 +rect 38 32 40 34 +rect 14 23 16 24 +rect 22 23 24 30 +rect 30 23 32 30 +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 28 49 32 53 +rect 9 41 13 45 +rect 22 41 26 45 +rect 41 41 45 45 +rect 12 24 16 28 +rect 38 24 42 28 +<< metal1 >> +rect 0 70 25 74 +rect 29 70 37 74 +rect 41 70 54 74 +rect 0 63 54 67 +rect 9 45 13 63 +rect 16 56 17 60 +rect 37 56 38 60 +rect 16 53 20 56 +rect 16 49 28 53 +rect 16 38 19 49 +rect 35 45 38 56 +rect 26 41 38 45 +rect 41 45 45 63 +rect 35 38 38 41 +rect 6 34 9 38 +rect 16 34 17 38 +rect 25 36 29 38 +rect 37 34 38 38 +rect 45 34 48 38 +rect 25 22 29 32 +rect 25 13 29 18 +rect 0 9 25 13 +rect 29 9 54 13 +rect 0 2 16 6 +rect 20 2 34 6 +rect 38 2 54 6 +<< m2contact >> +rect 25 70 29 74 +rect 25 56 29 60 +rect 2 34 6 38 +rect 48 34 52 38 +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 38 6 74 +rect 2 0 6 34 +rect 9 21 13 74 +rect 25 60 29 70 +rect 9 0 13 17 +rect 16 6 20 24 +rect 34 6 38 24 +rect 41 21 45 74 +rect 41 0 45 17 +rect 48 38 52 74 +rect 48 0 52 34 +<< comment >> +rect 0 0 54 72 +<< labels >> +rlabel metal1 27 4 27 4 4 wl1 +rlabel psubstratepcontact 27 11 27 11 4 gnd +rlabel metal2 4 7 4 7 4 bl0 +rlabel metal2 50 7 50 7 4 br0 +rlabel metal1 19 65 19 65 4 wl0 +rlabel metal2 11 7 11 7 4 bl1 +rlabel metal2 43 7 43 7 4 br1 +rlabel metal1 18 72 18 72 1 vdd +<< properties >> +string path 0.000 0.000 243.000 0.000 243.000 324.000 0.000 324.000 0.000 0.000 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/cell_6t.mag b/technology/scn3me_subm/mag_lib/cell_6t.mag new file mode 100644 index 00000000..f2e9906a --- /dev/null +++ b/technology/scn3me_subm/mag_lib/cell_6t.mag @@ -0,0 +1,117 @@ +magic +tech scmos +timestamp 1536091415 +<< nwell >> +rect -8 29 42 51 +<< pwell >> +rect -8 -8 42 29 +<< ntransistor >> +rect 7 10 9 18 +rect 29 10 31 18 +rect 10 3 14 5 +rect 24 3 28 5 +<< ptransistor >> +rect 7 37 11 40 +rect 27 37 31 40 +<< ndiffusion >> +rect -2 16 7 18 +rect 2 12 7 16 +rect -2 10 7 12 +rect 9 14 10 18 +rect 9 10 14 14 +rect 28 14 29 18 +rect 24 10 29 14 +rect 31 16 36 18 +rect 31 12 32 16 +rect 31 10 36 12 +rect 10 5 14 10 +rect 24 5 28 10 +rect 10 2 14 3 +rect 24 2 28 3 +<< pdiffusion >> +rect 2 37 7 40 +rect 11 37 12 40 +rect 26 37 27 40 +rect 31 37 32 40 +<< ndcontact >> +rect -2 12 2 16 +rect 10 14 14 18 +rect 24 14 28 18 +rect 32 12 36 16 +rect 10 -2 14 2 +rect 24 -2 28 2 +<< pdcontact >> +rect -2 36 2 40 +rect 12 36 16 40 +rect 22 36 26 40 +rect 32 36 36 40 +<< psubstratepcontact >> +rect -2 22 2 26 +rect 32 22 36 26 +<< nsubstratencontact >> +rect 32 44 36 48 +<< polysilicon >> +rect 7 40 11 42 +rect 27 40 31 42 +rect 7 35 11 37 +rect 7 21 9 35 +rect 27 34 31 37 +rect 15 33 31 34 +rect 19 32 31 33 +rect 7 20 21 21 +rect 7 19 24 20 +rect 7 18 9 19 +rect 29 18 31 32 +rect 7 8 9 10 +rect 17 5 21 6 +rect 29 8 31 10 +rect -2 3 10 5 +rect 14 3 24 5 +rect 28 3 36 5 +<< polycontact >> +rect 15 29 19 33 +rect 21 20 25 24 +rect 17 6 21 10 +<< metal1 >> +rect -2 44 15 48 +rect 19 44 32 48 +rect -2 40 2 44 +rect 32 40 36 44 +rect 11 36 12 40 +rect 26 36 27 40 +rect -2 26 2 29 +rect -2 16 2 22 +rect 11 18 15 36 +rect 23 24 27 36 +rect 25 20 27 24 +rect 14 14 15 18 +rect 23 18 27 20 +rect 32 26 36 29 +rect 23 14 24 18 +rect 32 16 36 22 +rect -2 6 17 9 +rect 21 6 36 9 +rect -2 5 36 6 +<< m2contact >> +rect 15 44 19 48 +rect -2 29 2 33 +rect 32 29 36 33 +rect 6 -2 10 2 +rect 20 -2 24 2 +<< metal2 >> +rect -2 33 2 48 +rect -2 -2 2 29 +rect 6 2 10 48 +rect 24 -2 28 48 +rect 32 33 36 48 +rect 32 -2 36 29 +<< bb >> +rect 0 0 34 46 +<< labels >> +rlabel metal2 0 0 0 0 1 gnd +rlabel metal2 34 0 34 0 1 gnd +rlabel m2contact 17 46 17 46 5 vdd +rlabel metal2 8 43 8 43 1 bl +rlabel metal2 26 43 26 43 1 br +rlabel metal1 4 7 4 7 1 wl +<< end >> diff --git a/technology/scn3me_subm/mag_lib/convertall.sh b/technology/scn3me_subm/mag_lib/convertall.sh new file mode 100755 index 00000000..43de584f --- /dev/null +++ b/technology/scn3me_subm/mag_lib/convertall.sh @@ -0,0 +1,22 @@ +magic -dnull -noconsole << EOF +load dff +gds write dff.gds +load cell_6t +gds write cell_6t.gds +load replica_cell_6t +gds write replica_cell_6t.gds +load sense_amp +gds write sense_amp.gds +load tri_gate +gds write tri_gate.gds +load write_driver +gds write write_driver.gds +load replica_cell_1w_1r +gds write replica_cell_1w_1r +load replica_cell_1rw_1r +gds write replica_cell_1rw_1r +load cell_1rw_1r +gds write cell_1rw_1r +load cell_1w_1r +gds write cell_1w_1r +EOF diff --git a/technology/scn3me_subm/mag_lib/dff.mag b/technology/scn3me_subm/mag_lib/dff.mag new file mode 100644 index 00000000..46d22c84 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/dff.mag @@ -0,0 +1,279 @@ +magic +tech scmos +timestamp 1536089597 +<< nwell >> +rect 0 48 109 103 +<< pwell >> +rect 0 -3 109 48 +<< ntransistor >> +rect 11 6 13 26 +rect 19 6 21 16 +rect 24 6 26 16 +rect 33 6 35 16 +rect 38 6 40 16 +rect 47 6 49 16 +rect 63 6 65 16 +rect 68 6 70 16 +rect 78 6 80 16 +rect 83 6 85 16 +rect 91 6 93 26 +<< ptransistor >> +rect 11 54 13 94 +rect 19 74 21 94 +rect 25 74 27 94 +rect 33 74 35 94 +rect 39 74 41 94 +rect 47 74 49 94 +rect 63 74 65 94 +rect 68 74 70 94 +rect 78 84 80 94 +rect 83 84 85 94 +rect 91 54 93 94 +<< ndiffusion >> +rect 6 25 11 26 +rect 10 6 11 25 +rect 13 25 18 26 +rect 13 6 14 25 +rect 86 25 91 26 +rect 18 6 19 16 +rect 21 6 24 16 +rect 26 15 33 16 +rect 26 6 28 15 +rect 32 6 33 15 +rect 35 6 38 16 +rect 40 15 47 16 +rect 40 6 41 15 +rect 45 6 47 15 +rect 49 15 54 16 +rect 49 6 50 15 +rect 58 15 63 16 +rect 62 6 63 15 +rect 65 6 68 16 +rect 70 15 78 16 +rect 70 6 72 15 +rect 76 6 78 15 +rect 80 6 83 16 +rect 85 6 86 16 +rect 90 6 91 25 +rect 93 25 98 26 +rect 93 6 94 25 +<< pdiffusion >> +rect 6 93 11 94 +rect 10 54 11 93 +rect 13 55 14 94 +rect 18 74 19 94 +rect 21 74 25 94 +rect 27 93 33 94 +rect 27 74 28 93 +rect 32 74 33 93 +rect 35 74 39 94 +rect 41 93 47 94 +rect 41 74 42 93 +rect 46 74 47 93 +rect 49 93 54 94 +rect 49 74 50 93 +rect 58 93 63 94 +rect 62 74 63 93 +rect 65 74 68 94 +rect 70 93 78 94 +rect 70 74 72 93 +rect 76 84 78 93 +rect 80 84 83 94 +rect 85 93 91 94 +rect 85 84 86 93 +rect 76 74 77 84 +rect 13 54 18 55 +rect 90 54 91 93 +rect 93 93 98 94 +rect 93 54 94 93 +<< ndcontact >> +rect 6 6 10 25 +rect 14 6 18 25 +rect 28 6 32 15 +rect 41 6 45 15 +rect 50 6 54 15 +rect 58 6 62 15 +rect 72 6 76 15 +rect 86 6 90 25 +rect 94 6 98 25 +<< pdcontact >> +rect 6 54 10 93 +rect 14 55 18 94 +rect 28 74 32 93 +rect 42 74 46 93 +rect 50 74 54 93 +rect 58 74 62 93 +rect 72 74 76 93 +rect 86 54 90 93 +rect 94 54 98 93 +<< psubstratepcontact >> +rect 102 6 106 10 +<< nsubstratencontact >> +rect 102 89 106 93 +<< polysilicon >> +rect 11 94 13 96 +rect 19 94 21 96 +rect 25 94 27 96 +rect 33 94 35 96 +rect 39 94 41 96 +rect 47 94 49 96 +rect 63 94 65 96 +rect 68 94 70 96 +rect 78 94 80 96 +rect 83 94 85 96 +rect 91 94 93 96 +rect 11 37 13 54 +rect 19 46 21 74 +rect 11 26 13 33 +rect 19 16 21 42 +rect 25 38 27 74 +rect 33 54 35 74 +rect 33 29 35 50 +rect 24 27 35 29 +rect 39 71 41 74 +rect 24 16 26 27 +rect 39 23 41 67 +rect 47 61 49 74 +rect 63 73 65 74 +rect 54 71 65 73 +rect 34 19 35 23 +rect 33 16 35 19 +rect 38 19 39 23 +rect 38 16 40 19 +rect 47 16 49 57 +rect 53 19 55 67 +rect 68 63 70 74 +rect 78 67 80 84 +rect 76 65 80 67 +rect 63 61 70 63 +rect 61 24 63 33 +rect 68 31 70 61 +rect 83 53 85 84 +rect 79 51 85 53 +rect 78 31 80 47 +rect 91 45 93 54 +rect 89 41 93 45 +rect 68 29 75 31 +rect 61 22 70 24 +rect 53 17 65 19 +rect 63 16 65 17 +rect 68 16 70 22 +rect 73 19 75 29 +rect 78 27 79 31 +rect 73 17 80 19 +rect 78 16 80 17 +rect 83 16 85 31 +rect 91 26 93 41 +rect 11 4 13 6 +rect 19 4 21 6 +rect 24 4 26 6 +rect 33 4 35 6 +rect 38 4 40 6 +rect 47 4 49 6 +rect 63 4 65 6 +rect 68 4 70 6 +rect 78 4 80 6 +rect 83 4 85 6 +rect 91 4 93 6 +<< polycontact >> +rect 17 42 21 46 +rect 10 33 14 37 +rect 31 50 35 54 +rect 25 34 29 38 +rect 39 67 43 71 +rect 45 57 49 61 +rect 30 19 34 23 +rect 39 19 43 23 +rect 53 67 57 71 +rect 59 59 63 63 +rect 74 61 78 65 +rect 59 33 63 37 +rect 77 47 81 51 +rect 85 41 89 45 +rect 79 27 83 31 +<< metal1 >> +rect 0 97 109 103 +rect 14 94 18 97 +rect 6 93 10 94 +rect 28 93 32 94 +rect 22 74 28 77 +rect 42 93 46 97 +rect 50 93 54 94 +rect 58 93 62 97 +rect 71 93 77 94 +rect 71 74 72 93 +rect 76 74 77 93 +rect 86 93 90 97 +rect 50 71 53 74 +rect 43 68 53 71 +rect 26 57 45 60 +rect 52 60 59 63 +rect 52 54 55 60 +rect 71 56 74 65 +rect 10 50 31 52 +rect 35 51 55 54 +rect 62 53 74 56 +rect 94 93 98 94 +rect 102 93 106 97 +rect 6 49 34 50 +rect 21 43 38 46 +rect 18 34 25 37 +rect 62 37 65 53 +rect 94 51 98 54 +rect 81 48 94 51 +rect 74 41 85 44 +rect 29 34 59 37 +rect 6 25 10 26 +rect 14 25 18 26 +rect 31 23 34 34 +rect 63 34 65 37 +rect 94 31 98 47 +rect 83 28 98 31 +rect 94 25 98 28 +rect 43 19 53 22 +rect 50 16 53 19 +rect 22 15 32 16 +rect 22 13 28 15 +rect 41 15 46 16 +rect 45 6 46 15 +rect 50 15 54 16 +rect 58 15 62 16 +rect 70 15 77 16 +rect 70 13 72 15 +rect 71 6 72 13 +rect 76 6 77 15 +rect 14 3 18 6 +rect 41 3 46 6 +rect 58 3 62 6 +rect 86 3 90 6 +rect 102 3 106 6 +rect 0 -3 109 3 +<< m2contact >> +rect 22 70 26 74 +rect 70 70 74 74 +rect 22 57 26 61 +rect 6 50 10 54 +rect 38 43 42 47 +rect 14 33 18 37 +rect 94 47 98 51 +rect 70 40 74 44 +rect 6 26 10 30 +rect 22 16 26 20 +rect 70 16 74 20 +<< metal2 >> +rect 22 61 26 70 +rect 6 30 10 50 +rect 22 20 26 57 +rect 70 44 74 70 +rect 70 20 74 40 +<< bb >> +rect 0 0 109 100 +<< labels >> +rlabel m2contact 15 34 15 34 4 clk +rlabel m2contact 40 45 40 45 4 D +rlabel m2contact 96 49 96 49 4 Q +rlabel metal1 32 98 32 98 4 vdd +rlabel metal1 44 1 44 1 4 gnd +<< properties >> +string path 0.000 0.000 900.000 0.000 900.000 900.000 0.000 900.000 0.000 0.000 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/ms_flop.mag b/technology/scn3me_subm/mag_lib/ms_flop.mag new file mode 100644 index 00000000..713d264f --- /dev/null +++ b/technology/scn3me_subm/mag_lib/ms_flop.mag @@ -0,0 +1,294 @@ +magic +tech scmos +timestamp 1536089622 +<< nwell >> +rect -2 0 18 200 +<< pwell >> +rect 18 0 40 200 +<< ntransistor >> +rect 24 178 27 180 +rect 24 162 27 164 +rect 24 138 27 140 +rect 24 130 27 132 +rect 24 112 27 114 +rect 24 93 27 95 +rect 24 77 27 79 +rect 24 50 27 52 +rect 24 42 27 44 +rect 24 24 27 26 +<< ptransistor >> +rect 6 178 12 180 +rect 6 162 12 164 +rect 6 138 12 140 +rect 6 130 12 132 +rect 6 112 12 114 +rect 6 93 12 95 +rect 6 77 12 79 +rect 6 50 12 52 +rect 6 42 12 44 +rect 6 24 12 26 +<< ndiffusion >> +rect 24 180 27 181 +rect 24 177 27 178 +rect 24 164 27 165 +rect 24 161 27 162 +rect 28 157 32 161 +rect 24 140 27 141 +rect 24 137 27 138 +rect 24 132 27 133 +rect 24 129 27 130 +rect 24 114 27 115 +rect 24 111 27 112 +rect 24 95 27 96 +rect 24 92 27 93 +rect 24 79 27 80 +rect 24 76 27 77 +rect 28 72 32 76 +rect 24 52 27 53 +rect 24 49 27 50 +rect 24 44 27 45 +rect 24 41 27 42 +rect 24 26 27 27 +rect 24 23 27 24 +<< pdiffusion >> +rect 6 180 12 181 +rect 6 177 12 178 +rect 6 164 12 165 +rect 6 161 12 162 +rect 6 140 12 141 +rect 6 137 12 138 +rect 6 132 12 133 +rect 6 129 12 130 +rect 6 114 12 115 +rect 6 111 12 112 +rect 6 95 12 96 +rect 6 92 12 93 +rect 6 79 12 80 +rect 6 76 12 77 +rect 6 52 12 53 +rect 6 49 12 50 +rect 6 44 12 45 +rect 6 41 12 42 +rect 6 26 12 27 +rect 6 23 12 24 +rect 8 18 12 19 +<< ndcontact >> +rect 24 181 28 185 +rect 24 173 28 177 +rect 24 165 28 169 +rect 24 157 28 161 +rect 24 141 28 145 +rect 24 133 28 137 +rect 24 125 28 129 +rect 24 115 28 119 +rect 24 107 28 111 +rect 24 96 28 100 +rect 24 88 28 92 +rect 24 80 28 84 +rect 24 72 28 76 +rect 24 53 28 57 +rect 24 45 28 49 +rect 24 37 28 41 +rect 24 27 28 31 +rect 24 19 28 23 +<< pdcontact >> +rect 6 181 12 185 +rect 6 173 12 177 +rect 6 165 12 169 +rect 6 157 12 161 +rect 6 141 12 145 +rect 6 133 12 137 +rect 6 125 12 129 +rect 6 115 12 119 +rect 6 107 12 111 +rect 6 96 12 100 +rect 6 88 12 92 +rect 6 80 12 84 +rect 6 72 12 76 +rect 6 53 12 57 +rect 6 45 12 49 +rect 6 37 12 41 +rect 6 27 12 31 +rect 6 19 12 23 +<< psubstratepcontact >> +rect 32 157 36 161 +rect 32 72 36 76 +<< nsubstratencontact >> +rect 8 14 12 18 +<< polysilicon >> +rect 4 178 6 180 +rect 12 178 24 180 +rect 27 178 29 180 +rect 17 173 19 178 +rect 4 162 6 164 +rect 12 163 24 164 +rect 12 162 17 163 +rect 21 162 24 163 +rect 27 162 29 164 +rect 3 148 13 150 +rect 3 140 5 148 +rect 3 138 6 140 +rect 12 138 14 140 +rect 17 138 24 140 +rect 27 138 29 140 +rect 17 132 19 138 +rect 3 130 6 132 +rect 12 130 19 132 +rect 22 130 24 132 +rect 27 130 31 132 +rect 3 114 5 130 +rect 29 122 31 130 +rect 20 120 31 122 +rect 3 112 6 114 +rect 12 112 24 114 +rect 27 112 29 114 +rect 4 93 6 95 +rect 12 93 24 95 +rect 27 93 29 95 +rect 19 89 21 93 +rect 4 77 6 79 +rect 12 78 24 79 +rect 12 77 17 78 +rect 21 77 24 78 +rect 27 77 29 79 +rect 3 60 13 62 +rect 3 52 5 60 +rect 3 50 6 52 +rect 12 50 14 52 +rect 17 50 24 52 +rect 27 50 29 52 +rect 17 44 19 50 +rect 3 42 6 44 +rect 12 42 19 44 +rect 22 42 24 44 +rect 27 42 31 44 +rect 3 26 5 42 +rect 29 34 31 42 +rect 20 32 31 34 +rect 3 24 6 26 +rect 12 24 24 26 +rect 27 24 29 26 +rect 16 14 18 24 +<< polycontact >> +rect 16 169 20 173 +rect 17 159 21 163 +rect 13 148 17 152 +rect 16 118 20 122 +rect 15 108 19 112 +rect 17 85 21 89 +rect 17 74 21 78 +rect 13 60 17 64 +rect 16 30 20 34 +rect 15 10 19 14 +<< metal1 >> +rect 16 182 24 185 +rect -2 173 6 177 +rect 28 173 36 177 +rect -2 164 2 173 +rect 12 166 20 169 +rect 2 160 6 161 +rect -2 157 6 160 +rect 33 161 36 173 +rect -2 111 2 157 +rect 28 157 32 161 +rect 12 142 24 145 +rect 12 134 20 137 +rect 12 126 20 129 +rect 20 118 24 119 +rect 16 116 24 118 +rect -2 107 6 111 +rect 33 111 36 153 +rect -2 92 2 107 +rect 28 107 36 111 +rect 12 97 24 100 +rect 33 92 36 107 +rect -2 88 6 92 +rect -2 76 2 88 +rect 28 88 36 92 +rect 6 84 20 85 +rect 12 82 20 84 +rect -2 72 6 76 +rect 33 76 36 88 +rect -2 41 2 72 +rect 28 72 32 76 +rect 12 54 24 57 +rect 12 46 20 49 +rect 12 38 20 41 +rect -2 22 2 37 +rect 20 30 24 31 +rect 16 28 24 30 +rect 33 23 36 68 +rect -2 19 6 22 +rect 28 20 36 23 +rect 8 18 12 19 +rect -2 10 15 11 +rect 19 10 36 11 +rect -2 8 36 10 +<< m2contact >> +rect 12 181 16 185 +rect 20 166 24 170 +rect -2 160 2 164 +rect 17 155 21 159 +rect 32 153 36 157 +rect 6 145 10 149 +rect 17 148 21 152 +rect 20 133 24 137 +rect 20 125 24 129 +rect 12 115 16 119 +rect 15 104 19 108 +rect 6 100 10 104 +rect 20 81 24 85 +rect 17 70 21 74 +rect 32 68 36 72 +rect 6 57 10 61 +rect 17 60 21 64 +rect 20 45 24 49 +rect -2 37 2 41 +rect 20 37 24 41 +rect 12 27 16 31 +<< metal2 >> +rect 6 185 10 200 +rect 15 196 19 200 +rect 15 192 24 196 +rect 6 181 12 185 +rect 6 149 9 181 +rect 20 170 24 192 +rect 21 155 27 159 +rect 18 143 21 148 +rect 13 140 21 143 +rect 13 119 16 140 +rect 24 133 27 155 +rect 5 100 6 104 +rect 5 61 8 100 +rect 15 93 19 104 +rect 11 90 19 93 +rect 11 67 14 90 +rect 24 81 27 129 +rect 21 70 27 74 +rect 11 64 16 67 +rect 5 57 6 61 +rect 13 60 17 64 +rect 13 31 16 60 +rect 24 45 27 70 +rect 24 8 27 41 +rect 19 4 27 8 +rect 15 0 19 4 +<< m3contact >> +rect 15 4 19 8 +<< metal3 >> +rect 14 8 20 9 +rect 14 4 15 8 +rect 19 4 20 8 +rect 14 3 20 4 +<< bb >> +rect 0 0 34 200 +<< labels >> +rlabel metal1 0 8 0 8 2 clk +rlabel metal3 15 4 15 4 1 din +rlabel metal2 6 196 6 196 5 dout_bar +rlabel metal2 15 196 15 196 5 dout +rlabel m2contact 34 70 34 70 1 gnd +rlabel m2contact 34 154 34 154 1 gnd +rlabel m2contact 0 162 0 162 3 vdd +rlabel m2contact 0 38 0 38 3 vdd +<< end >> diff --git a/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag b/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag new file mode 100644 index 00000000..a7387b7e --- /dev/null +++ b/technology/scn3me_subm/mag_lib/replica_cell_1rw_1r.mag @@ -0,0 +1,157 @@ +magic +tech scmos +timestamp 1558933826 +<< nwell >> +rect 0 48 54 77 +<< pwell >> +rect 0 0 54 48 +<< ntransistor >> +rect 14 34 16 38 +rect 22 30 24 38 +rect 30 30 32 38 +rect 38 34 40 38 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 56 24 59 +rect 30 56 32 59 +<< ndiffusion >> +rect 13 34 14 38 +rect 16 34 17 38 +rect 21 34 22 38 +rect 17 30 22 34 +rect 24 36 30 38 +rect 24 32 25 36 +rect 29 32 30 36 +rect 24 30 30 32 +rect 32 34 33 38 +rect 37 34 38 38 +rect 40 34 41 38 +rect 32 30 37 34 +rect 9 21 14 23 +rect 13 17 14 21 +rect 16 17 22 23 +rect 24 22 30 23 +rect 24 18 25 22 +rect 29 18 30 22 +rect 24 17 30 18 +rect 32 17 38 23 +rect 40 21 45 23 +rect 40 17 41 21 +<< pdiffusion >> +rect 21 56 22 59 +rect 24 56 25 59 +rect 29 56 30 59 +rect 32 56 33 59 +<< ndcontact >> +rect 9 34 13 38 +rect 17 34 21 38 +rect 25 32 29 36 +rect 33 34 37 38 +rect 41 34 45 38 +rect 9 17 13 21 +rect 25 18 29 22 +rect 41 17 45 21 +<< pdcontact >> +rect 17 56 21 60 +rect 25 56 29 60 +rect 33 56 37 60 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 37 70 41 74 +<< polysilicon >> +rect 22 59 24 62 +rect 30 59 32 62 +rect 22 45 24 56 +rect 30 53 32 56 +rect 13 41 16 43 +rect 14 38 16 41 +rect 22 38 24 41 +rect 30 38 32 49 +rect 38 41 41 43 +rect 38 38 40 41 +rect 14 32 16 34 +rect 38 32 40 34 +rect 14 23 16 24 +rect 22 23 24 30 +rect 30 23 32 30 +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 28 49 32 53 +rect 9 41 13 45 +rect 22 41 26 45 +rect 41 41 45 45 +rect 12 24 16 28 +rect 38 24 42 28 +<< metal1 >> +rect 0 70 25 74 +rect 29 70 37 74 +rect 41 70 54 74 +rect 0 63 54 67 +rect 9 45 13 63 +rect 16 56 17 60 +rect 29 56 33 60 +rect 37 56 38 60 +rect 16 53 20 56 +rect 16 49 28 53 +rect 16 38 19 49 +rect 35 45 38 56 +rect 26 41 38 45 +rect 41 45 45 63 +rect 35 38 38 41 +rect 6 34 9 38 +rect 16 34 17 38 +rect 25 36 29 38 +rect 37 34 38 38 +rect 45 34 48 38 +rect 25 22 29 32 +rect 25 13 29 18 +rect 0 9 25 13 +rect 29 9 54 13 +rect 0 2 16 6 +rect 20 2 34 6 +rect 38 2 54 6 +<< m2contact >> +rect 25 70 29 74 +rect 25 56 29 60 +rect 2 34 6 38 +rect 48 34 52 38 +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 38 6 74 +rect 2 0 6 34 +rect 9 21 13 74 +rect 25 60 29 70 +rect 9 0 13 17 +rect 16 6 20 24 +rect 34 6 38 24 +rect 41 21 45 74 +rect 41 0 45 17 +rect 48 38 52 74 +rect 48 0 52 34 +<< comment >> +rect 0 0 54 72 +<< labels >> +rlabel metal1 27 4 27 4 4 wl1 +rlabel psubstratepcontact 27 11 27 11 4 gnd +rlabel metal2 4 7 4 7 4 bl0 +rlabel metal2 50 7 50 7 4 br0 +rlabel metal1 19 65 19 65 4 wl0 +rlabel metal2 11 7 11 7 4 bl1 +rlabel metal2 43 7 43 7 4 br1 +rlabel metal1 18 72 18 72 1 vdd +<< properties >> +string path 0.000 0.000 243.000 0.000 243.000 324.000 0.000 324.000 0.000 0.000 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag b/technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag new file mode 100644 index 00000000..a7387b7e --- /dev/null +++ b/technology/scn3me_subm/mag_lib/replica_cell_1w_1r.mag @@ -0,0 +1,157 @@ +magic +tech scmos +timestamp 1558933826 +<< nwell >> +rect 0 48 54 77 +<< pwell >> +rect 0 0 54 48 +<< ntransistor >> +rect 14 34 16 38 +rect 22 30 24 38 +rect 30 30 32 38 +rect 38 34 40 38 +rect 14 17 16 23 +rect 22 17 24 23 +rect 30 17 32 23 +rect 38 17 40 23 +<< ptransistor >> +rect 22 56 24 59 +rect 30 56 32 59 +<< ndiffusion >> +rect 13 34 14 38 +rect 16 34 17 38 +rect 21 34 22 38 +rect 17 30 22 34 +rect 24 36 30 38 +rect 24 32 25 36 +rect 29 32 30 36 +rect 24 30 30 32 +rect 32 34 33 38 +rect 37 34 38 38 +rect 40 34 41 38 +rect 32 30 37 34 +rect 9 21 14 23 +rect 13 17 14 21 +rect 16 17 22 23 +rect 24 22 30 23 +rect 24 18 25 22 +rect 29 18 30 22 +rect 24 17 30 18 +rect 32 17 38 23 +rect 40 21 45 23 +rect 40 17 41 21 +<< pdiffusion >> +rect 21 56 22 59 +rect 24 56 25 59 +rect 29 56 30 59 +rect 32 56 33 59 +<< ndcontact >> +rect 9 34 13 38 +rect 17 34 21 38 +rect 25 32 29 36 +rect 33 34 37 38 +rect 41 34 45 38 +rect 9 17 13 21 +rect 25 18 29 22 +rect 41 17 45 21 +<< pdcontact >> +rect 17 56 21 60 +rect 25 56 29 60 +rect 33 56 37 60 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 37 70 41 74 +<< polysilicon >> +rect 22 59 24 62 +rect 30 59 32 62 +rect 22 45 24 56 +rect 30 53 32 56 +rect 13 41 16 43 +rect 14 38 16 41 +rect 22 38 24 41 +rect 30 38 32 49 +rect 38 41 41 43 +rect 38 38 40 41 +rect 14 32 16 34 +rect 38 32 40 34 +rect 14 23 16 24 +rect 22 23 24 30 +rect 30 23 32 30 +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 28 49 32 53 +rect 9 41 13 45 +rect 22 41 26 45 +rect 41 41 45 45 +rect 12 24 16 28 +rect 38 24 42 28 +<< metal1 >> +rect 0 70 25 74 +rect 29 70 37 74 +rect 41 70 54 74 +rect 0 63 54 67 +rect 9 45 13 63 +rect 16 56 17 60 +rect 29 56 33 60 +rect 37 56 38 60 +rect 16 53 20 56 +rect 16 49 28 53 +rect 16 38 19 49 +rect 35 45 38 56 +rect 26 41 38 45 +rect 41 45 45 63 +rect 35 38 38 41 +rect 6 34 9 38 +rect 16 34 17 38 +rect 25 36 29 38 +rect 37 34 38 38 +rect 45 34 48 38 +rect 25 22 29 32 +rect 25 13 29 18 +rect 0 9 25 13 +rect 29 9 54 13 +rect 0 2 16 6 +rect 20 2 34 6 +rect 38 2 54 6 +<< m2contact >> +rect 25 70 29 74 +rect 25 56 29 60 +rect 2 34 6 38 +rect 48 34 52 38 +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 38 6 74 +rect 2 0 6 34 +rect 9 21 13 74 +rect 25 60 29 70 +rect 9 0 13 17 +rect 16 6 20 24 +rect 34 6 38 24 +rect 41 21 45 74 +rect 41 0 45 17 +rect 48 38 52 74 +rect 48 0 52 34 +<< comment >> +rect 0 0 54 72 +<< labels >> +rlabel metal1 27 4 27 4 4 wl1 +rlabel psubstratepcontact 27 11 27 11 4 gnd +rlabel metal2 4 7 4 7 4 bl0 +rlabel metal2 50 7 50 7 4 br0 +rlabel metal1 19 65 19 65 4 wl0 +rlabel metal2 11 7 11 7 4 bl1 +rlabel metal2 43 7 43 7 4 br1 +rlabel metal1 18 72 18 72 1 vdd +<< properties >> +string path 0.000 0.000 243.000 0.000 243.000 324.000 0.000 324.000 0.000 0.000 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/replica_cell_6t.mag b/technology/scn3me_subm/mag_lib/replica_cell_6t.mag new file mode 100644 index 00000000..d0dc472f --- /dev/null +++ b/technology/scn3me_subm/mag_lib/replica_cell_6t.mag @@ -0,0 +1,118 @@ +magic +tech scmos +timestamp 1536091380 +<< nwell >> +rect -8 29 42 51 +<< pwell >> +rect -8 -8 42 29 +<< ntransistor >> +rect 7 10 9 18 +rect 29 10 31 18 +rect 10 3 14 5 +rect 24 3 28 5 +<< ptransistor >> +rect 7 37 11 40 +rect 27 37 31 40 +<< ndiffusion >> +rect -2 16 7 18 +rect 2 12 7 16 +rect -2 10 7 12 +rect 9 14 10 18 +rect 9 10 14 14 +rect 28 14 29 18 +rect 24 10 29 14 +rect 31 16 36 18 +rect 31 12 32 16 +rect 31 10 36 12 +rect 10 5 14 10 +rect 24 5 28 10 +rect 10 2 14 3 +rect 24 2 28 3 +<< pdiffusion >> +rect 2 37 7 40 +rect 11 37 12 40 +rect 26 37 27 40 +rect 31 37 32 40 +<< ndcontact >> +rect -2 12 2 16 +rect 10 14 14 18 +rect 24 14 28 18 +rect 32 12 36 16 +rect 10 -2 14 2 +rect 24 -2 28 2 +<< pdcontact >> +rect -2 36 2 40 +rect 12 36 16 40 +rect 22 36 26 40 +rect 32 36 36 40 +<< psubstratepcontact >> +rect -2 22 2 26 +rect 32 22 36 26 +<< nsubstratencontact >> +rect 32 44 36 48 +<< polysilicon >> +rect 7 40 11 42 +rect 27 40 31 42 +rect 7 35 11 37 +rect 7 21 9 35 +rect 27 34 31 37 +rect 15 33 31 34 +rect 19 32 31 33 +rect 7 20 21 21 +rect 7 19 24 20 +rect 7 18 9 19 +rect 29 18 31 32 +rect 7 8 9 10 +rect 17 5 21 6 +rect 29 8 31 10 +rect -2 3 10 5 +rect 14 3 24 5 +rect 28 3 36 5 +<< polycontact >> +rect 15 29 19 33 +rect 21 20 25 24 +rect 17 6 21 10 +<< metal1 >> +rect -2 44 15 48 +rect 19 44 32 48 +rect -2 40 2 44 +rect 32 40 36 44 +rect 11 36 12 40 +rect 26 36 27 40 +rect -2 26 2 29 +rect 11 22 15 36 +rect 23 24 27 36 +rect -2 18 15 22 +rect 25 20 27 24 +rect -2 16 2 18 +rect 14 14 15 18 +rect 23 18 27 20 +rect 32 26 36 29 +rect 23 14 24 18 +rect 32 16 36 22 +rect -2 6 17 9 +rect 21 6 36 9 +rect -2 5 36 6 +<< m2contact >> +rect 15 44 19 48 +rect -2 29 2 33 +rect 32 29 36 33 +rect 6 -2 10 2 +rect 20 -2 24 2 +<< metal2 >> +rect -2 33 2 48 +rect -2 -2 2 29 +rect 6 2 10 48 +rect 24 -2 28 48 +rect 32 33 36 48 +rect 32 -2 36 29 +<< bb >> +rect 0 0 34 46 +<< labels >> +rlabel metal2 0 0 0 0 1 gnd +rlabel metal2 34 0 34 0 1 gnd +rlabel m2contact 17 46 17 46 5 vdd +rlabel metal2 8 43 8 43 1 bl +rlabel metal2 26 43 26 43 1 br +rlabel metal1 4 7 4 7 1 wl +<< end >> diff --git a/technology/scn3me_subm/mag_lib/sense_amp.mag b/technology/scn3me_subm/mag_lib/sense_amp.mag new file mode 100644 index 00000000..e5fa4373 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/sense_amp.mag @@ -0,0 +1,136 @@ +magic +tech scmos +timestamp 1536089670 +<< nwell >> +rect 0 0 40 102 +<< pwell >> +rect 0 102 40 163 +<< ntransistor >> +rect 21 130 23 139 +rect 12 108 14 117 +rect 20 108 22 117 +<< ptransistor >> +rect 12 78 14 96 +rect 20 78 22 96 +rect 11 20 13 44 +rect 27 20 29 44 +<< ndiffusion >> +rect 20 130 21 139 +rect 23 130 24 139 +rect 11 108 12 117 +rect 14 108 15 117 +rect 19 108 20 117 +rect 22 108 23 117 +<< pdiffusion >> +rect 7 94 12 96 +rect 11 80 12 94 +rect 7 78 12 80 +rect 14 94 20 96 +rect 14 80 15 94 +rect 19 80 20 94 +rect 14 78 20 80 +rect 22 94 27 96 +rect 22 80 23 94 +rect 22 78 27 80 +rect 10 20 11 44 +rect 13 20 14 44 +rect 26 20 27 44 +rect 29 20 30 44 +<< ndcontact >> +rect 16 130 20 139 +rect 24 130 28 139 +rect 7 108 11 117 +rect 15 108 19 117 +rect 23 108 27 117 +<< pdcontact >> +rect 7 80 11 94 +rect 15 80 19 94 +rect 23 80 27 94 +rect 6 20 10 44 +rect 14 20 18 44 +rect 22 20 26 44 +rect 30 20 34 44 +<< psubstratepcontact >> +rect 32 137 36 141 +<< nsubstratencontact >> +rect 27 70 31 74 +<< polysilicon >> +rect 21 139 23 149 +rect 21 129 23 130 +rect 3 127 23 129 +rect 3 47 5 127 +rect 12 122 34 124 +rect 12 117 14 122 +rect 20 117 22 119 +rect 12 96 14 108 +rect 20 96 22 108 +rect 32 105 34 122 +rect 30 101 34 105 +rect 12 76 14 78 +rect 20 69 22 78 +rect 13 67 22 69 +rect 9 55 11 65 +rect 32 55 34 101 +rect 33 51 34 55 +rect 3 45 13 47 +rect 11 44 13 45 +rect 27 44 29 46 +rect 11 19 13 20 +rect 27 19 29 20 +rect 11 17 29 19 +<< polycontact >> +rect 20 149 24 153 +rect 26 101 30 105 +rect 9 65 13 69 +rect 9 51 13 55 +rect 29 51 33 55 +<< metal1 >> +rect -2 149 20 153 +rect 24 149 36 153 +rect 28 133 32 137 +rect 16 117 19 130 +rect 7 94 11 108 +rect 23 105 27 108 +rect 23 101 26 105 +rect 7 69 11 80 +rect 15 94 19 96 +rect 15 78 19 80 +rect 23 94 27 101 +rect 23 78 27 80 +rect 15 75 18 78 +rect 15 74 31 75 +rect 15 72 27 74 +rect 7 65 9 69 +rect 6 44 9 54 +rect 33 51 34 55 +rect 31 44 34 51 +rect 3 20 6 23 +rect 3 15 7 20 +<< m2contact >> +rect 32 133 36 137 +rect 27 66 31 70 +rect 13 44 17 48 +rect 22 44 26 48 +rect 3 11 7 15 +<< metal2 >> +rect 10 48 14 163 +rect 20 48 24 163 +rect 32 129 36 133 +rect 27 62 31 66 +rect 10 44 13 48 +rect 20 44 22 48 +rect 3 0 7 11 +rect 10 0 14 44 +rect 20 0 24 44 +<< bb >> +rect 0 0 34 163 +<< labels >> +flabel metal1 0 149 0 149 4 FreeSans 26 0 0 0 en +rlabel metal2 34 131 34 131 1 gnd +rlabel metal2 29 64 29 64 1 vdd +rlabel metal2 12 161 12 161 5 bl +rlabel metal2 22 161 22 161 5 br +rlabel metal2 5 3 5 3 1 dout +<< properties >> +string path 270.000 468.000 270.000 486.000 288.000 486.000 288.000 468.000 270.000 468.000 +<< end >> diff --git a/technology/scn3me_subm/mag_lib/setup.tcl b/technology/scn3me_subm/mag_lib/setup.tcl new file mode 100644 index 00000000..01639fe2 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/setup.tcl @@ -0,0 +1,17 @@ +# Setup file for netgen +ignore class c +equate class {-circuit1 nfet} {-circuit2 n} +equate class {-circuit1 pfet} {-circuit2 p} +# This circuit has symmetries and needs to be flattened to resolve them +# or the banks won't pass +flatten class {-circuit1 bitcell_array_0} +flatten class {-circuit1 bitcell_array_1} +#flatten class {-circuit1 precharge_array_0} +#flatten class {-circuit1 precharge_array_1} +#flatten class {-circuit1 precharge_array_2} +#flatten class {-circuit1 precharge_array_3} +property {-circuit1 nfet} remove as ad ps pd +property {-circuit1 pfet} remove as ad ps pd +property {-circuit2 n} remove as ad ps pd +property {-circuit2 p} remove as ad ps pd +permute transistors diff --git a/technology/scn3me_subm/mag_lib/tri_gate.mag b/technology/scn3me_subm/mag_lib/tri_gate.mag new file mode 100644 index 00000000..bda635c7 --- /dev/null +++ b/technology/scn3me_subm/mag_lib/tri_gate.mag @@ -0,0 +1,98 @@ +magic +tech scmos +timestamp 1536089695 +<< nwell >> +rect -2 45 38 73 +<< pwell >> +rect -2 0 38 45 +<< ntransistor >> +rect 9 27 11 31 +rect 17 27 19 31 +rect 25 27 27 31 +<< ptransistor >> +rect 9 53 11 61 +rect 17 53 19 61 +rect 25 53 27 61 +<< ndiffusion >> +rect 8 27 9 31 +rect 11 27 12 31 +rect 16 27 17 31 +rect 19 27 20 31 +rect 24 27 25 31 +rect 27 27 28 31 +<< pdiffusion >> +rect 8 53 9 61 +rect 11 53 12 61 +rect 16 53 17 61 +rect 19 53 20 61 +rect 24 53 25 61 +rect 27 53 28 61 +<< ndcontact >> +rect 4 27 8 31 +rect 12 27 16 31 +rect 20 27 24 31 +rect 28 27 32 31 +<< pdcontact >> +rect 4 53 8 61 +rect 12 53 16 61 +rect 20 53 24 61 +rect 28 53 32 61 +<< psubstratepcontact >> +rect 12 19 16 23 +<< nsubstratencontact >> +rect 12 65 16 69 +<< polysilicon >> +rect 25 63 35 65 +rect 9 61 11 63 +rect 17 61 19 63 +rect 25 61 27 63 +rect 9 50 11 53 +rect 9 31 11 46 +rect 17 42 19 53 +rect 25 51 27 53 +rect 17 31 19 38 +rect 25 31 27 33 +rect 9 25 11 27 +rect 17 25 19 27 +rect 25 16 27 27 +rect 33 8 35 63 +rect 32 6 35 8 +<< polycontact >> +rect 9 46 13 50 +rect 16 38 20 42 +rect 25 12 29 16 +rect 28 4 32 8 +<< metal1 >> +rect 16 65 23 69 +rect 12 61 16 65 +rect 3 53 4 61 +rect 3 42 6 53 +rect 13 46 15 50 +rect 3 38 16 42 +rect 3 31 6 38 +rect 29 31 32 53 +rect 3 27 4 31 +rect 12 23 16 27 +rect 16 19 24 23 +rect 0 12 25 16 +rect 29 12 36 16 +rect 0 4 28 8 +rect 32 4 36 8 +<< m2contact >> +rect 23 65 27 69 +rect 15 46 19 50 +rect 25 34 29 38 +rect 24 19 28 23 +<< metal2 >> +rect 15 34 25 38 +rect 15 0 19 34 +<< bb >> +rect 0 0 34 73 +<< labels >> +rlabel metal1 0 12 0 12 3 en +rlabel metal1 0 4 0 4 2 en_bar +rlabel metal2 16 1 16 1 1 out +rlabel m2contact 26 21 26 21 1 gnd +rlabel m2contact 25 67 25 67 1 vdd +rlabel m2contact 17 48 17 48 1 in +<< end >> diff --git a/technology/scn3me_subm/mag_lib/write_driver.mag b/technology/scn3me_subm/mag_lib/write_driver.mag new file mode 100644 index 00000000..ab2014aa --- /dev/null +++ b/technology/scn3me_subm/mag_lib/write_driver.mag @@ -0,0 +1,224 @@ +magic +tech scmos +timestamp 1536089714 +<< nwell >> +rect -3 101 37 138 +rect -3 0 37 51 +<< pwell >> +rect -3 138 37 202 +rect -3 51 37 101 +<< ntransistor >> +rect 9 177 11 189 +rect 17 177 19 189 +rect 15 162 27 164 +rect 9 144 11 148 +rect 17 144 19 148 +rect 10 82 12 89 +rect 18 82 20 89 +rect 8 57 10 64 +rect 16 57 18 64 +rect 24 60 26 64 +<< ptransistor >> +rect 9 125 11 132 +rect 17 125 19 132 +rect 10 107 12 114 +rect 18 107 20 114 +rect 8 38 10 45 +rect 16 38 18 45 +rect 24 38 26 45 +<< ndiffusion >> +rect 8 177 9 189 +rect 11 177 12 189 +rect 16 177 17 189 +rect 19 177 20 189 +rect 15 164 27 165 +rect 15 161 27 162 +rect 12 157 15 160 +rect 12 156 16 157 +rect 8 144 9 148 +rect 11 144 12 148 +rect 16 144 17 148 +rect 19 144 20 148 +rect 9 82 10 89 +rect 12 82 13 89 +rect 17 82 18 89 +rect 20 82 21 89 +rect 25 82 26 86 +rect 7 57 8 64 +rect 10 57 11 64 +rect 15 57 16 64 +rect 18 57 19 64 +rect 23 60 24 64 +rect 26 60 27 64 +<< pdiffusion >> +rect 8 125 9 132 +rect 11 125 12 132 +rect 16 125 17 132 +rect 19 125 20 132 +rect 12 122 16 125 +rect 9 107 10 114 +rect 12 107 13 114 +rect 17 107 18 114 +rect 20 107 21 114 +rect 7 38 8 45 +rect 10 38 11 45 +rect 15 38 16 45 +rect 18 38 19 45 +rect 23 38 24 45 +rect 26 38 27 45 +rect 3 35 7 38 +<< ndcontact >> +rect 4 177 8 189 +rect 12 177 16 189 +rect 20 177 24 189 +rect 15 165 27 169 +rect 15 157 27 161 +rect 4 144 8 148 +rect 12 144 16 148 +rect 20 144 24 148 +rect 5 82 9 89 +rect 13 82 17 89 +rect 21 82 25 89 +rect 3 57 7 64 +rect 11 57 15 64 +rect 19 57 23 64 +rect 27 60 31 64 +<< pdcontact >> +rect 4 125 8 132 +rect 12 125 16 132 +rect 20 125 24 132 +rect 5 107 9 114 +rect 13 107 17 114 +rect 21 107 25 114 +rect 3 38 7 45 +rect 11 38 15 45 +rect 19 38 23 45 +rect 27 38 31 45 +<< psubstratepcontact >> +rect 12 152 16 156 +rect 26 82 30 86 +<< nsubstratencontact >> +rect 12 118 16 122 +rect 3 31 7 35 +<< polysilicon >> +rect 9 194 30 196 +rect 9 189 11 194 +rect 17 189 19 191 +rect 28 185 30 194 +rect 9 175 11 177 +rect 17 172 19 177 +rect 6 170 19 172 +rect 6 167 8 170 +rect 13 162 15 164 +rect 27 162 33 164 +rect 9 148 11 150 +rect 17 148 19 150 +rect 9 132 11 144 +rect 17 132 19 144 +rect 9 124 11 125 +rect 2 122 11 124 +rect 17 124 19 125 +rect 17 122 28 124 +rect 2 75 4 122 +rect 10 114 12 116 +rect 18 114 20 116 +rect 10 89 12 107 +rect 18 106 20 107 +rect 16 104 20 106 +rect 16 92 18 104 +rect 26 100 28 122 +rect 27 96 28 100 +rect 16 90 20 92 +rect 18 89 20 90 +rect 10 81 12 82 +rect 10 79 13 81 +rect 2 71 3 75 +rect 11 71 13 79 +rect 18 79 20 82 +rect 18 77 23 79 +rect 31 71 33 162 +rect 11 69 33 71 +rect 11 67 13 69 +rect 8 65 13 67 +rect 8 64 10 65 +rect 16 64 18 66 +rect 24 64 26 66 +rect 8 45 10 57 +rect 16 52 18 57 +rect 24 52 26 60 +rect 16 50 26 52 +rect 16 45 18 50 +rect 24 45 26 50 +rect 8 28 10 38 +rect 16 14 18 38 +rect 24 36 26 38 +<< polycontact >> +rect 28 181 32 185 +rect 4 163 8 167 +rect 23 96 27 100 +rect 3 71 7 75 +rect 23 75 27 79 +rect 7 24 11 28 +rect 15 10 19 14 +<< metal1 >> +rect 5 192 10 196 +rect 5 189 8 192 +rect 32 181 33 185 +rect 13 169 16 177 +rect 13 165 15 169 +rect 4 148 8 163 +rect 12 157 15 161 +rect 12 156 16 157 +rect 12 148 16 152 +rect 4 132 8 144 +rect 20 142 24 144 +rect 30 142 33 181 +rect 20 138 33 142 +rect 20 132 24 138 +rect 12 122 16 125 +rect 13 114 17 118 +rect 5 104 9 107 +rect 21 104 25 107 +rect 5 101 25 104 +rect 5 89 9 101 +rect 21 100 25 101 +rect 21 96 23 100 +rect 25 82 26 90 +rect 4 64 7 71 +rect 27 64 31 79 +rect 3 51 7 57 +rect 3 48 15 51 +rect 11 45 15 48 +rect 27 45 31 60 +rect 3 35 7 38 +rect 19 35 23 38 +rect 7 31 19 35 +rect 0 24 7 28 +rect 11 24 36 28 +<< m2contact >> +rect 10 192 14 196 +rect 20 189 24 193 +rect 23 153 27 157 +rect 16 118 20 122 +rect 26 86 30 90 +rect 19 64 23 68 +rect 19 31 23 35 +rect 15 6 19 10 +<< metal2 >> +rect 10 196 14 202 +rect 20 193 24 202 +rect 20 177 24 189 +rect 15 0 19 6 +<< bb >> +rect 0 0 34 202 +<< labels >> +rlabel metal2 15 1 15 1 1 din +rlabel metal1 2 25 2 25 3 en +rlabel metal2 12 200 12 200 5 bl +rlabel metal2 22 200 22 200 5 br +rlabel m2contact 21 66 21 66 1 gnd +rlabel m2contact 28 88 28 88 1 gnd +rlabel m2contact 21 33 21 33 1 vdd +rlabel m2contact 18 120 18 120 1 vdd +rlabel m2contact 25 155 25 155 1 gnd +<< end >> diff --git a/technology/scn3me_subm/models/ff/nmos.sp b/technology/scn3me_subm/models/ff/nmos.sp new file mode 100644 index 00000000..9711c533 --- /dev/null +++ b/technology/scn3me_subm/models/ff/nmos.sp @@ -0,0 +1,10 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL n NMOS (LEVEL=49 VTHO=0.669845 ++ NSUB=6E16 U0=461 K1=0.5705 TOX=13.9n VERSION=3.3.0) + diff --git a/technology/scn3me_subm/models/ff/pmos.sp b/technology/scn3me_subm/models/ff/pmos.sp new file mode 100644 index 00000000..e08967e4 --- /dev/null +++ b/technology/scn3me_subm/models/ff/pmos.sp @@ -0,0 +1,9 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 ++ NSUB=6E16 U0=212 K1=0.0821 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/nom/nmos.sp b/technology/scn3me_subm/models/nom/nmos.sp new file mode 100644 index 00000000..59f88cfd --- /dev/null +++ b/technology/scn3me_subm/models/nom/nmos.sp @@ -0,0 +1,9 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL n NMOS (LEVEL=49 VTHO=0.669845 ++ NSUB=6E16 U0=458 K1=0.5705 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/nom/pmos.sp b/technology/scn3me_subm/models/nom/pmos.sp new file mode 100644 index 00000000..69f3aacd --- /dev/null +++ b/technology/scn3me_subm/models/nom/pmos.sp @@ -0,0 +1,9 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 ++ NSUB=6E16 U0=212 K1=0.0821 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/models/ss/nmos.sp b/technology/scn3me_subm/models/ss/nmos.sp new file mode 100644 index 00000000..4e8a531f --- /dev/null +++ b/technology/scn3me_subm/models/ss/nmos.sp @@ -0,0 +1,10 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL n NMOS (LEVEL=49 VTHO=0.669845 ++ NSUB=6E16 U0=460 K1=0.5705 TOX=13.9n VERSION=3.3.0) + diff --git a/technology/scn3me_subm/models/ss/pmos.sp b/technology/scn3me_subm/models/ss/pmos.sp new file mode 100644 index 00000000..e08967e4 --- /dev/null +++ b/technology/scn3me_subm/models/ss/pmos.sp @@ -0,0 +1,9 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL p PMOS (LEVEL=49 VTHO=-0.322431 ++ NSUB=6E16 U0=212 K1=0.0821 TOX=13.9n VERSION=3.3.0) diff --git a/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp b/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp new file mode 100644 index 00000000..f58867a7 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/cell_1rw_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left Q_bar gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 Q_bar wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q Q_bar gnd gnd n w=2.4u l=0.6u +MM0 Q_bar Q gnd gnd n w=2.4u l=0.6u +MM3 Q Q_bar vdd vdd p w=0.9u l=0.6u +MM2 Q_bar Q vdd vdd p w=0.9u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/cell_1w_1r.sp b/technology/scn3me_subm/sp_lib/cell_1w_1r.sp new file mode 100644 index 00000000..fe981d6d --- /dev/null +++ b/technology/scn3me_subm/sp_lib/cell_1w_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left Q_bar gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 Q_bar wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q Q_bar gnd gnd n w=2.4u l=0.6u +MM0 Q_bar Q gnd gnd n w=2.4u l=0.6u +MM3 Q Q_bar vdd vdd p w=0.9u l=0.6u +MM2 Q_bar Q vdd vdd p w=0.9u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/cell_6t.sp b/technology/scn3me_subm/sp_lib/cell_6t.sp new file mode 100644 index 00000000..76c40f31 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/cell_6t.sp @@ -0,0 +1,10 @@ + +*********************** "cell_6t" ****************************** +.SUBCKT cell_6t bl br wl vdd gnd +M_1 Q Qb vdd vdd p W='0.9u' L=1.2u +M_2 Qb Q vdd vdd p W='0.9u' L=1.2u +M_3 br wl Qb gnd n W='1.2u' L=0.6u +M_4 bl wl Q gnd n W='1.2u' L=0.6u +M_5 Qb Q gnd gnd n W='2.4u' L=0.6u +M_6 Q Qb gnd gnd n W='2.4u' L=0.6u +.ENDS $ cell_6t diff --git a/technology/scn3me_subm/sp_lib/dff.sp b/technology/scn3me_subm/sp_lib/dff.sp new file mode 100644 index 00000000..d3fa7635 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/dff.sp @@ -0,0 +1,27 @@ +*********************** "dff" ****************************** +* Positive edge-triggered FF +.SUBCKT dff D Q clk vdd gnd +M0 vdd clk a_2_6# vdd p w=12u l=0.6u +M1 a_17_74# D vdd vdd p w=6u l=0.6u +M2 a_22_6# clk a_17_74# vdd p w=6u l=0.6u +M3 a_31_74# a_2_6# a_22_6# vdd p w=6u l=0.6u +M4 vdd a_34_4# a_31_74# vdd p w=6u l=0.6u +M5 a_34_4# a_22_6# vdd vdd p w=6u l=0.6u +M6 a_61_74# a_34_4# vdd vdd p w=6u l=0.6u +M7 a_66_6# a_2_6# a_61_74# vdd p w=6u l=0.6u +M8 a_76_84# clk a_66_6# vdd p w=3u l=0.6u +M9 vdd Q a_76_84# vdd p w=3u l=0.6u +M10 gnd clk a_2_6# gnd n w=6u l=0.6u +M11 Q a_66_6# vdd vdd p w=12u l=0.6u +M12 a_17_6# D gnd gnd n w=3u l=0.6u +M13 a_22_6# a_2_6# a_17_6# gnd n w=3u l=0.6u +M14 a_31_6# clk a_22_6# gnd n w=3u l=0.6u +M15 gnd a_34_4# a_31_6# gnd n w=3u l=0.6u +M16 a_34_4# a_22_6# gnd gnd n w=3u l=0.6u +M17 a_61_6# a_34_4# gnd gnd n w=3u l=0.6u +M18 a_66_6# clk a_61_6# gnd n w=3u l=0.6u +M19 a_76_6# a_2_6# a_66_6# gnd n w=3u l=0.6u +M20 gnd Q a_76_6# gnd n w=3u l=0.6u +M21 Q a_66_6# gnd gnd n w=6u l=0.6u + +.ENDS dff diff --git a/technology/scn3me_subm/sp_lib/incorrect/cell_1rw_1r.sp b/technology/scn3me_subm/sp_lib/incorrect/cell_1rw_1r.sp new file mode 100644 index 00000000..1c4c1bc3 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/incorrect/cell_1rw_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left Q_bar gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 Q_bar wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q Q_bar gnd gnd n w=2.4u l=0.6u +MM0 Q_bar Q gnd gnd n w=2.4u l=0.6u +MM3 Q Q_bar vdd vdd p w=1.2u l=0.6u +MM2 Q_bar Q vdd vdd p w=1.2u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/incorrect/cell_1w_1r.sp b/technology/scn3me_subm/sp_lib/incorrect/cell_1w_1r.sp new file mode 100644 index 00000000..aed7466b --- /dev/null +++ b/technology/scn3me_subm/sp_lib/incorrect/cell_1w_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left Q_bar gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 Q_bar wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q Q_bar gnd gnd n w=2.4u l=0.6u +MM0 Q_bar Q gnd gnd n w=2.4u l=0.6u +MM3 Q Q_bar vdd vdd p w=1.2u l=0.6u +MM2 Q_bar Q vdd vdd p w=1.2u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/incorrect/replica_cell_1rw_1r.sp b/technology/scn3me_subm/sp_lib/incorrect/replica_cell_1rw_1r.sp new file mode 100644 index 00000000..e90dd033 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/incorrect/replica_cell_1rw_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT replica_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left vdd gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 vdd wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q vdd gnd gnd n w=2.4u l=0.6u +MM0 vdd Q gnd gnd n w=2.4u l=0.6u +MM3 Q vdd vdd vdd p w=1.2u l=0.6u +MM2 vdd Q vdd vdd p w=1.2u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/incorrect/replica_cell_1w_1r.sp b/technology/scn3me_subm/sp_lib/incorrect/replica_cell_1w_1r.sp new file mode 100644 index 00000000..bd2e5eb5 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/incorrect/replica_cell_1w_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT replica_cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left vdd gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 vdd wl0 br0 gnd n w=0.8u l=0.6u +MM1 Q vdd gnd gnd n w=2.4u l=0.6u +MM0 vdd Q gnd gnd n w=2.4u l=0.6u +MM3 Q vdd vdd vdd p w=0.6u l=0.6u +MM2 vdd Q vdd vdd p w=0.6u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/ms_flop.sp b/technology/scn3me_subm/sp_lib/ms_flop.sp new file mode 100644 index 00000000..abf664e7 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/ms_flop.sp @@ -0,0 +1,29 @@ +*master-slave flip-flop with both output and inverted ouput + +.subckt dlatch din dout dout_bar clk clk_bar vdd gnd +*clk inverter +mPff1 clk_bar clk vdd vdd p W=1.8u L=0.6u m=1 +mNff1 clk_bar clk gnd gnd n W=0.9u L=0.6u m=1 + +*transmission gate 1 +mtmP1 din clk int1 vdd p W=1.8u L=0.6u m=1 +mtmN1 din clk_bar int1 gnd n W=0.9u L=0.6u m=1 + +*foward inverter +mPff3 dout_bar int1 vdd vdd p W=1.8u L=0.6u m=1 +mNff3 dout_bar int1 gnd gnd n W=0.9u L=0.6u m=1 + +*backward inverter +mPff4 dout dout_bar vdd vdd p W=1.8u L=0.6u m=1 +mNf4 dout dout_bar gnd gnd n W=0.9u L=0.6u m=1 + +*transmission gate 2 +mtmP2 int1 clk_bar dout vdd p W=1.8u L=0.6u m=1 +mtmN2 int1 clk dout gnd n W=0.9u L=0.6u m=1 +.ends dlatch + +.subckt ms_flop din dout dout_bar clk vdd gnd +xmaster din mout mout_bar clk clk_bar vdd gnd dlatch +xslave mout_bar dout_bar dout clk_bar clk_nn vdd gnd dlatch +.ends flop + diff --git a/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp b/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp new file mode 100644 index 00000000..a8654c83 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/replica_cell_1rw_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT replica_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left vdd gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 vdd wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q vdd gnd gnd n w=2.4u l=0.6u +MM0 vdd Q gnd gnd n w=2.4u l=0.6u +MM3 Q vdd vdd vdd p w=0.9u l=0.6u +MM2 vdd Q vdd vdd p w=0.9u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp b/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp new file mode 100644 index 00000000..5b9c9b18 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/replica_cell_1w_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT replica_cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.8u l=0.6u +MM8 RA_to_R_right Q gnd gnd n w=1.8u l=0.6u +MM7 RA_to_R_left vdd gnd gnd n w=1.8u l=0.6u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.8u l=0.6u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.6u +MM4 vdd wl0 br0 gnd n w=1.2u l=0.6u +MM1 Q vdd gnd gnd n w=2.4u l=0.6u +MM0 vdd Q gnd gnd n w=2.4u l=0.6u +MM3 Q vdd vdd vdd p w=0.9u l=0.6u +MM2 vdd Q vdd vdd p w=0.9u l=0.6u +.ENDS + diff --git a/technology/scn3me_subm/sp_lib/replica_cell_6t.sp b/technology/scn3me_subm/sp_lib/replica_cell_6t.sp new file mode 100644 index 00000000..1fa75a55 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/replica_cell_6t.sp @@ -0,0 +1,10 @@ + +*********************** "cell_6t" ****************************** +.SUBCKT replica_cell_6t bl br wl vdd gnd +M_1 gnd net_2 vdd vdd p W='0.9u' L=1.2u +M_2 net_2 gnd vdd vdd p W='0.9u' L=1.2u +M_3 br wl net_2 gnd n W='1.2u' L=0.6u +M_4 bl wl gnd gnd n W='1.2u' L=0.6u +M_5 net_2 gnd gnd gnd n W='2.4u' L=0.6u +M_6 gnd net_2 gnd gnd n W='2.4u' L=0.6u +.ENDS $ replica_cell_6t diff --git a/technology/scn3me_subm/sp_lib/sense_amp.sp b/technology/scn3me_subm/sp_lib/sense_amp.sp new file mode 100644 index 00000000..1399228d --- /dev/null +++ b/technology/scn3me_subm/sp_lib/sense_amp.sp @@ -0,0 +1,12 @@ +*********************** "sense_amp" ****************************** + +.SUBCKT sense_amp bl br dout en vdd gnd +M_1 dout net_1 vdd vdd p W='5.4*1u' L=0.6u +M_2 dout net_1 net_2 gnd n W='2.7*1u' L=0.6u +M_3 net_1 dout vdd vdd p W='5.4*1u' L=0.6u +M_4 net_1 dout net_2 gnd n W='2.7*1u' L=0.6u +M_5 bl en dout vdd p W='7.2*1u' L=0.6u +M_6 br en net_1 vdd p W='7.2*1u' L=0.6u +M_7 net_2 en gnd gnd n W='2.7*1u' L=0.6u +.ENDS sense_amp + diff --git a/technology/scn3me_subm/sp_lib/tri_gate.sp b/technology/scn3me_subm/sp_lib/tri_gate.sp new file mode 100644 index 00000000..0d298172 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/tri_gate.sp @@ -0,0 +1,13 @@ +*********************** tri_gate ****************************** + +.SUBCKT tri_gate in out en en_bar vdd gnd + +M_1 net_2 in_inv gnd gnd n W='1.2*1u' L=0.6u +M_2 net_3 in_inv vdd vdd p W='2.4*1u' L=0.6u +M_3 out en_bar net_3 vdd p W='2.4*1u' L=0.6u +M_4 out en net_2 gnd n W='1.2*1u' L=0.6u +M_5 in_inv in vdd vdd p W='2.4*1u' L=0.6u +M_6 in_inv in gnd gnd n W='1.2*1u' L=0.6u + + +.ENDS diff --git a/technology/scn3me_subm/sp_lib/write_driver.sp b/technology/scn3me_subm/sp_lib/write_driver.sp new file mode 100644 index 00000000..88f80361 --- /dev/null +++ b/technology/scn3me_subm/sp_lib/write_driver.sp @@ -0,0 +1,38 @@ +*********************** Write_Driver ****************************** +.SUBCKT write_driver din bl br en vdd gnd + +**** Inverter to conver Data_in to data_in_bar ****** +* din_bar = inv(din) +M_1 din_bar din gnd gnd n W=1.2u L=0.6u +M_2 din_bar din vdd vdd p W=2.1u L=0.6u + +**** 2input nand gate follwed by inverter to drive BL ****** +* din_bar_gated = nand(en, din) +M_3 din_bar_gated en net_7 gnd n W=2.1u L=0.6u +M_4 net_7 din gnd gnd n W=2.1u L=0.6u +M_5 din_bar_gated en vdd vdd p W=2.1u L=0.6u +M_6 din_bar_gated din vdd vdd p W=2.1u L=0.6u +* din_bar_gated_bar = inv(din_bar_gated) +M_7 din_bar_gated_bar din_bar_gated vdd vdd p W=2.1u L=0.6u +M_8 din_bar_gated_bar din_bar_gated gnd gnd n W=1.2u L=0.6u + +**** 2input nand gate follwed by inverter to drive BR****** +* din_gated = nand(en, din_bar) +M_9 din_gated en vdd vdd p W=2.1u L=0.6u +M_10 din_gated en net_8 gnd n W=2.1u L=0.6u +M_11 net_8 din_bar gnd gnd n W=2.1u L=0.6u +M_12 din_gated din_bar vdd vdd p W=2.1u L=0.6u +* din_gated_bar = inv(din_gated) +M_13 din_gated_bar din_gated vdd vdd p W=2.1u L=0.6u +M_14 din_gated_bar din_gated gnd gnd n W=1.2u L=0.6u + +************************************************ +* pull down with en enable +M_15 bl din_gated_bar net_5 gnd n W=3.6u L=0.6u +M_16 br din_bar_gated_bar net_5 gnd n W=3.6u L=0.6u +M_17 net_5 en gnd gnd n W=3.6u L=0.6u + + + +.ENDS $ write_driver + diff --git a/technology/scn3me_subm/sue_lib/cell_6t.sue b/technology/scn3me_subm/sue_lib/cell_6t.sue new file mode 100644 index 00000000..427b1d05 --- /dev/null +++ b/technology/scn3me_subm/sue_lib/cell_6t.sue @@ -0,0 +1,46 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_cell_6t {} { + make inout -name BL -origin {190 360} + make inout -name BR -origin {830 360} + make input -name WL -origin {240 120} + make global -orient RXY -name vdd -origin {520 160} + make global -name gnd -origin {510 600} + make pmos -orient RY -W 0.9u -L 1.2u -origin {630 230} + make pmos -orient RXY -W 0.9u -L 1.2u -origin {400 230} + make nmos -orient R90 -W 1.2 -L 0.6u -origin {740 360} + make nmos -orient R90X -W 1.2 -L 0.6u -origin {270 360} + make nmos -W 2.4u -L 0.6u -origin {630 490} + make nmos -orient RX -W 2.4u -L 0.6u -origin {400 490} + make_wire 630 550 630 530 + make_wire 400 530 400 550 + make_wire 400 190 400 170 + make_wire 630 170 630 190 + make_wire 400 360 400 270 + make_wire 310 360 400 360 + make_wire 630 360 630 450 + make_wire 630 360 700 360 + make_wire 270 300 270 120 + make_wire 270 120 740 120 + make_wire 740 120 740 300 + make_wire 230 360 190 360 + make_wire 780 360 830 360 + make_wire 510 550 400 550 + make_wire 510 550 630 550 + make_wire 510 550 510 600 + make_wire 520 170 400 170 + make_wire 520 170 630 170 + make_wire 520 160 520 170 + make_wire 240 120 270 120 + make_wire 460 290 630 290 + make_wire 460 290 460 490 + make_wire 460 290 460 230 + make_wire 630 290 630 360 + make_wire 630 290 630 270 + make_wire 570 420 400 420 + make_wire 570 420 570 490 + make_wire 570 420 570 230 + make_wire 400 420 400 360 + make_wire 400 420 400 450 +} + diff --git a/technology/scn3me_subm/sue_lib/ms_flop.sue b/technology/scn3me_subm/sue_lib/ms_flop.sue new file mode 100644 index 00000000..85cc8e03 --- /dev/null +++ b/technology/scn3me_subm/sue_lib/ms_flop.sue @@ -0,0 +1,84 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_ms_flop {} { + make pmos -orient R90X -W 1.8u -L 0.6u -origin {40 250} + make nmos -orient R270 -W 0.9u -L 0.6u -origin {40 380} + make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {-270 540} + make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {310 310} + make inverter -orient RX -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {430 730} + make pmos -orient R90X -W 1.8u -L 0.6u -origin {190 670} + make nmos -orient R270 -W 0.9u -L 0.6u -origin {190 780} + make input -name clk -origin {-380 540} + make input -name din -origin {-370 320} + make pmos -orient R90X -W 1.8u -L 0.6u -origin {720 250} + make nmos -orient R270 -W 0.9u -L 0.6u -origin {720 380} + make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {990 310} + make pmos -orient R90X -W 1.8u -L 0.6u -origin {870 670} + make nmos -orient R270 -W 0.9u -L 0.6u -origin {870 780} + make inverter -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {620 540} + make output -name dout -origin {1410 310} + make output -name dout_bar -origin {1430 930} + make inverter -orient RX -WP 1.8u -LP 0.6u -WN 0.9u -LN 0.6u -origin {1110 730} + make_wire -330 160 40 160 + make_wire 40 160 40 190 + make_wire -370 320 0 320 + make_wire 360 310 480 310 + make_wire 460 730 480 730 + make_wire 230 730 380 730 + make_wire 100 310 100 720 + make_wire 100 720 150 720 + make_wire 100 310 80 310 + make_wire 100 310 280 310 + make_wire 0 250 0 320 + make_wire 0 320 0 380 + make_wire 80 250 80 310 + make_wire 80 310 80 380 + make_wire 40 440 40 540 + make_wire -330 840 190 840 + make_wire 230 670 230 730 + make_wire 230 730 230 780 + make_wire 150 670 150 720 + make_wire 150 720 150 780 + make_wire 190 540 190 610 + make_wire -330 540 -330 840 + make_wire -220 540 40 540 + make_wire 40 540 190 540 + make_wire -380 540 -330 540 + make_wire -330 540 -300 540 + make_wire -330 540 -330 160 + make_wire 720 160 720 190 + make_wire 1140 730 1160 730 + make_wire 780 310 780 720 + make_wire 780 720 830 720 + make_wire 780 310 760 310 + make_wire 780 310 960 310 + make_wire 680 320 680 380 + make_wire 760 250 760 310 + make_wire 760 310 760 380 + make_wire 720 440 720 540 + make_wire 910 670 910 730 + make_wire 910 730 910 780 + make_wire 830 670 830 720 + make_wire 830 720 830 780 + make_wire 870 540 870 610 + make_wire 720 540 870 540 + make_wire 670 540 720 540 + make_wire 480 310 480 730 + make_wire 1160 310 1160 730 + make_wire 530 540 530 160 + make_wire 530 160 720 160 + make_wire 530 540 190 540 + make_wire 530 540 590 540 + make_wire 530 540 530 840 + make_wire 530 840 870 840 + make_wire 680 310 480 310 + make_wire 680 310 680 250 + make_wire 680 310 680 320 + make_wire 950 730 910 730 + make_wire 950 730 1060 730 + make_wire 1040 310 1160 310 + make_wire 1160 310 1410 310 + make_wire 950 930 1430 930 + make_wire 950 730 950 930 +} + diff --git a/technology/scn3me_subm/sue_lib/replica_cell_6t.sue b/technology/scn3me_subm/sue_lib/replica_cell_6t.sue new file mode 100644 index 00000000..56e72056 --- /dev/null +++ b/technology/scn3me_subm/sue_lib/replica_cell_6t.sue @@ -0,0 +1,49 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_replica_cell_6t {} { + make inout -name BL -origin {190 360} + make inout -name BR -origin {830 360} + make input -name WL -origin {240 120} + make global -orient RXY -name vdd -origin {520 160} + make global -name gnd -origin {510 600} + make pmos -orient RY -W 0.9u -L 1.2u -origin {630 230} + make pmos -orient RXY -W 0.9u -L 1.2u -origin {400 230} + make nmos -orient R90 -W 1.2 -L 0.6u -origin {740 360} + make nmos -orient R90X -W 1.2 -L 0.6u -origin {270 360} + make nmos -W 2.4u -L 0.6u -origin {630 490} + make nmos -orient RX -W 2.4u -L 0.6u -origin {400 490} + make_wire 630 550 630 530 + make_wire 400 530 400 550 + make_wire 400 190 400 170 + make_wire 630 170 630 190 + make_wire 400 360 400 270 + make_wire 630 360 630 450 + make_wire 630 360 700 360 + make_wire 270 300 270 120 + make_wire 270 120 740 120 + make_wire 740 120 740 300 + make_wire 230 360 190 360 + make_wire 780 360 830 360 + make_wire 510 550 400 550 + make_wire 510 550 630 550 + make_wire 510 550 510 600 + make_wire 520 170 400 170 + make_wire 520 170 630 170 + make_wire 520 160 520 170 + make_wire 240 120 270 120 + make_wire 460 290 630 290 + make_wire 460 290 460 490 + make_wire 460 290 460 230 + make_wire 630 290 630 360 + make_wire 630 290 630 270 + make_wire 570 420 400 420 + make_wire 570 420 570 490 + make_wire 570 420 570 230 + make_wire 400 420 400 360 + make_wire 400 420 400 450 + make_wire 320 360 320 550 + make_wire 320 550 400 550 + make_wire 320 360 310 360 + make_wire 320 360 400 360 +} + diff --git a/technology/scn3me_subm/sue_lib/sense_amp.sue b/technology/scn3me_subm/sue_lib/sense_amp.sue new file mode 100644 index 00000000..4d29e11a --- /dev/null +++ b/technology/scn3me_subm/sue_lib/sense_amp.sue @@ -0,0 +1,52 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_sense_amp {} { + make inout -name BL -origin {260 10} + make global -orient RXY -name vdd -origin {490 170} + make global -name gnd -origin {480 660} + make input -name sclk -origin {180 610} + make nmos -W 3.9u -L 0.6u -origin {600 500} + make nmos -orient RX -W 3.9u -L 0.6u -origin {370 500} + make pmos -orient RY -W 3u -L 0.6u -origin {600 240} + make pmos -orient RXY -W 3u -L 0.6u -origin {370 240} + make nmos -W 3.9u -L 0.6u -origin {480 610} + make inout -name BR -origin {710 20} + make pmos -W 3.9u -L 0.6u -origin {710 90} + make pmos -orient RX -W 3.9u -L 0.6u -origin {260 90} + make output -orient RXY -name dout -origin {110 370} + make_wire 600 560 600 540 + make_wire 370 540 370 560 + make_wire 370 200 370 180 + make_wire 600 180 600 200 + make_wire 490 180 370 180 + make_wire 490 180 600 180 + make_wire 490 170 490 180 + make_wire 430 300 600 300 + make_wire 430 300 430 500 + make_wire 430 300 430 240 + make_wire 600 300 600 280 + make_wire 540 430 370 430 + make_wire 540 430 540 500 + make_wire 540 430 540 240 + make_wire 370 430 370 460 + make_wire 480 560 600 560 + make_wire 480 560 370 560 + make_wire 480 560 480 570 + make_wire 480 650 480 660 + make_wire 420 610 180 610 + make_wire 650 90 320 90 + make_wire 600 360 710 360 + make_wire 710 360 710 130 + make_wire 600 360 600 300 + make_wire 600 360 600 460 + make_wire 370 370 260 370 + make_wire 260 370 260 130 + make_wire 370 370 370 430 + make_wire 370 370 370 280 + make_wire 260 10 260 50 + make_wire 710 20 710 50 + make_wire 320 90 180 90 + make_wire 180 90 180 610 + make_wire 110 370 260 370 +} + diff --git a/technology/scn3me_subm/sue_lib/tri_gate.sue b/technology/scn3me_subm/sue_lib/tri_gate.sue new file mode 100644 index 00000000..d296171f --- /dev/null +++ b/technology/scn3me_subm/sue_lib/tri_gate.sue @@ -0,0 +1,37 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_tri_gate {} { + make global -orient RXY -name vdd -origin {630 150} + make global -name gnd -origin {630 570} + make input -name tri_in -origin {320 340} + make output -name tri_out -origin {690 360} + make input -name en -origin {570 410} + make input -name en_bar -origin {570 310} + make nmos -W 1.2u -L 0.6u -origin {630 490} + make nmos -W 1.2u -L 0.6u -origin {630 410} + make pmos -orient RY -W 2.4u -L 0.6u -origin {630 310} + make pmos -orient RY -W 2.4u -L 0.6u -origin {630 230} + make pmos -orient RY -W 2.4u -L 0.6u -origin {380 290} + make nmos -W 1.2u -L 0.6u -origin {380 400} + make_wire 570 490 470 490 + make_wire 470 230 570 230 + make_wire 630 550 380 550 + make_wire 380 550 380 440 + make_wire 630 550 630 570 + make_wire 630 550 630 530 + make_wire 630 170 380 170 + make_wire 380 170 380 250 + make_wire 630 170 630 190 + make_wire 630 170 630 150 + make_wire 320 340 320 400 + make_wire 320 340 320 290 + make_wire 380 340 470 340 + make_wire 380 340 380 330 + make_wire 380 340 380 360 + make_wire 470 340 470 490 + make_wire 470 340 470 230 + make_wire 630 360 630 350 + make_wire 630 360 630 370 + make_wire 630 360 690 360 +} + diff --git a/technology/scn3me_subm/sue_lib/write_driver.sue b/technology/scn3me_subm/sue_lib/write_driver.sue new file mode 100644 index 00000000..de3909a7 --- /dev/null +++ b/technology/scn3me_subm/sue_lib/write_driver.sue @@ -0,0 +1,44 @@ +# SUE version MMI_SUE5.0.7 + +proc SCHEMATIC_write_driver {} { + make inout -name BL -origin {550 260} + make inout -name BR -origin {830 250} + make inverter -WP 2.1u -LP 0.6u -WN 1.2u -LN 0.6u -origin {280 520} + make nand2 -WP 2.1u -WN 2.1u -origin {90 360} + make inverter -WP 2.1u -LP 0.6u -WN 1.2u -LN 0.6u -origin {270 360} + make nmos -W 3.6u -L 0.6u -origin {830 410} + make nmos -W 3.6u -L 0.6u -origin {710 610} + make global -name gnd -origin {710 690} + make nand2 -WP 2.1u -WN 2.1u -origin {90 520} + make nmos -W 3.6u -L 0.6u -origin {550 410} + make input -name wen -origin {-290 340} + make input -name din -origin {-290 380} + make inverter -WP 2.1u -LP 0.6u -WN 1.2u -LN 0.6u -origin {-80 540} + make_wire 160 360 240 360 + make_wire 830 250 830 370 + make_wire 550 260 550 370 + make_wire 550 450 550 560 + make_wire 550 560 710 560 + make_wire 710 560 710 570 + make_wire 710 560 830 560 + make_wire 830 560 830 450 + make_wire 710 650 710 690 + make_wire 250 520 160 520 + make_wire 770 410 770 520 + make_wire 770 520 330 520 + make_wire 320 360 490 360 + make_wire 490 360 490 410 + make_wire -180 380 -290 380 + make_wire -180 380 70 380 + make_wire -180 540 -110 540 + make_wire -180 380 -180 540 + make_wire -30 540 70 540 + make_wire 20 340 20 500 + make_wire 20 500 70 500 + make_wire 20 340 70 340 + make_wire -240 340 -240 610 + make_wire -240 610 650 610 + make_wire -240 340 20 340 + make_wire -240 340 -290 340 +} + diff --git a/technology/scn3me_subm/tech/README b/technology/scn3me_subm/tech/README new file mode 100644 index 00000000..0d923fcb --- /dev/null +++ b/technology/scn3me_subm/tech/README @@ -0,0 +1,10 @@ +The file SCN3ME_SUBM.30.tech is from qflow 1.2 and has the following +license information: +--------------------------------------------------------------- +Tim Edwards +Open Circuit Design +v1.0 April 2013 +v1.1 May 2015 +v1.2 April 2017 +--------------------------------------------------------------- +GPL Copyright (c) 2017 diff --git a/technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech b/technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech new file mode 100644 index 00000000..bc447205 --- /dev/null +++ b/technology/scn3me_subm/tech/SCN3ME_SUBM.30.tech @@ -0,0 +1,6942 @@ +tech + format 29 + scmos +end + +version + version 2001a + description "SCMOS: Submit as technology.lambda: SCN3ME_SUBM.30 [to process: AMIc5]" +end + +planes + well,w + implant,i + select,s + cap,c + active,a + metal1,m1 + metal2,m2 + metal3,m3 + oxide,ox + comment + xp + contact + via1,v1 + via2,v2 + fill +end + +types + well nwell,nw + well pwell,pw + implant n_field_implant,nfi + implant p_field_implant,pfi + select nselect,ns + select pselect,ps + cap electrode,poly2,el,p2 + metal1 electrodecontact,poly2contact,poly2c,p2c,elc + cap electrodecap,ecap,poly2cap,p2cap,pcap + contact genericpoly2contact,gc2 + active ntransistor,nfet + active ptransistor,pfet + active diffusion,diff + active transistor,fet + active ndiffusion,ndif,green + active pdiffusion,pdif,brown + active ndcontact,ndc + active pdcontact,pdc + active psubstratepdiff,pohmicdiff,pod,ppdiff,ppd,psd + active nsubstratendiff,nohmicdiff,nod,nndiff,nnd,nsd + active psubstratepcontact,pohmiccontact,poc,pwcontact,pwc,psc + active nsubstratencontact,nohmiccontact,noc,nwcontact,nwc,nsc + active polysilicon,red,poly,p + active polycontact,pcontact,polycut,pc + contact genericcontact,gcontact,gc + metal1 metal1,m1,blue + metal1 pseudo_rmetal1,prm1 + metal1 rmetal1,rm1 + metal1 fillm1,fm1 + metal1 m2contact,m2cut,m2c,via1,v1 + metal2 metal2,m2,purple + metal2 pseudo_rmetal2,prm2 + metal2 rmetal2,rm2 + metal2 fillm2,fm2 + via1 gv1 + metal2 m3contact,m3cut,m3c,via2,v2 + metal3 metal3,m3,cyan + metal3 pseudo_rmetal3,prm3 + metal3 rmetal3,rm3 + metal3 fillm3,fm3 + via2 gv2 + metal3 pad + oxide glass + cap high_resist,hr + cap poly2_high_resist,phr + active pseudo_rpoly,prp + active rpoly,rp + cap pseudo_rpoly2,prp2 + cap rpoly2,rp2 + active pseudo_rndiffusion,prnd + active rndiffusion,rndiff,rnd + active pseudo_rpdiffusion,prpd + active rpdiffusion,rpdiff,rpd + active pseudo_rnwell,prnwell,prnw + active rnwell,rnw + implant filln,fn + fill filla,fa + fill fillb,fb + active fillp,fp + active fillapm,fapm + xp xp + xp m1p + xp m2p + xp m3p + comment comment + comment bb +end + +contact + pc poly metal1 + ndc ndiff metal1 + pdc pdiff metal1 + nsc nsd metal1 + psc psd metal1 + m2c metal1 metal2 + m3c metal2 metal3 + stackable +end + +styles + styletype mos + nwell 12 + pwell 13 + nfi 53 + pfi 54 + nselect 43 + pselect 44 + diff 25 + tran 2 4 + ndiff 2 + pdiff 4 + nsd 3 + psd 5 + nfet 6 7 + pfet 8 9 + ndc 2 20 32 + pdc 4 20 32 + nsc 3 20 32 + psc 5 20 32 + poly 1 + pcontact 1 20 32 + gc 32 + metal1 20 + rm1 20 48 + prm1 48 + m1p 20 34 + fm1 20 34 + fp 1 34 + fa 32 + fb 45 34 + fn 45 34 + fapm 1 20 21 34 + gv1 55 + m2contact 20 21 55 + metal2 21 + rm2 21 48 + prm2 48 + m2p 21 34 + fm2 21 34 + gv2 56 + m3contact 21 22 56 + metal3 22 + rm3 22 48 + prm3 48 + m3p 22 34 + fm3 22 34 + pad 22 23 34 38 + glass 34 + xp 25 34 + ecap 10 14 + poly2 14 + p2c 14 20 32 + gc2 19 + hr 10 + phr 14 48 + rp 47 48 + prp 48 + rp2 14 48 + prp2 48 + rnd 2 48 + prnd 48 + rpd 4 53 + prpd 53 + rnw 12 53 + prnw 54 + comment 45 + bb 32 + error_p 42 + error_s 42 + error_ps 42 + magnet 54 + rotate 57 + fence 59 +end + +compose + compose nfet poly ndiff + compose pfet poly pdiff + paint diff nselect ndiff + paint diff pselect pdiff + compose tran poly diff + paint tran nselect nfet + paint tran pselect pfet + paint psd ns ndiff + paint nsd ps pdiff + paint ndiff ps psd + paint pdiff ns nsd + paint pad m1 pad + paint pad m2 pad + paint pad m2c pad + paint pfi nwell nfi + paint nfi pwell pfi + paint ndc nwell pdc + paint nfet nwell pfet + paint ndiff nwell pdiff + paint psd nwell nsd + paint psc nwell nsc + paint pdc pwell ndc + paint pfet pwell nfet + paint pdiff pwell ndiff + paint nsd pwell psd + paint nsc pwell psc + paint poly2 poly ecap + erase ecap poly poly2 + paint pad m3 pad + compose phr poly2 hr + paint hr poly2 phr + paint poly2 hr phr + erase phr hr poly2 +#CRE/CRM + compose rm1 prm1 m1 + compose rm2 prm2 m2 + compose rm3 prm3 m3 + compose rp prp poly + compose rp2 prp2 poly2 + compose rnd prnd ndiff + compose rpd prpd pdiff + paint nwell rnw space + paint nwell prnw space + paint poly fp fp + paint m1 fm1 fm1 + paint m2 fm2 fm2 + paint m3 fm3 fm3 +end + +connect + nwell,nsc/a,nsd nwell,nsc/a,nsd + pwell,psc/a,psd pwell,psc/a,psd + m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + m2,fm2,fapm,m2c/m2,m3c/m2,m3c/m2 m2,fm2,fapm,m2c/m2,m3c/m2,m3c/m2 + m3,fm3,fapm,m3c/m3 m3,fm3,fapm,m3c/m3 + ndiff,ndc/a,pdiff,pdc/a ndiff,ndc/a,pdiff,pdc/a + poly,fp,nfet,pfet,fet,fapm,pc/a poly,fp,nfet,pfet,fet,fapm,pc/a + poly2,ecap,p2c poly2,ecap,p2c + gc2 poly2,ecap,metal1 + gc poly,fp,ndiff,pdiff,nsd,psd,m1,fm1,fapm,m2c/m1 + gv1 m1,fm1,fapm,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2,fm2,fapm,m3c/m2 + gv2 m2,fm2,fapm,m2c/m2,m3c/m2,m3,fm3,fapm + pad m1,fm1,m2,fm2,m3,fm3 + rm1 prm1 + rm2 prm2 + rm3 prm3 + rnw prnw + rp prp + rp2 prp2 + rnd prnd + rpd prpd + phr hr +end + +cifoutput + +style lambda=0.30(p) + scalefactor 30 15 + options calma-permissive-labels + + layer CWN nwell,rnw + bloat-or pdiff,rpd,pdc/a,pfet * 180 + bloat-or nsd,nsc/a * 90 + bloat-or nfi * 120 + grow 90 + shrink 90 + labels nwell,rnw + calma 42 0 + + layer CWP pwell + bloat-or ndiff,rnd,ndc/a,nfet * 180 + bloat-or psd,psc/a * 90 + bloat-or pfi * 120 + grow 90 + shrink 90 + and-not CWN + labels pwell + calma 41 0 + + templayer TNS ns + + templayer TPS ps + +#we give priority to selects autogenerated around diffusions (vrs. ohmics) +#XDP = (pdiff*60) Or ps +#XDN = (ndiff*60) Or ns +#FSP = ((pdiff*60,psc*60) Or XDP And-Not XDN Or ps shrink-grow +#FSN = ((ndiff*60,nsc*60) Or XDN And-Not FDP Or ns shrink-grow +#CSN = FSN +#CSP = FSP + +#diffusion auto-nselect (will have priority) + templayer XDN + bloat-or ndiff,rnd,ndc/a * 60 psd,psc/a 0 + or TNS + +#diffusion auto-pselect (will have priority) + templayer XDP + bloat-or pdiff,rpd,pdc/a * 60 nsd,nsc/a 0 + or TPS + +#final pselect + templayer FSP + bloat-or pdiff,rpd,pfet,psd,pdc/a,psc/a,pfet * 60 ndiff,rnd,ndc/a,nsd,nsc/a,nfet 0 + or XDP +#give diff nselect priority + and-not XDN + or TPS + shrink 15 + grow 15 + grow 15 + shrink 15 + +#final nselect + templayer FSN + bloat-or ndiff,rnd,nfet,nsd,ndc/a,nsc/a,nfet * 60 pdiff,rpd,pdc/a,psd,psc/a,pfet 0 + or XDN +#never conflict with final pselect + and-not FSP +#drawn select always goes + or TNS + shrink 15 + grow 15 + grow 15 + shrink 15 + + layer CSN FSN + calma 45 0 + + layer CSP FSP + calma 44 0 + + layer CAA diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + labels diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + calma 43 0 + + layer CCA ndc/m1,nsc/m1 + squares 30 60 90 + calma 48 0 + + layer CCA pdc/m1,psc/m1 + squares 30 60 90 + calma 48 0 + + layer CPG poly,rp,nfet,pfet,fet,pc/a + labels poly,rp,nfet,pfet,fet,pc/a + calma 46 0 + + layer CCP pc/m1 + squares 30 60 90 + calma 47 0 + + layer CCE gc2 + squares 0 60 90 + calma 55 0 + + layer CCE p2c + squares 30 60 90 + calma 55 0 + + layer CCE gc2 + squares 0 60 90 + calma 55 0 + + layer CCC gc + squares 0 60 90 + calma 25 0 + + layer CV1 m2c/m1 + squares 30 60 90 + calma 50 0 + + layer CV1 gv1 + squares 0 60 90 + calma 50 0 + + layer CV2 m3c/m2 + squares 30 60 90 + calma 61 0 + + layer CV2 gv2 + squares 0 60 90 + calma 61 0 + + + templayer XPAD1 pad + shrink 180 + + templayer XPAD2 XPAD1 + shrink 180 + + layer CM3 pad + labels pad + calma 62 0 + + layer CV2 XPAD2 + squares 240 60 300 + calma 61 0 + + layer CM2 pad + labels pad + calma 51 0 + + layer CV1 XPAD2 + squares 60 60 300 + calma 50 0 + + layer CM1 pad + calma 49 0 + + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + calma 49 0 + + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2 + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2 + calma 51 0 + + layer CMFP m1p + labels m1p + calma 81 0 + + layer CMSP m2p + labels m2p + calma 82 0 + + layer 100 fp + labels fp + calma 100 0 + + layer 101 fm1 + labels fm1 + calma 101 0 + + layer 102 fm2 + labels fm2 + calma 102 0 + + layer 103 fm3 + labels fm3 + calma 103 0 + + layer 109 fa + or fb + squares 0 210 120 + labels fa + calma 109 0 + + layer 119 fn + calma 119 0 + + layer 110 fapm + labels fapm + calma 110 0 + +# layer CPG fp + layer CPG fp,fapm + squares 0 210 120 + labels fp + calma 46 0 + +# layer CM1 fm1 + layer CM1 fm1,fapm + squares 0 210 120 + labels fm1 + calma 49 0 + +# layer CM2 fm2 + layer CM2 fm2,fapm + + squares 0 210 120 + labels fm2 + calma 51 0 + +# layer CM3 fm3 + layer CM3 fm3,fapm + + squares 0 210 120 + labels fm3 + calma 62 0 + + layer CM3 m3,rm3,m3c/m3 + labels m3,rm3,m3c/m3 + calma 62 0 + + layer CMTP m3p + labels m3p + calma 83 0 + + layer COG pad + shrink 600 + labels pad + calma 52 0 + + layer COG glass + labels glass + calma 52 0 + + layer CFI nfi,pfi + labels nfi,pfi + calma 27 0 + + layer CHR hr,phr + labels hr,phr + calma 34 0 + + layer CEL poly2,ecap,phr,p2c + labels poly2,ecap,phr,p2c + calma 56 0 + +#CRE/CRM + layer CRW rnw,prnw + labels rnw,prnw + calma 65 0 + layer CRG rp,prp + labels rp,prp + calma 67 0 + layer CRD rnd,rpd,prnd,prpd + labels rnd,rpd,prnd,prpd + calma 66 0 + layer CRE rnw,rp,rnd,rpd,rp2 + labels rnw,rp,rnd,rpd,rp2 + calma 64 0 + layer CRF rm1,prm1 + labels rm1,prm1 + calma 71 0 + layer CRS rm2,prm2 + labels rm2,prm2 + calma 72 0 + layer CRG2 rp2,prp2 + labels rp2,prp2 + calma 68 0 + layer CRT rm3,prm3 + labels rm3,prm3 + calma 73 0 +#CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 +#CRE/CRM calma 70 0 + + layer CX comment,bb + labels comment,bb + calma 63 0 + + layer XP pad,xp + labels pad,xp + calma 26 0 + +style fill-only + scalefactor 30 15 + + layer 100 fp + calma 100 0 + + layer 101 fm1 + calma 101 0 + + layer 102 fm2 + calma 102 0 + + layer 103 fm3 + calma 103 0 + + layer 109 fa + or fb + calma 109 0 + + layer 119 fn + calma 119 0 + +style fapm-boxes + +# this output style creates fill boxes automatically (to meet minimum +# density requirements for poly and metal layers) 5 microns outside of +# drawn layout IF: 1. you have a flattened version of your chip +# 2. over which you paint the special fill layer 'fa', preferably with +# a size that is a multiple of 7 + n * (7 + 4), 3. set 'cif +# ostype fapm-boxes' and cif out to a file (this actually creates the +# fill boxes on cif/strm layer '110' using the magic 'squares' +# command), 4. cif in the resulting file (which creates boxes on magic +# layer 'fapm') and place this cell onto your chip (and verify absence +# of drc errors or shorts), then 5. cif out under your regular cif out +# style, where the 'fapm' layer creates fill boxes on poly and all +# metal layers. + + scalefactor 30 15 + + templayer CRIT fapm,fn,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet,poly,rp,nfet,pfet,fet,pc/a,poly2,ecap,phr,p2c + or fm1,m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + or fm2,m2,rm2,m2c/m2,m3c/m2,m3c/m2 + or fm3,m3,rm3,m3c/m3 + or glass,pad + grow 510 + and fa + + layer 110 fa + squares 0 210 120 + and-not CRIT + shrink 90 + grow 90 + or fapm + labels fapm + calma 110 0 + +style fapm-stripes + scalefactor 30 15 + +# this output style creates the above layer 110 as stripes for reduced size +# HOWEVER it requires each 'fa' box to first be an exact multiple as above +# and then *replacing* the left side (1-lambda wide) stripe of each 'fa' box +# to be a 1-lambda wide layer 'fb' box -- else you won't get strips! + + templayer CRIT fapm,fn,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet,poly,rp,nfet,pfet,fet,pc/a,poly2,ecap,phr,p2c + or fm1,m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + or fm2,m2,rm2,m2c/m2,m3c/m2,m3c/m2 + or fm3,m3,rm3,m3c/m3 + or glass,pad + grow 510 + and fa + + templayer FB fa + or fb + squares 0 210 120 + and-not CRIT + + layer 110 fa + squares 0 210 120 + and-not CRIT + or FB + shrink 90 + grow 90 + or fapm + labels fapm + calma 110 0 + + +style lambda=0.30(cp) + scalefactor 30 15 + + layer CWN nwell,rnw + bloat-or pdiff,rpd,pdc/a,pfet * 180 + bloat-or nsd,nsc/a * 90 + bloat-or nfi * 120 + grow 90 + shrink 90 + labels nwell,rnw + calma 42 0 + + layer CWP pwell + bloat-or ndiff,rnd,ndc/a,nfet * 180 + bloat-or psd,psc/a * 90 + bloat-or pfi * 120 + grow 90 + shrink 90 + and-not CWN + labels pwell + calma 41 0 + + templayer TNS ns + + templayer TPS ps + +#we give priority to selects autogenerated around diffusions (vrs. ohmics) +#XDP = (pdiff*60) Or ps +#XDN = (ndiff*60) Or ns +#FSP = ((pdiff*60,psc*60) Or XDP And-Not XDN Or ps shrink-grow +#FSN = ((ndiff*60,nsc*60) Or XDN And-Not FDP Or ns shrink-grow +#CSN = FSN +#CSP = FSP + +#diffusion auto-nselect (will have priority) + templayer XDN + bloat-or ndiff,rnd,ndc/a * 60 psd,psc/a 0 + or TNS + +#diffusion auto-pselect (will have priority) + templayer XDP + bloat-or pdiff,rpd,pdc/a * 60 nsd,nsc/a 0 + or TPS + +#final pselect + templayer FSP + bloat-or pdiff,rpd,pfet,psd,pdc/a,psc/a,pfet * 60 ndiff,rnd,ndc/a,nsd,nsc/a,nfet 0 + or XDP +#give diff nselect priority + and-not XDN + or TPS + shrink 15 + grow 15 + grow 15 + shrink 15 + +#final nselect + templayer FSN + bloat-or ndiff,rnd,nfet,nsd,ndc/a,nsc/a,nfet * 60 pdiff,rpd,pdc/a,psd,psc/a,pfet 0 + or XDN +#never conflict with final pselect + and-not FSP +#drawn select always goes + or TNS + shrink 15 + grow 15 + grow 15 + shrink 15 + + layer CSN FSN + calma 45 0 + + layer CSP FSP + calma 44 0 + + layer CAA diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + labels diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + calma 43 0 + + layer CCC ndc/m1,nsc/m1 + squares 30 60 90 + calma 25 0 + + layer CCC pdc/m1,psc/m1 + squares 30 60 90 + calma 25 0 + + layer CPG poly,rp,nfet,pfet,fet,pc/a + labels poly,rp,nfet,pfet,fet,pc/a + calma 46 0 + + layer CCC pc/m1 + squares 30 60 90 + calma 25 0 + + layer CCC gc2 + squares 0 60 90 + calma 25 0 + + layer CCC p2c + squares 30 60 90 + calma 25 0 + + layer CCC gc2 + squares 0 60 90 + calma 25 0 + + layer CCC gc + squares 0 60 90 + calma 25 0 + + layer CV1 m2c/m1 + squares 30 60 90 + calma 50 0 + + layer CV1 gv1 + squares 0 60 90 + calma 50 0 + + layer CV2 m3c/m2 + squares 30 60 90 + calma 61 0 + + layer CV2 gv2 + squares 0 60 90 + calma 61 0 + + + templayer XPAD1 pad + shrink 180 + + templayer XPAD2 XPAD1 + shrink 180 + + layer CM3 pad + labels pad + calma 62 0 + + layer CV2 XPAD2 + squares 240 60 300 + calma 61 0 + + layer CM2 pad + labels pad + calma 51 0 + + layer CV1 XPAD2 + squares 60 60 300 + calma 50 0 + + layer CM1 pad + calma 49 0 + + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + calma 49 0 + + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2 + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2 + calma 51 0 + + layer CMFP m1p + labels m1p + calma 81 0 + + layer CMSP m2p + labels m2p + calma 82 0 + + layer 100 fp + labels fp + calma 100 0 + + layer 101 fm1 + labels fm1 + calma 101 0 + + layer 102 fm2 + labels fm2 + calma 102 0 + + layer 103 fm3 + labels fm3 + calma 103 0 + + layer 109 fa + or fb + squares 0 210 120 + labels fa + calma 109 0 + + layer 119 fn + calma 119 0 + + layer 110 fapm + labels fapm + calma 110 0 + +# layer CPG fp + layer CPG fp,fapm + squares 0 210 120 + labels fp + calma 46 0 + +# layer CM1 fm1 + layer CM1 fm1,fapm + squares 0 210 120 + labels fm1 + calma 49 0 + +# layer CM2 fm2 + layer CM2 fm2,fapm + + squares 0 210 120 + labels fm2 + calma 51 0 + +# layer CM3 fm3 + layer CM3 fm3,fapm + + squares 0 210 120 + labels fm3 + calma 62 0 + + layer CM3 m3,rm3,m3c/m3 + labels m3,rm3,m3c/m3 + calma 62 0 + + layer CMTP m3p + labels m3p + calma 83 0 + + layer COG pad + shrink 600 + labels pad + calma 52 0 + + layer COG glass + labels glass + calma 52 0 + + layer CFI nfi,pfi + labels nfi,pfi + calma 27 0 + + layer CHR hr,phr + labels hr,phr + calma 34 0 + + layer CEL poly2,ecap,phr,p2c + labels poly2,ecap,phr,p2c + calma 56 0 + +#CRE/CRM + layer CRW rnw,prnw + labels rnw,prnw + calma 65 0 + layer CRG rp,prp + labels rp,prp + calma 67 0 + layer CRD rnd,rpd,prnd,prpd + labels rnd,rpd,prnd,prpd + calma 66 0 + layer CRE rnw,rp,rnd,rpd,rp2 + labels rnw,rp,rnd,rpd,rp2 + calma 64 0 + layer CRF rm1,prm1 + labels rm1,prm1 + calma 71 0 + layer CRS rm2,prm2 + labels rm2,prm2 + calma 72 0 + layer CRG2 rp2,prp2 + labels rp2,prp2 + calma 68 0 + layer CRT rm3,prm3 + labels rm3,prm3 + calma 73 0 +#CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 +#CRE/CRM calma 70 0 + + layer CX comment,bb + labels comment,bb + calma 63 0 + + layer XP pad,xp + labels pad,xp + calma 26 0 + + +style lambda=0.30(c) + scalefactor 30 15 + + layer CWN nwell,rnw + bloat-or pdiff,rpd,pdc/a,pfet * 180 + bloat-or nsd,nsc/a * 90 + bloat-or nfi * 120 + grow 90 + shrink 90 + labels nwell,rnw + calma 42 0 + + templayer TNS ns + + templayer TPS ps + +#we give priority to selects autogenerated around diffusions (vrs. ohmics) +#XDP = (pdiff*60) Or ps +#XDN = (ndiff*60) Or ns +#FSP = ((pdiff*60,psc*60) Or XDP And-Not XDN Or ps shrink-grow +#FSN = ((ndiff*60,nsc*60) Or XDN And-Not FDP Or ns shrink-grow +#CSN = FSN +#CSP = FSP + +#diffusion auto-nselect (will have priority) + templayer XDN + bloat-or ndiff,rnd,ndc/a * 60 psd,psc/a 0 + or TNS + +#diffusion auto-pselect (will have priority) + templayer XDP + bloat-or pdiff,rpd,pdc/a * 60 nsd,nsc/a 0 + or TPS + +#final pselect + templayer FSP + bloat-or pdiff,rpd,pfet,psd,pdc/a,psc/a,pfet * 60 ndiff,rnd,ndc/a,nsd,nsc/a,nfet 0 + or XDP +#give diff nselect priority + and-not XDN + or TPS + shrink 15 + grow 15 + grow 15 + shrink 15 + +#final nselect + templayer FSN + bloat-or ndiff,rnd,nfet,nsd,ndc/a,nsc/a,nfet * 60 pdiff,rpd,pdc/a,psd,psc/a,pfet 0 + or XDN +#never conflict with final pselect + and-not FSP +#drawn select always goes + or TNS + shrink 15 + grow 15 + grow 15 + shrink 15 + + layer CSN FSN + calma 45 0 + + layer CSP FSP + calma 44 0 + + layer CAA diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + labels diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + calma 43 0 + + layer CCC ndc/m1,nsc/m1 + squares 30 60 90 + calma 25 0 + + layer CCC pdc/m1,psc/m1 + squares 30 60 90 + calma 25 0 + + layer CPG poly,rp,nfet,pfet,fet,pc/a + labels poly,rp,nfet,pfet,fet,pc/a + calma 46 0 + + layer CCC pc/m1 + squares 30 60 90 + calma 25 0 + + layer CCC gc2 + squares 0 60 90 + calma 25 0 + + layer CCC p2c + squares 30 60 90 + calma 25 0 + + layer CCC gc2 + squares 0 60 90 + calma 25 0 + + layer CCC gc + squares 0 60 90 + calma 25 0 + + layer CV1 m2c/m1 + squares 30 60 90 + calma 50 0 + + layer CV1 gv1 + squares 0 60 90 + calma 50 0 + + layer CV2 m3c/m2 + squares 30 60 90 + calma 61 0 + + layer CV2 gv2 + squares 0 60 90 + calma 61 0 + + + templayer XPAD1 pad + shrink 180 + + templayer XPAD2 XPAD1 + shrink 180 + + layer CM3 pad + labels pad + calma 62 0 + + layer CV2 XPAD2 + squares 240 60 300 + calma 61 0 + + layer CM2 pad + labels pad + calma 51 0 + + layer CV1 XPAD2 + squares 60 60 300 + calma 50 0 + + layer CM1 pad + calma 49 0 + + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + calma 49 0 + + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2 + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2 + calma 51 0 + + layer CMFP m1p + labels m1p + calma 81 0 + + layer CMSP m2p + labels m2p + calma 82 0 + + layer 100 fp + labels fp + calma 100 0 + + layer 101 fm1 + labels fm1 + calma 101 0 + + layer 102 fm2 + labels fm2 + calma 102 0 + + layer 103 fm3 + labels fm3 + calma 103 0 + + layer 109 fa + or fb + squares 0 210 120 + labels fa + calma 109 0 + + layer 119 fn + calma 119 0 + + layer 110 fapm + labels fapm + calma 110 0 + +# layer CPG fp + layer CPG fp,fapm + squares 0 210 120 + labels fp + calma 46 0 + +# layer CM1 fm1 + layer CM1 fm1,fapm + squares 0 210 120 + labels fm1 + calma 49 0 + +# layer CM2 fm2 + layer CM2 fm2,fapm + + squares 0 210 120 + labels fm2 + calma 51 0 + +# layer CM3 fm3 + layer CM3 fm3,fapm + + squares 0 210 120 + labels fm3 + calma 62 0 + + layer CM3 m3,rm3,m3c/m3 + labels m3,rm3,m3c/m3 + calma 62 0 + + layer CMTP m3p + labels m3p + calma 83 0 + + layer COG pad + shrink 600 + labels pad + calma 52 0 + + layer COG glass + labels glass + calma 52 0 + + layer CFI nfi,pfi + labels nfi,pfi + calma 27 0 + + layer CHR hr,phr + labels hr,phr + calma 34 0 + + layer CEL poly2,ecap,phr,p2c + labels poly2,ecap,phr,p2c + calma 56 0 + +#CRE/CRM + layer CRW rnw,prnw + labels rnw,prnw + calma 65 0 + layer CRG rp,prp + labels rp,prp + calma 67 0 + layer CRD rnd,rpd,prnd,prpd + labels rnd,rpd,prnd,prpd + calma 66 0 + layer CRE rnw,rp,rnd,rpd,rp2 + labels rnw,rp,rnd,rpd,rp2 + calma 64 0 + layer CRF rm1,prm1 + labels rm1,prm1 + calma 71 0 + layer CRS rm2,prm2 + labels rm2,prm2 + calma 72 0 + layer CRG2 rp2,prp2 + labels rp2,prp2 + calma 68 0 + layer CRT rm3,prm3 + labels rm3,prm3 + calma 73 0 +#CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 +#CRE/CRM calma 70 0 + + layer CX comment,bb + labels comment,bb + calma 63 0 + + layer XP pad,xp + labels pad,xp + calma 26 0 + + +style lambda=0.30() + scalefactor 30 15 + + layer CWN nwell,rnw + bloat-or pdiff,rpd,pdc/a,pfet * 180 + bloat-or nsd,nsc/a * 90 + bloat-or nfi * 120 + grow 90 + shrink 90 + labels nwell,rnw + calma 42 0 + + templayer TNS ns + + templayer TPS ps + +#we give priority to selects autogenerated around diffusions (vrs. ohmics) +#XDP = (pdiff*60) Or ps +#XDN = (ndiff*60) Or ns +#FSP = ((pdiff*60,psc*60) Or XDP And-Not XDN Or ps shrink-grow +#FSN = ((ndiff*60,nsc*60) Or XDN And-Not FDP Or ns shrink-grow +#CSN = FSN +#CSP = FSP + +#diffusion auto-nselect (will have priority) + templayer XDN + bloat-or ndiff,rnd,ndc/a * 60 psd,psc/a 0 + or TNS + +#diffusion auto-pselect (will have priority) + templayer XDP + bloat-or pdiff,rpd,pdc/a * 60 nsd,nsc/a 0 + or TPS + +#final pselect + templayer FSP + bloat-or pdiff,rpd,pfet,psd,pdc/a,psc/a,pfet * 60 ndiff,rnd,ndc/a,nsd,nsc/a,nfet 0 + or XDP +#give diff nselect priority + and-not XDN + or TPS + shrink 15 + grow 15 + grow 15 + shrink 15 + +#final nselect + templayer FSN + bloat-or ndiff,rnd,nfet,nsd,ndc/a,nsc/a,nfet * 60 pdiff,rpd,pdc/a,psd,psc/a,pfet 0 + or XDN +#never conflict with final pselect + and-not FSP +#drawn select always goes + or TNS + shrink 15 + grow 15 + grow 15 + shrink 15 + + layer CSN FSN + calma 45 0 + + layer CSP FSP + calma 44 0 + + layer CAA diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + labels diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,pfet,pfet,fet + calma 43 0 + + layer CCA ndc/m1,nsc/m1 + squares 30 60 90 + calma 48 0 + + layer CCA pdc/m1,psc/m1 + squares 30 60 90 + calma 48 0 + + layer CPG poly,rp,nfet,pfet,fet,pc/a + labels poly,rp,nfet,pfet,fet,pc/a + calma 46 0 + + layer CCP pc/m1 + squares 30 60 90 + calma 47 0 + + layer CCE gc2 + squares 0 60 90 + calma 55 0 + + layer CCE p2c + squares 30 60 90 + calma 55 0 + + layer CCE gc2 + squares 0 60 90 + calma 55 0 + + layer CCC gc + squares 0 60 90 + calma 25 0 + + layer CV1 m2c/m1 + squares 30 60 90 + calma 50 0 + + layer CV1 gv1 + squares 0 60 90 + calma 50 0 + + layer CV2 m3c/m2 + squares 30 60 90 + calma 61 0 + + layer CV2 gv2 + squares 0 60 90 + calma 61 0 + + + templayer XPAD1 pad + shrink 180 + + templayer XPAD2 XPAD1 + shrink 180 + + layer CM3 pad + labels pad + calma 62 0 + + layer CV2 XPAD2 + squares 240 60 300 + calma 61 0 + + layer CM2 pad + labels pad + calma 51 0 + + layer CV1 XPAD2 + squares 60 60 300 + calma 50 0 + + layer CM1 pad + calma 49 0 + + layer CM1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + labels m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 + calma 49 0 + + layer CM2 m2,rm2,m2c/m2,m3c/m2,m3c/m2 + labels m2,rm2,m2c/m2,m3c/m2,m3c/m2 + calma 51 0 + + layer CMFP m1p + labels m1p + calma 81 0 + + layer CMSP m2p + labels m2p + calma 82 0 + + layer 100 fp + labels fp + calma 100 0 + + layer 101 fm1 + labels fm1 + calma 101 0 + + layer 102 fm2 + labels fm2 + calma 102 0 + + layer 103 fm3 + labels fm3 + calma 103 0 + + layer 109 fa + or fb + squares 0 210 120 + labels fa + calma 109 0 + + layer 119 fn + calma 119 0 + + layer 110 fapm + labels fapm + calma 110 0 + +# layer CPG fp + layer CPG fp,fapm + squares 0 210 120 + labels fp + calma 46 0 + +# layer CM1 fm1 + layer CM1 fm1,fapm + squares 0 210 120 + labels fm1 + calma 49 0 + +# layer CM2 fm2 + layer CM2 fm2,fapm + + squares 0 210 120 + labels fm2 + calma 51 0 + +# layer CM3 fm3 + layer CM3 fm3,fapm + + squares 0 210 120 + labels fm3 + calma 62 0 + + layer CM3 m3,rm3,m3c/m3 + labels m3,rm3,m3c/m3 + calma 62 0 + + layer CMTP m3p + labels m3p + calma 83 0 + + layer COG pad + shrink 600 + labels pad + calma 52 0 + + layer COG glass + labels glass + calma 52 0 + + layer CFI nfi,pfi + labels nfi,pfi + calma 27 0 + + layer CHR hr,phr + labels hr,phr + calma 34 0 + + layer CEL poly2,ecap,phr,p2c + labels poly2,ecap,phr,p2c + calma 56 0 + +#CRE/CRM + layer CRW rnw,prnw + labels rnw,prnw + calma 65 0 + layer CRG rp,prp + labels rp,prp + calma 67 0 + layer CRD rnd,rpd,prnd,prpd + labels rnd,rpd,prnd,prpd + calma 66 0 + layer CRE rnw,rp,rnd,rpd,rp2 + labels rnw,rp,rnd,rpd,rp2 + calma 64 0 + layer CRF rm1,prm1 + labels rm1,prm1 + calma 71 0 + layer CRS rm2,prm2 + labels rm2,prm2 + calma 72 0 + layer CRG2 rp2,prp2 + labels rp2,prp2 + calma 68 0 + layer CRT rm3,prm3 + labels rm3,prm3 + calma 73 0 +#CRE/CRM layer CRM rm1,prm1,rm2,prm2,rm3,prm3 +#CRE/CRM calma 70 0 + + layer CX comment,bb + labels comment,bb + calma 63 0 + + layer XP pad,xp + labels pad,xp + calma 26 0 + +end + +cifinput + +style lambda=0.30(p) + scalefactor 30 + + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + +layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + layer pwell CWP + and-not CTA + labels CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + calma CSN 45 * + + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer ndc CAA + and CSN + and CCA + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer pc CCP + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer gc CCP + and-not CPG + and-not CPC + calma CCP 47 * + + layer gc CCP + and-not CM1 + calma CCP 47 * + + layer gc CCA + and-not COP + and-not CAA + and-not CBA + calma CCA 48 * + + layer gc CCA + and-not COP + and-not CM1 + calma CCA 48 * + + layer gc CCC + and-not COP + and-not CPG + and-not CPC + and-not CEL + and-not CAA + and-not CBA + calma CCC 25 * + + layer gc CCC + and-not COP + and-not CM1 + calma CCC 25 * + + layer gc2 CCE + and-not CPC + and-not CEL + calma CCE 55 * + + layer gc2 CCE + and-not CM1 + calma CCE 55 * + + layer gv1 CV1 + and-not COP + and-not CM1 + calma CV1 50 * + + layer gv1 CV1 + and-not COP + and-not CM2 + calma CV1 50 * + + layer gv2 CV2 + and-not COP + and-not CM2 + calma CV2 61 * + + layer gv2 CV2 + and-not COP + and-not CM3 + calma CV2 61 * + + layer m2c CV1 + and-not XP + grow 30 + and CM2 + and CM1 + grow 15 + shrink 15 + calma CV1 50 * + + layer m1 CM1 + and-not CRM + and-not CRF + and-not XP + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer m2 CM2 + and-not CRM + and-not CRS + and-not XP + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer m3c CV2 + and-not XP + grow 30 + and CM3 + and CM2 + grow 15 + shrink 15 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + and-not XP + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer pad XP + labels pad + calma XP 26 * + + layer glass COG + and-not COP + and-not XP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer elc CCE + grow 30 + and CM1 + and CEL + labels CM1 + calma CCE 55 * + + layer elc CCC + grow 30 + and CM1 + and CEL + labels CM1 + calma CCC 25 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(s) + scalefactor 30 + + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + + ignore CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer nselect CSN + calma CSN 45 * + + layer pselect CSP + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer ndc CAA + and CSN + and CCA + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer pc CCP + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer gc CCP + and-not CPG + and-not CPC + calma CCP 47 * + + layer gc CCP + and-not CM1 + calma CCP 47 * + + layer gc CCA + and-not COP + and-not CAA + and-not CBA + calma CCA 48 * + + layer gc CCA + and-not COP + and-not CM1 + calma CCA 48 * + + layer gc CCC + and-not COP + and-not CPG + and-not CPC + and-not CEL + and-not CAA + and-not CBA + calma CCC 25 * + + layer gc CCC + and-not COP + and-not CM1 + calma CCC 25 * + + layer gc2 CCE + and-not CPC + and-not CEL + calma CCE 55 * + + layer gc2 CCE + and-not CM1 + calma CCE 55 * + + layer gv1 CV1 + and-not COP + and-not CM1 + calma CV1 50 * + + layer gv1 CV1 + and-not COP + and-not CM2 + calma CV1 50 * + + layer gv2 CV2 + and-not COP + and-not CM2 + calma CV2 61 * + + layer gv2 CV2 + and-not COP + and-not CM3 + calma CV2 61 * + + layer m2c CV1 + and-not XP + grow 30 + and CM2 + and CM1 + grow 15 + shrink 15 + calma CV1 50 * + + layer m1 CM1 + and-not CRM + and-not CRF + and-not XP + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer m2 CM2 + and-not CRM + and-not CRS + and-not XP + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer m3c CV2 + and-not XP + grow 30 + and CM3 + and CM2 + grow 15 + shrink 15 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + and-not XP + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer pad XP + labels pad + calma XP 26 * + + layer glass COG + and-not COP + and-not XP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer elc CCE + grow 30 + and CM1 + and CEL + labels CM1 + calma CCE 55 * + + layer elc CCC + grow 30 + and CM1 + and CEL + labels CM1 + calma CCC 25 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(ps) + scalefactor 30 + + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + layer pwell CWP + and-not CTA + labels CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer nselect CSN + calma CSN 45 * + + layer pselect CSP + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer ndc CAA + and CSN + and CCA + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer pc CCP + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer gc CCP + and-not CPG + and-not CPC + calma CCP 47 * + + layer gc CCP + and-not CM1 + calma CCP 47 * + + layer gc CCA + and-not COP + and-not CAA + and-not CBA + calma CCA 48 * + + layer gc CCA + and-not COP + and-not CM1 + calma CCA 48 * + + layer gc CCC + and-not COP + and-not CPG + and-not CPC + and-not CEL + and-not CAA + and-not CBA + calma CCC 25 * + + layer gc CCC + and-not COP + and-not CM1 + calma CCC 25 * + + layer gc2 CCE + and-not CPC + and-not CEL + calma CCE 55 * + + layer gc2 CCE + and-not CM1 + calma CCE 55 * + + layer gv1 CV1 + and-not COP + and-not CM1 + calma CV1 50 * + + layer gv1 CV1 + and-not COP + and-not CM2 + calma CV1 50 * + + layer gv2 CV2 + and-not COP + and-not CM2 + calma CV2 61 * + + layer gv2 CV2 + and-not COP + and-not CM3 + calma CV2 61 * + + layer m2c CV1 + and-not XP + grow 30 + and CM2 + and CM1 + grow 15 + shrink 15 + calma CV1 50 * + + layer m1 CM1 + and-not CRM + and-not CRF + and-not XP + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer m2 CM2 + and-not CRM + and-not CRS + and-not XP + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer m3c CV2 + and-not XP + grow 30 + and CM3 + and CM2 + grow 15 + shrink 15 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + and-not XP + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer pad XP + labels pad + calma XP 26 * + + layer glass COG + and-not COP + and-not XP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer elc CCE + grow 30 + and CM1 + and CEL + labels CM1 + calma CCE 55 * + + layer elc CCC + grow 30 + and CM1 + and CEL + labels CM1 + calma CCC 25 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30() + scalefactor 30 + + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + + ignore CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + calma CSN 45 * + + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer ndc CAA + and CSN + and CCA + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer ndc CAA + and CSN + and CCC + and-not CWNR + and-not CTA + + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer nsc CAA + and CSN + and CCA + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer nsc CAA + and CSN + and CCC + and-not CWNR + and-not CTA + + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer pdc CAA + and CSP + and CCA + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer pdc CAA + and CSP + and CCC + and-not CTA + + and-not CPS + and CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer psc CAA + and CSP + and CCA + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCA 48 * + + layer psc CAA + and CSP + and CCC + and-not CWNR + and-not CTA + + and-not CPS + and-not CWN + and CM1 + grow 30 + grow 15 + shrink 15 + calma CCC 25 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer pc CCP + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCP 47 * + + layer pc CCC + and CPG + and-not CPC + and-not CEL + and-not CAA + grow 30 + and CM1 + grow 15 + shrink 15 + calma CCC 25 * + + layer gc CCP + and-not CPG + and-not CPC + calma CCP 47 * + + layer gc CCP + and-not CM1 + calma CCP 47 * + + layer gc CCA + and-not COP + and-not CAA + and-not CBA + calma CCA 48 * + + layer gc CCA + and-not COP + and-not CM1 + calma CCA 48 * + + layer gc CCC + and-not COP + and-not CPG + and-not CPC + and-not CEL + and-not CAA + and-not CBA + calma CCC 25 * + + layer gc CCC + and-not COP + and-not CM1 + calma CCC 25 * + + layer gc2 CCE + and-not CPC + and-not CEL + calma CCE 55 * + + layer gc2 CCE + and-not CM1 + calma CCE 55 * + + layer gv1 CV1 + and-not COP + and-not CM1 + calma CV1 50 * + + layer gv1 CV1 + and-not COP + and-not CM2 + calma CV1 50 * + + layer gv2 CV2 + and-not COP + and-not CM2 + calma CV2 61 * + + layer gv2 CV2 + and-not COP + and-not CM3 + calma CV2 61 * + + layer m2c CV1 + and-not XP + grow 30 + and CM2 + and CM1 + grow 15 + shrink 15 + calma CV1 50 * + + layer m1 CM1 + and-not CRM + and-not CRF + and-not XP + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer m2 CM2 + and-not CRM + and-not CRS + and-not XP + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer m3c CV2 + and-not XP + grow 30 + and CM3 + and CM2 + grow 15 + shrink 15 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + and-not XP + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer pad XP + labels pad + calma XP 26 * + + layer glass COG + and-not COP + and-not XP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer elc CCE + grow 30 + and CM1 + and CEL + labels CM1 + calma CCE 55 * + + layer elc CCC + grow 30 + and CM1 + and CEL + labels CM1 + calma CCC 25 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(c) + scalefactor 30 + + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + + ignore CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + calma CSN 45 * + + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer gc2 CCA + and CEL + calma CCA 48 * + + layer gc2 CCP + and CEL + calma CCP 47 * + + layer gc2 CCC + and CEL + calma CCC 25 * + + layer gc2 CCE + and CEL + calma CCE 55 * + + layer gc2 CCA + and CPC + and-not CPG + calma CCA 48 * + + layer gc2 CCP + and CPC + and-not CPG + calma CCP 47 * + + layer gc2 CCC + and CPC + and-not CPG + calma CCC 25 * + + layer gc2 CCE + and CPC + and-not CPG + calma CCE 55 * + + layer gc CCA + and CPG + and-not CEL + calma CCA 48 * + + layer gc CCP + and CPG + and-not CEL + calma CCP 47 * + + layer gc CCC + and CPG + and-not CEL + calma CCC 25 * + + layer gc CCE + and CPG + and-not CEL + calma CCE 55 * + + layer gc CCA + and-not COP + and-not CPC + and-not CEL + calma CCA 48 * + + layer gc CCP + and-not COP + and-not CPC + and-not CEL + calma CCP 47 * + + layer gc CCC + and-not COP + and-not CPC + and-not CEL + calma CCC 25 * + + layer gc CCE + and-not COP + and-not CPC + and-not CEL + calma CCE 55 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer m1 CM1 + and-not CRM + and-not CRF + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer gv1 CV1 + calma CV1 50 * + + layer m2 CM2 + and-not CRM + and-not CRS + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer gv2 CV2 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer xp XP + calma XP 26 * + + layer glass COG + and-not COP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(cs) + scalefactor 30 + + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + + ignore CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer nselect CSN + calma CSN 45 * + + layer pselect CSP + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer gc2 CCA + and CEL + calma CCA 48 * + + layer gc2 CCP + and CEL + calma CCP 47 * + + layer gc2 CCC + and CEL + calma CCC 25 * + + layer gc2 CCE + and CEL + calma CCE 55 * + + layer gc2 CCA + and CPC + and-not CPG + calma CCA 48 * + + layer gc2 CCP + and CPC + and-not CPG + calma CCP 47 * + + layer gc2 CCC + and CPC + and-not CPG + calma CCC 25 * + + layer gc2 CCE + and CPC + and-not CPG + calma CCE 55 * + + layer gc CCA + and CPG + and-not CEL + calma CCA 48 * + + layer gc CCP + and CPG + and-not CEL + calma CCP 47 * + + layer gc CCC + and CPG + and-not CEL + calma CCC 25 * + + layer gc CCE + and CPG + and-not CEL + calma CCE 55 * + + layer gc CCA + and-not COP + and-not CPC + and-not CEL + calma CCA 48 * + + layer gc CCP + and-not COP + and-not CPC + and-not CEL + calma CCP 47 * + + layer gc CCC + and-not COP + and-not CPC + and-not CEL + calma CCC 25 * + + layer gc CCE + and-not COP + and-not CPC + and-not CEL + calma CCE 55 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer m1 CM1 + and-not CRM + and-not CRF + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer gv1 CV1 + calma CV1 50 * + + layer m2 CM2 + and-not CRM + and-not CRS + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer gv2 CV2 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer xp XP + calma XP 26 * + + layer glass COG + and-not COP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(cps) + scalefactor 30 + + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + layer pwell CWP + and-not CTA + labels CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer nselect CSN + calma CSN 45 * + + layer pselect CSP + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer gc2 CCA + and CEL + calma CCA 48 * + + layer gc2 CCP + and CEL + calma CCP 47 * + + layer gc2 CCC + and CEL + calma CCC 25 * + + layer gc2 CCE + and CEL + calma CCE 55 * + + layer gc2 CCA + and CPC + and-not CPG + calma CCA 48 * + + layer gc2 CCP + and CPC + and-not CPG + calma CCP 47 * + + layer gc2 CCC + and CPC + and-not CPG + calma CCC 25 * + + layer gc2 CCE + and CPC + and-not CPG + calma CCE 55 * + + layer gc CCA + and CPG + and-not CEL + calma CCA 48 * + + layer gc CCP + and CPG + and-not CEL + calma CCP 47 * + + layer gc CCC + and CPG + and-not CEL + calma CCC 25 * + + layer gc CCE + and CPG + and-not CEL + calma CCE 55 * + + layer gc CCA + and-not COP + and-not CPC + and-not CEL + calma CCA 48 * + + layer gc CCP + and-not COP + and-not CPC + and-not CEL + calma CCP 47 * + + layer gc CCC + and-not COP + and-not CPC + and-not CEL + calma CCC 25 * + + layer gc CCE + and-not COP + and-not CPC + and-not CEL + calma CCE 55 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer m1 CM1 + and-not CRM + and-not CRF + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer gv1 CV1 + calma CV1 50 * + + layer m2 CM2 + and-not CRM + and-not CRS + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer gv2 CV2 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer xp XP + calma XP 26 * + + layer glass COG + and-not COP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + + +style lambda=0.30(cp) + scalefactor 30 + + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + + layer nwell CWN + and-not CWNR + and-not CTA + labels CWN + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRE + and-not CSB + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer rnw CWN + and-not CWNR + and CRW + and-not CRD + and-not CAA + and-not CPG + calma CWN 42 * + + layer pseudo_rnwell CRW + and-not CRE + calma CRW 65 * + + layer pwell CWP + and-not CTA + labels CWP + calma CWP 41 * + + layer diff CAA + and-not CTA + and-not CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + layer tran CAA + and-not CTA + and CPG + and-not CWNR + and-not COP + and-not CSN + and-not CSP + labels CAA + calma CAA 43 * + + calma CSN 45 * + + calma CSP 44 * + + layer ndiff CAA + and CSN + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRE + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer rnd CAA + and CSN + and-not CWNR + and CRD + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rndiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and-not CWN + and-not CSP + and CSN + and-not CBA + calma CRD 66 * + + layer pdiff CAA + and CSP + and-not CWNR + and-not CTA + and-not CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRE + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer rpd CAA + and CSP + and-not CWNR + and CRD + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CAA 43 * + + layer pseudo_rpdiff CRD + and-not CRE + and-not CAA + and-not CSB + and-not CPG + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + calma CRD 66 * + + layer nfet CAA + and CSN + and-not CWNR + and-not CTA + and CPG + and-not CEL + and-not CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer pfet CAA + and CSP + and-not CWNR + and-not CTA + and CPG + and-not CEL + and CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer nsd CAA + and CSN + and-not CWNR + and-not CTA + and CWN + and-not CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer psd CAA + and CSP + and-not CWNR + and-not CTA + and-not CWN + and-not CSN + and-not CPS + and CSP + and-not CBA + labels CAA + calma CAA 43 * + + layer gc2 CCA + and CEL + calma CCA 48 * + + layer gc2 CCP + and CEL + calma CCP 47 * + + layer gc2 CCC + and CEL + calma CCC 25 * + + layer gc2 CCE + and CEL + calma CCE 55 * + + layer gc2 CCA + and CPC + and-not CPG + calma CCA 48 * + + layer gc2 CCP + and CPC + and-not CPG + calma CCP 47 * + + layer gc2 CCC + and CPC + and-not CPG + calma CCC 25 * + + layer gc2 CCE + and CPC + and-not CPG + calma CCE 55 * + + layer gc CCA + and CPG + and-not CEL + calma CCA 48 * + + layer gc CCP + and CPG + and-not CEL + calma CCP 47 * + + layer gc CCC + and CPG + and-not CEL + calma CCC 25 * + + layer gc CCE + and CPG + and-not CEL + calma CCE 55 * + + layer gc CCA + and-not COP + and-not CPC + and-not CEL + calma CCA 48 * + + layer gc CCP + and-not COP + and-not CPC + and-not CEL + calma CCP 47 * + + layer gc CCC + and-not COP + and-not CPC + and-not CEL + calma CCC 25 * + + layer gc CCE + and-not COP + and-not CPC + and-not CEL + calma CCE 55 * + + layer poly CPG + and-not CRE + labels CPG + calma CPG 46 * + + layer rp CPG + and CRE + and-not CSB + calma CPG 46 * + + layer rp CPG + and CRG + calma CPG 46 * + + layer pseudo_rpoly CRG + and-not CRE + calma CRG 67 * + + layer m1 CM1 + and-not CRM + and-not CRF + labels CM1 + calma CM1 49 * + + layer rm1 CRM + and CM1 + calma CRM 70 * + + layer rm1 CRF + and CM1 + calma CRF 71 * + + layer pseudo_rmetal1 CRF + and-not rm1 + calma CRF 71 * + + layer m1p CMFP + labels CMFP + calma CMFP 81 * + + layer gv1 CV1 + calma CV1 50 * + + layer m2 CM2 + and-not CRM + and-not CRS + labels CM2 + calma CM2 51 * + + layer rm2 CRM + and CM2 + calma CRM 70 * + + layer rm2 CRS + and CM2 + calma CRS 72 * + + layer pseudo_rmetal2 CRS + and-not rm2 + calma CRS 72 * + + layer m2p CMSP + labels CMSP + calma CMSP 82 * + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + + layer gv2 CV2 + calma CV2 61 * + + layer m3 CM3 + and-not CRM + and-not CRT + labels CM3 + calma CM3 62 * + + layer rm3 CRM + and CM3 + calma CRM 70 * + + layer rm3 CRT + and CM3 + calma CRT 73 * + + layer pseudo_rmetal3 CRT + and-not rm3 + calma CRT 73 * + + layer m3p CMTP + labels CMTP + calma CMTP 83 * + + layer xp XP + calma XP 26 * + + layer glass COG + and-not COP + labels COG + calma COG 52 * + + layer nfi CFI + and CWN + labels CFI + calma CFI 27 * + + layer pfi CFI + and-not CWN + labels CFI + calma CFI 27 * + + layer hr CHR + labels CHR + calma CHR 34 * + + layer phr CEL + and CHR + calma CEL 56 * + + layer ecap CEL + and CPG + labels CEL + calma CEL 56 * + + layer poly2 CEL + and-not CPG + labels CEL + calma CEL 56 * + + layer rp2 CEL + and CRG2 + calma CEL 56 * + + layer pseudo_rpoly2 CRG2 + and-not CRE + calma CRG2 68 * + + layer comment CX + labels CX + calma CX 63 * + + calma CTA 60 * + + calma CRW 65 * + calma CRG 67 * + calma CRD 66 * + calma CRE 64 * + calma CRF 71 * + calma CRS 72 * + calma CRT 73 * + calma CRM 70 * + +style fill-only + scalefactor 30 +# scalefactor 100 + + layer fp 100 + calma 100 100 * + + layer fm1 101 + calma 101 101 * + + layer fm2 102 + calma 102 102 * + + layer fm3 103 + calma 103 103 * + + layer fa 109 + or fb + calma 109 109 * + + layer fn 119 + calma 119 119 * + + layer fapm 110 + calma 110 110 * + +end + +mzrouter + style irouter +# layer hCost vCost jogCost hintCost + layer metal3 1 2 2 1 + layer metal2 2 1 2 1 + layer metal1 2 3 2 1 + layer poly 10 10 11 1 + contact m3contact metal3 metal2 5 + contact m2contact metal2 metal1 6 + contact pcontact metal1 poly 7 + notactive poly pcontact + +style garouter + layer m2 32 64 256 1 + layer m1 64 32 256 1 + contact m2contact metal1 metal2 1024 + +end + +drc + width nwell 12 \ + "N-well width < 12 (Mosis #1.1)" + + width rnw 12 \ + "rnwell (for resistor L/W extraction) width < 12 (Mosis #1.1)" + + width pwell 12 \ + "P-well width < 12 (Mosis #1.1)" + + width diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a 3 \ + "Diffusion width < 3 (Mosis #2.1)" + + width poly,fp,rp,pc/a,nfet,pfet,fet 2 \ + "Poly width < 2 (Mosis #3.1)" + + width nselect 2 \ + "N-Select width < 2 (Mosis #4.4)" + + width pselect 2 \ + "P-Select width < 2 (Mosis #4.4)" + + width pc/m1 4 \ + "Poly contact width < 4 (Mosis #5.1)" + + width gc 2 \ + "GC contact width < 2 (Mosis #6.1)" + + width ndc/m1 4 \ + "Diffusion contact width < 4 (Mosis #6.1)" + + width nsc/m1 4 \ + "Diffusion contact width < 4 (Mosis #6.1)" + + width pdc/m1 4 \ + "Diffusion contact width < 4 (Mosis #6.1)" + + width psc/m1 4 \ + "Diffusion contact width < 4 (Mosis #6.1)" + + width m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 3 \ + "Metal1 width < 3 (Mosis #7.1)" + + width gv1 2 \ + "GV1 via width < 2 (Mosis #8.1)" + + width m2c/m1 4 \ + "Metal2 contact width < 4 (Mosis #8.1)" + + width m2,fm2,rm2,m2c/m2,m3c/m2 3 \ + "Metal2 width < 3 (Mosis #9.1)" + + width ecap 8 \ + "Ecap width < 8 (Mosis #11.1)" + + width poly2,ecap,phr 5 \ + "Poly2 width < 5 (Mosis #11.1)" + + width gc2 2 \ + "Generic contact2 width < 2 (Mosis #13.1)" + + width p2c 4 \ + "Poly2 contact width < 4 (Mosis #13.1)" + + width gv2 2 \ + "GV2 via width < 2 (Mosis #14.1)" + + width m3c/m2 4 \ + "Metal3 contact width < 4 (Mosis #14.1)" + + width m3,fm3,rm3,m3c/m3,pad 5 \ + "Metal3 width < 5 (Mosis #15.1)" + + width hr,phr 4 \ + "High-Resist width < 4 (Mosis #27.1)" + + width phr 5 \ + "High-Resist poly2R width < 5 (Mosis #27.7)" + + width nfi,pfi 4 \ + "N/P_field-implant width < 4 (Mosis #29.1)" + + spacing nwell nwell 6 touching_ok \ + "N-well(at-same-potential) spacing < 6 (Mosis #1.3)" + + spacing pwell pwell 6 touching_ok \ + "P-well(at-same-potential) spacing < 6 (Mosis #1.3)" + + spacing rnw nwell 18 touching_illegal \ + "rnw (for resistor L/W extraction) spacing to N-well < 18 (Mosis #2.3)" + + edge4way ~(pwell)/well pwell 1 ~(rnw)/active 0 0 \ + "P-well cannot touch rnw (for resistor L/W extraction) (Mosis #1.4)" active + + spacing diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a 3 touching_ok \ + "Diffusion spacing < 3 (Mosis #2.2)" + + spacing nwell ndiff,rnd,nfet,ndc/a 6 touching_illegal \ + "N-well spacing to N-Diffusion < 6 (Mosis #2.3)" + + spacing pwell pdiff,rpd,pfet,pdc/a 6 touching_illegal \ + "P-well spacing to P-Diffusion < 6 (Mosis #2.3)" + + spacing ndiff,rnd,nfet,ndc/a pdiff,rpd,pfet,pdc/a 12 touching_illegal \ + "N-Diffusion spacing to P-Diffusion < 12 (Mosis #2.3+2.3)" + + edge4way ~(nwell)/well nwell 6 ~(pdiff,rpd,pfet,pdc/a)/active nwell 6 \ + "N-well overlap of P-Diffusion < 6 (Mosis #2.4)" active + + edge4way ~(pwell)/well pwell 6 ~(ndiff,rnd,nfet,ndc/a)/active pwell 6 \ + "P-well overlap of N-Diffusion < 6 (Mosis #2.4)" active + + edge4way ~(nwell)/well nwell 3 ~(nsd,nsc/a)/active nwell 3 \ + "N-well overlap of N-Ohmic < 3 (Mosis #2.4)" active + + edge4way ~(pwell)/well pwell 3 ~(psd,psc/a)/active pwell 3 \ + "P-well overlap of P-Ohmic < 3 (Mosis #2.4)" active + + spacing ndiff,rnd,ndc/a nsd,nsc/a 9 touching_illegal \ + "N-Diffusion spacing to N-Ohmic < 9 (Mosis #2.3+2.4)" + + spacing pdiff,rpd,pdc/a psd,psc/a 9 touching_illegal \ + "P-Diffusion spacing to P-Ohmic < 9 (Mosis #2.3+2.4)" + + spacing nwell psd,psc/a 3 touching_illegal \ + "N-well spacing to P-Ohmic < 3 (Mosis #2.4)" + + spacing pwell nsd,nsc/a 3 touching_illegal \ + "P-well spacing to N-Ohmic < 3 (Mosis #2.4)" + + spacing psd,psc/a rnw,prnw 3 touching_illegal \ + "P-Ohmic spacing to rnw,prnw < 3 (Mosis #2.4)" + + spacing nsd,nsc/a psd,psc/a 6 touching_illegal \ + "N-Ohmic spacing to P-Ohmic < 6 (Mosis #2.4+2.4)" + + spacing ndiff,rnd,nfet,ndc/a,nfet psd,psc/a 4 touching_ok \ + "N-Diffusion spacing to P-Ohmic < 4 (Mosis #2.5)" + + spacing pdiff,rpd,pfet,pdc/a,pfet nsd,nsc/a 4 touching_ok \ + "P-Diffusion spacing to N-Ohmic < 4 (Mosis #2.5)" + + spacing poly,rp,pc/a,nfet,pfet,fet poly,rp,pc/a,nfet,pfet,fet 3 touching_ok \ + "Poly spacing < 3 (Mosis #3.2)" + + spacing poly,rp,pc/a,nfet,pfet,fet fp,fapm 3 touching_illegal \ + "Poly spacing to fill layer (fp) < 3 (Mosis #3.2)" + + spacing fp fp 4 touching_ok \ + "Poly fill layer (fp) spacing < 4 (Mosis #0)" + + edge4way nfet,pfet,fet space/active,poly,fp,rp,pc/a 2 poly,fp,rp,pc/a 0 0 \ + "Poly overhang of Transistor < 2 (Mosis #3.3)" active + + edge4way nfet,pfet,fet space/active,ndiff,rnd,ndc/a,pdiff,rpd,pdc/a 3 ndiff,rnd,ndc/a,pdiff,rpd,pdc/a,nfet,pfet,fet 0 0 \ + "N-Diffusion,P-Diffusion overhang of Transistor < 3 (Mosis #3.4)" active + + edge4way poly,fp,rp,pc/a ~(poly,fp,rp,pc/a,nfet,pfet,fet,prp)/active 1 space/a space/a 1 \ + "Poly spacing to Diffusion < 1 (Mosis #3.5)" + + edge4way nfet ~(nfet)/active 3 ~(pselect)/select ~(nfet)/active 3 \ + "N-Transistor space to P-Select < 3 (Mosis #4.1)" select + + edge4way pfet ~(pfet)/active 3 ~(nselect)/select ~(pfet)/active 3 \ + "P-Transistor space to N-Select < 3 (Mosis #4.1)" select + + edge4way nfet ~(nfet)/active 3 ~(psd,psc/a)/active ~(nfet)/active 2 \ + "N-Transistor space to P-Ohmic < 3 (Mosis #4.1)" active + + edge4way pfet ~(pfet)/active 3 ~(nsd,nsc/a)/active ~(pfet)/active 2 \ + "P-Transistor space to N-Ohmic < 3 (Mosis #4.1)" active + +#PEZ edge4way psd,psc/a space ~(nfet)/active space \ +#PEZ "P-Ohmic space to N-Transistor < (Mosis #4.1)" active + +#PEZ edge4way nsd,nsc/a space ~(pfet)/active space \ +#PEZ "N-Ohmic space to P-Transistor < (Mosis #4.1)" active + + edge4way ~(nselect,pselect)/select nselect,pselect 2 ~(diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a)/active nselect,pselect 2 \ + "N-Select,P-Select overlap of Diffusion < 2 (Mosis #4.2_)" active + + edge4way space nselect,pselect 2 ~(ndiff,rnd,nfet,ndc/a)/active nselect 2 \ + "N-Select space to N-Diffusion < 2 (Mosis #4.2a)" active + + edge4way nselect,pselect space 2 ~(ndiff,rnd,nfet,ndc/a)/active nselect 2 \ + "N-Select space to N-Diffusion < 2 (Mosis #4.2b)" active + + edge4way nselect,pselect space 2 ~(ndiff,rnd,nfet,ndc/a)/active space,nselect,pselect 2 \ + "N-Select space to N-Diffusion < 2 (Mosis #4.2c)" active + + edge4way space nselect,pselect 2 ~(pdiff,rpd,pfet,pdc/a)/active pselect 2 \ + "P-Select space to P-Diffusion < 2 (Mosis #4.2aa)" active + + edge4way nselect,pselect space 2 ~(pdiff,rpd,pfet,pdc/a)/active pselect 2 \ + "P-Select space to P-Diffusion < 2 (Mosis #4.2bb)" active + + edge4way nselect,pselect space 2 ~(pdiff,rpd,pfet,pdc/a)/active space,nselect,pselect 2 \ + "P-Select space to P-Diffusion < 2 (Mosis #4.2cc)" active + + edge4way diff space 2 nselect space 2 \ + "N-Select must overlap Diffusion by 2 (Mosis #4.2)" select + + edge4way diff space 2 pselect space 2 \ + "P-Select must overlap Diffusion by 2 (Mosis #4.2)" select + + edge4way ndiff,rnd,nfet,ndc/a space 2 ~(pselect)/select space 2 \ + "P-Select space to N-Diffusion < 2 (Mosis #4.2e)" select + + edge4way pdiff,rpd,pfet,pdc/a space 2 ~(nselect)/select space 2 \ + "N-Select space to P-Diffusion < 2 (Mosis #4.2e)" select + + edge4way ~(pdiff,rpd,pfet,pdc/a,psd,psc/a)/active pdiff,rpd,pfet,pdc/a,psd,psc/a 1 ~(nselect)/select 0 0 \ + "N-Select cannot touch P-Diffusion,P-Ohmic (Mosis #4.2f)" select + + edge4way ~(ndiff,rnd,nfet,ndc/a,nsd,nsc/a)/active ndiff,rnd,nfet,ndc/a,nsd,nsc/a 1 ~(pselect)/select 0 0 \ + "P-Select cannot touch N-Diffusion,N-Ohmic (Mosis #4.2f)" select + + width nsd,nsc/a,psd,psc/a 2 \ + "N-Ohmic,P-Ohmic width < 2 (Mosis #4.1)" + + spacing nselect nselect 2 touching_ok \ + "N-Select spacing < 2 (Mosis #4.4)" + + spacing pselect pselect 2 touching_ok \ + "P-Select spacing < 2 (Mosis #4.4)" + + edge4way ndiff,rnd,ndc/a psd,psc/a 2 ~(ndiff,rnd,ndc/a)/active 0 0 \ + "P-Ohmic(that touches N-Diffusion) width < 2 (Mosis #4.4)" + + edge4way pdiff,rpd,pdc/a nsd,nsc/a 2 ~(pdiff,rpd,pdc/a)/active 0 0 \ + "N-Ohmic(that touches P-Diffusion) width < 2 (Mosis #4.4)" + + edge4way gc ~(gc)/contact 1 poly,fp,rp,pc/a,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a ~(gc)/contact 1 \ + "Poly,Diffusion overlap of GC contact < 1 (Mosis #5.2)" active + + edge4way gc space 1 poly,fp,rp,pc/a,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a space 1 \ + "one of: Poly,Diffusion must overlap GC contact by 1 (Mosis #5.2a,6.2a)" active + + edge4way ~(poly,fp,rp,pc/a,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a)/active poly,fp,rp,pc/a,diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a 1 ~(gc)/contact 0 0 \ + "Edge to one of: Poly,Diffusion cannot touch GC contact (Mosis #5.2a,6.2a)" contact + + spacing gc gc 3 touching_ok \ + "Generic contact spacing < 3 (Mosis #5.3)" + + edge4way ~(gc)/contact gc 1 ~(ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c)/metal1 0 0 \ + "GC contact cannot touch Metal1 contacts (Mosis #0)" metal1 + + spacing gv1 m2c/m2 2 touching_illegal \ + "GV1 via spacing to Metal2 contacts < 2 (Mosis #14.2)" + + spacing poly,fp,rp,pc/a pc/a 4 touching_ok \ + "Poly spacing to Poly contact < 4 (Mosis #5.5.b)" + + edge4way gc ~(gc)/contact 1 diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,poly,fp,rp,pc/a ~(gc)/contact 1 \ + "Diffusion,Poly overlap of GC contact < 1 (Mosis #6.2)" active + + spacing gc pc/a,ndc/a,pdc/a,psc/a,nsc/a 2 touching_illegal \ + "Generic contact spacing to Poly contact,Diffusion contact < 2 (Mosis #5.3)" + + spacing nsc/m1 pdc/m1 1 touching_illegal \ + "nsc spacing to pdc < 1 (Mosis #6.3)" + + spacing psc/m1 ndc/m1 1 touching_illegal \ + "psc spacing to ndc < 1 (Mosis #6.3)" + + spacing nfet,pfet ndc/a,pdc/a,psc/a,nsc/a 1 touching_illegal \ + "N-Transistor,P-Transistor spacing to Diffusion contact < 1 (Mosis #6.4)" + + spacing nfet,pfet gc 2 touching_illegal \ + "N-Transistor,P-Transistor spacing to Generic contact < 2 (Mosis #6.4)" + + spacing diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a pc/a 1 touching_illegal \ + "Diffusion spacing to Poly contact < 1 (Mosis #6.5.b)" + + spacing diff,ndiff,rnd,nfet,nsd,pdiff,rpd,pfet,psd,ndc/a,nsc/a,pdc/a,psc/a,nfet,pfet ndc/a,pdc/a,psc/a,nsc/a 4 touching_ok \ + "Diffusion spacing to Diffusion contact < 4 (Mosis #6.5.b)" + + spacing pc/a ndc/a,pdc/a,psc/a,nsc/a 2 touching_illegal \ + "pc/a spacing to ndc/a,pdc/a,psc/a,nsc/a < 2 (Mosis #6.7)" + + spacing m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 3 touching_ok \ + "Metal1 spacing < 3 (Mosis #7.2)" + + spacing m1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 fm1,fapm 3 touching_illegal \ + "Metal1 spacing to fill layer (fm1) < 3 (Mosis #7.2)" + + spacing fm1 fm1 4 touching_ok \ + "Metal1 fill layer (fm1) spacing < 4 (Mosis #0)" + + edge4way gc space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 space 1 \ + "Metal1 must overlap GC contact by 1 (Mosis #7.3,7.4)" metal1 + + edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 1 ~(gc)/contact 0 0 \ + "Metal1(edge) cannot touch GC contact (Mosis #7.3+7.4)" contact + + spacing gv1 gv1 3 touching_ok \ + "GV1 via spacing < 3 (Mosis #8.2)" + + edge4way gv1 ~(gv1)/via1 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 ~(gv1)/via1 1 \ + "Metal1 overlap of GV1 via < 1 (Mosis #8.3)" metal1 + + edge4way gv1 space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 space 1 \ + "Metal1 must overlap GV1 via by 1 (Mosis #8.3)" metal1 + + edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 1 ~(gv1)/via1 0 0 \ + "Metal1(edge) cannot touch GV1 via (Mosis #8.3)" via1 + + spacing gc gv1 2 touching_illegal \ + "GC contact spacing to GV1 via < 2 (Mosis #8.4)" + + spacing gc m2c/m2 2 touching_illegal \ + " spacing to Metal2 contacts < 2 (Mosis #14.2)" + + spacing gc m2c/m2 2 touching_illegal \ + "GC contact spacing to Metal2 contacts < 2 (Mosis #8.4)" + + spacing m2,rm2,m2c/m2,m3c/m2 m2,rm2,m2c/m2,m3c/m2 3 touching_ok \ + "Metal2 spacing < 3 (Mosis #9.2)" + + spacing m2,rm2,m2c/m2,m3c/m2 fm2,fapm 3 touching_illegal \ + "Metal2 spacing to fill layer (fm2) < 3 (Mosis #9.2)" + + spacing fm2 fm2 4 touching_ok \ + "Metal2 fill layer (fm2) spacing < 4 (Mosis #0)" + + edge4way gv1 space 1 m2,fm2,rm2,m2c/m2,m3c/m2 space 1 \ + "Metal2 must overlap GV1 via by 1 (Mosis #9.3)" metal2 + + edge4way ~(m2,fm2,rm2,m2c/m2,m3c/m2)/metal2 m2,fm2,rm2,m2c/m2,m3c/m2 1 ~(gv1)/via1 0 0 \ + "Metal2(edge) cannot touch GV1 via (Mosis #9.3)" via1 + + width glass 10 \ + "COG width < 10 (Mosis #10.2)" + + edge4way ~(pad)/metal3 pad 20 ~(glass)/oxide pad 20 \ + "pad overlap of COG < 20 (Mosis #10.3)" oxide + + spacing ecap ecap 3 touching_ok \ + "Ecap spacing < 3 (Mosis #11.2)" + + edge4way ecap ~(ecap)/cap 5 poly,fp,rp,pc/a ~(ecap)/cap 5 \ + "Poly overlap of Ecap < 5 (Mosis #11.3)" active + + edge4way ~(ecap)/cap ecap 1 poly,fp,rp,pc/a 0 0 \ + "Ecap must touch Poly (Mosis #11.3x)" active + + edge4way poly2,phr space 5 ~(poly,fp,rp,pc/a)/active space 5 \ + "Poly2 spacing to Poly < 5 (Mosis #11.3c)" active + + spacing ecap pc/a 2 touching_illegal \ + "Ecap spacing to Poly contact < 2 (Mosis #11.5)" + + spacing ecap gc 3 touching_illegal \ + "Ecap spacing to Generic contact < 3 (Mosis #11.5)" + + spacing poly2,ecap,phr poly2,ecap,phr 3 touching_ok \ + "Poly2 spacing < 3 (Mosis #11.2)" + + spacing poly2,ecap,phr pc/a,ndc/a,pdc/a,psc/a,nsc/a 2 touching_illegal \ + "Poly2 spacing to Poly contact,Diffusion contact < 2 (Mosis #11.5)" + + spacing poly2,ecap,phr gc,gc 3 touching_illegal \ + "Poly2 spacing to GC contact < 3 (Mosis #11.5)" + + spacing gc2 gc2 3 touching_ok \ + "Generic contact2 spacing < 3 (Mosis #13.2)" + + edge4way ~(ecap)/cap ecap 3 ~(gc2)/contact ecap 3 \ + "Ecap overlap of Generic contact2 < 3 (Mosis #13.3)" contact + + edge4way ~(ecap)/cap ecap 2 ~(p2c)/metal1 ecap 2 \ + "Ecap overlap of Poly2 contact < 2 (Mosis #13.3)" metal1 + + edge4way gc2 space 1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 space 1 \ + "Metal1 must overlap Generic contact2 by 1 (Mosis #13.4)" metal1 + + edge4way ~(m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1)/metal1 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 1 ~(gc2)/contact 0 0 \ + "Metal1(edge) cannot touch Generic contact2 (Mosis #13.4)" contact + + edge4way ~(poly2,ecap,phr)/cap poly2,ecap,phr 1 ~(p2c)/metal1 poly2,ecap,phr 1 \ + "Poly2 overlap of Poly2 contact < 1 (Mosis #13.4)" metal1 + + spacing gv2 gv2 3 touching_ok \ + "GV2 via spacing < 3 (Mosis #14.2)" + + spacing gv2 m3c/m2 2 touching_illegal \ + "GV2 via spacing to Metal3 contact < 2 (Mosis #14.2)" + + edge4way gv2 space 1 m2,fm2,rm2,m2c/m2,m3c/m2 space 1 \ + "Metal2 must overlap GV2 via by 1 (Mosis #14.3)" metal2 + + edge4way ~(m2,fm2,rm2,m2c/m2,m3c/m2)/metal2 m2,fm2,rm2,m2c/m2,m3c/m2 1 ~(gv2)/via2 0 0 \ + "Metal2(edge) cannot touch GV2 via (Mosis #14.3)" via2 + + spacing gv1 gv2 2 touching_illegal \ + "GV1 via spacing to GV2 via < 2 (Mosis #14.4)" + + spacing gv1 m3c/m2 1 touching_illegal \ + "GV1 via spacing to Metal3 contact < 1 (Mosis #14.4)" + + spacing m3,rm3,m3c/m3,pad m3,rm3,m3c/m3,pad 3 touching_ok \ + "Metal3 spacing < 3 (Mosis #15.2)" + + spacing m3,rm3,m3c/m3,pad fm3,fapm 3 touching_illegal \ + "Metal3 spacing to fill layer (fm3) < 3 (Mosis #15.2)" + + spacing fm3 fm3 4 touching_ok \ + "Metal3 fill layer (fm3) spacing < 4 (Mosis #0)" + + edge4way m3c/m2 ~(m3c/m2)/metal2 1 m3,fm3,rm3,m3c/m3,pad ~(m3c/m2)/metal2 1 \ + "Metal3 overlap of Metal3 contact < 1 (Mosis #15.3)" metal3 + + edge4way gv2 space 2 m3,fm3,rm3,m3c/m3,pad space 2 \ + "Metal3 must overlap GV2 via by 2 (Mosis #15.3)" metal3 + + edge4way ~(m3,fm3,rm3,m3c/m3,pad)/metal3 m3,fm3,rm3,m3c/m3,pad 1 ~(gv2)/via2 0 0 \ + "Metal3(edge) cannot touch GV2 via (Mosis #15.3)" via2 + + spacing hr,phr hr,phr 4 touching_ok \ + "High-Resist spacing < 4 (Mosis #27.2)" + + spacing hr,phr,phr p2c 2 touching_illegal \ + "High-Resist spacing to Poly2 contact < 2 (Mosis #27.3)" + + spacing hr,phr,phr gc 2 touching_illegal \ + "High-Resist spacing to GC contact < 2 (Mosis #27.3)" + + edge4way hr,phr space 2 ~(ndiff,rnd,ndc/a,pdiff,rpd,pdc/a)/active 0 2 \ + "High-Resist space to Diffusion < 2 (Mosis #27.4)" active + + spacing hr,phr,phr poly2,ecap,phr 2 touching_ok \ + "High-Resist spacing to other Poly2 < 2 (Mosis #27.5)" + + edge4way hr,phr space 2 ~(poly2,ecap,phr)/contact hr,phr 2 \ + "High-Resist space to Poly2 < 2 (Mosis #27.5x)" contact + + spacing nwell phr 4 touching_illegal \ + "N-well spacing to Silicide-Block poly2R < 4 (Mosis #27.6)" + + spacing phr phr 7 touching_ok \ + "High-Resist poly2R spacing < 7 (Mosis #27.13)" + + edge4way phr space/active,hr 2 hr hr 2 \ + "High-Resist overlap of High-Resist poly2R < 2 (Mosis #27.15)" + + spacing nfi nfi 4 touching_ok \ + "N_field-implant spacing < 4 (Mosis #35.2)" + + spacing pfi pfi 4 touching_ok \ + "P_field-implant spacing < 4 (Mosis #35.2)" + + spacing nfi pfi 4 touching_illegal \ + "N_field-implant spacing to P_field-implant < 4 (Mosis #35.2)" + + spacing nwell,pdiff,rpd,pfet,pdc/a pfi 4 touching_illegal \ + "N-well,P-Diffusion spacing to P_field-implant < 4 (Mosis #2.1)" + + spacing pwell,ndiff,rnd,nfet,ndc/a nfi 4 touching_illegal \ + "P-well,N-Diffusion spacing to N_field-implant < 4 (Mosis #2.1)" + + edge4way ~(nwell)/well nwell 4 ~(nfi)/implant nwell 4 \ + "N-well overlap of N_field-implant < 4 (Mosis #21.2)" implant + + edge4way ~(pwell)/well pwell 4 ~(pfi)/implant pwell 4 \ + "P-well overlap of P_field-implant < 4 (Mosis #21.2)" implant + + spacing fa fapm 4 touching_illegal \ + "fill layer fa spacing to fill layer fapm < 4 (Mosis #0)" + + width fa 7 \ + "filla width < 7 (Mosis #0)" + + width fapm 7 \ + "fillapm width < 7 (Mosis #0)" + + width fp 7 \ + "fillp width < 7 (Mosis #0)" + + width fm1 7 \ + "fillm1 width < 7 (Mosis #0)" + + width fm2 7 \ + "fillm2 width < 7 (Mosis #0)" + + width fm3 7 \ + "fillm3 width < 7 (Mosis #0)" + + edge4way fa ~(fa)/fill 1 ~(fa)/fill (~(fa),fa)/fill 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fb ~(fb)/fill 1 ~(fb)/fill (~(fb),fb)/fill 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fapm ~(fapm)/active 1 ~(fapm)/active (~(fapm),fapm)/active 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fp ~(fp)/active 1 ~(fp)/active (~(fp),fp)/active 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fm1 ~(fm1)/metal1 1 ~(fm1)/metal1 (~(fm1),fm1)/metal1 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fm2 ~(fm2)/metal2 1 ~(fm2)/metal2 (~(fm2),fm2)/metal2 1 \ + "Contact not rectangular (Magic rule)" + + edge4way fm3 ~(fm3)/metal3 1 ~(fm3)/metal3 (~(fm3),fm3)/metal3 1 \ + "Contact not rectangular (Magic rule)" + + edge4way rp space/active 1 prp 0 0 \ + "prp overhang of rpoly (for resistor L/W extraction) < 1 (Mosis #0)" active + + edge4way rp2 space/cap 1 prp2 0 0 \ + "prp2 overhang of rpoly2 (for resistor L/W extraction) < 1 (Mosis #0)" cap + + edge4way rnw space/active 1 prnw 0 0 \ + "prnw overhang of rnwell (for resistor L/W extraction) < 1 (Mosis #0)" active + + edge4way rpd space/active 1 prpd 0 0 \ + "prpd overhang of rpdiff (for resistor L/W extraction) < 1 (Mosis #0)" active + + edge4way rnd space/active 1 prnd 0 0 \ + "prnd overhang of rndiff (for resistor L/W extraction) < 1 (Mosis #0)" active + + edge4way rm1 space/metal1 1 prm1 0 0 \ + "prm1 overhang of rmetal1 (for resistor L/W extraction) < 1 (Mosis #0)" metal1 + + edge4way rm2 space/metal2 1 prm2 0 0 \ + "prm2 overhang of rmetal2 (for resistor L/W extraction) < 1 (Mosis #0)" metal2 + + edge4way rm3 space/metal3 1 prm3 0 0 \ + "prm3 overhang of rmetal3 (for resistor L/W extraction) < 1 (Mosis #0)" metal3 + + edge4way ndc/a,nsc/a ~(ndc/a,nsc/a)/active 1 ~(ndc/a,nsc/a)/active (~(ndc/a,nsc/a),ndc/a,nsc/a)/active 1 \ + "Contact not rectangular (Magic rule)" + + edge4way pdc/a,psc/a ~(pdc/a,psc/a)/active 1 ~(pdc/a,psc/a)/active (~(pdc/a,psc/a),pdc/a,psc/a)/active 1 \ + "Contact not rectangular (Magic rule)" + + edge4way pc/a ~(pc/a)/active 1 ~(pc/a)/active (~(pc/a),pc/a)/active 1 \ + "Contact not rectangular (Magic rule)" + + edge4way gc2 ~(gc2)/contact 1 ~(gc2)/contact (~(gc2),gc2)/contact 1 \ + "Contact not rectangular (Magic rule)" + + edge4way p2c ~(p2c)/metal1 1 ~(p2c)/metal1 (~(p2c),p2c)/metal1 1 \ + "Contact not rectangular (Magic rule)" + + edge4way gc ~(gc)/contact 1 ~(gc)/contact (~(gc),gc)/contact 1 \ + "Contact not rectangular (Magic rule)" + + edge4way gv1 ~(gv1)/via1 1 ~(gv1)/via1 (~(gv1),gv1)/via1 1 \ + "Contact not rectangular (Magic rule)" + + edge4way m2c/m1 ~(m2c/m1)/metal1 1 ~(m2c/m1)/metal1 (~(m2c/m1),m2c/m1)/metal1 1 \ + "Contact not rectangular (Magic rule)" + + edge4way gv2 ~(gv2)/via2 1 ~(gv2)/via2 (~(gv2),gv2)/via2 1 \ + "Contact not rectangular (Magic rule)" + + edge4way m3c/m2 ~(m3c/m2)/metal2 1 ~(m3c/m2)/metal2 (~(m3c/m2),m3c/m2)/metal2 1 \ + "Contact not rectangular (Magic rule)" + + exact_overlap gc,ndc/a,pdc/a,psc/a,nsc/a,gc,pc/a,gc + + exact_overlap gc2,p2c + + edge4way pad ~(pad)/m3 1 ~(pad)/m3 (~(pad),pad)/m3 1 \ + "Contact not rectangular (Magic rule)" + + exact_overlap ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c + + exact_overlap m2c/m2 + + exact_overlap m3c/m3 + + exact_overlap gv1 + + exact_overlap gv2 + + + width m1p 4 \ + "Metal1 PIN width < 4 (do_pins)" + + spacing m1p m1p 4 touching_ok \ + "Metal1 PIN spacing < 4 (do_pins)" + + width m2p 4 \ + "Metal2 PIN width < 4 (do_pins)" + + spacing m2p m2p 4 touching_ok \ + "Metal2 PIN spacing < 4 (do_pins)" + + width m3p 6 \ + "Metal3 PIN width < 6 (do_pins)" + + spacing m3p m3p 4 touching_ok \ + "Metal3 PIN spacing < 4 (do_pins)" + +#CC cifstyle lambda=0.30(p) +#CC cifwidth CWN 360 \ +#CC "generated CIF layer CWN width will be < 12 (';cif see CWN')" +#CC cifspacing CWN CWN 180 touching_ok \ +#CC "generated CIF layer CWN spacing will be < 6 (';cif see CWN')" +#CC cifwidth CWP 360 \ +#CC "generated CIF layer CWP width will be < 12 (';cif see CWP')" +#CC cifspacing CWP CWP 180 touching_ok \ +#CC "generated CIF layer CWP spacing will be < 6 (';cif see CWP')" +#CC cifwidth CSN 60 \ +#CC "generated CIF layer CSN width will be < 2 (';cif see CSN')" +#CC cifspacing CSN CSN 60 touching_ok \ +#CC "generated CIF layer CSN spacing will be < 2 (';cif see CSN')" +#CC cifwidth CSP 60 \ +#CC "generated CIF layer CSP width will be < 2 (';cif see CSP')" +#CC cifspacing CSP CSP 60 touching_ok \ +#CC "generated CIF layer CSP spacing will be < 2 (';cif see CSP')" + + stepsize 400 + +end + +#--------------------------------------------------- +# LEF format definitions +#--------------------------------------------------- + +lef + +ignore PC +ignore CA + +routing m1 metal1 M1 m1 met1 +routing m2 metal2 M2 m2 met2 +routing m3 metal3 M3 m3 met3 + +contact m2c via1 via V1 v1 +contact m3c via2 V2 v2 + +end + +extract + style AMI0.5um(amic5)from:T11Z + cscale 1 + lambda 30 + step 100 + sidehalo 8 + planeorder well 0 + planeorder implant 1 + planeorder select 2 + planeorder cap 3 + planeorder active 4 + planeorder metal1 5 + planeorder metal2 6 + planeorder metal3 7 + planeorder oxide 8 + planeorder xp 9 + planeorder comment 10 + planeorder contact 11 + planeorder via1 12 + planeorder via2 13 + planeorder fill 14 + + substrate *psd,space/w,pwell well + + resist (ndiff,rnd,ndc,nsd,nsc)/active 82400 + resist (pdiff,rpd,pdc,psd,psc)/active 102700 + resist (nwell)/well 816000 + resist (rnw)/active 816000 0.5 + resist (pwell)/well 1 + resist (poly,fp,rp,pc,pc,nfet,pfet,fet)/active 22300 + resist (poly2,ecap,p2c)/cap 41300 + resist (phr)/cap 41300 0.5 + resist (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c,m2c)/metal1 90 + resist (m2,fm2,rm2,m2c,m3c,m3c)/metal2 90 + resist (m3,fm3,rm3,m3c,pad)/metal3 60 + + contact ndc 4 58700 + contact pdc 4 141000 + contact pc 4 15800 + contact p2c 4 26800 + contact m2c 4 760 + contact m3c 4 730 + + +#poly2 + overlap (poly,fp,rp,pc,pc)/active (poly2,ecap,phr,p2c)/cap 82.260 + +#nwell,cwell,pwell + areacap (nwell)/well 3.510 + +#rnw + areacap (rnw)/active 3.510 + +#ndiff +# MODEL HANDLES THIS: areacap (ndiff,ndc)/active 38.070 +# MODEL HANDLES THIS: overlap (ndiff,ndc)/active ~space/w 38.070 +# MODEL HANDLES THIS: perimc (ndiff,ndc)/active ~(ndiff,ndc,nfet,pfet,fet)/active 95.700 +# MODEL HANDLES THIS: sideoverlap (ndiff,ndc)/active ~(ndiff,ndc,nfet,pfet,fet)/active ~space/w 95.700 + + areacap (rnd)/active 38.070 + overlap (rnd)/active ~space/w 38.070 + perimc (rnd)/active ~(rnd)/active 95.700 + sideoverlap (rnd)/active ~(rnd)/active ~space/w 95.700 + +#pdiff +# MODEL HANDLES THIS: areacap (pdiff,pdc)/active 65.610 +# MODEL HANDLES THIS: overlap (pdiff,pdc)/active ~space/w 65.610 +# MODEL HANDLES THIS: perimc (pdiff,pdc)/active ~(pdiff,pdc,nfet,pfet,fet)/active 73.800 +# MODEL HANDLES THIS: sideoverlap (pdiff,pdc)/active ~(pdiff,pdc,nfet,pfet,fet)/active ~space/w 73.800 + + areacap (rpd)/active 65.610 + overlap (rpd)/active ~space/w 65.610 + perimc (rpd)/active ~(rpd)/active 73.800 + sideoverlap (rpd)/active ~(rpd)/active ~space/w 73.800 + +#rnw + +#poly +# MODEL HANDLES THIS: overlap (nfet)/active (ndiff,rnd,ndc)/active 225.450 +# MODEL HANDLES THIS: sideoverlap (nfet)/active ~(nfet)/active (ndiff,rnd,ndc)/active 65.700 +# MODEL HANDLES THIS: overlap (pfet)/active (pdiff,rpd,pdc)/active 219.060 +# MODEL HANDLES THIS: sideoverlap (pfet)/active ~(pfet)/active (pdiff,rpd,pdc)/active 69 + + areacap (poly,fp,rp,pc)/active 7.920 + overlap (poly,fp,rp,pc)/active ~space/w 7.920 + +#poly2 + +#rnw + +#metal1 + areacap (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 2.790 + +#metal1-sub blocked by ~space/a,~space/c + overlap (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 ~space/w 2.790 ~space/a,~space/c + perimc (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 22.200 + sideoverlap (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 ~space/w 22.200 ~space/a,~space/c + +#rnw + overlap (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 rnw/active 2.790 ~space/c + sideoverlap (m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,pdc,pc,p2c,m2c)/metal1 rnw/active 22.200 ~space/c + +#metal1-diff blocked by ~space/c + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (ndiff,rnd,ndc)/active 3.150 ~space/c + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (ndiff,rnd,ndc)/active 22.200 ~space/c + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (pdiff,rpd,pdc)/active 3.150 ~space/c + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (pdiff,rpd,pdc)/active 22.200 ~space/c + +#metal1-poly blocked by ~space/c + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (poly,fp,rp,pc,nfet,pfet,fet)/active 4.680 ~space/c + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (poly,fp,rp,pc,nfet,pfet,fet)/active 18 ~space/c + sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 18 ~space/c + +#metal1-poly2 not blocked + overlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (poly2,ecap,phr)/cap 4.320 + +#metal2 + areacap (m2,fm2,rm2,m3c)/metal2 1.440 + +#metal2-sub blocked by + overlap (m2,fm2,rm2,m3c)/metal2 ~space/w 1.440 ~space/a,~space/m1,~space/c + perimc (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 17.400 + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 ~space/w 17.400 ~space/a,~space/m1,~space/c + overlap (m2,fm2,rm2,m3c)/metal2 rnw/active 1.440 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 rnw/active 17.400 ~space/m1,~space/c + +#metal2-*diff blocked by ~space/m1,~space/c + overlap (m2,fm2,rm2,m3c)/metal2 (ndiff,rnd,ndc)/active 1.440 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (ndiff,rnd,ndc)/active 17.400 ~space/m1,~space/c + overlap (m2,fm2,rm2,m2c,m3c)/metal2 (pdiff,rpd,pdc)/active 1.440 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (pdiff,rpd,pdc)/active 17.400 ~space/m1,~space/c + +#metal2-poly blocked by ~space/m1,~space/c + overlap (m2,fm2,rm2,m3c)/metal2 (poly,fp,rp,pc,nfet,pfet,fet)/active 1.350 ~space/m1,~space/c + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (poly,fp,rp,pc,nfet,pfet,fet)/active 11.400 ~space/m1,~space/c + sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m2,fm2,rm2,m2c,m3c)/metal2 11.400 ~space/m1,~space/c + +#metal2-poly2 blocked by ~space/m1 + +#M2->M1 + overlap (m2,fm2,rm2,m3c)/metal2 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 2.700 + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 15 + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (m2,fm2,rm2,m2c,m3c)/metal2 15 + +#metal3 + areacap (m3,fm3,rm3,pad)/metal3 0.900 + +#metal3-sub blocked by ~space/a,~space/m1,~space/m2,~space/c + overlap (m3,fm3,rm3,pad)/metal3 ~space/w 0.900 ~space/a,~space/m1,~space/m2,~space/c + perimc (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 11.400 + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 ~space/w 11.400 ~space/a,~space/m1,~space/m2,~space/c + +#rnw + overlap (m3,fm3,rm3,pad)/metal3 rnw/active 0.900 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 rnw/active 11.400 ~space/m1,~space/m2,~space/c + +#metal3-*diff blocked by ~space/m1,~space/m2,~space/c + overlap (m3,fm3,rm3,pad)/metal3 (ndiff,rnd,ndc)/active 0.990 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (ndiff,rnd,ndc)/active 11.400 ~space/m1,~space/m2,~space/c + overlap (m3,fm3,rm3,pad)/metal3 (pdiff,rpd,pdc)/active 0.990 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (pdiff,rpd,pdc)/active 11.400 ~space/m1,~space/m2,~space/c + +#metal3-poly blocked by ~space/m1,~space/m2,~space/c + overlap (m3,fm3,rm3,pad)/metal3 (poly,fp,rp,pc,nfet,pfet,fet)/active 0.810 ~space/m1,~space/m2,~space/c + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (poly,fp,rp,pc,nfet,pfet,fet)/active 8.400 ~space/m1,~space/m2,~space/c + sideoverlap (poly,fp,rp,pc,nfet,pfet,fet)/active ~(poly,fp,rp,pc,nfet,pfet,fet)/active (m3,fm3,rm3,m3c,pad)/metal3 8.400 ~space/m1,~space/m2,~space/c + +#metal3-poly2 blocked by ~space/m1,~space/m2 + +#M3->M1 + overlap (m3,fm3,rm3,pad)/metal3 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 1.080 ~space/m2 + +#metal3-metal1 blocked by ~space/m2 + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 9.600 ~space/m2 + sideoverlap (m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 ~(m1,fm1,rm1,ndc,nsc,pdc,psc,pc,p2c,m2c)/metal1 (m3,fm3,rm3,m3c,pad)/metal3 9.600 ~space/m2 + +#M3->M2 + overlap (m3,fm3,rm3,pad)/metal3 (m2,fm2,rm2,m2c,m3c)/metal2 2.880 + sideoverlap (m3,fm3,rm3,m3c,pad)/metal3 ~(m3,fm3,rm3,m3c,pad)/metal3 (m2,fm2,rm2,m2c,m3c)/metal2 15.600 + sideoverlap (m2,fm2,rm2,m2c,m3c)/metal2 ~(m2,fm2,rm2,m2c,m3c)/metal2 (m3,fm3,rm3,m3c,pad)/metal3 15.600 + +#metal4 + +#metal5 + +#metal6 + +#metal7 + +#metali + +#devices + + device mosfet pfet pfet pdiff,pdc nwell ERROR 69 219 + device mosfet nfet nfet ndiff,ndc pwell,space/w ERROR 66 225 + + fetresis pfet linear 21001 + fetresis pfet saturation 21001 + fetresis nfet linear 6020 + fetresis nfet saturation 6020 + + device resistor nwellResistor rnwell *nsd + device resistor polyResistor rpoly *poly + device resistor poly2Resistor rpoly2 *poly2 + device resistor ndiffResistor rndiff *ndiff + device resistor pdiffResistor rpdiff *pdiff + + device resistor metal1Resistor rmetal1 *metal1 + device resistor metal2Resistor rmetal2 *metal2 + device resistor metal3Resistor rmetal3 *metal3 + + device resistor presResistor phr *poly2 + + +end + +wiring + contact pdcontact 4 metal1 0 pdiff 0 + contact ndcontact 4 metal1 0 ndiff 0 + contact pcontact 4 metal1 0 poly 0 + contact m2contact 4 metal1 0 metal2 0 + contact m3contact 5 metal2 0 metal3 1 + +end + +router + layer2 metal2 3 m2,fm2,rm2,m2c/m2,m3c/m2,m3c/m2 4 poly,fp,rp,ndiff,rnd,nsd,pdiff,rpd,psd,m1,fm1,rm1 1 + layer1 metal1 3 m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 3 + contacts m2contact 4 + gridspacing 8 + +end + +plowing + fixed nfet,pfet,glass,pad + covered nfet,pfet + drag nfet,pfet + +end + +plot +style colorversatec + ndiff,rnd,ndc/a yellow \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA + ndiff,rnd,ndc/a cyan \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 + nsd,nsc/a yellow \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 + nsd,nsc/a cyan \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 + pdiff,rpd,pdc/a yellow \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA + pdiff,rpd,pdc/a cyan \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 \ + 0000 5555 0000 5555 + pdiff,rpd,pdc/a magenta \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 + psd,psc/a yellow \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 \ + 1515 2A2A 5151 A2A2 + psd,psc/a cyan \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 \ + 0000 1515 0000 5151 + psd,psc/a magenta \ + 2A2A 0000 A2A2 0000 \ + 2A2A 0000 A2A2 0000 \ + 2A2A 0000 A2A2 0000 \ + 2A2A 0000 A2A2 0000 + poly,fp,rp,pc/a magenta \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA \ + 5555 AAAA 5555 AAAA + nfet yellow \ + 0505 8282 1414 0A0A \ + 5050 2828 4141 A0A0 \ + 0505 8282 1414 0A0A \ + 5050 2828 4141 A0A0 + nfet cyan \ + 0000 0505 0000 1414 \ + 0000 5050 0000 4141 \ + 0000 0505 0000 1414 \ + 0000 5050 0000 4141 + nfet magenta \ + 5050 2828 4141 A0A0 \ + 0505 8282 1414 0A0A \ + 5050 2828 4141 A0A0 \ + 0505 8282 1414 0A0A + pfet yellow \ + 6363 A0A0 5050 2828 \ + 3636 0A0A 0505 8282 \ + 6363 A0A0 5050 2828 \ + 3636 0A0A 0505 8282 + pfet cyan \ + 0000 5151 0000 5454 \ + 0000 1515 0000 1515 \ + 0000 5151 0000 5454 \ + 0000 1515 0000 1515 + pfet magenta \ + 9494 0A0A 2525 8282 \ + 4949 A0A0 5252 2828 \ + 9494 0A0A 2525 8282 \ + 4949 A0A0 5252 2828 + poly2,ecap,phr yellow \ + FFFF FFFF FFFF FFFF \ + FFFF FFFF FFFF FFFF \ + FFFF FFFF FFFF FFFF \ + FFFF FFFF FFFF FFFF + m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 cyan \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 \ + AAAA 0000 AAAA 0000 + m2,fm2,rm2,m2c/m2,m3c/m2 cyan \ + 0000 1111 0000 4444 \ + 0000 1111 0000 4444 \ + 0000 1111 0000 4444 \ + 0000 1111 0000 4444 + m2,fm2,rm2,m2c/m2,m3c/m2 magenta \ + 0000 4444 0000 1111 \ + 0000 4444 0000 1111 \ + 0000 4444 0000 1111 \ + 0000 4444 0000 1111 + m2c/m1,gv1 black \ + 0000 6666 6666 0000 \ + 0000 9999 9999 0000 \ + 0000 6666 6666 0000 \ + 0000 9999 9999 0000 + pad,glass black \ + 0300 0700 0E00 1C00 \ + 3800 7000 E000 C000 \ + 00C0 00E0 0070 0038 \ + 001C 000E 0007 0003 + nwell yellow \ + 0800 1000 2000 4000 \ + 8000 0001 0002 0004 \ + 0008 0010 0020 0040 \ + 0080 0010 0200 0400 + nwell cyan \ + 1000 2000 4000 8000 \ + 0001 0002 0004 0008 \ + 0010 0020 0040 0080 \ + 0100 0200 0400 0800 + pwell yellow \ + 1000 0400 0400 0100 \ + 0100 0040 0040 0010 \ + 0010 0004 0004 0001 \ + 0001 4000 4000 1000 + pwell cyan \ + 0000 0800 0000 0200 \ + 0000 0080 0000 0020 \ + 0000 0008 0000 0002 \ + 0000 8000 0000 2000 + pwell magenta \ + 0800 0000 0200 0000 \ + 0080 0000 0020 0000 \ + 0008 0000 0002 0000 \ + 8000 0000 2000 0000 + m3c/m2,gv2 black \ + 0100 0000 0000 0000 \ + 1010 0000 0000 0000 \ + 0001 0000 0000 0000 \ + 1010 0000 0000 0000 + m3c/m2,gv2 cyan \ + 0280 0000 0820 0000 \ + 2008 0000 8002 0000 \ + 8002 0000 2008 0000 \ + 0820 0000 0280 0000 + m3c/m2,gv2 magenta \ + 0100 06C0 0440 1830 \ + 1010 600C 4004 8003 \ + 0001 C006 4004 3018 \ + 1010 0C60 0440 0380 + m3c/m2,gv2 black \ + 0820 0820 0820 0FE0 \ + E00F 2008 2008 2008 \ + 2008 2008 2008 E00F \ + 0000 0FE0 0820 0820 + error_p,error_s,error_ps black \ + 0000 3C3C 4646 4A4A \ + 5252 6262 3C3C 0000 \ + 0000 3C3C 4646 4A4A \ + 5252 6262 3C3C 0000 + magnet yellow \ + AAAA 0000 5555 0000 \ + AAAA 0000 5555 0000 \ + AAAA 0000 5555 0000 \ + AAAA 0000 5555 0000 + fence magenta \ + FFFF 0000 0000 0000 \ + 0000 0000 0000 0000 \ + FFFF 0000 0000 0000 \ + 0000 0000 0000 0000 + rotate cyan \ + 0000 E0E0 E0E0 E0E0 \ + 0000 0000 0000 0000 \ + 0000 E0E0 E0E0 E0E0 \ + 0000 0000 0000 0000 + pc/a,ndc/a,pdc/a,psc/a,nsc/a,gc,gc,gc X + +style versatec + pfet \ + 07c0 0f80 1f00 3e00 \ + 7c00 f800 f001 e003 \ + c007 800f 001f 003e \ + 00c7 00f8 01f0 03e0 + nfet \ + 1f00 0f80 07c0 03e0 \ + 01f0 00f8 007c 003e \ + 001f 800f c007 e003 \ + f001 f800 7c00 3e00 + gv1 \ + c3c3 c3c3 0000 0000 \ + 0000 0000 c3c3 c3c3 \ + c3c3 c3c3 0000 0000 \ + 0000 0000 c3c3 c3c3 + pwell \ + 2020 2020 2020 2020 \ + 2020 2020 2020 2020 \ + 0000 0000 0000 0000 \ + 0000 0000 0000 0000 + nwell \ + 0808 0404 0202 0101 \ + 0000 0000 0000 0000 \ + 0808 0404 0202 0101 \ + 0000 0000 0000 0000 + poly,fp,rp,pc/a,nfet,pfet \ + 0808 0400 0202 0101 \ + 8080 4000 2020 1010 \ + 0808 0004 0202 0101 \ + 8080 0040 2020 1010 + m1,fm1,rm1,ndc/m1,nsc/m1,pdc/m1,psc/m1,pc/m1,p2c,m2c/m1 \ + 8080 0000 0000 0000 \ + 0808 0000 0000 0000 \ + 8080 0000 0000 0000 \ + 0808 0000 0000 0000 + pad,glass \ + 0000 0000 1c1c 3e3e \ + 3636 3e3e 1c1c 0000 \ + 0000 0000 1c1c 3e3e \ + 3636 3e3e 1c1c 0000 + nsd,nsc/a \ + 0808 1414 2222 4141 \ + 8080 4040 2020 1010 \ + 0808 1414 2222 4141 \ + 8080 4040 2020 1010 + m2,fm2,rm2,m2c/m2,m3c/m2 \ + 0000 1111 0000 0000 \ + 0000 1111 0000 0000 \ + 0000 1111 0000 0000 \ + 0000 1111 0000 0000 + pdiff,rpd,pdc/a,pfet \ + 0000 0808 5555 8080 \ + 0000 8080 5555 0808 \ + 0000 0808 5555 8080 \ + 0000 8080 5555 0808 + psd,psc/a \ + 1414 2222 0000 2222 \ + 4141 2222 0000 2222 \ + 1414 2222 0000 2222 \ + 4141 2222 0000 2222 + ndiff,rnd,ndc/a,nfet \ + 0808 1010 2020 4040 \ + 8080 4141 2222 1414 \ + 0808 1010 2020 4040 \ + 8080 4141 2222 1414 + pc/a,ndc/a,pdc/a,psc/a,nsc/a,gc,gc,gc X + +style gremlin + pfet 9 + nfet 10 + gv1 11 + pwell 15 + nwell 16 + poly,fp,rp,pc/a,nfet,pfet 19 + pc/a,ndc/a,pdc/a,psc/a,nsc/a,gc,gc,gc 22 + pad,glass 23 + nsd,nsc/a 24 + gv1 28 + pdiff,rpd,pdc/a,pfet 29 + psd,psc/a 30 + ndiff,rnd,ndc/a,nfet 31 + pc/a,ndc/a,pdc/a,psc/a,nsc/a,gc,gc,gc,gv1 X + +end + diff --git a/technology/scn3me_subm/tech/__init__.py b/technology/scn3me_subm/tech/__init__.py new file mode 100755 index 00000000..2573d2c2 --- /dev/null +++ b/technology/scn3me_subm/tech/__init__.py @@ -0,0 +1,6 @@ +""" +Import tech specific modules. +""" + +from .tech import * + diff --git a/technology/scn3me_subm/tech/calibreDRC_scn3me_subm.rul b/technology/scn3me_subm/tech/calibreDRC_scn3me_subm.rul new file mode 100755 index 00000000..91d35fb4 --- /dev/null +++ b/technology/scn3me_subm/tech/calibreDRC_scn3me_subm.rul @@ -0,0 +1,225 @@ +//////////////////////////////////////////////////////////// +// DEFINE BOOLEAN LAYERS +//////////////////////////////////////////////////////////// +LAYOUT USE DATABASE PRECISION YES + +layer pwell 41 +layer nwell 42 +layer active 43 +layer poly 46 +layer nimplant 45 +layer pimplant 44 +layer contact 25 +layer active_contact 48 +layer poly_contact 47 +layer metal1 49 +layer via1 50 +layer metal2 51 +layer via2 61 +layer metal3 62 +layer glass 52 +layer pad 26 + +//Enabling incremental connectivity for antenna rule checks +DRC Incremental Connect Yes + +well = nwell OR pwell +gate = poly AND active +implant = nimplant OR pimplant +fieldpoly = poly NOT active + +contactenc1 = active OR poly +contactenc = contactenc1 AND metal1 +diode = contact AND active +act_poly = interact poly active + +GROUP mask_check +//Well.2 Well.4 +Poly.1 Poly.2 Poly.3 Poly.4 Poly.5 +Active.1 Active.2 // Active.3 +Contact.1 Contact.2 Contact.3 Contact.4 +Contact.5 Contact.6 Metal1.1 Metal1.2 Metal1.3 + + + +//Well.1 { +//@Nwell and Pwell must not overlap +//AND nwell pwell +//} + +//Well.2 { +//@Min spacing of pwell to nwell = 0.00 +//EXTERNAL nwell pwell < 0.00 +//} + +//Well.4 { +//@Min width of nwell = 3.6 +//INTERNAL nwell < 3.6 +//} + +Poly.1 { +@Min width of poly = 0.6 +INTERNAL poly < 0.6 +} + +Poly.2 { +@Min spacing of gate poly = 0.9 +EXTERNAL gate < 0.9 +} + +Poly.3 { +@Min extension of poly past active = 0.6 +ENCLOSURE active poly < 0.6 +} + +Poly.4 { +@Minimum active enclosure of gate =0.6 +ENCLOSURE poly active < 0.6 +} + +Poly.5 { +@Minimum spacing of poly to active = 0.3 +EXTERNAL act_poly active < 0.3 +} + +Active.1 { +@Minimum width of active = 0.9 +INTERNAL active < 0.9 +} + +Active.2 { +@Minimum spacing of active areas = 0.9 +EXTERNAL active < 0.9 +} + +//Active.3 { +//@Minimum well enclosure of active = 1.8 +//ENCLOSURE active well < 1.8 +//} + +Contact.1 { +@Minimum width of contact = 0.6 +INTERNAL contact < 0.6 +} + +Contact.2 { +@Minimum spacing of contact = 0.9 +EXTERNAL contact < 0.9 +} + +Contact.3 { +@Contact must be inside metal1 and active or poly +NOT contact contactenc +} + +Contact.4 { +@Minimum active enclosure of contact = 0.3 +ENCLOSURE contact active < 0.3 +} + +Contact.5 { +@Minimum poly enclosure of contact = 0.3 +ENCLOSURE contact poly < 0.3 +} + +Contact.6 { +@Minimum spacing of contact to poly = 0.6 +EXTERNAL poly contact < 0.6 +} + +Metal1.1 { +@Minimum width of metal1 = 0.9 +INTERNAL metal1 < 0.9 +} + +Metal1.2 { +@Minimum spacing of metal1 = 0.9 +EXTERNAL metal1 < 0.9 +} + +Metal1.3 { +@Metal1 must extend past contact by 0.3 on two opposite sides +RECTANGLE ENCLOSURE contact metal1 +GOOD 0.00 0.3 OPPOSITE 0.00 0.3 OPPOSITE +} + +Metal1.4 { +@Metal1 must extend past via1 by 0.3 on two opposite sides +RECTANGLE ENCLOSURE via1 metal1 +GOOD 0.00 0.3 OPPOSITE 0.00 0.3 OPPOSITE +} + +Via1.1 { +@Minimum width of via1 = 0.6 +INTERNAL via1 < 0.6 +} + +Via1.2 { +@Minimum spacing of via1 = 0.6 +EXTERNAL via1 < 0.6 +} + +Via1.3 { +@Via1 must be inside metal1 +NOT via1 metal1 +} + + +Metal2.1 { +@Minimum width of metal2 = 0.9 +INTERNAL metal2 < 0.9 +} + +Metal2.2 { +@Minimum spacing of metal2 = 0.9 +EXTERNAL metal2 < 0.9 +} + +Metal2.3 { +@Metal2 must extend past via1 by 0.3 on two opposite sides +RECTANGLE ENCLOSURE via1 metal2 +GOOD 0.00 0.3 OPPOSITE 0.00 0.3 OPPOSITE +} + +Metal2.4 { +@Metal2 must extend past via2 by 0.3 on two opposite sides +RECTANGLE ENCLOSURE via2 metal2 +GOOD 0.00 0.3 OPPOSITE 0.00 0.3 OPPOSITE +} + +Via2.1 { +@Minimum width of via2 = 0.6 +INTERNAL via2 < 0.6 +} + +Via2.2 { +@Minimum spacing of via2 = 0.9 +EXTERNAL via2 < 0.9 +} + +Via2.3 { +@Via2 must be inside metal2 +NOT via2 metal2 +} + +Via2.4 { +@Via2 must be inside metal3 +NOT via2 metal3 +} + +Metal3.1 { +@Minimum width of metal3 = 1.5 +INTERNAL metal3 < 1.5 +} + +Metal3.2 { +@Minimum spacing of metal3 = 0.9 +EXTERNAL metal3 < 0.9 +} + +Metal3.3 { +@Metal3 must extend past via2 by 0.6 on two opposite sides +RECTANGLE ENCLOSURE via2 metal3 +GOOD 0.00 0.6 OPPOSITE 0.00 0.6 OPPOSITE +} + diff --git a/technology/scn3me_subm/tech/calibreLVS_scn3me_subm.rul b/technology/scn3me_subm/tech/calibreLVS_scn3me_subm.rul new file mode 100755 index 00000000..5d3516a6 --- /dev/null +++ b/technology/scn3me_subm/tech/calibreLVS_scn3me_subm.rul @@ -0,0 +1,123 @@ +TITLE "LVS Rule File for scn3me_subm" + +LVS POWER NAME vdd +LVS GROUND NAME gnd GROUND +LVS REDUCE PARALLEL MOS yes +LVS REDUCE SERIES MOS yes +LVS REDUCE SEMI SERIES MOS yes +LVS FILTER UNUSED MOS no +LVS RECOGNIZE GATES all +LVS COMPONENT TYPE PROPERTY element +LVS COMPONENT SUBTYPE PROPERTY model +LVS IGNORE PORTS no + +LVS REPORT mask.lvs.rep +LVS REPORT OPTION N +LVS REPORT MAXIMUM 50 +MASK RESULTS DATABASE maskdb + +precision 1000 +resolution 250 + +TEXT LAYER metal1 metal2 metal3 +PORT LAYER TEXT metal1 metal2 metal3 + + +layer pwell 41 +layer nwell 42 +layer active 43 +layer poly 46 +layer nimplant 45 +layer pimplant 44 +layer contact 25 +layer active_contact 48 +layer poly_contact 47 +layer metal1 49 +layer via1 50 +layer metal2 51 +layer via2 61 +layer metal3 62 +layer glass 52 +layer pad 26 + +connect metal1 metal2 by via1 +connect metal2 metal3 by via2 + +pdif = active and pimplant // P-diffusion +ndif = active and nimplant // N-diffusion + +ngate = poly and ndif // N-Transistor +pgate = poly and pdif // P-transistor + +nsrcdrn = ndif not ngate // N-tansistor Source and Drain contacts diffusion region +psrcdrn = pdif not pgate // P-tansistor Source and Drain contacts diffusion region + +pcont = psrcdrn and pwell + +ntapcont = active not interact pimplant +ptapcont = active not interact nimplant + +bulk = extent +nsub = (bulk not pwell) and nwell +ncont = nsrcdrn and nsub + +connect metal1 poly psrcdrn nsrcdrn by contact mask +connect psrcdrn pwell by pcont mask +connect nsrcdrn nsub by ncont mask + +ncont1= ntapcont and nsub +pcont1= ptapcont and pwell +connect metal1 ncont1 by contact mask +connect metal1 pcont1 by contact mask +connect ncont1 nsub +connect pcont1 pwell + +connect psrcdrn metal1 by contact +connect nsrcdrn metal1 by contact + +connect psrcdrn metal1 by active_contact +connect nsrcdrn metal1 by active_contact + +connect poly metal1 by contact + +connect poly metal1 by poly_contact + +device mp (p) pgate poly (G) psrcdrn (S) psrcdrn (D) nsub CMACRO FET_PROPERTIES pgate nsub +device mn (n) ngate poly (G) nsrcdrn (S) nsrcdrn (D) pwell CMACRO FET_PROPERTIES ngate pwell + +VARIABLE trace_delta 4e-9 + +DMACRO FET_TRACE device_type device_name { +TRACE PROPERTY device_type(device_name) l l trace_delta ABSOLUTE +TRACE PROPERTY device_type(device_name) w w trace_delta ABSOLUTE + +} + +CMACRO FET_TRACE MN n +CMACRO FET_TRACE MP p + +DMACRO FET_PROPERTIES seed well{ +[ +PROPERTY W, L, AS, AD, PS, PD + + AS = area(S) + AD = area(D) + PS = perimeter(S) + PD = perimeter(D) + if ( AS == 0 ) { + AD = area(D) / 2 + AS = AD + PD = perimeter(D) / 2 + PS = PD + } + if ( AD == 0 ) { + AS = area(S) / 2 + AD = AS + PS = perimeter(S) / 2 + PD = PS + } + W = (perim_co(seed,S) + perim_co(seed,D) ) * 0.5 + L = (perim(seed) - perim_co(seed,S) - perim_in(seed,S) - perim_co(seed,D) - perim_in(seed,D) ) * 0.5 + +] +} diff --git a/technology/scn3me_subm/tech/tech.py b/technology/scn3me_subm/tech/tech.py new file mode 100755 index 00000000..fb7524c1 --- /dev/null +++ b/technology/scn3me_subm/tech/tech.py @@ -0,0 +1,311 @@ +import os +from design_rules import * + +""" +File containing the process technology parameters for SCMOS 3me, subm, 180nm. +""" + +#GDS file info +GDS={} +# gds units +# gds units +# From http://www.cnf.cornell.edu/cnf_spie9.html: "The first +#is the size of a database unit in user units. The second is the size +#of a database unit in meters. For example, if your library was +#created with the default units (user unit = 1 m and 1000 database +#units per user unit), then the first number would be 0.001 and the +#second number would be 10-9. Typically, the first number is less than +#1, since you use more than 1 database unit per user unit. To +#calculate the size of a user unit in meters, divide the second number +#by the first." +GDS["unit"]=(0.001,1e-6) +# default label zoom +GDS["zoom"] = 0.5 + + +################################################### +##GDS Layer Map +################################################### + +# create the GDS layer map +layer={} +layer["vtg"] = -1 +layer["vth"] = -1 +layer["contact"] = 47 +layer["pwell"] = 41 +layer["nwell"] = 42 +layer["active"] = 43 +layer["pimplant"] = 44 +layer["nimplant"] = 45 +layer["poly"] = 46 +layer["active_contact"] = 48 +layer["metal1"] = 49 +layer["via1"] = 50 +layer["metal2"] = 51 +layer["via2"] = 61 +layer["metal3"] = 62 +layer["text"] = 63 +layer["boundary"] = 63 +layer["blockage"] = 83 + +################################################### +##END GDS Layer Map +################################################### + +################################################### +##DRC/LVS Rules Setup +################################################### +_lambda_ = 0.3 + +#technology parameter +parameter={} +parameter["min_tx_size"] = 4*_lambda_ +parameter["beta"] = 2 + +parameter["6T_inv_nmos_size"] = 8*_lambda_ +parameter["6T_inv_pmos_size"] = 3*_lambda_ +parameter["6T_access_size"] = 4*_lambda_ + +drclvs_home=os.environ.get("DRCLVS_HOME") + +drc = design_rules("scn3me_subm") + +drc["body_tie_down"] = 0 +drc["has_pwell"] = True +drc["has_nwell"] = True + + +#grid size is 1/2 a lambda +drc["grid"]=0.5*_lambda_ +#DRC/LVS test set_up +drc["drc_rules"]=drclvs_home+"/calibreDRC_scn3me_subm.rul" +drc["lvs_rules"]=drclvs_home+"/calibreLVS_scn3me_subm.rul" +drc["layer_map"]=os.environ.get("OPENRAM_TECH")+"/scn3me_subm/layers.map" + + +# minwidth_tx with contact (no dog bone transistors) +drc["minwidth_tx"] = 4*_lambda_ +drc["minlength_channel"] = 2*_lambda_ + +# 1.3 Minimum spacing between wells of same type (if both are drawn) +drc["well_to_well"] = 6*_lambda_ +# 1.4 Minimum spacing between wells of different type (if both are drawn) +drc["pwell_to_nwell"] = 0 +# 1.1 Minimum width +drc["minwidth_well"] = 12*_lambda_ + +# 3.1 Minimum width +drc["minwidth_poly"] = 2*_lambda_ +# 3.2 Minimum spacing over active +drc["poly_to_poly"] = 3*_lambda_ +# 3.3 Minimum gate extension of active +drc["poly_extend_active"] = 2*_lambda_ +# 5.5.b Minimum spacing between poly contact and other poly (alternative rules) +drc["poly_to_polycontact"] = 4*_lambda_ +# ?? +drc["active_enclosure_gate"] = 0.0 +# 3.5 Minimum field poly to active +drc["poly_to_active"] = _lambda_ +# 3.2.a Minimum spacing over field poly +drc["poly_to_field_poly"] = 3*_lambda_ +# Not a rule +drc["minarea_poly"] = 0.0 + +# ?? +drc["active_to_body_active"] = 4*_lambda_ # Fix me +# 2.1 Minimum width +drc["minwidth_active"] = 3*_lambda_ +# 2.2 Minimum spacing +drc["active_to_active"] = 3*_lambda_ +# 2.3 Source/drain active to well edge +drc["well_enclosure_active"] = 6*_lambda_ +# Reserved for asymmetric enclosures +drc["well_extend_active"] = 6*_lambda_ +# Not a rule +drc["minarea_active"] = 0.0 + +# 4.1 Minimum select spacing to channel of transistor to ensure adequate source/drain width +drc["implant_to_channel"] = 3*_lambda_ +# 4.2 Minimum select overlap of active +drc["implant_enclosure_active"] = 2*_lambda_ +# 4.3 Minimum select overlap of contact +drc["implant_enclosure_contact"] = _lambda_ +# Not a rule +drc["implant_to_contact"] = 0 +# Not a rule +drc["implant_to_implant"] = 0 +# Not a rule +drc["minwidth_implant"] = 0 + +# 6.1 Exact contact size +drc["minwidth_contact"] = 2*_lambda_ +# 5.3 Minimum contact spacing +drc["contact_to_contact"] = 3*_lambda_ +# 6.2.b Minimum active overlap +drc["active_enclosure_contact"] = _lambda_ +# Reserved for asymmetric enclosure +drc["active_extend_contact"] = _lambda_ +# 5.2.b Minimum poly overlap +drc["poly_enclosure_contact"] = _lambda_ +# Reserved for asymmetric enclosures +drc["poly_extend_contact"] = _lambda_ +# Reserved for other technologies +drc["contact_to_gate"] = 2*_lambda_ +# 5.4 Minimum spacing to gate of transistor +drc["contact_to_poly"] = 2*_lambda_ + +# 7.1 Minimum width +drc["minwidth_metal1"] = 3*_lambda_ +# 7.2 Minimum spacing +drc["metal1_to_metal1"] = 3*_lambda_ +# 7.3 Minimum overlap of any contact +drc["metal1_enclosure_contact"] = _lambda_ +# Reserved for asymmetric enclosure +drc["metal1_extend_contact"] = _lambda_ +# 8.3 Minimum overlap by metal1 +drc["metal1_enclosure_via1"] = _lambda_ +# Reserve for asymmetric enclosures +drc["metal1_extend_via1"] = _lambda_ +# Not a rule +drc["minarea_metal1"] = 0 + +# 8.1 Exact size +drc["minwidth_via1"] = 2*_lambda_ +# 8.2 Minimum via1 spacing +drc["via1_to_via1"] = 3*_lambda_ + +# 9.1 Minimum width +drc["minwidth_metal2"] = 3*_lambda_ +# 9.2 Minimum spacing +drc["metal2_to_metal2"] = 3*_lambda_ +# 9.3 Minimum overlap of via1 +drc["metal2_extend_via1"] = _lambda_ +# Reserved for asymmetric enclosures +drc["metal2_enclosure_via1"] = _lambda_ +# 14.3 Minimum overlap by metal2 +drc["metal2_extend_via2"] = _lambda_ +# Reserved for asymmetric enclosures +drc["metal2_enclosure_via2"] = _lambda_ +# Not a rule +drc["minarea_metal2"] = 0 + +# 14.1 Exact size +drc["minwidth_via2"] = 2*_lambda_ +# 14.2 Minimum spacing +drc["via2_to_via2"] = 3*_lambda_ + +# 15.1 Minimum width +drc["minwidth_metal3"] = 5*_lambda_ +# 15.2 Minimum spacing to metal3 +drc["metal3_to_metal3"] = 3*_lambda_ +# 15.3 Minimum overlap of via 2 +drc["metal3_extend_via2"] = 2*_lambda_ +# Reserved for asymmetric enclosures +drc["metal3_enclosure_via2"] = 2*_lambda_ +# Not a rule +drc["minarea_metal3"] = 0 + +################################################### +##END DRC/LVS Rules +################################################### + +################################################### +##Spice Simulation Parameters +################################################### + +# spice model info +spice={} +spice["nmos"]="n" +spice["pmos"]="p" +# This is a map of corners to model files +SPICE_MODEL_DIR=os.environ.get("SPICE_MODEL_DIR") +# FIXME: Uncomment when we have the new spice models +#spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"] } +spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"], + "FF" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"], + "FS" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"], + "SF" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"], + "SS" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"], + "ST" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"], + "TS" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"], + "FT" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"], + "TF" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"], + } + + +#spice stimulus related variables +spice["feasible_period"] = 10 # estimated feasible period in ns +spice["supply_voltages"] = [4.5, 5.0, 5.5] # Supply voltage corners in [Volts] +spice["nom_supply_voltage"] = 5.0 # Nominal supply voltage in [Volts] +spice["rise_time"] = 0.05 # rise time in [Nano-seconds] +spice["fall_time"] = 0.05 # fall time in [Nano-seconds] +spice["temperatures"] = [0, 25, 100] # Temperature corners (celcius) +spice["nom_temperature"] = 25 # Nominal temperature (celcius) + +#sram signal names +#FIXME: We don't use these everywhere... +spice["vdd_name"] = "vdd" +spice["gnd_name"] = "gnd" +spice["control_signals"] = ["CSB", "WEB"] +spice["data_name"] = "DATA" +spice["addr_name"] = "ADDR" +spice["minwidth_tx"] = drc["minwidth_tx"] +spice["channel"] = drc["minlength_channel"] +spice["clk"] = "clk" + +# analytical delay parameters +# FIXME: These need to be updated for SCMOS, they are copied from FreePDK45. +spice["vdd_nominal"] = 5.0 # Typical Threshold voltage in Volts +spice["temp_nominal"] = 25.0 # Typical Threshold voltage in Volts +spice["v_threshold_typical"] = 1.3 # Typical Threshold voltage in Volts +spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square +spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2 +spice["min_tx_r"] = 9250.0 # Minimum transistor on resistance in ohms +spice["min_tx_drain_c"] = 0.7 # Minimum transistor drain capacitance in ff +spice["min_tx_gate_c"] = 0.1 # Minimum transistor gate capacitance in ff +spice["msflop_setup"] = 9 # DFF setup time in ps +spice["msflop_hold"] = 1 # DFF hold time in ps +spice["msflop_delay"] = 20.5 # DFF Clk-to-q delay in ps +spice["msflop_slew"] = 13.1 # DFF output slew in ps w/ no load +spice["msflop_in_cap"] = 9.8242 # Input capacitance of ms_flop (Din) [Femto-farad] +spice["dff_setup"] = 9 # DFF setup time in ps +spice["dff_hold"] = 1 # DFF hold time in ps +spice["dff_delay"] = 20.5 # DFF Clk-to-q delay in ps +spice["dff_slew"] = 13.1 # DFF output slew in ps w/ no load +spice["dff_in_cap"] = 9.8242 # Input capacitance of ms_flop (Din) [Femto-farad] + +# analytical power parameters, many values are temporary +spice["bitcell_leakage"] = 1 # Leakage power of a single bitcell in nW +spice["inv_leakage"] = 1 # Leakage power of inverter in nW +spice["nand2_leakage"] = 1 # Leakage power of 2-input nand in nW +spice["nand3_leakage"] = 1 # Leakage power of 3-input nand in nW +spice["nor2_leakage"] = 1 # Leakage power of 2-input nor in nW +spice["msflop_leakage"] = 1 # Leakage power of flop in nW +spice["flop_para_cap"] = 2 # Parasitic Output capacitance in fF + +spice["default_event_rate"] = 100 # Default event activity of every gate. MHz +spice["flop_transition_prob"] = .5 # Transition probability of inverter. +spice["inv_transition_prob"] = .5 # Transition probability of inverter. +spice["nand2_transition_prob"] = .1875 # Transition probability of 2-input nand. +spice["nand3_transition_prob"] = .1094 # Transition probability of 3-input nand. +spice["nor2_transition_prob"] = .1875 # Transition probability of 2-input nor. + +#Logical Effort relative values for the Handmade cells +parameter['le_tau'] = 23 #In pico-seconds. +parameter["min_inv_para_delay"] = .73 #In relative delay units +parameter['cap_relative_per_ff'] = .91 #Units of Relative Capacitance/ Femto-Farad +parameter["static_delay_stages"] = 4 +parameter["static_fanout_per_stage"] = 3 +parameter["static_fanout_list"] = parameter["static_delay_stages"]*[parameter["static_fanout_per_stage"]] +parameter["dff_clk_cin"] = 27.5 #In relative capacitance units +parameter["6tcell_wl_cin"] = 2 #In relative capacitance units +parameter["sa_en_pmos_size"] = 24*_lambda_ +parameter["sa_en_nmos_size"] = 9*_lambda_ +parameter["sa_inv_pmos_size"] = 18*_lambda_ +parameter["sa_inv_nmos_size"] = 9*_lambda_ +parameter["rbl_height_percentage"] = .5 #Height of RBL compared to bitcell array +parameter['bitcell_drain_cap'] = 0.2 #In Femto-Farad, approximation of drain capacitance + +################################################### +##END Spice Simulation Parameters +################################################### diff --git a/technology/scn3me_subm/tf/README b/technology/scn3me_subm/tf/README new file mode 100644 index 00000000..400cfe98 --- /dev/null +++ b/technology/scn3me_subm/tf/README @@ -0,0 +1,19 @@ +;; NCSU CDK v. 1.6.0.beta +;; Last Modified: 2007-07-12 + +The NCSU CDK is Copyright (C) NC State University, 1998, 1999, 2004, +2006, 2007. Users are free to use or modify the NCSU CDK as appropriate as long +as this notice appears in the modified package. The NCSU CDK is +provided with NO WARRANTY. + +As of version 1.5.1, all documentation for the NCSU CDK is provided +by the NCSU EDA Wiki which can be found at: + + http://www.eda.ncsu.edu/ + +This beta release of the kit is to be used in migrating to Cadence Virtuoso 6.1 +for OpenAccess. Details of the conversion of the CDK from the CDB version can +be found in the file cdb2oa/OA_Conversion.txt. + +This kit is not yet fully supported. Please post problems and solutions at +http://www.chiptalk.org -> Forums -> NCSU CDK -> NCSU CDK 1.6.0.beta for Virtuoso 6.1 diff --git a/technology/scn3me_subm/tf/display.drf b/technology/scn3me_subm/tf/display.drf new file mode 100644 index 00000000..4bd251e8 --- /dev/null +++ b/technology/scn3me_subm/tf/display.drf @@ -0,0 +1,714 @@ +drDefineDisplay( +;( DisplayName ) + ( display ) +) +drDefineColor( +;( DisplayName ColorsName Red Green Blue ) + ( display white 255 255 255 ) + ( display yellow 255 255 0 ) + ( display silver 217 230 255 ) + ( display cream 255 255 204 ) + ( display pink 255 191 242 ) + ( display magenta 255 0 255 ) + ( display lime 0 255 0 ) + ( display tan 255 230 191 ) + ( display cyan 0 255 255 ) + ( display cadetBlue 57 191 255 ) + ( display orange 255 128 0 ) + ( display red 255 51 51 ) + ( display purple 153 0 230 ) + ( display green 0 204 102 ) + ( display brown 191 64 38 ) + ( display blue 51 77 255 ) + ( display slate 140 140 166 ) + ( display gold 217 204 0 ) + ( display maroon 230 31 13 ) + ( display violet 94 0 230 ) + ( display forest 38 140 107 ) + ( display chocolate 128 38 38 ) + ( display navy 51 51 153 ) + ( display black 0 0 0 ) + ( display gray 204 204 217 ) + ( display winColor1 166 166 166 ) + ( display winColor2 115 115 115 ) + ( display winColor3 189 204 204 ) + ( display winColor4 204 204 204 ) + ( display winColor5 199 199 199 ) + ( display blinkRed 255 0 0 t ) + ( display blinkYellow 255 255 0 t ) + ( display blinkWhite 255 255 255 t ) + ( display winBack 224 224 224 ) + ( display winFore 128 0 0 ) + ( display winText 51 51 51 ) +) +drDefineStipple( +;( DisplayName StippleName Bitmap ) + ( display dots ( ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display dots1 ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display hLine ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) ) ) + ( display vLine ( ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) ) ) + ( display cross ( ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) ) ) + ( display grid ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) ) ) + ( display slash ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) ) ) + ( display backSlash ( ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) ) ) + ( display hZigZag ( ( 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 ) + ( 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ) + ( 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 ) + ( 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 ) + ( 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 ) + ( 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ) + ( 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 ) + ( 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 ) ) ) + ( display vZigZag ( ( 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 ) + ( 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 ) + ( 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ) + ( 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 ) + ( 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 ) + ( 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 ) + ( 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 ) + ( 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 ) + ( 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 ) + ( 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 ) + ( 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ) + ( 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 ) + ( 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 ) + ( 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 ) + ( 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 ) + ( 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 ) ) ) + ( display hCurb ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display vCurb ( ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) ) ) + ( display brick ( ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) + ( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 ) ) ) + ( display dagger ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 1 1 1 1 1 0 0 0 1 1 1 1 1 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) + ( 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 ) ) ) + ( display triangle ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 ) + ( 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display x ( ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ) ) ) + ( display stipple0 ( ( 1 ) ) ) + ( display stipple1 ( ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display stipple2 ( ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) + ( 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 ) ) ) + ( display stipple3 ( ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) ) ) + ( display stipple4 ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 ) ) ) + ( display stipple5 ( ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) ) ) + ( display stipple6 ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) ) ) + ( display stipple7 ( ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) + ( 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 ) + ( 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 ) + ( 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 ) ) ) + ( display stipple8 ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 ) ) ) + ( display stipple9 ( ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) + ( 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 ) ) ) + ( display stipple10 ( ( 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display stipple11 ( ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) ) ) + ( display dots2 ( ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) + ( display dots4 ( ( 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 ) ) ) + ( display dats5 ( ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) + ( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ) ) ) +) +drDefineLineStyle( +;( DisplayName LineStyle Size Pattern ) + ( display solid 1 (1 ) ) + ( display dashed 1 (1 1 1 0 0 1 1 1 ) ) + ( display dots 1 (1 0 0 ) ) + ( display dashDot 1 (1 1 1 0 0 1 0 0 ) ) + ( display shortDash 1 (1 1 0 0 ) ) + ( display doubleDash 1 (1 1 1 1 0 0 1 1 0 0 ) ) + ( display hidden 1 (1 0 0 0 ) ) + ( display thickLine 3 (1 1 1 ) ) + ( display lineStyle0 1 (1 ) ) + ( display lineStyle1 1 (1 1 1 0 1 1 1 0 1 1 1 0 1 1 0 1 ) ) +) +drDefinePacket( +;( DisplayName PacketName Stipple LineStyle Fill Outline [FillStyle]) + ( display NwellNet dots4 thickLine slate slate outlineStipple) + ( display border stipple0 solid tan tan solid ) + ( display y8 stipple0 solid gold gold solid ) + ( display background stipple1 lineStyle0 black black outlineStipple) + ( display y9 stipple0 solid silver silver solid ) + ( display Metal3Net dots4 solid navy navy outlineStipple) + ( display A1 stipple0 lineStyle0 winBack winBack solid ) + ( display pin solid lineStyle0 red red solid ) + ( display XPNet blank solid yellow yellow outline ) + ( display hardFence stipple0 solid red red solid ) + ( display PbaseNet dots4 solid yellow yellow outlineStipple) + ( display designFlow3 stipple1 lineStyle0 pink pink outlineStipple) + ( display A2 stipple0 lineStyle0 winBack winBack solid ) + ( display Unrouted1 stipple0 lineStyle1 brown brown solid ) + ( display RowLbl blank solid cyan cyan outline ) + ( display edgeLayerPin stipple0 solid yellow yellow solid ) + ( display instance blank solid winBack red outline ) + ( display Nselect dots4 solid green green outlineStipple) + ( display snap stipple0 solid yellow yellow solid ) + ( display pinAnt stipple0 solid red red solid ) + ( display winAttentionText solid solid winText winText solid ) + ( display designFlow2 stipple1 lineStyle0 purple purple outlineStipple) + ( display Unrouted2 stipple0 lineStyle1 red red solid ) + ( display hilite blank solid white white outline ) + ( display P2Con solid lineStyle0 orange orange solid ) + ( display designFlow1 stipple1 lineStyle0 red red outlineStipple) + ( display grid1 stipple0 solid gray gray solid ) + ( display Unrouted3 stipple0 lineStyle1 pink pink solid ) + ( display ViaNet x solid magenta magenta outlineStipple) + ( display select stipple0 solid tan tan solid ) + ( display Poly2Net dots4 lineStyle0 orange orange outlineStipple) + ( display winText solid solid winText winText solid ) + ( display Unrouted4 stipple0 lineStyle1 orange orange solid ) + ( display wireLbl solid lineStyle0 cyan cyan solid ) + ( display designFlow7 stipple1 lineStyle0 cyan cyan outlineStipple) + ( display align stipple0 solid tan tan solid ) + ( display Poly2Pin blank solid yellow yellow outline ) + ( display Unrouted5 stipple0 lineStyle1 green green solid ) + ( display unset stipple0 solid forest forest solid ) + ( display Poly1Net dots4 lineStyle0 red red outlineStipple) + ( display Resistor dots2 lineStyle0 cyan cyan outlineStipple) + ( display DiodeNet dots4 lineStyle0 cream cream outlineStipple) + ( display designFlow6 stipple1 lineStyle0 tan tan outlineStipple) + ( display Unrouted6 stipple0 lineStyle1 blue blue solid ) + ( display resist stipple0 solid cyan cyan solid ) + ( display designFlow5 stipple1 lineStyle0 silver silver outlineStipple) + ( display CapWellNet brick solid slate slate outlineStipple) + ( display Unrouted7 stipple0 lineStyle1 purple purple solid ) + ( display CannotoccupyBnd blank solid red red outline ) + ( display winTopShadow solid solid white white solid ) + ( display designFlow4 stipple1 lineStyle0 black black outlineStipple) + ( display softFence stipple0 solid yellow yellow solid ) + ( display ResistorNet dots4 solid cyan cyan outlineStipple) + ( display winError solid solid winColor5 winColor5 solid ) + ( display changedLayerTl1 stipple0 solid yellow yellow solid ) + ( display prBoundaryLbl stipple0 solid purple purple solid ) + ( display ActXNet x solid yellow yellow outlineStipple) + ( display Pbase stipple10 lineStyle0 yellow yellow outlineStipple) + ( display Active dots2 lineStyle0 yellow yellow outlineStipple) + ( display changedLayerTl0 stipple0 solid red red solid ) + ( display spike stipple0 solid purple purple solid ) + ( display Metal3 grid solid navy violet outlineStipple) + ( display text blank solid white white outline ) + ( display Poly1Pin stipple0 lineStyle0 red red solid ) + ( display Row blank solid cyan cyan outline ) + ( display Pwell stipple9 lineStyle0 slate slate outlineStipple) + ( display Metal2 stipple5 lineStyle0 magenta magenta outlineStipple) + ( display wire solid lineStyle0 cyan cyan solid ) + ( display ActX solid solid yellow yellow solid ) + ( display Metal1 stipple6 lineStyle0 cadetBlue cadetBlue outlineStipple) + ( display Cannotoccupy blank solid red red outline ) + ( display GroupLbl stipple0 solid green green solid ) + ( display axis stipple0 solid slate slate solid ) + ( display SiBlockNet x dashed tan tan outlineStipple) + ( display edgeLayer stipple0 solid gray gray solid ) + ( display annotate2 stipple0 solid lime lime solid ) + ( display Metal1Pin stipple0 lineStyle0 blue blue solid ) + ( display Diode stipple7 lineStyle0 cream cream outlineStipple) + ( display Glass X lineStyle0 white white X ) + ( display ViaXNet x solid magenta magenta outlineStipple) + ( display annotate3 stipple0 solid cyan cyan solid ) + ( display Poly2 dots1 lineStyle0 orange orange outlineStipple) + ( display deviceAnt stipple0 solid yellow yellow solid ) + ( display winBottomShadow solid solid winColor1 winColor1 solid ) + ( display PselectNet dots4 solid brown brown outlineStipple) + ( display comment stipple0 lineStyle0 winBack winBack outlineStipple) + ( display Poly1 dots lineStyle0 red red outlineStipple) + ( display Unrouted stipple0 lineStyle1 winColor5 winColor5 solid ) + ( display stretch stipple0 solid yellow yellow solid ) + ( display XP blank lineStyle0 winBack gold outline ) + ( display annotate1 stipple0 solid pink pink solid ) + ( display Group stipple2 solid green green outlineStipple) + ( display deviceLbl stipple0 solid green green solid ) + ( display annotate6 stipple0 solid silver silver solid ) + ( display GlassNet blank solid yellow yellow outline ) + ( display Canplace blank solid cyan cyan outline ) + ( display annotate7 stipple0 solid red red solid ) + ( display Via2 solid solid navy navy solid ) + ( display Metal2Pin stipple0 lineStyle0 magenta magenta solid ) + ( display annotate4 stipple0 solid yellow yellow solid ) + ( display device1 stipple1 lineStyle0 green green outlineStipple) + ( display "90" blank solid white white outline ) + ( display markerWarn x solid yellow yellow outlineStipple) + ( display text2 stipple1 lineStyle0 white white outlineStipple) + ( display CapacitorNet dots4 lineStyle0 tan tan outlineStipple) + ( display designFlow stipple1 lineStyle0 green green outlineStipple) + ( display hilite1 stipple0 solid silver silver solid ) + ( display device blank solid green green outline ) + ( display prBoundary stipple0 solid purple purple solid ) + ( display annotate5 stipple0 solid white white solid ) + ( display text1 stipple0 dashed white white solid ) + ( display Via solid solid magenta magenta solid ) + ( display Capacitor stipple7 lineStyle0 tan tan outlineStipple) + ( display markerErr x solid white white outlineStipple) + ( display unknown stipple0 solid yellow yellow solid ) + ( display annotate stipple0 solid orange orange solid ) + ( display P1ConNet x solid red red outlineStipple) + ( display hilite3 stipple0 solid cyan cyan solid ) + ( display winActiveBanner solid solid winColor3 winColor3 solid ) + ( display pinLbl stipple0 solid red red solid ) + ( display device2 stipple0 lineStyle1 green green solid ) + ( display grid stipple0 solid slate slate solid ) + ( display winBackground solid solid winBack winBack solid ) + ( display Metal1Net dots4 lineStyle0 blue blue outlineStipple) + ( display hilite2 stipple0 solid tan tan solid ) + ( display annotate8 stipple0 solid tan tan solid ) + ( display hilite5 stipple0 solid lime lime solid ) + ( display annotate9 stipple0 solid green green solid ) + ( display Metal2Net dots4 lineStyle0 magenta magenta outlineStipple) + ( display Metal3Pin stipple0 solid navy navy solid ) + ( display hilite4 stipple0 solid gray gray solid ) + ( display y0 stipple0 solid gray gray solid ) + ( display supply stipple0 solid lime lime solid ) + ( display ActiveNet dots4 lineStyle0 yellow yellow outlineStipple) + ( display hilite7 stipple0 solid cream cream solid ) + ( display y1 stipple0 solid brown brown solid ) + ( display defaultPacket x solid chocolate winColor2 outlineStipple) + ( display Via2Net cross solid navy navy outlineStipple) + ( display NselectNet dots4 solid green green outlineStipple) + ( display Unrouted8 stipple0 lineStyle1 gold gold solid ) + ( display hilite6 stipple0 solid orange orange solid ) + ( display y2 stipple0 solid red red solid ) + ( display winBorder solid solid winColor2 winColor2 solid ) + ( display Nwell dats5 thickLine slate slate outlineStipple) + ( display Unrouted9 stipple0 lineStyle1 silver silver solid ) + ( display hilite9 stipple0 solid pink pink solid ) + ( display SiBlock blank dashed tan tan outline ) + ( display y3 stipple0 solid orange orange solid ) + ( display prBoundaryBnd stipple0 solid cyan cyan solid ) + ( display winForeground solid solid winFore winFore solid ) + ( display hilite8 stipple0 solid magenta magenta solid ) + ( display y4 stipple0 solid yellow yellow solid ) + ( display Pselect dots1 solid brown brown outlineStipple) + ( display winInactiveBanner solid solid winColor4 winColor4 solid ) + ( display designFlow9 stipple1 lineStyle0 orange orange outlineStipple) + ( display winButton solid solid winFore winFore solid ) + ( display y5 stipple0 solid green green solid ) + ( display hiz stipple0 solid orange orange solid ) + ( display drive stipple0 solid blue blue solid ) + ( display wireFlt stipple0 dashed red red solid ) + ( display instanceLbl stipple0 solid gold gold solid ) + ( display P2ConNet x lineStyle0 orange orange outlineStipple) + ( display designFlow8 stipple1 lineStyle0 navy navy outlineStipple) + ( display y6 stipple0 solid blue blue solid ) + ( display PwellNet dots4 lineStyle0 slate slate outlineStipple) + ( display P1Con solid solid red red solid ) + ( display CapWell dagger solid slate slate outlineStipple) + ( display y7 stipple0 solid purple purple solid ) + ( display ViaX solid solid magenta magenta solid ) + ( display HR x solid chocolate winColor2 outlineStipple) + ( display HRnet x solid chocolate winColor2 outlineStipple) +) diff --git a/technology/scn3me_subm/tf/glade_scn3me_subm.py b/technology/scn3me_subm/tf/glade_scn3me_subm.py new file mode 100644 index 00000000..d2f9aa7e --- /dev/null +++ b/technology/scn3me_subm/tf/glade_scn3me_subm.py @@ -0,0 +1,7 @@ +import os +CWD = os.environ.get("OPENRAM_TECH") + "/scn3me_subm/tf" +ui().importCds("default", CWD+"/display.drf", CWD+"/mosis.tf", 1000, 1, CWD+"/layers.map") + + + + diff --git a/technology/scn3me_subm/tf/layers.map b/technology/scn3me_subm/tf/layers.map new file mode 100644 index 00000000..b5440f23 --- /dev/null +++ b/technology/scn3me_subm/tf/layers.map @@ -0,0 +1,16 @@ +Pwell drawing 41 0 +Nwell drawing 42 0 +Active drawing 43 0 +Poly1 drawing 46 0 +Pselect drawing 45 0 +Nselect drawing 44 0 +contact drawing 25 0 +P1Con drawing 47 0 +ActX drawing 48 0 +Metal1 drawing 49 0 +Via drawing 50 0 +Metal2 drawing 51 0 +Via2 drawing 61 0 +Metal3 drawing 62 0 +Glass drawing 52 0 +comment drawing 63 0 diff --git a/technology/scn3me_subm/tf/mosis.tf b/technology/scn3me_subm/tf/mosis.tf new file mode 100644 index 00000000..759221f1 --- /dev/null +++ b/technology/scn3me_subm/tf/mosis.tf @@ -0,0 +1,848 @@ +; Generated on Sep 28 16:05:23 1998 +; with @(#)$CDS: icfb.exe version 4.4.1 06/17/98 23:40 (cds10067) $ +; +; Matt Clapp fixed: October 10, 2002 +; added via devices, deleted useless app-specific crap, +; added lxExtractRules so undo in layout editor doesn't +; complain. + + +;******************************** +; LAYER DEFINITION +;******************************** + +layerDefinitions( + techLayers( + ;( LayerName Layer# Abbreviation ) + ;( --------- ------ ------------ ) + ;User-Defined Layers: + ( P2Con 3 P2Con ) + ( Poly2 7 Poly2 ) + ( Pbase 10 Pbase ) + ( Resistor 16 Resisto ) + ( Capacitor 17 Capacit ) + ( Diode 18 Diode ) + ( SiBlock 29 SiBlock ) + ( HR 34 HR ) + ( Pwell 41 Pwell ) + ( Nwell 42 Nwell ) + ( Active 43 Active ) + ( Pselect 44 Pselect ) + ( Nselect 45 Nselect ) + ( Poly1 46 Poly1 ) + ( P1Con 47 P1Con ) + ( ActX 48 ActX ) + ( Metal1 49 Metal1 ) + ( Via 50 Via ) + ( Metal2 51 Metal2 ) + ( Glass 52 Glass ) + ( CapWell 59 CapWell ) + ( XP 60 XP ) + ( Via2 61 Via2 ) + ( Metal3 62 Metal3 ) + ( A1 80 A1 ) + ( A2 81 A2 ) + ( comment 117 comment ) + ;System-Reserved Layers: + ( Unrouted 200 Unroute ) + ( Row 201 Row ) + ( Group 202 Group ) + ( Cannotoccupy 203 Cannoto ) + ( Canplace 204 Canplac ) + ( hardFence 205 hardFen ) + ( softFence 206 softFen ) + ( y0 207 y0 ) + ( y1 208 y1 ) + ( y2 209 y2 ) + ( y3 210 y3 ) + ( y4 211 y4 ) + ( y5 212 y5 ) + ( y6 213 y6 ) + ( y7 214 y7 ) + ( y8 215 y8 ) + ( y9 216 y9 ) + ( designFlow 217 designF ) + ( stretch 218 stretch ) + ( edgeLayer 219 edgeLay ) + ( changedLayer 220 changed ) + ( unset 221 unset ) + ( unknown 222 unknown ) + ( spike 223 spike ) + ( hiz 224 hiz ) + ( resist 225 resist ) + ( drive 226 drive ) + ( supply 227 supply ) + ( wire 228 wire ) + ( pin 229 pin ) + ( text 230 text ) + ( device 231 device ) + ( border 232 border ) + ( snap 233 snap ) + ( align 234 align ) + ( prBoundary 235 prBound ) + ( instance 236 instanc ) + ( annotate 237 annotat ) + ( marker 238 marker ) + ( select 239 select ) + ( grid 251 grid ) + ( axis 252 axis ) + ( hilite 253 hilite ) + ( background 254 backgro ) + ) ;techLayers + + techPurposes( + ;( PurposeName Purpose# Abbreviation ) + ;( ----------- -------- ------------ ) + ;User-Defined Purposes: + ;System-Reserved Purposes: + ( warning 234 wng ) + ( tool1 235 tl1 ) + ( tool0 236 tl0 ) + ( label 237 lbl ) + ( flight 238 flt ) + ( error 239 err ) + ( annotate 240 ant ) + ( drawing1 241 dr1 ) + ( drawing2 242 dr2 ) + ( drawing3 243 dr3 ) + ( drawing4 244 dr4 ) + ( drawing5 245 dr5 ) + ( drawing6 246 dr6 ) + ( drawing7 247 dr7 ) + ( drawing8 248 dr8 ) + ( drawing9 249 dr9 ) + ( boundary 250 bnd ) + ( pin 251 pin ) + ( drawing 252 drw ) + ( net 253 net ) + ( cell 254 cel ) + ( all 255 all ) + ) ;techPurposes + + techLayerPurposePriorities( + ;layers are ordered from lowest to highest priority + ; (higher priority is drawn on top of lower priority) + ;( LayerName Purpose ) + ;( --------- ------- ) + ( background drawing ) + ( grid drawing ) + ( grid drawing1 ) + ( Nwell drawing ) + ( Pwell drawing ) + ( CapWell drawing ) + ( Pselect drawing ) + ( Nselect drawing ) + ( Active drawing ) + ( ActX drawing ) + ( SiBlock drawing ) + ( HR drawing ) + ( Poly1 drawing ) + ( P1Con drawing ) + ( Poly2 drawing ) + ( P2Con drawing ) + ( Metal1 drawing ) + ( Via drawing ) + ( Metal2 drawing ) + ( Via2 drawing ) + ( Metal3 drawing ) + ( annotate drawing ) + ( annotate drawing1 ) + ( annotate drawing2 ) + ( annotate drawing3 ) + ( annotate drawing4 ) + ( annotate drawing5 ) + ( annotate drawing6 ) + ( annotate drawing7 ) + ( annotate drawing8 ) + ( annotate drawing9 ) + ( Poly1 pin ) + ( Metal1 pin ) + ( Metal2 pin ) + ( Metal3 pin ) + ( Glass drawing ) + ( XP drawing ) + ( prBoundary drawing ) + ( prBoundary boundary ) + ( instance drawing ) + ( prBoundary label ) + ( instance label ) + ( Row drawing ) + ( Nwell net ) + ( align drawing ) + ( Pwell net ) + ( CapWell net ) + ( hardFence drawing ) + ( Active net ) + ( softFence drawing ) + ( Row label ) + ( Group drawing ) + ( Group label ) + ( Cannotoccupy drawing ) + ( Cannotoccupy boundary ) + ( Canplace drawing ) + ( ActX net ) + ( A2 drawing ) + ( A1 drawing ) + ( comment drawing ) + ( border drawing ) + ( Pselect net ) + ( Nselect net ) + ( SiBlock net ) + ( HR net ) + ( wire drawing ) + ( Poly1 net ) + ( wire label ) + ( P1Con net ) + ( wire flight ) + ( Metal1 net ) + ( device annotate ) + ( Metal2 net ) + ( device label ) + ( Via net ) + ( Metal3 net ) + ( Via2 net ) + ( pin label ) + ( text drawing ) + ( pin drawing ) + ( text drawing1 ) + ( pin annotate ) + ( device drawing ) + ( axis drawing ) + ( edgeLayer drawing ) + ( edgeLayer pin ) + ( snap drawing ) + ( stretch drawing ) + ( y0 drawing ) + ( y1 drawing ) + ( y2 drawing ) + ( y3 drawing ) + ( y4 drawing ) + ( y5 drawing ) + ( y6 drawing ) + ( y7 drawing ) + ( y8 drawing ) + ( y9 drawing ) + ( hilite drawing ) + ( hilite drawing1 ) + ( hilite drawing2 ) + ( hilite drawing3 ) + ( hilite drawing4 ) + ( hilite drawing5 ) + ( hilite drawing6 ) + ( hilite drawing7 ) + ( hilite drawing8 ) + ( hilite drawing9 ) + ( select drawing ) + ( drive drawing ) + ( hiz drawing ) + ( resist drawing ) + ( spike drawing ) + ( supply drawing ) + ( unknown drawing ) + ( unset drawing ) + ( designFlow drawing ) + ( designFlow drawing1 ) + ( designFlow drawing2 ) + ( designFlow drawing3 ) + ( designFlow drawing4 ) + ( designFlow drawing5 ) + ( designFlow drawing6 ) + ( designFlow drawing7 ) + ( designFlow drawing8 ) + ( designFlow drawing9 ) + ( changedLayer tool0 ) + ( changedLayer tool1 ) + ( marker warning ) + ( marker error ) + ( device drawing1 ) + ( Pbase drawing ) + ( Pbase net ) + ( Resistor net ) + ( Resistor drawing ) + ( Capacitor net ) + ( Capacitor drawing ) + ( Diode net ) + ( Diode drawing ) + ( Poly2 net ) + ( P2Con net ) + ( device drawing2 ) + ( Unrouted drawing ) + ( text drawing2 ) + ( Unrouted drawing1 ) + ( Unrouted drawing2 ) + ( Unrouted drawing3 ) + ( Unrouted drawing4 ) + ( Unrouted drawing5 ) + ( Unrouted drawing6 ) + ( Unrouted drawing7 ) + ( Unrouted drawing8 ) + ( Unrouted drawing9 ) + ) ;techLayerPurposePriorities + + techDisplays( + ;( LayerName Purpose Packet Vis Sel Con2ChgLy DrgEnbl Valid ) + ;( --------- ------- ------ --- --- --------- ------- ----- ) + ( background drawing background t nil nil nil nil ) + ( grid drawing grid t nil nil nil nil ) + ( grid drawing1 grid1 t nil nil nil nil ) + ( Nwell drawing Nwell t t t t t ) + ( Pwell drawing Pwell t t t t nil ) + ( Active drawing Active t t t t t ) + ( ActX drawing ActX t t t t t ) + ( Pselect drawing Pselect t t t t t ) + ( Nselect drawing Nselect t t t t t ) + ( SiBlock drawing SiBlock t t t t t ) + ( HR drawing HR t t t t t ) + ( CapWell drawing CapWell t t t t t ) + ( Poly1 drawing Poly1 t t t t t ) + ( P1Con drawing P1Con t t t t t ) + ( Metal1 drawing Metal1 t t t t t ) + ( Via drawing Via t t t t t ) + ( Metal2 drawing Metal2 t t t t t ) + ( annotate drawing annotate t t nil t nil ) + ( annotate drawing1 annotate1 t t nil t nil ) + ( annotate drawing2 annotate2 t t nil t nil ) + ( annotate drawing3 annotate3 t t nil t nil ) + ( annotate drawing4 annotate4 t t nil t nil ) + ( annotate drawing5 annotate5 t t nil t nil ) + ( annotate drawing6 annotate6 t t nil t nil ) + ( annotate drawing7 annotate7 t t nil t nil ) + ( annotate drawing8 annotate8 t t nil t nil ) + ( annotate drawing9 annotate9 t t nil t nil ) + ( Via2 drawing Via2 t t t t t ) + ( Metal3 drawing Metal3 t t t t t ) + ( Glass drawing Glass t t t nil t ) + ( XP drawing XP t t t nil t ) + ( Metal1 pin Metal1Pin t t t nil t ) + ( Metal2 pin Metal2Pin t t t nil t ) + ( Metal3 pin Metal3Pin t t t nil t ) + ( Poly1 pin Poly1Pin t t t nil t ) + ( prBoundary drawing prBoundary t t nil t nil ) + ( prBoundary boundary prBoundaryBnd t t nil t nil ) + ( instance drawing instance t t nil t t ) + ( prBoundary label prBoundaryLbl t t t t nil ) + ( instance label instanceLbl t t t t nil ) + ( Row drawing Row t t t t nil ) + ( Nwell net NwellNet t t t nil nil ) + ( align drawing align t t nil t nil ) + ( Pwell net PwellNet t t t nil nil ) + ( CapWell net CapWellNet t t t nil nil ) + ( SiBlock net SiBlockNet t t t nil nil ) + ( HR net HRnet t t t nil nil ) + ( hardFence drawing hardFence t t t t nil ) + ( Active net ActiveNet t t t nil nil ) + ( softFence drawing softFence t t t t nil ) + ( Row label RowLbl t t t t nil ) + ( Group drawing Group t t t t nil ) + ( Group label GroupLbl t t t t nil ) + ( Cannotoccupy drawing Cannotoccupy t t t t nil ) + ( Cannotoccupy boundary CannotoccupyBnd t t t t nil ) + ( Canplace drawing Canplace t t t t nil ) + ( ActX net ActXNet t t t nil nil ) + ( A2 drawing A2 t t t t nil ) + ( A1 drawing A1 t t t t nil ) + ( comment drawing comment t t t t nil ) + ( border drawing border t t t t nil ) + ( Pselect net PselectNet t t t nil nil ) + ( Nselect net NselectNet t t t nil nil ) + ( wire drawing wire t t t t nil ) + ( Poly1 net Poly1Net t t t nil nil ) + ( wire label wireLbl t t t t nil ) + ( P1Con net P1ConNet t t t nil nil ) + ( wire flight wireFlt t t t t nil ) + ( Metal1 net Metal1Net t t t nil nil ) + ( device annotate deviceAnt t t t t nil ) + ( Metal2 net Metal2Net t t t nil nil ) + ( Metal3 net Metal3Net t t t nil nil ) + ( device label deviceLbl t t t t nil ) + ( Via net ViaNet t t t nil nil ) + ( Via2 net Via2Net t t t nil nil ) + ( pin label pinLbl t t t t nil ) + ( text drawing text t t t t t ) + ( pin drawing pin t t t t nil ) + ( text drawing1 text1 t t t t nil ) + ( pin annotate pinAnt t t t t nil ) + ( device drawing device t t t t nil ) + ( axis drawing axis t t t t nil ) + ( edgeLayer drawing edgeLayer t t nil t nil ) + ( edgeLayer pin edgeLayerPin t t nil t nil ) + ( snap drawing snap t t nil t nil ) + ( stretch drawing stretch t t nil t nil ) + ( y0 drawing y0 t t nil t nil ) + ( y1 drawing y1 t t nil t nil ) + ( y2 drawing y2 t t nil t nil ) + ( y3 drawing y3 t t nil t nil ) + ( y4 drawing y4 t t nil t nil ) + ( y5 drawing y5 t t nil t nil ) + ( y6 drawing y6 t t nil t nil ) + ( y7 drawing y7 t t nil t nil ) + ( y8 drawing y8 t t nil t nil ) + ( y9 drawing y9 t t nil t nil ) + ( hilite drawing hilite t t nil t nil ) + ( hilite drawing1 hilite1 t t t t nil ) + ( hilite drawing2 hilite2 t t nil t nil ) + ( hilite drawing3 hilite3 t t t t nil ) + ( hilite drawing4 hilite4 t t t t nil ) + ( hilite drawing5 hilite5 t t t t nil ) + ( hilite drawing6 hilite6 t t t t nil ) + ( hilite drawing7 hilite7 t t t t nil ) + ( hilite drawing8 hilite8 t t t t nil ) + ( hilite drawing9 hilite9 t t t t nil ) + ( select drawing select t t nil t nil ) + ( drive drawing drive t t t t nil ) + ( hiz drawing hiz t t t t nil ) + ( resist drawing resist t t t t nil ) + ( spike drawing spike t t t t nil ) + ( supply drawing supply t t t t nil ) + ( unknown drawing unknown t t t t nil ) + ( unset drawing unset t t t t nil ) + ( designFlow drawing designFlow t t t nil nil ) + ( designFlow drawing1 designFlow1 t t t nil nil ) + ( designFlow drawing2 designFlow2 t t t nil nil ) + ( designFlow drawing3 designFlow3 t t t nil nil ) + ( designFlow drawing4 designFlow4 t t t nil nil ) + ( designFlow drawing5 designFlow5 t t t nil nil ) + ( designFlow drawing6 designFlow6 t t t nil nil ) + ( designFlow drawing7 designFlow7 t t t nil nil ) + ( designFlow drawing8 designFlow8 t t t nil nil ) + ( designFlow drawing9 designFlow9 t t t nil nil ) + ( changedLayer tool0 changedLayerTl0 nil nil nil nil nil ) + ( changedLayer tool1 changedLayerTl1 nil nil t nil nil ) + ( marker warning markerWarn t t t t nil ) + ( marker error markerErr t t t t nil ) + ( device drawing1 device1 t t t t nil ) + ( Poly2 net Poly2Net t t t nil nil ) + ( Poly2 drawing Poly2 t t t t t ) + ( P2Con net P2ConNet t t t nil nil ) + ( P2Con drawing P2Con t t t t t ) + ( Pbase net PbaseNet t t t nil nil ) + ( Pbase drawing Pbase t t t t t ) + ( Resistor net ResistorNet t t t nil nil ) + ( Resistor drawing Resistor t t t t t ) + ( Capacitor net CapacitorNet t t t nil nil ) + ( Capacitor drawing Capacitor t t t t t ) + ( Diode net DiodeNet t t t nil nil ) + ( Diode drawing Diode t t t t t ) + ( device drawing2 device2 t t t t nil ) + ( Unrouted drawing Unrouted t t t t nil ) + ( text drawing2 text2 t t t t nil ) + ( Unrouted drawing1 Unrouted1 t t t t nil ) + ( Unrouted drawing2 Unrouted2 t t t t nil ) + ( Unrouted drawing3 Unrouted3 t t t t nil ) + ( Unrouted drawing4 Unrouted4 t t t t nil ) + ( Unrouted drawing5 Unrouted5 t t t t nil ) + ( Unrouted drawing6 Unrouted6 t t t t nil ) + ( Unrouted drawing7 Unrouted7 t t t t nil ) + ( Unrouted drawing8 Unrouted8 t t t t nil ) + ( Unrouted drawing9 Unrouted9 t t t t nil ) + ) ;techDisplays + +; I don't think the following is necessary (or used!) +techLayerProperties( +;( PropName Layer1 [ Layer2 ] PropValue ) + ( contactLimit P2Con 10000 ) + ( eqPinLimit P2Con 10000 ) + ( horizontalJogLength P2Con 2147483648.000000 ) + ( routingGrid P2Con 1.000000 ) + ( verticalJogLength P2Con 2147483648.000000 ) + ( routingGrid Poly2 1.000000 ) + ( contactLimit Active 10000 ) + ( eqPinLimit Active 10000 ) + ( horizontalJogLength Active 2147483648.000000 ) + ( routingGrid Active 1.000000 ) + ( verticalJogLength Active 2147483648.000000 ) + ( routingGrid Poly1 1.000000 ) + ( contactLimit P1Con 10000 ) + ( eqPinLimit P1Con 10000 ) + ( horizontalJogLength P1Con 2147483648.000000 ) + ( routingGrid P1Con 1.000000 ) + ( verticalJogLength P1Con 2147483648.000000 ) + ( contactLimit ActX 10000 ) + ( eqPinLimit ActX 10000 ) + ( horizontalJogLength ActX 2147483648.000000 ) + ( routingGrid ActX 1.000000 ) + ( verticalJogLength ActX 2147483648.000000 ) + ( routingGrid Metal1 1.000000 ) + ( contactLimit Via 10000 ) + ( eqPinLimit Via 10000 ) + ( horizontalJogLength Via 2147483648.000000 ) + ( routingGrid Via 1.000000 ) + ( verticalJogLength Via 2147483648.000000 ) + ( routingGrid Metal2 1.000000 ) +) + +) ;layerDefinitions + + +;******************************** +; DEVICE RULES +;******************************** + +devices( + tcCreateCDSDeviceClass() + + symContactDevice( + ;( deviceName viaLayer viaPurpose + ( VIA Via drawing + + ; layer1 purpose1 [implant1] + Metal1 drawing + + ; layer2 purpose2 [implant2] + Metal2 drawing + + ; width length [( row column xPitch yPitch xBias yBias )] + ; 2 2 ( 1 1 _NA_ _NA_ _NA_ _NA_ ) + 2 2 + + ; encLayer1 encLayer2 legalRegion ) + 1 1 _NA_) + ) ;symContactDevice + + symContactDevice( + ;( deviceName viaLayer viaPurpose + ( VIA2 Via2 drawing + + ; layer1 purpose1 [implant1] + Metal2 drawing + + ; layer2 purpose2 [implant2] + Metal3 drawing + + ; width length [( row column xPitch yPitch xBias yBias )] + ; 2 2 ( 1 1 _NA_ _NA_ _NA_ _NA_ ) + 2 2 + + ; encLayer1 encLayer2 legalRegion ) + 1 2 _NA_) + ) ;symContactDevice + +) ;devices + + +;******************************** +; LAYER RULES +;******************************** + +layerRules( + streamLayers( + ;( layer streamNumber dataType translate ) + ;( ----- ------------ -------- --------- ) + ( ("background" "drawing") 0 0 nil ) + ( ("grid" "drawing") 0 0 nil ) + ( ("grid" "drawing1") 0 0 nil ) + ( ("Nwell" "drawing") 42 0 t ) + ( ("Pwell" "drawing") 41 0 t ) + ( ("Active" "drawing") 43 0 t ) + ( ("ActX" "drawing") 48 0 t ) + ( ("Pselect" "drawing") 44 0 t ) + ( ("Nselect" "drawing") 45 0 t ) + ( ("Poly1" "drawing") 46 0 t ) + ( ("P1Con" "drawing") 47 0 t ) + ( ("Metal1" "drawing") 49 0 t ) + ( ("Metal2" "drawing") 51 0 t ) + ( ("annotate" "drawing") 0 0 nil ) + ( ("annotate" "drawing1") 0 0 nil ) + ( ("annotate" "drawing2") 0 0 nil ) + ( ("annotate" "drawing3") 0 0 nil ) + ( ("annotate" "drawing4") 0 0 nil ) + ( ("annotate" "drawing5") 0 0 nil ) + ( ("annotate" "drawing6") 0 0 nil ) + ( ("annotate" "drawing7") 0 0 nil ) + ( ("annotate" "drawing8") 0 0 nil ) + ( ("annotate" "drawing9") 0 0 nil ) + ( ("Via" "drawing") 50 0 t ) + ( ("Glass" "drawing") 52 0 t ) + ( ("XP" "drawing") 60 0 t ) + ( ("Metal2" "pin") 0 0 nil ) + ( ("Poly1" "pin") 0 0 nil ) + ( ("prBoundary" "drawing") 0 0 nil ) + ( ("Metal1" "pin") 0 0 nil ) + ( ("prBoundary" "boundary") 0 0 nil ) + ( ("instance" "drawing") 246 0 nil ) + ( ("instance" "label") 0 0 nil ) + ( ("Nwell" "net") 0 0 nil ) + ( ("align" "drawing") 0 0 nil ) + ( ("Pwell" "net") 0 0 nil ) + ( ("hardFence" "drawing") 0 0 nil ) + ( ("Active" "net") 0 0 nil ) + ( ("softFence" "drawing") 0 0 nil ) + ( ("ActX" "net") 0 0 nil ) + ( ("A2" "drawing") 5 0 nil ) + ( ("A1" "drawing") 2 0 nil ) + ( ("comment" "drawing") 0 0 nil ) + ( ("border" "drawing") 0 0 nil ) + ( ("Pselect" "net") 0 0 nil ) + ( ("Nselect" "net") 0 0 nil ) + ( ("wire" "drawing") 0 0 nil ) + ( ("Poly1" "net") 0 0 nil ) + ( ("P1Con" "net") 0 0 nil ) + ( ("Metal1" "net") 0 0 nil ) + ( ("Metal2" "net") 0 0 nil ) + ( ("device" "label") 0 0 nil ) + ( ("Via" "net") 0 0 nil ) + ( ("pin" "label") 0 0 nil ) + ( ("text" "drawing") 63 0 t ) + ( ("pin" "drawing") 0 0 nil ) + ( ("device" "drawing") 0 0 nil ) + ( ("axis" "drawing") 0 0 nil ) + ( ("edgeLayer" "drawing") 0 0 nil ) + ( ("edgeLayer" "pin") 0 0 nil ) + ( ("snap" "drawing") 0 0 nil ) + ( ("stretch" "drawing") 0 0 nil ) + ( ("y0" "drawing") 0 0 nil ) + ( ("y1" "drawing") 0 0 nil ) + ( ("y2" "drawing") 0 0 nil ) + ( ("y3" "drawing") 0 0 nil ) + ( ("y4" "drawing") 0 0 nil ) + ( ("y5" "drawing") 0 0 nil ) + ( ("y6" "drawing") 0 0 nil ) + ( ("y7" "drawing") 0 0 nil ) + ( ("y8" "drawing") 0 0 nil ) + ( ("y9" "drawing") 0 0 nil ) + ( ("hilite" "drawing") 0 0 nil ) + ( ("hilite" "drawing2") 0 0 nil ) + ( ("select" "drawing") 0 0 nil ) + ( ("drive" "drawing") 0 0 nil ) + ( ("hiz" "drawing") 0 0 nil ) + ( ("resist" "drawing") 0 0 nil ) + ( ("spike" "drawing") 0 0 nil ) + ( ("supply" "drawing") 0 0 nil ) + ( ("unknown" "drawing") 0 0 nil ) + ( ("unset" "drawing") 0 0 nil ) + ( ("changedLayer" "tool0") 0 0 nil ) + ( ("Resistor" "net") 0 0 nil ) + ( ("Resistor" "drawing") 0 0 nil ) + ( ("Capacitor" "net") 0 0 nil ) + ( ("Capacitor" "drawing") 0 0 nil ) + ( ("Diode" "net") 0 0 nil ) + ( ("Diode" "drawing") 0 0 nil ) + ( ("Poly2" "net") 0 0 nil ) + ( ("Poly2" "drawing") 0 0 nil ) + ( ("P2Con" "net") 0 0 nil ) + ( ("P2Con" "drawing") 0 0 nil ) + ( ("Pbase" "drawing") 0 0 nil ) + ( ("Pbase" "net") 0 0 nil ) + ( P2Con 0 0 nil ) + ( Poly2 0 0 nil ) + ( Pwell 0 0 nil ) + ( Nwell 0 0 nil ) + ( Active 0 0 nil ) + ( Pselect 0 0 nil ) + ( Nselect 0 0 nil ) + ( Poly1 0 0 nil ) + ( P1Con 0 0 nil ) + ( ActX 0 0 nil ) + ( Metal1 0 0 nil ) + ( Via 0 0 nil ) + ( Metal2 0 0 nil ) + ( Glass 0 0 nil ) + ( XP 0 0 nil ) + ( ("Via2" "drawing") 50 0 t ) + ( ("Via2" "net") 0 0 nil ) + ( ("Metal3" "drawing") 50 0 t ) + ( ("Metal3" "net") 0 0 nil ) + ( ("Metal3" "pin") 0 0 nil ) + ( ("CapWell" "drawing") 0 0 nil ) + ( ("CapWell" "net") 0 0 nil ) + ( ("SiBlock" "drawing") 0 0 nil ) + ( ("SiBlock" "net") 0 0 nil ) + ( ("HR" "drawing") 0 0 nil ) + ( ("HR" "net") 0 0 nil ) + ) ;streamLayers + + viaLayers( + ;( layer1 viaLayer layer2 ) + ;( ------ -------- ------ ) + ( Metal2 Via2 Metal3 ) + ( Metal1 Via Metal2 ) + ( Active ActX Poly1 ) + ( Poly1 P1Con Metal1 ) + ( Poly2 P2Con Metal1 ) + ) ;viaLayers + +) ;layerRules + + +;******************************** +; PHYSICAL RULES +;******************************** + +physicalRules( + orderedSpacingRules( + ;( rule layer1 layer2 value ) + ;( ---- ------ ------ ----- ) + ( minEnclosure "prBoundary" "Metal1" 0.0 ) + ( minEnclosure "Metal2" "Via" 1.0 ) + ( minEnclosure "Metal1" "Via" 1.0 ) + ( minEnclosure "Metal1" "P1Con" 1.0 ) + ( minEnclosure "Metal1" "ActX" 1.0 ) + ( minEnclosure "Nselect" "Active" 2.0 ) + ( minEnclosure "Pselect" "Active" 2.0 ) + ( minEnclosure "Active" "ActX" 1.0 ) + ( minEnclosure "Pwell" "Active" 5.0 ) + ( minEnclosure "Nwell" "Active" 5.0 ) + ) ;orderedSpacingRules + + spacingRules( + ;( rule layer1 layer2 value ) + ;( ---- ------ ------ ----- ) + ( minSpacing "P2Con" 2.0 ) + ( minSpacing "Poly2" 3.0 ) + ( minSpacing "Pwell" 9.0 ) + ( minSpacing "Nwell" 9.0 ) + ( minSpacing "Active" 3.0 ) + ( minSpacing "Pselect" 2.0 ) + ( minSpacing "Nselect" 2.0 ) + ( minSpacing "Poly1" 2.0 ) + ( minSpacing "P1Con" 2.0 ) + ( minSpacing "ActX" 2.0 ) + ( minSpacing "Metal1" 3.0 ) + ( minSpacing "Via" 3.0 ) + ( minSpacing "Via2" 3.0 ) + ( minSpacing "Metal2" 3.0 ) + ( minSpacing "Metal3" 4.0 ) + ( minSpacing "Glass" 75.0 ) + ( minSpacing "XP" 100.0 ) + ( minSpacing "Metal2" 4.0 ) + ( minSpacing "P1Con" "Via" 2.0 ) + ( minSpacing "ActX" "Via" 2.0 ) + ( minSpacing "ActX" "P2Con" 2.0 ) + ( minSpacing "Poly2" "P2Con" 4.0 ) + ( minSpacing "Poly1" "P1Con" 4.0 ) + ( minSpacing "ActX" "P1Con" 2.0 ) + ( minSpacing "Active" "P1Con" 2.0 ) + ( minSpacing "Active" "Poly2" 2.0 ) + ( minSpacing "Poly1" "Poly2" 2.0 ) + ( minSpacing "Active" "Poly1" 2.0 ) + ( minSpacing "ActX" "Poly1" 2.0 ) + ( minSpacing "Pselect" "Nselect" 0.0 ) + ( minSpacing "Nwell" "Pwell" 9.0 ) + ( minWidth "P2Con" 2.0 ) + ( minWidth "Poly2" 3.0 ) + ( minWidth "Pwell" 10.0 ) + ( minWidth "Nwell" 10.0 ) + ( minWidth "Active" 3.0 ) + ( minWidth "Pselect" 2.0 ) + ( minWidth "Nselect" 2.0 ) + ( minWidth "Poly1" 2.0 ) + ( minWidth "P1Con" 2.0 ) + ( minWidth "ActX" 2.0 ) + ( minWidth "Metal1" 4.0 ) + ( minWidth "Via" 2.0 ) + ( minWidth "Metal2" 4.0 ) + ( minWidth "Glass" 75.0 ) + ( minWidth "XP" 100.0 ) + ( minWidth "Metal3" 6.0 ) + ) ;spacingRules + + mfgGridResolution( + ( 1.000000 ) + ) ;mfgGridResolution + +) ;physicalRules + + +;******************************** +; ELECTRICAL RULES +;******************************** + +electricalRules( + characterizationRules( + ;( rule layer1 layer2 value ) + ;( ---- ------ ------ ----- ) + ( areaCap "P2Con" 0.0 ) + ( areaCap "Poly2" 0.0 ) + ( areaCap "Active" 0.0 ) + ( areaCap "Poly1" 6e-05 ) + ( areaCap "P1Con" 0.0 ) + ( areaCap "ActX" 0.0 ) + ( areaCap "Metal1" 2.6e-05 ) + ( areaCap "Via" 0.0 ) + ( areaCap "Metal2" 1.6e-05 ) + ( edgeCapacitance "P2Con" 0.0 ) + ( edgeCapacitance "Poly2" 0.0 ) + ( edgeCapacitance "Active" 0.0 ) + ( edgeCapacitance "Poly1" 0.0 ) + ( edgeCapacitance "P1Con" 0.0 ) + ( edgeCapacitance "ActX" 0.0 ) + ( edgeCapacitance "Metal1" 0.0 ) + ( edgeCapacitance "Via" 0.0 ) + ( edgeCapacitance "Metal2" 0.0 ) + ( sheetRes "P2Con" 0.0 ) + ( sheetRes "Poly2" 0.0 ) + ( sheetRes "Active" 0.0 ) + ( sheetRes "Poly1" 23.0 ) + ( sheetRes "P1Con" 0.0 ) + ( sheetRes "ActX" 0.0 ) + ( sheetRes "Metal1" 0.04 ) + ( sheetRes "Via" 0.0 ) + ( sheetRes "Metal2" 0.07 ) + ( currentDensity "P2Con" 1.0 ) + ( currentDensity "Poly2" 1.0 ) + ( currentDensity "Active" 1.0 ) + ( currentDensity "Poly1" 1.0 ) + ( currentDensity "P1Con" 1.0 ) + ( currentDensity "ActX" 1.0 ) + ( currentDensity "Metal1" 1.0 ) + ( currentDensity "Via" 1.0 ) + ( currentDensity "Metal2" 1.0 ) + ) ;characterizationRules + +) ;electricalRules + + +;******************************** +; LAYOUT EDITOR RULES +;******************************** +; specifies the ordering of the layers in the LSW + +leRules( + leLswLayers( + ;( layer purpose ) + ; ----- ------- ) + ( Nwell drawing ) + ( Pselect drawing ) + ( Nselect drawing ) + ( Active drawing ) + ( ActX drawing ) + ( Poly1 drawing ) + ( P1Con drawing ) + ( Metal1 drawing ) + ( Via drawing ) + ( Metal2 drawing ) + ( Via2 drawing ) + ( Metal3 drawing ) + ( Poly1 pin ) + ( Metal1 pin ) + ( Metal2 pin ) + ( Metal3 pin ) + ( Poly2 drawing ) + ( P2Con drawing ) + ( instance drawing ) + ( text drawing ) + ( CapWell drawing ) + ( SiBlock drawing ) + ( HR drawing ) + ( Pbase drawing ) + ( Resistor drawing ) + ( Capacitor drawing ) + ( Diode drawing ) + ( Glass drawing ) + ( XP drawing ) + + ) ;leLswLayers +) ;leRules + + +;******************************** +; VIRTUOSO XL RULES +;******************************** +; specifies the ordering of the layers in the LSW + +lxRules( + lxExtractLayers( + (Metal1 Metal2 Metal3) + ) ;lxExtractLayers +) ;lxRules + diff --git a/technology/scn4m_subm/mag_lib/cell_1w_1r.mag b/technology/scn4m_subm/mag_lib/cell_1w_1r.mag new file mode 100644 index 00000000..9aec1c5d --- /dev/null +++ b/technology/scn4m_subm/mag_lib/cell_1w_1r.mag @@ -0,0 +1,142 @@ +magic +tech scmos +timestamp 1542220294 +<< 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 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 +rect 0 61 54 65 +rect 10 44 14 61 +rect 17 51 20 54 +rect 17 47 27 51 +rect 17 37 20 47 +rect 34 44 37 54 +rect 27 40 37 44 +rect 40 44 44 61 +rect 34 37 37 40 +rect 6 33 9 37 +rect 45 33 48 37 +rect 25 23 29 29 +rect 25 13 29 17 +rect 0 9 25 13 +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 +rect 9 21 13 72 +rect 25 58 29 68 +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 48 0 52 33 +<< comment >> +rect 0 0 54 70 +<< labels >> +rlabel metal1 19 63 19 63 1 wl0 +rlabel metal1 19 70 19 70 5 vdd +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +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 +<< 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 new file mode 100644 index 00000000..f215ff04 --- /dev/null +++ b/technology/scn4m_subm/mag_lib/replica_cell_1w_1r.mag @@ -0,0 +1,145 @@ +magic +tech scmos +timestamp 1542221056 +<< 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 +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 +rect 0 61 54 65 +rect 10 44 14 61 +rect 29 54 33 58 +rect 17 51 20 54 +rect 17 47 27 51 +rect 17 37 20 47 +rect 34 44 37 54 +rect 27 40 37 44 +rect 40 44 44 61 +rect 34 37 37 40 +rect 6 33 9 37 +rect 45 33 48 37 +rect 25 23 29 29 +rect 25 13 29 17 +rect 0 9 25 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 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 +rect 9 21 13 72 +rect 25 58 29 68 +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 48 0 52 33 +<< comment >> +rect 0 0 54 70 +<< labels >> +rlabel metal1 19 63 19 63 1 wl0 +rlabel metal1 19 70 19 70 5 vdd +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +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 +<< end >> diff --git a/technology/scn4m_subm/tech/SCN4M_SUBM.20.tech b/technology/scn4m_subm/tech/SCN4M_SUBM.20.tech index deaae865..7207f681 100644 --- a/technology/scn4m_subm/tech/SCN4M_SUBM.20.tech +++ b/technology/scn4m_subm/tech/SCN4M_SUBM.20.tech @@ -1764,6 +1764,11 @@ cifinput style lambda=0.20(p) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -2450,10 +2455,6 @@ style lambda=0.20(p) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -2470,6 +2471,11 @@ style lambda=0.20(p) style lambda=0.20(s) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -3158,10 +3164,6 @@ style lambda=0.20(s) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -3178,6 +3180,11 @@ style lambda=0.20(s) style lambda=0.20(ps) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -3810,10 +3817,6 @@ style lambda=0.20(ps) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -3830,6 +3833,11 @@ style lambda=0.20(ps) style lambda=0.20() scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -4516,10 +4524,6 @@ style lambda=0.20() and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -4536,6 +4540,11 @@ style lambda=0.20() style lambda=0.20(c) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -4989,10 +4998,6 @@ style lambda=0.20(c) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -5009,6 +5014,11 @@ style lambda=0.20(c) style lambda=0.20(cs) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -5464,10 +5474,6 @@ style lambda=0.20(cs) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -5484,6 +5490,11 @@ style lambda=0.20(cs) style lambda=0.20(cps) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -5940,10 +5951,6 @@ style lambda=0.20(cps) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * @@ -5960,6 +5967,11 @@ style lambda=0.20(cps) style lambda=0.20(cp) scalefactor 20 + # This is a custom section to add bounding boxes in OpenRAM + layer bb BB + labels BB + calma BB 63 0 + layer nwell CWN and-not CWNR and-not CTA @@ -6414,10 +6426,6 @@ style lambda=0.20(cp) and-not CBA calma CAA 43 * - layer comment CX - labels CX - calma CX 63 * - calma CTA 60 * calma CRW 65 * diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 15278c7b..a5756ce3 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -9,7 +9,7 @@ import os from design_rules import * """ -File containing the process technology parameters for SCMOS 3me, subm, 180nm. +File containing the process technology parameters for SCMOS 4m, 0.35um """ #GDS file info @@ -86,8 +86,8 @@ drc["has_nwell"] = True drc["grid"]=0.5*_lambda_ #DRC/LVS test set_up -drc["drc_rules"]=drclvs_home+"/calibreDRC_scn3me_subm.rul" -drc["lvs_rules"]=drclvs_home+"/calibreLVS_scn3me_subm.rul" +drc["drc_rules"]=None #drclvs_home+"/calibreDRC_scn3me_subm.rul" +drc["lvs_rules"]=None #drclvs_home+"/calibreLVS_scn3me_subm.rul" drc["layer_map"]=os.environ.get("OPENRAM_TECH")+"/scn3me_subm/layers.map" # minwidth_tx with contact (no dog bone transistors) From 17d42d43b487cb74a306bacd39d89be601d8e4c8 Mon Sep 17 00:00:00 2001 From: mrg Date: Sun, 26 May 2019 22:30:54 -0700 Subject: [PATCH 033/234] Add boundary layer --- .../scn3me_subm/gds_lib/cell_1rw_1r.gds | Bin 6394 -> 6458 bytes technology/scn3me_subm/gds_lib/cell_1w_1r.gds | Bin 6390 -> 6454 bytes .../gds_lib/replica_cell_1rw_1r.gds | Bin 6346 -> 6410 bytes .../gds_lib/replica_cell_1w_1r.gds | Bin 6342 -> 6406 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds b/technology/scn3me_subm/gds_lib/cell_1rw_1r.gds index a4fea073f7794ef11cbd2daa04f721b08f919b4f..f9a19873f4bff1427a2f5ceea7c33f32d9b6df44 100644 GIT binary patch delta 53 zcmexmxXWmQJhL2w`a~sL5VbKWNSuR%fq{*eiNSv29tFOT1O_mG(3@9@2QUHvN4^Tr delta 26 fcmdmG^viI9JTn)A{zN5P5VbKWNPP1baW_T)YsLq# diff --git a/technology/scn3me_subm/gds_lib/cell_1w_1r.gds b/technology/scn3me_subm/gds_lib/cell_1w_1r.gds index 382018a72c5508ba11ee26a0f7b90ab724a76510..41cff8af7f7b4c2e2212a810a2b1d26337ea0000 100644 GIT binary patch delta 60 zcmexnxXoySJhL2w`a~sb5VbKOK%9evfq{*eiNSv24h6xG1O_mG(F~I>ipy_4A+E;= E0FgxuRsaA1 delta 30 jcmdmH^v!UBJTn)A{zN5f5VbKOKzy=`7TeWH>ph}xJXCC`7TeWH>xh}xJTA Date: Mon, 27 May 2019 16:19:29 -0700 Subject: [PATCH 034/234] Pbitcell updates. Fix module offset error. Add boundary for debugging. Line wrap code. --- compiler/base/design.py | 2 + compiler/bitcells/pbitcell.py | 106 ++++++++++++++++++++-------------- 2 files changed, 66 insertions(+), 42 deletions(-) diff --git a/compiler/base/design.py b/compiler/base/design.py index 516eef80..b6651dd4 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -30,6 +30,8 @@ class design(hierarchy_design): self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space, self.m3_space) if contact.m3m4: self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space) + else: + self.m3_pitch = self.m2_pitch def setup_drc_constants(self): """ These are some DRC constants used in many places in the compiler.""" diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index e045b763..c9eb3f58 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -79,9 +79,7 @@ class pbitcell(design.design): # in netlist_only mode, calling offset_all_coordinates or translate_all will not be possible # this function is not needed to calculate the dimensions of pbitcell in netlist_only mode though if not OPTS.netlist_only: - self.offset_all_coordinates() - gnd_overlap = vector(0, 0.5*contact.well.width) - self.translate_all(gnd_overlap) + self.translate_all(vector(self.leftmost_xpos, self.botmost_ypos)) def add_pins(self): @@ -141,7 +139,8 @@ class pbitcell(design.design): def add_modules(self): """ Determine size of transistors and add ptx modules """ - # if there are any read/write ports, then the inverter nmos is sized based the number of read/write ports + # if there are any read/write ports, + # then the inverter nmos is sized based the number of read/write ports if(self.num_rw_ports > 0): inverter_nmos_width = self.num_rw_ports*parameter["6T_inv_nmos_size"] inverter_pmos_width = parameter["6T_inv_pmos_size"] @@ -149,7 +148,8 @@ class pbitcell(design.design): write_nmos_width = parameter["6T_access_size"] read_nmos_width = 2*parameter["6T_inv_pmos_size"] - # if there are no read/write ports, then the inverter nmos is statically sized for the dual port case + # if there are no read/write ports, + # then the inverter nmos is statically sized for the dual port case else: inverter_nmos_width = 2*parameter["6T_inv_pmos_size"] inverter_pmos_width = parameter["6T_inv_pmos_size"] @@ -183,14 +183,21 @@ class pbitcell(design.design): def calculate_spacing(self): """ Calculate transistor spacings """ + # calculate metal contact extensions over transistor active - readwrite_nmos_contact_extension = 0.5*(self.readwrite_nmos.active_contact.height - self.readwrite_nmos.active_height) - write_nmos_contact_extension = 0.5*(self.write_nmos.active_contact.height - self.write_nmos.active_height) - read_nmos_contact_extension = 0.5*(self.read_nmos.active_contact.height - self.read_nmos.active_height) - max_contact_extension = max(readwrite_nmos_contact_extension, write_nmos_contact_extension, read_nmos_contact_extension) + readwrite_nmos_contact_extension = 0.5*(self.readwrite_nmos.active_contact.height \ + - self.readwrite_nmos.active_height) + write_nmos_contact_extension = 0.5*(self.write_nmos.active_contact.height \ + - self.write_nmos.active_height) + read_nmos_contact_extension = 0.5*(self.read_nmos.active_contact.height \ + - self.read_nmos.active_height) + max_contact_extension = max(readwrite_nmos_contact_extension, + write_nmos_contact_extension, + read_nmos_contact_extension) # y-offset for the access transistor's gate contact - self.gate_contact_yoffset = max_contact_extension + self.m2_space + 0.5*max(contact.poly.height, contact.m1m2.height) + self.gate_contact_yoffset = max_contact_extension + self.m2_space \ + + 0.5*max(contact.poly.height, contact.m1m2.height) # y-position of access transistors self.port_ypos = self.m1_space + 0.5*contact.m1m2.height + self.gate_contact_yoffset @@ -199,8 +206,10 @@ class pbitcell(design.design): self.inverter_nmos_ypos = self.port_ypos # spacing between ports (same for read/write and write ports) - self.bitline_offset = -0.5*self.readwrite_nmos.active_width + 0.5*contact.m1m2.height + self.m2_space + self.m2_width - m2_constraint = self.bitline_offset + self.m2_space + 0.5*contact.m1m2.height - 0.5*self.readwrite_nmos.active_width + self.bitline_offset = -0.5*self.readwrite_nmos.active_width + 0.5*contact.m1m2.height \ + + self.m2_space + self.m2_width + m2_constraint = self.bitline_offset + self.m2_space + 0.5*contact.m1m2.height \ + - 0.5*self.readwrite_nmos.active_width self.write_port_spacing = max(self.active_space, self.m1_space, m2_constraint) self.read_port_spacing = self.bitline_offset + self.m2_space @@ -211,7 +220,7 @@ class pbitcell(design.design): inverter_pmos_contact_extension = 0.5*(self.inverter_pmos.active_contact.height - self.inverter_pmos.active_height) inverter_nmos_contact_extension = 0.5*(self.inverter_nmos.active_contact.height - self.inverter_nmos.active_height) self.inverter_gap = max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \ - + self.poly_to_polycontact + 2*contact.poly.width \ + + self.poly_to_polycontact + 2*contact.poly.height \ + self.m1_space + inverter_pmos_contact_extension self.cross_couple_lower_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \ + max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \ @@ -222,11 +231,11 @@ class pbitcell(design.design): + 1.5*contact.poly.width # spacing between wordlines (and gnd) - self.rowline_spacing = self.m1_space + contact.m1m2.width - self.rowline_offset = -0.5*self.m1_width + self.m1_offset = -0.5*self.m1_width # spacing for vdd - implant_constraint = max(inverter_pmos_contact_extension, 0) + 2*self.implant_enclose_active + 0.5*(contact.well.width - self.m1_width) + implant_constraint = max(inverter_pmos_contact_extension, 0) + 2*self.implant_enclose_active \ + + 0.5*(contact.well.width - self.m1_width) metal1_constraint = max(inverter_pmos_contact_extension, 0) + self.m1_space self.vdd_offset = max(implant_constraint, metal1_constraint) + 0.5*self.m1_width @@ -236,8 +245,10 @@ class pbitcell(design.design): def calculate_postions(self): """ Calculate positions that describe the edges and dimensions of the cell """ - self.botmost_ypos = -0.5*self.m1_width - self.total_ports*self.rowline_spacing - self.topmost_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height + self.inverter_gap + self.inverter_pmos.active_height + self.vdd_offset + self.botmost_ypos = self.m1_offset - self.total_ports*self.m1_pitch + self.topmost_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \ + + self.inverter_gap + self.inverter_pmos.active_height \ + + self.vdd_offset self.leftmost_xpos = -0.5*self.inverter_to_inverter_spacing - self.inverter_nmos.active_width \ - self.num_rw_ports*(self.readwrite_nmos.active_width + self.write_port_spacing) \ @@ -247,9 +258,14 @@ class pbitcell(design.design): self.width = -2*self.leftmost_xpos self.height = self.topmost_ypos - self.botmost_ypos - self.center_ypos = 0.5*(self.topmost_ypos + self.botmost_ypos) - + + # Add this boundary for visual debug + self.add_rect(layer="boundary", + offset=vector(self.leftmost_xpos,self.botmost_ypos), + height=self.height, + width=self.width) + def create_storage(self): """ Creates the crossed coupled inverters that act as storage for the bitcell. @@ -307,13 +323,15 @@ class pbitcell(design.design): width=contact.active.second_layer_width) # add contacts to connect gate poly to drain/source metal1 (to connect Q to Q_bar) - contact_offset_left = vector(self.inverter_nmos_left.get_pin("D").rc().x + 0.5*contact.poly.height, self.cross_couple_upper_ypos) + contact_offset_left = vector(self.inverter_nmos_left.get_pin("D").rc().x + 0.5*contact.poly.height, + self.cross_couple_upper_ypos) self.add_via_center(layers=("poly", "contact", "metal1"), offset=contact_offset_left, directions=("H","H")) - contact_offset_right = vector(self.inverter_nmos_right.get_pin("S").lc().x - 0.5*contact.poly.height, self.cross_couple_lower_ypos) + contact_offset_right = vector(self.inverter_nmos_right.get_pin("S").lc().x - 0.5*contact.poly.height, + self.cross_couple_lower_ypos) self.add_via_center(layers=("poly", "contact", "metal1"), offset=contact_offset_right, directions=("H","H")) @@ -328,21 +346,21 @@ class pbitcell(design.design): def route_rails(self): """ Adds gnd and vdd rails and connects them to the inverters """ # Add rails for vdd and gnd - gnd_ypos = self.rowline_offset - self.total_ports*self.rowline_spacing + gnd_ypos = self.m1_offset - self.total_ports*self.m1_pitch self.gnd_position = vector(0, gnd_ypos) self.add_rect_center(layer="metal1", offset=self.gnd_position, - width=self.width, - height=self.m1_width) + width=self.width) self.add_power_pin("gnd", vector(0,gnd_ypos)) - vdd_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height + self.inverter_gap + self.inverter_pmos.active_height + self.vdd_offset + vdd_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \ + + self.inverter_gap + self.inverter_pmos.active_height \ + + self.vdd_offset self.vdd_position = vector(0, vdd_ypos) self.add_rect_center(layer="metal1", offset=self.vdd_position, - width=self.width, - height=self.m1_width) + width=self.width) self.add_power_pin("vdd", vector(0,vdd_ypos)) def create_readwrite_ports(self): @@ -393,13 +411,12 @@ class pbitcell(design.design): self.readwrite_nmos_right[k].place(offset=[right_readwrite_transistor_xpos, self.port_ypos]) # add pin for RWWL - rwwl_ypos = self.rowline_offset - k*self.rowline_spacing + rwwl_ypos = self.m1_offset - k*self.m1_pitch self.rwwl_positions[k] = vector(0, rwwl_ypos) self.add_layout_pin_rect_center(text=self.rw_wl_names[k], layer="metal1", offset=self.rwwl_positions[k], - width=self.width, - height=self.m1_width) + width=self.width) # add pins for RWBL and RWBR rwbl_xpos = left_readwrite_transistor_xpos - self.bitline_offset + 0.5*self.m2_width @@ -409,7 +426,8 @@ class pbitcell(design.design): offset=self.rwbl_positions[k], height=self.height) - rwbr_xpos = right_readwrite_transistor_xpos + self.readwrite_nmos.active_width + self.bitline_offset - 0.5*self.m2_width + rwbr_xpos = right_readwrite_transistor_xpos + self.readwrite_nmos.active_width \ + + self.bitline_offset - 0.5*self.m2_width self.rwbr_positions[k] = vector(rwbr_xpos, self.center_ypos) self.add_layout_pin_rect_center(text=self.rw_br_names[k], layer="metal2", @@ -468,13 +486,13 @@ class pbitcell(design.design): self.write_nmos_right[k].place(offset=[right_write_transistor_xpos, self.port_ypos]) # add pin for WWL - wwl_ypos = rwwl_ypos = self.rowline_offset - self.num_rw_ports*self.rowline_spacing - k*self.rowline_spacing + wwl_ypos = rwwl_ypos = self.m1_offset - self.num_rw_ports*self.m1_pitch \ + - k*self.m1_pitch self.wwl_positions[k] = vector(0, wwl_ypos) self.add_layout_pin_rect_center(text=self.w_wl_names[k], layer="metal1", offset=self.wwl_positions[k], - width=self.width, - height=self.m1_width) + width=self.width) # add pins for WBL and WBR wbl_xpos = left_write_transistor_xpos - self.bitline_offset + 0.5*self.m2_width @@ -484,7 +502,8 @@ class pbitcell(design.design): offset=self.wbl_positions[k], height=self.height) - wbr_xpos = right_write_transistor_xpos + self.write_nmos.active_width + self.bitline_offset - 0.5*self.m2_width + wbr_xpos = right_write_transistor_xpos + self.write_nmos.active_width + self.bitline_offset \ + - 0.5*self.m2_width self.wbr_positions[k] = vector(wbr_xpos, self.center_ypos) self.add_layout_pin_rect_center(text=self.w_br_names[k], layer="metal2", @@ -565,13 +584,13 @@ class pbitcell(design.design): self.read_nmos_right[k].place(offset=[right_read_transistor_xpos+overlap_offset, self.port_ypos]) # add pin for RWL - rwl_ypos = rwwl_ypos = self.rowline_offset - self.num_rw_ports*self.rowline_spacing - self.num_w_ports*self.rowline_spacing - k*self.rowline_spacing + rwl_ypos = rwwl_ypos = self.m1_offset - self.num_rw_ports*self.m1_pitch \ + - self.num_w_ports*self.m1_pitch - k*self.m1_pitch self.rwl_positions[k] = vector(0, rwl_ypos) self.add_layout_pin_rect_center(text=self.r_wl_names[k], layer="metal1", offset=self.rwl_positions[k], - width=self.width, - height=self.m1_width) + width=self.width) # add pins for RBL and RBR rbl_xpos = left_read_transistor_xpos - self.bitline_offset + 0.5*self.m2_width @@ -581,7 +600,8 @@ class pbitcell(design.design): offset=self.rbl_positions[k], height=self.height) - rbr_xpos = right_read_transistor_xpos + self.read_port_width + self.bitline_offset - 0.5*self.m2_width + rbr_xpos = right_read_transistor_xpos + self.read_port_width + self.bitline_offset \ + - 0.5*self.m2_width self.rbr_positions[k] = vector(rbr_xpos, self.center_ypos) self.add_layout_pin_rect_center(text=self.r_br_names[k], layer="metal2", @@ -739,12 +759,14 @@ class pbitcell(design.design): def route_read_access(self): """ Routes read access transistors to the storage component of the bitcell """ # add poly to metal1 contacts for gates of the inverters - left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x - self.poly_to_polycontact - 0.5*contact.poly.width, self.cross_couple_upper_ypos) + left_storage_contact = vector(self.inverter_nmos_left.get_pin("G").lc().x - self.poly_to_polycontact - 0.5*contact.poly.width, + self.cross_couple_upper_ypos) self.add_via_center(layers=("poly", "contact", "metal1"), offset=left_storage_contact, directions=("H","H")) - right_storage_contact = vector(self.inverter_nmos_right.get_pin("G").rc().x + self.poly_to_polycontact + 0.5*contact.poly.width, self.cross_couple_upper_ypos) + right_storage_contact = vector(self.inverter_nmos_right.get_pin("G").rc().x + self.poly_to_polycontact + 0.5*contact.poly.width, + self.cross_couple_upper_ypos) self.add_via_center(layers=("poly", "contact", "metal1"), offset=right_storage_contact, directions=("H","H")) From fc12ea24e9292d1d94432bd656d91d6440d266ff Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 27 May 2019 16:32:38 -0700 Subject: [PATCH 035/234] Add boundary to every module and pgate for visual debug. --- compiler/base/hierarchy_layout.py | 7 +++++++ compiler/bitcells/pbitcell.py | 6 +----- compiler/modules/bank.py | 1 + compiler/modules/bank_select.py | 1 + compiler/modules/bitcell_array.py | 2 ++ compiler/modules/control_logic.py | 3 ++- compiler/modules/delay_chain.py | 3 ++- compiler/modules/dff_array.py | 1 + compiler/modules/dff_buf.py | 1 + compiler/modules/dff_buf_array.py | 1 + compiler/modules/dff_inv.py | 1 + compiler/modules/dff_inv_array.py | 1 + compiler/modules/hierarchical_decoder.py | 1 + compiler/modules/hierarchical_predecode2x4.py | 1 + compiler/modules/hierarchical_predecode3x8.py | 1 + compiler/modules/precharge_array.py | 1 + compiler/modules/replica_bitline.py | 1 + compiler/modules/sense_amp_array.py | 1 + compiler/modules/single_level_column_mux_array.py | 1 + compiler/modules/tri_gate_array.py | 1 + compiler/modules/wordline_driver.py | 1 + compiler/modules/write_driver_array.py | 1 + compiler/pgates/pgate.py | 7 ++++--- 23 files changed, 35 insertions(+), 10 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index e8c1b0b9..2972ecf8 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -879,6 +879,13 @@ class layout(): Wrapper to create a horizontal channel route """ self.create_channel_route(netlist, offset, layer_stack, pitch, vertical=False) + + def add_boundary(self): + """ Add boundary for debugging dimensions """ + self.add_rect(layer="boundary", + offset=vector(0,0), + height=self.height, + width=self.width) def add_enclosure(self, insts, layer="nwell"): """ Add a layer that surrounds the given instances. Useful diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index c9eb3f58..3f0a6073 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -36,6 +36,7 @@ class pbitcell(design.design): self.create_netlist() # We must always create the bitcell layout because some transistor sizes in the other netlists depend on it self.create_layout() + self.add_boundary() def create_netlist(self): self.add_pins() @@ -260,11 +261,6 @@ class pbitcell(design.design): self.height = self.topmost_ypos - self.botmost_ypos self.center_ypos = 0.5*(self.topmost_ypos + self.botmost_ypos) - # Add this boundary for visual debug - self.add_rect(layer="boundary", - offset=vector(self.leftmost_xpos,self.botmost_ypos), - height=self.height, - width=self.width) def create_storage(self): """ diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index a854c40b..e7ec2967 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -47,6 +47,7 @@ class bank(design.design): if not OPTS.netlist_only: debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.") self.create_layout() + self.add_boundary() def create_netlist(self): diff --git a/compiler/modules/bank_select.py b/compiler/modules/bank_select.py index ac866456..41588e70 100644 --- a/compiler/modules/bank_select.py +++ b/compiler/modules/bank_select.py @@ -42,6 +42,7 @@ class bank_select(design.design): self.place_instances() self.route_instances() + self.add_boundary() self.DRC_LVS() diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index f2ab77ac..0bc4011c 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -68,6 +68,8 @@ class bitcell_array(design.design): self.add_layout_pins() + self.add_boundary() + self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 0bf309a6..3c6e31b4 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -67,6 +67,7 @@ class control_logic(design.design): self.place_instances() self.route_all() #self.add_lvs_correspondence_points() + self.add_boundary() self.DRC_LVS() @@ -969,4 +970,4 @@ class control_logic(design.design): total_cin += self.wl_en_driver.get_cin() if self.port_type == 'rw': total_cin +=self.and2.get_cin() - return total_cin \ No newline at end of file + return total_cin diff --git a/compiler/modules/delay_chain.py b/compiler/modules/delay_chain.py index 188efffa..99b5875b 100644 --- a/compiler/modules/delay_chain.py +++ b/compiler/modules/delay_chain.py @@ -52,8 +52,9 @@ class delay_chain(design.design): self.place_inverters() self.route_inverters() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() - + def add_pins(self): """ Add the pins of the delay chain""" self.add_pin("in") diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 8b03fe19..53e6b0ba 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -44,6 +44,7 @@ class dff_array(design.design): self.place_dff_array() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 42e86bc0..d113cd14 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -55,6 +55,7 @@ class dff_buf(design.design): self.place_instances() self.route_wires() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index dfd38760..8b107f04 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -49,6 +49,7 @@ class dff_buf_array(design.design): self.height = self.rows * self.dff.height self.place_dff_array() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/dff_inv.py b/compiler/modules/dff_inv.py index 2f831570..7eecfc68 100644 --- a/compiler/modules/dff_inv.py +++ b/compiler/modules/dff_inv.py @@ -53,6 +53,7 @@ class dff_inv(design.design): self.add_wires() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py index 3ae50a08..c8743722 100644 --- a/compiler/modules/dff_inv_array.py +++ b/compiler/modules/dff_inv_array.py @@ -49,6 +49,7 @@ class dff_inv_array(design.design): self.place_dff_array() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 1eac268d..b316e631 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -54,6 +54,7 @@ class hierarchical_decoder(design.design): self.route_predecode_rails() self.route_vdd_gnd() self.offset_all_coordinates() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/hierarchical_predecode2x4.py b/compiler/modules/hierarchical_predecode2x4.py index 938196d3..1efdae20 100644 --- a/compiler/modules/hierarchical_predecode2x4.py +++ b/compiler/modules/hierarchical_predecode2x4.py @@ -47,6 +47,7 @@ class hierarchical_predecode2x4(hierarchical_predecode): self.place_output_inverters() self.place_nand_array() self.route() + self.add_boundary() self.DRC_LVS() def get_nand_input_line_combination(self): diff --git a/compiler/modules/hierarchical_predecode3x8.py b/compiler/modules/hierarchical_predecode3x8.py index 77d9ce01..85069202 100644 --- a/compiler/modules/hierarchical_predecode3x8.py +++ b/compiler/modules/hierarchical_predecode3x8.py @@ -52,6 +52,7 @@ class hierarchical_predecode3x8(hierarchical_predecode): self.place_output_inverters() self.place_nand_array() self.route() + self.add_boundary() self.DRC_LVS() def get_nand_input_line_combination(self): diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index f88938c8..fa19d3d5 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -51,6 +51,7 @@ class precharge_array(design.design): self.place_insts() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index acd1f5d0..1371bb68 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -49,6 +49,7 @@ class replica_bitline(design.design): self.width = self.replica_column_inst.rx() - self.delay_chain_inst.lx() + self.m2_pitch self.height = max(self.replica_column_inst.uy(), self.delay_chain_inst.uy()) + self.m3_pitch + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 4dfa03ad..81b2218d 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -50,6 +50,7 @@ class sense_amp_array(design.design): self.place_sense_amp_array() self.add_layout_pins() self.route_rails() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 435f0cbe..e7a72856 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -52,6 +52,7 @@ class single_level_column_mux_array(design.design): self.add_layout_pins() self.add_enclosure(self.mux_inst, "pwell") + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/tri_gate_array.py b/compiler/modules/tri_gate_array.py index e3eb42cb..54760572 100644 --- a/compiler/modules/tri_gate_array.py +++ b/compiler/modules/tri_gate_array.py @@ -41,6 +41,7 @@ class tri_gate_array(design.design): self.place_array() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_modules(self): diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index dbef0417..f81cdd1a 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -44,6 +44,7 @@ class wordline_driver(design.design): self.route_layout() self.route_vdd_gnd() self.offset_all_coordinates() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 27da84b0..c2ceb386 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -50,6 +50,7 @@ class write_driver_array(design.design): self.place_write_array() self.add_layout_pins() + self.add_boundary() self.DRC_LVS() def add_pins(self): diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index 57b73a21..40c04cb6 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -31,17 +31,18 @@ class pgate(design.design): self.create_netlist() if not OPTS.netlist_only: self.create_layout() + self.add_boundary() self.DRC_LVS() - def create_netlist(): + def create_netlist(self): """ Pure virtual function """ debug.error("Must over-ride create_netlist.",-1) - def create_layout(): + def create_layout(self): """ Pure virtual function """ debug.error("Must over-ride create_layout.",-1) - + def connect_pin_to_rail(self,inst,pin,supply): """ Connects a ptx pin to a supply rail. """ source_pin = inst.get_pin(pin) From 4612c9c182da6ee416461aa9e020e22316cd6bf0 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 27 May 2019 16:38:47 -0700 Subject: [PATCH 036/234] Move power pins before no route option --- compiler/sram/sram_base.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 192bc669..be422135 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -129,14 +129,15 @@ class sram_base(design, verilog, lef): def route_supplies(self): """ Route the supply grid and connect the pins to them. """ + # Copy the pins to the top level + # This will either be used to route or left unconnected. + for inst in self.insts: + self.copy_power_pins(inst,"vdd") + self.copy_power_pins(inst,"gnd") # Do not route the power supply if not OPTS.route_supplies: return - for inst in self.insts: - self.copy_power_pins(inst,"vdd") - self.copy_power_pins(inst,"gnd") - from supply_router import supply_router as router layer_stack =("metal3","via3","metal4") rtr=router(layer_stack, self) @@ -579,4 +580,4 @@ class sram_base(design, verilog, lef): total_cin += self.data_dff.get_clk_cin() if self.col_addr_size > 0: total_cin += self.col_addr_dff.get_clk_cin() - return total_cin \ No newline at end of file + return total_cin From bd4d965e37306a41f1cb1a98f331414aea63a35b Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 27 May 2019 17:38:59 -0700 Subject: [PATCH 037/234] Begin single layer supply router --- compiler/base/design.py | 7 +- compiler/drc/design_rules.py | 1 + compiler/router/router.py | 9 + compiler/router/router_tech.py | 54 ++---- ...supply_router.py => supply_grid_router.py} | 4 +- compiler/router/supply_tree_router.py | 176 ++++++++++++++++++ compiler/sram/sram_base.py | 18 +- 7 files changed, 224 insertions(+), 45 deletions(-) rename compiler/router/{supply_router.py => supply_grid_router.py} (99%) create mode 100644 compiler/router/supply_tree_router.py diff --git a/compiler/base/design.py b/compiler/base/design.py index b6651dd4..bbd5b6f6 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -26,16 +26,17 @@ class design(hierarchy_design): self.setup_drc_constants() self.setup_multiport_constants() + from tech import layer self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space, self.m2_space) self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space, self.m3_space) - if contact.m3m4: + if "metal4" in layer: self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space) else: self.m3_pitch = self.m2_pitch def setup_drc_constants(self): """ These are some DRC constants used in many places in the compiler.""" - from tech import drc + from tech import drc,layer self.well_width = drc("minwidth_well") self.poly_width = drc("minwidth_poly") self.poly_space = drc("poly_to_poly") @@ -45,7 +46,7 @@ class design(hierarchy_design): self.m2_space = drc("metal2_to_metal2") self.m3_width = drc("minwidth_metal3") self.m3_space = drc("metal3_to_metal3") - if contact.m3m4: + if "metal4" in layer: self.m4_width = drc("minwidth_metal4") self.m4_space = drc("metal4_to_metal4") self.active_width = drc("minwidth_active") diff --git a/compiler/drc/design_rules.py b/compiler/drc/design_rules.py index 09729144..db94c75b 100644 --- a/compiler/drc/design_rules.py +++ b/compiler/drc/design_rules.py @@ -42,6 +42,7 @@ class design_rules(): return rule else: debug.error("Must call complex DRC rule {} with arguments.".format(b),-1) + diff --git a/compiler/router/router.py b/compiler/router/router.py index f4e570a7..1b953dd4 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -839,6 +839,15 @@ class router(router_tech): self.rg.add_target(pin_in_tracks) + def add_pin_component_target_except(self, pin_name, index): + """ + This will mark the grids for all *other* pin components as a target. + Marking as source or target also clears blockage status. + """ + for i in range(self.num_pin_components(pin_name)): + if i != index: + self.add_pin_component_target(pin_name, i) + def set_component_blockages(self, pin_name, value=True): """ Block all of the pin components. diff --git a/compiler/router/router_tech.py b/compiler/router/router_tech.py index b82d4ac1..71ccaeec 100644 --- a/compiler/router/router_tech.py +++ b/compiler/router/router_tech.py @@ -24,19 +24,28 @@ class router_tech: """ self.layers = layers self.rail_track_width = rail_track_width - - (self.horiz_layer_name, self.via_layer_name, self.vert_layer_name) = self.layers - # This is the minimum routed track spacing - via_connect = contact(self.layers, (1, 1)) - max_via_size = max(via_connect.width,via_connect.height) - - self.horiz_layer_number = layer[self.horiz_layer_name] - self.vert_layer_number = layer[self.vert_layer_name] - - if self.rail_track_width>1: + print(self.layers,len(self.layers)) + if len(self.layers)==1: + self.horiz_layer_name = self.vert_layer_name = self.layers[0] + self.horiz_layer_number = self.vert_layer_number = layer[self.layers[0]] + (self.vert_layer_minwidth, self.vert_layer_spacing) = self.get_supply_layer_width_space(1) (self.horiz_layer_minwidth, self.horiz_layer_spacing) = self.get_supply_layer_width_space(0) + + self.horiz_track_width = self.horiz_layer_minwidth + self.horiz_layer_spacing + self.vert_track_width = self.vert_layer_minwidth + self.vert_layer_spacing + else: + (self.horiz_layer_name, self.via_layer_name, self.vert_layer_name) = self.layers + via_connect = contact(self.layers, (1, 1)) + max_via_size = max(via_connect.width,via_connect.height) + + self.horiz_layer_number = layer[self.horiz_layer_name] + self.vert_layer_number = layer[self.vert_layer_name] + + (self.vert_layer_minwidth, self.vert_layer_spacing) = self.get_supply_layer_width_space(1) + (self.horiz_layer_minwidth, self.horiz_layer_spacing) = self.get_supply_layer_width_space(0) + # For supplies, we will make the wire wider than the vias self.vert_layer_minwidth = max(self.vert_layer_minwidth, max_via_size) self.horiz_layer_minwidth = max(self.horiz_layer_minwidth, max_via_size) @@ -44,13 +53,6 @@ class router_tech: self.horiz_track_width = self.horiz_layer_minwidth + self.horiz_layer_spacing self.vert_track_width = self.vert_layer_minwidth + self.vert_layer_spacing - else: - (self.vert_layer_minwidth, self.vert_layer_spacing) = self.get_layer_width_space(1) - (self.horiz_layer_minwidth, self.horiz_layer_spacing) = self.get_layer_width_space(0) - - self.horiz_track_width = max_via_size + self.horiz_layer_spacing - self.vert_track_width = max_via_size + self.vert_layer_spacing - # We'll keep horizontal and vertical tracks the same for simplicity. self.track_width = max(self.horiz_track_width,self.vert_track_width) debug.info(1,"Track width: {:.3f}".format(self.track_width)) @@ -80,24 +82,6 @@ class router_tech: else: debug.error("Invalid zindex {}".format(zindex),-1) - def get_layer_width_space(self, zindex, width=0, length=0): - """ - Return the width and spacing of a given layer - and wire of a given width and length. - """ - if zindex==1: - layer_name = self.vert_layer_name - elif zindex==0: - layer_name = self.horiz_layer_name - else: - debug.error("Invalid zindex for track", -1) - - min_width = drc("minwidth_{0}".format(layer_name), width, length) - min_spacing = drc(str(layer_name)+"_to_"+str(layer_name), width, length) - - return (min_width,min_spacing) - - def get_supply_layer_width_space(self, zindex): """ These are the width and spacing of a supply layer given a supply rail diff --git a/compiler/router/supply_router.py b/compiler/router/supply_grid_router.py similarity index 99% rename from compiler/router/supply_router.py rename to compiler/router/supply_grid_router.py index 060451de..1c89a1d4 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_grid_router.py @@ -20,7 +20,7 @@ from datetime import datetime import grid import grid_utils -class supply_router(router): +class supply_grid_router(router): """ A router class to read an obstruction map from a gds and routes a grid to connect the supply on the two layers. @@ -391,7 +391,7 @@ class supply_router(router): # Add the single component of the pin as the source # which unmarks it as a blockage too - self.add_pin_component_source(pin_name,index) + self.add_pin_component_source(pin_name, index) # Add all of the rails as targets # Don't add the other pins, but we could? diff --git a/compiler/router/supply_tree_router.py b/compiler/router/supply_tree_router.py new file mode 100644 index 00000000..fd4dcad0 --- /dev/null +++ b/compiler/router/supply_tree_router.py @@ -0,0 +1,176 @@ +# 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 gdsMill +import tech +import math +import debug +from globals import OPTS,print_time +from contact import contact +from pin_group import pin_group +from pin_layout import pin_layout +from vector3d import vector3d +from router import router +from direction import direction +from datetime import datetime +import grid +import grid_utils + +class supply_tree_router(router): + """ + A router class to read an obstruction map from a gds and + routes a grid to connect the supply on the two layers. + """ + + def __init__(self, layers, design, gds_filename=None): + """ + This will route on layers in design. It will get the blockages from + either the gds file name or the design itself (by saving to a gds file). + """ + # Power rail width in minimum wire widths + self.rail_track_width = 3 + + router.__init__(self, layers, design, gds_filename, self.rail_track_width) + + + def create_routing_grid(self): + """ + Create a sprase routing grid with A* expansion functions. + """ + size = self.ur - self.ll + debug.info(1,"Size: {0} x {1}".format(size.x,size.y)) + + import supply_grid + self.rg = supply_grid.supply_grid(self.ll, self.ur, self.track_width) + + def route(self, vdd_name="vdd", gnd_name="gnd"): + """ + Route the two nets in a single layer) + """ + debug.info(1,"Running supply router on {0} and {1}...".format(vdd_name, gnd_name)) + self.vdd_name = vdd_name + self.gnd_name = gnd_name + + # Clear the pins if we have previously routed + if (hasattr(self,'rg')): + self.clear_pins() + else: + # Creat a routing grid over the entire area + # FIXME: This could be created only over the routing region, + # but this is simplest for now. + self.create_routing_grid() + + # Get the pin shapes + start_time = datetime.now() + self.find_pins_and_blockages([self.vdd_name, self.gnd_name]) + print_time("Finding pins and blockages",datetime.now(), start_time, 3) + + # Add the supply rails in a mesh network and connect H/V with vias + start_time = datetime.now() + # Block everything + self.prepare_blockages(self.gnd_name) + self.prepare_blockages(self.vdd_name) + + # Route the supply pins to the supply rails + # Route vdd first since we want it to be shorter + start_time = datetime.now() + self.route_pins(vdd_name) + self.route_pins(gnd_name) + print_time("Maze routing supplies",datetime.now(), start_time, 3) + #self.write_debug_gds("final.gds",False) + + # Did we route everything?? + if not self.check_all_routed(vdd_name): + return False + if not self.check_all_routed(gnd_name): + return False + + return True + + + def check_all_routed(self, pin_name): + """ + Check that all pin groups are routed. + """ + for pg in self.pin_groups[pin_name]: + if not pg.is_routed(): + return False + + def prepare_blockages(self, pin_name): + """ + Reset and add all of the blockages in the design. + Names is a list of pins to add as a blockage. + """ + debug.info(3,"Preparing blockages.") + + # Start fresh. Not the best for run-time, but simpler. + self.clear_blockages() + # This adds the initial blockges of the design + #print("BLOCKING:",self.blocked_grids) + self.set_blockages(self.blocked_grids,True) + + # Block all of the pin components (some will be unblocked if they're a source/target) + # Also block the previous routes + for name in self.pin_groups: + blockage_grids = {y for x in self.pin_groups[name] for y in x.grids} + self.set_blockages(blockage_grids,True) + blockage_grids = {y for x in self.pin_groups[name] for y in x.blockages} + self.set_blockages(blockage_grids,True) + + # FIXME: These duplicate a bit of work + # These are the paths that have already been routed. + self.set_blockages(self.path_blockages) + + # Don't mark the other components as targets since we want to route + # directly to a rail, but unblock all the source components so we can + # route over them + blockage_grids = {y for x in self.pin_groups[pin_name] for y in x.grids} + self.set_blockages(blockage_grids,False) + + + + def route_pins(self, pin_name): + """ + This will route each of the remaining pin components to the other pins. + After it is done, the cells are added to the pin blockage list. + """ + + remaining_components = sum(not x.is_routed() for x in self.pin_groups[pin_name]) + debug.info(1,"Maze routing {0} with {1} pin components to connect.".format(pin_name, + remaining_components)) + + for index,pg in enumerate(self.pin_groups[pin_name]): + if pg.is_routed(): + continue + + debug.info(3,"Routing component {0} {1}".format(pin_name, index)) + + # Clear everything in the routing grid. + self.rg.reinit() + + # This is inefficient since it is non-incremental, but it was + # easier to debug. + self.prepare_blockages(pin_name) + + # Add the single component of the pin as the source + # which unmarks it as a blockage too + self.add_pin_component_source(pin_name,index) + + # Marks all pin components except index as target + self.add_pin_component_target_except(pin_name,index) + + # Actually run the A* router + if not self.run_router(detour_scale=5): + self.write_debug_gds("debug_route.gds",False) + + #if index==3 and pin_name=="vdd": + # self.write_debug_gds("route.gds",False) + + + + + diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index be422135..0f37917c 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -134,14 +134,22 @@ class sram_base(design, verilog, lef): for inst in self.insts: self.copy_power_pins(inst,"vdd") self.copy_power_pins(inst,"gnd") - # Do not route the power supply + + + import tech if not OPTS.route_supplies: + # Do not route the power supply (leave as must-connect pins) return - - from supply_router import supply_router as router - layer_stack =("metal3","via3","metal4") - rtr=router(layer_stack, self) + elif "metal4" in tech.layer: + # Route a M3/M4 grid + from supply_grid_router import supply_grid_router as router + rtr=router(("metal3","via3","metal4"), self) + elif "metal3" in tech.layer: + from supply_tree_router import supply_tree_router as router + rtr=router(("metal3",), self) + rtr.route() + From 7b8c2cac301bba26686eefbb7213d5995a93933f Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 31 May 2019 08:43:37 -0700 Subject: [PATCH 038/234] Starting single layer power router. --- compiler/bitcells/pbitcell.py | 2 +- compiler/router/grid.py | 10 +++---- compiler/router/grid_cell.py | 13 ++++++--- compiler/router/router.py | 41 +++++++++++++++++++++------ compiler/router/router_tech.py | 2 +- compiler/router/supply_tree_router.py | 25 +++++++++++++--- compiler/sram_factory.py | 5 ++-- compiler/tests/testutils.py | 1 + 8 files changed, 73 insertions(+), 26 deletions(-) diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 3f0a6073..e548c829 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -221,7 +221,7 @@ class pbitcell(design.design): inverter_pmos_contact_extension = 0.5*(self.inverter_pmos.active_contact.height - self.inverter_pmos.active_height) inverter_nmos_contact_extension = 0.5*(self.inverter_nmos.active_contact.height - self.inverter_nmos.active_height) self.inverter_gap = max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \ - + self.poly_to_polycontact + 2*contact.poly.height \ + + self.poly_to_polycontact + 2*contact.poly.width \ + self.m1_space + inverter_pmos_contact_extension self.cross_couple_lower_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \ + max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \ diff --git a/compiler/router/grid.py b/compiler/router/grid.py index 4533b8e7..52bf7af8 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -50,7 +50,7 @@ class grid: self.add_map(vector3d(x,y,1)) def set_blocked(self,n,value=True): - if isinstance(n, (list,tuple,set,frozenset)): + if not isinstance(n, vector3d): for item in n: self.set_blocked(item,value) else: @@ -58,7 +58,7 @@ class grid: self.map[n].blocked=value def is_blocked(self,n): - if isinstance(n, (list,tuple,set,frozenset)): + if not isinstance(n, vector3d): for item in n: if self.is_blocked(item): return True @@ -82,7 +82,7 @@ class grid: self.map[k].blocked=False def set_source(self,n,value=True): - if isinstance(n, (list,tuple,set,frozenset)): + if not isinstance(n, vector3d): for item in n: self.set_source(item,value) else: @@ -91,7 +91,7 @@ class grid: self.source.add(n) def set_target(self,n,value=True): - if isinstance(n, (list,tuple,set,frozenset)): + if not isinstance(n, vector3d): for item in n: self.set_target(item,value) else: @@ -125,7 +125,7 @@ class grid: """ Add a point to the map if it doesn't exist. """ - if isinstance(n, (list,tuple,set,frozenset)): + if not isinstance(n, vector3d): for item in n: self.add_map(item) else: diff --git a/compiler/router/grid_cell.py b/compiler/router/grid_cell.py index d2816c28..354ef646 100644 --- a/compiler/router/grid_cell.py +++ b/compiler/router/grid_cell.py @@ -36,16 +36,21 @@ class grid_cell: def get_type(self): + type_string = "" + if self.blocked: - return "X" + type_string += "X" if self.source: - return "S" + type_string += "S" if self.target: - return "T" + type_string += "T" if self.path: - return "P" + type_string += "P" + if type_string != "": + return type_string + return None diff --git a/compiler/router/router.py b/compiler/router/router.py index 1b953dd4..ac27e0f4 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -668,7 +668,10 @@ class router(router_tech): track. """ # to scale coordinates to tracks - x = track[0]*self.track_width - 0.5*self.track_width + try: + x = track[0]*self.track_width - 0.5*self.track_width + except TypeError: + print(track[0],type(track[0]),self.track_width,type(self.track_width)) y = track[1]*self.track_width - 0.5*self.track_width # offset lowest corner object to to (-track halo,-track halo) ll = snap_to_grid(vector(x,y)) @@ -832,7 +835,7 @@ class router(router_tech): This will mark only the pin tracks from the indexed pin component as a target. It also unsets it as a blockage. """ - debug.check(index1: + self.cell.add_route(layers=self.layers, + coordinates=abs_path, + layer_widths=self.layer_widths) + else: + self.cell.add_path(layer=self.layers[0], + coordinates=abs_path, + width=self.layer_widths[0]) def add_single_enclosure(self, track): """ @@ -965,12 +973,19 @@ class router(router_tech): """ This assumes the blockages, source, and target are all set up. """ + + # Double check source and taget are not same node, if so, we are done! + for k,v in self.rg.map.items(): + if v.source and v.target: + debug.error("Grid cell is source and target! {}".format(k)) + return False + # returns the path in tracks (path,cost) = self.rg.route(detour_scale) if path: - debug.info(2,"Found path: cost={0} ".format(cost)) - debug.info(3,str(path)) - + debug.info(1,"Found path: cost={0} ".format(cost)) + debug.info(1,str(path)) + self.paths.append(path) self.add_route(path) @@ -1011,6 +1026,7 @@ class router(router_tech): Write out a GDS file with the routing grid and search information annotated on it. """ debug.info(0,"Writing annotated router gds file to {}".format(gds_name)) + self.del_router_info() self.add_router_info() self.cell.gds_write(gds_name) @@ -1062,6 +1078,15 @@ class router(router_tech): offset=shape[0], zoom=0.05) + def del_router_info(self): + """ + Erase all of the comments on the current level. + """ + debug.info(0,"Erasing router info") + layer_num = techlayer["text"] + self.cell.objs = [x for x in self.cell.objs if x.layerNumber != layer_num] + + def add_router_info(self): """ Write the routing grid and router cost, blockage, pins on diff --git a/compiler/router/router_tech.py b/compiler/router/router_tech.py index 71ccaeec..919e07ea 100644 --- a/compiler/router/router_tech.py +++ b/compiler/router/router_tech.py @@ -24,7 +24,7 @@ class router_tech: """ self.layers = layers self.rail_track_width = rail_track_width - print(self.layers,len(self.layers)) + if len(self.layers)==1: self.horiz_layer_name = self.vert_layer_name = self.layers[0] self.horiz_layer_number = self.vert_layer_number = layer[self.layers[0]] diff --git a/compiler/router/supply_tree_router.py b/compiler/router/supply_tree_router.py index fd4dcad0..7def03e0 100644 --- a/compiler/router/supply_tree_router.py +++ b/compiler/router/supply_tree_router.py @@ -74,13 +74,14 @@ class supply_tree_router(router): # Block everything self.prepare_blockages(self.gnd_name) self.prepare_blockages(self.vdd_name) - + # Route the supply pins to the supply rails # Route vdd first since we want it to be shorter start_time = datetime.now() self.route_pins(vdd_name) self.route_pins(gnd_name) print_time("Maze routing supplies",datetime.now(), start_time, 3) + #self.write_debug_gds("final.gds",False) # Did we route everything?? @@ -147,7 +148,7 @@ class supply_tree_router(router): if pg.is_routed(): continue - debug.info(3,"Routing component {0} {1}".format(pin_name, index)) + debug.info(1,"Routing component {0} {1}".format(pin_name, index)) # Clear everything in the routing grid. self.rg.reinit() @@ -159,13 +160,29 @@ class supply_tree_router(router): # Add the single component of the pin as the source # which unmarks it as a blockage too self.add_pin_component_source(pin_name,index) - + # Marks all pin components except index as target self.add_pin_component_target_except(pin_name,index) + # Add the prevous paths as a target too + self.add_path_target(self.paths) + print("SOURCE: ") + for k,v in self.rg.map.items(): + if v.source: + print(k) + + print("TARGET: ") + for k,v in self.rg.map.items(): + if v.target: + print(k) + + import pdb; pdb.set_trace() + if index==1: + self.write_debug_gds("debug{}.gds".format(pin_name),False) + # Actually run the A* router if not self.run_router(detour_scale=5): - self.write_debug_gds("debug_route.gds",False) + self.write_debug_gds("debug_route.gds",True) #if index==3 and pin_name=="vdd": # self.write_debug_gds("route.gds",False) diff --git a/compiler/sram_factory.py b/compiler/sram_factory.py index 325261a0..1a5a4ae2 100644 --- a/compiler/sram_factory.py +++ b/compiler/sram_factory.py @@ -7,8 +7,6 @@ # import debug from globals import OPTS -from importlib import reload - class sram_factory: """ @@ -54,7 +52,8 @@ class sram_factory: try: mod = self.modules[module_type] except KeyError: - c = reload(__import__(module_name)) + import importlib + c = importlib.reload(__import__(module_name)) mod = getattr(c, module_name) self.modules[module_type] = mod self.module_indices[module_type] = 0 diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index c6da0d49..3a01733a 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -281,6 +281,7 @@ class openram_test(unittest.TestCase): debug.info(2,"MATCH {0} {1}".format(filename1,filename2)) return True + def header(filename, technology): # Skip the header for gitlab regression import getpass From 8418aea95a6e172ec3effb81e0a55b41f014a008 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 3 Jun 2019 15:36:14 -0700 Subject: [PATCH 039/234] Revert height to width --- compiler/bitcells/pbitcell.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 3f0a6073..e548c829 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -221,7 +221,7 @@ class pbitcell(design.design): inverter_pmos_contact_extension = 0.5*(self.inverter_pmos.active_contact.height - self.inverter_pmos.active_height) inverter_nmos_contact_extension = 0.5*(self.inverter_nmos.active_contact.height - self.inverter_nmos.active_height) self.inverter_gap = max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \ - + self.poly_to_polycontact + 2*contact.poly.height \ + + self.poly_to_polycontact + 2*contact.poly.width \ + self.m1_space + inverter_pmos_contact_extension self.cross_couple_lower_ypos = self.inverter_nmos_ypos + self.inverter_nmos.active_height \ + max(self.poly_to_active, self.m1_space + inverter_nmos_contact_extension) \ From a234b0af88350b5053dfeb77af0c0fa5a7fcf5c6 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 14 Jun 2019 08:43:41 -0700 Subject: [PATCH 040/234] Fix space before comment --- compiler/base/contact.py | 8 ++++---- compiler/base/design.py | 8 ++++---- compiler/base/geometry.py | 8 ++++---- compiler/base/hierarchy_design.py | 8 ++++---- compiler/base/hierarchy_layout.py | 8 ++++---- compiler/base/hierarchy_spice.py | 8 ++++---- compiler/base/lef.py | 8 ++++---- compiler/base/pin_layout.py | 8 ++++---- compiler/base/route.py | 8 ++++---- compiler/base/utils.py | 8 ++++---- compiler/base/vector.py | 8 ++++---- compiler/base/verilog.py | 8 ++++---- compiler/base/wire.py | 8 ++++---- compiler/base/wire_path.py | 8 ++++---- compiler/bitcells/bitcell.py | 8 ++++---- compiler/bitcells/bitcell_1rw_1r.py | 8 ++++---- compiler/bitcells/bitcell_1w_1r.py | 8 ++++---- compiler/bitcells/pbitcell.py | 8 ++++---- compiler/bitcells/replica_bitcell.py | 8 ++++---- compiler/bitcells/replica_bitcell_1rw_1r.py | 8 ++++---- compiler/bitcells/replica_bitcell_1w_1r.py | 8 ++++---- compiler/bitcells/replica_pbitcell.py | 8 ++++---- compiler/characterizer/__init__.py | 8 ++++---- compiler/characterizer/bitline_delay.py | 8 ++++---- compiler/characterizer/charutils.py | 8 ++++---- compiler/characterizer/delay.py | 8 ++++---- compiler/characterizer/functional.py | 8 ++++---- compiler/characterizer/lib.py | 8 ++++---- compiler/characterizer/logical_effort.py | 8 ++++---- compiler/characterizer/measurements.py | 8 ++++---- compiler/characterizer/model_check.py | 8 ++++---- compiler/characterizer/setup_hold.py | 8 ++++---- compiler/characterizer/simulation.py | 8 ++++---- compiler/characterizer/stimuli.py | 8 ++++---- compiler/characterizer/trim_spice.py | 8 ++++---- compiler/characterizer/worst_case.py | 8 ++++---- compiler/datasheet/add_db.py | 8 ++++---- compiler/datasheet/datasheet.py | 8 ++++---- compiler/datasheet/datasheet_gen.py | 8 ++++---- compiler/datasheet/table_gen.py | 8 ++++---- compiler/debug.py | 8 ++++---- compiler/drc/design_rules.py | 8 ++++---- compiler/drc/drc_lut.py | 8 ++++---- compiler/drc/drc_value.py | 8 ++++---- compiler/gen_stimulus.py | 8 ++++---- compiler/globals.py | 8 ++++---- compiler/modules/bank.py | 8 ++++---- compiler/modules/bank_select.py | 8 ++++---- compiler/modules/bitcell_array.py | 8 ++++---- compiler/modules/control_logic.py | 8 ++++---- compiler/modules/delay_chain.py | 8 ++++---- compiler/modules/dff.py | 8 ++++---- compiler/modules/dff_array.py | 8 ++++---- compiler/modules/dff_buf.py | 8 ++++---- compiler/modules/dff_buf_array.py | 8 ++++---- compiler/modules/dff_inv.py | 8 ++++---- compiler/modules/dff_inv_array.py | 8 ++++---- compiler/modules/hierarchical_decoder.py | 8 ++++---- compiler/modules/hierarchical_predecode.py | 8 ++++---- compiler/modules/hierarchical_predecode2x4.py | 8 ++++---- compiler/modules/hierarchical_predecode3x8.py | 8 ++++---- compiler/modules/multibank.py | 8 ++++---- compiler/modules/precharge_array.py | 8 ++++---- compiler/modules/replica_bitline.py | 8 ++++---- compiler/modules/sense_amp.py | 8 ++++---- compiler/modules/sense_amp_array.py | 8 ++++---- compiler/modules/single_level_column_mux_array.py | 8 ++++---- compiler/modules/tri_gate.py | 8 ++++---- compiler/modules/tri_gate_array.py | 8 ++++---- compiler/modules/wordline_driver.py | 8 ++++---- compiler/modules/write_driver.py | 8 ++++---- compiler/modules/write_driver_array.py | 8 ++++---- compiler/openram.py | 8 ++++---- compiler/options.py | 8 ++++---- compiler/pgates/pand2.py | 8 ++++---- compiler/pgates/pbuf.py | 8 ++++---- compiler/pgates/pdriver.py | 8 ++++---- compiler/pgates/pgate.py | 8 ++++---- compiler/pgates/pinv.py | 8 ++++---- compiler/pgates/pinvbuf.py | 8 ++++---- compiler/pgates/pnand2.py | 8 ++++---- compiler/pgates/pnand3.py | 8 ++++---- compiler/pgates/pnor2.py | 8 ++++---- compiler/pgates/precharge.py | 8 ++++---- compiler/pgates/ptristate_inv.py | 8 ++++---- compiler/pgates/ptx.py | 8 ++++---- compiler/pgates/single_level_column_mux.py | 8 ++++---- compiler/router/direction.py | 8 ++++---- compiler/router/grid.py | 8 ++++---- compiler/router/grid_cell.py | 8 ++++---- compiler/router/grid_path.py | 8 ++++---- compiler/router/grid_utils.py | 8 ++++---- compiler/router/pin_group.py | 8 ++++---- compiler/router/router.py | 8 ++++---- compiler/router/router_tech.py | 8 ++++---- compiler/router/signal_grid.py | 8 ++++---- compiler/router/signal_router.py | 8 ++++---- compiler/router/supply_grid.py | 8 ++++---- compiler/router/supply_router.py | 8 ++++---- compiler/router/tests/01_no_blockages_test.py | 8 ++++---- compiler/router/tests/02_blockages_test.py | 8 ++++---- compiler/router/tests/03_same_layer_pins_test.py | 8 ++++---- compiler/router/tests/04_diff_layer_pins_test.py | 8 ++++---- compiler/router/tests/05_two_nets_test.py | 8 ++++---- compiler/router/tests/06_pin_location_test.py | 8 ++++---- compiler/router/tests/07_big_test.py | 8 ++++---- compiler/router/tests/08_expand_region_test.py | 8 ++++---- compiler/router/tests/10_supply_grid_test.py | 8 ++++---- compiler/router/tests/config_freepdk45.py | 8 ++++---- compiler/router/tests/config_scn4m_subm.py | 8 ++++---- compiler/router/tests/gds_cell.py | 8 ++++---- compiler/router/tests/regress.py | 8 ++++---- compiler/router/tests/testutils.py | 8 ++++---- compiler/router/vector3d.py | 8 ++++---- compiler/sram.py | 8 ++++---- compiler/sram_1bank.py | 8 ++++---- compiler/sram_2bank.py | 8 ++++---- compiler/sram_base.py | 8 ++++---- compiler/sram_config.py | 8 ++++---- compiler/sram_factory.py | 8 ++++---- compiler/tests/00_code_format_check_test.py | 8 ++++---- compiler/tests/01_library_drc_test.py | 8 ++++---- compiler/tests/02_library_lvs_test.py | 8 ++++---- compiler/tests/03_contact_test.py | 8 ++++---- compiler/tests/03_path_test.py | 8 ++++---- compiler/tests/03_ptx_1finger_nmos_test.py | 8 ++++---- compiler/tests/03_ptx_1finger_pmos_test.py | 8 ++++---- compiler/tests/03_ptx_3finger_nmos_test.py | 8 ++++---- compiler/tests/03_ptx_3finger_pmos_test.py | 8 ++++---- compiler/tests/03_ptx_4finger_nmos_test.py | 8 ++++---- compiler/tests/03_ptx_4finger_pmos_test.py | 8 ++++---- compiler/tests/03_wire_test.py | 8 ++++---- compiler/tests/04_pand2_test.py | 8 ++++---- compiler/tests/04_pbitcell_test.py | 8 ++++---- compiler/tests/04_pbuf_test.py | 8 ++++---- compiler/tests/04_pdriver_test.py | 8 ++++---- compiler/tests/04_pinv_10x_test.py | 8 ++++---- compiler/tests/04_pinv_1x_beta_test.py | 8 ++++---- compiler/tests/04_pinv_1x_test.py | 8 ++++---- compiler/tests/04_pinv_2x_test.py | 8 ++++---- compiler/tests/04_pinvbuf_test.py | 8 ++++---- compiler/tests/04_pnand2_test.py | 8 ++++---- compiler/tests/04_pnand3_test.py | 8 ++++---- compiler/tests/04_pnor2_test.py | 8 ++++---- compiler/tests/04_precharge_test.py | 8 ++++---- compiler/tests/04_replica_pbitcell_test.py | 8 ++++---- compiler/tests/04_single_level_column_mux_test.py | 8 ++++---- compiler/tests/05_bitcell_1rw_1r_array_test.py | 8 ++++---- compiler/tests/05_bitcell_array_test.py | 8 ++++---- compiler/tests/05_pbitcell_array_test.py | 8 ++++---- compiler/tests/06_hierarchical_decoder_test.py | 8 ++++---- compiler/tests/06_hierarchical_predecode2x4_test.py | 8 ++++---- compiler/tests/06_hierarchical_predecode3x8_test.py | 8 ++++---- compiler/tests/07_single_level_column_mux_array_test.py | 8 ++++---- compiler/tests/08_precharge_array_test.py | 8 ++++---- compiler/tests/08_wordline_driver_test.py | 8 ++++---- compiler/tests/09_sense_amp_array_test.py | 8 ++++---- compiler/tests/10_write_driver_array_test.py | 8 ++++---- compiler/tests/11_dff_array_test.py | 8 ++++---- compiler/tests/11_dff_buf_array_test.py | 8 ++++---- compiler/tests/11_dff_buf_test.py | 8 ++++---- compiler/tests/12_tri_gate_array_test.py | 8 ++++---- compiler/tests/13_delay_chain_test.py | 8 ++++---- compiler/tests/14_replica_bitline_multiport_test.py | 8 ++++---- compiler/tests/14_replica_bitline_test.py | 8 ++++---- compiler/tests/16_control_logic_test.py | 8 ++++---- compiler/tests/19_bank_select_test.py | 8 ++++---- compiler/tests/19_multi_bank_test.py | 8 ++++---- compiler/tests/19_pmulti_bank_test.py | 8 ++++---- compiler/tests/19_psingle_bank_test.py | 8 ++++---- compiler/tests/19_single_bank_1rw_1r_test.py | 8 ++++---- compiler/tests/19_single_bank_test.py | 8 ++++---- compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py | 8 ++++---- compiler/tests/20_psram_1bank_2mux_1w_1r_test.py | 8 ++++---- compiler/tests/20_psram_1bank_2mux_test.py | 8 ++++---- compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py | 8 ++++---- compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py | 8 ++++---- compiler/tests/20_sram_1bank_2mux_1w_1r_test.py | 8 ++++---- compiler/tests/20_sram_1bank_2mux_test.py | 8 ++++---- compiler/tests/20_sram_1bank_4mux_test.py | 8 ++++---- compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py | 8 ++++---- compiler/tests/20_sram_1bank_8mux_test.py | 8 ++++---- compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py | 8 ++++---- compiler/tests/20_sram_1bank_nomux_test.py | 8 ++++---- compiler/tests/20_sram_2bank_test.py | 8 ++++---- compiler/tests/21_hspice_delay_test.py | 8 ++++---- compiler/tests/21_hspice_setuphold_test.py | 8 ++++---- compiler/tests/21_model_delay_test.py | 8 ++++---- compiler/tests/21_ngspice_delay_test.py | 8 ++++---- compiler/tests/21_ngspice_setuphold_test.py | 8 ++++---- compiler/tests/22_psram_1bank_2mux_func_test.py | 8 ++++---- compiler/tests/22_psram_1bank_4mux_func_test.py | 8 ++++---- compiler/tests/22_psram_1bank_8mux_func_test.py | 8 ++++---- compiler/tests/22_psram_1bank_nomux_func_test.py | 8 ++++---- compiler/tests/22_sram_1bank_2mux_func_test.py | 8 ++++---- compiler/tests/22_sram_1bank_4mux_func_test.py | 8 ++++---- compiler/tests/22_sram_1bank_8mux_func_test.py | 8 ++++---- compiler/tests/22_sram_1bank_nomux_func_test.py | 8 ++++---- compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py | 8 ++++---- compiler/tests/23_lib_sram_model_corners_test.py | 8 ++++---- compiler/tests/23_lib_sram_model_test.py | 8 ++++---- compiler/tests/23_lib_sram_prune_test.py | 8 ++++---- compiler/tests/23_lib_sram_test.py | 8 ++++---- compiler/tests/24_lef_sram_test.py | 8 ++++---- compiler/tests/25_verilog_sram_test.py | 8 ++++---- compiler/tests/26_pex_test.py | 8 ++++---- compiler/tests/30_openram_back_end_test.py | 8 ++++---- compiler/tests/config_freepdk45.py | 8 ++++---- compiler/tests/config_freepdk45_back_end.py | 8 ++++---- compiler/tests/config_freepdk45_front_end.py | 8 ++++---- compiler/tests/config_scn4m_subm.py | 8 ++++---- compiler/tests/config_scn4m_subm_back_end.py | 8 ++++---- compiler/tests/config_scn4m_subm_front_end.py | 8 ++++---- compiler/tests/regress.py | 8 ++++---- compiler/tests/testutils.py | 8 ++++---- compiler/verify/__init__.py | 8 ++++---- compiler/verify/assura.py | 8 ++++---- compiler/verify/calibre.py | 8 ++++---- compiler/verify/magic.py | 8 ++++---- compiler/verify/none.py | 8 ++++---- compiler/verify/run_script.py | 8 ++++---- compiler/view_profile.py | 8 ++++---- technology/freepdk45/__init__.py | 8 ++++---- technology/freepdk45/tech/__init__.py | 8 ++++---- technology/freepdk45/tech/tech.py | 8 ++++---- technology/scn4m_subm/__init__.py | 8 ++++---- technology/scn4m_subm/tech/__init__.py | 8 ++++---- technology/scn4m_subm/tech/tech.py | 8 ++++---- 228 files changed, 912 insertions(+), 912 deletions(-) diff --git a/compiler/base/contact.py b/compiler/base/contact.py index de1afec6..448cbf5d 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -1,9 +1,9 @@ # 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. +# 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 hierarchy_design import debug diff --git a/compiler/base/design.py b/compiler/base/design.py index 516eef80..f568309c 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -1,9 +1,9 @@ # 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. +# 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 hierarchy_design import hierarchy_design import contact diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 144043a2..ddff6049 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -1,9 +1,9 @@ # 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. +# 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. # """ This provides a set of useful generic types for the gdsMill interface. diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index dfc275ee..66ecba9c 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -1,9 +1,9 @@ # 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. +# 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 hierarchy_layout import hierarchy_spice diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index e8c1b0b9..af579f3b 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -1,9 +1,9 @@ # 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. +# 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 itertools import geometry diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index bfa4606c..0d649598 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -1,9 +1,9 @@ # 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. +# 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 re diff --git a/compiler/base/lef.py b/compiler/base/lef.py index 5932bb67..5bc76bb0 100644 --- a/compiler/base/lef.py +++ b/compiler/base/lef.py @@ -1,9 +1,9 @@ # 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. +# 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 gdsMill import tech diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index 4c3528fe..2d389119 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import GDS, drc diff --git a/compiler/base/route.py b/compiler/base/route.py index c0bc1724..c3e446a3 100644 --- a/compiler/base/route.py +++ b/compiler/base/route.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc import debug diff --git a/compiler/base/utils.py b/compiler/base/utils.py index 6642f095..61e12096 100644 --- a/compiler/base/utils.py +++ b/compiler/base/utils.py @@ -1,9 +1,9 @@ # 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. +# 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 os import gdsMill diff --git a/compiler/base/vector.py b/compiler/base/vector.py index a845b47c..8bf09f7d 100644 --- a/compiler/base/vector.py +++ b/compiler/base/vector.py @@ -1,9 +1,9 @@ # 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. +# 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 math diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index 8596e5bc..1f2ebd7b 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/base/wire.py b/compiler/base/wire.py index 2fe36026..bf1daa6a 100644 --- a/compiler/base/wire.py +++ b/compiler/base/wire.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc import debug diff --git a/compiler/base/wire_path.py b/compiler/base/wire_path.py index 71f6af27..ebfb8a0a 100644 --- a/compiler/base/wire_path.py +++ b/compiler/base/wire_path.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc from tech import layer as techlayer diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 7e2bd2c6..9711de62 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -1,9 +1,9 @@ # 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. +# 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 design import debug diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index 2dd9c9fa..b6519cd2 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -1,9 +1,9 @@ # 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. +# 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 design import debug diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index 9e920327..b32fedc3 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -1,9 +1,9 @@ # 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. +# 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 design import debug diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index e045b763..037d00c7 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -1,9 +1,9 @@ # 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. +# 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 contact import design diff --git a/compiler/bitcells/replica_bitcell.py b/compiler/bitcells/replica_bitcell.py index 0a0e4fbf..f95249b0 100644 --- a/compiler/bitcells/replica_bitcell.py +++ b/compiler/bitcells/replica_bitcell.py @@ -1,9 +1,9 @@ # 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. +# 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 design import debug diff --git a/compiler/bitcells/replica_bitcell_1rw_1r.py b/compiler/bitcells/replica_bitcell_1rw_1r.py index 2ada1381..1d8e647e 100644 --- a/compiler/bitcells/replica_bitcell_1rw_1r.py +++ b/compiler/bitcells/replica_bitcell_1rw_1r.py @@ -1,9 +1,9 @@ # 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. +# 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 design import debug diff --git a/compiler/bitcells/replica_bitcell_1w_1r.py b/compiler/bitcells/replica_bitcell_1w_1r.py index c079399a..7eea462a 100644 --- a/compiler/bitcells/replica_bitcell_1w_1r.py +++ b/compiler/bitcells/replica_bitcell_1w_1r.py @@ -1,9 +1,9 @@ # 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. +# 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 design import debug diff --git a/compiler/bitcells/replica_pbitcell.py b/compiler/bitcells/replica_pbitcell.py index 30898d82..8453411f 100644 --- a/compiler/bitcells/replica_pbitcell.py +++ b/compiler/bitcells/replica_pbitcell.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/characterizer/__init__.py b/compiler/characterizer/__init__.py index 4c3cd910..23efe86c 100644 --- a/compiler/characterizer/__init__.py +++ b/compiler/characterizer/__init__.py @@ -1,9 +1,9 @@ # 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. +# 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 os import debug diff --git a/compiler/characterizer/bitline_delay.py b/compiler/characterizer/bitline_delay.py index 90197619..68985b2a 100644 --- a/compiler/characterizer/bitline_delay.py +++ b/compiler/characterizer/bitline_delay.py @@ -1,9 +1,9 @@ # 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. +# 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 sys,re,shutil import debug diff --git a/compiler/characterizer/charutils.py b/compiler/characterizer/charutils.py index 7081ff85..315e5268 100644 --- a/compiler/characterizer/charutils.py +++ b/compiler/characterizer/charutils.py @@ -1,9 +1,9 @@ # 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. +# 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 re import debug diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 05c8862f..7a579abf 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -1,9 +1,9 @@ # 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. +# 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 sys,re,shutil import debug diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index c12b6669..7c9517fc 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -1,9 +1,9 @@ # 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. +# 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 sys,re,shutil from design import design diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 4f709999..6e47e5cc 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -1,9 +1,9 @@ # 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. +# 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 os,sys,re import debug diff --git a/compiler/characterizer/logical_effort.py b/compiler/characterizer/logical_effort.py index 13005695..024cd4f1 100644 --- a/compiler/characterizer/logical_effort.py +++ b/compiler/characterizer/logical_effort.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc, parameter, spice diff --git a/compiler/characterizer/measurements.py b/compiler/characterizer/measurements.py index 01c6fa51..8fec4601 100644 --- a/compiler/characterizer/measurements.py +++ b/compiler/characterizer/measurements.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc, parameter, spice diff --git a/compiler/characterizer/model_check.py b/compiler/characterizer/model_check.py index c7834602..e06c1dd2 100644 --- a/compiler/characterizer/model_check.py +++ b/compiler/characterizer/model_check.py @@ -1,9 +1,9 @@ # 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. +# 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 sys,re,shutil import debug diff --git a/compiler/characterizer/setup_hold.py b/compiler/characterizer/setup_hold.py index c85a5ad0..4e661a9e 100644 --- a/compiler/characterizer/setup_hold.py +++ b/compiler/characterizer/setup_hold.py @@ -1,9 +1,9 @@ # 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. +# 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 sys import tech diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index e6204490..afbef154 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -1,9 +1,9 @@ # 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. +# 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 sys,re,shutil from design import design diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index ddd1df7e..aef09ae1 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -1,9 +1,9 @@ # 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. +# 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. # """ This file generates simple spice cards for simulation. There are diff --git a/compiler/characterizer/trim_spice.py b/compiler/characterizer/trim_spice.py index b8878db3..ffc45a9c 100644 --- a/compiler/characterizer/trim_spice.py +++ b/compiler/characterizer/trim_spice.py @@ -1,9 +1,9 @@ # 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. +# 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 math import log diff --git a/compiler/characterizer/worst_case.py b/compiler/characterizer/worst_case.py index 612d6f9f..1d4c095e 100644 --- a/compiler/characterizer/worst_case.py +++ b/compiler/characterizer/worst_case.py @@ -1,9 +1,9 @@ # 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. +# 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 sys,re,shutil import debug diff --git a/compiler/datasheet/add_db.py b/compiler/datasheet/add_db.py index a5984969..9514cf1b 100644 --- a/compiler/datasheet/add_db.py +++ b/compiler/datasheet/add_db.py @@ -1,9 +1,9 @@ # 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. +# 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 pathlib import Path import glob diff --git a/compiler/datasheet/datasheet.py b/compiler/datasheet/datasheet.py index 0874cd01..35091d36 100644 --- a/compiler/datasheet/datasheet.py +++ b/compiler/datasheet/datasheet.py @@ -1,9 +1,9 @@ # 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. +# 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 table_gen import * import os diff --git a/compiler/datasheet/datasheet_gen.py b/compiler/datasheet/datasheet_gen.py index c7eecd8d..74764789 100644 --- a/compiler/datasheet/datasheet_gen.py +++ b/compiler/datasheet/datasheet_gen.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 """ diff --git a/compiler/datasheet/table_gen.py b/compiler/datasheet/table_gen.py index 01479d7f..85a6cfba 100644 --- a/compiler/datasheet/table_gen.py +++ b/compiler/datasheet/table_gen.py @@ -1,9 +1,9 @@ # 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. +# 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. # class table_gen: """small library of functions to generate the html tables""" diff --git a/compiler/debug.py b/compiler/debug.py index 4fa8b487..f98d8380 100644 --- a/compiler/debug.py +++ b/compiler/debug.py @@ -1,9 +1,9 @@ # 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. +# 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 os import inspect diff --git a/compiler/drc/design_rules.py b/compiler/drc/design_rules.py index 09729144..958b5522 100644 --- a/compiler/drc/design_rules.py +++ b/compiler/drc/design_rules.py @@ -1,9 +1,9 @@ # 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. +# 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 drc_value import * diff --git a/compiler/drc/drc_lut.py b/compiler/drc/drc_lut.py index 0a214231..0ad0fde4 100644 --- a/compiler/drc/drc_lut.py +++ b/compiler/drc/drc_lut.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/drc/drc_value.py b/compiler/drc/drc_value.py index 4c85657f..1649e203 100644 --- a/compiler/drc/drc_value.py +++ b/compiler/drc/drc_value.py @@ -1,9 +1,9 @@ # 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. +# 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. # class drc_value(): diff --git a/compiler/gen_stimulus.py b/compiler/gen_stimulus.py index 3b24cff7..6a6be1d1 100755 --- a/compiler/gen_stimulus.py +++ b/compiler/gen_stimulus.py @@ -1,10 +1,10 @@ #!/usr/bin/env python # 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. +# 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. # """ This script will generate a stimulus file for a given period, load, and slew input diff --git a/compiler/globals.py b/compiler/globals.py index 2fe0ec1b..40daddce 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -1,9 +1,9 @@ # 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. +# 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. # """ This is called globals.py, but it actually parses all the arguments and performs diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index a854c40b..80b2bcca 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -1,9 +1,9 @@ # 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. +# 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 sys from tech import drc, parameter diff --git a/compiler/modules/bank_select.py b/compiler/modules/bank_select.py index ac866456..11c7e3ca 100644 --- a/compiler/modules/bank_select.py +++ b/compiler/modules/bank_select.py @@ -1,9 +1,9 @@ # 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. +# 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 sys from tech import drc, parameter diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index f2ab77ac..ce098040 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 0bf309a6..1e7ebdd7 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -1,9 +1,9 @@ # 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. +# 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 math import log import design diff --git a/compiler/modules/delay_chain.py b/compiler/modules/delay_chain.py index 188efffa..5b9e9817 100644 --- a/compiler/modules/delay_chain.py +++ b/compiler/modules/delay_chain.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/dff.py b/compiler/modules/dff.py index e1139e09..f67d1e00 100644 --- a/compiler/modules/dff.py +++ b/compiler/modules/dff.py @@ -1,9 +1,9 @@ # 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. +# 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 globals import design diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 8b03fe19..67c811bf 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 42e86bc0..bdece239 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index dfd38760..23fd3a86 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/dff_inv.py b/compiler/modules/dff_inv.py index 2f831570..c8e1604d 100644 --- a/compiler/modules/dff_inv.py +++ b/compiler/modules/dff_inv.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py index 3ae50a08..ecdf09bf 100644 --- a/compiler/modules/dff_inv_array.py +++ b/compiler/modules/dff_inv_array.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 1eac268d..d8fcd614 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc import debug diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index 0449280a..a8d4797f 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/hierarchical_predecode2x4.py b/compiler/modules/hierarchical_predecode2x4.py index 938196d3..0fb6d494 100644 --- a/compiler/modules/hierarchical_predecode2x4.py +++ b/compiler/modules/hierarchical_predecode2x4.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc import debug diff --git a/compiler/modules/hierarchical_predecode3x8.py b/compiler/modules/hierarchical_predecode3x8.py index 77d9ce01..4c517a00 100644 --- a/compiler/modules/hierarchical_predecode3x8.py +++ b/compiler/modules/hierarchical_predecode3x8.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc import debug diff --git a/compiler/modules/multibank.py b/compiler/modules/multibank.py index 667c6380..25cce371 100644 --- a/compiler/modules/multibank.py +++ b/compiler/modules/multibank.py @@ -1,9 +1,9 @@ # 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. +# 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 sys from tech import drc, parameter diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index f88938c8..4cd82fff 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -1,9 +1,9 @@ # 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. +# 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 design import debug diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index acd1f5d0..b9228bdb 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index 8267f42f..0afdcd99 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -1,9 +1,9 @@ # 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. +# 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 design import debug diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 4dfa03ad..4302decc 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -1,9 +1,9 @@ # 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. +# 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 design from tech import drc diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 435f0cbe..a09f6965 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -1,9 +1,9 @@ # 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. +# 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 math import log import design diff --git a/compiler/modules/tri_gate.py b/compiler/modules/tri_gate.py index e5951a53..6721c5ba 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/tri_gate_array.py b/compiler/modules/tri_gate_array.py index e3eb42cb..404bf536 100644 --- a/compiler/modules/tri_gate_array.py +++ b/compiler/modules/tri_gate_array.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index dbef0417..3bc5b5ea 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc, parameter import debug diff --git a/compiler/modules/write_driver.py b/compiler/modules/write_driver.py index bbe676c0..801ae913 100644 --- a/compiler/modules/write_driver.py +++ b/compiler/modules/write_driver.py @@ -1,9 +1,9 @@ # 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. +# 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 diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 27da84b0..887047e7 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -1,9 +1,9 @@ # 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. +# 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 math import log import design diff --git a/compiler/openram.py b/compiler/openram.py index daef3b9c..b939b61e 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ SRAM Compiler diff --git a/compiler/options.py b/compiler/options.py index b3ac813a..51c541d9 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -1,9 +1,9 @@ # 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. +# 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 optparse import getpass diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index add59565..25f57cdd 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc diff --git a/compiler/pgates/pbuf.py b/compiler/pgates/pbuf.py index f34a1827..6ccc8c16 100644 --- a/compiler/pgates/pbuf.py +++ b/compiler/pgates/pbuf.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc diff --git a/compiler/pgates/pdriver.py b/compiler/pgates/pdriver.py index 39428515..8ea68e6e 100644 --- a/compiler/pgates/pdriver.py +++ b/compiler/pgates/pdriver.py @@ -1,9 +1,9 @@ # 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. +# 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 pgate diff --git a/compiler/pgates/pgate.py b/compiler/pgates/pgate.py index 57b73a21..596f724b 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -1,9 +1,9 @@ # 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. +# 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 contact import design diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 8f05c2b1..9a41321f 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -1,9 +1,9 @@ # 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. +# 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 contact import pgate diff --git a/compiler/pgates/pinvbuf.py b/compiler/pgates/pinvbuf.py index 75c64b08..72ab6a8a 100644 --- a/compiler/pgates/pinvbuf.py +++ b/compiler/pgates/pinvbuf.py @@ -1,9 +1,9 @@ # 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. +# 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 pgate diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 865e1c60..c20bfdaa 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -1,9 +1,9 @@ # 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. +# 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 contact import pgate diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 6f9d138d..0f2d0c56 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -1,9 +1,9 @@ # 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. +# 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 contact import pgate diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index 3cc01f1a..5f0c4de5 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -1,9 +1,9 @@ # 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. +# 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 pgate import debug diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index 61785d9d..4e37aeea 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -1,9 +1,9 @@ # 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. +# 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 contact import design diff --git a/compiler/pgates/ptristate_inv.py b/compiler/pgates/ptristate_inv.py index 531ce160..55a248a7 100644 --- a/compiler/pgates/ptristate_inv.py +++ b/compiler/pgates/ptristate_inv.py @@ -1,9 +1,9 @@ # 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. +# 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 contact import pgate diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index eade6682..a0d9b484 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -1,9 +1,9 @@ # 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. +# 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 design import debug diff --git a/compiler/pgates/single_level_column_mux.py b/compiler/pgates/single_level_column_mux.py index caf01862..7c21c0a8 100644 --- a/compiler/pgates/single_level_column_mux.py +++ b/compiler/pgates/single_level_column_mux.py @@ -1,9 +1,9 @@ # 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. +# 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 pgate import debug diff --git a/compiler/router/direction.py b/compiler/router/direction.py index 7508823d..a04fc18c 100644 --- a/compiler/router/direction.py +++ b/compiler/router/direction.py @@ -1,9 +1,9 @@ # 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. +# 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 enum import Enum from vector3d import vector3d diff --git a/compiler/router/grid.py b/compiler/router/grid.py index 4533b8e7..a07aaf5c 100644 --- a/compiler/router/grid.py +++ b/compiler/router/grid.py @@ -1,9 +1,9 @@ # 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. +# 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 numpy as np import string diff --git a/compiler/router/grid_cell.py b/compiler/router/grid_cell.py index d2816c28..98c0d6ed 100644 --- a/compiler/router/grid_cell.py +++ b/compiler/router/grid_cell.py @@ -1,9 +1,9 @@ # 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. +# 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. # class grid_cell: """ diff --git a/compiler/router/grid_path.py b/compiler/router/grid_path.py index f914e477..e4e0995d 100644 --- a/compiler/router/grid_path.py +++ b/compiler/router/grid_path.py @@ -1,9 +1,9 @@ # 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. +# 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 vector3d import vector3d diff --git a/compiler/router/grid_utils.py b/compiler/router/grid_utils.py index 6524a9d5..a9a4c08d 100644 --- a/compiler/router/grid_utils.py +++ b/compiler/router/grid_utils.py @@ -1,9 +1,9 @@ # 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. +# 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. # """ Some utility functions for sets of grid cells. diff --git a/compiler/router/pin_group.py b/compiler/router/pin_group.py index bef538e3..2303d4a7 100644 --- a/compiler/router/pin_group.py +++ b/compiler/router/pin_group.py @@ -1,9 +1,9 @@ # 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. +# 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 direction import direction from pin_layout import pin_layout diff --git a/compiler/router/router.py b/compiler/router/router.py index f4e570a7..7352dfc7 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -1,9 +1,9 @@ # 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. +# 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 sys import gdsMill diff --git a/compiler/router/router_tech.py b/compiler/router/router_tech.py index b82d4ac1..4d630507 100644 --- a/compiler/router/router_tech.py +++ b/compiler/router/router_tech.py @@ -1,9 +1,9 @@ # 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. +# 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 tech import drc,layer from contact import contact diff --git a/compiler/router/signal_grid.py b/compiler/router/signal_grid.py index 38d65053..cb012a5e 100644 --- a/compiler/router/signal_grid.py +++ b/compiler/router/signal_grid.py @@ -1,9 +1,9 @@ # 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. +# 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 itertools import tee import debug diff --git a/compiler/router/signal_router.py b/compiler/router/signal_router.py index da94c4f2..9390deaf 100644 --- a/compiler/router/signal_router.py +++ b/compiler/router/signal_router.py @@ -1,9 +1,9 @@ # 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. +# 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 gdsMill import tech diff --git a/compiler/router/supply_grid.py b/compiler/router/supply_grid.py index 839fc910..98c6f031 100644 --- a/compiler/router/supply_grid.py +++ b/compiler/router/supply_grid.py @@ -1,9 +1,9 @@ # 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. +# 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 vector3d import vector3d diff --git a/compiler/router/supply_router.py b/compiler/router/supply_router.py index 060451de..85093978 100644 --- a/compiler/router/supply_router.py +++ b/compiler/router/supply_router.py @@ -1,9 +1,9 @@ # 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. +# 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 gdsMill import tech diff --git a/compiler/router/tests/01_no_blockages_test.py b/compiler/router/tests/01_no_blockages_test.py index 4529864a..4a673c24 100644 --- a/compiler/router/tests/01_no_blockages_test.py +++ b/compiler/router/tests/01_no_blockages_test.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 "Run a regresion test the library cells for DRC" diff --git a/compiler/router/tests/02_blockages_test.py b/compiler/router/tests/02_blockages_test.py index 3abe2e7e..e317b642 100644 --- a/compiler/router/tests/02_blockages_test.py +++ b/compiler/router/tests/02_blockages_test.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 "Run a regresion test the library cells for DRC" diff --git a/compiler/router/tests/03_same_layer_pins_test.py b/compiler/router/tests/03_same_layer_pins_test.py index af3d1ee8..10a3544a 100644 --- a/compiler/router/tests/03_same_layer_pins_test.py +++ b/compiler/router/tests/03_same_layer_pins_test.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 "Run a regresion test the library cells for DRC" diff --git a/compiler/router/tests/04_diff_layer_pins_test.py b/compiler/router/tests/04_diff_layer_pins_test.py index b70cba36..8966d2e4 100644 --- a/compiler/router/tests/04_diff_layer_pins_test.py +++ b/compiler/router/tests/04_diff_layer_pins_test.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 "Run a regresion test the library cells for DRC" diff --git a/compiler/router/tests/05_two_nets_test.py b/compiler/router/tests/05_two_nets_test.py index 10c157d7..ebf84745 100644 --- a/compiler/router/tests/05_two_nets_test.py +++ b/compiler/router/tests/05_two_nets_test.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 "Run a regresion test the library cells for DRC" diff --git a/compiler/router/tests/06_pin_location_test.py b/compiler/router/tests/06_pin_location_test.py index 7f75e541..a035cc59 100644 --- a/compiler/router/tests/06_pin_location_test.py +++ b/compiler/router/tests/06_pin_location_test.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 "Run a regresion test the library cells for DRC" diff --git a/compiler/router/tests/07_big_test.py b/compiler/router/tests/07_big_test.py index 6692cee0..5410dcbf 100644 --- a/compiler/router/tests/07_big_test.py +++ b/compiler/router/tests/07_big_test.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 "Run a regresion test the library cells for DRC" diff --git a/compiler/router/tests/08_expand_region_test.py b/compiler/router/tests/08_expand_region_test.py index 46af863d..ab4bce59 100644 --- a/compiler/router/tests/08_expand_region_test.py +++ b/compiler/router/tests/08_expand_region_test.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 "Run a regresion test the library cells for DRC" diff --git a/compiler/router/tests/10_supply_grid_test.py b/compiler/router/tests/10_supply_grid_test.py index 4910797a..73e41b86 100644 --- a/compiler/router/tests/10_supply_grid_test.py +++ b/compiler/router/tests/10_supply_grid_test.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 "Run a regresion test the library cells for DRC" diff --git a/compiler/router/tests/config_freepdk45.py b/compiler/router/tests/config_freepdk45.py index a6eb3bcc..bdc576bf 100644 --- a/compiler/router/tests/config_freepdk45.py +++ b/compiler/router/tests/config_freepdk45.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 diff --git a/compiler/router/tests/config_scn4m_subm.py b/compiler/router/tests/config_scn4m_subm.py index fdf7a2c3..bfaa01f8 100644 --- a/compiler/router/tests/config_scn4m_subm.py +++ b/compiler/router/tests/config_scn4m_subm.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 diff --git a/compiler/router/tests/gds_cell.py b/compiler/router/tests/gds_cell.py index 60c0f48e..b93b512a 100644 --- a/compiler/router/tests/gds_cell.py +++ b/compiler/router/tests/gds_cell.py @@ -1,9 +1,9 @@ # 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. +# 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 design import design class gds_cell(design): diff --git a/compiler/router/tests/regress.py b/compiler/router/tests/regress.py index 8f6c8938..db21bbd9 100644 --- a/compiler/router/tests/regress.py +++ b/compiler/router/tests/regress.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/env python3 diff --git a/compiler/router/tests/testutils.py b/compiler/router/tests/testutils.py index 447cace6..c90046f3 100644 --- a/compiler/router/tests/testutils.py +++ b/compiler/router/tests/testutils.py @@ -1,9 +1,9 @@ # 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. +# 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,warnings import sys,os,glob,copy diff --git a/compiler/router/vector3d.py b/compiler/router/vector3d.py index cc830faf..0d183021 100644 --- a/compiler/router/vector3d.py +++ b/compiler/router/vector3d.py @@ -1,9 +1,9 @@ # 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. +# 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 math diff --git a/compiler/sram.py b/compiler/sram.py index d080acbc..f7c1111c 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -1,9 +1,9 @@ # 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. +# 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 sys import datetime diff --git a/compiler/sram_1bank.py b/compiler/sram_1bank.py index 8edc317e..c5ad07e9 100644 --- a/compiler/sram_1bank.py +++ b/compiler/sram_1bank.py @@ -1,9 +1,9 @@ # 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. +# 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 sys from tech import drc, spice diff --git a/compiler/sram_2bank.py b/compiler/sram_2bank.py index acf0e1a2..566b0b00 100644 --- a/compiler/sram_2bank.py +++ b/compiler/sram_2bank.py @@ -1,9 +1,9 @@ # 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. +# 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 sys from tech import drc, spice diff --git a/compiler/sram_base.py b/compiler/sram_base.py index 192bc669..034f7046 100644 --- a/compiler/sram_base.py +++ b/compiler/sram_base.py @@ -1,9 +1,9 @@ # 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. +# 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 sys import datetime diff --git a/compiler/sram_config.py b/compiler/sram_config.py index 671bcf62..d2ab5776 100644 --- a/compiler/sram_config.py +++ b/compiler/sram_config.py @@ -1,9 +1,9 @@ # 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. +# 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 math import log,sqrt,ceil diff --git a/compiler/sram_factory.py b/compiler/sram_factory.py index 325261a0..8e57b90a 100644 --- a/compiler/sram_factory.py +++ b/compiler/sram_factory.py @@ -1,9 +1,9 @@ # 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. +# 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 globals import OPTS diff --git a/compiler/tests/00_code_format_check_test.py b/compiler/tests/00_code_format_check_test.py index 373b1516..c01a0678 100755 --- a/compiler/tests/00_code_format_check_test.py +++ b/compiler/tests/00_code_format_check_test.py @@ -1,10 +1,10 @@ #!/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. +# 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 diff --git a/compiler/tests/01_library_drc_test.py b/compiler/tests/01_library_drc_test.py index c2052e4e..44c687ee 100755 --- a/compiler/tests/01_library_drc_test.py +++ b/compiler/tests/01_library_drc_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test the library cells for DRC" diff --git a/compiler/tests/02_library_lvs_test.py b/compiler/tests/02_library_lvs_test.py index 6775f41f..d84b6349 100755 --- a/compiler/tests/02_library_lvs_test.py +++ b/compiler/tests/02_library_lvs_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test the library cells for LVS" diff --git a/compiler/tests/03_contact_test.py b/compiler/tests/03_contact_test.py index 2aa79df6..261e2509 100755 --- a/compiler/tests/03_contact_test.py +++ b/compiler/tests/03_contact_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test for DRC on basic contacts of different array sizes" diff --git a/compiler/tests/03_path_test.py b/compiler/tests/03_path_test.py index 4748e18d..94459d43 100755 --- a/compiler/tests/03_path_test.py +++ b/compiler/tests/03_path_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test on a basic path" diff --git a/compiler/tests/03_ptx_1finger_nmos_test.py b/compiler/tests/03_ptx_1finger_nmos_test.py index cc6d6ed6..6dba75c1 100755 --- a/compiler/tests/03_ptx_1finger_nmos_test.py +++ b/compiler/tests/03_ptx_1finger_nmos_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test on a basic parameterized transistors" diff --git a/compiler/tests/03_ptx_1finger_pmos_test.py b/compiler/tests/03_ptx_1finger_pmos_test.py index cd2128be..717d726f 100755 --- a/compiler/tests/03_ptx_1finger_pmos_test.py +++ b/compiler/tests/03_ptx_1finger_pmos_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test on a basic parameterized transistors" diff --git a/compiler/tests/03_ptx_3finger_nmos_test.py b/compiler/tests/03_ptx_3finger_nmos_test.py index 8231f090..4ca94ae4 100755 --- a/compiler/tests/03_ptx_3finger_nmos_test.py +++ b/compiler/tests/03_ptx_3finger_nmos_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test on a basic parameterized transistors" diff --git a/compiler/tests/03_ptx_3finger_pmos_test.py b/compiler/tests/03_ptx_3finger_pmos_test.py index 16e3730b..c9bae39f 100755 --- a/compiler/tests/03_ptx_3finger_pmos_test.py +++ b/compiler/tests/03_ptx_3finger_pmos_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test on a basic parameterized transistors" diff --git a/compiler/tests/03_ptx_4finger_nmos_test.py b/compiler/tests/03_ptx_4finger_nmos_test.py index c0a54d85..02437dd5 100755 --- a/compiler/tests/03_ptx_4finger_nmos_test.py +++ b/compiler/tests/03_ptx_4finger_nmos_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test on a basic parameterized transistors" diff --git a/compiler/tests/03_ptx_4finger_pmos_test.py b/compiler/tests/03_ptx_4finger_pmos_test.py index afb874af..da593964 100755 --- a/compiler/tests/03_ptx_4finger_pmos_test.py +++ b/compiler/tests/03_ptx_4finger_pmos_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test on a basic parameterized transistors" diff --git a/compiler/tests/03_wire_test.py b/compiler/tests/03_wire_test.py index 3b3388e9..b6f74e81 100755 --- a/compiler/tests/03_wire_test.py +++ b/compiler/tests/03_wire_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # "Run a regression test on a basic wire" diff --git a/compiler/tests/04_pand2_test.py b/compiler/tests/04_pand2_test.py index af99f6ec..c19820bd 100755 --- a/compiler/tests/04_pand2_test.py +++ b/compiler/tests/04_pand2_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a pand2 cell diff --git a/compiler/tests/04_pbitcell_test.py b/compiler/tests/04_pbitcell_test.py index e8b7cb55..1a16eac3 100755 --- a/compiler/tests/04_pbitcell_test.py +++ b/compiler/tests/04_pbitcell_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run regresion tests on a parameterized bitcell diff --git a/compiler/tests/04_pbuf_test.py b/compiler/tests/04_pbuf_test.py index 9eeaaeab..ef06943c 100755 --- a/compiler/tests/04_pbuf_test.py +++ b/compiler/tests/04_pbuf_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 2-row buffer cell diff --git a/compiler/tests/04_pdriver_test.py b/compiler/tests/04_pdriver_test.py index ecd697c9..8b43af6a 100755 --- a/compiler/tests/04_pdriver_test.py +++ b/compiler/tests/04_pdriver_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 2-row buffer cell diff --git a/compiler/tests/04_pinv_10x_test.py b/compiler/tests/04_pinv_10x_test.py index 0548cbf4..99b3368d 100755 --- a/compiler/tests/04_pinv_10x_test.py +++ b/compiler/tests/04_pinv_10x_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run regression tests on a parameterized inverter diff --git a/compiler/tests/04_pinv_1x_beta_test.py b/compiler/tests/04_pinv_1x_beta_test.py index 1f8aae26..2e4a4c35 100755 --- a/compiler/tests/04_pinv_1x_beta_test.py +++ b/compiler/tests/04_pinv_1x_beta_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run regression tests on a parameterized inverter diff --git a/compiler/tests/04_pinv_1x_test.py b/compiler/tests/04_pinv_1x_test.py index fd70d8dc..85c50ec7 100755 --- a/compiler/tests/04_pinv_1x_test.py +++ b/compiler/tests/04_pinv_1x_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run regression tests on a parameterized inverter diff --git a/compiler/tests/04_pinv_2x_test.py b/compiler/tests/04_pinv_2x_test.py index 6b472f9e..f26c324a 100755 --- a/compiler/tests/04_pinv_2x_test.py +++ b/compiler/tests/04_pinv_2x_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run regression tests on a parameterized inverter diff --git a/compiler/tests/04_pinvbuf_test.py b/compiler/tests/04_pinvbuf_test.py index ea407d0c..887e6e94 100755 --- a/compiler/tests/04_pinvbuf_test.py +++ b/compiler/tests/04_pinvbuf_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 2-row buffer cell diff --git a/compiler/tests/04_pnand2_test.py b/compiler/tests/04_pnand2_test.py index 527c6204..0e9c1504 100755 --- a/compiler/tests/04_pnand2_test.py +++ b/compiler/tests/04_pnand2_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run regression tests on a parameterized nand 2. This module doesn't diff --git a/compiler/tests/04_pnand3_test.py b/compiler/tests/04_pnand3_test.py index 6dba468a..6c30b698 100755 --- a/compiler/tests/04_pnand3_test.py +++ b/compiler/tests/04_pnand3_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run regression tests on a parameterized pnand3. diff --git a/compiler/tests/04_pnor2_test.py b/compiler/tests/04_pnor2_test.py index 8a66324d..037161ed 100755 --- a/compiler/tests/04_pnor2_test.py +++ b/compiler/tests/04_pnor2_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run regression tests on a parameterized nor 2. This module doesn't diff --git a/compiler/tests/04_precharge_test.py b/compiler/tests/04_precharge_test.py index 162f1091..67e376f1 100755 --- a/compiler/tests/04_precharge_test.py +++ b/compiler/tests/04_precharge_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a precharge cell diff --git a/compiler/tests/04_replica_pbitcell_test.py b/compiler/tests/04_replica_pbitcell_test.py index 1e028e40..2e4ccdca 100755 --- a/compiler/tests/04_replica_pbitcell_test.py +++ b/compiler/tests/04_replica_pbitcell_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a replica pbitcell diff --git a/compiler/tests/04_single_level_column_mux_test.py b/compiler/tests/04_single_level_column_mux_test.py index 151f2797..c7e009a4 100755 --- a/compiler/tests/04_single_level_column_mux_test.py +++ b/compiler/tests/04_single_level_column_mux_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a wordline_driver array diff --git a/compiler/tests/05_bitcell_1rw_1r_array_test.py b/compiler/tests/05_bitcell_1rw_1r_array_test.py index 9df2c8c3..d3499e63 100755 --- a/compiler/tests/05_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/05_bitcell_1rw_1r_array_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a basic array diff --git a/compiler/tests/05_bitcell_array_test.py b/compiler/tests/05_bitcell_array_test.py index 21943a5d..7a209253 100755 --- a/compiler/tests/05_bitcell_array_test.py +++ b/compiler/tests/05_bitcell_array_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a basic array diff --git a/compiler/tests/05_pbitcell_array_test.py b/compiler/tests/05_pbitcell_array_test.py index 45968266..e5d9dec2 100755 --- a/compiler/tests/05_pbitcell_array_test.py +++ b/compiler/tests/05_pbitcell_array_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a basic array diff --git a/compiler/tests/06_hierarchical_decoder_test.py b/compiler/tests/06_hierarchical_decoder_test.py index bcc22ce8..125d575e 100755 --- a/compiler/tests/06_hierarchical_decoder_test.py +++ b/compiler/tests/06_hierarchical_decoder_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a hierarchical_decoder. diff --git a/compiler/tests/06_hierarchical_predecode2x4_test.py b/compiler/tests/06_hierarchical_predecode2x4_test.py index e4687d5e..d28e4967 100755 --- a/compiler/tests/06_hierarchical_predecode2x4_test.py +++ b/compiler/tests/06_hierarchical_predecode2x4_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a hierarchical_predecode2x4. diff --git a/compiler/tests/06_hierarchical_predecode3x8_test.py b/compiler/tests/06_hierarchical_predecode3x8_test.py index 12e87d06..1a77f5e3 100755 --- a/compiler/tests/06_hierarchical_predecode3x8_test.py +++ b/compiler/tests/06_hierarchical_predecode3x8_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a hierarchical_predecode3x8. diff --git a/compiler/tests/07_single_level_column_mux_array_test.py b/compiler/tests/07_single_level_column_mux_array_test.py index 8da5f252..842283cf 100755 --- a/compiler/tests/07_single_level_column_mux_array_test.py +++ b/compiler/tests/07_single_level_column_mux_array_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a single transistor column_mux. diff --git a/compiler/tests/08_precharge_array_test.py b/compiler/tests/08_precharge_array_test.py index 86f308f4..1a75de11 100755 --- a/compiler/tests/08_precharge_array_test.py +++ b/compiler/tests/08_precharge_array_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a precharge array diff --git a/compiler/tests/08_wordline_driver_test.py b/compiler/tests/08_wordline_driver_test.py index 585b85cd..57794aa0 100755 --- a/compiler/tests/08_wordline_driver_test.py +++ b/compiler/tests/08_wordline_driver_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a wordline_driver array diff --git a/compiler/tests/09_sense_amp_array_test.py b/compiler/tests/09_sense_amp_array_test.py index 12a20e8f..d8cea665 100755 --- a/compiler/tests/09_sense_amp_array_test.py +++ b/compiler/tests/09_sense_amp_array_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a sense amp array diff --git a/compiler/tests/10_write_driver_array_test.py b/compiler/tests/10_write_driver_array_test.py index f5d0c23c..bb4d6a42 100755 --- a/compiler/tests/10_write_driver_array_test.py +++ b/compiler/tests/10_write_driver_array_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a write driver array diff --git a/compiler/tests/11_dff_array_test.py b/compiler/tests/11_dff_array_test.py index fc48adce..edf11876 100755 --- a/compiler/tests/11_dff_array_test.py +++ b/compiler/tests/11_dff_array_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a dff_array. diff --git a/compiler/tests/11_dff_buf_array_test.py b/compiler/tests/11_dff_buf_array_test.py index 7d614d1b..d0d6592a 100755 --- a/compiler/tests/11_dff_buf_array_test.py +++ b/compiler/tests/11_dff_buf_array_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a dff_array. diff --git a/compiler/tests/11_dff_buf_test.py b/compiler/tests/11_dff_buf_test.py index afb1f73b..bfeb8013 100755 --- a/compiler/tests/11_dff_buf_test.py +++ b/compiler/tests/11_dff_buf_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a dff_buf. diff --git a/compiler/tests/12_tri_gate_array_test.py b/compiler/tests/12_tri_gate_array_test.py index 203c5f94..5c28d01b 100755 --- a/compiler/tests/12_tri_gate_array_test.py +++ b/compiler/tests/12_tri_gate_array_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a tri_gate_array. diff --git a/compiler/tests/13_delay_chain_test.py b/compiler/tests/13_delay_chain_test.py index 498c1005..9682d898 100755 --- a/compiler/tests/13_delay_chain_test.py +++ b/compiler/tests/13_delay_chain_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a test on a delay chain diff --git a/compiler/tests/14_replica_bitline_multiport_test.py b/compiler/tests/14_replica_bitline_multiport_test.py index 947f9c52..2abc3d8c 100755 --- a/compiler/tests/14_replica_bitline_multiport_test.py +++ b/compiler/tests/14_replica_bitline_multiport_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a test on a multiport replica bitline diff --git a/compiler/tests/14_replica_bitline_test.py b/compiler/tests/14_replica_bitline_test.py index b5830d63..47dfca02 100755 --- a/compiler/tests/14_replica_bitline_test.py +++ b/compiler/tests/14_replica_bitline_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a test on a replica bitline diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index ed8a0088..6d4ec46e 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a control_logic diff --git a/compiler/tests/19_bank_select_test.py b/compiler/tests/19_bank_select_test.py index 5ea16052..0015158e 100755 --- a/compiler/tests/19_bank_select_test.py +++ b/compiler/tests/19_bank_select_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/19_multi_bank_test.py b/compiler/tests/19_multi_bank_test.py index 3139b4eb..8a47d1de 100755 --- a/compiler/tests/19_multi_bank_test.py +++ b/compiler/tests/19_multi_bank_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/19_pmulti_bank_test.py b/compiler/tests/19_pmulti_bank_test.py index f31e2608..9af8a6a3 100755 --- a/compiler/tests/19_pmulti_bank_test.py +++ b/compiler/tests/19_pmulti_bank_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/19_psingle_bank_test.py b/compiler/tests/19_psingle_bank_test.py index 22c3da2f..bd6ae7ff 100755 --- a/compiler/tests/19_psingle_bank_test.py +++ b/compiler/tests/19_psingle_bank_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/19_single_bank_1rw_1r_test.py b/compiler/tests/19_single_bank_1rw_1r_test.py index fb0e1c66..6299a57b 100755 --- a/compiler/tests/19_single_bank_1rw_1r_test.py +++ b/compiler/tests/19_single_bank_1rw_1r_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on 1rw 1r sram bank diff --git a/compiler/tests/19_single_bank_test.py b/compiler/tests/19_single_bank_test.py index 72e61c0d..99c9c114 100755 --- a/compiler/tests/19_single_bank_test.py +++ b/compiler/tests/19_single_bank_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py b/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py index 4bdad91f..2cc283f3 100755 --- a/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py +++ b/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank SRAM diff --git a/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py b/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py index a0b2b242..735958c8 100755 --- a/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py +++ b/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank SRAM diff --git a/compiler/tests/20_psram_1bank_2mux_test.py b/compiler/tests/20_psram_1bank_2mux_test.py index c718daa3..81ff631b 100755 --- a/compiler/tests/20_psram_1bank_2mux_test.py +++ b/compiler/tests/20_psram_1bank_2mux_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank SRAM diff --git a/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py b/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py index f415bd77..b5845b2b 100755 --- a/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py +++ b/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank SRAM diff --git a/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py index 46725bc5..67461524 100755 --- a/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank, 2 port SRAM diff --git a/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py b/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py index fec42aeb..d98b1781 100755 --- a/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py +++ b/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank SRAM diff --git a/compiler/tests/20_sram_1bank_2mux_test.py b/compiler/tests/20_sram_1bank_2mux_test.py index c61ebe4f..ea87b845 100755 --- a/compiler/tests/20_sram_1bank_2mux_test.py +++ b/compiler/tests/20_sram_1bank_2mux_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank SRAM diff --git a/compiler/tests/20_sram_1bank_4mux_test.py b/compiler/tests/20_sram_1bank_4mux_test.py index 5d10903c..22c84566 100755 --- a/compiler/tests/20_sram_1bank_4mux_test.py +++ b/compiler/tests/20_sram_1bank_4mux_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank SRAM diff --git a/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py index 3a2c34e6..685cb911 100755 --- a/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank SRAM diff --git a/compiler/tests/20_sram_1bank_8mux_test.py b/compiler/tests/20_sram_1bank_8mux_test.py index 94c073f9..305fe6e5 100755 --- a/compiler/tests/20_sram_1bank_8mux_test.py +++ b/compiler/tests/20_sram_1bank_8mux_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank SRAM diff --git a/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py index 2ce13456..9fac84da 100755 --- a/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank, 2 port SRAM diff --git a/compiler/tests/20_sram_1bank_nomux_test.py b/compiler/tests/20_sram_1bank_nomux_test.py index 272d16ee..9c6f8ec4 100755 --- a/compiler/tests/20_sram_1bank_nomux_test.py +++ b/compiler/tests/20_sram_1bank_nomux_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 1 bank SRAM diff --git a/compiler/tests/20_sram_2bank_test.py b/compiler/tests/20_sram_2bank_test.py index b625f9ec..5b68ddb5 100755 --- a/compiler/tests/20_sram_2bank_test.py +++ b/compiler/tests/20_sram_2bank_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on a 2 bank SRAM diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index aa6cbf49..5ebef57d 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/21_hspice_setuphold_test.py b/compiler/tests/21_hspice_setuphold_test.py index 49c0d2cb..823aa0de 100755 --- a/compiler/tests/21_hspice_setuphold_test.py +++ b/compiler/tests/21_hspice_setuphold_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/21_model_delay_test.py b/compiler/tests/21_model_delay_test.py index c54a9118..cc893e85 100755 --- a/compiler/tests/21_model_delay_test.py +++ b/compiler/tests/21_model_delay_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index c12d3835..a938cdc7 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/21_ngspice_setuphold_test.py b/compiler/tests/21_ngspice_setuphold_test.py index abf64d33..16dd21c8 100755 --- a/compiler/tests/21_ngspice_setuphold_test.py +++ b/compiler/tests/21_ngspice_setuphold_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index 4a99f009..479efb5a 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index 9eaa2671..589a1572 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index a0d52d1b..5d35601c 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/22_psram_1bank_nomux_func_test.py b/compiler/tests/22_psram_1bank_nomux_func_test.py index 7b76e0da..8bae45b1 100755 --- a/compiler/tests/22_psram_1bank_nomux_func_test.py +++ b/compiler/tests/22_psram_1bank_nomux_func_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a functioal test on 1 bank SRAM diff --git a/compiler/tests/22_sram_1bank_2mux_func_test.py b/compiler/tests/22_sram_1bank_2mux_func_test.py index e5fa9280..717571f7 100755 --- a/compiler/tests/22_sram_1bank_2mux_func_test.py +++ b/compiler/tests/22_sram_1bank_2mux_func_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/22_sram_1bank_4mux_func_test.py b/compiler/tests/22_sram_1bank_4mux_func_test.py index dc06a882..c21e378a 100755 --- a/compiler/tests/22_sram_1bank_4mux_func_test.py +++ b/compiler/tests/22_sram_1bank_4mux_func_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/22_sram_1bank_8mux_func_test.py b/compiler/tests/22_sram_1bank_8mux_func_test.py index ee3449ab..865cd174 100755 --- a/compiler/tests/22_sram_1bank_8mux_func_test.py +++ b/compiler/tests/22_sram_1bank_8mux_func_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on various srams diff --git a/compiler/tests/22_sram_1bank_nomux_func_test.py b/compiler/tests/22_sram_1bank_nomux_func_test.py index bc626858..15d6ab91 100755 --- a/compiler/tests/22_sram_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1bank_nomux_func_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a functioal test on 1 bank SRAM diff --git a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py index 0b8bffcc..22461575 100755 --- a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a functioal test on 1 bank SRAM diff --git a/compiler/tests/23_lib_sram_model_corners_test.py b/compiler/tests/23_lib_sram_model_corners_test.py index 85d96a73..98fdb739 100755 --- a/compiler/tests/23_lib_sram_model_corners_test.py +++ b/compiler/tests/23_lib_sram_model_corners_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Check the .lib file for an SRAM diff --git a/compiler/tests/23_lib_sram_model_test.py b/compiler/tests/23_lib_sram_model_test.py index e1727794..ee3fa85f 100755 --- a/compiler/tests/23_lib_sram_model_test.py +++ b/compiler/tests/23_lib_sram_model_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Check the .lib file for an SRAM diff --git a/compiler/tests/23_lib_sram_prune_test.py b/compiler/tests/23_lib_sram_prune_test.py index 0d33d1af..d04076c6 100755 --- a/compiler/tests/23_lib_sram_prune_test.py +++ b/compiler/tests/23_lib_sram_prune_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Check the .lib file for an SRAM with pruning diff --git a/compiler/tests/23_lib_sram_test.py b/compiler/tests/23_lib_sram_test.py index 6f2bf0b7..b38f9830 100755 --- a/compiler/tests/23_lib_sram_test.py +++ b/compiler/tests/23_lib_sram_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Check the .lib file for an SRAM diff --git a/compiler/tests/24_lef_sram_test.py b/compiler/tests/24_lef_sram_test.py index 362495d7..27b1136f 100755 --- a/compiler/tests/24_lef_sram_test.py +++ b/compiler/tests/24_lef_sram_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Check the LEF file for an SRMA diff --git a/compiler/tests/25_verilog_sram_test.py b/compiler/tests/25_verilog_sram_test.py index 0bbe45b7..95ea8cb9 100755 --- a/compiler/tests/25_verilog_sram_test.py +++ b/compiler/tests/25_verilog_sram_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Check the .v file for an SRAM diff --git a/compiler/tests/26_pex_test.py b/compiler/tests/26_pex_test.py index 5d26d26e..62699f10 100755 --- a/compiler/tests/26_pex_test.py +++ b/compiler/tests/26_pex_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ Run a regression test on an extracted SRAM to ensure functionality. diff --git a/compiler/tests/30_openram_back_end_test.py b/compiler/tests/30_openram_back_end_test.py index d5cbe0af..030f9c93 100755 --- a/compiler/tests/30_openram_back_end_test.py +++ b/compiler/tests/30_openram_back_end_test.py @@ -1,10 +1,10 @@ #!/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. +# 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. # """ This tests the top-level executable. It checks that it generates the diff --git a/compiler/tests/config_freepdk45.py b/compiler/tests/config_freepdk45.py index 5a5b2054..3103217f 100644 --- a/compiler/tests/config_freepdk45.py +++ b/compiler/tests/config_freepdk45.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 diff --git a/compiler/tests/config_freepdk45_back_end.py b/compiler/tests/config_freepdk45_back_end.py index 5fc87ead..f30a5658 100644 --- a/compiler/tests/config_freepdk45_back_end.py +++ b/compiler/tests/config_freepdk45_back_end.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 diff --git a/compiler/tests/config_freepdk45_front_end.py b/compiler/tests/config_freepdk45_front_end.py index 69d58442..309a47eb 100644 --- a/compiler/tests/config_freepdk45_front_end.py +++ b/compiler/tests/config_freepdk45_front_end.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 diff --git a/compiler/tests/config_scn4m_subm.py b/compiler/tests/config_scn4m_subm.py index 61e5cfe9..abb31435 100644 --- a/compiler/tests/config_scn4m_subm.py +++ b/compiler/tests/config_scn4m_subm.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 diff --git a/compiler/tests/config_scn4m_subm_back_end.py b/compiler/tests/config_scn4m_subm_back_end.py index d966abfa..09d7a087 100644 --- a/compiler/tests/config_scn4m_subm_back_end.py +++ b/compiler/tests/config_scn4m_subm_back_end.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 diff --git a/compiler/tests/config_scn4m_subm_front_end.py b/compiler/tests/config_scn4m_subm_front_end.py index d0c8de85..142191a0 100644 --- a/compiler/tests/config_scn4m_subm_front_end.py +++ b/compiler/tests/config_scn4m_subm_front_end.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py index c6591cf4..4d2c74f7 100755 --- a/compiler/tests/regress.py +++ b/compiler/tests/regress.py @@ -1,10 +1,10 @@ #!/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. +# 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 re diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index dfe34361..719780c2 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -1,9 +1,9 @@ # 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. +# 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,warnings import sys,os,glob,copy diff --git a/compiler/verify/__init__.py b/compiler/verify/__init__.py index 04fa9746..5c7d232e 100644 --- a/compiler/verify/__init__.py +++ b/compiler/verify/__init__.py @@ -1,9 +1,9 @@ # 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. +# 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. # """ This is a module that will import the correct DRC/LVS/PEX diff --git a/compiler/verify/assura.py b/compiler/verify/assura.py index f7777fdb..d1d6146f 100644 --- a/compiler/verify/assura.py +++ b/compiler/verify/assura.py @@ -1,9 +1,9 @@ # 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. +# 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. # """ This is a DRC/LVS interface for Assura. It implements completely two diff --git a/compiler/verify/calibre.py b/compiler/verify/calibre.py index 509e05fd..8698b248 100644 --- a/compiler/verify/calibre.py +++ b/compiler/verify/calibre.py @@ -1,9 +1,9 @@ # 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. +# 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. # """ This is a DRC/LVS interface for calibre. It implements completely diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index 2db87ae2..fd082a45 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -1,9 +1,9 @@ # 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. +# 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. # """ This is a DRC/LVS/PEX interface file for magic + netgen. diff --git a/compiler/verify/none.py b/compiler/verify/none.py index 68246463..9d7ac938 100644 --- a/compiler/verify/none.py +++ b/compiler/verify/none.py @@ -1,9 +1,9 @@ # 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. +# 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. # """ This is a DRC/LVS/PEX interface file the case with no DRC/LVS tools. diff --git a/compiler/verify/run_script.py b/compiler/verify/run_script.py index 71f55074..3bc8d2d8 100644 --- a/compiler/verify/run_script.py +++ b/compiler/verify/run_script.py @@ -1,9 +1,9 @@ # 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. +# 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. # """ Some baseline functions to run scripts. diff --git a/compiler/view_profile.py b/compiler/view_profile.py index b292dce2..cad8e9ae 100755 --- a/compiler/view_profile.py +++ b/compiler/view_profile.py @@ -1,10 +1,10 @@ #!/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. +# 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 pstats p = pstats.Stats("profile.dat") diff --git a/technology/freepdk45/__init__.py b/technology/freepdk45/__init__.py index 0ad8d108..363df6f4 100644 --- a/technology/freepdk45/__init__.py +++ b/technology/freepdk45/__init__.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/python """ diff --git a/technology/freepdk45/tech/__init__.py b/technology/freepdk45/tech/__init__.py index a516facc..662a09b6 100644 --- a/technology/freepdk45/tech/__init__.py +++ b/technology/freepdk45/tech/__init__.py @@ -1,9 +1,9 @@ # 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. +# 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 tech specific modules. diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 12c314cf..1f1f84a8 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -1,9 +1,9 @@ # 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. +# 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 os from design_rules import * diff --git a/technology/scn4m_subm/__init__.py b/technology/scn4m_subm/__init__.py index e54e3e33..c7a863f0 100644 --- a/technology/scn4m_subm/__init__.py +++ b/technology/scn4m_subm/__init__.py @@ -1,9 +1,9 @@ # 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. +# 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. # #!/usr/bin/python """ diff --git a/technology/scn4m_subm/tech/__init__.py b/technology/scn4m_subm/tech/__init__.py index a516facc..662a09b6 100644 --- a/technology/scn4m_subm/tech/__init__.py +++ b/technology/scn4m_subm/tech/__init__.py @@ -1,9 +1,9 @@ # 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. +# 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 tech specific modules. diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 15278c7b..2f253bb2 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -1,9 +1,9 @@ # 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. +# 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 os from design_rules import * From d8baa5384da83bd4cc415dc6b0baab57986027e6 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 14 Jun 2019 10:13:13 -0700 Subject: [PATCH 041/234] Remove useless comments. Add missing copyright. --- compiler/tests/01_library_drc_test.py | 2 -- compiler/tests/02_library_lvs_test.py | 2 -- compiler/tests/03_contact_test.py | 2 -- compiler/tests/03_path_test.py | 2 -- compiler/tests/03_ptx_1finger_nmos_test.py | 2 -- compiler/tests/03_ptx_1finger_pmos_test.py | 2 -- compiler/tests/03_ptx_3finger_nmos_test.py | 2 -- compiler/tests/03_ptx_3finger_pmos_test.py | 2 -- compiler/tests/03_ptx_4finger_nmos_test.py | 2 -- compiler/tests/03_ptx_4finger_pmos_test.py | 2 -- compiler/tests/03_wire_test.py | 2 -- compiler/tests/04_pand2_test.py | 4 ---- compiler/tests/04_pbitcell_test.py | 4 ---- compiler/tests/04_pbuf_test.py | 4 ---- compiler/tests/04_pdriver_test.py | 4 ---- compiler/tests/04_pinv_10x_test.py | 4 ---- compiler/tests/04_pinv_1x_beta_test.py | 4 ---- compiler/tests/04_pinv_1x_test.py | 3 --- compiler/tests/04_pinv_2x_test.py | 4 ---- compiler/tests/04_pinvbuf_test.py | 4 ---- compiler/tests/04_pnand2_test.py | 6 ------ compiler/tests/04_pnand3_test.py | 6 ------ compiler/tests/04_pnor2_test.py | 6 ------ compiler/tests/04_precharge_test.py | 4 ---- compiler/tests/04_replica_pbitcell_test.py | 4 ---- compiler/tests/04_single_level_column_mux_test.py | 4 ---- compiler/tests/05_bitcell_1rw_1r_array_test.py | 4 ---- compiler/tests/05_bitcell_array_test.py | 4 ---- compiler/tests/05_pbitcell_array_test.py | 4 ---- compiler/tests/06_hierarchical_decoder_test.py | 4 ---- compiler/tests/06_hierarchical_predecode2x4_test.py | 4 ---- compiler/tests/06_hierarchical_predecode3x8_test.py | 4 ---- .../tests/07_single_level_column_mux_array_test.py | 4 ---- compiler/tests/08_precharge_array_test.py | 4 ---- compiler/tests/08_wordline_driver_test.py | 4 ---- compiler/tests/09_sense_amp_array_test.py | 4 ---- compiler/tests/10_write_driver_array_test.py | 4 ---- compiler/tests/11_dff_array_test.py | 4 ---- compiler/tests/11_dff_buf_array_test.py | 4 ---- compiler/tests/11_dff_buf_test.py | 4 ---- compiler/tests/12_tri_gate_array_test.py | 4 ---- compiler/tests/13_delay_chain_test.py | 4 ---- compiler/tests/14_replica_bitline_multiport_test.py | 4 ---- compiler/tests/14_replica_bitline_test.py | 4 ---- compiler/tests/16_control_logic_test.py | 4 ---- compiler/tests/19_bank_select_test.py | 4 ---- compiler/tests/19_multi_bank_test.py | 4 ---- compiler/tests/19_pmulti_bank_test.py | 4 ---- compiler/tests/19_psingle_bank_test.py | 4 ---- compiler/tests/19_single_bank_1rw_1r_test.py | 4 ---- compiler/tests/19_single_bank_test.py | 4 ---- compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py | 4 ---- compiler/tests/20_psram_1bank_2mux_1w_1r_test.py | 4 ---- compiler/tests/20_psram_1bank_2mux_test.py | 4 ---- compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py | 4 ---- compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py | 4 ---- compiler/tests/20_sram_1bank_2mux_1w_1r_test.py | 4 ---- compiler/tests/20_sram_1bank_2mux_test.py | 4 ---- compiler/tests/20_sram_1bank_4mux_test.py | 4 ---- compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py | 4 ---- compiler/tests/20_sram_1bank_8mux_test.py | 4 ---- compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py | 4 ---- compiler/tests/20_sram_1bank_nomux_test.py | 4 ---- compiler/tests/20_sram_2bank_test.py | 4 ---- compiler/tests/21_hspice_delay_test.py | 4 ---- compiler/tests/21_hspice_setuphold_test.py | 4 ---- compiler/tests/21_model_delay_test.py | 4 ---- compiler/tests/21_ngspice_delay_test.py | 4 ---- compiler/tests/21_ngspice_setuphold_test.py | 4 ---- compiler/tests/22_psram_1bank_2mux_func_test.py | 4 ---- compiler/tests/22_psram_1bank_4mux_func_test.py | 4 ---- compiler/tests/22_psram_1bank_8mux_func_test.py | 4 ---- compiler/tests/22_psram_1bank_nomux_func_test.py | 4 ---- compiler/tests/22_sram_1bank_2mux_func_test.py | 4 ---- compiler/tests/22_sram_1bank_4mux_func_test.py | 4 ---- compiler/tests/22_sram_1bank_8mux_func_test.py | 4 ---- compiler/tests/22_sram_1bank_nomux_func_test.py | 4 ---- .../tests/22_sram_1rw_1r_1bank_nomux_func_test.py | 4 ---- compiler/tests/23_lib_sram_model_corners_test.py | 4 ---- compiler/tests/23_lib_sram_model_test.py | 4 ---- compiler/tests/23_lib_sram_prune_test.py | 4 ---- compiler/tests/23_lib_sram_test.py | 4 ---- compiler/tests/24_lef_sram_test.py | 4 ---- compiler/tests/25_verilog_sram_test.py | 4 ---- compiler/tests/26_pex_test.py | 4 ---- compiler/tests/30_openram_back_end_test.py | 6 ------ compiler/tests/30_openram_front_end_test.py | 13 +++++++------ compiler/tests/config_scn3me_subm.py | 8 ++++---- compiler/tests/config_scn3me_subm_back_end.py | 8 ++++---- compiler/tests/config_scn3me_subm_front_end.py | 8 ++++---- 90 files changed, 19 insertions(+), 347 deletions(-) diff --git a/compiler/tests/01_library_drc_test.py b/compiler/tests/01_library_drc_test.py index ba3c032f..f8da685b 100755 --- a/compiler/tests/01_library_drc_test.py +++ b/compiler/tests/01_library_drc_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test the library cells for DRC" - import unittest from testutils import * import sys,os,re diff --git a/compiler/tests/02_library_lvs_test.py b/compiler/tests/02_library_lvs_test.py index 880d814d..ad150a2b 100755 --- a/compiler/tests/02_library_lvs_test.py +++ b/compiler/tests/02_library_lvs_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test the library cells for LVS" - import unittest from testutils import * import sys,os,re diff --git a/compiler/tests/03_contact_test.py b/compiler/tests/03_contact_test.py index dcfe2765..3d7254c3 100755 --- a/compiler/tests/03_contact_test.py +++ b/compiler/tests/03_contact_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test for DRC on basic contacts of different array sizes" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/03_path_test.py b/compiler/tests/03_path_test.py index 32769c03..21001718 100755 --- a/compiler/tests/03_path_test.py +++ b/compiler/tests/03_path_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test on a basic path" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/03_ptx_1finger_nmos_test.py b/compiler/tests/03_ptx_1finger_nmos_test.py index f6e06cf4..f436d7d0 100755 --- a/compiler/tests/03_ptx_1finger_nmos_test.py +++ b/compiler/tests/03_ptx_1finger_nmos_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test on a basic parameterized transistors" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/03_ptx_1finger_pmos_test.py b/compiler/tests/03_ptx_1finger_pmos_test.py index 639371bd..ae8078e7 100755 --- a/compiler/tests/03_ptx_1finger_pmos_test.py +++ b/compiler/tests/03_ptx_1finger_pmos_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test on a basic parameterized transistors" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/03_ptx_3finger_nmos_test.py b/compiler/tests/03_ptx_3finger_nmos_test.py index 9419c377..c010a948 100755 --- a/compiler/tests/03_ptx_3finger_nmos_test.py +++ b/compiler/tests/03_ptx_3finger_nmos_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test on a basic parameterized transistors" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/03_ptx_3finger_pmos_test.py b/compiler/tests/03_ptx_3finger_pmos_test.py index 9867f77d..85cca9e2 100755 --- a/compiler/tests/03_ptx_3finger_pmos_test.py +++ b/compiler/tests/03_ptx_3finger_pmos_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test on a basic parameterized transistors" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/03_ptx_4finger_nmos_test.py b/compiler/tests/03_ptx_4finger_nmos_test.py index 93808da2..4a410d51 100755 --- a/compiler/tests/03_ptx_4finger_nmos_test.py +++ b/compiler/tests/03_ptx_4finger_nmos_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test on a basic parameterized transistors" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/03_ptx_4finger_pmos_test.py b/compiler/tests/03_ptx_4finger_pmos_test.py index eb191058..34fbaf9f 100755 --- a/compiler/tests/03_ptx_4finger_pmos_test.py +++ b/compiler/tests/03_ptx_4finger_pmos_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test on a basic parameterized transistors" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/03_wire_test.py b/compiler/tests/03_wire_test.py index d1d9e00f..4ee360ce 100755 --- a/compiler/tests/03_wire_test.py +++ b/compiler/tests/03_wire_test.py @@ -6,8 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -"Run a regression test on a basic wire" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pand2_test.py b/compiler/tests/04_pand2_test.py index 744367e8..42045b43 100755 --- a/compiler/tests/04_pand2_test.py +++ b/compiler/tests/04_pand2_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a pand2 cell -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pbitcell_test.py b/compiler/tests/04_pbitcell_test.py index 1b28d0d4..0f14c4c5 100755 --- a/compiler/tests/04_pbitcell_test.py +++ b/compiler/tests/04_pbitcell_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run regresion tests on a parameterized bitcell -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pbuf_test.py b/compiler/tests/04_pbuf_test.py index 2e24536b..35db8ccf 100755 --- a/compiler/tests/04_pbuf_test.py +++ b/compiler/tests/04_pbuf_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 2-row buffer cell -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pdriver_test.py b/compiler/tests/04_pdriver_test.py index c4dbe5a1..abaab4a0 100755 --- a/compiler/tests/04_pdriver_test.py +++ b/compiler/tests/04_pdriver_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 2-row buffer cell -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pinv_10x_test.py b/compiler/tests/04_pinv_10x_test.py index ed356e49..2ccce34a 100755 --- a/compiler/tests/04_pinv_10x_test.py +++ b/compiler/tests/04_pinv_10x_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run regression tests on a parameterized inverter -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pinv_1x_beta_test.py b/compiler/tests/04_pinv_1x_beta_test.py index da89ee8a..2f96020c 100755 --- a/compiler/tests/04_pinv_1x_beta_test.py +++ b/compiler/tests/04_pinv_1x_beta_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run regression tests on a parameterized inverter -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pinv_1x_test.py b/compiler/tests/04_pinv_1x_test.py index c991eb5a..9b0f1bc6 100755 --- a/compiler/tests/04_pinv_1x_test.py +++ b/compiler/tests/04_pinv_1x_test.py @@ -6,9 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run regression tests on a parameterized inverter -""" import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pinv_2x_test.py b/compiler/tests/04_pinv_2x_test.py index 29bafb5d..d8a7598f 100755 --- a/compiler/tests/04_pinv_2x_test.py +++ b/compiler/tests/04_pinv_2x_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run regression tests on a parameterized inverter -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pinvbuf_test.py b/compiler/tests/04_pinvbuf_test.py index c84f2501..86af0708 100755 --- a/compiler/tests/04_pinvbuf_test.py +++ b/compiler/tests/04_pinvbuf_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 2-row buffer cell -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pnand2_test.py b/compiler/tests/04_pnand2_test.py index 40c592f7..bc066cfc 100755 --- a/compiler/tests/04_pnand2_test.py +++ b/compiler/tests/04_pnand2_test.py @@ -6,12 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run regression tests on a parameterized nand 2. This module doesn't -generate a multi_finger 2-input nand gate. It generates only a minimum -size 2-input nand gate. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pnand3_test.py b/compiler/tests/04_pnand3_test.py index 31315fb7..8bf5098f 100755 --- a/compiler/tests/04_pnand3_test.py +++ b/compiler/tests/04_pnand3_test.py @@ -6,12 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run regression tests on a parameterized pnand3. -This module doesn't generate a multi-finger 3-input nand gate. -It generates only a minimum size 3-input nand gate. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_pnor2_test.py b/compiler/tests/04_pnor2_test.py index bc650ae1..0e524506 100755 --- a/compiler/tests/04_pnor2_test.py +++ b/compiler/tests/04_pnor2_test.py @@ -6,12 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run regression tests on a parameterized nor 2. This module doesn't -generate a multi_finger 2-input nor gate. It generates only a minimum -size 2-input nor gate. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_precharge_test.py b/compiler/tests/04_precharge_test.py index 03ed932a..9b2addd5 100755 --- a/compiler/tests/04_precharge_test.py +++ b/compiler/tests/04_precharge_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a precharge cell -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_replica_pbitcell_test.py b/compiler/tests/04_replica_pbitcell_test.py index f18c7005..65ce5ecf 100755 --- a/compiler/tests/04_replica_pbitcell_test.py +++ b/compiler/tests/04_replica_pbitcell_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a replica pbitcell -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/04_single_level_column_mux_test.py b/compiler/tests/04_single_level_column_mux_test.py index 76fa2fec..3ecbbe9d 100755 --- a/compiler/tests/04_single_level_column_mux_test.py +++ b/compiler/tests/04_single_level_column_mux_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a wordline_driver array -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/05_bitcell_1rw_1r_array_test.py b/compiler/tests/05_bitcell_1rw_1r_array_test.py index 681dd33e..3a01e015 100755 --- a/compiler/tests/05_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/05_bitcell_1rw_1r_array_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a basic array -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/05_bitcell_array_test.py b/compiler/tests/05_bitcell_array_test.py index 726fee50..f24d5f38 100755 --- a/compiler/tests/05_bitcell_array_test.py +++ b/compiler/tests/05_bitcell_array_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a basic array -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/05_pbitcell_array_test.py b/compiler/tests/05_pbitcell_array_test.py index 8dafcc56..91bf7522 100755 --- a/compiler/tests/05_pbitcell_array_test.py +++ b/compiler/tests/05_pbitcell_array_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a basic array -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/06_hierarchical_decoder_test.py b/compiler/tests/06_hierarchical_decoder_test.py index 4bd125ae..c349e889 100755 --- a/compiler/tests/06_hierarchical_decoder_test.py +++ b/compiler/tests/06_hierarchical_decoder_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a hierarchical_decoder. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/06_hierarchical_predecode2x4_test.py b/compiler/tests/06_hierarchical_predecode2x4_test.py index 8dbb9410..0a5363ab 100755 --- a/compiler/tests/06_hierarchical_predecode2x4_test.py +++ b/compiler/tests/06_hierarchical_predecode2x4_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a hierarchical_predecode2x4. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/06_hierarchical_predecode3x8_test.py b/compiler/tests/06_hierarchical_predecode3x8_test.py index 08d731b8..b2a8d438 100755 --- a/compiler/tests/06_hierarchical_predecode3x8_test.py +++ b/compiler/tests/06_hierarchical_predecode3x8_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a hierarchical_predecode3x8. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/07_single_level_column_mux_array_test.py b/compiler/tests/07_single_level_column_mux_array_test.py index d74348f9..c6cd7ed2 100755 --- a/compiler/tests/07_single_level_column_mux_array_test.py +++ b/compiler/tests/07_single_level_column_mux_array_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a single transistor column_mux. -""" - from testutils import * import sys,os sys.path.append(os.getenv("OPENRAM_HOME")) diff --git a/compiler/tests/08_precharge_array_test.py b/compiler/tests/08_precharge_array_test.py index fc078db6..ee29211b 100755 --- a/compiler/tests/08_precharge_array_test.py +++ b/compiler/tests/08_precharge_array_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a precharge array -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/08_wordline_driver_test.py b/compiler/tests/08_wordline_driver_test.py index c845d26c..31415a6c 100755 --- a/compiler/tests/08_wordline_driver_test.py +++ b/compiler/tests/08_wordline_driver_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a wordline_driver array -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/09_sense_amp_array_test.py b/compiler/tests/09_sense_amp_array_test.py index d7fb77ac..e35ea3c3 100755 --- a/compiler/tests/09_sense_amp_array_test.py +++ b/compiler/tests/09_sense_amp_array_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a sense amp array -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/10_write_driver_array_test.py b/compiler/tests/10_write_driver_array_test.py index 9141b0cb..20dacca6 100755 --- a/compiler/tests/10_write_driver_array_test.py +++ b/compiler/tests/10_write_driver_array_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a write driver array -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/11_dff_array_test.py b/compiler/tests/11_dff_array_test.py index 6ea0e3f3..b843a6bb 100755 --- a/compiler/tests/11_dff_array_test.py +++ b/compiler/tests/11_dff_array_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a dff_array. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/11_dff_buf_array_test.py b/compiler/tests/11_dff_buf_array_test.py index a60c6fdc..ec0e7742 100755 --- a/compiler/tests/11_dff_buf_array_test.py +++ b/compiler/tests/11_dff_buf_array_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a dff_array. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/11_dff_buf_test.py b/compiler/tests/11_dff_buf_test.py index 64d860f0..161deaa2 100755 --- a/compiler/tests/11_dff_buf_test.py +++ b/compiler/tests/11_dff_buf_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a dff_buf. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/12_tri_gate_array_test.py b/compiler/tests/12_tri_gate_array_test.py index ba08711b..db28bde9 100755 --- a/compiler/tests/12_tri_gate_array_test.py +++ b/compiler/tests/12_tri_gate_array_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a tri_gate_array. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/13_delay_chain_test.py b/compiler/tests/13_delay_chain_test.py index 03f9f4f6..9dc8faeb 100755 --- a/compiler/tests/13_delay_chain_test.py +++ b/compiler/tests/13_delay_chain_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a test on a delay chain -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/14_replica_bitline_multiport_test.py b/compiler/tests/14_replica_bitline_multiport_test.py index 959ed325..9e2f90ab 100755 --- a/compiler/tests/14_replica_bitline_multiport_test.py +++ b/compiler/tests/14_replica_bitline_multiport_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a test on a multiport replica bitline -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/14_replica_bitline_test.py b/compiler/tests/14_replica_bitline_test.py index 3a732750..47171aae 100755 --- a/compiler/tests/14_replica_bitline_test.py +++ b/compiler/tests/14_replica_bitline_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a test on a replica bitline -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index 6571e3aa..9fa064cd 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a control_logic -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/19_bank_select_test.py b/compiler/tests/19_bank_select_test.py index ae7b495c..e2f5a9a8 100755 --- a/compiler/tests/19_bank_select_test.py +++ b/compiler/tests/19_bank_select_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/19_multi_bank_test.py b/compiler/tests/19_multi_bank_test.py index 1c67b5ac..1816cd61 100755 --- a/compiler/tests/19_multi_bank_test.py +++ b/compiler/tests/19_multi_bank_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/19_pmulti_bank_test.py b/compiler/tests/19_pmulti_bank_test.py index d21d8849..749460fa 100755 --- a/compiler/tests/19_pmulti_bank_test.py +++ b/compiler/tests/19_pmulti_bank_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/19_psingle_bank_test.py b/compiler/tests/19_psingle_bank_test.py index a6e44e23..7fe806b8 100755 --- a/compiler/tests/19_psingle_bank_test.py +++ b/compiler/tests/19_psingle_bank_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/19_single_bank_1rw_1r_test.py b/compiler/tests/19_single_bank_1rw_1r_test.py index 9c7a283c..c82200a7 100755 --- a/compiler/tests/19_single_bank_1rw_1r_test.py +++ b/compiler/tests/19_single_bank_1rw_1r_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on 1rw 1r sram bank -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/19_single_bank_test.py b/compiler/tests/19_single_bank_test.py index f1809690..1d010db5 100755 --- a/compiler/tests/19_single_bank_test.py +++ b/compiler/tests/19_single_bank_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py b/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py index f51bcc33..cd7086b6 100755 --- a/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py +++ b/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py b/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py index 231d409e..8b716d43 100755 --- a/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py +++ b/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_psram_1bank_2mux_test.py b/compiler/tests/20_psram_1bank_2mux_test.py index 1e5ef24b..5f0cba17 100755 --- a/compiler/tests/20_psram_1bank_2mux_test.py +++ b/compiler/tests/20_psram_1bank_2mux_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py b/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py index f17e221d..d674c04e 100755 --- a/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py +++ b/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py index 3f38f0e4..acaf5844 100755 --- a/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank, 2 port SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py b/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py index 2407995d..50af484f 100755 --- a/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py +++ b/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_sram_1bank_2mux_test.py b/compiler/tests/20_sram_1bank_2mux_test.py index e60190f7..7e5a4f3a 100755 --- a/compiler/tests/20_sram_1bank_2mux_test.py +++ b/compiler/tests/20_sram_1bank_2mux_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_sram_1bank_4mux_test.py b/compiler/tests/20_sram_1bank_4mux_test.py index 7ca61e5a..34af86a1 100755 --- a/compiler/tests/20_sram_1bank_4mux_test.py +++ b/compiler/tests/20_sram_1bank_4mux_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py index c181f2e9..1cd89037 100755 --- a/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_sram_1bank_8mux_test.py b/compiler/tests/20_sram_1bank_8mux_test.py index aa4d1e68..c5eaea75 100755 --- a/compiler/tests/20_sram_1bank_8mux_test.py +++ b/compiler/tests/20_sram_1bank_8mux_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py index fc2adec4..570cf092 100755 --- a/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank, 2 port SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_sram_1bank_nomux_test.py b/compiler/tests/20_sram_1bank_nomux_test.py index dba70be3..650d2ac2 100755 --- a/compiler/tests/20_sram_1bank_nomux_test.py +++ b/compiler/tests/20_sram_1bank_nomux_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/20_sram_2bank_test.py b/compiler/tests/20_sram_2bank_test.py index db491a24..c5d9d3d0 100755 --- a/compiler/tests/20_sram_2bank_test.py +++ b/compiler/tests/20_sram_2bank_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on a 2 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 06bfe44c..598a6291 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/21_hspice_setuphold_test.py b/compiler/tests/21_hspice_setuphold_test.py index f6ead751..ef5cf1a8 100755 --- a/compiler/tests/21_hspice_setuphold_test.py +++ b/compiler/tests/21_hspice_setuphold_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/21_model_delay_test.py b/compiler/tests/21_model_delay_test.py index 648a9336..a775c086 100755 --- a/compiler/tests/21_model_delay_test.py +++ b/compiler/tests/21_model_delay_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 9d0ffebc..1ff14250 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/21_ngspice_setuphold_test.py b/compiler/tests/21_ngspice_setuphold_test.py index 8e8fb53c..4a289812 100755 --- a/compiler/tests/21_ngspice_setuphold_test.py +++ b/compiler/tests/21_ngspice_setuphold_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index 052874bc..be875181 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index 6347507c..389575f7 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index 03e1d0a9..8a0001a9 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/22_psram_1bank_nomux_func_test.py b/compiler/tests/22_psram_1bank_nomux_func_test.py index ac4f1d36..e9b33db2 100755 --- a/compiler/tests/22_psram_1bank_nomux_func_test.py +++ b/compiler/tests/22_psram_1bank_nomux_func_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a functioal test on 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/22_sram_1bank_2mux_func_test.py b/compiler/tests/22_sram_1bank_2mux_func_test.py index 7026c553..a38d868d 100755 --- a/compiler/tests/22_sram_1bank_2mux_func_test.py +++ b/compiler/tests/22_sram_1bank_2mux_func_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/22_sram_1bank_4mux_func_test.py b/compiler/tests/22_sram_1bank_4mux_func_test.py index 1aabe78f..cefb9969 100755 --- a/compiler/tests/22_sram_1bank_4mux_func_test.py +++ b/compiler/tests/22_sram_1bank_4mux_func_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/22_sram_1bank_8mux_func_test.py b/compiler/tests/22_sram_1bank_8mux_func_test.py index b213633f..332e52df 100755 --- a/compiler/tests/22_sram_1bank_8mux_func_test.py +++ b/compiler/tests/22_sram_1bank_8mux_func_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on various srams -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/22_sram_1bank_nomux_func_test.py b/compiler/tests/22_sram_1bank_nomux_func_test.py index 6be32096..af626104 100755 --- a/compiler/tests/22_sram_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1bank_nomux_func_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a functioal test on 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py index 1bf58207..e733fce3 100755 --- a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a functioal test on 1 bank SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/23_lib_sram_model_corners_test.py b/compiler/tests/23_lib_sram_model_corners_test.py index 86edba77..6b6a02f5 100755 --- a/compiler/tests/23_lib_sram_model_corners_test.py +++ b/compiler/tests/23_lib_sram_model_corners_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Check the .lib file for an SRAM -""" - import unittest from testutils import * import sys,os,re diff --git a/compiler/tests/23_lib_sram_model_test.py b/compiler/tests/23_lib_sram_model_test.py index 43c834e9..8740e2d7 100755 --- a/compiler/tests/23_lib_sram_model_test.py +++ b/compiler/tests/23_lib_sram_model_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Check the .lib file for an SRAM -""" - import unittest from testutils import * import sys,os,re diff --git a/compiler/tests/23_lib_sram_prune_test.py b/compiler/tests/23_lib_sram_prune_test.py index 25039ff4..92070562 100755 --- a/compiler/tests/23_lib_sram_prune_test.py +++ b/compiler/tests/23_lib_sram_prune_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Check the .lib file for an SRAM with pruning -""" - import unittest from testutils import * import sys,os,re diff --git a/compiler/tests/23_lib_sram_test.py b/compiler/tests/23_lib_sram_test.py index 7a7ded0d..0ababf32 100755 --- a/compiler/tests/23_lib_sram_test.py +++ b/compiler/tests/23_lib_sram_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Check the .lib file for an SRAM -""" - import unittest from testutils import * import sys,os,re diff --git a/compiler/tests/24_lef_sram_test.py b/compiler/tests/24_lef_sram_test.py index b5b5aabd..5f7fdc60 100755 --- a/compiler/tests/24_lef_sram_test.py +++ b/compiler/tests/24_lef_sram_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Check the LEF file for an SRMA -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/25_verilog_sram_test.py b/compiler/tests/25_verilog_sram_test.py index 4c64cbe3..da6a2682 100755 --- a/compiler/tests/25_verilog_sram_test.py +++ b/compiler/tests/25_verilog_sram_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Check the .v file for an SRAM -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/26_pex_test.py b/compiler/tests/26_pex_test.py index 3c722859..78409249 100755 --- a/compiler/tests/26_pex_test.py +++ b/compiler/tests/26_pex_test.py @@ -6,10 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -Run a regression test on an extracted SRAM to ensure functionality. -""" - import unittest from testutils import * import sys,os diff --git a/compiler/tests/30_openram_back_end_test.py b/compiler/tests/30_openram_back_end_test.py index 3240d570..d375d605 100755 --- a/compiler/tests/30_openram_back_end_test.py +++ b/compiler/tests/30_openram_back_end_test.py @@ -6,12 +6,6 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # -""" -This tests the top-level executable. It checks that it generates the -appropriate files: .lef, .lib, .sp, .gds, .v. It DOES NOT, however, -check that these files are right. -""" - import unittest from testutils import * import sys,os,re,shutil diff --git a/compiler/tests/30_openram_front_end_test.py b/compiler/tests/30_openram_front_end_test.py index 8058153f..5252db7b 100755 --- a/compiler/tests/30_openram_front_end_test.py +++ b/compiler/tests/30_openram_front_end_test.py @@ -1,10 +1,11 @@ #!/usr/bin/env python3 -""" -This tests the top-level executable. It checks that it generates the -appropriate files: .lef, .lib, .sp, .gds, .v. It DOES NOT, however, -check that these files are right. -""" - +# 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,re,shutil diff --git a/compiler/tests/config_scn3me_subm.py b/compiler/tests/config_scn3me_subm.py index 2cd02b5e..7b5b5e15 100644 --- a/compiler/tests/config_scn3me_subm.py +++ b/compiler/tests/config_scn3me_subm.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 diff --git a/compiler/tests/config_scn3me_subm_back_end.py b/compiler/tests/config_scn3me_subm_back_end.py index 5586ebca..826a50ae 100644 --- a/compiler/tests/config_scn3me_subm_back_end.py +++ b/compiler/tests/config_scn3me_subm_back_end.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 diff --git a/compiler/tests/config_scn3me_subm_front_end.py b/compiler/tests/config_scn3me_subm_front_end.py index 7b39e46d..c73fc84e 100644 --- a/compiler/tests/config_scn3me_subm_front_end.py +++ b/compiler/tests/config_scn3me_subm_front_end.py @@ -1,9 +1,9 @@ # 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. +# 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. # word_size = 1 num_words = 16 From b67f06a65a703de2a596a5a26fff540ccc42fc88 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 14 Jun 2019 12:15:16 -0700 Subject: [PATCH 042/234] Add replica column for inclusion in replica bitcell array --- compiler/modules/replica_column.py | 142 +++++++++++++++++++++++ compiler/tests/05_replica_column_test.py | 32 +++++ 2 files changed, 174 insertions(+) create mode 100644 compiler/modules/replica_column.py create mode 100755 compiler/tests/05_replica_column_test.py diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py new file mode 100644 index 00000000..91f2881a --- /dev/null +++ b/compiler/modules/replica_column.py @@ -0,0 +1,142 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# All rights reserved. +# +import debug +import design +from tech import drc +import contact +from sram_factory import factory +from vector import vector +from globals import OPTS + +class replica_column(design.design): + """ + Generate a replica bitline column for the replica array. + """ + + def __init__(self, name, rows): + design.design.__init__(self, name) + + # One extra row for the dummy row + self.row_size = rows + 1 + + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() + + def create_netlist(self): + self.add_modules() + self.add_pins() + self.create_instances() + + def create_layout(self): + self.place_instances() + self.add_layout_pins() + + self.add_boundary() + self.DRC_LVS() + + def add_pins(self): + column_list = self.cell.list_all_bitline_names() + for cell_column in column_list: + self.add_pin("{0}_{1}".format(cell_column,0)) + row_list = self.cell.list_all_wl_names() + for row in range(self.row_size): + for cell_row in row_list: + self.add_pin("{0}_{1}".format(cell_row,row)) + + self.add_pin("vdd") + self.add_pin("gnd") + + def add_modules(self): + self.replica_cell = factory.create(module_type="replica_bitcell") + self.add_mod(self.replica_cell) + # Used for pin names only + self.cell = factory.create(module_type="bitcell") + + def create_instances(self): + self.cell_inst = {} + for row in range(self.row_size): + name="rbc_{0}".format(row) + self.cell_inst[row]=self.add_inst(name=name, + mod=self.replica_cell) + self.connect_inst(self.list_bitcell_pins(0, row)) + + def create_layout(self): + + # We increase it by a well enclosure so the precharges don't overlap our wells + self.height = self.row_size*self.cell.height + self.width = self.cell.width + + yoffset = 0.0 + for row in range(self.row_size): + name = "bit_r{0}_{1}".format(row,"rbl") + + # This is opposite of a bitcell array since we will be 1 row off + if not row % 2: + tempy = yoffset + self.cell.height + dir_key = "MX" + else: + tempy = yoffset + dir_key = "" + + self.cell_inst[row].place(offset=[0.0, tempy], + mirror=dir_key) + yoffset += self.cell.height + + self.add_layout_pins() + + self.add_boundary() + + self.DRC_LVS() + + + def add_layout_pins(self): + """ Add the layout pins """ + + row_list = self.cell.list_all_wl_names() + column_list = self.cell.list_all_bitline_names() + + col = "rbl" + for cell_column in column_list: + bl_pin = self.cell_inst[0].get_pin(cell_column) + self.add_layout_pin(text=cell_column+"_{0}".format(col), + layer="metal2", + offset=bl_pin.ll(), + width=bl_pin.width(), + height=self.height) + + for row in range(self.row_size): + for cell_row in row_list: + wl_pin = self.cell_inst[row].get_pin(cell_row) + self.add_layout_pin(text=cell_row+"_{0}".format(row), + layer="metal1", + offset=wl_pin.ll(), + width=self.width, + height=wl_pin.height()) + + # For every second row and column, add a via for gnd and vdd + for row in range(self.row_size): + inst = self.cell_inst[row] + for pin_name in ["vdd", "gnd"]: + self.copy_layout_pin(inst, pin_name) + + def list_bitcell_pins(self, col, row): + """ Creates a list of connections in the bitcell, + indexed by column and row, for instance use in bitcell_array """ + + bitcell_pins = [] + + pin_names = self.cell.list_all_bitline_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(col)) + pin_names = self.cell.list_all_wl_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(row)) + bitcell_pins.append("vdd") + bitcell_pins.append("gnd") + + return bitcell_pins + diff --git a/compiler/tests/05_replica_column_test.py b/compiler/tests/05_replica_column_test.py new file mode 100755 index 00000000..8a9f03bb --- /dev/null +++ b/compiler/tests/05_replica_column_test.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# 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 replica_column_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + debug.info(2, "Testing replica column for 6t_cell") + a = factory.create(module_type="replica_column", 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 3c3456596a4ed89076dfc2d6eebdf17d67efbc1d Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 14 Jun 2019 14:38:55 -0700 Subject: [PATCH 043/234] Add replica row with dummy cells. --- compiler/modules/replica_row.py | 133 ++++++++++++++++++ compiler/tests/05_replica_row_test.py | 32 +++++ .../scn4m_subm/mag_lib/dummy_cell_6t.mag | 117 +++++++++++++++ technology/scn4m_subm/sp_lib/dummy_cell_6t.sp | 18 +++ 4 files changed, 300 insertions(+) create mode 100644 compiler/modules/replica_row.py create mode 100755 compiler/tests/05_replica_row_test.py create mode 100644 technology/scn4m_subm/mag_lib/dummy_cell_6t.mag create mode 100644 technology/scn4m_subm/sp_lib/dummy_cell_6t.sp diff --git a/compiler/modules/replica_row.py b/compiler/modules/replica_row.py new file mode 100644 index 00000000..25268993 --- /dev/null +++ b/compiler/modules/replica_row.py @@ -0,0 +1,133 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# All rights reserved. +# +import debug +import design +from tech import drc +import contact +from sram_factory import factory +from vector import vector +from globals import OPTS + +class replica_row(design.design): + """ + Generate a replica wordline row for the replica array. + """ + + def __init__(self, name, cols): + design.design.__init__(self, name) + + self.column_size = cols + + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() + + def create_netlist(self): + self.add_modules() + self.add_pins() + self.create_instances() + + def create_layout(self): + self.place_instances() + self.add_layout_pins() + + self.add_boundary() + self.DRC_LVS() + + def add_pins(self): + column_list = self.cell.list_all_bitline_names() + for col in range(self.column_size): + for cell_column in column_list: + self.add_pin("{0}_{1}".format(cell_column,col)) + row_list = self.cell.list_all_wl_names() + for cell_row in row_list: + self.add_pin("{0}_{1}".format(cell_row,0)) + + self.add_pin("vdd") + self.add_pin("gnd") + + def add_modules(self): + self.dummy_cell = factory.create(module_type="dummy_bitcell") + self.add_mod(self.dummy_cell) + # Used for pin names only + self.cell = factory.create(module_type="bitcell") + + def create_instances(self): + self.cell_inst = {} + for col in range(self.column_size): + name="dummy_{0}".format(col) + self.cell_inst[col]=self.add_inst(name=name, + mod=self.dummy_cell) + self.connect_inst(self.list_bitcell_pins(col, 0)) + + def create_layout(self): + + # We increase it by a well enclosure so the precharges don't overlap our wells + self.height = self.cell.height + self.width = self.column_size*self.cell.width + + xoffset = 0.0 + tempy = self.cell.height + dir_key = "MX" + for col in range(self.column_size): + name = "bit_{0}_c{1}".format("dummy",col) + self.cell_inst[col].place(offset=[xoffset, tempy], + mirror=dir_key) + xoffset += self.cell.width + + self.add_layout_pins() + + self.add_boundary() + + self.DRC_LVS() + + + def add_layout_pins(self): + """ Add the layout pins """ + + row_list = self.cell.list_all_wl_names() + column_list = self.cell.list_all_bitline_names() + + for col in range(self.column_size): + for cell_column in column_list: + bl_pin = self.cell_inst[col].get_pin(cell_column) + self.add_layout_pin(text=cell_column+"_{0}".format(col), + layer="metal2", + offset=bl_pin.ll(), + width=bl_pin.width(), + height=self.height) + + for cell_row in row_list: + wl_pin = self.cell_inst[0].get_pin(cell_row) + self.add_layout_pin(text=cell_row+"_{0}".format(0), + layer="metal1", + offset=wl_pin.ll(), + width=self.width, + height=wl_pin.height()) + + # For every second row and column, add a via for gnd and vdd + for col in range(self.column_size): + inst = self.cell_inst[col] + for pin_name in ["vdd", "gnd"]: + self.copy_layout_pin(inst, pin_name) + + def list_bitcell_pins(self, col, row): + """ Creates a list of connections in the bitcell, + indexed by column and row, for instance use in bitcell_array """ + + bitcell_pins = [] + + pin_names = self.cell.list_all_bitline_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(col)) + pin_names = self.cell.list_all_wl_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(row)) + bitcell_pins.append("vdd") + bitcell_pins.append("gnd") + + return bitcell_pins + diff --git a/compiler/tests/05_replica_row_test.py b/compiler/tests/05_replica_row_test.py new file mode 100755 index 00000000..9d8e7ce2 --- /dev/null +++ b/compiler/tests/05_replica_row_test.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# 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 replica_row_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + debug.info(2, "Testing replica row for 6t_cell") + a = factory.create(module_type="replica_row", cols=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()) diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag b/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag new file mode 100644 index 00000000..f2e9906a --- /dev/null +++ b/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag @@ -0,0 +1,117 @@ +magic +tech scmos +timestamp 1536091415 +<< nwell >> +rect -8 29 42 51 +<< pwell >> +rect -8 -8 42 29 +<< ntransistor >> +rect 7 10 9 18 +rect 29 10 31 18 +rect 10 3 14 5 +rect 24 3 28 5 +<< ptransistor >> +rect 7 37 11 40 +rect 27 37 31 40 +<< ndiffusion >> +rect -2 16 7 18 +rect 2 12 7 16 +rect -2 10 7 12 +rect 9 14 10 18 +rect 9 10 14 14 +rect 28 14 29 18 +rect 24 10 29 14 +rect 31 16 36 18 +rect 31 12 32 16 +rect 31 10 36 12 +rect 10 5 14 10 +rect 24 5 28 10 +rect 10 2 14 3 +rect 24 2 28 3 +<< pdiffusion >> +rect 2 37 7 40 +rect 11 37 12 40 +rect 26 37 27 40 +rect 31 37 32 40 +<< ndcontact >> +rect -2 12 2 16 +rect 10 14 14 18 +rect 24 14 28 18 +rect 32 12 36 16 +rect 10 -2 14 2 +rect 24 -2 28 2 +<< pdcontact >> +rect -2 36 2 40 +rect 12 36 16 40 +rect 22 36 26 40 +rect 32 36 36 40 +<< psubstratepcontact >> +rect -2 22 2 26 +rect 32 22 36 26 +<< nsubstratencontact >> +rect 32 44 36 48 +<< polysilicon >> +rect 7 40 11 42 +rect 27 40 31 42 +rect 7 35 11 37 +rect 7 21 9 35 +rect 27 34 31 37 +rect 15 33 31 34 +rect 19 32 31 33 +rect 7 20 21 21 +rect 7 19 24 20 +rect 7 18 9 19 +rect 29 18 31 32 +rect 7 8 9 10 +rect 17 5 21 6 +rect 29 8 31 10 +rect -2 3 10 5 +rect 14 3 24 5 +rect 28 3 36 5 +<< polycontact >> +rect 15 29 19 33 +rect 21 20 25 24 +rect 17 6 21 10 +<< metal1 >> +rect -2 44 15 48 +rect 19 44 32 48 +rect -2 40 2 44 +rect 32 40 36 44 +rect 11 36 12 40 +rect 26 36 27 40 +rect -2 26 2 29 +rect -2 16 2 22 +rect 11 18 15 36 +rect 23 24 27 36 +rect 25 20 27 24 +rect 14 14 15 18 +rect 23 18 27 20 +rect 32 26 36 29 +rect 23 14 24 18 +rect 32 16 36 22 +rect -2 6 17 9 +rect 21 6 36 9 +rect -2 5 36 6 +<< m2contact >> +rect 15 44 19 48 +rect -2 29 2 33 +rect 32 29 36 33 +rect 6 -2 10 2 +rect 20 -2 24 2 +<< metal2 >> +rect -2 33 2 48 +rect -2 -2 2 29 +rect 6 2 10 48 +rect 24 -2 28 48 +rect 32 33 36 48 +rect 32 -2 36 29 +<< bb >> +rect 0 0 34 46 +<< labels >> +rlabel metal2 0 0 0 0 1 gnd +rlabel metal2 34 0 34 0 1 gnd +rlabel m2contact 17 46 17 46 5 vdd +rlabel metal2 8 43 8 43 1 bl +rlabel metal2 26 43 26 43 1 br +rlabel metal1 4 7 4 7 1 wl +<< end >> diff --git a/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp b/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp new file mode 100644 index 00000000..ea939036 --- /dev/null +++ b/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp @@ -0,0 +1,18 @@ + +*********************** "cell_6t" ****************************** +.SUBCKT cell_6t bl br wl vdd gnd +* 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 + +* 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 + +* 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 + +.ENDS From d35f180609083be83e53aebd66720bd03d59c419 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 14 Jun 2019 15:05:14 -0700 Subject: [PATCH 044/234] Add dummy row --- compiler/modules/{replica_row.py => dummy_row.py} | 2 +- .../tests/{05_replica_row_test.py => 05_dummy_row_test.py} | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename compiler/modules/{replica_row.py => dummy_row.py} (99%) rename compiler/tests/{05_replica_row_test.py => 05_dummy_row_test.py} (81%) diff --git a/compiler/modules/replica_row.py b/compiler/modules/dummy_row.py similarity index 99% rename from compiler/modules/replica_row.py rename to compiler/modules/dummy_row.py index 25268993..147bf740 100644 --- a/compiler/modules/replica_row.py +++ b/compiler/modules/dummy_row.py @@ -11,7 +11,7 @@ from sram_factory import factory from vector import vector from globals import OPTS -class replica_row(design.design): +class dummy_row(design.design): """ Generate a replica wordline row for the replica array. """ diff --git a/compiler/tests/05_replica_row_test.py b/compiler/tests/05_dummy_row_test.py similarity index 81% rename from compiler/tests/05_replica_row_test.py rename to compiler/tests/05_dummy_row_test.py index 9d8e7ce2..92e7c176 100755 --- a/compiler/tests/05_replica_row_test.py +++ b/compiler/tests/05_dummy_row_test.py @@ -13,13 +13,13 @@ from globals import OPTS from sram_factory import factory import debug -class replica_row_test(openram_test): +class dummy_row_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) - debug.info(2, "Testing replica row for 6t_cell") - a = factory.create(module_type="replica_row", cols=4) + debug.info(2, "Testing dummy row for 6t_cell") + a = factory.create(module_type="dummy_row", cols=4) self.local_check(a) globals.end_openram() From 5c4df2410e8d0f569c53d3d80cf79b1b442cb79b Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 14 Jun 2019 15:06:04 -0700 Subject: [PATCH 045/234] Fix dummy row LVS issue --- compiler/bitcells/dummy_bitcell.py | 48 ++++++++++++++++++ .../scn4m_subm/gds_lib/dummy_cell_6t.gds | Bin 0 -> 5608 bytes .../scn4m_subm/mag_lib/dummy_cell_6t.mag | 11 ++-- technology/scn4m_subm/mag_lib/setup.tcl | 1 + technology/scn4m_subm/sp_lib/dummy_cell_6t.sp | 5 +- 5 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 compiler/bitcells/dummy_bitcell.py create mode 100644 technology/scn4m_subm/gds_lib/dummy_cell_6t.gds diff --git a/compiler/bitcells/dummy_bitcell.py b/compiler/bitcells/dummy_bitcell.py new file mode 100644 index 00000000..db748203 --- /dev/null +++ b/compiler/bitcells/dummy_bitcell.py @@ -0,0 +1,48 @@ +# 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 design +import debug +import utils +from tech import GDS,layer,parameter,drc +import logical_effort + +class dummy_bitcell(design.design): + """ + A single bit cell (6T, 8T, etc.) This module implements the + single memory cell used in the design. It is a hand-made cell, so + the layout and netlist should be available in the technology + library. + """ + + pin_names = ["bl", "br", "wl", "vdd", "gnd"] + (width,height) = utils.get_libcell_size("dummy_cell_6t", GDS["unit"], layer["boundary"]) + pin_map = utils.get_libcell_pins(pin_names, "dummy_cell_6t", GDS["unit"]) + + def __init__(self, name=""): + # Ignore the name argument + design.design.__init__(self, "dummy_cell_6t") + debug.info(2, "Create dummy bitcell") + + self.width = dummy_bitcell.width + self.height = dummy_bitcell.height + self.pin_map = dummy_bitcell.pin_map + + def analytical_power(self, corner, load): + """Bitcell power in nW. Only characterizes leakage.""" + from tech import spice + leakage = spice["bitcell_leakage"] + dynamic = 0 #temporary + total_power = self.return_power(dynamic, leakage) + return total_power + + def get_wl_cin(self): + """Return the relative capacitance of the access transistor gates""" + #This is a handmade cell so the value must be entered in the tech.py file or estimated. + #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. + access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] + return 2*access_tx_cin diff --git a/technology/scn4m_subm/gds_lib/dummy_cell_6t.gds b/technology/scn4m_subm/gds_lib/dummy_cell_6t.gds new file mode 100644 index 0000000000000000000000000000000000000000..d17cdd3bbb1c66e5cf011be20d23bf69521dc067 GIT binary patch literal 5608 zcmbuDJ#1V>6os$7_Il%NoVDX$Y~m%sN&LgG&Y(Z~c8^8k zC@w6%SN(65ezS!qk^9yClD9gci$1oDzu*7+#3!|3*6x+Ox)-|W?HNCw=-cjz5r>%Z zDfFy=dOi9ve)_|!duHfjUH<9y$h+`Fj5vy$+N=5Rmh}tI@@C`}SqthSx?bylWyh@1 zH4~RN6*uU5#&0%p96siaA2JSfG4GG~)QSA!+)3!7>)HJ5AAG7ioI8pABM$lBEbC{s zWM(%WnXPn7uJu9}y}g>h;_vtW@%$^NvH!$X-&5$K>-B!mJ+c#HD0r&4iQSyv>{1## z`=2=!^zjtBSmS4(F>bu#>PGBeF+cw3hj;ct#3<~ z)<1I?{iq%N;Z(;AU98JLa~OF!Ym9?4Lmb6T?bZD21Lx<+?B?w_>*DJNUN_f8*R%fC zuGwYpKj|^VE1#L6i>_z=*Pe%OZm}djbTRMm_xtxFw;h$dd=R?mW6S1eo{XKlPGlbF zVx7OWt1*aXjD`6J3q70v+Vk+uEsEh|{`gaS#vdNeJ$=RN&q5c6&i}yrGiQ9vRlNQz zY9ZG7r~eEeWq*2i}=vRyg%kiF6J+)rlRYa`b8dmbjpE>iP)*^Qo-$nnP^-~|-AMlHKQ{4)>Uh8M<#eJJd z9L0s+UhC(*k@XXamwW|>-X90*&mGq|jroe)-{_+2+5Gb_A}{Mkeyt-q>yX+r{&;4L zZu;5lnu(3{{vx_w_1~-R|8_6l)p%C%E(ghrF1nue^Xz85wAPSwh%S12)=$3bTCsMl z1-j_%RsXxgLspjgf6FhkBrkb$;$`YF*q{iNrz|y*)GjsLv(ONBzX5qtHdyGycfK86CJkeH@pJYR2c3ASJ?rO=Kl)aGe_=0=?Z=)@?V0@4IQ-S$Kk!rgV9{Rnzc+Y)g@0s6 zG}FBmtn-)S*Y9EMo3&nyKUnW)-*HcH{zQD}qU)LQ#~x>%>>m*ydtY=t>;HfCf-UP^V+U8mzrN~=SRn108+0X2737!DCfZ6uKXRrV?9l= JCVVDi_Ah|$OXvUq literal 0 HcmV?d00001 diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag b/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag index f2e9906a..c1b14848 100644 --- a/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag @@ -1,6 +1,6 @@ magic tech scmos -timestamp 1536091415 +timestamp 1560540221 << nwell >> rect -8 29 42 51 << pwell >> @@ -92,17 +92,18 @@ rect 32 16 36 22 rect -2 6 17 9 rect 21 6 36 9 rect -2 5 36 6 +rect 6 -2 10 2 +rect 20 -2 24 2 << m2contact >> rect 15 44 19 48 rect -2 29 2 33 rect 32 29 36 33 -rect 6 -2 10 2 -rect 20 -2 24 2 << metal2 >> rect -2 33 2 48 rect -2 -2 2 29 -rect 6 2 10 48 -rect 24 -2 28 48 +rect 6 -2 10 48 +rect 24 2 28 48 +rect 20 -2 28 2 rect 32 33 36 48 rect 32 -2 36 29 << bb >> diff --git a/technology/scn4m_subm/mag_lib/setup.tcl b/technology/scn4m_subm/mag_lib/setup.tcl index 01639fe2..2ba148b5 100644 --- a/technology/scn4m_subm/mag_lib/setup.tcl +++ b/technology/scn4m_subm/mag_lib/setup.tcl @@ -4,6 +4,7 @@ equate class {-circuit1 nfet} {-circuit2 n} equate class {-circuit1 pfet} {-circuit2 p} # This circuit has symmetries and needs to be flattened to resolve them # or the banks won't pass +flatten class {-circuit1 dummy_cell_6t} flatten class {-circuit1 bitcell_array_0} flatten class {-circuit1 bitcell_array_1} #flatten class {-circuit1 precharge_array_0} diff --git a/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp b/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp index ea939036..3b0584df 100644 --- a/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp +++ b/technology/scn4m_subm/sp_lib/dummy_cell_6t.sp @@ -1,7 +1,6 @@ -*********************** "cell_6t" ****************************** -.SUBCKT cell_6t bl br wl vdd gnd -* SPICE3 file created from cell_6t.ext - technology: scmos +*********************** "dummy_cell_6t" ****************************** +.SUBCKT dummy_cell_6t bl br wl vdd gnd * Inverter 1 M1000 Q Qbar vdd vdd p w=0.6u l=0.8u From 2b07db33c8c13905df2e848ab202d2a6b517dcb7 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Mon, 17 Jun 2019 15:31:16 -0700 Subject: [PATCH 046/234] Added bitcell as input to array, but there are DRC errors now. --- compiler/modules/bank.py | 12 +++--- compiler/modules/bitcell_array.py | 5 +-- compiler/modules/replica_bitline.py | 4 +- compiler/sram_factory.py | 2 + compiler/tests/16_control_logic_test.py | 51 +++++++++++++------------ 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index efdf228d..557297bd 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -401,18 +401,18 @@ class bank(design.design): def add_modules(self): """ Add all the modules using the class loader """ - - self.bitcell_array = factory.create(module_type="bitcell_array", - cols=self.num_cols, - rows=self.num_rows) - self.add_mod(self.bitcell_array) - # create arrays of bitline and bitline_bar names for read, write, or all ports self.bitcell = factory.create(module_type="bitcell") self.bl_names = self.bitcell.list_all_bl_names() self.br_names = self.bitcell.list_all_br_names() self.wl_names = self.bitcell.list_all_wl_names() self.bitline_names = self.bitcell.list_all_bitline_names() + + self.bitcell_array = factory.create(module_type="bitcell_array", + cols=self.num_cols, + rows=self.num_rows, + bitcell=self.bitcell) + self.add_mod(self.bitcell_array) self.precharge_array = [] for port in self.all_ports: diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 361b922a..17b82199 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -19,13 +19,14 @@ class bitcell_array(design.design): and word line is connected by abutment. Connects the word lines and bit lines. """ - def __init__(self, cols, rows, name): + def __init__(self, cols, rows, name, bitcell): 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)) self.column_size = cols self.row_size = rows + self.cell = bitcell self.create_netlist() if not OPTS.netlist_only: @@ -84,8 +85,6 @@ class bitcell_array(design.design): def add_modules(self): """ Add the modules used in this design """ - self.cell = factory.create(module_type="bitcell") - debug.info(1,"Cell mod created, id={}".format(id(self.cell))) self.add_mod(self.cell) def create_instances(self): diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index acd1f5d0..8bfaf0f2 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -86,10 +86,12 @@ class replica_bitline(design.design): self.replica_bitcell = factory.create(module_type="replica_bitcell") self.add_mod(self.replica_bitcell) + bitcell = factory.create(module_type="bitcell") # This is the replica bitline load column that is the height of our array self.rbl = factory.create(module_type="bitcell_array", cols=1, - rows=self.bitcell_loads) + rows=self.bitcell_loads, + bitcell=bitcell) self.add_mod(self.rbl) # FIXME: The FO and depth of this should be tuned diff --git a/compiler/sram_factory.py b/compiler/sram_factory.py index 0b079780..f53a72d5 100644 --- a/compiler/sram_factory.py +++ b/compiler/sram_factory.py @@ -65,6 +65,8 @@ class sram_factory: # Must have the same dictionary exactly (conservative) if obj_kwargs == kwargs: #debug.info(0, "Existing module: type={0} name={1} kwargs={2}".format(module_type, obj_item.name, str(kwargs))) + if module_type == 'bitcell_array': + debug.info(1,'Returning existing mod!') return obj_item #else: # print("obj",obj_kwargs) diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index ed8a0088..78866d7b 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -26,36 +26,37 @@ class control_logic_test(openram_test): import control_logic import tech - # check control logic for single port - debug.info(1, "Testing sample for control_logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32) - self.local_check(a) + # # check control logic for single port + # debug.info(1, "Testing sample for control_logic") + # a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32) + # self.local_check(a) # check control logic for multi-port OPTS.bitcell = "pbitcell" OPTS.replica_bitcell = "replica_pbitcell" - OPTS.num_rw_ports = 1 - OPTS.num_w_ports = 0 - OPTS.num_r_ports = 0 - - debug.info(1, "Testing sample for control_logic for multiport") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8) - self.local_check(a) - - # Check port specific control logic - OPTS.num_rw_ports = 1 - OPTS.num_w_ports = 0 - OPTS.num_r_ports = 0 - - debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="rw") - self.local_check(a) - + #OPTS.num_rw_ports = 1 OPTS.num_rw_ports = 0 - OPTS.num_w_ports = 1 - debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="w") - self.local_check(a) + OPTS.num_w_ports = 0 + OPTS.num_r_ports = 0 + + # debug.info(1, "Testing sample for control_logic for multiport") + # a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8) + # self.local_check(a) + + # # Check port specific control logic + # OPTS.num_rw_ports = 1 + # OPTS.num_w_ports = 0 + # OPTS.num_r_ports = 0 + + # debug.info(1, "Testing sample for control_logic for multiport, only write control logic") + # a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="rw") + # self.local_check(a) + + # OPTS.num_rw_ports = 0 + # OPTS.num_w_ports = 1 + # debug.info(1, "Testing sample for control_logic for multiport, only write control logic") + # a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="w") + # self.local_check(a) OPTS.num_w_ports = 0 OPTS.num_r_ports = 1 From 4523a7b9f6dc23bf69207475010e48bfeb0c135b Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 19 Jun 2019 16:03:21 -0700 Subject: [PATCH 047/234] Replica bitcell array working --- compiler/base/hierarchy_layout.py | 22 +- compiler/base/hierarchy_spice.py | 4 + compiler/bitcells/bitcell.py | 9 - compiler/bitcells/replica_bitcell.py | 8 + compiler/modules/bank.py | 18 +- compiler/modules/bitcell_array.py | 40 +- compiler/modules/dummy_array.py | 156 ++++++++ compiler/modules/dummy_row.py | 133 ------- compiler/modules/replica_bitcell_array.py | 366 ++++++++++++++++++ compiler/modules/replica_column.py | 37 +- compiler/tests/05_dummy_array_test.py | 36 ++ ...st.py => 05_replica_bitcell_array_test.py} | 6 +- technology/scn4m_subm/gds_lib/cell_6t.gds | Bin 5724 -> 5788 bytes .../scn4m_subm/gds_lib/dummy_cell_6t.gds | Bin 5608 -> 5544 bytes .../scn4m_subm/gds_lib/replica_cell_6t.gds | Bin 5804 -> 5868 bytes technology/scn4m_subm/mag_lib/cell_6t.mag | 191 ++++----- .../scn4m_subm/mag_lib/dummy_cell_6t.mag | 189 +++++---- .../scn4m_subm/mag_lib/replica_cell_6t.mag | 193 ++++----- 18 files changed, 931 insertions(+), 477 deletions(-) create mode 100644 compiler/modules/dummy_array.py delete mode 100644 compiler/modules/dummy_row.py create mode 100644 compiler/modules/replica_bitcell_array.py create mode 100755 compiler/tests/05_dummy_array_test.py rename compiler/tests/{05_dummy_row_test.py => 05_replica_bitcell_array_test.py} (79%) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 24db008b..203344b5 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -214,7 +214,13 @@ class layout(): return self.pin_map[text] else: return set() - + + def get_pin_names(self): + """ + Return a pin list of all pins + """ + return self.pin_map.keys() + def copy_layout_pin(self, instance, pin_name, new_name=""): """ Create a copied version of the layout pin at the current level. @@ -226,6 +232,16 @@ class layout(): new_name = pin.name self.add_layout_pin(new_name, pin.layer, pin.ll(), pin.width(), pin.height()) + def copy_layout_pins(self, instance, prefix=""): + """ + Create a copied version of the layout pin at the current level. + You can optionally rename the pin to a new name. + """ + for pin_name in self.pin_map.keys(): + pins=instance.get_pins(pin_name) + for pin in pins: + self.add_layout_pin(prefix+pin_name, pin.layer, pin.ll(), pin.width(), pin.height()) + def add_layout_pin_segment_center(self, text, layer, start, end): """ Creates a path like pin with center-line convention @@ -880,10 +896,10 @@ class layout(): """ self.create_channel_route(netlist, offset, layer_stack, pitch, vertical=False) - def add_boundary(self): + def add_boundary(self, offset=vector(0,0)): """ Add boundary for debugging dimensions """ self.add_rect(layer="boundary", - offset=vector(0,0), + offset=offset, height=self.height, width=self.width) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 0d649598..d2c6813e 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -102,6 +102,10 @@ class spice(): output_list.append(pin) return output_list + def copy_pins(self, other_module, suffix=""): + """ This will copy all of the pins from the other module and add an optional suffix.""" + for pin in other_module.pins: + self.add_pin(pin+suffix, other_module.get_pin_type(pin)) def add_mod(self, mod): """Adds a subckt/submodule to the subckt hierarchy""" diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 9711de62..cd8b3a43 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -38,15 +38,6 @@ class bitcell(design.design): cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file. return logical_effort.logical_effort('bitline', size, cin, load, parasitic_delay, False) - def list_bitcell_pins(self, col, row): - """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ - bitcell_pins = ["bl_{0}".format(col), - "br_{0}".format(col), - "wl_{0}".format(row), - "vdd", - "gnd"] - return bitcell_pins - def list_all_wl_names(self): """ Creates a list of all wordline pin names """ row_pins = ["wl"] diff --git a/compiler/bitcells/replica_bitcell.py b/compiler/bitcells/replica_bitcell.py index f95249b0..6d714d7e 100644 --- a/compiler/bitcells/replica_bitcell.py +++ b/compiler/bitcells/replica_bitcell.py @@ -30,6 +30,14 @@ class replica_bitcell(design.design): self.height = replica_bitcell.height self.pin_map = replica_bitcell.pin_map + def analytical_power(self, corner, load): + """Bitcell power in nW. Only characterizes leakage.""" + from tech import spice + leakage = spice["bitcell_leakage"] + dynamic = 0 #temporary + total_power = self.return_power(dynamic, leakage) + return total_power + def get_wl_cin(self): """Return the relative capacitance of the access transistor gates""" #This is a handmade cell so the value must be entered in the tech.py file or estimated. diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 20498752..23bb28ae 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -270,13 +270,15 @@ class bank(design.design): # the bitcell array. # The decoder/driver logic is placed on the right and mirrored on Y-axis. # The write/sense/precharge/mux is placed on the top and mirrored on the X-axis. - + + bitcell_array_top = self.bitcell_array.height + self.m2_gap + drc("well_enclosure_active") + self.m1_width + bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap # LOWER LEFT QUADRANT # Bitcell array is placed at (0,0) # UPPER LEFT QUADRANT # Above the bitcell array - y_offset = self.bitcell_array.height + self.m2_gap + y_offset = bitcell_array_top for i,p in enumerate(self.vertical_port_order[port]): if p==None: continue @@ -292,7 +294,7 @@ class bank(design.design): # LOWER RIGHT QUADRANT # To the left of the bitcell array # The wordline driver is placed to the right of the main decoder width. - x_offset = self.bitcell_array.width + self.m2_gap + self.wordline_driver.width + x_offset = bitcell_array_right + self.wordline_driver.width self.wordline_driver_offsets[port] = vector(x_offset,0) x_offset += self.row_decoder.width + self.m2_gap self.row_decoder_offsets[port] = vector(x_offset,0) @@ -300,12 +302,12 @@ class bank(design.design): # UPPER RIGHT QUADRANT # Place the col decoder right aligned with wordline driver plus halfway under row decoder # Above the bitcell array with a well spacing - x_offset = self.bitcell_array.width + self.central_bus_width[port] + self.wordline_driver.width + x_offset = bitcell_array_right + self.central_bus_width[port] + self.wordline_driver.width if self.col_addr_size > 0: x_offset += self.column_decoder.width + self.col_addr_bus_width - y_offset = self.bitcell_array.height + self.column_decoder.height + self.m2_gap + y_offset = bitcell_array_height + self.column_decoder.height else: - y_offset = self.bitcell_array.height + y_offset = bitcell_array_height y_offset += 2*drc("well_to_well") self.column_decoder_offsets[port] = vector(x_offset,y_offset) @@ -860,8 +862,8 @@ class bank(design.design): # Port 1 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.bitcell_array.height - 2*self.m1_pitch - control_bus_offset = vector(self.bitcell_array.width + self.m2_width, + control_bus_length = self.max_y_offset - bitcell_array_top - 2*self.m1_pitch + control_bus_offset = vector(bitcell_array_right, self.max_y_offset - control_bus_length) self.bus_xoffset[1] = self.create_bus(layer="metal2", diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 01b64c11..db754ccf 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -45,8 +45,8 @@ class bitcell_array(design.design): def create_layout(self): # We increase it by a well enclosure so the precharges don't overlap our wells - self.height = self.row_size*self.cell.height + drc("well_enclosure_active") + self.m1_width - self.width = self.column_size*self.cell.width + self.m1_width + self.height = self.row_size*self.cell.height + self.width = self.column_size*self.cell.width xoffset = 0.0 for col in range(self.column_size): @@ -89,6 +89,24 @@ class bitcell_array(design.design): self.cell = factory.create(module_type="bitcell") self.add_mod(self.cell) + def list_bitcell_pins(self, col, row): + """ Creates a list of connections in the bitcell, + indexed by column and row, for instance use in bitcell_array """ + + bitcell_pins = [] + + pin_names = self.cell.list_all_bitline_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(col)) + pin_names = self.cell.list_all_wl_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(row)) + bitcell_pins.append("vdd") + bitcell_pins.append("gnd") + + return bitcell_pins + + def create_instances(self): """ Create the module instances used in this design """ self.cell_inst = {} @@ -97,7 +115,7 @@ class bitcell_array(design.design): 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.cell.list_bitcell_pins(col, row)) + self.connect_inst(self.list_bitcell_pins(col, row)) def add_layout_pins(self): """ Add the layout pins """ @@ -105,32 +123,24 @@ class bitcell_array(design.design): row_list = self.cell.list_all_wl_names() column_list = self.cell.list_all_bitline_names() - offset = vector(0.0, 0.0) 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), - layer="metal2", - offset=bl_pin.ll(), + layer=bl_pin.layer, + offset=bl_pin.ll().scale(1,0), width=bl_pin.width(), height=self.height) - - # increments to the next column width - offset.x += self.cell.width - offset.x = 0.0 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), - layer="metal1", - offset=wl_pin.ll(), + layer=wl_pin.layer, + offset=wl_pin.ll().scale(0,1), width=self.width, height=wl_pin.height()) - # increments to the next row height - offset.y += self.cell.height - # For every second row and column, add a via for gnd and vdd for row in range(self.row_size): for col in range(self.column_size): diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py new file mode 100644 index 00000000..0790367f --- /dev/null +++ b/compiler/modules/dummy_array.py @@ -0,0 +1,156 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# All rights reserved. +# +import debug +import design +from tech import drc +import contact +from sram_factory import factory +from vector import vector +from globals import OPTS + +class dummy_array(design.design): + """ + Generate a dummy row/column for the replica array. + """ + def __init__(self, cols, rows, 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)) + + self.column_size = cols + self.row_size = rows + + 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): + + # We increase it by a well enclosure so the precharges don't overlap our wells + self.height = self.row_size*self.dummy_cell.height + self.width = self.column_size*self.dummy_cell.width + + xoffset = 0.0 + for col in range(self.column_size): + yoffset = 0.0 + for row in range(self.row_size): + name = "dummy_r{0}_c{1}".format(row, col) + + if row % 2: + tempy = yoffset + self.dummy_cell.height + dir_key = "MX" + else: + tempy = yoffset + dir_key = "" + + self.cell_inst[row,col].place(offset=[xoffset, tempy], + mirror=dir_key) + yoffset += self.dummy_cell.height + xoffset += self.dummy_cell.width + + self.add_layout_pins() + + self.add_boundary() + + self.DRC_LVS() + + def add_pins(self): + row_list = self.cell.list_all_wl_names() + column_list = self.cell.list_all_bitline_names() + for col in range(self.column_size): + for cell_column in column_list: + self.add_pin(cell_column+"_{0}".format(col)) + for row in range(self.row_size): + for cell_row in row_list: + self.add_pin(cell_row+"_{0}".format(row)) + self.add_pin("vdd") + self.add_pin("gnd") + + def add_modules(self): + """ Add the modules used in this design """ + self.dummy_cell = factory.create(module_type="dummy_bitcell") + self.add_mod(self.dummy_cell) + + self.cell = factory.create(module_type="bitcell") + + def list_bitcell_pins(self, col, row): + """ Creates a list of connections in the bitcell, + indexed by column and row, for instance use in bitcell_array """ + + bitcell_pins = [] + + pin_names = self.cell.list_all_bitline_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(col)) + pin_names = self.cell.list_all_wl_names() + for pin in pin_names: + bitcell_pins.append(pin+"_{0}".format(row)) + bitcell_pins.append("vdd") + bitcell_pins.append("gnd") + + return bitcell_pins + + + def create_instances(self): + """ Create the module instances used in this design """ + self.cell_inst = {} + for col in range(self.column_size): + for row in range(self.row_size): + 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.list_bitcell_pins(col, row)) + + def add_layout_pins(self): + """ Add the layout pins """ + + row_list = self.cell.list_all_wl_names() + column_list = self.cell.list_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), + layer="metal2", + offset=bl_pin.ll(), + width=bl_pin.width(), + height=self.height) + + 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), + layer="metal1", + offset=wl_pin.ll(), + width=self.width, + height=wl_pin.height()) + + # For every second row and column, add a via for gnd and vdd + for row in range(self.row_size): + for col in range(self.column_size): + inst = self.cell_inst[row,col] + for pin_name in ["vdd", "gnd"]: + for pin in inst.get_pins(pin_name): + self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) + + + def input_load(self): + wl_wire = self.gen_wl_wire() + return wl_wire.return_input_cap() + + def get_wordline_cin(self): + """Get the relative input capacitance from the wordline connections in all the bitcell""" + #A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns + bitcell_wl_cin = self.cell.get_wl_cin() + total_cin = bitcell_wl_cin * self.column_size + return total_cin diff --git a/compiler/modules/dummy_row.py b/compiler/modules/dummy_row.py deleted file mode 100644 index 147bf740..00000000 --- a/compiler/modules/dummy_row.py +++ /dev/null @@ -1,133 +0,0 @@ -# See LICENSE for licensing information. -# -# Copyright (c) 2016-2019 Regents of the University of California -# All rights reserved. -# -import debug -import design -from tech import drc -import contact -from sram_factory import factory -from vector import vector -from globals import OPTS - -class dummy_row(design.design): - """ - Generate a replica wordline row for the replica array. - """ - - def __init__(self, name, cols): - design.design.__init__(self, name) - - self.column_size = cols - - self.create_netlist() - if not OPTS.netlist_only: - self.create_layout() - - def create_netlist(self): - self.add_modules() - self.add_pins() - self.create_instances() - - def create_layout(self): - self.place_instances() - self.add_layout_pins() - - self.add_boundary() - self.DRC_LVS() - - def add_pins(self): - column_list = self.cell.list_all_bitline_names() - for col in range(self.column_size): - for cell_column in column_list: - self.add_pin("{0}_{1}".format(cell_column,col)) - row_list = self.cell.list_all_wl_names() - for cell_row in row_list: - self.add_pin("{0}_{1}".format(cell_row,0)) - - self.add_pin("vdd") - self.add_pin("gnd") - - def add_modules(self): - self.dummy_cell = factory.create(module_type="dummy_bitcell") - self.add_mod(self.dummy_cell) - # Used for pin names only - self.cell = factory.create(module_type="bitcell") - - def create_instances(self): - self.cell_inst = {} - for col in range(self.column_size): - name="dummy_{0}".format(col) - self.cell_inst[col]=self.add_inst(name=name, - mod=self.dummy_cell) - self.connect_inst(self.list_bitcell_pins(col, 0)) - - def create_layout(self): - - # We increase it by a well enclosure so the precharges don't overlap our wells - self.height = self.cell.height - self.width = self.column_size*self.cell.width - - xoffset = 0.0 - tempy = self.cell.height - dir_key = "MX" - for col in range(self.column_size): - name = "bit_{0}_c{1}".format("dummy",col) - self.cell_inst[col].place(offset=[xoffset, tempy], - mirror=dir_key) - xoffset += self.cell.width - - self.add_layout_pins() - - self.add_boundary() - - self.DRC_LVS() - - - def add_layout_pins(self): - """ Add the layout pins """ - - row_list = self.cell.list_all_wl_names() - column_list = self.cell.list_all_bitline_names() - - for col in range(self.column_size): - for cell_column in column_list: - bl_pin = self.cell_inst[col].get_pin(cell_column) - self.add_layout_pin(text=cell_column+"_{0}".format(col), - layer="metal2", - offset=bl_pin.ll(), - width=bl_pin.width(), - height=self.height) - - for cell_row in row_list: - wl_pin = self.cell_inst[0].get_pin(cell_row) - self.add_layout_pin(text=cell_row+"_{0}".format(0), - layer="metal1", - offset=wl_pin.ll(), - width=self.width, - height=wl_pin.height()) - - # For every second row and column, add a via for gnd and vdd - for col in range(self.column_size): - inst = self.cell_inst[col] - for pin_name in ["vdd", "gnd"]: - self.copy_layout_pin(inst, pin_name) - - def list_bitcell_pins(self, col, row): - """ Creates a list of connections in the bitcell, - indexed by column and row, for instance use in bitcell_array """ - - bitcell_pins = [] - - pin_names = self.cell.list_all_bitline_names() - for pin in pin_names: - bitcell_pins.append(pin+"_{0}".format(col)) - pin_names = self.cell.list_all_wl_names() - for pin in pin_names: - bitcell_pins.append(pin+"_{0}".format(row)) - bitcell_pins.append("vdd") - bitcell_pins.append("gnd") - - return bitcell_pins - diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py new file mode 100644 index 00000000..0bf635ca --- /dev/null +++ b/compiler/modules/replica_bitcell_array.py @@ -0,0 +1,366 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# All rights reserved. +# + +import debug +import design +from tech import drc, spice +from vector import vector +from globals import OPTS +from sram_factory import factory +import logical_effort +import bitcell_array +import replica_column +import dummy_array + +class replica_bitcell_array(design.design): + """ + Creates a bitcell arrow of cols x rows and then adds the replica and dummy columns + and rows for one or two read ports. Replica columns are on the left and right, respectively. + Dummy are the outside columns/rows with WL and BL tied to gnd. + Requires a regular bitcell array, replica bitcell, and dummy bitcell (Bl/BR disconnected). + """ + def __init__(self, cols, rows, 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)) + + self.column_size = cols + self.row_size = rows + + 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 add_modules(self): + """ Array and dummy/replica columns + + d or D = dummy cell (caps to distinguish grouping) + r or R = replica cell (caps to distinguish grouping) + b or B = bitcell + replica columns 1 + v v + bdDDDDDDDDDDDDDDdb <- Dummy row + bdDDDDDDDDDDDDDDrb <- Dummy row + br--------------rb + br| Array |rb + br| row x col |rb + br--------------rb + brDDDDDDDDDDDDDDdb <- Dummy row + bdDDDDDDDDDDDDDDdb <- Dummy row + + ^^^^^^^^^^^^^^^ + dummy rows cols x 1 + + ^ dummy columns ^ + 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", + cols=self.column_size, + rows=self.row_size) + self.add_mod(self.bitcell_array) + + # Replica bitline + self.replica_column = factory.create(module_type="replica_column", + rows=self.row_size + 4) + self.add_mod(self.replica_column) + + # Dummy row + self.dummy_row = factory.create(module_type="dummy_array", + rows=1, + cols=self.column_size) + self.add_mod(self.dummy_row) + + # Dummy col + self.dummy_col = factory.create(module_type="dummy_array", + cols=1, + rows=self.row_size + 4) + self.add_mod(self.dummy_col) + + + + def add_pins(self): + + self.wl_names = [x for x in self.bitcell_array.pins if x.startswith("w")] + self.bl_names = [x for x in self.bitcell_array.pins if x.startswith("b")] + + # top/bottom rows (in the middle) + self.replica_wl_names = ["replica_"+x for x in self.cell.pins if x.startswith("w")] + self.dummy_wl_names = ["dummy_"+x for x in self.cell.pins if x.startswith("w")] + self.dummy_bl_names = ["dummy_"+x for x in self.cell.pins if x.startswith("b")] + self.dummy_row_bl_names = self.bl_names + + # dummy row and replica on each side of the bitcell rows + self.replica_col_wl_names = [x+"_0" for x in self.dummy_wl_names] \ + + ["replica_"+x+"_0" for x in self.cell.list_all_wl_names()] \ + + self.wl_names \ + + ["replica_"+x+"_1" for x in self.cell.list_all_wl_names()] \ + + [x+"_1" for x in self.dummy_wl_names] + self.replica_bl_names = ["replica_"+x for x in self.cell.pins if x.startswith("b")] + + # left/right rows + self.dummy_col_wl_names = self.replica_col_wl_names + + + self.add_pin_list(self.bl_names) + self.add_pin_list([x+"_0" for x in self.replica_bl_names]) + self.add_pin_list([x+"_1" for x in self.replica_bl_names]) + self.add_pin_list([x for x in self.replica_col_wl_names if not x.startswith("dummy")]) + + self.add_pin("vdd") + self.add_pin("gnd") + + + def create_instances(self): + """ Create the module instances used in this design """ + + supplies = ["vdd", "gnd"] + # Main array + self.bitcell_array_inst=self.add_inst(name="bitcell_array", + mod=self.bitcell_array) + self.connect_inst(self.bitcell_array.pins) + + # Replica columns (two even if one port for now) + self.replica_col_left_inst=self.add_inst(name="replica_col_left", + mod=self.replica_column) + self.connect_inst([x+"_0" for x in self.replica_bl_names] + self.replica_col_wl_names + supplies) + + self.replica_col_right_inst=self.add_inst(name="replica_col_right", + mod=self.replica_column) + self.connect_inst([x+"_1" for x in self.replica_bl_names] + self.replica_col_wl_names[::-1] + supplies) + + # Replica rows with replica bitcell + self.dummy_row_bottop_inst=self.add_inst(name="dummy_row_bottop", + mod=self.dummy_row) + self.connect_inst(self.dummy_row_bl_names + [x+"_0" for x in self.replica_wl_names] + supplies) + self.dummy_row_topbot_inst=self.add_inst(name="dummy_row_topbot", + mod=self.dummy_row) + self.connect_inst(self.dummy_row_bl_names + [x+"_1" for x in self.replica_wl_names] + supplies) + + + # Dummy rows without replica bitcell + self.dummy_row_botbot_inst=self.add_inst(name="dummy_row_botbot", + mod=self.dummy_row) + self.connect_inst(self.dummy_row_bl_names + [x+"_0" for x in self.dummy_wl_names] + supplies) + self.dummy_row_toptop_inst=self.add_inst(name="dummy_row_toptop", + mod=self.dummy_row) + self.connect_inst(self.dummy_row_bl_names + [x+"_1" for x in self.dummy_wl_names] + supplies) + + + # Dummy columns + self.dummy_col_left_inst=self.add_inst(name="dummy_col_left", + mod=self.dummy_col) + self.connect_inst([x+"_0" for x in self.dummy_bl_names] + self.dummy_col_wl_names + supplies) + self.dummy_col_right_inst=self.add_inst(name="dummy_col_right", + mod=self.dummy_col) + self.connect_inst([x+"_1" for x in self.dummy_bl_names] + self.dummy_col_wl_names + supplies) + + + + def create_layout(self): + + self.height = (self.row_size+4)*self.dummy_row.height + self.width = (self.column_size+4)*self.replica_column.width + + # This is a bitcell x bitcell offset to scale + offset = vector(self.replica_column.width, self.dummy_row.height) + + self.bitcell_array_inst.place(offset=[0,0]) + self.replica_col_left_inst.place(offset=offset.scale(-1,-2)) + self.replica_col_right_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ur(), + mirror="MX") + + self.dummy_row_toptop_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ul(), + mirror="MX") + self.dummy_row_topbot_inst.place(offset=offset.scale(0,0)+self.bitcell_array_inst.ul()) + self.dummy_row_bottop_inst.place(offset=offset.scale(0,0), + mirror="MX") + self.dummy_row_botbot_inst.place(offset=offset.scale(0,-2)) + + self.dummy_col_left_inst.place(offset=offset.scale(-2,-2)) + self.dummy_col_right_inst.place(offset=offset.scale(1,-2)+self.bitcell_array_inst.lr()) + + self.translate_all(offset.scale(-2,-2)) + + self.add_layout_pins() + + self.add_boundary() + + self.DRC_LVS() + + + def add_layout_pins(self): + """ Add the layout pins """ + + # Main array wl and bl/br + pin_names = self.bitcell_array.get_pin_names() + for pin_name in pin_names: + if pin_name.startswith("wl"): + pin_list = self.bitcell_array_inst.get_pins(pin_name) + for pin in pin_list: + self.add_layout_pin_rect_center(text=pin_name, + layer=pin.layer, + offset=pin.center(), + width=self.width, + height=pin.height()) + elif pin_name.startswith("bl") or pin_name.startswith("br"): + pin_list = self.bitcell_array_inst.get_pins(pin_name) + for pin in pin_list: + self.add_layout_pin_rect_center(text=pin_name, + layer=pin.layer, + offset=pin.center(), + width=pin.width(), + height=self.height) + + + for index,(side1,side2) in enumerate([("bottop","left"),("topbot","right")]): + inst = getattr(self, "dummy_row_{}_inst".format(side1)) + pin_names = inst.mod.get_pin_names() + for pin_name in pin_names: + if pin_name.startswith("wl"): + pin_list = inst.get_pins(pin_name) + for pin in pin_list: + name = "replica_{0}_{1}".format(pin_name,index) + self.add_layout_pin_rect_center(text=name, + layer=pin.layer, + offset=pin.center(), + width=self.width, + height=pin.height()) + + # Replica columns + for index,side in enumerate(["left","right"]): + inst = getattr(self, "replica_col_{}_inst".format(side)) + pin_names = inst.mod.get_pin_names() + for pin_name in pin_names: + if pin_name.startswith("bl") or pin_name.startswith("br"): + pin_list = inst.get_pins(pin_name) + for pin in pin_list: + name = "replica_{0}_{1}".format(pin_name,index) + self.add_layout_pin(text=name, + layer=pin.layer, + offset=pin.ll().scale(1,0), + width=pin.width(), + height=self.height) + + + for pin_name in ["vdd","gnd"]: + for inst in [self.bitcell_array_inst, + self.replica_col_left_inst, self.replica_col_right_inst, + self.dummy_col_left_inst, self.dummy_col_right_inst, + self.dummy_row_toptop_inst, self.dummy_row_topbot_inst, + self.dummy_row_bottop_inst, self.dummy_row_botbot_inst]: + pin_list = inst.get_pins(pin_name) + for pin in pin_list: + self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) + + + # Non-pins + + for side in ["botbot", "toptop"]: + inst = getattr(self, "dummy_row_{}_inst".format(side)) + pin_names = inst.mod.get_pin_names() + for pin_name in pin_names: + if pin_name.startswith("wl"): + pin_list = inst.get_pins(pin_name) + for pin in pin_list: + self.add_rect_center(layer=pin.layer, + offset=pin.center(), + width=self.width, + height=pin.height()) + + + for side in ["left", "right"]: + inst = getattr(self, "dummy_col_{}_inst".format(side)) + pin_names = inst.mod.get_pin_names() + for pin_name in pin_names: + if pin_name.startswith("b"): + pin_list = inst.get_pins(pin_name) + for pin in pin_list: + self.add_rect_center(layer=pin.layer, + offset=pin.center(), + width=pin.width(), + height=self.height) + + + + def analytical_delay(self, corner, slew, load): + """Returns relative delay of the bitline in the bitcell array""" + from tech import parameter + #The load being driven/drained is mostly the bitline but could include the sense amp or the column mux. + #The load from the bitlines is due to the drain capacitances from all the other bitlines and wire parasitics. + drain_load = logical_effort.convert_farad_to_relative_c(parameter['bitcell_drain_cap']) + wire_unit_load = .05 * drain_load #Wires add 5% to this. + bitline_load = (drain_load+wire_unit_load)*self.row_size + return [self.cell.analytical_delay(corner, slew, load+bitline_load)] + + def analytical_power(self, corner, load): + """Power of Bitcell array and bitline in nW.""" + from tech import drc, parameter + + # Dynamic Power from Bitline + bl_wire = self.gen_bl_wire() + cell_load = 2 * bl_wire.return_input_cap() + bl_swing = parameter["rbl_height_percentage"] + freq = spice["default_event_rate"] + 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) + return total_power + + def gen_wl_wire(self): + if OPTS.netlist_only: + width = 0 + else: + width = self.width + wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_metal1")) + wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell + return wl_wire + + def gen_bl_wire(self): + if OPTS.netlist_only: + height = 0 + else: + height = self.height + bl_pos = 0 + bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), height, drc("minwidth_metal1")) + bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell + return bl_wire + + def output_load(self, bl_pos=0): + bl_wire = self.gen_bl_wire() + return bl_wire.wire_c # sense amp only need to charge small portion of the bl + # set as one segment for now + + def input_load(self): + wl_wire = self.gen_wl_wire() + return wl_wire.return_input_cap() + + def get_wordline_cin(self): + """Get the relative input capacitance from the wordline connections in all the bitcell""" + #A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns + bitcell_wl_cin = self.cell.get_wl_cin() + total_cin = bitcell_wl_cin * self.column_size + return total_cin diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 91f2881a..0de0aace 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -19,8 +19,7 @@ class replica_column(design.design): def __init__(self, name, rows): design.design.__init__(self, name) - # One extra row for the dummy row - self.row_size = rows + 1 + self.row_size = rows self.create_netlist() if not OPTS.netlist_only: @@ -35,6 +34,9 @@ class replica_column(design.design): self.place_instances() self.add_layout_pins() + self.height = self.row_size*self.cell.height + self.width = self.cell.width + self.add_boundary() self.DRC_LVS() @@ -53,6 +55,8 @@ class replica_column(design.design): def add_modules(self): self.replica_cell = factory.create(module_type="replica_bitcell") self.add_mod(self.replica_cell) + self.dummy_cell = factory.create(module_type="dummy_bitcell") + self.add_mod(self.dummy_cell) # Used for pin names only self.cell = factory.create(module_type="bitcell") @@ -60,37 +64,32 @@ class replica_column(design.design): self.cell_inst = {} for row in range(self.row_size): name="rbc_{0}".format(row) - self.cell_inst[row]=self.add_inst(name=name, - mod=self.replica_cell) + if row>0 and row$rF~$fZBW@i@ zT)OGlu_KdVWMpJ??5K(Hc|PylFZb75&y9&UX+GuqyWewuzw`TZf7E)`v97J0=-316 z*_@rVzAe1^{iH41pws*6>z$p?-}}LAzB~Ql$3MOQ>2JRre(=e`&Ap%ReP%1uE#6-3 zo$8zQ&U9?udb1rf+ZcAo<3FF8UASvDdR}wmapWPADLa;uX)4!gf4n};vbLydTDm*&}`r_#Q8g+i>@brFUT#k6T9ITiGwb> zp8DrD<30M%`*8k_8M@e(pZCbictzqUZq;7q->B;s;~e?Kl2^R?D0I>FR{v!mYj2M9C~na8#BX-;i}11j@k9E7 zF1GnuU%bco#nr=Df1>MYe*ENR4n*Q8Zq=UpsXspQi}=w+*Asu#=lsj4pSWb9i>@dB z$b*mkBDu?-+#h+UIeS(-7iXS{uBZ9gAFO@+B5}|~*Hizwr|};B=Y5D){KeM(=4X!Z(_axEy4dEY&iJUmh!0)N{V~pk zUt|2@;#TOQ>*@H(gOB{;;#TAr8~(S-{lgrM`Z3=k_aSuA^)ml4KXX6hF+}1hE_6Nh zK(&&_&l<{TJ@mdxt$l9L0s+p8AK|(O1?FeTLkn(8ad# zQy;!v_(bAVb(^qpe>hfuyquFFaTFK2p7x)1&VJ@kBu?d<(Dl@R=60+d#;db*;PZzr zx}N%dZBFtsf8^IZqB9Rwd*YApAAMgL#Ta0}y1$6tUixpA>z_X2nH|<7FS_XMsh|4= z^F{qd`iw3%=Kn~3@^V(4-K)u(Ll?ch%>Pca|9tm&U*x+-|Ha1lukgn?!}vLW#f$r) zi;eLY{y1mwv4=$J#b8jr~&)0^E8*JPk3x9R)x_{vFMI6Yzm%Svm`K$ZwWbNT+4eH)3w)y|< z{!1Ou#Wp|vyyW#}t%~#mU39%%zs2~YKCE5pCti9Oy6Af1k36hB-F+baP`{wJxBA(; z^j{=i<(ts;)X#e3oTu(0<3<-x_Bl>=2nhbg^yz`OYwQ>L{{@%I}ZsN&jP=G1uf5 zPalLXx}NyWruO~ZaWCI4k-y!bi>{}BYNr49i1^UOhX38>`DOmFe?*;IqU&Y;!XN#_ z$9fU@y950fT~GbgoO6PGC*ngFT~Gb26~@W>5%HmmuBZP0SHH+({*a$X{|_ZU^8x)y z^RrHQSU)_Fexr;2Yw7=}o-E}MJL|-DY;58s!AgKY3`k%aFcJk4O^Os24Hg8E!a@;3A?22# zb7_gj9VuP9bcI~HOzG04%OD|^`^|kPGrQpp1(7!2`n);!zIWfx%#O9JVdJ(s*09Gm zWlfv$zit-aXRKqlZPPl9)_33U?tb&p&t~)E6Q6$m>&IXH@%zOmUmV>%`0eZawmMPc zZI#|;+pIOyu+OYD+c2{`-Esdv{d;XMzQCIo@m=)4nsfe1{A)+VDQ(O7iG(=(=U1X zAav2&Gk!dAZKp3r9Ad_&(6j!zjku2fb3MF#V1_Q%<)7P#yw@Iy5l3-Tdo}-^vVP%N z*^ay-b3t81*K7T(nem>PxU#LdLDw^Wv&qx&F>d^jexQqaf5fLwi(JVzT#!RMV`gbMc1qOU-5Sz`krl@iNsM{=z7-AzTv*Tv{{n8 z=;FxzdnkXg#=U&_IV%+how%tzo1b=nzO>orC5fZBsXgmw%zUV|$l1kr(Z6T?)Q9H> z{36~|w}P(M`ssUd-X;=9aiO=@`gv|-{zT#>U%`>*$D#Uj#*LrHcty@{bkX%}{>5jJ zmw6+<<`JEFNbMPa+%p>6zV~`&;&^&~5nZqP?^f4;rytL1+^cw&gXBdQUC;WtcQap_ zYsfxC7ri~}Ctr20m^_~u@S;bTtlr}nD<{jz?seqMe4 z4t>4`6P7F^^8CAa7GNB-`)@P3wnF4pS?r>MdBr2 zLD#c>_BeZx}yrb0u;X@moY3 zxqns853}ZBTwDG9#9D41#+pv;+5Yp6D1P^d;iLA%N$pkthr{Pr_{R1`Go4$(LeKci z{_A%jHCyjT|AX~@)*a^r`%lD&F1nu0&l+c(tRE2{y6Ae=|NrX8ITv+X?TL|>bw~cx zUgYoiBZ|NO^!hLI{|eKm6(4kAM5+=)I2)Z}0#7=_j@{ z(GsECj4<9a>z*64RqLJ~GqbgRXE^-xsoACbW`pN7*B*y1di(ganfy18`-j87zrimO zM{(guFa59AezRBIdwtjJ@4q9z&eH7rN+r;`f5wF*~&v zevvrnqU))DdOhBw|GW=p@0p>CZTWeRyo^^Qj^bABW&X9gelgC0Pb_)G>${V{8shl_imiw*y+ zx_)L0W_F`*w&eN6)%DOt*US8cKi2%UC$WCS<)hF=*IWJUJ?37#_C#@mt|xx8)1QTp z^^YIY4|K83&-&s$#xE`(#rhLnPxIp^FLNLgM{%q6)KC5Kkzd4*F1nuhqdpg3M*YME z3te%N5hnllz#hEzsOmscX&;DTT;}?m8F1nujXP(A;^q==3TKTUn zKkt#3v5Uk}+^W6IzkY20JoA0?BEB8s%`LB=>!Rzazvpw^_xI1N)SUjq3|;j0)c?xk z@Lim*i4R@O{lnpK!|ePEGkaFEzZJUZ?P-3-iJxz%$av7jHb3L+{2t>MCw5}|qU&jX z#)*&di}=vR+#lm)pD})Mc_nnw^)x^8hVSfQ&1Kin#Wp{4grEM3_|U~RKXt}O{Y8A} zV(yP|&ixwW7w0!Z7hO-sPab^a7w0!3zu54{aXPxzVpNsl2C zM{%L+sUOePJ7)A%Brm$?dg^E1`R3vmiGwb>-s-<}zur6SA>t@5^!C)>--^Dne&{pg zE`=_(ji37P?ZPJ#r>fhCjr+ri`s3xC6p5p_(Dk(cv~%_|e4FzhJ(ozeu0a#m4*}%THd;stfxyS##*3x0m_fYWAP+9`B2M_vpXa`2H3CIA<6? z=dXDAAat=Y{=y&U3_kXdNZmM>#D@RPy8khMy7!8!>!FK{`|k-q_qOu>dZVwn!N&cq z@K@)a`>7XkAootzve@RY?w6yv$Ilwjy;W@U|JVJKI-rYfe)@T3C)SEcKhQ0(ozO+s6My7k?sfNo^h5oE-rnkG@37WI;#Iy8T~Gadr#WY-yU4iFMb}e* ze=E*i{G6MLgRb+tasC$di+eJAm;Q^4gZs1SdYYep@*a6b`hhOG-s&eW_h*qfiVNHF zv(A`z_O8hMp^I(v&pFT7sh2pld;I)&J?Vd}Gv=E7;@QK{Mb{I5)LFl`i2Ut@`irio zerl!PJ4AfwV#EJ-^ZYV@*gvAqEz$Kdf8qCrgYeN`9?0+g=%UN1pPF+{u6os$7_Il%NoVDX$Y~m%sN&LgG&Y(Z~c8^8k zC@w6%SN(65ezS!qk^9yClD9gci$1oDzu*7+#3!|3*6x+Ox)-|W?HNCw=-cjz5r>%Z zDfFy=dOi9ve)_|!duHfjUH<9y$h+`Fj5vy$+N=5Rmh}tI@@C`}SqthSx?bylWyh@1 zH4~RN6*uU5#&0%p96siaA2JSfG4GG~)QSA!+)3!7>)HJ5AAG7ioI8pABM$lBEbC{s zWM(%WnXPn7uJu9}y}g>h;_vtW@%$^NvH!$X-&5$K>-B!mJ+c#HD0r&4iQSyv>{1## z`=2=!^zjtBSmS4(F>bu#>PGBeF+cw3hj;ct#3<~ z)<1I?{iq%N;Z(;AU98JLa~OF!Ym9?4Lmb6T?bZD21Lx<+?B?w_>*DJNUN_f8*R%fC zuGwYpKj|^VE1#L6i>_z=*Pe%OZm}djbTRMm_xtxFw;h$dd=R?mW6S1eo{XKlPGlbF zVx7OWt1*aXjD`6J3q70v+Vk+uEsEh|{`gaS#vdNeJ$=RN&q5c6&i}yrGiQ9vRlNQz zY9ZG7r~eEeWq*2i}=vRyg%kiF6J+)rlRYa`b8dmbjpE>iP)*^Qo-$nnP^-~|-AMlHKQ{4)>Uh8M<#eJJd z9L0s+UhC(*k@XXamwW|>-X90*&mGq|jroe)-{_+2+5Gb_A}{Mkeyt-q>yX+r{&;4L zZu;5lnu(3{{vx_w_1~-R|8_6l)p%C%E(ghrF1nue^Xz85wAPSwh%S12)=$3bTCsMl z1-j_%RsXxgLspjgf6FhkBrkb$;$`YF*q{iNrz|y*)GjsLv(ONBzX5qtHdyGycfK86CJkeH@pJYR2c3ASJ?rO=Kl)aGe_=0=?Z=)@?V0@4IQ-S$Kk!rgV9{Rnzc+Y)g@0s6 zG}FBmtn-)S*Y9EMo3&nyKUnW)-*HcH{zQD}qU)LQ#~x>%>>m*ydtY=t>;HfCf-UP^V+U8mzrN~=SRn108+0X2737!DCfZ6uKXRrV?9l= JCVVDi_Ah|$OXvUq diff --git a/technology/scn4m_subm/gds_lib/replica_cell_6t.gds b/technology/scn4m_subm/gds_lib/replica_cell_6t.gds index f16f7b1359aefef9b6d8246a47e897800a0a1bcd..191f12060d3946fea31423b3627a2dddaacf2cdb 100644 GIT binary patch literal 5868 zcmbuDKWvp{6vhv|?d=6hxy6EQDR4=Hlv1T=qIFSB97tRk9Eb}l5NpyHLX31|#H}NV zOE(=mc4RV)jEszq9W^mt&+ne^;d}el^J(IjG{5q^?{m)k|9z=-ZOl5hcx22TS=VOl zr1k9j>)(&sg3XR~AKrhk`R(1W?%chO{M)z=x@t#@t#F(vEcY4gsR{Ndd@Q-I^XK$MgUesKD61wQ+<1=RRUpeR>4*z<9 zUnGv=!jWG3->&^;Z@Tx=W3zL+HLrS`&_yp#{KMg&ugs3^n@xEParRc|qU(v@2jqs? zk?rt{#6cHbPyI7%QIGahAI{z~Ll@ifQ;)p#S0s+&R^?^>)q4D*p97y*@`{%phc3F_ z>c8N9?F`JsK~Hgmt|xx8$rs@xKYq0Xo%U4ai9g~qPUIICwnGbUGAGLdVXxfd@!RotNKiQnw# zm*HdmMYe*ENR4n*Q8ZdIQ88Gn4_7xANut|$H&pVO~m z{KR<+U35M1M;?6S7s*}z1XG+=)X9z75x`o zPxI4HeDq($hc4#+=qLM({)t+5!e&&AC zV~E62TK(&&_&l<{bz62dxt$l9L0rRp8ES6(N@+E zZHBz1(8ad?Gd|p1_(bAV<2GXB{cvdf@p4Xz#8F)6dfI-2tYjc#B`6IvP5uJIc$`gOwf3$sZ5Pg8X>ir^mdFj7au7BEyXS!dL zyy&8rr+(fS%opP?(q?qAG5-hhlb5sV#YX=Nf1ES;*h3=Y#KfRx6H@ev7r=91wVy%m`L;b4Clm5r}vi2E&@%&ckqU(u2 z^00RGc7n7+?Sfw3>Syn>S4HAgz7btd{j68+3C3Tf|LCIYsh@Su+QBdC-Vt3-{k-!z zduYE%KhQL)Mne~~zf3)}Lu&X{-39+CM&7u)8ady2j@jv{-h zyuVye+8^tTxhB7Od@pp-^~7&BzU$|fd%62W{`P||x}N$OGyT6w#D^|6{O>i-Kl6|M zBkJ4}T`%(&{%9vY){DsBEoi^!dg^D)IVae6B0hA{_0-Q=p`WZD5g)qfdg}jw;}?0% zKl1bG|FPs}KA?YTe%2`;>xU20ZgkOqE&U(Y^XDbi$KRUx;PTGs*Vpuajr>zSME>_z zpT9F>u1)njQP1b9H{bo{yL&D5i2Gmav2Q%T$NS-4TRi6Kt((@J?|!|Rw~iB}s`ckU*s86ZfB(qFZFac%_~G`}kN3a3cmLtm*1eB^Hk)mXe)h$$pM3qt?`NNWd2oC0 zw{O3(<&r`zt{Wo z&}{y>S?9Rq%@?7IK3?^|)$fmEJI5k%6c-lXtNwROzuC3z$o=Ym$(!xaMXxR6@AdvV z@usYsO?69N-V0sy@r)l&96Qw&BMvd+Q|MX$%vu~r{TvT3@0p>Cb@^x3BJZ_rG2$q0 z8n5QRRrW7DOB<0_W?L-X)PZc+@lk=O6r`lQn%%PyyQ|MxipLIsvc*T|VSifSv{x}Zr?A?e_ z(Bmm?!J7Q^zsOB~ecWH@V%8u1AqRaEXYYnCx}NEO)namc2simAav1d%jRdE)XrWfG7ogI&fnTq4Wb#fF#lkoXY*fu7QVR!F?`G)e;UvD z!^3sYvEucop^F38f8Y6M&iI(Cc>QVgLag)8ybK@p;)nRq#X3KI#z+4}eCT4{AM+#^ z^B2`q(e+IKA`d?Di_C%i;(-6X>h&|~wc_P`i#&^=i>_DmU+}jd`8C@z6N#g^(DkgJ z>xTRG!kv=jMHdI|-+lRuHSX=h&t9oG=)_Iq+5C+A^QBF{C`lZ}P2*WVbLK;@MfNVf zi~c?9r$0PD;1}_xz7=%6)=%xlew#=f#f3gz>*u+V^CuE7`3ep^Klb&XJ+5&Y^A*{@ z(M8v@`RAWUUd|i&bso_<4{1E(k9)@OhF^OfGqI7LUqsid{@c~{Kh=$AHSSeB%R%y@ zi>_z=+`BnnI@gfv5MA`~tekYju*M_QNK8F|Eu_8|6$(j zKjNZ=E)LAU;`bgU-;$pL{E)t(i*^3dwAYWdA}4dE7J3pa^z8iGkHRRI>-^NoS}FG1L}F=PX*`oZ`aACV=)bsl6uRho z#vgguWBT@guS0b~AFuUu?NPr-yyPqBde+Y#!Ja|?Mdpt#x}Np3&e=2Yi^M?}UC;X2 zqxsE1{UY-~7hTW#sgvW#FH#4(=z6W6ygc`d#8F&Wm!EYuz8Sp|t9wrx&*m@gQ?2M1 zdk=lnee0a9T>Y`mxbJbUMD{X%%ZLN_zsmk&HnJbbR)2r7mPhtuO{ei}{k&s}-%Vop z=sj`Lc-8-5|Na-gp&ijo`(CinGybxE{f?w(tKFzSSnp@uu}^UQiTKb(*R%Oq*ovOS)Z7nu``00VSjrXMg zb{x;L{`a59v7Y_Cs~`8|L0vqawO-q`=3?{vt$bGAK%}D{_Z{VHxSRv;&isDuv3^Oh J#(Wkd_74c8Zi@f_ diff --git a/technology/scn4m_subm/mag_lib/cell_6t.mag b/technology/scn4m_subm/mag_lib/cell_6t.mag index f2e9906a..bb9d943d 100644 --- a/technology/scn4m_subm/mag_lib/cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/cell_6t.mag @@ -1,117 +1,118 @@ magic tech scmos -timestamp 1536091415 +timestamp 1560809302 << nwell >> -rect -8 29 42 51 +rect -8 35 42 57 << pwell >> -rect -8 -8 42 29 +rect -8 -2 42 35 << ntransistor >> -rect 7 10 9 18 -rect 29 10 31 18 -rect 10 3 14 5 -rect 24 3 28 5 +rect 7 16 9 24 +rect 29 16 31 24 +rect 10 9 14 11 +rect 24 9 28 11 << ptransistor >> -rect 7 37 11 40 -rect 27 37 31 40 +rect 7 43 11 46 +rect 27 43 31 46 << ndiffusion >> +rect -2 22 7 24 +rect 2 18 7 22 rect -2 16 7 18 -rect 2 12 7 16 -rect -2 10 7 12 -rect 9 14 10 18 -rect 9 10 14 14 -rect 28 14 29 18 -rect 24 10 29 14 +rect 9 20 10 24 +rect 9 16 14 20 +rect 28 20 29 24 +rect 24 16 29 20 +rect 31 22 36 24 +rect 31 18 32 22 rect 31 16 36 18 -rect 31 12 32 16 -rect 31 10 36 12 -rect 10 5 14 10 -rect 24 5 28 10 -rect 10 2 14 3 -rect 24 2 28 3 +rect 10 11 14 16 +rect 24 11 28 16 +rect 10 8 14 9 +rect 24 8 28 9 << pdiffusion >> -rect 2 37 7 40 -rect 11 37 12 40 -rect 26 37 27 40 -rect 31 37 32 40 +rect 2 43 7 46 +rect 11 43 12 46 +rect 26 43 27 46 +rect 31 43 32 46 << ndcontact >> -rect -2 12 2 16 -rect 10 14 14 18 -rect 24 14 28 18 -rect 32 12 36 16 -rect 10 -2 14 2 -rect 24 -2 28 2 +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 36 2 40 -rect 12 36 16 40 -rect 22 36 26 40 -rect 32 36 36 40 +rect -2 42 2 46 +rect 12 42 16 46 +rect 22 42 26 46 +rect 32 42 36 46 << psubstratepcontact >> -rect -2 22 2 26 -rect 32 22 36 26 +rect -2 28 2 32 +rect 32 28 36 32 << nsubstratencontact >> -rect 32 44 36 48 +rect 32 50 36 54 << polysilicon >> -rect 7 40 11 42 -rect 27 40 31 42 -rect 7 35 11 37 -rect 7 21 9 35 -rect 27 34 31 37 -rect 15 33 31 34 -rect 19 32 31 33 -rect 7 20 21 21 -rect 7 19 24 20 -rect 7 18 9 19 -rect 29 18 31 32 -rect 7 8 9 10 -rect 17 5 21 6 -rect 29 8 31 10 -rect -2 3 10 5 -rect 14 3 24 5 -rect 28 3 36 5 +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 29 19 33 -rect 21 20 25 24 -rect 17 6 21 10 +rect 15 35 19 39 +rect 21 26 25 30 +rect 17 12 21 16 << metal1 >> -rect -2 44 15 48 -rect 19 44 32 48 -rect -2 40 2 44 -rect 32 40 36 44 -rect 11 36 12 40 -rect 26 36 27 40 -rect -2 26 2 29 -rect -2 16 2 22 -rect 11 18 15 36 -rect 23 24 27 36 -rect 25 20 27 24 -rect 14 14 15 18 -rect 23 18 27 20 -rect 32 26 36 29 -rect 23 14 24 18 -rect 32 16 36 22 -rect -2 6 17 9 -rect 21 6 36 9 -rect -2 5 36 6 +rect -2 50 15 54 +rect 19 50 32 54 +rect -2 46 2 50 +rect 32 46 36 50 +rect 11 42 12 46 +rect 26 42 27 46 +rect -2 32 2 35 +rect -2 22 2 28 +rect 11 24 15 42 +rect 23 30 27 42 +rect 25 26 27 30 +rect 14 20 15 24 +rect 23 24 27 26 +rect 32 32 36 35 +rect 23 20 24 24 +rect 32 22 36 28 +rect -2 12 17 15 +rect 21 12 36 15 +rect -2 11 36 12 << m2contact >> -rect 15 44 19 48 -rect -2 29 2 33 -rect 32 29 36 33 -rect 6 -2 10 2 -rect 20 -2 24 2 +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 33 2 48 -rect -2 -2 2 29 -rect 6 2 10 48 -rect 24 -2 28 48 -rect 32 33 36 48 -rect 32 -2 36 29 +rect -2 39 2 54 +rect -2 0 2 35 +rect 6 8 10 54 +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 46 +rect 0 0 34 52 << labels >> -rlabel metal2 0 0 0 0 1 gnd -rlabel metal2 34 0 34 0 1 gnd -rlabel m2contact 17 46 17 46 5 vdd -rlabel metal2 8 43 8 43 1 bl -rlabel metal2 26 43 26 43 1 br -rlabel metal1 4 7 4 7 1 wl +rlabel metal2 0 6 0 6 1 gnd +rlabel metal2 34 6 34 6 1 gnd +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 << end >> diff --git a/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag b/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag index c1b14848..74562f15 100644 --- a/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/dummy_cell_6t.mag @@ -1,118 +1,115 @@ magic tech scmos -timestamp 1560540221 +timestamp 1560809362 << nwell >> -rect -8 29 42 51 +rect -8 35 42 57 << pwell >> -rect -8 -8 42 29 +rect -8 -2 42 35 << ntransistor >> -rect 7 10 9 18 -rect 29 10 31 18 -rect 10 3 14 5 -rect 24 3 28 5 +rect 7 16 9 24 +rect 29 16 31 24 +rect 10 9 14 11 +rect 24 9 28 11 << ptransistor >> -rect 7 37 11 40 -rect 27 37 31 40 +rect 7 43 11 46 +rect 27 43 31 46 << ndiffusion >> +rect -2 22 7 24 +rect 2 18 7 22 rect -2 16 7 18 -rect 2 12 7 16 -rect -2 10 7 12 -rect 9 14 10 18 -rect 9 10 14 14 -rect 28 14 29 18 -rect 24 10 29 14 +rect 9 20 10 24 +rect 9 16 14 20 +rect 28 20 29 24 +rect 24 16 29 20 +rect 31 22 36 24 +rect 31 18 32 22 rect 31 16 36 18 -rect 31 12 32 16 -rect 31 10 36 12 -rect 10 5 14 10 -rect 24 5 28 10 -rect 10 2 14 3 -rect 24 2 28 3 +rect 10 11 14 16 +rect 24 11 28 16 +rect 10 8 14 9 +rect 24 8 28 9 << pdiffusion >> -rect 2 37 7 40 -rect 11 37 12 40 -rect 26 37 27 40 -rect 31 37 32 40 +rect 2 43 7 46 +rect 11 43 12 46 +rect 26 43 27 46 +rect 31 43 32 46 << ndcontact >> -rect -2 12 2 16 -rect 10 14 14 18 -rect 24 14 28 18 -rect 32 12 36 16 -rect 10 -2 14 2 -rect 24 -2 28 2 +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 36 2 40 -rect 12 36 16 40 -rect 22 36 26 40 -rect 32 36 36 40 +rect -2 42 2 46 +rect 12 42 16 46 +rect 22 42 26 46 +rect 32 42 36 46 << psubstratepcontact >> -rect -2 22 2 26 -rect 32 22 36 26 +rect -2 28 2 32 +rect 32 28 36 32 << nsubstratencontact >> -rect 32 44 36 48 +rect 32 50 36 54 << polysilicon >> -rect 7 40 11 42 -rect 27 40 31 42 -rect 7 35 11 37 -rect 7 21 9 35 -rect 27 34 31 37 -rect 15 33 31 34 -rect 19 32 31 33 -rect 7 20 21 21 -rect 7 19 24 20 -rect 7 18 9 19 -rect 29 18 31 32 -rect 7 8 9 10 -rect 17 5 21 6 -rect 29 8 31 10 -rect -2 3 10 5 -rect 14 3 24 5 -rect 28 3 36 5 +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 29 19 33 -rect 21 20 25 24 -rect 17 6 21 10 +rect 15 35 19 39 +rect 21 26 25 30 +rect 17 12 21 16 << metal1 >> -rect -2 44 15 48 -rect 19 44 32 48 -rect -2 40 2 44 -rect 32 40 36 44 -rect 11 36 12 40 -rect 26 36 27 40 -rect -2 26 2 29 -rect -2 16 2 22 -rect 11 18 15 36 -rect 23 24 27 36 -rect 25 20 27 24 -rect 14 14 15 18 -rect 23 18 27 20 -rect 32 26 36 29 -rect 23 14 24 18 -rect 32 16 36 22 -rect -2 6 17 9 -rect 21 6 36 9 -rect -2 5 36 6 -rect 6 -2 10 2 -rect 20 -2 24 2 +rect -2 50 15 54 +rect 19 50 32 54 +rect -2 46 2 50 +rect 32 46 36 50 +rect 11 42 12 46 +rect 26 42 27 46 +rect -2 32 2 35 +rect -2 22 2 28 +rect 11 24 15 42 +rect 23 30 27 42 +rect 25 26 27 30 +rect 14 20 15 24 +rect 23 24 27 26 +rect 32 32 36 35 +rect 23 20 24 24 +rect 32 22 36 28 +rect -2 12 17 15 +rect 21 12 36 15 +rect -2 11 36 12 << m2contact >> -rect 15 44 19 48 -rect -2 29 2 33 -rect 32 29 36 33 +rect 15 50 19 54 +rect -2 35 2 39 +rect 32 35 36 39 << metal2 >> -rect -2 33 2 48 -rect -2 -2 2 29 -rect 6 -2 10 48 -rect 24 2 28 48 -rect 20 -2 28 2 -rect 32 33 36 48 -rect 32 -2 36 29 +rect -2 39 2 54 +rect -2 0 2 35 +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 46 +rect 0 0 34 52 << labels >> -rlabel metal2 0 0 0 0 1 gnd -rlabel metal2 34 0 34 0 1 gnd -rlabel m2contact 17 46 17 46 5 vdd -rlabel metal2 8 43 8 43 1 bl -rlabel metal2 26 43 26 43 1 br -rlabel metal1 4 7 4 7 1 wl +rlabel metal2 0 6 0 6 1 gnd +rlabel metal2 34 6 34 6 1 gnd +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 << end >> diff --git a/technology/scn4m_subm/mag_lib/replica_cell_6t.mag b/technology/scn4m_subm/mag_lib/replica_cell_6t.mag index c28cb2c6..b5a5f7b8 100644 --- a/technology/scn4m_subm/mag_lib/replica_cell_6t.mag +++ b/technology/scn4m_subm/mag_lib/replica_cell_6t.mag @@ -1,118 +1,119 @@ magic tech scmos -timestamp 1541443051 +timestamp 1560809329 << nwell >> -rect -8 29 42 51 +rect -8 35 42 57 << pwell >> -rect -8 -8 42 29 +rect -8 -2 42 35 << ntransistor >> -rect 7 10 9 18 -rect 29 10 31 18 -rect 10 3 14 5 -rect 24 3 28 5 +rect 7 16 9 24 +rect 29 16 31 24 +rect 10 9 14 11 +rect 24 9 28 11 << ptransistor >> -rect 7 37 11 40 -rect 27 37 31 40 +rect 7 43 11 46 +rect 27 43 31 46 << ndiffusion >> +rect -2 22 7 24 +rect 2 18 7 22 rect -2 16 7 18 -rect 2 12 7 16 -rect -2 10 7 12 -rect 9 14 10 18 -rect 9 10 14 14 -rect 28 14 29 18 -rect 24 10 29 14 +rect 9 20 10 24 +rect 9 16 14 20 +rect 28 20 29 24 +rect 24 16 29 20 +rect 31 22 36 24 +rect 31 18 32 22 rect 31 16 36 18 -rect 31 12 32 16 -rect 31 10 36 12 -rect 10 5 14 10 -rect 24 5 28 10 -rect 10 2 14 3 -rect 24 2 28 3 +rect 10 11 14 16 +rect 24 11 28 16 +rect 10 8 14 9 +rect 24 8 28 9 << pdiffusion >> -rect 2 37 7 40 -rect 11 37 12 40 -rect 26 37 27 40 -rect 31 37 32 40 +rect 2 43 7 46 +rect 11 43 12 46 +rect 26 43 27 46 +rect 31 43 32 46 << ndcontact >> -rect -2 12 2 16 -rect 10 14 14 18 -rect 24 14 28 18 -rect 32 12 36 16 -rect 10 -2 14 2 -rect 24 -2 28 2 +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 36 2 40 -rect 12 36 16 40 -rect 22 36 26 40 -rect 32 36 36 40 +rect -2 42 2 46 +rect 12 42 16 46 +rect 22 42 26 46 +rect 32 42 36 46 << psubstratepcontact >> -rect -2 22 2 26 -rect 32 22 36 26 +rect -2 28 2 32 +rect 32 28 36 32 << nsubstratencontact >> -rect 32 44 36 48 +rect 32 50 36 54 << polysilicon >> -rect 7 40 11 42 -rect 27 40 31 42 -rect 7 35 11 37 -rect 7 21 9 35 -rect 27 34 31 37 -rect 15 33 31 34 -rect 19 32 31 33 -rect 7 20 21 21 -rect 7 19 24 20 -rect 7 18 9 19 -rect 29 18 31 32 -rect 7 8 9 10 -rect 17 5 21 6 -rect 29 8 31 10 -rect -2 3 10 5 -rect 14 3 24 5 -rect 28 3 36 5 +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 29 19 33 -rect 21 20 25 24 -rect 17 6 21 10 +rect 15 35 19 39 +rect 21 26 25 30 +rect 17 12 21 16 << metal1 >> -rect -2 44 15 48 -rect 19 44 32 48 -rect -2 40 2 44 -rect 22 40 26 44 -rect 32 40 36 44 -rect 11 36 12 40 -rect 26 36 27 40 -rect -2 26 2 29 -rect -2 16 2 22 -rect 11 18 15 36 -rect 23 24 27 36 -rect 25 20 27 24 -rect 14 14 15 18 -rect 23 18 27 20 -rect 32 26 36 29 -rect 23 14 24 18 -rect 32 16 36 22 -rect -2 6 17 9 -rect 21 6 36 9 -rect -2 5 36 6 +rect -2 50 15 54 +rect 19 50 32 54 +rect -2 46 2 50 +rect 22 46 26 50 +rect 32 46 36 50 +rect 11 42 12 46 +rect 26 42 27 46 +rect -2 32 2 35 +rect -2 22 2 28 +rect 11 24 15 42 +rect 23 30 27 42 +rect 25 26 27 30 +rect 14 20 15 24 +rect 23 24 27 26 +rect 32 32 36 35 +rect 23 20 24 24 +rect 32 22 36 28 +rect -2 12 17 15 +rect 21 12 36 15 +rect -2 11 36 12 << m2contact >> -rect 15 44 19 48 -rect -2 29 2 33 -rect 32 29 36 33 -rect 6 -2 10 2 -rect 20 -2 24 2 +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 33 2 48 -rect -2 -2 2 29 -rect 6 2 10 48 -rect 24 -2 28 48 -rect 32 33 36 48 -rect 32 -2 36 29 +rect -2 39 2 54 +rect -2 0 2 35 +rect 6 8 10 54 +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 46 +rect 0 0 34 52 << labels >> -rlabel metal2 0 0 0 0 1 gnd -rlabel metal2 34 0 34 0 1 gnd -rlabel m2contact 17 46 17 46 5 vdd -rlabel metal2 8 43 8 43 1 bl -rlabel metal2 26 43 26 43 1 br -rlabel metal1 4 7 4 7 1 wl +rlabel metal2 0 6 0 6 1 gnd +rlabel metal2 34 6 34 6 1 gnd +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 << end >> From d22d7de1950eb93ccac1c701559ff63076a6a3a3 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 24 Jun 2019 08:59:58 -0700 Subject: [PATCH 048/234] Reapply jsowash update without spice model file --- compiler/base/geometry.py | 23 ++++--- compiler/base/lef.py | 21 ++---- compiler/characterizer/lib.py | 66 ++++++++++--------- compiler/gdsMill/gdsMill/vlsiLayout.py | 17 ++++- ..._16_1_freepdk45_FF_1p0V_25C_analytical.lib | 16 ++--- ..._16_1_freepdk45_SS_1p0V_25C_analytical.lib | 16 ++--- .../sram_2_16_1_freepdk45_TT_1p0V_25C.lib | 16 ++--- ..._16_1_freepdk45_TT_1p0V_25C_analytical.lib | 16 ++--- ...am_2_16_1_freepdk45_TT_1p0V_25C_pruned.lib | 16 ++--- ...16_1_scn4m_subm_FF_5p0V_25C_analytical.lib | 16 ++--- ...16_1_scn4m_subm_SS_5p0V_25C_analytical.lib | 16 ++--- .../sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib | 16 ++--- ...16_1_scn4m_subm_TT_5p0V_25C_analytical.lib | 16 ++--- ...m_2_16_1_scn4m_subm_TT_5p0V_25C_pruned.lib | 16 ++--- 14 files changed, 149 insertions(+), 138 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index ddff6049..56bae83d 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -183,21 +183,20 @@ class instance(geometry): elif self.mirror=="XY": mirr = 1 angle += math.radians(180.0) - - if self.mod.is_library_cell: - # For lib cells, block the whole thing except on metal3 - # since they shouldn't use metal3 - if layer==tech.layer["metal1"] or layer==tech.layer["metal2"]: - return [self.transform_coords(self.mod.get_boundary(), self.offset, mirr, angle)] - else: - return [] - else: - blockages = self.mod.get_blockages(layer) - new_blockages = [] + new_blockages = [] + if self.mod.is_library_cell: + blockages = [] + blockages = self.mod.gds.getBlockages(layer) for b in blockages: new_blockages.append(self.transform_coords(b,self.offset, mirr, angle)) - return new_blockages + print(new_blockages) + else: + blockages = self.mod.get_blockages(layer) + for b in blockages: + new_blockages.append(self.transform_coords(b,self.offset, mirr, angle)) + return new_blockages + def gds_write_file(self, new_layout): """Recursively writes all the sub-modules in this instance""" diff --git a/compiler/base/lef.py b/compiler/base/lef.py index 5bc76bb0..ea2ff5ad 100644 --- a/compiler/base/lef.py +++ b/compiler/base/lef.py @@ -21,9 +21,11 @@ class lef: """ def __init__(self,layers): # LEF db units per micron - self.lef_units = 1000 + self.lef_units = 2000 # These are the layers of the obstructions self.lef_layers = layers + # Round to ensure float values are divisible by 0.0025 (the manufacturing grid) + self.round_grid = 4; def lef_write(self, lef_name): """Write the entire lef of the object to the file.""" @@ -48,25 +50,14 @@ class lef: self.lef.write("UNITS\n") self.lef.write(" DATABASE MICRONS {0} ;\n".format(self.lef_units)) self.lef.write("END UNITS\n") - - self.lef.write("SITE MacroSite\n") - self.indent += " " - self.lef.write("{0}CLASS Core ;\n".format(self.indent)) - self.lef.write("{0}SIZE {1} by {2} ;\n".format(self.indent, - self.lef_units*self.width, - self.lef_units*self.height)) - self.indent = self.indent[:-3] - self.lef.write("END MacroSite\n") self.lef.write("{0}MACRO {1}\n".format(self.indent,self.name)) self.indent += " " self.lef.write("{0}CLASS BLOCK ;\n".format(self.indent)) self.lef.write("{0}SIZE {1} BY {2} ;\n" .format(self.indent, - self.lef_units*self.width, - self.lef_units*self.height)) + round(self.width,self.round_grid), + round(self.height,self.round_grid))) self.lef.write("{0}SYMMETRY X Y R90 ;\n".format(self.indent)) - self.lef.write("{0}SITE MacroSite ;\n".format(self.indent)) - def lef_write_footer(self): self.lef.write("{0}END {1}\n".format(self.indent,self.name)) @@ -119,5 +110,5 @@ class lef: """ Write a LEF rectangle """ self.lef.write("{0}RECT ".format(self.indent)) for item in rect: - self.lef.write(" {0} {1}".format(self.lef_units*item[0], self.lef_units*item[1])) + self.lef.write(" {0} {1}".format(round(item[0],self.round_grid), round(item[1],self.round_grid))) self.lef.write(" ;\n") diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 6e47e5cc..747e9869 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -148,9 +148,9 @@ class lib: self.lib.write(" area : {};\n\n".format(self.sram.width * self.sram.height)) #Build string of all control signals. - control_str = 'CSb0' #assume at least 1 port + control_str = 'csb0' #assume at least 1 port for i in range(1, self.total_port_num): - control_str += ' & CSb{0}'.format(i) + control_str += ' & csb{0}'.format(i) # Leakage is included in dynamic when macro is enabled self.lib.write(" leakage_power () {\n") @@ -161,13 +161,17 @@ class lib: def write_units(self): - """ Adds default units for time, voltage, current,...""" - + """ Adds default units for time, voltage, current,... + Valid values are 1mV, 10mV, 100mV, and 1V. + For time: Valid values are 1ps, 10ps, 100ps, and 1ns. + For power: Valid values are 1mW, 100uW (for 100mW), 10uW (for 10mW), + 1uW (for 1mW), 100nW, 10nW, 1nW, 100pW, 10pW, and 1pW. + """ self.lib.write(" time_unit : \"1ns\" ;\n") - self.lib.write(" voltage_unit : \"1v\" ;\n") + self.lib.write(" voltage_unit : \"1V\" ;\n") self.lib.write(" current_unit : \"1mA\" ;\n") self.lib.write(" resistance_unit : \"1kohm\" ;\n") - self.lib.write(" capacitive_load_unit(1 ,fF) ;\n") + self.lib.write(" capacitive_load_unit(1, pF) ;\n") self.lib.write(" leakage_power_unit : \"1mW\" ;\n") self.lib.write(" pulling_resistance_unit :\"1kohm\" ;\n") self.lib.write(" operating_conditions(OC){\n") @@ -239,7 +243,9 @@ class lib: self.lib.write(" variable_1 : input_net_transition;\n") self.lib.write(" variable_2 : total_output_net_capacitance;\n") self.write_index(1,self.slews) - self.write_index(2,self.loads) + # Dividing by 1000 to all cap values since output of .sp is in fF, + # and it needs to be in pF for Innovus. + self.write_index(2,self.loads/1000) self.lib.write(" }\n\n") CONS = ["CONSTRAINT_TABLE"] @@ -327,8 +333,8 @@ class lib: self.lib.write(" bus_type : DATA; \n") self.lib.write(" direction : output; \n") # This is conservative, but limit to range that we characterized. - self.lib.write(" max_capacitance : {0}; \n".format(max(self.loads))) - self.lib.write(" min_capacitance : {0}; \n".format(min(self.loads))) + self.lib.write(" max_capacitance : {0}; \n".format(max(self.loads)/1000)) + self.lib.write(" min_capacitance : {0}; \n".format(min(self.loads)/1000)) self.lib.write(" memory_read(){ \n") self.lib.write(" address : ADDR{0}; \n".format(read_port)) self.lib.write(" }\n") @@ -362,7 +368,7 @@ class lib: self.lib.write(" bus_type : DATA; \n") self.lib.write(" direction : input; \n") # This is conservative, but limit to range that we characterized. - self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"])) + self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]/1000)) self.lib.write(" memory_write(){ \n") self.lib.write(" address : ADDR{0}; \n".format(write_port)) self.lib.write(" clocked_on : clk{0}; \n".format(write_port)) @@ -385,7 +391,7 @@ class lib: self.lib.write(" bus(ADDR{0}){{\n".format(port)) self.lib.write(" bus_type : ADDR; \n") self.lib.write(" direction : input; \n") - self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"])) + self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]/1000)) self.lib.write(" max_transition : {0};\n".format(self.slews[-1])) self.lib.write(" pin(ADDR{0}[{1}:0])".format(port,self.sram.addr_size-1)) self.lib.write("{\n") @@ -398,15 +404,15 @@ class lib: def write_control_pins(self, port): """ Adds control pins timing results.""" #The control pins are still to be determined. This is a placeholder for what could be. - ctrl_pin_names = ["CSb{0}".format(port)] + ctrl_pin_names = ["csb{0}".format(port)] if port in self.readwrite_ports: - ctrl_pin_names.append("WEb{0}".format(port)) + ctrl_pin_names.append("web{0}".format(port)) for i in ctrl_pin_names: self.lib.write(" pin({0})".format(i)) self.lib.write("{\n") self.lib.write(" direction : input; \n") - self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"])) + self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]/1000)) self.write_FF_setuphold(port) self.lib.write(" }\n\n") @@ -417,7 +423,7 @@ class lib: self.lib.write(" clock : true;\n") self.lib.write(" direction : input; \n") # FIXME: This depends on the clock buffer size in the control logic - self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"])) + self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]/1000)) self.add_clk_control_power(port) @@ -452,10 +458,10 @@ class lib: if port in self.write_ports: if port in self.read_ports: - web_name = " & !WEb{0}".format(port) + web_name = " & !web{0}".format(port) avg_write_power = np.mean(self.char_port_results[port]["write1_power"] + self.char_port_results[port]["write0_power"]) self.lib.write(" internal_power(){\n") - self.lib.write(" when : \"!CSb{0} & clk{0}{1}\"; \n".format(port, web_name)) + self.lib.write(" when : \"!csb{0} & clk{0}{1}\"; \n".format(port, web_name)) self.lib.write(" rise_power(scalar){\n") self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0)) self.lib.write(" }\n") @@ -466,10 +472,10 @@ class lib: if port in self.read_ports: if port in self.write_ports: - web_name = " & WEb{0}".format(port) + web_name = " & web{0}".format(port) avg_read_power = np.mean(self.char_port_results[port]["read1_power"] + self.char_port_results[port]["read0_power"]) self.lib.write(" internal_power(){\n") - self.lib.write(" when : \"!CSb{0} & !clk{0}{1}\"; \n".format(port, web_name)) + self.lib.write(" when : \"!csb{0} & !clk{0}{1}\"; \n".format(port, web_name)) self.lib.write(" rise_power(scalar){\n") self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0)) self.lib.write(" }\n") @@ -480,7 +486,7 @@ class lib: # Have 0 internal power when disabled, this will be represented as leakage power. self.lib.write(" internal_power(){\n") - self.lib.write(" when : \"CSb{0}\"; \n".format(port)) + self.lib.write(" when : \"csb{0}\"; \n".format(port)) self.lib.write(" rise_power(scalar){\n") self.lib.write(" values(\"0\");\n") self.lib.write(" }\n") @@ -610,9 +616,9 @@ class lib: )) for port in self.all_ports: - #CSb timings + #csb timings datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format( - "CSb{0}".format(port), + "csb{0}".format(port), min(list(map(round_time,self.times["setup_times_LH"]))), max(list(map(round_time,self.times["setup_times_LH"]))), @@ -649,9 +655,9 @@ class lib: for port in self.all_ports: if port in self.readwrite_ports: - #WEb timings + #web timings datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format( - "WEb{0}".format(port), + "web{0}".format(port), min(list(map(round_time,self.times["setup_times_LH"]))), max(list(map(round_time,self.times["setup_times_LH"]))), @@ -673,8 +679,8 @@ class lib: # write dynamic power usage if port in self.read_ports: - web_name = " & !WEb{0}".format(port) - name = "!CSb{0} & clk{0}{1}".format(port, web_name) + web_name = " & !web{0}".format(port) + name = "!csb{0} & clk{0}{1}".format(port, web_name) read_write = 'Read' datasheet.write("{0},{1},{2},{3},".format( @@ -686,8 +692,8 @@ class lib: )) if port in self.write_ports: - web_name = " & WEb{0}".format(port) - name = "!CSb{0} & !clk{0}{1}".format(port, web_name) + web_name = " & web{0}".format(port) + name = "!csb{0} & !clk{0}{1}".format(port, web_name) read_write = 'Write' datasheet.write("{0},{1},{2},{3},".format( @@ -699,9 +705,9 @@ class lib: )) # write leakage power - control_str = 'CSb0' + control_str = 'csb0' for i in range(1, self.total_port_num): - control_str += ' & CSb{0}'.format(i) + control_str += ' & csb{0}'.format(i) datasheet.write("{0},{1},{2},".format('leak', control_str, self.char_sram_results["leakage_power"])) diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index 03873ed4..992e3d26 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -2,6 +2,8 @@ from .gdsPrimitives import * from datetime import * #from mpmath import matrix #from numpy import matrix +from vector import vector +from pin_layout import pin_layout import numpy as np #import gdsPrimitives import debug @@ -729,7 +731,7 @@ class VlsiLayout: def getAllShapes(self,layer): """ - Return all gshapes on a given layer in [llx, lly, urx, ury] format and + Return all shapes on a given layer in [llx, lly, urx, ury] format and user units. """ boundaries = set() @@ -746,6 +748,19 @@ class VlsiLayout: return user_boundaries + def getBlockages(self,layer): + blockages = [] + + shapes = self.getAllShapes(layer) + for boundary in shapes: + ll = vector(boundary[0],boundary[1]) + ur = vector(boundary[2],boundary[3]) + rect = [ll,ur] + new_pin = rect + blockages.append(new_pin) + return blockages + + def getShapesInStructure(self,layer,structure): """ Go through all the shapes in a structure and return the list of shapes in diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib index 88b54eca..48133f90 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib @@ -1,10 +1,10 @@ library (sram_2_16_1_freepdk45_FF_1p0V_25C_lib){ delay_model : "table_lookup"; time_unit : "1ns" ; - voltage_unit : "1v" ; + voltage_unit : "1V" ; current_unit : "1mA" ; resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; + capacitive_load_unit(1, pF) ; leakage_power_unit : "1mW" ; pulling_resistance_unit :"1kohm" ; operating_conditions(OC){ @@ -81,7 +81,7 @@ cell (sram_2_16_1_freepdk45){ area : 1124.88; leakage_power () { - when : "CSb0"; + when : "csb0"; value : 0.000167; } cell_leakage_power : 0; @@ -198,7 +198,7 @@ cell (sram_2_16_1_freepdk45){ } } - pin(CSb0){ + pin(csb0){ direction : input; capacitance : 0.2091; timing(){ @@ -231,7 +231,7 @@ cell (sram_2_16_1_freepdk45){ } } - pin(WEb0){ + pin(web0){ direction : input; capacitance : 0.2091; timing(){ @@ -269,7 +269,7 @@ cell (sram_2_16_1_freepdk45){ direction : input; capacitance : 0.2091; internal_power(){ - when : "!CSb0 & clk0 & !WEb0"; + when : "!csb0 & clk0 & !web0"; rise_power(scalar){ values("0.033101244168888884"); } @@ -278,7 +278,7 @@ cell (sram_2_16_1_freepdk45){ } } internal_power(){ - when : "!CSb0 & !clk0 & WEb0"; + when : "!csb0 & !clk0 & web0"; rise_power(scalar){ values("0.033101244168888884"); } @@ -287,7 +287,7 @@ cell (sram_2_16_1_freepdk45){ } } internal_power(){ - when : "CSb0"; + when : "csb0"; rise_power(scalar){ values("0"); } diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib index e78fe8d3..59b51dfd 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib @@ -1,10 +1,10 @@ library (sram_2_16_1_freepdk45_SS_1p0V_25C_lib){ delay_model : "table_lookup"; time_unit : "1ns" ; - voltage_unit : "1v" ; + voltage_unit : "1V" ; current_unit : "1mA" ; resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; + capacitive_load_unit(1, pF) ; leakage_power_unit : "1mW" ; pulling_resistance_unit :"1kohm" ; operating_conditions(OC){ @@ -81,7 +81,7 @@ cell (sram_2_16_1_freepdk45){ area : 1124.88; leakage_power () { - when : "CSb0"; + when : "csb0"; value : 0.000167; } cell_leakage_power : 0; @@ -198,7 +198,7 @@ cell (sram_2_16_1_freepdk45){ } } - pin(CSb0){ + pin(csb0){ direction : input; capacitance : 0.2091; timing(){ @@ -231,7 +231,7 @@ cell (sram_2_16_1_freepdk45){ } } - pin(WEb0){ + pin(web0){ direction : input; capacitance : 0.2091; timing(){ @@ -269,7 +269,7 @@ cell (sram_2_16_1_freepdk45){ direction : input; capacitance : 0.2091; internal_power(){ - when : "!CSb0 & clk0 & !WEb0"; + when : "!csb0 & clk0 & !web0"; rise_power(scalar){ values("0.033101244168888884"); } @@ -278,7 +278,7 @@ cell (sram_2_16_1_freepdk45){ } } internal_power(){ - when : "!CSb0 & !clk0 & WEb0"; + when : "!csb0 & !clk0 & web0"; rise_power(scalar){ values("0.033101244168888884"); } @@ -287,7 +287,7 @@ cell (sram_2_16_1_freepdk45){ } } internal_power(){ - when : "CSb0"; + when : "csb0"; rise_power(scalar){ values("0"); } diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib index 0939b4bb..6b2723a0 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib @@ -1,10 +1,10 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ delay_model : "table_lookup"; time_unit : "1ns" ; - voltage_unit : "1v" ; + voltage_unit : "1V" ; current_unit : "1mA" ; resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; + capacitive_load_unit(1, pF) ; leakage_power_unit : "1mW" ; pulling_resistance_unit :"1kohm" ; operating_conditions(OC){ @@ -81,7 +81,7 @@ cell (sram_2_16_1_freepdk45){ area : 977.4951374999999; leakage_power () { - when : "CSb0"; + when : "csb0"; value : 0.0011164579999999999; } cell_leakage_power : 0; @@ -198,7 +198,7 @@ cell (sram_2_16_1_freepdk45){ } } - pin(CSb0){ + pin(csb0){ direction : input; capacitance : 0.2091; timing(){ @@ -231,7 +231,7 @@ cell (sram_2_16_1_freepdk45){ } } - pin(WEb0){ + pin(web0){ direction : input; capacitance : 0.2091; timing(){ @@ -269,7 +269,7 @@ cell (sram_2_16_1_freepdk45){ direction : input; capacitance : 0.2091; internal_power(){ - when : "!CSb0 & clk0 & !WEb0"; + when : "!csb0 & clk0 & !web0"; rise_power(scalar){ values("0.03599689694444445"); } @@ -278,7 +278,7 @@ cell (sram_2_16_1_freepdk45){ } } internal_power(){ - when : "!CSb0 & !clk0 & WEb0"; + when : "!csb0 & !clk0 & web0"; rise_power(scalar){ values("0.029906643888888886"); } @@ -287,7 +287,7 @@ cell (sram_2_16_1_freepdk45){ } } internal_power(){ - when : "CSb0"; + when : "csb0"; rise_power(scalar){ values("0"); } diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib index a06ff5b5..4708c2ef 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib @@ -1,10 +1,10 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ delay_model : "table_lookup"; time_unit : "1ns" ; - voltage_unit : "1v" ; + voltage_unit : "1V" ; current_unit : "1mA" ; resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; + capacitive_load_unit(1, pF) ; leakage_power_unit : "1mW" ; pulling_resistance_unit :"1kohm" ; operating_conditions(OC){ @@ -81,7 +81,7 @@ cell (sram_2_16_1_freepdk45){ area : 977.4951374999999; leakage_power () { - when : "CSb0"; + when : "csb0"; value : 0.000179; } cell_leakage_power : 0; @@ -198,7 +198,7 @@ cell (sram_2_16_1_freepdk45){ } } - pin(CSb0){ + pin(csb0){ direction : input; capacitance : 0.2091; timing(){ @@ -231,7 +231,7 @@ cell (sram_2_16_1_freepdk45){ } } - pin(WEb0){ + pin(web0){ direction : input; capacitance : 0.2091; timing(){ @@ -269,7 +269,7 @@ cell (sram_2_16_1_freepdk45){ direction : input; capacitance : 0.2091; internal_power(){ - when : "!CSb0 & clk0 & !WEb0"; + when : "!csb0 & clk0 & !web0"; rise_power(scalar){ values("0.0747594982142222"); } @@ -278,7 +278,7 @@ cell (sram_2_16_1_freepdk45){ } } internal_power(){ - when : "!CSb0 & !clk0 & WEb0"; + when : "!csb0 & !clk0 & web0"; rise_power(scalar){ values("0.0747594982142222"); } @@ -287,7 +287,7 @@ cell (sram_2_16_1_freepdk45){ } } internal_power(){ - when : "CSb0"; + when : "csb0"; rise_power(scalar){ values("0"); } diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_pruned.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_pruned.lib index d7d7de7e..dbd7e03b 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_pruned.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_pruned.lib @@ -1,10 +1,10 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ delay_model : "table_lookup"; time_unit : "1ns" ; - voltage_unit : "1v" ; + voltage_unit : "1V" ; current_unit : "1mA" ; resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; + capacitive_load_unit(1, pF) ; leakage_power_unit : "1mW" ; pulling_resistance_unit :"1kohm" ; operating_conditions(OC){ @@ -81,7 +81,7 @@ cell (sram_2_16_1_freepdk45){ area : 977.4951374999999; leakage_power () { - when : "CSb0"; + when : "csb0"; value : 0.0011164579999999999; } cell_leakage_power : 0; @@ -198,7 +198,7 @@ cell (sram_2_16_1_freepdk45){ } } - pin(CSb0){ + pin(csb0){ direction : input; capacitance : 0.2091; timing(){ @@ -231,7 +231,7 @@ cell (sram_2_16_1_freepdk45){ } } - pin(WEb0){ + pin(web0){ direction : input; capacitance : 0.2091; timing(){ @@ -269,7 +269,7 @@ cell (sram_2_16_1_freepdk45){ direction : input; capacitance : 0.2091; internal_power(){ - when : "!CSb0 & clk0 & !WEb0"; + when : "!csb0 & clk0 & !web0"; rise_power(scalar){ values("0.03334771594444444"); } @@ -278,7 +278,7 @@ cell (sram_2_16_1_freepdk45){ } } internal_power(){ - when : "!CSb0 & !clk0 & WEb0"; + when : "!csb0 & !clk0 & web0"; rise_power(scalar){ values("0.028457026222222223"); } @@ -287,7 +287,7 @@ cell (sram_2_16_1_freepdk45){ } } internal_power(){ - when : "CSb0"; + when : "csb0"; rise_power(scalar){ values("0"); } diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib index 5cbecd94..eef7df1b 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib @@ -1,10 +1,10 @@ library (sram_2_16_1_scn4m_subm_FF_5p0V_25C_lib){ delay_model : "table_lookup"; time_unit : "1ns" ; - voltage_unit : "1v" ; + voltage_unit : "1V" ; current_unit : "1mA" ; resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; + capacitive_load_unit(1, pF) ; leakage_power_unit : "1mW" ; pulling_resistance_unit :"1kohm" ; operating_conditions(OC){ @@ -81,7 +81,7 @@ cell (sram_2_16_1_scn4m_subm){ area : 73068.14000000001; leakage_power () { - when : "CSb0"; + when : "csb0"; value : 0.000167; } cell_leakage_power : 0; @@ -198,7 +198,7 @@ cell (sram_2_16_1_scn4m_subm){ } } - pin(CSb0){ + pin(csb0){ direction : input; capacitance : 9.8242; timing(){ @@ -231,7 +231,7 @@ cell (sram_2_16_1_scn4m_subm){ } } - pin(WEb0){ + pin(web0){ direction : input; capacitance : 9.8242; timing(){ @@ -269,7 +269,7 @@ cell (sram_2_16_1_scn4m_subm){ direction : input; capacitance : 9.8242; internal_power(){ - when : "!CSb0 & clk0 & !WEb0"; + when : "!csb0 & clk0 & !web0"; rise_power(scalar){ values("4.99880645"); } @@ -278,7 +278,7 @@ cell (sram_2_16_1_scn4m_subm){ } } internal_power(){ - when : "!CSb0 & !clk0 & WEb0"; + when : "!csb0 & !clk0 & web0"; rise_power(scalar){ values("4.99880645"); } @@ -287,7 +287,7 @@ cell (sram_2_16_1_scn4m_subm){ } } internal_power(){ - when : "CSb0"; + when : "csb0"; rise_power(scalar){ values("0"); } diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib index 3324f119..2f5c534c 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib @@ -1,10 +1,10 @@ library (sram_2_16_1_scn4m_subm_SS_5p0V_25C_lib){ delay_model : "table_lookup"; time_unit : "1ns" ; - voltage_unit : "1v" ; + voltage_unit : "1V" ; current_unit : "1mA" ; resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; + capacitive_load_unit(1, pF) ; leakage_power_unit : "1mW" ; pulling_resistance_unit :"1kohm" ; operating_conditions(OC){ @@ -81,7 +81,7 @@ cell (sram_2_16_1_scn4m_subm){ area : 73068.14000000001; leakage_power () { - when : "CSb0"; + when : "csb0"; value : 0.000167; } cell_leakage_power : 0; @@ -198,7 +198,7 @@ cell (sram_2_16_1_scn4m_subm){ } } - pin(CSb0){ + pin(csb0){ direction : input; capacitance : 9.8242; timing(){ @@ -231,7 +231,7 @@ cell (sram_2_16_1_scn4m_subm){ } } - pin(WEb0){ + pin(web0){ direction : input; capacitance : 9.8242; timing(){ @@ -269,7 +269,7 @@ cell (sram_2_16_1_scn4m_subm){ direction : input; capacitance : 9.8242; internal_power(){ - when : "!CSb0 & clk0 & !WEb0"; + when : "!csb0 & clk0 & !web0"; rise_power(scalar){ values("4.99880645"); } @@ -278,7 +278,7 @@ cell (sram_2_16_1_scn4m_subm){ } } internal_power(){ - when : "!CSb0 & !clk0 & WEb0"; + when : "!csb0 & !clk0 & web0"; rise_power(scalar){ values("4.99880645"); } @@ -287,7 +287,7 @@ cell (sram_2_16_1_scn4m_subm){ } } internal_power(){ - when : "CSb0"; + when : "csb0"; rise_power(scalar){ values("0"); } diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib index f8a337d3..943f2ecc 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib @@ -1,10 +1,10 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ delay_model : "table_lookup"; time_unit : "1ns" ; - voltage_unit : "1v" ; + voltage_unit : "1V" ; current_unit : "1mA" ; resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; + capacitive_load_unit(1, pF) ; leakage_power_unit : "1mW" ; pulling_resistance_unit :"1kohm" ; operating_conditions(OC){ @@ -81,7 +81,7 @@ cell (sram_2_16_1_scn4m_subm){ area : 60774.3; leakage_power () { - when : "CSb0"; + when : "csb0"; value : 0.0009813788999999999; } cell_leakage_power : 0; @@ -198,7 +198,7 @@ cell (sram_2_16_1_scn4m_subm){ } } - pin(CSb0){ + pin(csb0){ direction : input; capacitance : 9.8242; timing(){ @@ -231,7 +231,7 @@ cell (sram_2_16_1_scn4m_subm){ } } - pin(WEb0){ + pin(web0){ direction : input; capacitance : 9.8242; timing(){ @@ -269,7 +269,7 @@ cell (sram_2_16_1_scn4m_subm){ direction : input; capacitance : 9.8242; internal_power(){ - when : "!CSb0 & clk0 & !WEb0"; + when : "!csb0 & clk0 & !web0"; rise_power(scalar){ values("9.972790277777777"); } @@ -278,7 +278,7 @@ cell (sram_2_16_1_scn4m_subm){ } } internal_power(){ - when : "!CSb0 & !clk0 & WEb0"; + when : "!csb0 & !clk0 & web0"; rise_power(scalar){ values("8.899322499999998"); } @@ -287,7 +287,7 @@ cell (sram_2_16_1_scn4m_subm){ } } internal_power(){ - when : "CSb0"; + when : "csb0"; rise_power(scalar){ values("0"); } diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib index 72a106ac..4f98380c 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib @@ -1,10 +1,10 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ delay_model : "table_lookup"; time_unit : "1ns" ; - voltage_unit : "1v" ; + voltage_unit : "1V" ; current_unit : "1mA" ; resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; + capacitive_load_unit(1, pF) ; leakage_power_unit : "1mW" ; pulling_resistance_unit :"1kohm" ; operating_conditions(OC){ @@ -81,7 +81,7 @@ cell (sram_2_16_1_scn4m_subm){ area : 60774.3; leakage_power () { - when : "CSb0"; + when : "csb0"; value : 0.000179; } cell_leakage_power : 0; @@ -198,7 +198,7 @@ cell (sram_2_16_1_scn4m_subm){ } } - pin(CSb0){ + pin(csb0){ direction : input; capacitance : 9.8242; timing(){ @@ -231,7 +231,7 @@ cell (sram_2_16_1_scn4m_subm){ } } - pin(WEb0){ + pin(web0){ direction : input; capacitance : 9.8242; timing(){ @@ -269,7 +269,7 @@ cell (sram_2_16_1_scn4m_subm){ direction : input; capacitance : 9.8242; internal_power(){ - when : "!CSb0 & clk0 & !WEb0"; + when : "!csb0 & clk0 & !web0"; rise_power(scalar){ values("11.3049604371"); } @@ -278,7 +278,7 @@ cell (sram_2_16_1_scn4m_subm){ } } internal_power(){ - when : "!CSb0 & !clk0 & WEb0"; + when : "!csb0 & !clk0 & web0"; rise_power(scalar){ values("11.3049604371"); } @@ -287,7 +287,7 @@ cell (sram_2_16_1_scn4m_subm){ } } internal_power(){ - when : "CSb0"; + when : "csb0"; rise_power(scalar){ values("0"); } diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_pruned.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_pruned.lib index 124f80ff..b601f3b0 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_pruned.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_pruned.lib @@ -1,10 +1,10 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ delay_model : "table_lookup"; time_unit : "1ns" ; - voltage_unit : "1v" ; + voltage_unit : "1V" ; current_unit : "1mA" ; resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; + capacitive_load_unit(1, pF) ; leakage_power_unit : "1mW" ; pulling_resistance_unit :"1kohm" ; operating_conditions(OC){ @@ -81,7 +81,7 @@ cell (sram_2_16_1_scn4m_subm){ area : 60774.3; leakage_power () { - when : "CSb0"; + when : "csb0"; value : 0.0009813788999999999; } cell_leakage_power : 0; @@ -198,7 +198,7 @@ cell (sram_2_16_1_scn4m_subm){ } } - pin(CSb0){ + pin(csb0){ direction : input; capacitance : 9.8242; timing(){ @@ -231,7 +231,7 @@ cell (sram_2_16_1_scn4m_subm){ } } - pin(WEb0){ + pin(web0){ direction : input; capacitance : 9.8242; timing(){ @@ -269,7 +269,7 @@ cell (sram_2_16_1_scn4m_subm){ direction : input; capacitance : 9.8242; internal_power(){ - when : "!CSb0 & clk0 & !WEb0"; + when : "!csb0 & clk0 & !web0"; rise_power(scalar){ values("9.602821763527778"); } @@ -278,7 +278,7 @@ cell (sram_2_16_1_scn4m_subm){ } } internal_power(){ - when : "!CSb0 & !clk0 & WEb0"; + when : "!csb0 & !clk0 & web0"; rise_power(scalar){ values("8.647938152416664"); } @@ -287,7 +287,7 @@ cell (sram_2_16_1_scn4m_subm){ } } internal_power(){ - when : "CSb0"; + when : "csb0"; rise_power(scalar){ values("0"); } From 91febec3a2acf53b7fca99bdcedab51d62f0319c Mon Sep 17 00:00:00 2001 From: Bin Wu Date: Tue, 25 Jun 2019 09:19:37 -0700 Subject: [PATCH 049/234] add hspice and ngspice pex tests --- compiler/tests/26_hspice_pex_pinv_test.py | 121 ++++++++++++++++++++ compiler/tests/26_ngspice_pex_pinv_test.py | 124 +++++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100755 compiler/tests/26_hspice_pex_pinv_test.py create mode 100755 compiler/tests/26_ngspice_pex_pinv_test.py diff --git a/compiler/tests/26_hspice_pex_pinv_test.py b/compiler/tests/26_hspice_pex_pinv_test.py new file mode 100755 index 00000000..60e5737c --- /dev/null +++ b/compiler/tests/26_hspice_pex_pinv_test.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# All rights reserved. +# +""" +Run regression tests/pex test on an extracted pinv to ensure pex functionality +with HSPICE. +""" +import unittest +from testutils import header,openram_test +import sys,os +sys.path.append(os.path.join(sys.path[0],"..")) +import globals +from globals import OPTS +import debug + + +class hspice_pex_pinv_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + import pinv + # generate the pinv module + OPTS.purge_temp = False + debug.info(2, "Checking 1x size inverter") + tx = pinv.pinv(name="pinv", size=1) + self.local_check(tx) + # generate its pex file + pex_file = self.run_pex(tx) + OPTS.purge_temp = True + OPTS.analytical_delay = False + + # load the hspice + OPTS.spice_name = "hspice" + OPTS.spice_exe = "hspice" + + import os + from characterizer import charutils + from charutils import parse_spice_list + # setup simulation + sim_file = OPTS.openram_temp + "stim.sp" + log_file_name = "timing" + + # make sure that the library simulation is successful + tempsp = "{0}{1}.sp".format(OPTS.openram_temp,tx.name) + self.write_simulaton(sim_file, tempsp, tx.name) + sp_delay = parse_spice_list(log_file_name, "pinv_delay") + assert sp_delay is not "Failed" + + # generate simulation for pex, make sure the simulation is successful + self.write_simulaton(sim_file, pex_file, tx.name) + pex_delay = parse_spice_list(log_file_name, "pinv_delay") + # make sure the extracted spice simulated + assert pex_delay is not "Failed" + + # if pex data is bigger than original spice file then result is ok + # actually this may not always be true depending on the netlist provided + # comment out for now + #debug.info(2,"pex_delay: {0}".format(pex_delay)) + #debug.info(2,"sp_delay: {0}".format(sp_delay)) + + #assert pex_delay > sp_delay, "pex delay {0} is smaller than sp_delay {1}"\ + #.format(pex_delay,sp_delay) + + globals.end_openram() + + def write_simulaton(self, sim_file, cir_file, top_module_name): + """ write pex spice simulation for a pinv test""" + import tech + from characterizer import measurements, stimuli + corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) + sim_file = open(sim_file, "w") + simulaton = stimuli(sim_file,corner) + + # library files + simulaton.write_include(cir_file) + + # supply voltages + simulaton.gen_constant(sig_name ="vdd", + v_val = tech.spice["nom_supply_voltage"]) + simulaton.gen_constant(sig_name = "gnd", + v_val = "0v") + + + run_time = tech.spice["feasible_period"] * 2 + # input voltage + simulaton.gen_pwl(sig_name ="input", + clk_times = [1,1], + data_values = [1,0], + period=1e9, + slew=0.000002, + setup=0) + + # instantiation of simulated pinv + simulaton.inst_model(pins = ["input", "output", "vdd", "gnd"], + model_name = top_module_name) + + # delay measurement + delay_measure = measurements.delay_measure(measure_name = "pinv_delay", + trig_name = "input", + targ_name = "output", + trig_dir_str = "FALL", + targ_dir_str = "RISE") + trig_td = trag_td = 0.01 * run_time + rest_info = trig_td,trag_td,tech.spice["nom_supply_voltage"] + delay_measure.write_measure(simulaton, rest_info) + + simulaton.write_control(end_time = run_time) + sim_file.close() + simulaton.run_sim() + + +# 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() diff --git a/compiler/tests/26_ngspice_pex_pinv_test.py b/compiler/tests/26_ngspice_pex_pinv_test.py new file mode 100755 index 00000000..12f71632 --- /dev/null +++ b/compiler/tests/26_ngspice_pex_pinv_test.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# All rights reserved. +# +""" +Run regression tests/pex test on an extracted pinv to ensure pex functionality +with Ngspice. +""" +import unittest +from testutils import header,openram_test +import sys,os +sys.path.append(os.path.join(sys.path[0],"..")) +import globals +from globals import OPTS +import debug + + +class ngspice_pex_pinv_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + import pinv + # generate the pinv module + OPTS.purge_temp = False + debug.info(2, "Checking 1x size inverter") + tx = pinv.pinv(name="pinv", size=1) + self.local_check(tx) + # generate its pex file + pex_file = self.run_pex(tx) + OPTS.purge_temp = True + OPTS.analytical_delay = False + + # load the ngspice + OPTS.spice_name = "ngspice" + OPTS.spice_exe = "ngspice" + + import os + from characterizer import charutils + from charutils import parse_spice_list + # setup simulaton + sim_file = OPTS.openram_temp + "stim.sp" + log_file_name = "timing" + + # make sure that the library simulation is successful + tempsp = "{0}{1}.sp".format(OPTS.openram_temp,tx.name) + self.write_simulaton(sim_file, tempsp, tx.name) + sp_delay = parse_spice_list(log_file_name, "pinv_delay") + assert sp_delay is not "Failed" + + # generate simulation for pex, make sure the simulation is successful + self.write_simulaton(sim_file, pex_file, tx.name) + pex_delay = parse_spice_list(log_file_name, "pinv_delay") + # make sure the extracted spice simulated + assert pex_delay is not "Failed" + + # if pex data is bigger than original spice file then result is ok + # actually this may not always be true depending on the netlist provided + # comment out for now + #debug.info(2,"pex_delay: {0}".format(pex_delay)) + #debug.info(2,"sp_delay: {0}".format(sp_delay)) + + #assert pex_delay > sp_delay, "pex delay {0} is smaller than sp_delay {1}"\ + #.format(pex_delay,sp_delay) + + globals.end_openram() + + def write_simulaton(self, sim_file, cir_file, top_module_name): + """ write pex spice simulation for a pinv test""" + import tech + from characterizer import measurements, stimuli + corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) + sim_file = open(sim_file, "w") + simulaton = stimuli(sim_file,corner) + + # library files + simulaton.write_include(cir_file) + + # supply voltages + simulaton.gen_constant(sig_name ="vdd", + v_val = tech.spice["nom_supply_voltage"]) + # The scn4m_subm and ngspice combination will have a gnd source error: + # "Fatal error: instance vgnd is a shorted VSRC" + # However, remove gnd power for all techa pass for this test + # simulaton.gen_constant(sig_name = "gnd", + # v_val = "0v") + + + run_time = tech.spice["feasible_period"] * 2 + # input voltage + simulaton.gen_pwl(sig_name ="input", + clk_times = [1,1], + data_values = [1,0], + period=1e9, + slew=0.000002, + setup=0) + + # instantiation of simulated pinv + simulaton.inst_model(pins = ["input", "output", "vdd", "gnd"], + model_name = top_module_name) + + # delay measurement + delay_measure = measurements.delay_measure(measure_name = "pinv_delay", + trig_name = "input", + targ_name = "output", + trig_dir_str = "FALL", + targ_dir_str = "RISE") + trig_td = trag_td = 0.01 * run_time + rest_info = trig_td,trag_td,tech.spice["nom_supply_voltage"] + delay_measure.write_measure(simulaton, rest_info) + + simulaton.write_control(end_time = run_time) + sim_file.close() + simulaton.run_sim() + + +# 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() From 3bd69d2759822ef935d973e494316fb7ce7a1fd7 Mon Sep 17 00:00:00 2001 From: jsowash Date: Tue, 25 Jun 2019 09:20:00 -0700 Subject: [PATCH 050/234] Added functionality to express polygons in LEF files. --- compiler/base/geometry.py | 4 +- compiler/base/lef.py | 31 +++++-- compiler/gdsMill/gdsMill/vlsiLayout.py | 107 +++++++++++++++---------- 3 files changed, 91 insertions(+), 51 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 56bae83d..7063cf81 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -165,7 +165,7 @@ class instance(geometry): debug.info(4, "creating instance: " + self.name) def get_blockages(self, layer, top=False): - """ Retrieve rectangular blockages of all modules in this instance. + """ Retrieve blockages of all modules in this instance. Apply the transform of the instance placement to give absolute blockages.""" angle = math.radians(float(self.rotate)) mirr = 1 @@ -186,11 +186,11 @@ class instance(geometry): new_blockages = [] if self.mod.is_library_cell: + # Writes library cell blockages as shapes instead of a large metal blockage blockages = [] blockages = self.mod.gds.getBlockages(layer) for b in blockages: new_blockages.append(self.transform_coords(b,self.offset, mirr, angle)) - print(new_blockages) else: blockages = self.mod.get_blockages(layer) for b in blockages: diff --git a/compiler/base/lef.py b/compiler/base/lef.py index ea2ff5ad..af539742 100644 --- a/compiler/base/lef.py +++ b/compiler/base/lef.py @@ -12,6 +12,7 @@ import math import debug import datetime from collections import defaultdict +import pdb class lef: """ @@ -84,7 +85,7 @@ class lef: pin_list = self.get_pins(name) for pin in pin_list: self.lef.write("{0}LAYER {1} ;\n".format(self.indent,pin.layer)) - self.lef_write_rect(pin.rect) + self.lef_write_shape(pin.rect) # End the PORT self.indent = self.indent[:-3] @@ -100,15 +101,29 @@ class lef: for layer in self.lef_layers: self.lef.write("{0}LAYER {1} ;\n".format(self.indent,layer)) self.indent += " " + # pdb.set_trace() blockages = self.get_blockages(layer,True) for b in blockages: - self.lef_write_rect(b) + # if len(b) > 2: + # print(b) + self.lef_write_shape(b) self.indent = self.indent[:-3] self.lef.write("{0}END\n".format(self.indent)) - def lef_write_rect(self, rect): - """ Write a LEF rectangle """ - self.lef.write("{0}RECT ".format(self.indent)) - for item in rect: - self.lef.write(" {0} {1}".format(round(item[0],self.round_grid), round(item[1],self.round_grid))) - self.lef.write(" ;\n") + def lef_write_shape(self, rect): + if len(rect) == 2: + """ Write a LEF rectangle """ + self.lef.write("{0}RECT ".format(self.indent)) + for item in rect: + # print(rect) + self.lef.write(" {0} {1}".format(round(item[0],self.round_grid), round(item[1],self.round_grid))) + self.lef.write(" ;\n") + else: + """ Write a LEF polygon """ + self.lef.write("{0}POLYGON ".format(self.indent)) + for item in rect: + self.lef.write(" {0} {1}".format(round(item[0],self.round_grid), round(item[1],self.round_grid))) + # for i in range(0,len(rect)): + # self.lef.write(" {0} {1}".format(round(rect[i][0],self.round_grid), round(rect[i][1],self.round_grid))) + self.lef.write(" ;\n") + diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index 992e3d26..57e81768 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -3,7 +3,6 @@ from datetime import * #from mpmath import matrix #from numpy import matrix from vector import vector -from pin_layout import pin_layout import numpy as np #import gdsPrimitives import debug @@ -727,12 +726,26 @@ class VlsiLayout: self.pins[label_text] = [] self.pins[label_text].append(pin_shapes) - + + def getBlockages(self,layer): + """ + Return all blockages on a given layer in [llx, lly, urx, ury] format and + user units. + """ + blockages = [] + + shapes = self.getAllShapes(layer) + for boundary in shapes: + vectors = [] + for i in range(0,len(boundary),2): + vectors.append(vector(boundary[i],boundary[i+1])) + blockages.append(vectors) + return blockages def getAllShapes(self,layer): """ - Return all shapes on a given layer in [llx, lly, urx, ury] format and - user units. + Return all shapes on a given layer in [llx, lly, urx, ury] format and user units for rectangles + and [coordinate 1, coordinate 2,...] format and user units for polygons. """ boundaries = set() for TreeUnit in self.xyTree: @@ -742,55 +755,67 @@ class VlsiLayout: # Convert to user units user_boundaries = [] for boundary in boundaries: - user_boundaries.append([boundary[0]*self.units[0],boundary[1]*self.units[0], - boundary[2]*self.units[0],boundary[3]*self.units[0]]) - + boundaries_list = [] + for i in range(0,len(boundary)): + boundaries_list.append(boundary[i]*self.units[0]) + user_boundaries.append(boundaries_list) return user_boundaries - def getBlockages(self,layer): - blockages = [] - - shapes = self.getAllShapes(layer) - for boundary in shapes: - ll = vector(boundary[0],boundary[1]) - ur = vector(boundary[2],boundary[3]) - rect = [ll,ur] - new_pin = rect - blockages.append(new_pin) - return blockages - - def getShapesInStructure(self,layer,structure): """ Go through all the shapes in a structure and return the list of shapes in - the form [llx, lly, urx, ury] + the form [llx, lly, urx, ury] for rectangles and [coordinate 1, coordinate 2,...] for polygons. """ - (structureName,structureOrigin,structureuVector,structurevVector)=structure #print(structureName,"u",structureuVector.transpose(),"v",structurevVector.transpose(),"o",structureOrigin.transpose()) boundaries = [] for boundary in self.structures[str(structureName)].boundaries: - # FIXME: Right now, this only supports rectangular shapes! - # We should trigger an error but some FreePDK45 library cells contain paths. - # These get saved fine, but we cannot parse them as blockages... - #debug.check(len(boundary.coordinates)==5,"Non-rectangular shapes are not supported.") - if len(boundary.coordinates)!=5: - continue if layer==boundary.drawingLayer: - left_bottom=boundary.coordinates[0] - right_top=boundary.coordinates[2] - # Rectangle is [leftx, bottomy, rightx, topy]. - boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]] - # perform the rotation - boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector) - # add the offset and make it a tuple - boundaryRect=(boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(), - boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()) - boundaries.append(boundaryRect) - + if len(boundary.coordinates)!=5: + # if shape is a polygon (used in DFF) + boundaryPolygon = [] + # Polygon is a list of coordinates going ccw + for coord in range(0,len(boundary.coordinates)): + boundaryPolygon.append(boundary.coordinates[coord][0]) + boundaryPolygon.append(boundary.coordinates[coord][1]) + # perform the rotation + boundaryPolygon=self.transformPolygon(boundaryPolygon,structureuVector,structurevVector) + # add the offset + polygon = [] + for i in range(0,len(boundaryPolygon),2): + polygon.append(boundaryPolygon[i]+structureOrigin[0].item()) + polygon.append(boundaryPolygon[i+1]+structureOrigin[1].item()) + # make it a tuple + polygon = tuple(polygon) + boundaries.append(polygon) + else: + # else shape is a rectangle + left_bottom=boundary.coordinates[0] + right_top=boundary.coordinates[2] + # Rectangle is [leftx, bottomy, rightx, topy]. + boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]] + # perform the rotation + boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector) + # add the offset and make it a tuple + boundaryRect=(boundaryRect[0]+structureOrigin[0].item(),boundaryRect[1]+structureOrigin[1].item(), + boundaryRect[2]+structureOrigin[0].item(),boundaryRect[3]+structureOrigin[1].item()) + boundaries.append(boundaryRect) return boundaries - + + + def transformPolygon(self,originalPolygon,uVector,vVector): + """ + Transforms the coordinates of a polygon in space. + """ + polygon = [] + newPolygon = [] + for i in range(0,len(originalPolygon),2): + polygon.append(self.transformCoordinate([originalPolygon[i],originalPolygon[i+1]],uVector,vVector)) + newPolygon.append(polygon[int(i/2)][0]) + newPolygon.append(polygon[int(i/2)][1]) + return newPolygon + def transformRectangle(self,originalRectangle,uVector,vVector): """ Transforms the four coordinates of a rectangle in space @@ -814,7 +839,7 @@ class VlsiLayout: """ Rotate a coordinate in space. """ - # MRG: 9/3/18 Incorrect matrixi multiplication! + # MRG: 9/3/18 Incorrect matrix multiplication! # This is fixed to be: # |u[0] v[0]| |x| |x'| # |u[1] v[1]|x|y|=|y'| From 3f3ee9b8859fd000242a6e2ea1bfe0d08111b85f Mon Sep 17 00:00:00 2001 From: Bin Wu Date: Tue, 25 Jun 2019 11:24:25 -0700 Subject: [PATCH 051/234] add pex function for magic and openram test --- compiler/tests/testutils.py | 53 +++++---- compiler/verify/magic.py | 217 +++++++++++++++++++++++++----------- 2 files changed, 185 insertions(+), 85 deletions(-) diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index 28313115..cffee8c5 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -16,7 +16,7 @@ import debug class openram_test(unittest.TestCase): """ Base unit test that we have some shared classes in. """ - + def local_drc_check(self, w): self.reset() @@ -31,11 +31,11 @@ class openram_test(unittest.TestCase): if OPTS.purge_temp: self.cleanup() - + def local_check(self, a, final_verification=False): self.reset() - + tempspice = "{0}{1}.sp".format(OPTS.openram_temp,a.name) tempgds = "{0}{1}.gds".format(OPTS.openram_temp,a.name) @@ -52,7 +52,7 @@ class openram_test(unittest.TestCase): #shutil.make_archive(zip_file, 'zip', OPTS.openram_temp) self.fail("DRC failed: {}".format(a.name)) - + result=verify.run_lvs(a.name, tempgds, tempspice, final_verification=final_verification) if result != 0: #zip_file = "/tmp/{0}_{1}".format(a.name,os.getpid()) @@ -63,6 +63,17 @@ class openram_test(unittest.TestCase): if OPTS.purge_temp: self.cleanup() + def run_pex(self, a, output=None): + if output == None: + output = OPTS.openram_temp + a.name + ".pex.netlist" + tempspice = "{0}{1}.sp".format(OPTS.openram_temp,a.name) + tempgds = "{0}{1}.gds".format(OPTS.openram_temp,a.name) + + import verify + result=verify.run_pex(a.name, tempgds, tempspice, output=output, final_verification=False) + if result != 0: + self.fail("PEX ERROR: {}".format(a.name)) + return output def find_feasible_test_period(self, delay_obj, sram, load, slew): """Creates a delay simulation to determine a feasible period for the functional tests to run. @@ -75,19 +86,19 @@ class openram_test(unittest.TestCase): delay_obj.create_signal_names() delay_obj.create_measurement_names() delay_obj.create_measurement_objects() - delay_obj.find_feasible_period_one_port(test_port) - return delay_obj.period - + delay_obj.find_feasible_period_one_port(test_port) + return delay_obj.period + def cleanup(self): """ Reset the duplicate checker and cleanup files. """ files = glob.glob(OPTS.openram_temp + '*') for f in files: # Only remove the files if os.path.isfile(f): - os.remove(f) + os.remove(f) def reset(self): - """ + """ Reset everything after each test. """ # Reset the static duplicate name checker for unit tests. @@ -116,7 +127,7 @@ class openram_test(unittest.TestCase): data_string=pprint.pformat(data) debug.error("Results exceeded {:.1f}% tolerance compared to golden results:\n".format(error_tolerance*100)+data_string) return data_matches - + def isclose(self,key,value,actual_value,error_tolerance=1e-2): @@ -132,7 +143,7 @@ class openram_test(unittest.TestCase): return False def relative_diff(self, value1, value2): - """ Compute the relative difference of two values and normalize to the largest. + """ Compute the relative difference of two values and normalize to the largest. If largest value is 0, just return the difference.""" # Edge case to avoid divide by zero @@ -148,7 +159,7 @@ class openram_test(unittest.TestCase): # Edge case where greater is a zero if norm_value == 0: min_value = abs(min(value1, value2)) - + return abs(value1 - value2) / norm_value @@ -162,15 +173,15 @@ class openram_test(unittest.TestCase): """Compare two files. Arguments: - + filename1 -- First file name - + filename2 -- Second file name Return value: - + True if the files are the same, False otherwise. - + """ import re import debug @@ -203,7 +214,7 @@ class openram_test(unittest.TestCase): debug.info(3,"line1_floats: "+str(line1_floats)) debug.info(3,"line2_floats: "+str(line2_floats)) - + # 2. Remove the floats from the string for f in line1_floats: line1=line1.replace(f,"",1) @@ -215,10 +226,10 @@ class openram_test(unittest.TestCase): # 3. Convert to floats rather than strings line1_floats = [float(x) for x in line1_floats] line2_floats = [float(x) for x in line1_floats] - + # 4. Check if remaining string matches if line1 != line2: - #Uncomment if you want to see all the individual chars of the two lines + #Uncomment if you want to see all the individual chars of the two lines #print(str([i for i in line1])) #print(str([i for i in line2])) if mismatches==0: @@ -281,13 +292,13 @@ class openram_test(unittest.TestCase): debug.info(2,"MATCH {0} {1}".format(filename1,filename2)) return True - + def header(filename, technology): # Skip the header for gitlab regression import getpass if getpass.getuser() == "gitlab-runner": return - + tst = "Running Test for:" print("\n") print(" ______________________________________________________________________________ ") diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index fd082a45..63aeaabe 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -6,11 +6,11 @@ # All rights reserved. # """ -This is a DRC/LVS/PEX interface file for magic + netgen. +This is a DRC/LVS/PEX interface file for magic + netgen. We include the tech file for SCN4M_SUBM in the tech directory, -that is included in OpenRAM during DRC. -You can use this interactively by appending the magic system path in +that is included in OpenRAM during DRC. +You can use this interactively by appending the magic system path in your .magicrc file path sys /Users/mrg/openram/technology/scn3me_subm/tech @@ -33,7 +33,7 @@ num_drc_runs = 0 num_lvs_runs = 0 num_pex_runs = 0 - + def write_magic_script(cell_name, extract=False, final_verification=False): """ Write a magic script to perform DRC and optionally extraction. """ @@ -69,7 +69,7 @@ def write_magic_script(cell_name, extract=False, final_verification=False): if final_verification: f.write(pre+"extract unique all\n".format(cell_name)) f.write(pre+"extract\n".format(cell_name)) - #f.write(pre+"ext2spice hierarchy on\n") + #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 #f.write(pre+"ext2spice lvs\n") @@ -82,18 +82,18 @@ def write_magic_script(cell_name, extract=False, final_verification=False): 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)) f.write("quit -noprompt\n") f.write("EOF\n") - + f.close() os.system("chmod u+x {}".format(run_file)) - + def write_netgen_script(cell_name): """ Write a netgen script to perform LVS. """ @@ -119,7 +119,7 @@ def write_netgen_script(cell_name): f.close() os.system("chmod u+x {}".format(run_file)) - + def run_drc(cell_name, gds_name, extract=True, final_verification=False): """Run DRC check on a cell which is implemented in gds_name.""" @@ -129,7 +129,7 @@ def run_drc(cell_name, gds_name, extract=True, final_verification=False): # 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) - + # Copy .magicrc file into temp dir magic_file = OPTS.openram_tech + "mag_lib/.magicrc" if os.path.exists(magic_file): @@ -151,7 +151,7 @@ def run_drc(cell_name, gds_name, extract=True, final_verification=False): f = open(outfile, "r") except FileNotFoundError: debug.error("Unable to load DRC results file from {}. Is magic set up?".format(outfile),1) - + results = f.readlines() f.close() errors=1 @@ -162,7 +162,7 @@ def run_drc(cell_name, gds_name, extract=True, final_verification=False): break else: debug.error("Unable to find the total error line in Magic output.",1) - + # always display this summary if errors > 0: @@ -189,19 +189,19 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): shutil.copy(gds_name, OPTS.openram_temp) if os.path.dirname(sp_name)!=OPTS.openram_temp.rstrip('/'): shutil.copy(sp_name, OPTS.openram_temp) - + write_netgen_script(cell_name) (outfile, errfile, resultsfile) = run_script(cell_name, "lvs") - + total_errors = 0 - + # check the result for these lines in the summary: try: f = open(resultsfile, "r") except FileNotFoundError: debug.error("Unable to load LVS results from {}".format(resultsfile),1) - + results = f.readlines() f.close() # Look for the results after the final "Subcircuit summary:" @@ -217,14 +217,14 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): test = re.compile("Property errors were found.") propertyerrors = list(filter(test.search, results)) total_errors += len(propertyerrors) - + # Require pins to match? # Cell pin lists for pnand2_1.spice and pnand2_1 altered to match. # test = re.compile(".*altered to match.") # pinerrors = list(filter(test.search, results)) # if len(pinerrors)>0: # debug.warning("Pins altered to match in {}.".format(cell_name)) - + #if len(propertyerrors)>0: # debug.warning("Property errors found, but not checking them.") @@ -232,7 +232,7 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): test = re.compile("Netlists do not match.") incorrect = list(filter(test.search, final_results)) total_errors += len(incorrect) - + # Netlists match uniquely. test = re.compile("match uniquely.") correct = list(filter(test.search, final_results)) @@ -244,7 +244,7 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): # Just print out the whole file, it is short. for e in results: debug.info(1,e.strip("\n")) - debug.error("{0}\tLVS mismatch (results in {1})".format(cell_name,resultsfile)) + debug.error("{0}\tLVS mismatch (results in {1})".format(cell_name,resultsfile)) else: debug.info(1, "{0}\tLVS matches".format(cell_name)) @@ -257,9 +257,9 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False): global num_pex_runs num_pex_runs += 1 - - debug.warning("PEX using magic not implemented.") - return 1 + #debug.warning("PEX using magic not implemented.") + #return 1 + os.chdir(OPTS.openram_temp) from tech import drc if output == None: @@ -271,25 +271,67 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False): run_drc(name, gds_name) run_lvs(name, gds_name, sp_name) - """ - 2. magic can perform extraction with the following: - #!/bin/sh - rm -f $1.ext - rm -f $1.spice - magic -dnull -noconsole << EOF - tech load SCN3ME_SUBM.30 - #scalegrid 1 2 - gds rescale no - gds polygon subcell true - gds warning default - gds read $1 - extract - ext2spice scale off - ext2spice - quit -noprompt - EOF - """ - + # pex_fix did run the pex using a script while dev orignial method + # use batch mode. + # the dev old code using batch mode does not run and is split into functions + #pex_runset = write_batch_pex_rule(gds_name,name,sp_name,output) + pex_runset = write_script_pex_rule(gds_name,name,output) + + errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name) + outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name) + + # bash mode command from dev branch + #batch_cmd = "{0} -gui -pex {1}pex_runset -batch 2> {2} 1> {3}".format(OPTS.pex_exe, + # OPTS.openram_temp, + # errfile, + # outfile) + script_cmd = "{0} 2> {1} 1> {2}".format(pex_runset, + errfile, + outfile) + cmd = script_cmd + debug.info(2, cmd) + os.system(cmd) + + # rename technology models + pex_nelist = open(output, 'r') + s = pex_nelist.read() + pex_nelist.close() + s = s.replace('pfet','p') + s = s.replace('nfet','n') + f = open(output, 'w') + f.write(s) + f.close() + + # also check the output file + f = open(outfile, "r") + results = f.readlines() + f.close() + out_errors = find_error(results) + debug.check(os.path.isfile(output),"Couldn't find PEX extracted output.") + + correct_port(name,output,sp_name) + return out_errors + +def write_batch_pex_rule(gds_name,name,sp_name,output): + """ + The dev branch old batch mode runset + 2. magic can perform extraction with the following: + #!/bin/sh + rm -f $1.ext + rm -f $1.spice + magic -dnull -noconsole << EOF + tech load SCN3ME_SUBM.30 + #scalegrid 1 2 + gds rescale no + gds polygon subcell true + gds warning default + gds read $1 + extract + ext2spice scale off + ext2spice + quit -noprompt + EOF + """ pex_rules = drc["xrc_rules"] pex_runset = { 'pexRulesFile': pex_rules, @@ -307,42 +349,89 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False): } # write the runset file - f = open(OPTS.openram_temp + "pex_runset", "w") - for k in sorted(pex_runset.iterkeys()): + file = OPTS.openram_temp + "pex_runset" + f = open(file, "w") + for k in sorted(pex_runset.keys()): f.write("*{0}: {1}\n".format(k, pex_runset[k])) f.close() + return file - # run pex - cwd = os.getcwd() - os.chdir(OPTS.openram_temp) - errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name) - outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name) +def write_script_pex_rule(gds_name,cell_name,output): + global OPTS + run_file = OPTS.openram_temp + "run_pex.sh" + f = open(run_file, "w") + f.write("#!/bin/sh\n") + 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 read {}\n".format(gds_name)) + f.write("load {}\n".format(cell_name)) + f.write("select top cell\n") + f.write("expand\n") + f.write("port makeall\n") + extract = True + if not extract: + pre = "#" + 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 subcircuit top on\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") + f.write("mv {0}.spice {1}\n".format(cell_name,output)) - cmd = "{0} -gui -pex {1}pex_runset -batch 2> {2} 1> {3}".format(OPTS.pex_exe, - OPTS.openram_temp, - errfile, - outfile) - debug.info(2, cmd) - os.system(cmd) - os.chdir(cwd) - - # also check the output file - f = open(outfile, "r") - results = f.readlines() f.close() + os.system("chmod u+x {}".format(run_file)) + return run_file +def find_error(results): # Errors begin with "ERROR:" test = re.compile("ERROR:") stdouterrors = list(filter(test.search, results)) for e in stdouterrors: debug.error(e.strip("\n")) - out_errors = len(stdouterrors) - - debug.check(os.path.isfile(output),"Couldn't find PEX extracted output.") - return out_errors +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_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() + # 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) + part2 = pex_file.read() + 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 = 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(part2) + output_file.close() + def print_drc_stats(): debug.info(1,"DRC runs: {0}".format(num_drc_runs)) def print_lvs_stats(): From 04ce3d5f457f6da81465c30bf3a79e9b3e01bc01 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 25 Jun 2019 14:55:28 -0700 Subject: [PATCH 052/234] Split control logic into different tests to avoid factory errors. --- compiler/bitcells/replica_pbitcell.py | 1 - compiler/sram_factory.py | 2 - .../tests/16_control_logic_multiport_test.py | 59 +++++++++++++++++++ compiler/tests/16_control_logic_test.py | 41 +------------ 4 files changed, 62 insertions(+), 41 deletions(-) create mode 100755 compiler/tests/16_control_logic_multiport_test.py diff --git a/compiler/bitcells/replica_pbitcell.py b/compiler/bitcells/replica_pbitcell.py index d39d361a..30898d82 100644 --- a/compiler/bitcells/replica_pbitcell.py +++ b/compiler/bitcells/replica_pbitcell.py @@ -54,7 +54,6 @@ class replica_pbitcell(design.design): def add_modules(self): self.prbc = factory.create(module_type="pbitcell",replica_bitcell=True) - debug.info(1,"rbl bitcell name={}".format(self.prbc.name)) self.add_mod(self.prbc) self.height = self.prbc.height diff --git a/compiler/sram_factory.py b/compiler/sram_factory.py index f53a72d5..0b079780 100644 --- a/compiler/sram_factory.py +++ b/compiler/sram_factory.py @@ -65,8 +65,6 @@ class sram_factory: # Must have the same dictionary exactly (conservative) if obj_kwargs == kwargs: #debug.info(0, "Existing module: type={0} name={1} kwargs={2}".format(module_type, obj_item.name, str(kwargs))) - if module_type == 'bitcell_array': - debug.info(1,'Returning existing mod!') return obj_item #else: # print("obj",obj_kwargs) diff --git a/compiler/tests/16_control_logic_multiport_test.py b/compiler/tests/16_control_logic_multiport_test.py new file mode 100755 index 00000000..66c34d24 --- /dev/null +++ b/compiler/tests/16_control_logic_multiport_test.py @@ -0,0 +1,59 @@ +#!/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. +# +""" +Run a regression test on a control_logic +""" + +import unittest +from testutils import header,openram_test +import sys,os +sys.path.append(os.path.join(sys.path[0],"..")) +import globals +from globals import OPTS +from sram_factory import factory +import debug + +class control_logic_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + import control_logic + import tech + + # check control logic for multi-port + OPTS.bitcell = "pbitcell" + OPTS.replica_bitcell = "replica_pbitcell" + OPTS.num_rw_ports = 1 + OPTS.num_w_ports = 1 + OPTS.num_r_ports = 1 + + debug.info(1, "Testing sample for control_logic for multiport, only write control logic") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="rw") + self.local_check(a) + + # OPTS.num_rw_ports = 0 + # OPTS.num_w_ports = 1 + debug.info(1, "Testing sample for control_logic for multiport, only write control logic") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="w") + self.local_check(a) + + # OPTS.num_w_ports = 0 + # OPTS.num_r_ports = 1 + debug.info(1, "Testing sample for control_logic for multiport, only read control logic") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="r") + 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() diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index 78866d7b..21409132 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -26,45 +26,10 @@ class control_logic_test(openram_test): import control_logic import tech - # # check control logic for single port - # debug.info(1, "Testing sample for control_logic") - # a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32) - # self.local_check(a) - - # check control logic for multi-port - OPTS.bitcell = "pbitcell" - OPTS.replica_bitcell = "replica_pbitcell" - #OPTS.num_rw_ports = 1 - OPTS.num_rw_ports = 0 - OPTS.num_w_ports = 0 - OPTS.num_r_ports = 0 - - # debug.info(1, "Testing sample for control_logic for multiport") - # a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8) - # self.local_check(a) - - # # Check port specific control logic - # OPTS.num_rw_ports = 1 - # OPTS.num_w_ports = 0 - # OPTS.num_r_ports = 0 - - # debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - # a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="rw") - # self.local_check(a) - - # OPTS.num_rw_ports = 0 - # OPTS.num_w_ports = 1 - # debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - # a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="w") - # self.local_check(a) - - OPTS.num_w_ports = 0 - OPTS.num_r_ports = 1 - debug.info(1, "Testing sample for control_logic for multiport, only read control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="r") + # check control logic for single port + debug.info(1, "Testing sample for control_logic") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32) self.local_check(a) - - globals.end_openram() # run the test from the command line if __name__ == "__main__": From 8e5fa7c7aeaf60e9df8aaf22f0191490056f405b Mon Sep 17 00:00:00 2001 From: Bin Wu Date: Tue, 25 Jun 2019 15:06:07 -0700 Subject: [PATCH 053/234] fix the run_pex function for calibre --- compiler/verify/calibre.py | 39 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/compiler/verify/calibre.py b/compiler/verify/calibre.py index 8698b248..8abca448 100644 --- a/compiler/verify/calibre.py +++ b/compiler/verify/calibre.py @@ -93,11 +93,11 @@ def write_calibre_lvs_script(cell_name, final_verification): 'cmnFDIUseLayerMap': 1, 'cmnTranscriptFile': './lvs.log', 'cmnTranscriptEchoToFile': 1, - 'lvsRecognizeGates': 'NONE', + 'lvsRecognizeGates': 'NONE', } # FIXME: Remove when vdd/gnd connected #'cmnVConnectNamesState' : 'ALL', #connects all nets with the same namee - # FIXME: Remove when vdd/gnd connected + # FIXME: Remove when vdd/gnd connected #'lvsAbortOnSupplyError' : 0 if not final_verification: @@ -106,7 +106,7 @@ def write_calibre_lvs_script(cell_name, final_verification): lvs_runset['cmnVConnectNames']='vdd gnd' else: lvs_runset['lvsAbortOnSupplyError']=1 - + # write the runset file @@ -127,20 +127,23 @@ def write_calibre_lvs_script(cell_name, final_verification): f.write("\n") f.close() os.system("chmod u+x {}".format(run_file)) - + return lvs_runset def write_calibre_pex_script(cell_name, extract, output, final_verification): - + if output == None: output = 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"): + gds_name = OPTS.openram_temp +"/"+ cell_name + ".gds" + sp_name = OPTS.openram_temp +"/"+ cell_name + ".sp" run_drc(cell_name, gds_name) run_lvs(cell_name, gds_name, sp_name) + from tech import drc pex_rules = drc["xrc_rules"] pex_runset = { 'pexRulesFile': pex_rules, @@ -175,18 +178,18 @@ def write_calibre_pex_script(cell_name, extract, output, final_verification): os.system("chmod u+x {}".format(run_file)) return pex_runset - + def run_drc(cell_name, gds_name, extract=False, final_verification=False): """Run DRC check on a given top-level name which is implemented in gds_name.""" - + global num_drc_runs num_drc_runs += 1 # 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) - + drc_runset = write_calibre_drc_script(cell_name, extract, final_verification) (outfile, errfile, resultsfile) = run_script(cell_name, "drc") @@ -209,12 +212,12 @@ def run_drc(cell_name, gds_name, extract=False, final_verification=False): # always display this summary if errors > 0: - debug.error("{0}\tGeometries: {1}\tChecks: {2}\tErrors: {3}".format(cell_name, + debug.error("{0}\tGeometries: {1}\tChecks: {2}\tErrors: {3}".format(cell_name, geometries, rulechecks, errors)) else: - debug.info(1, "{0}\tGeometries: {1}\tChecks: {2}\tErrors: {3}".format(cell_name, + debug.info(1, "{0}\tGeometries: {1}\tChecks: {2}\tErrors: {3}".format(cell_name, geometries, rulechecks, errors)) @@ -225,10 +228,10 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): """Run LVS check on a given top-level name which is implemented in gds_name and sp_name. Final verification will ensure that there are no remaining virtual conections. """ - + global num_lvs_runs num_lvs_runs += 1 - + lvs_runset = write_calibre_lvs_script(cell_name, final_verification) # Copy file to local dir if it isn't already @@ -280,7 +283,7 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): # MRG - 9/26/17 - Change this to exclude warnings because of # multiple labels on different pins in column mux. ext_errors = len(exterrors) - ext_warnings = len(extwarnings) + ext_warnings = len(extwarnings) # also check the output file f = open(outfile, "r") @@ -297,16 +300,16 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): total_errors = summary_errors + out_errors + ext_errors if total_errors > 0: - debug.error("{0}\tSummary: {1}\tOutput: {2}\tExtraction: {3}".format(cell_name, + debug.error("{0}\tSummary: {1}\tOutput: {2}\tExtraction: {3}".format(cell_name, summary_errors, out_errors, ext_errors)) else: - debug.info(1, "{0}\tSummary: {1}\tOutput: {2}\tExtraction: {3}".format(cell_name, + debug.info(1, "{0}\tSummary: {1}\tOutput: {2}\tExtraction: {3}".format(cell_name, summary_errors, out_errors, ext_errors)) - + return total_errors @@ -317,10 +320,10 @@ 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() + write_calibre_pex_script(cell_name,True,output,final_verification) (outfile, errfile, resultsfile) = run_script(cell_name, "pex") - + # also check the output file f = open(outfile, "r") From 33c17ac41c847c3bc5a48467583e86b8d71ee255 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 25 Jun 2019 15:45:02 -0700 Subject: [PATCH 054/234] Moved manual delay chain declarations from tech files to options. --- compiler/characterizer/__init__.py | 1 - compiler/characterizer/bitline_delay.py | 248 ------------------------ compiler/modules/bitcell_array.py | 2 +- compiler/modules/control_logic.py | 4 +- compiler/modules/replica_bitline.py | 2 + compiler/options.py | 11 +- technology/freepdk45/tech/tech.py | 4 - technology/scn4m_subm/tech/tech.py | 4 - 8 files changed, 13 insertions(+), 263 deletions(-) delete mode 100644 compiler/characterizer/bitline_delay.py diff --git a/compiler/characterizer/__init__.py b/compiler/characterizer/__init__.py index 4c3cd910..649d6bb2 100644 --- a/compiler/characterizer/__init__.py +++ b/compiler/characterizer/__init__.py @@ -15,7 +15,6 @@ from .setup_hold import * from .functional import * from .worst_case import * from .simulation import * -from .bitline_delay import * from .measurements import * from .model_check import * diff --git a/compiler/characterizer/bitline_delay.py b/compiler/characterizer/bitline_delay.py deleted file mode 100644 index 90197619..00000000 --- a/compiler/characterizer/bitline_delay.py +++ /dev/null @@ -1,248 +0,0 @@ -# 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 sys,re,shutil -import debug -import tech -import math -from .stimuli import * -from .trim_spice import * -from .charutils import * -import utils -from globals import OPTS -from .delay import delay - -class bitline_delay(delay): - """Functions to test for the worst case delay in a target SRAM - - The current worst case determines a feasible period for the SRAM then tests - several bits and record the delay and differences between the bits. - - """ - - def __init__(self, sram, spfile, corner): - delay.__init__(self,sram,spfile,corner) - self.period = tech.spice["feasible_period"] - self.is_bitline_measure = True - - def create_signal_names(self): - delay.create_signal_names(self) - self.bl_signal_names = ["Xsram.Xbank0.bl", "Xsram.Xbank0.br"] - self.sen_name = "Xsram.s_en" - - def create_measurement_names(self): - """Create measurement names. The names themselves currently define the type of measurement""" - #Altering the names will crash the characterizer. TODO: object orientated approach to the measurements. - self.bl_volt_meas_names = ["volt_bl", "volt_br"] - self.bl_delay_meas_names = ["delay_bl", "delay_br"] #only used in SPICE simulation - self.bl_delay_result_name = "delay_bl_vth" #Used in the return value - - def set_probe(self,probe_address, probe_data): - """ Probe address and data can be set separately to utilize other - functions in this characterizer besides analyze.""" - delay.set_probe(self,probe_address, probe_data) - self.bitline_column = self.get_data_bit_column_number(probe_address, probe_data) - - def write_delay_measures(self): - """ - Write the measure statements to quantify the bitline voltage at sense amp enable 50%. - """ - self.sf.write("\n* Measure statements for delay and power\n") - - # Output some comments to aid where cycles start and - for comment in self.cycle_comments: - self.sf.write("* {}\n".format(comment)) - - for read_port in self.targ_read_ports: - self.write_bitline_voltage_measures(read_port) - self.write_bitline_delay_measures(read_port) - - def write_bitline_voltage_measures(self, port): - """ - Add measurments to capture the bitline voltages at 50% Sense amp enable - """ - debug.info(2, "Measuring bitline column={}, port={}".format(self.bitline_column,port)) - if len(self.all_ports) == 1: #special naming case for single port sram bitlines - bitline_port = "" - else: - bitline_port = str(port) - - sen_port_name = "{}{}".format(self.sen_name,port) - for (measure_name, bl_signal_name) in zip(self.bl_volt_meas_names, self.bl_signal_names): - bl_port_name = "{}{}_{}".format(bl_signal_name, bitline_port, self.bitline_column) - measure_port_name = "{}{}".format(measure_name,port) - self.stim.gen_meas_find_voltage(measure_port_name, sen_port_name, bl_port_name, .5, "RISE", self.cycle_times[self.measure_cycles[port]["read0"]]) - - def write_bitline_delay_measures(self, port): - """ - Write the measure statements to quantify the delay and power results for a read port. - """ - # add measure statements for delays/slews - for (measure_name, bl_signal_name) in zip(self.bl_delay_meas_names, self.bl_signal_names): - meas_values = self.get_delay_meas_values(measure_name, bl_signal_name, port) - self.stim.gen_meas_delay(*meas_values) - - def get_delay_meas_values(self, delay_name, bitline_name, port): - """Get the values needed to generate a Spice measurement statement based on the name of the measurement.""" - if len(self.all_ports) == 1: #special naming case for single port sram bitlines - bitline_port = "" - else: - bitline_port = str(port) - - meas_name="{0}{1}".format(delay_name, port) - targ_name = "{0}{1}_{2}".format(bitline_name,bitline_port,self.bitline_column) - half_vdd = 0.5 * self.vdd_voltage - trig_val = half_vdd - targ_val = self.vdd_voltage-tech.spice["v_threshold_typical"] - trig_name = "clk{0}".format(port) - trig_dir="FALL" - targ_dir="FALL" - #Half period added to delay measurement to negative clock edge - trig_td = targ_td = self.cycle_times[self.measure_cycles[port]["read0"]] + self.period/2 - return (meas_name,trig_name,targ_name,trig_val,targ_val,trig_dir,targ_dir,trig_td,targ_td) - - def gen_test_cycles_one_port(self, read_port, write_port): - """Sets a list of key time-points [ns] of the waveform (each rising edge) - of the cycles to do a timing evaluation of a single port """ - - # Create the inverse address for a scratch address - inverse_address = self.calculate_inverse_address() - - # For now, ignore data patterns and write ones or zeros - data_ones = "1"*self.word_size - data_zeros = "0"*self.word_size - - if self.t_current == 0: - self.add_noop_all_ports("Idle cycle (no positive clock edge)", - inverse_address, data_zeros) - - self.add_write("W data 1 address {}".format(inverse_address), - inverse_address,data_ones,write_port) - - self.add_write("W data 0 address {} to write value".format(self.probe_address), - self.probe_address,data_zeros,write_port) - self.measure_cycles[write_port]["write0"] = len(self.cycle_times)-1 - - # This also ensures we will have a H->L transition on the next read - self.add_read("R data 1 address {} to set DOUT caps".format(inverse_address), - inverse_address,data_zeros,read_port) - self.measure_cycles[read_port]["read1"] = len(self.cycle_times)-1 - - self.add_read("R data 0 address {} to check W0 worked".format(self.probe_address), - self.probe_address,data_zeros,read_port) - self.measure_cycles[read_port]["read0"] = len(self.cycle_times)-1 - - def get_data_bit_column_number(self, probe_address, probe_data): - """Calculates bitline column number of data bit under test using bit position and mux size""" - if self.sram.col_addr_size>0: - col_address = int(probe_address[0:self.sram.col_addr_size],2) - else: - col_address = 0 - bl_column = int(self.sram.words_per_row*probe_data + col_address) - return bl_column - - def run_delay_simulation(self): - """ - This tries to simulate a period and checks if the result works. If - so, it returns True and the delays, slews, and powers. It - works on the trimmed netlist by default, so powers do not - include leakage of all cells. - """ - #Sanity Check - debug.check(self.period > 0, "Target simulation period non-positive") - - result = [{} for i in self.all_ports] - # Checking from not data_value to data_value - self.write_delay_stimulus() - - self.stim.run_sim() #running sim prodoces spice output file. - - for port in self.targ_read_ports: - #Parse and check the voltage measurements - bl_volt_meas_dict = {} - for mname in self.bl_volt_meas_names: - mname_port = "{}{}".format(mname,port) - volt_meas_val = parse_spice_list("timing", mname_port) - if type(volt_meas_val)!=float: - debug.error("Failed to Parse Bitline Voltage:\n\t\t{0}={1}".format(mname,volt_meas_val),1) - bl_volt_meas_dict[mname] = volt_meas_val - result[port].update(bl_volt_meas_dict) - - #Parse and check the delay measurements. Intended that one measurement will fail, save the delay that did not fail. - bl_delay_meas_dict = {} - values_added = 0 #For error checking - for mname in self.bl_delay_meas_names: #Parse - mname_port = "{}{}".format(mname,port) - delay_meas_val = parse_spice_list("timing", mname_port) - if type(delay_meas_val)==float: #Only add if value is float, do not error. - bl_delay_meas_dict[self.bl_delay_result_name] = delay_meas_val * 1e9 #convert to ns - values_added+=1 - debug.check(values_added>0, "Bitline delay measurements failed in SPICE simulation.") - debug.check(values_added<2, "Both bitlines experienced a Vth drop, check simulation results.") - result[port].update(bl_delay_meas_dict) - - # The delay is from the negative edge for our SRAM - return (True,result) - - def check_bitline_all_results(self, results): - """Checks the bitline values measured for each tested port""" - for port in self.targ_read_ports: - self.check_bitline_port_results(results[port]) - - def check_bitline_port_results(self, port_results): - """Performs three different checks for the bitline values: functionality, bitline swing from vdd, and differential bit swing""" - bl_volt, br_volt = port_results["volt_bl"], port_results["volt_br"] - self.check_functionality(bl_volt,br_volt) - self.check_swing_from_vdd(bl_volt,br_volt) - self.check_differential_swing(bl_volt,br_volt) - - def check_functionality(self, bl_volt, br_volt): - """Checks whether the read failed or not. Measured values are hardcoded with the intention of reading a 0.""" - if bl_volt > br_volt: - debug.error("Read failure. Value 1 was read instead of 0.",1) - - def check_swing_from_vdd(self, bl_volt, br_volt): - """Checks difference on discharging bitline from VDD to see if it is within margin of the RBL height parameter.""" - if bl_volt < br_volt: - discharge_volt = bl_volt - else: - discharge_volt = br_volt - desired_bl_volt = tech.parameter["rbl_height_percentage"]*self.vdd_voltage - debug.info(1, "Active bitline={:.3f}v, Desired bitline={:.3f}v".format(discharge_volt,desired_bl_volt)) - vdd_error_margin = .2 #20% of vdd margin for bitline, a little high for now. - if abs(discharge_volt - desired_bl_volt) > vdd_error_margin*self.vdd_voltage: - debug.warning("Bitline voltage is not within {}% Vdd margin. Delay chain/RBL could need resizing.".format(vdd_error_margin*100)) - - def check_differential_swing(self, bl_volt, br_volt): - """This check looks at the difference between the bitline voltages. This needs to be large enough to prevent - sensing errors.""" - bitline_swing = abs(bl_volt-br_volt) - debug.info(1,"Bitline swing={:.3f}v".format(bitline_swing)) - vdd_error_margin = .2 #20% of vdd margin for bitline, a little high for now. - if bitline_swing < vdd_error_margin*self.vdd_voltage: - debug.warning("Bitline swing less than {}% Vdd margin. Sensing errors more likely to occur.".format(vdd_error_margin)) - - def analyze(self, probe_address, probe_data, slews, loads): - """Measures the bitline swing of the differential bitlines (bl/br) at 50% s_en """ - self.set_probe(probe_address, probe_data) - self.load=max(loads) - self.slew=max(slews) - - read_port = self.read_ports[0] #only test the first read port - bitline_swings = {} - self.targ_read_ports = [read_port] - self.targ_write_ports = [self.write_ports[0]] - debug.info(1,"Bitline swing test: corner {}".format(self.corner)) - (success, results)=self.run_delay_simulation() - debug.check(success, "Bitline Failed: period {}".format(self.period)) - debug.info(1,"Bitline values (voltages/delays):\n\t {}".format(results[read_port])) - self.check_bitline_all_results(results) - - return results - - - diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 17b82199..f9d62e0e 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -154,7 +154,7 @@ class bitcell_array(design.design): # Dynamic Power from Bitline bl_wire = self.gen_bl_wire() cell_load = 2 * bl_wire.return_input_cap() - bl_swing = parameter["rbl_height_percentage"] + bl_swing = OPTS.rbl_delay_percentage freq = spice["default_event_rate"] bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 35795972..64aea76d 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -143,10 +143,10 @@ class control_logic(design.design): self.delay_chain_resized = False c = reload(__import__(OPTS.replica_bitline)) replica_bitline = getattr(c, OPTS.replica_bitline) - bitcell_loads = int(math.ceil(self.num_rows * parameter["rbl_height_percentage"])) + bitcell_loads = int(math.ceil(self.num_rows * OPTS.rbl_delay_percentage)) #Use a model to determine the delays with that heuristic if OPTS.use_tech_delay_chain_size: #Use tech parameters if set. - fanout_list = parameter["static_fanout_list"] + fanout_list = OPTS.delay_chain_stages*[OPTS.delay_chain_fanout_per_stage] debug.info(1, "Using tech parameters to size delay chain: fanout_list={}".format(fanout_list)) self.replica_bitline = factory.create(module_type="replica_bitline", delay_fanout_list=fanout_list, diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index 8bfaf0f2..720802c3 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -25,6 +25,8 @@ class replica_bitline(design.design): self.bitcell_loads = bitcell_loads self.delay_fanout_list = delay_fanout_list + if len(delay_fanout_list) == 0 or len(delay_fanout_list)%2 == 1: + debug.error('Delay chain must contain an even amount of stages to maintain polarity.',1) self.create_netlist() if not OPTS.netlist_only: diff --git a/compiler/options.py b/compiler/options.py index b3ac813a..bb3811c6 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -42,10 +42,15 @@ class options(optparse.Values): ################### # Optimization options - ################### - # Uses the delay chain size in the tech.py file rather automatic sizing. + ################### + rbl_delay_percentage = .5 #Approximate percentage of delay compared to bitlines + + # Allow manual adjustment of the delay chain over automatic use_tech_delay_chain_size = False - + delay_chain_stages = 4 + delay_chain_fanout_per_stage = 3 + + ################### # Debug options. diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 12c314cf..4654770e 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -354,9 +354,6 @@ spice["nor2_transition_prob"] = .1875 # Transition probability of 2-input no #Parameters related to sense amp enable timing and delay chain/RBL sizing parameter['le_tau'] = 2.25 #In pico-seconds. parameter['cap_relative_per_ff'] = 7.5 #Units of Relative Capacitance/ Femto-Farad -parameter["static_delay_stages"] = 4 -parameter["static_fanout_per_stage"] = 3 -parameter["static_fanout_list"] = parameter["static_delay_stages"]*[parameter["static_fanout_per_stage"]] parameter["dff_clk_cin"] = 30.6 #relative capacitance parameter["6tcell_wl_cin"] = 3 #relative capacitance parameter["min_inv_para_delay"] = 2.4 #Tau delay units @@ -364,7 +361,6 @@ parameter["sa_en_pmos_size"] = .72 #micro-meters parameter["sa_en_nmos_size"] = .27 #micro-meters parameter["sa_inv_pmos_size"] = .54 #micro-meters parameter["sa_inv_nmos_size"] = .27 #micro-meters -parameter["rbl_height_percentage"] = .5 #Height of RBL compared to bitcell array parameter['bitcell_drain_cap'] = 0.1 #In Femto-Farad, approximation of drain capacitance ################################################### diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 15278c7b..bf982b48 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -321,16 +321,12 @@ spice["nor2_transition_prob"] = .1875 # Transition probability of 2-input no parameter['le_tau'] = 23 #In pico-seconds. parameter["min_inv_para_delay"] = .73 #In relative delay units parameter['cap_relative_per_ff'] = .91 #Units of Relative Capacitance/ Femto-Farad -parameter["static_delay_stages"] = 4 -parameter["static_fanout_per_stage"] = 3 -parameter["static_fanout_list"] = parameter["static_delay_stages"]*[parameter["static_fanout_per_stage"]] parameter["dff_clk_cin"] = 27.5 #In relative capacitance units parameter["6tcell_wl_cin"] = 2 #In relative capacitance units parameter["sa_en_pmos_size"] = 24*_lambda_ parameter["sa_en_nmos_size"] = 9*_lambda_ parameter["sa_inv_pmos_size"] = 18*_lambda_ parameter["sa_inv_nmos_size"] = 9*_lambda_ -parameter["rbl_height_percentage"] = .5 #Height of RBL compared to bitcell array parameter['bitcell_drain_cap'] = 0.2 #In Femto-Farad, approximation of drain capacitance ################################################### From 4f3340e973ee87a8c84d913cff0a816713aab5f3 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 25 Jun 2019 16:37:35 -0700 Subject: [PATCH 055/234] Cleaned up graph additions to characterizer. --- compiler/base/graph_util.py | 17 +-------------- compiler/base/hierarchy_design.py | 19 +---------------- compiler/characterizer/delay.py | 35 +++++++++++++------------------ compiler/pgates/pand2.py | 2 +- 4 files changed, 18 insertions(+), 55 deletions(-) diff --git a/compiler/base/graph_util.py b/compiler/base/graph_util.py index af4d0888..b6ac4677 100644 --- a/compiler/base/graph_util.py +++ b/compiler/base/graph_util.py @@ -56,7 +56,7 @@ class timing_graph(): # Call the recursive helper function to print all paths self.get_all_paths_util(src_node, dest_node, visited, path) - debug.info(1, "Paths found={}".format(len(self.all_paths))) + debug.info(2, "Paths found={}".format(len(self.all_paths))) return self.all_paths @@ -69,7 +69,6 @@ class timing_graph(): # If current vertex is same as destination, then print # current path[] if cur_node == dest_node: - debug.info(1,"{}".format(path)) self.all_paths.append(copy.deepcopy(path)) else: # If current vertex is not destination @@ -82,20 +81,6 @@ class timing_graph(): path.pop() visited.remove(cur_node) - def get_path_preconvergence_point(self, path1, path2): - """Assuming the inputs paths have the same starting point and end point, the - paths should split and converge at some point before/at the last stage. Finds the - point before convergence.""" - debug.check(path1[0] == path2[0], "Paths must start from the same point.") - debug.check(path1[-1] == path2[-1], "Paths must end from the same point.") - #Paths must end at the same point, so the paths are traversed backwards to find - #point of convergence. There could be multiple points, only finds first. - for point1,point2 in zip(reversed(path1), reversed(path2)): - if point1 != point2: - return (point1,point2) - debug.info(1,"Pre-convergence point not found, paths are equals.") - return path1[0],path2[0] - def __str__(self): """ override print function output """ return "Nodes: {}\nEdges:{} ".format(list(self.graph), self.graph) \ No newline at end of file diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index a75e5a3c..a8a191af 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -147,7 +147,6 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): """Given a list of nets, will compare the internal alias of a mod to determine if the nets have a connection to this mod's net (but not inst). """ - #path_nets = ['xsram_0.xbank0.bl0_7'] if exclusion_set == None: exclusion_set = set() try: @@ -155,31 +154,17 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): except AttributeError: self.name_dict = {} self.build_names(self.name_dict, inst_name, port_nets) - #debug.info(1,"names={}".format(list(self.name_dict))) aliases = [] for net in path_nets: net = net.lower() int_net = self.name_dict[net]['int_net'] int_mod = self.name_dict[net]['mod'] - # debug.info(1,"int_net={}".format(int_net)) - # debug.info(1,"int_mod={}".format(int_mod.name)) - # debug.info(1,"alias_net={}".format(alias)) - # debug.info(1,"alias_mod={}".format(alias_mod.name)) - # debug.info(1,"mod id={}".format(id(alias_mod))) if int_mod.is_net_alias(int_net, alias, alias_mod, exclusion_set): aliases.append(net) - # debug.info(1,"Alias found\n") - # else: - # debug.info(1,"Alias not found\n") - debug.info(1,"Aliases Found={}".format(aliases)) return aliases def is_net_alias(self, known_net, net_alias, mod, exclusion_set): - """Checks if the alias_net in mod is the same as the input net.""" - # debug.info(1,"self name={}".format(self.name)) - # debug.info(1,"self mod id={}".format(id(self))) - # debug.info(1,"self pins={}".format(self.pins)) - # debug.info(1,"known_net={}".format(known_net)) + """Checks if the alias_net in input mod is the same as the input net for this mod (self).""" if self in exclusion_set: return False #Check ports of this mod @@ -193,8 +178,6 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): if self.is_net_alias_name_check(known_net, inst_conn, net_alias, mod): return True elif inst_conn.lower() == known_net.lower() and subinst.mod not in mod_set: - # debug.info(1,"found matching conn={}".format(inst_conn)) - # debug.info(1,"Setting known pin={}".format(mod_pin)) if subinst.mod.is_net_alias(mod_pin, net_alias, mod, exclusion_set): return True mod_set.add(subinst.mod) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index a927ef69..6c5be96c 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -216,17 +216,19 @@ class delay(simulation): self.graph = graph_util.timing_graph() self.sram_spc_name = "X{}".format(self.sram.name) self.sram.build_graph(self.graph,self.sram_spc_name,self.pins) - #debug.info(1,"{}".format(self.graph)) + + def set_internal_spice_names(self): + """Sets important names for characterization such as Sense amp enable and internal bit nets.""" port = 0 self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), \ '{}{}_{}'.format(self.dout_name, port, self.probe_data)) self.sen_name = self.get_sen_name(self.graph.all_paths) - debug.info(1,"s_en name = {}".format(self.sen_name)) + debug.info(2,"s_en name = {}".format(self.sen_name)) self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths) - debug.info(1,"bl name={}, br name={}".format(self.bl_name,self.br_name)) - + debug.info(2,"bl name={}, br name={}".format(self.bl_name,self.br_name)) + def get_sen_name(self, paths): """Gets the signal name associated with the sense amp enable from input paths. Only expects a single path to contain the sen signal name.""" @@ -245,13 +247,7 @@ class delay(simulation): cell_mod = self.get_primary_cell_mod(cell_mods) elif len(cell_mods)==0: debug.error("No bitcells found. Cannot determine bitline names.", 1) - #Any sense amp instantiated should be identical, any change to that - #will require some identification to determine the mod desired. - # debug.check(self.are_mod_pins_equal(cell_mods), "Only expected one type of bitcell. Cannot perform bitline checks") - # debug.info(1,"num pbitcells={}".format(len(cell_mods))) - # debug.info(1,"cell ids={}".format([id(i) for i in cell_mods])) - - #cell_mods = cell_mods[1:] + cell_bl = cell_mod.get_bl_name() cell_br = cell_mod.get_br_name() @@ -705,9 +701,8 @@ class delay(simulation): def check_sen_measure(self, port): """Checks that the sen occurred within a half-period""" - self.sen_meas sen_val = self.sen_meas.retrieve_measure(port=port) - debug.info(1,"S_EN delay={} ns".format(sen_val)) + debug.info(2,"S_EN delay={} ns".format(sen_val)) if self.sen_meas.meta_add_delay: max_delay = self.period/2 else: @@ -729,7 +724,7 @@ class delay(simulation): elif self.br_name == meas.targ_name_no_port: br_vals[meas.meta_str] = val - debug.info(1,"{}={}".format(meas.name,val)) + debug.info(2,"{}={}".format(meas.name,val)) bl_check = False for meas in self.debug_volt_meas: @@ -762,24 +757,23 @@ class delay(simulation): for polarity, meas_list in self.bit_meas.items(): for meas in meas_list: val = meas.retrieve_measure() - debug.info(1,"{}={}".format(meas.name, val)) + debug.info(2,"{}={}".format(meas.name, val)) if type(val) != float: continue meas_cycle = meas.meta_str + #Loose error conditions. Assume it's not metastable but account for noise during reads. if (meas_cycle == sram_op.READ_ZERO and polarity == bit_polarity.NONINVERTING) or\ (meas_cycle == sram_op.READ_ONE and polarity == bit_polarity.INVERTING): - success = val < self.vdd_voltage*.1 + success = val < self.vdd_voltage/2 elif (meas_cycle == sram_op.READ_ZERO and polarity == bit_polarity.INVERTING) or\ (meas_cycle == sram_op.READ_ONE and polarity == bit_polarity.NONINVERTING): - success = val > self.vdd_voltage*.9 + success = val > self.vdd_voltage/2 if not success: debug.info(1,("Wrong value detected on probe bit during read cycle. " "Check writes and control logic for bugs.\n measure={}, op={}, " - "bit_storage={}").format(meas.name, meas_cycle.name, polarity.name)) + "bit_storage={}, V(bit)={}").format(meas.name, meas_cycle.name, polarity.name,val)) return success - - def check_bitline_meas(self, v_discharged_bl, v_charged_bl): """Checks the value of the discharging bitline. Confirms s_en timing errors. Returns true if the bitlines are at there expected value.""" @@ -991,6 +985,7 @@ class delay(simulation): """Sets values which are dependent on the data address/bit being tested.""" self.set_probe(probe_address, probe_data) self.create_graph() + self.set_internal_spice_names() self.create_measurement_names() self.create_measurement_objects() diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index add59565..f7c26032 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -18,7 +18,7 @@ class pand2(pgate.pgate): This is a simple buffer used for driving loads. """ def __init__(self, name, size=1, height=None): - debug.info(1, "reating pnand2 {}".format(name)) + debug.info(1, "Creating pnand2 {}".format(name)) self.add_comment("size: {}".format(size)) self.size = size From ce7e3205053e43a4da3a1bb4707ec31f011262e6 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 25 Jun 2019 18:26:13 -0700 Subject: [PATCH 056/234] Undid change to add bitcell as input to array mod. --- compiler/characterizer/bitline_delay.py | 248 ------------------------ compiler/modules/bank.py | 3 +- compiler/modules/bitcell_array.py | 4 +- compiler/modules/replica_bitline.py | 6 +- 4 files changed, 5 insertions(+), 256 deletions(-) delete mode 100644 compiler/characterizer/bitline_delay.py diff --git a/compiler/characterizer/bitline_delay.py b/compiler/characterizer/bitline_delay.py deleted file mode 100644 index 68985b2a..00000000 --- a/compiler/characterizer/bitline_delay.py +++ /dev/null @@ -1,248 +0,0 @@ -# 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 sys,re,shutil -import debug -import tech -import math -from .stimuli import * -from .trim_spice import * -from .charutils import * -import utils -from globals import OPTS -from .delay import delay - -class bitline_delay(delay): - """Functions to test for the worst case delay in a target SRAM - - The current worst case determines a feasible period for the SRAM then tests - several bits and record the delay and differences between the bits. - - """ - - def __init__(self, sram, spfile, corner): - delay.__init__(self,sram,spfile,corner) - self.period = tech.spice["feasible_period"] - self.is_bitline_measure = True - - def create_signal_names(self): - delay.create_signal_names(self) - self.bl_signal_names = ["Xsram.Xbank0.bl", "Xsram.Xbank0.br"] - self.sen_name = "Xsram.s_en" - - def create_measurement_names(self): - """Create measurement names. The names themselves currently define the type of measurement""" - #Altering the names will crash the characterizer. TODO: object orientated approach to the measurements. - self.bl_volt_meas_names = ["volt_bl", "volt_br"] - self.bl_delay_meas_names = ["delay_bl", "delay_br"] #only used in SPICE simulation - self.bl_delay_result_name = "delay_bl_vth" #Used in the return value - - def set_probe(self,probe_address, probe_data): - """ Probe address and data can be set separately to utilize other - functions in this characterizer besides analyze.""" - delay.set_probe(self,probe_address, probe_data) - self.bitline_column = self.get_data_bit_column_number(probe_address, probe_data) - - def write_delay_measures(self): - """ - Write the measure statements to quantify the bitline voltage at sense amp enable 50%. - """ - self.sf.write("\n* Measure statements for delay and power\n") - - # Output some comments to aid where cycles start and - for comment in self.cycle_comments: - self.sf.write("* {}\n".format(comment)) - - for read_port in self.targ_read_ports: - self.write_bitline_voltage_measures(read_port) - self.write_bitline_delay_measures(read_port) - - def write_bitline_voltage_measures(self, port): - """ - Add measurments to capture the bitline voltages at 50% Sense amp enable - """ - debug.info(2, "Measuring bitline column={}, port={}".format(self.bitline_column,port)) - if len(self.all_ports) == 1: #special naming case for single port sram bitlines - bitline_port = "" - else: - bitline_port = str(port) - - sen_port_name = "{}{}".format(self.sen_name,port) - for (measure_name, bl_signal_name) in zip(self.bl_volt_meas_names, self.bl_signal_names): - bl_port_name = "{}{}_{}".format(bl_signal_name, bitline_port, self.bitline_column) - measure_port_name = "{}{}".format(measure_name,port) - self.stim.gen_meas_find_voltage(measure_port_name, sen_port_name, bl_port_name, .5, "RISE", self.cycle_times[self.measure_cycles[port]["read0"]]) - - def write_bitline_delay_measures(self, port): - """ - Write the measure statements to quantify the delay and power results for a read port. - """ - # add measure statements for delays/slews - for (measure_name, bl_signal_name) in zip(self.bl_delay_meas_names, self.bl_signal_names): - meas_values = self.get_delay_meas_values(measure_name, bl_signal_name, port) - self.stim.gen_meas_delay(*meas_values) - - def get_delay_meas_values(self, delay_name, bitline_name, port): - """Get the values needed to generate a Spice measurement statement based on the name of the measurement.""" - if len(self.all_ports) == 1: #special naming case for single port sram bitlines - bitline_port = "" - else: - bitline_port = str(port) - - meas_name="{0}{1}".format(delay_name, port) - targ_name = "{0}{1}_{2}".format(bitline_name,bitline_port,self.bitline_column) - half_vdd = 0.5 * self.vdd_voltage - trig_val = half_vdd - targ_val = self.vdd_voltage-tech.spice["v_threshold_typical"] - trig_name = "clk{0}".format(port) - trig_dir="FALL" - targ_dir="FALL" - #Half period added to delay measurement to negative clock edge - trig_td = targ_td = self.cycle_times[self.measure_cycles[port]["read0"]] + self.period/2 - return (meas_name,trig_name,targ_name,trig_val,targ_val,trig_dir,targ_dir,trig_td,targ_td) - - def gen_test_cycles_one_port(self, read_port, write_port): - """Sets a list of key time-points [ns] of the waveform (each rising edge) - of the cycles to do a timing evaluation of a single port """ - - # Create the inverse address for a scratch address - inverse_address = self.calculate_inverse_address() - - # For now, ignore data patterns and write ones or zeros - data_ones = "1"*self.word_size - data_zeros = "0"*self.word_size - - if self.t_current == 0: - self.add_noop_all_ports("Idle cycle (no positive clock edge)", - inverse_address, data_zeros) - - self.add_write("W data 1 address {}".format(inverse_address), - inverse_address,data_ones,write_port) - - self.add_write("W data 0 address {} to write value".format(self.probe_address), - self.probe_address,data_zeros,write_port) - self.measure_cycles[write_port]["write0"] = len(self.cycle_times)-1 - - # This also ensures we will have a H->L transition on the next read - self.add_read("R data 1 address {} to set DOUT caps".format(inverse_address), - inverse_address,data_zeros,read_port) - self.measure_cycles[read_port]["read1"] = len(self.cycle_times)-1 - - self.add_read("R data 0 address {} to check W0 worked".format(self.probe_address), - self.probe_address,data_zeros,read_port) - self.measure_cycles[read_port]["read0"] = len(self.cycle_times)-1 - - def get_data_bit_column_number(self, probe_address, probe_data): - """Calculates bitline column number of data bit under test using bit position and mux size""" - if self.sram.col_addr_size>0: - col_address = int(probe_address[0:self.sram.col_addr_size],2) - else: - col_address = 0 - bl_column = int(self.sram.words_per_row*probe_data + col_address) - return bl_column - - def run_delay_simulation(self): - """ - This tries to simulate a period and checks if the result works. If - so, it returns True and the delays, slews, and powers. It - works on the trimmed netlist by default, so powers do not - include leakage of all cells. - """ - #Sanity Check - debug.check(self.period > 0, "Target simulation period non-positive") - - result = [{} for i in self.all_ports] - # Checking from not data_value to data_value - self.write_delay_stimulus() - - self.stim.run_sim() #running sim prodoces spice output file. - - for port in self.targ_read_ports: - #Parse and check the voltage measurements - bl_volt_meas_dict = {} - for mname in self.bl_volt_meas_names: - mname_port = "{}{}".format(mname,port) - volt_meas_val = parse_spice_list("timing", mname_port) - if type(volt_meas_val)!=float: - debug.error("Failed to Parse Bitline Voltage:\n\t\t{0}={1}".format(mname,volt_meas_val),1) - bl_volt_meas_dict[mname] = volt_meas_val - result[port].update(bl_volt_meas_dict) - - #Parse and check the delay measurements. Intended that one measurement will fail, save the delay that did not fail. - bl_delay_meas_dict = {} - values_added = 0 #For error checking - for mname in self.bl_delay_meas_names: #Parse - mname_port = "{}{}".format(mname,port) - delay_meas_val = parse_spice_list("timing", mname_port) - if type(delay_meas_val)==float: #Only add if value is float, do not error. - bl_delay_meas_dict[self.bl_delay_result_name] = delay_meas_val * 1e9 #convert to ns - values_added+=1 - debug.check(values_added>0, "Bitline delay measurements failed in SPICE simulation.") - debug.check(values_added<2, "Both bitlines experienced a Vth drop, check simulation results.") - result[port].update(bl_delay_meas_dict) - - # The delay is from the negative edge for our SRAM - return (True,result) - - def check_bitline_all_results(self, results): - """Checks the bitline values measured for each tested port""" - for port in self.targ_read_ports: - self.check_bitline_port_results(results[port]) - - def check_bitline_port_results(self, port_results): - """Performs three different checks for the bitline values: functionality, bitline swing from vdd, and differential bit swing""" - bl_volt, br_volt = port_results["volt_bl"], port_results["volt_br"] - self.check_functionality(bl_volt,br_volt) - self.check_swing_from_vdd(bl_volt,br_volt) - self.check_differential_swing(bl_volt,br_volt) - - def check_functionality(self, bl_volt, br_volt): - """Checks whether the read failed or not. Measured values are hardcoded with the intention of reading a 0.""" - if bl_volt > br_volt: - debug.error("Read failure. Value 1 was read instead of 0.",1) - - def check_swing_from_vdd(self, bl_volt, br_volt): - """Checks difference on discharging bitline from VDD to see if it is within margin of the RBL height parameter.""" - if bl_volt < br_volt: - discharge_volt = bl_volt - else: - discharge_volt = br_volt - desired_bl_volt = tech.parameter["rbl_height_percentage"]*self.vdd_voltage - debug.info(1, "Active bitline={:.3f}v, Desired bitline={:.3f}v".format(discharge_volt,desired_bl_volt)) - vdd_error_margin = .2 #20% of vdd margin for bitline, a little high for now. - if abs(discharge_volt - desired_bl_volt) > vdd_error_margin*self.vdd_voltage: - debug.warning("Bitline voltage is not within {}% Vdd margin. Delay chain/RBL could need resizing.".format(vdd_error_margin*100)) - - def check_differential_swing(self, bl_volt, br_volt): - """This check looks at the difference between the bitline voltages. This needs to be large enough to prevent - sensing errors.""" - bitline_swing = abs(bl_volt-br_volt) - debug.info(1,"Bitline swing={:.3f}v".format(bitline_swing)) - vdd_error_margin = .2 #20% of vdd margin for bitline, a little high for now. - if bitline_swing < vdd_error_margin*self.vdd_voltage: - debug.warning("Bitline swing less than {}% Vdd margin. Sensing errors more likely to occur.".format(vdd_error_margin)) - - def analyze(self, probe_address, probe_data, slews, loads): - """Measures the bitline swing of the differential bitlines (bl/br) at 50% s_en """ - self.set_probe(probe_address, probe_data) - self.load=max(loads) - self.slew=max(slews) - - read_port = self.read_ports[0] #only test the first read port - bitline_swings = {} - self.targ_read_ports = [read_port] - self.targ_write_ports = [self.write_ports[0]] - debug.info(1,"Bitline swing test: corner {}".format(self.corner)) - (success, results)=self.run_delay_simulation() - debug.check(success, "Bitline Failed: period {}".format(self.period)) - debug.info(1,"Bitline values (voltages/delays):\n\t {}".format(results[read_port])) - self.check_bitline_all_results(results) - - return results - - - diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index e5a1693f..1126c0d7 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -411,8 +411,7 @@ class bank(design.design): self.bitcell_array = factory.create(module_type="bitcell_array", cols=self.num_cols, - rows=self.num_rows, - bitcell=self.bitcell) + rows=self.num_rows) self.add_mod(self.bitcell_array) self.precharge_array = [] diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 2f3fbdc3..15141bb3 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -19,14 +19,13 @@ class bitcell_array(design.design): and word line is connected by abutment. Connects the word lines and bit lines. """ - def __init__(self, cols, rows, name, bitcell): + def __init__(self, cols, rows, 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)) self.column_size = cols self.row_size = rows - self.cell = bitcell self.create_netlist() if not OPTS.netlist_only: @@ -87,6 +86,7 @@ class bitcell_array(design.design): def add_modules(self): """ Add the modules used in this design """ + self.cell = factory.create(module_type="bitcell") self.add_mod(self.cell) def create_instances(self): diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index f0bcbdc6..2a441f02 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -88,13 +88,11 @@ class replica_bitline(design.design): self.replica_bitcell = factory.create(module_type="replica_bitcell") self.add_mod(self.replica_bitcell) - - bitcell = factory.create(module_type="bitcell") + # This is the replica bitline load column that is the height of our array self.rbl = factory.create(module_type="bitcell_array", cols=1, - rows=self.bitcell_loads, - bitcell=bitcell) + rows=self.bitcell_loads) self.add_mod(self.rbl) # FIXME: The FO and depth of this should be tuned From 3f5b60856a004d97bac702fb6c8ff2490f851bdd Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Fri, 28 Jun 2019 13:49:04 -0700 Subject: [PATCH 057/234] Fixed key error with analytical delay of write ports. --- compiler/sram/sram_base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 547bc222..ff41e9f2 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -529,6 +529,7 @@ class sram_base(design, verilog, lef): elif port in self.readwrite_ports: control_logic = self.control_logic_rw else: + delays[port] = self.return_delay(0,0) #Write ports do not have a lib defined delay, marked as 0 continue clk_to_wlen_delays = control_logic.analytical_delay(corner, slew, load) wlen_to_dout_delays = self.bank.analytical_delay(corner,slew,load,port) #port should probably be specified... From 1f76afd294366a1b7661e4450c436f78c160c2fe Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 28 Jun 2019 15:43:09 -0700 Subject: [PATCH 058/234] Begin wmask functionality. Added wmask to verilog file and config parameters. --- compiler/globals.py | 17 ++++++++++++++++- compiler/modules/bank.py | 3 +++ compiler/openram.py | 3 ++- compiler/options.py | 4 ++++ compiler/sram/sram_base.py | 24 +++++++++++++++++++----- compiler/sram/sram_config.py | 8 ++++++-- 6 files changed, 50 insertions(+), 9 deletions(-) diff --git a/compiler/globals.py b/compiler/globals.py index 40daddce..4f6398e4 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -20,8 +20,8 @@ import copy import importlib USAGE = "Usage: openram.py [options] \nUse -h for help.\n" - # Anonymous object that will be the options + OPTS = options.options() CHECKPOINT_OPTS=None @@ -464,6 +464,18 @@ def report_status(): debug.error("{0} is not an integer in config file.".format(OPTS.word_size)) if type(OPTS.num_words)!=int: debug.error("{0} is not an integer in config file.".format(OPTS.sram_size)) + if type(OPTS.write_size) != int and OPTS.write_size != None: + debug.error("{0} is not an integer in config file.".format(OPTS.write_size)) + + # Determine if a write mask is specified by the user; if it's not, the mask write size should + # be the same as the word size so that an entire word is written at once + if OPTS.write_size==None: + OPTS.write_size = OPTS.word_size + + if (OPTS.write_size < 1 or OPTS.write_size > OPTS.word_size): + debug.error("Write size needs to be between 1 bit and {0} bits.".format(OPTS.word_size)) + if (OPTS.word_size % OPTS.write_size != 0): + debug.error("Write size needs to be an integer multiple of word size.") if not OPTS.tech_name: debug.error("Tech name must be specified in config file.") @@ -477,9 +489,12 @@ def report_status(): debug.print_raw("Word size: {0}\nWords: {1}\nBanks: {2}".format(OPTS.word_size, OPTS.num_words, OPTS.num_banks)) + if (OPTS.write_size != OPTS.word_size): + debug.print_raw("Write size: {}".format(OPTS.write_size)) debug.print_raw("RW ports: {0}\nR-only ports: {1}\nW-only ports: {2}".format(OPTS.num_rw_ports, OPTS.num_r_ports, OPTS.num_w_ports)) + if OPTS.netlist_only: debug.print_raw("Netlist only mode (no physical design is being done, netlist_only=False to disable).") diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 20498752..b84ad678 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -79,6 +79,9 @@ class bank(design.design): for port in self.write_ports: for bit in range(self.word_size): self.add_pin("din{0}_{1}".format(port,bit),"IN") + # if (self.word_size != self.write_size): + # for bit in range(self.word_size): + # self.add_pin() for port in self.all_ports: for bit in range(self.addr_size): self.add_pin("addr{0}_{1}".format(port,bit),"INPUT") diff --git a/compiler/openram.py b/compiler/openram.py index b939b61e..9bd3b898 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -50,7 +50,8 @@ from sram_config import sram_config # Configure the SRAM organization c = sram_config(word_size=OPTS.word_size, - num_words=OPTS.num_words) + num_words=OPTS.num_words, + write_size=OPTS.write_size) debug.print_raw("Words per row: {}".format(c.words_per_row)) #from parser import * diff --git a/compiler/options.py b/compiler/options.py index 51c541d9..354c2470 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -8,6 +8,7 @@ import optparse import getpass import os +#import sram_config class options(optparse.Values): """ @@ -28,6 +29,9 @@ class options(optparse.Values): num_rw_ports = 1 num_r_ports = 0 num_w_ports = 0 + + # Write mask size, default will be overwritten with word_size if not user specified + write_size = None # These will get initialized by the user or the tech file supply_voltages = "" diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 547bc222..931b11c4 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -68,7 +68,10 @@ class sram_base(design, verilog, lef): self.add_pin("web{}".format(port),"INPUT") for port in self.all_ports: self.add_pin("clk{}".format(port),"INPUT") - + # add the optional write mask pins + if self.word_size != self.write_size: + for port in self.write_ports: + self.add_pin("wmask{}".format(port),"INPUT") for port in self.read_ports: for bit in range(self.word_size): self.add_pin("DOUT{0}[{1}]".format(port,bit),"OUTPUT") @@ -150,9 +153,6 @@ class sram_base(design, verilog, lef): rtr.route() - - - def compute_bus_sizes(self): """ Compute the independent bus widths shared between two and four bank SRAMs """ @@ -464,8 +464,22 @@ class sram_base(design, verilog, lef): if port in self.readwrite_ports: temp.append("web{}".format(port)) temp.append("clk{}".format(port)) + # if port in self.write_ports: + # temp.append("wmask{}".format(port)) - # Ouputs + # for port in self.all_ports: + # self.add_pin("csb{}".format(port), "INPUT") + # for port in self.readwrite_ports: + # self.add_pin("web{}".format(port), "INPUT") + # for port in self.all_ports: + # self.add_pin("clk{}".format(port), "INPUT") + # # add the optional write mask pins + # if self.word_size != self.write_size: + # for port in self.write_ports: + # print("write_ports", port) + # self.add_pin("wmask{0}".format(port), "INPUT") + + # Outputs if port in self.read_ports: temp.append("s_en{}".format(port)) if port in self.write_ports: diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index d2ab5776..d74fce7a 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -14,16 +14,20 @@ from sram_factory import factory class sram_config: """ This is a structure that is used to hold the SRAM configuration options. """ - def __init__(self, word_size, num_words, num_banks=1, words_per_row=None): + def __init__(self, word_size, num_words, write_size = None, num_banks=1, words_per_row=None): self.word_size = word_size self.num_words = num_words + self.write_size = write_size self.num_banks = num_banks # This will get over-written when we determine the organization self.words_per_row = words_per_row + if OPTS.write_size == None: + OPTS.write_size = OPTS.word_size + self.compute_sizes() - + def set_local_config(self, module): """ Copy all of the member variables to the given module for convenience """ From 1fcb20f8461e73c66a6cbb85d2f2e0c4afef1617 Mon Sep 17 00:00:00 2001 From: Bin Wu Date: Sun, 30 Jun 2019 00:16:04 -0700 Subject: [PATCH 059/234] clean pex test based on feedback --- compiler/tests/26_hspice_pex_pinv_test.py | 96 ++++++++++++---------- compiler/tests/26_ngspice_pex_pinv_test.py | 91 ++++++++++---------- 2 files changed, 101 insertions(+), 86 deletions(-) diff --git a/compiler/tests/26_hspice_pex_pinv_test.py b/compiler/tests/26_hspice_pex_pinv_test.py index 60e5737c..90ce5d90 100755 --- a/compiler/tests/26_hspice_pex_pinv_test.py +++ b/compiler/tests/26_hspice_pex_pinv_test.py @@ -21,43 +21,40 @@ class hspice_pex_pinv_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) - import pinv - # generate the pinv module - OPTS.purge_temp = False - debug.info(2, "Checking 1x size inverter") - tx = pinv.pinv(name="pinv", size=1) - self.local_check(tx) - # generate its pex file - pex_file = self.run_pex(tx) - OPTS.purge_temp = True - OPTS.analytical_delay = False # load the hspice OPTS.spice_name = "hspice" OPTS.spice_exe = "hspice" - import os - from characterizer import charutils - from charutils import parse_spice_list - # setup simulation - sim_file = OPTS.openram_temp + "stim.sp" - log_file_name = "timing" - - # make sure that the library simulation is successful + # generate the pinv + prev_purge_value = OPTS.purge_temp + OPTS.purge_temp = False # force set purge to false to save the sp file + debug.info(2, "Checking 1x size inverter") + tx = pinv.pinv(name="pinv", size=1) + tempgds = "{0}{1}.gds".format(OPTS.openram_temp,tx.name) + tx.gds_write(tempgds) tempsp = "{0}{1}.sp".format(OPTS.openram_temp,tx.name) - self.write_simulaton(sim_file, tempsp, tx.name) - sp_delay = parse_spice_list(log_file_name, "pinv_delay") - assert sp_delay is not "Failed" + tx.sp_write(tempsp) + # make sure that the library simulation is successful\ + sp_delay = self.simulate_delay(test_module = tempsp, + top_level_name = tx.name) + if sp_delay is "Failed": + self.fail('Library Spice module did not behave as expected') + + # now generate its pex file + pex_file = self.run_pex(tx) + OPTS.purge_temp = prev_purge_value # restore the old purge value # generate simulation for pex, make sure the simulation is successful - self.write_simulaton(sim_file, pex_file, tx.name) - pex_delay = parse_spice_list(log_file_name, "pinv_delay") + pex_delay = self.simulate_delay(test_module = pex_file, + top_level_name = tx.name) # make sure the extracted spice simulated - assert pex_delay is not "Failed" + if pex_delay is "Failed": + self.fail('Pex file did not behave as expected') # if pex data is bigger than original spice file then result is ok - # actually this may not always be true depending on the netlist provided + # However this may not always be true depending on the netlist provided # comment out for now #debug.info(2,"pex_delay: {0}".format(pex_delay)) #debug.info(2,"sp_delay: {0}".format(sp_delay)) @@ -67,35 +64,46 @@ class hspice_pex_pinv_test(openram_test): globals.end_openram() - def write_simulaton(self, sim_file, cir_file, top_module_name): + def simulate_delay(self, test_module, top_level_name): + from characterizer import charutils + from charutils import parse_spice_list + # setup simulation + sim_file = OPTS.openram_temp + "stim.sp" + log_file_name = "timing" + test_sim = self.write_simulation(sim_file, test_module, top_level_name) + test_sim.run_sim() + delay = parse_spice_list(log_file_name, "pinv_delay") + return delay + + def write_simulation(self, sim_file, cir_file, top_module_name): """ write pex spice simulation for a pinv test""" import tech from characterizer import measurements, stimuli corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) sim_file = open(sim_file, "w") - simulaton = stimuli(sim_file,corner) + simulation = stimuli(sim_file,corner) # library files - simulaton.write_include(cir_file) + simulation.write_include(cir_file) # supply voltages - simulaton.gen_constant(sig_name ="vdd", - v_val = tech.spice["nom_supply_voltage"]) - simulaton.gen_constant(sig_name = "gnd", - v_val = "0v") + simulation.gen_constant(sig_name ="vdd", + v_val = tech.spice["nom_supply_voltage"]) + simulation.gen_constant(sig_name = "gnd", + v_val = "0v") - - run_time = tech.spice["feasible_period"] * 2 + run_time = tech.spice["feasible_period"] * 4 # input voltage - simulaton.gen_pwl(sig_name ="input", - clk_times = [1,1], - data_values = [1,0], - period=1e9, - slew=0.000002, - setup=0) + clk_period = tech.spice["feasible_period"] + simulation.gen_pwl(sig_name ="input", + clk_times = [clk_period,clk_period], + data_values = [1,0], + period = clk_period, + slew = 0.001*tech.spice["feasible_period"], + setup = 0) # instantiation of simulated pinv - simulaton.inst_model(pins = ["input", "output", "vdd", "gnd"], + simulation.inst_model(pins = ["input", "output", "vdd", "gnd"], model_name = top_module_name) # delay measurement @@ -106,11 +114,11 @@ class hspice_pex_pinv_test(openram_test): targ_dir_str = "RISE") trig_td = trag_td = 0.01 * run_time rest_info = trig_td,trag_td,tech.spice["nom_supply_voltage"] - delay_measure.write_measure(simulaton, rest_info) + delay_measure.write_measure(simulation, rest_info) - simulaton.write_control(end_time = run_time) + simulation.write_control(end_time = run_time) sim_file.close() - simulaton.run_sim() + return simulation # run the test from the command line diff --git a/compiler/tests/26_ngspice_pex_pinv_test.py b/compiler/tests/26_ngspice_pex_pinv_test.py index 12f71632..42181630 100755 --- a/compiler/tests/26_ngspice_pex_pinv_test.py +++ b/compiler/tests/26_ngspice_pex_pinv_test.py @@ -18,46 +18,42 @@ import debug class ngspice_pex_pinv_test(openram_test): - def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) - import pinv - # generate the pinv module - OPTS.purge_temp = False - debug.info(2, "Checking 1x size inverter") - tx = pinv.pinv(name="pinv", size=1) - self.local_check(tx) - # generate its pex file - pex_file = self.run_pex(tx) - OPTS.purge_temp = True - OPTS.analytical_delay = False - # load the ngspice + # load the hspice OPTS.spice_name = "ngspice" OPTS.spice_exe = "ngspice" - import os - from characterizer import charutils - from charutils import parse_spice_list - # setup simulaton - sim_file = OPTS.openram_temp + "stim.sp" - log_file_name = "timing" + # generate the pinv module + prev_purge_value = OPTS.purge_temp + OPTS.purge_temp = False # force set purge to false to save the sp file + debug.info(2, "Checking 1x size inverter") + tx = pinv.pinv(name="pinv", size=1) + tempgds = "{0}{1}.gds".format(OPTS.openram_temp,tx.name) + tx.gds_write(tempgds) + tempsp = "{0}{1}.sp".format(OPTS.openram_temp,tx.name) + tx.sp_write(tempsp) # make sure that the library simulation is successful - tempsp = "{0}{1}.sp".format(OPTS.openram_temp,tx.name) - self.write_simulaton(sim_file, tempsp, tx.name) - sp_delay = parse_spice_list(log_file_name, "pinv_delay") - assert sp_delay is not "Failed" + sp_delay = self.simulate_delay(test_module = tempsp, + top_level_name = tx.name) + if sp_delay is "Failed": + self.fail('Library Spice module did not behave as expected') + # now generate its pex file + pex_file = self.run_pex(tx) + OPTS.purge_temp = prev_purge_value # restore the old purge value # generate simulation for pex, make sure the simulation is successful - self.write_simulaton(sim_file, pex_file, tx.name) - pex_delay = parse_spice_list(log_file_name, "pinv_delay") + pex_delay = self.simulate_delay(test_module = pex_file, + top_level_name = tx.name) # make sure the extracted spice simulated - assert pex_delay is not "Failed" + if pex_delay is "Failed": + self.fail('Pex file did not behave as expected') # if pex data is bigger than original spice file then result is ok - # actually this may not always be true depending on the netlist provided + # However this may not always be true depending on the netlist provided # comment out for now #debug.info(2,"pex_delay: {0}".format(pex_delay)) #debug.info(2,"sp_delay: {0}".format(sp_delay)) @@ -67,38 +63,50 @@ class ngspice_pex_pinv_test(openram_test): globals.end_openram() - def write_simulaton(self, sim_file, cir_file, top_module_name): + def simulate_delay(self, test_module, top_level_name): + from characterizer import charutils + from charutils import parse_spice_list + # setup simulation + sim_file = OPTS.openram_temp + "stim.sp" + log_file_name = "timing" + test_sim = self.write_simulation(sim_file, test_module, top_level_name) + test_sim.run_sim() + delay = parse_spice_list(log_file_name, "pinv_delay") + return delay + + def write_simulation(self, sim_file, cir_file, top_module_name): """ write pex spice simulation for a pinv test""" import tech from characterizer import measurements, stimuli corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) sim_file = open(sim_file, "w") - simulaton = stimuli(sim_file,corner) + simulation = stimuli(sim_file,corner) # library files - simulaton.write_include(cir_file) + simulation.write_include(cir_file) # supply voltages - simulaton.gen_constant(sig_name ="vdd", + simulation.gen_constant(sig_name ="vdd", v_val = tech.spice["nom_supply_voltage"]) # The scn4m_subm and ngspice combination will have a gnd source error: # "Fatal error: instance vgnd is a shorted VSRC" # However, remove gnd power for all techa pass for this test - # simulaton.gen_constant(sig_name = "gnd", + # simulation.gen_constant(sig_name = "gnd", # v_val = "0v") - run_time = tech.spice["feasible_period"] * 2 + run_time = tech.spice["feasible_period"] * 4 # input voltage - simulaton.gen_pwl(sig_name ="input", - clk_times = [1,1], + clk_period = tech.spice["feasible_period"] + simulation.gen_pwl(sig_name ="input", + clk_times = [clk_period,clk_period], data_values = [1,0], - period=1e9, - slew=0.000002, - setup=0) + period = clk_period, + slew = 0.001*tech.spice["feasible_period"], + setup = 0) # instantiation of simulated pinv - simulaton.inst_model(pins = ["input", "output", "vdd", "gnd"], + simulation.inst_model(pins = ["input", "output", "vdd", "gnd"], model_name = top_module_name) # delay measurement @@ -109,12 +117,11 @@ class ngspice_pex_pinv_test(openram_test): targ_dir_str = "RISE") trig_td = trag_td = 0.01 * run_time rest_info = trig_td,trag_td,tech.spice["nom_supply_voltage"] - delay_measure.write_measure(simulaton, rest_info) + delay_measure.write_measure(simulation, rest_info) - simulaton.write_control(end_time = run_time) + simulation.write_control(end_time = run_time) sim_file.close() - simulaton.run_sim() - + return simulation # run the test from the command line if __name__ == "__main__": From 67c6cdf3bbddfd3ab16e56339cde955ad8c04663 Mon Sep 17 00:00:00 2001 From: jsowash Date: Mon, 1 Jul 2019 15:51:40 -0700 Subject: [PATCH 060/234] Fixed error where word_size was compared to num_words and added write_size to control_logic.py --- compiler/modules/control_logic.py | 9 +++++++-- compiler/sram/sram.py | 5 +---- compiler/sram/sram_base.py | 3 +++ compiler/sram/sram_config.py | 4 ++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 74fb86c5..7b863b7a 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -21,7 +21,7 @@ class control_logic(design.design): Dynamically generated Control logic for the total SRAM circuit. """ - def __init__(self, num_rows, words_per_row, word_size, sram=None, port_type="rw", name=""): + def __init__(self, num_rows, words_per_row, word_size, write_size, sram=None, port_type="rw", name=""): """ Constructor """ name = "control_logic_" + port_type design.design.__init__(self, name) @@ -35,6 +35,7 @@ class control_logic(design.design): self.words_per_row = words_per_row self.word_size = word_size self.port_type = port_type + self.write_size = write_size self.num_cols = word_size*words_per_row self.num_words = num_rows*words_per_row @@ -314,7 +315,11 @@ class control_logic(design.design): self.input_list = ["csb", "web"] else: self.input_list = ["csb"] - + + if self.word_size != self.write_size: + print(self.word_size, self.write_size) + self.input_list = ["wmask"] + if self.port_type == "rw": self.dff_output_list = ["cs_bar", "cs", "we_bar", "we"] else: diff --git a/compiler/sram/sram.py b/compiler/sram/sram.py index f7c1111c..5e7ac08a 100644 --- a/compiler/sram/sram.py +++ b/compiler/sram/sram.py @@ -34,7 +34,6 @@ class sram(): start_time = datetime.datetime.now() self.name = name - if self.num_banks == 1: from sram_1bank import sram_1bank as sram @@ -84,8 +83,6 @@ class sram(): self.gds_write(gdsname) print_time("GDS", datetime.datetime.now(), start_time) - - # Save the spice file start_time = datetime.datetime.now() spname = OPTS.output_path + self.s.name + ".sp" @@ -133,4 +130,4 @@ class sram(): vname = OPTS.output_path + self.s.name + ".v" debug.print_raw("Verilog: Writing to {0}".format(vname)) self.verilog_write(vname) - print_time("Verilog", datetime.datetime.now(), start_time) + print_time("Verilog", datetime.datetime.now(), start_time) \ No newline at end of file diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index d5b56242..934869d8 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -303,6 +303,7 @@ class sram_base(design, verilog, lef): self.control_logic_rw = self.mod_control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, word_size=self.word_size, + write_size = self.write_size, sram=self, port_type="rw") self.add_mod(self.control_logic_rw) @@ -310,6 +311,7 @@ class sram_base(design, verilog, lef): self.control_logic_w = self.mod_control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, word_size=self.word_size, + write_size=self.write_size, sram=self, port_type="w") self.add_mod(self.control_logic_w) @@ -317,6 +319,7 @@ class sram_base(design, verilog, lef): self.control_logic_r = self.mod_control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, word_size=self.word_size, + write_size=self.write_size, sram=self, port_type="r") self.add_mod(self.control_logic_r) diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index d74fce7a..af841ebf 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -23,8 +23,8 @@ class sram_config: # This will get over-written when we determine the organization self.words_per_row = words_per_row - if OPTS.write_size == None: - OPTS.write_size = OPTS.word_size + if self.write_size == None: + self.write_size = self.word_size self.compute_sizes() From 2abe859df1ca8ba54c7fa0a0e668a727d23cea97 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 1 Jul 2019 16:29:59 -0700 Subject: [PATCH 061/234] Fix shared bank offset. --- compiler/modules/bank.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 23bb28ae..6c4a45a8 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -192,10 +192,21 @@ class bank(design.design): self.column_decoder_offsets = [None]*len(self.all_ports) self.bank_select_offsets = [None]*len(self.all_ports) + + + # The center point for these cells are the upper-right corner of + # the bitcell array. + # The decoder/driver logic is placed on the right and mirrored on Y-axis. + # The write/sense/precharge/mux is placed on the top and mirrored on the X-axis. + + self.bitcell_array_top = self.bitcell_array.height + self.m2_gap + drc("well_enclosure_active") + self.m1_width + self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap self.compute_instance_port0_offsets() if len(self.all_ports)==2: self.compute_instance_port1_offsets() + else: + debug.error("Too many ports.", -1) def compute_instance_port0_offsets(self): @@ -266,19 +277,12 @@ class bank(design.design): port=1 - # The center point for these cells are the upper-right corner of - # the bitcell array. - # The decoder/driver logic is placed on the right and mirrored on Y-axis. - # The write/sense/precharge/mux is placed on the top and mirrored on the X-axis. - - bitcell_array_top = self.bitcell_array.height + self.m2_gap + drc("well_enclosure_active") + self.m1_width - bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap # LOWER LEFT QUADRANT # Bitcell array is placed at (0,0) # UPPER LEFT QUADRANT # Above the bitcell array - y_offset = bitcell_array_top + y_offset = self.bitcell_array_top for i,p in enumerate(self.vertical_port_order[port]): if p==None: continue @@ -294,7 +298,7 @@ class bank(design.design): # LOWER RIGHT QUADRANT # To the left of the bitcell array # The wordline driver is placed to the right of the main decoder width. - x_offset = bitcell_array_right + self.wordline_driver.width + x_offset = self.bitcell_array_right + self.wordline_driver.width self.wordline_driver_offsets[port] = vector(x_offset,0) x_offset += self.row_decoder.width + self.m2_gap self.row_decoder_offsets[port] = vector(x_offset,0) @@ -302,12 +306,12 @@ class bank(design.design): # UPPER RIGHT QUADRANT # Place the col decoder right aligned with wordline driver plus halfway under row decoder # Above the bitcell array with a well spacing - x_offset = bitcell_array_right + self.central_bus_width[port] + self.wordline_driver.width + x_offset = self.bitcell_array_right + self.central_bus_width[port] + self.wordline_driver.width if self.col_addr_size > 0: x_offset += self.column_decoder.width + self.col_addr_bus_width - y_offset = bitcell_array_height + self.column_decoder.height + y_offset = self.bitcell_array_top + self.column_decoder.height else: - y_offset = bitcell_array_height + y_offset = self.bitcell_array_top y_offset += 2*drc("well_to_well") self.column_decoder_offsets[port] = vector(x_offset,y_offset) @@ -862,8 +866,8 @@ class bank(design.design): # Port 1 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 - bitcell_array_top - 2*self.m1_pitch - control_bus_offset = vector(bitcell_array_right, + control_bus_length = self.max_y_offset - self.bitcell_array_top - 2*self.m1_pitch + control_bus_offset = vector(self.bitcell_array_right, self.max_y_offset - control_bus_length) self.bus_xoffset[1] = self.create_bus(layer="metal2", From 244604fb0d2840182fac53c5706b23df2f5672f3 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 2 Jul 2019 15:35:53 -0700 Subject: [PATCH 062/234] Data port module working by itself. --- compiler/modules/bank.py | 2 - compiler/modules/port_data.py | 452 ++++++++++++++++++++++++++++ compiler/tests/18_port_data_test.py | 112 +++++++ 3 files changed, 564 insertions(+), 2 deletions(-) create mode 100644 compiler/modules/port_data.py create mode 100755 compiler/tests/18_port_data_test.py diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 6c4a45a8..de9f2ee7 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -205,8 +205,6 @@ class bank(design.design): self.compute_instance_port0_offsets() if len(self.all_ports)==2: self.compute_instance_port1_offsets() - else: - debug.error("Too many ports.", -1) def compute_instance_port0_offsets(self): diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py new file mode 100644 index 00000000..0baafba0 --- /dev/null +++ b/compiler/modules/port_data.py @@ -0,0 +1,452 @@ +# 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 sys +from tech import drc, parameter +import debug +import design +from sram_factory import factory +from vector import vector + +from globals import OPTS + +class port_data(design.design): + """ + Create the data port (column mux, sense amps, write driver, etc.) + """ + + def __init__(self, sram_config, port, name=""): + + sram_config.set_local_config(self) + self.port = port + + if name == "": + name = "bank_{0}_{1}".format(self.word_size, self.num_words) + design.design.__init__(self, name) + debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words)) + + self.create_netlist() + if not OPTS.netlist_only: + debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.") + self.create_layout() + self.add_boundary() + + + def create_netlist(self): + self.compute_sizes() + self.add_pins() + self.add_modules() + self.create_instances() + + def create_instances(self): + if self.precharge_array: + self.create_precharge_array() + else: + self.precharge_array_inst = None + + if self.sense_amp_array: + self.create_sense_amp_array() + else: + self.sense_amp_array_inst = None + + if self.write_driver_array: + self.create_write_driver_array() + else: + self.write_driver_array_inst = None + + if self.column_mux_array: + self.create_column_mux_array() + else: + self.column_mux_array_inst = None + + + + def create_layout(self): + self.compute_instance_offsets() + self.place_instances() + self.route_layout() + self.DRC_LVS() + + def add_pins(self): + """ Adding pins for Bank module""" + if self.port in self.read_ports: + for bit in range(self.word_size): + self.add_pin("dout{0}_{1}".format(self.port,bit),"OUT") + if self.port in self.write_ports: + for bit in range(self.word_size): + self.add_pin("din{0}_{1}".format(self.port,bit),"IN") + + if self.port in self.read_ports: + self.add_pin("s_en{0}".format(self.port), "INPUT") + if self.port in self.read_ports: + self.add_pin("p_en_bar{0}".format(self.port), "INPUT") + if self.port in self.write_ports: + self.add_pin("w_en{0}".format(self.port), "INPUT") + self.add_pin("vdd","POWER") + self.add_pin("gnd","GROUND") + + + def route_layout(self): + """ Create routing amoung the modules """ + self.route_bitlines() + self.route_supplies() + + def route_bitlines(self): + """ Route the bitlines depending on the port type rw, w, or r. """ + + if self.port in self.readwrite_ports: + # write_driver -> sense_amp -> (column_mux) -> precharge -> bitcell_array + self.route_write_driver_in(self.port) + self.route_sense_amp_out(self.port) + self.route_write_driver_to_sense_amp(self.port) + self.route_sense_amp_to_column_mux_or_precharge_array(self.port) + self.route_column_mux_to_precharge_array(self.port) + elif self.port in self.read_ports: + # sense_amp -> (column_mux) -> precharge -> bitcell_array + self.route_sense_amp_out(self.port) + self.route_sense_amp_to_column_mux_or_precharge_array(self.port) + self.route_column_mux_to_precharge_array(self.port) + else: + # write_driver -> (column_mux) -> bitcell_array + self.route_write_driver_in(self.port) + self.route_write_driver_to_column_mux_or_bitcell_array(self.port) + + def route_supplies(self): + """ Propagate all vdd/gnd pins up to this level for all modules """ + for inst in self.insts: + self.copy_power_pins(inst,"vdd") + self.copy_power_pins(inst,"gnd") + + def add_modules(self): + + if self.port in self.read_ports: + self.precharge_array = factory.create(module_type="precharge_array", + columns=self.num_cols, + bitcell_bl=self.bl_names[self.port], + bitcell_br=self.br_names[self.port]) + self.add_mod(self.precharge_array) + + self.sense_amp_array = factory.create(module_type="sense_amp_array", + word_size=self.word_size, + words_per_row=self.words_per_row) + self.add_mod(self.sense_amp_array) + else: + self.precharge_array = None + self.sense_amp_array = None + + if self.col_addr_size > 0: + self.column_mux_array = factory.create(module_type="column_mux_array", + columns=self.num_cols, + word_size=self.word_size, + bitcell_bl=self.bl_names[self.port], + bitcell_br=self.br_names[self.port]) + self.add_mod(self.column_mux_array) + else: + self.column_mux_array = None + + + if self.port in self.write_ports or self.port in self.readwrite_ports: + self.write_driver_array = factory.create(module_type="write_driver_array", + columns=self.num_cols, + word_size=self.word_size) + self.add_mod(self.write_driver_array) + else: + self.write_driver_array = None + + + def compute_sizes(self): + """ Computes the required sizes to create the bank """ + + self.num_cols = int(self.words_per_row*self.word_size) + self.num_rows = int(self.num_words / self.words_per_row) + + # A space for wells or jogging m2 between modules + self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclosure_active"), + 3*self.m2_pitch) + + + # create arrays of bitline and bitline_bar names for read, write, or all ports + self.bitcell = factory.create(module_type="bitcell") + self.bl_names = self.bitcell.list_all_bl_names() + self.br_names = self.bitcell.list_all_br_names() + self.wl_names = self.bitcell.list_all_wl_names() + self.bitline_names = self.bitcell.list_all_bitline_names() + + def create_precharge_array(self): + """ Creating Precharge """ + if not self.precharge_array: + self.precharge_array_inst = None + return + + self.precharge_array_inst = self.add_inst(name="precharge_array{}".format(self.port), + mod=self.precharge_array) + temp = [] + for i in range(self.num_cols): + temp.append(self.bl_names[self.port]+"_{0}".format(i)) + temp.append(self.br_names[self.port]+"_{0}".format(i)) + temp.extend(["p_en_bar{0}".format(self.port), "vdd"]) + self.connect_inst(temp) + + + def place_precharge_array(self, offset): + """ Placing Precharge """ + self.precharge_array_inst.place(offset=offset, mirror="MX") + + + def create_column_mux_array(self): + """ Creating Column Mux when words_per_row > 1 . """ + self.column_mux_array_inst = self.add_inst(name="column_mux_array{}".format(self.port), + mod=self.column_mux_array) + + temp = [] + for col in range(self.num_cols): + temp.append(self.bl_names[self.port]+"_{0}".format(col)) + temp.append(self.br_names[self.port]+"_{0}".format(col)) + for word in range(self.words_per_row): + temp.append("sel{0}_{1}".format(self.port,word)) + for bit in range(self.word_size): + temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) + temp.append("gnd") + self.connect_inst(temp) + + + + def place_column_mux_array(self, offset): + """ Placing Column Mux when words_per_row > 1 . """ + if self.col_addr_size == 0: + return + + self.column_mux_array_inst.place(offset=offset, mirror="MX") + + + def create_sense_amp_array(self): + """ Creating Sense amp """ + self.sense_amp_array_inst = self.add_inst(name="sense_amp_array{}".format(self.port), + mod=self.sense_amp_array) + + temp = [] + for bit in range(self.word_size): + temp.append("dout{0}_{1}".format(self.port,bit)) + if self.words_per_row == 1: + temp.append(self.bl_names[self.port]+"_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_{0}".format(bit)) + else: + temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) + + temp.extend(["s_en{}".format(self.port), "vdd", "gnd"]) + self.connect_inst(temp) + + + def place_sense_amp_array(self, offset): + """ Placing Sense amp """ + self.sense_amp_array_inst.place(offset=offset, mirror="MX") + + + def create_write_driver_array(self): + """ Creating Write Driver """ + self.write_driver_array_inst = self.add_inst(name="write_driver_array{}".format(self.port), + mod=self.write_driver_array) + + temp = [] + for bit in range(self.word_size): + temp.append("din{0}_{1}".format(self.port,bit)) + for bit in range(self.word_size): + if (self.words_per_row == 1): + temp.append(self.bl_names[self.port]+"_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_{0}".format(bit)) + else: + temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) + temp.extend(["w_en{0}".format(self.port), "vdd", "gnd"]) + self.connect_inst(temp) + + + def place_write_driver_array(self, offset): + """ Placing Write Driver """ + self.write_driver_array_inst.place(offset=offset, mirror="MX") + + + def compute_instance_offsets(self): + """ + Compute the empty instance offsets for port0 and port1 (if needed) + """ + + vertical_port_order = [] + vertical_port_order.append(self.precharge_array_inst) + vertical_port_order.append(self.column_mux_array_inst) + vertical_port_order.append(self.sense_amp_array_inst) + vertical_port_order.append(self.write_driver_array_inst) + + vertical_port_offsets = 4*[None] + self.width = 0 + self.height = 0 + for i,p in enumerate(vertical_port_order): + if p==None: + continue + self.height += (p.height + self.m2_gap) + self.width = max(self.width, p.width) + vertical_port_offsets[i]=vector(0,self.height) + + # Reversed order + self.write_driver_offset = vertical_port_offsets[3] + self.sense_amp_offset = vertical_port_offsets[2] + self.column_mux_offset = vertical_port_offsets[1] + self.precharge_offset = vertical_port_offsets[0] + + + + def place_instances(self): + """ Place the instances. """ + + # These are fixed in the order: write driver, sense amp, clumn mux, precharge, + # even if the item is not used in a given port (it will be None then) + if self.write_driver_offset: + self.place_write_driver_array(self.write_driver_offset) + if self.sense_amp_offset: + self.place_sense_amp_array(self.sense_amp_offset) + if self.precharge_offset: + self.place_precharge_array(self.precharge_offset) + if self.column_mux_offset: + self.place_column_mux_array(self.column_mux_offset) + + def route_sense_amp_out(self, port): + """ Add pins for the sense amp output """ + + for bit in range(self.word_size): + data_pin = self.sense_amp_array_inst.get_pin("data_{}".format(bit)) + self.add_layout_pin_rect_center(text="dout{0}_{1}".format(port,bit), + layer=data_pin.layer, + offset=data_pin.center(), + height=data_pin.height(), + width=data_pin.width()) + + def route_write_driver_in(self, port): + """ Connecting write driver """ + + for row in range(self.word_size): + data_name = "data_{}".format(row) + din_name = "din{0}_{1}".format(self.port,row) + self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name) + + def route_column_mux_to_precharge_array(self, port): + """ Routing of BL and BR between col mux and precharge array """ + + # Only do this if we have a column mux! + if self.col_addr_size==0: + return + + inst1 = self.column_mux_array_inst + inst2 = self.precharge_array_inst + self.connect_bitlines(inst1, inst2, self.num_cols) + + + + def route_sense_amp_to_column_mux_or_precharge_array(self, port): + """ Routing of BL and BR between sense_amp and column mux or precharge array """ + inst2 = self.sense_amp_array_inst + + if self.col_addr_size>0: + # Sense amp is connected to the col mux + inst1 = self.column_mux_array_inst + inst1_bl_name = "bl_out_{}" + inst1_br_name = "br_out_{}" + else: + # Sense amp is directly connected to the precharge array + inst1 = self.precharge_array_inst + inst1_bl_name = "bl_{}" + inst1_br_name = "br_{}" + + self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, + inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) + + def route_write_driver_to_column_mux_or_bitcell_array(self, port): + """ Routing of BL and BR between sense_amp and column mux or bitcell array """ + inst2 = self.write_driver_array_inst + + if self.col_addr_size>0: + # Write driver is connected to the col mux + inst1 = self.column_mux_array_inst + inst1_bl_name = "bl_out_{}" + inst1_br_name = "br_out_{}" + else: + # Write driver is directly connected to the bitcell array + return + + self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, + inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) + + def route_write_driver_to_sense_amp(self, port): + """ Routing of BL and BR between write driver and sense amp """ + + inst1 = self.write_driver_array_inst + inst2 = self.sense_amp_array_inst + + # These should be pitch matched in the cell library, + # but just in case, do a channel route. + self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size) + + + def channel_route_bitlines(self, inst1, inst2, num_bits, + inst1_bl_name="bl_{}", inst1_br_name="br_{}", + inst2_bl_name="bl_{}", inst2_br_name="br_{}"): + """ + Route the bl and br of two modules using the channel router. + """ + + # determine top and bottom automatically. + # since they don't overlap, we can just check the bottom y coordinate. + if inst1.by() < inst2.by(): + (bottom_inst, bottom_bl_name, bottom_br_name) = (inst1, inst1_bl_name, inst1_br_name) + (top_inst, top_bl_name, top_br_name) = (inst2, inst2_bl_name, inst2_br_name) + else: + (bottom_inst, bottom_bl_name, bottom_br_name) = (inst2, inst2_bl_name, inst2_br_name) + (top_inst, top_bl_name, top_br_name) = (inst1, inst1_bl_name, inst1_br_name) + + + # Channel route each mux separately since we don't minimize the number + # of tracks in teh channel router yet. If we did, we could route all the bits at once! + offset = bottom_inst.ul() + vector(0,self.m1_pitch) + for bit in range(num_bits): + bottom_names = [bottom_inst.get_pin(bottom_bl_name.format(bit)), bottom_inst.get_pin(bottom_br_name.format(bit))] + top_names = [top_inst.get_pin(top_bl_name.format(bit)), top_inst.get_pin(top_br_name.format(bit))] + route_map = list(zip(bottom_names, top_names)) + self.create_horizontal_channel_route(route_map, offset) + + + def connect_bitlines(self, inst1, inst2, num_bits, + inst1_bl_name="bl_{}", inst1_br_name="br_{}", + inst2_bl_name="bl_{}", inst2_br_name="br_{}"): + """ + Connect the bl and br of two modules. + This assumes that they have sufficient space to create a jog + in the middle between the two modules (if needed). + """ + + # determine top and bottom automatically. + # since they don't overlap, we can just check the bottom y coordinate. + if inst1.by() < inst2.by(): + (bottom_inst, bottom_bl_name, bottom_br_name) = (inst1, inst1_bl_name, inst1_br_name) + (top_inst, top_bl_name, top_br_name) = (inst2, inst2_bl_name, inst2_br_name) + else: + (bottom_inst, bottom_bl_name, bottom_br_name) = (inst2, inst2_bl_name, inst2_br_name) + (top_inst, top_bl_name, top_br_name) = (inst1, inst1_bl_name, inst1_br_name) + + for col in range(num_bits): + bottom_bl = bottom_inst.get_pin(bottom_bl_name.format(col)).uc() + bottom_br = bottom_inst.get_pin(bottom_br_name.format(col)).uc() + top_bl = top_inst.get_pin(top_bl_name.format(col)).bc() + top_br = top_inst.get_pin(top_br_name.format(col)).bc() + + yoffset = 0.5*(top_bl.y+bottom_bl.y) + self.add_path("metal2",[bottom_bl, vector(bottom_bl.x,yoffset), + vector(top_bl.x,yoffset), top_bl]) + self.add_path("metal2",[bottom_br, vector(bottom_br.x,yoffset), + vector(top_br.x,yoffset), top_br]) + + diff --git a/compiler/tests/18_port_data_test.py b/compiler/tests/18_port_data_test.py new file mode 100755 index 00000000..7bd5837d --- /dev/null +++ b/compiler/tests/18_port_data_test.py @@ -0,0 +1,112 @@ +#!/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 port_data_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + from sram_config import sram_config + + c = sram_config(word_size=4, + num_words=16) + + c.words_per_row=1 + factory.reset() + c.recompute_sizes() + debug.info(1, "No column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + + c.num_words=32 + c.words_per_row=2 + factory.reset() + c.recompute_sizes() + debug.info(1, "Two way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + + c.num_words=64 + c.words_per_row=4 + factory.reset() + c.recompute_sizes() + debug.info(1, "Four way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + + c.word_size=2 + c.num_words=128 + c.words_per_row=8 + factory.reset() + c.recompute_sizes() + debug.info(1, "Eight way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + + OPTS.bitcell = "bitcell_1w_1r" + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 0 + + c.num_words=16 + c.words_per_row=1 + factory.reset() + c.recompute_sizes() + debug.info(1, "No column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + a = factory.create("port_data", sram_config=c, port=1) + self.local_check(a) + + c.num_words=32 + c.words_per_row=2 + factory.reset() + c.recompute_sizes() + debug.info(1, "Two way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + a = factory.create("port_data", sram_config=c, port=1) + self.local_check(a) + + c.num_words=64 + c.words_per_row=4 + factory.reset() + c.recompute_sizes() + debug.info(1, "Four way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + a = factory.create("port_data", sram_config=c, port=1) + self.local_check(a) + + c.word_size=2 + c.num_words=128 + c.words_per_row=8 + factory.reset() + c.recompute_sizes() + debug.info(1, "Eight way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + a = factory.create("port_data", sram_config=c, port=1) + 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 474ac67af5bcd910217e603fe9aec503a43c9061 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 3 Jul 2019 10:14:15 -0700 Subject: [PATCH 063/234] Added optional write_size and wmask. --- compiler/characterizer/simulation.py | 5 ++++- compiler/modules/control_logic.py | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 83d367b0..c5e26da1 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -24,6 +24,7 @@ class simulation(): self.name = self.sram.name self.word_size = self.sram.word_size self.addr_size = self.sram.addr_size + self.write_size = self.sram.write_size self.num_cols = self.sram.num_cols self.num_rows = self.sram.num_rows self.num_banks = self.sram.num_banks @@ -266,7 +267,9 @@ class simulation(): for port in range(total_ports): if (port in read_index) and (port in write_index): pin_names.append("WEB{0}".format(port)) - + if (self.write_size != self.word_size): + pin_names.append("WMASK{0}".format(port)) + for port in range(total_ports): pin_names.append("{0}{1}".format(tech.spice["clk"], port)) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 7b863b7a..fa269e26 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -75,6 +75,7 @@ class control_logic(design.design): def add_pins(self): """ Add the pins to the control logic module. """ for pin in self.input_list + ["clk"]: + print(pin) self.add_pin(pin,"INPUT") for pin in self.output_list: self.add_pin(pin,"OUTPUT") From bc4a3ee2b7f6414e7e203999f972dfc634e3ce02 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 3 Jul 2019 13:17:12 -0700 Subject: [PATCH 064/234] New port_data module works in SCMOS --- compiler/modules/bank.py | 434 ++++-------------- compiler/modules/port_data.py | 85 +++- compiler/pgates/ptx.py | 2 +- compiler/sram/sram_1bank.py | 97 ++-- compiler/sram/sram_base.py | 3 + .../tests/05_replica_bitcell_array_test.py | 1 + compiler/tests/19_single_bank_1w_1r_test.py | 71 +++ 7 files changed, 276 insertions(+), 417 deletions(-) create mode 100755 compiler/tests/19_single_bank_1w_1r_test.py diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index de9f2ee7..f1b7a772 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -28,6 +28,7 @@ class bank(design.design): def __init__(self, sram_config, name=""): + self.sram_config = sram_config sram_config.set_local_config(self) if name == "": @@ -117,41 +118,22 @@ class bank(design.design): def route_bitlines(self, port): """ Route the bitlines depending on the port type rw, w, or r. """ + + if port in self.write_ports: + self.route_port_data_in(port) + if port in self.read_ports: + self.route_port_data_out(port) + self.route_port_data_to_bitcell_array(port) - if port in self.readwrite_ports: - # write_driver -> sense_amp -> (column_mux) -> precharge -> bitcell_array - self.route_write_driver_in(port) - self.route_sense_amp_out(port) - self.route_write_driver_to_sense_amp(port) - self.route_sense_amp_to_column_mux_or_precharge_array(port) - self.route_column_mux_to_precharge_array(port) - self.route_precharge_to_bitcell_array(port) - elif port in self.read_ports: - # sense_amp -> (column_mux) -> precharge -> bitcell_array - self.route_sense_amp_out(port) - self.route_sense_amp_to_column_mux_or_precharge_array(port) - self.route_column_mux_to_precharge_array(port) - self.route_precharge_to_bitcell_array(port) - else: - # write_driver -> (column_mux) -> bitcell_array - self.route_write_driver_in(port) - self.route_write_driver_to_column_mux_or_bitcell_array(port) - self.route_column_mux_to_bitcell_array(port) def create_instances(self): """ Create the instances of the netlist. """ self.create_bitcell_array() - - self.create_precharge_array() - self.create_column_mux_array() - self.create_sense_amp_array() - self.create_write_driver_array() - + self.create_port_data() self.create_row_decoder() self.create_wordline_driver() self.create_column_decoder() - self.create_bank_select() def compute_instance_offsets(self): @@ -159,34 +141,7 @@ class bank(design.design): Compute the empty instance offsets for port0 and port1 (if needed) """ - # These are created even if the port type (e.g. read only) - # doesn't need the instance (e.g. write driver). - - # Create the bottom-up and left to right order of components in each port - # which deepends on the port type rw, w, r - self.vertical_port_order = [] - self.vertical_port_offsets = [] - for port in self.all_ports: - self.vertical_port_order.append([]) - self.vertical_port_offsets.append([None]*4) - - # For later placement, these are fixed in the order: write driver, - # sense amp, clumn mux, precharge, even if the item is not used - # in a given port (it will be None then) - self.vertical_port_order[port].append(self.write_driver_array_inst[port]) - self.vertical_port_order[port].append(self.sense_amp_array_inst[port]) - self.vertical_port_order[port].append(self.column_mux_array_inst[port]) - self.vertical_port_order[port].append(self.precharge_array_inst[port]) - - # For the odd ones they will go on top, so reverse in place - if port%2: - self.vertical_port_order[port]=self.vertical_port_order[port][::-1] - - self.write_driver_offsets = [None]*len(self.all_ports) - self.sense_amp_offsets = [None]*len(self.all_ports) - self.column_mux_offsets = [None]*len(self.all_ports) - self.precharge_offsets = [None]*len(self.all_ports) - + self.port_data_offsets = [None]*len(self.all_ports) self.wordline_driver_offsets = [None]*len(self.all_ports) self.row_decoder_offsets = [None]*len(self.all_ports) @@ -199,7 +154,7 @@ class bank(design.design): # The decoder/driver logic is placed on the right and mirrored on Y-axis. # The write/sense/precharge/mux is placed on the top and mirrored on the X-axis. - self.bitcell_array_top = self.bitcell_array.height + self.m2_gap + drc("well_enclosure_active") + self.m1_width + self.bitcell_array_top = self.bitcell_array.height self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap self.compute_instance_port0_offsets() @@ -220,23 +175,7 @@ class bank(design.design): # LOWER RIGHT QUADRANT # Below the bitcell array - y_height = 0 - for p in self.vertical_port_order[port]: - if p==None: - continue - y_height += p.height + self.m2_gap - - y_offset = -y_height - for i,p in enumerate(self.vertical_port_order[port]): - if p==None: - continue - self.vertical_port_offsets[port][i]=vector(0,y_offset) - y_offset += (p.height + self.m2_gap) - - self.write_driver_offsets[port] = self.vertical_port_offsets[port][0] - self.sense_amp_offsets[port] = self.vertical_port_offsets[port][1] - self.column_mux_offsets[port] = self.vertical_port_offsets[port][2] - self.precharge_offsets[port] = self.vertical_port_offsets[port][3] + self.port_data_offsets[port] = vector(0,0) # UPPER LEFT QUADRANT # To the left of the bitcell array @@ -261,7 +200,7 @@ class bank(design.design): # Bank select gets placed below the column decoder (x_offset doesn't change) if self.col_addr_size > 0: - y_offset = min(self.column_decoder_offsets[port].y, self.column_mux_offsets[port].y) + y_offset = min(self.column_decoder_offsets[port].y, self.port_data[port].column_mux_offset.y) else: y_offset = self.row_decoder_offsets[port].y if self.num_banks > 1: @@ -280,18 +219,7 @@ class bank(design.design): # UPPER LEFT QUADRANT # Above the bitcell array - y_offset = self.bitcell_array_top - for i,p in enumerate(self.vertical_port_order[port]): - if p==None: - continue - y_offset += (p.height + self.m2_gap) - self.vertical_port_offsets[port][i]=vector(0,y_offset) - - # Reversed order - self.write_driver_offsets[port] = self.vertical_port_offsets[port][3] - self.sense_amp_offsets[port] = self.vertical_port_offsets[port][2] - self.column_mux_offsets[port] = self.vertical_port_offsets[port][1] - self.precharge_offsets[port] = self.vertical_port_offsets[port][0] + self.port_data_offsets[port] = vector(0,self.bitcell_array_top) # LOWER RIGHT QUADRANT # To the left of the bitcell array @@ -307,7 +235,7 @@ class bank(design.design): x_offset = self.bitcell_array_right + self.central_bus_width[port] + self.wordline_driver.width if self.col_addr_size > 0: x_offset += self.column_decoder.width + self.col_addr_bus_width - y_offset = self.bitcell_array_top + self.column_decoder.height + y_offset = self.bitcell_array_top + self.m2_gap + self.column_decoder.height else: y_offset = self.bitcell_array_top y_offset += 2*drc("well_to_well") @@ -316,7 +244,7 @@ class bank(design.design): # Bank select gets placed above the column decoder (x_offset doesn't change) if self.col_addr_size > 0: y_offset = max(self.column_decoder_offsets[port].y + self.column_decoder.height, - self.column_mux_offsets[port].y + self.column_mux_array[port].height) + self.port_data[port].column_mux_offset.y + self.port_data[port].column_mux_array.height) else: y_offset = self.row_decoder_offsets[port].y self.bank_select_offsets[port] = vector(x_offset,y_offset) @@ -330,12 +258,7 @@ class bank(design.design): self.place_bitcell_array(self.bitcell_array_offset) # LOWER RIGHT QUADRANT - # These are fixed in the order: write driver, sense amp, clumn mux, precharge, - # even if the item is not used in a given port (it will be None then) - self.place_write_driver_array(self.write_driver_offsets) - self.place_sense_amp_array(self.sense_amp_offsets) - self.place_column_mux_array(self.column_mux_offsets) - self.place_precharge_array(self.precharge_offsets) + self.place_port_data(self.port_data_offsets) # UPPER LEFT QUADRANT self.place_row_decoder(self.row_decoder_offsets) @@ -419,39 +342,13 @@ class bank(design.design): self.wl_names = self.bitcell.list_all_wl_names() self.bitline_names = self.bitcell.list_all_bitline_names() - self.precharge_array = [] + self.port_data = [] for port in self.all_ports: - if port in self.read_ports: - temp_pre = factory.create(module_type="precharge_array", - columns=self.num_cols, - bitcell_bl=self.bl_names[port], - bitcell_br=self.br_names[port]) - self.precharge_array.append(temp_pre) - self.add_mod(self.precharge_array[port]) - else: - self.precharge_array.append(None) - - if self.col_addr_size > 0: - self.column_mux_array = [] - for port in self.all_ports: - temp_col = factory.create(module_type="column_mux_array", - columns=self.num_cols, - word_size=self.word_size, - bitcell_bl=self.bl_names[port], - bitcell_br=self.br_names[port]) - self.column_mux_array.append(temp_col) - self.add_mod(self.column_mux_array[port]) - - - self.sense_amp_array = factory.create(module_type="sense_amp_array", - word_size=self.word_size, - words_per_row=self.words_per_row) - self.add_mod(self.sense_amp_array) - - self.write_driver_array = factory.create(module_type="write_driver_array", - columns=self.num_cols, - word_size=self.word_size) - self.add_mod(self.write_driver_array) + temp_pre = factory.create(module_type="port_data", + sram_config=self.sram_config, + port=port) + self.port_data.append(temp_pre) + self.add_mod(self.port_data[port]) self.row_decoder = factory.create(module_type="decoder", rows=self.num_rows) @@ -494,142 +391,48 @@ class bank(design.design): self.bitcell_array_inst.place(offset) - def create_precharge_array(self): - """ Creating Precharge """ - - self.precharge_array_inst = [None]*len(self.all_ports) - for port in self.read_ports: - self.precharge_array_inst[port]=self.add_inst(name="precharge_array{}".format(port), - mod=self.precharge_array[port]) - temp = [] - for i in range(self.num_cols): - temp.append(self.bl_names[port]+"_{0}".format(i)) - temp.append(self.br_names[port]+"_{0}".format(i)) - temp.extend([self.prefix+"p_en_bar{0}".format(port), "vdd"]) - self.connect_inst(temp) - - - def place_precharge_array(self, offsets): - """ Placing Precharge """ - - debug.check(len(offsets)>=len(self.all_ports), "Insufficient offsets to place precharge array.") - - for port in self.read_ports: - if port%2 == 1: - mirror = "MX" - else: - mirror = "R0" - self.precharge_array_inst[port].place(offset=offsets[port], mirror=mirror) - - - def create_column_mux_array(self): - """ Creating Column Mux when words_per_row > 1 . """ - self.column_mux_array_inst = [None]*len(self.all_ports) - - if self.col_addr_size == 0: - return + def create_port_data(self): + """ Creating Port Data """ + self.port_data_inst = [None]*len(self.all_ports) for port in self.all_ports: - self.column_mux_array_inst[port] = self.add_inst(name="column_mux_array{}".format(port), - mod=self.column_mux_array[port]) + self.port_data_inst[port]=self.add_inst(name="port_data{}".format(port), + mod=self.port_data[port]) temp = [] - for col in range(self.num_cols): - temp.append(self.bl_names[port]+"_{0}".format(col)) - temp.append(self.br_names[port]+"_{0}".format(col)) - for word in range(self.words_per_row): - temp.append("sel{0}_{1}".format(port,word)) - for bit in range(self.word_size): - temp.append(self.bl_names[port]+"_out_{0}".format(bit)) - temp.append(self.br_names[port]+"_out_{0}".format(bit)) - temp.append("gnd") + for col in range(self.num_cols): + temp.append("{0}_{1}".format(self.bl_names[port],col)) + temp.append("{0}_{1}".format(self.br_names[port],col)) + if port in self.read_ports: + for bit in range(self.word_size): + temp.append("dout{0}_{1}".format(port,bit)) + if port in self.write_ports: + for bit in range(self.word_size): + temp.append("din{0}_{1}".format(port,bit)) + # Will be empty if no col addr lines + sel_names = ["sel{0}_{1}".format(port,x) for x in range(self.num_col_addr_lines)] + temp.extend(sel_names) + if port in self.read_ports: + temp.append("s_en{0}".format(port)) + if port in self.read_ports: + temp.append("p_en_bar{0}".format(port)) + if port in self.write_ports: + temp.append("w_en{0}".format(port)) + temp.extend(["vdd","gnd"]) + self.connect_inst(temp) - - def place_column_mux_array(self, offsets): - """ Placing Column Mux when words_per_row > 1 . """ - if self.col_addr_size == 0: - return - - debug.check(len(offsets)>=len(self.all_ports), "Insufficient offsets to place column mux array.") + def place_port_data(self, offsets): + """ Placing Port Data """ for port in self.all_ports: + # Top one is unflipped, bottom is flipped along X direction if port%2 == 1: - mirror = "MX" - else: mirror = "R0" - self.column_mux_array_inst[port].place(offset=offsets[port], mirror=mirror) - - - def create_sense_amp_array(self): - """ Creating Sense amp """ - - self.sense_amp_array_inst = [None]*len(self.all_ports) - for port in self.read_ports: - self.sense_amp_array_inst[port] = self.add_inst(name="sense_amp_array{}".format(port), - mod=self.sense_amp_array) - - temp = [] - for bit in range(self.word_size): - temp.append("dout{0}_{1}".format(port,bit)) - if self.words_per_row == 1: - temp.append(self.bl_names[port]+"_{0}".format(bit)) - temp.append(self.br_names[port]+"_{0}".format(bit)) - else: - temp.append(self.bl_names[port]+"_out_{0}".format(bit)) - temp.append(self.br_names[port]+"_out_{0}".format(bit)) - - temp.extend([self.prefix+"s_en{}".format(port), "vdd", "gnd"]) - self.connect_inst(temp) - - - def place_sense_amp_array(self, offsets): - """ Placing Sense amp """ - - debug.check(len(offsets)>=len(self.read_ports), "Insufficient offsets to place sense amp array.") - for port in self.read_ports: - if port%2 == 1: - mirror = "MX" else: - mirror = "R0" - self.sense_amp_array_inst[port].place(offset=offsets[port], mirror=mirror) - - - def create_write_driver_array(self): - """ Creating Write Driver """ - - self.write_driver_array_inst = [None]*len(self.all_ports) - for port in self.write_ports: - self.write_driver_array_inst[port] = self.add_inst(name="write_driver_array{}".format(port), - mod=self.write_driver_array) - - temp = [] - for bit in range(self.word_size): - temp.append("din{0}_{1}".format(port,bit)) - for bit in range(self.word_size): - if (self.words_per_row == 1): - temp.append(self.bl_names[port]+"_{0}".format(bit)) - temp.append(self.br_names[port]+"_{0}".format(bit)) - else: - temp.append(self.bl_names[port]+"_out_{0}".format(bit)) - temp.append(self.br_names[port]+"_out_{0}".format(bit)) - temp.extend([self.prefix+"w_en{0}".format(port), "vdd", "gnd"]) - self.connect_inst(temp) - - - def place_write_driver_array(self, offsets): - """ Placing Write Driver """ - - debug.check(len(offsets)>=len(self.write_ports), "Insufficient offsets to place write driver array.") - - for port in self.write_ports: - if port%2 == 1: mirror = "MX" - else: - mirror = "R0" - self.write_driver_array_inst[port].place(offset=offsets[port], mirror=mirror) - + self.port_data_inst[port].place(offset=offsets[port], mirror=mirror) def create_row_decoder(self): """ Create the hierarchical row decoder """ @@ -877,10 +680,10 @@ class bank(design.design): make_pins=(self.num_banks==1)) - def route_precharge_to_bitcell_array(self, port): - """ Routing of BL and BR between pre-charge and bitcell array """ + def route_port_data_to_bitcell_array(self, port): + """ Routing of BL and BR between port data and bitcell array """ - inst2 = self.precharge_array_inst[port] + inst2 = self.port_data_inst[port] inst1 = self.bitcell_array_inst inst1_bl_name = self.bl_names[port]+"_{}" inst1_br_name = self.br_names[port]+"_{}" @@ -888,96 +691,17 @@ class bank(design.design): inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) + def route_port_data_out(self, port): + """ Add pins for the port data out """ - def route_column_mux_to_precharge_array(self, port): - """ Routing of BL and BR between col mux and precharge array """ - - # Only do this if we have a column mux! - if self.col_addr_size==0: - return - - inst1 = self.column_mux_array_inst[port] - inst2 = self.precharge_array_inst[port] - self.connect_bitlines(inst1, inst2, self.num_cols) - - def route_column_mux_to_bitcell_array(self, port): - """ Routing of BL and BR between col mux bitcell array """ - - # Only do this if we have a column mux! - if self.col_addr_size==0: - return - - inst2 = self.column_mux_array_inst[port] - inst1 = self.bitcell_array_inst - inst1_bl_name = self.bl_names[port]+"_{}" - inst1_br_name = self.br_names[port]+"_{}" - - # The column mux is constructed to match the bitline pitch, so we can directly connect - # here and not channel route the bitlines. - self.connect_bitlines(inst1=inst1, inst2=inst2, num_bits=self.num_cols, - inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) - - - - def route_sense_amp_to_column_mux_or_precharge_array(self, port): - """ Routing of BL and BR between sense_amp and column mux or precharge array """ - inst2 = self.sense_amp_array_inst[port] - - if self.col_addr_size>0: - # Sense amp is connected to the col mux - inst1 = self.column_mux_array_inst[port] - inst1_bl_name = "bl_out_{}" - inst1_br_name = "br_out_{}" - else: - # Sense amp is directly connected to the precharge array - inst1 = self.precharge_array_inst[port] - inst1_bl_name = "bl_{}" - inst1_br_name = "br_{}" - - self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, - inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) - - def route_write_driver_to_column_mux_or_bitcell_array(self, port): - """ Routing of BL and BR between sense_amp and column mux or bitcell array """ - inst2 = self.write_driver_array_inst[port] - - if self.col_addr_size>0: - # Write driver is connected to the col mux - inst1 = self.column_mux_array_inst[port] - inst1_bl_name = "bl_out_{}" - inst1_br_name = "br_out_{}" - else: - # Write driver is directly connected to the bitcell array - inst1 = self.bitcell_array_inst - inst1_bl_name = self.bl_names[port]+"_{}" - inst1_br_name = self.br_names[port]+"_{}" - - self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, - inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) - - def route_write_driver_to_sense_amp(self, port): - """ Routing of BL and BR between write driver and sense amp """ - - inst1 = self.write_driver_array_inst[port] - inst2 = self.sense_amp_array_inst[port] - - # These should be pitch matched in the cell library, - # but just in case, do a channel route. - self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size) - - - - def route_sense_amp_out(self, port): - """ Add pins for the sense amp output """ - for bit in range(self.word_size): - data_pin = self.sense_amp_array_inst[port].get_pin("data_{}".format(bit)) + data_pin = self.port_data_inst[port].get_pin("dout_{0}".format(bit)) self.add_layout_pin_rect_center(text="dout{0}_{1}".format(port,bit), layer=data_pin.layer, offset=data_pin.center(), height=data_pin.height(), width=data_pin.width()) - + def route_row_decoder(self, port): """ Routes the row decoder inputs and supplies """ @@ -990,13 +714,13 @@ class bank(design.design): self.copy_layout_pin(self.row_decoder_inst[port], decoder_name, addr_name) - def route_write_driver_in(self, port): - """ Connecting write driver """ + def route_port_data_in(self, port): + """ Connecting port data in """ for row in range(self.word_size): - data_name = "data_{}".format(row) + data_name = "din_{}".format(row) din_name = "din{0}_{1}".format(port,row) - self.copy_layout_pin(self.write_driver_array_inst[port], data_name, din_name) + self.copy_layout_pin(self.port_data_inst[port], data_name, din_name) def channel_route_bitlines(self, inst1, inst2, num_bits, inst1_bl_name="bl_{}", inst1_br_name="br_{}", @@ -1131,7 +855,7 @@ class bank(design.design): decode_pins = [self.column_decoder_inst[port].get_pin(x) for x in decode_names] sel_names = ["sel_{}".format(x) for x in range(self.num_col_addr_lines)] - column_mux_pins = [self.column_mux_array_inst[port].get_pin(x) for x in sel_names] + column_mux_pins = [self.port_data_inst[port].get_pin(x) for x in sel_names] route_map = list(zip(decode_pins, column_mux_pins)) self.create_vertical_channel_route(route_map, offset) @@ -1194,13 +918,13 @@ class bank(design.design): connection = [] if port in self.read_ports: - connection.append((self.prefix+"p_en_bar{}".format(port), self.precharge_array_inst[port].get_pin("en_bar").lc())) + connection.append((self.prefix+"p_en_bar{}".format(port), self.port_data_inst[port].get_pin("p_en_bar").lc())) if port in self.write_ports: - connection.append((self.prefix+"w_en{}".format(port), self.write_driver_array_inst[port].get_pin("en").lc())) + connection.append((self.prefix+"w_en{}".format(port), self.port_data_inst[port].get_pin("w_en").lc())) if port in self.read_ports: - connection.append((self.prefix+"s_en{}".format(port), self.sense_amp_array_inst[port].get_pin("en").lc())) + connection.append((self.prefix+"s_en{}".format(port), self.port_data_inst[port].get_pin("s_en").lc())) for (control_signal, pin_pos) in connection: control_pos = vector(self.bus_xoffset[port][control_signal].x ,pin_pos.y) @@ -1232,26 +956,26 @@ class bank(design.design): #FIXME: Array delay is the same for every port. word_driver_slew = 0 if self.words_per_row > 1: - bitline_ext_load = self.column_mux_array[port].get_drain_cin() + bitline_ext_load = self.port_data[port].column_mux_array.get_drain_cin() else: - bitline_ext_load = self.sense_amp_array.get_drain_cin() + bitline_ext_load = self.port_data[port].sense_amp_array.get_drain_cin() bitcell_array_delay = self.bitcell_array.analytical_delay(corner, word_driver_slew, bitline_ext_load) bitcell_array_slew = 0 #This also essentially creates the same delay for each port. Good structure, no substance if self.words_per_row > 1: - sa_load = self.sense_amp_array.get_drain_cin() - column_mux_delay = self.column_mux_array[port].analytical_delay(corner, - bitcell_array_slew, - sa_load) + sa_load = self.port_data[port].sense_amp_array.get_drain_cin() + column_mux_delay = self.port_data[port].column_mux_array.analytical_delay(corner, + bitcell_array_slew, + sa_load) else: column_mux_delay = [] column_mux_slew = 0 - sense_amp_delay = self.sense_amp_array.analytical_delay(corner, - column_mux_slew, - load) + sense_amp_delay = self.port_data[port].sense_amp_array.analytical_delay(corner, + column_mux_slew, + load) # output load of bitcell_array is set to be only small part of bl for sense amp. return bitcell_array_delay + column_mux_delay + sense_amp_delay @@ -1272,7 +996,8 @@ class bank(design.design): def get_w_en_cin(self): """Get the relative capacitance of all the clk connections in the bank""" #wl_en only used in the wordline driver. - return self.write_driver.get_w_en_cin() + port = self.write_ports[0] + return self.port_data[port].write_driver.get_w_en_cin() def get_clk_bar_cin(self): """Get the relative capacitance of all the clk_bar connections in the bank""" @@ -1280,9 +1005,10 @@ class bank(design.design): #Precharges are the all the same in Mulitport, one is picked port = self.read_ports[0] - return self.precharge_array[port].get_en_cin() + return self.port_data[port].precharge_array.get_en_cin() def get_sen_cin(self): """Get the relative capacitance of all the sense amp enable connections in the bank""" #Current bank only uses sen as an enable for the sense amps. - return self.sense_amp_array.get_en_cin() + port = self.read_ports[0] + return self.port_data[port].sense_amp_array.get_en_cin() diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 0baafba0..3737892c 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -73,29 +73,41 @@ class port_data(design.design): def add_pins(self): """ Adding pins for Bank module""" + for bit in range(self.num_cols): + self.add_pin(self.bl_names[self.port]+"_{0}".format(bit),"INOUT") + self.add_pin(self.br_names[self.port]+"_{0}".format(bit),"INOUT") if self.port in self.read_ports: for bit in range(self.word_size): - self.add_pin("dout{0}_{1}".format(self.port,bit),"OUT") + self.add_pin("dout_{}".format(bit),"OUTPUT") if self.port in self.write_ports: for bit in range(self.word_size): - self.add_pin("din{0}_{1}".format(self.port,bit),"IN") - + self.add_pin("din_{}".format(bit),"INPUT") + # Will be empty if no col addr lines + sel_names = ["sel_{}".format(x) for x in range(self.num_col_addr_lines)] + for pin_name in sel_names: + self.add_pin(pin_name,"INPUT") if self.port in self.read_ports: - self.add_pin("s_en{0}".format(self.port), "INPUT") + self.add_pin("s_en", "INPUT") if self.port in self.read_ports: - self.add_pin("p_en_bar{0}".format(self.port), "INPUT") + self.add_pin("p_en_bar", "INPUT") if self.port in self.write_ports: - self.add_pin("w_en{0}".format(self.port), "INPUT") + self.add_pin("w_en", "INPUT") self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") def route_layout(self): """ Create routing amoung the modules """ - self.route_bitlines() + self.route_data_lines() + self.route_layout_pins() self.route_supplies() - def route_bitlines(self): + def route_layout_pins(self): + """ Add the pins """ + self.route_bitline_pins() + self.route_control_pins() + + def route_data_lines(self): """ Route the bitlines depending on the port type rw, w, or r. """ if self.port in self.readwrite_ports: @@ -164,6 +176,12 @@ class port_data(design.design): self.num_cols = int(self.words_per_row*self.word_size) self.num_rows = int(self.num_words / self.words_per_row) + # The central bus is the column address (one hot) and row address (binary) + if self.col_addr_size>0: + self.num_col_addr_lines = 2**self.col_addr_size + else: + self.num_col_addr_lines = 0 + # A space for wells or jogging m2 between modules self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclosure_active"), 3*self.m2_pitch) @@ -174,7 +192,6 @@ class port_data(design.design): self.bl_names = self.bitcell.list_all_bl_names() self.br_names = self.bitcell.list_all_br_names() self.wl_names = self.bitcell.list_all_wl_names() - self.bitline_names = self.bitcell.list_all_bitline_names() def create_precharge_array(self): """ Creating Precharge """ @@ -185,10 +202,10 @@ class port_data(design.design): self.precharge_array_inst = self.add_inst(name="precharge_array{}".format(self.port), mod=self.precharge_array) temp = [] - for i in range(self.num_cols): - temp.append(self.bl_names[self.port]+"_{0}".format(i)) - temp.append(self.br_names[self.port]+"_{0}".format(i)) - temp.extend(["p_en_bar{0}".format(self.port), "vdd"]) + for bit in range(self.num_cols): + temp.append(self.bl_names[self.port]+"_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_{0}".format(bit)) + temp.extend(["p_en_bar", "vdd"]) self.connect_inst(temp) @@ -207,7 +224,7 @@ class port_data(design.design): temp.append(self.bl_names[self.port]+"_{0}".format(col)) temp.append(self.br_names[self.port]+"_{0}".format(col)) for word in range(self.words_per_row): - temp.append("sel{0}_{1}".format(self.port,word)) + temp.append("sel_{}".format(word)) for bit in range(self.word_size): temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) @@ -231,7 +248,7 @@ class port_data(design.design): temp = [] for bit in range(self.word_size): - temp.append("dout{0}_{1}".format(self.port,bit)) + temp.append("dout_{}".format(bit)) if self.words_per_row == 1: temp.append(self.bl_names[self.port]+"_{0}".format(bit)) temp.append(self.br_names[self.port]+"_{0}".format(bit)) @@ -239,7 +256,7 @@ class port_data(design.design): temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) - temp.extend(["s_en{}".format(self.port), "vdd", "gnd"]) + temp.extend(["s_en", "vdd", "gnd"]) self.connect_inst(temp) @@ -255,7 +272,7 @@ class port_data(design.design): temp = [] for bit in range(self.word_size): - temp.append("din{0}_{1}".format(self.port,bit)) + temp.append("din_{}".format(bit)) for bit in range(self.word_size): if (self.words_per_row == 1): temp.append(self.bl_names[self.port]+"_{0}".format(bit)) @@ -263,7 +280,7 @@ class port_data(design.design): else: temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) - temp.extend(["w_en{0}".format(self.port), "vdd", "gnd"]) + temp.extend(["w_en", "vdd", "gnd"]) self.connect_inst(temp) @@ -320,7 +337,7 @@ class port_data(design.design): for bit in range(self.word_size): data_pin = self.sense_amp_array_inst.get_pin("data_{}".format(bit)) - self.add_layout_pin_rect_center(text="dout{0}_{1}".format(port,bit), + self.add_layout_pin_rect_center(text="dout_{0}".format(bit), layer=data_pin.layer, offset=data_pin.center(), height=data_pin.height(), @@ -331,7 +348,7 @@ class port_data(design.design): for row in range(self.word_size): data_name = "data_{}".format(row) - din_name = "din{0}_{1}".format(self.port,row) + din_name = "din_{}".format(row) self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name) def route_column_mux_to_precharge_array(self, port): @@ -392,6 +409,34 @@ class port_data(design.design): self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size) + def route_bitline_pins(self): + """ Add the bitline pins for the given port """ + + for bit in range(self.num_cols): + if self.port in self.read_ports: + self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit)) + self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit)) + elif self.column_mux_array_inst: + self.copy_layout_pin(self.column_mux_array_inst, "bl_{}".format(bit)) + self.copy_layout_pin(self.column_mux_array_inst, "br_{}".format(bit)) + else: + self.copy_layout_pin(self.write_driver_array_inst, "bl_{}".format(bit)) + self.copy_layout_pin(self.write_driver_array_inst, "br_{}".format(bit)) + + def route_control_pins(self): + """ Add the control pins: s_en, p_en_bar, w_en """ + if self.precharge_array_inst: + self.copy_layout_pin(self.precharge_array_inst, "en_bar", "p_en_bar") + if self.column_mux_array_inst: + sel_names = ["sel_{}".format(x) for x in range(self.num_col_addr_lines)] + for pin_name in sel_names: + self.copy_layout_pin(self.column_mux_array_inst, pin_name) + if self.sense_amp_array_inst: + self.copy_layout_pin(self.sense_amp_array_inst, "en", "s_en") + if self.write_driver_array_inst: + self.copy_layout_pin(self.write_driver_array_inst, "en", "w_en") + + def channel_route_bitlines(self, inst1, inst2, num_bits, inst1_bl_name="bl_{}", inst1_br_name="br_{}", inst2_bl_name="bl_{}", inst2_br_name="br_{}"): diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index a0d9b484..80948a82 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -26,7 +26,7 @@ class ptx(design.design): # will use the last record with a given name. I.e., you will # over-write a design in GDS if one has and the other doesn't # have poly connected, for example. - name = "{0}_m{1}_w{2}".format(tx_type, mults, width) + name = "{0}_m{1}_w{2:.3f}".format(tx_type, mults, width) if connect_active: name += "_a" if connect_poly: diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index c5ad07e9..7f027509 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -45,6 +45,7 @@ class sram_1bank(sram_base): self.col_addr_dff_insts = self.create_col_addr_dff() self.data_dff_insts = self.create_data_dff() + def place_instances(self): """ @@ -72,25 +73,6 @@ class sram_1bank(sram_base): # Port 0 port = 0 - # This includes 2 M2 pitches for the row addr clock line. - # It is also placed to align with the column decoder (if it exists hence the bank gap) - control_pos[port] = vector(-self.control_logic_insts[port].width - 2*self.m2_pitch, - self.bank.bank_array_ll.y - self.control_logic_insts[port].mod.control_logic_center.y - self.bank.m2_gap) - self.control_logic_insts[port].place(control_pos[port]) - - # The row address bits are placed above the control logic aligned on the right. - x_offset = self.control_logic_insts[port].rx() - self.row_addr_dff_insts[port].width - # It is aove the control logic but below the top of the bitcell array - y_offset = max(self.control_logic_insts[port].uy(), self.bank.bank_array_ur.y - self.row_addr_dff_insts[port].height) - row_addr_pos[port] = vector(x_offset, y_offset) - self.row_addr_dff_insts[port].place(row_addr_pos[port]) - - # Add the col address flops below the bank to the left of the lower-left of bank array - if self.col_addr_dff: - col_addr_pos[port] = vector(self.bank.bank_array_ll.x - self.col_addr_dff_insts[port].width - self.bank.m2_gap, - -max_gap_size - self.col_addr_dff_insts[port].height) - self.col_addr_dff_insts[port].place(col_addr_pos[port]) - # Add the data flops below the bank to the right of the lower-left of bank array # This relies on the lower-left of the array of the bank # decoder in upper left, bank in upper right, sensing in lower right. @@ -98,43 +80,69 @@ class sram_1bank(sram_base): # sense amps. if port in self.write_ports: data_pos[port] = vector(self.bank.bank_array_ll.x, - -max_gap_size - self.data_dff_insts[port].height) + -max_gap_size - self.dff.height) self.data_dff_insts[port].place(data_pos[port]) + else: + data_pos[port] = vector(self.bank.bank_array_ll.x,0) + # Add the col address flops below the bank to the left of the lower-left of bank array + if self.col_addr_dff: + col_addr_pos[port] = vector(self.bank.bank_array_ll.x - self.col_addr_dff_insts[port].width - self.bank.m2_gap, + -max_gap_size - self.col_addr_dff_insts[port].height) + self.col_addr_dff_insts[port].place(col_addr_pos[port]) + else: + col_addr_pos[port] = vector(self.bank.bank_array_ll.x,0) + + # This includes 2 M2 pitches for the row addr clock line. + control_pos[port] = vector(-self.control_logic_insts[port].width - 2*self.m2_pitch, + self.bank.bank_array_ll.y - self.control_logic_insts[port].mod.control_logic_center.y - self.bank.m2_gap) + self.control_logic_insts[port].place(control_pos[port]) + + # The row address bits are placed above the control logic aligned on the right. + x_offset = self.control_logic_insts[port].rx() - self.row_addr_dff_insts[port].width + # It is aove the control logic but below the top of the bitcell array + y_offset = self.control_logic_insts[port].uy() + row_addr_pos[port] = vector(x_offset, y_offset) + self.row_addr_dff_insts[port].place(row_addr_pos[port]) + if len(self.all_ports)>1: # Port 1 port = 1 - # This includes 2 M2 pitches for the row addr clock line - # It is also placed to align with the column decoder (if it exists hence the bank gap) - control_pos[port] = vector(self.bank_inst.rx() + self.control_logic_insts[port].width + 2*self.m2_pitch, - self.bank.bank_array_ll.y - self.control_logic_insts[port].mod.control_logic_center.y + self.bank.m2_gap) - self.control_logic_insts[port].place(control_pos[port], mirror="MY") - - # The row address bits are placed above the control logic aligned on the left. - x_offset = control_pos[port].x - self.control_logic_insts[port].width + self.row_addr_dff_insts[port].width - # It is above the control logic but below the top of the bitcell array - y_offset = max(self.control_logic_insts[port].uy(), self.bank.bank_array_ur.y - self.row_addr_dff_insts[port].height) - row_addr_pos[port] = vector(x_offset, y_offset) - self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="MY") - - # Add the col address flops above the bank to the right of the upper-right of bank array - if self.col_addr_dff: - col_addr_pos[port] = vector(self.bank.bank_array_ur.x + self.bank.m2_gap, - self.bank.height + max_gap_size + self.col_addr_dff_insts[port].height) - self.col_addr_dff_insts[port].place(col_addr_pos[port], mirror="MX") - # Add the data flops above the bank to the left of the upper-right of bank array # This relies on the upper-right of the array of the bank # decoder in upper left, bank in upper right, sensing in lower right. # These flops go below the sensing and leave a gap to channel route to the - # sense amps. + # sense amps. if port in self.write_ports: data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - self.bank.height + max_gap_size + self.data_dff_insts[port].height) + self.bank.height + max_gap_size + self.dff.height) self.data_dff_insts[port].place(data_pos[port], mirror="MX") + else: + data_pos[port] = self.bank_inst.ur() + + # Add the col address flops above the bank to the right of the upper-right of bank array + if self.col_addr_dff: + col_addr_pos[port] = vector(self.bank.bank_array_ur.x + self.bank.m2_gap, + self.bank.height + max_gap_size + self.dff.height) + self.col_addr_dff_insts[port].place(col_addr_pos[port], mirror="MX") + else: + col_addr_pos[port] = self.bank_inst.ur() + # This includes 2 M2 pitches for the row addr clock line + control_pos[port] = vector(self.bank_inst.rx() + self.control_logic_insts[port].width + 2*self.m2_pitch, + self.bank.bank_array_ur.y + self.control_logic_insts[port].mod.control_logic_center.y + self.bank.m2_gap) + self.control_logic_insts[port].place(control_pos[port], mirror="XY") + + # The row address bits are placed above the control logic aligned on the left. + x_offset = control_pos[port].x - self.control_logic_insts[port].width + self.row_addr_dff_insts[port].width + # It is above the control logic but below the top of the bitcell array + y_offset = self.control_logic_insts[port].by() + row_addr_pos[port] = vector(x_offset, y_offset) + self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="XY") + + def add_layout_pins(self): """ @@ -260,10 +268,15 @@ class sram_1bank(sram_base): def route_col_addr_dff(self): """ Connect the output of the row flops to the bank pins """ for port in self.all_ports: + if port%2: + offset = self.col_addr_dff_insts[port].ll() - vector(0, (self.word_size+2)*self.m1_pitch) + else: + offset = self.col_addr_dff_insts[port].ul() + vector(0, 2*self.m1_pitch) + bus_names = ["addr_{}".format(x) for x in range(self.col_addr_size)] col_addr_bus_offsets = self.create_horizontal_bus(layer="metal1", pitch=self.m1_pitch, - offset=self.col_addr_dff_insts[port].ul() + vector(0, self.m1_pitch), + offset=offset, names=bus_names, length=self.col_addr_dff_insts[port].width) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 547bc222..33d0ad68 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -262,6 +262,7 @@ class sram_base(design, verilog, lef): def add_modules(self): self.bitcell = factory.create(module_type=OPTS.bitcell) + self.dff = factory.create(module_type="dff") # Create the address and control flops (but not the clk) from dff_array import dff_array @@ -276,6 +277,8 @@ class sram_base(design, verilog, lef): self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size) self.add_mod(self.data_dff) + + # Create the bank module (up to four are instantiated) from bank import bank diff --git a/compiler/tests/05_replica_bitcell_array_test.py b/compiler/tests/05_replica_bitcell_array_test.py index e4c38337..db1c2924 100755 --- a/compiler/tests/05_replica_bitcell_array_test.py +++ b/compiler/tests/05_replica_bitcell_array_test.py @@ -13,6 +13,7 @@ from globals import OPTS from sram_factory import factory import debug +@unittest.skip("SKIPPING 05_replica_bitcell_array_test") class replica_bitcell_array_test(openram_test): def runTest(self): diff --git a/compiler/tests/19_single_bank_1w_1r_test.py b/compiler/tests/19_single_bank_1w_1r_test.py new file mode 100755 index 00000000..d60c33f6 --- /dev/null +++ b/compiler/tests/19_single_bank_1w_1r_test.py @@ -0,0 +1,71 @@ +#!/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 single_bank_1w_1r_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + OPTS.bitcell = "bitcell_1w_1r" + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 0 + + from sram_config import sram_config + c = sram_config(word_size=4, + num_words=16) + + c.words_per_row=1 + factory.reset() + c.recompute_sizes() + debug.info(1, "No column mux") + a = factory.create(module_type="bank", sram_config=c) + self.local_check(a) + + c.num_words=32 + c.words_per_row=2 + factory.reset() + c.recompute_sizes() + debug.info(1, "Two way column mux") + a = factory.create(module_type="bank", sram_config=c) + self.local_check(a) + + c.num_words=64 + c.words_per_row=4 + factory.reset() + c.recompute_sizes() + debug.info(1, "Four way column mux") + a = factory.create(module_type="bank", sram_config=c) + self.local_check(a) + + c.word_size=2 + c.num_words=128 + c.words_per_row=8 + factory.reset() + c.recompute_sizes() + debug.info(1, "Eight way column mux") + a = factory.create(module_type="bank", sram_config=c) + 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 70c83f20b6728ae6251eb407d0d462afc7f51e5a Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 3 Jul 2019 13:37:56 -0700 Subject: [PATCH 065/234] Fixes to pass unit tests. Skip replica tests until freepdk45 cells are made. Revert to previous control and row addr dff placement. --- compiler/sram/sram_1bank.py | 4 ++-- compiler/tests/05_dummy_array_test.py | 1 + compiler/tests/05_replica_column_test.py | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 7f027509..a5565e90 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -101,7 +101,7 @@ class sram_1bank(sram_base): # The row address bits are placed above the control logic aligned on the right. x_offset = self.control_logic_insts[port].rx() - self.row_addr_dff_insts[port].width # It is aove the control logic but below the top of the bitcell array - y_offset = self.control_logic_insts[port].uy() + y_offset = max(self.control_logic_insts[port].uy(), self.bank.bank_array_ur.y - self.row_addr_dff_insts[port].height) row_addr_pos[port] = vector(x_offset, y_offset) self.row_addr_dff_insts[port].place(row_addr_pos[port]) @@ -138,7 +138,7 @@ class sram_1bank(sram_base): # The row address bits are placed above the control logic aligned on the left. x_offset = control_pos[port].x - self.control_logic_insts[port].width + self.row_addr_dff_insts[port].width # It is above the control logic but below the top of the bitcell array - y_offset = self.control_logic_insts[port].by() + y_offset = min(self.control_logic_insts[port].by(), self.bank.bank_array_ll.y - self.row_addr_dff_insts[port].height) row_addr_pos[port] = vector(x_offset, y_offset) self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="XY") diff --git a/compiler/tests/05_dummy_array_test.py b/compiler/tests/05_dummy_array_test.py index de379a97..0925246d 100755 --- a/compiler/tests/05_dummy_array_test.py +++ b/compiler/tests/05_dummy_array_test.py @@ -13,6 +13,7 @@ from globals import OPTS from sram_factory import factory import debug +@unittest.skip("SKIPPING 05_dummy_array_test") class dummy_row_test(openram_test): def runTest(self): diff --git a/compiler/tests/05_replica_column_test.py b/compiler/tests/05_replica_column_test.py index 8a9f03bb..6f81193f 100755 --- a/compiler/tests/05_replica_column_test.py +++ b/compiler/tests/05_replica_column_test.py @@ -13,6 +13,7 @@ from globals import OPTS from sram_factory import factory import debug +@unittest.skip("SKIPPING 05_replica_column_test") class replica_column_test(openram_test): def runTest(self): From 0fbfa924f7cca13a8a867fa6b471c94b40586497 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 3 Jul 2019 14:28:12 -0700 Subject: [PATCH 066/234] Add other SCMOS dummy cells --- .../scn4m_subm/gds_lib/dummy_cell_1rw_1r.gds | Bin 0 -> 6086 bytes .../scn4m_subm/gds_lib/dummy_cell_1w_1r.gds | Bin 0 -> 6082 bytes .../scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag | 136 ++++++++++++++++++ .../scn4m_subm/mag_lib/dummy_cell_1w_1r.mag | 136 ++++++++++++++++++ .../scn4m_subm/sp_lib/dummy_cell_1rw_1r.sp | 14 ++ .../scn4m_subm/sp_lib/dummy_cell_1w_1r.sp | 14 ++ 6 files changed, 300 insertions(+) create mode 100644 technology/scn4m_subm/gds_lib/dummy_cell_1rw_1r.gds create mode 100644 technology/scn4m_subm/gds_lib/dummy_cell_1w_1r.gds create mode 100644 technology/scn4m_subm/mag_lib/dummy_cell_1rw_1r.mag create mode 100644 technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag create mode 100644 technology/scn4m_subm/sp_lib/dummy_cell_1rw_1r.sp create mode 100644 technology/scn4m_subm/sp_lib/dummy_cell_1w_1r.sp diff --git a/technology/scn4m_subm/gds_lib/dummy_cell_1rw_1r.gds b/technology/scn4m_subm/gds_lib/dummy_cell_1rw_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..42727119f93a92031336ac2d7e1a4b91a1254bb0 GIT binary patch literal 6086 zcmai&J!~CC6os#!?Pn)Ajtz-p69a}2#hCoqiA)>{2oePn4Fv_Fi3LWaa1e?F4xLNr zQbwY2N6M5bsZdInl$0r5QgS}e9__qM?y}PJw>mTD-kCe|cE>M-a3pxH`Si{Cm$5=yH8ubDGl9J?9~5?e6Rgl`kIUd-ISjC$wOcA zo5VpkrPuz;_5AUy9+dp%)qhGXQ+n#BPOgDTOmtIv?SH?{&lopXA{HLE+`3)HZmK=? zpZZK2NipW`w!HF11iGpA)K7l=Ib3^3a$3CTovwN>BaNnZD#UPp+2wo6>9ldcA+n zsMed$BhG5inl~TlktN-fp8BT_BVKJASL$a{3v^R@>L<_a-zC2}cems> zrKf)8NnYk}k{8|V%a3PG`<1>X-#>IydYYf{<75As_|VNhKQ+e3TABFJ%|1VQs5SY` z6Wb-fDZL*5)%yE0zg}wh>Ypun?xUNkZR$VwW5gw`AA85dhi*zw{bv`;y9+<>FvmeB zUeliXne$t>BWCtnvKP=zwWt1*N98?>pZBffpcA)gPyN)1evH#3uj|^hr+(Im+LPC0 zEzwQssh{!jp2cqx2i=sO`WYWS`kKtc^J>~tKkJN-bu(Elcish4?auH-hQ*ZD{M z(~mUvX|4Ba%eSSWn`%$}$8(mS=Lm5iK6JCskB1L^&HBD+PxJd7PwhAhK)y@pru5X$ z85FkGv*6bhG2%sOulPHdj=;^_HCbxlFa! z`Csr~dtChH^=HLzN>BZMf7H)=;-H(I=g&xf>crSNtC*bo(M{=Te%1^h=U)>ay4mOF zjE;}`oA}VpK0o8+J$w3~C2>5jrac`$?L6lfw^|a?#Jx&`~1TC@y>ue3(-yKX@36aBNyX084J28J@xZF!OQo@Wc=u+ z^wiIs`Ow#_@0<42&wGbH{B~mEM>nOXe%6_~bH>Ib3)|rd-HyJm&DLwUH+{ab+uZa)c zlwSKkuGbF_7wd0+pt*3Fx;^&Kl;3~#{#@Yq-x+@Y<=nBc71K+@yV7c@Z(=@fA+_3M|VDXzIyQMS6{^9 zct?!>$rxjk5&bj0Sc(30FCwnZjOwqh%SRC_Yb`%`Qgl=8W3v(VzdP)wH-3|NT&8Yo z|Ml8G`**~x#}V_JE${o{{{_nqf0-;{=KDt79BMZVX5E`3eLf^JGr{p6u9 z`Ay=Wo6>9lwR-+|mJdpP^TuB#mMJ~;QzzHJBqq8kz4pIX=Vy!?OA+Uvw%oj1#%`)T z^`H4v8%Z%{?zg=Dc?7zt_S8>){Ny+Bp_^U)g%`!Q__8HFbhFFPIN7`SO~&DQHSOv6 zCnig-%gZf^g>Gsrsh{}FoxUbxM>nOXe)7BG66gsej@y;`PT7r?y)zYCoczYES*sGsSoIpd~(Zv&&CzKJ+!~ z`=&k3zjRo9Z*RB6k8UbP>ZeW%QR-)s6Wx@a`l%ChrG6&0KsTkQe)3HJS@N4R_e*|L zdg^DM-=%)14e{R0KyYTZ4a~yQy zHSMXNIlpx`Vrsu7djZ{4d+I-ZRNk}rdEYt?I&qu!)K8u0$2d*$x~@%o>Sv9pJ$X&m z65W)Z`WYYZS^Oq(&`s&7pYh?NugN?-uckfqv(ETfHIckH=dQcQ8V&FKIo?O zPCx60*W})Dq4Z8abLV+sQg?i&^iDtXCZ|ap{N~X7SL^Q|Ij-!NdYM;eN^VnnoqxbT z`9x!%)Os(syd(|XRD0?_p0oTsM~DOQp_^TPJbdVD*7r?&n&0nuYR6ds@?AnVrKf(* z*!aj};zKuw{5R|RGhd$@OrIOfq4UEDKhJH}(e!iQ9D05a_&GB%Zr*(+<3=~T#((k4 z;^X{=AL2tdyZq$osW17>QN=(vrPuWz7(aRNk=MkBZVvg^>-vYTjV0A?ttIDvE>rDw z{uBPyr^RpHd{O+S^wjV7NBz7f4!Sw?{29nkoftc36_ay6x+y))&zj-m{A=PvH@p0t z(eY7#6Cb+SM4!YU3{&@J%*JR&tZ|XkH&p63lfAFH4YD@hi>c?91yflf0 zZc0!6)E6K7*TmP<{g_>TpI=x%-WiZ*A-X9&&CmaQU zp8AY=%)14&pK1L;qwPN^=sNwKY6HI{r@+0LpQtX7rLl5 z-x-rSa+%W8{Pbh5;Wx*gp+=a}YyYkK`H!dWi-+evx~cZm&zQM9R)`PXRCDV8ujem5 zbW?Ln{Zsp8tn7Qn?ER0<`ZevTpY_GZdC~N`o6=K1>&(Uan~WRXl%D#p?Bgo?*Tjcz zO0WGN)$50ci}g3(*Ic+v-5&d=%J08=f1c;}-zk3o<=nBp8IueBy> +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 +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 +rect 0 61 54 65 +rect 10 44 14 61 +rect 17 51 20 54 +rect 17 47 27 51 +rect 17 37 20 47 +rect 34 44 37 54 +rect 27 40 37 44 +rect 40 44 44 61 +rect 34 37 37 40 +rect 2 33 9 37 +rect 45 33 52 37 +rect 25 23 29 29 +rect 25 13 29 17 +rect 0 9 25 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 +rect 25 58 29 68 +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 +<< labels >> +rlabel metal1 19 63 19 63 1 wl0 +rlabel metal1 19 70 19 70 5 vdd +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +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 +<< 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 new file mode 100644 index 00000000..03e49f03 --- /dev/null +++ b/technology/scn4m_subm/mag_lib/dummy_cell_1w_1r.mag @@ -0,0 +1,136 @@ +magic +tech scmos +timestamp 1562189027 +<< 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 +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 +rect 0 61 54 65 +rect 10 44 14 61 +rect 17 51 20 54 +rect 17 47 27 51 +rect 17 37 20 47 +rect 34 44 37 54 +rect 27 40 37 44 +rect 40 44 44 61 +rect 34 37 37 40 +rect 2 33 9 37 +rect 45 33 52 37 +rect 25 23 29 29 +rect 25 13 29 17 +rect 0 9 25 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 +rect 25 58 29 68 +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 +<< labels >> +rlabel metal1 19 63 19 63 1 wl0 +rlabel metal1 19 70 19 70 5 vdd +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +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 +<< end >> diff --git a/technology/scn4m_subm/sp_lib/dummy_cell_1rw_1r.sp b/technology/scn4m_subm/sp_lib/dummy_cell_1rw_1r.sp new file mode 100644 index 00000000..9766a840 --- /dev/null +++ b/technology/scn4m_subm/sp_lib/dummy_cell_1rw_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT dummy_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1_noconn gnd n w=1.2u l=0.4u +MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u +MM7 RA_to_R_left Q_bar gnd gnd n w=1.2u l=0.4u +MM6 RA_to_R_left wl1 bl1_noconn gnd n w=1.2u l=0.4u +MM5 Q wl0 bl0_noconn gnd n w=0.8u l=0.4u +MM4 Q_bar wl0 br0_noconn gnd n w=0.8u l=0.4u +MM1 Q Q_bar gnd gnd n w=1.6u l=0.4u +MM0 Q_bar Q gnd gnd n w=1.6u l=0.4u +MM3 Q Q_bar vdd vdd p w=0.6u l=0.4u +MM2 Q_bar Q vdd vdd p w=0.6u l=0.4u +.ENDS + diff --git a/technology/scn4m_subm/sp_lib/dummy_cell_1w_1r.sp b/technology/scn4m_subm/sp_lib/dummy_cell_1w_1r.sp new file mode 100644 index 00000000..f5424998 --- /dev/null +++ b/technology/scn4m_subm/sp_lib/dummy_cell_1w_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT dummy_cell_1w_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1_noconn gnd n w=1.2u l=0.4u +MM8 RA_to_R_right Q gnd gnd n w=1.2u l=0.4u +MM7 RA_to_R_left Q_bar gnd gnd n w=1.2u l=0.4u +MM6 RA_to_R_left wl1 bl1_noconn gnd n w=1.2u l=0.4u +MM5 Q wl0 bl0_noconn gnd n w=0.8u l=0.4u +MM4 Q_bar wl0 br0_noconn gnd n w=0.8u l=0.4u +MM1 Q Q_bar gnd gnd n w=1.6u l=0.4u +MM0 Q_bar Q gnd gnd n w=1.6u l=0.4u +MM3 Q Q_bar vdd vdd p w=0.6u l=0.4u +MM2 Q_bar Q vdd vdd p w=0.6u l=0.4u +.ENDS + From 0cb86b8ba29a3b7b4889ceef8d2b3588891939eb Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 3 Jul 2019 14:46:20 -0700 Subject: [PATCH 067/234] Exclude new precharge in graph build --- compiler/modules/bank.py | 6 +++--- compiler/modules/port_data.py | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 9b78f2dd..9a274cd1 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -1014,9 +1014,9 @@ class bank(design.design): def graph_exclude_precharge(self): """Precharge adds a loop between bitlines, can be excluded to reduce complexity""" - for inst in self.precharge_array_inst: - if inst != None: - self.graph_inst_exclude.add(inst) + for port in self.read_ports: + if self.port_data[port]: + self.port_data[port].graph_exclude_precharge() def get_cell_name(self, inst_name, row, col): """Gets the spice name of the target bitcell.""" diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 3737892c..a03741c4 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -494,4 +494,7 @@ class port_data(design.design): self.add_path("metal2",[bottom_br, vector(bottom_br.x,yoffset), vector(top_br.x,yoffset), top_br]) - + def graph_exclude_precharge(self): + """Precharge adds a loop between bitlines, can be excluded to reduce complexity""" + if self.precharge_array_inst: + self.graph_inst_exclude.add(self.precharge_array_inst) From ae9dbe203d6473600d5128113b327bd43ec610c1 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 3 Jul 2019 14:53:44 -0700 Subject: [PATCH 068/234] Add freepdk45 dummy cells --- .../freepdk45/gds_lib/dummy_cell_1rw_1r.gds | Bin 0 -> 16384 bytes .../freepdk45/gds_lib/dummy_cell_1w_1r.gds | Bin 0 -> 16384 bytes technology/freepdk45/gds_lib/dummy_cell_6t.gds | Bin 0 -> 20480 bytes .../freepdk45/sp_lib/dummy_cell_1rw_1r.sp | 14 ++++++++++++++ technology/freepdk45/sp_lib/dummy_cell_1w_1r.sp | 14 ++++++++++++++ technology/freepdk45/sp_lib/dummy_cell_6t.sp | 15 +++++++++++++++ 6 files changed, 43 insertions(+) create mode 100644 technology/freepdk45/gds_lib/dummy_cell_1rw_1r.gds create mode 100644 technology/freepdk45/gds_lib/dummy_cell_1w_1r.gds create mode 100644 technology/freepdk45/gds_lib/dummy_cell_6t.gds create mode 100644 technology/freepdk45/sp_lib/dummy_cell_1rw_1r.sp create mode 100644 technology/freepdk45/sp_lib/dummy_cell_1w_1r.sp create mode 100644 technology/freepdk45/sp_lib/dummy_cell_6t.sp diff --git a/technology/freepdk45/gds_lib/dummy_cell_1rw_1r.gds b/technology/freepdk45/gds_lib/dummy_cell_1rw_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..2ac1a2878c1edd041f7dbfc0da598f385ff98783 GIT binary patch literal 16384 zcmeI3TdZAG6^7T^m$f$MQf;f$+L~024@O0r2$m4Qc%f-)!KNXxLTzeK=|hXL)l!t8 zA);u2czH2eE1(iY!-HtlsQ6MNVoRh}jEIfVN<=WJi4nsC#{VC4{%ftd+;g6F_DM}l z*vaNQ9drGAj5+3g?oC!?y{yPq=e=xMHj@pr<=Lui9sXNp{cK70CUB-#%EU}$Z+-TnS6#E>(ara-$yN`gU6#$_)0*0Ii(>BJb=Q4($FAM`_U%}E z;1J$fHW+1DG25f(CA}=mUjO2Lmi2#)zkcr6dv}%%=dw(c9ULr;=%KD&<*_U~=e#Tv zs{&|a`oU}A^C~<5Qdc}wQ+6<_A0CDNk9dRBk9O9S9gOSmL46;C9vrTO_W7E!gHe6H z*6B&=`=72!y)TdId-pp%N&RqGlX_ns*YCme$X^d+{izpaPvtLr1RCUzq^`fWrtGQw z^-sI_NycB?T$Azp@@D+~X8&U!nSze5*)^{Jh_ZuGeg79(HiLdk&OQa-@2M#}7}Yax z^g~YH2mPj+vZwsB-|{(O)}P~!{bT{-FYrIX z_zUzCjK5Hiexq@waVN^&8h?R)g7FvVCm4Tuv;XBAF?Nn%o&pD3z<<}29c+%DKwqBk z^d$A=pKDU@%cJ_iTamwKpaF|J!DnmA4kq>ag-)M8?erC8zc8-1`oGQB|6AY>@EM+c zZwI6P%j;2pJV#Pz_4kxLr5~)r{PiED+}>)-a@*8B2K zdam27e?^~{RQ?uR-j{dM_a8?L zsDDL{e^cgT5ua18cK(gBC;a#Sg*)3zFlUk{k-s|{l>L&p|NK4|Kgsxem(^tazC0TL z;BGv>6n@Ej(P!V>pzKTI{`=6BD-b_8^)7r4_F!NkI~dj5eF^-N z^vm^5q<>$Y)DQmTo}*vtMcKiqzIYJze*o4q z@i+C{FH$FV)w7=C{8#qv@%FQRkMA!?es974FY@~fUmne0Q*ZMf^c6emIbV+RU)e8? z$Itdon|j9Iyie$=XPo2w%btp#{f>S}#%KW%a|FX{)Kj%s6%VREnQTEjQWjf3shmZ1 zxKjSPK5(A1bpr9*Ioeb9)co1hH_qGkIbHRv=Q#hBJu!cB+_RlY_8(h6JY`SypQfJu zhI+B9p8aH;f7!ui`%O3ZpZRYP|5og?NYtZ;@9!$gzBR5d@Vz1RM(9g?7f-!W_Jp3l z*Wj7mez$?OZ*&@3Puam}{Ka#4{%iOQaP)2bePd18!Kl96fP8-dI&kn&kYmVGb}*_R zT#elS1RAh74xXwhI~dguzv=R4MBWN~|H%9qkw0G^)%WndBlB;Bu78Wu8)Z-AKidRf z$Un)v+wVX;Wl!Zl-{ta0GH*HVphV`+mq+8zzXQK$Ka%a&yP&4*U{sHYvl*Nd_?q2` zvj={EB+3p(^*%m}Q*n!3;%DBOJL4lR|I8utU)eXs{V%%zZNdHr{&|j`-UgnmDLWXg zKi50viDce5hl#SM^4I?na=sq*B_GD;;9XJn^$GtkMcZTFJ0MTEd90%B;rFk>{59B( z{;~>s@(A=FY*6-9asM1&Y$qeyjpL5(XOumWKWa5jIDYbn+&Cg-PmP~)k9&^PyeCrc z%cJdwXf1vt;%5J6{6@rPuSEQuxANPNKd^WU$ob1tb};Fm?Z+3}jeaZ2o@l?`_u&uz zN%r6VMKxsyqyBkk!uB_!{dxbueqfY6(f+(QVE;9u?-qyfZ&CI{{~i9*#ZNMR>P5!y z%cJo#Z_`ikzZi$xUH(Mb!KmKWJksQsKctNt)L)c6 z<)3jgPbBl!NBpAfsr=>daCsuf&ELK}+W$Cj_DggSkZTy{Pf>QTsh@4`zir*a9@>aK zIQQ|~iyLL%7}wjr<8suW`;cEDmRlN>{qndz!!x!{fvi72LzEqi#$RI2uzfPfeN*{p zP1(Vy-uAawpuXG({|>Qm|0~LVMO>f1*ZC)H-}ZD(+rPQ;sDI|I2R}ymwSBWFd&0ks ze>`vdr)yDz^n)81>I}pU;uh@$4(gp3<{^e37$Xb@dlz2c!Pk zfB7P*WB(Op2cvq9AA5n+ar}s~gHb*EEng&c{OzhJI~dhl|F{Vcp#N~+&i*4#c{>=@ zk3NR}cNOwR9tIz8PS%n0VZv?;GpzPuPIn-m#v)_)BTDQcF_&itM z?0=zt8vCq{^QW&r^z-+>!RJwr*D(Lr&!HQc{{`vqMtyFhe$V@*A7OgL{xyvM4m^iB zkLQj2>);O?l>JaJ{-&DwxBG|hL9+|mb>NdV``!*V^B3rQt1(}0#hZK#@2@l{dwBm7 z=()e=UeWgXd!fAmbAYGpVAOx{S!m$L2><0W=iexM!oS_$aj*KE^K18a@K4$v7WR~X zyFWpm?EVh+w=FgW$^__eOTl1KPTAvZm~<`=20wJHMd5 zWXbkMoyEf2!D#$;e!;%S_yowlAj-ZiuDA2c=g{Y{|DRrt{lm_hQ{E0n{j>gj&hF2k zxBD|s*;9HuzdwA}j#z9i=%cK77{Bpv@&%D|B#gqB-p%Tpy8cs9_RT^5W}5R?@5flPHX%+DeV~77gR+PBPl0~;cW6;xBj%6d0RAn? z9?lG1nvJ{dX1Bg<0sIw-prp7`D6W=N2BbC{Mo#NzP5n* xXGydD7Omg1;Q8ZB(?4oky=K>7?mG|jk7reY>Mg~a$81b#FT7sJ!2fv${sTM^TUh`A literal 0 HcmV?d00001 diff --git a/technology/freepdk45/gds_lib/dummy_cell_1w_1r.gds b/technology/freepdk45/gds_lib/dummy_cell_1w_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..fa89439e38db7d4cd8f7d72c5e43a4b43284f11e GIT binary patch literal 16384 zcmeI3U94S27035JAA29}N3|_dYim+9J{T2gB3RM@#t)jd7Hk?4E7YcPOCMT{t(Kw$ z4G~2H#E%!FwE`+ZG(3n#jfyWdBDO?o#faD#twscsniw%WVEq5r%zy7a+cR_bJvTKm z;UtIO?V9~RYt7m-Yi9O2WJT7?ifnb>%a&y`*)Ut4t;*Knzh&0XmSk_t)@L)lVs7_! zyAJOAV3wWRA6~lVCx`Dnz3thHUwO@n$F@9hUbcED?XqkZpVri#TNHB#ufP67JFnfn zZ{N*0T!S}ms z$__^L%p3iX)AvKaxu)zX{~Wixj-;OBSCqY_FPiJNezE=MyyG}o z!2ApRPcZ)i{RHzb)MMOeo@w5RvbW}6pr2s=1^Nl*U)~&l`6kSrBdAm0U@Q3VnzDn< z`4i~N3!I*$zWh^7>V11uKX?oB_Y5>(aToY(P1(VuKEKH6^QWD@qU;yN_16El`u=|t z{60Rzv+wO-)PH#c`j6{K>a72svZwTeb*NuIg%+IsF!;BcvV&3oHvf+zhj^Dekh|?Q z8*OJzKlr@!P167HRW<3~w@3ZA_3ilQ)6)lQ?zsNT4o3YKShtHS@dhn_57m?%jOtAT zJ!$WM)TG|GpEZ3u{<7uYw|DYi{2B2=U$H~{tld+$xf(vb9&=$Y);~|#!KnYm>IWN~ zf0BL&r)tu_Z;$$4tiBz8+rMv*`VaIk_xbbelD{B+=*+)or~YH!+I1lF$N4MD4o2hW zyyJBwb)3JV>}ONY`anOV{ED)7_K&<-{GQbN{zdy=EO+&vWc{}_%#-!sw@3A5->)B_ ztskGRY3qk;kLuh0%a(pV|2fuN`XTAR_u87WgHiuI_~UgX_5D>fWl!nb{@Z%r9`(=b z>8H}&=lz4Sr~D75-E}16=Qt9n_wAkixAi{0sGgtCF-CH&pk9<6jOtlGcpXWdo!>lV z|6l6c@%#9a@pGLX7r*SO^*d+Hxf0_SWdHLMHDyn&-;34v_B;P1{r8@)N&mh*+W)ry zw%)gQ(sSKr|10{ur25Z2yNz?u#{FMv%ATA*i_{NqbN)&Cuj;6;tG+$j|91Rsy>IWN z?>~VU(Eo~@|E_;c{a}&jr$9f!`6Wp}w{LcUXS|{RHb@pl`2#9oC;f-(EkIM>4X01o{c;SD>F@{tlb-kK=!V=l?*@ z{&Sy4a^Kit{~qX>C+#z}?-XSRoAu+IX8gTn@Vyal^7nXuy+PSG#`VP+tT)h+ql5VS z<27XmqyCFez#se=@j2yc=iexM!hio?cxHPEY9@IS`Ma}0*)NIv&+m8flZ?N2Sxv_8 z+oSOh?!om-;g`G*WA;rA%Dy!2zYk5h0`Y@W@5JX|A12BUM*UOAXIA9!4yPAo2cvp> zUIPCl{c^n%>EE{}^@BgU>*$wyQFbt@FCIewAH@9!ZT!5VrtDx;-n$-LD zsGj}fb5iT)F&BU7DSPYrX)u3Gw`07X`!V0%$v^9z3HvdHbx%256=Q#hBJrO^j7jW$%`TZH62Z*wR z(fl{{+^;vECv?@@zI%*+*}jUeYtrLjf&e5K-r|M@@-#BmE=XBMxpX2;j_C)>Uyytx;Ieu*Y@RU6@ zewuoY8|uZbdXAHE{$&T7_iwtn|IB}l__tx7MWP=)e1BI__HA)}f$t5eH$q?HyLjr2 zvM2QXy#~+h_PY(NeWTORdddz)<1e1W^s?q=b}*_(#Muna z34G1&!r24AKN4jJqk12o#i_W(F7Y$(%$@O3mw)Dv`LFDobSh@5Xgf5}JiIe1r;eM7?kOK|V8?;VgQTpg<@d-(lp zP`?JdFN)Z|ffFEIIQwjF+2gj=UX=>aFgwPNV)(&-yD; z@7tsL>~{!!4sY^qT#p=7lzq{QqGfyP*)<^uJ?5X_aZ+Cej$JKA&9vy$IoBa|41mqgV`YFl|Huba3{kN@q z*h3q!2j@PXdvT-eo8o%gcU+GCb06|c#BytcvR@w8XSl}JDUki=XNaTQ2}1^UZ<@NW?d_rId-SH$)Cdz^pL_H9qswEdfFkNRicdhla}U)wi} zvM2o8{KxgSf4UC+Sc(0U=Zv?5QU8N?`1u2J+z)`i6>|oSC*L_|`QpdBeD0@oJ{_#c5e#P}) zlpT!v=lJD|q>kfPlpT!fIe+X0Qpfot$__^L9JhRt)bY2gqU>N)Z{y=;T!8VzeLKgG zIOXkNR6qJC#@|)Q8+jOfqCwgH|9|1vPt>pZ*Kd9o1HV|m-+Q37eg^fg+>h(#kazNK z@WBRU5BCq9{PTNQJkK@%YZLj)Z^3mpBJU(>P=35Y*>80DTS))&FXD3!oB#IyCFp;) z6W8HB8NUPKJtfNS@83fFXLr>8Tls%cu>O1!<7E{RM7{z1QiHOG`{z)PHP3!KPHNo} zH{tVKdvpAS`f2R5I@V9$f9U5Qe}m7VAFpQqZrpDHz<4f{3g(If6l$0?bG){dm-kq zr|e)e|AD^v3^ed#g#U7x^KX7@?fH`@^}ao-=QC1!en1|6{9BYg zJpTsyALN-kf0BrpdbDnTJ+b5`coXh zzeU-@`V;8s*Xkz;9sO5?-nTdN7w9Lr|No`eJn1-p0zLc9{27ry_Mdq)%AUxd)g6qr z1=OD<&HJ}#{niE7k26jG=xz0yU4z zE&9+G1rh9vg;G#a=!-s-643Y&QDT(7Xe z3zy$??eo8D?X}n5=j?rMLKDi+ge!|OTo!hP-C;GXgtvt^g{4rzaxGd{%jWofpS%0P z6JHA9%~gHl)u+Gny_ar(^@ICAyZ5=h_V|K{>SR^ z-ADQTWS4i(zwG3o|JCgHO%XH4apiI!KT&qDAAe8pey5K(spGhbvZwW)x8;-0T_5%Q ziL!$U|6}#T`01DRD<vy29e&%|Ty2%|K zsgLdR>7R=JBj?c%;$KG}+mrss>IeOYf9rqbJn@gyW9+f^OkZ{~|Ka1Fe^U0`_!S3y z{7CAHUvy;ru|1K$8UN_F=_5DxzgBPYLqA{qWA$zSte?wk;&0m%{cqd1tmpXGM|_^t zfA;!mDf^N1{A2x6Z-k!nmwKb@89n_^Zt48@^|FJ>{?F=J|BC;Ap=ZD8XTAQ*o{N91 zp7VqGHzMz>fA-%fdourCzx9zw=vepE8)e@>Ke?sT_x;PB>p$aWp4N+B_U+Sq+={d9 zckI9HY5!yO==-YDzwEjA$Lfo-o_{0yU*6;SHzNPBJ=y>88P^-35C3qz5&GDk z)w7?{_x;PB>p$b;b?e11`*!LXH~lF7e*b09`5&t<@5FwKbB;WZd4P>}OWChU*ME5@ z)`0K3p0QBxl--ydzw!D_$3N*mf6v}O=eYm&^lR6@IoAK4-q#(Dv#nF>tRHcH_VYK; z&yN2b^*_*WVf@GH>)HJ4Ii1gc%)co6%=2?k@A=nr?%L-^wGZmIr)S+-eOmp`S-;Eu z__@B*FUfuP1Nev*2wKO*Cg?aBDr zPCrJ(Pd(!|%D#br>E&0H9ZdRX-gr(y@_C8*6J?({zgUw$dtQc~=NHtAvV(K^mrk6= zKl8@xNXE^)iL&S7r_P?+K>DR#lsy-J-@kO?JpQYH;{Jv6QzOUA&WN~+Z+iSj**DNLPU`8GI#Kpq{C)q@iEUgN z|K;r%^WPzdU~w<_*N(D-$@~@H4q@r%(16oVLjS&wvV+^Eui&$RZ*mE~E36%&>|oOW zSUu~Xc_NuV&VNz%T>iN3aK703&Gj03u3POo;_b=!>DT5PXzLy3uP8g1)Q|N)JN_0w z#)6z@{4IWrAE|K@IexJ{8UGggzpH=$tq&nzKf)RaE}sH_+EI3}?|-1L&bXeWesZ)U z^|3vn$Fsv}>Ydbwn_W-Jp7UQEbpIsv#j_phKei|QdwezS+l;e$hsQ6<4kq=?8?Pg& zWBx?hb9%qzPtzbJcJ?|G{)cT&f^iL$5l=8M|*q+oEe{?-befg=5)W`OuJ{)&FNqzWBN9tpHQeWSMKA*=2Z2kuRvZL(aLXQ%e zA~ksbJedFE@`t*87@t!l#tLH)9us9J)A^sgZtY?6y6c){QTDvP+>7hap@u+v-g#F? z*}=v5C&r&STl%f%YJL7D^QeAV$Oq0??jOA=_osx^gmWVuKs=9 z(K>T6u0O?3eElVD{XX2$)^Bf5Pp`iVJ=R9tzqXpci@*NH&Oh!I z?KuUs=a*k~lpRdeFSOTt?#t`FcB_wwvKzNeKlc8&)B3UFx6pI``#j$K{R6c*_WA2i zsCW3EfV`J;JVe>SWc~N|pDWPv{95GxEw*R%+$XjBFX*}dvG)+sp4yGCb zvZwox+>ffC@%sM$SLfa$?_c@-uh)(0M0F#|o~|FydpPIhyl4JJ*|mRKMYHc8-&!KF zW^WPjF6r$B{$9PJK795p&k^zWo(kXh1it6pq1o4b`9ym3{u|lXDx+0LlpV~@K0Bqt zEToR7FQV*eJ*o`7zK=qQ;arTO=-q>#O$L#M8%|_WrOfRAzkB8~L z=Aq;KY8vPNhd9Px-`*8K;DGF$Jr9;Mrep~W~S;D*bNz!Z2PESyS;W63C z^!VA+A8OZ5Pk3_3(-WiVV9)CpR!AQ>YwWk*D2C={~zus`^@^)TR*(UZ1;*9 zWZtayB4wZ1{V(+G`a3p%s9j&5{pmTb+m}-PRyTV6lD7Ll(~o4{3 z-`W0S{*JtV*N5;OJORW!=B~$f&qmpeiTXv`X??KvegGeQk5hIs{rphefcD>G{lCF= z#ScZzmzA&1W8-9^mb(Q}zw~pF#U|@Pm2J zf3?J4&p2f_CjA!&{5t*$g*x5`owDcjXydaR|Me5@f7J2*=aijH=ikO3@pJsCfzq6ckjo#{RNy< z;H@9I3(u|PzdOnf_Q!6ezjrAg^1Yf7bEf>4&mkjfDYj?y$P;Rp*RkfPbINW^>mQBR zJ?grOdt!V~Rmz^%S9c@DPvUxzZ@#LRI?6ut=4;UZvHAkO?F}DjZ~PF0DErKtzk&a; zdj9g(-q3p+DQTB}9&JJ*$5jy^IgL zJD8Zip10|1PU@IHQTDXnmN_*oBhy{-vzM- zwv>JUp#KYfyZ4HDQ=T@RKh(`BeNa0XgYF|cnajVm+xSt-@pH<)k$y4$mu~%gjWqis zQNOGm&VQrq$@#y~^Vx6f`5U`_{6FZuhIs$k+WNKA`o;RWbL%I^ULUU?){uW>C)4-O wE$shZ=|4ZgTl?S2S1}*)5!(hl*74oh5 Date: Wed, 3 Jul 2019 14:57:47 -0700 Subject: [PATCH 069/234] Re-enable replica tests --- compiler/tests/05_dummy_array_test.py | 1 - compiler/tests/05_replica_bitcell_array_test.py | 1 - compiler/tests/05_replica_column_test.py | 1 - 3 files changed, 3 deletions(-) diff --git a/compiler/tests/05_dummy_array_test.py b/compiler/tests/05_dummy_array_test.py index 0925246d..de379a97 100755 --- a/compiler/tests/05_dummy_array_test.py +++ b/compiler/tests/05_dummy_array_test.py @@ -13,7 +13,6 @@ from globals import OPTS from sram_factory import factory import debug -@unittest.skip("SKIPPING 05_dummy_array_test") class dummy_row_test(openram_test): def runTest(self): diff --git a/compiler/tests/05_replica_bitcell_array_test.py b/compiler/tests/05_replica_bitcell_array_test.py index db1c2924..e4c38337 100755 --- a/compiler/tests/05_replica_bitcell_array_test.py +++ b/compiler/tests/05_replica_bitcell_array_test.py @@ -13,7 +13,6 @@ from globals import OPTS from sram_factory import factory import debug -@unittest.skip("SKIPPING 05_replica_bitcell_array_test") class replica_bitcell_array_test(openram_test): def runTest(self): diff --git a/compiler/tests/05_replica_column_test.py b/compiler/tests/05_replica_column_test.py index 6f81193f..8a9f03bb 100755 --- a/compiler/tests/05_replica_column_test.py +++ b/compiler/tests/05_replica_column_test.py @@ -13,7 +13,6 @@ from globals import OPTS from sram_factory import factory import debug -@unittest.skip("SKIPPING 05_replica_column_test") class replica_column_test(openram_test): def runTest(self): From 3176ae9d50272185cfdc03e102f6b4e8ef73b5aa Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 3 Jul 2019 15:12:22 -0700 Subject: [PATCH 070/234] Fix pnand2 height in bank select. Unsure how it passed before. --- compiler/modules/bank_select.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/modules/bank_select.py b/compiler/modules/bank_select.py index 5a9609ac..296cef8b 100644 --- a/compiler/modules/bank_select.py +++ b/compiler/modules/bank_select.py @@ -89,7 +89,7 @@ class bank_select(design.design): self.inv4x_nor = factory.create(module_type="pinv", height=height, size=4) self.add_mod(self.inv4x_nor) - self.nand2 = factory.create(module_type="pnand2") + self.nand2 = factory.create(module_type="pnand2", height=height) self.add_mod(self.nand2) def calculate_module_offsets(self): From 125112b562471418f54555560397f1e020a8186b Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 4 Jul 2019 10:34:14 -0700 Subject: [PATCH 071/234] Added wmask flip flop. Need work on placement still. --- compiler/base/hierarchy_spice.py | 3 ++- compiler/base/verilog.py | 33 +++++++++++++++++++++++++++---- compiler/modules/control_logic.py | 13 +++++++----- compiler/sram/sram_1bank.py | 27 ++++++++++++++++++++++--- compiler/sram/sram_base.py | 29 +++++++++++++++++++++++++-- 5 files changed, 90 insertions(+), 15 deletions(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index f4fc9d8a..496d7534 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -11,6 +11,7 @@ import os import math import tech + class spice(): """ This provides a set of useful generic types for hierarchy @@ -126,13 +127,13 @@ class spice(): """Adds a subckt/submodule to the subckt hierarchy""" self.mods.append(mod) + def connect_inst(self, args, check=True): """Connects the pins of the last instance added It is preferred to use the function with the check to find if there is a problem. The check option can be set to false where we dynamically generate groups of connections after a group of modules are generated.""" - if (check and (len(self.insts[-1].mod.pins) != len(args))): from pprint import pformat modpins_string=pformat(self.insts[-1].mod.pins) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index 1f2ebd7b..435b6912 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -18,10 +18,16 @@ class verilog: def verilog_write(self,verilog_name): """ Write a behavioral Verilog model. """ self.vf = open(verilog_name, "w") + # Determine if optional write mask is used + self.wmask_enabled = False + if self.word_size != self.write_size: + self.wmask_enabled = True self.vf.write("// OpenRAM SRAM model\n") self.vf.write("// Words: {0}\n".format(self.num_words)) - self.vf.write("// Word size: {0}\n\n".format(self.word_size)) + self.vf.write("// Word size: {0}\n".format(self.word_size)) + if self.wmask_enabled: + self.vf.write("// Write size: {0}\n\n".format(self.write_size)) self.vf.write("module {0}(\n".format(self.name)) for port in self.all_ports: @@ -32,9 +38,15 @@ class verilog: elif port in self.write_ports: self.vf.write("// Port {0}: W\n".format(port)) if port in self.readwrite_ports: - self.vf.write(" clk{0},csb{0},web{0},ADDR{0},DIN{0},DOUT{0}".format(port)) + self.vf.write(" clk{0},csb{0},web{0},".format(port)) + if self.wmask_enabled: + self.vf.write("wmask{},".format(port)) + self.vf.write("ADDR{0},DIN{0},DOUT{0}".format(port)) elif port in self.write_ports: - self.vf.write(" clk{0},csb{0},ADDR{0},DIN{0}".format(port)) + self.vf.write(" clk{0},csb{0},".format(port)) + if self.wmask_enabled: + self.vf.write("wmask{},".format(port)) + self.vf.write("ADDR{0},DIN{0}".format(port)) elif port in self.read_ports: self.vf.write(" clk{0},csb{0},ADDR{0},DOUT{0}".format(port)) # Continue for every port on a new line @@ -44,6 +56,9 @@ class verilog: self.vf.write(" parameter DATA_WIDTH = {0} ;\n".format(self.word_size)) self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_size)) + if self.wmask_enabled: + self.num_wmask = int(self.word_size/self.write_size) + self.vf.write(" parameter NUM_WMASK = {0} ;\n".format(self.num_wmask)) self.vf.write(" parameter RAM_DEPTH = 1 << ADDR_WIDTH;\n") self.vf.write(" // FIXME: This delay is arbitrary.\n") self.vf.write(" parameter DELAY = 3 ;\n") @@ -131,6 +146,8 @@ class verilog: self.vf.write(" input csb{0}; // active low chip select\n".format(port)) if port in self.readwrite_ports: self.vf.write(" input web{0}; // active low write control\n".format(port)) + if (self.wmask_enabled): + self.vf.write(" input [NUM_WMASK-1:0] wmask{0}; // write mask\n".format(port)) self.vf.write(" input [ADDR_WIDTH-1:0] ADDR{0};\n".format(port)) if port in self.write_ports: self.vf.write(" input [DATA_WIDTH-1:0] DIN{0};\n".format(port)) @@ -151,7 +168,15 @@ class verilog: self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port)) else: self.vf.write(" if (!csb{0}_reg)\n".format(port)) - self.vf.write(" mem[ADDR{0}_reg] = DIN{0}_reg;\n".format(port)) + + if self.wmask_enabled: + for mask in range(0,self.num_wmask): + lower = mask * self.write_size + upper = lower + self.write_size-1 + self.vf.write(" if(wmask[{}])\n".format(mask)) + self.vf.write(" mem[ADDR{0}_reg][{1}:{2}] = DIN{0}_reg[{1}:{2}];\n".format(port,upper,lower)) + else: + self.vf.write(" mem[ADDR{0}_reg] = DIN_reg{0};\n".format(port)) self.vf.write(" end\n") def add_read_block(self, port): diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index fa269e26..09528509 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -75,7 +75,6 @@ class control_logic(design.design): def add_pins(self): """ Add the pins to the control logic module. """ for pin in self.input_list + ["clk"]: - print(pin) self.add_pin(pin,"INPUT") for pin in self.output_list: self.add_pin(pin,"OUTPUT") @@ -317,12 +316,14 @@ class control_logic(design.design): else: self.input_list = ["csb"] - if self.word_size != self.write_size: - print(self.word_size, self.write_size) - self.input_list = ["wmask"] + # if self.word_size != self.write_size: + # self.input_list = ["wmask"] if self.port_type == "rw": self.dff_output_list = ["cs_bar", "cs", "we_bar", "we"] + # if self.word_size != self.write_size: + # self.dff_output_list.append("wm_bar") + # self.dff_output_list.append("wm") else: self.dff_output_list = ["cs_bar", "cs"] @@ -758,7 +759,9 @@ class control_logic(design.design): def route_dffs(self): if self.port_type == "rw": - dff_out_map = zip(["dout_bar_0", "dout_bar_1", "dout_1"], ["cs", "we", "we_bar"]) + #print("hi") + #if (self.word_size == self.write_size): + dff_out_map = zip(["dout_bar_0", "dout_bar_1", "dout_1"], ["cs", "we", "we_bar"]) elif self.port_type == "r": dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"]) else: diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 7025d228..6e771feb 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -45,6 +45,9 @@ class sram_1bank(sram_base): self.col_addr_dff_insts = self.create_col_addr_dff() self.data_dff_insts = self.create_data_dff() + + if (self.write_size != self.word_size): + self.wmask_dff_insts = self.create_wmask_dff() def place_instances(self): """ @@ -64,6 +67,7 @@ class sram_1bank(sram_base): row_addr_pos = [None]*len(self.all_ports) col_addr_pos = [None]*len(self.all_ports) data_pos = [None]*len(self.all_ports) + wmask_pos = [None]*len(self.all_ports) # This is M2 pitch even though it is on M1 to help stem via spacings on the trunk # The M1 pitch is for supply rail spacings @@ -101,6 +105,13 @@ class sram_1bank(sram_base): -max_gap_size - self.data_dff_insts[port].height) self.data_dff_insts[port].place(data_pos[port]) + # Add the write mask flops to the left of the din flops. + if (self.write_size != self.word_size): + if port in self.write_ports: + wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, + self.bank.height + max_gap_size + self.data_dff_insts[port].height) + self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") + if len(self.all_ports)>1: # Port 1 @@ -134,7 +145,14 @@ class sram_1bank(sram_base): data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, self.bank.height + max_gap_size + self.data_dff_insts[port].height) self.data_dff_insts[port].place(data_pos[port], mirror="MX") - + + # Add the write mask flops to the left of the din flops. + if (self.write_size != self.word_size): + if port in self.write_ports: + wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, + self.bank.height + max_gap_size + self.data_dff_insts[port].height) + self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") + def add_layout_pins(self): """ @@ -311,10 +329,13 @@ class sram_1bank(sram_base): offset=pin.center()) def graph_exclude_data_dff(self): - """Removes data dff from search graph. """ - #Data dffs are only for writing so are not useful for evaluating read delay. + """Removes data dff and wmask dff (if applicable) from search graph. """ + #Data dffs and wmask dffs are only for writing so are not useful for evaluating read delay. for inst in self.data_dff_insts: self.graph_inst_exclude.add(inst) + if (self.write_size != self.word_size): + for inst in self.wmask_dff_insts: + self.graph_inst_exclude.add(inst) def graph_exclude_addr_dff(self): """Removes data dff from search graph. """ diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 934869d8..23d0a8bd 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -276,6 +276,9 @@ class sram_base(design, verilog, lef): self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size) self.add_mod(self.data_dff) + + self.wmask_dff = dff_array(name="wmask_dff", rows=1, columns=int(self.word_size/self.write_size)) + self.add_mod(self.wmask_dff) # Create the bank module (up to four are instantiated) from bank import bank @@ -319,8 +322,7 @@ class sram_base(design, verilog, lef): self.control_logic_r = self.mod_control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, word_size=self.word_size, - write_size=self.write_size, - sram=self, + sram=self, port_type="r") self.add_mod(self.control_logic_r) @@ -447,6 +449,29 @@ class sram_base(design, verilog, lef): return insts + def create_wmask_dff(self): + """ Add and place all wmask flops """ + num_wmask = int(self.word_size/self.write_size) + insts = [] + for port in self.all_ports: + if port in self.write_ports: + insts.append(self.add_inst(name="wmask_dff{}".format(port), + mod=self.wmask_dff)) + else: + insts.append(None) + continue + + # inputs, outputs/output/bar + inputs = [] + outputs = [] + for bit in range(num_wmask): + inputs.append("wmask{}[{}]".format(port, bit)) + outputs.append("BANK_WMASK{}[{}]".format(port, bit)) + + self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"]) + + return insts + def create_control_logic(self): """ Add control logic instances """ From dd62269e0ba3bf9edd6c100cae3a847840ffa4f5 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 5 Jul 2019 08:18:58 -0700 Subject: [PATCH 072/234] Some cleanup --- compiler/debug.py | 2 +- compiler/modules/port_data.py | 18 ++++++++---------- compiler/sram/sram_config.py | 6 +++--- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/debug.py b/compiler/debug.py index f98d8380..02a28c22 100644 --- a/compiler/debug.py +++ b/compiler/debug.py @@ -85,7 +85,7 @@ def log(str): # use a static list of strings to store messages until the global paths are set up log.setup_output = [] -log.create_file = 1 +log.create_file = True def info(lev, str): diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index a03741c4..77f11c4e 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -16,7 +16,7 @@ from globals import OPTS class port_data(design.design): """ - Create the data port (column mux, sense amps, write driver, etc.) + Create the data port (column mux, sense amps, write driver, etc.) for the given port number. """ def __init__(self, sram_config, port, name=""): @@ -25,9 +25,9 @@ class port_data(design.design): self.port = port if name == "": - name = "bank_{0}_{1}".format(self.word_size, self.num_words) + name = "port_data_{0}".format(self.port) design.design.__init__(self, name) - debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words)) + debug.info(2, "create data port of size {0} with {1} words per row".format(self.word_size,self.words_per_row)) self.create_netlist() if not OPTS.netlist_only: @@ -37,7 +37,7 @@ class port_data(design.design): def create_netlist(self): - self.compute_sizes() + self.precompute_constants() self.add_pins() self.add_modules() self.create_instances() @@ -161,7 +161,7 @@ class port_data(design.design): self.column_mux_array = None - if self.port in self.write_ports or self.port in self.readwrite_ports: + if self.port in self.write_ports: self.write_driver_array = factory.create(module_type="write_driver_array", columns=self.num_cols, word_size=self.word_size) @@ -170,17 +170,15 @@ class port_data(design.design): self.write_driver_array = None - def compute_sizes(self): - """ Computes the required sizes to create the bank """ - - self.num_cols = int(self.words_per_row*self.word_size) - self.num_rows = int(self.num_words / self.words_per_row) + def precompute_constants(self): + """ Get some preliminary data ready """ # The central bus is the column address (one hot) and row address (binary) if self.col_addr_size>0: self.num_col_addr_lines = 2**self.col_addr_size else: self.num_col_addr_lines = 0 + # A space for wells or jogging m2 between modules self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclosure_active"), diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index d2ab5776..c97d63b0 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -37,7 +37,7 @@ class sram_config: def compute_sizes(self): """ Computes the organization of the memory using bitcell size by trying to make it square.""" - self.bitcell = factory.create(module_type="bitcell") + bitcell = factory.create(module_type="bitcell") debug.check(self.num_banks in [1,2,4], "Valid number of banks are 1 , 2 and 4.") @@ -48,11 +48,11 @@ class sram_config: # If this was hard coded, don't dynamically compute it! if not self.words_per_row: # Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry) - self.bank_area = self.bitcell.width*self.bitcell.height*self.num_bits_per_bank + self.bank_area = bitcell.width*bitcell.height*self.num_bits_per_bank self.bank_side_length = sqrt(self.bank_area) # Estimate the words per row given the height of the bitcell and the square side length - self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width) + self.tentative_num_cols = int(self.bank_side_length/bitcell.width) self.words_per_row = self.estimate_words_per_row(self.tentative_num_cols, self.word_size) # Estimate the number of rows given the tentative words per row From c0f9cdbc12aa0b7f4212c4001d1bd4ac6435d291 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 5 Jul 2019 09:03:52 -0700 Subject: [PATCH 073/234] Create port address module --- compiler/base/hierarchy_layout.py | 7 +++--- compiler/modules/bank.py | 3 --- compiler/modules/port_data.py | 6 ++--- compiler/tests/18_port_address_test.py | 32 ++++++++++++++++++++++++++ compiler/tests/18_port_data_test.py | 4 +--- 5 files changed, 39 insertions(+), 13 deletions(-) create mode 100755 compiler/tests/18_port_address_test.py diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 203344b5..287be926 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -227,6 +227,9 @@ class layout(): You can optionally rename the pin to a new name. """ pins=instance.get_pins(pin_name) + + debug.check(len(pins)>0,"Could not find pin {}".format(pin_name)) + for pin in pins: if new_name=="": new_name = pin.name @@ -238,9 +241,7 @@ class layout(): You can optionally rename the pin to a new name. """ for pin_name in self.pin_map.keys(): - pins=instance.get_pins(pin_name) - for pin in pins: - self.add_layout_pin(prefix+pin_name, pin.layer, pin.ll(), pin.width(), pin.height()) + self.copy_layout_pin(instance, pin_name, prefix+pin_name) def add_layout_pin_segment_center(self, text, layer, start, end): """ diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 9a274cd1..2cd557f1 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -358,9 +358,6 @@ class bank(design.design): cols=self.num_cols) self.add_mod(self.wordline_driver) - self.inv = factory.create(module_type="pinv") - self.add_mod(self.inv) - if(self.num_banks > 1): self.bank_select = factory.create(module_type="bank_select") self.add_mod(self.bank_select) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 77f11c4e..ab594c09 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -1,8 +1,6 @@ # 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) +# Copyright (c) 2016-2019 Regents of the University of California # All rights reserved. # import sys @@ -72,7 +70,7 @@ class port_data(design.design): self.DRC_LVS() def add_pins(self): - """ Adding pins for Bank module""" + """ Adding pins for port address module""" for bit in range(self.num_cols): self.add_pin(self.bl_names[self.port]+"_{0}".format(bit),"INOUT") self.add_pin(self.br_names[self.port]+"_{0}".format(bit),"INOUT") diff --git a/compiler/tests/18_port_address_test.py b/compiler/tests/18_port_address_test.py new file mode 100755 index 00000000..c8db6ec2 --- /dev/null +++ b/compiler/tests/18_port_address_test.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# 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 port_address_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + debug.info(1, "Port address 16 rows") + a = factory.create("port_address", cols=16, rows=16) + 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()) diff --git a/compiler/tests/18_port_data_test.py b/compiler/tests/18_port_data_test.py index 7bd5837d..5d72e405 100755 --- a/compiler/tests/18_port_data_test.py +++ b/compiler/tests/18_port_data_test.py @@ -1,9 +1,7 @@ #!/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) +# Copyright (c) 2016-2019 Regents of the University of California # All rights reserved. # import unittest From 4c6556f1bcb91dd6064ddcd574c51b56089d6d6f Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 5 Jul 2019 09:04:48 -0700 Subject: [PATCH 074/234] Add port address module --- compiler/modules/port_address.py | 157 +++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 compiler/modules/port_address.py diff --git a/compiler/modules/port_address.py b/compiler/modules/port_address.py new file mode 100644 index 00000000..b01a502a --- /dev/null +++ b/compiler/modules/port_address.py @@ -0,0 +1,157 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# All rights reserved. +# +import sys +from tech import drc, parameter +from math import log +import debug +import design +from sram_factory import factory +from vector import vector + +from globals import OPTS + +class port_address(design.design): + """ + Create the address port (row decoder and wordline driver).. + """ + + def __init__(self, cols, rows, name=""): + + self.num_cols = cols + self.num_rows = rows + self.addr_size = int(log(self.num_rows, 2)) + + if name == "": + name = "port_address_{0}_{1}".format(cols,rows) + design.design.__init__(self, name) + debug.info(2, "create data port of cols {0} rows {1}".format(cols,rows)) + + self.create_netlist() + if not OPTS.netlist_only: + debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.") + self.create_layout() + self.add_boundary() + + + def create_netlist(self): + self.add_pins() + self.add_modules() + self.create_row_decoder() + self.create_wordline_driver() + + def create_layout(self): + self.place_instances() + self.route_layout() + self.DRC_LVS() + + def add_pins(self): + """ Adding pins for port address module""" + + for bit in range(self.addr_size): + self.add_pin("addr_{0}".format(bit),"INPUT") + + self.add_pin("wl_en", "INPUT") + + for bit in range(self.num_rows): + self.add_pin("wl_{0}".format(bit),"OUTPUT") + + self.add_pin("vdd","POWER") + self.add_pin("gnd","GROUND") + + + def route_layout(self): + """ Create routing amoung the modules """ + self.route_pins() + self.route_internal() + self.route_supplies() + + def route_supplies(self): + """ Propagate all vdd/gnd pins up to this level for all modules """ + for inst in self.insts: + self.copy_power_pins(inst,"vdd") + self.copy_power_pins(inst,"gnd") + + def route_pins(self): + for row in range(self.addr_size): + decoder_name = "addr_{}".format(row) + self.copy_layout_pin(self.row_decoder_inst, decoder_name) + + for row in range(self.num_rows): + driver_name = "wl_{}".format(row) + self.copy_layout_pin(self.wordline_driver_inst, driver_name) + + def route_internal(self): + for row in range(self.num_rows): + # The pre/post is to access the pin from "outside" the cell to avoid DRCs + decoder_out_pos = self.row_decoder_inst.get_pin("decode_{}".format(row)).rc() + driver_in_pos = self.wordline_driver_inst.get_pin("in_{}".format(row)).lc() + mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0) + mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1) + self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos]) + + def add_modules(self): + + self.row_decoder = factory.create(module_type="decoder", + rows=self.num_rows) + self.add_mod(self.row_decoder) + + self.wordline_driver = factory.create(module_type="wordline_driver", + rows=self.num_rows, + cols=self.num_cols) + self.add_mod(self.wordline_driver) + + + def create_row_decoder(self): + """ Create the hierarchical row decoder """ + + self.row_decoder_inst = self.add_inst(name="row_decoder", + mod=self.row_decoder) + + temp = [] + for bit in range(self.addr_size): + temp.append("addr_{0}".format(bit)) + for row in range(self.num_rows): + temp.append("dec_out_{0}".format(row)) + temp.extend(["vdd", "gnd"]) + self.connect_inst(temp) + + + + def create_wordline_driver(self): + """ Create the Wordline Driver """ + + self.wordline_driver_inst = self.add_inst(name="wordline_driver", + mod=self.wordline_driver) + + temp = [] + for row in range(self.num_rows): + temp.append("dec_out_{0}".format(row)) + for row in range(self.num_rows): + temp.append("wl_{0}".format(row)) + temp.append("wl_en") + temp.append("vdd") + temp.append("gnd") + self.connect_inst(temp) + + + + def place_instances(self): + """ + Compute the offsets and place the instances. + """ + + # A space for wells or jogging m2 + self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclosure_active"), + 3*self.m2_pitch) + + row_decoder_offset = vector(0,0) + wordline_driver_offset = vector(self.row_decoder.width + self.m2_gap,0) + + self.wordline_driver_inst.place(wordline_driver_offset) + self.row_decoder_inst.place(row_decoder_offset) + + self.height = self.row_decoder.height + self.width = self.wordline_driver_inst.rx() From bfe4213fce95f1bf710a4e76d935fbc0c8ff5e09 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 5 Jul 2019 09:44:42 -0700 Subject: [PATCH 075/234] Port address added to entire SRAM. --- compiler/modules/bank.py | 139 ++++++++++--------------------- compiler/modules/port_address.py | 6 ++ 2 files changed, 49 insertions(+), 96 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 2cd557f1..523f34df 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -107,8 +107,7 @@ class bank(design.design): for port in self.all_ports: self.route_bitlines(port) - self.route_wordline_driver(port) - self.route_row_decoder(port) + self.route_port_address(port) self.route_column_address_lines(port) self.route_control_lines(port) if self.num_banks > 1: @@ -131,8 +130,7 @@ class bank(design.design): self.create_bitcell_array() self.create_port_data() - self.create_row_decoder() - self.create_wordline_driver() + self.create_port_address() self.create_column_decoder() self.create_bank_select() @@ -142,8 +140,7 @@ class bank(design.design): """ self.port_data_offsets = [None]*len(self.all_ports) - self.wordline_driver_offsets = [None]*len(self.all_ports) - self.row_decoder_offsets = [None]*len(self.all_ports) + self.port_address_offsets = [None]*len(self.all_ports) self.column_decoder_offsets = [None]*len(self.all_ports) self.bank_select_offsets = [None]*len(self.all_ports) @@ -180,16 +177,14 @@ class bank(design.design): # UPPER LEFT QUADRANT # To the left of the bitcell array # The wordline driver is placed to the right of the main decoder width. - x_offset = self.m2_gap + self.wordline_driver.width - self.wordline_driver_offsets[port] = vector(-x_offset,0) - x_offset += self.row_decoder.width + self.m2_gap - self.row_decoder_offsets[port] = vector(-x_offset,0) + x_offset = self.m2_gap + self.port_address.width + self.port_address_offsets[port] = vector(-x_offset,0) # LOWER LEFT QUADRANT # Place the col decoder left aligned with wordline driver plus halfway under row decoder # Place the col decoder left aligned with row decoder (x_offset doesn't change) # Below the bitcell array with well spacing - x_offset = self.central_bus_width[port] + self.wordline_driver.width + x_offset = self.central_bus_width[port] + self.port_address.wordline_driver.width if self.col_addr_size > 0: x_offset += self.column_decoder.width + self.col_addr_bus_width y_offset = self.m2_gap + self.column_decoder.height @@ -202,7 +197,7 @@ class bank(design.design): if self.col_addr_size > 0: y_offset = min(self.column_decoder_offsets[port].y, self.port_data[port].column_mux_offset.y) else: - y_offset = self.row_decoder_offsets[port].y + y_offset = self.port_address_offsets[port].y if self.num_banks > 1: y_offset += self.bank_select.height + drc("well_to_well") self.bank_select_offsets[port] = vector(-x_offset,-y_offset) @@ -224,15 +219,13 @@ class bank(design.design): # LOWER RIGHT QUADRANT # To the left of the bitcell array # The wordline driver is placed to the right of the main decoder width. - x_offset = self.bitcell_array_right + self.wordline_driver.width - self.wordline_driver_offsets[port] = vector(x_offset,0) - x_offset += self.row_decoder.width + self.m2_gap - self.row_decoder_offsets[port] = vector(x_offset,0) + x_offset = self.bitcell_array_right + self.port_address.width + self.m2_gap + self.port_address_offsets[port] = vector(x_offset,0) # UPPER RIGHT QUADRANT # Place the col decoder right aligned with wordline driver plus halfway under row decoder # Above the bitcell array with a well spacing - x_offset = self.bitcell_array_right + self.central_bus_width[port] + self.wordline_driver.width + x_offset = self.bitcell_array_right + self.central_bus_width[port] + self.port_address.wordline_driver.width if self.col_addr_size > 0: x_offset += self.column_decoder.width + self.col_addr_bus_width y_offset = self.bitcell_array_top + self.m2_gap + self.column_decoder.height @@ -246,7 +239,7 @@ class bank(design.design): y_offset = max(self.column_decoder_offsets[port].y + self.column_decoder.height, self.port_data[port].column_mux_offset.y + self.port_data[port].column_mux_array.height) else: - y_offset = self.row_decoder_offsets[port].y + y_offset = self.port_address_offsets[port].y self.bank_select_offsets[port] = vector(x_offset,y_offset) def place_instances(self): @@ -261,8 +254,7 @@ class bank(design.design): self.place_port_data(self.port_data_offsets) # UPPER LEFT QUADRANT - self.place_row_decoder(self.row_decoder_offsets) - self.place_wordline_driver(self.wordline_driver_offsets) + self.place_port_address(self.port_address_offsets) # LOWER LEFT QUADRANT self.place_column_decoder(self.column_decoder_offsets) @@ -349,15 +341,12 @@ class bank(design.design): self.port_data.append(temp_pre) self.add_mod(self.port_data[port]) - self.row_decoder = factory.create(module_type="decoder", - rows=self.num_rows) - self.add_mod(self.row_decoder) - - self.wordline_driver = factory.create(module_type="wordline_driver", - rows=self.num_rows, - cols=self.num_cols) - self.add_mod(self.wordline_driver) + self.port_address = factory.create(module_type="port_address", + cols=self.num_cols, + rows=self.num_rows) + self.add_mod(self.port_address) + if(self.num_banks > 1): self.bank_select = factory.create(module_type="bank_select") self.add_mod(self.bank_select) @@ -430,24 +419,25 @@ class bank(design.design): mirror = "MX" self.port_data_inst[port].place(offset=offsets[port], mirror=mirror) - def create_row_decoder(self): + def create_port_address(self): """ Create the hierarchical row decoder """ - self.row_decoder_inst = [None]*len(self.all_ports) + self.port_address_inst = [None]*len(self.all_ports) for port in self.all_ports: - self.row_decoder_inst[port] = self.add_inst(name="row_decoder{}".format(port), - mod=self.row_decoder) + self.port_address_inst[port] = self.add_inst(name="port_address{}".format(port), + mod=self.port_address) 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)) for row in range(self.num_rows): - temp.append("dec_out{0}_{1}".format(port,row)) + temp.append(self.wl_names[port]+"_{0}".format(row)) temp.extend(["vdd", "gnd"]) self.connect_inst(temp) - def place_row_decoder(self, offsets): + def place_port_address(self, offsets): """ Place the hierarchical row decoder """ debug.check(len(offsets)>=len(self.all_ports), "Insufficient offsets to place row decoder array.") @@ -463,39 +453,7 @@ class bank(design.design): mirror = "MY" else: mirror = "R0" - self.row_decoder_inst[port].place(offset=offsets[port], mirror=mirror) - - - def create_wordline_driver(self): - """ Create the Wordline Driver """ - - self.wordline_driver_inst = [None]*len(self.all_ports) - for port in self.all_ports: - self.wordline_driver_inst[port] = self.add_inst(name="wordline_driver{}".format(port), - mod=self.wordline_driver) - - temp = [] - for row in range(self.num_rows): - temp.append("dec_out{0}_{1}".format(port,row)) - for row in range(self.num_rows): - temp.append(self.wl_names[port]+"_{0}".format(row)) - temp.append(self.prefix+"wl_en{0}".format(port)) - temp.append("vdd") - temp.append("gnd") - self.connect_inst(temp) - - - def place_wordline_driver(self, offsets): - """ Place the Wordline Driver """ - - debug.check(len(offsets)>=len(self.all_ports), "Insufficient offsets to place wordline driver array.") - - for port in self.all_ports: - if port%2 == 1: - mirror = "MY" - else: - mirror = "R0" - self.wordline_driver_inst[port].place(offset=offsets[port], mirror=mirror) + self.port_address_inst[port].place(offset=offsets[port], mirror=mirror) def create_column_decoder(self): @@ -699,7 +657,7 @@ class bank(design.design): width=data_pin.width()) - def route_row_decoder(self, port): + def route_port_address_in(self, port): """ Routes the row decoder inputs and supplies """ # Create inputs for the row address lines @@ -707,7 +665,7 @@ class bank(design.design): addr_idx = row + self.col_addr_size decoder_name = "addr_{}".format(row) addr_name = "addr{0}_{1}".format(port,addr_idx) - self.copy_layout_pin(self.row_decoder_inst[port], decoder_name, addr_name) + self.copy_layout_pin(self.port_address_inst[port], decoder_name, addr_name) def route_port_data_in(self, port): @@ -776,47 +734,36 @@ class bank(design.design): vector(top_br.x,yoffset), top_br]) - def route_wordline_driver(self, port): + def route_port_address(self, port): """ Connect Wordline driver to bitcell array wordline """ + + self.route_port_address_in(port) + if port%2: - self.route_wordline_driver_right(port) + self.route_port_address_right(port) else: - self.route_wordline_driver_left(port) + self.route_port_address_left(port) - def route_wordline_driver_left(self, port): + def route_port_address_left(self, port): """ Connecting Wordline driver output to Bitcell WL connection """ for row in range(self.num_rows): - # The pre/post is to access the pin from "outside" the cell to avoid DRCs - decoder_out_pos = self.row_decoder_inst[port].get_pin("decode_{}".format(row)).rc() - driver_in_pos = self.wordline_driver_inst[port].get_pin("in_{}".format(row)).lc() - mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0) - mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1) - self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos]) - # The mid guarantees we exit the input cell to the right. - driver_wl_pos = self.wordline_driver_inst[port].get_pin("wl_{}".format(row)).rc() + driver_wl_pos = self.port_address_inst[port].get_pin("wl_{}".format(row)).rc() bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.wl_names[port]+"_{}".format(row)).lc() - mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.wordline_driver_inst[port].rx() + 0.5*self.bitcell_array_inst.lx(),0) + mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.port_address_inst[port].rx() + 0.5*self.bitcell_array_inst.lx(),0) mid2 = mid1.scale(1,0)+bitcell_wl_pos.scale(0.5,1) self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos]) - def route_wordline_driver_right(self, port): + def route_port_address_right(self, port): """ Connecting Wordline driver output to Bitcell WL connection """ for row in range(self.num_rows): - # The pre/post is to access the pin from "outside" the cell to avoid DRCs - decoder_out_pos = self.row_decoder_inst[port].get_pin("decode_{}".format(row)).lc() - driver_in_pos = self.wordline_driver_inst[port].get_pin("in_{}".format(row)).rc() - mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0) - mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1) - self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos]) - # The mid guarantees we exit the input cell to the right. - driver_wl_pos = self.wordline_driver_inst[port].get_pin("wl_{}".format(row)).lc() + driver_wl_pos = self.port_address_inst[port].get_pin("wl_{}".format(row)).lc() bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.wl_names[port]+"_{}".format(row)).rc() - mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.wordline_driver_inst[port].lx() + 0.5*self.bitcell_array_inst.rx(),0) + mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.port_address_inst[port].lx() + 0.5*self.bitcell_array_inst.rx(),0) mid2 = mid1.scale(1,0)+bitcell_wl_pos.scale(0,1) self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos]) @@ -931,10 +878,10 @@ class bank(design.design): # clk to wordline_driver control_signal = self.prefix+"wl_en{}".format(port) if port%2: - pin_pos = self.wordline_driver_inst[port].get_pin("en_bar").uc() + pin_pos = self.port_address_inst[port].get_pin("wl_en").uc() mid_pos = pin_pos + vector(0,self.m2_gap) # to route down to the top of the bus else: - pin_pos = self.wordline_driver_inst[port].get_pin("en_bar").bc() + pin_pos = self.port_address_inst[port].get_pin("wl_en").bc() mid_pos = pin_pos - vector(0,self.m2_gap) # to route down to the top of the bus control_x_offset = self.bus_xoffset[port][control_signal].x control_pos = vector(control_x_offset, mid_pos.y) @@ -980,14 +927,14 @@ class bank(design.design): #Decoder is assumed to have settled before the negative edge of the clock. Delay model relies on this assumption stage_effort_list = [] wordline_cout = self.bitcell_array.get_wordline_cin() + external_cout - stage_effort_list += self.wordline_driver.determine_wordline_stage_efforts(wordline_cout,inp_is_rise) + 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. - return self.wordline_driver.get_wl_en_cin() + return self.port_address.wordline_driver.get_wl_en_cin() def get_w_en_cin(self): """Get the relative capacitance of all the clk connections in the bank""" diff --git a/compiler/modules/port_address.py b/compiler/modules/port_address.py index b01a502a..bfa34710 100644 --- a/compiler/modules/port_address.py +++ b/compiler/modules/port_address.py @@ -82,6 +82,9 @@ class port_address(design.design): for row in range(self.num_rows): driver_name = "wl_{}".format(row) self.copy_layout_pin(self.wordline_driver_inst, driver_name) + + # FIXME: Is this still inverted!? + self.copy_layout_pin(self.wordline_driver_inst, "en_bar", "wl_en") def route_internal(self): for row in range(self.num_rows): @@ -91,6 +94,9 @@ class port_address(design.design): mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0) mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1) self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos]) + + + def add_modules(self): From f542613d784663be871301d47d2cb04530ab29e5 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 5 Jul 2019 10:31:05 -0700 Subject: [PATCH 076/234] Correct wordline_driver enable to en, not en_bar. --- compiler/modules/port_address.py | 3 +-- compiler/modules/wordline_driver.py | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/modules/port_address.py b/compiler/modules/port_address.py index bfa34710..0a624c60 100644 --- a/compiler/modules/port_address.py +++ b/compiler/modules/port_address.py @@ -83,8 +83,7 @@ class port_address(design.design): driver_name = "wl_{}".format(row) self.copy_layout_pin(self.wordline_driver_inst, driver_name) - # FIXME: Is this still inverted!? - self.copy_layout_pin(self.wordline_driver_inst, "en_bar", "wl_en") + self.copy_layout_pin(self.wordline_driver_inst, "en", "wl_en") def route_internal(self): for row in range(self.num_rows): diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index 97af8b2a..b29901c5 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -54,7 +54,7 @@ class wordline_driver(design.design): # Outputs from wordline_driver. for i in range(self.rows): self.add_pin("wl_{0}".format(i)) - self.add_pin("en_bar") + self.add_pin("en") self.add_pin("vdd") self.add_pin("gnd") @@ -109,7 +109,7 @@ class wordline_driver(design.design): # add nand 2 self.nand_inst.append(self.add_inst(name=name_nand, mod=self.nand2)) - self.connect_inst(["en_bar", + self.connect_inst(["en", "in_{0}".format(row), "wl_bar_{0}".format(row), "vdd", "gnd"]) @@ -151,7 +151,7 @@ class wordline_driver(design.design): """ Route all of the signals """ # Wordline enable connection - en_pin=self.add_layout_pin(text="en_bar", + en_pin=self.add_layout_pin(text="en", layer="metal2", offset=[self.m1_width + 2*self.m1_space,0], width=self.m2_width, @@ -162,7 +162,7 @@ class wordline_driver(design.design): nand_inst = self.nand_inst[row] inv2_inst = self.inv2_inst[row] - # en_bar connection + # en connection a_pin = nand_inst.get_pin("A") a_pos = a_pin.lc() clk_offset = vector(en_pin.bc().x,a_pos.y) From 150259e2bada95b53c554a5f712d9b42ca41e88c Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 5 Jul 2019 11:40:02 -0700 Subject: [PATCH 077/234] Added write_size to control_logic_r parameters. --- compiler/sram/sram_base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 3477c2e0..821c75d4 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -324,6 +324,7 @@ class sram_base(design, verilog, lef): self.control_logic_r = self.mod_control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, word_size=self.word_size, + write_size=self.write_size, sram=self, port_type="r") self.add_mod(self.control_logic_r) From b9d993c88b6cfa1b152c3145c8cd9b010b7a0154 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 5 Jul 2019 12:57:12 -0700 Subject: [PATCH 078/234] Add dummy bitcell module. Modify bitcell logic to guess if bitcell is not "bitcell" No longer need to specify replica (and dummy) bitcell explicitly Add support for 1 or 2 port replica array. --- compiler/bitcells/dummy_bitcell_1rw_1r.py | 53 +++++++++++++ compiler/bitcells/dummy_bitcell_1w_1r.py | 51 ++++++++++++ compiler/globals.py | 36 +++++---- compiler/modules/bank.py | 38 ++++----- compiler/modules/replica_bitcell_array.py | 77 +++++++++++-------- compiler/modules/replica_column.py | 5 +- compiler/options.py | 1 + compiler/sram/sram_base.py | 3 - .../tests/05_bitcell_1rw_1r_array_test.py | 1 - .../tests/05_replica_bitcell_array_test.py | 11 ++- compiler/tests/05_replica_column_test.py | 6 +- .../14_replica_bitline_multiport_test.py | 2 + 12 files changed, 208 insertions(+), 76 deletions(-) create mode 100644 compiler/bitcells/dummy_bitcell_1rw_1r.py create mode 100644 compiler/bitcells/dummy_bitcell_1w_1r.py diff --git a/compiler/bitcells/dummy_bitcell_1rw_1r.py b/compiler/bitcells/dummy_bitcell_1rw_1r.py new file mode 100644 index 00000000..189c4894 --- /dev/null +++ b/compiler/bitcells/dummy_bitcell_1rw_1r.py @@ -0,0 +1,53 @@ +# 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 design +import debug +import utils +from tech import GDS,layer,drc,parameter + +class dummy_bitcell_1rw_1r(design.design): + """ + A single bit cell which is forced to store a 0. + This module implements the single memory cell used in the design. It + is a hand-made cell, so the layout and netlist should be available in + the technology library. """ + + pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "OUTPUT", "OUTPUT", "INPUT", "INPUT", "POWER", "GROUND"] + (width,height) = utils.get_libcell_size("dummy_cell_1rw_1r", GDS["unit"], layer["boundary"]) + pin_map = utils.get_libcell_pins(pin_names, "dummy_cell_1rw_1r", GDS["unit"]) + + def __init__(self, name=""): + # Ignore the name argument + design.design.__init__(self, "dummy_cell_1rw_1r") + debug.info(2, "Create dummy bitcell 1rw+1r object") + + self.width = dummy_bitcell_1rw_1r.width + self.height = dummy_bitcell_1rw_1r.height + self.pin_map = dummy_bitcell_1rw_1r.pin_map + self.add_pin_types(self.type_list) + + def get_wl_cin(self): + """Return the relative capacitance of the access transistor gates""" + #This is a handmade cell so the value must be entered in the tech.py file or estimated. + #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. + #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. + access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] + return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Multiport bitcell timing graph is too complex + to use the add_graph_edges function.""" + pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} + #Edges hardcoded here. Essentially wl->bl/br for both ports. + # Port 0 edges + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) + # Port 1 edges + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) diff --git a/compiler/bitcells/dummy_bitcell_1w_1r.py b/compiler/bitcells/dummy_bitcell_1w_1r.py new file mode 100644 index 00000000..95d514f8 --- /dev/null +++ b/compiler/bitcells/dummy_bitcell_1w_1r.py @@ -0,0 +1,51 @@ +# 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 design +import debug +import utils +from tech import GDS,layer,drc,parameter + +class dummy_bitcell_1w_1r(design.design): + """ + A single bit cell which is forced to store a 0. + This module implements the single memory cell used in the design. It + is a hand-made cell, so the layout and netlist should be available in + the technology library. """ + + pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"] + type_list = ["OUTPUT", "OUTPUT", "INPUT", "INPUT", "INPUT", "INPUT", "POWER", "GROUND"] + (width,height) = utils.get_libcell_size("dummy_cell_1w_1r", GDS["unit"], layer["boundary"]) + pin_map = utils.get_libcell_pins(pin_names, "dummy_cell_1w_1r", GDS["unit"]) + + def __init__(self, name=""): + # Ignore the name argument + design.design.__init__(self, "dummy_cell_1w_1r") + debug.info(2, "Create dummy bitcell 1w+1r object") + + self.width = dummy_bitcell_1w_1r.width + self.height = dummy_bitcell_1w_1r.height + self.pin_map = dummy_bitcell_1w_1r.pin_map + self.add_pin_types(self.type_list) + + def get_wl_cin(self): + """Return the relative capacitance of the access transistor gates""" + #This is a handmade cell so the value must be entered in the tech.py file or estimated. + #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. + #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. + access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] + return 2*access_tx_cin + + def build_graph(self, graph, inst_name, port_nets): + """Adds edges to graph. Multiport bitcell timing graph is too complex + to use the add_graph_edges function.""" + pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} + #Edges hardcoded here. Essentially wl->bl/br for both ports. + # Port 0 edges + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) + # Port 1 is a write port, so its timing is not considered here. diff --git a/compiler/globals.py b/compiler/globals.py index 40daddce..c29cd081 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -169,11 +169,12 @@ def setup_bitcell(): # If we have non-1rw ports, # and the user didn't over-ride the bitcell manually, # figure out the right bitcell to use - if (OPTS.bitcell=="bitcell" and OPTS.replica_bitcell=="replica_bitcell"): + if (OPTS.bitcell=="bitcell"): if (OPTS.num_rw_ports==1 and OPTS.num_w_ports==0 and OPTS.num_r_ports==0): OPTS.bitcell = "bitcell" OPTS.replica_bitcell = "replica_bitcell" + OPTS.dummy_bitcell = "dummy_bitcell" else: ports = "" if OPTS.num_rw_ports>0: @@ -185,21 +186,26 @@ def setup_bitcell(): OPTS.bitcell = "bitcell_"+ports OPTS.replica_bitcell = "replica_bitcell_"+ports - - # See if a custom bitcell exists - from importlib import find_loader - try: - __import__(OPTS.bitcell) - __import__(OPTS.replica_bitcell) - except ImportError: - # Use the pbitcell if we couldn't find a custom bitcell - # or its custom replica bitcell - # Use the pbitcell (and give a warning if not in unit test mode) - OPTS.bitcell = "pbitcell" - OPTS.replica_bitcell = "replica_pbitcell" - if not OPTS.is_unit_test: - debug.warning("Using the parameterized bitcell which may have suboptimal density.") + OPTS.dummy_bitcell = "dummy_bitcell_"+ports + else: + OPTS.replica_bitcell = "replica_" + OPTS.bitcell + OPTS.replica_bitcell = "dummy_" + OPTS.bitcell + # See if bitcell exists + from importlib import find_loader + try: + __import__(OPTS.bitcell) + __import__(OPTS.replica_bitcell) + __import__(OPTS.dummy_bitcell) + except ImportError: + # Use the pbitcell if we couldn't find a custom bitcell + # or its custom replica bitcell + # Use the pbitcell (and give a warning if not in unit test mode) + OPTS.bitcell = "pbitcell" + OPTS.replica_bitcell = "replica_pbitcell" + OPTS.replica_bitcell = "dummy_pbitcell" + if not OPTS.is_unit_test: + debug.warning("Using the parameterized bitcell which may have suboptimal density.") debug.info(1,"Using bitcell: {}".format(OPTS.bitcell)) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 523f34df..841f99b1 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -148,11 +148,12 @@ class bank(design.design): # The center point for these cells are the upper-right corner of # the bitcell array. - # The decoder/driver logic is placed on the right and mirrored on Y-axis. - # The write/sense/precharge/mux is placed on the top and mirrored on the X-axis. - + # The port address decoder/driver logic is placed on the right and mirrored on X- and Y-axis. + # The port data write/sense/precharge/mux is placed on the top and mirrored on the X-axis. self.bitcell_array_top = self.bitcell_array.height - self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap + self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap + # Offset past the dummy/RBL column + self.bitcell_array_left = 2*self.bitcell.width self.compute_instance_port0_offsets() if len(self.all_ports)==2: @@ -161,7 +162,7 @@ class bank(design.design): def compute_instance_port0_offsets(self): """ - Compute the instance offsets for port0. + Compute the instance offsets for port0 on the left/bottom of the bank. """ port = 0 @@ -172,17 +173,15 @@ class bank(design.design): # LOWER RIGHT QUADRANT # Below the bitcell array - self.port_data_offsets[port] = vector(0,0) + self.port_data_offsets[port] = vector(self.bitcell_array_left,0) # UPPER LEFT QUADRANT # To the left of the bitcell array - # The wordline driver is placed to the right of the main decoder width. x_offset = self.m2_gap + self.port_address.width self.port_address_offsets[port] = vector(-x_offset,0) # LOWER LEFT QUADRANT - # Place the col decoder left aligned with wordline driver plus halfway under row decoder - # Place the col decoder left aligned with row decoder (x_offset doesn't change) + # Place the col decoder left aligned with wordline driver # Below the bitcell array with well spacing x_offset = self.central_bus_width[port] + self.port_address.wordline_driver.width if self.col_addr_size > 0: @@ -204,7 +203,7 @@ class bank(design.design): def compute_instance_port1_offsets(self): """ - Compute the instance offsets for port1 on the top of the bank. + Compute the instance offsets for port1 on the right/top of the bank. """ port=1 @@ -218,12 +217,11 @@ class bank(design.design): # LOWER RIGHT QUADRANT # To the left of the bitcell array - # The wordline driver is placed to the right of the main decoder width. x_offset = self.bitcell_array_right + self.port_address.width + self.m2_gap self.port_address_offsets[port] = vector(x_offset,0) # UPPER RIGHT QUADRANT - # Place the col decoder right aligned with wordline driver plus halfway under row decoder + # Place the col decoder right aligned with wordline driver # Above the bitcell array with a well spacing x_offset = self.bitcell_array_right + self.central_bus_width[port] + self.port_address.wordline_driver.width if self.col_addr_size > 0: @@ -247,16 +245,12 @@ class bank(design.design): self.compute_instance_offsets() - # UPPER RIGHT QUADRANT self.place_bitcell_array(self.bitcell_array_offset) - # LOWER RIGHT QUADRANT self.place_port_data(self.port_data_offsets) - # UPPER LEFT QUADRANT self.place_port_address(self.port_address_offsets) - # LOWER LEFT QUADRANT self.place_column_decoder(self.column_decoder_offsets) self.place_bank_select(self.bank_select_offsets) @@ -274,11 +268,6 @@ class bank(design.design): debug.check(self.num_rows*self.num_cols==self.word_size*self.num_words,"Invalid bank sizes.") debug.check(self.addr_size==self.col_addr_size + self.row_addr_size,"Invalid address break down.") - # Width for the vdd/gnd rails - self.supply_rail_width = 4*self.m2_width - # FIXME: This spacing should be width dependent... - self.supply_rail_pitch = self.supply_rail_width + 4*self.m2_space - # The order of the control signals on the control bus: self.input_control_signals = [] port_num = 0 @@ -328,7 +317,7 @@ class bank(design.design): self.wl_names = self.bitcell.list_all_wl_names() self.bitline_names = self.bitcell.list_all_bitline_names() - self.bitcell_array = factory.create(module_type="bitcell_array", + self.bitcell_array = factory.create(module_type="replica_bitcell_array", cols=self.num_cols, rows=self.num_rows) self.add_mod(self.bitcell_array) @@ -358,11 +347,14 @@ class bank(design.design): self.bitcell_array_inst=self.add_inst(name="bitcell_array", mod=self.bitcell_array) - + print(self.bitcell_array.pins) temp = [] for col in range(self.num_cols): for bitline in self.bitline_names: temp.append(bitline+"_{0}".format(col)) + for col in range(2): + for bitline in self.bitline_names: + temp.append("replica_"+bitline+"_{0}".format(col)) for row in range(self.num_rows): for wordline in self.wl_names: temp.append(wordline+"_{0}".format(row)) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 0bf635ca..feab1cce 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -22,13 +22,18 @@ class replica_bitcell_array(design.design): Dummy are the outside columns/rows with WL and BL tied to gnd. Requires a regular bitcell array, replica bitcell, and dummy bitcell (Bl/BR disconnected). """ - def __init__(self, cols, rows, name): + def __init__(self, cols, rows, num_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)) self.column_size = cols self.row_size = rows + self.num_ports = num_ports + + # Two dummy rows/cols plus replica for each port + self.extra_rows = 2 + self.num_ports + self.extra_cols = 2 + self.num_ports self.create_netlist() if not OPTS.netlist_only: @@ -80,19 +85,20 @@ class replica_bitcell_array(design.design): # Replica bitline self.replica_column = factory.create(module_type="replica_column", - rows=self.row_size + 4) + rows=self.row_size + self.extra_rows, + num_ports = self.num_ports) self.add_mod(self.replica_column) # Dummy row self.dummy_row = factory.create(module_type="dummy_array", - rows=1, - cols=self.column_size) + cols=self.column_size, + rows=1) self.add_mod(self.dummy_row) # Dummy col self.dummy_col = factory.create(module_type="dummy_array", cols=1, - rows=self.row_size + 4) + rows=self.row_size + self.extra_rows) self.add_mod(self.dummy_col) @@ -103,27 +109,33 @@ class replica_bitcell_array(design.design): self.bl_names = [x for x in self.bitcell_array.pins if x.startswith("b")] # top/bottom rows (in the middle) - self.replica_wl_names = ["replica_"+x for x in self.cell.pins if x.startswith("w")] - self.dummy_wl_names = ["dummy_"+x for x in self.cell.pins if x.startswith("w")] - self.dummy_bl_names = ["dummy_"+x for x in self.cell.pins if x.startswith("b")] + self.replica_wl_names = ["replica_"+x for x in self.cell.list_all_wl_names()] + self.dummy_wl_names = ["dummy_"+x for x in self.cell.list_all_wl_names()] + self.dummy_bl_names = ["dummy_"+x for x in self.cell.list_all_bitline_names()] self.dummy_row_bl_names = self.bl_names # dummy row and replica on each side of the bitcell rows self.replica_col_wl_names = [x+"_0" for x in self.dummy_wl_names] \ + ["replica_"+x+"_0" for x in self.cell.list_all_wl_names()] \ - + self.wl_names \ - + ["replica_"+x+"_1" for x in self.cell.list_all_wl_names()] \ - + [x+"_1" for x in self.dummy_wl_names] - self.replica_bl_names = ["replica_"+x for x in self.cell.pins if x.startswith("b")] + + self.wl_names + if self.num_ports==2: + self.replica_col_wl_names.extend(["replica_"+x+"_1" for x in self.cell.list_all_wl_names()]) + self.replica_col_wl_names.extend([x+"_1" for x in self.dummy_wl_names]) + self.replica_bl_names = ["replica_"+x for x in self.cell.list_all_bitline_names()] + self.replica_bl0_names = [x+"_0" for x in self.replica_bl_names] + self.replica_bl1_names = [x+"_1" for x in self.replica_bl_names] # left/right rows self.dummy_col_wl_names = self.replica_col_wl_names self.add_pin_list(self.bl_names) - self.add_pin_list([x+"_0" for x in self.replica_bl_names]) - self.add_pin_list([x+"_1" for x in self.replica_bl_names]) - self.add_pin_list([x for x in self.replica_col_wl_names if not x.startswith("dummy")]) + self.add_pin_list(self.replica_bl0_names) + if self.num_ports==2: + self.add_pin_list(self.replica_bl1_names) + self.add_pin_list(self.wl_names) + self.add_pin_list(self.replica_wl_names) + #self.add_pin_list([x for x in self.replica_col_wl_names if not x.startswith("dummy")]) self.add_pin("vdd") self.add_pin("gnd") @@ -142,10 +154,11 @@ class replica_bitcell_array(design.design): self.replica_col_left_inst=self.add_inst(name="replica_col_left", mod=self.replica_column) self.connect_inst([x+"_0" for x in self.replica_bl_names] + self.replica_col_wl_names + supplies) - - self.replica_col_right_inst=self.add_inst(name="replica_col_right", - mod=self.replica_column) - self.connect_inst([x+"_1" for x in self.replica_bl_names] + self.replica_col_wl_names[::-1] + supplies) + + if self.num_ports==2: + self.replica_col_right_inst=self.add_inst(name="replica_col_right", + mod=self.replica_column) + self.connect_inst([x+"_1" for x in self.replica_bl_names] + self.replica_col_wl_names[::-1] + supplies) # Replica rows with replica bitcell self.dummy_row_bottop_inst=self.add_inst(name="dummy_row_bottop", @@ -177,16 +190,17 @@ class replica_bitcell_array(design.design): def create_layout(self): - self.height = (self.row_size+4)*self.dummy_row.height - self.width = (self.column_size+4)*self.replica_column.width + self.height = (self.row_size+self.extra_rows)*self.dummy_row.height + self.width = (self.column_size+self.extra_cols)*self.replica_column.width # This is a bitcell x bitcell offset to scale offset = vector(self.replica_column.width, self.dummy_row.height) self.bitcell_array_inst.place(offset=[0,0]) self.replica_col_left_inst.place(offset=offset.scale(-1,-2)) - self.replica_col_right_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ur(), - mirror="MX") + if self.num_ports==2: + self.replica_col_right_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ur(), + mirror="MX") self.dummy_row_toptop_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ul(), mirror="MX") @@ -196,7 +210,11 @@ class replica_bitcell_array(design.design): self.dummy_row_botbot_inst.place(offset=offset.scale(0,-2)) self.dummy_col_left_inst.place(offset=offset.scale(-2,-2)) - self.dummy_col_right_inst.place(offset=offset.scale(1,-2)+self.bitcell_array_inst.lr()) + if self.num_ports==2: + self.dummy_col_right_inst.place(offset=offset.scale(1,-2)+self.bitcell_array_inst.lr()) + else: + self.dummy_col_right_inst.place(offset=offset.scale(0,-2)+self.bitcell_array_inst.lr()) + self.translate_all(offset.scale(-2,-2)) @@ -246,7 +264,10 @@ class replica_bitcell_array(design.design): height=pin.height()) # Replica columns - for index,side in enumerate(["left","right"]): + replica_sides = ["left"] + if self.num_ports==2: + replica_sides.append("right") + for index,side in enumerate(replica_sides): inst = getattr(self, "replica_col_{}_inst".format(side)) pin_names = inst.mod.get_pin_names() for pin_name in pin_names: @@ -262,11 +283,7 @@ class replica_bitcell_array(design.design): for pin_name in ["vdd","gnd"]: - for inst in [self.bitcell_array_inst, - self.replica_col_left_inst, self.replica_col_right_inst, - self.dummy_col_left_inst, self.dummy_col_right_inst, - self.dummy_row_toptop_inst, self.dummy_row_topbot_inst, - self.dummy_row_bottop_inst, self.dummy_row_botbot_inst]: + for inst in self.insts: pin_list = inst.get_pins(pin_name) for pin in pin_list: self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 0de0aace..d692db78 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -16,10 +16,11 @@ class replica_column(design.design): Generate a replica bitline column for the replica array. """ - def __init__(self, name, rows): + def __init__(self, name, rows, num_ports): design.design.__init__(self, name) self.row_size = rows + self.num_ports = num_ports self.create_netlist() if not OPTS.netlist_only: @@ -64,7 +65,7 @@ class replica_column(design.design): self.cell_inst = {} for row in range(self.row_size): name="rbc_{0}".format(row) - if row>0 and row0 and row Date: Fri, 5 Jul 2019 13:44:29 -0700 Subject: [PATCH 079/234] Single bank working with replica array. --- compiler/modules/bank.py | 25 +++++++++++++++-------- compiler/modules/replica_bitcell_array.py | 4 ++-- compiler/tests/19_single_bank_test.py | 8 ++++---- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 841f99b1..45d860b2 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -26,10 +26,11 @@ class bank(design.design): This can create up to two ports in any combination: rw, w, r. """ - def __init__(self, sram_config, name=""): + def __init__(self, sram_config, num_ports, name=""): self.sram_config = sram_config sram_config.set_local_config(self) + self.num_ports = num_ports if name == "": name = "bank_{0}_{1}".format(self.word_size, self.num_words) @@ -152,8 +153,11 @@ class bank(design.design): # The port data write/sense/precharge/mux is placed on the top and mirrored on the X-axis. self.bitcell_array_top = self.bitcell_array.height self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap - # Offset past the dummy/RBL column - self.bitcell_array_left = 2*self.bitcell.width + + # These are the offsets of the main array (excluding dummy and replica rows/cols) + self.main_bitcell_array_top = self.bitcell_array_top - (self.num_ports*self.bitcell.height) + self.main_bitcell_array_left = 2*self.bitcell.width + self.main_bitcell_array_bottom = 2*self.bitcell.height self.compute_instance_port0_offsets() if len(self.all_ports)==2: @@ -173,12 +177,12 @@ class bank(design.design): # LOWER RIGHT QUADRANT # Below the bitcell array - self.port_data_offsets[port] = vector(self.bitcell_array_left,0) + self.port_data_offsets[port] = vector(self.main_bitcell_array_left,0) # UPPER LEFT QUADRANT # To the left of the bitcell array x_offset = self.m2_gap + self.port_address.width - self.port_address_offsets[port] = vector(-x_offset,0) + self.port_address_offsets[port] = vector(-x_offset,self.main_bitcell_array_bottom) # LOWER LEFT QUADRANT # Place the col decoder left aligned with wordline driver @@ -218,7 +222,7 @@ class bank(design.design): # LOWER RIGHT QUADRANT # To the left 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,0) + self.port_address_offsets[port] = vector(x_offset,self.main_bitcell_array_top) # UPPER RIGHT QUADRANT # Place the col decoder right aligned with wordline driver @@ -319,7 +323,8 @@ class bank(design.design): self.bitcell_array = factory.create(module_type="replica_bitcell_array", cols=self.num_cols, - rows=self.num_rows) + rows=self.num_rows, + num_ports=self.num_ports) self.add_mod(self.bitcell_array) self.port_data = [] @@ -347,17 +352,19 @@ class bank(design.design): self.bitcell_array_inst=self.add_inst(name="bitcell_array", mod=self.bitcell_array) - print(self.bitcell_array.pins) temp = [] for col in range(self.num_cols): for bitline in self.bitline_names: temp.append(bitline+"_{0}".format(col)) - for col in range(2): + for col in range(self.num_ports): for bitline in self.bitline_names: temp.append("replica_"+bitline+"_{0}".format(col)) for row in range(self.num_rows): for wordline in self.wl_names: temp.append(wordline+"_{0}".format(row)) + for row in range(self.num_ports): + for wordline in self.wl_names: + temp.append(wordline+"_{0}".format(row)) temp.append("vdd") temp.append("gnd") self.connect_inst(temp) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index feab1cce..4596f94d 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -153,12 +153,12 @@ class replica_bitcell_array(design.design): # Replica columns (two even if one port for now) self.replica_col_left_inst=self.add_inst(name="replica_col_left", mod=self.replica_column) - self.connect_inst([x+"_0" for x in self.replica_bl_names] + self.replica_col_wl_names + supplies) + self.connect_inst(self.replica_bl0_names + self.replica_col_wl_names + supplies) if self.num_ports==2: self.replica_col_right_inst=self.add_inst(name="replica_col_right", mod=self.replica_column) - self.connect_inst([x+"_1" for x in self.replica_bl_names] + self.replica_col_wl_names[::-1] + supplies) + self.connect_inst(self.replica_bl1_names + self.replica_col_wl_names[::-1] + supplies) # Replica rows with replica bitcell self.dummy_row_bottop_inst=self.add_inst(name="dummy_row_bottop", diff --git a/compiler/tests/19_single_bank_test.py b/compiler/tests/19_single_bank_test.py index 1d010db5..74bb4032 100755 --- a/compiler/tests/19_single_bank_test.py +++ b/compiler/tests/19_single_bank_test.py @@ -28,7 +28,7 @@ class single_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "No column mux") - a = factory.create("bank", sram_config=c) + a = factory.create("bank", sram_config=c, num_ports=1) self.local_check(a) c.num_words=32 @@ -36,7 +36,7 @@ class single_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Two way column mux") - a = factory.create("bank", sram_config=c) + a = factory.create("bank", sram_config=c, num_ports=1) self.local_check(a) c.num_words=64 @@ -44,7 +44,7 @@ class single_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Four way column mux") - a = factory.create("bank", sram_config=c) + a = factory.create("bank", sram_config=c, num_ports=1) self.local_check(a) c.word_size=2 @@ -53,7 +53,7 @@ class single_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Eight way column mux") - a = factory.create("bank", sram_config=c) + a = factory.create("bank", sram_config=c, num_ports=1) self.local_check(a) globals.end_openram() From ad9193ad5a99c4645f41a27614a93df0aba61099 Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 5 Jul 2019 15:08:59 -0700 Subject: [PATCH 080/234] Verified 1rw mask writing and changed verilog.py accordingly. --- compiler/base/verilog.py | 31 +++++--- compiler/tests/sram_1rw_wmask_tb.v | 110 +++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 compiler/tests/sram_1rw_wmask_tb.v diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index 435b6912..f1e5cd13 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -53,12 +53,12 @@ class verilog: if port != self.all_ports[-1]: self.vf.write(",\n") self.vf.write("\n );\n\n") - - self.vf.write(" parameter DATA_WIDTH = {0} ;\n".format(self.word_size)) - self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_size)) + if self.wmask_enabled: self.num_wmask = int(self.word_size/self.write_size) self.vf.write(" parameter NUM_WMASK = {0} ;\n".format(self.num_wmask)) + self.vf.write(" parameter DATA_WIDTH = {0} ;\n".format(self.word_size)) + self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_size)) self.vf.write(" parameter RAM_DEPTH = 1 << ADDR_WIDTH;\n") self.vf.write(" // FIXME: This delay is arbitrary.\n") self.vf.write(" parameter DELAY = 3 ;\n") @@ -100,6 +100,9 @@ class verilog: self.vf.write(" reg csb{0}_reg;\n".format(port)) if port in self.readwrite_ports: self.vf.write(" reg web{0}_reg;\n".format(port)) + if port in self.write_ports: + if self.wmask_enabled: + self.vf.write(" reg [NUM_WMASK-1:0] wmask{0}_reg;\n".format(port)) self.vf.write(" reg [ADDR_WIDTH-1:0] ADDR{0}_reg;\n".format(port)) if port in self.write_ports: self.vf.write(" reg [DATA_WIDTH-1:0] DIN{0}_reg;\n".format(port)) @@ -117,6 +120,9 @@ class verilog: self.vf.write(" csb{0}_reg = csb{0};\n".format(port)) if port in self.readwrite_ports: self.vf.write(" web{0}_reg = web{0};\n".format(port)) + if port in self.write_ports: + if self.wmask_enabled: + self.vf.write(" wmask{0}_reg = wmask{0};\n".format(port)) self.vf.write(" ADDR{0}_reg = ADDR{0};\n".format(port)) if port in self.write_ports: self.vf.write(" DIN{0}_reg = DIN{0};\n".format(port)) @@ -128,13 +134,19 @@ class verilog: elif port in self.read_ports: self.vf.write(" if ( !csb{0}_reg ) \n".format(port)) self.vf.write(" $display($time,\" Reading %m ADDR{0}=%b DOUT{0}=%b\",ADDR{0}_reg,mem[ADDR{0}_reg]);\n".format(port)) - if port in self.readwrite_ports: self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port)) - self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b\",ADDR{0}_reg,DIN{0}_reg);\n".format(port)) + if self.wmask_enabled: + self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b wmask{0}=%b\",ADDR{0}_reg,DIN{0}_reg,wmask{0}_reg);\n".format(port)) + else: + self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b\",ADDR{0}_reg,DIN{0}_reg);\n".format(port)) elif port in self.write_ports: self.vf.write(" if ( !csb{0}_reg )\n".format(port)) - self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b\",ADDR{0}_reg,DIN{0}_reg);\n".format(port)) + if self.wmask_enabled: + self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b wmask{0}=%b\",ADDR{0}_reg,DIN{0}_reg,wmask{0}_reg);\n".format(port)) + else: + self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b\",ADDR{0}_reg,DIN{0}_reg);\n".format(port)) + self.vf.write(" end\n\n") @@ -165,18 +177,19 @@ class verilog: self.vf.write(" always @ (negedge clk{0})\n".format(port)) self.vf.write(" begin : MEM_WRITE{0}\n".format(port)) if port in self.readwrite_ports: - self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port)) + self.vf.write(" if ( !csb{0}_reg && !web{0}_reg ) begin\n".format(port)) else: - self.vf.write(" if (!csb{0}_reg)\n".format(port)) + self.vf.write(" if (!csb{0}_reg) begin\n".format(port)) if self.wmask_enabled: for mask in range(0,self.num_wmask): lower = mask * self.write_size upper = lower + self.write_size-1 - self.vf.write(" if(wmask[{}])\n".format(mask)) + self.vf.write(" if (wmask{0}_reg[{1}])\n".format(port,mask)) self.vf.write(" mem[ADDR{0}_reg][{1}:{2}] = DIN{0}_reg[{1}:{2}];\n".format(port,upper,lower)) else: self.vf.write(" mem[ADDR{0}_reg] = DIN_reg{0};\n".format(port)) + self.vf.write(" end\n") self.vf.write(" end\n") def add_read_block(self, port): diff --git a/compiler/tests/sram_1rw_wmask_tb.v b/compiler/tests/sram_1rw_wmask_tb.v new file mode 100644 index 00000000..54aada6e --- /dev/null +++ b/compiler/tests/sram_1rw_wmask_tb.v @@ -0,0 +1,110 @@ +`define assert(signal, value) \ +if (!(signal === value)) begin \ + $display("ASSERTION FAILED in %m: signal != value"); \ + $finish;\ +end + +module sram_1rw_wmask_tb; + reg clk; + + reg [3:0] addr0; + reg [1:0] din0; + reg csb0; + reg web0; + reg [1:0] wmask0; + wire [1:0] dout0; + + sram_2b_16_1rw_freepdk45 U0 (.DIN0(din0), + .DOUT0(dout0), + .ADDR0(addr0), + .csb0(csb0), + .web0(web0), + .wmask0(wmask0), + .clk0(clk) + ); + + + initial + begin + //$monitor("%g addr0=%b din0=%b dout0=%b", + // $time, addr0, din0, dout0); + + + clk = 1; + csb0 = 1; + web0 = 1; + wmask0 = 2'b01; + addr0 = 0; + din0 = 0; + + // write + #10 din0=2'b10; + addr0=4'h1; + web0 = 0; + csb0 = 0; + wmask0 = 2'b10; + + // read + #10 din0=2'b11; + addr0=4'h1; + web0 = 1; + csb0 = 0; + + #10 `assert(dout0, 2'b1x) + + // write another + #10 din0=2'b01; + addr0=4'hC; + web0 = 0; + csb0 = 0; + wmask0 = 2'b01; + + // read undefined + #10 din0=2'b11; + addr0=4'h0; + web0 = 1; + csb0 = 0; + wmask0 = 2'b01; + + #10 `assert(dout0, 2'bxx) + + // read defined + din0=2'b11; + addr0=4'hC; + web0 = 1; + csb0 = 0; + wmask0 = 2'b01; + + #10 `assert(dout0, 2'bx1) + + // write another + din0=2'b01; + addr0=4'h1; + web0 = 0; + csb0 = 0; + + // read defined + #10 din0=2'b11; + addr0=4'h1; + web0 = 1; + csb0 = 0; + + + #10 `assert(dout0, 2'b11) + + // read undefined + din0=2'b11; + addr0=4'h0; + web0 = 1; + csb0 = 0; + + #10 `assert(dout0, 2'bxx) + + #10 $finish; + + end + + always + #5 clk = !clk; + +endmodule \ No newline at end of file From 24bfaa3b76e889ea94bab17012c111d45ddc70a1 Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 5 Jul 2019 15:55:03 -0700 Subject: [PATCH 081/234] Added write_size to test 16 and added a newline to Verilog with no wmask for test 25. --- compiler/base/verilog.py | 2 ++ compiler/tests/16_control_logic_multiport_test.py | 6 +++--- compiler/tests/16_control_logic_test.py | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index f1e5cd13..5489a3cd 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -28,6 +28,8 @@ class verilog: self.vf.write("// Word size: {0}\n".format(self.word_size)) if self.wmask_enabled: self.vf.write("// Write size: {0}\n\n".format(self.write_size)) + else: + self.vf.write("\n") self.vf.write("module {0}(\n".format(self.name)) for port in self.all_ports: diff --git a/compiler/tests/16_control_logic_multiport_test.py b/compiler/tests/16_control_logic_multiport_test.py index 66c34d24..3ad898b1 100755 --- a/compiler/tests/16_control_logic_multiport_test.py +++ b/compiler/tests/16_control_logic_multiport_test.py @@ -34,19 +34,19 @@ class control_logic_test(openram_test): OPTS.num_r_ports = 1 debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="rw") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, write_size=8, port_type="rw") self.local_check(a) # OPTS.num_rw_ports = 0 # OPTS.num_w_ports = 1 debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="w") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, write_size=8, port_type="w") self.local_check(a) # OPTS.num_w_ports = 0 # OPTS.num_r_ports = 1 debug.info(1, "Testing sample for control_logic for multiport, only read control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="r") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, write_size=8, port_type="r") self.local_check(a) globals.end_openram() diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index 2be0bf0f..13e6c46c 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -24,7 +24,7 @@ class control_logic_test(openram_test): # check control logic for single port debug.info(1, "Testing sample for control_logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32) + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32, write_size=32) self.local_check(a) # run the test from the command line From 6fe78fe04a9e42d0d4ecf9f39f2d1961464c4373 Mon Sep 17 00:00:00 2001 From: jsowash Date: Sat, 6 Jul 2019 11:29:34 -0700 Subject: [PATCH 082/234] Removed begin end for Verilog without wmask. --- compiler/base/verilog.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index 5489a3cd..2b6e10ff 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -179,9 +179,15 @@ class verilog: self.vf.write(" always @ (negedge clk{0})\n".format(port)) self.vf.write(" begin : MEM_WRITE{0}\n".format(port)) if port in self.readwrite_ports: - self.vf.write(" if ( !csb{0}_reg && !web{0}_reg ) begin\n".format(port)) + if self.wmask_enabled: + self.vf.write(" if ( !csb{0}_reg && !web{0}_reg ) begin\n".format(port)) + else: + self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port)) else: - self.vf.write(" if (!csb{0}_reg) begin\n".format(port)) + if self.wmask_enabled: + self.vf.write(" if (!csb{0}_reg) begin\n".format(port)) + else: + self.vf.write(" if (!csb{0}_reg)\n".format(port)) if self.wmask_enabled: for mask in range(0,self.num_wmask): @@ -189,9 +195,9 @@ class verilog: upper = lower + self.write_size-1 self.vf.write(" if (wmask{0}_reg[{1}])\n".format(port,mask)) self.vf.write(" mem[ADDR{0}_reg][{1}:{2}] = DIN{0}_reg[{1}:{2}];\n".format(port,upper,lower)) + self.vf.write(" end\n") else: self.vf.write(" mem[ADDR{0}_reg] = DIN_reg{0};\n".format(port)) - self.vf.write(" end\n") self.vf.write(" end\n") def add_read_block(self, port): From 5258016c9f3923eaa9dfcff2d176c21039e0594f Mon Sep 17 00:00:00 2001 From: jsowash Date: Sat, 6 Jul 2019 12:27:24 -0700 Subject: [PATCH 083/234] Changed location of port for din_reg. --- compiler/base/verilog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index 2b6e10ff..c4d4ee00 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -197,7 +197,7 @@ class verilog: self.vf.write(" mem[ADDR{0}_reg][{1}:{2}] = DIN{0}_reg[{1}:{2}];\n".format(port,upper,lower)) self.vf.write(" end\n") else: - self.vf.write(" mem[ADDR{0}_reg] = DIN_reg{0};\n".format(port)) + self.vf.write(" mem[ADDR{0}_reg] = DIN{0}_reg;\n".format(port)) self.vf.write(" end\n") def add_read_block(self, port): From c9c839ca461c14348e1350ec2d1b3bffe18b2337 Mon Sep 17 00:00:00 2001 From: Bin Wu Date: Wed, 10 Jul 2019 04:39:40 -0700 Subject: [PATCH 084/234] fix the delay measure bug in pex tests --- compiler/tests/26_hspice_pex_pinv_test.py | 12 +++++++++--- compiler/tests/26_ngspice_pex_pinv_test.py | 14 ++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/compiler/tests/26_hspice_pex_pinv_test.py b/compiler/tests/26_hspice_pex_pinv_test.py index 90ce5d90..f0cccba3 100755 --- a/compiler/tests/26_hspice_pex_pinv_test.py +++ b/compiler/tests/26_hspice_pex_pinv_test.py @@ -24,8 +24,13 @@ class hspice_pex_pinv_test(openram_test): import pinv # load the hspice - OPTS.spice_name = "hspice" - OPTS.spice_exe = "hspice" + OPTS.spice_name="hspice" + OPTS.analytical_delay = False + + # This is a hack to reload the characterizer __init__ with the spice version + from importlib import reload + import characterizer + reload(characterizer) # generate the pinv prev_purge_value = OPTS.purge_temp @@ -111,7 +116,8 @@ class hspice_pex_pinv_test(openram_test): trig_name = "input", targ_name = "output", trig_dir_str = "FALL", - targ_dir_str = "RISE") + targ_dir_str = "RISE", + has_port = False) trig_td = trag_td = 0.01 * run_time rest_info = trig_td,trag_td,tech.spice["nom_supply_voltage"] delay_measure.write_measure(simulation, rest_info) diff --git a/compiler/tests/26_ngspice_pex_pinv_test.py b/compiler/tests/26_ngspice_pex_pinv_test.py index 42181630..2eb95948 100755 --- a/compiler/tests/26_ngspice_pex_pinv_test.py +++ b/compiler/tests/26_ngspice_pex_pinv_test.py @@ -22,9 +22,14 @@ class ngspice_pex_pinv_test(openram_test): globals.init_openram("config_{0}".format(OPTS.tech_name)) import pinv - # load the hspice - OPTS.spice_name = "ngspice" - OPTS.spice_exe = "ngspice" + # load the ngspice + OPTS.spice_name="ngspice" + OPTS.analytical_delay = False + + # This is a hack to reload the characterizer __init__ with the spice version + from importlib import reload + import characterizer + reload(characterizer) # generate the pinv module prev_purge_value = OPTS.purge_temp @@ -114,7 +119,8 @@ class ngspice_pex_pinv_test(openram_test): trig_name = "input", targ_name = "output", trig_dir_str = "FALL", - targ_dir_str = "RISE") + targ_dir_str = "RISE", + has_port = False) trig_td = trag_td = 0.01 * run_time rest_info = trig_td,trag_td,tech.spice["nom_supply_voltage"] delay_measure.write_measure(simulation, rest_info) From b841fd7ce3fdb74f6b2a9c98e56decaf5e98b8ff Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 10 Jul 2019 15:56:51 -0700 Subject: [PATCH 085/234] Replica bitcell array with arbitrary RBLs working --- compiler/bitcells/dummy_pbitcell.py | 91 ++++ compiler/bitcells/pbitcell.py | 15 +- compiler/modules/bank.py | 12 +- compiler/modules/dummy_array.py | 5 +- compiler/modules/port_data.py | 90 ++-- compiler/modules/replica_bitcell_array.py | 298 ++++++++------ compiler/modules/replica_bitline.py | 387 +----------------- compiler/modules/replica_column.py | 69 ++-- compiler/sram/sram_base.py | 3 +- compiler/tests/04_dummy_pbitcell_test.py | 50 +++ .../tests/05_bitcell_1rw_1r_array_test.py | 4 +- .../05_replica_bitcell_1rw_1r_array_test.py | 36 ++ .../tests/05_replica_bitcell_array_test.py | 9 +- compiler/tests/05_replica_column_test.py | 8 +- .../tests/05_replica_pbitcell_array_test.py | 40 ++ compiler/tests/19_single_bank_1rw_1r_test.py | 13 +- compiler/tests/19_single_bank_1w_1r_test.py | 17 +- compiler/tests/testutils.py | 2 + technology/scn4m_subm/mag_lib/setup.tcl | 12 +- 19 files changed, 565 insertions(+), 596 deletions(-) create mode 100644 compiler/bitcells/dummy_pbitcell.py create mode 100755 compiler/tests/04_dummy_pbitcell_test.py create mode 100755 compiler/tests/05_replica_bitcell_1rw_1r_array_test.py create mode 100755 compiler/tests/05_replica_pbitcell_array_test.py diff --git a/compiler/bitcells/dummy_pbitcell.py b/compiler/bitcells/dummy_pbitcell.py new file mode 100644 index 00000000..ee15e03c --- /dev/null +++ b/compiler/bitcells/dummy_pbitcell.py @@ -0,0 +1,91 @@ +# 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, spice,parameter +from vector import vector +from globals import OPTS +from sram_factory import factory + +class dummy_pbitcell(design.design): + """ + Creates a replica bitcell using pbitcell + """ + + def __init__(self, name): + self.num_rw_ports = OPTS.num_rw_ports + 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 + + design.design.__init__(self, name) + debug.info(1, "create a dummy bitcell using pbitcell with {0} rw ports, {1} w ports and {2} r ports".format(self.num_rw_ports, + self.num_w_ports, + self.num_r_ports)) + + self.create_netlist() + self.create_layout() + + def create_netlist(self): + self.add_pins() + self.add_modules() + self.create_modules() + + def create_layout(self): + self.place_pbitcell() + self.route_rbc_connections() + self.DRC_LVS() + + def add_pins(self): + for port in range(self.total_ports): + self.add_pin("bl{}".format(port)) + self.add_pin("br{}".format(port)) + + for port in range(self.total_ports): + self.add_pin("wl{}".format(port)) + + self.add_pin("vdd") + self.add_pin("gnd") + + def add_modules(self): + self.prbc = factory.create(module_type="pbitcell",dummy_bitcell=True) + self.add_mod(self.prbc) + + self.height = self.prbc.height + self.width = self.prbc.width + + def create_modules(self): + self.prbc_inst = self.add_inst(name="pbitcell", + mod=self.prbc) + + temp = [] + for port in range(self.total_ports): + temp.append("bl{}".format(port)) + temp.append("br{}".format(port)) + for port in range(self.total_ports): + temp.append("wl{}".format(port)) + temp.append("vdd") + temp.append("gnd") + self.connect_inst(temp) + + def place_pbitcell(self): + self.prbc_inst.place(offset=vector(0,0)) + + def route_rbc_connections(self): + for port in range(self.total_ports): + self.copy_layout_pin(self.prbc_inst, "bl{}".format(port)) + self.copy_layout_pin(self.prbc_inst, "br{}".format(port)) + for port in range(self.total_ports): + self.copy_layout_pin(self.prbc_inst, "wl{}".format(port)) + self.copy_layout_pin(self.prbc_inst, "vdd") + self.copy_layout_pin(self.prbc_inst, "gnd") + + def get_wl_cin(self): + """Return the relative capacitance of the access transistor gates""" + #This module is made using a pbitcell. Get the cin from that module + return self.prbc.get_wl_cin() diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index eb44a27a..63691233 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -20,13 +20,14 @@ class pbitcell(design.design): with a variable number of read/write, write, and read ports """ - def __init__(self, name, replica_bitcell=False): + def __init__(self, name, replica_bitcell=False, dummy_bitcell=False): self.num_rw_ports = OPTS.num_rw_ports 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 design.design.__init__(self, name) debug.info(2, "create a multi-port bitcell with {0} rw ports, {1} w ports and {2} r ports".format(self.num_rw_ports, @@ -686,8 +687,10 @@ class pbitcell(design.design): port_contact_offest = left_port_transistors[k].get_pin("S").center() bl_offset = vector(bl_positions[k].x, port_contact_offest.y) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=port_contact_offest) + # Leave bitline disconnected if a dummy cell + if not self.dummy_bitcell: + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=port_contact_offest) self.add_path("metal2", [port_contact_offest, bl_offset], width=contact.m1m2.height) @@ -695,8 +698,10 @@ class pbitcell(design.design): port_contact_offest = right_port_transistors[k].get_pin("D").center() br_offset = vector(br_positions[k].x, port_contact_offest.y) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=port_contact_offest) + # Leave bitline disconnected if a dummy cell + if not self.dummy_bitcell: + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=port_contact_offest) self.add_path("metal2", [port_contact_offest, br_offset], width=contact.m1m2.height) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 45d860b2..ebf25236 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -156,7 +156,9 @@ class bank(design.design): # These are the offsets of the main array (excluding dummy and replica rows/cols) self.main_bitcell_array_top = self.bitcell_array_top - (self.num_ports*self.bitcell.height) - self.main_bitcell_array_left = 2*self.bitcell.width + # Just past the dummy column + self.main_bitcell_array_left = self.bitcell.width + # Just past the dummy row and replica row self.main_bitcell_array_bottom = 2*self.bitcell.height self.compute_instance_port0_offsets() @@ -362,9 +364,8 @@ class bank(design.design): for row in range(self.num_rows): for wordline in self.wl_names: temp.append(wordline+"_{0}".format(row)) - for row in range(self.num_ports): - for wordline in self.wl_names: - temp.append(wordline+"_{0}".format(row)) + for wordline in self.wl_names: + temp.append("replica_"+wordline) temp.append("vdd") temp.append("gnd") self.connect_inst(temp) @@ -384,6 +385,9 @@ class bank(design.design): mod=self.port_data[port]) temp = [] + if port in self.read_ports: + temp.append("rbl_{0}".format(self.bl_names[port])) + temp.append("rbl_{0}".format(self.br_names[port])) for col in range(self.num_cols): temp.append("{0}_{1}".format(self.bl_names[port],col)) temp.append("{0}_{1}".format(self.br_names[port],col)) diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py index 0790367f..861e0fad 100644 --- a/compiler/modules/dummy_array.py +++ b/compiler/modules/dummy_array.py @@ -15,13 +15,14 @@ class dummy_array(design.design): """ Generate a dummy row/column for the replica array. """ - def __init__(self, cols, rows, name): + def __init__(self, cols, rows, mirror, 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)) self.column_size = cols self.row_size = rows + self.mirror = mirror self.create_netlist() if not OPTS.netlist_only: @@ -46,7 +47,7 @@ class dummy_array(design.design): for row in range(self.row_size): name = "dummy_r{0}_c{1}".format(row, col) - if row % 2: + if (row+self.mirror) % 2: tempy = yoffset + self.dummy_cell.height dir_key = "MX" else: diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index ab594c09..4dce8d59 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -71,6 +71,9 @@ class port_data(design.design): def add_pins(self): """ Adding pins for port address module""" + if self.port in self.read_ports or self.col_addr_size>0: + self.add_pin("rbl_"+self.bl_names[self.port],"INOUT") + self.add_pin("rbl_"+self.br_names[self.port],"INOUT") for bit in range(self.num_cols): self.add_pin(self.bl_names[self.port]+"_{0}".format(bit),"INOUT") self.add_pin(self.br_names[self.port]+"_{0}".format(bit),"INOUT") @@ -134,8 +137,9 @@ class port_data(design.design): def add_modules(self): if self.port in self.read_ports: + # Extra column for RBL self.precharge_array = factory.create(module_type="precharge_array", - columns=self.num_cols, + columns=self.num_cols + 1, bitcell_bl=self.bl_names[self.port], bitcell_br=self.br_names[self.port]) self.add_mod(self.precharge_array) @@ -144,9 +148,19 @@ class port_data(design.design): word_size=self.word_size, words_per_row=self.words_per_row) self.add_mod(self.sense_amp_array) + elif self.col_addr_size>0: + # Precharge is needed when we have a column mux + self.precharge_array = factory.create(module_type="precharge_array", + columns=self.num_cols, + bitcell_bl=self.bl_names[self.port], + bitcell_br=self.br_names[self.port]) + self.add_mod(self.precharge_array) + self.sense_amp_array = None + else: self.precharge_array = None self.sense_amp_array = None + if self.col_addr_size > 0: self.column_mux_array = factory.create(module_type="column_mux_array", @@ -197,7 +211,10 @@ class port_data(design.design): self.precharge_array_inst = self.add_inst(name="precharge_array{}".format(self.port), mod=self.precharge_array) + temp = [] + temp.append("rbl_"+self.bl_names[self.port]) + temp.append("rbl_"+self.br_names[self.port]) for bit in range(self.num_cols): temp.append(self.bl_names[self.port]+"_{0}".format(bit)) temp.append(self.br_names[self.port]+"_{0}".format(bit)) @@ -296,21 +313,30 @@ class port_data(design.design): vertical_port_order.append(self.sense_amp_array_inst) vertical_port_order.append(self.write_driver_array_inst) + # Add one column for the the RBL + if self.port in self.read_ports: + x_offset = self.bitcell.width + else: + x_offset = 0 + vertical_port_offsets = 4*[None] - self.width = 0 + self.width = x_offset self.height = 0 for i,p in enumerate(vertical_port_order): if p==None: continue self.height += (p.height + self.m2_gap) self.width = max(self.width, p.width) - vertical_port_offsets[i]=vector(0,self.height) + vertical_port_offsets[i]=vector(x_offset,self.height) # Reversed order self.write_driver_offset = vertical_port_offsets[3] self.sense_amp_offset = vertical_port_offsets[2] self.column_mux_offset = vertical_port_offsets[1] self.precharge_offset = vertical_port_offsets[0] + if self.precharge_offset: + self.precharge_offset -= vector(x_offset,0) + @@ -356,14 +382,15 @@ class port_data(design.design): inst1 = self.column_mux_array_inst inst2 = self.precharge_array_inst - self.connect_bitlines(inst1, inst2, self.num_cols) - + self.connect_bitlines(inst1, inst2, self.num_cols, inst2_start_bit=1) + def route_sense_amp_to_column_mux_or_precharge_array(self, port): """ Routing of BL and BR between sense_amp and column mux or precharge array """ inst2 = self.sense_amp_array_inst - + + start_bit = 0 if self.col_addr_size>0: # Sense amp is connected to the col mux inst1 = self.column_mux_array_inst @@ -374,9 +401,11 @@ class port_data(design.design): inst1 = self.precharge_array_inst inst1_bl_name = "bl_{}" inst1_br_name = "br_{}" - + start_bit=1 + + self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, - inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) + inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name, inst1_start_bit=start_bit) def route_write_driver_to_column_mux_or_bitcell_array(self, port): """ Routing of BL and BR between sense_amp and column mux or bitcell array """ @@ -408,10 +437,14 @@ class port_data(design.design): def route_bitline_pins(self): """ Add the bitline pins for the given port """ + if self.port in self.read_ports: + self.copy_layout_pin(self.precharge_array_inst, "bl_0", "rbl_bl") + self.copy_layout_pin(self.precharge_array_inst, "br_0", "rbl_br") + for bit in range(self.num_cols): if self.port in self.read_ports: - self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit)) - self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit)) + self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit+1), "bl_{}".format(bit)) + self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit+1), "br_{}".format(bit)) elif self.column_mux_array_inst: self.copy_layout_pin(self.column_mux_array_inst, "bl_{}".format(bit)) self.copy_layout_pin(self.column_mux_array_inst, "br_{}".format(bit)) @@ -434,8 +467,8 @@ class port_data(design.design): def channel_route_bitlines(self, inst1, inst2, num_bits, - inst1_bl_name="bl_{}", inst1_br_name="br_{}", - inst2_bl_name="bl_{}", inst2_br_name="br_{}"): + inst1_bl_name="bl_{}", inst1_br_name="br_{}", inst1_start_bit=0, + inst2_bl_name="bl_{}", inst2_br_name="br_{}", inst2_start_bit=0): """ Route the bl and br of two modules using the channel router. """ @@ -443,26 +476,27 @@ class port_data(design.design): # determine top and bottom automatically. # since they don't overlap, we can just check the bottom y coordinate. if inst1.by() < inst2.by(): - (bottom_inst, bottom_bl_name, bottom_br_name) = (inst1, inst1_bl_name, inst1_br_name) - (top_inst, top_bl_name, top_br_name) = (inst2, inst2_bl_name, inst2_br_name) + (bottom_inst, bottom_bl_name, bottom_br_name, bottom_start_bit) = (inst1, inst1_bl_name, inst1_br_name, inst1_start_bit) + (top_inst, top_bl_name, top_br_name, top_start_bit) = (inst2, inst2_bl_name, inst2_br_name, inst2_start_bit) else: - (bottom_inst, bottom_bl_name, bottom_br_name) = (inst2, inst2_bl_name, inst2_br_name) - (top_inst, top_bl_name, top_br_name) = (inst1, inst1_bl_name, inst1_br_name) + (bottom_inst, bottom_bl_name, bottom_br_name, bottom_start_bit) = (inst2, inst2_bl_name, inst2_br_name, inst2_start_bit) + (top_inst, top_bl_name, top_br_name, top_start_bit) = (inst1, inst1_bl_name, inst1_br_name, inst1_start_bit) # Channel route each mux separately since we don't minimize the number # of tracks in teh channel router yet. If we did, we could route all the bits at once! offset = bottom_inst.ul() + vector(0,self.m1_pitch) for bit in range(num_bits): - bottom_names = [bottom_inst.get_pin(bottom_bl_name.format(bit)), bottom_inst.get_pin(bottom_br_name.format(bit))] - top_names = [top_inst.get_pin(top_bl_name.format(bit)), top_inst.get_pin(top_br_name.format(bit))] + bottom_names = [bottom_inst.get_pin(bottom_bl_name.format(bit+bottom_start_bit)), bottom_inst.get_pin(bottom_br_name.format(bit+bottom_start_bit))] + top_names = [top_inst.get_pin(top_bl_name.format(bit+top_start_bit)), top_inst.get_pin(top_br_name.format(bit+top_start_bit))] route_map = list(zip(bottom_names, top_names)) self.create_horizontal_channel_route(route_map, offset) def connect_bitlines(self, inst1, inst2, num_bits, - inst1_bl_name="bl_{}", inst1_br_name="br_{}", - inst2_bl_name="bl_{}", inst2_br_name="br_{}"): + inst1_bl_name="bl_{}", inst1_br_name="br_{}", inst1_start_bit=0, + inst2_bl_name="bl_{}", inst2_br_name="br_{}", inst2_start_bit=0): + """ Connect the bl and br of two modules. This assumes that they have sufficient space to create a jog @@ -472,17 +506,17 @@ class port_data(design.design): # determine top and bottom automatically. # since they don't overlap, we can just check the bottom y coordinate. if inst1.by() < inst2.by(): - (bottom_inst, bottom_bl_name, bottom_br_name) = (inst1, inst1_bl_name, inst1_br_name) - (top_inst, top_bl_name, top_br_name) = (inst2, inst2_bl_name, inst2_br_name) + (bottom_inst, bottom_bl_name, bottom_br_name, bottom_start_bit) = (inst1, inst1_bl_name, inst1_br_name, inst1_start_bit) + (top_inst, top_bl_name, top_br_name, top_start_bit) = (inst2, inst2_bl_name, inst2_br_name, inst2_start_bit) else: - (bottom_inst, bottom_bl_name, bottom_br_name) = (inst2, inst2_bl_name, inst2_br_name) - (top_inst, top_bl_name, top_br_name) = (inst1, inst1_bl_name, inst1_br_name) + (bottom_inst, bottom_bl_name, bottom_br_name, bottom_start_bit) = (inst2, inst2_bl_name, inst2_br_name, inst2_start_bit) + (top_inst, top_bl_name, top_br_name, top_start_bit) = (inst1, inst1_bl_name, inst1_br_name, inst1_start_bit) for col in range(num_bits): - bottom_bl = bottom_inst.get_pin(bottom_bl_name.format(col)).uc() - bottom_br = bottom_inst.get_pin(bottom_br_name.format(col)).uc() - top_bl = top_inst.get_pin(top_bl_name.format(col)).bc() - top_br = top_inst.get_pin(top_br_name.format(col)).bc() + bottom_bl = bottom_inst.get_pin(bottom_bl_name.format(col+bottom_start_bit)).uc() + bottom_br = bottom_inst.get_pin(bottom_br_name.format(col+bottom_start_bit)).uc() + top_bl = top_inst.get_pin(top_bl_name.format(col+top_start_bit)).bc() + top_br = top_inst.get_pin(top_br_name.format(col+top_start_bit)).bc() yoffset = 0.5*(top_bl.y+bottom_bl.y) self.add_path("metal2",[bottom_bl, vector(bottom_bl.x,yoffset), diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 4596f94d..29724125 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -22,18 +22,25 @@ class replica_bitcell_array(design.design): Dummy are the outside columns/rows with WL and BL tied to gnd. Requires a regular bitcell array, replica bitcell, and dummy bitcell (Bl/BR disconnected). """ - def __init__(self, cols, rows, num_ports, name): + def __init__(self, cols, rows, left_rbl, right_rbl, 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)) self.column_size = cols self.row_size = rows - self.num_ports = num_ports + self.left_rbl = left_rbl + self.right_rbl = right_rbl + # FIXME: If we want more than 2 ports of RBL, we also need to modify + # replica_column to support this. Right now, it only supports a single + # RBL and is used for both the left and right column (right is flipped). + #debug.check(self.left_rbl<=1,"Only one RBL supported now.") + #debug.check(self.right_rbl<=1,"Only one RBL supported now.") + # Two dummy rows/cols plus replica for each port - self.extra_rows = 2 + self.num_ports - self.extra_cols = 2 + self.num_ports + self.extra_rows = 2 + left_rbl + right_rbl + self.extra_cols = 2 + left_rbl + right_rbl self.create_netlist() if not OPTS.netlist_only: @@ -83,22 +90,32 @@ class replica_bitcell_array(design.design): rows=self.row_size) self.add_mod(self.bitcell_array) - # Replica bitline - self.replica_column = factory.create(module_type="replica_column", - rows=self.row_size + self.extra_rows, - num_ports = self.num_ports) - self.add_mod(self.replica_column) + # Replica bitlines + self.replica_columns = {} + for bit in range(self.left_rbl+self.right_rbl): + if bit1 port) + for bit in range(self.left_rbl): + self.replica_col_wl_names.extend(["replica_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()]) + # Regular WLs + self.replica_col_wl_names.extend(self.wl_names) + # Right port WLs (one dummy for each port when we allow >1 port) + for bit in range(self.left_rbl,self.left_rbl+self.right_rbl): + self.replica_col_wl_names.extend(["replica_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()]) + self.replica_col_wl_names.extend(["{0}_top".format(x) for x in self.dummy_cell_wl_names]) + + # Left/right dummy columns are connected identically to the replica column self.dummy_col_wl_names = self.replica_col_wl_names - - + + + # Per bit bitline names + self.replica_bl_names_list = {} + self.replica_wl_names_list = {} + # Array of all bitline names + self.replica_bl_names = [] + self.replica_wl_names = [] + for bit in range(self.left_rbl+self.right_rbl): + self.replica_bl_names_list[bit] = ["replica_{0}_{1}".format(x,bit) for x in self.cell.list_all_bitline_names()] + self.replica_bl_names.extend(self.replica_bl_names_list[bit]) + + self.replica_wl_names_list[bit] = ["{0}_{1}".format(x,bit) for x in self.replica_cell_wl_names] + self.replica_wl_names.extend(self.replica_wl_names_list[bit]) + + self.add_pin_list(self.bl_names) - self.add_pin_list(self.replica_bl0_names) - if self.num_ports==2: - self.add_pin_list(self.replica_bl1_names) + self.add_pin_list(self.replica_bl_names) self.add_pin_list(self.wl_names) self.add_pin_list(self.replica_wl_names) - #self.add_pin_list([x for x in self.replica_col_wl_names if not x.startswith("dummy")]) - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def create_instances(self): """ Create the module instances used in this design """ supplies = ["vdd", "gnd"] + + # Used for names/dimensions only + self.cell = factory.create(module_type="bitcell") + # Main array self.bitcell_array_inst=self.add_inst(name="bitcell_array", mod=self.bitcell_array) self.connect_inst(self.bitcell_array.pins) - # Replica columns (two even if one port for now) - self.replica_col_left_inst=self.add_inst(name="replica_col_left", - mod=self.replica_column) - self.connect_inst(self.replica_bl0_names + self.replica_col_wl_names + supplies) + # Replica columns + self.replica_col_inst = {} + for bit in range(self.left_rbl): + self.replica_col_inst[bit]=self.add_inst(name="replica_col_left_{}".format(bit), + mod=self.replica_columns[bit]) + self.connect_inst(self.replica_bl_names_list[bit] + self.replica_col_wl_names + supplies) - if self.num_ports==2: - self.replica_col_right_inst=self.add_inst(name="replica_col_right", - mod=self.replica_column) - self.connect_inst(self.replica_bl1_names + self.replica_col_wl_names[::-1] + supplies) + for bit in range(self.left_rbl,self.left_rbl+self.right_rbl): + self.replica_col_inst[bit]=self.add_inst(name="replica_col_right_{}".format(bit), + mod=self.replica_columns[bit]) + self.connect_inst(self.replica_bl_names_list[bit] + self.replica_col_wl_names + supplies) + # Replica rows with replica bitcell - self.dummy_row_bottop_inst=self.add_inst(name="dummy_row_bottop", - mod=self.dummy_row) - self.connect_inst(self.dummy_row_bl_names + [x+"_0" for x in self.replica_wl_names] + supplies) - self.dummy_row_topbot_inst=self.add_inst(name="dummy_row_topbot", - mod=self.dummy_row) - self.connect_inst(self.dummy_row_bl_names + [x+"_1" for x in self.replica_wl_names] + supplies) + self.dummy_row_replica_inst = {} + for bit in range(self.left_rbl+self.right_rbl): + self.dummy_row_replica_inst[bit]=self.add_inst(name="dummy_row_{}".format(bit), + mod=self.dummy_row) + self.connect_inst(self.dummy_row_bl_names + self.replica_wl_names_list[bit] + supplies) - # Dummy rows without replica bitcell - self.dummy_row_botbot_inst=self.add_inst(name="dummy_row_botbot", + # Top/bottom dummy rows + self.dummy_row_bot_inst=self.add_inst(name="dummy_row_bot", mod=self.dummy_row) - self.connect_inst(self.dummy_row_bl_names + [x+"_0" for x in self.dummy_wl_names] + supplies) - self.dummy_row_toptop_inst=self.add_inst(name="dummy_row_toptop", + self.connect_inst(self.dummy_row_bl_names + [x+"_bot" for x in self.dummy_cell_wl_names] + supplies) + self.dummy_row_top_inst=self.add_inst(name="dummy_row_top", mod=self.dummy_row) - self.connect_inst(self.dummy_row_bl_names + [x+"_1" for x in self.dummy_wl_names] + supplies) + self.connect_inst(self.dummy_row_bl_names + [x+"_top" for x in self.dummy_cell_wl_names] + supplies) - # Dummy columns + # Left/right Dummy columns self.dummy_col_left_inst=self.add_inst(name="dummy_col_left", mod=self.dummy_col) - self.connect_inst([x+"_0" for x in self.dummy_bl_names] + self.dummy_col_wl_names + supplies) + self.connect_inst([x+"_left" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies) self.dummy_col_right_inst=self.add_inst(name="dummy_col_right", mod=self.dummy_col) - self.connect_inst([x+"_1" for x in self.dummy_bl_names] + self.dummy_col_wl_names + supplies) + self.connect_inst([x+"_right" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies) def create_layout(self): self.height = (self.row_size+self.extra_rows)*self.dummy_row.height - self.width = (self.column_size+self.extra_cols)*self.replica_column.width + self.width = (self.column_size+self.extra_cols)*self.cell.width # This is a bitcell x bitcell offset to scale - offset = vector(self.replica_column.width, self.dummy_row.height) + offset = vector(self.cell.width, self.cell.height) self.bitcell_array_inst.place(offset=[0,0]) - self.replica_col_left_inst.place(offset=offset.scale(-1,-2)) - if self.num_ports==2: - self.replica_col_right_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ur(), - mirror="MX") - - self.dummy_row_toptop_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ul(), - mirror="MX") - self.dummy_row_topbot_inst.place(offset=offset.scale(0,0)+self.bitcell_array_inst.ul()) - self.dummy_row_bottop_inst.place(offset=offset.scale(0,0), - mirror="MX") - self.dummy_row_botbot_inst.place(offset=offset.scale(0,-2)) - self.dummy_col_left_inst.place(offset=offset.scale(-2,-2)) - if self.num_ports==2: - self.dummy_col_right_inst.place(offset=offset.scale(1,-2)+self.bitcell_array_inst.lr()) - else: - self.dummy_col_right_inst.place(offset=offset.scale(0,-2)+self.bitcell_array_inst.lr()) + # 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()) + + + # 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") + # 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(-2,-2)) + self.translate_all(offset.scale(-1-self.left_rbl,-1-self.left_rbl)) self.add_layout_pins() @@ -234,52 +282,50 @@ class replica_bitcell_array(design.design): if pin_name.startswith("wl"): pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: - self.add_layout_pin_rect_center(text=pin_name, - layer=pin.layer, - offset=pin.center(), - width=self.width, - height=pin.height()) + self.add_layout_pin(text=pin_name, + layer=pin.layer, + offset=pin.ll().scale(0,1), + width=self.width, + height=pin.height()) elif pin_name.startswith("bl") or pin_name.startswith("br"): pin_list = self.bitcell_array_inst.get_pins(pin_name) for pin in pin_list: - self.add_layout_pin_rect_center(text=pin_name, - layer=pin.layer, - offset=pin.center(), - width=pin.width(), - height=self.height) + self.add_layout_pin(text=pin_name, + layer=pin.layer, + offset=pin.ll().scale(1,0), + width=pin.width(), + height=self.height) - for index,(side1,side2) in enumerate([("bottop","left"),("topbot","right")]): - inst = getattr(self, "dummy_row_{}_inst".format(side1)) - pin_names = inst.mod.get_pin_names() - for pin_name in pin_names: - if pin_name.startswith("wl"): - pin_list = inst.get_pins(pin_name) - for pin in pin_list: - name = "replica_{0}_{1}".format(pin_name,index) - self.add_layout_pin_rect_center(text=name, - layer=pin.layer, - offset=pin.center(), - width=self.width, - height=pin.height()) + # Replica wordlines + for bit in range(self.left_rbl+self.right_rbl): + inst = self.replica_col_inst[bit] + for (pin_name,wl_name) in zip(self.cell.list_all_wl_names(),self.replica_wl_names_list[bit]): + # +1 for dummy row + pin_bit = bit+1 + # +row_size if above the array + if bit>=self.left_rbl: + pin_bit += self.row_size + + pin_name += "_{}".format(pin_bit) + pin = inst.get_pin(pin_name) + self.add_layout_pin(text=wl_name, + layer=pin.layer, + offset=pin.ll().scale(0,1), + width=self.width, + height=pin.height()) - # Replica columns - replica_sides = ["left"] - if self.num_ports==2: - replica_sides.append("right") - for index,side in enumerate(replica_sides): - inst = getattr(self, "replica_col_{}_inst".format(side)) - pin_names = inst.mod.get_pin_names() - for pin_name in pin_names: - if pin_name.startswith("bl") or pin_name.startswith("br"): - pin_list = inst.get_pins(pin_name) - for pin in pin_list: - name = "replica_{0}_{1}".format(pin_name,index) - self.add_layout_pin(text=name, - layer=pin.layer, - offset=pin.ll().scale(1,0), - width=pin.width(), - height=self.height) + # Replica bitlines + for bit in range(self.left_rbl+self.right_rbl): + inst = self.replica_col_inst[bit] + for (pin_name, bl_name) in zip(self.cell.list_all_bitline_names(),self.replica_bl_names_list[bit]): + pin = inst.get_pin(pin_name) + name = "replica_{0}_{1}".format(pin_name,bit) + self.add_layout_pin(text=name, + layer=pin.layer, + offset=pin.ll().scale(1,0), + width=pin.width(), + height=self.height) for pin_name in ["vdd","gnd"]: @@ -291,17 +337,17 @@ class replica_bitcell_array(design.design): # Non-pins - for side in ["botbot", "toptop"]: + for side in ["bot", "top"]: inst = getattr(self, "dummy_row_{}_inst".format(side)) pin_names = inst.mod.get_pin_names() for pin_name in pin_names: if pin_name.startswith("wl"): pin_list = inst.get_pins(pin_name) for pin in pin_list: - self.add_rect_center(layer=pin.layer, - offset=pin.center(), - width=self.width, - height=pin.height()) + self.add_rect(layer=pin.layer, + offset=pin.ll().scale(0,1), + width=self.width, + height=pin.height()) for side in ["left", "right"]: @@ -311,10 +357,10 @@ class replica_bitcell_array(design.design): if pin_name.startswith("b"): pin_list = inst.get_pins(pin_name) for pin in pin_list: - self.add_rect_center(layer=pin.layer, - offset=pin.center(), - width=pin.width(), - height=self.height) + self.add_rect(layer=pin.layer, + offset=pin.ll().scale(1,0), + width=pin.width(), + height=self.height) diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index 2a441f02..61e540cc 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -48,53 +48,34 @@ class replica_bitline(design.design): #self.add_lvs_correspondence_points() # Extra pitch on top and right - self.width = self.replica_column_inst.rx() - self.delay_chain_inst.lx() + self.m2_pitch - self.height = max(self.replica_column_inst.uy(), self.delay_chain_inst.uy()) + self.m3_pitch + self.width = self.delay_chain_inst.rx() + self.m2_pitch + self.height = self.delay_chain_inst.uy() + self.m3_pitch self.add_boundary() self.DRC_LVS() def add_pins(self): - for pin in ["en", "out", "vdd", "gnd"]: - self.add_pin(pin) - + pin_list = ["en", "bl", "wl", "out", "vdd", "gnd"] + pin_dir = ["INPUT", "INPUT", "OUTPUT", "OUTPUT", "POWER", "GROUND"] + self.add_pin_list(pin_list, pin_dir) + def calculate_module_offsets(self): """ Calculate all the module offsets """ - # These aren't for instantiating, but we use them to get the dimensions - self.poly_contact_offset = vector(0.5*contact.poly.width,0.5*contact.poly.height) - - # Quadrant 1: Replica bitline and such are not rotated, but they must be placed far enough - # away from the delay chain/inverter with space for three M2 tracks - self.bitcell_offset = vector(0,self.replica_bitcell.height) - self.rbl_offset = self.bitcell_offset - - # Gap between the delay chain and RBL - gap_width = 2*self.m2_pitch - # Quadrant 4: with some space below it and tracks on the right for vdd/gnd - self.delay_chain_offset = vector(-self.delay_chain.width-gap_width,self.replica_bitcell.height) + self.delay_chain_offset = vector(0, self.inv.height) # Will be flipped vertically below the delay chain # Align it with the inverters in the delay chain to simplify supply connections self.rbl_inv_offset = self.delay_chain_offset + vector(2*self.inv.width, 0) # Placed next to the replica bitcell - self.access_tx_offset = vector(-gap_width-self.access_tx.width-self.inv.width, 0.5*self.inv.height) + self.access_tx_offset = vector(self.rbl_inv_offset.x + self.inv.width, 0.5*self.inv.height) def add_modules(self): """ Add the modules for later usage """ - self.replica_bitcell = factory.create(module_type="replica_bitcell") - self.add_mod(self.replica_bitcell) - - # This is the replica bitline load column that is the height of our array - self.rbl = factory.create(module_type="bitcell_array", - cols=1, - rows=self.bitcell_loads) - self.add_mod(self.rbl) - # FIXME: The FO and depth of this should be tuned self.delay_chain = factory.create(module_type="delay_chain", fanout_list=self.delay_fanout_list) @@ -125,35 +106,6 @@ class replica_bitline(design.design): mod=self.delay_chain) self.connect_inst(["en", "delayed_en", "vdd", "gnd"]) - self.replica_cell_inst=self.add_inst(name="bitcell", - mod=self.replica_bitcell) - temp = [] - for port in self.all_ports: - temp.append("bl{}_0".format(port)) - temp.append("br{}_0".format(port)) - for port in self.all_ports: - temp.append("delayed_en") - temp.append("vdd") - temp.append("gnd") - self.connect_inst(temp) - - self.replica_column_inst=self.add_inst(name="load", - mod=self.rbl) - - temp = [] - for port in self.all_ports: - temp.append("bl{}_0".format(port)) - temp.append("br{}_0".format(port)) - for wl in range(self.bitcell_loads): - for port in self.all_ports: - temp.append("gnd") - temp.append("vdd") - temp.append("gnd") - self.connect_inst(temp) - - self.wl_list = self.rbl.cell.list_all_wl_names() - self.bl_list = self.rbl.cell.list_all_bl_names() - def place_instances(self): """ Add all of the module instances in the logical netlist """ @@ -165,113 +117,23 @@ class replica_bitline(design.design): self.delay_chain_inst.place(self.delay_chain_offset) - self.replica_cell_inst.place(offset=self.bitcell_offset, - mirror="MX") - - self.replica_column_inst.place(self.rbl_offset) - def route(self): """ Connect all the signals together """ self.route_supplies() - self.route_wl() self.route_access_tx() - def route_wl(self): - """ Connect the RBL word lines to gnd """ - # Connect the WL and gnd pins directly to the center and right gnd rails - for row in range(self.bitcell_loads): - wl = self.wl_list[0]+"_{}".format(row) - pin = self.replica_column_inst.get_pin(wl) - - # Route the connection to the right so that it doesn't interfere with the cells - # Wordlines may be close to each other when tiled, so gnd connections are routed in opposite directions - pin_right = pin.rc() - pin_extension = pin_right + vector(self.m3_pitch,0) - - if pin.layer != "metal1": - continue - pin_width_ydir = pin.uy()-pin.by() - #Width is set to pin y width to avoid DRC issues with m1 gaps - self.add_path("metal1", [pin_right, pin_extension], pin_width_ydir) - self.add_power_pin("gnd", pin_extension) - - # for multiport, need to short wordlines to each other so they all connect to gnd. - wl_last = self.wl_list[-1]+"_{}".format(row) - pin_last = self.replica_column_inst.get_pin(wl_last) - self.short_wordlines(pin, pin_last, "right", False, row, vector(self.m3_pitch,0)) - - def short_wordlines(self, wl_pin_a, wl_pin_b, pin_side, is_replica_cell, cell_row=0, offset_x_vec=None): - """Connects the word lines together for a single bitcell. Also requires which side of the bitcell to short the pins.""" - #Assumes input pins are wordlines. Also assumes the word lines are horizontal in metal1. Also assumes pins have same x coord. - #This is my (Hunter) first time editing layout in openram so this function is likely not optimal. - if len(self.all_ports) > 1: - #1. Create vertical metal for all the bitlines to connect to - #m1 needs to be extended in the y directions, direction needs to be determined as every other cell is flipped - correct_y = vector(0, 0.5*drc("minwidth_metal1")) - #x spacing depends on the side being drawn. Unknown to me (Hunter) why the size of the space differs by the side. - #I assume this is related to how a wire is draw, but I have not investigated the issue. - if pin_side == "right": - correct_x = vector(0.5*drc("minwidth_metal1"), 0) - if offset_x_vec != None: - correct_x = offset_x_vec - else: - correct_x = vector(1.5*drc("minwidth_metal1"), 0) - - if wl_pin_a.uy() > wl_pin_b.uy(): - self.add_path("metal1", [wl_pin_a.rc()+correct_x+correct_y, wl_pin_b.rc()+correct_x-correct_y]) - else: - self.add_path("metal1", [wl_pin_a.rc()+correct_x-correct_y, wl_pin_b.rc()+correct_x+correct_y]) - elif pin_side == "left": - if offset_x_vec != None: - correct_x = offset_x_vec - else: - correct_x = vector(1.5*drc("minwidth_metal1"), 0) - - if wl_pin_a.uy() > wl_pin_b.uy(): - self.add_path("metal1", [wl_pin_a.lc()-correct_x+correct_y, wl_pin_b.lc()-correct_x-correct_y]) - else: - self.add_path("metal1", [wl_pin_a.lc()-correct_x-correct_y, wl_pin_b.lc()-correct_x+correct_y]) - else: - debug.error("Could not connect wordlines on specified input side={}".format(pin_side),1) - - #2. Connect word lines horizontally. Only replica cell needs. Bitline loads currently already do this. - for port in self.all_ports: - if is_replica_cell: - wl = self.wl_list[port] - pin = self.replica_cell_inst.get_pin(wl) - else: - wl = self.wl_list[port]+"_{}".format(cell_row) - pin = self.replica_column_inst.get_pin(wl) - - if pin_side == "left": - self.add_path("metal1", [pin.lc()-correct_x, pin.lc()]) - elif pin_side == "right": - self.add_path("metal1", [pin.rc()+correct_x, pin.rc()]) - - - def route_supplies(self): """ Propagate all vdd/gnd pins up to this level for all modules """ - # These are the instances that every bank has - top_instances = [self.replica_column_inst, - self.delay_chain_inst] - for inst in top_instances: - self.copy_layout_pin(inst, "vdd") - self.copy_layout_pin(inst, "gnd") - + self.copy_layout_pin(self.delay_chain_inst, "vdd") + self.copy_layout_pin(self.delay_chain_inst, "gnd") # Route the inverter supply pin from M1 # Only vdd is needed because gnd shares a rail with the delay chain pin = self.rbl_inv_inst.get_pin("vdd") self.add_power_pin("vdd", pin.lc()) - for pin in self.replica_cell_inst.get_pins("vdd"): - self.add_power_pin(name="vdd", loc=pin.center(), vertical=True, start_layer=pin.layer) - - for pin in self.replica_cell_inst.get_pins("gnd"): - self.add_power_pin("gnd", pin.center(), vertical=True, start_layer=pin.layer) @@ -304,24 +166,10 @@ class replica_bitline(design.design): # 3. Route the contact of previous route to the bitcell WL # route bend of previous net to bitcell WL - wl_offset = self.replica_cell_inst.get_pin(self.wl_list[0]).lc() - wl_mid1 = wl_offset - vector(1.5*drc("minwidth_metal1"), 0) - wl_mid2 = vector(wl_mid1.x, contact_offset.y) - #xmid_point= 0.5*(wl_offset.x+contact_offset.x) - #wl_mid1 = vector(xmid_point,contact_offset.y) - #wl_mid2 = vector(xmid_point,wl_offset.y) - self.add_path("metal1", [wl_offset, wl_mid1, wl_mid2, contact_offset]) + self.add_layout_pin_rect_center(text="wl", + layer="metal1", + offset=contact_offset) - # 4. Short wodlines if multiport - wl = self.wl_list[0] - wl_last = self.wl_list[-1] - pin = self.replica_cell_inst.get_pin(wl) - pin_last = self.replica_cell_inst.get_pin(wl_last) - x_offset = self.short_wordlines(pin, pin_last, "left", True) - - #correct = vector(0.5*drc("minwidth_metal1"), 0) - #self.add_path("metal1", [pin.lc()+correct, pin_last.lc()+correct]) - # DRAIN ROUTE # Route the drain to the vdd rail drain_offset = self.tx_inst.get_pin("D").center() @@ -334,13 +182,13 @@ class replica_bitline(design.design): self.add_path("metal1",[source_offset, inv_A_offset]) # Route the connection of the source route to the RBL bitline (left) - # Via will go halfway down from the bitcell - bl_offset = self.replica_cell_inst.get_pin(self.bl_list[0]).bc() - # Route down a pitch so we can use M2 routing - bl_down_offset = bl_offset - vector(0, self.m2_pitch) - self.add_path("metal2",[source_offset, bl_down_offset, bl_offset]) + source_down_offset = source_offset - vector(0,3*self.m2_pitch) + self.add_path("metal1",[source_offset, source_down_offset]) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=source_offset) + self.add_layout_pin_rect_center(text="bl", + layer="metal1", + offset=source_down_offset) # BODY ROUTE # Connect it to the inverter well @@ -351,205 +199,6 @@ class replica_bitline(design.design): width=ur_offset.x-nwell_offset.x, height=ur_offset.y-nwell_offset.y) - def route_vdd(self): - """ Route all signals connected to vdd """ - - self.copy_layout_pin(self.delay_chain_inst,"vdd") - self.copy_layout_pin(self.replica_cell_inst,"vdd") - - # Connect the WL and vdd pins directly to the center and right vdd rails - # Connect RBL vdd pins to center and right rails - rbl_vdd_pins = self.replica_column_inst.get_pins("vdd") - for pin in rbl_vdd_pins: - if pin.layer != "metal1": - continue - start = vector(self.center_vdd_pin.cx(),pin.cy()) - end = vector(self.right_vdd_pin.cx(),pin.cy()) - self.add_layout_pin_segment_center(text="vdd", - layer="metal1", - start=start, - end=end) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=start) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=end) - - # Add via for the inverter - pin = self.rbl_inv_inst.get_pin("vdd") - start = vector(self.left_vdd_pin.cx(),pin.cy()) - end = vector(self.center_vdd_pin.cx(),pin.cy()) - self.add_segment_center(layer="metal1", - start=start, - end=end) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=start) - - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=end) - - - # Add via for the RBC - pin = self.replica_cell_inst.get_pin("vdd") - start = pin.lc() - end = vector(self.right_vdd_pin.cx(),pin.cy()) - self.add_segment_center(layer="metal1", - start=start, - end=end) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=end) - - # Create the RBL rails too - rbl_pins = self.replica_column_inst.get_pins("vdd") - for pin in rbl_pins: - if pin.layer != "metal1": - continue - # If above the delay line, route the full width - left = vector(self.left_vdd_pin.cx(),pin.cy()) - center = vector(self.center_vdd_pin.cx(),pin.cy()) - if pin.cy() > self.delay_chain_inst.uy() + self.m1_pitch: - start = left - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=left) - else: - start = center - end = vector(self.right_vdd_pin.cx()+0.5*self.m1_width,pin.cy()) - self.add_layout_pin_segment_center(text="vdd", - layer="metal1", - start=start, - end=end) - - - - - - - def route_gnd(self): - """ Route all signals connected to gnd """ - - # Route the gnd lines from left to right - - # Add via for the delay chain - left_gnd_start = self.delay_chain_inst.ll().scale(1,0) - vector(2*self.m2_pitch,0) - left_gnd_end = vector(left_gnd_start.x, self.replica_column_inst.uy()+self.m2_pitch) - self.left_gnd_pin=self.add_segment_center(layer="metal2", - start=left_gnd_start, - end=left_gnd_end) - - # Gnd line to the left of the replica bitline - center_gnd_start = self.replica_cell_inst.ll().scale(1,0) - vector(2*self.m2_pitch,0) - center_gnd_end = vector(center_gnd_start.x, self.replica_column_inst.uy()+self.m2_pitch) - self.center_gnd_pin=self.add_segment_center(layer="metal2", - start=center_gnd_start, - end=center_gnd_end) - - # Gnd line to the right of the replica bitline - right_gnd_start = self.replica_cell_inst.lr().scale(1,0) + vector(self.m2_pitch,0) - right_gnd_end = vector(right_gnd_start.x, self.replica_column_inst.uy()+self.m2_pitch) - self.right_gnd_pin=self.add_segment_center(layer="metal2", - start=right_gnd_start, - end=right_gnd_end) - - - - # Connect the WL and gnd pins directly to the center and right gnd rails - for row in range(self.bitcell_loads): - wl = self.wl_list[0]+"_{}".format(row) - pin = self.replica_column_inst.get_pin(wl) - if pin.layer != "metal1": - continue - # If above the delay line, route the full width - left = vector(self.left_gnd_pin.cx(),pin.cy()) - center = vector(self.center_gnd_pin.cx(),pin.cy()) - if pin.cy() > self.delay_chain_inst.uy() + self.m1_pitch: - start = left - else: - start = center - end = vector(self.right_gnd_pin.cx(),pin.cy()) - self.add_layout_pin_segment_center(text="gnd", - layer="metal1", - start=start, - end=end) - if start == left: - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=left) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=center) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=end) - - - # rbl_gnd_pins = self.replica_column_inst.get_pins("gnd") - # # Add L shapes to each vertical gnd rail - # for pin in rbl_gnd_pins: - # if pin.layer != "metal1": - # continue - # # If above the delay line, route the full width - # left = vector(self.left_gnd_pin.cx(),pin.cy()) - # center = vector(self.center_gnd_pin.cx(),pin.cy()) - # if pin.cy() > self.delay_chain_inst.uy() + self.m1_pitch: - # start = left - # else: - # start = center - # end = vector(self.right_gnd_pin.cx(),pin.cy()) - # self.add_segment_center(layer="metal1", - # start=start, - # end=end) - # if start == left: - # self.add_via_center(layers=("metal1", "via1", "metal2"), - # offset=left) - # self.add_via_center(layers=("metal1", "via1", "metal2"), - # offset=center) - # self.add_via_center(layers=("metal1", "via1", "metal2"), - # offset=end) - - - - # Connect the gnd pins of the delay chain to the left rails - dc_gnd_pins = self.delay_chain_inst.get_pins("gnd") - for pin in dc_gnd_pins: - if pin.layer != "metal1": - continue - start = vector(self.left_gnd_pin.cx(),pin.cy()) - # Note, we don't connect to the center rails because of - # via conflicts with the RBL - #end = vector(self.center_gnd_pin.cx(),pin.cy()) - end = pin.rc() - self.add_segment_center(layer="metal1", - start=start, - end=end) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=start) - - # self.add_via_center(layers=("metal1", "via1", "metal2"), - # offset=end) - - - # Add via for the inverter - # pin = self.rbl_inv_inst.get_pin("gnd") - # start = vector(self.left_gnd_pin.cx(),pin.cy()) - # end = vector(self.center_gnd_pin.cx(),pin.cy()) - # self.add_segment_center(layer="metal1", - # start=start, - # end=end) - # self.add_via_center(layers=("metal1", "via1", "metal2"), - # offset=start) - # self.add_via_center(layers=("metal1", "via1", "metal2"), - # offset=end) - - - - # Create RBL rails too - rbl_pins = self.replica_column_inst.get_pins("gnd") - for pin in rbl_pins: - if pin.layer != "metal2": - continue - start = vector(pin.cx(),self.right_gnd_pin.by()) - end = vector(pin.cx(),self.right_gnd_pin.uy()) - self.add_layout_pin_segment_center(text="gnd", - layer="metal2", - start=start, - end=end) - def add_layout_pins(self): diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index d692db78..42903e7c 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -14,13 +14,25 @@ from globals import OPTS class replica_column(design.design): """ Generate a replica bitline column for the replica array. + Rows is the total number of rows i the main array. + Left_rbl and right_rbl are the number of left and right replica bitlines. + Replica bit specifies which replica column this is (to determine where to put the + replica cell. """ - def __init__(self, name, rows, num_ports): + def __init__(self, name, rows, left_rbl, right_rbl, replica_bit): design.design.__init__(self, name) - self.row_size = rows - self.num_ports = num_ports + self.rows = rows + self.left_rbl = left_rbl + self.right_rbl = right_rbl + self.replica_bit = replica_bit + # left, right, regular rows plus top/bottom dummy cells + self.total_size = self.left_rbl+rows+self.right_rbl+2 + + debug.check(replica_bit!=0 and replica_bit!=rows,"Replica bit cannot be the dummy row.") + debug.check(replica_bit<=left_rbl or replica_bit>=self.total_size-right_rbl-1, + "Replica bit cannot be in the regular array.") self.create_netlist() if not OPTS.netlist_only: @@ -32,12 +44,11 @@ class replica_column(design.design): self.create_instances() def create_layout(self): - self.place_instances() - self.add_layout_pins() - - self.height = self.row_size*self.cell.height + self.height = self.total_size*self.cell.height self.width = self.cell.width + self.place_instances() + self.add_layout_pins() self.add_boundary() self.DRC_LVS() @@ -46,7 +57,7 @@ class replica_column(design.design): for cell_column in column_list: self.add_pin("{0}_{1}".format(cell_column,0)) row_list = self.cell.list_all_wl_names() - for row in range(self.row_size): + for row in range(self.total_size): for cell_row in row_list: self.add_pin("{0}_{1}".format(cell_row,row)) @@ -63,9 +74,15 @@ class replica_column(design.design): def create_instances(self): self.cell_inst = {} - for row in range(self.row_size): + for row in range(self.total_size): name="rbc_{0}".format(row) - if row>0 and rowleft_rbl and self.left_rbl and row Date: Thu, 11 Jul 2019 14:47:27 -0700 Subject: [PATCH 086/234] Single banks working with new RBL --- compiler/bitcells/bitcell.py | 8 +- compiler/bitcells/bitcell_1rw_1r.py | 2 + compiler/modules/bank.py | 135 ++++++++++++------- compiler/modules/port_data.py | 97 ++++++++----- compiler/modules/replica_bitcell_array.py | 10 +- compiler/tests/18_port_data_test.py | 4 +- compiler/tests/19_single_bank_1rw_1r_test.py | 8 +- compiler/tests/19_single_bank_1w_1r_test.py | 8 +- compiler/tests/19_single_bank_test.py | 8 +- technology/scn4m_subm/mag_lib/setup.tcl | 3 +- 10 files changed, 176 insertions(+), 107 deletions(-) diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 069d42a7..0c27f116 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -62,12 +62,14 @@ class bitcell(design.design): column_pins = ["br"] return column_pins - def get_bl_name(self): + def get_bl_name(self, port=0): """Get bl name""" + debug.check(port==0,"One port for bitcell only.") return "bl" - def get_br_name(self): + def get_br_name(self, port=0): """Get bl name""" + debug.check(port==0,"One port for bitcell only.") return "br" def analytical_power(self, corner, load): @@ -96,4 +98,4 @@ class bitcell(design.design): def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" - self.add_graph_edges(graph, port_nets) \ No newline at end of file + self.add_graph_edges(graph, port_nets) diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index bd72c61a..aac66514 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -97,10 +97,12 @@ class bitcell_1rw_1r(design.design): def get_bl_name(self, port=0): """Get bl name by port""" + debug.check(port<2,"Two ports for bitcell_1rw_1r only.") return "bl{}".format(port) def get_br_name(self, port=0): """Get bl name by port""" + debug.check(port<2,"Two ports for bitcell_1rw_1r only.") return "br{}".format(port) def analytical_power(self, corner, load): diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index ebf25236..3c1e4136 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -26,17 +26,18 @@ class bank(design.design): This can create up to two ports in any combination: rw, w, r. """ - def __init__(self, sram_config, num_ports, name=""): + def __init__(self, sram_config, name=""): self.sram_config = sram_config sram_config.set_local_config(self) - self.num_ports = num_ports if name == "": name = "bank_{0}_{1}".format(self.word_size, self.num_words) design.design.__init__(self, name) debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words)) + debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.") + # The local control signals are gated when we have bank select logic, # so this prefix will be added to all of the input signals to create # the internal gated signals. @@ -47,7 +48,6 @@ class bank(design.design): self.create_netlist() if not OPTS.netlist_only: - debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.") self.create_layout() self.add_boundary() @@ -155,11 +155,11 @@ class bank(design.design): self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap # These are the offsets of the main array (excluding dummy and replica rows/cols) - self.main_bitcell_array_top = self.bitcell_array_top - (self.num_ports*self.bitcell.height) + self.main_bitcell_array_top = self.bitcell_array.bitcell_array_inst.uy() # Just past the dummy column - self.main_bitcell_array_left = self.bitcell.width + self.main_bitcell_array_left = self.bitcell_array.bitcell_array_inst.lx() # Just past the dummy row and replica row - self.main_bitcell_array_bottom = 2*self.bitcell.height + self.main_bitcell_array_bottom = self.bitcell_array.bitcell_array_inst.by() self.compute_instance_port0_offsets() if len(self.all_ports)==2: @@ -179,7 +179,10 @@ class bank(design.design): # LOWER RIGHT QUADRANT # Below the bitcell array - self.port_data_offsets[port] = vector(self.main_bitcell_array_left,0) + if self.port_data[port].has_rbl(): + self.port_data_offsets[port] = vector(self.main_bitcell_array_left - self.bitcell_array.cell.width,0) + else: + self.port_data_offsets[port] = vector(self.main_bitcell_array_left,0) # UPPER LEFT QUADRANT # To the left of the bitcell array @@ -219,12 +222,12 @@ class bank(design.design): # UPPER LEFT QUADRANT # Above the bitcell array - self.port_data_offsets[port] = vector(0,self.bitcell_array_top) + 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 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_top) + self.port_address_offsets[port] = vector(x_offset,self.main_bitcell_array_bottom) # UPPER RIGHT QUADRANT # Place the col decoder right aligned with wordline driver @@ -322,12 +325,6 @@ class bank(design.design): self.br_names = self.bitcell.list_all_br_names() self.wl_names = self.bitcell.list_all_wl_names() self.bitline_names = self.bitcell.list_all_bitline_names() - - self.bitcell_array = factory.create(module_type="replica_bitcell_array", - cols=self.num_cols, - rows=self.num_rows, - num_ports=self.num_ports) - self.add_mod(self.bitcell_array) self.port_data = [] for port in self.all_ports: @@ -342,7 +339,32 @@ class bank(design.design): cols=self.num_cols, rows=self.num_rows) self.add_mod(self.port_address) - + + + # The number of replica lines depends on the port configuration + rbl_num = [self.read_ports.count(p) for p in self.all_ports] + if len(rbl_num)<2: + rbl_num.append(0) + self.num_rbl = sum(rbl_num) + # The indices always start at 0 + self.rbl_indices = [] + index = 0 + for num in rbl_num: + if num>0: + self.rbl_indices.append(index) + index += 1 + else: + self.rbl_indices.append(-1) + + + self.bitcell_array = factory.create(module_type="replica_bitcell_array", + cols=self.num_cols, + rows=self.num_rows, + left_rbl=rbl_num[0], + right_rbl=rbl_num[1]) + self.add_mod(self.bitcell_array) + + if(self.num_banks > 1): self.bank_select = factory.create(module_type="bank_select") self.add_mod(self.bank_select) @@ -357,15 +379,16 @@ class bank(design.design): temp = [] for col in range(self.num_cols): for bitline in self.bitline_names: - temp.append(bitline+"_{0}".format(col)) - for col in range(self.num_ports): + temp.append("{0}_{1}".format(bitline,col)) + for rbl in range(self.num_rbl): for bitline in self.bitline_names: - temp.append("replica_"+bitline+"_{0}".format(col)) + temp.append("rbl_{0}_{1}".format(bitline,rbl)) for row in range(self.num_rows): for wordline in self.wl_names: - temp.append(wordline+"_{0}".format(row)) - for wordline in self.wl_names: - temp.append("replica_"+wordline) + temp.append("{0}_{1}".format(wordline,row)) + for rbl in range(self.num_rbl): + for wordline in self.wl_names: + temp.append("rbl_{0}_{1}".format(wordline,rbl)) temp.append("vdd") temp.append("gnd") self.connect_inst(temp) @@ -385,9 +408,9 @@ class bank(design.design): mod=self.port_data[port]) temp = [] - if port in self.read_ports: - temp.append("rbl_{0}".format(self.bl_names[port])) - temp.append("rbl_{0}".format(self.br_names[port])) + if self.port_data[port].has_rbl(): + temp.append("rbl_{0}_{1}".format(self.bl_names[port],self.rbl_indices[port])) + temp.append("rbl_{0}_{1}".format(self.br_names[port],self.rbl_indices[port])) for col in range(self.num_cols): temp.append("{0}_{1}".format(self.bl_names[port],col)) temp.append("{0}_{1}".format(self.br_names[port],col)) @@ -435,7 +458,7 @@ class bank(design.design): temp.append("addr{0}_{1}".format(port,bit+self.col_addr_size)) temp.append("wl_en{0}".format(port)) for row in range(self.num_rows): - temp.append(self.wl_names[port]+"_{0}".format(row)) + temp.append("{0}_{1}".format(self.wl_names[port],row)) temp.extend(["vdd", "gnd"]) self.connect_inst(temp) @@ -452,7 +475,7 @@ class bank(design.design): # The address flop and decoder are aligned in the x coord. for port in self.all_ports: - if port%2 == 1: + if port%2: mirror = "MY" else: mirror = "R0" @@ -612,7 +635,7 @@ class bank(design.design): # 2 pitches on the right for vias/jogs to access the inputs control_bus_offset = vector(-self.m2_pitch * self.num_control_lines[0] - self.m2_width, self.min_y_offset) # The control bus is routed up to two pitches below the bitcell array - control_bus_length = -2*self.m1_pitch - self.min_y_offset + control_bus_length = self.main_bitcell_array_bottom - self.min_y_offset - 2*self.m1_pitch self.bus_xoffset[0] = self.create_bus(layer="metal2", pitch=self.m2_pitch, offset=control_bus_offset, @@ -624,7 +647,7 @@ class bank(design.design): # Port 1 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.bitcell_array_top - 2*self.m1_pitch + 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.max_y_offset - control_bus_length) @@ -640,12 +663,20 @@ class bank(design.design): def route_port_data_to_bitcell_array(self, port): """ Routing of BL and BR between port data and bitcell array """ + # Connect the regular bitlines inst2 = self.port_data_inst[port] inst1 = self.bitcell_array_inst inst1_bl_name = self.bl_names[port]+"_{}" inst1_br_name = self.br_names[port]+"_{}" + self.connect_bitlines(inst1=inst1, inst2=inst2, num_bits=self.num_cols, inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) + + # Connect the replica bitlines + if self.port_data[port].has_rbl(): + self.connect_bitline(inst1, inst2, "rbl_{0}_{1}".format(self.bitcell.get_bl_name(port),self.rbl_indices[port]), "rbl_bl") + self.connect_bitline(inst1, inst2, "rbl_{0}_{1}".format(self.bitcell.get_br_name(port),self.rbl_indices[port]), "rbl_br") + def route_port_data_out(self, port): @@ -705,12 +736,9 @@ class bank(design.design): route_map = list(zip(bottom_names, top_names)) self.create_horizontal_channel_route(route_map, offset) - - def connect_bitlines(self, inst1, inst2, num_bits, - inst1_bl_name="bl_{}", inst1_br_name="br_{}", - inst2_bl_name="bl_{}", inst2_br_name="br_{}"): + def connect_bitline(self, inst1, inst2, inst1_name, inst2_name): """ - Connect the bl and br of two modules. + Connect two pins of two modules. This assumes that they have sufficient space to create a jog in the middle between the two modules (if needed). """ @@ -718,23 +746,34 @@ class bank(design.design): # determine top and bottom automatically. # since they don't overlap, we can just check the bottom y coordinate. if inst1.by() < inst2.by(): - (bottom_inst, bottom_bl_name, bottom_br_name) = (inst1, inst1_bl_name, inst1_br_name) - (top_inst, top_bl_name, top_br_name) = (inst2, inst2_bl_name, inst2_br_name) + (bottom_inst, bottom_name) = (inst1, inst1_name) + (top_inst, top_name) = (inst2, inst2_name) else: - (bottom_inst, bottom_bl_name, bottom_br_name) = (inst2, inst2_bl_name, inst2_br_name) - (top_inst, top_bl_name, top_br_name) = (inst1, inst1_bl_name, inst1_br_name) + (bottom_inst, bottom_name) = (inst2, inst2_name) + (top_inst, top_name) = (inst1, inst1_name) + + bottom_pin = bottom_inst.get_pin(bottom_name) + top_pin = top_inst.get_pin(top_name) + debug.check(bottom_pin.layer == top_pin.layer, "Pin layers do not match.") + + bottom_loc = bottom_pin.uc() + top_loc = top_pin.bc() + + yoffset = 0.5*(top_loc.y+bottom_loc.y) + self.add_path(top_pin.layer,[bottom_loc, vector(bottom_loc.x,yoffset), + vector(top_loc.x,yoffset), top_loc]) + + + def connect_bitlines(self, inst1, inst2, num_bits, + inst1_bl_name="bl_{}", inst1_br_name="br_{}", + inst2_bl_name="bl_{}", inst2_br_name="br_{}"): + """ + Connect the bl and br of two modules. + """ for col in range(num_bits): - bottom_bl = bottom_inst.get_pin(bottom_bl_name.format(col)).uc() - bottom_br = bottom_inst.get_pin(bottom_br_name.format(col)).uc() - top_bl = top_inst.get_pin(top_bl_name.format(col)).bc() - top_br = top_inst.get_pin(top_br_name.format(col)).bc() - - yoffset = 0.5*(top_bl.y+bottom_bl.y) - self.add_path("metal2",[bottom_bl, vector(bottom_bl.x,yoffset), - vector(top_bl.x,yoffset), top_bl]) - self.add_path("metal2",[bottom_br, vector(bottom_br.x,yoffset), - vector(top_br.x,yoffset), top_br]) + self.connect_bitline(inst1, inst2, inst1_bl_name.format(col), inst2_bl_name.format(col)) + self.connect_bitline(inst1, inst2, inst1_br_name.format(col), inst2_br_name.format(col)) def route_port_address(self, port): diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 4dce8d59..89020a2b 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -15,6 +15,7 @@ from globals import OPTS class port_data(design.design): """ Create the data port (column mux, sense amps, write driver, etc.) for the given port number. + Port 0 always has the RBL on the left while port 1 is on the right. """ def __init__(self, sram_config, port, name=""): @@ -71,12 +72,12 @@ class port_data(design.design): def add_pins(self): """ Adding pins for port address module""" - if self.port in self.read_ports or self.col_addr_size>0: - self.add_pin("rbl_"+self.bl_names[self.port],"INOUT") - self.add_pin("rbl_"+self.br_names[self.port],"INOUT") + if self.has_rbl(): + self.add_pin("rbl_bl","INOUT") + self.add_pin("rbl_br","INOUT") for bit in range(self.num_cols): - self.add_pin(self.bl_names[self.port]+"_{0}".format(bit),"INOUT") - self.add_pin(self.br_names[self.port]+"_{0}".format(bit),"INOUT") + self.add_pin("bl_{0}".format(bit),"INOUT") + self.add_pin("br_{0}".format(bit),"INOUT") if self.port in self.read_ports: for bit in range(self.word_size): self.add_pin("dout_{}".format(bit),"OUTPUT") @@ -124,9 +125,10 @@ class port_data(design.design): self.route_sense_amp_to_column_mux_or_precharge_array(self.port) self.route_column_mux_to_precharge_array(self.port) else: - # write_driver -> (column_mux) -> bitcell_array + # write_driver -> (column_mux -> precharge) -> bitcell_array self.route_write_driver_in(self.port) - self.route_write_driver_to_column_mux_or_bitcell_array(self.port) + self.route_write_driver_to_column_mux_or_bitcell_array(self.port) + self.route_column_mux_to_precharge_array(self.port) def route_supplies(self): """ Propagate all vdd/gnd pins up to this level for all modules """ @@ -213,11 +215,15 @@ class port_data(design.design): mod=self.precharge_array) temp = [] - temp.append("rbl_"+self.bl_names[self.port]) - temp.append("rbl_"+self.br_names[self.port]) + if self.has_rbl() and self.port==0: + temp.append("rbl_bl") + temp.append("rbl_br") for bit in range(self.num_cols): - temp.append(self.bl_names[self.port]+"_{0}".format(bit)) - temp.append(self.br_names[self.port]+"_{0}".format(bit)) + temp.append("bl_{0}".format(bit)) + temp.append("br_{0}".format(bit)) + if self.has_rbl() and self.port==1: + temp.append("rbl_bl") + temp.append("rbl_br") temp.extend(["p_en_bar", "vdd"]) self.connect_inst(temp) @@ -234,13 +240,13 @@ class port_data(design.design): temp = [] for col in range(self.num_cols): - temp.append(self.bl_names[self.port]+"_{0}".format(col)) - temp.append(self.br_names[self.port]+"_{0}".format(col)) + temp.append("bl_{0}".format(col)) + temp.append("br_{0}".format(col)) for word in range(self.words_per_row): temp.append("sel_{}".format(word)) for bit in range(self.word_size): - temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) - temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) + temp.append("bl_out_{0}".format(bit)) + temp.append("br_out_{0}".format(bit)) temp.append("gnd") self.connect_inst(temp) @@ -263,11 +269,11 @@ class port_data(design.design): for bit in range(self.word_size): temp.append("dout_{}".format(bit)) if self.words_per_row == 1: - temp.append(self.bl_names[self.port]+"_{0}".format(bit)) - temp.append(self.br_names[self.port]+"_{0}".format(bit)) + temp.append("bl_{0}".format(bit)) + temp.append("br_{0}".format(bit)) else: - temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) - temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) + temp.append("bl_out_{0}".format(bit)) + temp.append("br_out_{0}".format(bit)) temp.extend(["s_en", "vdd", "gnd"]) self.connect_inst(temp) @@ -288,11 +294,11 @@ class port_data(design.design): temp.append("din_{}".format(bit)) for bit in range(self.word_size): if (self.words_per_row == 1): - temp.append(self.bl_names[self.port]+"_{0}".format(bit)) - temp.append(self.br_names[self.port]+"_{0}".format(bit)) + temp.append("bl_{0}".format(bit)) + temp.append("br_{0}".format(bit)) else: - temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) - temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) + temp.append("bl_out_{0}".format(bit)) + temp.append("br_out_{0}".format(bit)) temp.extend(["w_en", "vdd", "gnd"]) self.connect_inst(temp) @@ -314,7 +320,7 @@ class port_data(design.design): vertical_port_order.append(self.write_driver_array_inst) # Add one column for the the RBL - if self.port in self.read_ports: + if self.has_rbl() and self.port==0: x_offset = self.bitcell.width else: x_offset = 0 @@ -334,8 +340,10 @@ class port_data(design.design): self.sense_amp_offset = vertical_port_offsets[2] self.column_mux_offset = vertical_port_offsets[1] self.precharge_offset = vertical_port_offsets[0] - if self.precharge_offset: - self.precharge_offset -= vector(x_offset,0) + # Shift the precharge left if port 0 + if self.precharge_offset and self.port==0: + self.precharge_offset -= vector(x_offset,0) + @@ -382,8 +390,11 @@ class port_data(design.design): inst1 = self.column_mux_array_inst inst2 = self.precharge_array_inst - self.connect_bitlines(inst1, inst2, self.num_cols, inst2_start_bit=1) - + if self.has_rbl() and self.port==0: + self.connect_bitlines(inst1, inst2, self.num_cols, inst2_start_bit=1) + else: + self.connect_bitlines(inst1, inst2, self.num_cols) + def route_sense_amp_to_column_mux_or_precharge_array(self, port): @@ -401,7 +412,10 @@ class port_data(design.design): inst1 = self.precharge_array_inst inst1_bl_name = "bl_{}" inst1_br_name = "br_{}" - start_bit=1 + if self.has_rbl() and self.port==0: + start_bit=1 + else: + start_bit=0 self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, @@ -437,17 +451,25 @@ class port_data(design.design): def route_bitline_pins(self): """ Add the bitline pins for the given port """ - if self.port in self.read_ports: + if self.has_rbl() and self.port==0: self.copy_layout_pin(self.precharge_array_inst, "bl_0", "rbl_bl") self.copy_layout_pin(self.precharge_array_inst, "br_0", "rbl_br") + bit_offset=1 + elif self.has_rbl() and self.port==1: + self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(self.num_cols), "rbl_bl") + self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(self.num_cols), "rbl_br") + bit_offset=0 + else: + bit_offset=0 + for bit in range(self.num_cols): - if self.port in self.read_ports: - self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit+1), "bl_{}".format(bit)) - self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit+1), "br_{}".format(bit)) - elif self.column_mux_array_inst: - self.copy_layout_pin(self.column_mux_array_inst, "bl_{}".format(bit)) - self.copy_layout_pin(self.column_mux_array_inst, "br_{}".format(bit)) + if self.precharge_array_inst: + self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit+bit_offset), "bl_{}".format(bit)) + self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit+bit_offset), "br_{}".format(bit)) + # elif self.column_mux_array_inst: + # self.copy_layout_pin(self.column_mux_array_inst, "bl_{}".format(bit)) + # self.copy_layout_pin(self.column_mux_array_inst, "br_{}".format(bit)) else: self.copy_layout_pin(self.write_driver_array_inst, "bl_{}".format(bit)) self.copy_layout_pin(self.write_driver_array_inst, "br_{}".format(bit)) @@ -528,3 +550,6 @@ class port_data(design.design): """Precharge adds a loop between bitlines, can be excluded to reduce complexity""" if self.precharge_array_inst: self.graph_inst_exclude.add(self.precharge_array_inst) + + def has_rbl(self): + return self.port in self.read_ports diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 29724125..2513e419 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -126,7 +126,7 @@ class replica_bitcell_array(design.design): self.bl_names = [x for x in self.bitcell_array.pins if x.startswith("b")] # These are the non-indexed names - self.replica_cell_wl_names = ["replica_"+x for x in self.cell.list_all_wl_names()] + self.replica_cell_wl_names = ["rbl_"+x for x in self.cell.list_all_wl_names()] self.dummy_cell_wl_names = ["dummy_"+x for x in self.cell.list_all_wl_names()] self.dummy_cell_bl_names = ["dummy_"+x for x in self.cell.list_all_bitline_names()] self.dummy_row_bl_names = self.bl_names @@ -136,12 +136,12 @@ class replica_bitcell_array(design.design): 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 bit in range(self.left_rbl): - self.replica_col_wl_names.extend(["replica_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()]) + self.replica_col_wl_names.extend(["rbl_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()]) # Regular WLs self.replica_col_wl_names.extend(self.wl_names) # Right port WLs (one dummy for each port when we allow >1 port) for bit in range(self.left_rbl,self.left_rbl+self.right_rbl): - self.replica_col_wl_names.extend(["replica_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()]) + self.replica_col_wl_names.extend(["rbl_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()]) self.replica_col_wl_names.extend(["{0}_top".format(x) for x in self.dummy_cell_wl_names]) # Left/right dummy columns are connected identically to the replica column @@ -155,7 +155,7 @@ class replica_bitcell_array(design.design): self.replica_bl_names = [] self.replica_wl_names = [] for bit in range(self.left_rbl+self.right_rbl): - self.replica_bl_names_list[bit] = ["replica_{0}_{1}".format(x,bit) for x in self.cell.list_all_bitline_names()] + self.replica_bl_names_list[bit] = ["rbl_{0}_{1}".format(x,bit) for x in self.cell.list_all_bitline_names()] self.replica_bl_names.extend(self.replica_bl_names_list[bit]) self.replica_wl_names_list[bit] = ["{0}_{1}".format(x,bit) for x in self.replica_cell_wl_names] @@ -320,7 +320,7 @@ class replica_bitcell_array(design.design): inst = self.replica_col_inst[bit] for (pin_name, bl_name) in zip(self.cell.list_all_bitline_names(),self.replica_bl_names_list[bit]): pin = inst.get_pin(pin_name) - name = "replica_{0}_{1}".format(pin_name,bit) + name = "rbl_{0}_{1}".format(pin_name,bit) self.add_layout_pin(text=name, layer=pin.layer, offset=pin.ll().scale(1,0), diff --git a/compiler/tests/18_port_data_test.py b/compiler/tests/18_port_data_test.py index 5d72e405..e5f94329 100755 --- a/compiler/tests/18_port_data_test.py +++ b/compiler/tests/18_port_data_test.py @@ -55,9 +55,9 @@ class port_data_test(openram_test): self.local_check(a) OPTS.bitcell = "bitcell_1w_1r" - OPTS.num_rw_ports = 1 + OPTS.num_rw_ports = 0 OPTS.num_r_ports = 1 - OPTS.num_w_ports = 0 + OPTS.num_w_ports = 1 c.num_words=16 c.words_per_row=1 diff --git a/compiler/tests/19_single_bank_1rw_1r_test.py b/compiler/tests/19_single_bank_1rw_1r_test.py index 1bf11a2f..690c621c 100755 --- a/compiler/tests/19_single_bank_1rw_1r_test.py +++ b/compiler/tests/19_single_bank_1rw_1r_test.py @@ -32,7 +32,7 @@ class single_bank_1rw_1r_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "No column mux") - a = factory.create(module_type="bank", sram_config=c, num_ports=2) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) c.num_words=32 @@ -40,7 +40,7 @@ class single_bank_1rw_1r_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Two way column mux") - a = factory.create(module_type="bank", sram_config=c, num_ports=2) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) c.num_words=64 @@ -48,7 +48,7 @@ class single_bank_1rw_1r_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Four way column mux") - a = factory.create(module_type="bank", sram_config=c, num_ports=2) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) c.word_size=2 @@ -57,7 +57,7 @@ class single_bank_1rw_1r_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Eight way column mux") - a = factory.create(module_type="bank", sram_config=c, num_ports=2) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) globals.end_openram() diff --git a/compiler/tests/19_single_bank_1w_1r_test.py b/compiler/tests/19_single_bank_1w_1r_test.py index f40fd929..7c8ad56e 100755 --- a/compiler/tests/19_single_bank_1w_1r_test.py +++ b/compiler/tests/19_single_bank_1w_1r_test.py @@ -32,7 +32,7 @@ class single_bank_1w_1r_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "No column mux") - a = factory.create(module_type="bank", sram_config=c, num_ports=2) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) c.num_words=32 @@ -40,7 +40,7 @@ class single_bank_1w_1r_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Two way column mux") - a = factory.create(module_type="bank", sram_config=c, num_ports=2) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) c.num_words=64 @@ -48,7 +48,7 @@ class single_bank_1w_1r_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Four way column mux") - a = factory.create(module_type="bank", sram_config=c, num_ports=2) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) c.word_size=2 @@ -57,7 +57,7 @@ class single_bank_1w_1r_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Eight way column mux") - a = factory.create(module_type="bank", sram_config=c, num_ports=2) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) globals.end_openram() diff --git a/compiler/tests/19_single_bank_test.py b/compiler/tests/19_single_bank_test.py index 74bb4032..1d010db5 100755 --- a/compiler/tests/19_single_bank_test.py +++ b/compiler/tests/19_single_bank_test.py @@ -28,7 +28,7 @@ class single_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "No column mux") - a = factory.create("bank", sram_config=c, num_ports=1) + a = factory.create("bank", sram_config=c) self.local_check(a) c.num_words=32 @@ -36,7 +36,7 @@ class single_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Two way column mux") - a = factory.create("bank", sram_config=c, num_ports=1) + a = factory.create("bank", sram_config=c) self.local_check(a) c.num_words=64 @@ -44,7 +44,7 @@ class single_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Four way column mux") - a = factory.create("bank", sram_config=c, num_ports=1) + a = factory.create("bank", sram_config=c) self.local_check(a) c.word_size=2 @@ -53,7 +53,7 @@ class single_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Eight way column mux") - a = factory.create("bank", sram_config=c, num_ports=1) + a = factory.create("bank", sram_config=c) self.local_check(a) globals.end_openram() diff --git a/technology/scn4m_subm/mag_lib/setup.tcl b/technology/scn4m_subm/mag_lib/setup.tcl index 17fa18dd..f2567d7d 100644 --- a/technology/scn4m_subm/mag_lib/setup.tcl +++ b/technology/scn4m_subm/mag_lib/setup.tcl @@ -6,7 +6,8 @@ equate class {-circuit1 pfet} {-circuit2 p} flatten class {-circuit1 dummy_cell_6t} flatten class {-circuit1 dummy_cell_1rw_1r} flatten class {-circuit1 dummy_cell_1w_1r} -flatten class {-circuit1 dummy_pbitcell} +flatten class {-circuit1 pbitcell_0} +flatten class {-circuit1 pbitcell_1} property {-circuit1 nfet} remove as ad ps pd property {-circuit1 pfet} remove as ad ps pd property {-circuit2 n} remove as ad ps pd From 043018e8bacb481ecb876b289de429c2fd595387 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 12 Jul 2019 08:42:36 -0700 Subject: [PATCH 087/234] Functional tests working with new RBL. --- compiler/bitcells/bitcell.py | 7 +- compiler/bitcells/bitcell_1rw_1r.py | 5 + compiler/bitcells/bitcell_1w_1r.py | 5 + compiler/bitcells/pbitcell.py | 8 +- compiler/modules/bank.py | 27 ++- compiler/modules/control_logic.py | 171 +++++++++--------- compiler/modules/replica_bitcell_array.py | 5 + compiler/options.py | 4 +- compiler/sram/sram_1bank.py | 4 +- compiler/sram/sram_base.py | 11 +- .../tests/22_psram_1bank_2mux_func_test.py | 2 - .../tests/22_psram_1bank_4mux_func_test.py | 2 - .../tests/22_psram_1bank_8mux_func_test.py | 2 - .../tests/22_psram_1bank_nomux_func_test.py | 2 - .../tests/22_sram_1bank_2mux_func_test.py | 4 +- .../tests/22_sram_1bank_4mux_func_test.py | 2 - .../tests/22_sram_1bank_8mux_func_test.py | 2 - compiler/tests/testutils.py | 2 +- 18 files changed, 152 insertions(+), 113 deletions(-) diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 0c27f116..f18bf700 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -71,7 +71,12 @@ class bitcell(design.design): """Get bl name""" debug.check(port==0,"One port for bitcell only.") return "br" - + + def get_wl_name(self, port=0): + """Get wl name""" + debug.check(port==0,"One port for bitcell only.") + return "wl" + def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" from tech import spice diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index aac66514..68619184 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -104,6 +104,11 @@ class bitcell_1rw_1r(design.design): """Get bl name by port""" debug.check(port<2,"Two ports for bitcell_1rw_1r only.") return "br{}".format(port) + + def get_wl_name(self, port=0): + """Get wl name by port""" + debug.check(port<2,"Two ports for bitcell_1rw_1r only.") + return "wl{}".format(port) def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index 13669dcb..c58ceb9d 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -103,6 +103,11 @@ class bitcell_1w_1r(design.design): """Get bl name by port""" return "br{}".format(port) + def get_wl_name(self, port=0): + """Get wl name by port""" + debug.check(port<2,"Two ports for bitcell_1rw_1r only.") + return "wl{}".format(port) + def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" from tech import spice diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 63691233..01306f7f 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -902,7 +902,13 @@ class pbitcell(design.design): def get_br_name(self, port=0): """Get bl name by port""" - return "br{}".format(port) + return "br{}".format(port) + + def get_wl_name(self, port=0): + """Get wl name by port""" + debug.check(port<2,"Two ports for bitcell_1rw_1r only.") + return "wl{}".format(port) + def analytical_delay(self, corner, slew, load=0, swing = 0.5): parasitic_delay = 1 diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 3c1e4136..f9de4195 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -78,6 +78,9 @@ class bank(design.design): for port in self.read_ports: for bit in range(self.word_size): self.add_pin("dout{0}_{1}".format(port,bit),"OUT") + self.add_pin("rbl_bl{0}_{0}".format(port),"OUT") + for port in self.read_ports: + self.add_pin("rbl_wl{0}_{0}".format(port),"IN") for port in self.write_ports: for bit in range(self.word_size): self.add_pin("din{0}_{1}".format(port,bit),"IN") @@ -108,6 +111,7 @@ class bank(design.design): for port in self.all_ports: self.route_bitlines(port) + self.route_rbl(port) self.route_port_address(port) self.route_column_address_lines(port) self.route_control_lines(port) @@ -116,6 +120,20 @@ class bank(design.design): self.route_supplies() + def route_rbl(self,port): + """ Route the rbl_bl and rbl_wl """ + + if self.port_data[port].has_rbl(): + bl_name = self.bitcell.get_bl_name(port) + bl_pin = self.bitcell_array_inst.get_pin("rbl_{0}_{1}".format(bl_name,port)) + self.add_layout_pin(text="rbl_bl{0}".format(port), + layer=bl_pin.layer, + offset=bl_pin.ll(), + height=bl_pin.height(), + width=bl_pin.width()) + + + def route_bitlines(self, port): """ Route the bitlines depending on the port type rw, w, or r. """ @@ -281,13 +299,13 @@ class bank(design.design): self.input_control_signals = [] port_num = 0 for port in range(OPTS.num_rw_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)]) + self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "rbl_wl{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_w_ports): self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_r_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)]) + self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "rbl_wl{}".format(port_num)]) port_num += 1 # Number of control lines in the bus for each port @@ -904,7 +922,10 @@ class bank(design.design): connection = [] if port in self.read_ports: connection.append((self.prefix+"p_en_bar{}".format(port), self.port_data_inst[port].get_pin("p_en_bar").lc())) - + + if port in self.read_ports: + connection.append((self.prefix+"rbl_wl{}".format(port), self.bitcell_array_inst.get_pin("rbl_{0}_{1}".format(self.bitcell.get_wl_name(port),port)).lc())) + if port in self.write_ports: connection.append((self.prefix+"w_en{}".format(port), self.port_data_inst[port].get_pin("w_en").lc())) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 74fb86c5..f67507b9 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -39,7 +39,7 @@ class control_logic(design.design): self.num_cols = word_size*words_per_row self.num_words = num_rows*words_per_row - self.enable_delay_chain_resizing = True + self.enable_delay_chain_resizing = False self.inv_parasitic_delay = logical_effort.logical_effort.pinv #Determines how much larger the sen delay should be. Accounts for possible error in model. @@ -73,10 +73,8 @@ class control_logic(design.design): def add_pins(self): """ Add the pins to the control logic module. """ - for pin in self.input_list + ["clk"]: - self.add_pin(pin,"INPUT") - for pin in self.output_list: - self.add_pin(pin,"OUTPUT") + self.add_pin_list(self.input_list + ["clk"] + self.rbl_list, "INPUT") + self.add_pin_list(self.output_list,"OUTPUT") self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") @@ -139,46 +137,48 @@ class control_logic(design.design): height=dff_height) self.add_mod(self.p_en_bar_driver) - if (self.port_type == "rw") or (self.port_type == "r"): - from importlib import reload - self.delay_chain_resized = False - c = reload(__import__(OPTS.replica_bitline)) - replica_bitline = getattr(c, OPTS.replica_bitline) - bitcell_loads = int(math.ceil(self.num_rows * OPTS.rbl_delay_percentage)) - #Use a model to determine the delays with that heuristic - if OPTS.use_tech_delay_chain_size: #Use tech parameters if set. - fanout_list = OPTS.delay_chain_stages*[OPTS.delay_chain_fanout_per_stage] - debug.info(1, "Using tech parameters to size delay chain: fanout_list={}".format(fanout_list)) - self.replica_bitline = factory.create(module_type="replica_bitline", - delay_fanout_list=fanout_list, - bitcell_loads=bitcell_loads) - if self.sram != None: #Calculate model value even for specified sizes - self.set_sen_wl_delays() + # if (self.port_type == "rw") or (self.port_type == "r"): + # from importlib import reload + # self.delay_chain_resized = False + # c = reload(__import__(OPTS.replica_bitline)) + # replica_bitline = getattr(c, OPTS.replica_bitline) + # bitcell_loads = int(math.ceil(self.num_rows * OPTS.rbl_delay_percentage)) + # #Use a model to determine the delays with that heuristic + # if OPTS.use_tech_delay_chain_size: #Use tech parameters if set. + # fanout_list = OPTS.delay_chain_stages*[OPTS.delay_chain_fanout_per_stage] + # debug.info(1, "Using tech parameters to size delay chain: fanout_list={}".format(fanout_list)) + # self.replica_bitline = factory.create(module_type="replica_bitline", + # delay_fanout_list=fanout_list, + # bitcell_loads=bitcell_loads) + # if self.sram != None: #Calculate model value even for specified sizes + # self.set_sen_wl_delays() - else: #Otherwise, use a heuristic and/or model based sizing. - #First use a heuristic - delay_stages_heuristic, delay_fanout_heuristic = self.get_heuristic_delay_chain_size() - self.replica_bitline = factory.create(module_type="replica_bitline", - delay_fanout_list=[delay_fanout_heuristic]*delay_stages_heuristic, - bitcell_loads=bitcell_loads) - #Resize if necessary, condition depends on resizing method - if self.sram != None and self.enable_delay_chain_resizing and not self.does_sen_rise_fall_timing_match(): - #This resizes to match fall and rise delays, can make the delay chain weird sizes. - stage_list = self.get_dynamic_delay_fanout_list(delay_stages_heuristic, delay_fanout_heuristic) - self.replica_bitline = factory.create(module_type="replica_bitline", - delay_fanout_list=stage_list, - bitcell_loads=bitcell_loads) + # else: #Otherwise, use a heuristic and/or model based sizing. + # #First use a heuristic + # delay_stages_heuristic, delay_fanout_heuristic = self.get_heuristic_delay_chain_size() + # self.replica_bitline = factory.create(module_type="replica_bitline", + # delay_fanout_list=[delay_fanout_heuristic]*delay_stages_heuristic, + # bitcell_loads=bitcell_loads) + # #Resize if necessary, condition depends on resizing method + # if self.sram != None and self.enable_delay_chain_resizing and not self.does_sen_rise_fall_timing_match(): + # #This resizes to match fall and rise delays, can make the delay chain weird sizes. + # stage_list = self.get_dynamic_delay_fanout_list(delay_stages_heuristic, delay_fanout_heuristic) + # self.replica_bitline = factory.create(module_type="replica_bitline", + # delay_fanout_list=stage_list, + # bitcell_loads=bitcell_loads) - #This resizes based on total delay. - # delay_stages, delay_fanout = self.get_dynamic_delay_chain_size(delay_stages_heuristic, delay_fanout_heuristic) - # self.replica_bitline = factory.create(module_type="replica_bitline", - # delay_fanout_list=[delay_fanout]*delay_stages, - # bitcell_loads=bitcell_loads) + # #This resizes based on total delay. + # # delay_stages, delay_fanout = self.get_dynamic_delay_chain_size(delay_stages_heuristic, delay_fanout_heuristic) + # # self.replica_bitline = factory.create(module_type="replica_bitline", + # # delay_fanout_list=[delay_fanout]*delay_stages, + # # bitcell_loads=bitcell_loads) - self.sen_delay_rise,self.sen_delay_fall = self.get_delays_to_sen() #get the new timing - self.delay_chain_resized = True - - self.add_mod(self.replica_bitline) + # self.sen_delay_rise,self.sen_delay_fall = self.get_delays_to_sen() #get the new timing + # self.delay_chain_resized = True + + self.delay_chain=factory.create(module_type="delay_chain", + fanout_list = OPTS.delay_chain_stages*[OPTS.delay_chain_fanout_per_stage]) + self.add_mod(self.delay_chain) def get_heuristic_delay_chain_size(self): """Use a basic heuristic to determine the size of the delay chain used for the Sense Amp Enable """ @@ -312,8 +312,13 @@ class control_logic(design.design): # List of input control signals if self.port_type == "rw": self.input_list = ["csb", "web"] + self.rbl_list = ["rbl_bl"] + elif self.port_type == "r": + self.input_list = ["csb"] + self.rbl_list = ["rbl_bl"] else: self.input_list = ["csb"] + self.rbl_list = [] if self.port_type == "rw": self.dff_output_list = ["cs_bar", "cs", "we_bar", "we"] @@ -332,9 +337,9 @@ class control_logic(design.design): # Outputs to the bank if self.port_type == "rw": - self.output_list = ["s_en", "w_en", "p_en_bar"] + self.output_list = ["rbl_wl", "s_en", "w_en", "p_en_bar"] elif self.port_type == "r": - self.output_list = ["s_en", "p_en_bar"] + self.output_list = ["rbl_wl", "s_en", "p_en_bar"] else: self.output_list = ["w_en"] self.output_list.append("wl_en") @@ -361,11 +366,11 @@ class control_logic(design.design): if (self.port_type == "rw") or (self.port_type == "w"): self.create_wen_row() if self.port_type == "rw": - self.create_rbl_in_row() + self.create_rbl_row() if (self.port_type == "rw") or (self.port_type == "r"): self.create_pen_row() self.create_sen_row() - self.create_rbl() + self.create_delay() def place_instances(self): @@ -395,17 +400,16 @@ class control_logic(design.design): height = self.w_en_inst.uy() control_center_y = self.w_en_inst.uy() row += 1 - if self.port_type == "rw": - self.place_rbl_in_row(row) - row += 1 if (self.port_type == "rw") or (self.port_type == "r"): + self.place_rbl_row(row) + row += 1 self.place_pen_row(row) row += 1 self.place_sen_row(row) row += 1 - self.place_rbl(row) - height = self.rbl_inst.uy() - control_center_y = self.rbl_inst.by() + self.place_delay(row) + height = self.delay_inst.uy() + control_center_y = self.delay_inst.by() # This offset is used for placement of the control logic in the SRAM level. self.control_logic_center = vector(self.ctrl_dff_inst.rx(), control_center_y) @@ -415,7 +419,7 @@ class control_logic(design.design): # Max of modules or logic rows self.width = max([inst.rx() for inst in self.row_end_inst]) if (self.port_type == "rw") or (self.port_type == "r"): - self.width = max(self.rbl_inst.rx() , self.width) + self.width = max(self.delay_inst.rx() , self.width) self.width += self.m2_pitch def route_all(self): @@ -426,7 +430,7 @@ class control_logic(design.design): if (self.port_type == "rw") or (self.port_type == "w"): self.route_wen() if (self.port_type == "rw") or (self.port_type == "r"): - self.route_rbl_in() + self.route_rbl() self.route_pen() self.route_sen() self.route_clk_buf() @@ -435,24 +439,20 @@ class control_logic(design.design): self.route_supply() - def create_rbl(self): + def create_delay(self): """ Create the replica bitline """ - if self.port_type == "r": - input_name = "gated_clk_bar" - else: - input_name = "rbl_in" - self.rbl_inst=self.add_inst(name="replica_bitline", - mod=self.replica_bitline) - self.connect_inst([input_name, "pre_s_en", "vdd", "gnd"]) + self.delay_inst=self.add_inst(name="delay_chain", + mod=self.delay_chain) + self.connect_inst(["rbl_bl", "pre_s_en", "vdd", "gnd"]) - def place_rbl(self,row): + def place_delay(self,row): """ Place the replica bitline """ y_off = row * self.and2.height + 2*self.m1_pitch # Add the RBL above the rows # Add to the right of the control rows and routing channel offset = vector(0, y_off) - self.rbl_inst.place(offset) + self.delay_inst.place(offset) def create_clk_buf_row(self): @@ -588,44 +588,41 @@ class control_logic(design.design): self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.rail_offsets) self.connect_output(self.wl_en_inst, "Z", "wl_en") - def create_rbl_in_row(self): + def create_rbl_row(self): # input: gated_clk_bar, we_bar, output: rbl_in - self.rbl_in_inst=self.add_inst(name="and2_rbl_in", + self.rbl_inst=self.add_inst(name="and2_rbl", mod=self.and2) - self.connect_inst(["gated_clk_bar", "we_bar", "rbl_in", "vdd", "gnd"]) + self.connect_inst(["gated_clk_bar", "we_bar", "rbl_wl", "vdd", "gnd"]) - def place_rbl_in_row(self,row): + def place_rbl_row(self,row): x_off = self.control_x_offset (y_off,mirror)=self.get_offset(row) offset = vector(x_off, y_off) - self.rbl_in_inst.place(offset, mirror) + self.rbl_inst.place(offset, mirror) - self.row_end_inst.append(self.rbl_in_inst) + self.row_end_inst.append(self.rbl_inst) - def route_rbl_in(self): + def route_rbl(self): """ Connect the logic for the rbl_in generation """ if self.port_type == "rw": input_name = "we_bar" # Connect the NAND gate inputs to the bus rbl_in_map = zip(["A", "B"], ["gated_clk_bar", "we_bar"]) - self.connect_vertical_bus(rbl_in_map, self.rbl_in_inst, self.rail_offsets) + self.connect_vertical_bus(rbl_in_map, self.rbl_inst, self.rail_offsets) # Connect the output of the precharge enable to the RBL input - if self.port_type == "rw": - out_pos = self.rbl_in_inst.get_pin("Z").center() - else: - out_pos = vector(self.rail_offsets["gated_clk_bar"].x, self.rbl_inst.by()-3*self.m2_pitch) - in_pos = self.rbl_inst.get_pin("en").center() - mid1 = vector(in_pos.x,out_pos.y) - self.add_wire(("metal3","via2","metal2"),[out_pos, mid1, in_pos]) - self.add_via_center(layers=("metal1","via1","metal2"), - offset=out_pos) - self.add_via_center(layers=("metal2","via2","metal3"), - offset=out_pos) + #if self.port_type == "rw": + # out_pos = self.rbl_in_inst.get_pin("Z").center() + #else: + # out_pos = vector(self.rail_offsets["gated_clk_bar"].x, self.rbl_inst.by()-3*self.m2_pitch) + + self.copy_layout_pin(self.rbl_inst, "Z", "rbl_wl") + + self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") def create_pen_row(self): if self.port_type == "rw": @@ -698,7 +695,7 @@ class control_logic(design.design): def route_sen(self): - out_pos = self.rbl_inst.get_pin("out").bc() + out_pos = self.delay_inst.get_pin("out").bc() in_pos = self.s_en_inst.get_pin("A").lc() mid1 = vector(out_pos.x,in_pos.y) self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) @@ -817,8 +814,8 @@ class control_logic(design.design): self.add_path("metal1", [row_loc, pin_loc]) if (self.port_type == "rw") or (self.port_type == "r"): - self.copy_layout_pin(self.rbl_inst,"gnd") - self.copy_layout_pin(self.rbl_inst,"vdd") + self.copy_layout_pin(self.delay_inst,"gnd") + self.copy_layout_pin(self.delay_inst,"vdd") self.copy_layout_pin(self.ctrl_dff_inst,"gnd") self.copy_layout_pin(self.ctrl_dff_inst,"vdd") @@ -844,7 +841,7 @@ class control_logic(design.design): # height=pin.height(), # width=pin.width()) - pin=self.rbl_inst.get_pin("out") + pin=self.delay_inst.get_pin("out") self.add_label_pin(text="out", layer=pin.layer, offset=pin.ll(), diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 2513e419..9d141ae9 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -427,3 +427,8 @@ class replica_bitcell_array(design.design): 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""" + self.bitcell_array.graph_exclude_bits(targ_row, targ_col) + diff --git a/compiler/options.py b/compiler/options.py index 6f4859a1..1882f8a1 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -43,11 +43,11 @@ class options(optparse.Values): ################### # Optimization options ################### - rbl_delay_percentage = .5 #Approximate percentage of delay compared to bitlines + rbl_delay_percentage = 0.5 #Approximate percentage of delay compared to bitlines # Allow manual adjustment of the delay chain over automatic use_tech_delay_chain_size = False - delay_chain_stages = 4 + delay_chain_stages = 5 delay_chain_fanout_per_stage = 3 diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 426d7cfe..75308fe7 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -243,6 +243,8 @@ class sram_1bank(sram_base): # The clock gets routed separately and is not a part of the bank if "clk" in signal: continue + if signal.startswith("rbl"): + continue src_pin = self.control_logic_insts[port].get_pin(signal) dest_pin = self.bank_inst.get_pin(signal+"{}".format(port)) self.connect_rail_from_left_m2m3(src_pin, dest_pin) @@ -364,4 +366,4 @@ class sram_1bank(sram_base): #Sanity check in case it was forgotten 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) \ No newline at end of file + return self.bank_inst.mod.get_cell_name(inst_name+'.x'+self.bank_inst.name, row, col) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 2871b67b..97c9831b 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -283,8 +283,7 @@ class sram_base(design, verilog, lef): # Create the bank module (up to four are instantiated) from bank import bank self.bank = bank(self.sram_config, - name="bank", - num_ports=len(self.all_ports)) + name="bank") self.add_mod(self.bank) # Create bank decoder @@ -331,6 +330,10 @@ class sram_base(design, verilog, lef): for port in self.read_ports: for bit in range(self.word_size): temp.append("DOUT{0}[{1}]".format(port,bit)) + for port in self.read_ports: + temp.append("rbl_bl{0}".format(port)) + for port in self.read_ports: + temp.append("rbl_wl{0}".format(port)) for port in self.write_ports: for bit in range(self.word_size): temp.append("BANK_DIN{0}[{1}]".format(port,bit)) @@ -465,8 +468,12 @@ class sram_base(design, verilog, lef): if port in self.readwrite_ports: temp.append("web{}".format(port)) temp.append("clk{}".format(port)) + if port in self.read_ports: + temp.append("rbl_bl{}".format(port)) # Ouputs + if port in self.read_ports: + temp.append("rbl_wl{}".format(port)) if port in self.read_ports: temp.append("s_en{}".format(port)) if port in self.write_ports: diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index be875181..2eaaf48d 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -53,8 +53,6 @@ class psram_1bank_2mux_1rw_1r_1w_func_test(openram_test): corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - d = delay(s.s, tempspice, corner) - feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew) f.num_cycles = 10 (fail, error) = f.run() diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index 389575f7..30d2a465 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -53,8 +53,6 @@ class psram_1bank_4mux_func_test(openram_test): corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - d = delay(s.s, tempspice, corner) - feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew) f.num_cycles = 10 (fail, error) = f.run() diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index 8a0001a9..e5b2e91e 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -53,8 +53,6 @@ class psram_1bank_8mux_func_test(openram_test): corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - d = delay(s.s, tempspice, corner) - feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew) f.num_cycles = 10 (fail, error) = f.run() diff --git a/compiler/tests/22_psram_1bank_nomux_func_test.py b/compiler/tests/22_psram_1bank_nomux_func_test.py index e9b33db2..2f350aa9 100755 --- a/compiler/tests/22_psram_1bank_nomux_func_test.py +++ b/compiler/tests/22_psram_1bank_nomux_func_test.py @@ -53,8 +53,6 @@ class psram_1bank_nomux_func_test(openram_test): corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - d = delay(s.s, tempspice, corner) - feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew) f.num_cycles = 10 (fail, error) = f.run() diff --git a/compiler/tests/22_sram_1bank_2mux_func_test.py b/compiler/tests/22_sram_1bank_2mux_func_test.py index a38d868d..d60d7040 100755 --- a/compiler/tests/22_sram_1bank_2mux_func_test.py +++ b/compiler/tests/22_sram_1bank_2mux_func_test.py @@ -45,11 +45,9 @@ class sram_1bank_2mux_func_test(openram_test): corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - d = delay(s.s, tempspice, corner) - feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew) f.num_cycles = 10 - (fail, error) = f.run(feasible_period) + (fail, error) = f.run() self.assertTrue(fail,error) globals.end_openram() diff --git a/compiler/tests/22_sram_1bank_4mux_func_test.py b/compiler/tests/22_sram_1bank_4mux_func_test.py index cefb9969..e81b3682 100755 --- a/compiler/tests/22_sram_1bank_4mux_func_test.py +++ b/compiler/tests/22_sram_1bank_4mux_func_test.py @@ -45,8 +45,6 @@ class sram_1bank_4mux_func_test(openram_test): corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - d = delay(s.s, tempspice, corner) - feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew) f.num_cycles = 10 (fail, error) = f.run() diff --git a/compiler/tests/22_sram_1bank_8mux_func_test.py b/compiler/tests/22_sram_1bank_8mux_func_test.py index 332e52df..33151f0f 100755 --- a/compiler/tests/22_sram_1bank_8mux_func_test.py +++ b/compiler/tests/22_sram_1bank_8mux_func_test.py @@ -48,8 +48,6 @@ class sram_1bank_8mux_func_test(openram_test): corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - d = delay(s.s, tempspice, corner) - feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew) f.num_cycles = 10 (fail, error) = f.run() diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index df865e00..95cb8122 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -61,7 +61,7 @@ class openram_test(unittest.TestCase): self.fail("LVS mismatch: {}".format(a.name)) # For debug... - #import pdb; pdb.set_trace() + import pdb; pdb.set_trace() if OPTS.purge_temp: self.cleanup() From aa552f8e96e530dfdf74b61f0ecf051f7a6e9133 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 12 Jul 2019 10:17:33 -0700 Subject: [PATCH 088/234] Remove debug trace --- compiler/tests/testutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index 95cb8122..df865e00 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -61,7 +61,7 @@ class openram_test(unittest.TestCase): self.fail("LVS mismatch: {}".format(a.name)) # For debug... - import pdb; pdb.set_trace() + #import pdb; pdb.set_trace() if OPTS.purge_temp: self.cleanup() From dfa2b29b8f1ad0915fde124b76500d43b4b540f2 Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 12 Jul 2019 10:34:29 -0700 Subject: [PATCH 089/234] Begin adding wmask netlist and spice tests. --- compiler/characterizer/functional.py | 66 +++++++-- compiler/characterizer/simulation.py | 34 +++-- compiler/modules/control_logic.py | 2 - compiler/modules/multibank.py | 12 +- compiler/modules/port_data.py | 21 +++ compiler/modules/write_mask_array.py | 158 ++++++++++++++++++++++ compiler/sram/sram_1bank.py | 6 +- compiler/sram/sram_base.py | 14 +- compiler/tests/22_sram_wmask_func_test.py | 62 +++++++++ 9 files changed, 342 insertions(+), 33 deletions(-) create mode 100644 compiler/modules/write_mask_array.py create mode 100755 compiler/tests/22_sram_wmask_func_test.py diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 939ecf96..cf0a30c4 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -37,13 +37,27 @@ class functional(simulation): #self.set_feasible_period(sram, spfile, corner) self.set_stimulus_variables() self.create_signal_names() + self.initilize_wmask() - # Number of checks can be changed self.num_cycles = 2 self.stored_words = {} self.write_check = [] self.read_check = [] + + def initilize_wmask(self): + self.wmask = [None]*self.num_wmask + self.num_wmask = int(self.word_size/self.write_size) + self.wmask_enabled = False + if self.word_size !=self.write_size: + self.wmask_enabled = True + # initialize first wmask bit to 1, otherwise 0 + for bit in range(self.num_wmask): + if bit == 0: + self.wmask[self.num_wmask-1 - bit] = 1 + else: + self.wmask[self.num_wmask-1 - bit] = 0 + print(self.wmask) def run(self, feasible_period=None): if feasible_period: #period defaults to tech.py feasible period otherwise. @@ -71,23 +85,44 @@ class functional(simulation): check = 0 # First cycle idle - comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.t_current) + comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.wmask, self.t_current) self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size) # Write at least once addr = self.gen_addr() word = self.gen_data() - comment = self.gen_cycle_comment("write", word, addr, 0, self.t_current) - self.add_write(comment, addr, word, 0) - self.stored_words[addr] = word - + comment = self.gen_cycle_comment("write", word, addr, 0, self.wmask, self.t_current) + self.add_write(comment, addr, word, self.wmask, 0) + if self.wmask_enabled: + old_word = "" + if self.stored_words.get(addr) == None: + for i in range(self.word_size): + old_word += "X" + else: + old_word = self.stored_words[addr] + for bit in self.wmask: + # Don't write the bits of the new word to the address + if self.wmask[bit] == 0: + lower = bit * self.write_size + upper = lower + self.write_size - 1 + if bit == self.num_wmask-1: + word = word[0:lower] + old_word[lower:upper+1] + elif bit == 0: + word = old_word[lower:upper+1] + word [upper+1:self.word_size] + else: + word = word[0:lower] + old_word[lower:upper+1] + word [upper+1:self.word_size]cfusms + #word = word.replace(word[lower:upper+1],old_word[lower:upper+1],1) + self.stored_words[addr] = word + else: + self.stored_words[addr] = word + # Read at least once. For multiport, it is important that one read cycle uses all RW and R port to read from the same address simultaniously. # This will test the viablilty of the transistor sizing in the bitcell. for port in self.all_ports: if port in self.write_ports: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port) else: - comment = self.gen_cycle_comment("read", word, addr, port, self.t_current) + comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current) self.add_read_one_port(comment, addr, rw_read_din_data, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) check += 1 @@ -95,6 +130,7 @@ class functional(simulation): self.t_current += self.period # Perform a random sequence of writes and reads on random ports, using random addresses and random words + # and random write masks (if applicable) for i in range(self.num_cycles): w_addrs = [] for port in self.all_ports: @@ -112,11 +148,12 @@ class functional(simulation): elif op == "write": addr = self.gen_addr() word = self.gen_data() + wmask = self.gen_wmask() # two ports cannot write to the same address if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port) else: - comment = self.gen_cycle_comment("write", word, addr, port, self.t_current) + comment = self.gen_cycle_comment("write", word, addr, port, wmask, self.t_current) self.add_write_one_port(comment, addr, word, port) self.stored_words[addr] = word w_addrs.append(addr) @@ -126,7 +163,7 @@ class functional(simulation): if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port) else: - comment = self.gen_cycle_comment("read", word, addr, port, self.t_current) + comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current) self.add_read_one_port(comment, addr, rw_read_din_data, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) check += 1 @@ -135,7 +172,7 @@ class functional(simulation): self.t_current += self.period # Last cycle idle needed to correctly measure the value on the second to last clock edge - comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.t_current) + comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.wmask, self.t_current) self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size) def read_stim_results(self): @@ -170,7 +207,14 @@ class functional(simulation): self.read_check[i][2]) return(0, error) return(1, "SUCCESS") - + + def gen_wmask(self): + wmask_bits = [None]*self.num_wmask + for bit in range(self.num_wmask): + rand = random.randint(0, 1) + wmask_bits[bit] = rand + return wmask_bits + def gen_data(self): """ Generates a random word to write. """ rand = random.randint(0,(2**self.word_size)-1) diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index c5e26da1..53e73616 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -34,6 +34,10 @@ class simulation(): self.readwrite_ports = self.sram.readwrite_ports self.read_ports = self.sram.read_ports self.write_ports = self.sram.write_ports + self.num_wmask = int(self.word_size/self.write_size) + self.wmask_enabled = False + if self.word_size !=self.write_size: + self.wmask_enabled = True def set_corner(self,corner): """ Set the corner values """ @@ -127,7 +131,7 @@ class simulation(): debug.error("Non-binary address string",1) bit -= 1 - def add_write(self, comment, address, data, port): + def add_write(self, comment, address, data, wmask, port): """ Add the control values for a write cycle. """ debug.check(port in self.write_ports, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_ports)) debug.info(2, comment) @@ -223,18 +227,28 @@ class simulation(): time_spacing, comment)) - def gen_cycle_comment(self, op, word, addr, port, t_current): + def gen_cycle_comment(self, op, word, addr, port, wmask, t_current): if op == "noop": comment = "\tIdle during cycle {0} ({1}ns - {2}ns)".format(int(t_current/self.period), t_current, t_current+self.period) elif op == "write": - comment = "\tWriting {0} to address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, - addr, - port, - int(t_current/self.period), - t_current, - t_current+self.period) + if (self.wmask_enabled): + comment = "\tWriting {0} to address {1} with mask bit {0} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, + addr, + wmask, + port, + int( + t_current / self.period), + t_current + self.period) + + else: + comment = "\tWriting {0} to address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, + addr, + port, + int(t_current/self.period), + t_current, + t_current+self.period) else: comment = "\tReading {0} from address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, addr, @@ -268,7 +282,9 @@ class simulation(): if (port in read_index) and (port in write_index): pin_names.append("WEB{0}".format(port)) if (self.write_size != self.word_size): - pin_names.append("WMASK{0}".format(port)) + num_wmask = int(self.word_size/self.write_size) + for bit in range(num_wmask): + pin_names.append("WMASK{0}_{1}".format(port,bit)) for port in range(total_ports): pin_names.append("{0}{1}".format(tech.spice["clk"], port)) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 09528509..e2138396 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -759,8 +759,6 @@ class control_logic(design.design): def route_dffs(self): if self.port_type == "rw": - #print("hi") - #if (self.word_size == self.write_size): dff_out_map = zip(["dout_bar_0", "dout_bar_1", "dout_1"], ["cs", "we", "we_bar"]) elif self.port_type == "r": dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"]) diff --git a/compiler/modules/multibank.py b/compiler/modules/multibank.py index 25cce371..e99dab93 100644 --- a/compiler/modules/multibank.py +++ b/compiler/modules/multibank.py @@ -187,9 +187,15 @@ class multibank(design.design): words_per_row=self.words_per_row) self.add_mod(self.sense_amp_array) - self.write_driver_array = self.mod_write_driver_array(columns=self.num_cols, - word_size=self.word_size) - self.add_mod(self.write_driver_array) + if (self.write_size != self.word_size): + self.write_mask_driver_array = self.mod_write_mask_driver_array(columns=self.num_cols, + word_size=self.word_size, + write_size=self.write_size) + self.add_mod(self.write_mask_driver_array) + else: + self.write_driver_array = self.mod_write_driver_array(columns=self.num_cols, + word_size=self.word_size) + self.add_mod(self.write_driver_array) self.row_decoder = self.mod_decoder(rows=self.num_rows) self.add_mod(self.row_decoder) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index ab594c09..b0c74a8d 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -21,6 +21,7 @@ class port_data(design.design): sram_config.set_local_config(self) self.port = port + self.num_wmask = int(self.word_size/self.write_size) if name == "": name = "port_data_{0}".format(self.port) @@ -53,6 +54,8 @@ class port_data(design.design): if self.write_driver_array: self.create_write_driver_array() + if (self.word_size != self.write_size): + self.create_write_mask_array() else: self.write_driver_array_inst = None @@ -164,6 +167,12 @@ class port_data(design.design): columns=self.num_cols, word_size=self.word_size) self.add_mod(self.write_driver_array) + if (self.word_size != self.write_size): + self.write_mask_array = factory.create(module_type="write_mask_array", + columns=self.num_cols, + word_size=self.word_size, + write_size=self.write_size) + self.add_mod(self.write_driver_array) else: self.write_driver_array = None @@ -279,6 +288,18 @@ class port_data(design.design): temp.extend(["w_en", "vdd", "gnd"]) self.connect_inst(temp) + + def create_write_mask_array(self): + """ Creating Write Masks """ + self.write_mask_array_inst = self.add_inst(name="write_mask_array{}".format(self.port), + mod=self.write_mask_array) + + temp = [] + for bit in range(self.num_wmask): + temp.append("write_mask_".format(bit)) + temp.extend(["w_en", "vdd", "gnd"]) + self.connect_inst(temp) + def place_write_driver_array(self, offset): """ Placing Write Driver """ diff --git a/compiler/modules/write_mask_array.py b/compiler/modules/write_mask_array.py new file mode 100644 index 00000000..1a349289 --- /dev/null +++ b/compiler/modules/write_mask_array.py @@ -0,0 +1,158 @@ +# 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 math import log +import design +from tech import drc +import debug +from sram_factory import factory +from vector import vector +from globals import OPTS + + +class write_mask_array(design.design): + """ + Array of tristate drivers to write to the bitlines through the column mux. + Dynamically generated write driver array of all bitlines. + """ + + def __init__(self, name, columns, word_size, write_size): + design.design.__init__(self, 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)) + self.add_comment("write_size {0}".format(write_size)) + + self.columns = columns + self.word_size = word_size + self.write_size = write_size + self.words_per_row = int(columns / word_size) + self.num_wmask = int(word_size / write_size) + + self.create_netlist() + # if not OPTS.netlist_only: + # self.create_layout() + + def create_netlist(self): + self.add_modules() + self.add_pins() + self.create_write_mask_array() + self.create_and2_array() + + + # def create_layout(self): + # + # if self.bitcell.width > self.driver.width: + # self.width = self.columns * self.bitcell.width + # else: + # self.width = self.columns * self.driver.width + # + # self.height = self.driver.height + # + # self.place_write_array() + # self.add_layout_pins() + # self.add_boundary() + # self.DRC_LVS() + + def add_pins(self): + for bit in range(self.num_wmask): + self.add_pin("wdriver_sel_{}".format(bit)) + self.add_pin("en") + self.add_pin("vdd") + self.add_pin("gnd") + + def add_modules(self): + self.wmask = factory.create(module_type="dff_buf") + self.add_mod(self.wmask) + dff_height = self.wmask.height + + self.and2 = factory.create(module_type="pand2", + size=4, + height=dff_height) + self.add_mod(self.and2) + + + def create_write_mask_array(self): + self.wmask_insts = {} + for bit in range(self.num_wmask): + name = "write_mask_{}".format(bit) + self.wmask_insts[bit] = self.add_inst(name=name, + mod=self.wmask) + + self.connect_inst(["wmask_{}".format(bit), + "bank_wmask_{}".format(bit), + "bank_wmask_bar_{}".format(bit), + "clk", "vdd", "gnd"]) + + def create_and2_array(self): + self.and2_insts = {} + for bit in range(self.num_wmask): + name = "and2_{}".format(bit) + self.and2_insts[bit] = self.add_inst(name=name, + mod=self.and2) + self.connect_inst(["bank_wmask_{}".format(bit), + "en", + "wdriver_sel_{}".format(bit), + "vdd", "gnd"]) + + + # def place_write_array(self): + # if self.bitcell.width > self.driver.width: + # driver_spacing = self.bitcell.width + # else: + # driver_spacing = self.driver.width + # + # for i in range(0, self.columns, self.words_per_row): + # index = int(i / self.words_per_row) + # base = vector(i * driver_spacing, 0) + # self.driver_insts[index].place(base) + + # def add_layout_pins(self): + # for i in range(self.word_size): + # din_pin = self.driver_insts[i].get_pin("din") + # self.add_layout_pin(text="data_{0}".format(i), + # layer="metal2", + # offset=din_pin.ll(), + # width=din_pin.width(), + # height=din_pin.height()) + # bl_pin = self.driver_insts[i].get_pin("bl") + # self.add_layout_pin(text="bl_{0}".format(i), + # layer="metal2", + # offset=bl_pin.ll(), + # width=bl_pin.width(), + # height=bl_pin.height()) + # + # br_pin = self.driver_insts[i].get_pin("br") + # self.add_layout_pin(text="br_{0}".format(i), + # layer="metal2", + # offset=br_pin.ll(), + # width=br_pin.width(), + # height=br_pin.height()) + # + # for n in ["vdd", "gnd"]: + # pin_list = self.driver_insts[i].get_pins(n) + # for pin in pin_list: + # pin_pos = pin.center() + # # Add the M2->M3 stack + # self.add_via_center(layers=("metal2", "via2", "metal3"), + # offset=pin_pos) + # self.add_layout_pin_rect_center(text=n, + # layer="metal3", + # offset=pin_pos) + # + # self.add_layout_pin(text="en", + # layer="metal1", + # offset=self.driver_insts[0].get_pin("en").ll().scale(0, 1), + # width=self.width, + # height=drc('minwidth_metal1')) + + # def get_w_en_cin(self): + # """Get the relative capacitance of all the enable connections in the bank""" + # # The enable is connected to a nand2 for every row. + # return self.driver.get_w_en_cin() * len(self.driver_insts) + + diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index c51e51fd..1d749e16 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -128,9 +128,9 @@ class sram_1bank(sram_base): # Add the write mask flops to the left of the din flops. if (self.write_size != self.word_size): if port in self.write_ports: - wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - self.bank.height + max_gap_size + self.data_dff_insts[port].height) - self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") + wmask_pos[port] = vector(self.bank.bank_array_ll.x - self.control_logic_insts[port].width, + -max_gap_size - self.wmask_dff_insts[port].height) + self.wmask_dff_insts[port].place(wmask_pos[port]) if len(self.all_ports)>1: diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 821c75d4..6295f587 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -40,6 +40,7 @@ class sram_base(design, verilog, lef): def add_pins(self): """ Add pins for entire SRAM. """ + self.num_masks = int(self.word_size/self.write_size) for port in self.write_ports: for bit in range(self.word_size): self.add_pin("DIN{0}[{1}]".format(port,bit),"INPUT") @@ -71,7 +72,8 @@ class sram_base(design, verilog, lef): # add the optional write mask pins if self.word_size != self.write_size: for port in self.write_ports: - self.add_pin("wmask{}".format(port),"INPUT") + for bit in range(self.num_masks): + self.add_pin("wmask{0}[{1}]".format(port,bit),"INPUT") for port in self.read_ports: for bit in range(self.word_size): self.add_pin("DOUT{0}[{1}]".format(port,bit),"OUTPUT") @@ -149,7 +151,7 @@ class sram_base(design, verilog, lef): elif "metal3" in tech.layer: from supply_tree_router import supply_tree_router as router rtr=router(("metal3",), self) - + rtr.route() @@ -278,8 +280,10 @@ class sram_base(design, verilog, lef): self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size) self.add_mod(self.data_dff) - self.wmask_dff = dff_array(name="wmask_dff", rows=1, columns=int(self.word_size/self.write_size)) - self.add_mod(self.wmask_dff) + if (self.write_size != self.word_size): + num_wmask = int(self.word_size/self.write_size) + self.wmask_dff = dff_array(name="wmask_dff", rows=1, columns=num_wmask) + self.add_mod(self.wmask_dff) # Create the bank module (up to four are instantiated) @@ -469,7 +473,7 @@ class sram_base(design, verilog, lef): outputs = [] for bit in range(num_wmask): inputs.append("wmask{}[{}]".format(port, bit)) - outputs.append("BANK_WMASK{}[{}]".format(port, bit)) + outputs.append("bank_wmask{}[{}]".format(port, bit)) self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"]) diff --git a/compiler/tests/22_sram_wmask_func_test.py b/compiler/tests/22_sram_wmask_func_test.py new file mode 100755 index 00000000..ebf2137f --- /dev/null +++ b/compiler/tests/22_sram_wmask_func_test.py @@ -0,0 +1,62 @@ +#!/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 + +#@unittest.skip("SKIPPING sram_wmask_func_test") +class sram_wmask_func_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + OPTS.analytical_delay = False + OPTS.netlist_only = True + OPTS.trim_netlist = False + + # This is a hack to reload the characterizer __init__ with the spice version + from importlib import reload + import characterizer + reload(characterizer) + from characterizer import functional, delay + from sram_config import sram_config + c = sram_config(word_size=8, + num_words=16, + write_size=4, + num_banks=1) + c.words_per_row=4 + c.recompute_sizes() + debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} bit writes, {} banks".format(c.word_size, + c.num_words, + c.words_per_row, + c.write_size, + c.num_banks)) + s = factory.create(module_type="sram", sram_config=c) + tempspice = OPTS.openram_temp + "temp.sp" + s.sp_write(tempspice) + + corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) + + f = functional(s.s, tempspice, corner) + f.num_cycles = 10 + (fail, error) = f.run() + self.assertTrue(fail, error) + + 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 17d144b5b547ba2d8ca52bb07d3bef4c1762eb18 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 12 Jul 2019 10:39:55 -0700 Subject: [PATCH 090/234] Clean up multiport test options to be consistent. --- compiler/modules/control_logic.py | 3 +-- compiler/tests/05_bitcell_1rw_1r_array_test.py | 9 ++++++--- compiler/tests/05_replica_bitcell_1rw_1r_array_test.py | 7 +++++-- compiler/tests/19_single_bank_1rw_1r_test.py | 9 ++++++--- compiler/tests/19_single_bank_1w_1r_test.py | 9 ++++++--- compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py | 3 ++- compiler/tests/20_psram_1bank_2mux_1w_1r_test.py | 3 ++- compiler/tests/20_psram_1bank_2mux_test.py | 1 + compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py | 3 ++- compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py | 1 + compiler/tests/20_sram_1bank_2mux_1w_1r_test.py | 3 ++- compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py | 1 + compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py | 1 + compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py | 1 + 14 files changed, 37 insertions(+), 17 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index f67507b9..c795888a 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -365,9 +365,8 @@ class control_logic(design.design): self.create_wlen_row() if (self.port_type == "rw") or (self.port_type == "w"): self.create_wen_row() - if self.port_type == "rw": - self.create_rbl_row() if (self.port_type == "rw") or (self.port_type == "r"): + self.create_rbl_row() self.create_pen_row() self.create_sen_row() self.create_delay() diff --git a/compiler/tests/05_bitcell_1rw_1r_array_test.py b/compiler/tests/05_bitcell_1rw_1r_array_test.py index 78d8d646..972fb8e6 100755 --- a/compiler/tests/05_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/05_bitcell_1rw_1r_array_test.py @@ -21,13 +21,16 @@ class bitcell_1rw_1r_array_test(openram_test): def runTest(self): - debug.info(2, "Testing 4x4 array for cell_1rw_1r") + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + OPTS.bitcell = "bitcell_1rw_1r" + OPTS.replica_bitcell = "replica_bitcell_1rw_1r" + OPTS.dummy_bitcell="dummy_bitcell_1rw_1r" OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 - globals.init_openram("config_{0}".format(OPTS.tech_name)) - + debug.info(2, "Testing 4x4 array for cell_1rw_1r") a = factory.create(module_type="bitcell_array", cols=4, rows=4) self.local_check(a) diff --git a/compiler/tests/05_replica_bitcell_1rw_1r_array_test.py b/compiler/tests/05_replica_bitcell_1rw_1r_array_test.py index 6a7c6aaf..ddf6be60 100755 --- a/compiler/tests/05_replica_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/05_replica_bitcell_1rw_1r_array_test.py @@ -16,12 +16,15 @@ import debug class replica_bitcell_array_test(openram_test): def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + OPTS.bitcell = "bitcell_1rw_1r" + OPTS.replica_bitcell = "replica_bitcell_1rw_1r" + OPTS.dummy_bitcell="dummy_bitcell_1rw_1r" OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 - globals.init_openram("config_{0}".format(OPTS.tech_name)) - 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) self.local_check(a) diff --git a/compiler/tests/19_single_bank_1rw_1r_test.py b/compiler/tests/19_single_bank_1rw_1r_test.py index 690c621c..ab5ce041 100755 --- a/compiler/tests/19_single_bank_1rw_1r_test.py +++ b/compiler/tests/19_single_bank_1rw_1r_test.py @@ -18,13 +18,16 @@ import debug class single_bank_1rw_1r_test(openram_test): def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + from sram_config import sram_config + + OPTS.bitcell = "bitcell_1rw_1r" + OPTS.replica_bitcell = "replica_bitcell_1rw_1r" + OPTS.dummy_bitcell="dummy_bitcell_1rw_1r" OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 - globals.init_openram("config_{0}".format(OPTS.tech_name)) - - from sram_config import sram_config c = sram_config(word_size=4, num_words=16) diff --git a/compiler/tests/19_single_bank_1w_1r_test.py b/compiler/tests/19_single_bank_1w_1r_test.py index 7c8ad56e..81d4c8e6 100755 --- a/compiler/tests/19_single_bank_1w_1r_test.py +++ b/compiler/tests/19_single_bank_1w_1r_test.py @@ -18,13 +18,16 @@ import debug class single_bank_1w_1r_test(openram_test): def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + from sram_config import sram_config + + OPTS.bitcell = "bitcell_1w_1r" + OPTS.replica_bitcell = "replica_bitcell_1w_1r" + OPTS.dummy_bitcell="dummy_bitcell_1w_1r" OPTS.num_rw_ports = 0 OPTS.num_r_ports = 1 OPTS.num_w_ports = 1 - globals.init_openram("config_{0}".format(OPTS.tech_name)) - - from sram_config import sram_config c = sram_config(word_size=4, num_words=16) diff --git a/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py b/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py index cd7086b6..fdeae56f 100755 --- a/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py +++ b/compiler/tests/20_psram_1bank_2mux_1rw_1w_test.py @@ -21,9 +21,10 @@ class psram_1bank_2mux_1rw_1w_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) from sram_config import sram_config + OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" - + OPTS.dummy_bitcell="dummy_pbitcell" OPTS.num_rw_ports = 1 OPTS.num_w_ports = 1 OPTS.num_r_ports = 0 diff --git a/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py b/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py index 8b716d43..a5c01d8f 100755 --- a/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py +++ b/compiler/tests/20_psram_1bank_2mux_1w_1r_test.py @@ -21,9 +21,10 @@ class psram_1bank_2mux_1w_1r_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) from sram_config import sram_config + OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" - + OPTS.dummy_bitcell="dummy_pbitcell" OPTS.num_rw_ports = 0 OPTS.num_w_ports = 1 OPTS.num_r_ports = 1 diff --git a/compiler/tests/20_psram_1bank_2mux_test.py b/compiler/tests/20_psram_1bank_2mux_test.py index 5f0cba17..64fa72ca 100755 --- a/compiler/tests/20_psram_1bank_2mux_test.py +++ b/compiler/tests/20_psram_1bank_2mux_test.py @@ -23,6 +23,7 @@ class psram_1bank_2mux_test(openram_test): from sram_config import sram_config OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" + OPTS.dummy_bitcell="dummy_pbitcell" # testing layout of sram using pbitcell with 1 RW port (a 6T-cell equivalent) OPTS.num_rw_ports = 1 diff --git a/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py b/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py index d674c04e..7779b794 100755 --- a/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py +++ b/compiler/tests/20_psram_1bank_4mux_1rw_1r_test.py @@ -20,9 +20,10 @@ class psram_1bank_4mux_1rw_1r_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) from sram_config import sram_config + OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" - + OPTS.dummy_bitcell="dummy_pbitcell" OPTS.num_rw_ports = 1 OPTS.num_w_ports = 0 OPTS.num_r_ports = 1 diff --git a/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py index acaf5844..60192759 100755 --- a/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_2mux_1rw_1r_test.py @@ -23,6 +23,7 @@ class sram_1bank_2mux_1rw_1r_test(openram_test): OPTS.bitcell = "bitcell_1rw_1r" OPTS.replica_bitcell = "replica_bitcell_1rw_1r" + OPTS.dummy_bitcell="dummy_bitcell_1rw_1r" OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 diff --git a/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py b/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py index 50af484f..2e1e848f 100755 --- a/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py +++ b/compiler/tests/20_sram_1bank_2mux_1w_1r_test.py @@ -21,9 +21,10 @@ class psram_1bank_2mux_1w_1r_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) from sram_config import sram_config + OPTS.bitcell = "bitcell_1w_1r" OPTS.replica_bitcell="replica_bitcell_1w_1r" - + OPTS.dummy_bitcell="dummy_bitcell_1w_1r" OPTS.num_rw_ports = 0 OPTS.num_w_ports = 1 OPTS.num_r_ports = 1 diff --git a/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py index 1cd89037..48a42106 100755 --- a/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_8mux_1rw_1r_test.py @@ -23,6 +23,7 @@ class sram_1bank_8mux_1rw_1r_test(openram_test): OPTS.bitcell = "bitcell_1rw_1r" OPTS.replica_bitcell = "replica_bitcell_1rw_1r" + OPTS.dummy_bitcell="dummy_bitcell_1rw_1r" OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 diff --git a/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py b/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py index 570cf092..f6bccc13 100755 --- a/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py +++ b/compiler/tests/20_sram_1bank_nomux_1rw_1r_test.py @@ -23,6 +23,7 @@ class sram_1bank_nomux_1rw_1r_test(openram_test): OPTS.bitcell = "bitcell_1rw_1r" OPTS.replica_bitcell = "replica_bitcell_1rw_1r" + OPTS.dummy_bitcell = "dummy_bitcell_1rw_1r" OPTS.num_rw_ports = 1 OPTS.num_r_ports = 1 OPTS.num_w_ports = 0 diff --git a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py index e733fce3..fb85f5bf 100755 --- a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py @@ -25,6 +25,7 @@ class psram_1bank_nomux_func_test(openram_test): OPTS.trim_netlist = False OPTS.bitcell = "bitcell_1rw_1r" OPTS.replica_bitcell = "replica_bitcell_1rw_1r" + OPTS.dummy_bitcell="dummy_bitcell_1rw_1r" OPTS.num_rw_ports = 1 OPTS.num_w_ports = 0 OPTS.num_r_ports = 1 From 80145c0a9269f4584982aac83af756c65ab349c5 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 12 Jul 2019 10:57:59 -0700 Subject: [PATCH 091/234] Only enable pdb post-mortem when not purging temp for debug. --- compiler/tests/testutils.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index d4d289bb..057fd7bf 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -309,16 +309,18 @@ def header(filename, technology): def debugTestRunner(post_mortem=None): """unittest runner doing post mortem debugging on failing tests""" - if post_mortem is None: + if post_mortem is None and not OPTS.purge_temp: post_mortem = pdb.post_mortem class DebugTestResult(unittest.TextTestResult): def addError(self, test, err): # called before tearDown() traceback.print_exception(*err) - post_mortem(err[2]) + if post_mortem: + post_mortem(err[2]) super(DebugTestResult, self).addError(test, err) def addFailure(self, test, err): traceback.print_exception(*err) - post_mortem(err[2]) + if post_mortem: + post_mortem(err[2]) super(DebugTestResult, self).addFailure(test, err) return unittest.TextTestRunner(resultclass=DebugTestResult) From d72691f6c2568d4234978b52ae93a26795071f07 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 12 Jul 2019 11:14:47 -0700 Subject: [PATCH 092/234] Make mirror optional argument --- compiler/modules/dummy_array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py index 861e0fad..e175e732 100644 --- a/compiler/modules/dummy_array.py +++ b/compiler/modules/dummy_array.py @@ -15,7 +15,7 @@ class dummy_array(design.design): """ Generate a dummy row/column for the replica array. """ - def __init__(self, cols, rows, mirror, name): + def __init__(self, cols, rows, mirror=0, 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)) From 9092fa4ee6f1bee54195d65a03baf562e29cce3d Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 12 Jul 2019 11:18:47 -0700 Subject: [PATCH 093/234] Remove multiport control logic test since it doesn't have a bitcell anymore. --- .../tests/16_control_logic_multiport_test.py | 59 ------------------- 1 file changed, 59 deletions(-) delete mode 100755 compiler/tests/16_control_logic_multiport_test.py diff --git a/compiler/tests/16_control_logic_multiport_test.py b/compiler/tests/16_control_logic_multiport_test.py deleted file mode 100755 index 3ad898b1..00000000 --- a/compiler/tests/16_control_logic_multiport_test.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/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. -# -""" -Run a regression test on a control_logic -""" - -import unittest -from testutils import header,openram_test -import sys,os -sys.path.append(os.path.join(sys.path[0],"..")) -import globals -from globals import OPTS -from sram_factory import factory -import debug - -class control_logic_test(openram_test): - - def runTest(self): - globals.init_openram("config_{0}".format(OPTS.tech_name)) - import control_logic - import tech - - # check control logic for multi-port - OPTS.bitcell = "pbitcell" - OPTS.replica_bitcell = "replica_pbitcell" - OPTS.num_rw_ports = 1 - OPTS.num_w_ports = 1 - OPTS.num_r_ports = 1 - - debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, write_size=8, port_type="rw") - self.local_check(a) - - # OPTS.num_rw_ports = 0 - # OPTS.num_w_ports = 1 - debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, write_size=8, port_type="w") - self.local_check(a) - - # OPTS.num_w_ports = 0 - # OPTS.num_r_ports = 1 - debug.info(1, "Testing sample for control_logic for multiport, only read control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, write_size=8, port_type="r") - 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() From 8815ddf7f1365ef8400c6fddab775d4633c6d8c0 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 12 Jul 2019 11:55:42 -0700 Subject: [PATCH 094/234] Remove unnecessary feasible period search. --- compiler/tests/22_sram_1bank_nomux_func_test.py | 2 +- compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/tests/22_sram_1bank_nomux_func_test.py b/compiler/tests/22_sram_1bank_nomux_func_test.py index af626104..9f777dc1 100755 --- a/compiler/tests/22_sram_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1bank_nomux_func_test.py @@ -43,8 +43,8 @@ class sram_1bank_nomux_func_test(openram_test): s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) - f = functional(s.s, tempspice, corner) + f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail,error) diff --git a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py index fb85f5bf..293d52d8 100755 --- a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py @@ -51,8 +51,6 @@ class psram_1bank_nomux_func_test(openram_test): corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - d = delay(s.s, tempspice, corner) - feasible_period = self.find_feasible_test_period(d, s.s, f.load, f.slew) f.num_cycles = 10 (fail, error) = f.run() From 2271946eefa6f6acadc30205d7181ad1a875f2a4 Mon Sep 17 00:00:00 2001 From: mrg Date: Fri, 12 Jul 2019 14:39:56 -0700 Subject: [PATCH 095/234] Fix replica array pin names --- compiler/modules/replica_bitcell_array.py | 164 ++++++++++------------ 1 file changed, 76 insertions(+), 88 deletions(-) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 9d141ae9..12401301 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -32,11 +32,7 @@ class replica_bitcell_array(design.design): self.left_rbl = left_rbl self.right_rbl = right_rbl - # FIXME: If we want more than 2 ports of RBL, we also need to modify - # replica_column to support this. Right now, it only supports a single - # RBL and is used for both the left and right column (right is flipped). - #debug.check(self.left_rbl<=1,"Only one RBL supported now.") - #debug.check(self.right_rbl<=1,"Only one RBL supported now.") + debug.check(left_rbl+right_rbl==len(self.read_ports),"Invalid number of RBLs for port configuration.") # Two dummy rows/cols plus replica for each port self.extra_rows = 2 + left_rbl + right_rbl @@ -122,50 +118,69 @@ class replica_bitcell_array(design.design): def add_pins(self): - self.wl_names = [x for x in self.bitcell_array.pins if x.startswith("w")] - self.bl_names = [x for x in self.bitcell_array.pins if x.startswith("b")] + self.bitcell_array_wl_names = [x for x in self.bitcell_array.pins if x.startswith("w")] + self.bitcell_array_bl_names = [x for x in self.bitcell_array.pins if x.startswith("b")] # These are the non-indexed names - self.replica_cell_wl_names = ["rbl_"+x for x in self.cell.list_all_wl_names()] self.dummy_cell_wl_names = ["dummy_"+x for x in self.cell.list_all_wl_names()] self.dummy_cell_bl_names = ["dummy_"+x for x in self.cell.list_all_bitline_names()] - self.dummy_row_bl_names = self.bl_names + self.dummy_row_bl_names = self.bitcell_array_bl_names + self.rbl_bl_names = [] + self.rbl_wl_names = [] + for port in range(self.left_rbl+self.right_rbl): + self.rbl_bl_names.append("rbl_bl{}".format(port)) + self.rbl_wl_names.append("rbl_wl{}".format(port)) + # 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 bit in range(self.left_rbl): - self.replica_col_wl_names.extend(["rbl_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()]) + for port in range(self.left_rbl): + # Make names for all RBLs + wl_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.list_all_wl_names()] + # Rename the one we will use + wl_names[port] = self.rbl_wl_names[port] + self.replica_col_wl_names.extend(wl_names) # Regular WLs - self.replica_col_wl_names.extend(self.wl_names) + 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 bit in range(self.left_rbl,self.left_rbl+self.right_rbl): - self.replica_col_wl_names.extend(["rbl_{0}_{1}".format(x,bit) for x in self.cell.list_all_wl_names()]) + for port in range(self.left_rbl,self.left_rbl+self.right_rbl): + # Make names for all RBLs + wl_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.list_all_wl_names()] + # Rename the one we will use + wl_names[port] = self.rbl_wl_names[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]) # Left/right dummy columns are connected identically to the replica column self.dummy_col_wl_names = self.replica_col_wl_names - # Per bit bitline names - self.replica_bl_names_list = {} - self.replica_wl_names_list = {} - # Array of all bitline names - self.replica_bl_names = [] - self.replica_wl_names = [] - for bit in range(self.left_rbl+self.right_rbl): - self.replica_bl_names_list[bit] = ["rbl_{0}_{1}".format(x,bit) for x in self.cell.list_all_bitline_names()] - self.replica_bl_names.extend(self.replica_bl_names_list[bit]) + # 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): + left_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.list_all_bl_names()] + right_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.list_all_br_names()] + left_names[port] = self.rbl_bl_names[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 - self.replica_wl_names_list[bit] = ["{0}_{1}".format(x,bit) for x in self.replica_cell_wl_names] - self.replica_wl_names.extend(self.replica_wl_names_list[bit]) + wl_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.list_all_wl_names()] + wl_names[port] = "rbl_wl{}".format(port) + self.replica_wl_names[port] = wl_names - self.add_pin_list(self.bl_names) - self.add_pin_list(self.replica_bl_names) - self.add_pin_list(self.wl_names) - self.add_pin_list(self.replica_wl_names) + # External pins + self.add_pin_list(self.bitcell_array_bl_names, "INOUT") + for port in range(self.left_rbl+self.right_rbl): + self.add_pin("rbl_bl{}".format(port),"INPUT") + self.add_pin_list(self.bitcell_array_wl_names, "INPUT") + for port in range(self.left_rbl+self.right_rbl): + self.add_pin("rbl_wl{}".format(port),"OUTPUT") self.add_pin("vdd", "POWER") self.add_pin("gnd", "GROUND") @@ -182,27 +197,22 @@ class replica_bitcell_array(design.design): # Main array self.bitcell_array_inst=self.add_inst(name="bitcell_array", mod=self.bitcell_array) - self.connect_inst(self.bitcell_array.pins) + self.connect_inst(self.bitcell_array_bl_names + self.bitcell_array_wl_names + supplies) # Replica columns self.replica_col_inst = {} - for bit in range(self.left_rbl): - self.replica_col_inst[bit]=self.add_inst(name="replica_col_left_{}".format(bit), - mod=self.replica_columns[bit]) - self.connect_inst(self.replica_bl_names_list[bit] + self.replica_col_wl_names + supplies) - - for bit in range(self.left_rbl,self.left_rbl+self.right_rbl): - self.replica_col_inst[bit]=self.add_inst(name="replica_col_right_{}".format(bit), - mod=self.replica_columns[bit]) - self.connect_inst(self.replica_bl_names_list[bit] + self.replica_col_wl_names + supplies) + for port in range(self.left_rbl+self.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) - # Replica rows with replica bitcell + # Dummy rows under the bitcell array (connected with with the replica cell wl) self.dummy_row_replica_inst = {} - for bit in range(self.left_rbl+self.right_rbl): - self.dummy_row_replica_inst[bit]=self.add_inst(name="dummy_row_{}".format(bit), - mod=self.dummy_row) - self.connect_inst(self.dummy_row_bl_names + self.replica_wl_names_list[bit] + supplies) + 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) # Top/bottom dummy rows @@ -298,34 +308,37 @@ class replica_bitcell_array(design.design): # Replica wordlines - for bit in range(self.left_rbl+self.right_rbl): - inst = self.replica_col_inst[bit] - for (pin_name,wl_name) in zip(self.cell.list_all_wl_names(),self.replica_wl_names_list[bit]): + for port in range(self.left_rbl+self.right_rbl): + inst = self.replica_col_inst[port] + for (pin_name,wl_name) in zip(self.cell.list_all_wl_names(),self.replica_wl_names[port]): # +1 for dummy row - pin_bit = bit+1 + pin_bit = port+1 # +row_size if above the array - if bit>=self.left_rbl: + if port>=self.left_rbl: pin_bit += self.row_size pin_name += "_{}".format(pin_bit) pin = inst.get_pin(pin_name) - self.add_layout_pin(text=wl_name, - layer=pin.layer, - offset=pin.ll().scale(0,1), - width=self.width, - height=pin.height()) + if wl_name in self.rbl_wl_names: + 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 bit in range(self.left_rbl+self.right_rbl): - inst = self.replica_col_inst[bit] - for (pin_name, bl_name) in zip(self.cell.list_all_bitline_names(),self.replica_bl_names_list[bit]): + for port in range(self.left_rbl+self.right_rbl): + inst = self.replica_col_inst[port] + for (pin_name, bl_name) in zip(self.cell.list_all_bitline_names(),self.replica_bl_names[port]): pin = inst.get_pin(pin_name) - name = "rbl_{0}_{1}".format(pin_name,bit) - self.add_layout_pin(text=name, - layer=pin.layer, - offset=pin.ll().scale(1,0), - width=pin.width(), - height=self.height) + name = "rbl_{0}_{1}".format(pin_name,port) + if bl_name in self.rbl_bl_names: + self.add_layout_pin(text=name, + layer=pin.layer, + offset=pin.ll().scale(1,0), + width=pin.width(), + height=self.height) for pin_name in ["vdd","gnd"]: @@ -335,32 +348,7 @@ class replica_bitcell_array(design.design): self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) - # Non-pins - for side in ["bot", "top"]: - inst = getattr(self, "dummy_row_{}_inst".format(side)) - pin_names = inst.mod.get_pin_names() - for pin_name in pin_names: - if pin_name.startswith("wl"): - pin_list = inst.get_pins(pin_name) - for pin in pin_list: - self.add_rect(layer=pin.layer, - offset=pin.ll().scale(0,1), - width=self.width, - height=pin.height()) - - - for side in ["left", "right"]: - inst = getattr(self, "dummy_col_{}_inst".format(side)) - pin_names = inst.mod.get_pin_names() - for pin_name in pin_names: - if pin_name.startswith("b"): - pin_list = inst.get_pins(pin_name) - for pin in pin_list: - self.add_rect(layer=pin.layer, - offset=pin.ll().scale(1,0), - width=pin.width(), - height=self.height) From e550d6ff1086c00eb777aac2f4c190ecdc74d2c2 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 15 Jul 2019 11:29:29 -0700 Subject: [PATCH 096/234] Port name maps between bank and replica array working. --- compiler/bitcells/bitcell.py | 8 +- compiler/bitcells/bitcell_1rw_1r.py | 18 ++-- compiler/bitcells/bitcell_1w_1r.py | 18 ++-- compiler/bitcells/pbitcell.py | 10 +- compiler/modules/bank.py | 72 ++++++++------ compiler/modules/bitcell_array.py | 18 ++-- compiler/modules/dummy_array.py | 16 +-- compiler/modules/port_data.py | 6 +- compiler/modules/replica_bitcell_array.py | 98 ++++++++++++------- compiler/modules/replica_column.py | 16 +-- .../05_replica_bitcell_1rw_1r_array_test.py | 6 +- .../tests/05_replica_bitcell_array_test.py | 6 +- .../tests/05_replica_pbitcell_array_test.py | 2 +- 13 files changed, 166 insertions(+), 128 deletions(-) diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index f18bf700..96432cea 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -42,22 +42,22 @@ class bitcell(design.design): cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file. return logical_effort.logical_effort('bitline', size, cin, load, parasitic_delay, False) - def list_all_wl_names(self): + def get_all_wl_names(self): """ Creates a list of all wordline pin names """ row_pins = ["wl"] return row_pins - def list_all_bitline_names(self): + def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ column_pins = ["bl", "br"] return column_pins - def list_all_bl_names(self): + def get_all_bl_names(self): """ Creates a list of all bl pins names """ column_pins = ["bl"] return column_pins - def list_all_br_names(self): + def get_all_br_names(self): """ Creates a list of all br pins names """ column_pins = ["br"] return column_pins diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index 68619184..f627a4ac 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -43,7 +43,7 @@ class bitcell_1rw_1r(design.design): read_port_load = 0.5 #min size NMOS gate load return logical_effort.logical_effort('bitline', size, cin, load+read_port_load, parasitic_delay, False) - def list_bitcell_pins(self, col, row): + def get_bitcell_pins(self, col, row): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ bitcell_pins = ["bl0_{0}".format(col), "br0_{0}".format(col), @@ -55,42 +55,42 @@ class bitcell_1rw_1r(design.design): "gnd"] return bitcell_pins - def list_all_wl_names(self): + def get_all_wl_names(self): """ Creates a list of all wordline pin names """ row_pins = ["wl0", "wl1"] return row_pins - def list_all_bitline_names(self): + def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ column_pins = ["bl0", "br0", "bl1", "br1"] return column_pins - def list_all_bl_names(self): + def get_all_bl_names(self): """ Creates a list of all bl pins names """ column_pins = ["bl0", "bl1"] return column_pins - def list_all_br_names(self): + def get_all_br_names(self): """ Creates a list of all br pins names """ column_pins = ["br0", "br1"] return column_pins - def list_read_bl_names(self): + def get_read_bl_names(self): """ Creates a list of bl pin names associated with read ports """ column_pins = ["bl0", "bl1"] return column_pins - def list_read_br_names(self): + def get_read_br_names(self): """ Creates a list of br pin names associated with read ports """ column_pins = ["br0", "br1"] return column_pins - def list_write_bl_names(self): + def get_write_bl_names(self): """ Creates a list of bl pin names associated with write ports """ column_pins = ["bl0"] return column_pins - def list_write_br_names(self): + def get_write_br_names(self): """ Creates a list of br pin names asscociated with write ports""" column_pins = ["br0"] return column_pins diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index c58ceb9d..b36c38bf 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -43,7 +43,7 @@ class bitcell_1w_1r(design.design): read_port_load = 0.5 #min size NMOS gate load return logical_effort.logical_effort('bitline', size, cin, load+read_port_load, parasitic_delay, False) - def list_bitcell_pins(self, col, row): + def get_bitcell_pins(self, col, row): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ bitcell_pins = ["bl0_{0}".format(col), "br0_{0}".format(col), @@ -55,42 +55,42 @@ class bitcell_1w_1r(design.design): "gnd"] return bitcell_pins - def list_all_wl_names(self): + def get_all_wl_names(self): """ Creates a list of all wordline pin names """ row_pins = ["wl0", "wl1"] return row_pins - def list_all_bitline_names(self): + def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ column_pins = ["bl0", "br0", "bl1", "br1"] return column_pins - def list_all_bl_names(self): + def get_all_bl_names(self): """ Creates a list of all bl pins names """ column_pins = ["bl0", "bl1"] return column_pins - def list_all_br_names(self): + def get_all_br_names(self): """ Creates a list of all br pins names """ column_pins = ["br0", "br1"] return column_pins - def list_read_bl_names(self): + def get_read_bl_names(self): """ Creates a list of bl pin names associated with read ports """ column_pins = ["bl0", "bl1"] return column_pins - def list_read_br_names(self): + def get_read_br_names(self): """ Creates a list of br pin names associated with read ports """ column_pins = ["br0", "br1"] return column_pins - def list_write_bl_names(self): + def get_write_bl_names(self): """ Creates a list of bl pin names associated with write ports """ column_pins = ["bl0"] return column_pins - def list_write_br_names(self): + def get_write_br_names(self): """ Creates a list of br pin names asscociated with write ports""" column_pins = ["br0"] return column_pins diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 01306f7f..7ed748ec 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -851,7 +851,7 @@ class pbitcell(design.design): implant_type="n", well_type="n") - def list_bitcell_pins(self, col, row): + def get_bitcell_pins(self, col, row): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ bitcell_pins = [] for port in range(self.total_ports): @@ -863,12 +863,12 @@ class pbitcell(design.design): bitcell_pins.append("gnd") return bitcell_pins - def list_all_wl_names(self): + def get_all_wl_names(self): """ Creates a list of all wordline pin names """ wordline_names = self.rw_wl_names + self.w_wl_names + self.r_wl_names return wordline_names - def list_all_bitline_names(self): + def get_all_bitline_names(self): """ Creates a list of all bitline pin names (both bl and br) """ bitline_pins = [] for port in range(self.total_ports): @@ -876,12 +876,12 @@ class pbitcell(design.design): bitline_pins.append("br{0}".format(port)) return bitline_pins - def list_all_bl_names(self): + def get_all_bl_names(self): """ Creates a list of all bl pins names """ bl_pins = self.rw_bl_names + self.w_bl_names + self.r_bl_names return bl_pins - def list_all_br_names(self): + def get_all_br_names(self): """ Creates a list of all br pins names """ br_pins = self.rw_br_names + self.w_br_names + self.r_br_names return br_pins diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index a9a47ec6..5c08df30 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -127,8 +127,8 @@ class bank(design.design): """ Route the rbl_bl and rbl_wl """ if self.port_data[port].has_rbl(): - bl_name = self.bitcell.get_bl_name(port) - bl_pin = self.bitcell_array_inst.get_pin("rbl_{0}_{1}".format(bl_name,port)) + bl_pin_name = self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]) + bl_pin = self.bitcell_array_inst.get_pin(bl_pin_name) self.add_layout_pin(text="rbl_bl{0}".format(port), layer=bl_pin.layer, offset=bl_pin.ll(), @@ -342,10 +342,10 @@ class bank(design.design): # create arrays of bitline and bitline_bar names for read, write, or all ports self.bitcell = factory.create(module_type="bitcell") - self.bl_names = self.bitcell.list_all_bl_names() - self.br_names = self.bitcell.list_all_br_names() - self.wl_names = self.bitcell.list_all_wl_names() - self.bitline_names = self.bitcell.list_all_bitline_names() + self.bl_names = self.bitcell.get_all_bl_names() + self.br_names = self.bitcell.get_all_br_names() + self.wl_names = self.bitcell.get_all_wl_names() + self.bitline_names = self.bitcell.get_all_bitline_names() self.port_data = [] for port in self.all_ports: @@ -363,26 +363,35 @@ class bank(design.design): # The number of replica lines depends on the port configuration - rbl_num = [self.read_ports.count(p) for p in self.all_ports] - if len(rbl_num)<2: - rbl_num.append(0) - self.num_rbl = sum(rbl_num) - # The indices always start at 0 - self.rbl_indices = [] + rbl_counts = [self.read_ports.count(p) for p in self.all_ports] + self.num_rbl = sum(rbl_counts) + + # The replica array indices always start at 0, so this will map them to + # the correct SRAM port + # (e.g. if port 0 is w, then port 1 will use RBL 0 in replica bitcell array + # because write ports don't use an RBL) + self.port_rbl_map = {} index = 0 - for num in rbl_num: + for (i,num) in enumerate(rbl_counts): if num>0: - self.rbl_indices.append(index) + self.port_rbl_map[i]=index index += 1 - else: - self.rbl_indices.append(-1) - + if len(rbl_counts)<2: + rbl_counts.append(0) + + + # Which bitcell port should be used in the RBL + # For now (since only 2 ports), if port 0 is not a read port, skip it in the RBLs + bitcell_ports=list(range(len(self.read_ports))) + if 0 not in self.read_ports: + bitcell_ports = [x+1 for x in bitcell_ports] self.bitcell_array = factory.create(module_type="replica_bitcell_array", cols=self.num_cols, rows=self.num_rows, - left_rbl=rbl_num[0], - right_rbl=rbl_num[1]) + left_rbl=rbl_counts[0], + right_rbl=rbl_counts[1], + bitcell_ports=bitcell_ports) self.add_mod(self.bitcell_array) @@ -402,14 +411,16 @@ class bank(design.design): for bitline in self.bitline_names: temp.append("{0}_{1}".format(bitline,col)) for rbl in range(self.num_rbl): - for bitline in self.bitline_names: - temp.append("rbl_{0}_{1}".format(bitline,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 rbl in range(self.num_rbl): - for wordline in self.wl_names: - temp.append("rbl_{0}_{1}".format(wordline,rbl)) + rbl_wl_name=self.bitcell_array.get_rbl_wl_name(rbl) + temp.append(rbl_wl_name) temp.append("vdd") temp.append("gnd") self.connect_inst(temp) @@ -430,8 +441,10 @@ class bank(design.design): temp = [] if self.port_data[port].has_rbl(): - temp.append("rbl_{0}_{1}".format(self.bl_names[port],self.rbl_indices[port])) - temp.append("rbl_{0}_{1}".format(self.br_names[port],self.rbl_indices[port])) + 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) for col in range(self.num_cols): temp.append("{0}_{1}".format(self.bl_names[port],col)) temp.append("{0}_{1}".format(self.br_names[port],col)) @@ -695,8 +708,10 @@ class bank(design.design): # Connect the replica bitlines if self.port_data[port].has_rbl(): - self.connect_bitline(inst1, inst2, "rbl_{0}_{1}".format(self.bitcell.get_bl_name(port),self.rbl_indices[port]), "rbl_bl") - self.connect_bitline(inst1, inst2, "rbl_{0}_{1}".format(self.bitcell.get_br_name(port),self.rbl_indices[port]), "rbl_br") + 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") @@ -927,7 +942,8 @@ class bank(design.design): connection.append((self.prefix+"p_en_bar{}".format(port), self.port_data_inst[port].get_pin("p_en_bar").lc())) if port in self.read_ports: - connection.append((self.prefix+"rbl_wl{}".format(port), self.bitcell_array_inst.get_pin("rbl_{0}_{1}".format(self.bitcell.get_wl_name(port),port)).lc())) + rbl_wl_name = self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]) + connection.append((self.prefix+"rbl_wl{}".format(port), self.bitcell_array_inst.get_pin(rbl_wl_name).lc())) if port in self.write_ports: connection.append((self.prefix+"w_en{}".format(port), self.port_data_inst[port].get_pin("w_en").lc())) diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 293d3e08..4b8ac212 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -73,8 +73,8 @@ class bitcell_array(design.design): self.DRC_LVS() def add_pins(self): - row_list = self.cell.list_all_wl_names() - column_list = self.cell.list_all_bitline_names() + 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)) @@ -89,16 +89,16 @@ class bitcell_array(design.design): self.cell = factory.create(module_type="bitcell") self.add_mod(self.cell) - def list_bitcell_pins(self, col, row): + def get_bitcell_pins(self, col, row): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ bitcell_pins = [] - pin_names = self.cell.list_all_bitline_names() + pin_names = self.cell.get_all_bitline_names() for pin in pin_names: bitcell_pins.append(pin+"_{0}".format(col)) - pin_names = self.cell.list_all_wl_names() + pin_names = self.cell.get_all_wl_names() for pin in pin_names: bitcell_pins.append(pin+"_{0}".format(row)) bitcell_pins.append("vdd") @@ -115,13 +115,13 @@ class bitcell_array(design.design): 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.list_bitcell_pins(col, row)) + self.connect_inst(self.get_bitcell_pins(col, row)) def add_layout_pins(self): """ Add the layout pins """ - row_list = self.cell.list_all_wl_names() - column_list = self.cell.list_all_bitline_names() + 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: @@ -224,4 +224,4 @@ class bitcell_array(design.design): 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] \ No newline at end of file + return inst_name+'.x'+self.cell_inst[row,col].name, self.cell_inst[row,col] diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py index e175e732..10007106 100644 --- a/compiler/modules/dummy_array.py +++ b/compiler/modules/dummy_array.py @@ -66,8 +66,8 @@ class dummy_array(design.design): self.DRC_LVS() def add_pins(self): - row_list = self.cell.list_all_wl_names() - column_list = self.cell.list_all_bitline_names() + 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)) @@ -84,16 +84,16 @@ class dummy_array(design.design): self.cell = factory.create(module_type="bitcell") - def list_bitcell_pins(self, col, row): + def get_bitcell_pins(self, col, row): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ bitcell_pins = [] - pin_names = self.cell.list_all_bitline_names() + pin_names = self.cell.get_all_bitline_names() for pin in pin_names: bitcell_pins.append(pin+"_{0}".format(col)) - pin_names = self.cell.list_all_wl_names() + pin_names = self.cell.get_all_wl_names() for pin in pin_names: bitcell_pins.append(pin+"_{0}".format(row)) bitcell_pins.append("vdd") @@ -110,13 +110,13 @@ class dummy_array(design.design): 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.list_bitcell_pins(col, row)) + self.connect_inst(self.get_bitcell_pins(col, row)) def add_layout_pins(self): """ Add the layout pins """ - row_list = self.cell.list_all_wl_names() - column_list = self.cell.list_all_bitline_names() + 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: diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 89020a2b..0b93b66d 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -201,9 +201,9 @@ class port_data(design.design): # create arrays of bitline and bitline_bar names for read, write, or all ports self.bitcell = factory.create(module_type="bitcell") - self.bl_names = self.bitcell.list_all_bl_names() - self.br_names = self.bitcell.list_all_br_names() - self.wl_names = self.bitcell.list_all_wl_names() + self.bl_names = self.bitcell.get_all_bl_names() + self.br_names = self.bitcell.get_all_br_names() + self.wl_names = self.bitcell.get_all_wl_names() def create_precharge_array(self): """ Creating Precharge """ diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 12401301..ba92240e 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -17,12 +17,14 @@ import dummy_array class replica_bitcell_array(design.design): """ - Creates a bitcell arrow of cols x rows and then adds the replica and dummy columns - and rows for one or two read ports. Replica columns are on the left and right, respectively. + 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 + right, respectively and connected to the given bitcell ports. Dummy are the outside columns/rows with WL and BL tied to gnd. - Requires a regular bitcell array, replica bitcell, and dummy bitcell (Bl/BR disconnected). + Requires a regular bitcell array, replica bitcell, and dummy + bitcell (Bl/BR disconnected). """ - def __init__(self, cols, rows, left_rbl, right_rbl, name): + def __init__(self, cols, rows, 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)) @@ -31,8 +33,10 @@ class replica_bitcell_array(design.design): self.row_size = rows self.left_rbl = left_rbl self.right_rbl = right_rbl + self.bitcell_ports = bitcell_ports debug.check(left_rbl+right_rbl==len(self.read_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 @@ -122,15 +126,14 @@ class replica_bitcell_array(design.design): self.bitcell_array_bl_names = [x for x in self.bitcell_array.pins if x.startswith("b")] # These are the non-indexed names - self.dummy_cell_wl_names = ["dummy_"+x for x in self.cell.list_all_wl_names()] - self.dummy_cell_bl_names = ["dummy_"+x for x in self.cell.list_all_bitline_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 - self.rbl_bl_names = [] - self.rbl_wl_names = [] - for port in range(self.left_rbl+self.right_rbl): - self.rbl_bl_names.append("rbl_bl{}".format(port)) - self.rbl_wl_names.append("rbl_wl{}".format(port)) + # 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 = [] @@ -138,18 +141,18 @@ class replica_bitcell_array(design.design): # 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(x,port) for x in self.cell.list_all_wl_names()] - # Rename the one we will use - wl_names[port] = self.rbl_wl_names[port] + wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x),port) for x in range(len(self.all_ports))] + # 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.left_rbl,self.left_rbl+self.right_rbl): # Make names for all RBLs - wl_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.list_all_wl_names()] - # Rename the one we will use - wl_names[port] = self.rbl_wl_names[port] + wl_names=["rbl_{0}_{1}".format(self.cell.get_wl_name(x),port) for x in range(len(self.all_ports))] + # 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]) @@ -162,26 +165,33 @@ class replica_bitcell_array(design.design): self.replica_wl_names = {} # Array of all port bitline names for port in range(self.left_rbl+self.right_rbl): - left_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.list_all_bl_names()] - right_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.list_all_br_names()] - left_names[port] = self.rbl_bl_names[port] + 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]] # 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 - wl_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.list_all_wl_names()] - wl_names[port] = "rbl_wl{}".format(port) + wl_names = ["rbl_{0}_{1}".format(x,port) for x in self.cell.get_all_wl_names()] + #wl_names[port] = "rbl_wl{}".format(port) self.replica_wl_names[port] = wl_names # External pins self.add_pin_list(self.bitcell_array_bl_names, "INOUT") - for port in range(self.left_rbl+self.right_rbl): - self.add_pin("rbl_bl{}".format(port),"INPUT") + # 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,"INPUT") + self.add_pin(br_name,"INPUT") self.add_pin_list(self.bitcell_array_wl_names, "INPUT") - for port in range(self.left_rbl+self.right_rbl): - self.add_pin("rbl_wl{}".format(port),"OUTPUT") - + # 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") @@ -310,7 +320,7 @@ class replica_bitcell_array(design.design): # Replica wordlines for port in range(self.left_rbl+self.right_rbl): inst = self.replica_col_inst[port] - for (pin_name,wl_name) in zip(self.cell.list_all_wl_names(),self.replica_wl_names[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 @@ -319,7 +329,7 @@ class replica_bitcell_array(design.design): pin_name += "_{}".format(pin_bit) pin = inst.get_pin(pin_name) - if wl_name in self.rbl_wl_names: + 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), @@ -330,15 +340,17 @@ class replica_bitcell_array(design.design): # Replica bitlines for port in range(self.left_rbl+self.right_rbl): inst = self.replica_col_inst[port] - for (pin_name, bl_name) in zip(self.cell.list_all_bitline_names(),self.replica_bl_names[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) - name = "rbl_{0}_{1}".format(pin_name,port) - if bl_name in self.rbl_bl_names: - self.add_layout_pin(text=name, - layer=pin.layer, - offset=pin.ll().scale(1,0), - width=pin.width(), - height=self.height) + if bl_name in self.rbl_bl_names or bl_name in self.rbl_br_names: + name = bl_name + else: + name = "rbl_{0}_{1}".format(pin_name,port) + self.add_layout_pin(text=name, + layer=pin.layer, + offset=pin.ll().scale(1,0), + width=pin.width(), + height=self.height) for pin_name in ["vdd","gnd"]: @@ -350,7 +362,17 @@ class replica_bitcell_array(design.design): + def get_rbl_wl_name(self, port): + """ Return the WL for the given RBL port """ + return self.rbl_wl_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] def analytical_delay(self, corner, slew, load): """Returns relative delay of the bitline in the bitcell array""" @@ -358,7 +380,7 @@ class replica_bitcell_array(design.design): #The load being driven/drained is mostly the bitline but could include the sense amp or the column mux. #The load from the bitlines is due to the drain capacitances from all the other bitlines and wire parasitics. drain_load = logical_effort.convert_farad_to_relative_c(parameter['bitcell_drain_cap']) - wire_unit_load = .05 * drain_load #Wires add 5% to this. + wire_unit_load = 0.05 * drain_load #Wires add 5% to this. bitline_load = (drain_load+wire_unit_load)*self.row_size return [self.cell.analytical_delay(corner, slew, load+bitline_load)] diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index 42903e7c..cf2a910a 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -53,10 +53,10 @@ class replica_column(design.design): self.DRC_LVS() def add_pins(self): - column_list = self.cell.list_all_bitline_names() + column_list = self.cell.get_all_bitline_names() for cell_column in column_list: self.add_pin("{0}_{1}".format(cell_column,0)) - row_list = self.cell.list_all_wl_names() + row_list = self.cell.get_all_wl_names() for row in range(self.total_size): for cell_row in row_list: self.add_pin("{0}_{1}".format(cell_row,row)) @@ -88,7 +88,7 @@ class replica_column(design.design): else: self.cell_inst[row]=self.add_inst(name=name, mod=self.dummy_cell) - self.connect_inst(self.list_bitcell_pins(0, row)) + self.connect_inst(self.get_bitcell_pins(0, row)) def place_instances(self): @@ -112,8 +112,8 @@ class replica_column(design.design): def add_layout_pins(self): """ Add the layout pins """ - row_list = self.cell.list_all_wl_names() - column_list = self.cell.list_all_bitline_names() + row_list = self.cell.get_all_wl_names() + column_list = self.cell.get_all_bitline_names() for cell_column in column_list: bl_pin = self.cell_inst[0].get_pin(cell_column) @@ -138,16 +138,16 @@ class replica_column(design.design): for pin_name in ["vdd", "gnd"]: self.copy_layout_pin(inst, pin_name) - def list_bitcell_pins(self, col, row): + def get_bitcell_pins(self, col, row): """ Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """ bitcell_pins = [] - pin_names = self.cell.list_all_bitline_names() + pin_names = self.cell.get_all_bitline_names() for pin in pin_names: bitcell_pins.append(pin+"_{0}".format(col)) - pin_names = self.cell.list_all_wl_names() + pin_names = self.cell.get_all_wl_names() for pin in pin_names: bitcell_pins.append(pin+"_{0}".format(row)) bitcell_pins.append("vdd") diff --git a/compiler/tests/05_replica_bitcell_1rw_1r_array_test.py b/compiler/tests/05_replica_bitcell_1rw_1r_array_test.py index ddf6be60..bae7edde 100755 --- a/compiler/tests/05_replica_bitcell_1rw_1r_array_test.py +++ b/compiler/tests/05_replica_bitcell_1rw_1r_array_test.py @@ -26,7 +26,11 @@ class replica_bitcell_array_test(openram_test): OPTS.num_w_ports = 0 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) + 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) + + 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) globals.end_openram() diff --git a/compiler/tests/05_replica_bitcell_array_test.py b/compiler/tests/05_replica_bitcell_array_test.py index 00c14953..2b446758 100755 --- a/compiler/tests/05_replica_bitcell_array_test.py +++ b/compiler/tests/05_replica_bitcell_array_test.py @@ -19,13 +19,9 @@ class replica_bitcell_array_test(openram_test): globals.init_openram("config_{0}".format(OPTS.tech_name)) debug.info(2, "Testing 4x4 array for 6t_cell") - a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=1, right_rbl=0) + a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=1, right_rbl=0, bitcell_ports=[0]) self.local_check(a) - debug.info(2, "Testing 4x4 array for 6t_cell") - a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=0, right_rbl=1) - self.local_check(a) - globals.end_openram() # run the test from the command line diff --git a/compiler/tests/05_replica_pbitcell_array_test.py b/compiler/tests/05_replica_pbitcell_array_test.py index a31e392c..b7bce868 100755 --- a/compiler/tests/05_replica_pbitcell_array_test.py +++ b/compiler/tests/05_replica_pbitcell_array_test.py @@ -27,7 +27,7 @@ class replica_bitcell_array_test(openram_test): OPTS.num_w_ports = 0 debug.info(2, "Testing 4x4 array for pbitcell") - a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=1, right_rbl=1) + 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) globals.end_openram() From ea2f786dcfe744b3d7fcee95fb2a0d6c6fa331e5 Mon Sep 17 00:00:00 2001 From: jsowash Date: Mon, 15 Jul 2019 14:41:26 -0700 Subject: [PATCH 097/234] Redefined write_size inrecompute_sizes() to take the new word_size() --- compiler/characterizer/functional.py | 5 ++--- compiler/modules/port_data.py | 10 ++++++++-- compiler/options.py | 1 + compiler/sram/sram_config.py | 4 ++++ 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index cf0a30c4..743520e8 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -57,8 +57,7 @@ class functional(simulation): self.wmask[self.num_wmask-1 - bit] = 1 else: self.wmask[self.num_wmask-1 - bit] = 0 - print(self.wmask) - + def run(self, feasible_period=None): if feasible_period: #period defaults to tech.py feasible period otherwise. self.period = feasible_period @@ -110,7 +109,7 @@ class functional(simulation): elif bit == 0: word = old_word[lower:upper+1] + word [upper+1:self.word_size] else: - word = word[0:lower] + old_word[lower:upper+1] + word [upper+1:self.word_size]cfusms + word = word[0:lower] + old_word[lower:upper+1] + word [upper+1:self.word_size] #word = word.replace(word[lower:upper+1],old_word[lower:upper+1],1) self.stored_words[addr] = word else: diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index b0c74a8d..2f5b634f 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -56,9 +56,12 @@ class port_data(design.design): self.create_write_driver_array() if (self.word_size != self.write_size): self.create_write_mask_array() + else: + self.write_mask_array_inst = None else: self.write_driver_array_inst = None - + self.write_mask_array_inst = None + if self.column_mux_array: self.create_column_mux_array() else: @@ -173,9 +176,12 @@ class port_data(design.design): word_size=self.word_size, write_size=self.write_size) self.add_mod(self.write_driver_array) + else: + self.write_mask_array_inst = None + else: self.write_driver_array = None - + self.write_mask_array = None def precompute_constants(self): """ Get some preliminary data ready """ diff --git a/compiler/options.py b/compiler/options.py index 833d5289..a80790eb 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -142,4 +142,5 @@ class options(optparse.Values): wordline_driver = "wordline_driver" write_driver_array = "write_driver_array" write_driver = "write_driver" + write_mask_array = "write_mask_array" diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index ded595e0..67bfc452 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -73,6 +73,10 @@ class sram_config: SRAM for testing. """ + # This function is ran without the write mask option, but word_size can be redefined + # which makes the tests think there is a write mask. + self.write_size = self.word_size + # If the banks changed self.num_words_per_bank = self.num_words/self.num_banks self.num_bits_per_bank = self.word_size*self.num_words_per_bank From 021d6048329a6878954cce3e55c6e86729b04ac7 Mon Sep 17 00:00:00 2001 From: jsowash Date: Mon, 15 Jul 2019 16:48:36 -0700 Subject: [PATCH 098/234] Removed wmask from addwrite() --- compiler/characterizer/functional.py | 2 +- compiler/characterizer/simulation.py | 2 +- compiler/sram/sram_config.py | 21 ++++++++++++++++++++- compiler/tests/22_sram_wmask_func_test.py | 2 -- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 743520e8..1aed19b9 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -91,7 +91,7 @@ class functional(simulation): addr = self.gen_addr() word = self.gen_data() comment = self.gen_cycle_comment("write", word, addr, 0, self.wmask, self.t_current) - self.add_write(comment, addr, word, self.wmask, 0) + self.add_write(comment, addr, word, 0) if self.wmask_enabled: old_word = "" if self.stored_words.get(addr) == None: diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 53e73616..d9154f0e 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -131,7 +131,7 @@ class simulation(): debug.error("Non-binary address string",1) bit -= 1 - def add_write(self, comment, address, data, wmask, port): + def add_write(self, comment, address, data, port): """ Add the control values for a write cycle. """ debug.check(port in self.write_ports, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_ports)) debug.info(2, comment) diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index 67bfc452..80be7939 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -64,7 +64,26 @@ class sram_config: self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row) debug.info(1,"Words per row: {}".format(self.words_per_row)) - self.recompute_sizes() + self.recompute_sizes_once() + + def recompute_sizes_once(self): + """ + Calculate the auxiliary values assuming fixed number of words per row. + """ + + # If the banks changed + self.num_words_per_bank = self.num_words / self.num_banks + self.num_bits_per_bank = self.word_size * self.num_words_per_bank + + # Fix the number of columns and rows + self.num_cols = int(self.words_per_row * self.word_size) + self.num_rows = int(self.num_words_per_bank / self.words_per_row) + + # Compute the address and bank sizes + self.row_addr_size = int(log(self.num_rows, 2)) + self.col_addr_size = int(log(self.words_per_row, 2)) + self.bank_addr_size = self.col_addr_size + self.row_addr_size + self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2)) def recompute_sizes(self): """ diff --git a/compiler/tests/22_sram_wmask_func_test.py b/compiler/tests/22_sram_wmask_func_test.py index ebf2137f..4fcc63c9 100755 --- a/compiler/tests/22_sram_wmask_func_test.py +++ b/compiler/tests/22_sram_wmask_func_test.py @@ -34,8 +34,6 @@ class sram_wmask_func_test(openram_test): num_words=16, write_size=4, num_banks=1) - c.words_per_row=4 - c.recompute_sizes() debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} bit writes, {} banks".format(c.word_size, c.num_words, c.words_per_row, From 37c15937e21d3290f00f7f9c02c69ab63b33aba2 Mon Sep 17 00:00:00 2001 From: mrg Date: Mon, 15 Jul 2019 17:07:50 -0700 Subject: [PATCH 099/234] Add multiple control logic port types. --- compiler/tests/16_control_logic_test.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index 13e6c46c..f8fa3061 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -22,10 +22,17 @@ class control_logic_test(openram_test): import control_logic import tech - # check control logic for single port - debug.info(1, "Testing sample for control_logic") + debug.info(1, "Testing sample for control_logic_rw") a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32, write_size=32) self.local_check(a) + + debug.info(1, "Testing sample for control_logic_r") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32, write_size=32, port_type="r") + self.local_check(a) + + debug.info(1, "Testing sample for control_logic_w") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32, write_size=32, port_type="w") + self.local_check(a) # run the test from the command line if __name__ == "__main__": From bea07c2319746aa79fd01fac5bb5bde2f868a3c7 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 16 Jul 2019 09:04:58 -0700 Subject: [PATCH 100/234] SRAM with RBL integration in array. --- compiler/modules/bank.py | 22 ++++++---- compiler/modules/control_logic.py | 63 +++++++++++++++++----------- compiler/sram/sram_1bank.py | 70 ++++++++++++++++--------------- compiler/sram/sram_base.py | 33 +++++++++------ 4 files changed, 109 insertions(+), 79 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 5c08df30..af093d03 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -54,8 +54,8 @@ class bank(design.design): def create_netlist(self): self.compute_sizes() - self.add_pins() self.add_modules() + self.add_pins() # Must create the replica bitcell array first self.create_instances() @@ -78,9 +78,10 @@ class bank(design.design): for port in self.read_ports: for bit in range(self.word_size): self.add_pin("dout{0}_{1}".format(port,bit),"OUT") - self.add_pin("rbl_bl{0}_{0}".format(port),"OUT") - for port in self.read_ports: - self.add_pin("rbl_wl{0}_{0}".format(port),"IN") + for port in self.read_ports: + self.add_pin(self.bitcell_array.get_rbl_bl_name(port),"OUT") + for port in self.read_ports: + self.add_pin(self.bitcell_array.get_rbl_wl_name(port),"IN") for port in self.write_ports: for bit in range(self.word_size): self.add_pin("din{0}_{1}".format(port,bit),"IN") @@ -247,7 +248,7 @@ class bank(design.design): # LOWER RIGHT QUADRANT # To the left of the bitcell array - x_offset = self.bitcell_array_right + self.port_address.width + self.m2_gap + x_offset = self.bitcell_array_right + self.port_address.width self.port_address_offsets[port] = vector(x_offset,self.main_bitcell_array_bottom) # UPPER RIGHT QUADRANT @@ -684,11 +685,12 @@ class bank(design.design): 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.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_xoffset[1] = self.create_bus(layer="metal2", pitch=self.m2_pitch, offset=control_bus_offset, - names=self.control_signals[1], + names=list(reversed(self.control_signals[1])), length=control_bus_length, vertical=True, make_pins=(self.num_banks==1)) @@ -950,13 +952,15 @@ class bank(design.design): if port in self.read_ports: connection.append((self.prefix+"s_en{}".format(port), self.port_data_inst[port].get_pin("s_en").lc())) - + for (control_signal, pin_pos) in connection: + control_mid_pos = self.bus_xoffset[port][control_signal] control_pos = vector(self.bus_xoffset[port][control_signal].x ,pin_pos.y) - self.add_path("metal1", [control_pos, pin_pos]) + self.add_wire(("metal1","via1","metal2"), [control_mid_pos, control_pos, pin_pos]) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=control_pos) + # clk to wordline_driver control_signal = self.prefix+"wl_en{}".format(port) if port%2: diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index e39dbb9f..52207a77 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -95,6 +95,18 @@ class control_logic(design.design): size=4, height=dff_height) self.add_mod(self.and2) + + if self.port_type=="rw": + self.rbl_driver = factory.create(module_type="pand2", + size=self.num_cols, + height=dff_height) + self.add_mod(self.rbl_driver) + elif self.port_type=="r": + self.rbl_driver = factory.create(module_type="pbuf", + size=self.num_cols, + height=dff_height) + self.add_mod(self.rbl_driver) + # clk_buf drives a flop for every address and control bit # plus about 5 fanouts for the control logic @@ -131,12 +143,14 @@ class control_logic(design.design): height=dff_height) self.add_mod(self.inv) - # p_en_bar drives every column in the bicell array + # p_en_bar drives every column in the bitcell array self.p_en_bar_driver = factory.create(module_type="pdriver", neg_polarity=True, fanout=self.num_cols, height=dff_height) self.add_mod(self.p_en_bar_driver) + + # if (self.port_type == "rw") or (self.port_type == "r"): # from importlib import reload @@ -366,11 +380,13 @@ class control_logic(design.design): self.create_wlen_row() if (self.port_type == "rw") or (self.port_type == "w"): self.create_wen_row() - if (self.port_type == "rw") or (self.port_type == "r"): + if (self.port_type == "rw") or (self.port_type == "r"): self.create_rbl_row() - self.create_pen_row() self.create_sen_row() self.create_delay() + if (self.port_type == "rw") or (self.port_type == "r") or self.words_per_row>1: + self.create_pen_row() + def place_instances(self): @@ -400,9 +416,10 @@ class control_logic(design.design): height = self.w_en_inst.uy() control_center_y = self.w_en_inst.uy() row += 1 - if (self.port_type == "rw") or (self.port_type == "r"): + if (self.port_type == "rw") or (self.port_type == "r"): self.place_rbl_row(row) row += 1 + if (self.port_type == "rw") or (self.port_type == "r") or self.words_per_row>1: self.place_pen_row(row) row += 1 self.place_sen_row(row) @@ -431,8 +448,9 @@ class control_logic(design.design): self.route_wen() if (self.port_type == "rw") or (self.port_type == "r"): self.route_rbl() - self.route_pen() self.route_sen() + if (self.port_type == "rw") or (self.port_type == "r") or self.words_per_row>1: + self.route_pen() self.route_clk_buf() self.route_gated_clk_bar() self.route_gated_clk_buf() @@ -451,8 +469,8 @@ class control_logic(design.design): # Add the RBL above the rows # Add to the right of the control rows and routing channel - offset = vector(0, y_off) - self.delay_inst.place(offset) + offset = vector(self.delay_chain.width, y_off) + self.delay_inst.place(offset, mirror="MY") def create_clk_buf_row(self): @@ -589,11 +607,15 @@ class control_logic(design.design): self.connect_output(self.wl_en_inst, "Z", "wl_en") def create_rbl_row(self): - - # input: gated_clk_bar, we_bar, output: rbl_in - self.rbl_inst=self.add_inst(name="and2_rbl", - mod=self.and2) - self.connect_inst(["gated_clk_bar", "we_bar", "rbl_wl", "vdd", "gnd"]) + + self.rbl_inst=self.add_inst(name="rbl_driver", + mod=self.rbl_driver) + if self.port_type == "rw": + # input: gated_clk_bar, we_bar, output: rbl_wl + self.connect_inst(["gated_clk_bar", "we_bar", "rbl_wl", "vdd", "gnd"]) + elif self.port_type == "r": + # input: gated_clk_bar, output: rbl_wl + self.connect_inst(["gated_clk_bar", "rbl_wl", "vdd", "gnd"]) def place_rbl_row(self,row): x_off = self.control_x_offset @@ -608,20 +630,14 @@ class control_logic(design.design): """ Connect the logic for the rbl_in generation """ if self.port_type == "rw": - input_name = "we_bar" # Connect the NAND gate inputs to the bus rbl_in_map = zip(["A", "B"], ["gated_clk_bar", "we_bar"]) - self.connect_vertical_bus(rbl_in_map, self.rbl_inst, self.rail_offsets) - - - # Connect the output of the precharge enable to the RBL input - #if self.port_type == "rw": - # out_pos = self.rbl_in_inst.get_pin("Z").center() - #else: - # out_pos = vector(self.rail_offsets["gated_clk_bar"].x, self.rbl_inst.by()-3*self.m2_pitch) - - self.copy_layout_pin(self.rbl_inst, "Z", "rbl_wl") + else: + rbl_in_map = zip(["A"], ["gated_clk_bar"]) + self.connect_vertical_bus(rbl_in_map, self.rbl_inst, self.rail_offsets) + self.connect_output(self.rbl_inst, "Z", "rbl_wl") + # Input from RBL goes to the delay line for futher delay self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") def create_pen_row(self): @@ -727,7 +743,6 @@ class control_logic(design.design): self.row_end_inst.append(self.w_en_inst) def route_wen(self): - if self.port_type == "rw": input_name = "we" else: diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 8d158bfe..ce0d742e 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -99,13 +99,13 @@ class sram_1bank(sram_base): # This includes 2 M2 pitches for the row addr clock line. control_pos[port] = vector(-self.control_logic_insts[port].width - 2*self.m2_pitch, - self.bank.bank_array_ll.y - self.control_logic_insts[port].mod.control_logic_center.y - self.bank.m2_gap) + self.bank.bank_array_ll.y - self.control_logic_insts[port].mod.control_logic_center.y - 2*self.bank.m2_gap ) self.control_logic_insts[port].place(control_pos[port]) # The row address bits are placed above the control logic aligned on the right. x_offset = self.control_logic_insts[port].rx() - self.row_addr_dff_insts[port].width - # It is aove the control logic but below the top of the bitcell array - y_offset = max(self.control_logic_insts[port].uy(), self.bank.bank_array_ur.y - self.row_addr_dff_insts[port].height) + # It is above the control logic but below the top of the bitcell array + y_offset = max(self.control_logic_insts[port].uy(), self.bank_inst.uy() - self.row_addr_dff_insts[port].height) row_addr_pos[port] = vector(x_offset, y_offset) self.row_addr_dff_insts[port].place(row_addr_pos[port]) @@ -137,6 +137,30 @@ class sram_1bank(sram_base): # Port 1 port = 1 + + # Add the col address flops above the bank to the right of the upper-right of bank array + if self.col_addr_dff: + col_addr_pos[port] = vector(self.bank.bank_array_ur.x + self.bank.m2_gap, + self.bank.height + max_gap_size + self.dff.height) + self.col_addr_dff_insts[port].place(col_addr_pos[port], mirror="MX") + else: + col_addr_pos[port] = self.bank_inst.ur() + + # This includes 2 M2 pitches for the row addr clock line + control_pos[port] = vector(self.bank_inst.rx() + self.control_logic_insts[port].width + 2*self.m2_pitch, + self.bank.bank_array_ur.y + self.control_logic_insts[port].height - + (self.control_logic_insts[port].height - self.control_logic_insts[port].mod.control_logic_center.y) + + 2*self.bank.m2_gap) + #import pdb; pdb.set_trace() + self.control_logic_insts[port].place(control_pos[port], mirror="XY") + + # The row address bits are placed above the control logic aligned on the left. + x_offset = control_pos[port].x - self.control_logic_insts[port].width + self.row_addr_dff_insts[port].width + # It is below the control logic but below the bottom of the bitcell array + y_offset = min(self.control_logic_insts[port].by(), self.bank_inst.by() + self.row_addr_dff_insts[port].height) + row_addr_pos[port] = vector(x_offset, y_offset) + self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="XY") + # Add the data flops above the bank to the left of the upper-right of bank array # This relies on the upper-right of the array of the bank # decoder in upper left, bank in upper right, sensing in lower right. @@ -153,29 +177,6 @@ class sram_1bank(sram_base): wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, self.bank.height + max_gap_size + self.data_dff_insts[port].height) self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") - else: - data_pos[port] = self.bank_inst.ur() - - # Add the col address flops above the bank to the right of the upper-right of bank array - if self.col_addr_dff: - col_addr_pos[port] = vector(self.bank.bank_array_ur.x + self.bank.m2_gap, - self.bank.height + max_gap_size + self.dff.height) - self.col_addr_dff_insts[port].place(col_addr_pos[port], mirror="MX") - else: - col_addr_pos[port] = self.bank_inst.ur() - - # This includes 2 M2 pitches for the row addr clock line - control_pos[port] = vector(self.bank_inst.rx() + self.control_logic_insts[port].width + 2*self.m2_pitch, - self.bank.bank_array_ur.y + self.control_logic_insts[port].mod.control_logic_center.y + self.bank.m2_gap) - self.control_logic_insts[port].place(control_pos[port], mirror="XY") - - # The row address bits are placed above the control logic aligned on the left. - x_offset = control_pos[port].x - self.control_logic_insts[port].width + self.row_addr_dff_insts[port].width - # It is above the control logic but below the top of the bitcell array - y_offset = min(self.control_logic_insts[port].by(), self.bank.bank_array_ll.y - self.row_addr_dff_insts[port].height) - row_addr_pos[port] = vector(x_offset, y_offset) - self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="XY") - def add_layout_pins(self): @@ -271,20 +272,23 @@ class sram_1bank(sram_base): def route_control_logic(self): - """ Route the outputs from the control logic module """ + """ Route the control logic pins that are not inputs """ + for port in self.all_ports: for signal in self.control_logic_outputs[port]: # The clock gets routed separately and is not a part of the bank if "clk" in signal: continue - if signal.startswith("rbl"): - continue src_pin = self.control_logic_insts[port].get_pin(signal) dest_pin = self.bank_inst.get_pin(signal+"{}".format(port)) - self.connect_rail_from_left_m2m3(src_pin, dest_pin) - self.add_via_center(layers=("metal1","via1","metal2"), - offset=src_pin.rc()) - + self.connect_vbus_m2m3(src_pin, dest_pin) + + for port in self.read_ports: + # Only input (besides pins) is the replica bitline + src_pin = self.control_logic_insts[port].get_pin("rbl_bl") + dest_pin = self.bank_inst.get_pin("rbl_bl{}".format(port)) + self.connect_vbus_m2m3(src_pin, dest_pin) + def route_row_addr_dff(self): """ Connect the output of the row flops to the bank pins """ diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 096f4987..ec2bc608 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -114,7 +114,7 @@ class sram_base(design, verilog, lef): self.add_lvs_correspondence_points() - self.offset_all_coordinates() + #self.offset_all_coordinates() highest_coord = self.find_highest_coords() self.width = highest_coord[0] @@ -514,21 +514,28 @@ class sram_base(design, verilog, lef): return insts - def connect_rail_from_left_m2m3(self, src_pin, dest_pin): - """ Helper routine to connect an unrotated/mirrored oriented instance to the rails """ - in_pos = src_pin.rc() + def connect_vbus_m2m3(self, src_pin, dest_pin): + """ Helper routine to connect an instance to a vertical bus. + Routes horizontal then vertical L shape. + Dest pin is assumed to be on M2. + Src pin can be on M1/M2/M3.""" + + if src_pin.cx() Date: Tue, 16 Jul 2019 11:53:20 -0700 Subject: [PATCH 101/234] Flatten bitcell array for LVS symmetries. --- technology/scn4m_subm/mag_lib/setup.tcl | 1 + 1 file changed, 1 insertion(+) diff --git a/technology/scn4m_subm/mag_lib/setup.tcl b/technology/scn4m_subm/mag_lib/setup.tcl index f2567d7d..95e7dbea 100644 --- a/technology/scn4m_subm/mag_lib/setup.tcl +++ b/technology/scn4m_subm/mag_lib/setup.tcl @@ -6,6 +6,7 @@ equate class {-circuit1 pfet} {-circuit2 p} flatten class {-circuit1 dummy_cell_6t} flatten class {-circuit1 dummy_cell_1rw_1r} flatten class {-circuit1 dummy_cell_1w_1r} +flatten class {-circuit1 bitcell_array_0} flatten class {-circuit1 pbitcell_0} flatten class {-circuit1 pbitcell_1} property {-circuit1 nfet} remove as ad ps pd From 42ad0cd282bb774bd118f3514062f0301d8e7c4f Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 16 Jul 2019 11:54:39 -0700 Subject: [PATCH 102/234] Add pbitcell RW test --- compiler/tests/05_replica_pbitcell_array_test.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/tests/05_replica_pbitcell_array_test.py b/compiler/tests/05_replica_pbitcell_array_test.py index b7bce868..2bc4a0d2 100755 --- a/compiler/tests/05_replica_pbitcell_array_test.py +++ b/compiler/tests/05_replica_pbitcell_array_test.py @@ -18,7 +18,6 @@ class replica_bitcell_array_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) - debug.info(2, "Testing 4x4 array for multiport bitcell, with read ports at the edge of the bit cell") OPTS.bitcell = "pbitcell" OPTS.replica_bitcell = "replica_pbitcell" OPTS.dummy_bitcell = "dummy_pbitcell" @@ -30,6 +29,18 @@ class replica_bitcell_array_test(openram_test): 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) + OPTS.bitcell = "pbitcell" + OPTS.replica_bitcell = "replica_pbitcell" + OPTS.dummy_bitcell = "dummy_pbitcell" + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 0 + OPTS.num_w_ports = 0 + + factory.reset() + debug.info(2, "Testing 4x4 array for pbitcell") + a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4, left_rbl=1, right_rbl=0, bitcell_ports=[0]) + self.local_check(a) + globals.end_openram() # run the test from the command line From 70ee026fcff9f76a22ed0cb382fca75513c74a51 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 16 Jul 2019 11:54:57 -0700 Subject: [PATCH 103/234] Add cell names to psingle_bank test --- compiler/tests/19_psingle_bank_test.py | 85 +------------------------- 1 file changed, 2 insertions(+), 83 deletions(-) diff --git a/compiler/tests/19_psingle_bank_test.py b/compiler/tests/19_psingle_bank_test.py index 7fe806b8..e747b13b 100755 --- a/compiler/tests/19_psingle_bank_test.py +++ b/compiler/tests/19_psingle_bank_test.py @@ -23,6 +23,8 @@ class psingle_bank_test(openram_test): from bank import bank from sram_config import sram_config OPTS.bitcell = "pbitcell" + OPTS.replica_bitcell="replica_pbitcell" + OPTS.dummy_bitcell="dummy_pbitcell" # testing layout of bank using pbitcell with 1 RW port (a 6T-cell equivalent) OPTS.num_rw_ports = 1 @@ -67,89 +69,6 @@ class psingle_bank_test(openram_test): a = bank(c, name=name) self.local_check(a) - - # testing bank using pbitcell in various port combinations - # layout for multiple ports does not work yet - """ - OPTS.netlist_only = True - - c.num_words=16 - c.words_per_row=1 - - OPTS.num_rw_ports = c.num_rw_ports = 2 - OPTS.num_w_ports = c.num_w_ports = 2 - OPTS.num_r_ports = c.num_r_ports = 2 - - debug.info(1, "No column mux") - name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports) - a = bank(c, name=name) - self.local_check(a) - - OPTS.num_rw_ports = c.num_rw_ports = 0 - OPTS.num_w_ports = c.num_w_ports = 2 - OPTS.num_r_ports = c.num_r_ports = 2 - - debug.info(1, "No column mux") - name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports) - a = bank(c, name=name) - self.local_check(a) - - OPTS.num_rw_ports = c.num_rw_ports = 2 - OPTS.num_w_ports = c.num_w_ports = 0 - OPTS.num_r_ports = c.num_r_ports = 2 - - debug.info(1, "No column mux") - name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports) - a = bank(c, name=name) - self.local_check(a) - - OPTS.num_rw_ports = c.num_rw_ports = 2 - OPTS.num_w_ports = c.num_w_ports = 2 - OPTS.num_r_ports = c.num_r_ports = 0 - - debug.info(1, "No column mux") - name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports) - a = bank(c, name=name) - self.local_check(a) - - OPTS.num_rw_ports = c.num_rw_ports = 2 - OPTS.num_w_ports = c.num_w_ports = 0 - OPTS.num_r_ports = c.num_r_ports = 0 - - debug.info(1, "No column mux") - name = "bank1_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports) - a = bank(c, name=name) - self.local_check(a) - - # testing with various column muxes - OPTS.num_rw_ports = c.num_rw_ports = 2 - OPTS.num_w_ports = c.num_w_ports = 2 - OPTS.num_r_ports = c.num_r_ports = 2 - - c.num_words=32 - c.words_per_row=2 - debug.info(1, "Two way column mux") - name = "bank2_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports) - a = bank(c, name=name) - self.local_check(a) - - c.num_words=64 - c.words_per_row=4 - debug.info(1, "Four way column mux") - name = "bank3_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports) - a = bank(c, name=name) - self.local_check(a) - - # Eight way has a short circuit of one column mux select to gnd rail - c.word_size=2 - c.num_words=128 - c.words_per_row=8 - debug.info(1, "Eight way column mux") - name = "bank4_{0}rw_{1}w_{2}r_single".format(c.num_rw_ports, c.num_w_ports, c.num_r_ports) - a = bank(c, name=name) - self.local_check(a) - """ - globals.end_openram() # run the test from the command line From 2f55911604dcf99c596470a14591de295e5e0b1c Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 16 Jul 2019 11:55:25 -0700 Subject: [PATCH 104/234] Simplify column decoder placement. --- compiler/bitcells/pbitcell.py | 6 ++---- compiler/modules/bank.py | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 7ed748ec..f9a5ebd9 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -878,13 +878,11 @@ class pbitcell(design.design): def get_all_bl_names(self): """ Creates a list of all bl pins names """ - bl_pins = self.rw_bl_names + self.w_bl_names + self.r_bl_names - return bl_pins + return self.rw_bl_names + self.w_bl_names + self.r_bl_names def get_all_br_names(self): """ Creates a list of all br pins names """ - br_pins = self.rw_br_names + self.w_br_names + self.r_br_names - return br_pins + return self.rw_br_names + self.w_br_names + self.r_br_names def route_rbc_short(self): """ route the short from Q_bar to gnd necessary for the replica bitcell """ diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index af093d03..9d4dac7a 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -171,7 +171,7 @@ class bank(design.design): # The center point for these cells are the upper-right corner of # the bitcell array. - # The port address decoder/driver logic is placed on the right and mirrored on X- and Y-axis. + # The port address decoder/driver logic is placed on the right and mirrored on Y-axis. # The port data write/sense/precharge/mux is placed on the top and mirrored on the X-axis. self.bitcell_array_top = self.bitcell_array.height self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap @@ -213,14 +213,15 @@ class bank(design.design): # LOWER LEFT QUADRANT # Place the col decoder left aligned with wordline driver - # Below the bitcell array with well spacing + # This is also placed so that it's supply rails do not align with the SRAM-level + # control logic to allow control signals to easily pass over in M3 + # by placing 1/2 a cell pitch down x_offset = self.central_bus_width[port] + self.port_address.wordline_driver.width if self.col_addr_size > 0: x_offset += self.column_decoder.width + self.col_addr_bus_width - y_offset = self.m2_gap + self.column_decoder.height + y_offset = 0.5*self.dff.height + self.column_decoder.height else: y_offset = 0 - y_offset += 2*drc("well_to_well") self.column_decoder_offsets[port] = vector(-x_offset,-y_offset) # Bank select gets placed below the column decoder (x_offset doesn't change) @@ -257,10 +258,9 @@ class bank(design.design): x_offset = self.bitcell_array_right + self.central_bus_width[port] + self.port_address.wordline_driver.width if self.col_addr_size > 0: x_offset += self.column_decoder.width + self.col_addr_bus_width - y_offset = self.bitcell_array_top + self.m2_gap + self.column_decoder.height + y_offset = self.bitcell_array_top + 0.5*self.dff.height + self.column_decoder.height else: y_offset = self.bitcell_array_top - y_offset += 2*drc("well_to_well") self.column_decoder_offsets[port] = vector(x_offset,y_offset) # Bank select gets placed above the column decoder (x_offset doesn't change) @@ -522,16 +522,16 @@ class bank(design.design): Create a 2:4 or 3:8 column address decoder. """ - dff = factory.create(module_type="dff") + self.dff = factory.create(module_type="dff") if self.col_addr_size == 0: return elif self.col_addr_size == 1: - self.column_decoder = factory.create(module_type="pinvbuf", height=dff.height) + self.column_decoder = factory.create(module_type="pinvbuf", height=self.dff.height) elif self.col_addr_size == 2: - self.column_decoder = factory.create(module_type="hierarchical_predecode2x4", height=dff.height) + self.column_decoder = factory.create(module_type="hierarchical_predecode2x4", height=self.dff.height) elif self.col_addr_size == 3: - self.column_decoder = factory.create(module_type="hierarchical_predecode3x8", height=dff.height) + self.column_decoder = factory.create(module_type="hierarchical_predecode3x8", height=self.dff.height) else: # No error checking before? debug.error("Invalid column decoder?",-1) From 12fa36317e400880bb49814f88f3d8eef990eb7b Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 16 Jul 2019 13:51:31 -0700 Subject: [PATCH 105/234] Cleanup unit test. Fix s_en control bug for r-only. --- compiler/modules/bank.py | 4 ++-- compiler/modules/control_logic.py | 1 + compiler/tests/19_psingle_bank_test.py | 16 ++++++---------- compiler/tests/19_single_bank_1w_1r_test.py | 1 + 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 9d4dac7a..027ec3a6 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -79,9 +79,9 @@ class bank(design.design): for bit in range(self.word_size): self.add_pin("dout{0}_{1}".format(port,bit),"OUT") for port in self.read_ports: - self.add_pin(self.bitcell_array.get_rbl_bl_name(port),"OUT") + self.add_pin(self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]),"OUT") for port in self.read_ports: - self.add_pin(self.bitcell_array.get_rbl_wl_name(port),"IN") + self.add_pin(self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]),"IN") for port in self.write_ports: for bit in range(self.word_size): self.add_pin("din{0}_{1}".format(port,bit),"IN") diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 52207a77..602d289c 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -422,6 +422,7 @@ class control_logic(design.design): if (self.port_type == "rw") or (self.port_type == "r") or self.words_per_row>1: self.place_pen_row(row) row += 1 + if (self.port_type == "rw") or (self.port_type == "r"): self.place_sen_row(row) row += 1 self.place_delay(row) diff --git a/compiler/tests/19_psingle_bank_test.py b/compiler/tests/19_psingle_bank_test.py index e747b13b..90e886f4 100755 --- a/compiler/tests/19_psingle_bank_test.py +++ b/compiler/tests/19_psingle_bank_test.py @@ -20,16 +20,16 @@ class psingle_bank_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) - from bank import bank from sram_config import sram_config + OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" OPTS.dummy_bitcell="dummy_pbitcell" - # testing layout of bank using pbitcell with 1 RW port (a 6T-cell equivalent) OPTS.num_rw_ports = 1 OPTS.num_w_ports = 0 OPTS.num_r_ports = 0 + c = sram_config(word_size=4, num_words=16) @@ -37,8 +37,7 @@ class psingle_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "No column mux") - name = "bank1_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports) - a = bank(c, name=name) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) c.num_words=32 @@ -46,8 +45,7 @@ class psingle_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Two way column mux") - name = "bank2_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports) - a = bank(c, name=name) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) c.num_words=64 @@ -55,8 +53,7 @@ class psingle_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Four way column mux") - name = "bank3_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports) - a = bank(c, name=name) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) c.word_size=2 @@ -65,8 +62,7 @@ class psingle_bank_test(openram_test): factory.reset() c.recompute_sizes() debug.info(1, "Four way column mux") - name = "bank4_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports) - a = bank(c, name=name) + a = factory.create(module_type="bank", sram_config=c) self.local_check(a) globals.end_openram() diff --git a/compiler/tests/19_single_bank_1w_1r_test.py b/compiler/tests/19_single_bank_1w_1r_test.py index 81d4c8e6..12b9f3a0 100755 --- a/compiler/tests/19_single_bank_1w_1r_test.py +++ b/compiler/tests/19_single_bank_1w_1r_test.py @@ -24,6 +24,7 @@ class single_bank_1w_1r_test(openram_test): OPTS.bitcell = "bitcell_1w_1r" OPTS.replica_bitcell = "replica_bitcell_1w_1r" OPTS.dummy_bitcell="dummy_bitcell_1w_1r" + OPTS.num_rw_ports = 0 OPTS.num_r_ports = 1 OPTS.num_w_ports = 1 From b546ecce2ca72f2f93096f224d37dd8da7c82a6e Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 16 Jul 2019 14:11:54 -0700 Subject: [PATCH 106/234] Check 2 ports only for layout. --- 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 027ec3a6..1402015e 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -36,7 +36,6 @@ class bank(design.design): design.design.__init__(self, name) debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words)) - debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.") # The local control signals are gated when we have bank select logic, # so this prefix will be added to all of the input signals to create @@ -48,6 +47,7 @@ class bank(design.design): self.create_netlist() if not OPTS.netlist_only: + debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.") self.create_layout() self.add_boundary() From 8ca656959b52c0e599bbe558544ac6c06c7f6933 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 16 Jul 2019 15:09:46 -0700 Subject: [PATCH 107/234] Change direction of RBL bitline pins --- compiler/modules/replica_bitcell_array.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index ba92240e..3cbc54fa 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -185,8 +185,8 @@ class replica_bitcell_array(design.design): 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,"INPUT") - self.add_pin(br_name,"INPUT") + 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())] From 37fcf3bf37e923fee94f6f075eb9cd9e131353a5 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 16 Jul 2019 15:18:04 -0700 Subject: [PATCH 108/234] Move classes to individual file. --- compiler/base/delay_data.py | 43 +++++++++++++ compiler/base/hierarchy_spice.py | 102 +----------------------------- compiler/base/power_data.py | 38 +++++++++++ compiler/base/wire_spice_model.py | 42 ++++++++++++ 4 files changed, 126 insertions(+), 99 deletions(-) create mode 100644 compiler/base/delay_data.py create mode 100644 compiler/base/power_data.py create mode 100644 compiler/base/wire_spice_model.py diff --git a/compiler/base/delay_data.py b/compiler/base/delay_data.py new file mode 100644 index 00000000..e3d5a8bc --- /dev/null +++ b/compiler/base/delay_data.py @@ -0,0 +1,43 @@ +# 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. +# + +class delay_data(): + """ + This is the delay class to represent the delay information + Time is 50% of the signal to 50% of reference signal delay. + Slew is the 10% of the signal to 90% of signal + """ + def __init__(self, delay=0.0, slew=0.0): + """ init function support two init method""" + # will take single input as a coordinate + self.delay = delay + self.slew = slew + + def __str__(self): + """ override print function output """ + return "Delay Data: Delay "+str(self.delay)+", Slew "+str(self.slew)+"" + + def __add__(self, other): + """ + Override - function (left), for delay_data: a+b != b+a + """ + assert isinstance(other,delay_data) + return delay_data(other.delay + self.delay, + other.slew) + + def __radd__(self, other): + """ + Override - function (right), for delay_data: a+b != b+a + """ + assert isinstance(other,delay_data) + return delay_data(other.delay + self.delay, + self.slew) + + + + diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index e106cb2a..9730c7ef 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -10,6 +10,9 @@ import re import os import math import tech +from delay_data import * +from wire_spice_model import * +from power_data import * class spice(): @@ -383,102 +386,3 @@ class spice(): def return_power(self, dynamic=0.0, leakage=0.0): return power_data(dynamic, leakage) -class delay_data: - """ - This is the delay class to represent the delay information - Time is 50% of the signal to 50% of reference signal delay. - Slew is the 10% of the signal to 90% of signal - """ - def __init__(self, delay=0.0, slew=0.0): - """ init function support two init method""" - # will take single input as a coordinate - self.delay = delay - self.slew = slew - - def __str__(self): - """ override print function output """ - return "Delay Data: Delay "+str(self.delay)+", Slew "+str(self.slew)+"" - - def __add__(self, other): - """ - Override - function (left), for delay_data: a+b != b+a - """ - assert isinstance(other,delay_data) - return delay_data(other.delay + self.delay, - other.slew) - - def __radd__(self, other): - """ - Override - function (right), for delay_data: a+b != b+a - """ - assert isinstance(other,delay_data) - return delay_data(other.delay + self.delay, - self.slew) - -class power_data: - """ - This is the power class to represent the power information - Dynamic and leakage power are stored as a single object with this class. - """ - def __init__(self, dynamic=0.0, leakage=0.0): - """ init function support two init method""" - # will take single input as a coordinate - self.dynamic = dynamic - self.leakage = leakage - - def __str__(self): - """ override print function output """ - return "Power Data: Dynamic "+str(self.dynamic)+", Leakage "+str(self.leakage)+" in nW" - - def __add__(self, other): - """ - Override - function (left), for power_data: a+b != b+a - """ - assert isinstance(other,power_data) - return power_data(other.dynamic + self.dynamic, - other.leakage + self.leakage) - - def __radd__(self, other): - """ - Override - function (left), for power_data: a+b != b+a - """ - assert isinstance(other,power_data) - return power_data(other.dynamic + self.dynamic, - other.leakage + self.leakage) - - -class wire_spice_model: - """ - This is the spice class to represent a wire - """ - def __init__(self, lump_num, wire_length, wire_width): - self.lump_num = lump_num # the number of segment the wire delay has - self.wire_c = self.cal_wire_c(wire_length, wire_width) # c in each segment - self.wire_r = self.cal_wire_r(wire_length, wire_width) # r in each segment - - def cal_wire_c(self, wire_length, wire_width): - from tech import spice - total_c = spice["wire_unit_c"] * wire_length * wire_width - wire_c = total_c / self.lump_num - return wire_c - - def cal_wire_r(self, wire_length, wire_width): - from tech import spice - total_r = spice["wire_unit_r"] * wire_length / wire_width - wire_r = total_r / self.lump_num - return wire_r - - def return_input_cap(self): - return 0.5 * self.wire_c * self.lump_num - - def return_delay_over_wire(self, slew, swing = 0.5): - # delay will be sum of arithmetic sequence start from - # rc to self.lump_num*rc with step of rc - - swing_factor = abs(math.log(1-swing)) # time constant based on swing - sum_factor = (1+self.lump_num) * self.lump_num * 0.5 # sum of the arithmetic sequence - delay = sum_factor * swing_factor * self.wire_r * self.wire_c - slew = delay * 2 + slew - result= delay_data(delay, slew) - return result - diff --git a/compiler/base/power_data.py b/compiler/base/power_data.py new file mode 100644 index 00000000..77d50d34 --- /dev/null +++ b/compiler/base/power_data.py @@ -0,0 +1,38 @@ +# 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. +# + +class power_data(): + """ + This is the power class to represent the power information + Dynamic and leakage power are stored as a single object with this class. + """ + def __init__(self, dynamic=0.0, leakage=0.0): + """ init function support two init method""" + # will take single input as a coordinate + self.dynamic = dynamic + self.leakage = leakage + + def __str__(self): + """ override print function output """ + return "Power Data: Dynamic "+str(self.dynamic)+", Leakage "+str(self.leakage)+" in nW" + + def __add__(self, other): + """ + Override - function (left), for power_data: a+b != b+a + """ + assert isinstance(other,power_data) + return power_data(other.dynamic + self.dynamic, + other.leakage + self.leakage) + + def __radd__(self, other): + """ + Override - function (left), for power_data: a+b != b+a + """ + assert isinstance(other,power_data) + return power_data(other.dynamic + self.dynamic, + other.leakage + self.leakage) diff --git a/compiler/base/wire_spice_model.py b/compiler/base/wire_spice_model.py new file mode 100644 index 00000000..5624b575 --- /dev/null +++ b/compiler/base/wire_spice_model.py @@ -0,0 +1,42 @@ +# 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. +# + +class wire_spice_model(): + """ + This is the spice class to represent a wire + """ + def __init__(self, lump_num, wire_length, wire_width): + self.lump_num = lump_num # the number of segment the wire delay has + self.wire_c = self.cal_wire_c(wire_length, wire_width) # c in each segment + self.wire_r = self.cal_wire_r(wire_length, wire_width) # r in each segment + + def cal_wire_c(self, wire_length, wire_width): + from tech import spice + total_c = spice["wire_unit_c"] * wire_length * wire_width + wire_c = total_c / self.lump_num + return wire_c + + def cal_wire_r(self, wire_length, wire_width): + from tech import spice + total_r = spice["wire_unit_r"] * wire_length / wire_width + wire_r = total_r / self.lump_num + return wire_r + + def return_input_cap(self): + return 0.5 * self.wire_c * self.lump_num + + def return_delay_over_wire(self, slew, swing = 0.5): + # delay will be sum of arithmetic sequence start from + # rc to self.lump_num*rc with step of rc + + swing_factor = abs(math.log(1-swing)) # time constant based on swing + sum_factor = (1+self.lump_num) * self.lump_num * 0.5 # sum of the arithmetic sequence + delay = sum_factor * swing_factor * self.wire_r * self.wire_c + slew = delay * 2 + slew + result= delay_data(delay, slew) + return result From e2602dd79bb7ffd4e8914577c4d4bffa28337c51 Mon Sep 17 00:00:00 2001 From: mrg Date: Tue, 16 Jul 2019 17:30:31 -0700 Subject: [PATCH 109/234] Add comments for pins. Fix noconn in dummy pbitcell. --- compiler/base/hierarchy_spice.py | 10 ++++--- compiler/bitcells/pbitcell.py | 46 +++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 9730c7ef..02a72e0c 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -52,12 +52,13 @@ class spice(): def add_comment(self, comment): """ Add a comment to the spice file """ + try: self.commments except: self.comments = [] - else: - self.comments.append(comment) + + self.comments.append(comment) def add_pin(self, name, pin_type="INOUT"): """ Adds a pin to the pins list. Default type is INOUT signal. """ @@ -241,9 +242,12 @@ class spice(): sp.write("\n.SUBCKT {0} {1}\n".format(self.name, " ".join(self.pins))) + for pin in self.pins: + sp.write("* {1:6}: {0} \n".format(pin,self.pin_type[pin])) + for line in self.comments: sp.write("* {}\n".format(line)) - + # every instance must have a set of connections, even if it is empty. if len(self.insts)!=len(self.conns): debug.error("{0} : Not all instance pins ({1}) are connected ({2}).".format(self.name, diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index f9a5ebd9..6d95a15f 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -30,12 +30,20 @@ class pbitcell(design.design): self.dummy_bitcell = dummy_bitcell design.design.__init__(self, name) - debug.info(2, "create a multi-port bitcell with {0} rw ports, {1} w ports and {2} r ports".format(self.num_rw_ports, - self.num_w_ports, - self.num_r_ports)) + info_string = "{0} rw ports, {1} w ports and {2} r ports".format(self.num_rw_ports, + self.num_w_ports, + self.num_r_ports) + debug.info(2, "create a multi-port bitcell with {}".format(info_string)) + self.add_comment(info_string) + + if self.dummy_bitcell: + self.add_comment("dummy bitcell") + if self.replica_bitcell: + self.add_comment("replica bitcell") self.create_netlist() - # We must always create the bitcell layout because some transistor sizes in the other netlists depend on it + # We must always create the bitcell layout + # because some transistor sizes in the other netlists depend on it self.create_layout() self.add_boundary() @@ -377,14 +385,20 @@ class pbitcell(design.design): # iterate over the number of read/write ports for k in range(0,self.num_rw_ports): + bl_name = self.rw_bl_names[k] + br_name = self.rw_br_names[k] + if self.dummy_bitcell: + bl_name += "_noconn" + br_name += "_noconn" + # add read/write transistors self.readwrite_nmos_left[k] = self.add_inst(name="readwrite_nmos_left{}".format(k), mod=self.readwrite_nmos) - self.connect_inst([self.rw_bl_names[k], self.rw_wl_names[k], self.Q, "gnd"]) + self.connect_inst([bl_name, self.rw_wl_names[k], self.Q, "gnd"]) self.readwrite_nmos_right[k] = self.add_inst(name="readwrite_nmos_right{}".format(k), mod=self.readwrite_nmos) - self.connect_inst([self.Q_bar, self.rw_wl_names[k], self.rw_br_names[k], "gnd"]) + self.connect_inst([self.Q_bar, self.rw_wl_names[k], br_name, "gnd"]) def place_readwrite_ports(self): """ Places read/write ports in the bit cell """ @@ -451,14 +465,20 @@ class pbitcell(design.design): # iterate over the number of write ports for k in range(0,self.num_w_ports): + bl_name = self.w_bl_names[k] + br_name = self.w_br_names[k] + if self.dummy_bitcell: + bl_name += "_noconn" + br_name += "_noconn" + # add write transistors self.write_nmos_left[k] = self.add_inst(name="write_nmos_left{}".format(k), mod=self.write_nmos) - self.connect_inst([self.w_bl_names[k], self.w_wl_names[k], self.Q, "gnd"]) + self.connect_inst([bl_name, self.w_wl_names[k], self.Q, "gnd"]) self.write_nmos_right[k] = self.add_inst(name="write_nmos_right{}".format(k), mod=self.write_nmos) - self.connect_inst([self.Q_bar, self.w_wl_names[k], self.w_br_names[k], "gnd"]) + self.connect_inst([self.Q_bar, self.w_wl_names[k], br_name, "gnd"]) def place_write_ports(self): """ Places write ports in the bit cell """ @@ -533,6 +553,12 @@ class pbitcell(design.design): # iterate over the number of read ports for k in range(0,self.num_r_ports): + bl_name = self.r_bl_names[k] + br_name = self.r_br_names[k] + if self.dummy_bitcell: + bl_name += "_noconn" + br_name += "_noconn" + # add read-access transistors self.read_access_nmos_left[k] = self.add_inst(name="read_access_nmos_left{}".format(k), mod=self.read_nmos) @@ -545,11 +571,11 @@ class pbitcell(design.design): # add read transistors self.read_nmos_left[k] = self.add_inst(name="read_nmos_left{}".format(k), mod=self.read_nmos) - self.connect_inst([self.r_bl_names[k], self.r_wl_names[k], "RA_to_R_left{}".format(k), "gnd"]) + self.connect_inst([bl_name, self.r_wl_names[k], "RA_to_R_left{}".format(k), "gnd"]) self.read_nmos_right[k] = self.add_inst(name="read_nmos_right{}".format(k), mod=self.read_nmos) - self.connect_inst(["RA_to_R_right{}".format(k), self.r_wl_names[k], self.r_br_names[k], "gnd"]) + self.connect_inst(["RA_to_R_right{}".format(k), self.r_wl_names[k], br_name, "gnd"]) def place_read_ports(self): """ Places the read ports in the bit cell """ From 9696401f349bbb3a4f9b840f8980918bfe36cb6d Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 16 Jul 2019 23:47:34 -0700 Subject: [PATCH 110/234] Added graph exclusions to replica column to reduce s_en paths. --- compiler/characterizer/delay.py | 1 + compiler/modules/replica_bitcell_array.py | 10 ++++++++++ compiler/modules/replica_column.py | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 59f5dcf5..8dac8ad4 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -206,6 +206,7 @@ class delay(simulation): self.sram.graph_exclude_addr_dff() self.sram.graph_exclude_data_dff() self.sram.graph_exclude_ctrl_dffs() + self.sram.bank.bitcell_array.graph_exclude_replica_col_bits() def create_graph(self): """Creates timing graph to generate the timing paths for the SRAM output.""" diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 3cbc54fa..63224033 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -138,6 +138,8 @@ class replica_bitcell_array(design.design): # 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]) + #Save where the RBL wordlines start for graph purposes. Even positions are changed then graph will break + self.rbl_row_pos = len(self.replica_col_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 @@ -442,3 +444,11 @@ class replica_bitcell_array(design.design): """Excludes bits in column from being added to graph except target""" self.bitcell_array.graph_exclude_bits(targ_row, targ_col) + def graph_exclude_replica_col_bits(self): + for port in range(self.left_rbl+self.right_rbl): + #While the rbl_wl bits may be on a few rows. Only keep one for simplicity. + self.replica_columns[port].exclude_bits_except_one(self.rbl_row_pos) + + def get_cell_name(self, inst_name, row, col): + """Gets the spice name of the target bitcell.""" + return self.bitcell_array.get_cell_name(inst_name+'.x'+self.bitcell_array_inst.name, row, col) \ No newline at end of file diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index cf2a910a..fdd726f5 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -155,3 +155,8 @@ class replica_column(design.design): return bitcell_pins + def exclude_bits_except_one(self, selected_row): + for row, cell in self.cell_inst.items(): + if row == selected_row: + continue + self.graph_inst_exclude.add(cell) \ No newline at end of file From 720739a1922c10080765072722451408ec7a7125 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 17 Jul 2019 11:04:17 -0700 Subject: [PATCH 111/234] Skipping test 22_sram_wmask_func_test and changed a typo of write_driver to write_mask --- compiler/characterizer/functional.py | 3 ++- compiler/gdsMill/gdsMill/vlsiLayout.py | 4 ++-- compiler/modules/port_data.py | 4 ++-- compiler/tests/22_sram_wmask_func_test.py | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 1aed19b9..4386b293 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -124,6 +124,7 @@ class functional(simulation): comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current) self.add_read_one_port(comment, addr, rw_read_din_data, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) + # don't check X's check += 1 self.cycle_times.append(self.t_current) self.t_current += self.period @@ -136,7 +137,7 @@ class functional(simulation): if port in self.readwrite_ports: op = random.choice(rw_ops) elif port in self.write_ports: - op = random.choice(w_ops) + op = rcandom.choice(w_ops) else: op = random.choice(r_ops) diff --git a/compiler/gdsMill/gdsMill/vlsiLayout.py b/compiler/gdsMill/gdsMill/vlsiLayout.py index 57e81768..f4248ebd 100644 --- a/compiler/gdsMill/gdsMill/vlsiLayout.py +++ b/compiler/gdsMill/gdsMill/vlsiLayout.py @@ -729,7 +729,7 @@ class VlsiLayout: def getBlockages(self,layer): """ - Return all blockages on a given layer in [llx, lly, urx, ury] format and + Return all blockages on a given layer in [coordinate 1, coordinate 2,...] format and user units. """ blockages = [] @@ -744,7 +744,7 @@ class VlsiLayout: def getAllShapes(self,layer): """ - Return all shapes on a given layer in [llx, lly, urx, ury] format and user units for rectangles + Return all shapes on a given layer in [llx, lly, urx, ury] format and user units for rectangles and [coordinate 1, coordinate 2,...] format and user units for polygons. """ boundaries = set() diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 2f5b634f..480047fe 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -175,7 +175,7 @@ class port_data(design.design): columns=self.num_cols, word_size=self.word_size, write_size=self.write_size) - self.add_mod(self.write_driver_array) + self.add_mod(self.write_mask_array) else: self.write_mask_array_inst = None @@ -309,7 +309,7 @@ class port_data(design.design): def place_write_driver_array(self, offset): """ Placing Write Driver """ - self.write_driver_array_inst.place(offset=offset, mirror="MX") + self .write_driver_array_inst.place(offset=offset, mirror="MX") def compute_instance_offsets(self): diff --git a/compiler/tests/22_sram_wmask_func_test.py b/compiler/tests/22_sram_wmask_func_test.py index 4fcc63c9..db239ccf 100755 --- a/compiler/tests/22_sram_wmask_func_test.py +++ b/compiler/tests/22_sram_wmask_func_test.py @@ -15,7 +15,7 @@ from globals import OPTS from sram_factory import factory import debug -#@unittest.skip("SKIPPING sram_wmask_func_test") +@unittest.skip("SKIPPING sram_wmask_func_test") class sram_wmask_func_test(openram_test): def runTest(self): From 917a69723f4fec9ce46cfabab1c9efabe7f1e1bf Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 17 Jul 2019 12:26:05 -0700 Subject: [PATCH 112/234] Fixed typo --- compiler/characterizer/functional.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 4386b293..ce22e01a 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -137,7 +137,7 @@ class functional(simulation): if port in self.readwrite_ports: op = random.choice(rw_ops) elif port in self.write_ports: - op = rcandom.choice(w_ops) + op = random.choice(w_ops) else: op = random.choice(r_ops) From a707c6fa50245c18c458ac376b3a78b5fa9dbe37 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 18 Jul 2019 14:49:54 -0700 Subject: [PATCH 113/234] Convert psram tests to only 2 port. --- compiler/tests/22_psram_1bank_2mux_func_test.py | 8 +++++--- compiler/tests/22_psram_1bank_4mux_func_test.py | 5 ++++- compiler/tests/22_psram_1bank_8mux_func_test.py | 5 ++++- compiler/tests/22_psram_1bank_nomux_func_test.py | 5 ++++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index 2eaaf48d..90cc8bd2 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -15,18 +15,20 @@ from globals import OPTS from sram_factory import factory import debug -#@unittest.skip("SKIPPING 22_psram_1bank_2mux_1rw_1r_1w_func_test, third port reads are broken?") -class psram_1bank_2mux_1rw_1r_1w_func_test(openram_test): +class psram_1bank_2mux_func_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) OPTS.analytical_delay = False OPTS.netlist_only = True OPTS.trim_netlist = False + OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" + OPTS.dummy_bitcell="dummy_pbitcell" + OPTS.num_rw_ports = 1 - OPTS.num_r_ports = 1 + OPTS.num_r_ports = 0 OPTS.num_w_ports = 1 # This is a hack to reload the characterizer __init__ with the spice version diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index 30d2a465..ac0b733c 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -23,10 +23,13 @@ class psram_1bank_4mux_func_test(openram_test): OPTS.analytical_delay = False OPTS.netlist_only = True OPTS.trim_netlist = False + OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" + OPTS.dummy_bitcell="dummy_pbitcell" + OPTS.num_rw_ports = 1 - OPTS.num_r_ports = 1 + OPTS.num_r_ports = 0 OPTS.num_w_ports = 1 # This is a hack to reload the characterizer __init__ with the spice version diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index e5b2e91e..8b1881fb 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -23,10 +23,13 @@ class psram_1bank_8mux_func_test(openram_test): OPTS.analytical_delay = False OPTS.netlist_only = True OPTS.trim_netlist = False + OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" + OPTS.dummy_bitcell="dummy_pbitcell" + OPTS.num_rw_ports = 1 - OPTS.num_r_ports = 1 + OPTS.num_r_ports = 0 OPTS.num_w_ports = 1 # This is a hack to reload the characterizer __init__ with the spice version diff --git a/compiler/tests/22_psram_1bank_nomux_func_test.py b/compiler/tests/22_psram_1bank_nomux_func_test.py index 2f350aa9..323282e5 100755 --- a/compiler/tests/22_psram_1bank_nomux_func_test.py +++ b/compiler/tests/22_psram_1bank_nomux_func_test.py @@ -23,10 +23,13 @@ class psram_1bank_nomux_func_test(openram_test): OPTS.analytical_delay = False OPTS.netlist_only = True OPTS.trim_netlist = False + OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" + OPTS.dummy_bitcell="dummy_pbitcell" + OPTS.num_rw_ports = 1 - OPTS.num_r_ports = 1 + OPTS.num_r_ports = 0 OPTS.num_w_ports = 1 # This is a hack to reload the characterizer __init__ with the spice version From 864639d96e6c3f7f81eb8f7509686aae68e94527 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 18 Jul 2019 15:19:40 -0700 Subject: [PATCH 114/234] Remove old replica bitline. --- compiler/modules/replica_bitline.py | 270 ------------------ ...> 14_replica_bitcell_1rw_1r_array_test.py} | 0 ...st.py => 14_replica_bitcell_array_test.py} | 0 .../14_replica_bitline_multiport_test.py | 68 ----- compiler/tests/14_replica_bitline_test.py | 44 --- ...lumn_test.py => 14_replica_column_test.py} | 0 6 files changed, 382 deletions(-) delete mode 100644 compiler/modules/replica_bitline.py rename compiler/tests/{05_replica_bitcell_1rw_1r_array_test.py => 14_replica_bitcell_1rw_1r_array_test.py} (100%) rename compiler/tests/{05_replica_bitcell_array_test.py => 14_replica_bitcell_array_test.py} (100%) delete mode 100755 compiler/tests/14_replica_bitline_multiport_test.py delete mode 100755 compiler/tests/14_replica_bitline_test.py rename compiler/tests/{05_replica_column_test.py => 14_replica_column_test.py} (100%) diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py deleted file mode 100644 index 61e540cc..00000000 --- a/compiler/modules/replica_bitline.py +++ /dev/null @@ -1,270 +0,0 @@ -# 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 -import contact -from sram_factory import factory -from vector import vector -from globals import OPTS - -class replica_bitline(design.design): - """ - Generate a module that simulates the delay of control logic - and bit line charging. Stages is the depth of the delay - line and rows is the height of the replica bit loads. - """ - - def __init__(self, name, delay_fanout_list, bitcell_loads): - design.design.__init__(self, name) - - self.bitcell_loads = bitcell_loads - self.delay_fanout_list = delay_fanout_list - if len(delay_fanout_list) == 0 or len(delay_fanout_list)%2 == 1: - debug.error('Delay chain must contain an even amount of stages to maintain polarity.',1) - - self.create_netlist() - if not OPTS.netlist_only: - self.create_layout() - - def create_netlist(self): - self.add_modules() - self.add_pins() - self.create_instances() - - def create_layout(self): - self.calculate_module_offsets() - self.place_instances() - self.route() - self.add_layout_pins() - - self.offset_all_coordinates() - - #self.add_lvs_correspondence_points() - - # Extra pitch on top and right - self.width = self.delay_chain_inst.rx() + self.m2_pitch - self.height = self.delay_chain_inst.uy() + self.m3_pitch - - self.add_boundary() - self.DRC_LVS() - - def add_pins(self): - pin_list = ["en", "bl", "wl", "out", "vdd", "gnd"] - pin_dir = ["INPUT", "INPUT", "OUTPUT", "OUTPUT", "POWER", "GROUND"] - self.add_pin_list(pin_list, pin_dir) - - def calculate_module_offsets(self): - """ Calculate all the module offsets """ - - # Quadrant 4: with some space below it and tracks on the right for vdd/gnd - self.delay_chain_offset = vector(0, self.inv.height) - - # Will be flipped vertically below the delay chain - # Align it with the inverters in the delay chain to simplify supply connections - self.rbl_inv_offset = self.delay_chain_offset + vector(2*self.inv.width, 0) - - # Placed next to the replica bitcell - self.access_tx_offset = vector(self.rbl_inv_offset.x + self.inv.width, 0.5*self.inv.height) - - - def add_modules(self): - """ Add the modules for later usage """ - - # FIXME: The FO and depth of this should be tuned - self.delay_chain = factory.create(module_type="delay_chain", - fanout_list=self.delay_fanout_list) - self.add_mod(self.delay_chain) - - self.inv = factory.create(module_type="pinv") - self.add_mod(self.inv) - - self.access_tx = factory.create(module_type="ptx", - tx_type="pmos") - self.add_mod(self.access_tx) - - def create_instances(self): - """ Create all of the module instances in the logical netlist """ - - # This is the threshold detect inverter on the output of the RBL - self.rbl_inv_inst=self.add_inst(name="rbl_inv", - mod=self.inv) - self.connect_inst(["bl0_0", "out", "vdd", "gnd"]) - - self.tx_inst=self.add_inst(name="rbl_access_tx", - mod=self.access_tx) - # D, G, S, B - self.connect_inst(["vdd", "delayed_en", "bl0_0", "vdd"]) - # add the well and poly contact - - self.delay_chain_inst=self.add_inst(name="delay_chain", - mod=self.delay_chain) - self.connect_inst(["en", "delayed_en", "vdd", "gnd"]) - - def place_instances(self): - """ Add all of the module instances in the logical netlist """ - - # This is the threshold detect inverter on the output of the RBL - self.rbl_inv_inst.place(offset=self.rbl_inv_offset, - rotate=180) - - self.tx_inst.place(self.access_tx_offset) - - self.delay_chain_inst.place(self.delay_chain_offset) - - - def route(self): - """ Connect all the signals together """ - self.route_supplies() - self.route_access_tx() - - def route_supplies(self): - """ Propagate all vdd/gnd pins up to this level for all modules """ - - self.copy_layout_pin(self.delay_chain_inst, "vdd") - self.copy_layout_pin(self.delay_chain_inst, "gnd") - - # Route the inverter supply pin from M1 - # Only vdd is needed because gnd shares a rail with the delay chain - pin = self.rbl_inv_inst.get_pin("vdd") - self.add_power_pin("vdd", pin.lc()) - - - - - def route_access_tx(self): - # GATE ROUTE - # 1. Add the poly contact and nwell enclosure - # Determines the y-coordinate of where to place the gate input poly pin - # (middle in between the pmos and nmos) - - poly_pin = self.tx_inst.get_pin("G") - poly_offset = poly_pin.uc() - # This centers the contact above the poly by one pitch - contact_offset = poly_offset + vector(0,self.m2_pitch) - self.add_via_center(layers=("poly", "contact", "metal1"), - offset=contact_offset) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=contact_offset) - self.add_segment_center(layer="poly", - start=poly_offset, - end=contact_offset) - nwell_offset = self.rbl_inv_offset + vector(-self.inv.height,self.inv.width) - # self.add_rect(layer="nwell", - # offset=nwell_offset, - # width=0.5*self.inv.height, - # height=self.delay_chain_offset.y-nwell_offset.y) - - # 2. Route delay chain output to access tx gate - delay_en_offset = self.delay_chain_inst.get_pin("out").bc() - self.add_path("metal2", [delay_en_offset,contact_offset]) - - # 3. Route the contact of previous route to the bitcell WL - # route bend of previous net to bitcell WL - self.add_layout_pin_rect_center(text="wl", - layer="metal1", - offset=contact_offset) - - # DRAIN ROUTE - # Route the drain to the vdd rail - drain_offset = self.tx_inst.get_pin("D").center() - self.add_power_pin("vdd", drain_offset, vertical=True) - - # SOURCE ROUTE - # Route the drain to the RBL inverter input - source_offset = self.tx_inst.get_pin("S").center() - inv_A_offset = self.rbl_inv_inst.get_pin("A").center() - self.add_path("metal1",[source_offset, inv_A_offset]) - - # Route the connection of the source route to the RBL bitline (left) - source_down_offset = source_offset - vector(0,3*self.m2_pitch) - self.add_path("metal1",[source_offset, source_down_offset]) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=source_offset) - self.add_layout_pin_rect_center(text="bl", - layer="metal1", - offset=source_down_offset) - - # BODY ROUTE - # Connect it to the inverter well - nwell_offset = self.rbl_inv_inst.lr() - ur_offset = self.tx_inst.ur() - self.add_rect(layer="nwell", - offset=nwell_offset, - width=ur_offset.x-nwell_offset.x, - height=ur_offset.y-nwell_offset.y) - - - - def add_layout_pins(self): - """ Route the input and output signal """ - en_offset = self.delay_chain_inst.get_pin("in").bc() - self.add_layout_pin_segment_center(text="en", - layer="metal2", - start=en_offset, - end=en_offset.scale(1,0)) - - out_offset = self.rbl_inv_inst.get_pin("Z").center() - self.add_layout_pin_segment_center(text="out", - layer="metal2", - start=out_offset, - end=out_offset.scale(1,0)) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=out_offset) - - def add_lvs_correspondence_points(self): - """ This adds some points for easier debugging if LVS goes wrong. - These should probably be turned off by default though, since extraction - will show these as ports in the extracted netlist. - """ - - pin = self.rbl_inv_inst.get_pin("A") - self.add_label_pin(text="bl[0]", - layer=pin.layer, - offset=pin.ll(), - height=pin.height(), - width=pin.width()) - - pin = self.delay_chain_inst.get_pin("out") - self.add_label_pin(text="delayed_en", - layer=pin.layer, - offset=pin.ll(), - height=pin.height(), - width=pin.width()) - - def get_en_cin(self): - """Get the enable input relative capacitance""" - #The enable is only connected to the delay, get the cin from that module - en_cin = self.delay_chain.get_cin() - return en_cin - - def determine_sen_stage_efforts(self, ext_cout, inp_is_rise=True): - """Get the stage efforts from the en to s_en. Does not compute the delay for the bitline load.""" - stage_effort_list = [] - #Stage 1 is the delay chain - stage1_cout = self.get_delayed_en_cin() - stage1 = self.delay_chain.determine_delayed_en_stage_efforts(stage1_cout, inp_is_rise) - stage_effort_list += stage1 - - #There is a disconnect between the delay chain and inverter. The rise/fall of the input to the inverter - #Will be the negation of the previous stage. - last_stage_is_rise = not stage_effort_list[-1].is_rise - - #The delay chain triggers the enable on the replica bitline (rbl). This is used to track the bitline delay whereas this - #model is intended to track every but that. Therefore, the next stage is the inverter after the rbl. - stage2 = self.inv.get_stage_effort(ext_cout, last_stage_is_rise) - stage_effort_list.append(stage2) - - return stage_effort_list - - def get_delayed_en_cin(self): - """Get the fanout capacitance (relative) of the delayed enable from the delay chain.""" - access_tx_cin = self.access_tx.get_cin() - rbc_cin = self.replica_bitcell.get_wl_cin() - return access_tx_cin + rbc_cin - diff --git a/compiler/tests/05_replica_bitcell_1rw_1r_array_test.py b/compiler/tests/14_replica_bitcell_1rw_1r_array_test.py similarity index 100% rename from compiler/tests/05_replica_bitcell_1rw_1r_array_test.py rename to compiler/tests/14_replica_bitcell_1rw_1r_array_test.py diff --git a/compiler/tests/05_replica_bitcell_array_test.py b/compiler/tests/14_replica_bitcell_array_test.py similarity index 100% rename from compiler/tests/05_replica_bitcell_array_test.py rename to compiler/tests/14_replica_bitcell_array_test.py diff --git a/compiler/tests/14_replica_bitline_multiport_test.py b/compiler/tests/14_replica_bitline_multiport_test.py deleted file mode 100755 index 369111e9..00000000 --- a/compiler/tests/14_replica_bitline_multiport_test.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/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 replica_bitline_multiport_test(openram_test): - - def runTest(self): - globals.init_openram("config_{0}".format(OPTS.tech_name)) - - stages=4 - fanout=4 - rows=13 - - OPTS.bitcell = "bitcell_1rw_1r" - OPTS.replica_bitcell = "replica_bitcell_1rw_1r" - OPTS.dummy_bitcell = "dummy_bitcell_1rw_1r" - OPTS.num_rw_ports = 1 - OPTS.num_r_ports = 1 - OPTS.num_w_ports = 0 - - factory.reset() - debug.info(2, "Testing 1rw 1r RBL with {0} FO4 stages, {1} rows".format(stages,rows)) - a = factory.create(module_type="replica_bitline", delay_fanout_list=stages*[fanout], bitcell_loads=rows) - self.local_check(a) - - # check replica bitline in pbitcell multi-port - OPTS.bitcell = "pbitcell" - OPTS.replica_bitcell = "replica_pbitcell" - OPTS.dummy_bitcell = "dummy_pbitcell" - OPTS.num_rw_ports = 1 - OPTS.num_w_ports = 0 - OPTS.num_r_ports = 0 - - factory.reset() - debug.info(2, "Testing RBL pbitcell 1rw with {0} FO4 stages, {1} rows".format(stages,rows)) - a = factory.create(module_type="replica_bitline", delay_fanout_list=stages*[fanout], bitcell_loads=rows) - self.local_check(a) - - OPTS.num_rw_ports = 1 - OPTS.num_w_ports = 1 - OPTS.num_r_ports = 1 - - factory.reset() - debug.info(2, "Testing RBL pbitcell 1rw 1w 1r with {0} FO4 stages, {1} rows".format(stages,rows)) - a = factory.create(module_type="replica_bitline", delay_fanout_list=stages*[fanout], bitcell_loads=rows) - 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()) diff --git a/compiler/tests/14_replica_bitline_test.py b/compiler/tests/14_replica_bitline_test.py deleted file mode 100755 index 47171aae..00000000 --- a/compiler/tests/14_replica_bitline_test.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/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 replica_bitline_test(openram_test): - - def runTest(self): - globals.init_openram("config_{0}".format(OPTS.tech_name)) - - # check replica bitline in single port - stages=4 - fanout=4 - rows=13 - debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows)) - a = factory.create(module_type="replica_bitline", delay_fanout_list=stages*[fanout], bitcell_loads=rows) - self.local_check(a) - - stages=8 - rows=100 - debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows)) - a = factory.create(module_type="replica_bitline", delay_fanout_list=stages*[fanout], bitcell_loads=rows) - 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()) diff --git a/compiler/tests/05_replica_column_test.py b/compiler/tests/14_replica_column_test.py similarity index 100% rename from compiler/tests/05_replica_column_test.py rename to compiler/tests/14_replica_column_test.py From 5f37067da7d92e3ccca0cae29405a5da080c4509 Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 18 Jul 2019 15:24:41 -0700 Subject: [PATCH 115/234] Turned write_mask_array into write_mask_and_array with flip flops from sram_base --- ..._mask_array.py => write_mask_and_array.py} | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) rename compiler/modules/{write_mask_array.py => write_mask_and_array.py} (89%) diff --git a/compiler/modules/write_mask_array.py b/compiler/modules/write_mask_and_array.py similarity index 89% rename from compiler/modules/write_mask_array.py rename to compiler/modules/write_mask_and_array.py index 1a349289..f17f458c 100644 --- a/compiler/modules/write_mask_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -14,7 +14,7 @@ from vector import vector from globals import OPTS -class write_mask_array(design.design): +class write_mask_and_array(design.design): """ Array of tristate drivers to write to the bitlines through the column mux. Dynamically generated write driver array of all bitlines. @@ -40,7 +40,7 @@ class write_mask_array(design.design): def create_netlist(self): self.add_modules() self.add_pins() - self.create_write_mask_array() +# self.create_write_mask_array() self.create_and2_array() @@ -67,7 +67,7 @@ class write_mask_array(design.design): def add_modules(self): self.wmask = factory.create(module_type="dff_buf") - self.add_mod(self.wmask) + #self.add_mod(self.wmask) dff_height = self.wmask.height self.and2 = factory.create(module_type="pand2", @@ -76,17 +76,17 @@ class write_mask_array(design.design): self.add_mod(self.and2) - def create_write_mask_array(self): - self.wmask_insts = {} - for bit in range(self.num_wmask): - name = "write_mask_{}".format(bit) - self.wmask_insts[bit] = self.add_inst(name=name, - mod=self.wmask) - - self.connect_inst(["wmask_{}".format(bit), - "bank_wmask_{}".format(bit), - "bank_wmask_bar_{}".format(bit), - "clk", "vdd", "gnd"]) + # def create_write_mask_array(self): + # self.wmask_insts = {} + # for bit in range(self.num_wmask): + # name = "write_mask_{}".format(bit) + # self.wmask_insts[bit] = self.add_inst(name=name, + # mod=self.wmask) + # + # self.connect_inst(["wmask_{}".format(bit), + # "bank_wmask_{}".format(bit), + # "bank_wmask_bar_{}".format(bit), + # "clk", "vdd", "gnd"]) def create_and2_array(self): self.and2_insts = {} From 082decba18c35b05598ba31d557cd3cb9e73d3f3 Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 18 Jul 2019 15:26:38 -0700 Subject: [PATCH 116/234] Temporarily made the functional tests write/read only all 0's or 1's --- compiler/characterizer/functional.py | 59 +++++++++++----------------- compiler/characterizer/simulation.py | 6 +-- compiler/modules/port_data.py | 36 +++++++++-------- 3 files changed, 46 insertions(+), 55 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index ce22e01a..d49d307b 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -51,12 +51,13 @@ class functional(simulation): self.wmask_enabled = False if self.word_size !=self.write_size: self.wmask_enabled = True - # initialize first wmask bit to 1, otherwise 0 + # initialize wmask to 1 for bit in range(self.num_wmask): - if bit == 0: - self.wmask[self.num_wmask-1 - bit] = 1 - else: - self.wmask[self.num_wmask-1 - bit] = 0 + self.wmask[bit] = 1 + # if bit == 0: + # self.wmask[self.num_wmask-1 - bit] = 1 + # else: + # self.wmask[self.num_wmask-1 - bit] = 0 def run(self, feasible_period=None): if feasible_period: #period defaults to tech.py feasible period otherwise. @@ -82,7 +83,7 @@ class functional(simulation): r_ops = ["noop", "read"] rw_read_din_data = "0"*self.word_size check = 0 - + # First cycle idle comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.wmask, self.t_current) self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size) @@ -92,28 +93,7 @@ class functional(simulation): word = self.gen_data() comment = self.gen_cycle_comment("write", word, addr, 0, self.wmask, self.t_current) self.add_write(comment, addr, word, 0) - if self.wmask_enabled: - old_word = "" - if self.stored_words.get(addr) == None: - for i in range(self.word_size): - old_word += "X" - else: - old_word = self.stored_words[addr] - for bit in self.wmask: - # Don't write the bits of the new word to the address - if self.wmask[bit] == 0: - lower = bit * self.write_size - upper = lower + self.write_size - 1 - if bit == self.num_wmask-1: - word = word[0:lower] + old_word[lower:upper+1] - elif bit == 0: - word = old_word[lower:upper+1] + word [upper+1:self.word_size] - else: - word = word[0:lower] + old_word[lower:upper+1] + word [upper+1:self.word_size] - #word = word.replace(word[lower:upper+1],old_word[lower:upper+1],1) - self.stored_words[addr] = word - else: - self.stored_words[addr] = word + self.stored_words[addr] = word # Read at least once. For multiport, it is important that one read cycle uses all RW and R port to read from the same address simultaniously. # This will test the viablilty of the transistor sizing in the bitcell. @@ -124,7 +104,6 @@ class functional(simulation): comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current) self.add_read_one_port(comment, addr, rw_read_din_data, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) - # don't check X's check += 1 self.cycle_times.append(self.t_current) self.t_current += self.period @@ -148,12 +127,13 @@ class functional(simulation): elif op == "write": addr = self.gen_addr() word = self.gen_data() - wmask = self.gen_wmask() + # wmask = self.gen_wmask() # two ports cannot write to the same address if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port) else: - comment = self.gen_cycle_comment("write", word, addr, port, wmask, self.t_current) + # comment = self.gen_cycle_comment("write", word, addr, port, wmask, self.t_current) + comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current) self.add_write_one_port(comment, addr, word, port) self.stored_words[addr] = word w_addrs.append(addr) @@ -215,17 +195,26 @@ class functional(simulation): wmask_bits[bit] = rand return wmask_bits + # def gen_data(self): + # """ Generates a random word to write. """ + # rand = random.randint(0,(2**self.word_size)-1) + # data_bits = self.convert_to_bin(rand,False) + # return data_bits + def gen_data(self): - """ Generates a random word to write. """ - rand = random.randint(0,(2**self.word_size)-1) - data_bits = self.convert_to_bin(rand,False) + """ Generates a random word, either all 0 or all 1's, to write. """ + rand = random.randint(0,1) + bits = [] + for bit in range(self.word_size): + bits.append(rand) + data_bits = ''.join(map(str,bits)) return data_bits def gen_addr(self): """ Generates a random address value to write to. """ rand = random.randint(0,(2**self.addr_size)-1) addr_bits = self.convert_to_bin(rand,True) - return addr_bits + return addr_bits def get_data(self): """ Gets an available address and corresponding word. """ diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index d9154f0e..5b34ce01 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -234,12 +234,12 @@ class simulation(): t_current+self.period) elif op == "write": if (self.wmask_enabled): - comment = "\tWriting {0} to address {1} with mask bit {0} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, + comment = "\tWriting {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word, addr, wmask, port, - int( - t_current / self.period), + int(t_current / self.period), + t_current, t_current + self.period) else: diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 480047fe..7f77652e 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -55,12 +55,12 @@ class port_data(design.design): if self.write_driver_array: self.create_write_driver_array() if (self.word_size != self.write_size): - self.create_write_mask_array() + self.create_write_mask_and_array() else: - self.write_mask_array_inst = None + self.write_mask_and_array_inst = None else: self.write_driver_array_inst = None - self.write_mask_array_inst = None + self.write_mask_and_array_inst = None if self.column_mux_array: self.create_column_mux_array() @@ -171,17 +171,17 @@ class port_data(design.design): word_size=self.word_size) self.add_mod(self.write_driver_array) if (self.word_size != self.write_size): - self.write_mask_array = factory.create(module_type="write_mask_array", - columns=self.num_cols, - word_size=self.word_size, - write_size=self.write_size) - self.add_mod(self.write_mask_array) + self.write_mask_and_array = factory.create(module_type="write_mask_and_array", + columns=self.num_cols, + word_size=self.word_size, + write_size=self.write_size) + self.add_mod(self.write_mask_and_array) else: - self.write_mask_array_inst = None + self.write_mask_and_array_inst = None else: self.write_driver_array = None - self.write_mask_array = None + self.write_mask_and_array = None def precompute_constants(self): """ Get some preliminary data ready """ @@ -282,8 +282,10 @@ class port_data(design.design): mod=self.write_driver_array) temp = [] - for bit in range(self.word_size): - temp.append("din_{}".format(bit)) + m + for bit in range(self.word_size): + temp.append("din_{}".format(bit)) + for bit in range(self.word_size): if (self.words_per_row == 1): temp.append(self.bl_names[self.port]+"_{0}".format(bit)) @@ -295,18 +297,18 @@ class port_data(design.design): self.connect_inst(temp) - def create_write_mask_array(self): + def create_write_mask_and_array(self): """ Creating Write Masks """ - self.write_mask_array_inst = self.add_inst(name="write_mask_array{}".format(self.port), - mod=self.write_mask_array) + self.write_mask_and_array_inst = self.add_inst(name="write_mask_and_array{}".format(self.port), + mod=self.write_mask_and_array) temp = [] for bit in range(self.num_wmask): - temp.append("write_mask_".format(bit)) + temp.append("write_mask_{}".format(bit)) temp.extend(["w_en", "vdd", "gnd"]) self.connect_inst(temp) - + def place_write_driver_array(self, offset): """ Placing Write Driver """ self .write_driver_array_inst.place(offset=offset, mirror="MX") From 45cb159d7f3ced59b0ee37ba803d68234445bfb3 Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 19 Jul 2019 13:17:55 -0700 Subject: [PATCH 117/234] Connected wmask in the spice netlist. --- compiler/characterizer/functional.py | 12 ++++++++ compiler/characterizer/simulation.py | 22 +++++++++++++-- compiler/modules/bank.py | 12 ++++++++ compiler/modules/port_data.py | 34 +++++++++++++++++------ compiler/modules/write_driver_array.py | 23 +++++++++++---- compiler/modules/write_mask_and_array.py | 14 ++++++---- compiler/sram/sram_base.py | 12 ++++---- compiler/tests/22_sram_wmask_func_test.py | 4 ++- 8 files changed, 102 insertions(+), 31 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index d49d307b..87ba0678 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -290,6 +290,18 @@ class functional(simulation): for port in self.readwrite_ports: self.stim.gen_pwl("WEB{}".format(port), self.cycle_times , self.web_values[port], self.period, self.slew, 0.05) + # Generate wmask bits + for port in self.write_ports: + self.sf.write("\n* Generation of wmask signals\n") + if (self.write_size != self.word_size): + num_wmask = int(self.word_size / self.write_size) + for bit in range(num_wmask): + sig_name = "WMASK{0}_{1} ".format(port, bit) + self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[port][bit], self.period, + self.slew, 0.05) + # self.stim.gen_pwl(sig_name, self.cycle_times, self.wmask_values[port][bit], self.period, + # self.slew, 0.05) + # Generate CLK signals for port in self.all_ports: self.stim.gen_pulse(sig_name="{0}{1}".format(tech.spice["clk"], port), diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 5b34ce01..4dee96df 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -79,6 +79,7 @@ class simulation(): # Three dimensional list to handle each addr and data bits for wach port over the number of checks self.addr_values = [[[] for bit in range(self.addr_size)] for port in self.all_ports] self.data_values = [[[] for bit in range(self.word_size)] for port in self.write_ports] + self.wmask_values = [[[] for bit in range(self.num_wmask)] for port in self.write_ports] # For generating comments in SPICE stimulus self.cycle_comments = [] @@ -130,6 +131,20 @@ class simulation(): else: debug.error("Non-binary address string",1) bit -= 1 + + def add_wmask(self, wmask, port): + """ Add the array of address values """ + debug.check(len(wmask) == self.num_wmask, "Invalid wmask size.") + + bit = self.addr_size - 1 + for c in wmask: + if c == "0": + self.wmask_values[port][bit].append(0) + elif c == "1": + self.wmask_values[port][bit].append(1) + else: + debug.error("Non-binary address string", 1) + bit -= 1 def add_write(self, comment, address, data, port): """ Add the control values for a write cycle. """ @@ -281,13 +296,14 @@ class simulation(): for port in range(total_ports): if (port in read_index) and (port in write_index): pin_names.append("WEB{0}".format(port)) + + for port in range(total_ports): + pin_names.append("{0}{1}".format(tech.spice["clk"], port)) + if (self.write_size != self.word_size): num_wmask = int(self.word_size/self.write_size) for bit in range(num_wmask): pin_names.append("WMASK{0}_{1}".format(port,bit)) - - for port in range(total_ports): - pin_names.append("{0}{1}".format(tech.spice["clk"], port)) for read_output in read_index: for i in range(dbits): diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index c0f14a93..f62c9f8a 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -30,6 +30,8 @@ class bank(design.design): self.sram_config = sram_config sram_config.set_local_config(self) + if (self.word_size != self.write_size): + self.num_wmask = int(self.word_size/self.write_size) if name == "": name = "bank_{0}_{1}".format(self.word_size, self.num_words) @@ -98,6 +100,11 @@ class bank(design.design): self.add_pin("p_en_bar{0}".format(port), "INPUT") for port in self.write_ports: self.add_pin("w_en{0}".format(port), "INPUT") + if (self.word_size != self.write_size): + for bit in range(self.num_wmask): + self.add_pin("bank_wmask{0}_{1}".format(port,bit),"INPUT") + # for bit in range(self.num_wmask): + # self.add_pin("wdriver_sel{0}_{1}".format(port, bit),"INOUT") for port in self.all_ports: self.add_pin("wl_en{0}".format(port), "INPUT") self.add_pin("vdd","POWER") @@ -406,6 +413,11 @@ class bank(design.design): temp.append("p_en_bar{0}".format(port)) if port in self.write_ports: temp.append("w_en{0}".format(port)) + if (self.word_size != self.write_size): + for bit in range(self.num_wmask): + temp.append("bank_wmask{0}_{1}".format(port, bit)) + # for bit in range(self.num_wmask): + # temp.append("wdriver_sel_{0}_{1}".format(port, bit)) temp.extend(["vdd","gnd"]) self.connect_inst(temp) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 7f77652e..413922dd 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -21,7 +21,8 @@ class port_data(design.design): sram_config.set_local_config(self) self.port = port - self.num_wmask = int(self.word_size/self.write_size) + if (self.word_size != self.write_size): + self.num_wmask = int(self.word_size/self.write_size) if name == "": name = "port_data_{0}".format(self.port) @@ -96,6 +97,11 @@ class port_data(design.design): self.add_pin("p_en_bar", "INPUT") if self.port in self.write_ports: self.add_pin("w_en", "INPUT") + if (self.word_size != self.write_size): + for bit in range(self.num_wmask): + self.add_pin("bank_wmask_{}".format(bit),"INPUT") + # for bit in range(self.num_wmask): + # self.add_pin("wdriver_sel_{}".format(bit), "INOUT") self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") @@ -168,7 +174,8 @@ class port_data(design.design): if self.port in self.write_ports: self.write_driver_array = factory.create(module_type="write_driver_array", columns=self.num_cols, - word_size=self.word_size) + word_size=self.word_size, + write_size=self.write_size) self.add_mod(self.write_driver_array) if (self.word_size != self.write_size): self.write_mask_and_array = factory.create(module_type="write_mask_and_array", @@ -282,9 +289,8 @@ class port_data(design.design): mod=self.write_driver_array) temp = [] - m - for bit in range(self.word_size): - temp.append("din_{}".format(bit)) + for bit in range(self.word_size): + temp.append("din_{}".format(bit)) for bit in range(self.word_size): if (self.words_per_row == 1): @@ -293,7 +299,16 @@ class port_data(design.design): else: temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) - temp.extend(["w_en", "vdd", "gnd"]) + + if (self.write_size != self.word_size): + i = 0 + for bit in range(0,self.word_size,self.write_size): + for x in range(self.write_size): + temp.append("wdriver_sel_{}".format(i)) + i+=1 + else: + temp.append("w_en") + temp.extend(["vdd", "gnd"]) self.connect_inst(temp) @@ -304,8 +319,11 @@ class port_data(design.design): temp = [] for bit in range(self.num_wmask): - temp.append("write_mask_{}".format(bit)) - temp.extend(["w_en", "vdd", "gnd"]) + temp.append("bank_wmask_{}".format(bit)) + temp.extend(["w_en"]) + for bit in range(self.num_wmask): + temp.append("wdriver_sel_{}".format(bit)) + temp.extend(["vdd", "gnd"]) self.connect_inst(temp) diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 599c4cd0..0a9f0f6b 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -19,7 +19,7 @@ class write_driver_array(design.design): Dynamically generated write driver array of all bitlines. """ - def __init__(self, name, columns, word_size): + def __init__(self, name, columns, word_size,write_size): design.design.__init__(self, name) debug.info(1, "Creating {0}".format(self.name)) self.add_comment("columns: {0}".format(columns)) @@ -27,6 +27,7 @@ class write_driver_array(design.design): self.columns = columns self.word_size = word_size + self.write_size = write_size self.words_per_row = int(columns / word_size) self.create_netlist() @@ -59,7 +60,11 @@ class write_driver_array(design.design): for i in range(self.word_size): self.add_pin("bl_{0}".format(i)) self.add_pin("br_{0}".format(i)) - self.add_pin("en") + if self.word_size != self.write_size: + for i in range(self.word_size): + self.add_pin("en_{}".format(i)) + else: + self.add_pin("en") self.add_pin("vdd") self.add_pin("gnd") @@ -79,10 +84,16 @@ class write_driver_array(design.design): self.driver_insts[index]=self.add_inst(name=name, mod=self.driver) - self.connect_inst(["data_{0}".format(index), - "bl_{0}".format(index), - "br_{0}".format(index), - "en", "vdd", "gnd"]) + if self.word_size != self.write_size: + self.connect_inst(["data_{0}".format(index), + "bl_{0}".format(index), + "br_{0}".format(index), + "en_{0}".format(index), "vdd", "gnd"]) + else: + self.connect_inst(["data_{0}".format(index), + "bl_{0}".format(index), + "br_{0}".format(index), + "en", "vdd", "gnd"]) def place_write_array(self): diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index f17f458c..04e5e21b 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -60,10 +60,12 @@ class write_mask_and_array(design.design): def add_pins(self): for bit in range(self.num_wmask): - self.add_pin("wdriver_sel_{}".format(bit)) - self.add_pin("en") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("wmask_in_{}".format(bit),"INPUT") + self.add_pin("en", "INPUT") + for bit in range(self.num_wmask): + self.add_pin("wmask_out_{}".format(bit),"OUTPUT") + self.add_pin("vdd","POWER") + self.add_pin("gnd","GROUND") def add_modules(self): self.wmask = factory.create(module_type="dff_buf") @@ -94,9 +96,9 @@ class write_mask_and_array(design.design): name = "and2_{}".format(bit) self.and2_insts[bit] = self.add_inst(name=name, mod=self.and2) - self.connect_inst(["bank_wmask_{}".format(bit), + self.connect_inst(["wmask_in_{}".format(bit), "en", - "wdriver_sel_{}".format(bit), + "wmask_out_{}".format(bit), "vdd", "gnd"]) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 6295f587..66dcdb0f 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -357,6 +357,11 @@ class sram_base(design, verilog, lef): temp.append("p_en_bar{0}".format(port)) for port in self.write_ports: temp.append("w_en{0}".format(port)) + if (self.word_size != self.write_size): + for bit in range(self.num_masks): + temp.append("bank_wmask{}[{}]".format(port, bit)) + # for bit in range(self.num_masks): + # temp.append("wdriver_sel{}[{}]".format(port, bit)) for port in self.all_ports: temp.append("wl_en{0}".format(port)) temp.extend(["vdd", "gnd"]) @@ -499,8 +504,6 @@ class sram_base(design, verilog, lef): if port in self.readwrite_ports: temp.append("web{}".format(port)) temp.append("clk{}".format(port)) - # if port in self.write_ports: - # temp.append("wmask{}".format(port)) # for port in self.all_ports: # self.add_pin("csb{}".format(port), "INPUT") @@ -508,11 +511,6 @@ class sram_base(design, verilog, lef): # self.add_pin("web{}".format(port), "INPUT") # for port in self.all_ports: # self.add_pin("clk{}".format(port), "INPUT") - # # add the optional write mask pins - # if self.word_size != self.write_size: - # for port in self.write_ports: - # print("write_ports", port) - # self.add_pin("wmask{0}".format(port), "INPUT") # Outputs if port in self.read_ports: diff --git a/compiler/tests/22_sram_wmask_func_test.py b/compiler/tests/22_sram_wmask_func_test.py index db239ccf..f76fdeef 100755 --- a/compiler/tests/22_sram_wmask_func_test.py +++ b/compiler/tests/22_sram_wmask_func_test.py @@ -15,7 +15,7 @@ from globals import OPTS from sram_factory import factory import debug -@unittest.skip("SKIPPING sram_wmask_func_test") +#@unittest.skip("SKIPPING sram_wmask_func_test") class sram_wmask_func_test(openram_test): def runTest(self): @@ -34,6 +34,8 @@ class sram_wmask_func_test(openram_test): num_words=16, write_size=4, num_banks=1) + c.words_per_row=1 + c.recompute_sizes_once() debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} bit writes, {} banks".format(c.word_size, c.num_words, c.words_per_row, From 0a5461201a530e04fd6cd504700ff74324903ece Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 19 Jul 2019 14:58:37 -0700 Subject: [PATCH 118/234] Change num_wmask to num_wmasks and write_size = None not word_size if wmask not used. --- compiler/base/verilog.py | 40 ++++++++++------------- compiler/characterizer/functional.py | 25 +++++++------- compiler/characterizer/simulation.py | 18 +++++----- compiler/modules/bank.py | 23 +++++-------- compiler/modules/control_logic.py | 9 +---- compiler/modules/multibank.py | 2 +- compiler/modules/port_data.py | 23 +++++++------ compiler/modules/write_driver_array.py | 6 ++-- compiler/modules/write_mask_and_array.py | 8 ++--- compiler/sram/sram_1bank.py | 8 ++--- compiler/sram/sram_base.py | 38 ++++++++++----------- compiler/sram/sram_config.py | 27 +-------------- compiler/tests/22_sram_wmask_func_test.py | 2 +- 13 files changed, 91 insertions(+), 138 deletions(-) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index c4d4ee00..a11ffd0a 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -18,15 +18,11 @@ class verilog: def verilog_write(self,verilog_name): """ Write a behavioral Verilog model. """ self.vf = open(verilog_name, "w") - # Determine if optional write mask is used - self.wmask_enabled = False - if self.word_size != self.write_size: - self.wmask_enabled = True self.vf.write("// OpenRAM SRAM model\n") self.vf.write("// Words: {0}\n".format(self.num_words)) self.vf.write("// Word size: {0}\n".format(self.word_size)) - if self.wmask_enabled: + if self.write_size is not None: self.vf.write("// Write size: {0}\n\n".format(self.write_size)) else: self.vf.write("\n") @@ -41,12 +37,12 @@ class verilog: self.vf.write("// Port {0}: W\n".format(port)) if port in self.readwrite_ports: self.vf.write(" clk{0},csb{0},web{0},".format(port)) - if self.wmask_enabled: + if self.write_size is not None: self.vf.write("wmask{},".format(port)) self.vf.write("ADDR{0},DIN{0},DOUT{0}".format(port)) elif port in self.write_ports: self.vf.write(" clk{0},csb{0},".format(port)) - if self.wmask_enabled: + if self.write_size is not None: self.vf.write("wmask{},".format(port)) self.vf.write("ADDR{0},DIN{0}".format(port)) elif port in self.read_ports: @@ -56,11 +52,11 @@ class verilog: self.vf.write(",\n") self.vf.write("\n );\n\n") - if self.wmask_enabled: - self.num_wmask = int(self.word_size/self.write_size) - self.vf.write(" parameter NUM_WMASK = {0} ;\n".format(self.num_wmask)) + if self.write_size is not None: + self.num_wmasks = int(self.word_size/self.write_size) + self.vf.write(" parameter NUM_WMASKS = {0} ;\n".format(self.num_wmasks)) self.vf.write(" parameter DATA_WIDTH = {0} ;\n".format(self.word_size)) - self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_size)) + self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_sizeaddr_size)) self.vf.write(" parameter RAM_DEPTH = 1 << ADDR_WIDTH;\n") self.vf.write(" // FIXME: This delay is arbitrary.\n") self.vf.write(" parameter DELAY = 3 ;\n") @@ -103,8 +99,8 @@ class verilog: if port in self.readwrite_ports: self.vf.write(" reg web{0}_reg;\n".format(port)) if port in self.write_ports: - if self.wmask_enabled: - self.vf.write(" reg [NUM_WMASK-1:0] wmask{0}_reg;\n".format(port)) + if self.write_size is not None: + self.vf.write(" reg [NUM_WMASKS-1:0] wmask{0}_reg;\n".format(port)) self.vf.write(" reg [ADDR_WIDTH-1:0] ADDR{0}_reg;\n".format(port)) if port in self.write_ports: self.vf.write(" reg [DATA_WIDTH-1:0] DIN{0}_reg;\n".format(port)) @@ -123,7 +119,7 @@ class verilog: if port in self.readwrite_ports: self.vf.write(" web{0}_reg = web{0};\n".format(port)) if port in self.write_ports: - if self.wmask_enabled: + if self.write_size is not None: self.vf.write(" wmask{0}_reg = wmask{0};\n".format(port)) self.vf.write(" ADDR{0}_reg = ADDR{0};\n".format(port)) if port in self.write_ports: @@ -138,13 +134,13 @@ class verilog: self.vf.write(" $display($time,\" Reading %m ADDR{0}=%b DOUT{0}=%b\",ADDR{0}_reg,mem[ADDR{0}_reg]);\n".format(port)) if port in self.readwrite_ports: self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port)) - if self.wmask_enabled: + if self.write_size is not None: self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b wmask{0}=%b\",ADDR{0}_reg,DIN{0}_reg,wmask{0}_reg);\n".format(port)) else: self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b\",ADDR{0}_reg,DIN{0}_reg);\n".format(port)) elif port in self.write_ports: self.vf.write(" if ( !csb{0}_reg )\n".format(port)) - if self.wmask_enabled: + if self.write_size is not None: self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b wmask{0}=%b\",ADDR{0}_reg,DIN{0}_reg,wmask{0}_reg);\n".format(port)) else: self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b\",ADDR{0}_reg,DIN{0}_reg);\n".format(port)) @@ -160,8 +156,8 @@ class verilog: self.vf.write(" input csb{0}; // active low chip select\n".format(port)) if port in self.readwrite_ports: self.vf.write(" input web{0}; // active low write control\n".format(port)) - if (self.wmask_enabled): - self.vf.write(" input [NUM_WMASK-1:0] wmask{0}; // write mask\n".format(port)) + if self.write_size is not None: + self.vf.write(" input [NUM_WMASKS-1:0] wmask{0}; // write mask\n".format(port)) self.vf.write(" input [ADDR_WIDTH-1:0] ADDR{0};\n".format(port)) if port in self.write_ports: self.vf.write(" input [DATA_WIDTH-1:0] DIN{0};\n".format(port)) @@ -179,18 +175,18 @@ class verilog: self.vf.write(" always @ (negedge clk{0})\n".format(port)) self.vf.write(" begin : MEM_WRITE{0}\n".format(port)) if port in self.readwrite_ports: - if self.wmask_enabled: + if self.write_size is not None: self.vf.write(" if ( !csb{0}_reg && !web{0}_reg ) begin\n".format(port)) else: self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port)) else: - if self.wmask_enabled: + if self.write_size is not None: self.vf.write(" if (!csb{0}_reg) begin\n".format(port)) else: self.vf.write(" if (!csb{0}_reg)\n".format(port)) - if self.wmask_enabled: - for mask in range(0,self.num_wmask): + if self.write_size is not None: + for mask in range(0,self.num_wmasks): lower = mask * self.write_size upper = lower + self.write_size-1 self.vf.write(" if (wmask{0}_reg[{1}])\n".format(port,mask)) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 87ba0678..8389fdea 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -32,6 +32,11 @@ class functional(simulation): if OPTS.is_unit_test: random.seed(12345) + if self.write_size is not None: + self.num_wmasks = int(self.word_size / self.write_size) + else: + self.num_wmasks = 0 + self.set_corner(corner) self.set_spice_constants() #self.set_feasible_period(sram, spfile, corner) @@ -46,13 +51,10 @@ class functional(simulation): self.read_check = [] def initilize_wmask(self): - self.wmask = [None]*self.num_wmask - self.num_wmask = int(self.word_size/self.write_size) - self.wmask_enabled = False - if self.word_size !=self.write_size: - self.wmask_enabled = True + self.wmask = [None]*self.num_wmasks + if self.write_size is not None: # initialize wmask to 1 - for bit in range(self.num_wmask): + for bit in range(self.num_wmasks): self.wmask[bit] = 1 # if bit == 0: # self.wmask[self.num_wmask-1 - bit] = 1 @@ -189,8 +191,8 @@ class functional(simulation): return(1, "SUCCESS") def gen_wmask(self): - wmask_bits = [None]*self.num_wmask - for bit in range(self.num_wmask): + wmask_bits = [None]*self.num_wmasks + for bit in range(self.num_wmasks): rand = random.randint(0, 1) wmask_bits[bit] = rand return wmask_bits @@ -292,10 +294,9 @@ class functional(simulation): # Generate wmask bits for port in self.write_ports: - self.sf.write("\n* Generation of wmask signals\n") - if (self.write_size != self.word_size): - num_wmask = int(self.word_size / self.write_size) - for bit in range(num_wmask): + self.sf.write("\n* Generation of wmask sibfssgnals\n") + if self.write_size is not None: + for bit in range(self.num_wmasks): sig_name = "WMASK{0}_{1} ".format(port, bit) self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[port][bit], self.period, self.slew, 0.05) diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 4dee96df..c75783b3 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -34,10 +34,11 @@ class simulation(): self.readwrite_ports = self.sram.readwrite_ports self.read_ports = self.sram.read_ports self.write_ports = self.sram.write_ports - self.num_wmask = int(self.word_size/self.write_size) - self.wmask_enabled = False - if self.word_size !=self.write_size: - self.wmask_enabled = True + if self.write_size is not None: + self.num_wmasks = int(self.word_size/self.write_size) + else: + self.num_wmasks = 0 + def set_corner(self,corner): """ Set the corner values """ @@ -79,7 +80,7 @@ class simulation(): # Three dimensional list to handle each addr and data bits for wach port over the number of checks self.addr_values = [[[] for bit in range(self.addr_size)] for port in self.all_ports] self.data_values = [[[] for bit in range(self.word_size)] for port in self.write_ports] - self.wmask_values = [[[] for bit in range(self.num_wmask)] for port in self.write_ports] + self.wmask_values = [[[] for bit in range(self.num_wmasks)] for port in self.write_ports] # For generating comments in SPICE stimulus self.cycle_comments = [] @@ -248,7 +249,7 @@ class simulation(): t_current, t_current+self.period) elif op == "write": - if (self.wmask_enabled): + if self.write_size is not None: comment = "\tWriting {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word, addr, wmask, @@ -300,9 +301,8 @@ class simulation(): for port in range(total_ports): pin_names.append("{0}{1}".format(tech.spice["clk"], port)) - if (self.write_size != self.word_size): - num_wmask = int(self.word_size/self.write_size) - for bit in range(num_wmask): + if self.write_size is not None: + for bit in range(self.num_wmasks): pin_names.append("WMASK{0}_{1}".format(port,bit)) for read_output in read_index: diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index f62c9f8a..f4f1cabe 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -30,8 +30,10 @@ class bank(design.design): self.sram_config = sram_config sram_config.set_local_config(self) - if (self.word_size != self.write_size): - self.num_wmask = int(self.word_size/self.write_size) + if self.write_size is not None: + self.num_wmasks = int(self.word_size/self.write_size) + else: + self.num_wmasks = 0 if name == "": name = "bank_{0}_{1}".format(self.word_size, self.num_words) @@ -82,9 +84,6 @@ class bank(design.design): for port in self.write_ports: for bit in range(self.word_size): self.add_pin("din{0}_{1}".format(port,bit),"IN") - # if (self.word_size != self.write_size): - # for bit in range(self.word_size): - # self.add_pin() for port in self.all_ports: for bit in range(self.addr_size): self.add_pin("addr{0}_{1}".format(port,bit),"INPUT") @@ -100,11 +99,8 @@ class bank(design.design): self.add_pin("p_en_bar{0}".format(port), "INPUT") for port in self.write_ports: self.add_pin("w_en{0}".format(port), "INPUT") - if (self.word_size != self.write_size): - for bit in range(self.num_wmask): - self.add_pin("bank_wmask{0}_{1}".format(port,bit),"INPUT") - # for bit in range(self.num_wmask): - # self.add_pin("wdriver_sel{0}_{1}".format(port, bit),"INOUT") + for bit in range(self.num_wmasks): + self.add_pin("bank_wmask{0}_{1}".format(port,bit),"INPUT") for port in self.all_ports: self.add_pin("wl_en{0}".format(port), "INPUT") self.add_pin("vdd","POWER") @@ -413,11 +409,8 @@ class bank(design.design): temp.append("p_en_bar{0}".format(port)) if port in self.write_ports: temp.append("w_en{0}".format(port)) - if (self.word_size != self.write_size): - for bit in range(self.num_wmask): - temp.append("bank_wmask{0}_{1}".format(port, bit)) - # for bit in range(self.num_wmask): - # temp.append("wdriver_sel_{0}_{1}".format(port, bit)) + for bit in range(self.num_wmasks): + temp.append("bank_wmask{0}_{1}".format(port, bit)) temp.extend(["vdd","gnd"]) self.connect_inst(temp) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index e2138396..fd7a6b42 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -21,7 +21,7 @@ class control_logic(design.design): Dynamically generated Control logic for the total SRAM circuit. """ - def __init__(self, num_rows, words_per_row, word_size, write_size, sram=None, port_type="rw", name=""): + def __init__(self, num_rows, words_per_row, word_size, sram=None, port_type="rw", name=""): """ Constructor """ name = "control_logic_" + port_type design.design.__init__(self, name) @@ -35,7 +35,6 @@ class control_logic(design.design): self.words_per_row = words_per_row self.word_size = word_size self.port_type = port_type - self.write_size = write_size self.num_cols = word_size*words_per_row self.num_words = num_rows*words_per_row @@ -316,14 +315,8 @@ class control_logic(design.design): else: self.input_list = ["csb"] - # if self.word_size != self.write_size: - # self.input_list = ["wmask"] - if self.port_type == "rw": self.dff_output_list = ["cs_bar", "cs", "we_bar", "we"] - # if self.word_size != self.write_size: - # self.dff_output_list.append("wm_bar") - # self.dff_output_list.append("wm") else: self.dff_output_list = ["cs_bar", "cs"] diff --git a/compiler/modules/multibank.py b/compiler/modules/multibank.py index e99dab93..fd061273 100644 --- a/compiler/modules/multibank.py +++ b/compiler/modules/multibank.py @@ -187,7 +187,7 @@ class multibank(design.design): words_per_row=self.words_per_row) self.add_mod(self.sense_amp_array) - if (self.write_size != self.word_size): + if self.write_size is not None: self.write_mask_driver_array = self.mod_write_mask_driver_array(columns=self.num_cols, word_size=self.word_size, write_size=self.write_size) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 413922dd..0b2fca51 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -21,8 +21,10 @@ class port_data(design.design): sram_config.set_local_config(self) self.port = port - if (self.word_size != self.write_size): - self.num_wmask = int(self.word_size/self.write_size) + if self.write_size is not None: + self.num_wmasks = int(self.word_size/self.write_size) + else: + self.num_wmasks = 0 if name == "": name = "port_data_{0}".format(self.port) @@ -55,7 +57,7 @@ class port_data(design.design): if self.write_driver_array: self.create_write_driver_array() - if (self.word_size != self.write_size): + if self.write_size is not None: self.create_write_mask_and_array() else: self.write_mask_and_array_inst = None @@ -97,11 +99,8 @@ class port_data(design.design): self.add_pin("p_en_bar", "INPUT") if self.port in self.write_ports: self.add_pin("w_en", "INPUT") - if (self.word_size != self.write_size): - for bit in range(self.num_wmask): - self.add_pin("bank_wmask_{}".format(bit),"INPUT") - # for bit in range(self.num_wmask): - # self.add_pin("wdriver_sel_{}".format(bit), "INOUT") + for bit in range(self.num_wmasks): + self.add_pin("bank_wmask_{}".format(bit),"INPUT") self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") @@ -177,7 +176,7 @@ class port_data(design.design): word_size=self.word_size, write_size=self.write_size) self.add_mod(self.write_driver_array) - if (self.word_size != self.write_size): + if self.write_size is not None: self.write_mask_and_array = factory.create(module_type="write_mask_and_array", columns=self.num_cols, word_size=self.word_size, @@ -300,7 +299,7 @@ class port_data(design.design): temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) - if (self.write_size != self.word_size): + if self.write_size is not None: i = 0 for bit in range(0,self.word_size,self.write_size): for x in range(self.write_size): @@ -318,10 +317,10 @@ class port_data(design.design): mod=self.write_mask_and_array) temp = [] - for bit in range(self.num_wmask): + for bit in range(self.num_wmasks): temp.append("bank_wmask_{}".format(bit)) temp.extend(["w_en"]) - for bit in range(self.num_wmask): + for bit in range(self.num_wmasks): temp.append("wdriver_sel_{}".format(bit)) temp.extend(["vdd", "gnd"]) self.connect_inst(temp) diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 0a9f0f6b..9e0f992f 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -19,7 +19,7 @@ class write_driver_array(design.design): Dynamically generated write driver array of all bitlines. """ - def __init__(self, name, columns, word_size,write_size): + def __init__(self, name, columns, word_size,write_size=None): design.design.__init__(self, name) debug.info(1, "Creating {0}".format(self.name)) self.add_comment("columns: {0}".format(columns)) @@ -60,7 +60,7 @@ class write_driver_array(design.design): for i in range(self.word_size): self.add_pin("bl_{0}".format(i)) self.add_pin("br_{0}".format(i)) - if self.word_size != self.write_size: + if self.write_size != None: for i in range(self.word_size): self.add_pin("en_{}".format(i)) else: @@ -84,7 +84,7 @@ class write_driver_array(design.design): self.driver_insts[index]=self.add_inst(name=name, mod=self.driver) - if self.word_size != self.write_size: + if self.write_size != None: self.connect_inst(["data_{0}".format(index), "bl_{0}".format(index), "br_{0}".format(index), diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 04e5e21b..9a9a8f12 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -31,7 +31,7 @@ class write_mask_and_array(design.design): self.word_size = word_size self.write_size = write_size self.words_per_row = int(columns / word_size) - self.num_wmask = int(word_size / write_size) + self.num_wmasks = int(word_size / write_size) self.create_netlist() # if not OPTS.netlist_only: @@ -59,10 +59,10 @@ class write_mask_and_array(design.design): # self.DRC_LVS() def add_pins(self): - for bit in range(self.num_wmask): + for bit in range(self.num_wmasks): self.add_pin("wmask_in_{}".format(bit),"INPUT") self.add_pin("en", "INPUT") - for bit in range(self.num_wmask): + for bit in range(self.num_wmasks): self.add_pin("wmask_out_{}".format(bit),"OUTPUT") self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") @@ -92,7 +92,7 @@ class write_mask_and_array(design.design): def create_and2_array(self): self.and2_insts = {} - for bit in range(self.num_wmask): + for bit in range(self.num_wmasks): name = "and2_{}".format(bit) self.and2_insts[bit] = self.add_inst(name=name, mod=self.and2) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 1d749e16..0ee0bb4f 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -46,7 +46,7 @@ class sram_1bank(sram_base): self.data_dff_insts = self.create_data_dff() - if (self.write_size != self.word_size): + if self.write_size is not None: self.wmask_dff_insts = self.create_wmask_dff() @@ -126,7 +126,7 @@ class sram_1bank(sram_base): self.data_dff_insts[port].place(data_pos[port]) # Add the write mask flops to the left of the din flops. - if (self.write_size != self.word_size): + if self.write_size is not None: if port in self.write_ports: wmask_pos[port] = vector(self.bank.bank_array_ll.x - self.control_logic_insts[port].width, -max_gap_size - self.wmask_dff_insts[port].height) @@ -148,7 +148,7 @@ class sram_1bank(sram_base): self.data_dff_insts[port].place(data_pos[port], mirror="MX") # Add the write mask flops to the left of the din flops. - if (self.write_size != self.word_size): + if self.write_size is not None: if port in self.write_ports: wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, self.bank.height + max_gap_size + self.data_dff_insts[port].height) @@ -362,7 +362,7 @@ class sram_1bank(sram_base): #Data dffs and wmask dffs are only for writing so are not useful for evaluating read delay. for inst in self.data_dff_insts: self.graph_inst_exclude.add(inst) - if (self.write_size != self.word_size): + if self.write_size is not None: for inst in self.wmask_dff_insts: self.graph_inst_exclude.add(inst) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 66dcdb0f..7b7a77f0 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -34,13 +34,18 @@ class sram_base(design, verilog, lef): sram_config.set_local_config(self) self.bank_insts = [] - + + if self.write_size is not None: + self.num_wmasks = int(self.word_size/self.write_size) + else: + self.num_wmasks = 0 + #For logical effort delay calculations. self.all_mods_except_control_done = False def add_pins(self): """ Add pins for entire SRAM. """ - self.num_masks = int(self.word_size/self.write_size) + for port in self.write_ports: for bit in range(self.word_size): self.add_pin("DIN{0}[{1}]".format(port,bit),"INPUT") @@ -70,10 +75,9 @@ class sram_base(design, verilog, lef): for port in self.all_ports: self.add_pin("clk{}".format(port),"INPUT") # add the optional write mask pins - if self.word_size != self.write_size: - for port in self.write_ports: - for bit in range(self.num_masks): - self.add_pin("wmask{0}[{1}]".format(port,bit),"INPUT") + for port in self.write_ports: + for bit in range(self.num_wmasks): + self.add_pin("wmask{0}[{1}]".format(port,bit),"INPUT") for port in self.read_ports: for bit in range(self.word_size): self.add_pin("DOUT{0}[{1}]".format(port,bit),"OUTPUT") @@ -280,9 +284,8 @@ class sram_base(design, verilog, lef): self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size) self.add_mod(self.data_dff) - if (self.write_size != self.word_size): - num_wmask = int(self.word_size/self.write_size) - self.wmask_dff = dff_array(name="wmask_dff", rows=1, columns=num_wmask) + if self.write_size is not None: + self.wmask_dff = dff_array(name="wmask_dff", rows=1, columns=self.num_wmasks) self.add_mod(self.wmask_dff) @@ -312,23 +315,20 @@ class sram_base(design, verilog, lef): self.control_logic_rw = self.mod_control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, word_size=self.word_size, - write_size = self.write_size, - sram=self, + sram=self, port_type="rw") self.add_mod(self.control_logic_rw) if len(self.writeonly_ports)>0: self.control_logic_w = self.mod_control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, word_size=self.word_size, - write_size=self.write_size, - sram=self, + sram=self, port_type="w") self.add_mod(self.control_logic_w) if len(self.readonly_ports)>0: self.control_logic_r = self.mod_control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, word_size=self.word_size, - write_size=self.write_size, sram=self, port_type="r") self.add_mod(self.control_logic_r) @@ -357,11 +357,8 @@ class sram_base(design, verilog, lef): temp.append("p_en_bar{0}".format(port)) for port in self.write_ports: temp.append("w_en{0}".format(port)) - if (self.word_size != self.write_size): - for bit in range(self.num_masks): - temp.append("bank_wmask{}[{}]".format(port, bit)) - # for bit in range(self.num_masks): - # temp.append("wdriver_sel{}[{}]".format(port, bit)) + for bit in range(self.num_wmasks): + temp.append("bank_wmask{}[{}]".format(port, bit)) for port in self.all_ports: temp.append("wl_en{0}".format(port)) temp.extend(["vdd", "gnd"]) @@ -463,7 +460,6 @@ class sram_base(design, verilog, lef): def create_wmask_dff(self): """ Add and place all wmask flops """ - num_wmask = int(self.word_size/self.write_size) insts = [] for port in self.all_ports: if port in self.write_ports: @@ -476,7 +472,7 @@ class sram_base(design, verilog, lef): # inputs, outputs/output/bar inputs = [] outputs = [] - for bit in range(num_wmask): + for bit in range(self.num_wmasks): inputs.append("wmask{}[{}]".format(port, bit)) outputs.append("bank_wmask{}[{}]".format(port, bit)) diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index 80be7939..df9ae677 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -23,8 +23,6 @@ class sram_config: # This will get over-written when we determine the organization self.words_per_row = words_per_row - if self.write_size == None: - self.write_size = self.word_size self.compute_sizes() @@ -64,26 +62,7 @@ class sram_config: self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row) debug.info(1,"Words per row: {}".format(self.words_per_row)) - self.recompute_sizes_once() - - def recompute_sizes_once(self): - """ - Calculate the auxiliary values assuming fixed number of words per row. - """ - - # If the banks changed - self.num_words_per_bank = self.num_words / self.num_banks - self.num_bits_per_bank = self.word_size * self.num_words_per_bank - - # Fix the number of columns and rows - self.num_cols = int(self.words_per_row * self.word_size) - self.num_rows = int(self.num_words_per_bank / self.words_per_row) - - # Compute the address and bank sizes - self.row_addr_size = int(log(self.num_rows, 2)) - self.col_addr_size = int(log(self.words_per_row, 2)) - self.bank_addr_size = self.col_addr_size + self.row_addr_size - self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2)) + self.recompute_sizes() def recompute_sizes(self): """ @@ -92,10 +71,6 @@ class sram_config: SRAM for testing. """ - # This function is ran without the write mask option, but word_size can be redefined - # which makes the tests think there is a write mask. - self.write_size = self.word_size - # If the banks changed self.num_words_per_bank = self.num_words/self.num_banks self.num_bits_per_bank = self.word_size*self.num_words_per_bank diff --git a/compiler/tests/22_sram_wmask_func_test.py b/compiler/tests/22_sram_wmask_func_test.py index f76fdeef..9a7b04fd 100755 --- a/compiler/tests/22_sram_wmask_func_test.py +++ b/compiler/tests/22_sram_wmask_func_test.py @@ -35,7 +35,7 @@ class sram_wmask_func_test(openram_test): write_size=4, num_banks=1) c.words_per_row=1 - c.recompute_sizes_once() + c.recompute_sizes() debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} bit writes, {} banks".format(c.word_size, c.num_words, c.words_per_row, From a69d35b50adc969f72f0f0ab591f18e006f6b4e2 Mon Sep 17 00:00:00 2001 From: jsowash Date: Sun, 21 Jul 2019 15:53:05 -0700 Subject: [PATCH 119/234] Removed write_size from parameters. --- compiler/tests/16_control_logic_multiport_test.py | 6 +++--- compiler/tests/16_control_logic_test.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/tests/16_control_logic_multiport_test.py b/compiler/tests/16_control_logic_multiport_test.py index 3ad898b1..66c34d24 100755 --- a/compiler/tests/16_control_logic_multiport_test.py +++ b/compiler/tests/16_control_logic_multiport_test.py @@ -34,19 +34,19 @@ class control_logic_test(openram_test): OPTS.num_r_ports = 1 debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, write_size=8, port_type="rw") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="rw") self.local_check(a) # OPTS.num_rw_ports = 0 # OPTS.num_w_ports = 1 debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, write_size=8, port_type="w") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="w") self.local_check(a) # OPTS.num_w_ports = 0 # OPTS.num_r_ports = 1 debug.info(1, "Testing sample for control_logic for multiport, only read control logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, write_size=8, port_type="r") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=8, port_type="r") self.local_check(a) globals.end_openram() diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index 13e6c46c..2be0bf0f 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -24,7 +24,7 @@ class control_logic_test(openram_test): # check control logic for single port debug.info(1, "Testing sample for control_logic") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32, write_size=32) + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32) self.local_check(a) # run the test from the command line From 72e16f8fe6335c846a139c799ed7853d25e22b7d Mon Sep 17 00:00:00 2001 From: jsowash Date: Mon, 22 Jul 2019 11:19:14 -0700 Subject: [PATCH 120/234] Added ability to do partial writes to addresses that have already been written to. --- compiler/characterizer/functional.py | 110 ++++++++++++++++++++------- compiler/characterizer/simulation.py | 41 ++++++---- 2 files changed, 108 insertions(+), 43 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 8389fdea..b1fbaada 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -42,7 +42,7 @@ class functional(simulation): #self.set_feasible_period(sram, spfile, corner) self.set_stimulus_variables() self.create_signal_names() - self.initilize_wmask() + self.initialize_wmask() # Number of checks can be changed self.num_cycles = 2 @@ -50,16 +50,13 @@ class functional(simulation): self.write_check = [] self.read_check = [] - def initilize_wmask(self): - self.wmask = [None]*self.num_wmasks + def initialize_wmask(self): + #self.wmask = [None]*self.num_wmasks + self.wmask = "" if self.write_size is not None: - # initialize wmask to 1 + # initialize all wmask bits to 1 for bit in range(self.num_wmasks): - self.wmask[bit] = 1 - # if bit == 0: - # self.wmask[self.num_wmask-1 - bit] = 1 - # else: - # self.wmask[self.num_wmask-1 - bit] = 0 + self.wmask += "1" def run(self, feasible_period=None): if feasible_period: #period defaults to tech.py feasible period otherwise. @@ -80,8 +77,12 @@ class functional(simulation): return self.check_stim_results() def write_random_memory_sequence(self): - rw_ops = ["noop", "write", "read"] - w_ops = ["noop", "write"] + if self.write_size is not None: + rw_ops = ["noop", "write", "partial_write", "read"] + w_ops = ["noop", "write", "partial_write"] + else: + rw_ops = ["noop", "write", "read"] + w_ops = ["noop", "write"] r_ops = ["noop", "read"] rw_read_din_data = "0"*self.word_size check = 0 @@ -129,16 +130,45 @@ class functional(simulation): elif op == "write": addr = self.gen_addr() word = self.gen_data() - # wmask = self.gen_wmask() # two ports cannot write to the same address if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port) else: - # comment = self.gen_cycle_comment("write", word, addr, port, wmask, self.t_current) comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current) self.add_write_one_port(comment, addr, word, port) self.stored_words[addr] = word w_addrs.append(addr) + elif op == "partial_write": + #write only to a word that's been written to + addr, old_word = self.get_data() + # rand = random.randint(0,len(w_addrs)-1) + # addr = w_addrs[rand] + word = self.gen_data() + wmask = self.gen_wmask() + new_word = word + for bit in range(len(wmask)): + # Remove the bits of the word that's been written to + if wmask[bit] == "0": + lower = bit * self.write_size + upper = lower + self.write_size - 1 + new_word = new_word[:lower] + old_word[lower:upper+1] + new_word[upper + 1:] + # if bit == self.num_wmask - 1: + # new_word = new_word[0:lower] + old_word[lower:upper+1] + # elif bit == 0: + # new_word = old_word[lower:upper + 1] + new_word[upper + 1:self.word_size] + # else: + # new_word = new_word[0:lower] + old_word[lower:upper+1] + new_word[upper+1:self.word_size] + + #wmask = wmask[:index] + "1" + wmask[index + 1:] + + # two ports cannot write to the same address + if addr in w_addrs: + self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port) + else: + comment = self.gen_cycle_comment("partial_write", word, addr, port, wmask, self.t_current) + self.add_partial_write_one_port(comment, addr, word, wmask, port) + self.stored_words[addr] = new_word + w_addrs.append(addr) else: (addr,word) = random.choice(list(self.stored_words.items())) # cannot read from an address that is currently being written to @@ -191,26 +221,48 @@ class functional(simulation): return(1, "SUCCESS") def gen_wmask(self): - wmask_bits = [None]*self.num_wmasks + # wmask_bits = [None]*self.num_wmasks + # for bit in range(self.num_wmasks): + # rand = random.randint(0,1) + # wmask_bits[bit] = rand + wmask = "" for bit in range(self.num_wmasks): rand = random.randint(0, 1) - wmask_bits[bit] = rand - return wmask_bits + wmask += str(rand) + # prevent the wmask from having all bits on + all_zeroes = True + all_ones = True + for bit in range(self.num_wmasks): + if wmask[bit]=="0": + all_ones = False + elif wmask[bit]=="1": + all_zeroes = False + if all_zeroes: + index = random.randint(0, self.num_wmasks - 1) + wmask = wmask[:index] + "1" + wmask[index + 1:] + elif all_ones: + index = random.randint(0, self.num_wmasks - 1) + wmask = wmask[:index] + "0" + wmask[index + 1:] + return wmask + + + # prevent the wmask from having all bits off - # def gen_data(self): - # """ Generates a random word to write. """ - # rand = random.randint(0,(2**self.word_size)-1) - # data_bits = self.convert_to_bin(rand,False) - # return data_bits def gen_data(self): - """ Generates a random word, either all 0 or all 1's, to write. """ - rand = random.randint(0,1) - bits = [] - for bit in range(self.word_size): - bits.append(rand) - data_bits = ''.join(map(str,bits)) + """ Generates a random word to write. """ + rand = random.randint(0,(2**self.word_size)-1) + data_bits = self.convert_to_bin(rand,False) return data_bits + + # def gen_data(self): + # """ Generates a random word, either all 0 or all 1's, to write. """ + # rand = random.randint(0,1) + # bits = [] + # for bit in range(self.word_size): + # bits.append(rand) + # data_bits = ''.join(map(str,bits)) + # return data_bits def gen_addr(self): """ Generates a random address value to write to. """ @@ -221,7 +273,7 @@ class functional(simulation): def get_data(self): """ Gets an available address and corresponding word. """ # Currently unused but may need later depending on how the functional test develops - addr = random.choice(self.stored_words.keys()) + addr = random.choice(list(self.stored_words.keys())) word = self.stored_words[addr] return (addr,word) @@ -294,8 +346,8 @@ class functional(simulation): # Generate wmask bits for port in self.write_ports: - self.sf.write("\n* Generation of wmask sibfssgnals\n") if self.write_size is not None: + self.sf.write("\n* Generation of wmask signals\n") for bit in range(self.num_wmasks): sig_name = "WMASK{0}_{1} ".format(port, bit) self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[port][bit], self.period, diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index c75783b3..4cb8895b 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -135,7 +135,7 @@ class simulation(): def add_wmask(self, wmask, port): """ Add the array of address values """ - debug.check(len(wmask) == self.num_wmask, "Invalid wmask size.") + debug.check(len(wmask) == self.num_wmasks, "Invalid wmask size.") bit = self.addr_size - 1 for c in wmask: @@ -144,7 +144,8 @@ class simulation(): elif c == "1": self.wmask_values[port][bit].append(1) else: - debug.error("Non-binary address string", 1) + print(c) + #debug.error("Non-binary wmask string", 1) bit -= 1 def add_write(self, comment, address, data, port): @@ -208,10 +209,24 @@ class simulation(): debug.check(port in self.write_ports, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_ports)) debug.info(2, comment) self.fn_cycle_comments.append(comment) - + self.add_control_one_port(port, "write") self.add_data(data,port) self.add_address(address,port) + + def add_partial_write_one_port(self, comment, address, data, wmask, port): + """ Add the control values for a write cycle (partial). Does not increment the period. """ + debug.check(port in self.write_ports, + "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, + self.write_ports)) + debug.info(2, comment) + self.fn_cycle_comments.append(comment) + + self.add_control_one_port(port, "write") + self.add_data(data, port) + self.add_address(address, port) + #self.add_wmask(wmask,port) + def add_read_one_port(self, comment, address, din_data, port): """ Add the control values for a read cycle. Does not increment the period. """ @@ -249,22 +264,20 @@ class simulation(): t_current, t_current+self.period) elif op == "write": - if self.write_size is not None: - comment = "\tWriting {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word, - addr, - wmask, - port, - int(t_current / self.period), - t_current, - t_current + self.period) - - else: - comment = "\tWriting {0} to address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, + comment = "\tWriting {0} to address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, addr, port, int(t_current/self.period), t_current, t_current+self.period) + elif op == "partial_write": + comment = "\tWriting {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word, + addr, + wmask, + port, + int(t_current / self.period), + t_current, + t_current + self.period) else: comment = "\tReading {0} from address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, addr, From 2b29e505e062434e88432f285d1e9d0e3421d7f5 Mon Sep 17 00:00:00 2001 From: jsowash Date: Mon, 22 Jul 2019 12:44:35 -0700 Subject: [PATCH 121/234] Reversed order of wmask bits in functional.py since python lists go left to right. Made # of en bits equal to num_masks. --- compiler/characterizer/functional.py | 21 ++++----------------- compiler/characterizer/simulation.py | 2 +- compiler/modules/port_data.py | 7 ++----- compiler/modules/write_driver_array.py | 15 ++++++++++++--- 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index b1fbaada..db455e38 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -152,14 +152,6 @@ class functional(simulation): lower = bit * self.write_size upper = lower + self.write_size - 1 new_word = new_word[:lower] + old_word[lower:upper+1] + new_word[upper + 1:] - # if bit == self.num_wmask - 1: - # new_word = new_word[0:lower] + old_word[lower:upper+1] - # elif bit == 0: - # new_word = old_word[lower:upper + 1] + new_word[upper + 1:self.word_size] - # else: - # new_word = new_word[0:lower] + old_word[lower:upper+1] + new_word[upper+1:self.word_size] - - #wmask = wmask[:index] + "1" + wmask[index + 1:] # two ports cannot write to the same address if addr in w_addrs: @@ -221,15 +213,12 @@ class functional(simulation): return(1, "SUCCESS") def gen_wmask(self): - # wmask_bits = [None]*self.num_wmasks - # for bit in range(self.num_wmasks): - # rand = random.randint(0,1) - # wmask_bits[bit] = rand wmask = "" + # generate a random wmask for bit in range(self.num_wmasks): rand = random.randint(0, 1) wmask += str(rand) - # prevent the wmask from having all bits on + # prevent the wmask from having all bits on or off (not partial write) all_zeroes = True all_ones = True for bit in range(self.num_wmasks): @@ -243,10 +232,8 @@ class functional(simulation): elif all_ones: index = random.randint(0, self.num_wmasks - 1) wmask = wmask[:index] + "0" + wmask[index + 1:] - return wmask - - - # prevent the wmask from having all bits off + # wmask must be reversed since a python list goes right to left and sram bits go left to right. + return wmask[::-1] def gen_data(self): diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 4cb8895b..84ec925d 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -271,7 +271,7 @@ class simulation(): t_current, t_current+self.period) elif op == "partial_write": - comment = "\tWriting {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word, + comment = "\tWriting (partial) {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word, addr, wmask, port, diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 0b2fca51..e0979955 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -300,11 +300,8 @@ class port_data(design.design): temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) if self.write_size is not None: - i = 0 - for bit in range(0,self.word_size,self.write_size): - for x in range(self.write_size): - temp.append("wdriver_sel_{}".format(i)) - i+=1 + for i in range(self.num_wmasks): + temp.append("wdriver_sel_{}".format(i)) else: temp.append("w_en") temp.extend(["vdd", "gnd"]) diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 9e0f992f..5f71b038 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -30,6 +30,9 @@ class write_driver_array(design.design): self.write_size = write_size self.words_per_row = int(columns / word_size) + if self.write_size is not None: + self.num_wmasks = int(self.word_size/self.write_size) + self.create_netlist() if not OPTS.netlist_only: self.create_layout() @@ -61,7 +64,7 @@ class write_driver_array(design.design): self.add_pin("bl_{0}".format(i)) self.add_pin("br_{0}".format(i)) if self.write_size != None: - for i in range(self.word_size): + for i in range(self.num_wmasks): self.add_pin("en_{}".format(i)) else: self.add_pin("en") @@ -78,17 +81,23 @@ class write_driver_array(design.design): def create_write_array(self): self.driver_insts = {} + w = 0 + windex=0 for i in range(0,self.columns,self.words_per_row): name = "write_driver{}".format(i) index = int(i/self.words_per_row) self.driver_insts[index]=self.add_inst(name=name, mod=self.driver) - if self.write_size != None: + if self.write_size is not None: self.connect_inst(["data_{0}".format(index), "bl_{0}".format(index), "br_{0}".format(index), - "en_{0}".format(index), "vdd", "gnd"]) + "en_{0}".format(windex), "vdd", "gnd"]) + w+=1 + if w == self.write_size: + w = 0 + windex+=1 else: self.connect_inst(["data_{0}".format(index), "bl_{0}".format(index), From ad0af54a9f3af7629de93279b5472d4c79722884 Mon Sep 17 00:00:00 2001 From: jsowash Date: Mon, 22 Jul 2019 13:18:52 -0700 Subject: [PATCH 122/234] Removed dupliction of addr_size. --- compiler/base/verilog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index a11ffd0a..f9043491 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -56,7 +56,7 @@ class verilog: self.num_wmasks = int(self.word_size/self.write_size) self.vf.write(" parameter NUM_WMASKS = {0} ;\n".format(self.num_wmasks)) self.vf.write(" parameter DATA_WIDTH = {0} ;\n".format(self.word_size)) - self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_sizeaddr_size)) + self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_size)) self.vf.write(" parameter RAM_DEPTH = 1 << ADDR_WIDTH;\n") self.vf.write(" // FIXME: This delay is arbitrary.\n") self.vf.write(" parameter DELAY = 3 ;\n") From ddf5148fa5c424af74e93d76a9349e4e0684cea5 Mon Sep 17 00:00:00 2001 From: jsowash Date: Mon, 22 Jul 2019 14:58:43 -0700 Subject: [PATCH 123/234] Removed code where if there was no write mask, word_size=write_size. Now it stays None. --- compiler/globals.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/compiler/globals.py b/compiler/globals.py index 4f6398e4..ac7bf9e8 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -464,18 +464,16 @@ def report_status(): debug.error("{0} is not an integer in config file.".format(OPTS.word_size)) if type(OPTS.num_words)!=int: debug.error("{0} is not an integer in config file.".format(OPTS.sram_size)) - if type(OPTS.write_size) != int and OPTS.write_size != None: + if type(OPTS.write_size) is not int and OPTS.write_size is not None: debug.error("{0} is not an integer in config file.".format(OPTS.write_size)) - # Determine if a write mask is specified by the user; if it's not, the mask write size should - # be the same as the word size so that an entire word is written at once - if OPTS.write_size==None: - OPTS.write_size = OPTS.word_size - - if (OPTS.write_size < 1 or OPTS.write_size > OPTS.word_size): - debug.error("Write size needs to be between 1 bit and {0} bits.".format(OPTS.word_size)) - if (OPTS.word_size % OPTS.write_size != 0): - debug.error("Write size needs to be an integer multiple of word size.") + # If a write mask is specified by the user, the mask write size should be the same as + # the word size so that an entire word is written at once. + if OPTS.write_size is not None: + if (OPTS.write_size < 1 or OPTS.write_size > OPTS.word_size): + debug.error("Write size needs to be between 1 bit and {0} bits.".format(OPTS.word_size)) + if (OPTS.word_size % OPTS.write_size != 0): + debug.error("Write size needs to be an integer multiple of word size.") if not OPTS.tech_name: debug.error("Tech name must be specified in config file.") From 07401fc6ea0bdd04281b0da8f702b03ee4a5d21d Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 23 Jul 2019 09:39:28 -0700 Subject: [PATCH 124/234] Make control bus routing offset consistent --- compiler/modules/bank.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 1402015e..9e1fb9ba 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -174,7 +174,7 @@ class bank(design.design): # The port address decoder/driver logic is placed on the right and mirrored on Y-axis. # The port data write/sense/precharge/mux is placed on the top and mirrored on the X-axis. self.bitcell_array_top = self.bitcell_array.height - self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap + self.bitcell_array_right = self.bitcell_array.width # These are the offsets of the main array (excluding dummy and replica rows/cols) self.main_bitcell_array_top = self.bitcell_array.bitcell_array_inst.uy() @@ -249,7 +249,7 @@ class bank(design.design): # LOWER RIGHT QUADRANT # To the left of the bitcell array - x_offset = self.bitcell_array_right + self.port_address.width + 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) # UPPER RIGHT QUADRANT @@ -668,7 +668,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.m2_pitch * self.num_control_lines[0] - self.m2_width, self.min_y_offset) + control_bus_offset = vector(-self.m2_pitch * self.num_control_lines[0] - self.m2_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_xoffset[0] = self.create_bus(layer="metal2", @@ -683,9 +683,8 @@ 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, + control_bus_offset = vector(self.bitcell_array_right + self.m2_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_xoffset[1] = self.create_bus(layer="metal2", pitch=self.m2_pitch, From 01493aab3ecc8b6088e6a632e91d321d101ed866 Mon Sep 17 00:00:00 2001 From: jsowash Date: Tue, 23 Jul 2019 15:58:54 -0700 Subject: [PATCH 125/234] Added wmask valuesto functional test through add_wmask() --- compiler/characterizer/delay.py | 28 ++++++++------ compiler/characterizer/functional.py | 58 ++++++++++++++++------------ compiler/characterizer/simulation.py | 57 ++++++++++++++------------- 3 files changed, 81 insertions(+), 62 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 59f5dcf5..41ab7993 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -44,6 +44,10 @@ class delay(simulation): self.targ_read_ports = [] self.targ_write_ports = [] self.period = 0 + if self.write_size is not None: + self.num_wmasks = int(self.word_size / self.write_size) + else: + self.num_wmasks = 0 self.set_load_slew(0,0) self.set_corner(corner) self.create_signal_names() @@ -1078,46 +1082,48 @@ class delay(simulation): # For now, ignore data patterns and write ones or zeros data_ones = "1"*self.word_size data_zeros = "0"*self.word_size + wmask_ones = "1"*self.num_wmasks + wmask_zeroes = "0"*self.num_wmasks if self.t_current == 0: self.add_noop_all_ports("Idle cycle (no positive clock edge)", - inverse_address, data_zeros) + inverse_address, data_zeros,wmask_zeroes) self.add_write("W data 1 address {}".format(inverse_address), - inverse_address,data_ones,write_port) + inverse_address,data_ones,wmask_ones,write_port) self.add_write("W data 0 address {} to write value".format(self.probe_address), - self.probe_address,data_zeros,write_port) + self.probe_address,data_zeros,wmask_ones,write_port) self.measure_cycles[write_port][sram_op.WRITE_ZERO] = len(self.cycle_times)-1 # This also ensures we will have a H->L transition on the next read self.add_read("R data 1 address {} to set DOUT caps".format(inverse_address), - inverse_address,data_zeros,read_port) + inverse_address,data_zeros,wmask_ones,read_port) self.add_read("R data 0 address {} to check W0 worked".format(self.probe_address), - self.probe_address,data_zeros,read_port) + self.probe_address,data_zeros,wmask_ones,read_port) self.measure_cycles[read_port][sram_op.READ_ZERO] = len(self.cycle_times)-1 self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)", - inverse_address,data_zeros) + inverse_address,data_zeros,wmask_zeroes) self.add_write("W data 1 address {} to write value".format(self.probe_address), - self.probe_address,data_ones,write_port) + self.probe_address,data_ones,wmask_ones,write_port) self.measure_cycles[write_port][sram_op.WRITE_ONE] = len(self.cycle_times)-1 self.add_write("W data 0 address {} to clear DIN caps".format(inverse_address), - inverse_address,data_zeros,write_port) + inverse_address,data_zeros,wmask_ones,write_port) # This also ensures we will have a L->H transition on the next read self.add_read("R data 0 address {} to clear DOUT caps".format(inverse_address), - inverse_address,data_zeros,read_port) + inverse_address,data_zeros,wmask_ones,read_port) self.add_read("R data 1 address {} to check W1 worked".format(self.probe_address), - self.probe_address,data_zeros,read_port) + self.probe_address,data_zeros,wmask_ones,read_port) self.measure_cycles[read_port][sram_op.READ_ONE] = len(self.cycle_times)-1 self.add_noop_all_ports("Idle cycle (if read takes >1 cycle))", - self.probe_address,data_zeros) + self.probe_address,data_zeros,wmask_zeroes) def get_available_port(self,get_read_port): """Returns the first accessible read or write port. """ diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index db455e38..ffb5f70d 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -30,7 +30,10 @@ class functional(simulation): # Seed the characterizer with a constant seed for unit tests if OPTS.is_unit_test: - random.seed(12345) + random.seed(91218) + #12364? + #12365 + #91218 if self.write_size is not None: self.num_wmasks = int(self.word_size / self.write_size) @@ -88,24 +91,26 @@ class functional(simulation): check = 0 # First cycle idle - comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.wmask, self.t_current) - self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size) + comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, self.wmask, 0, self.t_current) + self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks) # Write at least once addr = self.gen_addr() word = self.gen_data() - comment = self.gen_cycle_comment("write", word, addr, 0, self.wmask, self.t_current) - self.add_write(comment, addr, word, 0) + # print("write", self.t_current, addr, word) + comment = self.gen_cycle_comment("write", word, addr, self.wmask, 0, self.t_current) + self.add_write(comment, addr, word, self.wmask, 0) self.stored_words[addr] = word # Read at least once. For multiport, it is important that one read cycle uses all RW and R port to read from the same address simultaniously. # This will test the viablilty of the transistor sizing in the bitcell. for port in self.all_ports: if port in self.write_ports: - self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port) + self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) else: - comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current) - self.add_read_one_port(comment, addr, rw_read_din_data, port) + # print("read", self.t_current, addr, word) + comment = self.gen_cycle_comment("read", word, addr, self.wmask, port, self.t_current) + self.add_read_one_port(comment, addr, rw_read_din_data, "1"*self.num_wmasks, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) check += 1 self.cycle_times.append(self.t_current) @@ -126,21 +131,23 @@ class functional(simulation): if op == "noop": addr = "0"*self.addr_size word = "0"*self.word_size - self.add_noop_one_port(addr, word, port) + wmask = "0" * self.num_wmasks + self.add_noop_one_port(addr, word, wmask, port) elif op == "write": addr = self.gen_addr() word = self.gen_data() + # print("w",self.t_current,addr,word) # two ports cannot write to the same address if addr in w_addrs: - self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port) + self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) else: - comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current) - self.add_write_one_port(comment, addr, word, port) + comment = self.gen_cycle_comment("write", word, addr, self.wmask, port, self.t_current) + self.add_write_one_port(comment, addr, word, self.wmask, port) self.stored_words[addr] = word w_addrs.append(addr) elif op == "partial_write": #write only to a word that's been written to - addr, old_word = self.get_data() + (addr,old_word) = self.get_data() # rand = random.randint(0,len(w_addrs)-1) # addr = w_addrs[rand] word = self.gen_data() @@ -152,23 +159,24 @@ class functional(simulation): lower = bit * self.write_size upper = lower + self.write_size - 1 new_word = new_word[:lower] + old_word[lower:upper+1] + new_word[upper + 1:] - + # print("partial_w",self.t_current,addr,wmask,word, "new", new_word) # two ports cannot write to the same address if addr in w_addrs: - self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port) + self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) else: - comment = self.gen_cycle_comment("partial_write", word, addr, port, wmask, self.t_current) - self.add_partial_write_one_port(comment, addr, word, wmask, port) + comment = self.gen_cycle_comment("partial_write", word, addr, wmask, port, self.t_current) + self.add_write_one_port(comment, addr, word, wmask, port) self.stored_words[addr] = new_word w_addrs.append(addr) else: (addr,word) = random.choice(list(self.stored_words.items())) + # print("read",self.t_current,addr,word) # cannot read from an address that is currently being written to if addr in w_addrs: - self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, port) + self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) else: - comment = self.gen_cycle_comment("read", word, addr, port, self.wmask, self.t_current) - self.add_read_one_port(comment, addr, rw_read_din_data, port) + comment = self.gen_cycle_comment("read", word, addr, self.wmask, port, self.t_current) + self.add_read_one_port(comment, addr, rw_read_din_data, "1"*self.num_wmasks, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) check += 1 @@ -176,8 +184,8 @@ class functional(simulation): self.t_current += self.period # Last cycle idle needed to correctly measure the value on the second to last clock edge - comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.wmask, self.t_current) - self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size) + comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, self.wmask, 0, self.t_current) + self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks) def read_stim_results(self): # Extrat DOUT values from spice timing.lis @@ -337,10 +345,10 @@ class functional(simulation): self.sf.write("\n* Generation of wmask signals\n") for bit in range(self.num_wmasks): sig_name = "WMASK{0}_{1} ".format(port, bit) - self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[port][bit], self.period, - self.slew, 0.05) - # self.stim.gen_pwl(sig_name, self.cycle_times, self.wmask_values[port][bit], self.period, + # self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[port][bit], self.period, # self.slew, 0.05) + self.stim.gen_pwl(sig_name, self.cycle_times, self.wmask_values[port][bit], self.period, + self.slew, 0.05) # Generate CLK signals for port in self.all_ports: diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 84ec925d..52070a35 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -137,18 +137,17 @@ class simulation(): """ Add the array of address values """ debug.check(len(wmask) == self.num_wmasks, "Invalid wmask size.") - bit = self.addr_size - 1 + bit = self.num_wmasks - 1 for c in wmask: if c == "0": self.wmask_values[port][bit].append(0) elif c == "1": self.wmask_values[port][bit].append(1) else: - print(c) - #debug.error("Non-binary wmask string", 1) + debug.error("Non-binary wmask string", 1) bit -= 1 - def add_write(self, comment, address, data, port): + def add_write(self, comment, address, data, wmask, port): """ Add the control values for a write cycle. """ debug.check(port in self.write_ports, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_ports)) debug.info(2, comment) @@ -161,15 +160,16 @@ class simulation(): self.add_control_one_port(port, "write") self.add_data(data,port) self.add_address(address,port) + self.add_wmask(wmask,port) #This value is hard coded here. Possibly change to member variable or set in add_noop_one_port noop_data = "0"*self.word_size #Add noops to all other ports. for unselected_port in self.all_ports: if unselected_port != port: - self.add_noop_one_port(address, noop_data, unselected_port) + self.add_noop_one_port(address, noop_data, wmask, unselected_port) - def add_read(self, comment, address, din_data, port): + def add_read(self, comment, address, din_data, wmask, port): """ Add the control values for a read cycle. """ debug.check(port in self.read_ports, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_ports)) debug.info(2, comment) @@ -183,6 +183,7 @@ class simulation(): #If the port is also a readwrite then add data. if port in self.write_ports: self.add_data(din_data,port) + self.add_wmask(wmask,port) self.add_address(address, port) #This value is hard coded here. Possibly change to member variable or set in add_noop_one_port @@ -190,9 +191,9 @@ class simulation(): #Add noops to all other ports. for unselected_port in self.all_ports: if unselected_port != port: - self.add_noop_one_port(address, noop_data, unselected_port) + self.add_noop_one_port(address, noop_data, wmask, unselected_port) - def add_noop_all_ports(self, comment, address, data): + def add_noop_all_ports(self, comment, address, data, wmask): """ Add the control values for a noop to all ports. """ debug.info(2, comment) self.fn_cycle_comments.append(comment) @@ -202,9 +203,9 @@ class simulation(): self.t_current += self.period for port in self.all_ports: - self.add_noop_one_port(address, data, port) - - def add_write_one_port(self, comment, address, data, port): + self.add_noop_one_port(address, data, wmask, port) + + def add_write_one_port(self, comment, address, data, wmask, port): """ Add the control values for a write cycle. Does not increment the period. """ debug.check(port in self.write_ports, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_ports)) debug.info(2, comment) @@ -213,22 +214,24 @@ class simulation(): self.add_control_one_port(port, "write") self.add_data(data,port) self.add_address(address,port) + self.add_wmask(wmask,port) - def add_partial_write_one_port(self, comment, address, data, wmask, port): - """ Add the control values for a write cycle (partial). Does not increment the period. """ - debug.check(port in self.write_ports, - "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, - self.write_ports)) - debug.info(2, comment) - self.fn_cycle_comments.append(comment) - - self.add_control_one_port(port, "write") - self.add_data(data, port) - self.add_address(address, port) - #self.add_wmask(wmask,port) + # + # def add_partial_write_one_port(self, comment, address, data, wmask, port): + # """ Add the control values for a write cycle (partial). Does not increment the period. """ + # debug.check(port in self.write_ports, + # "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, + # self.write_ports)) + # debug.info(2, comment) + # self.fn_cycle_comments.append(comment) + # + # self.add_control_one_port(port, "write") + # self.add_data(data, port) + # self.add_address(address, port) + # self.add_wmask(wmask,port) - def add_read_one_port(self, comment, address, din_data, port): + def add_read_one_port(self, comment, address, din_data, wmask, port): """ Add the control values for a read cycle. Does not increment the period. """ debug.check(port in self.read_ports, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_ports)) debug.info(2, comment) @@ -238,13 +241,15 @@ class simulation(): #If the port is also a readwrite then add data. if port in self.write_ports: self.add_data(din_data,port) + self.add_wmask(wmask,port) self.add_address(address, port) - def add_noop_one_port(self, address, data, port): + def add_noop_one_port(self, address, data, wmask, port): """ Add the control values for a noop to a single port. Does not increment the period. """ self.add_control_one_port(port, "noop") if port in self.write_ports: self.add_data(data,port) + self.add_wmask(wmask,port) self.add_address(address, port) def append_cycle_comment(self, port, comment): @@ -258,7 +263,7 @@ class simulation(): time_spacing, comment)) - def gen_cycle_comment(self, op, word, addr, port, wmask, t_current): + def gen_cycle_comment(self, op, word, addr, wmask, port, t_current): if op == "noop": comment = "\tIdle during cycle {0} ({1}ns - {2}ns)".format(int(t_current/self.period), t_current, From 3df8abd38c653c31bb4e2b847c84b46bddd8eb80 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 24 Jul 2019 08:15:10 -0700 Subject: [PATCH 126/234] Clean up. Split class into own file. --- compiler/base/hierarchy_spice.py | 19 ++- compiler/characterizer/bit_polarity.py | 14 ++ compiler/characterizer/charutils.py | 12 +- compiler/characterizer/delay.py | 224 +++++++++++++------------ compiler/characterizer/sram_op.py | 15 ++ compiler/modules/bank.py | 8 +- compiler/options.py | 2 +- 7 files changed, 163 insertions(+), 131 deletions(-) create mode 100644 compiler/characterizer/bit_polarity.py create mode 100644 compiler/characterizer/sram_op.py diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 02a72e0c..2dcc3d73 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -28,6 +28,7 @@ class spice(): def __init__(self, name): self.name = name + self.valid_signal_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"] # Holds subckts/mods for this module self.mods = [] # Holds the pins for this module @@ -64,16 +65,20 @@ class spice(): """ Adds a pin to the pins list. Default type is INOUT signal. """ self.pins.append(name) self.pin_type[name]=pin_type + debug.check(pin_type in self.valid_signal_types, "Invalid signaltype for {0}: {1}".format(name,pin_type)) - def add_pin_list(self, pin_list, pin_type_list="INOUT"): + def add_pin_list(self, pin_list, pin_type="INOUT"): """ Adds a pin_list to the pins list """ # The type list can be a single type for all pins # or a list that is the same length as the pin list. - if type(pin_type_list)==str: + if type(pin_type)==str: for pin in pin_list: - self.add_pin(pin,pin_type_list) - elif len(pin_type_list)==len(pin_list): - for (pin,ptype) in zip(pin_list, pin_type_list): + debug.check(pin_type in self.valid_signal_types, "Invalid signaltype for {0}: {1}".format(pin,pin_type)) + self.add_pin(pin,pin_type) + + elif len(pin_type)==len(pin_list): + for (pin,ptype) in zip(pin_list, pin_type): + debug.check(ptype in self.valid_signal_types, "Invalid signaltype for {0}: {1}".format(pin,ptype)) self.add_pin(pin,ptype) else: debug.error("Mismatch in type and pin list lengths.", -1) @@ -91,7 +96,9 @@ class spice(): def get_pin_type(self, name): """ Returns the type of the signal pin. """ - return self.pin_type[name] + pin_type = self.pin_type[name] + debug.check(pin_type in self.valid_signal_types, "Invalid signaltype for {0}: {1}".format(name,pin_type)) + return pin_type def get_pin_dir(self, name): """ Returns the direction of the pin. (Supply/ground are INOUT). """ diff --git a/compiler/characterizer/bit_polarity.py b/compiler/characterizer/bit_polarity.py new file mode 100644 index 00000000..c14c167e --- /dev/null +++ b/compiler/characterizer/bit_polarity.py @@ -0,0 +1,14 @@ +# 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 enum import Enum + +class bit_polarity(Enum): + NONINVERTING = 0 + INVERTING = 1 + diff --git a/compiler/characterizer/charutils.py b/compiler/characterizer/charutils.py index 6cc995e1..fa49b1ed 100644 --- a/compiler/characterizer/charutils.py +++ b/compiler/characterizer/charutils.py @@ -8,17 +8,7 @@ import re import debug from globals import OPTS -from enum import Enum -class sram_op(Enum): - READ_ZERO = 0 - READ_ONE = 1 - WRITE_ZERO = 2 - WRITE_ONE = 3 - -class bit_polarity(Enum): - NONINVERTING = 0 - INVERTING = 1 def relative_compare(value1,value2,error_tolerance=0.001): """ This is used to compare relative values for convergence. """ @@ -102,4 +92,4 @@ def check_dict_values_is_float(dict): for key, value in dict.items(): if type(value)!=float: return False - return True \ No newline at end of file + return True diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 8dac8ad4..44be5656 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -12,6 +12,8 @@ import math from .stimuli import * from .trim_spice import * from .charutils import * +from .sram_op import * +from .bit_polarity import * import utils from globals import OPTS from .simulation import simulation @@ -21,7 +23,8 @@ import graph_util from sram_factory import factory class delay(simulation): - """Functions to measure the delay and power of an SRAM at a given address and + """ + Functions to measure the delay and power of an SRAM at a given address and data bit. In general, this will perform the following actions: @@ -40,7 +43,6 @@ class delay(simulation): def __init__(self, sram, spfile, corner): simulation.__init__(self, sram, spfile, corner) - # These are the member variables for a simulation self.targ_read_ports = [] self.targ_write_ports = [] self.period = 0 @@ -51,11 +53,11 @@ class delay(simulation): def create_measurement_names(self): """Create measurement names. The names themselves currently define the type of measurement""" - #Altering the names will crash the characterizer. TODO: object orientated approach to the measurements. + self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"] self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power"] - #self.voltage_when_names = ["volt_bl", "volt_br"] - #self.bitline_delay_names = ["delay_bl", "delay_br"] + # self.voltage_when_names = ["volt_bl", "volt_br"] + # self.bitline_delay_names = ["delay_bl", "delay_br"] def create_measurement_objects(self): """Create the measurements used for read and write ports""" @@ -78,11 +80,11 @@ class delay(simulation): """Create the measurements used for read ports: delays, slews, powers""" self.read_lib_meas = [] - self.clk_frmt = "clk{0}" #Unformatted clock name - targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit + self.clk_frmt = "clk{0}" # Unformatted clock name + targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) # Empty values are the port and probe data bit self.delay_meas = [] self.delay_meas.append(delay_measure("delay_lh", self.clk_frmt, targ_name, "RISE", "RISE", measure_scale=1e9)) - self.delay_meas[-1].meta_str = sram_op.READ_ONE #Used to index time delay values when measurements written to spice file. + self.delay_meas[-1].meta_str = sram_op.READ_ONE # Used to index time delay values when measurements written to spice file. self.delay_meas.append(delay_measure("delay_hl", self.clk_frmt, targ_name, "FALL", "FALL", measure_scale=1e9)) self.delay_meas[-1].meta_str = sram_op.READ_ZERO self.read_lib_meas+=self.delay_meas @@ -99,14 +101,14 @@ class delay(simulation): self.read_lib_meas.append(power_measure("read0_power", "FALL", measure_scale=1e3)) self.read_lib_meas[-1].meta_str = sram_op.READ_ZERO - #This will later add a half-period to the spice time delay. Only for reading 0. + # This will later add a half-period to the spice time delay. Only for reading 0. for obj in self.read_lib_meas: if obj.meta_str is sram_op.READ_ZERO: obj.meta_add_delay = True read_measures = [] read_measures.append(self.read_lib_meas) - #Other measurements associated with the read port not included in the liberty file + # Other measurements associated with the read port not included in the liberty file read_measures.append(self.create_bitline_measurement_objects()) read_measures.append(self.create_debug_measurement_objects()) read_measures.append(self.create_read_bit_measures()) @@ -114,11 +116,13 @@ class delay(simulation): return read_measures def create_bitline_measurement_objects(self): - """Create the measurements used for bitline delay values. Due to unique error checking, these are separated from other measurements. - These measurements are only associated with read values + """ + Create the measurements used for bitline delay values. Due to + unique error checking, these are separated from other measurements. + These measurements are only associated with read values. """ self.bitline_volt_meas = [] - #Bitline voltage measures + self.bitline_volt_meas.append(voltage_at_measure("v_bl_READ_ZERO", self.bl_name)) self.bitline_volt_meas[-1].meta_str = sram_op.READ_ZERO @@ -151,7 +155,7 @@ class delay(simulation): """Create debug measurement to help identify failures.""" self.debug_volt_meas = [] for meas in self.delay_meas: - #Output voltage measures + # Output voltage measures self.debug_volt_meas.append(voltage_at_measure("v_{}".format(meas.name), meas.targ_name_no_port)) self.debug_volt_meas[-1].meta_str = meas.meta_str @@ -172,7 +176,7 @@ class delay(simulation): for polarity,meas in single_bit_meas.items(): meas.meta_str = cycle self.bit_meas[polarity].append(meas) - #Dictionary values are lists, reduce to a single list of measurements + # Dictionary values are lists, reduce to a single list of measurements return [meas for meas_list in self.bit_meas.values() for meas in meas_list] def get_bit_measures(self, meas_tag, probe_address, probe_data): @@ -186,7 +190,7 @@ class delay(simulation): "supported for characterization. Storage nets={}").format(storage_names)) q_name = cell_name+'.'+str(storage_names[0]) qbar_name = cell_name+'.'+str(storage_names[1]) - #Bit measures, measurements times to be defined later. The measurement names must be unique + # Bit measures, measurements times to be defined later. The measurement names must be unique # but they is enforced externally q_meas = voltage_at_measure("v_q_{}".format(meas_tag), q_name, has_port=False) qbar_meas = voltage_at_measure("v_qbar_{}".format(meas_tag), qbar_name, has_port=False) @@ -200,8 +204,8 @@ class delay(simulation): def add_graph_exclusions(self): """Exclude portions of SRAM from timing graph which are not relevant""" - #other initializations can only be done during analysis when a bit has been selected - #for testing. + # other initializations can only be done during analysis when a bit has been selected + # for testing. self.sram.bank.graph_exclude_precharge() self.sram.graph_exclude_addr_dff() self.sram.graph_exclude_data_dff() @@ -210,10 +214,10 @@ class delay(simulation): def create_graph(self): """Creates timing graph to generate the timing paths for the SRAM output.""" - self.sram.bank.bitcell_array.init_graph_params() #Removes previous bit exclusions + self.sram.bank.bitcell_array.init_graph_params() # Removes previous bit exclusions self.sram.bank.bitcell_array.graph_exclude_bits(self.wordline_row, self.bitline_column) - #Generate new graph every analysis as edges might change depending on test bit + # Generate new graph every analysis as edges might change depending on test bit self.graph = graph_util.timing_graph() self.sram_spc_name = "X{}".format(self.sram.name) self.sram.build_graph(self.graph,self.sram_spc_name,self.pins) @@ -234,8 +238,8 @@ class delay(simulation): """Gets the signal name associated with the sense amp enable from input paths. Only expects a single path to contain the sen signal name.""" sa_mods = factory.get_mods(OPTS.sense_amp) - #Any sense amp instantiated should be identical, any change to that - #will require some identification to determine the mod desired. + # Any sense amp instantiated should be identical, any change to that + # will require some identification to determine the mod desired. 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]) @@ -253,7 +257,7 @@ class delay(simulation): cell_br = cell_mod.get_br_name() bl_found = False - #Only a single path should contain a single s_en name. Anything else is an error. + # Only a single path should contain a single s_en name. Anything else is an error. bl_names = [] exclude_set = self.get_bl_name_search_exclusions() for int_net in [cell_bl, cell_br]: @@ -263,8 +267,8 @@ class delay(simulation): def get_bl_name_search_exclusions(self): """Gets the mods as a set which should be excluded while searching for name.""" - #Exclude the RBL as it contains bitcells which are not in the main bitcell array - #so it makes the search awkward + # Exclude the RBL as it contains bitcells which are not in the main bitcell array + # so it makes the search awkward return set(factory.get_mods(OPTS.replica_bitline)) def get_primary_cell_mod(self, cell_mods): @@ -325,7 +329,7 @@ class delay(simulation): if not isinstance(self.probe_data, int) or self.probe_data>self.word_size or self.probe_data<0: debug.error("Given probe_data is not an integer to specify a data bit",1) - #Adding port options here which the characterizer cannot handle. Some may be added later like ROM + # Adding port options here which the characterizer cannot handle. Some may be added later like ROM if len(self.read_ports) == 0: debug.error("Characterizer does not currently support SRAMs without read ports.",1) if len(self.write_ports) == 0: @@ -460,26 +464,26 @@ class delay(simulation): variant_tuple = self.get_volt_at_measure_variants(port, measure_obj) else: debug.error("Input function not defined for measurement type={}".format(meas_type)) - #Removes port input from any object which does not use it. This shorthand only works if - #the measurement has port as the last input. Could be implemented by measurement type or - #remove entirely from measurement classes. + # Removes port input from any object which does not use it. This shorthand only works if + # the measurement has port as the last input. Could be implemented by measurement type or + # remove entirely from measurement classes. if not measure_obj.has_port: variant_tuple = variant_tuple[:-1] return variant_tuple def get_delay_measure_variants(self, port, delay_obj): """Get the measurement values that can either vary from simulation to simulation (vdd, address) or port to port (time delays)""" - #Return value is intended to match the delay measure format: trig_td, targ_td, vdd, port - #vdd is arguably constant as that is true for a single lib file. + # Return value is intended to match the delay measure format: trig_td, targ_td, vdd, port + # vdd is arguably constant as that is true for a single lib file. if delay_obj.meta_str == sram_op.READ_ZERO: - #Falling delay are measured starting from neg. clk edge. Delay adjusted to that. + # Falling delay are measured starting from neg. clk edge. Delay adjusted to that. meas_cycle_delay = self.cycle_times[self.measure_cycles[port][delay_obj.meta_str]] elif delay_obj.meta_str == sram_op.READ_ONE: meas_cycle_delay = self.cycle_times[self.measure_cycles[port][delay_obj.meta_str]] else: debug.error("Unrecognised delay Index={}".format(delay_obj.meta_str),1) - #These measurements have there time further delayed to the neg. edge of the clock. + # These measurements have there time further delayed to the neg. edge of the clock. if delay_obj.meta_add_delay: meas_cycle_delay += self.period/2 @@ -487,7 +491,7 @@ class delay(simulation): def get_power_measure_variants(self, port, power_obj, operation): """Get the measurement values that can either vary port to port (time delays)""" - #Return value is intended to match the power measure format: t_initial, t_final, port + # Return value is intended to match the power measure format: t_initial, t_final, port t_initial = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]] t_final = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]+1] @@ -495,21 +499,21 @@ class delay(simulation): def get_volt_at_measure_variants(self, port, volt_meas): """Get the measurement values that can either vary port to port (time delays)""" - #Only checking 0 value reads for now. + # Only checking 0 value reads for now. if volt_meas.meta_str == sram_op.READ_ZERO: - #Falling delay are measured starting from neg. clk edge. Delay adjusted to that. + # Falling delay are measured starting from neg. clk edge. Delay adjusted to that. meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]] elif volt_meas.meta_str == sram_op.READ_ONE: meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]] else: debug.error("Unrecognised delay Index={}".format(volt_meas.meta_str),1) - #Measurement occurs at the end of the period -> current period start + period + # Measurement occurs at the end of the period -> current period start + period at_time = meas_cycle+self.period return (at_time, port) def get_volt_when_measure_variants(self, port, volt_meas): """Get the measurement values that can either vary port to port (time delays)""" - #Only checking 0 value reads for now. + # Only checking 0 value reads for now. t_trig = meas_cycle_delay = self.cycle_times[self.measure_cycles[port][sram_op.READ_ZERO]] return (t_trig, self.vdd_voltage, port) @@ -590,7 +594,7 @@ class delay(simulation): if (time_out <= 0): debug.error("Timed out, could not find a feasible period.",2) - #Clear any write target ports and set read port + # Clear any write target ports and set read port self.targ_write_ports = [] self.targ_read_ports = [port] success = False @@ -598,14 +602,14 @@ class delay(simulation): debug.info(1, "Trying feasible period: {0}ns on Port {1}".format(feasible_period, port)) self.period = feasible_period (success, results)=self.run_delay_simulation() - #Clear these target ports after simulation + # Clear these target ports after simulation self.targ_read_ports = [] if not success: feasible_period = 2 * feasible_period continue - #Positions of measurements currently hardcoded. First 2 are delays, next 2 are slews + # Positions of measurements currently hardcoded. First 2 are delays, next 2 are slews feasible_delays = [results[port][mname] for mname in self.delay_meas_names if "delay" in mname] feasible_slews = [results[port][mname] for mname in self.delay_meas_names if "slew" in mname] delay_str = "feasible_delay {0:.4f}ns/{1:.4f}ns".format(*feasible_delays) @@ -618,7 +622,7 @@ class delay(simulation): if success: debug.info(2, "Found feasible_period for port {0}: {1}ns".format(port, feasible_period)) self.period = feasible_period - #Only return results related to input port. + # Only return results related to input port. return results[port] def find_feasible_period(self): @@ -628,19 +632,19 @@ class delay(simulation): """ feasible_delays = [{} for i in self.all_ports] - #Get initial feasible delays from first port + # Get initial feasible delays from first port feasible_delays[self.read_ports[0]] = self.find_feasible_period_one_port(self.read_ports[0]) previous_period = self.period - #Loops through all the ports checks if the feasible period works. Everything restarts it if does not. - #Write ports do not produce delays which is why they are not included here. + # Loops through all the ports checks if the feasible period works. Everything restarts it if does not. + # Write ports do not produce delays which is why they are not included here. i = 1 while i < len(self.read_ports): port = self.read_ports[i] - #Only extract port values from the specified port, not the entire results. + # Only extract port values from the specified port, not the entire results. feasible_delays[port].update(self.find_feasible_period_one_port(port)) - #Function sets the period. Restart the entire process if period changes to collect accurate delays + # Function sets the period. Restart the entire process if period changes to collect accurate delays if self.period > previous_period: i = 0 else: @@ -656,7 +660,7 @@ class delay(simulation): works on the trimmed netlist by default, so powers do not include leakage of all cells. """ - #Sanity Check + # Sanity Check debug.check(self.period > 0, "Target simulation period non-positive") sim_passed = True @@ -666,25 +670,25 @@ class delay(simulation): self.stim.run_sim() - #Loop through all targeted ports and collect delays and powers. - #Too much duplicate code here. Try reducing + # Loop through all targeted ports and collect delays and powers. + # Too much duplicate code here. Try reducing for port in self.targ_read_ports: debug.info(2, "Checking delay values for port {}".format(port)) read_port_dict = {} - #Get measurements from output file + # Get measurements from output file for measure in self.read_lib_meas: read_port_dict[measure.name] = measure.retrieve_measure(port=port) - #Check sen timing, then bitlines, then general measurements. + # Check sen timing, then bitlines, then general measurements. if not self.check_sen_measure(port): return (False,{}) success = self.check_debug_measures(port) success = success and self.check_bit_measures() - #Check timing for read ports. Power is only checked if it was read correctly + # Check timing for read ports. Power is only checked if it was read correctly if not self.check_valid_delays(read_port_dict) or not success: return (False,{}) if not check_dict_values_is_float(read_port_dict): - debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) #Printing the entire dict looks bad. + debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) # Printing the entire dict looks bad. result[port].update(read_port_dict) @@ -694,7 +698,7 @@ class delay(simulation): write_port_dict[measure.name] = measure.retrieve_measure(port=port) if not check_dict_values_is_float(write_port_dict): - debug.error("Failed to Measure Write Port Values:\n\t\t{0}".format(write_port_dict),1) #Printing the entire dict looks bad. + debug.error("Failed to Measure Write Port Values:\n\t\t{0}".format(write_port_dict),1) # Printing the entire dict looks bad. result[port].update(write_port_dict) # The delay is from the negative edge for our SRAM @@ -712,10 +716,10 @@ class delay(simulation): def check_debug_measures(self, port): """Debug measures that indicate special conditions.""" - #Currently, only check if the opposite than intended value was read during + # Currently, only check if the opposite than intended value was read during # the read cycles i.e. neither of these measurements should pass. success = True - #FIXME: these checks need to be re-done to be more robust against possible errors + # FIXME: these checks need to be re-done to be more robust against possible errors bl_vals = {} br_vals = {} for meas in self.bitline_volt_meas: @@ -734,17 +738,17 @@ class delay(simulation): if type(val) != float: continue - if meas.meta_str == sram_op.READ_ONE and val < self.vdd_voltage*.1: + if meas.meta_str == sram_op.READ_ONE and val < self.vdd_voltage*0.1: success = False - debug.info(1, "Debug measurement failed. Value {}v was read on read 1 cycle.".format(val)) + debug.info(1, "Debug measurement failed. Value {}V was read on read 1 cycle.".format(val)) bl_check = self.check_bitline_meas(bl_vals[sram_op.READ_ONE], br_vals[sram_op.READ_ONE]) - elif meas.meta_str == sram_op.READ_ZERO and val > self.vdd_voltage*.9: + elif meas.meta_str == sram_op.READ_ZERO and val > self.vdd_voltage*0.9: success = False - debug.info(1, "Debug measurement failed. Value {}v was read on read 0 cycle.".format(val)) + debug.info(1, "Debug measurement failed. Value {}V was read on read 0 cycle.".format(val)) bl_check = self.check_bitline_meas(br_vals[sram_op.READ_ONE], bl_vals[sram_op.READ_ONE]) - #If the bitlines have a correct value while the output does not then that is a - #sen error. FIXME: there are other checks that can be done to solidfy this conclusion. + # If the bitlines have a correct value while the output does not then that is a + # sen error. FIXME: there are other checks that can be done to solidfy this conclusion. if bl_check: debug.error("Sense amp enable timing error. Increase the delay chain through the configuration file.",1) @@ -762,7 +766,7 @@ class delay(simulation): if type(val) != float: continue meas_cycle = meas.meta_str - #Loose error conditions. Assume it's not metastable but account for noise during reads. + # Loose error conditions. Assume it's not metastable but account for noise during reads. if (meas_cycle == sram_op.READ_ZERO and polarity == bit_polarity.NONINVERTING) or\ (meas_cycle == sram_op.READ_ONE and polarity == bit_polarity.INVERTING): success = val < self.vdd_voltage/2 @@ -778,9 +782,9 @@ class delay(simulation): def check_bitline_meas(self, v_discharged_bl, v_charged_bl): """Checks the value of the discharging bitline. Confirms s_en timing errors. Returns true if the bitlines are at there expected value.""" - #The inputs looks at discharge/charged bitline rather than left or right (bl/br) - #Performs two checks, discharging bitline is at least 10% away from vdd and there is a - #10% vdd difference between the bitlines. Both need to fail to be considered a s_en error. + # The inputs looks at discharge/charged bitline rather than left or right (bl/br) + # Performs two checks, discharging bitline is at least 10% away from vdd and there is a + # 10% vdd difference between the bitlines. Both need to fail to be considered a s_en error. min_dicharge = v_discharged_bl < self.vdd_voltage*0.9 min_diff = (v_charged_bl - v_discharged_bl) > self.vdd_voltage*0.1 @@ -798,8 +802,8 @@ class delay(simulation): leakage_power=parse_spice_list("timing", "leakage_power") debug.check(leakage_power!="Failed","Could not measure leakage power.") debug.info(1, "Leakage power of full array is {0} mW".format(leakage_power*1e3)) - #debug - #sys.exit(1) + # debug + # sys.exit(1) self.write_power_stimulus(trim=True) self.stim.run_sim() @@ -808,12 +812,12 @@ class delay(simulation): debug.info(1, "Leakage power of trimmed array is {0} mW".format(trim_leakage_power*1e3)) # For debug, you sometimes want to inspect each simulation. - #key=raw_input("press return to continue") + # key=raw_input("press return to continue") return (leakage_power*1e3, trim_leakage_power*1e3) def check_valid_delays(self, result_dict): """ Check if the measurements are defined and if they are valid. """ - #Hard coded names currently + # Hard coded names currently delay_hl = result_dict["delay_hl"] delay_lh = result_dict["delay_lh"] slew_hl = result_dict["slew_hl"] @@ -831,7 +835,7 @@ class delay(simulation): delays_str = "delay_hl={0} delay_lh={1}".format(delay_hl, delay_lh) slews_str = "slew_hl={0} slew_lh={1}".format(slew_hl,slew_lh) - half_period = self.period/2 #high-to-low delays start at neg. clk edge, so they need to be less than half_period + half_period = self.period/2 # high-to-low delays start at neg. clk edge, so they need to be less than half_period if abs(delay_hl)>half_period or abs(delay_lh)>self.period or abs(slew_hl)>half_period or abs(slew_lh)>self.period \ or delay_hl<0 or delay_lh<0 or slew_hl<0 or slew_lh<0: debug.info(2,"UNsuccessful simulation (in ns):\n\t\t{0}\n\t\t{1}\n\t\t{2}".format(period_load_slew_str, @@ -854,15 +858,15 @@ class delay(simulation): lb_period = 0.0 target_period = 0.5 * (ub_period + lb_period) - #Find the minimum period for all ports. Start at one port and perform binary search then use that delay as a starting position. - #For testing purposes, only checks read ports. + # Find the minimum period for all ports. Start at one port and perform binary search then use that delay as a starting position. + # For testing purposes, only checks read ports. for port in self.read_ports: target_period = self.find_min_period_one_port(feasible_delays, port, lb_period, ub_period, target_period) - #The min period of one port becomes the new lower bound. Reset the upper_bound. + # The min period of one port becomes the new lower bound. Reset the upper_bound. lb_period = target_period ub_period = feasible_period - #Clear the target ports before leaving + # Clear the target ports before leaving self.targ_read_ports = [] self.targ_write_ports = [] return target_period @@ -873,10 +877,10 @@ class delay(simulation): long period. For the current logic to characterize multiport, bounds are required as an input. """ - #previous_period = ub_period = self.period - #ub_period = self.period - #lb_period = 0.0 - #target_period = 0.5 * (ub_period + lb_period) + # previous_period = ub_period = self.period + # ub_period = self.period + # lb_period = 0.0 + # target_period = 0.5 * (ub_period + lb_period) # Binary search algorithm to find the min period (max frequency) of input port time_out = 25 @@ -901,9 +905,9 @@ class delay(simulation): # ub_period is always feasible. return ub_period - #Update target + # Update target target_period = 0.5 * (ub_period + lb_period) - #key=input("press return to continue") + # key=input("press return to continue") def try_period(self, feasible_delays): @@ -916,13 +920,13 @@ class delay(simulation): if not success: return False - #Check the values of target readwrite and read ports. Write ports do not produce delays in this current version + # Check the values of target readwrite and read ports. Write ports do not produce delays in this current version for port in self.targ_read_ports: - for dname in self.delay_meas_names: #check that the delays and slews do not degrade with tested period. + for dname in self.delay_meas_names: # check that the delays and slews do not degrade with tested period. - #FIXME: This is a hack solution to fix the min period search. The slew will always be based on the period when there - #is a column mux. Therefore, the checks are skipped for this condition. This is hard to solve without changing the netlist. - #Delays/slews based on the period will cause the min_period search to come to the wrong period. + # FIXME: This is a hack solution to fix the min period search. The slew will always be based on the period when there + # is a column mux. Therefore, the checks are skipped for this condition. This is hard to solve without changing the netlist. + # Delays/slews based on the period will cause the min_period search to come to the wrong period. if self.sram.col_addr_size>0 and "slew" in dname: continue @@ -930,9 +934,9 @@ class delay(simulation): debug.info(2,"Delay too big {0} vs {1}".format(results[port][dname],feasible_delays[port][dname])) return False - #key=raw_input("press return to continue") + # key=raw_input("press return to continue") - #Dynamic way to build string. A bit messy though. + # Dynamic way to build string. A bit messy though. delay_str = ', '.join("{0}={1}ns".format(mname, results[port][mname]) for mname in self.delay_meas_names) debug.info(2,"Successful period {0}, Port {2}, {1}".format(self.period, delay_str, @@ -994,7 +998,7 @@ class delay(simulation): """ Main function to characterize an SRAM for a table. Computes both delay and power characterization. """ - #Dict to hold all characterization values + # Dict to hold all characterization values char_sram_data = {} self.analysis_init(probe_address, probe_data) @@ -1019,14 +1023,14 @@ class delay(simulation): self.period = min_period char_port_data = self.simulate_loads_and_slews(slews, loads, leakage_offset) - #FIXME: low-to-high delays are altered to be independent of the period. This makes the lib results less accurate. + # FIXME: low-to-high delays are altered to be independent of the period. This makes the lib results less accurate. self.alter_lh_char_data(char_port_data) return (char_sram_data, char_port_data) def alter_lh_char_data(self, char_port_data): """Copies high-to-low data to low-to-high data to make them consistent on the same clock edge.""" - #This is basically a hack solution which should be removed/fixed later. + # This is basically a hack solution which should be removed/fixed later. for port in self.all_ports: char_port_data[port]['delay_lh'] = char_port_data[port]['delay_hl'] char_port_data[port]['slew_lh'] = char_port_data[port]['slew_hl'] @@ -1034,7 +1038,7 @@ class delay(simulation): def simulate_loads_and_slews(self, slews, loads, leakage_offset): """Simulate all specified output loads and input slews pairs of all ports""" measure_data = self.get_empty_measure_data_dict() - #Set the target simulation ports to all available ports. This make sims slower but failed sims exit anyways. + # Set the target simulation ports to all available ports. This make sims slower but failed sims exit anyways. self.targ_read_ports = self.read_ports self.targ_write_ports = self.write_ports for slew in slews: @@ -1044,7 +1048,7 @@ class delay(simulation): (success, delay_results) = self.run_delay_simulation() debug.check(success,"Couldn't run a simulation. slew={0} load={1}\n".format(self.slew,self.load)) debug.info(1, "Simulation Passed: Port {0} slew={1} load={2}".format("All", self.slew,self.load)) - #The results has a dict for every port but dicts can be empty (e.g. ports were not targeted). + # The results has a dict for every port but dicts can be empty (e.g. ports were not targeted). for port in self.all_ports: for mname,value in delay_results[port].items(): if "power" in mname: @@ -1056,11 +1060,11 @@ class delay(simulation): def calculate_inverse_address(self): """Determine dummy test address based on probe address and column mux size.""" - #The inverse address needs to share the same bitlines as the probe address as the trimming will remove all other bitlines - #This is only an issue when there is a column mux and the address maps to different bitlines. - column_addr = self.probe_address[:self.sram.col_addr_size] #do not invert this part + # The inverse address needs to share the same bitlines as the probe address as the trimming will remove all other bitlines + # This is only an issue when there is a column mux and the address maps to different bitlines. + column_addr = self.probe_address[:self.sram.col_addr_size] # do not invert this part inverse_address = "" - for c in self.probe_address[self.sram.col_addr_size:]: #invert everything else + for c in self.probe_address[self.sram.col_addr_size:]: # invert everything else if c=="0": inverse_address += "1" elif c=="1": @@ -1133,29 +1137,31 @@ class delay(simulation): self.measure_cycles = [{} for port in self.all_ports] def create_test_cycles(self): - """Returns a list of key time-points [ns] of the waveform (each rising edge) + """ + Returns a list of key time-points [ns] of the waveform (each rising edge) of the cycles to do a timing evaluation. The last time is the end of the simulation - and does not need a rising edge.""" - #Using this requires setting at least one port to target for simulation. + and does not need a rising edge. + """ + # Using this requires setting at least one port to target for simulation. if len(self.targ_write_ports) == 0 and len(self.targ_read_ports) == 0: debug.error("No port selected for characterization.",1) self.set_stimulus_variables() - #Get any available read/write port in case only a single write or read ports is being characterized. + # Get any available read/write port in case only a single write or read ports is being characterized. cur_read_port = self.get_available_port(get_read_port=True) cur_write_port = self.get_available_port(get_read_port=False) debug.check(cur_read_port != None, "Characterizer requires at least 1 read port") debug.check(cur_write_port != None, "Characterizer requires at least 1 write port") - #Create test cycles for specified target ports. + # Create test cycles for specified target ports. write_pos = 0 read_pos = 0 while True: - #Exit when all ports have been characterized + # Exit when all ports have been characterized if write_pos >= len(self.targ_write_ports) and read_pos >= len(self.targ_read_ports): break - #Select new write and/or read ports for the next cycle. Use previous port if none remaining. + # Select new write and/or read ports for the next cycle. Use previous port if none remaining. if write_pos < len(self.targ_write_ports): cur_write_port = self.targ_write_ports[write_pos] write_pos+=1 @@ -1163,7 +1169,7 @@ class delay(simulation): cur_read_port = self.targ_read_ports[read_pos] read_pos+=1 - #Add test cycle of read/write port pair. One port could have been used already, but the other has not. + # Add test cycle of read/write port pair. One port could have been used already, but the other has not. self.gen_test_cycles_one_port(cur_read_port, cur_write_port) def analytical_delay(self, slews, loads): @@ -1200,10 +1206,10 @@ class delay(simulation): def analytical_power(self, slews, loads): """Get the dynamic and leakage power from the SRAM""" - #slews unused, only last load is used + # slews unused, only last load is used load = loads[-1] power = self.sram.analytical_power(self.corner, load) - #convert from nW to mW + # convert from nW to mW power.dynamic /= 1e6 power.leakage /= 1e6 debug.info(1,"Dynamic Power: {0} mW".format(power.dynamic)) @@ -1238,6 +1244,6 @@ class delay(simulation): def get_empty_measure_data_dict(self): """Make a dict of lists for each type of delay and power measurement to append results to""" measure_names = self.delay_meas_names + self.power_meas_names - #Create list of dicts. List lengths is # of ports. Each dict maps the measurement names to lists. + # Create list of dicts. List lengths is # of ports. Each dict maps the measurement names to lists. measure_data = [{mname:[] for mname in measure_names} for i in self.all_ports] return measure_data diff --git a/compiler/characterizer/sram_op.py b/compiler/characterizer/sram_op.py new file mode 100644 index 00000000..58999ca0 --- /dev/null +++ b/compiler/characterizer/sram_op.py @@ -0,0 +1,15 @@ +# 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 enum import Enum + +class sram_op(Enum): + READ_ZERO = 0 + READ_ONE = 1 + WRITE_ZERO = 2 + WRITE_ONE = 3 diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 9e1fb9ba..11e5adca 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -77,14 +77,14 @@ class bank(design.design): """ Adding pins for Bank module""" for port in self.read_ports: for bit in range(self.word_size): - self.add_pin("dout{0}_{1}".format(port,bit),"OUT") + self.add_pin("dout{0}_{1}".format(port,bit),"OUTPUT") for port in self.read_ports: - self.add_pin(self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]),"OUT") + self.add_pin(self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]),"OUTPUT") for port in self.read_ports: - self.add_pin(self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]),"IN") + self.add_pin(self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]),"INPUT") for port in self.write_ports: for bit in range(self.word_size): - self.add_pin("din{0}_{1}".format(port,bit),"IN") + self.add_pin("din{0}_{1}".format(port,bit),"INPUT") # if (self.word_size != self.write_size): # for bit in range(self.word_size): # self.add_pin() diff --git a/compiler/options.py b/compiler/options.py index ab337e31..c10d3158 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -84,7 +84,7 @@ class options(optparse.Values): # This determines whether LVS and DRC is checked for every submodule. inline_lvsdrc = False # Remove noncritical memory cells for characterization speed-up - trim_netlist = True + trim_netlist = False # Run with extracted parasitics use_pex = False From 9cb96bda7d487661f1f7600478242999ee1643e5 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 24 Jul 2019 10:57:33 -0700 Subject: [PATCH 127/234] Mostly formatting. Added write measurements. --- compiler/characterizer/delay.py | 273 ++++++++++++++++++++++---------- 1 file changed, 191 insertions(+), 82 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 44be5656..9757fbbb 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -52,7 +52,7 @@ class delay(simulation): self.add_graph_exclusions() def create_measurement_names(self): - """Create measurement names. The names themselves currently define the type of measurement""" + """ Create measurement names. The names themselves currently define the type of measurement """ self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"] self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power"] @@ -60,14 +60,17 @@ class delay(simulation): # self.bitline_delay_names = ["delay_bl", "delay_br"] def create_measurement_objects(self): - """Create the measurements used for read and write ports""" + """ Create the measurements used for read and write ports """ + self.read_meas_lists = self.create_read_port_measurement_objects() self.write_meas_lists = self.create_write_port_measurement_objects() self.check_meas_names(self.read_meas_lists+self.write_meas_lists) def check_meas_names(self, measures_lists): - """Given measurements (in 2d list), checks that their names are unique. - Spice sim will fail otherwise.""" + """ + Given measurements (in 2d list), checks that their names are unique. + Spice sim will fail otherwise. + """ name_set = set() for meas_list in measures_lists: for meas in meas_list: @@ -121,6 +124,7 @@ class delay(simulation): unique error checking, these are separated from other measurements. These measurements are only associated with read values. """ + self.bitline_volt_meas = [] self.bitline_volt_meas.append(voltage_at_measure("v_bl_READ_ZERO", @@ -140,6 +144,7 @@ class delay(simulation): def create_write_port_measurement_objects(self): """Create the measurements used for read ports: delays, slews, powers""" + self.write_lib_meas = [] self.write_lib_meas.append(power_measure("write1_power", "RISE", measure_scale=1e3)) @@ -149,10 +154,12 @@ class delay(simulation): write_measures = [] write_measures.append(self.write_lib_meas) + write_measures.append(self.create_write_bit_measures()) return write_measures def create_debug_measurement_objects(self): """Create debug measurement to help identify failures.""" + self.debug_volt_meas = [] for meas in self.delay_meas: # Output voltage measures @@ -167,7 +174,8 @@ class delay(simulation): return self.debug_volt_meas+[self.sen_meas] def create_read_bit_measures(self): - """Adds bit measurements for read0 and read1 cycles""" + """ Adds bit measurements for read0 and read1 cycles """ + self.bit_meas = {bit_polarity.NONINVERTING:[], bit_polarity.INVERTING:[]} meas_cycles = (sram_op.READ_ZERO, sram_op.READ_ONE) for cycle in meas_cycles: @@ -178,10 +186,27 @@ class delay(simulation): self.bit_meas[polarity].append(meas) # Dictionary values are lists, reduce to a single list of measurements return [meas for meas_list in self.bit_meas.values() for meas in meas_list] - + + def create_write_bit_measures(self): + """ Adds bit measurements for write0 and write1 cycles """ + + self.bit_meas = {bit_polarity.NONINVERTING:[], bit_polarity.INVERTING:[]} + meas_cycles = (sram_op.WRITE_ZERO, sram_op.WRITE_ONE) + for cycle in meas_cycles: + meas_tag = "a{}_b{}_{}".format(self.probe_address, self.probe_data, cycle.name) + single_bit_meas = self.get_bit_measures(meas_tag, self.probe_address, self.probe_data) + for polarity,meas in single_bit_meas.items(): + meas.meta_str = cycle + self.bit_meas[polarity].append(meas) + # Dictionary values are lists, reduce to a single list of measurements + return [meas for meas_list in self.bit_meas.values() for meas in meas_list] + def get_bit_measures(self, meas_tag, probe_address, probe_data): - """Creates measurements for the q/qbar of input bit position. - meas_tag is a unique identifier for the measurement.""" + """ + Creates measurements for the q/qbar of input bit position. + meas_tag is a unique identifier for the measurement. + """ + bit_col = self.get_data_bit_column_number(probe_address, probe_data) bit_row = self.get_address_row_number(probe_address) (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, bit_row, bit_col) @@ -190,6 +215,7 @@ class delay(simulation): "supported for characterization. Storage nets={}").format(storage_names)) q_name = cell_name+'.'+str(storage_names[0]) qbar_name = cell_name+'.'+str(storage_names[1]) + # Bit measures, measurements times to be defined later. The measurement names must be unique # but they is enforced externally q_meas = voltage_at_measure("v_q_{}".format(meas_tag), q_name, has_port=False) @@ -199,11 +225,13 @@ class delay(simulation): def set_load_slew(self,load,slew): """ Set the load and slew """ + self.load = load self.slew = slew def add_graph_exclusions(self): """Exclude portions of SRAM from timing graph which are not relevant""" + # other initializations can only be done during analysis when a bit has been selected # for testing. self.sram.bank.graph_exclude_precharge() @@ -214,6 +242,7 @@ class delay(simulation): def create_graph(self): """Creates timing graph to generate the timing paths for the SRAM output.""" + self.sram.bank.bitcell_array.init_graph_params() # Removes previous bit exclusions self.sram.bank.bitcell_array.graph_exclude_bits(self.wordline_row, self.bitline_column) @@ -224,6 +253,7 @@ class delay(simulation): def set_internal_spice_names(self): """Sets important names for characterization such as Sense amp enable and internal bit nets.""" + port = 0 self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), \ '{}{}_{}'.format(self.dout_name, port, self.probe_data)) @@ -233,10 +263,13 @@ class delay(simulation): self.bl_name,self.br_name = self.get_bl_name(self.graph.all_paths) debug.info(2,"bl name={}, br name={}".format(self.bl_name,self.br_name)) - + def get_sen_name(self, paths): - """Gets the signal name associated with the sense amp enable from input paths. - Only expects a single path to contain the sen signal name.""" + """ + Gets the signal name associated with the sense amp enable from input paths. + Only expects a single path to contain the sen signal name. + """ + sa_mods = factory.get_mods(OPTS.sense_amp) # Any sense amp instantiated should be identical, any change to that # will require some identification to determine the mod desired. @@ -247,6 +280,7 @@ class delay(simulation): def get_bl_name(self, paths): """Gets the signal name associated with the bitlines in the bank.""" + cell_mods = factory.get_mods(OPTS.bitcell) if len(cell_mods)>=1: cell_mod = self.get_primary_cell_mod(cell_mods) @@ -264,16 +298,20 @@ class delay(simulation): bl_names.append(self.get_alias_in_path(paths, int_net, cell_mod, exclude_set)) return bl_names[0], bl_names[1] - + + def get_bl_name_search_exclusions(self): """Gets the mods as a set which should be excluded while searching for name.""" + # Exclude the RBL as it contains bitcells which are not in the main bitcell array # so it makes the search awkward return set(factory.get_mods(OPTS.replica_bitline)) def get_primary_cell_mod(self, cell_mods): - """Distinguish bitcell array mod from replica bitline array. - Assume there are no replica bitcells in the primary array.""" + """ + Distinguish bitcell array mod from replica bitline array. + Assume there are no replica bitcells in the primary array. + """ if len(cell_mods) == 1: return cell_mods[0] rbc_mods = factory.get_mods(OPTS.replica_bitcell) @@ -290,6 +328,7 @@ class delay(simulation): def are_mod_pins_equal(self, mods): """Determines if there are pins differences in the input mods""" + if len(mods) == 0: return True pins = mods[0].pins @@ -299,8 +338,11 @@ class delay(simulation): return True def get_alias_in_path(self, paths, int_net, mod, exclusion_set=None): - """Finds a single alias for the int_net in given paths. - More or less hits cause an error""" + """ + Finds a single alias for the int_net in given paths. + More or less hits cause an error + """ + net_found = False for path in paths: aliases = self.sram.find_aliases(self.sram_spc_name, self.pins, path, int_net, mod, exclusion_set) @@ -318,6 +360,7 @@ class delay(simulation): def check_arguments(self): """Checks if arguments given for write_stimulus() meets requirements""" + try: int(self.probe_address, 2) except ValueError: @@ -353,10 +396,12 @@ class delay(simulation): def write_delay_stimulus(self): - """ Creates a stimulus file for simulations to probe a bitcell at a given clock period. + """ + Creates a stimulus file for simulations to probe a bitcell at a given clock period. Address and bit were previously set with set_probe(). Input slew (in ns) and output capacitive load (in fF) are required for charaterization. """ + self.check_arguments() # obtains list of time-points for each rising clk edge @@ -452,7 +497,11 @@ class delay(simulation): self.sf.close() def get_read_measure_variants(self, port, measure_obj): - """Checks the measurement object and calls respective function for related measurement inputs.""" + """ + Checks the measurement object and calls respective function for + related measurement inputs. + """ + meas_type = type(measure_obj) if meas_type is delay_measure or meas_type is slew_measure: variant_tuple = self.get_delay_measure_variants(port, measure_obj) @@ -472,7 +521,11 @@ class delay(simulation): return variant_tuple def get_delay_measure_variants(self, port, delay_obj): - """Get the measurement values that can either vary from simulation to simulation (vdd, address) or port to port (time delays)""" + """ + Get the measurement values that can either vary from simulation to + simulation (vdd, address) or port to port (time delays) + """ + # Return value is intended to match the delay measure format: trig_td, targ_td, vdd, port # vdd is arguably constant as that is true for a single lib file. if delay_obj.meta_str == sram_op.READ_ZERO: @@ -491,6 +544,7 @@ class delay(simulation): def get_power_measure_variants(self, port, power_obj, operation): """Get the measurement values that can either vary port to port (time delays)""" + # Return value is intended to match the power measure format: t_initial, t_final, port t_initial = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]] t_final = self.cycle_times[self.measure_cycles[port][power_obj.meta_str]+1] @@ -498,21 +552,21 @@ class delay(simulation): return (t_initial, t_final, port) def get_volt_at_measure_variants(self, port, volt_meas): - """Get the measurement values that can either vary port to port (time delays)""" - # Only checking 0 value reads for now. - if volt_meas.meta_str == sram_op.READ_ZERO: - # Falling delay are measured starting from neg. clk edge. Delay adjusted to that. - meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]] - elif volt_meas.meta_str == sram_op.READ_ONE: - meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]] - else: - debug.error("Unrecognised delay Index={}".format(volt_meas.meta_str),1) + """ + Get the measurement values that can either vary port to port (time delays) + """ + + meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]] + # Measurement occurs at the end of the period -> current period start + period at_time = meas_cycle+self.period return (at_time, port) def get_volt_when_measure_variants(self, port, volt_meas): - """Get the measurement values that can either vary port to port (time delays)""" + """ + Get the measurement values that can either vary port to port (time delays) + """ + # Only checking 0 value reads for now. t_trig = meas_cycle_delay = self.cycle_times[self.measure_cycles[port][sram_op.READ_ZERO]] @@ -522,6 +576,7 @@ class delay(simulation): """ Write the measure statements to quantify the delay and power results for a read port. """ + # add measure statements for delays/slews for meas_list in self.read_meas_lists: for measure in meas_list: @@ -529,17 +584,31 @@ class delay(simulation): measure.write_measure(self.stim, measure_variant_inp_tuple) def get_write_measure_variants(self, port, measure_obj): - """Checks the measurement object and calls respective function for related measurement inputs.""" + """ + Checks the measurement object and calls respective function for related measurement inputs. + """ + meas_type = type(measure_obj) if meas_type is power_measure: return self.get_power_measure_variants(port, measure_obj, "write") + elif meas_type is voltage_at_measure: + variant_tuple = self.get_volt_at_measure_variants(port, measure_obj) else: - debug.error("Input function not defined for measurement type={}".format(meas_type)) + debug.error("Input function not defined for measurement type={}".format(meas_type)) + + # Removes port input from any object which does not use it. This shorthand only works if + # the measurement has port as the last input. Could be implemented by measurement type or + # remove entirely from measurement classes. + if not measure_obj.has_port: + variant_tuple = variant_tuple[:-1] + return variant_tuple + def write_delay_measures_write_port(self, port): """ Write the measure statements to quantify the power results for a write port. """ + # add measure statements for power for meas_list in self.write_meas_lists: for measure in meas_list: @@ -550,17 +619,22 @@ class delay(simulation): """ Write the measure statements to quantify the delay and power results for all targeted ports. """ + self.sf.write("\n* Measure statements for delay and power\n") # Output some comments to aid where cycles start and # what is happening for comment in self.cycle_comments: self.sf.write("* {}\n".format(comment)) - + + self.sf.write("\n") for read_port in self.targ_read_ports: - self.write_delay_measures_read_port(read_port) + self.sf.write("* Read ports {}\n".format(read_port)) + self.write_delay_measures_read_port(read_port) + for write_port in self.targ_write_ports: - self.write_delay_measures_write_port(write_port) + self.sf.write("* Write ports {}\n".format(write_port)) + self.write_delay_measures_write_port(write_port) def write_power_measures(self): @@ -595,14 +669,16 @@ class delay(simulation): debug.error("Timed out, could not find a feasible period.",2) # Clear any write target ports and set read port - self.targ_write_ports = [] + self.targ_write_ports = [port] self.targ_read_ports = [port] success = False debug.info(1, "Trying feasible period: {0}ns on Port {1}".format(feasible_period, port)) self.period = feasible_period (success, results)=self.run_delay_simulation() + # Clear these target ports after simulation + self.targ_write_ports = [] self.targ_read_ports = [] if not success: @@ -615,9 +691,9 @@ class delay(simulation): delay_str = "feasible_delay {0:.4f}ns/{1:.4f}ns".format(*feasible_delays) slew_str = "slew {0:.4f}ns/{1:.4f}ns".format(*feasible_slews) debug.info(2, "feasible_period passed for Port {3}: {0}ns {1} {2} ".format(feasible_period, - delay_str, - slew_str, - port)) + delay_str, + slew_str, + port)) if success: debug.info(2, "Found feasible_period for port {0}: {1}ns".format(port, feasible_period)) @@ -660,39 +736,23 @@ class delay(simulation): works on the trimmed netlist by default, so powers do not include leakage of all cells. """ - # Sanity Check + debug.check(self.period > 0, "Target simulation period non-positive") - sim_passed = True - result = [{} for i in self.all_ports] - # Checking from not data_value to data_value self.write_delay_stimulus() self.stim.run_sim() + + self.check_measurements() + + def check_measurements(self): + """ Check the write and read measurements """ - # Loop through all targeted ports and collect delays and powers. - # Too much duplicate code here. Try reducing - for port in self.targ_read_ports: - debug.info(2, "Checking delay values for port {}".format(port)) - read_port_dict = {} - # Get measurements from output file - for measure in self.read_lib_meas: - read_port_dict[measure.name] = measure.retrieve_measure(port=port) - - # Check sen timing, then bitlines, then general measurements. - if not self.check_sen_measure(port): - return (False,{}) - success = self.check_debug_measures(port) - success = success and self.check_bit_measures() - # Check timing for read ports. Power is only checked if it was read correctly - if not self.check_valid_delays(read_port_dict) or not success: - return (False,{}) - if not check_dict_values_is_float(read_port_dict): - debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) # Printing the entire dict looks bad. - - result[port].update(read_port_dict) - + # Loop through all targeted ports and collect delays and powers. + result = [{} for i in self.all_ports] + for port in self.targ_write_ports: + debug.info(2, "Checking write values for port {}".format(port)) write_port_dict = {} for measure in self.write_lib_meas: write_port_dict[measure.name] = measure.retrieve_measure(port=port) @@ -701,21 +761,45 @@ class delay(simulation): debug.error("Failed to Measure Write Port Values:\n\t\t{0}".format(write_port_dict),1) # Printing the entire dict looks bad. result[port].update(write_port_dict) - # The delay is from the negative edge for our SRAM - return (sim_passed,result) + + for port in self.targ_read_ports: + debug.info(2, "Checking read delay values for port {}".format(port)) + read_port_dict = {} + # Get measurements from output file + for measure in self.read_lib_meas: + read_port_dict[measure.name] = measure.retrieve_measure(port=port) + + # Check sen timing, then bitlines, then general measurements. + if not self.check_sen_measure(port): + return (False,{}) + success = self.check_read_debug_measures(port) + success = success and self.check_bit_measures() + + # Check timing for read ports. Power is only checked if it was read correctly + if not self.check_valid_delays(read_port_dict) or not success: + return (False,{}) + if not check_dict_values_is_float(read_port_dict): + debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) # Printing the entire dict looks bad. + + result[port].update(read_port_dict) + + return (True,result) def check_sen_measure(self, port): """Checks that the sen occurred within a half-period""" + sen_val = self.sen_meas.retrieve_measure(port=port) - debug.info(2,"S_EN delay={} ns".format(sen_val)) + debug.info(2,"s_en delay={}ns".format(sen_val)) if self.sen_meas.meta_add_delay: max_delay = self.period/2 else: max_delay = self.period return not (type(sen_val) != float or sen_val > max_delay) - def check_debug_measures(self, port): + + def check_read_debug_measures(self, port): """Debug measures that indicate special conditions.""" + # Currently, only check if the opposite than intended value was read during # the read cycles i.e. neither of these measurements should pass. success = True @@ -756,8 +840,10 @@ class delay(simulation): def check_bit_measures(self): - """Checks the measurements which represent the internal storage voltages - at the end of the read cycle.""" + """ + Checks the measurements which represent the internal storage voltages + at the end of the read cycle. + """ success = True for polarity, meas_list in self.bit_meas.items(): for meas in meas_list: @@ -780,8 +866,10 @@ class delay(simulation): return success def check_bitline_meas(self, v_discharged_bl, v_charged_bl): - """Checks the value of the discharging bitline. Confirms s_en timing errors. - Returns true if the bitlines are at there expected value.""" + """ + Checks the value of the discharging bitline. Confirms s_en timing errors. + Returns true if the bitlines are at there expected value. + """ # The inputs looks at discharge/charged bitline rather than left or right (bl/br) # Performs two checks, discharging bitline is at least 10% away from vdd and there is a # 10% vdd difference between the bitlines. Both need to fail to be considered a s_en error. @@ -794,8 +882,8 @@ class delay(simulation): def run_power_simulation(self): """ This simulates a disabled SRAM to get the leakage power when it is off. - """ + debug.info(1, "Performing leakage power simulations.") self.write_power_stimulus(trim=False) self.stim.run_sim() @@ -817,6 +905,7 @@ class delay(simulation): def check_valid_delays(self, result_dict): """ Check if the measurements are defined and if they are valid. """ + # Hard coded names currently delay_hl = result_dict["delay_hl"] delay_lh = result_dict["delay_lh"] @@ -884,6 +973,7 @@ class delay(simulation): # Binary search algorithm to find the min period (max frequency) of input port time_out = 25 + self.targ_write_ports = [port] self.targ_read_ports = [port] while True: time_out -= 1 @@ -892,9 +982,9 @@ class delay(simulation): self.period = target_period debug.info(1, "MinPeriod Search Port {3}: {0}ns (ub: {1} lb: {2})".format(target_period, - ub_period, - lb_period, - port)) + ub_period, + lb_period, + port)) if self.try_period(feasible_delays): ub_period = target_period @@ -915,14 +1005,16 @@ class delay(simulation): This tries to simulate a period and checks if the result works. If it does and the delay is within 5% still, it returns True. """ + # Run Delay simulation but Power results not used. (success, results) = self.run_delay_simulation() if not success: return False # Check the values of target readwrite and read ports. Write ports do not produce delays in this current version - for port in self.targ_read_ports: - for dname in self.delay_meas_names: # check that the delays and slews do not degrade with tested period. + for port in self.targ_read_ports: + # check that the delays and slews do not degrade with tested period. + for dname in self.delay_meas_names: # FIXME: This is a hack solution to fix the min period search. The slew will always be based on the period when there # is a column mux. Therefore, the checks are skipped for this condition. This is hard to solve without changing the netlist. @@ -936,7 +1028,6 @@ class delay(simulation): # key=raw_input("press return to continue") - # Dynamic way to build string. A bit messy though. delay_str = ', '.join("{0}={1}ns".format(mname, results[port][mname]) for mname in self.delay_meas_names) debug.info(2,"Successful period {0}, Port {2}, {1}".format(self.period, delay_str, @@ -944,8 +1035,11 @@ class delay(simulation): return True def set_probe(self,probe_address, probe_data): - """ Probe address and data can be set separately to utilize other - functions in this characterizer besides analyze.""" + """ + Probe address and data can be set separately to utilize other + functions in this characterizer besides analyze. + """ + self.probe_address = probe_address self.probe_data = probe_data self.bitline_column = self.get_data_bit_column_number(probe_address, probe_data) @@ -954,6 +1048,7 @@ class delay(simulation): def get_data_bit_column_number(self, probe_address, probe_data): """Calculates bitline column number of data bit under test using bit position and mux size""" + if self.sram.col_addr_size>0: col_address = int(probe_address[0:self.sram.col_addr_size],2) else: @@ -963,6 +1058,7 @@ class delay(simulation): def get_address_row_number(self, probe_address): """Calculates wordline row number of data bit under test using address and column mux size""" + return int(probe_address[self.sram.col_addr_size:],2) def prepare_netlist(self): @@ -988,6 +1084,7 @@ class delay(simulation): def analysis_init(self, probe_address, probe_data): """Sets values which are dependent on the data address/bit being tested.""" + self.set_probe(probe_address, probe_data) self.create_graph() self.set_internal_spice_names() @@ -998,6 +1095,7 @@ class delay(simulation): """ Main function to characterize an SRAM for a table. Computes both delay and power characterization. """ + # Dict to hold all characterization values char_sram_data = {} self.analysis_init(probe_address, probe_data) @@ -1030,6 +1128,7 @@ class delay(simulation): def alter_lh_char_data(self, char_port_data): """Copies high-to-low data to low-to-high data to make them consistent on the same clock edge.""" + # This is basically a hack solution which should be removed/fixed later. for port in self.all_ports: char_port_data[port]['delay_lh'] = char_port_data[port]['delay_hl'] @@ -1037,6 +1136,7 @@ class delay(simulation): def simulate_loads_and_slews(self, slews, loads, leakage_offset): """Simulate all specified output loads and input slews pairs of all ports""" + measure_data = self.get_empty_measure_data_dict() # Set the target simulation ports to all available ports. This make sims slower but failed sims exit anyways. self.targ_read_ports = self.read_ports @@ -1060,6 +1160,7 @@ class delay(simulation): def calculate_inverse_address(self): """Determine dummy test address based on probe address and column mux size.""" + # The inverse address needs to share the same bitlines as the probe address as the trimming will remove all other bitlines # This is only an issue when there is a column mux and the address maps to different bitlines. column_addr = self.probe_address[:self.sram.col_addr_size] # do not invert this part @@ -1125,6 +1226,7 @@ class delay(simulation): self.probe_address,data_zeros) def get_available_port(self,get_read_port): + """Returns the first accessible read or write port. """ if get_read_port and len(self.read_ports) > 0: return self.read_ports[0] @@ -1142,6 +1244,7 @@ class delay(simulation): of the cycles to do a timing evaluation. The last time is the end of the simulation and does not need a rising edge. """ + # Using this requires setting at least one port to target for simulation. if len(self.targ_write_ports) == 0 and len(self.targ_read_ports) == 0: debug.error("No port selected for characterization.",1) @@ -1173,7 +1276,8 @@ class delay(simulation): self.gen_test_cycles_one_port(cur_read_port, cur_write_port) def analytical_delay(self, slews, loads): - """ Return the analytical model results for the SRAM. + """ + 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.") @@ -1206,6 +1310,7 @@ class delay(simulation): def analytical_power(self, slews, loads): """Get the dynamic and leakage power from the SRAM""" + # slews unused, only last load is used load = loads[-1] power = self.sram.analytical_power(self.corner, load) @@ -1218,6 +1323,7 @@ class delay(simulation): def gen_data(self): """ Generates the PWL data inputs for a simulation timing test. """ + for write_port in self.write_ports: for i in range(self.word_size): sig_name="{0}{1}_{2} ".format(self.din_name,write_port, i) @@ -1228,6 +1334,7 @@ class delay(simulation): Generates the address inputs for a simulation timing test. This alternates between all 1's and all 0's for the address. """ + for port in self.all_ports: for i in range(self.addr_size): sig_name = "{0}{1}_{2}".format(self.addr_name,port,i) @@ -1235,6 +1342,7 @@ class delay(simulation): def gen_control(self): """ Generates the control signals """ + for port in self.all_ports: self.stim.gen_pwl("CSB{0}".format(port), self.cycle_times, self.csb_values[port], self.period, self.slew, 0.05) if port in self.readwrite_ports: @@ -1243,6 +1351,7 @@ class delay(simulation): def get_empty_measure_data_dict(self): """Make a dict of lists for each type of delay and power measurement to append results to""" + measure_names = self.delay_meas_names + self.power_meas_names # Create list of dicts. List lengths is # of ports. Each dict maps the measurement names to lists. measure_data = [{mname:[] for mname in measure_names} for i in self.all_ports] From fe0db68965b76e6e778bbaac08060cd37dc9a455 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 24 Jul 2019 11:29:29 -0700 Subject: [PATCH 128/234] Refactor to share get_measurement_variant --- compiler/characterizer/delay.py | 38 ++++++++------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 9757fbbb..1274fafc 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -76,12 +76,13 @@ class delay(simulation): for meas in meas_list: name = meas.name.lower() debug.check(name not in name_set,("SPICE measurements must have unique names. " - "Duplicate name={}").format(name)) + "Duplicate name={}").format(name)) name_set.add(name) def create_read_port_measurement_objects(self): """Create the measurements used for read ports: delays, slews, powers""" - + + import pdb; pdb.set_trace() self.read_lib_meas = [] self.clk_frmt = "clk{0}" # Unformatted clock name targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) # Empty values are the port and probe data bit @@ -496,7 +497,7 @@ class delay(simulation): self.sf.close() - def get_read_measure_variants(self, port, measure_obj): + def get_measure_variants(self, port, measure_obj, measure_type=None): """ Checks the measurement object and calls respective function for related measurement inputs. @@ -506,7 +507,7 @@ class delay(simulation): if meas_type is delay_measure or meas_type is slew_measure: variant_tuple = self.get_delay_measure_variants(port, measure_obj) elif meas_type is power_measure: - variant_tuple = self.get_power_measure_variants(port, measure_obj, "read") + variant_tuple = self.get_power_measure_variants(port, measure_obj, measure_type) elif meas_type is voltage_when_measure: variant_tuple = self.get_volt_when_measure_variants(port, measure_obj) elif meas_type is voltage_at_measure: @@ -580,29 +581,9 @@ class delay(simulation): # add measure statements for delays/slews for meas_list in self.read_meas_lists: for measure in meas_list: - measure_variant_inp_tuple = self.get_read_measure_variants(port, measure) + measure_variant_inp_tuple = self.get_measure_variants(port, measure, "read") measure.write_measure(self.stim, measure_variant_inp_tuple) - def get_write_measure_variants(self, port, measure_obj): - """ - Checks the measurement object and calls respective function for related measurement inputs. - """ - - meas_type = type(measure_obj) - if meas_type is power_measure: - return self.get_power_measure_variants(port, measure_obj, "write") - elif meas_type is voltage_at_measure: - variant_tuple = self.get_volt_at_measure_variants(port, measure_obj) - else: - debug.error("Input function not defined for measurement type={}".format(meas_type)) - - # Removes port input from any object which does not use it. This shorthand only works if - # the measurement has port as the last input. Could be implemented by measurement type or - # remove entirely from measurement classes. - if not measure_obj.has_port: - variant_tuple = variant_tuple[:-1] - return variant_tuple - def write_delay_measures_write_port(self, port): """ @@ -612,7 +593,7 @@ class delay(simulation): # add measure statements for power for meas_list in self.write_meas_lists: for measure in meas_list: - measure_variant_inp_tuple = self.get_write_measure_variants(port, measure) + measure_variant_inp_tuple = self.get_measure_variants(port, measure, "write") measure.write_measure(self.stim, measure_variant_inp_tuple) def write_delay_measures(self): @@ -758,14 +739,13 @@ class delay(simulation): write_port_dict[measure.name] = measure.retrieve_measure(port=port) if not check_dict_values_is_float(write_port_dict): - debug.error("Failed to Measure Write Port Values:\n\t\t{0}".format(write_port_dict),1) # Printing the entire dict looks bad. + debug.error("Failed to Measure Write Port Values:\n\t\t{0}".format(write_port_dict),1) result[port].update(write_port_dict) for port in self.targ_read_ports: debug.info(2, "Checking read delay values for port {}".format(port)) read_port_dict = {} - # Get measurements from output file for measure in self.read_lib_meas: read_port_dict[measure.name] = measure.retrieve_measure(port=port) @@ -779,7 +759,7 @@ class delay(simulation): if not self.check_valid_delays(read_port_dict) or not success: return (False,{}) if not check_dict_values_is_float(read_port_dict): - debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) # Printing the entire dict looks bad. + debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) result[port].update(read_port_dict) From 3bcb79d9d5bf6a32d2ea703785eef74681f2ddb5 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 24 Jul 2019 15:01:20 -0700 Subject: [PATCH 129/234] Removed code for RW ports to not precharge on writes. Previously, the entire bitline was written where part was an old value and part was the wmask value. --- compiler/characterizer/functional.py | 13 ++++--------- compiler/modules/control_logic.py | 16 ++++++++-------- compiler/options.py | 2 +- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index ffb5f70d..6e9f81d4 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -30,10 +30,7 @@ class functional(simulation): # Seed the characterizer with a constant seed for unit tests if OPTS.is_unit_test: - random.seed(91218) - #12364? - #12365 - #91218 + random.seed(12345) if self.write_size is not None: self.num_wmasks = int(self.word_size / self.write_size) @@ -136,7 +133,7 @@ class functional(simulation): elif op == "write": addr = self.gen_addr() word = self.gen_data() - # print("w",self.t_current,addr,word) + # print("write",self.t_current,addr,word) # two ports cannot write to the same address if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) @@ -148,8 +145,6 @@ class functional(simulation): elif op == "partial_write": #write only to a word that's been written to (addr,old_word) = self.get_data() - # rand = random.randint(0,len(w_addrs)-1) - # addr = w_addrs[rand] word = self.gen_data() wmask = self.gen_wmask() new_word = word @@ -159,7 +154,7 @@ class functional(simulation): lower = bit * self.write_size upper = lower + self.write_size - 1 new_word = new_word[:lower] + old_word[lower:upper+1] + new_word[upper + 1:] - # print("partial_w",self.t_current,addr,wmask,word, "new", new_word) + # print("partial_w",self.t_current,addr,wmask,word, "partial_w_word:", new_word) # two ports cannot write to the same address if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) @@ -175,7 +170,7 @@ class functional(simulation): if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) else: - comment = self.gen_cycle_comment("read", word, addr, self.wmask, port, self.t_current) + # comment = self.gen_cycle_comment("read", word, addr, self.wmask, port, self.t_current) self.add_read_one_port(comment, addr, rw_read_din_data, "1"*self.num_wmasks, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) check += 1 diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index fd7a6b42..3607f826 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -628,14 +628,14 @@ class control_logic(design.design): offset=out_pos) def create_pen_row(self): - if self.port_type == "rw": - # input: gated_clk_bar, we_bar, output: pre_p_en - self.pre_p_en_inst=self.add_inst(name="and2_pre_p_en", - mod=self.and2) - self.connect_inst(["gated_clk_buf", "we_bar", "pre_p_en", "vdd", "gnd"]) - input_name = "pre_p_en" - else: - input_name = "gated_clk_buf" + # if self.port_type == "rw": + # # input: gated_clk_bar, we_bar, output: pre_p_en + # self.pre_p_en_inst=self.add_inst(name="and2_pre_p_en", + # mod=self.and2) + # self.connect_inst(["gated_clk_buf", "we_bar", "pre_p_en", "vdd", "gnd"]) + # input_name = "pre_p_en" + # else: + input_name = "gated_clk_buf" # input: pre_p_en, output: p_en_bar self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar", diff --git a/compiler/options.py b/compiler/options.py index a80790eb..3598c6f1 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -142,5 +142,5 @@ class options(optparse.Values): wordline_driver = "wordline_driver" write_driver_array = "write_driver_array" write_driver = "write_driver" - write_mask_array = "write_mask_array" + write_mask_and_array = "write_mask_and_array" From c8bbee884b6186a382f1559717080da296109308 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 24 Jul 2019 16:01:12 -0700 Subject: [PATCH 130/234] Removed layout related rw port's special pen. --- compiler/modules/control_logic.py | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 3607f826..45e1f643 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -647,11 +647,11 @@ class control_logic(design.design): x_off = self.control_x_offset (y_off,mirror)=self.get_offset(row) - if self.port_type == "rw": - offset = vector(x_off, y_off) - self.pre_p_en_inst.place(offset, mirror) - - x_off += self.and2.width + # if self.port_type == "rw": + # offset = vector(x_off, y_off) + # self.pre_p_en_inst.place(offset, mirror) + # + # x_off += self.and2.width offset = vector(x_off,y_off) self.p_en_bar_inst.place(offset, mirror) @@ -659,18 +659,18 @@ class control_logic(design.design): self.row_end_inst.append(self.p_en_bar_inst) def route_pen(self): - if self.port_type == "rw": - # Connect the NAND gate inputs to the bus - pre_p_en_in_map = zip(["A", "B"], ["gated_clk_buf", "we_bar"]) - self.connect_vertical_bus(pre_p_en_in_map, self.pre_p_en_inst, self.rail_offsets) - - out_pos = self.pre_p_en_inst.get_pin("Z").center() - in_pos = self.p_en_bar_inst.get_pin("A").lc() - mid1 = vector(out_pos.x,in_pos.y) - self.add_wire(("metal1","via1","metal2"),[out_pos,mid1,in_pos]) - else: - in_map = zip(["A"], ["gated_clk_buf"]) - self.connect_vertical_bus(in_map, self.p_en_bar_inst, self.rail_offsets) + # if self.port_type == "rw": + # # Connect the NAND gate inputs to the bus + # pre_p_en_in_map = zip(["A", "B"], ["gated_clk_buf", "we_bar"]) + # self.connect_vertical_bus(pre_p_en_in_map, self.pre_p_en_inst, self.rail_offsets) + # + # out_pos = self.pre_p_en_inst.get_pin("Z").center() + # in_pos = self.p_en_bar_inst.get_pin("A").lc() + # mid1 = vector(out_pos.x,in_pos.y) + # self.add_wire(("metal1","via1","metal2"),[out_pos,mid1,in_pos]) + # else: + in_map = zip(["A"], ["gated_clk_buf"]) + self.connect_vertical_bus(in_map, self.p_en_bar_inst, self.rail_offsets) self.connect_output(self.p_en_bar_inst, "Z", "p_en_bar") From fb60b51c7268ee1ddc8729a35deed950c38fa9b2 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 24 Jul 2019 16:57:04 -0700 Subject: [PATCH 131/234] Add check bits. Clean up logic. Move read/write bit check to next cycle. --- compiler/characterizer/delay.py | 71 ++++++++++++++++++------------ compiler/modules/bank.py | 2 +- compiler/modules/replica_column.py | 29 ++++++------ compiler/sram_factory.py | 1 + 4 files changed, 59 insertions(+), 44 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 1274fafc..921b73b9 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -82,7 +82,6 @@ class delay(simulation): def create_read_port_measurement_objects(self): """Create the measurements used for read ports: delays, slews, powers""" - import pdb; pdb.set_trace() self.read_lib_meas = [] self.clk_frmt = "clk{0}" # Unformatted clock name targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) # Empty values are the port and probe data bit @@ -161,18 +160,18 @@ class delay(simulation): def create_debug_measurement_objects(self): """Create debug measurement to help identify failures.""" - self.debug_volt_meas = [] + self.dout_volt_meas = [] for meas in self.delay_meas: # Output voltage measures - self.debug_volt_meas.append(voltage_at_measure("v_{}".format(meas.name), + self.dout_volt_meas.append(voltage_at_measure("v_{}".format(meas.name), meas.targ_name_no_port)) - self.debug_volt_meas[-1].meta_str = meas.meta_str + 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) self.sen_meas.meta_str = sram_op.READ_ZERO self.sen_meas.meta_add_delay = True - return self.debug_volt_meas+[self.sen_meas] + return self.dout_volt_meas+[self.sen_meas] def create_read_bit_measures(self): """ Adds bit measurements for read0 and read1 cycles """ @@ -213,7 +212,7 @@ class delay(simulation): (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, bit_row, bit_col) 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)) + "supported for characterization. Storage nets={}").format(storage_names)) q_name = cell_name+'.'+str(storage_names[0]) qbar_name = cell_name+'.'+str(storage_names[1]) @@ -559,8 +558,10 @@ class delay(simulation): meas_cycle = self.cycle_times[self.measure_cycles[port][volt_meas.meta_str]] - # Measurement occurs at the end of the period -> current period start + period - at_time = meas_cycle+self.period + # Measurement occurs slightly into the next period so we know that the value + # "stuck" after the end of the period -> current period start + 1.25*period + at_time = meas_cycle+1.25*self.period + return (at_time, port) def get_volt_when_measure_variants(self, port, volt_meas): @@ -732,6 +733,11 @@ class delay(simulation): # Loop through all targeted ports and collect delays and powers. result = [{} for i in self.all_ports] + + # First, check that the memory has the right values at the right times + if not self.check_bit_measures(): + return(False,{}) + for port in self.targ_write_ports: debug.info(2, "Checking write values for port {}".format(port)) write_port_dict = {} @@ -753,7 +759,6 @@ class delay(simulation): if not self.check_sen_measure(port): return (False,{}) success = self.check_read_debug_measures(port) - success = success and self.check_bit_measures() # Check timing for read ports. Power is only checked if it was read correctly if not self.check_valid_delays(read_port_dict) or not success: @@ -762,7 +767,7 @@ class delay(simulation): debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) result[port].update(read_port_dict) - + return (True,result) def check_sen_measure(self, port): @@ -782,7 +787,6 @@ class delay(simulation): # Currently, only check if the opposite than intended value was read during # the read cycles i.e. neither of these measurements should pass. - success = True # FIXME: these checks need to be re-done to be more robust against possible errors bl_vals = {} br_vals = {} @@ -794,29 +798,35 @@ class delay(simulation): br_vals[meas.meta_str] = val debug.info(2,"{}={}".format(meas.name,val)) - - bl_check = False - for meas in self.debug_volt_meas: + + for meas in self.dout_volt_meas: val = meas.retrieve_measure(port=port) debug.info(2,"{}={}".format(meas.name, val)) - if type(val) != float: - continue + debug.check(type(val)==float, "Error retrieving numeric measurement: {0} {1}".format(meas.name,val)) if meas.meta_str == sram_op.READ_ONE and val < self.vdd_voltage*0.1: - success = False + dout_success = False debug.info(1, "Debug measurement failed. Value {}V was read on read 1 cycle.".format(val)) - bl_check = self.check_bitline_meas(bl_vals[sram_op.READ_ONE], br_vals[sram_op.READ_ONE]) + bl_success = self.check_bitline_meas(bl_vals[sram_op.READ_ONE], br_vals[sram_op.READ_ONE]) elif meas.meta_str == sram_op.READ_ZERO and val > self.vdd_voltage*0.9: - success = False + dout_success = False debug.info(1, "Debug measurement failed. Value {}V was read on read 0 cycle.".format(val)) - bl_check = self.check_bitline_meas(br_vals[sram_op.READ_ONE], bl_vals[sram_op.READ_ONE]) - + bl_success = self.check_bitline_meas(br_vals[sram_op.READ_ONE], bl_vals[sram_op.READ_ONE]) + elif meas.meta_str == sram_op.READ_ONE and val > self.vdd_voltage*0.9: + dout_success = True + bl_success = True + elif meas.meta_str == sram_op.READ_ZERO and val < self.vdd_voltage*0.1: + dout_success = True + bl_success = True + else: + dout_success = False + bl_success = False # If the bitlines have a correct value while the output does not then that is a # sen error. FIXME: there are other checks that can be done to solidfy this conclusion. - if bl_check: + if not dout_success and bl_success: debug.error("Sense amp enable timing error. Increase the delay chain through the configuration file.",1) - return success + return dout_success def check_bit_measures(self): @@ -824,7 +834,6 @@ class delay(simulation): Checks the measurements which represent the internal storage voltages at the end of the read cycle. """ - success = True for polarity, meas_list in self.bit_meas.items(): for meas in meas_list: val = meas.retrieve_measure() @@ -839,10 +848,18 @@ class delay(simulation): elif (meas_cycle == sram_op.READ_ZERO and polarity == bit_polarity.INVERTING) or\ (meas_cycle == sram_op.READ_ONE and polarity == bit_polarity.NONINVERTING): success = val > self.vdd_voltage/2 + elif (meas_cycle == sram_op.WRITE_ZERO and polarity == bit_polarity.INVERTING) or\ + (meas_cycle == sram_op.WRITE_ONE and polarity == bit_polarity.NONINVERTING): + success = val > self.vdd_voltage/2 + elif (meas_cycle == sram_op.WRITE_ONE and polarity == bit_polarity.INVERTING) or\ + (meas_cycle == sram_op.WRITE_ZERO and polarity == bit_polarity.NONINVERTING): + success = val < self.vdd_voltage/2 + else: + success = False if not success: - debug.info(1,("Wrong value detected on probe bit during read cycle. " - "Check writes and control logic for bugs.\n measure={}, op={}, " - "bit_storage={}, V(bit)={}").format(meas.name, meas_cycle.name, polarity.name,val)) + debug.info(1,("Wrong value detected on probe bit during read/write cycle. " + "Check writes and control logic for bugs.\n measure={}, op={}, " + "bit_storage={}, V(bit)={}").format(meas.name, meas_cycle.name, polarity.name,val)) return success def check_bitline_meas(self, v_discharged_bl, v_charged_bl): diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 11e5adca..2f467961 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -404,7 +404,7 @@ class bank(design.design): def create_bitcell_array(self): """ Creating Bitcell Array """ - self.bitcell_array_inst=self.add_inst(name="bitcell_array", + self.bitcell_array_inst=self.add_inst(name="replica_bitcell_array", mod=self.bitcell_array) temp = [] diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index fdd726f5..b18c49fe 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -53,13 +53,13 @@ class replica_column(design.design): self.DRC_LVS() def add_pins(self): - column_list = self.cell.get_all_bitline_names() - for cell_column in column_list: - self.add_pin("{0}_{1}".format(cell_column,0)) - row_list = self.cell.get_all_wl_names() + + for bl_name in self.cell.get_all_bitline_names(): + self.add_pin("{0}_{1}".format(bl_name,0)) + for row in range(self.total_size): - for cell_row in row_list: - self.add_pin("{0}_{1}".format(cell_row,row)) + for wl_name in self.cell.get_all_wl_names(): + self.add_pin("{0}_{1}".format(wl_name,row)) self.add_pin("vdd") self.add_pin("gnd") @@ -112,21 +112,18 @@ class replica_column(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() - - for cell_column in column_list: - bl_pin = self.cell_inst[0].get_pin(cell_column) - self.add_layout_pin(text=cell_column, + for bl_name in self.cell.get_all_bitline_names(): + bl_pin = self.cell_inst[0].get_pin(bl_name) + self.add_layout_pin(text=bl_name, layer="metal2", offset=bl_pin.ll(), width=bl_pin.width(), height=self.height) for row in range(self.total_size): - for cell_row in row_list: - wl_pin = self.cell_inst[row].get_pin(cell_row) - self.add_layout_pin(text=cell_row+"_{0}".format(row), + for wl_name in self.cell.get_all_wl_names(): + wl_pin = self.cell_inst[row].get_pin(wl_name) + self.add_layout_pin(text="{0}_{1}".format(wl_name,row), layer="metal1", offset=wl_pin.ll().scale(0,1), width=self.width, @@ -159,4 +156,4 @@ class replica_column(design.design): for row, cell in self.cell_inst.items(): if row == selected_row: continue - self.graph_inst_exclude.add(cell) \ No newline at end of file + self.graph_inst_exclude.add(cell) diff --git a/compiler/sram_factory.py b/compiler/sram_factory.py index 0083841d..b5e46646 100644 --- a/compiler/sram_factory.py +++ b/compiler/sram_factory.py @@ -70,6 +70,7 @@ class sram_factory: # Use the default name if there are default arguments # This is especially for library cells so that the spice and gds files can be found. + print(module_type,len(kwargs)) if len(kwargs)>0: # Create a unique name and increment the index module_name = "{0}_{1}".format(module_type, self.module_indices[module_type]) From cfc04064af6783fa74ff7d81632dbae6928e923e Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 24 Jul 2019 16:57:57 -0700 Subject: [PATCH 132/234] Remove print. --- compiler/sram_factory.py | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/sram_factory.py b/compiler/sram_factory.py index b5e46646..0083841d 100644 --- a/compiler/sram_factory.py +++ b/compiler/sram_factory.py @@ -70,7 +70,6 @@ class sram_factory: # Use the default name if there are default arguments # This is especially for library cells so that the spice and gds files can be found. - print(module_type,len(kwargs)) if len(kwargs)>0: # Create a unique name and increment the index module_name = "{0}_{1}".format(module_type, self.module_indices[module_type]) From 2f03c594c52783454039479fd964190450059891 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 24 Jul 2019 16:59:19 -0700 Subject: [PATCH 133/234] Remove success initialization --- compiler/characterizer/delay.py | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 921b73b9..ff1bb4e7 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -653,7 +653,6 @@ class delay(simulation): # Clear any write target ports and set read port self.targ_write_ports = [port] self.targ_read_ports = [port] - success = False debug.info(1, "Trying feasible period: {0}ns on Port {1}".format(feasible_period, port)) self.period = feasible_period From 54b312eaf9735cb257ae0efe90eff4bf3915b58f Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 24 Jul 2019 17:00:38 -0700 Subject: [PATCH 134/234] Add return type --- 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 ff1bb4e7..d46ed3d9 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -724,7 +724,7 @@ class delay(simulation): self.stim.run_sim() - self.check_measurements() + return self.check_measurements() def check_measurements(self): """ Check the write and read measurements """ From 5452ed69e781d3f06e4b15971be8b10acc6e4892 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 25 Jul 2019 10:31:39 -0700 Subject: [PATCH 135/234] Always have a precharge. --- compiler/modules/control_logic.py | 11 ++++------- compiler/modules/port_data.py | 32 +++++++++++++++++-------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 602d289c..44573615 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -384,8 +384,7 @@ class control_logic(design.design): self.create_rbl_row() self.create_sen_row() self.create_delay() - if (self.port_type == "rw") or (self.port_type == "r") or self.words_per_row>1: - self.create_pen_row() + self.create_pen_row() @@ -419,9 +418,8 @@ class control_logic(design.design): if (self.port_type == "rw") or (self.port_type == "r"): self.place_rbl_row(row) row += 1 - if (self.port_type == "rw") or (self.port_type == "r") or self.words_per_row>1: - self.place_pen_row(row) - row += 1 + self.place_pen_row(row) + row += 1 if (self.port_type == "rw") or (self.port_type == "r"): self.place_sen_row(row) row += 1 @@ -450,8 +448,7 @@ class control_logic(design.design): if (self.port_type == "rw") or (self.port_type == "r"): self.route_rbl() self.route_sen() - if (self.port_type == "rw") or (self.port_type == "r") or self.words_per_row>1: - self.route_pen() + self.route_pen() self.route_clk_buf() self.route_gated_clk_bar() self.route_gated_clk_buf() diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 0b93b66d..d3b3662a 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -125,9 +125,9 @@ class port_data(design.design): self.route_sense_amp_to_column_mux_or_precharge_array(self.port) self.route_column_mux_to_precharge_array(self.port) else: - # write_driver -> (column_mux -> precharge) -> bitcell_array + # write_driver -> (column_mux ->) precharge -> bitcell_array self.route_write_driver_in(self.port) - self.route_write_driver_to_column_mux_or_bitcell_array(self.port) + self.route_write_driver_to_column_mux_or_precharge_array(self.port) self.route_column_mux_to_precharge_array(self.port) def route_supplies(self): @@ -150,8 +150,9 @@ class port_data(design.design): word_size=self.word_size, words_per_row=self.words_per_row) self.add_mod(self.sense_amp_array) - elif self.col_addr_size>0: - # Precharge is needed when we have a column mux + else: + # Precharge is needed when we have a column mux or for byte writes + # to prevent corruption of half-selected cells, so just always add it self.precharge_array = factory.create(module_type="precharge_array", columns=self.num_cols, bitcell_bl=self.bl_names[self.port], @@ -159,10 +160,6 @@ class port_data(design.design): self.add_mod(self.precharge_array) self.sense_amp_array = None - else: - self.precharge_array = None - self.sense_amp_array = None - if self.col_addr_size > 0: self.column_mux_array = factory.create(module_type="column_mux_array", @@ -401,12 +398,12 @@ class port_data(design.design): """ Routing of BL and BR between sense_amp and column mux or precharge array """ inst2 = self.sense_amp_array_inst - start_bit = 0 if self.col_addr_size>0: # Sense amp is connected to the col mux inst1 = self.column_mux_array_inst inst1_bl_name = "bl_out_{}" inst1_br_name = "br_out_{}" + start_bit = 0 else: # Sense amp is directly connected to the precharge array inst1 = self.precharge_array_inst @@ -421,8 +418,8 @@ class port_data(design.design): self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name, inst1_start_bit=start_bit) - def route_write_driver_to_column_mux_or_bitcell_array(self, port): - """ Routing of BL and BR between sense_amp and column mux or bitcell array """ + def route_write_driver_to_column_mux_or_precharge_array(self, port): + """ Routing of BL and BR between sense_amp and column mux or precharge array """ inst2 = self.write_driver_array_inst if self.col_addr_size>0: @@ -430,12 +427,19 @@ class port_data(design.design): inst1 = self.column_mux_array_inst inst1_bl_name = "bl_out_{}" inst1_br_name = "br_out_{}" + start_bit = 0 else: - # Write driver is directly connected to the bitcell array - return + # Sense amp is directly connected to the precharge array + inst1 = self.precharge_array_inst + inst1_bl_name = "bl_{}" + inst1_br_name = "br_{}" + if self.has_rbl() and self.port==0: + start_bit=1 + else: + start_bit=0 self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, - inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) + inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name, inst1_start_bit=start_bit) def route_write_driver_to_sense_amp(self, port): """ Routing of BL and BR between write driver and sense amp """ From 80df996720a0ac9d5a7b68ba6fe895548fcb6d6b Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 25 Jul 2019 11:19:16 -0700 Subject: [PATCH 136/234] Modify control logic for new RBL. --- compiler/modules/control_logic.py | 93 ++++++++++++------------------- 1 file changed, 36 insertions(+), 57 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 44573615..7843de93 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -126,16 +126,16 @@ class control_logic(design.design): self.add_mod(self.wl_en_driver) # w_en drives every write driver - self.w_en_driver = factory.create(module_type="pdriver", - fanout=self.word_size+8, - height=dff_height) - self.add_mod(self.w_en_driver) + self.wen_and2 = factory.create(module_type="pand2", + size=self.word_size+8, + height=dff_height) + self.add_mod(self.wen_and2) # s_en drives every sense amp - self.s_en_driver = factory.create(module_type="pdriver", - fanout=self.word_size, - height=dff_height) - self.add_mod(self.s_en_driver) + self.sen_and2 = factory.create(module_type="pand2", + size=self.word_size, + height=dff_height) + self.add_mod(self.sen_and2) # used to generate inverted signals with low fanout self.inv = factory.create(module_type="pinv", @@ -412,8 +412,8 @@ class control_logic(design.design): row += 1 if (self.port_type == "rw") or (self.port_type == "w"): self.place_wen_row(row) - height = self.w_en_inst.uy() - control_center_y = self.w_en_inst.uy() + height = self.w_en_gate_inst.uy() + control_center_y = self.w_en_gate_inst.uy() row += 1 if (self.port_type == "rw") or (self.port_type == "r"): self.place_rbl_row(row) @@ -639,14 +639,7 @@ class control_logic(design.design): self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") def create_pen_row(self): - if self.port_type == "rw": - # input: gated_clk_bar, we_bar, output: pre_p_en - self.pre_p_en_inst=self.add_inst(name="and2_pre_p_en", - mod=self.and2) - self.connect_inst(["gated_clk_buf", "we_bar", "pre_p_en", "vdd", "gnd"]) - input_name = "pre_p_en" - else: - input_name = "gated_clk_buf" + input_name = "gated_clk_buf" # input: pre_p_en, output: p_en_bar self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar", @@ -657,41 +650,24 @@ class control_logic(design.design): def place_pen_row(self,row): x_off = self.control_x_offset (y_off,mirror)=self.get_offset(row) - - if self.port_type == "rw": - offset = vector(x_off, y_off) - self.pre_p_en_inst.place(offset, mirror) - - x_off += self.and2.width - offset = vector(x_off,y_off) self.p_en_bar_inst.place(offset, mirror) self.row_end_inst.append(self.p_en_bar_inst) def route_pen(self): - if self.port_type == "rw": - # Connect the NAND gate inputs to the bus - pre_p_en_in_map = zip(["A", "B"], ["gated_clk_buf", "we_bar"]) - self.connect_vertical_bus(pre_p_en_in_map, self.pre_p_en_inst, self.rail_offsets) - - out_pos = self.pre_p_en_inst.get_pin("Z").center() - in_pos = self.p_en_bar_inst.get_pin("A").lc() - mid1 = vector(out_pos.x,in_pos.y) - self.add_wire(("metal1","via1","metal2"),[out_pos,mid1,in_pos]) - else: - in_map = zip(["A"], ["gated_clk_buf"]) - self.connect_vertical_bus(in_map, self.p_en_bar_inst, self.rail_offsets) + in_map = zip(["A"], ["gated_clk_buf"]) + self.connect_vertical_bus(in_map, self.p_en_bar_inst, self.rail_offsets) self.connect_output(self.p_en_bar_inst, "Z", "p_en_bar") def create_sen_row(self): """ Create the sense enable buffer. """ - # BUFFER FOR S_EN - # input: pre_s_en, output: s_en - self.s_en_inst=self.add_inst(name="buf_s_en", - mod=self.s_en_driver) - self.connect_inst(["pre_s_en", "s_en", "vdd", "gnd"]) + # GATE FOR S_EN + self.s_en_gate_inst = self.add_inst(name="buf_s_en_and", + mod=self.sen_and2) + self.connect_inst(["pre_s_en", "gated_clk_bar", "s_en", "vdd", "gnd"]) + def place_sen_row(self,row): """ @@ -702,19 +678,22 @@ class control_logic(design.design): (y_off,mirror)=self.get_offset(row) offset = vector(x_off, y_off) - self.s_en_inst.place(offset, mirror) + self.s_en_gate_inst.place(offset, mirror) - self.row_end_inst.append(self.s_en_inst) + self.row_end_inst.append(self.s_en_gate_inst) def route_sen(self): + + sen_map = zip(["B"], ["gated_clk_bar"]) + self.connect_vertical_bus(sen_map, self.s_en_gate_inst, self.rail_offsets) out_pos = self.delay_inst.get_pin("out").bc() - in_pos = self.s_en_inst.get_pin("A").lc() + in_pos = self.s_en_gate_inst.get_pin("A").lc() mid1 = vector(out_pos.x,in_pos.y) self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) - self.connect_output(self.s_en_inst, "Z", "s_en") + self.connect_output(self.s_en_gate_inst, "Z", "s_en") def create_wen_row(self): @@ -724,21 +703,21 @@ class control_logic(design.design): else: # No we for write-only reports, so use cs input_name = "cs" - - # BUFFER FOR W_EN - self.w_en_inst = self.add_inst(name="buf_w_en_buf", - mod=self.w_en_driver) - self.connect_inst([input_name, "w_en", "vdd", "gnd"]) + # GATE THE W_EN + self.w_en_gate_inst = self.add_inst(name="buf_w_en_and", + mod=self.wen_and2) + self.connect_inst([input_name, "gated_clk_bar", "w_en", "vdd", "gnd"]) + def place_wen_row(self,row): x_off = self.ctrl_dff_inst.width + self.internal_bus_width (y_off,mirror)=self.get_offset(row) offset = vector(x_off, y_off) - self.w_en_inst.place(offset, mirror) + self.w_en_gate_inst.place(offset, mirror) - self.row_end_inst.append(self.w_en_inst) + self.row_end_inst.append(self.w_en_gate_inst) def route_wen(self): if self.port_type == "rw": @@ -747,10 +726,10 @@ class control_logic(design.design): # No we for write-only reports, so use cs input_name = "cs" - wen_map = zip(["A"], [input_name]) - self.connect_vertical_bus(wen_map, self.w_en_inst, self.rail_offsets) + wen_map = zip(["A", "B"], [input_name, "gated_clk_bar"]) + self.connect_vertical_bus(wen_map, self.w_en_gate_inst, self.rail_offsets) - self.connect_output(self.w_en_inst, "Z", "w_en") + self.connect_output(self.w_en_gate_inst, "Z", "w_en") def create_dffs(self): self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs", @@ -917,7 +896,7 @@ class control_logic(design.design): last_stage_rise = stage_effort_list[-1].is_rise #Replica bitline stage, rbl_in -(rbl)-> pre_s_en - stage2_cout = self.s_en_driver.get_cin() + stage2_cout = self.sen_and2.get_cin() stage_effort_list += self.replica_bitline.determine_sen_stage_efforts(stage2_cout, last_stage_rise) last_stage_rise = stage_effort_list[-1].is_rise From 61ba23706c31d69d2edc0ae913d7ac4a2404d962 Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 25 Jul 2019 12:24:27 -0700 Subject: [PATCH 137/234] Removed comments for rw pen() and added a wmask func test. --- compiler/characterizer/functional.py | 6 +- compiler/characterizer/simulation.py | 20 +----- compiler/modules/control_logic.py | 25 +------- compiler/tests/22_psram_wmask_func_test.py | 73 ++++++++++++++++++++++ 4 files changed, 80 insertions(+), 44 deletions(-) create mode 100644 compiler/tests/22_psram_wmask_func_test.py diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 6e9f81d4..173feb6c 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -30,7 +30,7 @@ class functional(simulation): # Seed the characterizer with a constant seed for unit tests if OPTS.is_unit_test: - random.seed(12345) + random.seed(687234) if self.write_size is not None: self.num_wmasks = int(self.word_size / self.write_size) @@ -149,7 +149,7 @@ class functional(simulation): wmask = self.gen_wmask() new_word = word for bit in range(len(wmask)): - # Remove the bits of the word that's been written to + # AWhen the write mask's bits are 0, the old data values should appear in the new word if wmask[bit] == "0": lower = bit * self.write_size upper = lower + self.write_size - 1 @@ -170,7 +170,7 @@ class functional(simulation): if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) else: - # comment = self.gen_cycle_comment("read", word, addr, self.wmask, port, self.t_current) + comment = self.gen_cycle_comment("read", word, addr, self.wmask, port, self.t_current) self.add_read_one_port(comment, addr, rw_read_din_data, "1"*self.num_wmasks, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) check += 1 diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 52070a35..aea8f1cd 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -215,21 +215,6 @@ class simulation(): self.add_data(data,port) self.add_address(address,port) self.add_wmask(wmask,port) - - # - # def add_partial_write_one_port(self, comment, address, data, wmask, port): - # """ Add the control values for a write cycle (partial). Does not increment the period. """ - # debug.check(port in self.write_ports, - # "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, - # self.write_ports)) - # debug.info(2, comment) - # self.fn_cycle_comments.append(comment) - # - # self.add_control_one_port(port, "write") - # self.add_data(data, port) - # self.add_address(address, port) - # self.add_wmask(wmask,port) - def add_read_one_port(self, comment, address, din_data, wmask, port): """ Add the control values for a read cycle. Does not increment the period. """ @@ -320,8 +305,9 @@ class simulation(): pin_names.append("{0}{1}".format(tech.spice["clk"], port)) if self.write_size is not None: - for bit in range(self.num_wmasks): - pin_names.append("WMASK{0}_{1}".format(port,bit)) + for port in write_index: + for bit in range(self.num_wmasks): + pin_names.append("WMASK{0}_{1}".format(port,bit)) for read_output in read_index: for i in range(dbits): diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 45e1f643..bbd78a13 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -628,13 +628,6 @@ class control_logic(design.design): offset=out_pos) def create_pen_row(self): - # if self.port_type == "rw": - # # input: gated_clk_bar, we_bar, output: pre_p_en - # self.pre_p_en_inst=self.add_inst(name="and2_pre_p_en", - # mod=self.and2) - # self.connect_inst(["gated_clk_buf", "we_bar", "pre_p_en", "vdd", "gnd"]) - # input_name = "pre_p_en" - # else: input_name = "gated_clk_buf" # input: pre_p_en, output: p_en_bar @@ -646,29 +639,13 @@ class control_logic(design.design): def place_pen_row(self,row): x_off = self.control_x_offset (y_off,mirror)=self.get_offset(row) - - # if self.port_type == "rw": - # offset = vector(x_off, y_off) - # self.pre_p_en_inst.place(offset, mirror) - # - # x_off += self.and2.width - + offset = vector(x_off,y_off) self.p_en_bar_inst.place(offset, mirror) self.row_end_inst.append(self.p_en_bar_inst) def route_pen(self): - # if self.port_type == "rw": - # # Connect the NAND gate inputs to the bus - # pre_p_en_in_map = zip(["A", "B"], ["gated_clk_buf", "we_bar"]) - # self.connect_vertical_bus(pre_p_en_in_map, self.pre_p_en_inst, self.rail_offsets) - # - # out_pos = self.pre_p_en_inst.get_pin("Z").center() - # in_pos = self.p_en_bar_inst.get_pin("A").lc() - # mid1 = vector(out_pos.x,in_pos.y) - # self.add_wire(("metal1","via1","metal2"),[out_pos,mid1,in_pos]) - # else: in_map = zip(["A"], ["gated_clk_buf"]) self.connect_vertical_bus(in_map, self.p_en_bar_inst, self.rail_offsets) diff --git a/compiler/tests/22_psram_wmask_func_test.py b/compiler/tests/22_psram_wmask_func_test.py new file mode 100644 index 00000000..bbf28331 --- /dev/null +++ b/compiler/tests/22_psram_wmask_func_test.py @@ -0,0 +1,73 @@ +#!/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 + + +# @unittest.skip("SKIPPING psram_wmask_func_test") +class psram_wmask_func_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + OPTS.analytical_delay = False + OPTS.netlist_only = True + OPTS.trim_netlist = False + OPTS.bitcell = "bitcell_1w_1r" + OPTS.replica_bitcell = "replica_bitcell_1w_1r" + + OPTS.num_rw_ports = 0 + OPTS.num_w_ports = 1 + OPTS.num_r_ports = 1 + + # This is a hack to reload the characterizer __init__ with the spice version + from importlib import reload + import characterizer + reload(characterizer) + from characterizer import functional, delay + from sram_config import sram_config + c = sram_config(word_size=8, + num_words=16, + write_size=2, + num_banks=1) + c.words_per_row = 1 + c.recompute_sizes() + debug.info(1, + "Functional test for sram with {} bit words, {} words, {} words per row, {} bit writes, {} banks".format( + c.word_size, + c.num_words, + c.words_per_row, + c.write_size, + c.num_banks)) + s = factory.create(module_type="sram", sram_config=c) + tempspice = OPTS.openram_temp + "temp.sp" + s.sp_write(tempspice) + + corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) + + f = functional(s.s, tempspice, corner) + f.num_cycles = 10 + (fail, error) = f.run() + self.assertTrue(fail, error) + + 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()) \ No newline at end of file From de485182bc9be1e34e5fd05fad8ed09e06d52488 Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 25 Jul 2019 13:21:17 -0700 Subject: [PATCH 138/234] Cleaned up comments about wmask. --- compiler/characterizer/functional.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 173feb6c..f675bab5 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -30,7 +30,7 @@ class functional(simulation): # Seed the characterizer with a constant seed for unit tests if OPTS.is_unit_test: - random.seed(687234) + random.seed(12345) if self.write_size is not None: self.num_wmasks = int(self.word_size / self.write_size) @@ -51,7 +51,6 @@ class functional(simulation): self.read_check = [] def initialize_wmask(self): - #self.wmask = [None]*self.num_wmasks self.wmask = "" if self.write_size is not None: # initialize all wmask bits to 1 @@ -149,7 +148,8 @@ class functional(simulation): wmask = self.gen_wmask() new_word = word for bit in range(len(wmask)): - # AWhen the write mask's bits are 0, the old data values should appear in the new word + # When the write mask's bits are 0, the old data values should appear in the new word + # as to not overwrite the old values if wmask[bit] == "0": lower = bit * self.write_size upper = lower + self.write_size - 1 @@ -221,7 +221,7 @@ class functional(simulation): for bit in range(self.num_wmasks): rand = random.randint(0, 1) wmask += str(rand) - # prevent the wmask from having all bits on or off (not partial write) + # prevent the wmask from having all bits on or off (this is not a partial write) all_zeroes = True all_ones = True for bit in range(self.num_wmasks): @@ -245,14 +245,14 @@ class functional(simulation): data_bits = self.convert_to_bin(rand,False) return data_bits - # def gen_data(self): - # """ Generates a random word, either all 0 or all 1's, to write. """ - # rand = random.randint(0,1) - # bits = [] - # for bit in range(self.word_size): - # bits.append(rand) - # data_bits = ''.join(map(str,bits)) - # return data_bits + def gen_data_all_bits(self): + """ Generates a random word, either all 0's or all 1's, to write. """ + rand = random.randint(0,1) + bits = [] + for bit in range(self.word_size): + bits.append(rand) + data_bits = ''.join(map(str,bits)) + return data_bits def gen_addr(self): """ Generates a random address value to write to. """ From 0bb41b8a5df2d48ecc8836aee43b86b367535611 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 25 Jul 2019 13:25:58 -0700 Subject: [PATCH 139/234] Fix duplicate paths for timing checks --- compiler/base/graph_util.py | 35 ++++++++++++++++++++++--------- compiler/modules/control_logic.py | 11 ++++++++-- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/compiler/base/graph_util.py b/compiler/base/graph_util.py index b6ac4677..7cf8ee6f 100644 --- a/compiler/base/graph_util.py +++ b/compiler/base/graph_util.py @@ -10,8 +10,9 @@ from vector import vector from pin_layout import pin_layout class timing_graph(): - """Implements a directed graph - Nodes are currently just Strings. + """ + Implements a directed graph + Nodes are currently just Strings. """ def __init__(self): @@ -20,30 +21,34 @@ class timing_graph(): def add_edge(self, src_node, dest_node): """Adds edge to graph. Nodes added as well if they do not exist.""" + src_node = src_node.lower() dest_node = dest_node.lower() self.graph[src_node].add(dest_node) def add_node(self, node): """Add node to graph with no edges""" + node = node.lower() if not node in self.graph: self.graph[node] = set() def remove_edges(self, node): + """Helper function to remove edges, useful for removing vdd/gnd""" node = node.lower() self.graph[node] = set() - def get_all_paths(self, src_node, dest_node, rmv_rail_nodes=True): + def get_all_paths(self, src_node, dest_node, remove_rail_nodes=True, reduce_paths=True): """Traverse all paths from source to destination""" + src_node = src_node.lower() dest_node = dest_node.lower() - #Remove vdd and gnd by default - #Will require edits if separate supplies are implemented. - if rmv_rail_nodes: - #Names are also assumed. + # Remove vdd and gnd by default + # Will require edits if separate supplies are implemented. + if remove_rail_nodes: + # Names are also assumed. self.remove_edges('vdd') self.remove_edges('gnd') @@ -57,11 +62,20 @@ class timing_graph(): # Call the recursive helper function to print all paths self.get_all_paths_util(src_node, dest_node, visited, path) debug.info(2, "Paths found={}".format(len(self.all_paths))) - + + if reduce_paths: + self.reduce_paths() + return self.all_paths + + def reduce_paths(self): + """ Remove any path that is a subset of another path """ + + self.all_paths = [p1 for p1 in self.all_paths if not any(set(p1)<=set(p2) for p2 in self.all_paths if p1 is not p2)] def get_all_paths_util(self, cur_node, dest_node, visited, path): """Recursive function to find all paths in a Depth First Search manner""" + # Mark the current node as visited and store in path visited.add(cur_node) path.append(cur_node) @@ -72,7 +86,7 @@ class timing_graph(): self.all_paths.append(copy.deepcopy(path)) else: # If current vertex is not destination - #Recur for all the vertices adjacent to this vertex + # Recur for all the vertices adjacent to this vertex for node in self.graph[cur_node]: if node not in visited: self.get_all_paths_util(node, dest_node, visited, path) @@ -83,4 +97,5 @@ class timing_graph(): def __str__(self): """ override print function output """ - return "Nodes: {}\nEdges:{} ".format(list(self.graph), self.graph) \ No newline at end of file + + return "Nodes: {}\nEdges:{} ".format(list(self.graph), self.graph) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 7843de93..ca65b57b 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -909,6 +909,7 @@ class control_logic(design.design): def get_wl_sen_delays(self): """Gets a list of the stages and delays in order of their path.""" + if self.sen_stage_efforts == None or self.wl_stage_efforts == None: debug.error("Model delays not calculated for SRAM.", 1) wl_delays = logical_effort.calculate_delays(self.wl_stage_efforts) @@ -917,6 +918,7 @@ class control_logic(design.design): def analytical_delay(self, corner, slew, load): """Gets the analytical delay from clk input to wl_en output""" + stage_effort_list = [] #Calculate the load on clk_buf_bar ext_clk_buf_cout = self.sram.get_clk_bar_cin() @@ -944,8 +946,10 @@ class control_logic(design.design): return stage_effort_list def get_clk_buf_cin(self): - """Get the loads that are connected to the buffered clock. - Includes all the DFFs and some logic.""" + """ + Get the loads that are connected to the buffered clock. + Includes all the DFFs and some logic. + """ #Control logic internal load int_clk_buf_cap = self.inv.get_cin() + self.ctrl_dff_array.get_clk_cin() + self.and2.get_cin() @@ -957,6 +961,7 @@ class control_logic(design.design): def get_gated_clk_bar_cin(self): """Get intermediates net gated_clk_bar's capacitance""" + total_cin = 0 total_cin += self.wl_en_driver.get_cin() if self.port_type == 'rw': @@ -965,4 +970,6 @@ class control_logic(design.design): def graph_exclude_dffs(self): """Exclude dffs from graph as they do not represent critical path""" + self.graph_inst_exclude.add(self.ctrl_dff_inst) + self.graph_inst_exclude.add(self.w_en_gate_inst) From c8c4d05bba45229f1f152935f987882fc71efafe Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 25 Jul 2019 14:18:08 -0700 Subject: [PATCH 140/234] Fix some regression fails. --- compiler/modules/replica_bitcell_array.py | 4 +-- compiler/tests/21_hspice_delay_test.py | 41 +++++++++++------------ compiler/tests/21_model_delay_test.py | 9 ++--- compiler/tests/21_ngspice_delay_test.py | 41 +++++++++++------------ technology/freepdk45/tech/tech.py | 18 +++++----- technology/scn3me_subm/tech/tech.py | 18 ++++------ 6 files changed, 63 insertions(+), 68 deletions(-) diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 63224033..c748e83d 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -393,7 +393,7 @@ class replica_bitcell_array(design.design): # Dynamic Power from Bitline bl_wire = self.gen_bl_wire() cell_load = 2 * bl_wire.return_input_cap() - bl_swing = parameter["rbl_height_percentage"] + bl_swing = OPTS.rbl_delay_percentage freq = spice["default_event_rate"] bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing) @@ -451,4 +451,4 @@ class replica_bitcell_array(design.design): def get_cell_name(self, inst_name, row, col): """Gets the spice name of the target bitcell.""" - return self.bitcell_array.get_cell_name(inst_name+'.x'+self.bitcell_array_inst.name, row, col) \ No newline at end of file + return self.bitcell_array.get_cell_name(inst_name+'.x'+self.bitcell_array_inst.name, row, col) diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index e6ea5a32..9a72edee 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -61,28 +61,27 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_hl': [0.2121267], - 'delay_lh': [0.2121267], - 'leakage_power': 0.0023761999999999998, - 'min_period': 0.43, - 'read0_power': [0.5139368], - 'read1_power': [0.48940979999999995], - 'slew_hl': [0.0516745], - 'slew_lh': [0.0516745], - 'write0_power': [0.46267169999999996], - 'write1_power': [0.4670826]} + golden_data = {'delay_hl': [0.2192123], + 'delay_lh': [0.2192123], + 'leakage_power': 0.006427800000000001, + 'min_period': 0.527, + 'read0_power': [0.4519997], + 'read1_power': [0.42609269999999994], + 'slew_hl': [0.10185999999999999], + 'slew_lh': [0.10185999999999999], + 'write0_power': [0.49744869999999997], + 'write1_power': [0.4460337]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.288], - 'delay_lh': [1.288], - 'leakage_power': 0.0273896, - 'min_period': 2.578, - 'read0_power': [16.9996], - 'read1_power': [16.2616], - 'slew_hl': [0.47891700000000004], - 'slew_lh': [0.47891700000000004], - 'write0_power': [16.0656], - 'write1_power': [16.2616]} - + golden_data = {'delay_hl': [1.4249], + 'delay_lh': [1.4249], + 'leakage_power': 0.7340832, + 'min_period': 3.125, + 'read0_power': [14.8099], + 'read1_power': [14.0866], + 'slew_hl': [0.7280485], + 'slew_lh': [0.7280485], + 'write0_power': [16.865], + 'write1_power': [14.8288]} else: self.assertTrue(False) # other techs fail # Check if no too many or too few results diff --git a/compiler/tests/21_model_delay_test.py b/compiler/tests/21_model_delay_test.py index a775c086..51edb48f 100755 --- a/compiler/tests/21_model_delay_test.py +++ b/compiler/tests/21_model_delay_test.py @@ -15,8 +15,9 @@ from globals import OPTS from sram_factory import factory import debug -class model_delay_sram_test(openram_test): - +class model_delay_test(openram_test): + """ Compare the accuracy of the analytical model with a spice simulation. """ + def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) OPTS.analytical_delay = False @@ -61,9 +62,9 @@ class model_delay_sram_test(openram_test): debug.info(1,"Spice Delays={}".format(spice_delays)) debug.info(1,"Model Delays={}".format(model_delays)) if OPTS.tech_name == "freepdk45": - error_tolerance = .25 + error_tolerance = 0.25 elif OPTS.tech_name == "scn4m_subm": - error_tolerance = .25 + error_tolerance = 0.25 else: self.assertTrue(False) # other techs fail # Check if no too many or too few results diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 1ff14250..e57ad120 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -54,28 +54,27 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_hl': [0.2108836], - 'delay_lh': [0.2108836], - 'leakage_power': 0.001564799, - 'min_period': 0.508, - 'read0_power': [0.43916689999999997], - 'read1_power': [0.4198608], - 'slew_hl': [0.0455126], - 'slew_lh': [0.0455126], - 'write0_power': [0.40681890000000004], - 'write1_power': [0.4198608]} + golden_data = {'delay_hl': [0.2265453], + 'delay_lh': [0.2265453], + 'leakage_power': 0.003688569, + 'min_period': 0.547, + 'read0_power': [0.4418831], + 'read1_power': [0.41914969999999996], + 'slew_hl': [0.103665], + 'slew_lh': [0.103665], + 'write0_power': [0.48889660000000007], + 'write1_power': [0.4419755]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.5747600000000002], - 'delay_lh': [1.5747600000000002], - 'leakage_power': 0.00195795, - 'min_period': 3.281, - 'read0_power': [14.92874], - 'read1_power': [14.369810000000001], - 'slew_hl': [0.49631959999999997], - 'slew_lh': [0.49631959999999997], - 'write0_power': [13.79953], - 'write1_power': [14.369810000000001]} - + golden_data = {'delay_hl': [1.718183], + 'delay_lh': [1.718183], + 'leakage_power': 0.1342958, + 'min_period': 3.75, + 'read0_power': [14.1499], + 'read1_power': [13.639719999999999], + 'slew_hl': [0.7794919], + 'slew_lh': [0.7794919], + 'write0_power': [15.978829999999999], + 'write1_power': [14.128079999999999]} else: self.assertTrue(False) # other techs fail diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 84d1f2db..77ddda76 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -345,11 +345,11 @@ spice["msflop_leakage"] = 1 # Leakage power of flop in nW spice["flop_para_cap"] = 2 # Parasitic Output capacitance in fF spice["default_event_rate"] = 100 # Default event activity of every gate. MHz -spice["flop_transition_prob"] = .5 # Transition probability of inverter. -spice["inv_transition_prob"] = .5 # Transition probability of inverter. -spice["nand2_transition_prob"] = .1875 # Transition probability of 2-input nand. -spice["nand3_transition_prob"] = .1094 # Transition probability of 3-input nand. -spice["nor2_transition_prob"] = .1875 # Transition probability of 2-input nor. +spice["flop_transition_prob"] = 0.5 # Transition probability of inverter. +spice["inv_transition_prob"] = 0.5 # Transition probability of inverter. +spice["nand2_transition_prob"] = 0.1875 # Transition probability of 2-input nand. +spice["nand3_transition_prob"] = 0.1094 # Transition probability of 3-input nand. +spice["nor2_transition_prob"] = 0.1875 # Transition probability of 2-input nor. #Parameters related to sense amp enable timing and delay chain/RBL sizing parameter['le_tau'] = 2.25 #In pico-seconds. @@ -357,10 +357,10 @@ parameter['cap_relative_per_ff'] = 7.5 #Units of Relative Capacitance/ Femt parameter["dff_clk_cin"] = 30.6 #relative capacitance parameter["6tcell_wl_cin"] = 3 #relative capacitance parameter["min_inv_para_delay"] = 2.4 #Tau delay units -parameter["sa_en_pmos_size"] = .72 #micro-meters -parameter["sa_en_nmos_size"] = .27 #micro-meters -parameter["sa_inv_pmos_size"] = .54 #micro-meters -parameter["sa_inv_nmos_size"] = .27 #micro-meters +parameter["sa_en_pmos_size"] = 0.72 #micro-meters +parameter["sa_en_nmos_size"] = 0.27 #micro-meters +parameter["sa_inv_pmos_size"] = 0.54 #micro-meters +parameter["sa_inv_nmos_size"] = 0.27 #micro-meters parameter['bitcell_drain_cap'] = 0.1 #In Femto-Farad, approximation of drain capacitance ################################################### diff --git a/technology/scn3me_subm/tech/tech.py b/technology/scn3me_subm/tech/tech.py index fb7524c1..2d9abe16 100755 --- a/technology/scn3me_subm/tech/tech.py +++ b/technology/scn3me_subm/tech/tech.py @@ -284,26 +284,22 @@ spice["msflop_leakage"] = 1 # Leakage power of flop in nW spice["flop_para_cap"] = 2 # Parasitic Output capacitance in fF spice["default_event_rate"] = 100 # Default event activity of every gate. MHz -spice["flop_transition_prob"] = .5 # Transition probability of inverter. -spice["inv_transition_prob"] = .5 # Transition probability of inverter. -spice["nand2_transition_prob"] = .1875 # Transition probability of 2-input nand. -spice["nand3_transition_prob"] = .1094 # Transition probability of 3-input nand. -spice["nor2_transition_prob"] = .1875 # Transition probability of 2-input nor. +spice["flop_transition_prob"] = 0.5 # Transition probability of inverter. +spice["inv_transition_prob"] = 0.5 # Transition probability of inverter. +spice["nand2_transition_prob"] = 0.1875 # Transition probability of 2-input nand. +spice["nand3_transition_prob"] = 0.1094 # Transition probability of 3-input nand. +spice["nor2_transition_prob"] = 0.1875 # Transition probability of 2-input nor. #Logical Effort relative values for the Handmade cells parameter['le_tau'] = 23 #In pico-seconds. -parameter["min_inv_para_delay"] = .73 #In relative delay units -parameter['cap_relative_per_ff'] = .91 #Units of Relative Capacitance/ Femto-Farad -parameter["static_delay_stages"] = 4 -parameter["static_fanout_per_stage"] = 3 -parameter["static_fanout_list"] = parameter["static_delay_stages"]*[parameter["static_fanout_per_stage"]] +parameter["min_inv_para_delay"] = 0.73 #In relative delay units +parameter['cap_relative_per_ff'] = 0.91 #Units of Relative Capacitance/ Femto-Farad parameter["dff_clk_cin"] = 27.5 #In relative capacitance units parameter["6tcell_wl_cin"] = 2 #In relative capacitance units parameter["sa_en_pmos_size"] = 24*_lambda_ parameter["sa_en_nmos_size"] = 9*_lambda_ parameter["sa_inv_pmos_size"] = 18*_lambda_ parameter["sa_inv_nmos_size"] = 9*_lambda_ -parameter["rbl_height_percentage"] = .5 #Height of RBL compared to bitcell array parameter['bitcell_drain_cap'] = 0.2 #In Femto-Farad, approximation of drain capacitance ################################################### From d5419f99f66b49cc5f1312b8a978f556d78cfdf3 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 25 Jul 2019 14:46:33 -0700 Subject: [PATCH 141/234] Skip model tests for now --- compiler/tests/23_lib_sram_model_corners_test.py | 3 ++- compiler/tests/23_lib_sram_model_test.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/tests/23_lib_sram_model_corners_test.py b/compiler/tests/23_lib_sram_model_corners_test.py index 6b6a02f5..51fcbca6 100755 --- a/compiler/tests/23_lib_sram_model_corners_test.py +++ b/compiler/tests/23_lib_sram_model_corners_test.py @@ -14,7 +14,8 @@ import globals from globals import OPTS import debug -class model_corners_lib_test(openram_test): +@unittest.skip("SKIPPING 23_lib_sram_model_corners_test") +class lib_model_corners_lib_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) diff --git a/compiler/tests/23_lib_sram_model_test.py b/compiler/tests/23_lib_sram_model_test.py index 8740e2d7..fd75dc25 100755 --- a/compiler/tests/23_lib_sram_model_test.py +++ b/compiler/tests/23_lib_sram_model_test.py @@ -14,7 +14,8 @@ import globals from globals import OPTS import debug -class lib_test(openram_test): +@unittest.skip("SKIPPING 23_lib_sram_model_test") +class lib_sram_model_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) From 88c399bc6cb92a6d51ea175067bffde88fd94713 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 25 Jul 2019 14:49:11 -0700 Subject: [PATCH 142/234] Skip prune test for now --- compiler/tests/23_lib_sram_prune_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/tests/23_lib_sram_prune_test.py b/compiler/tests/23_lib_sram_prune_test.py index 92070562..1fc5a66b 100755 --- a/compiler/tests/23_lib_sram_prune_test.py +++ b/compiler/tests/23_lib_sram_prune_test.py @@ -14,7 +14,8 @@ import globals from globals import OPTS import debug -class lib_test(openram_test): +@unittest.skip("SKIPPING 23_lib_sram_prune_test") +class lib_sram_prune_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) From 20d9c30a648a0ada327819426500be9905a8391b Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 25 Jul 2019 14:55:42 -0700 Subject: [PATCH 143/234] Use non-analytical models for now --- compiler/tests/config_freepdk45_back_end.py | 2 +- compiler/tests/config_freepdk45_front_end.py | 2 +- compiler/tests/config_scn3me_subm_back_end.py | 1 + compiler/tests/config_scn3me_subm_front_end.py | 2 ++ compiler/tests/config_scn4m_subm_back_end.py | 1 + compiler/tests/config_scn4m_subm_front_end.py | 2 ++ 6 files changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/tests/config_freepdk45_back_end.py b/compiler/tests/config_freepdk45_back_end.py index f30a5658..68417a3b 100644 --- a/compiler/tests/config_freepdk45_back_end.py +++ b/compiler/tests/config_freepdk45_back_end.py @@ -16,5 +16,5 @@ temperatures = [25] inline_lvsdrc = True route_supplies = True check_lvsdrc = True - +analytical_delay = False diff --git a/compiler/tests/config_freepdk45_front_end.py b/compiler/tests/config_freepdk45_front_end.py index 309a47eb..1886d808 100644 --- a/compiler/tests/config_freepdk45_front_end.py +++ b/compiler/tests/config_freepdk45_front_end.py @@ -13,6 +13,6 @@ process_corners = ["TT"] supply_voltages = [1.0] temperatures = [25] - +analytical_delay = False diff --git a/compiler/tests/config_scn3me_subm_back_end.py b/compiler/tests/config_scn3me_subm_back_end.py index 826a50ae..f9c23417 100644 --- a/compiler/tests/config_scn3me_subm_back_end.py +++ b/compiler/tests/config_scn3me_subm_back_end.py @@ -16,6 +16,7 @@ temperatures = [25] route_supplies = True check_lvsdrc = True inline_lvsdrc = True +analytical_delay = False drc_name = "magic" lvs_name = "netgen" diff --git a/compiler/tests/config_scn3me_subm_front_end.py b/compiler/tests/config_scn3me_subm_front_end.py index c73fc84e..40504a18 100644 --- a/compiler/tests/config_scn3me_subm_front_end.py +++ b/compiler/tests/config_scn3me_subm_front_end.py @@ -13,6 +13,8 @@ process_corners = ["TT"] supply_voltages = [5.0] temperatures = [25] +analytical_delay = False + drc_name = "magic" lvs_name = "netgen" pex_name = "magic" diff --git a/compiler/tests/config_scn4m_subm_back_end.py b/compiler/tests/config_scn4m_subm_back_end.py index 09d7a087..35e4cd91 100644 --- a/compiler/tests/config_scn4m_subm_back_end.py +++ b/compiler/tests/config_scn4m_subm_back_end.py @@ -16,6 +16,7 @@ temperatures = [25] route_supplies = True check_lvsdrc = True inline_lvsdrc = True +analytical_delay = False drc_name = "magic" lvs_name = "netgen" diff --git a/compiler/tests/config_scn4m_subm_front_end.py b/compiler/tests/config_scn4m_subm_front_end.py index 142191a0..5004580e 100644 --- a/compiler/tests/config_scn4m_subm_front_end.py +++ b/compiler/tests/config_scn4m_subm_front_end.py @@ -13,6 +13,8 @@ process_corners = ["TT"] supply_voltages = [5.0] temperatures = [25] +analytical_delay = False + drc_name = "magic" lvs_name = "netgen" pex_name = "magic" From 8ebc568e8bc45068fd2e3b757aa6c7651394f293 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 26 Jul 2019 08:33:06 -0700 Subject: [PATCH 144/234] Minor cleanup. Skip more tests until analytical fixed. --- compiler/characterizer/delay.py | 15 +++++++++------ compiler/tests/21_model_delay_test.py | 1 + compiler/tests/30_openram_back_end_test.py | 2 +- compiler/tests/30_openram_front_end_test.py | 3 ++- compiler/tests/config_scn4m_subm_front_end.py | 2 -- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index d46ed3d9..e36cc1ed 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -750,18 +750,21 @@ class delay(simulation): for port in self.targ_read_ports: debug.info(2, "Checking read delay values for port {}".format(port)) + # Check sen timing, then bitlines, then general measurements. + if not self.check_sen_measure(port): + return (False,{}) + + if not self.check_read_debug_measures(port): + return (False,{}) + + # Check timing for read ports. Power is only checked if it was read correctly read_port_dict = {} for measure in self.read_lib_meas: read_port_dict[measure.name] = measure.retrieve_measure(port=port) - # Check sen timing, then bitlines, then general measurements. - if not self.check_sen_measure(port): + if not self.check_valid_delays(read_port_dict): return (False,{}) - success = self.check_read_debug_measures(port) - # Check timing for read ports. Power is only checked if it was read correctly - if not self.check_valid_delays(read_port_dict) or not success: - return (False,{}) if not check_dict_values_is_float(read_port_dict): debug.error("Failed to Measure Read Port Values:\n\t\t{0}".format(read_port_dict),1) diff --git a/compiler/tests/21_model_delay_test.py b/compiler/tests/21_model_delay_test.py index 51edb48f..3b43e789 100755 --- a/compiler/tests/21_model_delay_test.py +++ b/compiler/tests/21_model_delay_test.py @@ -15,6 +15,7 @@ from globals import OPTS from sram_factory import factory import debug +@unittest.skip("SKIPPING 21_model_delay_test") class model_delay_test(openram_test): """ Compare the accuracy of the analytical model with a spice simulation. """ diff --git a/compiler/tests/30_openram_back_end_test.py b/compiler/tests/30_openram_back_end_test.py index d375d605..c579bde6 100755 --- a/compiler/tests/30_openram_back_end_test.py +++ b/compiler/tests/30_openram_back_end_test.py @@ -16,7 +16,7 @@ from sram_factory import factory import debug import getpass -class openram_test(openram_test): +class openram_back_end_test(openram_test): def runTest(self): OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) diff --git a/compiler/tests/30_openram_front_end_test.py b/compiler/tests/30_openram_front_end_test.py index 5252db7b..2be14001 100755 --- a/compiler/tests/30_openram_front_end_test.py +++ b/compiler/tests/30_openram_front_end_test.py @@ -16,7 +16,8 @@ from sram_factory import factory import debug import getpass -class openram_test(openram_test): +@unittest.skip("SKIPPING 30_openram_front_end_test") +class openram_front_end_test(openram_test): def runTest(self): OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME")) diff --git a/compiler/tests/config_scn4m_subm_front_end.py b/compiler/tests/config_scn4m_subm_front_end.py index 5004580e..142191a0 100644 --- a/compiler/tests/config_scn4m_subm_front_end.py +++ b/compiler/tests/config_scn4m_subm_front_end.py @@ -13,8 +13,6 @@ process_corners = ["TT"] supply_voltages = [5.0] temperatures = [25] -analytical_delay = False - drc_name = "magic" lvs_name = "netgen" pex_name = "magic" From dc46d07ca3f5bde8c1196b16c888fd43f4033b43 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Fri, 26 Jul 2019 14:20:47 -0700 Subject: [PATCH 145/234] Removed unused code for input loads --- compiler/modules/bitcell_array.py | 9 --------- compiler/modules/replica_bitcell_array.py | 18 ------------------ 2 files changed, 27 deletions(-) diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 293d3e08..75c831d7 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -197,15 +197,6 @@ class bitcell_array(design.design): bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell return bl_wire - def output_load(self, bl_pos=0): - bl_wire = self.gen_bl_wire() - return bl_wire.wire_c # sense amp only need to charge small portion of the bl - # set as one segment for now - - def input_load(self): - wl_wire = self.gen_wl_wire() - return wl_wire.return_input_cap() - def get_wordline_cin(self): """Get the relative input capacitance from the wordline connections in all the bitcell""" #A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 0bf635ca..0d72891d 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -330,15 +330,6 @@ class replica_bitcell_array(design.design): cell_power.leakage * self.column_size * self.row_size) return total_power - def gen_wl_wire(self): - if OPTS.netlist_only: - width = 0 - else: - width = self.width - wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_metal1")) - wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell - return wl_wire - def gen_bl_wire(self): if OPTS.netlist_only: height = 0 @@ -349,15 +340,6 @@ class replica_bitcell_array(design.design): bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell return bl_wire - def output_load(self, bl_pos=0): - bl_wire = self.gen_bl_wire() - return bl_wire.wire_c # sense amp only need to charge small portion of the bl - # set as one segment for now - - def input_load(self): - wl_wire = self.gen_wl_wire() - return wl_wire.return_input_cap() - def get_wordline_cin(self): """Get the relative input capacitance from the wordline connections in all the bitcell""" #A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns From 3327fa58c02802935ccb09356c03ed908b6a30db Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 26 Jul 2019 14:49:53 -0700 Subject: [PATCH 146/234] Add some signal names to functional test comments --- compiler/characterizer/delay.py | 8 +- compiler/characterizer/functional.py | 167 ++++++++++++++++++++++++++- 2 files changed, 167 insertions(+), 8 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index e36cc1ed..9e203961 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -135,10 +135,10 @@ class delay(simulation): 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 @@ -255,8 +255,8 @@ class delay(simulation): """Sets important names for characterization such as Sense amp enable and internal bit nets.""" port = 0 - self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), \ - '{}{}_{}'.format(self.dout_name, port, self.probe_data)) + self.graph.get_all_paths('{}{}'.format(tech.spice["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)) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 939ecf96..66737ce1 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -15,9 +15,10 @@ from .stimuli import * from .charutils import * import utils from globals import OPTS - from .simulation import simulation from .delay import delay +import graph_util +from sram_factory import factory class functional(simulation): """ @@ -34,10 +35,13 @@ class functional(simulation): self.set_corner(corner) self.set_spice_constants() - #self.set_feasible_period(sram, spfile, corner) self.set_stimulus_variables() - self.create_signal_names() + # For the debug signal names + self.create_signal_names() + self.add_graph_exclusions() + self.create_graph() + self.set_internal_spice_names() # Number of checks can be changed self.num_cycles = 2 @@ -230,9 +234,17 @@ class functional(simulation): for bit in range(self.word_size): sig_name="{0}{1}_{2} ".format(self.dout_name, port, bit) self.sf.write("CD{0}{1} {2} 0 {3}f\n".format(port, bit, sig_name, self.load)) + + # Write important signals to stim file + self.sf.write("\n\n* Important signals for debug\n") + self.sf.write("* bl: {}\n".format(self.bl_name)) + self.sf.write("* br: {}\n".format(self.br_name)) + self.sf.write("* s_en: {}\n".format(self.sen_name)) + self.sf.write("* q: {}\n".format(self.q_name)) + self.sf.write("* qbar: {}\n".format(self.qbar_name)) # Write debug comments to stim file - self.sf.write("\n\n * Sequence of operations\n") + self.sf.write("\n\n* Sequence of operations\n") for comment in self.fn_cycle_comments: self.sf.write("*{}\n".format(comment)) @@ -281,4 +293,151 @@ class functional(simulation): self.stim.write_control(self.cycle_times[-1] + self.period) self.sf.close() + # FIXME: refactor to share with delay.py + def add_graph_exclusions(self): + """Exclude portions of SRAM from timing graph which are not relevant""" + + # other initializations can only be done during analysis when a bit has been selected + # for testing. + self.sram.bank.graph_exclude_precharge() + self.sram.graph_exclude_addr_dff() + self.sram.graph_exclude_data_dff() + self.sram.graph_exclude_ctrl_dffs() + self.sram.bank.bitcell_array.graph_exclude_replica_col_bits() + + # FIXME: refactor to share with delay.py + def create_graph(self): + """Creates timing graph to generate the timing paths for the SRAM output.""" + + self.sram.bank.bitcell_array.init_graph_params() # Removes previous bit exclusions + # Does wordline=0 and column=0 just for debug names + self.sram.bank.bitcell_array.graph_exclude_bits(0, 0) + + # Generate new graph every analysis as edges might change depending on test bit + self.graph = graph_util.timing_graph() + self.sram_spc_name = "X{}".format(self.sram.name) + self.sram.build_graph(self.graph,self.sram_spc_name,self.pins) + # FIXME: refactor to share with delay.py + def set_internal_spice_names(self): + """Sets important names for characterization such as Sense amp enable and internal bit nets.""" + + port = 0 + self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), + '{}{}_{}'.format(self.dout_name, port, 0)) + + 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) + debug.info(2,"bl name={}, br name={}".format(self.bl_name,self.br_name)) + + self.q_name,self.qbar_name = self.get_bit_name() + debug.info(2,"q name={}\nqbar name={}".format(self.bl_name,self.br_name)) + + def get_bit_name(self): + """ Get a bit cell name """ + (cell_name, cell_inst) = self.sram.get_cell_name(self.sram.name, 0, 0) + 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]) + + return (q_name,qbar_name) + + # FIXME: refactor to share with delay.py + def get_sen_name(self, paths): + """ + Gets the signal name associated with the sense amp enable from input paths. + Only expects a single path to contain the sen signal name. + """ + + sa_mods = factory.get_mods(OPTS.sense_amp) + # Any sense amp instantiated should be identical, any change to that + # will require some identification to determine the mod desired. + 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]) + return sen_name + + # FIXME: refactor to share with delay.py + def get_bl_name(self, paths): + """Gets the signal name associated with the bitlines in the bank.""" + + cell_mods = factory.get_mods(OPTS.bitcell) + if len(cell_mods)>=1: + cell_mod = self.get_primary_cell_mod(cell_mods) + elif len(cell_mods)==0: + debug.error("No bitcells found. Cannot determine bitline names.", 1) + + cell_bl = cell_mod.get_bl_name() + cell_br = cell_mod.get_br_name() + + bl_found = False + # Only a single path should contain a single s_en name. Anything else is an error. + bl_names = [] + 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)) + + return bl_names[0], bl_names[1] + + def get_bl_name_search_exclusions(self): + """Gets the mods as a set which should be excluded while searching for name.""" + + # Exclude the RBL as it contains bitcells which are not in the main bitcell array + # so it makes the search awkward + return set(factory.get_mods(OPTS.replica_bitline)) + + def get_primary_cell_mod(self, cell_mods): + """ + Distinguish bitcell array mod from replica bitline array. + Assume there are no replica bitcells in the primary array. + """ + if len(cell_mods) == 1: + return cell_mods[0] + rbc_mods = factory.get_mods(OPTS.replica_bitcell) + non_rbc_mods = [] + for bitcell in cell_mods: + has_cell = False + for replica_cell in rbc_mods: + has_cell = has_cell or replica_cell.contains(bitcell, replica_cell.mods) + if not has_cell: + non_rbc_mods.append(bitcell) + if len(non_rbc_mods) != 1: + debug.error('Multiple bitcell mods found. Cannot distinguish for characterization',1) + return non_rbc_mods[0] + + def are_mod_pins_equal(self, mods): + """Determines if there are pins differences in the input mods""" + + if len(mods) == 0: + return True + pins = mods[0].pins + for mod in mods[1:]: + if pins != mod.pins: + return False + return True + + def get_alias_in_path(self, paths, int_net, mod, exclusion_set=None): + """ + Finds a single alias for the int_net in given paths. + More or less hits cause an error + """ + + net_found = False + for path in paths: + aliases = self.sram.find_aliases(self.sram_spc_name, self.pins, path, int_net, mod, exclusion_set) + if net_found and len(aliases) >= 1: + debug.error('Found multiple paths with {} net.'.format(int_net),1) + elif len(aliases) > 1: + debug.error('Found multiple {} nets in single path.'.format(int_net),1) + elif not net_found and len(aliases) == 1: + path_net_name = aliases[0] + net_found = True + if not net_found: + debug.error("Could not find {} net in timing paths.".format(int_net),1) + + return path_net_name + From dce852d945e93f818bc3e9720f1c4356af31e36c Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 26 Jul 2019 14:54:55 -0700 Subject: [PATCH 147/234] Restructure control logic for improved drive and timing. --- compiler/modules/control_logic.py | 114 ++++++++++++++++++------------ 1 file changed, 70 insertions(+), 44 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index ca65b57b..6543b887 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -91,10 +91,9 @@ class control_logic(design.design): self.add_mod(self.ctrl_dff_array) - self.and2 = factory.create(module_type="pand2", - size=4, + self.nand2 = factory.create(module_type="pnand2", height=dff_height) - self.add_mod(self.and2) + self.add_mod(self.nand2) if self.port_type=="rw": self.rbl_driver = factory.create(module_type="pand2", @@ -126,16 +125,24 @@ class control_logic(design.design): self.add_mod(self.wl_en_driver) # w_en drives every write driver - self.wen_and2 = factory.create(module_type="pand2", - size=self.word_size+8, - height=dff_height) - self.add_mod(self.wen_and2) + self.wen_nand2 = factory.create(module_type="pnand2", + height=dff_height) + self.add_mod(self.wen_nand2) + self.wen_inv = factory.create(module_type="pdriver", + neg_polarity=True, + fanout=self.word_size+8, + height=dff_height) + self.add_mod(self.wen_inv) # s_en drives every sense amp - self.sen_and2 = factory.create(module_type="pand2", - size=self.word_size, + self.sen_nand2 = factory.create(module_type="pand2", height=dff_height) - self.add_mod(self.sen_and2) + self.add_mod(self.sen_nand2) + self.sen_inv = factory.create(module_type="pdriver", + neg_polarity=True, + fanout=self.word_size, + height=dff_height) + self.add_mod(self.sen_inv) # used to generate inverted signals with low fanout self.inv = factory.create(module_type="pinv", @@ -511,41 +518,26 @@ class control_logic(design.design): self.connect_output(self.clk_buf_inst, "Z", "clk_buf") def create_gated_clk_bar_row(self): - self.clk_bar_inst = self.add_inst(name="inv_clk_bar", - mod=self.inv) - self.connect_inst(["clk_buf","clk_bar","vdd","gnd"]) - - self.gated_clk_bar_inst = self.add_inst(name="and2_gated_clk_bar", - mod=self.and2) - self.connect_inst(["cs","clk_bar","gated_clk_bar","vdd","gnd"]) + self.gated_clk_bar_inst = self.add_inst(name="gated_clk_bar_nand2", + mod=self.nand2) + self.connect_inst(["cs","clk_buf","gated_clk_bar","vdd","gnd"]) def place_gated_clk_bar_row(self,row): """ Place the gated clk logic below the control flops """ x_off = self.control_x_offset (y_off,mirror)=self.get_offset(row) - offset = vector(x_off,y_off) - self.clk_bar_inst.place(offset, mirror) - - x_off += self.inv.width - offset = vector(x_off,y_off) self.gated_clk_bar_inst.place(offset, mirror) self.row_end_inst.append(self.gated_clk_bar_inst) def route_gated_clk_bar(self): - clkbuf_map = zip(["A"], ["clk_buf"]) - self.connect_vertical_bus(clkbuf_map, self.clk_bar_inst, self.rail_offsets) - out_pos = self.clk_bar_inst.get_pin("Z").center() - in_pos = self.gated_clk_bar_inst.get_pin("B").center() - mid1 = vector(in_pos.x,out_pos.y) - self.add_path("metal1",[out_pos, mid1, in_pos]) - # This is the second gate over, so it needs to be on M3 clkbuf_map = zip(["A"], ["cs"]) - self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("metal3", "via2", "metal2")) + self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("metal3", "via2", "metal2")) + # The pin is on M1, so we need another via as well self.add_via_center(layers=("metal1","via1","metal2"), offset=self.gated_clk_bar_inst.get_pin("A").center()) @@ -559,14 +551,23 @@ class control_logic(design.design): offset=self.gated_clk_bar_inst.get_pin("Z").center()) def create_gated_clk_buf_row(self): - self.gated_clk_buf_inst = self.add_inst(name="and2_gated_clk_buf", - mod=self.and2) - self.connect_inst(["clk_buf", "cs","gated_clk_buf","vdd","gnd"]) + self.clk_bar_inst = self.add_inst(name="inv_clk_bar", + mod=self.inv) + self.connect_inst(["clk_buf","clk_bar","vdd","gnd"]) + + self.gated_clk_buf_inst = self.add_inst(name="gated_clk_nand2", + mod=self.nand2) + self.connect_inst(["clk_bar", "cs","gated_clk_buf","vdd","gnd"]) def place_gated_clk_buf_row(self,row): """ Place the gated clk logic below the control flops """ x_off = self.control_x_offset (y_off,mirror)=self.get_offset(row) + + offset = vector(x_off,y_off) + self.clk_bar_inst.place(offset, mirror) + + x_off += self.inv.width offset = vector(x_off,y_off) self.gated_clk_buf_inst.place(offset, mirror) @@ -574,7 +575,15 @@ class control_logic(design.design): self.row_end_inst.append(self.gated_clk_buf_inst) def route_gated_clk_buf(self): - clkbuf_map = zip(["A", "B"], ["clk_buf", "cs"]) + clkbuf_map = zip(["A"], ["clk_buf"]) + self.connect_vertical_bus(clkbuf_map, self.clk_bar_inst, self.rail_offsets) + + out_pos = self.clk_bar_inst.get_pin("Z").center() + in_pos = self.gated_clk_buf_inst.get_pin("A").center() + mid1 = vector(in_pos.x,out_pos.y) + self.add_path("metal1",[out_pos, mid1, in_pos]) + + clkbuf_map = zip(["B"], ["cs"]) self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets) @@ -665,8 +674,12 @@ class control_logic(design.design): """ Create the sense enable buffer. """ # GATE FOR S_EN self.s_en_gate_inst = self.add_inst(name="buf_s_en_and", - mod=self.sen_and2) - self.connect_inst(["pre_s_en", "gated_clk_bar", "s_en", "vdd", "gnd"]) + mod=self.sen_nand2) + self.connect_inst(["pre_s_en", "gated_clk_bar", "s_en_bar", "vdd", "gnd"]) + + self.s_en_inv_inst = self.add_inst(name="s_en_inv", + mod=self.sen_inv) + self.connect_inst(["s_en_bar", "s_en", "vdd", "gnd"]) def place_sen_row(self,row): @@ -693,6 +706,11 @@ class control_logic(design.design): mid1 = vector(out_pos.x,in_pos.y) self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) + out_pos = self.s_en_gate_inst.get_pin("Z").bc() + in_pos = self.s_en_inv_inst.get_pin("A").lc() + mid1 = vector(out_pos.x,in_pos.y) + self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) + self.connect_output(self.s_en_gate_inst, "Z", "s_en") @@ -705,9 +723,14 @@ class control_logic(design.design): input_name = "cs" # GATE THE W_EN - self.w_en_gate_inst = self.add_inst(name="buf_w_en_and", - mod=self.wen_and2) - self.connect_inst([input_name, "gated_clk_bar", "w_en", "vdd", "gnd"]) + self.w_en_gate_inst = self.add_inst(name="w_en_nand", + mod=self.wen_nand2) + self.connect_inst([input_name, "gated_clk_bar", "w_en_bar", "vdd", "gnd"]) + + + self.w_en_buf_inst = self.add_inst(name="w_en_inv", + mod=self.wen_inv) + self.connect_inst(["w_en_bar", "w_en", "vdd", "gnd"]) def place_wen_row(self,row): @@ -721,15 +744,20 @@ class control_logic(design.design): def route_wen(self): if self.port_type == "rw": - input_name = "we" + input_name = "we_bar" else: # No we for write-only reports, so use cs input_name = "cs" - wen_map = zip(["A", "B"], [input_name, "gated_clk_bar"]) + wen_map = zip(["A", "B"], [input_name, "gated_clk_buf"]) self.connect_vertical_bus(wen_map, self.w_en_gate_inst, self.rail_offsets) - self.connect_output(self.w_en_gate_inst, "Z", "w_en") + out_pos = self.w_en_gate_inst.get_pin("Z").bc() + in_pos = self.w_en_inv_inst.get_pin("A").lc() + mid1 = vector(out_pos.x,in_pos.y) + self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) + + self.connect_output(self.w_en_inv_inst, "Z", "w_en") def create_dffs(self): self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs", @@ -744,8 +772,6 @@ class control_logic(design.design): #print("hi") #if (self.word_size == self.write_size): dff_out_map = zip(["dout_bar_0", "dout_bar_1", "dout_1"], ["cs", "we", "we_bar"]) - elif self.port_type == "r": - dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"]) else: dff_out_map = zip(["dout_bar_0"], ["cs"]) self.connect_vertical_bus(dff_out_map, self.ctrl_dff_inst, self.rail_offsets, ("metal3", "via2", "metal2")) From 7eea63116f2ced1d054fd2dbad1aadc7e06dc11e Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 26 Jul 2019 15:50:10 -0700 Subject: [PATCH 148/234] Control logic LVS clean --- compiler/modules/control_logic.py | 79 ++++++++++++++++++------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 6543b887..77ec3933 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -135,9 +135,9 @@ class control_logic(design.design): self.add_mod(self.wen_inv) # s_en drives every sense amp - self.sen_nand2 = factory.create(module_type="pand2", - height=dff_height) - self.add_mod(self.sen_nand2) + self.and2 = factory.create(module_type="pand2", + height=dff_height) + self.add_mod(self.and2) self.sen_inv = factory.create(module_type="pdriver", neg_polarity=True, fanout=self.word_size, @@ -470,7 +470,7 @@ class control_logic(design.design): def place_delay(self,row): """ Place the replica bitline """ - y_off = row * self.and2.height + 2*self.m1_pitch + y_off = row * self.nand2.height + 2*self.m1_pitch # Add the RBL above the rows # Add to the right of the control rows and routing channel @@ -511,6 +511,7 @@ class control_logic(design.design): mid2 = vector(self.rail_offsets["clk_buf"].x, mid1.y) bus_pos = self.rail_offsets["clk_buf"] self.add_wire(("metal3","via2","metal2"),[out_pos, mid1, mid2, bus_pos]) + # The pin is on M1, so we need another via as well self.add_via_center(layers=("metal1","via1","metal2"), offset=self.clk_buf_inst.get_pin("Z").center()) @@ -534,15 +535,14 @@ class control_logic(design.design): def route_gated_clk_bar(self): - # This is the second gate over, so it needs to be on M3 - clkbuf_map = zip(["A"], ["cs"]) - self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("metal3", "via2", "metal2")) + + clkbuf_map = zip(["A", "B"], ["cs", "clk_buf"]) + self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets) # The pin is on M1, so we need another via as well self.add_via_center(layers=("metal1","via1","metal2"), offset=self.gated_clk_bar_inst.get_pin("A").center()) - # This is the second gate over, so it needs to be on M3 clkbuf_map = zip(["Z"], ["gated_clk_bar"]) self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("metal3", "via2", "metal2")) @@ -551,7 +551,7 @@ class control_logic(design.design): offset=self.gated_clk_bar_inst.get_pin("Z").center()) def create_gated_clk_buf_row(self): - self.clk_bar_inst = self.add_inst(name="inv_clk_bar", + self.clk_bar_inst = self.add_inst(name="clk_bar_inv", mod=self.inv) self.connect_inst(["clk_buf","clk_bar","vdd","gnd"]) @@ -583,8 +583,12 @@ class control_logic(design.design): mid1 = vector(in_pos.x,out_pos.y) self.add_path("metal1",[out_pos, mid1, in_pos]) + # This is the second gate over, so it needs to be on M3 clkbuf_map = zip(["B"], ["cs"]) - self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets) + self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets, ("metal3", "via2", "metal2")) + # The pin is on M1, so we need another via as well + self.add_via_center(layers=("metal1","via1","metal2"), + offset=self.gated_clk_buf_inst.get_pin("B").center()) clkbuf_map = zip(["Z"], ["gated_clk_buf"]) @@ -595,7 +599,7 @@ class control_logic(design.design): def create_wlen_row(self): # input pre_p_en, output: wl_en - self.wl_en_inst=self.add_inst(name="buf_wl_en", + self.wl_en_inst=self.add_inst(name="wl_en_buf", mod=self.wl_en_driver) self.connect_inst(["gated_clk_bar", "wl_en", "vdd", "gnd"]) @@ -648,12 +652,10 @@ class control_logic(design.design): self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") def create_pen_row(self): - input_name = "gated_clk_buf" - - # input: pre_p_en, output: p_en_bar - self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar", + # input: gated_clk_bar, output: p_en_bar + self.p_en_bar_inst=self.add_inst(name="p_en_bar_inv", mod=self.p_en_bar_driver) - self.connect_inst([input_name, "p_en_bar", "vdd", "gnd"]) + self.connect_inst(["gated_clk_bar", "p_en_bar", "vdd", "gnd"]) def place_pen_row(self,row): @@ -665,7 +667,7 @@ class control_logic(design.design): self.row_end_inst.append(self.p_en_bar_inst) def route_pen(self): - in_map = zip(["A"], ["gated_clk_buf"]) + in_map = zip(["A"], ["gated_clk_bar"]) self.connect_vertical_bus(in_map, self.p_en_bar_inst, self.rail_offsets) self.connect_output(self.p_en_bar_inst, "Z", "p_en_bar") @@ -673,8 +675,8 @@ class control_logic(design.design): def create_sen_row(self): """ Create the sense enable buffer. """ # GATE FOR S_EN - self.s_en_gate_inst = self.add_inst(name="buf_s_en_and", - mod=self.sen_nand2) + self.s_en_gate_inst = self.add_inst(name="s_en_and", + mod=self.and2) self.connect_inst(["pre_s_en", "gated_clk_bar", "s_en_bar", "vdd", "gnd"]) self.s_en_inv_inst = self.add_inst(name="s_en_inv", @@ -692,8 +694,14 @@ class control_logic(design.design): offset = vector(x_off, y_off) self.s_en_gate_inst.place(offset, mirror) + + x_off += self.and2.width - self.row_end_inst.append(self.s_en_gate_inst) + offset = vector(x_off,y_off) + self.s_en_inv_inst.place(offset, mirror) + + + self.row_end_inst.append(self.s_en_inv_inst) def route_sen(self): @@ -711,7 +719,7 @@ class control_logic(design.design): mid1 = vector(out_pos.x,in_pos.y) self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) - self.connect_output(self.s_en_gate_inst, "Z", "s_en") + self.connect_output(self.s_en_inv_inst, "Z", "s_en") def create_wen_row(self): @@ -728,7 +736,7 @@ class control_logic(design.design): self.connect_inst([input_name, "gated_clk_bar", "w_en_bar", "vdd", "gnd"]) - self.w_en_buf_inst = self.add_inst(name="w_en_inv", + self.w_en_inv_inst = self.add_inst(name="w_en_inv", mod=self.wen_inv) self.connect_inst(["w_en_bar", "w_en", "vdd", "gnd"]) @@ -739,17 +747,22 @@ class control_logic(design.design): offset = vector(x_off, y_off) self.w_en_gate_inst.place(offset, mirror) + + x_off += self.nand2.width - self.row_end_inst.append(self.w_en_gate_inst) + offset = vector(x_off,y_off) + self.w_en_inv_inst.place(offset, mirror) + + self.row_end_inst.append(self.w_en_inv_inst) def route_wen(self): if self.port_type == "rw": - input_name = "we_bar" + input_name = "we" else: # No we for write-only reports, so use cs input_name = "cs" - wen_map = zip(["A", "B"], [input_name, "gated_clk_buf"]) + wen_map = zip(["A", "B"], [input_name, "gated_clk_bar"]) self.connect_vertical_bus(wen_map, self.w_en_gate_inst, self.rail_offsets) out_pos = self.w_en_gate_inst.get_pin("Z").bc() @@ -790,9 +803,9 @@ class control_logic(design.design): def get_offset(self,row): """ Compute the y-offset and mirroring """ - y_off = row*self.and2.height + y_off = row*self.nand2.height if row % 2: - y_off += self.and2.height + y_off += self.nand2.height mirror="MX" else: mirror="R0" @@ -918,11 +931,11 @@ class control_logic(design.design): #First stage, gated_clk_bar -(and2)-> rbl_in. Only for RW ports. if self.port_type == "rw": stage1_cout = self.replica_bitline.get_en_cin() - stage_effort_list += self.and2.get_stage_efforts(stage1_cout, last_stage_rise) + stage_effort_list += self.nand2.get_stage_efforts(stage1_cout, last_stage_rise) last_stage_rise = stage_effort_list[-1].is_rise #Replica bitline stage, rbl_in -(rbl)-> pre_s_en - stage2_cout = self.sen_and2.get_cin() + stage2_cout = self.and2.get_cin() stage_effort_list += self.replica_bitline.determine_sen_stage_efforts(stage2_cout, last_stage_rise) last_stage_rise = stage_effort_list[-1].is_rise @@ -958,8 +971,8 @@ class control_logic(design.design): last_stage_rise = stage_effort_list[-1].is_rise #Second stage, clk_buf -(inv)-> clk_bar - clk_bar_cout = self.and2.get_cin() - stage_effort_list += self.and2.get_stage_efforts(clk_bar_cout, last_stage_rise) + clk_bar_cout = self.nand2.get_cin() + stage_effort_list += self.nand2.get_stage_efforts(clk_bar_cout, last_stage_rise) last_stage_rise = stage_effort_list[-1].is_rise #Third stage clk_bar -(and)-> gated_clk_bar @@ -978,7 +991,7 @@ class control_logic(design.design): """ #Control logic internal load - int_clk_buf_cap = self.inv.get_cin() + self.ctrl_dff_array.get_clk_cin() + self.and2.get_cin() + int_clk_buf_cap = self.inv.get_cin() + self.ctrl_dff_array.get_clk_cin() + self.nand2.get_cin() #Control logic external load (in the other parts of the SRAM) ext_clk_buf_cap = self.sram.get_clk_bar_cin() @@ -991,7 +1004,7 @@ class control_logic(design.design): total_cin = 0 total_cin += self.wl_en_driver.get_cin() if self.port_type == 'rw': - total_cin +=self.and2.get_cin() + total_cin +=self.nand2.get_cin() return total_cin def graph_exclude_dffs(self): From e750ef22f561a49a12b7d71210ed4857a4c04fd5 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 26 Jul 2019 21:41:27 -0700 Subject: [PATCH 149/234] Undo some control logic changes. --- compiler/modules/control_logic.py | 173 ++++++++++++------------------ 1 file changed, 66 insertions(+), 107 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 97acff81..e9b212fa 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -90,9 +90,10 @@ class control_logic(design.design): self.add_mod(self.ctrl_dff_array) - self.nand2 = factory.create(module_type="pnand2", + self.and2 = factory.create(module_type="pand2", + size=4, height=dff_height) - self.add_mod(self.nand2) + self.add_mod(self.and2) if self.port_type=="rw": self.rbl_driver = factory.create(module_type="pand2", @@ -124,24 +125,16 @@ class control_logic(design.design): self.add_mod(self.wl_en_driver) # w_en drives every write driver - self.wen_nand2 = factory.create(module_type="pnand2", - height=dff_height) - self.add_mod(self.wen_nand2) - self.wen_inv = factory.create(module_type="pdriver", - neg_polarity=True, - fanout=self.word_size+8, - height=dff_height) - self.add_mod(self.wen_inv) + self.wen_and2 = factory.create(module_type="pand2", + size=self.word_size+8, + height=dff_height) + self.add_mod(self.wen_and2) # s_en drives every sense amp - self.and2 = factory.create(module_type="pand2", - height=dff_height) - self.add_mod(self.and2) - self.sen_inv = factory.create(module_type="pdriver", - neg_polarity=True, - fanout=self.word_size, - height=dff_height) - self.add_mod(self.sen_inv) + self.sen_and2 = factory.create(module_type="pand2", + size=self.word_size, + height=dff_height) + self.add_mod(self.sen_and2) # used to generate inverted signals with low fanout self.inv = factory.create(module_type="pinv", @@ -469,7 +462,7 @@ class control_logic(design.design): def place_delay(self,row): """ Place the replica bitline """ - y_off = row * self.nand2.height + 2*self.m1_pitch + y_off = row * self.and2.height + 2*self.m1_pitch # Add the RBL above the rows # Add to the right of the control rows and routing channel @@ -510,7 +503,6 @@ class control_logic(design.design): mid2 = vector(self.rail_offsets["clk_buf"].x, mid1.y) bus_pos = self.rail_offsets["clk_buf"] self.add_wire(("metal3","via2","metal2"),[out_pos, mid1, mid2, bus_pos]) - # The pin is on M1, so we need another via as well self.add_via_center(layers=("metal1","via1","metal2"), offset=self.clk_buf_inst.get_pin("Z").center()) @@ -518,30 +510,46 @@ class control_logic(design.design): self.connect_output(self.clk_buf_inst, "Z", "clk_buf") def create_gated_clk_bar_row(self): - self.gated_clk_bar_inst = self.add_inst(name="gated_clk_bar_nand2", - mod=self.nand2) - self.connect_inst(["cs","clk_buf","gated_clk_bar","vdd","gnd"]) + self.clk_bar_inst = self.add_inst(name="inv_clk_bar", + mod=self.inv) + self.connect_inst(["clk_buf","clk_bar","vdd","gnd"]) + + self.gated_clk_bar_inst = self.add_inst(name="and2_gated_clk_bar", + mod=self.and2) + self.connect_inst(["cs","clk_bar","gated_clk_bar","vdd","gnd"]) def place_gated_clk_bar_row(self,row): """ Place the gated clk logic below the control flops """ x_off = self.control_x_offset (y_off,mirror)=self.get_offset(row) + offset = vector(x_off,y_off) + self.clk_bar_inst.place(offset, mirror) + + x_off += self.inv.width + offset = vector(x_off,y_off) self.gated_clk_bar_inst.place(offset, mirror) self.row_end_inst.append(self.gated_clk_bar_inst) def route_gated_clk_bar(self): + clkbuf_map = zip(["A"], ["clk_buf"]) + self.connect_vertical_bus(clkbuf_map, self.clk_bar_inst, self.rail_offsets) + out_pos = self.clk_bar_inst.get_pin("Z").center() + in_pos = self.gated_clk_bar_inst.get_pin("B").center() + mid1 = vector(in_pos.x,out_pos.y) + self.add_path("metal1",[out_pos, mid1, in_pos]) - clkbuf_map = zip(["A", "B"], ["cs", "clk_buf"]) - self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets) - + # This is the second gate over, so it needs to be on M3 + clkbuf_map = zip(["A"], ["cs"]) + self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("metal3", "via2", "metal2")) # The pin is on M1, so we need another via as well self.add_via_center(layers=("metal1","via1","metal2"), offset=self.gated_clk_bar_inst.get_pin("A").center()) + # This is the second gate over, so it needs to be on M3 clkbuf_map = zip(["Z"], ["gated_clk_bar"]) self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("metal3", "via2", "metal2")) @@ -550,23 +558,14 @@ class control_logic(design.design): offset=self.gated_clk_bar_inst.get_pin("Z").center()) def create_gated_clk_buf_row(self): - self.clk_bar_inst = self.add_inst(name="clk_bar_inv", - mod=self.inv) - self.connect_inst(["clk_buf","clk_bar","vdd","gnd"]) - - self.gated_clk_buf_inst = self.add_inst(name="gated_clk_nand2", - mod=self.nand2) - self.connect_inst(["clk_bar", "cs","gated_clk_buf","vdd","gnd"]) + self.gated_clk_buf_inst = self.add_inst(name="and2_gated_clk_buf", + mod=self.and2) + self.connect_inst(["clk_buf", "cs","gated_clk_buf","vdd","gnd"]) def place_gated_clk_buf_row(self,row): """ Place the gated clk logic below the control flops """ x_off = self.control_x_offset (y_off,mirror)=self.get_offset(row) - - offset = vector(x_off,y_off) - self.clk_bar_inst.place(offset, mirror) - - x_off += self.inv.width offset = vector(x_off,y_off) self.gated_clk_buf_inst.place(offset, mirror) @@ -574,20 +573,8 @@ class control_logic(design.design): self.row_end_inst.append(self.gated_clk_buf_inst) def route_gated_clk_buf(self): - clkbuf_map = zip(["A"], ["clk_buf"]) - self.connect_vertical_bus(clkbuf_map, self.clk_bar_inst, self.rail_offsets) - - out_pos = self.clk_bar_inst.get_pin("Z").center() - in_pos = self.gated_clk_buf_inst.get_pin("A").center() - mid1 = vector(in_pos.x,out_pos.y) - self.add_path("metal1",[out_pos, mid1, in_pos]) - - # This is the second gate over, so it needs to be on M3 - clkbuf_map = zip(["B"], ["cs"]) - self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets, ("metal3", "via2", "metal2")) - # The pin is on M1, so we need another via as well - self.add_via_center(layers=("metal1","via1","metal2"), - offset=self.gated_clk_buf_inst.get_pin("B").center()) + clkbuf_map = zip(["A", "B"], ["clk_buf", "cs"]) + self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets) clkbuf_map = zip(["Z"], ["gated_clk_buf"]) @@ -598,7 +585,7 @@ class control_logic(design.design): def create_wlen_row(self): # input pre_p_en, output: wl_en - self.wl_en_inst=self.add_inst(name="wl_en_buf", + self.wl_en_inst=self.add_inst(name="buf_wl_en", mod=self.wl_en_driver) self.connect_inst(["gated_clk_bar", "wl_en", "vdd", "gnd"]) @@ -651,24 +638,24 @@ class control_logic(design.design): self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") def create_pen_row(self): - # input: gated_clk_bar, output: p_en_bar - self.p_en_bar_inst=self.add_inst(name="p_en_bar_inv", + input_name = "gated_clk_buf" + + # input: pre_p_en, output: p_en_bar + self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar", mod=self.p_en_bar_driver) - self.connect_inst(["gated_clk_bar", "p_en_bar", "vdd", "gnd"]) + self.connect_inst([input_name, "p_en_bar", "vdd", "gnd"]) def place_pen_row(self,row): x_off = self.control_x_offset (y_off,mirror)=self.get_offset(row) - offset = vector(x_off,y_off) self.p_en_bar_inst.place(offset, mirror) self.row_end_inst.append(self.p_en_bar_inst) def route_pen(self): - - in_map = zip(["A"], ["gated_clk_bar"]) + in_map = zip(["A"], ["gated_clk_buf"]) self.connect_vertical_bus(in_map, self.p_en_bar_inst, self.rail_offsets) self.connect_output(self.p_en_bar_inst, "Z", "p_en_bar") @@ -676,13 +663,9 @@ class control_logic(design.design): def create_sen_row(self): """ Create the sense enable buffer. """ # GATE FOR S_EN - self.s_en_gate_inst = self.add_inst(name="s_en_and", - mod=self.and2) - self.connect_inst(["pre_s_en", "gated_clk_bar", "s_en_bar", "vdd", "gnd"]) - - self.s_en_inv_inst = self.add_inst(name="s_en_inv", - mod=self.sen_inv) - self.connect_inst(["s_en_bar", "s_en", "vdd", "gnd"]) + self.s_en_gate_inst = self.add_inst(name="buf_s_en_and", + mod=self.sen_and2) + self.connect_inst(["pre_s_en", "gated_clk_bar", "s_en", "vdd", "gnd"]) def place_sen_row(self,row): @@ -695,14 +678,8 @@ class control_logic(design.design): offset = vector(x_off, y_off) self.s_en_gate_inst.place(offset, mirror) - - x_off += self.and2.width - offset = vector(x_off,y_off) - self.s_en_inv_inst.place(offset, mirror) - - - self.row_end_inst.append(self.s_en_inv_inst) + self.row_end_inst.append(self.s_en_gate_inst) def route_sen(self): @@ -715,12 +692,7 @@ class control_logic(design.design): mid1 = vector(out_pos.x,in_pos.y) self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) - out_pos = self.s_en_gate_inst.get_pin("Z").bc() - in_pos = self.s_en_inv_inst.get_pin("A").lc() - mid1 = vector(out_pos.x,in_pos.y) - self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) - - self.connect_output(self.s_en_inv_inst, "Z", "s_en") + self.connect_output(self.s_en_gate_inst, "Z", "s_en") def create_wen_row(self): @@ -732,14 +704,9 @@ class control_logic(design.design): input_name = "cs" # GATE THE W_EN - self.w_en_gate_inst = self.add_inst(name="w_en_nand", - mod=self.wen_nand2) - self.connect_inst([input_name, "gated_clk_bar", "w_en_bar", "vdd", "gnd"]) - - - self.w_en_inv_inst = self.add_inst(name="w_en_inv", - mod=self.wen_inv) - self.connect_inst(["w_en_bar", "w_en", "vdd", "gnd"]) + self.w_en_gate_inst = self.add_inst(name="buf_w_en_and", + mod=self.wen_and2) + self.connect_inst([input_name, "gated_clk_bar", "w_en", "vdd", "gnd"]) def place_wen_row(self,row): @@ -748,13 +715,8 @@ class control_logic(design.design): offset = vector(x_off, y_off) self.w_en_gate_inst.place(offset, mirror) - - x_off += self.nand2.width - offset = vector(x_off,y_off) - self.w_en_inv_inst.place(offset, mirror) - - self.row_end_inst.append(self.w_en_inv_inst) + self.row_end_inst.append(self.w_en_gate_inst) def route_wen(self): if self.port_type == "rw": @@ -766,12 +728,7 @@ class control_logic(design.design): wen_map = zip(["A", "B"], [input_name, "gated_clk_bar"]) self.connect_vertical_bus(wen_map, self.w_en_gate_inst, self.rail_offsets) - out_pos = self.w_en_gate_inst.get_pin("Z").bc() - in_pos = self.w_en_inv_inst.get_pin("A").lc() - mid1 = vector(out_pos.x,in_pos.y) - self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) - - self.connect_output(self.w_en_inv_inst, "Z", "w_en") + self.connect_output(self.w_en_gate_inst, "Z", "w_en") def create_dffs(self): self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs", @@ -784,6 +741,8 @@ class control_logic(design.design): def route_dffs(self): if self.port_type == "rw": dff_out_map = zip(["dout_bar_0", "dout_bar_1", "dout_1"], ["cs", "we", "we_bar"]) + elif self.port_type == "r": + dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"]) else: dff_out_map = zip(["dout_bar_0"], ["cs"]) self.connect_vertical_bus(dff_out_map, self.ctrl_dff_inst, self.rail_offsets, ("metal3", "via2", "metal2")) @@ -802,9 +761,9 @@ class control_logic(design.design): def get_offset(self,row): """ Compute the y-offset and mirroring """ - y_off = row*self.nand2.height + y_off = row*self.and2.height if row % 2: - y_off += self.nand2.height + y_off += self.and2.height mirror="MX" else: mirror="R0" @@ -930,11 +889,11 @@ class control_logic(design.design): #First stage, gated_clk_bar -(and2)-> rbl_in. Only for RW ports. if self.port_type == "rw": stage1_cout = self.replica_bitline.get_en_cin() - stage_effort_list += self.nand2.get_stage_efforts(stage1_cout, last_stage_rise) + stage_effort_list += self.and2.get_stage_efforts(stage1_cout, last_stage_rise) last_stage_rise = stage_effort_list[-1].is_rise #Replica bitline stage, rbl_in -(rbl)-> pre_s_en - stage2_cout = self.and2.get_cin() + stage2_cout = self.sen_and2.get_cin() stage_effort_list += self.replica_bitline.determine_sen_stage_efforts(stage2_cout, last_stage_rise) last_stage_rise = stage_effort_list[-1].is_rise @@ -970,8 +929,8 @@ class control_logic(design.design): last_stage_rise = stage_effort_list[-1].is_rise #Second stage, clk_buf -(inv)-> clk_bar - clk_bar_cout = self.nand2.get_cin() - stage_effort_list += self.nand2.get_stage_efforts(clk_bar_cout, last_stage_rise) + clk_bar_cout = self.and2.get_cin() + stage_effort_list += self.and2.get_stage_efforts(clk_bar_cout, last_stage_rise) last_stage_rise = stage_effort_list[-1].is_rise #Third stage clk_bar -(and)-> gated_clk_bar @@ -990,7 +949,7 @@ class control_logic(design.design): """ #Control logic internal load - int_clk_buf_cap = self.inv.get_cin() + self.ctrl_dff_array.get_clk_cin() + self.nand2.get_cin() + int_clk_buf_cap = self.inv.get_cin() + self.ctrl_dff_array.get_clk_cin() + self.and2.get_cin() #Control logic external load (in the other parts of the SRAM) ext_clk_buf_cap = self.sram.get_clk_bar_cin() @@ -1003,7 +962,7 @@ class control_logic(design.design): total_cin = 0 total_cin += self.wl_en_driver.get_cin() if self.port_type == 'rw': - total_cin +=self.nand2.get_cin() + total_cin +=self.and2.get_cin() return total_cin def graph_exclude_dffs(self): From 179efe4d048d172ff6a16065bb875c949bce08b3 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 26 Jul 2019 22:03:50 -0700 Subject: [PATCH 150/234] Fix bitline names in merge error --- compiler/modules/port_data.py | 29 ++++++++++++------------- compiler/tests/16_control_logic_test.py | 6 ++--- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index cee79c47..ac023eb0 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -237,8 +237,8 @@ class port_data(design.design): temp.append("rbl_bl") temp.append("rbl_br") for bit in range(self.num_cols): - temp.append("bl_{0}".format(bit)) - temp.append("br_{0}".format(bit)) + temp.append(self.bl_names[self.port]+"_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_{0}".format(bit)) if self.has_rbl() and self.port==1: temp.append("rbl_bl") temp.append("rbl_br") @@ -258,17 +258,16 @@ class port_data(design.design): temp = [] for col in range(self.num_cols): - temp.append("bl_{0}".format(col)) - temp.append("br_{0}".format(col)) + temp.append(self.bl_names[self.port]+"_{0}".format(col)) + temp.append(self.br_names[self.port]+"_{0}".format(col)) for word in range(self.words_per_row): temp.append("sel_{}".format(word)) for bit in range(self.word_size): - temp.append("bl_out_{0}".format(bit)) - temp.append("br_out_{0}".format(bit)) + temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) temp.append("gnd") self.connect_inst(temp) - def place_column_mux_array(self, offset): """ Placing Column Mux when words_per_row > 1 . """ @@ -287,12 +286,12 @@ class port_data(design.design): for bit in range(self.word_size): temp.append("dout_{}".format(bit)) if self.words_per_row == 1: - temp.append("bl_{0}".format(bit)) - temp.append("br_{0}".format(bit)) + temp.append(self.bl_names[self.port]+"_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_{0}".format(bit)) else: - temp.append("bl_out_{0}".format(bit)) - temp.append("br_out_{0}".format(bit)) - + temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) + temp.extend(["s_en", "vdd", "gnd"]) self.connect_inst(temp) @@ -312,9 +311,9 @@ class port_data(design.design): temp.append("din_{}".format(bit)) for bit in range(self.word_size): - if (self.words_per_row == 1): - temp.append("bl_{0}".format(bit)) - temp.append("br_{0}".format(bit)) + if (self.words_per_row == 1): + temp.append(self.bl_names[self.port]+"_{0}".format(bit)) + temp.append(self.br_names[self.port]+"_{0}".format(bit)) else: temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index f8fa3061..92d5c94b 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -23,15 +23,15 @@ class control_logic_test(openram_test): import tech debug.info(1, "Testing sample for control_logic_rw") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32, write_size=32) + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32) self.local_check(a) debug.info(1, "Testing sample for control_logic_r") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32, write_size=32, port_type="r") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32, port_type="r") self.local_check(a) debug.info(1, "Testing sample for control_logic_w") - a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32, write_size=32, port_type="w") + a = factory.create(module_type="control_logic", num_rows=128, words_per_row=1, word_size=32, port_type="w") self.local_check(a) # run the test from the command line From 52029d8e485ec58f0979b8808465f09f8a2d44e9 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 27 Jul 2019 06:11:45 -0700 Subject: [PATCH 151/234] Fix incorrect port_data BL pin name. --- compiler/modules/port_data.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index ac023eb0..bf015666 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -81,12 +81,13 @@ class port_data(design.design): def add_pins(self): """ Adding pins for port address module""" + if self.has_rbl(): self.add_pin("rbl_bl","INOUT") self.add_pin("rbl_br","INOUT") for bit in range(self.num_cols): - self.add_pin("bl_{0}".format(bit),"INOUT") - self.add_pin("br_{0}".format(bit),"INOUT") + self.add_pin("{0}_{1}".format(self.bl_names[self.port], bit),"INOUT") + self.add_pin("{0}_{1}".format(self.br_names[self.port], bit),"INOUT") if self.port in self.read_ports: for bit in range(self.word_size): self.add_pin("dout_{}".format(bit),"OUTPUT") @@ -143,6 +144,7 @@ class port_data(design.design): def route_supplies(self): """ Propagate all vdd/gnd pins up to this level for all modules """ + for inst in self.insts: self.copy_power_pins(inst,"vdd") self.copy_power_pins(inst,"gnd") @@ -150,7 +152,8 @@ class port_data(design.design): def add_modules(self): if self.port in self.read_ports: - # Extra column for RBL + # Extra column +1 is for RBL + # Precharge will be shifted left if needed self.precharge_array = factory.create(module_type="precharge_array", columns=self.num_cols + 1, bitcell_bl=self.bl_names[self.port], @@ -164,6 +167,8 @@ class port_data(design.design): else: # Precharge is needed when we have a column mux or for byte writes # to prevent corruption of half-selected cells, so just always add it + # This is a little power inefficient for write ports without a column mux, + # but it is simpler. self.precharge_array = factory.create(module_type="precharge_array", columns=self.num_cols, bitcell_bl=self.bl_names[self.port], @@ -233,12 +238,14 @@ class port_data(design.design): mod=self.precharge_array) temp = [] + # Use left BLs for RBL if self.has_rbl() and self.port==0: temp.append("rbl_bl") temp.append("rbl_br") for bit in range(self.num_cols): temp.append(self.bl_names[self.port]+"_{0}".format(bit)) temp.append(self.br_names[self.port]+"_{0}".format(bit)) + # Use right BLs for RBL if self.has_rbl() and self.port==1: temp.append("rbl_bl") temp.append("rbl_br") @@ -248,11 +255,13 @@ class port_data(design.design): def place_precharge_array(self, offset): """ Placing Precharge """ + self.precharge_array_inst.place(offset=offset, mirror="MX") def create_column_mux_array(self): """ Creating Column Mux when words_per_row > 1 . """ + self.column_mux_array_inst = self.add_inst(name="column_mux_array{}".format(self.port), mod=self.column_mux_array) @@ -498,6 +507,7 @@ class port_data(design.design): def route_bitline_pins(self): """ Add the bitline pins for the given port """ + # Connect one bitline to the RBL and offset the indices for the other BLs if self.has_rbl() and self.port==0: self.copy_layout_pin(self.precharge_array_inst, "bl_0", "rbl_bl") self.copy_layout_pin(self.precharge_array_inst, "br_0", "rbl_br") @@ -514,12 +524,8 @@ class port_data(design.design): if self.precharge_array_inst: self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit+bit_offset), "bl_{}".format(bit)) self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit+bit_offset), "br_{}".format(bit)) - # elif self.column_mux_array_inst: - # self.copy_layout_pin(self.column_mux_array_inst, "bl_{}".format(bit)) - # self.copy_layout_pin(self.column_mux_array_inst, "br_{}".format(bit)) else: - self.copy_layout_pin(self.write_driver_array_inst, "bl_{}".format(bit)) - self.copy_layout_pin(self.write_driver_array_inst, "br_{}".format(bit)) + debug.error("Didn't find precharge arra.") def route_control_pins(self): """ Add the control pins: s_en, p_en_bar, w_en """ From 468a759d1e99ad270e75b77164ea6dfb4206fbeb Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 27 Jul 2019 11:09:08 -0700 Subject: [PATCH 152/234] Fixed control problems (probably) Extended functional tests for 15 cycles (slow, but more checking) Fixed s_en to be gated AFTER the RBL. --- compiler/characterizer/functional.py | 7 +++-- compiler/modules/control_logic.py | 26 ++++++------------- .../tests/22_psram_1bank_2mux_func_test.py | 19 +++++++------- .../tests/22_psram_1bank_4mux_func_test.py | 19 +++++++------- .../tests/22_psram_1bank_8mux_func_test.py | 19 +++++++------- .../tests/22_psram_1bank_nomux_func_test.py | 19 +++++++------- compiler/tests/22_psram_wmask_func_test.py | 6 ++--- .../tests/22_sram_1bank_2mux_func_test.py | 15 +++++------ .../tests/22_sram_1bank_4mux_func_test.py | 15 +++++------ .../tests/22_sram_1bank_8mux_func_test.py | 15 +++++------ .../tests/22_sram_1bank_nomux_func_test.py | 15 +++++------ .../22_sram_1rw_1r_1bank_nomux_func_test.py | 4 +-- compiler/tests/22_sram_wmask_func_test.py | 4 +-- 13 files changed, 79 insertions(+), 104 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 3b3f7efd..0b3e7b4b 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -51,11 +51,12 @@ class functional(simulation): self.initialize_wmask() # Number of checks can be changed - self.num_cycles = 2 + self.num_cycles = 15 self.stored_words = {} self.write_check = [] self.read_check = [] + def initialize_wmask(self): self.wmask = "" if self.write_size is not None: @@ -294,9 +295,7 @@ class functional(simulation): self.stim = stimuli(self.sf,self.corner) #Write include statements - self.sram_sp_file = "{}sram.sp".format(OPTS.openram_temp) - shutil.copy(self.sp_file, self.sram_sp_file) - self.stim.write_include(self.sram_sp_file) + self.stim.write_include(self.sp_file) #Write Vdd/Gnd statements self.sf.write("\n* Global Power Supplies\n") diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index e9b212fa..9cabb6c4 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -95,16 +95,10 @@ class control_logic(design.design): height=dff_height) self.add_mod(self.and2) - if self.port_type=="rw": - self.rbl_driver = factory.create(module_type="pand2", - size=self.num_cols, - height=dff_height) - self.add_mod(self.rbl_driver) - elif self.port_type=="r": - self.rbl_driver = factory.create(module_type="pbuf", - size=self.num_cols, - height=dff_height) - self.add_mod(self.rbl_driver) + self.rbl_driver = factory.create(module_type="pbuf", + size=self.num_cols, + height=dff_height) + self.add_mod(self.rbl_driver) # clk_buf drives a flop for every address and control bit @@ -607,12 +601,8 @@ class control_logic(design.design): self.rbl_inst=self.add_inst(name="rbl_driver", mod=self.rbl_driver) - if self.port_type == "rw": - # input: gated_clk_bar, we_bar, output: rbl_wl - self.connect_inst(["gated_clk_bar", "we_bar", "rbl_wl", "vdd", "gnd"]) - elif self.port_type == "r": - # input: gated_clk_bar, output: rbl_wl - self.connect_inst(["gated_clk_bar", "rbl_wl", "vdd", "gnd"]) + # input: gated_clk_bar, output: rbl_wl + self.connect_inst(["gated_clk_bar", "rbl_wl", "vdd", "gnd"]) def place_rbl_row(self,row): x_off = self.control_x_offset @@ -665,7 +655,7 @@ class control_logic(design.design): # GATE FOR S_EN self.s_en_gate_inst = self.add_inst(name="buf_s_en_and", mod=self.sen_and2) - self.connect_inst(["pre_s_en", "gated_clk_bar", "s_en", "vdd", "gnd"]) + self.connect_inst(["pre_s_en", "we_bar", "s_en", "vdd", "gnd"]) def place_sen_row(self,row): @@ -684,7 +674,7 @@ class control_logic(design.design): def route_sen(self): - sen_map = zip(["B"], ["gated_clk_bar"]) + sen_map = zip(["B"], ["we_bar"]) self.connect_vertical_bus(sen_map, self.s_en_gate_inst, self.rail_offsets) out_pos = self.delay_inst.get_pin("out").bc() diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index 90cc8bd2..035f6b41 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -42,21 +42,20 @@ class psram_1bank_2mux_func_test(openram_test): num_banks=1) c.words_per_row=2 c.recompute_sizes() - debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, - OPTS.num_r_ports, - OPTS.num_w_ports, - c.word_size, - c.num_words, - c.words_per_row, - c.num_banks)) + debug.info(1, "Functional test for {}rw,{}r,{}w psram with" + "{} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, + OPTS.num_r_ports, + OPTS.num_w_ports, + c.word_size, + c.num_words, + c.words_per_row, + c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail,error) diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index ac0b733c..9a280492 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -43,21 +43,20 @@ class psram_1bank_4mux_func_test(openram_test): num_banks=1) c.words_per_row=4 c.recompute_sizes() - debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, - OPTS.num_r_ports, - OPTS.num_w_ports, - c.word_size, - c.num_words, - c.words_per_row, - c.num_banks)) + debug.info(1, "Functional test for {}rw,{}r,{}w psram with" + "{} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, + OPTS.num_r_ports, + OPTS.num_w_ports, + c.word_size, + c.num_words, + c.words_per_row, + c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail,error) diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index 8b1881fb..d99a0959 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -43,21 +43,20 @@ class psram_1bank_8mux_func_test(openram_test): num_banks=1) c.words_per_row=8 c.recompute_sizes() - debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, - OPTS.num_r_ports, - OPTS.num_w_ports, - c.word_size, - c.num_words, - c.words_per_row, - c.num_banks)) + debug.info(1, "Functional test for {}rw,{}r,{}w psram with" + "{} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, + OPTS.num_r_ports, + OPTS.num_w_ports, + c.word_size, + c.num_words, + c.words_per_row, + c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail,error) diff --git a/compiler/tests/22_psram_1bank_nomux_func_test.py b/compiler/tests/22_psram_1bank_nomux_func_test.py index 323282e5..78da5a11 100755 --- a/compiler/tests/22_psram_1bank_nomux_func_test.py +++ b/compiler/tests/22_psram_1bank_nomux_func_test.py @@ -43,21 +43,20 @@ class psram_1bank_nomux_func_test(openram_test): num_banks=1) c.words_per_row=1 c.recompute_sizes() - debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, - OPTS.num_r_ports, - OPTS.num_w_ports, - c.word_size, - c.num_words, - c.words_per_row, - c.num_banks)) + debug.info(1, "Functional test for {}rw,{}r,{}w psram with" + "{} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, + OPTS.num_r_ports, + OPTS.num_w_ports, + c.word_size, + c.num_words, + c.words_per_row, + c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail,error) diff --git a/compiler/tests/22_psram_wmask_func_test.py b/compiler/tests/22_psram_wmask_func_test.py index bbf28331..75e3cbf1 100644 --- a/compiler/tests/22_psram_wmask_func_test.py +++ b/compiler/tests/22_psram_wmask_func_test.py @@ -52,13 +52,11 @@ class psram_wmask_func_test(openram_test): c.write_size, c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) - f = functional(s.s, tempspice, corner) - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail, error) @@ -70,4 +68,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main(testRunner=debugTestRunner()) \ No newline at end of file + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/22_sram_1bank_2mux_func_test.py b/compiler/tests/22_sram_1bank_2mux_func_test.py index d60d7040..2037169e 100755 --- a/compiler/tests/22_sram_1bank_2mux_func_test.py +++ b/compiler/tests/22_sram_1bank_2mux_func_test.py @@ -31,22 +31,21 @@ class sram_1bank_2mux_func_test(openram_test): from characterizer import functional, delay from sram_config import sram_config c = sram_config(word_size=4, - num_words=64, + num_words=32, num_banks=1) c.words_per_row=2 c.recompute_sizes() - debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, - c.num_words, - c.words_per_row, - c.num_banks)) + debug.info(1, "Functional test for sram with " + "{} bit words, {} words, {} words per row, {} banks".format(c.word_size, + c.num_words, + c.words_per_row, + c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail,error) diff --git a/compiler/tests/22_sram_1bank_4mux_func_test.py b/compiler/tests/22_sram_1bank_4mux_func_test.py index e81b3682..178f955b 100755 --- a/compiler/tests/22_sram_1bank_4mux_func_test.py +++ b/compiler/tests/22_sram_1bank_4mux_func_test.py @@ -31,22 +31,21 @@ class sram_1bank_4mux_func_test(openram_test): from characterizer import functional, delay from sram_config import sram_config c = sram_config(word_size=4, - num_words=256, + num_words=128, num_banks=1) c.words_per_row=4 c.recompute_sizes() - debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, - c.num_words, - c.words_per_row, - c.num_banks)) + debug.info(1, "Functional test for sram with " + "{} bit words, {} words, {} words per row, {} banks".format(c.word_size, + c.num_words, + c.words_per_row, + c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail,error) diff --git a/compiler/tests/22_sram_1bank_8mux_func_test.py b/compiler/tests/22_sram_1bank_8mux_func_test.py index 33151f0f..d531163a 100755 --- a/compiler/tests/22_sram_1bank_8mux_func_test.py +++ b/compiler/tests/22_sram_1bank_8mux_func_test.py @@ -34,22 +34,21 @@ class sram_1bank_8mux_func_test(openram_test): from sram_config import sram_config c = sram_config(word_size=4, - num_words=256, + num_words=128, num_banks=1) c.words_per_row=8 c.recompute_sizes() - debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, - c.num_words, - c.words_per_row, - c.num_banks)) + debug.info(1, "Functional test for sram with " + "{} bit words, {} words, {} words per row, {} banks".format(c.word_size, + c.num_words, + c.words_per_row, + c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail,error) diff --git a/compiler/tests/22_sram_1bank_nomux_func_test.py b/compiler/tests/22_sram_1bank_nomux_func_test.py index 9f777dc1..eb6d2412 100755 --- a/compiler/tests/22_sram_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1bank_nomux_func_test.py @@ -30,22 +30,21 @@ class sram_1bank_nomux_func_test(openram_test): from characterizer import functional from sram_config import sram_config c = sram_config(word_size=4, - num_words=32, + num_words=16, num_banks=1) c.words_per_row=1 c.recompute_sizes() - debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, - c.num_words, - c.words_per_row, - c.num_banks)) + debug.info(1, "Functional test for sram with " + "{} bit words, {} words, {} words per row, {} banks".format(c.word_size, + c.num_words, + c.words_per_row, + c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail,error) diff --git a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py index 293d52d8..c7de01ee 100755 --- a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py @@ -46,13 +46,11 @@ class psram_1bank_nomux_func_test(openram_test): c.words_per_row, c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) f = functional(s.s, tempspice, corner) - - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail,error) diff --git a/compiler/tests/22_sram_wmask_func_test.py b/compiler/tests/22_sram_wmask_func_test.py index 9a7b04fd..f45f57b3 100755 --- a/compiler/tests/22_sram_wmask_func_test.py +++ b/compiler/tests/22_sram_wmask_func_test.py @@ -42,13 +42,11 @@ class sram_wmask_func_test(openram_test): c.write_size, c.num_banks)) s = factory.create(module_type="sram", sram_config=c) - tempspice = OPTS.openram_temp + "temp.sp" + tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) - f = functional(s.s, tempspice, corner) - f.num_cycles = 10 (fail, error) = f.run() self.assertTrue(fail, error) From 37fffb2ed2320e4908fd88272f2e9fe509d3dc0a Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 27 Jul 2019 11:14:56 -0700 Subject: [PATCH 153/234] Fix bad indent. --- compiler/tests/22_psram_1bank_2mux_func_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index 035f6b41..446352e8 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -42,7 +42,7 @@ class psram_1bank_2mux_func_test(openram_test): num_banks=1) c.words_per_row=2 c.recompute_sizes() - debug.info(1, "Functional test for {}rw,{}r,{}w psram with" + debug.info(1, "Functional test for {}rw,{}r,{}w psram with" "{} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, OPTS.num_r_ports, OPTS.num_w_ports, From fa4f98b122ba26f121915023fc0e38a3d31b26f2 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 27 Jul 2019 11:30:48 -0700 Subject: [PATCH 154/234] Fix ALL of the indents. --- compiler/tests/22_psram_1bank_4mux_func_test.py | 2 +- compiler/tests/22_psram_1bank_8mux_func_test.py | 2 +- .../tests/22_sram_1rw_1r_1bank_nomux_func_test.py | 9 +++++---- compiler/tests/22_sram_wmask_func_test.py | 11 ++++++----- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index 9a280492..04ce7118 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -43,7 +43,7 @@ class psram_1bank_4mux_func_test(openram_test): num_banks=1) c.words_per_row=4 c.recompute_sizes() - debug.info(1, "Functional test for {}rw,{}r,{}w psram with" + debug.info(1, "Functional test for {}rw,{}r,{}w psram with" "{} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, OPTS.num_r_ports, OPTS.num_w_ports, diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index d99a0959..acb168c0 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -43,7 +43,7 @@ class psram_1bank_8mux_func_test(openram_test): num_banks=1) c.words_per_row=8 c.recompute_sizes() - debug.info(1, "Functional test for {}rw,{}r,{}w psram with" + debug.info(1, "Functional test for {}rw,{}r,{}w psram with" "{} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, OPTS.num_r_ports, OPTS.num_w_ports, diff --git a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py index c7de01ee..169e34d0 100755 --- a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py +++ b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py @@ -41,10 +41,11 @@ class psram_1bank_nomux_func_test(openram_test): num_banks=1) c.words_per_row=1 c.recompute_sizes() - debug.info(1, "Functional test for sram 1rw,1r with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, - c.num_words, - c.words_per_row, - c.num_banks)) + debug.info(1, "Functional test for sram 1rw,1r with " + "{} bit words, {} words, {} words per row, {} banks".format(c.word_size, + c.num_words, + c.words_per_row, + c.num_banks)) s = factory.create(module_type="sram", sram_config=c) tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) diff --git a/compiler/tests/22_sram_wmask_func_test.py b/compiler/tests/22_sram_wmask_func_test.py index f45f57b3..c390f030 100755 --- a/compiler/tests/22_sram_wmask_func_test.py +++ b/compiler/tests/22_sram_wmask_func_test.py @@ -36,11 +36,12 @@ class sram_wmask_func_test(openram_test): num_banks=1) c.words_per_row=1 c.recompute_sizes() - debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} bit writes, {} banks".format(c.word_size, - c.num_words, - c.words_per_row, - c.write_size, - c.num_banks)) + debug.info(1, "Functional test for sram with " + "{} bit words, {} words, {} words per row, {} bit writes, {} banks".format(c.word_size, + c.num_words, + c.words_per_row, + c.write_size, + c.num_banks)) s = factory.create(module_type="sram", sram_config=c) tempspice = OPTS.openram_temp + "sram.sp" s.sp_write(tempspice) From 5cb320a4ef69fd3242dacda8966f81531237234c Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 27 Jul 2019 11:44:35 -0700 Subject: [PATCH 155/234] Fix wrong pin error. --- compiler/modules/control_logic.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 9cabb6c4..44953b8e 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -616,11 +616,7 @@ class control_logic(design.design): def route_rbl(self): """ Connect the logic for the rbl_in generation """ - if self.port_type == "rw": - # Connect the NAND gate inputs to the bus - rbl_in_map = zip(["A", "B"], ["gated_clk_bar", "we_bar"]) - else: - rbl_in_map = zip(["A"], ["gated_clk_bar"]) + rbl_in_map = zip(["A"], ["gated_clk_bar"]) self.connect_vertical_bus(rbl_in_map, self.rbl_inst, self.rail_offsets) self.connect_output(self.rbl_inst, "Z", "rbl_wl") @@ -652,10 +648,14 @@ class control_logic(design.design): def create_sen_row(self): """ Create the sense enable buffer. """ + if self.port_type=="rw": + input_name = "we_bar" + else: + input_name = "cs_bar" # GATE FOR S_EN self.s_en_gate_inst = self.add_inst(name="buf_s_en_and", mod=self.sen_and2) - self.connect_inst(["pre_s_en", "we_bar", "s_en", "vdd", "gnd"]) + self.connect_inst(["pre_s_en", input_name, "s_en", "vdd", "gnd"]) def place_sen_row(self,row): @@ -674,7 +674,12 @@ class control_logic(design.design): def route_sen(self): - sen_map = zip(["B"], ["we_bar"]) + if self.port_type=="rw": + input_name = "we_bar" + else: + input_name = "cs_bar" + + sen_map = zip(["B"], [input_name]) self.connect_vertical_bus(sen_map, self.s_en_gate_inst, self.rail_offsets) out_pos = self.delay_inst.get_pin("out").bc() @@ -694,7 +699,7 @@ class control_logic(design.design): input_name = "cs" # GATE THE W_EN - self.w_en_gate_inst = self.add_inst(name="buf_w_en_and", + self.w_en_gate_inst = self.add_inst(name="w_en_and", mod=self.wen_and2) self.connect_inst([input_name, "gated_clk_bar", "w_en", "vdd", "gnd"]) From 2824315f79fe79e76ade41cfbebfe217104b169a Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 27 Jul 2019 11:51:40 -0700 Subject: [PATCH 156/234] Fix error in wmask if --- compiler/sram/sram_1bank.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 2f6760d0..355ca769 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -190,7 +190,7 @@ class sram_1bank(sram_base): self.data_dff_insts[port].place(data_pos[port], mirror="MX") # Add the write mask flops to the left of the din flops. - if (self.write_size != self.word_size): + if self.write_size is not None: if port in self.write_ports: wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, self.bank.height + max_gap_size + self.data_dff_insts[port].height) From d7bc3e82075fa96301832d4acb34bc968381789e Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 27 Jul 2019 12:13:35 -0700 Subject: [PATCH 157/234] Add dummy pbitcell --- compiler/tests/22_psram_wmask_func_test.py | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 compiler/tests/22_psram_wmask_func_test.py diff --git a/compiler/tests/22_psram_wmask_func_test.py b/compiler/tests/22_psram_wmask_func_test.py old mode 100644 new mode 100755 index 75e3cbf1..eafeb0a9 --- a/compiler/tests/22_psram_wmask_func_test.py +++ b/compiler/tests/22_psram_wmask_func_test.py @@ -27,6 +27,7 @@ class psram_wmask_func_test(openram_test): OPTS.trim_netlist = False OPTS.bitcell = "bitcell_1w_1r" OPTS.replica_bitcell = "replica_bitcell_1w_1r" + OPTS.dummy_bitcell = "dummy_bitcell_1w_1r" OPTS.num_rw_ports = 0 OPTS.num_w_ports = 1 From 8e434694861e61bc1ef392aa0c718d6ff4dea6fe Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 27 Jul 2019 12:13:44 -0700 Subject: [PATCH 158/234] Update spice results --- compiler/tests/21_hspice_delay_test.py | 36 ++++++++++++------------- compiler/tests/21_ngspice_delay_test.py | 18 ++++++------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 9a72edee..d63d6c30 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -61,27 +61,27 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_hl': [0.2192123], - 'delay_lh': [0.2192123], - 'leakage_power': 0.006427800000000001, + golden_data = {'delay_hl': [0.2179763], + 'delay_lh': [0.2179763], + 'leakage_power': 0.0025727, 'min_period': 0.527, - 'read0_power': [0.4519997], - 'read1_power': [0.42609269999999994], - 'slew_hl': [0.10185999999999999], - 'slew_lh': [0.10185999999999999], - 'write0_power': [0.49744869999999997], - 'write1_power': [0.4460337]} + 'read0_power': [0.4479132], + 'read1_power': [0.422467], + 'slew_hl': [0.0988916], + 'slew_lh': [0.0988916], + 'write0_power': [0.4976688], + 'write1_power': [0.4605285]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.4249], - 'delay_lh': [1.4249], - 'leakage_power': 0.7340832, + golden_data = {'delay_hl': [1.4119000000000002], + 'delay_lh': [1.4119000000000002], + 'leakage_power': 0.027366399999999996, 'min_period': 3.125, - 'read0_power': [14.8099], - 'read1_power': [14.0866], - 'slew_hl': [0.7280485], - 'slew_lh': [0.7280485], - 'write0_power': [16.865], - 'write1_power': [14.8288]} + 'read0_power': [14.7569], + 'read1_power': [14.008800000000003], + 'slew_hl': [0.7314153], + 'slew_lh': [0.7314153], + 'write0_power': [16.700500000000005], + 'write1_power': [15.214100000000002]} else: self.assertTrue(False) # other techs fail # Check if no too many or too few results diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index e57ad120..1373f1f3 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -65,16 +65,16 @@ class timing_sram_test(openram_test): 'write0_power': [0.48889660000000007], 'write1_power': [0.4419755]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.718183], - 'delay_lh': [1.718183], - 'leakage_power': 0.1342958, + golden_data = {'delay_hl': [1.710243], + 'delay_lh': [1.710243], + 'leakage_power': 0.06079017, 'min_period': 3.75, - 'read0_power': [14.1499], - 'read1_power': [13.639719999999999], - 'slew_hl': [0.7794919], - 'slew_lh': [0.7794919], - 'write0_power': [15.978829999999999], - 'write1_power': [14.128079999999999]} + 'read0_power': [14.046140000000001], + 'read1_power': [13.52625], + 'slew_hl': [0.7730236], + 'slew_lh': [0.7730236], + 'write0_power': [15.86152], + 'write1_power': [14.612160000000001]} else: self.assertTrue(False) # other techs fail From 98878a0a27fd026517df701fdfdf1df5dd2a8d2a Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 27 Jul 2019 12:14:00 -0700 Subject: [PATCH 159/234] Conditionally path exclude --- compiler/modules/control_logic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 44953b8e..2fbaf31c 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -964,4 +964,5 @@ class control_logic(design.design): """Exclude dffs from graph as they do not represent critical path""" self.graph_inst_exclude.add(self.ctrl_dff_inst) - self.graph_inst_exclude.add(self.w_en_gate_inst) + if self.port_type=="rw" or self.port_type=="w": + self.graph_inst_exclude.add(self.w_en_gate_inst) From c12dd987dcd8dbfbb4894ec4fc7ac5fd64e703ad Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 30 Jul 2019 00:49:43 -0700 Subject: [PATCH 160/234] Fixed pbitcell graph edge formation. --- compiler/bitcells/pbitcell.py | 7 ++++++- compiler/characterizer/delay.py | 11 +++-------- compiler/characterizer/functional.py | 14 +++++--------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 6d95a15f..3c59a9e3 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -962,11 +962,16 @@ class pbitcell(design.design): def build_graph(self, graph, inst_name, port_nets): """Adds edges to graph for pbitcell. Only readwrite and read ports.""" + + if self.dummy_bitcell: + return + pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} # Edges added wl->bl, wl->br for every port except write ports rw_pin_names = zip(self.r_wl_names, self.r_bl_names, self.r_br_names) r_pin_names = zip(self.rw_wl_names, self.rw_bl_names, self.rw_br_names) - for pin_zip in zip(rw_pin_names, r_pin_names): + + for pin_zip in [rw_pin_names, r_pin_names]: for wl,bl,br in pin_zip: graph.add_edge(pin_dict[wl],pin_dict[bl]) graph.add_edge(pin_dict[wl],pin_dict[br]) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 09bf4571..854739cb 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -261,7 +261,7 @@ class delay(simulation): port = 0 self.graph.get_all_paths('{}{}'.format(tech.spice["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)) @@ -285,12 +285,7 @@ class delay(simulation): def get_bl_name(self, paths): """Gets the signal name associated with the bitlines in the bank.""" - cell_mods = factory.get_mods(OPTS.bitcell) - if len(cell_mods)>=1: - cell_mod = self.get_primary_cell_mod(cell_mods) - elif len(cell_mods)==0: - debug.error("No bitcells found. Cannot determine bitline names.", 1) - + cell_mod = factory.create(module_type=OPTS.bitcell) cell_bl = cell_mod.get_bl_name() cell_br = cell_mod.get_br_name() @@ -301,7 +296,7 @@ class delay(simulation): for int_net in [cell_bl, cell_br]: bl_names.append(self.get_alias_in_path(paths, int_net, cell_mod, exclude_set)) - return bl_names[0], bl_names[1] + return bl_names[0], bl_names[1] def get_bl_name_search_exclusions(self): diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 0b3e7b4b..dc4fe48a 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -413,7 +413,7 @@ class functional(simulation): port = 0 self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), - '{}{}_{}'.format(self.dout_name, port, 0)) + '{}{}_{}'.format(self.dout_name, port, 0).lower()) self.sen_name = self.get_sen_name(self.graph.all_paths) debug.info(2,"s_en name = {}".format(self.sen_name)) @@ -422,7 +422,7 @@ class functional(simulation): debug.info(2,"bl name={}, br name={}".format(self.bl_name,self.br_name)) self.q_name,self.qbar_name = self.get_bit_name() - debug.info(2,"q name={}\nqbar name={}".format(self.bl_name,self.br_name)) + debug.info(2,"q name={}\nqbar name={}".format(self.q_name,self.qbar_name)) def get_bit_name(self): """ Get a bit cell name """ @@ -454,12 +454,7 @@ class functional(simulation): def get_bl_name(self, paths): """Gets the signal name associated with the bitlines in the bank.""" - cell_mods = factory.get_mods(OPTS.bitcell) - if len(cell_mods)>=1: - cell_mod = self.get_primary_cell_mod(cell_mods) - elif len(cell_mods)==0: - debug.error("No bitcells found. Cannot determine bitline names.", 1) - + cell_mod = factory.create(module_type=OPTS.bitcell) cell_bl = cell_mod.get_bl_name() cell_br = cell_mod.get_br_name() @@ -494,8 +489,9 @@ class functional(simulation): has_cell = has_cell or replica_cell.contains(bitcell, replica_cell.mods) if not has_cell: non_rbc_mods.append(bitcell) + if len(non_rbc_mods) != 1: - debug.error('Multiple bitcell mods found. Cannot distinguish for characterization',1) + debug.error('{} possible bitcell mods found. Cannot distinguish for characterization'.format(len(non_rbc_mods)),1) return non_rbc_mods[0] def are_mod_pins_equal(self, mods): From 24b1fa38a0466606771f876b5acb70562486b5ac Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 30 Jul 2019 20:31:32 -0700 Subject: [PATCH 161/234] Added graph fixes to handmade multiport cells. --- compiler/bitcells/bitcell_1w_1r.py | 4 +-- compiler/bitcells/dummy_bitcell_1rw_1r.py | 12 ++----- compiler/bitcells/dummy_bitcell_1w_1r.py | 10 ++---- compiler/bitcells/replica_bitcell_1w_1r.py | 11 +++--- compiler/characterizer/delay.py | 10 +++--- compiler/characterizer/functional.py | 42 ++++------------------ compiler/modules/replica_bitcell_array.py | 7 ++-- compiler/modules/replica_column.py | 11 +++--- 8 files changed, 32 insertions(+), 75 deletions(-) diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index b36c38bf..6063cf86 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -139,6 +139,6 @@ class bitcell_1w_1r(design.design): pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} #Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges - graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) - graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) # Port 1 is a write port, so its timing is not considered here. diff --git a/compiler/bitcells/dummy_bitcell_1rw_1r.py b/compiler/bitcells/dummy_bitcell_1rw_1r.py index 189c4894..f8986f2d 100644 --- a/compiler/bitcells/dummy_bitcell_1rw_1r.py +++ b/compiler/bitcells/dummy_bitcell_1rw_1r.py @@ -41,13 +41,5 @@ class dummy_bitcell_1rw_1r(design.design): return 2*access_tx_cin def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Multiport bitcell timing graph is too complex - to use the add_graph_edges function.""" - pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} - #Edges hardcoded here. Essentially wl->bl/br for both ports. - # Port 0 edges - graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) - graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) - # Port 1 edges - graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) - graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) + """Dummy bitcells are cannot form a path and be part of the timing graph""" + return diff --git a/compiler/bitcells/dummy_bitcell_1w_1r.py b/compiler/bitcells/dummy_bitcell_1w_1r.py index 95d514f8..ef451b8c 100644 --- a/compiler/bitcells/dummy_bitcell_1w_1r.py +++ b/compiler/bitcells/dummy_bitcell_1w_1r.py @@ -41,11 +41,5 @@ class dummy_bitcell_1w_1r(design.design): return 2*access_tx_cin def build_graph(self, graph, inst_name, port_nets): - """Adds edges to graph. Multiport bitcell timing graph is too complex - to use the add_graph_edges function.""" - pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} - #Edges hardcoded here. Essentially wl->bl/br for both ports. - # Port 0 edges - graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) - graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) - # Port 1 is a write port, so its timing is not considered here. + """Dummy bitcells are cannot form a path and be part of the timing graph""" + return diff --git a/compiler/bitcells/replica_bitcell_1w_1r.py b/compiler/bitcells/replica_bitcell_1w_1r.py index c0d31a69..79171bf5 100644 --- a/compiler/bitcells/replica_bitcell_1w_1r.py +++ b/compiler/bitcells/replica_bitcell_1w_1r.py @@ -43,9 +43,10 @@ class replica_bitcell_1w_1r(design.design): def build_graph(self, graph, inst_name, port_nets): """Adds edges to graph. Multiport bitcell timing graph is too complex to use the add_graph_edges function.""" + debug.info(1,'Adding edges for {}'.format(inst_name)) pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} - #Edges hardcoded here. Essentially wl->bl/br for both ports. - # Port 0 edges - graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) - graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) - # Port 1 is a write port, so its timing is not considered here. \ No newline at end of file + #Edges hardcoded here. Essentially wl->bl/br for the read port. + # Port 1 edges + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) + # Port 0 is a write port, so its timing is not considered here. \ No newline at end of file diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 854739cb..37c38353 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -258,14 +258,14 @@ class delay(simulation): def set_internal_spice_names(self): """Sets important names for characterization such as Sense amp enable and internal bit nets.""" - port = 0 + port = self.read_ports[0] self.graph.get_all_paths('{}{}'.format(tech.spice["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) + 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)) def get_sen_name(self, paths): @@ -282,12 +282,12 @@ class delay(simulation): sen_name = self.get_alias_in_path(paths, enable_name, sa_mods[0]) return sen_name - def get_bl_name(self, paths): + def get_bl_name(self, paths, port): """Gets the signal name associated with the bitlines in the bank.""" cell_mod = factory.create(module_type=OPTS.bitcell) - cell_bl = cell_mod.get_bl_name() - cell_br = cell_mod.get_br_name() + cell_bl = cell_mod.get_bl_name(port) + cell_br = cell_mod.get_br_name(port) bl_found = False # Only a single path should contain a single s_en name. Anything else is an error. diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index dc4fe48a..9f8e3d43 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -411,14 +411,15 @@ class functional(simulation): def set_internal_spice_names(self): """Sets important names for characterization such as Sense amp enable and internal bit nets.""" - port = 0 + # For now, only testing these using first read port. + port = self.read_ports[0] self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), '{}{}_{}'.format(self.dout_name, port, 0).lower()) 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) + 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)) self.q_name,self.qbar_name = self.get_bit_name() @@ -451,12 +452,12 @@ class functional(simulation): return sen_name # FIXME: refactor to share with delay.py - def get_bl_name(self, paths): + def get_bl_name(self, paths, port): """Gets the signal name associated with the bitlines in the bank.""" cell_mod = factory.create(module_type=OPTS.bitcell) - cell_bl = cell_mod.get_bl_name() - cell_br = cell_mod.get_br_name() + cell_bl = cell_mod.get_bl_name(port) + cell_br = cell_mod.get_br_name(port) bl_found = False # Only a single path should contain a single s_en name. Anything else is an error. @@ -473,37 +474,6 @@ class functional(simulation): # Exclude the RBL as it contains bitcells which are not in the main bitcell array # so it makes the search awkward return set(factory.get_mods(OPTS.replica_bitline)) - - def get_primary_cell_mod(self, cell_mods): - """ - Distinguish bitcell array mod from replica bitline array. - Assume there are no replica bitcells in the primary array. - """ - if len(cell_mods) == 1: - return cell_mods[0] - rbc_mods = factory.get_mods(OPTS.replica_bitcell) - non_rbc_mods = [] - for bitcell in cell_mods: - has_cell = False - for replica_cell in rbc_mods: - has_cell = has_cell or replica_cell.contains(bitcell, replica_cell.mods) - if not has_cell: - non_rbc_mods.append(bitcell) - - if len(non_rbc_mods) != 1: - debug.error('{} possible bitcell mods found. Cannot distinguish for characterization'.format(len(non_rbc_mods)),1) - return non_rbc_mods[0] - - def are_mod_pins_equal(self, mods): - """Determines if there are pins differences in the input mods""" - - if len(mods) == 0: - return True - pins = mods[0].pins - for mod in mods[1:]: - if pins != mod.pins: - return False - return True def get_alias_in_path(self, paths, int_net, mod, exclusion_set=None): """ diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index c748e83d..6f4e96c5 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -138,8 +138,6 @@ class replica_bitcell_array(design.design): # 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]) - #Save where the RBL wordlines start for graph purposes. Even positions are changed then graph will break - self.rbl_row_pos = len(self.replica_col_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 @@ -445,9 +443,10 @@ class replica_bitcell_array(design.design): self.bitcell_array.graph_exclude_bits(targ_row, targ_col) def graph_exclude_replica_col_bits(self): + """Exclude all replica/dummy cells in the replica columns except the replica bit.""" + for port in range(self.left_rbl+self.right_rbl): - #While the rbl_wl bits may be on a few rows. Only keep one for simplicity. - self.replica_columns[port].exclude_bits_except_one(self.rbl_row_pos) + self.replica_columns[port].exclude_all_but_replica() def get_cell_name(self, inst_name, row, col): """Gets the spice name of the target bitcell.""" diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index b18c49fe..fb11a8f5 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -29,7 +29,7 @@ class replica_column(design.design): self.replica_bit = replica_bit # left, right, regular rows plus top/bottom dummy cells self.total_size = self.left_rbl+rows+self.right_rbl+2 - + debug.check(replica_bit!=0 and replica_bit!=rows,"Replica bit cannot be the dummy row.") debug.check(replica_bit<=left_rbl or replica_bit>=self.total_size-right_rbl-1, "Replica bit cannot be in the regular array.") @@ -152,8 +152,9 @@ class replica_column(design.design): return bitcell_pins - def exclude_bits_except_one(self, selected_row): + def exclude_all_but_replica(self): + """Excludes all bits except the replica cell (self.replica_bit).""" + for row, cell in self.cell_inst.items(): - if row == selected_row: - continue - self.graph_inst_exclude.add(cell) + if row != self.replica_bit: + self.graph_inst_exclude.add(cell) From b4ef0ec36dc099a455e40f142f6547c9d53e0bb2 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 30 Jul 2019 20:33:17 -0700 Subject: [PATCH 162/234] Removed unused characterization module. --- compiler/characterizer/__init__.py | 1 - compiler/characterizer/worst_case.py | 84 ---------------------------- 2 files changed, 85 deletions(-) delete mode 100644 compiler/characterizer/worst_case.py diff --git a/compiler/characterizer/__init__.py b/compiler/characterizer/__init__.py index 8153251b..93dd5bcb 100644 --- a/compiler/characterizer/__init__.py +++ b/compiler/characterizer/__init__.py @@ -13,7 +13,6 @@ from .lib import * from .delay import * from .setup_hold import * from .functional import * -from .worst_case import * from .simulation import * from .measurements import * from .model_check import * diff --git a/compiler/characterizer/worst_case.py b/compiler/characterizer/worst_case.py deleted file mode 100644 index 1d4c095e..00000000 --- a/compiler/characterizer/worst_case.py +++ /dev/null @@ -1,84 +0,0 @@ -# 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 sys,re,shutil -import debug -import tech -import math -from .stimuli import * -from .trim_spice import * -from .charutils import * -import utils -from globals import OPTS -from .delay import delay - -class worst_case(delay): - """Functions to test for the worst case delay in a target SRAM - - The current worst case determines a feasible period for the SRAM then tests - several bits and record the delay and differences between the bits. - - """ - - def __init__(self, sram, spfile, corner): - delay.__init__(self,sram,spfile,corner) - - - def analyze(self,probe_address, probe_data, slews, loads): - """ - Main function to test the delays of different bits. - """ - debug.check(OPTS.num_rw_ports < 2 and OPTS.num_w_ports < 1 and OPTS.num_r_ports < 1 , - "Bit testing does not currently support multiport.") - #Dict to hold all characterization values - char_sram_data = {} - - self.set_probe(probe_address, probe_data) - #self.prepare_netlist() - - self.load=max(loads) - self.slew=max(slews) - - # 1) Find a feasible period and it's corresponding delays using the trimmed array. - feasible_delays = self.find_feasible_period() - - # 2) Find the delays of several bits - test_bits = self.get_test_bits() - bit_delays = self.simulate_for_bit_delays(test_bits) - - for i in range(len(test_bits)): - debug.info(1, "Bit tested: addr {0[0]} data_pos {0[1]}\n Values {1}".format(test_bits[i], bit_delays[i])) - - def simulate_for_bit_delays(self, test_bits): - """Simulates the delay of the sram of over several bits.""" - bit_delays = [{} for i in range(len(test_bits))] - - #Assumes a bitcell with only 1 rw port. (6t, port 0) - port = 0 - self.targ_read_ports = [self.read_ports[port]] - self.targ_write_ports = [self.write_ports[port]] - - for i in range(len(test_bits)): - (bit_addr, bit_data) = test_bits[i] - self.set_probe(bit_addr, bit_data) - debug.info(1,"Delay bit test: period {}, addr {}, data_pos {}".format(self.period, bit_addr, bit_data)) - (success, results)=self.run_delay_simulation() - debug.check(success, "Bit Test Failed: period {}, addr {}, data_pos {}".format(self.period, bit_addr, bit_data)) - bit_delays[i] = results[port] - - return bit_delays - - - def get_test_bits(self): - """Statically determines address and bit values to test""" - #First and last address, first middle, and last bit. Last bit is repeated twice with different data position. - bit_addrs = ["0"*self.addr_size, "0"+"1"*(self.addr_size-1), "1"*self.addr_size, "1"*self.addr_size] - data_positions = [0, (self.word_size-1)//2, 0, self.word_size-1] - #Return them in a tuple form - return [(bit_addrs[i], data_positions[i]) for i in range(len(bit_addrs))] - - From 774f08da513ea0c62f244fda46939892cbd12689 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 31 Jul 2019 14:11:37 -0700 Subject: [PATCH 163/234] Added layout pins to and test for write_mask_and_array. --- compiler/modules/write_driver_array.py | 2 - compiler/modules/write_mask_and_array.py | 141 +++++++++------------- compiler/tests/10_write_mask_and_array.py | 57 +++++++++ 3 files changed, 113 insertions(+), 87 deletions(-) create mode 100644 compiler/tests/10_write_mask_and_array.py diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 5f71b038..7da57b37 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -150,8 +150,6 @@ class write_driver_array(design.design): layer="metal3", offset=pin_pos) - - self.add_layout_pin(text="en", layer="metal1", offset=self.driver_insts[0].get_pin("en").ll().scale(0,1), diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 9a9a8f12..b43399e0 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -16,8 +16,8 @@ from globals import OPTS class write_mask_and_array(design.design): """ - Array of tristate drivers to write to the bitlines through the column mux. - Dynamically generated write driver array of all bitlines. + Array of AND gates to turn write mask signal on only when w_en is on. + The write mask AND array goes between the write driver array and the sense amp array. """ def __init__(self, name, columns, word_size, write_size): @@ -34,29 +34,25 @@ class write_mask_and_array(design.design): self.num_wmasks = int(word_size / write_size) self.create_netlist() - # if not OPTS.netlist_only: - # self.create_layout() + if not OPTS.netlist_only: + self.create_layout() def create_netlist(self): self.add_modules() self.add_pins() -# self.create_write_mask_array() self.create_and2_array() - # def create_layout(self): - # - # if self.bitcell.width > self.driver.width: - # self.width = self.columns * self.bitcell.width - # else: - # self.width = self.columns * self.driver.width - # - # self.height = self.driver.height - # - # self.place_write_array() - # self.add_layout_pins() - # self.add_boundary() - # self.DRC_LVS() + def create_layout(self): + + self.width = self.num_wmasks * self.and2.width + + self.height = self.and2.height + + self.place_and2_array() + self.add_layout_pins() + self.add_boundary() + self.DRC_LVS() def add_pins(self): for bit in range(self.num_wmasks): @@ -68,28 +64,10 @@ class write_mask_and_array(design.design): self.add_pin("gnd","GROUND") def add_modules(self): - self.wmask = factory.create(module_type="dff_buf") - #self.add_mod(self.wmask) - dff_height = self.wmask.height - - self.and2 = factory.create(module_type="pand2", - size=4, - height=dff_height) + self.and2 = factory.create(module_type="pand2") self.add_mod(self.and2) - # def create_write_mask_array(self): - # self.wmask_insts = {} - # for bit in range(self.num_wmask): - # name = "write_mask_{}".format(bit) - # self.wmask_insts[bit] = self.add_inst(name=name, - # mod=self.wmask) - # - # self.connect_inst(["wmask_{}".format(bit), - # "bank_wmask_{}".format(bit), - # "bank_wmask_bar_{}".format(bit), - # "clk", "vdd", "gnd"]) - def create_and2_array(self): self.and2_insts = {} for bit in range(self.num_wmasks): @@ -102,55 +80,48 @@ class write_mask_and_array(design.design): "vdd", "gnd"]) - # def place_write_array(self): - # if self.bitcell.width > self.driver.width: - # driver_spacing = self.bitcell.width - # else: - # driver_spacing = self.driver.width - # - # for i in range(0, self.columns, self.words_per_row): - # index = int(i / self.words_per_row) - # base = vector(i * driver_spacing, 0) - # self.driver_insts[index].place(base) + def place_and2_array(self): + # place the write mask AND array below the write driver array + and2_spacing = self.and2.width + for i in range(self.num_wmasks): + base = vector(i * and2_spacing, 0) + self.and2_insts[i].place(base) + + + def add_layout_pins(self): + for i in range(self.num_wmasks): + wmask_in_pin = self.and2_insts[i].get_pin("A") + self.add_layout_pin(text="wmask_in_{0}".format(i), + layer=wmask_in_pin.layer, + offset=wmask_in_pin.ll(), + width=wmask_in_pin.width(), + height=wmask_in_pin.height()) + + en_pin = self.and2_insts[i].get_pin("B") + self.add_layout_pin(text="en", + layer=en_pin.layer, + offset=en_pin.ll(), + width=en_pin.width(), + height=en_pin.height()) + + wmask_out_pin = self.and2_insts[i].get_pin("Z") + self.add_layout_pin(text="wmask_out_{0}".format(i), + layer=wmask_out_pin.layer, + offset=wmask_out_pin.ll(), + width=wmask_out_pin.width(), + height=wmask_out_pin.height()) + + for n in ["vdd", "gnd"]: + pin_list = self.and2_insts[i].get_pins(n) + for pin in pin_list: + pin_pos = pin.center() + # Add the M2->M3 stack + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=pin_pos) + self.add_layout_pin_rect_center(text=n, + layer="metal3", + offset=pin_pos) - # def add_layout_pins(self): - # for i in range(self.word_size): - # din_pin = self.driver_insts[i].get_pin("din") - # self.add_layout_pin(text="data_{0}".format(i), - # layer="metal2", - # offset=din_pin.ll(), - # width=din_pin.width(), - # height=din_pin.height()) - # bl_pin = self.driver_insts[i].get_pin("bl") - # self.add_layout_pin(text="bl_{0}".format(i), - # layer="metal2", - # offset=bl_pin.ll(), - # width=bl_pin.width(), - # height=bl_pin.height()) - # - # br_pin = self.driver_insts[i].get_pin("br") - # self.add_layout_pin(text="br_{0}".format(i), - # layer="metal2", - # offset=br_pin.ll(), - # width=br_pin.width(), - # height=br_pin.height()) - # - # for n in ["vdd", "gnd"]: - # pin_list = self.driver_insts[i].get_pins(n) - # for pin in pin_list: - # pin_pos = pin.center() - # # Add the M2->M3 stack - # self.add_via_center(layers=("metal2", "via2", "metal3"), - # offset=pin_pos) - # self.add_layout_pin_rect_center(text=n, - # layer="metal3", - # offset=pin_pos) - # - # self.add_layout_pin(text="en", - # layer="metal1", - # offset=self.driver_insts[0].get_pin("en").ll().scale(0, 1), - # width=self.width, - # height=drc('minwidth_metal1')) # def get_w_en_cin(self): # """Get the relative capacitance of all the enable connections in the bank""" diff --git a/compiler/tests/10_write_mask_and_array.py b/compiler/tests/10_write_mask_and_array.py new file mode 100644 index 00000000..c79b8fc6 --- /dev/null +++ b/compiler/tests/10_write_mask_and_array.py @@ -0,0 +1,57 @@ +#!/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 write_mask_and_array_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + # check write driver array for single port + debug.info(2, "Testing write_mask_and_array for columns=8, word_size=8, write_size=4") + a = factory.create(module_type="write_mask_and_array", columns=8, word_size=8, write_size=4) + self.local_check(a) + + debug.info(2, "Testing write_mask_and_array for columns=16, word_size=8, write_size=2") + a = factory.create(module_type="write_mask_and_array", columns=16, word_size=8, write_size=2) + self.local_check(a) + + # check write driver array for multi-port + OPTS.bitcell = "pbitcell" + OPTS.num_rw_ports = 1 + OPTS.num_w_ports = 0 + OPTS.num_r_ports = 0 + + factory.reset() + debug.info(2, "Testing write_mask_and_array for columns=8, word_size=8, write_size=4 (multi-port case)") + a = factory.create(module_type="write_mask_and_array", columns=8, word_size=8, write_size=4) + self.local_check(a) + + debug.info(2, "Testing write_mask_and_array for columns=16, word_size=8, write_size=2 (multi-port case)") + a = factory.create(module_type="write_mask_and_array", columns=16, word_size=8, write_size=2) + 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()) \ No newline at end of file From bb1627bcec4ce34da8f154fde7fc28a20c12a52f Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 31 Jul 2019 14:59:33 -0700 Subject: [PATCH 164/234] Added test to end of w_mask_and_array so a regression test will be performed on it. --- ...10_write_mask_and_array.py => 10_write_mask_and_array_test.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename compiler/tests/{10_write_mask_and_array.py => 10_write_mask_and_array_test.py} (100%) diff --git a/compiler/tests/10_write_mask_and_array.py b/compiler/tests/10_write_mask_and_array_test.py similarity index 100% rename from compiler/tests/10_write_mask_and_array.py rename to compiler/tests/10_write_mask_and_array_test.py From 4b75e49302ac5357f3f5054f0b8368215337b2b8 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 1 Aug 2019 08:59:41 -0700 Subject: [PATCH 165/234] Remove unnecessary footer in write driver --- .../scn4m_subm/gds_lib/write_driver.gds | Bin 11484 -> 10204 bytes .../scn4m_subm/mag_lib/write_driver.mag | 29 ++++-------------- technology/scn4m_subm/sp_lib/write_driver.sp | 5 ++- 3 files changed, 8 insertions(+), 26 deletions(-) diff --git a/technology/scn4m_subm/gds_lib/write_driver.gds b/technology/scn4m_subm/gds_lib/write_driver.gds index 1f9274ac7ef3ec3b246ba7fcd29ea8c597cf71ce..63bf58d2d6f921b243ba1f25395427be28429454 100644 GIT binary patch delta 287 zcmcZ;dB6_|xko}k$aV(<1IG*o1{iG;FM08Vn4z z3=9n1Ks7MBZUO@XNE}AjGHlM1m13IQq2MstLs3L%N&y1{X95EQj4o)HyiR`B;uDG- zY9Qen3kC+B1_WIn0Z|U4Yb-Xu)9hfHJWt1Ba*4Kx6xRo!)h8G@B-zsQQWzLm1c8_x Hh*=l_NJu-K delta 1058 zcmZvav2W8*7{t$sNkSV+nxr&MqKI0>MM8=?P}Kwc4Rkb2h=H-n(!`-DNvjA&>H>Nl zPzL4>$SU&Ev17;1QHG8cgJ(wG`Srs>Fhswn@7;HHd^dkJf9)WL46@#Ecl%UyU141M6yS;|ju0nUX(U&U6->E9TckZbvCvqtuBqR^UJ zF3N=uzMNB_AKi@_zoNgz{3|Q#|40M;c=ka3ymkIMp4;FNyW0B3#rW46Vrib zOoeCC51@orLRxcfsD4%)XInpo5+S8@6K>zCxY923 znq%Q}KZ>hU+b!$df?c4he?qo~b78O>g=_VU%REm?CTHR4UCzRjl4>`n$@gH9iX&4f zk}K@DaD1)8#+yWXbZ$x}> rect -3 101 37 138 rect -3 0 37 51 @@ -10,7 +10,6 @@ rect -3 51 37 101 << ntransistor >> rect 9 178 11 190 rect 17 178 19 190 -rect 15 163 27 165 rect 9 144 11 148 rect 17 144 19 148 rect 10 82 12 89 @@ -31,10 +30,6 @@ rect 8 178 9 190 rect 11 178 12 190 rect 16 178 17 190 rect 19 178 20 190 -rect 15 165 27 166 -rect 15 162 27 163 -rect 12 158 15 161 -rect 12 156 16 158 rect 8 144 9 148 rect 11 144 12 148 rect 16 144 17 148 @@ -71,8 +66,6 @@ rect 3 35 7 38 rect 4 178 8 190 rect 12 178 16 190 rect 20 178 24 190 -rect 15 166 27 170 -rect 15 158 27 162 rect 4 144 8 148 rect 12 144 16 148 rect 20 144 24 148 @@ -95,7 +88,6 @@ rect 11 38 15 45 rect 19 38 23 45 rect 27 38 31 45 << psubstratepcontact >> -rect 12 152 16 156 rect 26 82 30 89 << nsubstratencontact >> rect 12 118 16 122 @@ -109,8 +101,6 @@ rect 9 176 11 178 rect 17 173 19 178 rect 6 171 19 173 rect 6 168 8 171 -rect 13 163 15 165 -rect 27 163 33 165 rect 9 148 11 150 rect 17 148 19 150 rect 9 132 11 144 @@ -133,12 +123,9 @@ rect 18 89 20 90 rect 10 81 12 82 rect 10 79 13 81 rect 2 71 3 75 -rect 11 71 13 79 +rect 11 67 13 79 rect 18 79 20 82 rect 18 77 23 79 -rect 31 71 33 163 -rect 11 69 33 71 -rect 11 67 13 69 rect 8 65 13 67 rect 8 64 10 65 rect 16 64 18 66 @@ -164,13 +151,9 @@ rect 15 10 19 14 rect 5 193 10 197 rect 5 190 8 193 rect 32 182 33 186 -rect 13 170 16 178 -rect 13 166 15 170 rect 4 148 8 164 -rect 12 158 15 162 -rect 12 156 16 158 -rect 23 157 27 158 -rect 12 148 16 152 +rect 12 163 16 178 +rect 12 148 16 159 rect 4 132 8 144 rect 20 142 24 144 rect 30 142 33 182 @@ -199,7 +182,7 @@ rect 11 24 36 28 << m2contact >> rect 10 193 14 197 rect 20 190 24 194 -rect 23 153 27 157 +rect 12 159 16 163 rect 16 118 20 122 rect 26 89 30 90 rect 26 86 30 89 @@ -220,7 +203,7 @@ rlabel m2contact 21 66 21 66 1 gnd rlabel m2contact 28 88 28 88 1 gnd rlabel m2contact 21 33 21 33 1 vdd rlabel m2contact 18 120 18 120 1 vdd -rlabel m2contact 25 155 25 155 1 gnd rlabel metal2 12 201 12 201 5 bl rlabel metal2 22 201 22 201 5 br +rlabel m2contact 14 161 14 161 1 gnd << end >> diff --git a/technology/scn4m_subm/sp_lib/write_driver.sp b/technology/scn4m_subm/sp_lib/write_driver.sp index d1dbf9b2..e86da288 100644 --- a/technology/scn4m_subm/sp_lib/write_driver.sp +++ b/technology/scn4m_subm/sp_lib/write_driver.sp @@ -28,9 +28,8 @@ M_14 din_gated_bar din_gated gnd gnd n W=0.8u L=0.4u ************************************************ * pull down with en enable -M_15 bl din_gated_bar net_5 gnd n W=2.4u L=0.4u -M_16 br din_bar_gated_bar net_5 gnd n W=2.4u L=0.4u -M_17 net_5 en gnd gnd n W=2.4u L=0.4u +M_15 bl din_gated_bar gnd gnd n W=2.4u L=0.4u +M_16 br din_bar_gated_bar gnd gnd n W=2.4u L=0.4u From d4033621838160e14a5b528231b2bda9a4a957ee Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 1 Aug 2019 11:32:49 -0700 Subject: [PATCH 166/234] Sort keys for random read address choice. --- compiler/characterizer/functional.py | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 9f8e3d43..6b71ee8b 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -139,7 +139,6 @@ class functional(simulation): elif op == "write": addr = self.gen_addr() word = self.gen_data() - # print("write",self.t_current,addr,word) # two ports cannot write to the same address if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) @@ -161,7 +160,6 @@ class functional(simulation): lower = bit * self.write_size upper = lower + self.write_size - 1 new_word = new_word[:lower] + old_word[lower:upper+1] + new_word[upper + 1:] - # print("partial_w",self.t_current,addr,wmask,word, "partial_w_word:", new_word) # two ports cannot write to the same address if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) @@ -172,7 +170,6 @@ class functional(simulation): w_addrs.append(addr) else: (addr,word) = random.choice(list(self.stored_words.items())) - # print("read",self.t_current,addr,word) # cannot read from an address that is currently being written to if addr in w_addrs: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) @@ -248,29 +245,20 @@ class functional(simulation): def gen_data(self): """ Generates a random word to write. """ - rand = random.randint(0,(2**self.word_size)-1) - data_bits = self.convert_to_bin(rand,False) + random_value = random.randint(0,(2**self.word_size)-1) + data_bits = self.convert_to_bin(random_value,False) return data_bits - def gen_data_all_bits(self): - """ Generates a random word, either all 0's or all 1's, to write. """ - rand = random.randint(0,1) - bits = [] - for bit in range(self.word_size): - bits.append(rand) - data_bits = ''.join(map(str,bits)) - return data_bits - def gen_addr(self): """ Generates a random address value to write to. """ - rand = random.randint(0,(2**self.addr_size)-1) - addr_bits = self.convert_to_bin(rand,True) + random_value = random.randint(0,(2**self.addr_size)-1) + addr_bits = self.convert_to_bin(random_value,True) return addr_bits def get_data(self): """ Gets an available address and corresponding word. """ # Currently unused but may need later depending on how the functional test develops - addr = random.choice(list(self.stored_words.keys())) + addr = random.choice(sort(list(self.stored_words.keys()))) word = self.stored_words[addr] return (addr,word) @@ -280,6 +268,7 @@ class functional(simulation): if(is_addr): expected_value = self.addr_size else: + expected_value = self.word_size for i in range (expected_value - len(new_value)): new_value = "0" + new_value From a8d09acd402084cf8fdce284ae3844946e1c6622 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 1 Aug 2019 12:21:30 -0700 Subject: [PATCH 167/234] Use ordered dict instead of sorting keys --- compiler/characterizer/functional.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 6b71ee8b..6dcb54e0 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -6,6 +6,7 @@ # All rights reserved. # import sys,re,shutil +import collections from design import design import debug import math @@ -52,7 +53,8 @@ class functional(simulation): # Number of checks can be changed self.num_cycles = 15 - self.stored_words = {} + # This is to have ordered keys for random selection + self.stored_words = collections.OrderedDict() self.write_check = [] self.read_check = [] @@ -258,7 +260,7 @@ class functional(simulation): def get_data(self): """ Gets an available address and corresponding word. """ # Currently unused but may need later depending on how the functional test develops - addr = random.choice(sort(list(self.stored_words.keys()))) + addr = random.choice(list(self.stored_words.keys())) word = self.stored_words[addr] return (addr,word) From ff64e7663e46b856f5950bb012ee4271a8a5ca54 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 1 Aug 2019 12:21:43 -0700 Subject: [PATCH 168/234] Add p_en_bar to write ports as well --- compiler/modules/bank.py | 15 ++++++--------- compiler/modules/port_data.py | 3 +-- compiler/sram/sram_base.py | 7 +++---- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 127963ab..f60b5f32 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -100,8 +100,7 @@ class bank(design.design): self.add_pin("bank_sel{}".format(port),"INPUT") for port in self.read_ports: self.add_pin("s_en{0}".format(port), "INPUT") - for port in self.read_ports: - self.add_pin("p_en_bar{0}".format(port), "INPUT") + self.add_pin("p_en_bar{0}".format(port), "INPUT") for port in self.write_ports: self.add_pin("w_en{0}".format(port), "INPUT") for bit in range(self.num_wmasks): @@ -309,7 +308,7 @@ class bank(design.design): self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "rbl_wl{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_w_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num)]) + self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "p_en_bar{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_r_ports): self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "rbl_wl{}".format(port_num)]) @@ -463,8 +462,7 @@ class bank(design.design): temp.extend(sel_names) if port in self.read_ports: temp.append("s_en{0}".format(port)) - if port in self.read_ports: - temp.append("p_en_bar{0}".format(port)) + temp.append("p_en_bar{0}".format(port)) if port in self.write_ports: temp.append("w_en{0}".format(port)) for bit in range(self.num_wmasks): @@ -618,8 +616,8 @@ class bank(design.design): bank_sel_signals = ["clk_buf", "w_en", "s_en", "p_en_bar", "bank_sel"] gated_bank_sel_signals = ["gated_clk_buf", "gated_w_en", "gated_s_en", "gated_p_en_bar"] elif self.port_id[port] == "w": - bank_sel_signals = ["clk_buf", "w_en", "bank_sel"] - gated_bank_sel_signals = ["gated_clk_buf", "gated_w_en"] + bank_sel_signals = ["clk_buf", "w_en", "p_en_bar", "bank_sel"] + gated_bank_sel_signals = ["gated_clk_buf", "gated_w_en", "gated_p_en_bar"] else: bank_sel_signals = ["clk_buf", "s_en", "p_en_bar", "bank_sel"] gated_bank_sel_signals = ["gated_clk_buf", "gated_s_en", "gated_p_en_bar"] @@ -944,8 +942,7 @@ class bank(design.design): read_inst = 0 connection = [] - if port in self.read_ports: - connection.append((self.prefix+"p_en_bar{}".format(port), self.port_data_inst[port].get_pin("p_en_bar").lc())) + connection.append((self.prefix+"p_en_bar{}".format(port), self.port_data_inst[port].get_pin("p_en_bar").lc())) if port in self.read_ports: rbl_wl_name = self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index bf015666..3e4caf57 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -100,8 +100,7 @@ class port_data(design.design): self.add_pin(pin_name,"INPUT") if self.port in self.read_ports: self.add_pin("s_en", "INPUT") - if self.port in self.read_ports: - self.add_pin("p_en_bar", "INPUT") + self.add_pin("p_en_bar", "INPUT") if self.port in self.write_ports: self.add_pin("w_en", "INPUT") for bit in range(self.num_wmasks): diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 637c7c8a..45befe16 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -197,7 +197,7 @@ class sram_base(design, verilog, lef): if self.port_id[port] == "r": self.control_bus_names[port].extend([sen, pen]) elif self.port_id[port] == "w": - self.control_bus_names[port].extend([wen]) + self.control_bus_names[port].extend([wen, pen]) else: self.control_bus_names[port].extend([sen, wen, pen]) self.vert_control_bus_positions = self.create_vertical_bus(layer="metal2", @@ -354,7 +354,7 @@ class sram_base(design, verilog, lef): temp.append("bank_sel{0}[{1}]".format(port,bank_num)) for port in self.read_ports: temp.append("s_en{0}".format(port)) - for port in self.read_ports: + for port in self.all_ports: temp.append("p_en_bar{0}".format(port)) for port in self.write_ports: temp.append("w_en{0}".format(port)) @@ -513,8 +513,7 @@ class sram_base(design, verilog, lef): temp.append("s_en{}".format(port)) if port in self.write_ports: temp.append("w_en{}".format(port)) - if port in self.read_ports: - temp.append("p_en_bar{}".format(port)) + temp.append("p_en_bar{}".format(port)) temp.extend(["wl_en{}".format(port), "clk_buf{}".format(port), "vdd", "gnd"]) self.connect_inst(temp) From 8771ffbfed1eb2f0b4eafa27eae9e57305f7e4bd Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 1 Aug 2019 12:28:21 -0700 Subject: [PATCH 169/234] Fix bug to add all p_en_bar to banks --- compiler/modules/bank.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index f60b5f32..613a3381 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -100,7 +100,8 @@ class bank(design.design): self.add_pin("bank_sel{}".format(port),"INPUT") for port in self.read_ports: self.add_pin("s_en{0}".format(port), "INPUT") - self.add_pin("p_en_bar{0}".format(port), "INPUT") + for port in self.all_ports: + self.add_pin("p_en_bar{0}".format(port), "INPUT") for port in self.write_ports: self.add_pin("w_en{0}".format(port), "INPUT") for bit in range(self.num_wmasks): From 7ba97ee0ba6c422d7d70acd2e97ec3035cd2be1d Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 1 Aug 2019 12:42:51 -0700 Subject: [PATCH 170/234] Fix missing port in control logic --- compiler/modules/control_logic.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 2fbaf31c..8ae62401 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -345,11 +345,12 @@ class control_logic(design.design): # Outputs to the bank if self.port_type == "rw": - self.output_list = ["rbl_wl", "s_en", "w_en", "p_en_bar"] + self.output_list = ["rbl_wl", "s_en", "w_en"] elif self.port_type == "r": - self.output_list = ["rbl_wl", "s_en", "p_en_bar"] + self.output_list = ["rbl_wl", "s_en"] else: self.output_list = ["w_en"] + self.output_list.append("p_en_bar") self.output_list.append("wl_en") self.output_list.append("clk_buf") From e4532083da84227fcf6b12ca4f85f8fe7df6cd14 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 5 Aug 2019 13:52:32 -0700 Subject: [PATCH 171/234] Increase stages and FO of fixed delay line. --- compiler/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/options.py b/compiler/options.py index 8cb99ad3..ce974d63 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -51,8 +51,8 @@ class options(optparse.Values): # Allow manual adjustment of the delay chain over automatic use_tech_delay_chain_size = False - delay_chain_stages = 5 - delay_chain_fanout_per_stage = 3 + delay_chain_stages = 9 + delay_chain_fanout_per_stage = 4 From 4d11de64ac9c137e8320419203278cdb439c942d Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 5 Aug 2019 13:53:14 -0700 Subject: [PATCH 172/234] Additional debug. Smaller psram func tests. --- compiler/characterizer/simulation.py | 27 +++++++++---------- compiler/modules/control_logic.py | 1 + compiler/sram/sram_config.py | 7 ++++- .../tests/22_psram_1bank_2mux_func_test.py | 4 +-- .../tests/22_psram_1bank_4mux_func_test.py | 2 +- .../tests/22_psram_1bank_nomux_func_test.py | 2 +- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index aea8f1cd..657c3609 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -25,9 +25,6 @@ class simulation(): self.word_size = self.sram.word_size self.addr_size = self.sram.addr_size self.write_size = self.sram.write_size - self.num_cols = self.sram.num_cols - self.num_rows = self.sram.num_rows - self.num_banks = self.sram.num_banks self.sp_file = spfile self.all_ports = self.sram.all_ports @@ -262,19 +259,21 @@ class simulation(): t_current+self.period) elif op == "partial_write": comment = "\tWriting (partial) {0} to address {1} with mask bit {2} (from port {3}) during cycle {4} ({5}ns - {6}ns)".format(word, - addr, - wmask, - port, - int(t_current / self.period), - t_current, - t_current + self.period) + addr, + wmask, + port, + int(t_current / self.period), + t_current, + t_current + self.period) else: comment = "\tReading {0} from address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, - addr, - port, - int(t_current/self.period), - t_current, - t_current+self.period) + addr, + port, + int(t_current/self.period), + t_current, + t_current+self.period) + + return comment def gen_pin_names(self, port_signal_names, port_info, abits, dbits): diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 8ae62401..1d2226b1 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -184,6 +184,7 @@ class control_logic(design.design): # self.sen_delay_rise,self.sen_delay_fall = self.get_delays_to_sen() #get the new timing # self.delay_chain_resized = True + debug.check(OPTS.delay_chain_stages%2, "Must use odd number of delay chain stages for inverting delay chain.") self.delay_chain=factory.create(module_type="delay_chain", fanout_list = OPTS.delay_chain_stages*[OPTS.delay_chain_fanout_per_stage]) self.add_mod(self.delay_chain) diff --git a/compiler/sram/sram_config.py b/compiler/sram/sram_config.py index df9ae677..376bf42b 100644 --- a/compiler/sram/sram_config.py +++ b/compiler/sram/sram_config.py @@ -61,7 +61,6 @@ class sram_config: self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size) self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row) - debug.info(1,"Words per row: {}".format(self.words_per_row)) self.recompute_sizes() def recompute_sizes(self): @@ -71,6 +70,8 @@ class sram_config: SRAM for testing. """ + debug.info(1,"Recomputing with words per row: {}".format(self.words_per_row)) + # If the banks changed self.num_words_per_bank = self.num_words/self.num_banks self.num_bits_per_bank = self.word_size*self.num_words_per_bank @@ -78,12 +79,16 @@ class sram_config: # Fix the number of columns and rows self.num_cols = int(self.words_per_row*self.word_size) self.num_rows = int(self.num_words_per_bank/self.words_per_row) + debug.info(1,"Rows: {} Cols: {}".format(self.num_rows,self.num_cols)) # Compute the address and bank sizes self.row_addr_size = int(log(self.num_rows, 2)) self.col_addr_size = int(log(self.words_per_row, 2)) self.bank_addr_size = self.col_addr_size + self.row_addr_size self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2)) + debug.info(1,"Row addr size: {}".format(self.row_addr_size) + + " Col addr size: {}".format(self.col_addr_size) + + " Bank addr size: {}".format(self.bank_addr_size)) def estimate_words_per_row(self,tentative_num_cols, word_size): diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index 446352e8..f986c3e7 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -37,8 +37,8 @@ class psram_1bank_2mux_func_test(openram_test): reload(characterizer) from characterizer import functional, delay from sram_config import sram_config - c = sram_config(word_size=4, - num_words=64, + c = sram_config(word_size=2, + num_words=32, num_banks=1) c.words_per_row=2 c.recompute_sizes() diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index 04ce7118..c5fd8945 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -38,7 +38,7 @@ class psram_1bank_4mux_func_test(openram_test): reload(characterizer) from characterizer import functional, delay from sram_config import sram_config - c = sram_config(word_size=4, + c = sram_config(word_size=2, num_words=256, num_banks=1) c.words_per_row=4 diff --git a/compiler/tests/22_psram_1bank_nomux_func_test.py b/compiler/tests/22_psram_1bank_nomux_func_test.py index 78da5a11..a2a2b41c 100755 --- a/compiler/tests/22_psram_1bank_nomux_func_test.py +++ b/compiler/tests/22_psram_1bank_nomux_func_test.py @@ -38,7 +38,7 @@ class psram_1bank_nomux_func_test(openram_test): reload(characterizer) from characterizer import functional, delay from sram_config import sram_config - c = sram_config(word_size=4, + c = sram_config(word_size=2, num_words=32, num_banks=1) c.words_per_row=1 From aae8566ff244cd7fbeab1be8a3766dc5c60b667c Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 5 Aug 2019 15:45:59 -0700 Subject: [PATCH 173/234] Update golden delays. Fix uninitialized boolean. --- compiler/characterizer/delay.py | 4 +-- compiler/tests/21_hspice_delay_test.py | 40 ++++++++++++------------- compiler/tests/21_ngspice_delay_test.py | 40 ++++++++++++------------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 37c38353..bb48564e 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -835,6 +835,7 @@ class delay(simulation): Checks the measurements which represent the internal storage voltages at the end of the read cycle. """ + success = False for polarity, meas_list in self.bit_meas.items(): for meas in meas_list: val = meas.retrieve_measure() @@ -855,12 +856,11 @@ class delay(simulation): elif (meas_cycle == sram_op.WRITE_ONE and polarity == bit_polarity.INVERTING) or\ (meas_cycle == sram_op.WRITE_ZERO and polarity == bit_polarity.NONINVERTING): success = val < self.vdd_voltage/2 - else: - success = False if not success: debug.info(1,("Wrong value detected on probe bit during read/write cycle. " "Check writes and control logic for bugs.\n measure={}, op={}, " "bit_storage={}, V(bit)={}").format(meas.name, meas_cycle.name, polarity.name,val)) + return success def check_bitline_meas(self, v_discharged_bl, v_charged_bl): diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index d63d6c30..f4827db2 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -61,27 +61,27 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_hl': [0.2179763], - 'delay_lh': [0.2179763], - 'leakage_power': 0.0025727, - 'min_period': 0.527, - 'read0_power': [0.4479132], - 'read1_power': [0.422467], - 'slew_hl': [0.0988916], - 'slew_lh': [0.0988916], - 'write0_power': [0.4976688], - 'write1_power': [0.4605285]} + golden_data = {'delay_hl': [0.2181231], + 'delay_lh': [0.2181231], + 'leakage_power': 0.0025453999999999997, + 'min_period': 0.781, + 'read0_power': [0.34664159999999994], + 'read1_power': [0.32656349999999995], + 'slew_hl': [0.21136519999999998], + 'slew_lh': [0.21136519999999998], + 'write0_power': [0.37980179999999997], + 'write1_power': [0.3532026]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.4119000000000002], - 'delay_lh': [1.4119000000000002], - 'leakage_power': 0.027366399999999996, - 'min_period': 3.125, - 'read0_power': [14.7569], - 'read1_power': [14.008800000000003], - 'slew_hl': [0.7314153], - 'slew_lh': [0.7314153], - 'write0_power': [16.700500000000005], - 'write1_power': [15.214100000000002]} + golden_data = {'delay_hl': [1.4082], + 'delay_lh': [1.4082], + 'leakage_power': 0.0267388, + 'min_period': 4.688, + 'read0_power': [11.5255], + 'read1_power': [10.9406], + 'slew_hl': [1.2979], + 'slew_lh': [1.2979], + 'write0_power': [12.9458], + 'write1_power': [11.7444]} else: self.assertTrue(False) # other techs fail # Check if no too many or too few results diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 1373f1f3..2aad39ca 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -54,27 +54,27 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_hl': [0.2265453], - 'delay_lh': [0.2265453], - 'leakage_power': 0.003688569, - 'min_period': 0.547, - 'read0_power': [0.4418831], - 'read1_power': [0.41914969999999996], - 'slew_hl': [0.103665], - 'slew_lh': [0.103665], - 'write0_power': [0.48889660000000007], - 'write1_power': [0.4419755]} + golden_data = {'delay_hl': [0.2179763], + 'delay_lh': [0.2179763], + 'leakage_power': 0.0025727, + 'min_period': 0.527, + 'read0_power': [0.4479132], + 'read1_power': [0.422467], + 'slew_hl': [0.0988916], + 'slew_lh': [0.0988916], + 'write0_power': [0.4976688], + 'write1_power': [0.4605285]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.710243], - 'delay_lh': [1.710243], - 'leakage_power': 0.06079017, - 'min_period': 3.75, - 'read0_power': [14.046140000000001], - 'read1_power': [13.52625], - 'slew_hl': [0.7730236], - 'slew_lh': [0.7730236], - 'write0_power': [15.86152], - 'write1_power': [14.612160000000001]} + golden_data = {'delay_hl': [1.708615], + 'delay_lh': [1.708615], + 'leakage_power': 0.06831667, + 'min_period': 5.312, + 'read0_power': [11.68257], + 'read1_power': [11.20223], + 'slew_hl': [1.391469], + 'slew_lh': [1.391469], + 'write0_power': [13.101120000000002], + 'write1_power': [11.99391]} else: self.assertTrue(False) # other techs fail From c3f38a5cac387ea2767c6840d78f519cf371af83 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 5 Aug 2019 16:09:27 -0700 Subject: [PATCH 174/234] ngspice delays updated (again) --- compiler/tests/21_ngspice_delay_test.py | 40 ++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 2aad39ca..06a61d55 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -54,27 +54,27 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_hl': [0.2179763], - 'delay_lh': [0.2179763], - 'leakage_power': 0.0025727, - 'min_period': 0.527, - 'read0_power': [0.4479132], - 'read1_power': [0.422467], - 'slew_hl': [0.0988916], - 'slew_lh': [0.0988916], - 'write0_power': [0.4976688], - 'write1_power': [0.4605285]} + golden_data = {'delay_hl': [0.22609590000000002], + 'delay_lh': [0.22609590000000002], + 'leakage_power': 0.003317743, + 'min_period': 0.859, + 'read0_power': [0.3271056], + 'read1_power': [0.3064244], + 'slew_hl': [0.2153979], + 'slew_lh': [0.2153979], + 'write0_power': [0.3532067], + 'write1_power': [0.3381259]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.708615], - 'delay_lh': [1.708615], - 'leakage_power': 0.06831667, - 'min_period': 5.312, - 'read0_power': [11.68257], - 'read1_power': [11.20223], - 'slew_hl': [1.391469], - 'slew_lh': [1.391469], - 'write0_power': [13.101120000000002], - 'write1_power': [11.99391]} + golden_data = {'delay_hl': [1.709791], + 'delay_lh': [1.709791], + 'leakage_power': 0.06803324999999999, + 'min_period': 7.812, + 'read0_power': [7.9499070000000005], + 'read1_power': [7.619662999999999], + 'slew_hl': [1.390261], + 'slew_lh': [1.390261], + 'write0_power': [8.913003], + 'write1_power': [8.166687000000001]} else: self.assertTrue(False) # other techs fail From ad35f8745ee88499d9af51e9ce444f7622b4ee85 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 6 Aug 2019 14:14:09 -0700 Subject: [PATCH 175/234] Add direction to pins of all modules --- compiler/modules/bitcell_array.py | 8 ++--- compiler/modules/delay_chain.py | 8 ++--- compiler/modules/dff_array.py | 10 +++---- compiler/modules/dff_buf.py | 12 ++++---- compiler/modules/dff_buf_array.py | 12 ++++---- compiler/modules/dff_inv_array.py | 12 ++++---- compiler/modules/dummy_array.py | 8 ++--- compiler/modules/hierarchical_decoder.py | 8 ++--- compiler/modules/hierarchical_predecode.py | 8 ++--- compiler/modules/precharge_array.py | 11 +++---- compiler/modules/replica_column.py | 9 +++--- compiler/modules/sense_amp_array.py | 12 ++++---- compiler/modules/wordline_driver.py | 10 +++---- compiler/modules/write_driver_array.py | 14 ++++----- compiler/pgates/pand2.py | 10 +++---- compiler/pgates/pbuf.py | 8 ++--- compiler/pgates/pdriver.py | 35 ++++++++++++---------- compiler/pgates/pinv.py | 4 +-- compiler/pgates/pnand2.py | 4 +-- compiler/pgates/pnand3.py | 4 +-- compiler/pgates/pnor2.py | 4 +-- compiler/pgates/precharge.py | 2 +- 22 files changed, 109 insertions(+), 104 deletions(-) diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 4b8ac212..999382ec 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -77,12 +77,12 @@ class bitcell_array(design.design): 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)) + 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)) - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin(cell_row+"_{0}".format(row), "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def add_modules(self): """ Add the modules used in this design """ diff --git a/compiler/modules/delay_chain.py b/compiler/modules/delay_chain.py index 6a54c1a3..bc932a26 100644 --- a/compiler/modules/delay_chain.py +++ b/compiler/modules/delay_chain.py @@ -57,10 +57,10 @@ class delay_chain(design.design): def add_pins(self): """ Add the pins of the delay chain""" - self.add_pin("in") - self.add_pin("out") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("in", "INPUT") + self.add_pin("out", "OUTPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def add_modules(self): self.inv = factory.create(module_type="pinv", route_output=False) diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 3ea3fc7f..32b36765 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -54,13 +54,13 @@ class dff_array(design.design): def add_pins(self): for row in range(self.rows): for col in range(self.columns): - self.add_pin(self.get_din_name(row,col)) + self.add_pin(self.get_din_name(row,col), "INPUT") for row in range(self.rows): for col in range(self.columns): - self.add_pin(self.get_dout_name(row,col)) - self.add_pin("clk") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin(self.get_dout_name(row,col), "OUTPUT") + self.add_pin("clk", "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def create_dff_array(self): self.dff_insts={} diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 9533d647..9359329a 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -75,12 +75,12 @@ class dff_buf(design.design): def add_pins(self): - self.add_pin("D") - self.add_pin("Q") - self.add_pin("Qb") - self.add_pin("clk") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("D", "INPUT") + self.add_pin("Q", "OUTPUT") + self.add_pin("Qb", "OUTPUT") + self.add_pin("clk", "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def create_instances(self): self.dff_inst=self.add_inst(name="dff_buf_dff", diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index 60bdae02..df36b2aa 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -55,14 +55,14 @@ class dff_buf_array(design.design): def add_pins(self): for row in range(self.rows): for col in range(self.columns): - self.add_pin(self.get_din_name(row,col)) + self.add_pin(self.get_din_name(row,col), "INPUT") for row in range(self.rows): for col in range(self.columns): - self.add_pin(self.get_dout_name(row,col)) - self.add_pin(self.get_dout_bar_name(row,col)) - self.add_pin("clk") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin(self.get_dout_name(row,col), "OUTPUT") + self.add_pin(self.get_dout_bar_name(row,col), "OUTPUT") + self.add_pin("clk", "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def add_modules(self): self.dff = factory.create(module_type="dff_buf", diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py index 1e6754b9..051dd237 100644 --- a/compiler/modules/dff_inv_array.py +++ b/compiler/modules/dff_inv_array.py @@ -59,14 +59,14 @@ class dff_inv_array(design.design): def add_pins(self): for row in range(self.rows): for col in range(self.columns): - self.add_pin(self.get_din_name(row,col)) + self.add_pin(self.get_din_name(row,col), "INPUT") for row in range(self.rows): for col in range(self.columns): - self.add_pin(self.get_dout_name(row,col)) - self.add_pin(self.get_dout_bar_name(row,col)) - self.add_pin("clk") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin(self.get_dout_name(row,col), "OUTPUT") + self.add_pin(self.get_dout_bar_name(row,col), "OUTPUT") + self.add_pin("clk", "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def create_dff_array(self): self.dff_insts={} diff --git a/compiler/modules/dummy_array.py b/compiler/modules/dummy_array.py index 10007106..f1f433ce 100644 --- a/compiler/modules/dummy_array.py +++ b/compiler/modules/dummy_array.py @@ -70,12 +70,12 @@ class dummy_array(design.design): 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)) + 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)) - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin(cell_row+"_{0}".format(row), "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def add_modules(self): """ Add the modules used in this design """ diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 4f359c95..75eb3345 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -231,12 +231,12 @@ class hierarchical_decoder(design.design): """ Add the module pins """ for i in range(self.num_inputs): - self.add_pin("addr_{0}".format(i)) + self.add_pin("addr_{0}".format(i), "INPUT") for j in range(self.rows): - self.add_pin("decode_{0}".format(j)) - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("decode_{0}".format(j), "OUTPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def create_pre_decoder(self): diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index a8d4797f..bec0ce06 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -26,11 +26,11 @@ class hierarchical_predecode(design.design): def add_pins(self): for k in range(self.number_of_inputs): - self.add_pin("in_{0}".format(k)) + self.add_pin("in_{0}".format(k), "INPUT") for i in range(self.number_of_outputs): - self.add_pin("out_{0}".format(i)) - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("out_{0}".format(i), "OUTPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def add_modules(self): """ Add the INV and NAND gate modules """ diff --git a/compiler/modules/precharge_array.py b/compiler/modules/precharge_array.py index bf45afd5..2d98ba14 100644 --- a/compiler/modules/precharge_array.py +++ b/compiler/modules/precharge_array.py @@ -35,10 +35,11 @@ class precharge_array(design.design): def add_pins(self): """Adds pins for spice file""" for i in range(self.columns): - self.add_pin("bl_{0}".format(i)) - self.add_pin("br_{0}".format(i)) - self.add_pin("en_bar") - self.add_pin("vdd") + # These are outputs from the precharge only + self.add_pin("bl_{0}".format(i), "OUTPUT") + self.add_pin("br_{0}".format(i), "OUTPUT") + self.add_pin("en_bar", "INPUT") + self.add_pin("vdd", "POWER") def create_netlist(self): self.add_modules() @@ -115,4 +116,4 @@ class precharge_array(design.design): #Assume single port precharge_en_cin = self.pc_cell.get_en_cin() return precharge_en_cin*self.columns - \ No newline at end of file + diff --git a/compiler/modules/replica_column.py b/compiler/modules/replica_column.py index fb11a8f5..c3f63b19 100644 --- a/compiler/modules/replica_column.py +++ b/compiler/modules/replica_column.py @@ -55,14 +55,15 @@ class replica_column(design.design): def add_pins(self): for bl_name in self.cell.get_all_bitline_names(): - self.add_pin("{0}_{1}".format(bl_name,0)) + # In the replica column, these are only outputs! + self.add_pin("{0}_{1}".format(bl_name,0), "OUTPUT") for row in range(self.total_size): for wl_name in self.cell.get_all_wl_names(): - self.add_pin("{0}_{1}".format(wl_name,row)) + self.add_pin("{0}_{1}".format(wl_name,row), "INPUT") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def add_modules(self): self.replica_cell = factory.create(module_type="replica_bitcell") diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index ab67e981..40c3adeb 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -55,12 +55,12 @@ class sense_amp_array(design.design): def add_pins(self): for i in range(0,self.word_size): - self.add_pin("data_{0}".format(i)) - self.add_pin("bl_{0}".format(i)) - self.add_pin("br_{0}".format(i)) - self.add_pin("en") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("data_{0}".format(i), "OUTPUT") + self.add_pin("bl_{0}".format(i), "INPUT") + self.add_pin("br_{0}".format(i), "INPUT") + self.add_pin("en", "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def add_modules(self): self.amp = factory.create(module_type="sense_amp") diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index b29901c5..39700799 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -50,13 +50,13 @@ class wordline_driver(design.design): def add_pins(self): # inputs to wordline_driver. for i in range(self.rows): - self.add_pin("in_{0}".format(i)) + 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)) - self.add_pin("en") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("wl_{0}".format(i), "OUTPUT") + self.add_pin("en", "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def add_modules(self): diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 5f71b038..1b152e89 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -59,17 +59,17 @@ class write_driver_array(design.design): def add_pins(self): for i in range(self.word_size): - self.add_pin("data_{0}".format(i)) + self.add_pin("data_{0}".format(i), "INPUT") for i in range(self.word_size): - self.add_pin("bl_{0}".format(i)) - self.add_pin("br_{0}".format(i)) + self.add_pin("bl_{0}".format(i), "OUTPUT") + self.add_pin("br_{0}".format(i), "OUTPUT") if self.write_size != None: for i in range(self.num_wmasks): - self.add_pin("en_{}".format(i)) + self.add_pin("en_{}".format(i), "INPUT") else: - self.add_pin("en") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("en", "INPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def add_modules(self): self.driver = factory.create(module_type="write_driver") diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index 546eb830..d299cc56 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -47,11 +47,11 @@ class pand2(pgate.pgate): self.DRC_LVS() def add_pins(self): - self.add_pin("A") - self.add_pin("B") - self.add_pin("Z") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("A", "INPUT") + self.add_pin("B", "INPUT") + self.add_pin("Z", "OUTPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def create_insts(self): self.nand_inst=self.add_inst(name="pand2_nand", diff --git a/compiler/pgates/pbuf.py b/compiler/pgates/pbuf.py index 6ccc8c16..125a1190 100644 --- a/compiler/pgates/pbuf.py +++ b/compiler/pgates/pbuf.py @@ -42,10 +42,10 @@ class pbuf(pgate.pgate): self.add_layout_pins() def add_pins(self): - self.add_pin("A") - self.add_pin("Z") - self.add_pin("vdd") - self.add_pin("gnd") + 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 diff --git a/compiler/pgates/pdriver.py b/compiler/pgates/pdriver.py index 8ea68e6e..a3180006 100644 --- a/compiler/pgates/pdriver.py +++ b/compiler/pgates/pdriver.py @@ -53,15 +53,15 @@ class pdriver(pgate.pgate): elif not self.neg_polarity and (self.num_stages%2): self.num_stages += 1 - self.size_list = [] - # compute sizes backwards from the fanout - fanout_prev = self.fanout - for x in range(self.num_stages): - fanout_prev = max(round(fanout_prev/self.stage_effort),1) - self.size_list.append(fanout_prev) + self.size_list = [] + # compute sizes backwards from the fanout + fanout_prev = self.fanout + for x in range(self.num_stages): + fanout_prev = max(round(fanout_prev/self.stage_effort),1) + self.size_list.append(fanout_prev) - # reverse the sizes to be from input to output - self.size_list.reverse() + # reverse the sizes to be from input to output + self.size_list.reverse() def create_netlist(self): @@ -81,10 +81,10 @@ class pdriver(pgate.pgate): def add_pins(self): - self.add_pin("A") - self.add_pin("Z") - self.add_pin("vdd") - self.add_pin("gnd") + self.add_pin("A", "INPUT") + self.add_pin("Z", "OUTPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") def add_modules(self): self.inv_list = [] @@ -178,7 +178,7 @@ class pdriver(pgate.pgate): return self.inv_list[0].input_load() def analytical_delay(self, corner, slew, load=0.0): - """Calculate the analytical delay of INV1 -> ... -> INVn""" + """ Calculate the analytical delay of INV1 -> ... -> INVn """ cout_list = [] for prev_inv,inv in zip(self.inv_list, self.inv_list[1:]): @@ -198,9 +198,12 @@ class pdriver(pgate.pgate): return delay - + def get_sizes(self): + """ Return the relative sizes of the buffers """ + return self.size_list + def get_stage_efforts(self, external_cout, inp_is_rise=False): - """Get the stage efforts of the A -> Z path""" + """ Get the stage efforts of the A -> Z path """ cout_list = [] for prev_inv,inv in zip(self.inv_list, self.inv_list[1:]): cout_list.append(inv.get_cin()) @@ -217,5 +220,5 @@ class pdriver(pgate.pgate): return stage_effort_list def get_cin(self): - """Returns the relative capacitance of the input""" + """ Returns the relative capacitance of the input """ return self.inv_list[0].get_cin() diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 906a009d..773a0452 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -60,7 +60,7 @@ class pinv(pgate.pgate): def add_pins(self): """ Adds pins for spice netlist """ pin_list = ["A", "Z", "vdd", "gnd"] - dir_list = ['INPUT', 'OUTPUT', 'POWER', 'GROUND'] + dir_list = ["INPUT", "OUTPUT", "POWER", "GROUND"] self.add_pin_list(pin_list, dir_list) @@ -300,4 +300,4 @@ class pinv(pgate.pgate): def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" - self.add_graph_edges(graph, port_nets) \ No newline at end of file + self.add_graph_edges(graph, port_nets) diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 6e3fb7ae..956f0a30 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -61,7 +61,7 @@ class pnand2(pgate.pgate): def add_pins(self): """ Adds pins for spice netlist """ pin_list = ["A", "B", "Z", "vdd", "gnd"] - dir_list = ['INPUT', 'INPUT', 'OUTPUT', 'POWER', 'GROUND'] + dir_list = ["INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"] self.add_pin_list(pin_list, dir_list) @@ -281,4 +281,4 @@ class pnand2(pgate.pgate): def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" - self.add_graph_edges(graph, port_nets) \ No newline at end of file + self.add_graph_edges(graph, port_nets) diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index a8cce176..30da9165 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -44,7 +44,7 @@ class pnand3(pgate.pgate): def add_pins(self): """ Adds pins for spice netlist """ pin_list = ["A", "B", "C", "Z", "vdd", "gnd"] - dir_list = ['INPUT', 'INPUT', 'INPUT', 'OUTPUT', 'POWER', 'GROUND'] + dir_list = ["INPUT", "INPUT", "INPUT", "OUTPUT", "POWER", "GROUND"] self.add_pin_list(pin_list, dir_list) def create_netlist(self): @@ -283,4 +283,4 @@ class pnand3(pgate.pgate): def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" - self.add_graph_edges(graph, port_nets) \ No newline at end of file + self.add_graph_edges(graph, port_nets) diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index 7f026da3..fa52c528 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -41,7 +41,7 @@ class pnor2(pgate.pgate): def add_pins(self): """ Adds pins for spice netlist """ pin_list = ["A", "B", "Z", "vdd", "gnd"] - dir_list = ['INPUT', 'INPUT', 'OUTPUT', 'INOUT', 'INOUT'] + dir_list = ["INPUT", "INPUT", "OUTPUT", "INOUT", "INOUT"] self.add_pin_list(pin_list, dir_list) def create_netlist(self): @@ -242,4 +242,4 @@ class pnor2(pgate.pgate): def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" - self.add_graph_edges(graph, port_nets) \ No newline at end of file + self.add_graph_edges(graph, port_nets) diff --git a/compiler/pgates/precharge.py b/compiler/pgates/precharge.py index 4e37aeea..b4423bed 100644 --- a/compiler/pgates/precharge.py +++ b/compiler/pgates/precharge.py @@ -53,7 +53,7 @@ class precharge(design.design): self.connect_to_bitlines() def add_pins(self): - self.add_pin_list(["bl", "br", "en_bar", "vdd"]) + self.add_pin_list(["bl", "br", "en_bar", "vdd"], ["OUTPUT", "OUTPUT", "INPUT", "POWER"]) def add_ptx(self): """ From a2f81aeae486c0af1a0e6e67b12790d25e287eef Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 6 Aug 2019 16:29:07 -0700 Subject: [PATCH 176/234] Combine rbl_wl and wl_en. Size p_en_bar slower than wl_en. --- compiler/modules/bank.py | 18 ++++---- compiler/modules/control_logic.py | 74 +++++++++++-------------------- compiler/sram/sram_base.py | 10 ++--- 3 files changed, 39 insertions(+), 63 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 613a3381..f3491b79 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -84,8 +84,6 @@ class bank(design.design): self.add_pin("dout{0}_{1}".format(port,bit),"OUTPUT") for port in self.read_ports: self.add_pin(self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]),"OUTPUT") - for port in self.read_ports: - self.add_pin(self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]),"INPUT") for port in self.write_ports: for bit in range(self.word_size): self.add_pin("din{0}_{1}".format(port,bit),"INPUT") @@ -306,13 +304,13 @@ class bank(design.design): self.input_control_signals = [] port_num = 0 for port in range(OPTS.num_rw_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "rbl_wl{}".format(port_num)]) + self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_w_ports): self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "p_en_bar{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_r_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "rbl_wl{}".format(port_num)]) + self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)]) port_num += 1 # Number of control lines in the bus for each port @@ -422,9 +420,9 @@ class bank(design.design): for row in range(self.num_rows): for wordline in self.wl_names: temp.append("{0}_{1}".format(wordline,row)) - for rbl in range(self.num_rbl): - rbl_wl_name=self.bitcell_array.get_rbl_wl_name(rbl) - temp.append(rbl_wl_name) + for port in self.all_ports: + if self.port_data[port].has_rbl(): + temp.append("wl_en{0}".format(port)) temp.append("vdd") temp.append("gnd") self.connect_inst(temp) @@ -947,7 +945,7 @@ class bank(design.design): if port in self.read_ports: rbl_wl_name = self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]) - connection.append((self.prefix+"rbl_wl{}".format(port), self.bitcell_array_inst.get_pin(rbl_wl_name).lc())) + connection.append((self.prefix+"wl_en{}".format(port), self.bitcell_array_inst.get_pin(rbl_wl_name).lc())) if port in self.write_ports: connection.append((self.prefix+"w_en{}".format(port), self.port_data_inst[port].get_pin("w_en").lc())) @@ -967,10 +965,10 @@ class bank(design.design): control_signal = self.prefix+"wl_en{}".format(port) if port%2: pin_pos = self.port_address_inst[port].get_pin("wl_en").uc() - mid_pos = pin_pos + vector(0,self.m2_gap) # to route down to the top of the bus + mid_pos = pin_pos + vector(0,2*self.m2_gap) # to route down to the top of the bus else: pin_pos = self.port_address_inst[port].get_pin("wl_en").bc() - mid_pos = pin_pos - vector(0,self.m2_gap) # to route down to the top of the bus + mid_pos = pin_pos - vector(0,2*self.m2_gap) # to route down to the top of the bus control_x_offset = self.bus_xoffset[port][control_signal].x control_pos = vector(control_x_offset, mid_pos.y) self.add_wire(("metal1","via1","metal2"),[pin_pos, mid_pos, control_pos]) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 1d2226b1..f5531d6f 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -101,20 +101,26 @@ class control_logic(design.design): self.add_mod(self.rbl_driver) - # clk_buf drives a flop for every address and control bit + # clk_buf drives a flop for every address + addr_flops = math.log(self.num_words,2) + math.log(self.words_per_row,2) + # plus data flops and control flops + num_flops = addr_flops + self.word_size + self.num_control_signals + # each flop internally has a FO 5 approximately # plus about 5 fanouts for the control logic - # each flop internally has a FO 4 approximately - clock_fanout = 4*(math.log(self.num_words,2) + math.log(self.words_per_row,2) \ - + self.num_control_signals) + 5 + clock_fanout = 5*num_flops + 5 self.clk_buf_driver = factory.create(module_type="pdriver", fanout=clock_fanout, height=dff_height) self.add_mod(self.clk_buf_driver) + # We will use the maximum since this same value is used to size the wl_en + # and the p_en_bar drivers + max_fanout = max(self.num_rows,self.num_cols) + # wl_en drives every row in the bank self.wl_en_driver = factory.create(module_type="pdriver", - fanout=self.num_rows, + fanout=max_fanout, height=dff_height) self.add_mod(self.wl_en_driver) @@ -132,14 +138,16 @@ class control_logic(design.design): # used to generate inverted signals with low fanout self.inv = factory.create(module_type="pinv", - size=1, - height=dff_height) + size=1, + height=dff_height) self.add_mod(self.inv) # p_en_bar drives every column in the bitcell array + # but it is sized the same as the wl_en driver with + # prepended 3 inverter stages to guarantee it is slower and odd polarity + driver_size_list = [1,1,1,*self.wl_en_driver.get_sizes()] self.p_en_bar_driver = factory.create(module_type="pdriver", - neg_polarity=True, - fanout=self.num_cols, + size_list=driver_size_list, height=dff_height) self.add_mod(self.p_en_bar_driver) @@ -346,9 +354,9 @@ class control_logic(design.design): # Outputs to the bank if self.port_type == "rw": - self.output_list = ["rbl_wl", "s_en", "w_en"] + self.output_list = ["s_en", "w_en"] elif self.port_type == "r": - self.output_list = ["rbl_wl", "s_en"] + self.output_list = ["s_en"] else: self.output_list = ["w_en"] self.output_list.append("p_en_bar") @@ -376,7 +384,6 @@ class control_logic(design.design): if (self.port_type == "rw") or (self.port_type == "w"): self.create_wen_row() if (self.port_type == "rw") or (self.port_type == "r"): - self.create_rbl_row() self.create_sen_row() self.create_delay() self.create_pen_row() @@ -410,9 +417,6 @@ class control_logic(design.design): height = self.w_en_gate_inst.uy() control_center_y = self.w_en_gate_inst.uy() row += 1 - if (self.port_type == "rw") or (self.port_type == "r"): - self.place_rbl_row(row) - row += 1 self.place_pen_row(row) row += 1 if (self.port_type == "rw") or (self.port_type == "r"): @@ -441,7 +445,6 @@ class control_logic(design.design): if (self.port_type == "rw") or (self.port_type == "w"): self.route_wen() if (self.port_type == "rw") or (self.port_type == "r"): - self.route_rbl() self.route_sen() self.route_pen() self.route_clk_buf() @@ -596,42 +599,15 @@ class control_logic(design.design): def route_wlen(self): wlen_map = zip(["A"], ["gated_clk_bar"]) - self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.rail_offsets) + self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.rail_offsets) + self.connect_output(self.wl_en_inst, "Z", "wl_en") - def create_rbl_row(self): - - self.rbl_inst=self.add_inst(name="rbl_driver", - mod=self.rbl_driver) - # input: gated_clk_bar, output: rbl_wl - self.connect_inst(["gated_clk_bar", "rbl_wl", "vdd", "gnd"]) - - def place_rbl_row(self,row): - x_off = self.control_x_offset - (y_off,mirror)=self.get_offset(row) - - offset = vector(x_off, y_off) - self.rbl_inst.place(offset, mirror) - - self.row_end_inst.append(self.rbl_inst) - - def route_rbl(self): - """ Connect the logic for the rbl_in generation """ - - rbl_in_map = zip(["A"], ["gated_clk_bar"]) - self.connect_vertical_bus(rbl_in_map, self.rbl_inst, self.rail_offsets) - self.connect_output(self.rbl_inst, "Z", "rbl_wl") - - # Input from RBL goes to the delay line for futher delay - self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") - def create_pen_row(self): - input_name = "gated_clk_buf" - - # input: pre_p_en, output: p_en_bar + # input: gated_clk_bar, output: p_en_bar self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar", mod=self.p_en_bar_driver) - self.connect_inst([input_name, "p_en_bar", "vdd", "gnd"]) + self.connect_inst(["gated_clk_buf", "p_en_bar", "vdd", "gnd"]) def place_pen_row(self,row): @@ -690,6 +666,10 @@ class control_logic(design.design): self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) self.connect_output(self.s_en_gate_inst, "Z", "s_en") + + # Input from RBL goes to the delay line for futher delay + self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") + def create_wen_row(self): diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 45befe16..f34d058e 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -341,8 +341,6 @@ class sram_base(design, verilog, lef): temp.append("DOUT{0}[{1}]".format(port,bit)) for port in self.read_ports: temp.append("rbl_bl{0}".format(port)) - for port in self.read_ports: - temp.append("rbl_wl{0}".format(port)) for port in self.write_ports: for bit in range(self.word_size): temp.append("BANK_DIN{0}[{1}]".format(port,bit)) @@ -506,9 +504,6 @@ class sram_base(design, verilog, lef): temp.append("rbl_bl{}".format(port)) # Ouputs - if port in self.read_ports: - temp.append("rbl_wl{}".format(port)) - if port in self.read_ports: temp.append("s_en{}".format(port)) if port in self.write_ports: @@ -530,7 +525,10 @@ class sram_base(design, verilog, lef): in_pos = src_pin.rc() else: in_pos = src_pin.lc() - out_pos = dest_pin.center() + if src_pin.cy() < dest_pin.cy(): + out_pos = dest_pin.bc() + else: + out_pos = dest_pin.uc() # move horizontal first self.add_wire(("metal3","via2","metal2"),[in_pos, vector(out_pos.x,in_pos.y),out_pos]) From 2ce7323838df9f9b0f8e8c414acf420a1746d49a Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 6 Aug 2019 17:09:25 -0700 Subject: [PATCH 177/234] Removed all unused analytical delay functions. --- compiler/modules/control_logic.py | 3 ++- compiler/modules/dff.py | 5 ---- compiler/modules/dff_array.py | 5 ---- compiler/modules/dff_buf.py | 11 +-------- compiler/modules/dff_buf_array.py | 5 ---- compiler/modules/dff_inv.py | 10 +------- compiler/modules/dff_inv_array.py | 6 ----- compiler/modules/hierarchical_decoder.py | 22 ----------------- compiler/modules/hierarchical_predecode2x4.py | 19 +-------------- compiler/modules/hierarchical_predecode3x8.py | 19 +-------------- compiler/modules/multibank.py | 20 +--------------- compiler/modules/tri_gate.py | 6 ----- compiler/modules/tri_gate_array.py | 8 +------ compiler/modules/wordline_driver.py | 15 ------------ compiler/pgates/pand2.py | 8 ------- compiler/pgates/pbuf.py | 8 ------- compiler/pgates/pdriver.py | 24 ------------------- compiler/pgates/pinv.py | 9 ------- compiler/pgates/pinvbuf.py | 10 +------- compiler/pgates/pnand2.py | 11 --------- compiler/pgates/pnand3.py | 10 -------- compiler/pgates/pnor2.py | 10 -------- compiler/pgates/ptristate_inv.py | 7 ------ 23 files changed, 9 insertions(+), 242 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 1d2226b1..372820d9 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -921,7 +921,8 @@ class control_logic(design.design): last_stage_rise = False #First stage(s), clk -(pdriver)-> clk_buf. - clk_buf_cout = self.replica_bitline.get_en_cin() + #clk_buf_cout = self.replica_bitline.get_en_cin() + clk_buf_cout = 0 stage_effort_list += self.clk_buf_driver.get_stage_efforts(clk_buf_cout, last_stage_rise) last_stage_rise = stage_effort_list[-1].is_rise diff --git a/compiler/modules/dff.py b/compiler/modules/dff.py index c8d7414a..083d92b7 100644 --- a/compiler/modules/dff.py +++ b/compiler/modules/dff.py @@ -48,11 +48,6 @@ class dff(design.design): transition_prob = spice["flop_transition_prob"] return transition_prob*(c_load + c_para) - def analytical_delay(self, corner, slew, load = 0.0): - # dont know how to calculate this now, use constant in tech file - result = self.return_delay(spice["dff_delay"], spice["dff_slew"]) - return result - def get_clk_cin(self): """Return the total capacitance (in relative units) that the clock is loaded by in the dff""" #This is a handmade cell so the value must be entered in the tech.py file or estimated. diff --git a/compiler/modules/dff_array.py b/compiler/modules/dff_array.py index 32b36765..89b29476 100644 --- a/compiler/modules/dff_array.py +++ b/compiler/modules/dff_array.py @@ -160,11 +160,6 @@ class dff_array(design.design): self.add_via_center(layers=("metal2","via2","metal3"), offset=vector(clk_pin.cx(),clk_ypos)) - - - def analytical_delay(self, corner, slew, load=0.0): - return self.dff.analytical_delay(corner, slew=slew, load=load) - def get_clk_cin(self): """Return the total capacitance (in relative units) that the clock is loaded by in the dff array""" dff_clk_cin = self.dff.get_clk_cin() diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 9359329a..f6fc1cf2 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -177,16 +177,7 @@ class dff_buf(design.design): self.add_path("metal1", [self.mid_qb_pos, qb_pos]) self.add_via_center(layers=("metal1","via1","metal2"), offset=qb_pos) - - - - def analytical_delay(self, corner, slew, load=0.0): - """ Calculate the analytical delay of DFF-> INV -> INV """ - dff_delay=self.dff.analytical_delay(corner, slew=slew, load=self.inv1.input_load()) - inv1_delay = self.inv1.analytical_delay(corner, slew=dff_delay.slew, load=self.inv2.input_load()) - inv2_delay = self.inv2.analytical_delay(corner, slew=inv1_delay.slew, load=load) - return dff_delay + inv1_delay + inv2_delay - + def get_clk_cin(self): """Return the total capacitance (in relative units) that the clock is loaded by in the dff""" #This is a handmade cell so the value must be entered in the tech.py file or estimated. diff --git a/compiler/modules/dff_buf_array.py b/compiler/modules/dff_buf_array.py index df36b2aa..2fafee76 100644 --- a/compiler/modules/dff_buf_array.py +++ b/compiler/modules/dff_buf_array.py @@ -193,11 +193,6 @@ class dff_buf_array(design.design): self.add_via_center(layers=("metal2","via2","metal3"), offset=vector(clk_pin.cx(),clk_ypos)) - - - def analytical_delay(self, corner, slew, load=0.0): - return self.dff.analytical_delay(slew=slew, load=load) - def get_clk_cin(self): """Return the total capacitance (in relative units) that the clock is loaded by in the dff array""" dff_clk_cin = self.dff.get_clk_cin() diff --git a/compiler/modules/dff_inv.py b/compiler/modules/dff_inv.py index 226db290..207a5ad0 100644 --- a/compiler/modules/dff_inv.py +++ b/compiler/modules/dff_inv.py @@ -150,15 +150,7 @@ class dff_inv(design.design): offset=dout_pin.center()) self.add_via_center(layers=("metal1","via1","metal2"), offset=dout_pin.center()) - - - - def analytical_delay(self, corner, slew, load=0.0): - """ Calculate the analytical delay of DFF-> INV -> INV """ - dff_delay=self.dff.analytical_delay(corner, slew=slew, load=self.inv1.input_load()) - inv1_delay = self.inv1.analytical_delay(corner, slew=dff_delay.slew, load=load) - return dff_delay + inv1_delay - + def get_clk_cin(self): """Return the total capacitance (in relative units) that the clock is loaded by in the dff""" return self.dff.get_clk_cin() diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py index 051dd237..760a2337 100644 --- a/compiler/modules/dff_inv_array.py +++ b/compiler/modules/dff_inv_array.py @@ -190,12 +190,6 @@ class dff_inv_array(design.design): self.add_via_center(layers=("metal2","via2","metal3"), offset=vector(clk_pin.cx(),clk_ypos)) - - - - def analytical_delay(self, corner, slew, load=0.0): - return self.dff.analytical_delay(corner, slew=slew, load=load) - def get_clk_cin(self): """Return the total capacitance (in relative units) that the clock is loaded by in the dff array""" dff_clk_cin = self.dff.get_clk_cin() diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 75eb3345..0e70db55 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -596,28 +596,6 @@ class hierarchical_decoder(design.design): self.add_via_center(layers=("metal2", "via2", "metal3"), offset=rail_pos) - - def analytical_delay(self, corner, slew, load = 0.0): - # A -> out - if self.determine_predecodes(self.num_inputs)[1]==0: - pre = self.pre2_4 - nand = self.nand2 - else: - pre = self.pre3_8 - nand = self.nand3 - a_t_out_delay = pre.analytical_delay(corner, slew=slew,load = nand.input_load()) - - # out -> z - out_t_z_delay = nand.analytical_delay(corner, slew= a_t_out_delay.slew, - load = self.inv.input_load()) - result = a_t_out_delay + out_t_z_delay - - # Z -> decode_out - z_t_decodeout_delay = self.inv.analytical_delay(corner, slew = out_t_z_delay.slew , load = load) - result = result + z_t_decodeout_delay - return result - - def input_load(self): if self.determine_predecodes(self.num_inputs)[1]==0: pre = self.pre2_4 diff --git a/compiler/modules/hierarchical_predecode2x4.py b/compiler/modules/hierarchical_predecode2x4.py index 56046c74..f05f54b0 100644 --- a/compiler/modules/hierarchical_predecode2x4.py +++ b/compiler/modules/hierarchical_predecode2x4.py @@ -56,21 +56,4 @@ class hierarchical_predecode2x4(hierarchical_predecode): ["A_0", "Abar_1"], ["Abar_0", "A_1"], ["A_0", "A_1"]] - return combination - - - def analytical_delay(self, corner, slew, load = 0.0 ): - # in -> inbar - a_t_b_delay = self.inv.analytical_delay(corner, slew=slew, load=self.nand.input_load()) - - # inbar -> z - b_t_z_delay = self.nand.analytical_delay(corner, slew=a_t_b_delay.slew, load=self.inv.input_load()) - - # Z -> out - a_t_out_delay = self.inv.analytical_delay(corner, slew=b_t_z_delay.slew, load=load) - - return a_t_b_delay + b_t_z_delay + a_t_out_delay - - - def input_load(self): - return self.nand.input_load() + return combination \ No newline at end of file diff --git a/compiler/modules/hierarchical_predecode3x8.py b/compiler/modules/hierarchical_predecode3x8.py index a7794395..20b629bb 100644 --- a/compiler/modules/hierarchical_predecode3x8.py +++ b/compiler/modules/hierarchical_predecode3x8.py @@ -65,21 +65,4 @@ class hierarchical_predecode3x8(hierarchical_predecode): ["A_0", "Abar_1", "A_2"], ["Abar_0", "A_1", "A_2"], ["A_0", "A_1", "A_2"]] - return combination - - - def analytical_delay(self, corner, slew, load = 0.0 ): - # A -> Abar - a_t_b_delay = self.inv.analytical_delay(corner, slew=slew, load=self.nand.input_load()) - - # Abar -> z - b_t_z_delay = self.nand.analytical_delay(corner, slew=a_t_b_delay.slew, load=self.inv.input_load()) - - # Z -> out - a_t_out_delay = self.inv.analytical_delay(corner, slew=b_t_z_delay.slew, load=load) - - return a_t_b_delay + b_t_z_delay + a_t_out_delay - - - def input_load(self): - return self.nand.input_load() + return combination \ No newline at end of file diff --git a/compiler/modules/multibank.py b/compiler/modules/multibank.py index fd061273..28f689f7 100644 --- a/compiler/modules/multibank.py +++ b/compiler/modules/multibank.py @@ -827,22 +827,4 @@ class multibank(design.design): rotate=90) self.add_via(layers=("metal2","via2","metal3"), offset=in_pin + self.m2m3_via_offset, - rotate=90) - - def analytical_delay(self, corner, slew, load): - """ return analytical delay of the bank""" - decoder_delay = self.row_decoder.analytical_delay(corner, slew, self.wordline_driver.input_load()) - - word_driver_delay = self.wordline_driver.analytical_delay(corner, decoder_delay.slew, self.bitcell_array.input_load()) - - bitcell_array_delay = self.bitcell_array.analytical_delay(corner, word_driver_delay.slew) - - bl_t_data_out_delay = self.sense_amp_array.analytical_delay(corner, bitcell_array_delay.slew, - self.bitcell_array.output_load()) - # output load of bitcell_array is set to be only small part of bl for sense amp. - - data_t_DATA_delay = self.tri_gate_array.analytical_delay(corner, bl_t_data_out_delay.slew, load) - - result = decoder_delay + word_driver_delay + bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay - return result - + rotate=90) \ No newline at end of file diff --git a/compiler/modules/tri_gate.py b/compiler/modules/tri_gate.py index 3907a03b..fe59e7b9 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -36,12 +36,6 @@ class tri_gate(design.design): self.pin_map = tri_gate.pin_map self.add_pin_types(self.type_list) - def analytical_delay(self, corner, slew, load=0.0): - from tech import spice - r = spice["min_tx_r"] - c_para = spice["min_tx_drain_c"] - return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" #Power in this module currently not defined. Returns 0 nW (leakage and dynamic). diff --git a/compiler/modules/tri_gate_array.py b/compiler/modules/tri_gate_array.py index df39ad96..7d1c21d0 100644 --- a/compiler/modules/tri_gate_array.py +++ b/compiler/modules/tri_gate_array.py @@ -120,10 +120,4 @@ class tri_gate_array(design.design): layer="metal1", offset=enbar_pin.ll().scale(0, 1), width=width, - height=drc("minwidth_metal1")) - - - - def analytical_delay(self, corner, slew, load=0.0): - return self.tri.analytical_delay(corner, slew = slew, load = load) - + height=drc("minwidth_metal1")) \ No newline at end of file diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index 39700799..b1292560 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -210,21 +210,6 @@ class wordline_driver(design.design): start=wl_offset, end=wl_offset-vector(self.m1_width,0)) - - def analytical_delay(self, corner, slew, load=0): - # decode -> net - decode_t_net = self.nand2.analytical_delay(corner, slew, self.inv.input_load()) - - # net -> wl - net_t_wl = self.inv.analytical_delay(corner, decode_t_net.slew, load) - - return decode_t_net + net_t_wl - - - def input_load(self): - """Gets the capacitance of the wordline driver in absolute units (fF)""" - return self.nand2.input_load() - def determine_wordline_stage_efforts(self, external_cout, inp_is_rise=True): """Follows the clk_buf to a wordline signal adding each stages stage effort to a list""" stage_effort_list = [] diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index d299cc56..48f111c7 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -110,14 +110,6 @@ class pand2(pgate.pgate): width=pin.width(), height=pin.height()) - - - def analytical_delay(self, corner, slew, load=0.0): - """ Calculate the analytical delay of DFF-> INV -> INV """ - nand_delay = self.nand.analytical_delay(corner, slew=slew, load=self.inv.input_load()) - inv_delay = self.inv.analytical_delay(corner, slew=nand_delay.slew, load=load) - return nand_delay + inv_delay - def get_stage_efforts(self, external_cout, inp_is_rise=False): """Get the stage efforts of the A or B -> Z path""" stage_effort_list = [] diff --git a/compiler/pgates/pbuf.py b/compiler/pgates/pbuf.py index 125a1190..fcfc6586 100644 --- a/compiler/pgates/pbuf.py +++ b/compiler/pgates/pbuf.py @@ -113,14 +113,6 @@ class pbuf(pgate.pgate): width=a_pin.width(), height=a_pin.height()) - - - def analytical_delay(self, corner, slew, load=0.0): - """ Calculate the analytical delay of DFF-> INV -> INV """ - inv1_delay = self.inv1.analytical_delay(corner, slew=slew, load=self.inv2.input_load()) - inv2_delay = self.inv2.analytical_delay(corner, slew=inv1_delay.slew, load=load) - return inv1_delay + inv2_delay - def get_stage_efforts(self, external_cout, inp_is_rise=False): """Get the stage efforts of the A -> Z path""" stage_effort_list = [] diff --git a/compiler/pgates/pdriver.py b/compiler/pgates/pdriver.py index a3180006..36811a5e 100644 --- a/compiler/pgates/pdriver.py +++ b/compiler/pgates/pdriver.py @@ -173,30 +173,6 @@ class pdriver(pgate.pgate): offset=a_pin.center(), width = a_pin.width(), height = a_pin.height()) - - def input_load(self): - return self.inv_list[0].input_load() - - def analytical_delay(self, corner, slew, load=0.0): - """ Calculate the analytical delay of INV1 -> ... -> INVn """ - - cout_list = [] - for prev_inv,inv in zip(self.inv_list, self.inv_list[1:]): - cout_list.append(inv.input_load()) - cout_list.append(load) - - input_slew = slew - - delays = [] - for inv,cout in zip(self.inv_list,cout_list): - delays.append(inv.analytical_delay(corner, slew=input_slew, load=cout)) - input_slew = delays[-1].slew - - delay = delays[0] - for i in range(len(delays)-1): - delay += delays[i] - - return delay def get_sizes(self): """ Return the relative sizes of the buffers """ diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 773a0452..28eb03e8 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -255,15 +255,6 @@ class pinv(pgate.pgate): self.connect_pin_to_rail(self.pmos_inst,"S","vdd") - - def input_load(self): - return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] - - def analytical_delay(self, corner, slew, load=0.0): - r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) - c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff - return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) diff --git a/compiler/pgates/pinvbuf.py b/compiler/pgates/pinvbuf.py index 72ab6a8a..a8d2c8b8 100644 --- a/compiler/pgates/pinvbuf.py +++ b/compiler/pgates/pinvbuf.py @@ -178,15 +178,7 @@ class pinvbuf(pgate.pgate): offset=a_pin.center()) self.add_via_center(layers=("metal1","via1","metal2"), offset=a_pin.center()) - - - - def analytical_delay(self, corner, slew, load=0.0): - """ Calculate the analytical delay of DFF-> INV -> INV """ - inv1_delay = self.inv1.analytical_delay(corner, slew=slew, load=self.inv2.input_load()) - inv2_delay = self.inv2.analytical_delay(corner, slew=inv1_delay.slew, load=load) - return inv1_delay + inv2_delay - + def determine_clk_buf_stage_efforts(self, external_cout, inp_is_rise=False): """Get the stage efforts of the clk -> clk_buf path""" stage_effort_list = [] diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 956f0a30..b0d30b7b 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -233,17 +233,6 @@ class pnand2(pgate.pgate): width=contact.m1m2.first_layer_height, height=contact.m1m2.first_layer_width) - - - - def input_load(self): - return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] - - def analytical_delay(self, corner, slew, load=0.0): - r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) - c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff - return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 30da9165..eee6ca9a 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -243,16 +243,6 @@ class pnand3(pgate.pgate): width=contact.m1m2.first_layer_width, height=contact.m1m2.first_layer_height) - - - def input_load(self): - return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] - - def analytical_delay(self, corner, slew, load=0.0): - r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) - c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff - return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index fa52c528..ee55dbcb 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -213,16 +213,6 @@ class pnor2(pgate.pgate): width=contact.m1m2.first_layer_height, height=contact.m1m2.first_layer_width) - - - def input_load(self): - return ((self.nmos_size+self.pmos_size)/parameter["min_tx_size"])*spice["min_tx_gate_c"] - - def analytical_delay(self, corner, slew, load=0.0): - r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"]) - c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff - return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" c_eff = self.calculate_effective_capacitance(load) diff --git a/compiler/pgates/ptristate_inv.py b/compiler/pgates/ptristate_inv.py index 55a248a7..3176915a 100644 --- a/compiler/pgates/ptristate_inv.py +++ b/compiler/pgates/ptristate_inv.py @@ -210,13 +210,6 @@ class ptristate_inv(pgate.pgate): self.connect_pin_to_rail(self.nmos1_inst,"S","gnd") self.connect_pin_to_rail(self.pmos1_inst,"S","vdd") - - def analytical_delay(self, corner, slew, load=0.0): - from tech import spice - r = spice["min_tx_r"] - c_para = spice["min_tx_drain_c"] - return self.cal_delay_with_rc(corner, r = r, c = c_para+load, slew = slew) - def analytical_power(self, corner, load): """Returns dynamic and leakage power. Results in nW""" #Power in this module currently not defined. Returns 0 nW (leakage and dynamic). From ae46a464b99468e7e11c7c3eabc2969ba128604d Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 6 Aug 2019 17:17:59 -0700 Subject: [PATCH 178/234] Undo delay changes. Fix bus order for DRC. --- compiler/modules/bank.py | 6 +++--- compiler/modules/control_logic.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index f3491b79..4fa95c44 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -304,13 +304,13 @@ class bank(design.design): self.input_control_signals = [] port_num = 0 for port in range(OPTS.num_rw_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)]) + self.input_control_signals.append(["w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_w_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "p_en_bar{}".format(port_num)]) + self.input_control_signals.append(["w_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_r_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)]) + self.input_control_signals.append(["s_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".format(port_num)]) port_num += 1 # Number of control lines in the bus for each port diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index f5531d6f..a5c5dc12 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -120,7 +120,7 @@ class control_logic(design.design): # wl_en drives every row in the bank self.wl_en_driver = factory.create(module_type="pdriver", - fanout=max_fanout, + fanout=self.num_rows, height=dff_height) self.add_mod(self.wl_en_driver) @@ -145,9 +145,9 @@ class control_logic(design.design): # p_en_bar drives every column in the bitcell array # but it is sized the same as the wl_en driver with # prepended 3 inverter stages to guarantee it is slower and odd polarity - driver_size_list = [1,1,1,*self.wl_en_driver.get_sizes()] self.p_en_bar_driver = factory.create(module_type="pdriver", - size_list=driver_size_list, + fanout=self.num_cols, + neg_polarity=True, height=dff_height) self.add_mod(self.p_en_bar_driver) From 6860d3258ecedfe595e7dae0cda0335525b82cf4 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Wed, 7 Aug 2019 01:50:48 -0700 Subject: [PATCH 179/234] Added graph functions to compute analytical delay based on graph path. --- compiler/base/graph_util.py | 36 ++++++++- compiler/base/hierarchy_design.py | 2 +- compiler/base/hierarchy_spice.py | 24 ++++-- compiler/bitcells/bitcell.py | 12 ++- compiler/bitcells/bitcell_1rw_1r.py | 8 +- compiler/bitcells/bitcell_1w_1r.py | 4 +- compiler/bitcells/pbitcell.py | 4 +- compiler/bitcells/replica_bitcell_1rw_1r.py | 4 +- compiler/bitcells/replica_bitcell_1w_1r.py | 4 +- compiler/characterizer/delay.py | 73 +++++++++++++------ .../example_config_scn4m_subm.py | 2 + compiler/modules/sense_amp.py | 2 +- compiler/pgates/pinv.py | 7 +- compiler/pgates/pnand2.py | 6 +- compiler/pgates/single_level_column_mux.py | 2 +- 15 files changed, 141 insertions(+), 49 deletions(-) diff --git a/compiler/base/graph_util.py b/compiler/base/graph_util.py index 7cf8ee6f..8a6588af 100644 --- a/compiler/base/graph_util.py +++ b/compiler/base/graph_util.py @@ -18,13 +18,16 @@ class timing_graph(): def __init__(self): self.graph = defaultdict(set) self.all_paths = [] + self.edge_mods = {} - def add_edge(self, src_node, dest_node): - """Adds edge to graph. Nodes added as well if they do not exist.""" + def add_edge(self, src_node, dest_node, edge_mod): + """Adds edge to graph. Nodes added as well if they do not exist. + Module which defines the edge must be provided for timing information.""" src_node = src_node.lower() dest_node = dest_node.lower() self.graph[src_node].add(dest_node) + self.edge_mods[(src_node, dest_node)] = edge_mod def add_node(self, node): """Add node to graph with no edges""" @@ -34,8 +37,8 @@ class timing_graph(): self.graph[node] = set() def remove_edges(self, node): - """Helper function to remove edges, useful for removing vdd/gnd""" + node = node.lower() self.graph[node] = set() @@ -93,7 +96,32 @@ class timing_graph(): # Remove current vertex from path[] and mark it as unvisited path.pop() - visited.remove(cur_node) + visited.remove(cur_node) + + def get_timing(self, path, corner, slew, load): + """Returns the analytical delays in the input path""" + + if len(path) == 0: + return [] + + delays = [] + for i in range(len(path)-1): + + path_edge_mod = self.edge_mods[(path[i], path[i+1])] + + # On the output of the current stage, get COUT from all other mods connected + cout = 0 + for node in self.graph[path[i+1]]: + output_edge_mode = self.edge_mods[(path[i+1], node)] + cout+=output_edge_mode.input_load() + # If at the last output, include the final output load + if i == len(path)-2: + cout+=load + + delays.append(path_edge_mod.analytical_delay(corner, slew, cout)) + slew = delays[-1].slew + + return delays def __str__(self): """ override print function output """ diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index 05b2182f..ec0b4e96 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -219,7 +219,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): for inp in input_pins+inout_pins: for out in output_pins+inout_pins: if inp != out: #do not add self loops - graph.add_edge(pin_dict[inp], pin_dict[out]) + graph.add_edge(pin_dict[inp], pin_dict[out], self) def __str__(self): """ override print function output """ diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 2dcc3d73..c8ffb151 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -13,7 +13,7 @@ import tech from delay_data import * from wire_spice_model import * from power_data import * - +import logical_effort class spice(): """ @@ -304,14 +304,28 @@ class spice(): def analytical_delay(self, corner, slew, load=0.0): """Inform users undefined delay module while building new modules""" - debug.warning("Design Class {0} delay function needs to be defined" + relative_cap = logical_effort.convert_farad_to_relative_c(load) + stage_effort = self.get_stage_effort(relative_cap) + + # If it fails, then keep running with a valid object. + if stage_effort == None: + return delay_data(0.0, 0.0) + + abs_delay = stage_effort.get_absolute_delay() + corner_delay = self.apply_corners_analytically(abs_delay, corner) + SLEW_APPROXIMATION = 0.1 + corner_slew = SLEW_APPROXIMATION*corner_delay + return delay_data(corner_delay, corner_slew) + + def get_stage_effort(self, corner, slew, load=0.0): + """Inform users undefined delay module while building new modules""" + debug.warning("Design Class {0} logical effort function needs to be defined" .format(self.__class__.__name__)) debug.warning("Class {0} name {1}" .format(self.__class__.__name__, self.name)) - # return 0 to keep code running while building - return delay_data(0.0, 0.0) - + return None + def cal_delay_with_rc(self, corner, r, c ,slew, swing = 0.5): """ Calculate the delay of a mosfet by diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 96432cea..360e08de 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -36,12 +36,22 @@ class bitcell(design.design): self.add_pin_types(self.type_list) self.nets_match = self.do_nets_exist(self.storage_nets) - def analytical_delay(self, corner, slew, load=0, swing = 0.5): + def get_stage_effort(self, load): parasitic_delay = 1 size = 0.5 #This accounts for bitline being drained thought the access TX and internal node cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file. return logical_effort.logical_effort('bitline', size, cin, load, parasitic_delay, False) + def input_load(self): + """Return the relative capacitance of the access transistor gates""" + #This is a handmade cell so the value must be entered in the tech.py file or estimated. + #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. + + #FIXME: The graph algorithm will apply this capacitance to the bitline load as they cannot be + # distinguished currently + access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] + return 2*access_tx_cin + def get_all_wl_names(self): """ Creates a list of all wordline pin names """ row_pins = ["wl"] diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index f627a4ac..42bd3855 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -141,8 +141,8 @@ class bitcell_1rw_1r(design.design): pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} #Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges - graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) - graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"], self) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"], self) # Port 1 edges - graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) - graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self) diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index 6063cf86..b8f0e49b 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -139,6 +139,6 @@ class bitcell_1w_1r(design.design): pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} #Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges - graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) - graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self) # Port 1 is a write port, so its timing is not considered here. diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index 3c59a9e3..b09e81c2 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -973,6 +973,6 @@ class pbitcell(design.design): for pin_zip in [rw_pin_names, r_pin_names]: for wl,bl,br in pin_zip: - graph.add_edge(pin_dict[wl],pin_dict[bl]) - graph.add_edge(pin_dict[wl],pin_dict[br]) + graph.add_edge(pin_dict[wl],pin_dict[bl], self) + graph.add_edge(pin_dict[wl],pin_dict[br], self) diff --git a/compiler/bitcells/replica_bitcell_1rw_1r.py b/compiler/bitcells/replica_bitcell_1rw_1r.py index e5c33317..9737669d 100644 --- a/compiler/bitcells/replica_bitcell_1rw_1r.py +++ b/compiler/bitcells/replica_bitcell_1rw_1r.py @@ -46,8 +46,8 @@ class replica_bitcell_1rw_1r(design.design): pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} #Edges hardcoded here. Essentially wl->bl/br for both ports. # Port 0 edges - graph.add_edge(pin_dict["wl0"], pin_dict["bl0"]) - graph.add_edge(pin_dict["wl0"], pin_dict["br0"]) + graph.add_edge(pin_dict["wl0"], pin_dict["bl0"], self) + graph.add_edge(pin_dict["wl0"], pin_dict["br0"], self) # Port 1 edges graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1w_1r.py b/compiler/bitcells/replica_bitcell_1w_1r.py index 79171bf5..fad5032d 100644 --- a/compiler/bitcells/replica_bitcell_1w_1r.py +++ b/compiler/bitcells/replica_bitcell_1w_1r.py @@ -47,6 +47,6 @@ class replica_bitcell_1w_1r(design.design): pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} #Edges hardcoded here. Essentially wl->bl/br for the read port. # Port 1 edges - graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) - graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self) # Port 0 is a write port, so its timing is not considered here. \ No newline at end of file diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index bb48564e..90e1561e 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -1275,36 +1275,65 @@ class delay(simulation): # Add test cycle of read/write port pair. One port could have been used already, but the other has not. self.gen_test_cycles_one_port(cur_read_port, cur_write_port) + def sum_delays(self, delays): + """Adds the delays (delay_data objects) so the correct slew is maintained""" + delay = delays[0] + for i in range(1, len(delays)): + delay+=delays[i] + return delay + def analytical_delay(self, slews, loads): """ 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.") + + # Probe set to 0th bit, does not matter for analytical delay. + self.set_probe('0', 0) + self.create_graph() + self.set_internal_spice_names() self.create_measurement_names() - power = self.analytical_power(slews, loads) - port_data = self.get_empty_measure_data_dict() - relative_loads = [logical_effort.convert_farad_to_relative_c(c_farad) for c_farad in loads] + + port = self.read_ports[0] + self.graph.get_all_paths('{}{}'.format(tech.spice["clk"], port), + '{}{}_{}'.format(self.dout_name, port, self.probe_data)) + + # Select the path with the bitline (bl) + bl_name,br_name = self.get_bl_name(self.graph.all_paths, port) + bl_path = [path for path in self.graph.all_paths if bl_name in path][0] + + debug.info(1,'Slew, Load, Delay(ns), Slew(ns)') for slew in slews: - for load in relative_loads: - self.set_load_slew(load,slew) - bank_delay = self.sram.analytical_delay(self.corner, self.slew,self.load) - for port in self.all_ports: - for mname in self.delay_meas_names+self.power_meas_names: - if "power" in mname: - port_data[port][mname].append(power.dynamic) - elif "delay" in mname: - port_data[port][mname].append(bank_delay[port].delay/1e3) - elif "slew" in mname: - port_data[port][mname].append(bank_delay[port].slew/1e3) - else: - debug.error("Measurement name not recognized: {}".format(mname),1) - period_margin = 0.1 - risefall_delay = bank_delay[self.read_ports[0]].delay/1e3 - sram_data = { "min_period":risefall_delay*2*period_margin, - "leakage_power": power.leakage} - debug.info(2,"SRAM Data:\n{}".format(sram_data)) - debug.info(2,"Port Data:\n{}".format(port_data)) + for load in loads: + path_delays = self.graph.get_timing(bl_path, self.corner, slew, load) + total_delay = self.sum_delays(path_delays) + debug.info(1,'{}, {}, {}, {}'.format(slew,load,total_delay.delay/1e3, total_delay.slew/1e3)) + + debug.error('Not finished with graph delay characterization.', 1) + # power = self.analytical_power(slews, loads) + # port_data = self.get_empty_measure_data_dict() + # relative_loads = [logical_effort.convert_farad_to_relative_c(c_farad) for c_farad in loads] + # for slew in slews: + # for load in relative_loads: + # self.set_load_slew(load,slew) + # bank_delay = self.sram.analytical_delay(self.corner, self.slew,self.load) + # for port in self.all_ports: + # for mname in self.delay_meas_names+self.power_meas_names: + # if "power" in mname: + # port_data[port][mname].append(power.dynamic) + # elif "delay" in mname: + # port_data[port][mname].append(bank_delay[port].delay/1e3) + # elif "slew" in mname: + # port_data[port][mname].append(bank_delay[port].slew/1e3) + # else: + # debug.error("Measurement name not recognized: {}".format(mname),1) + # period_margin = 0.1 + # risefall_delay = bank_delay[self.read_ports[0]].delay/1e3 + # sram_data = { "min_period":risefall_delay*2*period_margin, + # "leakage_power": power.leakage} + # debug.info(2,"SRAM Data:\n{}".format(sram_data)) + # debug.info(2,"Port Data:\n{}".format(port_data)) return (sram_data,port_data) diff --git a/compiler/example_configs/example_config_scn4m_subm.py b/compiler/example_configs/example_config_scn4m_subm.py index cf973225..657eceda 100644 --- a/compiler/example_configs/example_config_scn4m_subm.py +++ b/compiler/example_configs/example_config_scn4m_subm.py @@ -15,3 +15,5 @@ output_name = "sram_{0}_{1}_{2}".format(word_size,num_words,tech_name) drc_name = "magic" lvs_name = "netgen" pex_name = "magic" + +netlist_only = True \ No newline at end of file diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index e104356f..a053aff8 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -41,7 +41,7 @@ class sense_amp(design.design): bitline_pmos_size = 8 #FIXME: This should be set somewhere and referenced. Probably in tech file. return spice["min_tx_drain_c"]*(bitline_pmos_size/parameter["min_tx_size"])#ff - def analytical_delay(self, corner, slew, load): + def get_stage_effort(self, load): #Delay of the sense amp will depend on the size of the amp and the output load. parasitic_delay = 1 cin = (parameter["sa_inv_pmos_size"] + parameter["sa_inv_nmos_size"])/drc("minwidth_tx") diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 28eb03e8..d841b318 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -276,7 +276,12 @@ class pinv(pgate.pgate): """Return the capacitance of the gate connection in generic capacitive units relative to the minimum width of a transistor""" return self.nmos_size + self.pmos_size - + + def input_load(self): + """Return the capacitance of the gate connection in generic capacitive + units relative to the minimum width of a transistor""" + return self.nmos_size + self.pmos_size + def get_stage_effort(self, cout, inp_is_rise=True): """Returns an object representing the parameters for delay in tau units. Optional is_rise refers to the input direction rise/fall. Input inverted by this stage. diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index b0d30b7b..2275a336 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -253,7 +253,11 @@ class pnand2(pgate.pgate): def get_cin(self): """Return the relative input capacitance of a single input""" return self.nmos_size+self.pmos_size - + + def input_load(self): + """Return the relative input capacitance of a single input""" + return self.nmos_size+self.pmos_size + def get_stage_effort(self, cout, inp_is_rise=True): """Returns an object representing the parameters for delay in tau units. Optional is_rise refers to the input direction rise/fall. Input inverted by this stage. diff --git a/compiler/pgates/single_level_column_mux.py b/compiler/pgates/single_level_column_mux.py index 7c21c0a8..999d3ccd 100644 --- a/compiler/pgates/single_level_column_mux.py +++ b/compiler/pgates/single_level_column_mux.py @@ -189,7 +189,7 @@ class single_level_column_mux(pgate.pgate): width=self.bitcell.width, height=self.height) - def analytical_delay(self, corner, slew, load): + def get_stage_effort(self, corner, slew, load): """Returns relative delay that the column mux. Difficult to convert to LE model.""" parasitic_delay = 1 cin = 2*self.tx_size #This is not CMOS, so using this may be incorrect. From a6bb4105602e25b55e22b551a455f571c6e6430c Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 7 Aug 2019 09:12:21 -0700 Subject: [PATCH 180/234] Begin implementing a write mask layout as the port data level. --- compiler/characterizer/functional.py | 10 +- compiler/modules/port_data.py | 99 ++++++++++----- compiler/modules/write_driver_array.py | 20 ++- compiler/tests/18_port_data_wmask_test.py | 114 ++++++++++++++++++ ...st.py => 22_sram_wmask_1w_1r_func_test.py} | 4 +- 5 files changed, 203 insertions(+), 44 deletions(-) create mode 100644 compiler/tests/18_port_data_wmask_test.py rename compiler/tests/{22_psram_wmask_func_test.py => 22_sram_wmask_1w_1r_func_test.py} (95%) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 6dcb54e0..60ebd339 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -102,7 +102,6 @@ class functional(simulation): # Write at least once addr = self.gen_addr() word = self.gen_data() - # print("write", self.t_current, addr, word) comment = self.gen_cycle_comment("write", word, addr, self.wmask, 0, self.t_current) self.add_write(comment, addr, word, self.wmask, 0) self.stored_words[addr] = word @@ -113,9 +112,8 @@ class functional(simulation): if port in self.write_ports: self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) else: - # print("read", self.t_current, addr, word) comment = self.gen_cycle_comment("read", word, addr, self.wmask, port, self.t_current) - self.add_read_one_port(comment, addr, rw_read_din_data, "1"*self.num_wmasks, port) + self.add_read_one_port(comment, addr, rw_read_din_data, "0"*self.num_wmasks, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) check += 1 self.cycle_times.append(self.t_current) @@ -150,7 +148,7 @@ class functional(simulation): self.stored_words[addr] = word w_addrs.append(addr) elif op == "partial_write": - #write only to a word that's been written to + # write only to a word that's been written to (addr,old_word) = self.get_data() word = self.gen_data() wmask = self.gen_wmask() @@ -177,7 +175,7 @@ class functional(simulation): self.add_noop_one_port("0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks, port) else: comment = self.gen_cycle_comment("read", word, addr, self.wmask, port, self.t_current) - self.add_read_one_port(comment, addr, rw_read_din_data, "1"*self.num_wmasks, port) + self.add_read_one_port(comment, addr, rw_read_din_data, "0"*self.num_wmasks, port) self.write_check.append([word, "{0}{1}".format(self.dout_name,port), self.t_current+self.period, check]) check += 1 @@ -259,7 +257,7 @@ class functional(simulation): def get_data(self): """ Gets an available address and corresponding word. """ - # Currently unused but may need later depending on how the functional test develops + # Used for write masks since they should be writing to previously written addresses addr = random.choice(list(self.stored_words.keys())) word = self.stored_words[addr] return (addr,word) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 3e4caf57..15e84f2b 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -308,23 +308,23 @@ class port_data(design.design): """ Placing Sense amp """ self.sense_amp_array_inst.place(offset=offset, mirror="MX") - + def create_write_driver_array(self): """ Creating Write Driver """ - self.write_driver_array_inst = self.add_inst(name="write_driver_array{}".format(self.port), + self.write_driver_array_inst = self.add_inst(name="write_driver_array{}".format(self.port), mod=self.write_driver_array) temp = [] for bit in range(self.word_size): temp.append("din_{}".format(bit)) - for bit in range(self.word_size): + for bit in range(self.word_size): if (self.words_per_row == 1): - temp.append(self.bl_names[self.port]+"_{0}".format(bit)) - temp.append(self.br_names[self.port]+"_{0}".format(bit)) + temp.append(self.bl_names[self.port] + "_{0}".format(bit)) + temp.append(self.br_names[self.port] + "_{0}".format(bit)) else: - temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) - temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) + temp.append(self.bl_names[self.port] + "_out_{0}".format(bit)) + temp.append(self.br_names[self.port] + "_out_{0}".format(bit)) if self.write_size is not None: for i in range(self.num_wmasks): @@ -336,10 +336,15 @@ class port_data(design.design): self.connect_inst(temp) + def place_write_driver_array(self, offset): + """ Placing Write Driver """ + self.write_driver_array_inst.place(offset=offset, mirror="MX") + + def create_write_mask_and_array(self): - """ Creating Write Masks """ + """ Creating Write Mask AND Array """ self.write_mask_and_array_inst = self.add_inst(name="write_mask_and_array{}".format(self.port), - mod=self.write_mask_and_array) + mod=self.write_mask_and_array) temp = [] for bit in range(self.num_wmasks): @@ -351,10 +356,10 @@ class port_data(design.design): self.connect_inst(temp) - def place_write_driver_array(self, offset): - """ Placing Write Driver """ - self .write_driver_array_inst.place(offset=offset, mirror="MX") - + def place_write_mask_and_array(self, offset): + """ Placing Write Mask AND array """ + self.write_mask_and_array_inst.place(offset=offset, mirror="MX") + def compute_instance_offsets(self): """ @@ -366,41 +371,41 @@ class port_data(design.design): vertical_port_order.append(self.column_mux_array_inst) vertical_port_order.append(self.sense_amp_array_inst) vertical_port_order.append(self.write_driver_array_inst) + vertical_port_order.append(self.write_mask_and_array_inst) # Add one column for the the RBL - if self.has_rbl() and self.port==0: + if self.has_rbl() and self.port == 0: x_offset = self.bitcell.width else: x_offset = 0 - - vertical_port_offsets = 4*[None] + + vertical_port_offsets = 5 * [None] self.width = x_offset self.height = 0 - for i,p in enumerate(vertical_port_order): - if p==None: + for i, p in enumerate(vertical_port_order): + if p == None: continue self.height += (p.height + self.m2_gap) self.width = max(self.width, p.width) - vertical_port_offsets[i]=vector(x_offset,self.height) + vertical_port_offsets[i] = vector(x_offset, self.height) # Reversed order + self.write_mask_and_offset = vertical_port_offsets[4] self.write_driver_offset = vertical_port_offsets[3] self.sense_amp_offset = vertical_port_offsets[2] self.column_mux_offset = vertical_port_offsets[1] self.precharge_offset = vertical_port_offsets[0] # Shift the precharge left if port 0 - if self.precharge_offset and self.port==0: - self.precharge_offset -= vector(x_offset,0) - + if self.precharge_offset and self.port == 0: + self.precharge_offset -= vector(x_offset, 0) - - - def place_instances(self): """ Place the instances. """ - # These are fixed in the order: write driver, sense amp, clumn mux, precharge, + # These are fixed in the order: write mask ANDs, write driver, sense amp, column mux, precharge, # even if the item is not used in a given port (it will be None then) + if self.write_mask_and_offset: + self.place_write_mask_and_array(self.write_mask_and_offset) if self.write_driver_offset: self.place_write_driver_array(self.write_driver_offset) if self.sense_amp_offset: @@ -410,6 +415,7 @@ class port_data(design.design): if self.column_mux_offset: self.place_column_mux_array(self.column_mux_offset) + def route_sense_amp_out(self, port): """ Add pins for the sense amp output """ @@ -420,7 +426,8 @@ class port_data(design.design): offset=data_pin.center(), height=data_pin.height(), width=data_pin.width()) - + + def route_write_driver_in(self, port): """ Connecting write driver """ @@ -428,7 +435,25 @@ class port_data(design.design): data_name = "data_{}".format(row) din_name = "din_{}".format(row) self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name) - + + + def route_write_mask_and_out(self, port): + """ Add pins for the write mask and array output """ + + for bit in range(self.num_wmasks): + wdriver_sel_pin = self.write_mask_and_array_inst.get_pin("wdriver_sel_{}".format(bit)) + self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), + layer=wdriver_sel_pin.layer, + offset=wdriver_sel_pin.center(), + height=wdriver_sel_pin.height(), + width=wdriver_sel_pin.width()) + + # for bit in range(self.num_wmasks): + # print(bit) + # wdriver_sel_name = "wdriver_sel_{}".format(bit) + # self.copy_layout_pin(self.write_mask_and_array_inst, wdriver_sel_name) + + def route_column_mux_to_precharge_array(self, port): """ Routing of BL and BR between col mux and precharge array """ @@ -503,6 +528,14 @@ class port_data(design.design): self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size) + def route_write_mask_and_to_write_driver(self,port): + """ Routing of wdriver_sel_{} between write mask AND and write driver """ + inst1 = self.write_mask_and_array_inst + inst2 = self.write_driver_array_inst + + inst1_wdriver_sel_name = "wdriver_sel_{}" + start_bit=0 + def route_bitline_pins(self): """ Add the bitline pins for the given port """ @@ -524,7 +557,7 @@ class port_data(design.design): self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit+bit_offset), "bl_{}".format(bit)) self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit+bit_offset), "br_{}".format(bit)) else: - debug.error("Didn't find precharge arra.") + debug.error("Didn't find precharge array.") def route_control_pins(self): """ Add the control pins: s_en, p_en_bar, w_en """ @@ -537,7 +570,13 @@ class port_data(design.design): if self.sense_amp_array_inst: self.copy_layout_pin(self.sense_amp_array_inst, "en", "s_en") if self.write_driver_array_inst: - self.copy_layout_pin(self.write_driver_array_inst, "en", "w_en") + if self.write_mask_and_array_inst: + for bit in range(self.num_wmasks): +s self.copy_layout_pin(self.write_driver_array_inst, "en_{}".format(bit), "wdriver_sel_{}".format(bit)) + else: + self.copy_layout_pin(self.write_driver_array_inst, "en", "w_en") + if self.write_mask_and_array_inst: + self.copy_layout_pin(self.write_mask_and_array_inst, "en", "w_en") def channel_route_bitlines(self, inst1, inst2, num_bits, diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 7da57b37..cddd81e4 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -95,6 +95,7 @@ class write_driver_array(design.design): "br_{0}".format(index), "en_{0}".format(windex), "vdd", "gnd"]) w+=1 + # when w equals write size, the next en pin can be connected since we are now at the next wmask bit if w == self.write_size: w = 0 windex+=1 @@ -149,12 +150,19 @@ class write_driver_array(design.design): self.add_layout_pin_rect_center(text=n, layer="metal3", offset=pin_pos) - - self.add_layout_pin(text="en", - layer="metal1", - offset=self.driver_insts[0].get_pin("en").ll().scale(0,1), - width=self.width, - height=drc('minwidth_metal1')) + if self.write_size is not None: + for bit in range(self.num_wmasks): + self.add_layout_pin(text="en_{}".format(bit), + layer="metal1", + offset=self.driver_insts[bit*(self.write_size-1)].get_pin("en").ll().scale(0,1), + width=self.width, + height=drc('minwidth_metal1')) + else: + self.add_layout_pin(text="en", + layer="metal1", + offset=self.driver_insts[0].get_pin("en").ll().scale(0,1), + width=self.width, + height=drc('minwidth_metal1')) diff --git a/compiler/tests/18_port_data_wmask_test.py b/compiler/tests/18_port_data_wmask_test.py new file mode 100644 index 00000000..abc4f5d0 --- /dev/null +++ b/compiler/tests/18_port_data_wmask_test.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California +# 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 port_data_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + from sram_config import sram_config + + c = sram_config(word_size=8, + write_size=4, + num_words=16) + + c.words_per_row = 1 + factory.reset() + c.recompute_sizes() + debug.info(1, "No column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + + c.num_words = 32 + c.words_per_row = 2 + factory.reset() + c.recompute_sizes() + debug.info(1, "Two way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + + c.num_words = 64 + c.words_per_row = 4 + factory.reset() + c.recompute_sizes() + debug.info(1, "Four way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + + c.word_size = 2 + c.num_words = 128 + c.words_per_row = 8 + factory.reset() + c.recompute_sizes() + debug.info(1, "Eight way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + + OPTS.bitcell = "bitcell_1w_1r" + OPTS.num_rw_ports = 0 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 1 + + c.num_words = 16 + c.words_per_row = 1 + factory.reset() + c.recompute_sizes() + debug.info(1, "No column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + a = factory.create("port_data", sram_config=c, port=1) + self.local_check(a) + + c.num_words = 32 + c.words_per_row = 2 + factory.reset() + c.recompute_sizes() + debug.info(1, "Two way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + a = factory.create("port_data", sram_config=c, port=1) + self.local_check(a) + + c.num_words = 64 + c.words_per_row = 4 + factory.reset() + c.recompute_sizes() + debug.info(1, "Four way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + a = factory.create("port_data", sram_config=c, port=1) + self.local_check(a) + + c.word_size = 2 + c.num_words = 128 + c.words_per_row = 8 + factory.reset() + c.recompute_sizes() + debug.info(1, "Eight way column mux") + a = factory.create("port_data", sram_config=c, port=0) + self.local_check(a) + a = factory.create("port_data", sram_config=c, port=1) + 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()) \ No newline at end of file diff --git a/compiler/tests/22_psram_wmask_func_test.py b/compiler/tests/22_sram_wmask_1w_1r_func_test.py similarity index 95% rename from compiler/tests/22_psram_wmask_func_test.py rename to compiler/tests/22_sram_wmask_1w_1r_func_test.py index eafeb0a9..2ee79750 100755 --- a/compiler/tests/22_psram_wmask_func_test.py +++ b/compiler/tests/22_sram_wmask_1w_1r_func_test.py @@ -17,8 +17,8 @@ from sram_factory import factory import debug -# @unittest.skip("SKIPPING psram_wmask_func_test") -class psram_wmask_func_test(openram_test): +# @unittest.skip("SKIPPING sram_wmask_1w_1r_func_test") +class sram_wmask_1w_1r_func_test(openram_test): def runTest(self): globals.init_openram("config_{0}".format(OPTS.tech_name)) From abb9af0ea8a05b3be3280da38292f6eb9c21c47d Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 7 Aug 2019 09:33:19 -0700 Subject: [PATCH 181/234] Added layout pins for wmask_and_array --- compiler/modules/port_data.py | 48 ++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 15e84f2b..24fc4557 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -437,21 +437,26 @@ class port_data(design.design): self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name) - def route_write_mask_and_out(self, port): + def route_write_mask_and_in(self, port): """ Add pins for the write mask and array output """ for bit in range(self.num_wmasks): - wdriver_sel_pin = self.write_mask_and_array_inst.get_pin("wdriver_sel_{}".format(bit)) - self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), - layer=wdriver_sel_pin.layer, - offset=wdriver_sel_pin.center(), - height=wdriver_sel_pin.height(), - width=wdriver_sel_pin.width()) + wmask_out_name = "wmask_out_{}".format(bit) + wdriver_sel_name = "wdriver_sel_{}".format(bit) + self.copy_layout_pin(self.write_mask_and_array_inst, wmask_out_name, wdriver_sel_name) + + for bit in range(self.num_wmasks): + wmask_in_name = "wmask_in_{}".format(bit) + bank_wmask_name = "bank_wmask_{}".format(bit) + self.copy_layout_pin(self.write_mask_and_array_inst, wmask_in_name, bank_wmask_name) # for bit in range(self.num_wmasks): - # print(bit) - # wdriver_sel_name = "wdriver_sel_{}".format(bit) - # self.copy_layout_pin(self.write_mask_and_array_inst, wdriver_sel_name) + # wdriver_sel_pin = self.write_mask_and_array_inst.get_pin("wdriver_sel_{}".format(bit)) + # self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), + # layer=wdriver_sel_pin.layer, + # offset=wdriver_sel_pin.center(), + # height=wdriver_sel_pin.height(), + # width=wdriver_sel_pin.width()) def route_column_mux_to_precharge_array(self, port): @@ -469,7 +474,6 @@ class port_data(design.design): self.connect_bitlines(inst1, inst2, self.num_cols) - def route_sense_amp_to_column_mux_or_precharge_array(self, port): """ Routing of BL and BR between sense_amp and column mux or precharge array """ inst2 = self.sense_amp_array_inst @@ -494,6 +498,7 @@ class port_data(design.design): self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name, inst1_start_bit=start_bit) + def route_write_driver_to_column_mux_or_precharge_array(self, port): """ Routing of BL and BR between sense_amp and column mux or precharge array """ inst2 = self.write_driver_array_inst @@ -516,7 +521,8 @@ class port_data(design.design): self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size, inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name, inst1_start_bit=start_bit) - + + def route_write_driver_to_sense_amp(self, port): """ Routing of BL and BR between write driver and sense amp """ @@ -528,13 +534,13 @@ class port_data(design.design): self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size) - def route_write_mask_and_to_write_driver(self,port): - """ Routing of wdriver_sel_{} between write mask AND and write driver """ - inst1 = self.write_mask_and_array_inst - inst2 = self.write_driver_array_inst - - inst1_wdriver_sel_name = "wdriver_sel_{}" - start_bit=0 + # def route_write_mask_and_to_write_driver(self,port): + # """ Routing of wdriver_sel_{} between write mask AND and write driver """ + # inst1 = self.write_mask_and_array_inst + # inst2 = self.write_driver_array_inst + # + # inst1_wdriver_sel_name = "wdriver_sel_{}" + # start_bit=0 def route_bitline_pins(self): """ Add the bitline pins for the given port """ @@ -551,7 +557,6 @@ class port_data(design.design): else: bit_offset=0 - for bit in range(self.num_cols): if self.precharge_array_inst: self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit+bit_offset), "bl_{}".format(bit)) @@ -559,6 +564,7 @@ class port_data(design.design): else: debug.error("Didn't find precharge array.") + def route_control_pins(self): """ Add the control pins: s_en, p_en_bar, w_en """ if self.precharge_array_inst: @@ -572,7 +578,7 @@ class port_data(design.design): if self.write_driver_array_inst: if self.write_mask_and_array_inst: for bit in range(self.num_wmasks): -s self.copy_layout_pin(self.write_driver_array_inst, "en_{}".format(bit), "wdriver_sel_{}".format(bit)) + self.copy_layout_pin(self.write_driver_array_inst, "en_{}".format(bit), "wdriver_sel_{}".format(bit)) else: self.copy_layout_pin(self.write_driver_array_inst, "en", "w_en") if self.write_mask_and_array_inst: From c2655fcaa9a3429cda129df6da9d798ce68e0b44 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 7 Aug 2019 16:01:05 -0700 Subject: [PATCH 182/234] Update pnor2 to new placement logic --- compiler/pgates/pnor2.py | 76 ++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index fa52c528..15bdba9c 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -5,12 +5,13 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # +import contact import pgate import debug from tech import drc, parameter, spice from vector import vector from globals import OPTS -import contact +import logical_effort from sram_factory import factory class pnor2(pgate.pgate): @@ -38,28 +39,30 @@ class pnor2(pgate.pgate): pgate.pgate.__init__(self, name, height) - def add_pins(self): - """ Adds pins for spice netlist """ - pin_list = ["A", "B", "Z", "vdd", "gnd"] - dir_list = ["INPUT", "INPUT", "OUTPUT", "INOUT", "INOUT"] - self.add_pin_list(pin_list, dir_list) - def create_netlist(self): self.add_pins() + self.add_ptx() self.create_ptx() - self.setup_layout_constants() def create_layout(self): """ Calls all functions related to the generation of the layout """ - self.add_supply_rails() - self.add_ptx() + + self.setup_layout_constants() + self.route_supply_rails() + self.place_ptx() self.connect_rails() self.add_well_contacts() self.extend_wells(self.well_pos) self.route_inputs() self.route_output() - def create_ptx(self): + def add_pins(self): + """ Adds pins for spice netlist """ + pin_list = ["A", "B", "Z", "vdd", "gnd"] + dir_list = ["INPUT", "INPUT", "OUTPUT", "INOUT", "INOUT"] + self.add_pin_list(pin_list, dir_list) + + def add_ptx(self): """ Create the PMOS and NMOS transistors. """ self.nmos = factory.create(module_type="ptx", width=self.nmos_width, @@ -104,7 +107,7 @@ class pnor2(pgate.pgate): self.top_bottom_space = max(0.5*self.m1_width + self.m1_space + extra_contact_space, drc("poly_extend_active"), self.poly_space) - def add_supply_rails(self): + def route_supply_rails(self): """ Add vdd/gnd rails to the top and bottom. """ self.add_layout_pin_rect_center(text="gnd", layer="metal1", @@ -116,7 +119,31 @@ class pnor2(pgate.pgate): offset=vector(0.5*self.width,self.height), width=self.width) - def add_ptx(self): + def create_ptx(self): + """ + Add PMOS and NMOS to the layout at the upper-most and lowest position + to provide maximum routing in channel + """ + + self.pmos1_inst=self.add_inst(name="pnor2_pmos1", + mod=self.pmos) + self.connect_inst(["vdd", "A", "net1", "vdd"]) + + self.pmos2_inst = self.add_inst(name="pnor2_pmos2", + mod=self.pmos) + self.connect_inst(["net1", "B", "Z", "vdd"]) + + + self.nmos1_inst=self.add_inst(name="pnor2_nmos1", + mod=self.nmos) + self.connect_inst(["Z", "A", "gnd", "gnd"]) + + self.nmos2_inst=self.add_inst(name="pnor2_nmos2", + mod=self.nmos) + self.connect_inst(["Z", "B", "gnd", "gnd"]) + + + def place_ptx(self): """ Add PMOS and NMOS to the layout at the upper-most and lowest position to provide maximum routing in channel @@ -124,29 +151,16 @@ class pnor2(pgate.pgate): pmos1_pos = vector(self.pmos.active_offset.x, self.height - self.pmos.active_height - self.top_bottom_space) - self.pmos1_inst=self.add_inst(name="pnor2_pmos1", - mod=self.pmos, - offset=pmos1_pos) - self.connect_inst(["vdd", "A", "net1", "vdd"]) + self.pmos1_inst.place(pmos1_pos) self.pmos2_pos = pmos1_pos + self.overlap_offset - self.pmos2_inst = self.add_inst(name="pnor2_pmos2", - mod=self.pmos, - offset=self.pmos2_pos) - self.connect_inst(["net1", "B", "Z", "vdd"]) - + self.pmos2_inst.place(self.pmos2_pos) nmos1_pos = vector(self.pmos.active_offset.x, self.top_bottom_space) - self.nmos1_inst=self.add_inst(name="pnor2_nmos1", - mod=self.nmos, - offset=nmos1_pos) - self.connect_inst(["Z", "A", "gnd", "gnd"]) - + self.nmos1_inst.place(nmos1_pos) + self.nmos2_pos = nmos1_pos + self.overlap_offset - self.nmos2_inst=self.add_inst(name="pnor2_nmos2", - mod=self.nmos, - offset=self.nmos2_pos) - self.connect_inst(["Z", "B", "gnd", "gnd"]) + self.nmos2_inst.place(self.nmos2_pos) # Output position will be in between the PMOS and NMOS self.output_pos = vector(0,0.5*(pmos1_pos.y+nmos1_pos.y+self.nmos.active_height)) From 275891084b744b8d8b34b40ab2b350945c48c236 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 7 Aug 2019 16:33:29 -0700 Subject: [PATCH 183/234] Add pand3 --- compiler/pgates/pand3.py | 138 ++++++++++++++++++++++++++++++++ compiler/tests/04_pand3_test.py | 38 +++++++++ 2 files changed, 176 insertions(+) create mode 100644 compiler/pgates/pand3.py create mode 100755 compiler/tests/04_pand3_test.py diff --git a/compiler/pgates/pand3.py b/compiler/pgates/pand3.py new file mode 100644 index 00000000..b221ad84 --- /dev/null +++ b/compiler/pgates/pand3.py @@ -0,0 +1,138 @@ +# 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 tech import drc +from math import log +from vector import vector +from globals import OPTS +import pgate +from sram_factory import factory + +class pand3(pgate.pgate): + """ + This is a simple buffer used for driving loads. + """ + def __init__(self, name, size=1, height=None): + debug.info(1, "Creating pand3 {}".format(name)) + self.add_comment("size: {}".format(size)) + + self.size = size + + # 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_modules(self): + # Shield the cap, but have at least a stage effort of 4 + self.nand = factory.create(module_type="pnand3",height=self.height) + self.add_mod(self.nand) + + self.inv = factory.create(module_type="pinv", size=self.size, height=self.height) + self.add_mod(self.inv) + + def create_layout(self): + self.width = self.nand.width + self.inv.width + self.place_insts() + self.add_wires() + self.add_layout_pins() + self.DRC_LVS() + + def add_pins(self): + self.add_pin("A", "INPUT") + self.add_pin("B", "INPUT") + self.add_pin("C", "INPUT") + self.add_pin("Z", "OUTPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + def create_insts(self): + self.nand_inst=self.add_inst(name="pand3_nand", + mod=self.nand) + self.connect_inst(["A", "B", "C", "zb_int", "vdd", "gnd"]) + + self.inv_inst=self.add_inst(name="pand3_inv", + mod=self.inv) + self.connect_inst(["zb_int", "Z", "vdd", "gnd"]) + + def place_insts(self): + # Add NAND to the right + self.nand_inst.place(offset=vector(0,0)) + + # Add INV to the right + self.inv_inst.place(offset=vector(self.nand_inst.rx(),0)) + + def add_wires(self): + # nand Z to inv A + z1_pin = self.nand_inst.get_pin("Z") + a2_pin = self.inv_inst.get_pin("A") + mid1_point = vector(0.5*(z1_pin.cx()+a2_pin.cx()), z1_pin.cy()) + mid2_point = vector(mid1_point, a2_pin.cy()) + self.add_path("metal1", [z1_pin.center(), mid1_point, mid2_point, a2_pin.center()]) + + + def add_layout_pins(self): + # Continous vdd rail along with label. + vdd_pin=self.inv_inst.get_pin("vdd") + self.add_layout_pin(text="vdd", + layer="metal1", + offset=vdd_pin.ll().scale(0,1), + width=self.width, + height=vdd_pin.height()) + + # Continous gnd rail along with label. + gnd_pin=self.inv_inst.get_pin("gnd") + self.add_layout_pin(text="gnd", + layer="metal1", + offset=gnd_pin.ll().scale(0,1), + width=self.width, + height=vdd_pin.height()) + + pin = self.inv_inst.get_pin("Z") + self.add_layout_pin_rect_center(text="Z", + layer=pin.layer, + offset=pin.center(), + width=pin.width(), + height=pin.height()) + + for pin_name in ["A","B", "C"]: + pin = self.nand_inst.get_pin(pin_name) + self.add_layout_pin_rect_center(text=pin_name, + layer=pin.layer, + offset=pin.center(), + width=pin.width(), + height=pin.height()) + + + + def analytical_delay(self, corner, slew, load=0.0): + """ Calculate the analytical delay of DFF-> INV -> INV """ + nand_delay = self.nand.analytical_delay(corner, slew=slew, load=self.inv.input_load()) + inv_delay = self.inv.analytical_delay(corner, slew=nand_delay.slew, load=load) + return nand_delay + inv_delay + + def get_stage_efforts(self, external_cout, inp_is_rise=False): + """Get the stage efforts of the A or B -> Z path""" + stage_effort_list = [] + stage1_cout = self.inv.get_cin() + stage1 = self.nand.get_stage_effort(stage1_cout, inp_is_rise) + stage_effort_list.append(stage1) + last_stage_is_rise = stage1.is_rise + + stage2 = self.inv.get_stage_effort(external_cout, last_stage_is_rise) + stage_effort_list.append(stage2) + + return stage_effort_list + + def get_cin(self): + """Return the relative input capacitance of a single input""" + return self.nand.get_cin() + diff --git a/compiler/tests/04_pand3_test.py b/compiler/tests/04_pand3_test.py new file mode 100755 index 00000000..4408f6e8 --- /dev/null +++ b/compiler/tests/04_pand3_test.py @@ -0,0 +1,38 @@ +#!/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 pand3_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + global verify + import verify + + import pand3 + + debug.info(2, "Testing pand3 gate 4x") + a = pand3.pand3(name="pand3x4", size=4) + 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 d36f14b40877b7435dc409d65f6733cb83ba7bde Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 7 Aug 2019 17:14:33 -0700 Subject: [PATCH 184/234] New control logic, netlist only working --- compiler/modules/bank.py | 74 +++++++---------------- compiler/modules/control_logic.py | 58 ++++++++++-------- compiler/modules/port_data.py | 59 +++++++----------- compiler/modules/replica_bitcell_array.py | 2 +- compiler/sram/sram_base.py | 6 +- 5 files changed, 82 insertions(+), 117 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 4fa95c44..6b7462de 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -82,7 +82,7 @@ class bank(design.design): for port in self.read_ports: for bit in range(self.word_size): self.add_pin("dout{0}_{1}".format(port,bit),"OUTPUT") - for port in self.read_ports: + for port in self.all_ports: self.add_pin(self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]),"OUTPUT") for port in self.write_ports: for bit in range(self.word_size): @@ -128,14 +128,13 @@ class bank(design.design): def route_rbl(self,port): """ Route the rbl_bl and rbl_wl """ - if self.port_data[port].has_rbl(): - bl_pin_name = self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]) - bl_pin = self.bitcell_array_inst.get_pin(bl_pin_name) - self.add_layout_pin(text="rbl_bl{0}".format(port), - layer=bl_pin.layer, - offset=bl_pin.ll(), - height=bl_pin.height(), - width=bl_pin.width()) + bl_pin_name = self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]) + bl_pin = self.bitcell_array_inst.get_pin(bl_pin_name) + self.add_layout_pin(text="rbl_bl{0}".format(port), + layer=bl_pin.layer, + offset=bl_pin.ll(), + height=bl_pin.height(), + width=bl_pin.width()) @@ -202,10 +201,7 @@ class bank(design.design): # LOWER RIGHT QUADRANT # Below the bitcell array - if self.port_data[port].has_rbl(): - self.port_data_offsets[port] = vector(self.main_bitcell_array_left - self.bitcell_array.cell.width,0) - else: - self.port_data_offsets[port] = vector(self.main_bitcell_array_left,0) + self.port_data_offsets[port] = vector(self.main_bitcell_array_left - self.bitcell_array.cell.width,0) # UPPER LEFT QUADRANT # To the left of the bitcell array @@ -364,36 +360,15 @@ class bank(design.design): self.add_mod(self.port_address) - # The number of replica lines depends on the port configuration - rbl_counts = [self.read_ports.count(p) for p in self.all_ports] - self.num_rbl = sum(rbl_counts) - - # The replica array indices always start at 0, so this will map them to - # the correct SRAM port - # (e.g. if port 0 is w, then port 1 will use RBL 0 in replica bitcell array - # because write ports don't use an RBL) - self.port_rbl_map = {} - index = 0 - for (i,num) in enumerate(rbl_counts): - if num>0: - self.port_rbl_map[i]=index - index += 1 - if len(rbl_counts)<2: - rbl_counts.append(0) - - - # Which bitcell port should be used in the RBL - # For now (since only 2 ports), if port 0 is not a read port, skip it in the RBLs - bitcell_ports=list(range(len(self.read_ports))) - if 0 not in self.read_ports: - bitcell_ports = [x+1 for x in bitcell_ports] + self.port_rbl_map = self.all_ports + self.num_rbl = len(self.all_ports) self.bitcell_array = factory.create(module_type="replica_bitcell_array", cols=self.num_cols, rows=self.num_rows, - left_rbl=rbl_counts[0], - right_rbl=rbl_counts[1], - bitcell_ports=bitcell_ports) + left_rbl=1, + right_rbl=1 if len(self.all_ports)>1 else 0, + bitcell_ports=self.all_ports) self.add_mod(self.bitcell_array) @@ -421,8 +396,7 @@ class bank(design.design): for wordline in self.wl_names: temp.append("{0}_{1}".format(wordline,row)) for port in self.all_ports: - if self.port_data[port].has_rbl(): - temp.append("wl_en{0}".format(port)) + temp.append("wl_en{0}".format(port)) temp.append("vdd") temp.append("gnd") self.connect_inst(temp) @@ -442,11 +416,10 @@ class bank(design.design): mod=self.port_data[port]) temp = [] - if self.port_data[port].has_rbl(): - 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_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) for col in range(self.num_cols): temp.append("{0}_{1}".format(self.bl_names[port],col)) temp.append("{0}_{1}".format(self.br_names[port],col)) @@ -710,11 +683,10 @@ class bank(design.design): inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name) # Connect the replica bitlines - if self.port_data[port].has_rbl(): - 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_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") diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index a5c5dc12..c2d86da8 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -125,10 +125,10 @@ class control_logic(design.design): self.add_mod(self.wl_en_driver) # w_en drives every write driver - self.wen_and2 = factory.create(module_type="pand2", + self.wen_and = factory.create(module_type="pand3", size=self.word_size+8, height=dff_height) - self.add_mod(self.wen_and2) + self.add_mod(self.wen_and) # s_en drives every sense amp self.sen_and2 = factory.create(module_type="pand2", @@ -141,17 +141,19 @@ class control_logic(design.design): size=1, height=dff_height) self.add_mod(self.inv) - + # p_en_bar drives every column in the bitcell array # but it is sized the same as the wl_en driver with # prepended 3 inverter stages to guarantee it is slower and odd polarity self.p_en_bar_driver = factory.create(module_type="pdriver", fanout=self.num_cols, - neg_polarity=True, height=dff_height) self.add_mod(self.p_en_bar_driver) - + + self.nand2 = factory.create(module_type="pnand2", + height=dff_height) + self.add_mod(self.nand2) # if (self.port_type == "rw") or (self.port_type == "r"): # from importlib import reload @@ -330,12 +332,9 @@ class control_logic(design.design): if self.port_type == "rw": self.input_list = ["csb", "web"] self.rbl_list = ["rbl_bl"] - elif self.port_type == "r": - self.input_list = ["csb"] - self.rbl_list = ["rbl_bl"] else: self.input_list = ["csb"] - self.rbl_list = [] + self.rbl_list = ["rbl_bl"] if self.port_type == "rw": self.dff_output_list = ["cs_bar", "cs", "we_bar", "we"] @@ -385,7 +384,7 @@ class control_logic(design.design): self.create_wen_row() if (self.port_type == "rw") or (self.port_type == "r"): self.create_sen_row() - self.create_delay() + self.create_delay() self.create_pen_row() @@ -422,9 +421,9 @@ class control_logic(design.design): if (self.port_type == "rw") or (self.port_type == "r"): self.place_sen_row(row) row += 1 - self.place_delay(row) - height = self.delay_inst.uy() - control_center_y = self.delay_inst.by() + self.place_delay(row) + height = self.delay_inst.uy() + control_center_y = self.delay_inst.by() # This offset is used for placement of the control logic in the SRAM level. self.control_logic_center = vector(self.ctrl_dff_inst.rx(), control_center_y) @@ -446,6 +445,7 @@ class control_logic(design.design): self.route_wen() if (self.port_type == "rw") or (self.port_type == "r"): self.route_sen() + self.route_delay() self.route_pen() self.route_clk_buf() self.route_gated_clk_bar() @@ -457,7 +457,7 @@ class control_logic(design.design): """ Create the replica bitline """ self.delay_inst=self.add_inst(name="delay_chain", mod=self.delay_chain) - self.connect_inst(["rbl_bl", "pre_s_en", "vdd", "gnd"]) + self.connect_inst(["rbl_bl", "rbl_bl_delay", "vdd", "gnd"]) def place_delay(self,row): """ Place the replica bitline """ @@ -468,6 +468,11 @@ class control_logic(design.design): offset = vector(self.delay_chain.width, y_off) self.delay_inst.place(offset, mirror="MY") + def route_delay(self): + + # Input from RBL goes to the delay line for futher delay + self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") + def create_clk_buf_row(self): """ Create the multistage and gated clock buffer """ @@ -604,10 +609,14 @@ class control_logic(design.design): self.connect_output(self.wl_en_inst, "Z", "wl_en") def create_pen_row(self): - # input: gated_clk_bar, output: p_en_bar - self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar", + self.p_en_bar_inst=self.add_inst(name="nand_p_en_bar", + mod=self.nand2) + self.connect_inst(["gated_clk_buf", "rbl_bl_delay", "p_en_bar_unbuf", "vdd", "gnd"]) + + self.p_en_bar_inst=self.add_inst(name="buf_p_en_bar", mod=self.p_en_bar_driver) - self.connect_inst(["gated_clk_buf", "p_en_bar", "vdd", "gnd"]) + self.connect_inst(["p_en_bar_unbuf", "p_en_bar", "vdd", "gnd"]) + def place_pen_row(self,row): @@ -633,7 +642,7 @@ class control_logic(design.design): # GATE FOR S_EN self.s_en_gate_inst = self.add_inst(name="buf_s_en_and", mod=self.sen_and2) - self.connect_inst(["pre_s_en", input_name, "s_en", "vdd", "gnd"]) + self.connect_inst(["rbl_bl_delay", input_name, "s_en", "vdd", "gnd"]) def place_sen_row(self,row): @@ -667,12 +676,13 @@ class control_logic(design.design): self.connect_output(self.s_en_gate_inst, "Z", "s_en") - # Input from RBL goes to the delay line for futher delay - self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") - - def create_wen_row(self): + + self.rbl_bl_delay_inv_inst = self.add_inst(name="rbl_bl_delay_inv", + mod=self.inv) + self.connect_inst(["rbl_bl_delay", "rbl_bl_delay_bar", "vdd", "gnd"]) + # input: we (or cs) output: w_en if self.port_type == "rw": input_name = "we" @@ -682,8 +692,8 @@ class control_logic(design.design): # GATE THE W_EN self.w_en_gate_inst = self.add_inst(name="w_en_and", - mod=self.wen_and2) - self.connect_inst([input_name, "gated_clk_bar", "w_en", "vdd", "gnd"]) + mod=self.wen_and) + self.connect_inst([input_name, "rbl_bl_delay_bar", "gated_clk_bar", "w_en", "vdd", "gnd"]) def place_wen_row(self,row): diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 3e4caf57..b4027be9 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -82,9 +82,8 @@ class port_data(design.design): def add_pins(self): """ Adding pins for port address module""" - if self.has_rbl(): - self.add_pin("rbl_bl","INOUT") - self.add_pin("rbl_br","INOUT") + self.add_pin("rbl_bl","INOUT") + self.add_pin("rbl_br","INOUT") for bit in range(self.num_cols): self.add_pin("{0}_{1}".format(self.bl_names[self.port], bit),"INOUT") self.add_pin("{0}_{1}".format(self.br_names[self.port], bit),"INOUT") @@ -150,30 +149,18 @@ class port_data(design.design): def add_modules(self): - if self.port in self.read_ports: - # Extra column +1 is for RBL - # Precharge will be shifted left if needed - self.precharge_array = factory.create(module_type="precharge_array", - columns=self.num_cols + 1, - bitcell_bl=self.bl_names[self.port], - bitcell_br=self.br_names[self.port]) - self.add_mod(self.precharge_array) - - self.sense_amp_array = factory.create(module_type="sense_amp_array", - word_size=self.word_size, - words_per_row=self.words_per_row) - self.add_mod(self.sense_amp_array) - else: - # Precharge is needed when we have a column mux or for byte writes - # to prevent corruption of half-selected cells, so just always add it - # This is a little power inefficient for write ports without a column mux, - # but it is simpler. - self.precharge_array = factory.create(module_type="precharge_array", - columns=self.num_cols, - bitcell_bl=self.bl_names[self.port], - bitcell_br=self.br_names[self.port]) - self.add_mod(self.precharge_array) - self.sense_amp_array = None + # Extra column +1 is for RBL + # Precharge will be shifted left if needed + self.precharge_array = factory.create(module_type="precharge_array", + columns=self.num_cols + 1, + bitcell_bl=self.bl_names[self.port], + bitcell_br=self.br_names[self.port]) + self.add_mod(self.precharge_array) + + self.sense_amp_array = factory.create(module_type="sense_amp_array", + word_size=self.word_size, + words_per_row=self.words_per_row) + self.add_mod(self.sense_amp_array) if self.col_addr_size > 0: @@ -238,14 +225,14 @@ class port_data(design.design): temp = [] # Use left BLs for RBL - if self.has_rbl() and self.port==0: + if self.port==0: temp.append("rbl_bl") temp.append("rbl_br") for bit in range(self.num_cols): temp.append(self.bl_names[self.port]+"_{0}".format(bit)) temp.append(self.br_names[self.port]+"_{0}".format(bit)) # Use right BLs for RBL - if self.has_rbl() and self.port==1: + if self.port==1: temp.append("rbl_bl") temp.append("rbl_br") temp.extend(["p_en_bar", "vdd"]) @@ -368,7 +355,7 @@ class port_data(design.design): vertical_port_order.append(self.write_driver_array_inst) # Add one column for the the RBL - if self.has_rbl() and self.port==0: + if self.port==0: x_offset = self.bitcell.width else: x_offset = 0 @@ -438,7 +425,7 @@ class port_data(design.design): inst1 = self.column_mux_array_inst inst2 = self.precharge_array_inst - if self.has_rbl() and self.port==0: + if self.port==0: self.connect_bitlines(inst1, inst2, self.num_cols, inst2_start_bit=1) else: self.connect_bitlines(inst1, inst2, self.num_cols) @@ -460,7 +447,7 @@ class port_data(design.design): inst1 = self.precharge_array_inst inst1_bl_name = "bl_{}" inst1_br_name = "br_{}" - if self.has_rbl() and self.port==0: + if self.port==0: start_bit=1 else: start_bit=0 @@ -484,7 +471,7 @@ class port_data(design.design): inst1 = self.precharge_array_inst inst1_bl_name = "bl_{}" inst1_br_name = "br_{}" - if self.has_rbl() and self.port==0: + if self.port==0: start_bit=1 else: start_bit=0 @@ -507,11 +494,11 @@ class port_data(design.design): """ Add the bitline pins for the given port """ # Connect one bitline to the RBL and offset the indices for the other BLs - if self.has_rbl() and self.port==0: + if self.port==0: self.copy_layout_pin(self.precharge_array_inst, "bl_0", "rbl_bl") self.copy_layout_pin(self.precharge_array_inst, "br_0", "rbl_br") bit_offset=1 - elif self.has_rbl() and self.port==1: + elif self.port==1: self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(self.num_cols), "rbl_bl") self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(self.num_cols), "rbl_br") bit_offset=0 @@ -603,5 +590,3 @@ class port_data(design.design): if self.precharge_array_inst: self.graph_inst_exclude.add(self.precharge_array_inst) - def has_rbl(self): - return self.port in self.read_ports diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 6f4e96c5..39d9c6e7 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -35,7 +35,7 @@ class replica_bitcell_array(design.design): self.right_rbl = right_rbl self.bitcell_ports = bitcell_ports - debug.check(left_rbl+right_rbl==len(self.read_ports),"Invalid number of RBLs for port configuration.") + 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 diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index f34d058e..7cc60fab 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -339,7 +339,7 @@ class sram_base(design, verilog, lef): for port in self.read_ports: for bit in range(self.word_size): temp.append("DOUT{0}[{1}]".format(port,bit)) - for port in self.read_ports: + for port in self.all_ports: temp.append("rbl_bl{0}".format(port)) for port in self.write_ports: for bit in range(self.word_size): @@ -499,9 +499,7 @@ class sram_base(design, verilog, lef): if port in self.readwrite_ports: temp.append("web{}".format(port)) temp.append("clk{}".format(port)) - - if port in self.read_ports: - temp.append("rbl_bl{}".format(port)) + temp.append("rbl_bl{}".format(port)) # Ouputs if port in self.read_ports: From fc1cba099ca5ab1b1ac5966383ee06b37f4dc8fb Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Thu, 8 Aug 2019 01:57:04 -0700 Subject: [PATCH 185/234] Made all cin function relate to farads and all input_load relate to relative units. --- compiler/base/graph_util.py | 9 +++++---- compiler/base/hierarchy_spice.py | 20 ++++++++++++++++++++ compiler/bitcells/bitcell.py | 16 +++------------- compiler/bitcells/bitcell_1rw_1r.py | 10 +++++----- compiler/bitcells/bitcell_1w_1r.py | 10 +++++----- compiler/bitcells/pbitcell.py | 8 +++++--- compiler/bitcells/replica_bitcell.py | 21 ++++++++++++++------- compiler/bitcells/replica_bitcell_1rw_1r.py | 19 +++++++++++++------ compiler/bitcells/replica_bitcell_1w_1r.py | 15 +++++++++++---- compiler/bitcells/replica_pbitcell.py | 6 +----- compiler/characterizer/logical_effort.py | 13 ++++++++----- compiler/modules/sense_amp.py | 5 ++++- compiler/modules/tri_gate.py | 4 ++-- compiler/pgates/pinv.py | 7 +------ compiler/pgates/pnand2.py | 18 ++---------------- compiler/pgates/pnand3.py | 4 ++-- compiler/pgates/ptristate_inv.py | 2 +- 17 files changed, 102 insertions(+), 85 deletions(-) diff --git a/compiler/base/graph_util.py b/compiler/base/graph_util.py index 8a6588af..5d1ee692 100644 --- a/compiler/base/graph_util.py +++ b/compiler/base/graph_util.py @@ -104,7 +104,8 @@ class timing_graph(): if len(path) == 0: return [] - delays = [] + delays = [] + cur_slew = slew for i in range(len(path)-1): path_edge_mod = self.edge_mods[(path[i], path[i+1])] @@ -112,14 +113,14 @@ class timing_graph(): # On the output of the current stage, get COUT from all other mods connected cout = 0 for node in self.graph[path[i+1]]: - output_edge_mode = self.edge_mods[(path[i+1], node)] - cout+=output_edge_mode.input_load() + output_edge_mod = self.edge_mods[(path[i+1], node)] + cout+=output_edge_mod.get_cin() # If at the last output, include the final output load if i == len(path)-2: cout+=load delays.append(path_edge_mod.analytical_delay(corner, slew, cout)) - slew = delays[-1].slew + cur_slew = delays[-1].slew return delays diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index c8ffb151..5166ac6b 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -304,6 +304,8 @@ class spice(): def analytical_delay(self, corner, slew, load=0.0): """Inform users undefined delay module while building new modules""" + + # FIXME: Slew is not used in the model right now. Can be added heuristically as linear factor relative_cap = logical_effort.convert_farad_to_relative_c(load) stage_effort = self.get_stage_effort(relative_cap) @@ -326,6 +328,24 @@ class spice(): self.name)) return None + def get_cin(self): + """Returns input load in Femto-Farads. All values generated using + relative capacitance function then converted based on tech file parameter.""" + + # Override this function within a module if a more accurate input capacitance is needed. + # Input/outputs with differing capacitances is not implemented. + relative_cap = self.input_load() + return logical_effort.convert_relative_c_to_farad(relative_cap) + + def input_load(self): + """Inform users undefined relative capacitance functions used for analytical delays.""" + debug.warning("Design Class {0} input capacitance function needs to be defined" + .format(self.__class__.__name__)) + debug.warning("Class {0} name {1}" + .format(self.__class__.__name__, + self.name)) + return 0 + def cal_delay_with_rc(self, corner, r, c ,slew, swing = 0.5): """ Calculate the delay of a mosfet by diff --git a/compiler/bitcells/bitcell.py b/compiler/bitcells/bitcell.py index 360e08de..cad069a5 100644 --- a/compiler/bitcells/bitcell.py +++ b/compiler/bitcells/bitcell.py @@ -42,16 +42,6 @@ class bitcell(design.design): cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file. return logical_effort.logical_effort('bitline', size, cin, load, parasitic_delay, False) - def input_load(self): - """Return the relative capacitance of the access transistor gates""" - #This is a handmade cell so the value must be entered in the tech.py file or estimated. - #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. - - #FIXME: The graph algorithm will apply this capacitance to the bitline load as they cannot be - # distinguished currently - access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] - return 2*access_tx_cin - def get_all_wl_names(self): """ Creates a list of all wordline pin names """ row_pins = ["wl"] @@ -104,10 +94,10 @@ class bitcell(design.design): debug.info(1,"Storage nodes={} not found in spice file.".format(self.storage_nets)) return None - def get_wl_cin(self): + def input_load(self): """Return the relative capacitance of the access transistor gates""" - #This is a handmade cell so the value must be entered in the tech.py file or estimated. - #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. + + # FIXME: This applies to bitline capacitances as well. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin diff --git a/compiler/bitcells/bitcell_1rw_1r.py b/compiler/bitcells/bitcell_1rw_1r.py index 42bd3855..0d536b38 100644 --- a/compiler/bitcells/bitcell_1rw_1r.py +++ b/compiler/bitcells/bitcell_1rw_1r.py @@ -36,7 +36,7 @@ class bitcell_1rw_1r(design.design): self.add_pin_types(self.type_list) self.nets_match = self.do_nets_exist(self.storage_nets) - def analytical_delay(self, corner, slew, load=0, swing = 0.5): + def get_stage_effort(self, load): parasitic_delay = 1 size = 0.5 #This accounts for bitline being drained thought the access TX and internal node cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file. @@ -118,11 +118,11 @@ class bitcell_1rw_1r(design.design): total_power = self.return_power(dynamic, leakage) return total_power - def get_wl_cin(self): + def input_load(self): """Return the relative capacitance of the access transistor gates""" - #This is a handmade cell so the value must be entered in the tech.py file or estimated. - #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. - #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. + + # FIXME: This applies to bitline capacitances as well. + # FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin diff --git a/compiler/bitcells/bitcell_1w_1r.py b/compiler/bitcells/bitcell_1w_1r.py index b8f0e49b..7e8c9e75 100644 --- a/compiler/bitcells/bitcell_1w_1r.py +++ b/compiler/bitcells/bitcell_1w_1r.py @@ -36,7 +36,7 @@ class bitcell_1w_1r(design.design): self.add_pin_types(self.type_list) self.nets_match = self.do_nets_exist(self.storage_nets) - def analytical_delay(self, corner, slew, load=0, swing = 0.5): + def get_stage_effort(self, load): parasitic_delay = 1 size = 0.5 #This accounts for bitline being drained thought the access TX and internal node cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file. @@ -116,11 +116,11 @@ class bitcell_1w_1r(design.design): total_power = self.return_power(dynamic, leakage) return total_power - def get_wl_cin(self): + def input_load(self): """Return the relative capacitance of the access transistor gates""" - #This is a handmade cell so the value must be entered in the tech.py file or estimated. - #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. - #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. + + # FIXME: This applies to bitline capacitances as well. + # FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin diff --git a/compiler/bitcells/pbitcell.py b/compiler/bitcells/pbitcell.py index b09e81c2..919a0316 100644 --- a/compiler/bitcells/pbitcell.py +++ b/compiler/bitcells/pbitcell.py @@ -934,7 +934,7 @@ class pbitcell(design.design): return "wl{}".format(port) - def analytical_delay(self, corner, slew, load=0, swing = 0.5): + def get_stage_effort(self, load): parasitic_delay = 1 size = 0.5 #This accounts for bitline being drained thought the access TX and internal node cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file. @@ -954,9 +954,11 @@ class pbitcell(design.design): total_power = self.return_power(dynamic, leakage) return total_power - def get_wl_cin(self): + def input_load(self): """Return the relative capacitance of the access transistor gates""" - #pbitcell uses the different sizing for the port access tx's. Not accounted for in this model. + + # FIXME: This applies to bitline capacitances as well. + # pbitcell uses the different sizing for the port access tx's. Not accounted for in this model. access_tx_cin = self.readwrite_nmos.get_cin() return 2*access_tx_cin diff --git a/compiler/bitcells/replica_bitcell.py b/compiler/bitcells/replica_bitcell.py index f8ded969..2f804bf0 100644 --- a/compiler/bitcells/replica_bitcell.py +++ b/compiler/bitcells/replica_bitcell.py @@ -31,6 +31,20 @@ class replica_bitcell(design.design): self.height = replica_bitcell.height self.pin_map = replica_bitcell.pin_map self.add_pin_types(self.type_list) + + def get_stage_effort(self, load): + parasitic_delay = 1 + size = 0.5 #This accounts for bitline being drained thought the access TX and internal node + cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file. + read_port_load = 0.5 #min size NMOS gate load + return logical_effort.logical_effort('bitline', size, cin, load+read_port_load, parasitic_delay, False) + + def input_load(self): + """Return the relative capacitance of the access transistor gates""" + + # FIXME: This applies to bitline capacitances as well. + access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] + return 2*access_tx_cin def analytical_power(self, corner, load): """Bitcell power in nW. Only characterizes leakage.""" @@ -40,13 +54,6 @@ class replica_bitcell(design.design): total_power = self.return_power(dynamic, leakage) return total_power - def get_wl_cin(self): - """Return the relative capacitance of the access transistor gates""" - #This is a handmade cell so the value must be entered in the tech.py file or estimated. - #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. - access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] - return 2*access_tx_cin - def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" self.add_graph_edges(graph, port_nets) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1rw_1r.py b/compiler/bitcells/replica_bitcell_1rw_1r.py index 9737669d..0f56319e 100644 --- a/compiler/bitcells/replica_bitcell_1rw_1r.py +++ b/compiler/bitcells/replica_bitcell_1rw_1r.py @@ -32,11 +32,18 @@ class replica_bitcell_1rw_1r(design.design): self.pin_map = replica_bitcell_1rw_1r.pin_map self.add_pin_types(self.type_list) - def get_wl_cin(self): + def get_stage_effort(self, load): + parasitic_delay = 1 + size = 0.5 #This accounts for bitline being drained thought the access TX and internal node + cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file. + read_port_load = 0.5 #min size NMOS gate load + return logical_effort.logical_effort('bitline', size, cin, load+read_port_load, parasitic_delay, False) + + def input_load(self): """Return the relative capacitance of the access transistor gates""" - #This is a handmade cell so the value must be entered in the tech.py file or estimated. - #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. - #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. + + # FIXME: This applies to bitline capacitances as well. + # FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin @@ -49,5 +56,5 @@ class replica_bitcell_1rw_1r(design.design): graph.add_edge(pin_dict["wl0"], pin_dict["bl0"], self) graph.add_edge(pin_dict["wl0"], pin_dict["br0"], self) # Port 1 edges - graph.add_edge(pin_dict["wl1"], pin_dict["bl1"]) - graph.add_edge(pin_dict["wl1"], pin_dict["br1"]) \ No newline at end of file + graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self) + graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self) \ No newline at end of file diff --git a/compiler/bitcells/replica_bitcell_1w_1r.py b/compiler/bitcells/replica_bitcell_1w_1r.py index fad5032d..b903e0ad 100644 --- a/compiler/bitcells/replica_bitcell_1w_1r.py +++ b/compiler/bitcells/replica_bitcell_1w_1r.py @@ -32,11 +32,18 @@ class replica_bitcell_1w_1r(design.design): self.pin_map = replica_bitcell_1w_1r.pin_map self.add_pin_types(self.type_list) - def get_wl_cin(self): + def get_stage_effort(self, load): + parasitic_delay = 1 + size = 0.5 #This accounts for bitline being drained thought the access TX and internal node + cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file. + read_port_load = 0.5 #min size NMOS gate load + return logical_effort.logical_effort('bitline', size, cin, load+read_port_load, parasitic_delay, False) + + def input_load(self): """Return the relative capacitance of the access transistor gates""" - #This is a handmade cell so the value must be entered in the tech.py file or estimated. - #Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width. - #FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. + + # FIXME: This applies to bitline capacitances as well. + # FIXME: sizing is not accurate with the handmade cell. Change once cell widths are fixed. access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"] return 2*access_tx_cin diff --git a/compiler/bitcells/replica_pbitcell.py b/compiler/bitcells/replica_pbitcell.py index 8453411f..4fcfb4c5 100644 --- a/compiler/bitcells/replica_pbitcell.py +++ b/compiler/bitcells/replica_pbitcell.py @@ -84,8 +84,4 @@ class replica_pbitcell(design.design): self.copy_layout_pin(self.prbc_inst, "wl{}".format(port)) self.copy_layout_pin(self.prbc_inst, "vdd") self.copy_layout_pin(self.prbc_inst, "gnd") - - def get_wl_cin(self): - """Return the relative capacitance of the access transistor gates""" - #This module is made using a pbitcell. Get the cin from that module - return self.prbc.get_wl_cin() + \ No newline at end of file diff --git a/compiler/characterizer/logical_effort.py b/compiler/characterizer/logical_effort.py index 024cd4f1..42ac8861 100644 --- a/compiler/characterizer/logical_effort.py +++ b/compiler/characterizer/logical_effort.py @@ -23,23 +23,23 @@ class logical_effort(): self.cin = cin self.cout = cout self.logical_effort = (self.cin/size)/logical_effort.min_inv_cin - self.eletrical_effort = self.cout/self.cin + self.electrical_effort = self.cout/self.cin self.parasitic_scale = parasitic self.is_rise = out_is_rise def __str__(self): return "Name={}, g={}, h={}, p={}*pinv, rise_delay={}".format(self.name, self.logical_effort, - self.eletrical_effort, + self.electrical_effort, self.parasitic_scale, self.is_rise ) def get_stage_effort(self): - return self.logical_effort*self.eletrical_effort + return self.logical_effort*self.electrical_effort def get_parasitic_delay(self): - return logical_effort.pinv * self.parasitic_scale + return logical_effort.pinv*self.parasitic_scale def get_stage_delay(self): return self.get_stage_effort()+self.get_parasitic_delay() @@ -78,4 +78,7 @@ def calculate_relative_rise_fall_delays(stage_effort_list): def convert_farad_to_relative_c(c_farad): """Converts capacitance in Femto-Farads to relative capacitance.""" return c_farad*parameter['cap_relative_per_ff'] - \ No newline at end of file + +def convert_relative_c_to_farad(c_relative): + """Converts capacitance in logical effort relative units to Femto-Farads.""" + return c_relative/parameter['cap_relative_per_ff'] \ No newline at end of file diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index a053aff8..8c92440c 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -33,7 +33,10 @@ class sense_amp(design.design): self.pin_map = sense_amp.pin_map self.add_pin_types(self.type_list) - def input_load(self): + def get_cin(self): + + # FIXME: This input load will be applied to both the s_en timing and bitline timing. + #Input load for the bitlines which are connected to the source/drain of a TX. Not the selects. from tech import spice, parameter # Default is 8x. Per Samira and Hodges-Jackson book: diff --git a/compiler/modules/tri_gate.py b/compiler/modules/tri_gate.py index fe59e7b9..998562b1 100644 --- a/compiler/modules/tri_gate.py +++ b/compiler/modules/tri_gate.py @@ -12,7 +12,7 @@ from tech import GDS,layer class tri_gate(design.design): """ - This module implements the tri gate cell used in the design for + This module implements the tri gate cell used in the design forS bit-line isolation. It is a hand-made cell, so the layout and netlist should be available in the technology library. """ @@ -42,7 +42,7 @@ class tri_gate(design.design): total_power = self.return_power() return total_power - def input_load(self): + def get_cin(self): return 9*spice["min_tx_gate_c"] def build_graph(self, graph, inst_name, port_nets): diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index d841b318..0844c762 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -272,11 +272,6 @@ class pinv(pgate.pgate): transition_prob = spice["inv_transition_prob"] return transition_prob*(c_load + c_para) - def get_cin(self): - """Return the capacitance of the gate connection in generic capacitive - units relative to the minimum width of a transistor""" - return self.nmos_size + self.pmos_size - def input_load(self): """Return the capacitance of the gate connection in generic capacitive units relative to the minimum width of a transistor""" @@ -289,7 +284,7 @@ class pinv(pgate.pgate): parasitic_delay = 1 return logical_effort.logical_effort(self.name, self.size, - self.get_cin(), + self.input_load(), cout, parasitic_delay, not inp_is_rise) diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 2275a336..21ca4184 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -37,10 +37,7 @@ class pnand2(pgate.pgate): # Creates the netlist and layout pgate.pgate.__init__(self, name, height) - - #For characterization purposes only - #self.exclude_nmos_from_graph() - + def create_netlist(self): self.add_pins() self.add_ptx() @@ -250,10 +247,6 @@ class pnand2(pgate.pgate): transition_prob = spice["nand2_transition_prob"] return transition_prob*(c_load + c_para) - def get_cin(self): - """Return the relative input capacitance of a single input""" - return self.nmos_size+self.pmos_size - def input_load(self): """Return the relative input capacitance of a single input""" return self.nmos_size+self.pmos_size @@ -263,14 +256,7 @@ class pnand2(pgate.pgate): Optional is_rise refers to the input direction rise/fall. Input inverted by this stage. """ parasitic_delay = 2 - return logical_effort.logical_effort(self.name, self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise) - - def exclude_nmos_from_graph(self): - """Exclude the nmos TXs from the graph to reduce complexity""" - #The pull-down network has an internal net which causes 2 different in->out paths - #Removing them simplifies generic path searching. - self.graph_inst_exclude.add(self.nmos1_inst) - self.graph_inst_exclude.add(self.nmos2_inst) + return logical_effort.logical_effort(self.name, self.size, self.input_load(), cout, parasitic_delay, not inp_is_rise) def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index eee6ca9a..89628267 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -260,7 +260,7 @@ class pnand3(pgate.pgate): transition_prob = spice["nand3_transition_prob"] return transition_prob*(c_load + c_para) - def get_cin(self): + def input_load(self): """Return the relative input capacitance of a single input""" return self.nmos_size+self.pmos_size @@ -269,7 +269,7 @@ class pnand3(pgate.pgate): Optional is_rise refers to the input direction rise/fall. Input inverted by this stage. """ parasitic_delay = 3 - return logical_effort.logical_effort(self.name, self.size, self.get_cin(), cout, parasitic_delay, not inp_is_rise) + return logical_effort.logical_effort(self.name, self.size, self.input_load(), cout, parasitic_delay, not inp_is_rise) def build_graph(self, graph, inst_name, port_nets): """Adds edges based on inputs/outputs. Overrides base class function.""" diff --git a/compiler/pgates/ptristate_inv.py b/compiler/pgates/ptristate_inv.py index 3176915a..0564bf86 100644 --- a/compiler/pgates/ptristate_inv.py +++ b/compiler/pgates/ptristate_inv.py @@ -216,5 +216,5 @@ class ptristate_inv(pgate.pgate): total_power = self.return_power() return total_power - def input_load(self): + def get_cin(self): return 9*spice["min_tx_gate_c"] From 3c44ce2df65bd8be4719af18550d968debce6704 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Thu, 8 Aug 2019 02:33:51 -0700 Subject: [PATCH 186/234] Replaced analytical characterization with graph implementation. Removed most analytical delay functions used by old chacterizer. --- compiler/characterizer/delay.py | 54 ++++++++++--------- compiler/modules/bank.py | 35 +----------- compiler/modules/bitcell_array.py | 12 +---- compiler/modules/replica_bitcell_array.py | 12 +---- compiler/modules/sense_amp_array.py | 5 +- .../modules/single_level_column_mux_array.py | 9 ---- compiler/sram/sram_base.py | 26 +-------- 7 files changed, 33 insertions(+), 120 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 90e1561e..81b31ef8 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -1277,6 +1277,7 @@ class delay(simulation): def sum_delays(self, delays): """Adds the delays (delay_data objects) so the correct slew is maintained""" + delay = delays[0] for i in range(1, len(delays)): delay+=delays[i] @@ -1303,40 +1304,41 @@ class delay(simulation): bl_name,br_name = self.get_bl_name(self.graph.all_paths, port) bl_path = [path for path in self.graph.all_paths if bl_name in path][0] + # Set delay/power for slews and loads + port_data = self.get_empty_measure_data_dict() + power = self.analytical_power(slews, loads) debug.info(1,'Slew, Load, Delay(ns), Slew(ns)') + max_delay = 0.0 for slew in slews: for load in loads: + # Calculate delay based on slew and load path_delays = self.graph.get_timing(bl_path, self.corner, slew, load) total_delay = self.sum_delays(path_delays) + max_delay = max(max_delay, total_delay.delay) debug.info(1,'{}, {}, {}, {}'.format(slew,load,total_delay.delay/1e3, total_delay.slew/1e3)) - debug.error('Not finished with graph delay characterization.', 1) - # power = self.analytical_power(slews, loads) - # port_data = self.get_empty_measure_data_dict() - # relative_loads = [logical_effort.convert_farad_to_relative_c(c_farad) for c_farad in loads] - # for slew in slews: - # for load in relative_loads: - # self.set_load_slew(load,slew) - # bank_delay = self.sram.analytical_delay(self.corner, self.slew,self.load) - # for port in self.all_ports: - # for mname in self.delay_meas_names+self.power_meas_names: - # if "power" in mname: - # port_data[port][mname].append(power.dynamic) - # elif "delay" in mname: - # port_data[port][mname].append(bank_delay[port].delay/1e3) - # elif "slew" in mname: - # port_data[port][mname].append(bank_delay[port].slew/1e3) - # else: - # debug.error("Measurement name not recognized: {}".format(mname),1) - # period_margin = 0.1 - # risefall_delay = bank_delay[self.read_ports[0]].delay/1e3 - # sram_data = { "min_period":risefall_delay*2*period_margin, - # "leakage_power": power.leakage} - # debug.info(2,"SRAM Data:\n{}".format(sram_data)) - # debug.info(2,"Port Data:\n{}".format(port_data)) - return (sram_data,port_data) + # Delay is only calculated on a single port and replicated for now. + for port in self.all_ports: + for mname in self.delay_meas_names+self.power_meas_names: + if "power" in mname: + port_data[port][mname].append(power.dynamic) + elif "delay" in mname and port in self.read_ports: + port_data[port][mname].append(total_delay.delay/1e3) + elif "slew" in mname and port in self.read_ports: + port_data[port][mname].append(total_delay.slew/1e3) + else: + debug.error("Measurement name not recognized: {}".format(mname),1) - + # Estimate the period as double the delay with margin + period_margin = 0.1 + sram_data = { "min_period":(max_delay/1e3)*2*period_margin, + "leakage_power": power.leakage} + + debug.info(2,"SRAM Data:\n{}".format(sram_data)) + debug.info(2,"Port Data:\n{}".format(port_data)) + + return (sram_data,port_data) + def analytical_power(self, slews, loads): """Get the dynamic and leakage power from the SRAM""" diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 613a3381..7774e15f 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -976,40 +976,7 @@ class bank(design.design): self.add_wire(("metal1","via1","metal2"),[pin_pos, mid_pos, control_pos]) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=control_pos) - - def analytical_delay(self, corner, slew, load, port): - """ return analytical delay of the bank. This will track the clock to output path""" - #FIXME: This delay is determined in the control logic. Should be moved here. - # word_driver_delay = self.wordline_driver.analytical_delay(corner, - # slew, - # self.bitcell_array.input_load()) - - #FIXME: Array delay is the same for every port. - word_driver_slew = 0 - if self.words_per_row > 1: - bitline_ext_load = self.port_data[port].column_mux_array.get_drain_cin() - else: - bitline_ext_load = self.port_data[port].sense_amp_array.get_drain_cin() - - bitcell_array_delay = self.bitcell_array.analytical_delay(corner, word_driver_slew, bitline_ext_load) - - bitcell_array_slew = 0 - #This also essentially creates the same delay for each port. Good structure, no substance - if self.words_per_row > 1: - sa_load = self.port_data[port].sense_amp_array.get_drain_cin() - column_mux_delay = self.port_data[port].column_mux_array.analytical_delay(corner, - bitcell_array_slew, - sa_load) - else: - column_mux_delay = [] - - column_mux_slew = 0 - sense_amp_delay = self.port_data[port].sense_amp_array.analytical_delay(corner, - column_mux_slew, - load) - # output load of bitcell_array is set to be only small part of bl for sense amp. - return bitcell_array_delay + column_mux_delay + sense_amp_delay - + 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. Delay model relies on this assumption diff --git a/compiler/modules/bitcell_array.py b/compiler/modules/bitcell_array.py index 90405d75..bf4932a3 100644 --- a/compiler/modules/bitcell_array.py +++ b/compiler/modules/bitcell_array.py @@ -148,17 +148,7 @@ class bitcell_array(design.design): for pin_name in ["vdd", "gnd"]: for pin in inst.get_pins(pin_name): self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) - - def analytical_delay(self, corner, slew, load): - """Returns relative delay of the bitline in the bitcell array""" - from tech import parameter - #The load being driven/drained is mostly the bitline but could include the sense amp or the column mux. - #The load from the bitlines is due to the drain capacitances from all the other bitlines and wire parasitics. - drain_load = logical_effort.convert_farad_to_relative_c(parameter['bitcell_drain_cap']) - wire_unit_load = .05 * drain_load #Wires add 5% to this. - bitline_load = (drain_load+wire_unit_load)*self.row_size - return [self.cell.analytical_delay(corner, slew, load+bitline_load)] - + def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" from tech import drc, parameter diff --git a/compiler/modules/replica_bitcell_array.py b/compiler/modules/replica_bitcell_array.py index 89a8ff04..d6d7d19e 100644 --- a/compiler/modules/replica_bitcell_array.py +++ b/compiler/modules/replica_bitcell_array.py @@ -373,17 +373,7 @@ class replica_bitcell_array(design.design): def get_rbl_br_name(self, port): """ Return the BR for the given RBL port """ return self.rbl_br_names[port] - - def analytical_delay(self, corner, slew, load): - """Returns relative delay of the bitline in the bitcell array""" - from tech import parameter - #The load being driven/drained is mostly the bitline but could include the sense amp or the column mux. - #The load from the bitlines is due to the drain capacitances from all the other bitlines and wire parasitics. - drain_load = logical_effort.convert_farad_to_relative_c(parameter['bitcell_drain_cap']) - wire_unit_load = 0.05 * drain_load #Wires add 5% to this. - bitline_load = (drain_load+wire_unit_load)*self.row_size - return [self.cell.analytical_delay(corner, slew, load+bitline_load)] - + def analytical_power(self, corner, load): """Power of Bitcell array and bitline in nW.""" from tech import drc, parameter diff --git a/compiler/modules/sense_amp_array.py b/compiler/modules/sense_amp_array.py index 40c3adeb..598886c0 100644 --- a/compiler/modules/sense_amp_array.py +++ b/compiler/modules/sense_amp_array.py @@ -144,10 +144,7 @@ class sense_amp_array(design.design): def input_load(self): return self.amp.input_load() - - def analytical_delay(self, corner, slew, load): - return [self.amp.analytical_delay(corner, slew=slew, load=load)] - + def get_en_cin(self): """Get the relative capacitance of all the sense amp enable connections in the array""" sense_amp_en_cin = self.amp.get_en_cin() diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index e270f2f6..7e3beaad 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -210,15 +210,6 @@ class single_level_column_mux_array(design.design): self.add_via_center(layers=("metal1", "via1", "metal2"), offset=br_out_offset) - - def analytical_delay(self, corner, slew, load): - from tech import parameter - """Returns relative delay that the column mux adds""" - #Single level column mux will add parasitic loads from other mux pass transistors and the sense amp. - drain_load = logical_effort.convert_farad_to_relative_c(parameter['bitcell_drain_cap']) - array_load = drain_load*self.words_per_row - return [self.mux.analytical_delay(corner, slew, load+array_load)] - def get_drain_cin(self): """Get the relative capacitance of the drain of the NMOS pass TX""" from tech import parameter diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 45befe16..da780317 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -566,31 +566,7 @@ class sram_base(design, verilog, lef): self.sp_write_file(sp, usedMODS) del usedMODS sp.close() - - - def analytical_delay(self, corner, slew,load): - """ Estimates the delay from clk -> DOUT - LH and HL are the same in analytical model. """ - delays = {} - for port in self.all_ports: - if port in self.readonly_ports: - control_logic = self.control_logic_r - elif port in self.readwrite_ports: - control_logic = self.control_logic_rw - else: - delays[port] = self.return_delay(0,0) #Write ports do not have a lib defined delay, marked as 0 - continue - clk_to_wlen_delays = control_logic.analytical_delay(corner, slew, load) - wlen_to_dout_delays = self.bank.analytical_delay(corner,slew,load,port) #port should probably be specified... - all_delays = clk_to_wlen_delays+wlen_to_dout_delays - total_delay = logical_effort.calculate_absolute_delay(all_delays) - total_delay = self.apply_corners_analytically(total_delay, corner) - last_slew = .1*all_delays[-1].get_absolute_delay() #slew approximated as 10% of delay - last_slew = self.apply_corners_analytically(last_slew, corner) - delays[port] = self.return_delay(delay=total_delay, slew=last_slew) - - return delays - + def get_wordline_stage_efforts(self, inp_is_rise=True): """Get the all the stage efforts for each stage in the path from clk_buf to a wordline""" stage_effort_list = [] From 59e5441aef7012ae995db197762991f08fc49d28 Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 8 Aug 2019 08:46:58 -0700 Subject: [PATCH 187/234] Added write mask to write driver array --- compiler/modules/port_data.py | 32 +++++++++++++----------- compiler/modules/write_driver_array.py | 25 +++++++++--------- compiler/modules/write_mask_and_array.py | 8 +++--- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 24fc4557..64229685 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -110,7 +110,7 @@ class port_data(design.design): def route_layout(self): - """ Create routing amoung the modules """ + """ Create routing among the modules """ self.route_data_lines() self.route_layout_pins() self.route_supplies() @@ -124,7 +124,8 @@ class port_data(design.design): """ Route the bitlines depending on the port type rw, w, or r. """ if self.port in self.readwrite_ports: - # write_driver -> sense_amp -> (column_mux) -> precharge -> bitcell_array + # (write_mask_and ->) write_driver -> sense_amp -> (column_mux ->) precharge -> bitcell_array + self.route_write_mask_and(self.port) self.route_write_driver_in(self.port) self.route_sense_amp_out(self.port) self.route_write_driver_to_sense_amp(self.port) @@ -136,7 +137,8 @@ class port_data(design.design): self.route_sense_amp_to_column_mux_or_precharge_array(self.port) self.route_column_mux_to_precharge_array(self.port) else: - # write_driver -> (column_mux ->) precharge -> bitcell_array + # (write_mask_and ->) write_driver -> (column_mux ->) precharge -> bitcell_array + self.route_write_mask_and(self.port) self.route_write_driver_in(self.port) self.route_write_driver_to_column_mux_or_precharge_array(self.port) self.route_column_mux_to_precharge_array(self.port) @@ -437,26 +439,26 @@ class port_data(design.design): self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name) - def route_write_mask_and_in(self, port): + def route_write_mask_and(self, port): """ Add pins for the write mask and array output """ - for bit in range(self.num_wmasks): - wmask_out_name = "wmask_out_{}".format(bit) - wdriver_sel_name = "wdriver_sel_{}".format(bit) - self.copy_layout_pin(self.write_mask_and_array_inst, wmask_out_name, wdriver_sel_name) + # for bit in range(self.num_wmasks): + # wmask_out_name = "wmask_out_{}".format(bit) + # wdriver_sel_name = "wdriver_sel_{}".format(bit) + # self.copy_layout_pin(self.write_mask_and_array_inst, wmask_out_name, wdriver_sel_name) for bit in range(self.num_wmasks): wmask_in_name = "wmask_in_{}".format(bit) bank_wmask_name = "bank_wmask_{}".format(bit) self.copy_layout_pin(self.write_mask_and_array_inst, wmask_in_name, bank_wmask_name) - # for bit in range(self.num_wmasks): - # wdriver_sel_pin = self.write_mask_and_array_inst.get_pin("wdriver_sel_{}".format(bit)) - # self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), - # layer=wdriver_sel_pin.layer, - # offset=wdriver_sel_pin.center(), - # height=wdriver_sel_pin.height(), - # width=wdriver_sel_pin.width()) + for bit in range(self.num_wmasks): + wdriver_sel_pin = self.write_mask_and_array_inst.get_pin("wmask_out_{}".format(bit)) + self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), + layer=wdriver_sel_pin.layer, + offset=wdriver_sel_pin.center(), + height=wdriver_sel_pin.height(), + width=wdriver_sel_pin.width()) def route_column_mux_to_precharge_array(self, port): diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 5a7fd3ac..c1d9a539 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -49,7 +49,6 @@ class write_driver_array(design.design): self.width = self.columns * self.bitcell.width else: self.width = self.columns * self.driver.width - self.height = self.driver.height self.place_write_array() @@ -63,9 +62,9 @@ class write_driver_array(design.design): for i in range(self.word_size): self.add_pin("bl_{0}".format(i), "OUTPUT") self.add_pin("br_{0}".format(i), "OUTPUT") - if self.write_size != None: + if self.write_size is not None: for i in range(self.num_wmasks): - self.add_pin("en_{}".format(i), "INPUT") + self.add_pin("en_{0}".format(i), "INPUT") else: self.add_pin("en", "INPUT") self.add_pin("vdd", "POWER") @@ -111,10 +110,10 @@ class write_driver_array(design.design): driver_spacing = self.bitcell.width else: driver_spacing = self.driver.width - for i in range(0,self.columns,self.words_per_row): - index = int(i/self.words_per_row) - base = vector(i * driver_spacing,0) + index = int(i/self.words_per_row) + base = vector(i * driver_spacing, 0) + self.driver_insts[index].place(base) @@ -152,18 +151,18 @@ class write_driver_array(design.design): offset=pin_pos) if self.write_size is not None: for bit in range(self.num_wmasks): - self.add_layout_pin(text="en_{}".format(bit), - layer="metal1", - offset=self.driver_insts[bit*(self.write_size-1)].get_pin("en").ll().scale(0,1), - width=self.width, - height=drc('minwidth_metal1')) - else: + en_pin = self.driver_insts[bit*self.write_size].get_pin("en") + self.add_layout_pin(text="en_{0}".format(bit), + layer=en_pin.layer, + offset=en_pin.ll(), + width=1.75*self.write_size*en_pin.width(), + height=en_pin.height()) self.add_layout_pin(text="en", layer="metal1", offset=self.driver_insts[0].get_pin("en").ll().scale(0,1), width=self.width, height=drc('minwidth_metal1')) - + def get_w_en_cin(self): diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index b43399e0..b7435e51 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -123,9 +123,9 @@ class write_mask_and_array(design.design): offset=pin_pos) - # def get_w_en_cin(self): - # """Get the relative capacitance of all the enable connections in the bank""" - # # The enable is connected to a nand2 for every row. - # return self.driver.get_w_en_cin() * len(self.driver_insts) + def get_cin(self): + """Get the relative capacitance of all the input connections in the bank""" + # The enable is connected to an and2 for every row. + return self.and2.get_cin() * len(self.and2_insts) From 0cfa0ac7557a223ce26a24040ff12a81687ba04f Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 8 Aug 2019 12:57:32 -0700 Subject: [PATCH 188/234] Shortened write driver enable pin so that a write mask can be used without a col mux in layout. --- compiler/modules/write_driver_array.py | 6 +- .../tests/10_write_driver_array_wmask_test.py | 57 ++++++++++++++++++ .../scn4m_subm/gds_lib/write_driver.gds | Bin 10204 -> 10204 bytes .../scn4m_subm/mag_lib/write_driver.mag | 4 +- 4 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 compiler/tests/10_write_driver_array_wmask_test.py diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index c1d9a539..64b836ba 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -113,7 +113,6 @@ class write_driver_array(design.design): for i in range(0,self.columns,self.words_per_row): index = int(i/self.words_per_row) base = vector(i * driver_spacing, 0) - self.driver_insts[index].place(base) @@ -152,11 +151,14 @@ class write_driver_array(design.design): if self.write_size is not None: for bit in range(self.num_wmasks): en_pin = self.driver_insts[bit*self.write_size].get_pin("en") + # modifier to stretch enable pin for column mux + modifier = (self.words_per_row-1) + 0.65 self.add_layout_pin(text="en_{0}".format(bit), layer=en_pin.layer, offset=en_pin.ll(), - width=1.75*self.write_size*en_pin.width(), + width=modifier*self.write_size*en_pin.width(), height=en_pin.height()) + else: self.add_layout_pin(text="en", layer="metal1", offset=self.driver_insts[0].get_pin("en").ll().scale(0,1), diff --git a/compiler/tests/10_write_driver_array_wmask_test.py b/compiler/tests/10_write_driver_array_wmask_test.py new file mode 100644 index 00000000..e0f0285e --- /dev/null +++ b/compiler/tests/10_write_driver_array_wmask_test.py @@ -0,0 +1,57 @@ +#!/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 write_driver_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + + # check write driver array for single port + debug.info(2, "Testing write_driver_array for columns=8, word_size=8, write_size=2") + a = factory.create(module_type="write_driver_array", columns=8, word_size=8, write_size=2) + self.local_check(a) + + debug.info(2, "Testing write_driver_array for columns=16, word_size=8, write_size=4") + a = factory.create(module_type="write_driver_array", columns=16, word_size=8, write_size=4) + self.local_check(a) + + # check write driver array for multi-port + # OPTS.bitcell = "pbitcell" + # OPTS.num_rw_ports = 1 + # OPTS.num_w_ports = 0 + # OPTS.num_r_ports = 0 + # + # factory.reset() + # debug.info(2, "Testing write_driver_array for columns=8, word_size=8, write_size=4 (multi-port case)") + # a = factory.create(module_type="write_driver_array", columns=8, word_size=8, write_size=4) + # self.local_check(a) + # + # debug.info(2, "Testing write_driver_array for columns=16, word_size=8, write_size=4 (multi-port case)") + # a = factory.create(module_type="write_driver_array", columns=16, word_size=8, write_size=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()) \ No newline at end of file diff --git a/technology/scn4m_subm/gds_lib/write_driver.gds b/technology/scn4m_subm/gds_lib/write_driver.gds index 63bf58d2d6f921b243ba1f25395427be28429454..6976213c7e63be2ca878e03fb280e2d0a2748c57 100644 GIT binary patch delta 82 zcmccPf5%^mfsKKQftf*uk%^(4fddG+8B`fGk=VKum2`!%2yaZvQ|6MeU|X delta 82 zcmccPf5%^mfsKKQftf*uk%^(4frEh&h^-j(kl3aZm2`!%2yaZvQ|6LUU|> rect -3 101 37 138 rect -3 0 37 51 @@ -178,7 +178,7 @@ rect 3 35 7 38 rect 19 35 23 38 rect 7 31 19 35 rect 0 24 7 28 -rect 11 24 36 28 +rect 11 24 31 28 << m2contact >> rect 10 193 14 197 rect 20 190 24 194 From 49fffcbc921a4c852cf7e363279cdc6f34f16d35 Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 8 Aug 2019 15:49:23 -0700 Subject: [PATCH 189/234] Added way to determine length of en pin with wmask in write_driver_array and shortened en to width of driver. --- compiler/modules/write_driver_array.py | 18 ++++++++++++------ .../tests/10_write_driver_array_wmask_test.py | 8 ++++++-- .../scn4m_subm/gds_lib/write_driver.gds | Bin 10204 -> 10204 bytes .../scn4m_subm/mag_lib/write_driver.mag | 6 +++--- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 64b836ba..7f7aa00a 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -107,12 +107,12 @@ class write_driver_array(design.design): def place_write_array(self): if self.bitcell.width > self.driver.width: - driver_spacing = self.bitcell.width + self.driver_spacing = self.bitcell.width else: - driver_spacing = self.driver.width + self.driver_spacing = self.driver.width for i in range(0,self.columns,self.words_per_row): index = int(i/self.words_per_row) - base = vector(i * driver_spacing, 0) + base = vector(i * self.driver_spacing, 0) self.driver_insts[index].place(base) @@ -151,12 +151,18 @@ class write_driver_array(design.design): if self.write_size is not None: for bit in range(self.num_wmasks): en_pin = self.driver_insts[bit*self.write_size].get_pin("en") - # modifier to stretch enable pin for column mux - modifier = (self.words_per_row-1) + 0.65 + # Determine width of wmask modified en_pin with/without col mux + if (self.words_per_row == 1): + wmask_en_len = (self.write_size * self.driver_spacing) + en_gap = self.driver_spacing - en_pin.width() + else: + wmask_en_len = 2*(self.write_size * self.driver_spacing) + en_gap = self.driver_spacing + self.add_layout_pin(text="en_{0}".format(bit), layer=en_pin.layer, offset=en_pin.ll(), - width=modifier*self.write_size*en_pin.width(), + width=wmask_en_len-en_gap, height=en_pin.height()) else: self.add_layout_pin(text="en", diff --git a/compiler/tests/10_write_driver_array_wmask_test.py b/compiler/tests/10_write_driver_array_wmask_test.py index e0f0285e..0a831572 100644 --- a/compiler/tests/10_write_driver_array_wmask_test.py +++ b/compiler/tests/10_write_driver_array_wmask_test.py @@ -23,8 +23,12 @@ class write_driver_test(openram_test): globals.init_openram("config_{0}".format(OPTS.tech_name)) # check write driver array for single port - debug.info(2, "Testing write_driver_array for columns=8, word_size=8, write_size=2") - a = factory.create(module_type="write_driver_array", columns=8, word_size=8, write_size=2) + debug.info(2, "Testing write_driver_array for columns=8, word_size=8, write_size=4") + a = factory.create(module_type="write_driver_array", columns=8, word_size=8, write_size=4) + self.local_check(a) + + debug.info(2, "Testing write_driver_array for columns=16, word_size=16, write_size=2") + a = factory.create(module_type="write_driver_array", columns=16, word_size=16, write_size=2) self.local_check(a) debug.info(2, "Testing write_driver_array for columns=16, word_size=8, write_size=4") diff --git a/technology/scn4m_subm/gds_lib/write_driver.gds b/technology/scn4m_subm/gds_lib/write_driver.gds index 6976213c7e63be2ca878e03fb280e2d0a2748c57..8223c795bae070e4d734e567c739a4440f0194ac 100644 GIT binary patch delta 157 zcmccPf5%^mfsKKQftf*uk%^(4fddHn88jJ0;cP7izKKfuf*67ulhTxxm?9V$gbpw; zNLV0f(FY6+AaMx2`IYicrpeW6yo;}?G3xLzFtG75F&Hwii7_!SFz^U4GcfRaFffP& VFtACorRFiP2r@9Rumdp*0|41!6+Hj| delta 136 zcmccPf5%^mfsKKQftf*uk%^(4fddG+8B`fGk=VKumGlKM1UDw7DJwAmfzSa41_=uU zE&2c?%D@1jH@{Ne$uxPpIxi371O^7-4hA+!w$!}Id1_LNH>fePu`@8RurL4sBp4NZ diff --git a/technology/scn4m_subm/mag_lib/write_driver.mag b/technology/scn4m_subm/mag_lib/write_driver.mag index b3bae978..0aa48197 100644 --- a/technology/scn4m_subm/mag_lib/write_driver.mag +++ b/technology/scn4m_subm/mag_lib/write_driver.mag @@ -1,6 +1,6 @@ magic tech scmos -timestamp 1565289461 +timestamp 1565304081 << nwell >> rect -3 101 37 138 rect -3 0 37 51 @@ -177,7 +177,7 @@ rect 27 45 31 60 rect 3 35 7 38 rect 19 35 23 38 rect 7 31 19 35 -rect 0 24 7 28 +rect 3 24 7 28 rect 11 24 31 28 << m2contact >> rect 10 193 14 197 @@ -198,7 +198,6 @@ rect 15 0 19 6 rect 0 0 34 203 << labels >> rlabel metal2 15 1 15 1 1 din -rlabel metal1 2 25 2 25 3 en rlabel m2contact 21 66 21 66 1 gnd rlabel m2contact 28 88 28 88 1 gnd rlabel m2contact 21 33 21 33 1 vdd @@ -206,4 +205,5 @@ rlabel m2contact 18 120 18 120 1 vdd rlabel metal2 12 201 12 201 5 bl rlabel metal2 22 201 22 201 5 br rlabel m2contact 14 161 14 161 1 gnd +rlabel metal1 17 26 17 26 1 en << end >> From 1d22d39667e4b9f7873c79c774c4454f243b1f24 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Thu, 8 Aug 2019 18:26:12 -0700 Subject: [PATCH 190/234] Uncommented tests that use model delays. Fixed issue in sense amp cin. --- compiler/base/hierarchy_design.py | 2 +- compiler/characterizer/delay.py | 3 ++- compiler/modules/sense_amp.py | 2 +- compiler/tests/21_model_delay_test.py | 9 +++++++-- compiler/tests/23_lib_sram_model_corners_test.py | 2 +- compiler/tests/23_lib_sram_model_test.py | 2 +- compiler/tests/30_openram_front_end_test.py | 2 +- 7 files changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index ec0b4e96..055bf412 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -110,7 +110,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): """Initializes parameters relevant to the graph creation""" #Only initializes a set for checking instances which should not be added self.graph_inst_exclude = set() - + def build_graph(self, graph, inst_name, port_nets): """Recursively create graph from instances in module.""" diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 81b31ef8..c4afc8a1 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -247,7 +247,7 @@ class delay(simulation): def create_graph(self): """Creates timing graph to generate the timing paths for the SRAM output.""" - self.sram.bank.bitcell_array.init_graph_params() # Removes previous bit exclusions + self.sram.bank.bitcell_array.bitcell_array.init_graph_params() # Removes previous bit exclusions self.sram.bank.bitcell_array.graph_exclude_bits(self.wordline_row, self.bitline_column) # Generate new graph every analysis as edges might change depending on test bit @@ -1313,6 +1313,7 @@ class delay(simulation): for load in loads: # Calculate delay based on slew and load path_delays = self.graph.get_timing(bl_path, self.corner, slew, load) + total_delay = self.sum_delays(path_delays) max_delay = max(max_delay, total_delay.delay) debug.info(1,'{}, {}, {}, {}'.format(slew,load,total_delay.delay/1e3, total_delay.slew/1e3)) diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index 8c92440c..e77d577f 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -42,7 +42,7 @@ class sense_amp(design.design): # Default is 8x. Per Samira and Hodges-Jackson book: # "Column-mux transistors driven by the decoder must be sized for optimal speed" bitline_pmos_size = 8 #FIXME: This should be set somewhere and referenced. Probably in tech file. - return spice["min_tx_drain_c"]*(bitline_pmos_size/parameter["min_tx_size"])#ff + return spice["min_tx_drain_c"]*(bitline_pmos_size)#ff def get_stage_effort(self, load): #Delay of the sense amp will depend on the size of the amp and the output load. diff --git a/compiler/tests/21_model_delay_test.py b/compiler/tests/21_model_delay_test.py index 3b43e789..114f0c6e 100755 --- a/compiler/tests/21_model_delay_test.py +++ b/compiler/tests/21_model_delay_test.py @@ -15,7 +15,7 @@ from globals import OPTS from sram_factory import factory import debug -@unittest.skip("SKIPPING 21_model_delay_test") +# @unittest.skip("SKIPPING 21_model_delay_test") class model_delay_test(openram_test): """ Compare the accuracy of the analytical model with a spice simulation. """ @@ -51,23 +51,28 @@ class model_delay_test(openram_test): import tech loads = [tech.spice["msflop_in_cap"]*4] slews = [tech.spice["rise_time"]*2] + + # Run a spice characterization spice_data, port_data = d.analyze(probe_address, probe_data, slews, loads) spice_data.update(port_data[0]) + # Run analytical characterization model_data, port_data = d.analytical_delay(slews, loads) model_data.update(port_data[0]) - #Only compare the delays + # Only compare the delays spice_delays = {key:value for key, value in spice_data.items() if 'delay' in key} model_delays = {key:value for key, value in model_data.items() if 'delay' in key} debug.info(1,"Spice Delays={}".format(spice_delays)) debug.info(1,"Model Delays={}".format(model_delays)) + if OPTS.tech_name == "freepdk45": error_tolerance = 0.25 elif OPTS.tech_name == "scn4m_subm": error_tolerance = 0.25 else: self.assertTrue(False) # other techs fail + # Check if no too many or too few results self.assertTrue(len(spice_delays.keys())==len(model_delays.keys())) diff --git a/compiler/tests/23_lib_sram_model_corners_test.py b/compiler/tests/23_lib_sram_model_corners_test.py index 51fcbca6..84b54e3d 100755 --- a/compiler/tests/23_lib_sram_model_corners_test.py +++ b/compiler/tests/23_lib_sram_model_corners_test.py @@ -14,7 +14,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 23_lib_sram_model_corners_test") +#@unittest.skip("SKIPPING 23_lib_sram_model_corners_test") class lib_model_corners_lib_test(openram_test): def runTest(self): diff --git a/compiler/tests/23_lib_sram_model_test.py b/compiler/tests/23_lib_sram_model_test.py index fd75dc25..9fdda7e7 100755 --- a/compiler/tests/23_lib_sram_model_test.py +++ b/compiler/tests/23_lib_sram_model_test.py @@ -14,7 +14,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 23_lib_sram_model_test") +#@unittest.skip("SKIPPING 23_lib_sram_model_test") class lib_sram_model_test(openram_test): def runTest(self): diff --git a/compiler/tests/30_openram_front_end_test.py b/compiler/tests/30_openram_front_end_test.py index 2be14001..db75fe0a 100755 --- a/compiler/tests/30_openram_front_end_test.py +++ b/compiler/tests/30_openram_front_end_test.py @@ -16,7 +16,7 @@ from sram_factory import factory import debug import getpass -@unittest.skip("SKIPPING 30_openram_front_end_test") +#@unittest.skip("SKIPPING 30_openram_front_end_test") class openram_front_end_test(openram_test): def runTest(self): From 2573d4e7d06a0471a876f3b131da06ba03df0d24 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Thu, 8 Aug 2019 19:27:44 -0700 Subject: [PATCH 191/234] Removed testing code from config file. --- compiler/example_configs/example_config_scn4m_subm.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/example_configs/example_config_scn4m_subm.py b/compiler/example_configs/example_config_scn4m_subm.py index 657eceda..cf973225 100644 --- a/compiler/example_configs/example_config_scn4m_subm.py +++ b/compiler/example_configs/example_config_scn4m_subm.py @@ -15,5 +15,3 @@ output_name = "sram_{0}_{1}_{2}".format(word_size,num_words,tech_name) drc_name = "magic" lvs_name = "netgen" pex_name = "magic" - -netlist_only = True \ No newline at end of file From d5e331d4f360f0ad8ce2c06f2e62e0ae9809698b Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 9 Aug 2019 14:27:53 -0700 Subject: [PATCH 192/234] Connected en together in write_mask_and_array. --- compiler/globals.py | 8 ++- compiler/modules/write_mask_and_array.py | 49 +++++++++++++++--- .../tests/10_write_mask_and_array_test.py | 4 ++ technology/freepdk45/gds_lib/write_driver.gds | Bin 20480 -> 20480 bytes 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/compiler/globals.py b/compiler/globals.py index 0b262430..aa64c0a3 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -476,10 +476,14 @@ def report_status(): # If a write mask is specified by the user, the mask write size should be the same as # the word size so that an entire word is written at once. if OPTS.write_size is not None: - if (OPTS.write_size < 1 or OPTS.write_size > OPTS.word_size): - debug.error("Write size needs to be between 1 bit and {0} bits.".format(OPTS.word_size)) if (OPTS.word_size % OPTS.write_size != 0): debug.error("Write size needs to be an integer multiple of word size.") + # If write size is more than half of the word size, then it doesn't need a write mask. It would be writing + # the whole word. + if (OPTS.write_size < 1 or OPTS.write_size > OPTS.word_size/2): + debug.error("Write size needs to be between 1 bit and {0} bits/2.".format(OPTS.word_size)) + + if not OPTS.tech_name: debug.error("Tech name must be specified in config file.") diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index b7435e51..e5052c07 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -51,6 +51,7 @@ class write_mask_and_array(design.design): self.place_and2_array() self.add_layout_pins() + self.route_en() self.add_boundary() self.DRC_LVS() @@ -81,10 +82,28 @@ class write_mask_and_array(design.design): def place_and2_array(self): - # place the write mask AND array below the write driver array - and2_spacing = self.and2.width + # Place the write mask AND array at the start of each write driver enable length. + # This ensures the write mask AND array will be directly under the corresponding write driver enable wire. + + # This is just used for measurements, so don't add the module + self.bitcell = factory.create(module_type="bitcell") + self.driver = factory.create(module_type="write_driver") + if self.bitcell.width > self.driver.width: + self.driver_spacing = self.bitcell.width + else: + self.driver_spacing = self.driver.width + + if (self.words_per_row == 1): + wmask_en_len = (self.write_size * self.driver_spacing) + if self.driver_spacing * self.write_size < self.and2.width: + debug.error("Cannot layout write mask AND array. One pand2 is longer than the corresponding write drivers.") + else: + wmask_en_len = 2 * (self.write_size * self.driver_spacing) + if wmask_en_len < self.and2.width: + debug.error("Cannot layout write mask AND array. One pand2 is longer than the corresponding write drivers.") + for i in range(self.num_wmasks): - base = vector(i * and2_spacing, 0) + base = vector(i * wmask_en_len, 0) self.and2_insts[i].place(base) @@ -98,11 +117,13 @@ class write_mask_and_array(design.design): height=wmask_in_pin.height()) en_pin = self.and2_insts[i].get_pin("B") - self.add_layout_pin(text="en", - layer=en_pin.layer, - offset=en_pin.ll(), - width=en_pin.width(), - height=en_pin.height()) + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=en_pin.center()) + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=en_pin.center()) + self.add_layout_pin_rect_center(text="en", + layer="metal3", + offset=en_pin.center()) wmask_out_pin = self.and2_insts[i].get_pin("Z") self.add_layout_pin(text="wmask_out_{0}".format(i), @@ -115,6 +136,9 @@ class write_mask_and_array(design.design): pin_list = self.and2_insts[i].get_pins(n) for pin in pin_list: pin_pos = pin.center() + # Add the M1->M2 stack + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=pin_pos) # Add the M2->M3 stack self.add_via_center(layers=("metal2", "via2", "metal3"), offset=pin_pos) @@ -123,6 +147,15 @@ class write_mask_and_array(design.design): offset=pin_pos) + def route_en(self): + for i in range(self.num_wmasks-1): + en_pin = self.and2_insts[i].get_pin("B") + next_en_pin = self.and2_insts[i+1].get_pin("B") + offset = en_pin.center() + next_offset = next_en_pin.center() + self.add_path("metal3", [offset, + next_offset]) + def get_cin(self): """Get the relative capacitance of all the input connections in the bank""" # The enable is connected to an and2 for every row. diff --git a/compiler/tests/10_write_mask_and_array_test.py b/compiler/tests/10_write_mask_and_array_test.py index c79b8fc6..830448eb 100644 --- a/compiler/tests/10_write_mask_and_array_test.py +++ b/compiler/tests/10_write_mask_and_array_test.py @@ -27,6 +27,10 @@ class write_mask_and_array_test(openram_test): a = factory.create(module_type="write_mask_and_array", columns=8, word_size=8, write_size=4) self.local_check(a) + debug.info(2, "Testing write_mask_and_array for columns=8, word_size=8, write_size=4") + a = factory.create(module_type="write_mask_and_array", columns=16, word_size=16, write_size=4) + self.local_check(a) + debug.info(2, "Testing write_mask_and_array for columns=16, word_size=8, write_size=2") a = factory.create(module_type="write_mask_and_array", columns=16, word_size=8, write_size=2) self.local_check(a) diff --git a/technology/freepdk45/gds_lib/write_driver.gds b/technology/freepdk45/gds_lib/write_driver.gds index 742e39d40ba6e581ac7a4effccb6d226bc0b9930..86015e7a7991ff9a3775c8e11fa1fee5ce5113a1 100644 GIT binary patch delta 126 zcmZozz}T>Wae}zJFarkzCj%FQHiIz(4-;ETYFc7xP6-2p2s5jl!jaia9|wQ4REiP5 z;JfA>gA6MZ10Mr7gCtOg27?I$lHQGRPc&5+7#N}$7?{MN^h^c@mTy2lj0THuPScvD F3ILqN7}o#* delta 126 zcmZozz}T>Wae}zJ5Cb;@Cj%FQHG>rc4-;ETYFc7xP6-2p2s5jl!jaia9|wQ4REiP5 z;JfArgA6MZ10PVmBv6M2g9!tY-i>ijG*$lp|G$fYfk_-n&tza=JptsyXt4O^G_6^x E0JEkd&;S4c From bac684a82a1c855752b98ced590177998fff69ef Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 10 Aug 2019 08:53:02 -0700 Subject: [PATCH 193/234] Fix control logic routing. --- compiler/modules/control_logic.py | 155 +++++++++++++++++------------- 1 file changed, 88 insertions(+), 67 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index c2d86da8..3ce7921a 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -343,11 +343,11 @@ class control_logic(design.design): # list of output control signals (for making a vertical bus) if self.port_type == "rw": - self.internal_bus_list = ["gated_clk_bar", "gated_clk_buf", "we", "clk_buf", "we_bar", "cs"] + self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "we", "clk_buf", "we_bar", "cs"] elif self.port_type == "r": - self.internal_bus_list = ["gated_clk_bar", "gated_clk_buf", "clk_buf", "cs_bar", "cs"] + self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "clk_buf", "cs_bar", "cs"] else: - self.internal_bus_list = ["gated_clk_bar", "gated_clk_buf", "clk_buf", "cs"] + self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "clk_buf", "cs"] # leave space for the bus plus one extra space self.internal_bus_width = (len(self.internal_bus_list)+1)*self.m2_pitch @@ -381,6 +381,7 @@ class control_logic(design.design): self.create_gated_clk_buf_row() self.create_wlen_row() if (self.port_type == "rw") or (self.port_type == "w"): + self.create_rbl_delay_row() self.create_wen_row() if (self.port_type == "rw") or (self.port_type == "r"): self.create_sen_row() @@ -418,6 +419,9 @@ class control_logic(design.design): row += 1 self.place_pen_row(row) row += 1 + if (self.port_type == "rw") or (self.port_type == "w"): + self.place_rbl_delay_row(row) + row += 1 if (self.port_type == "rw") or (self.port_type == "r"): self.place_sen_row(row) row += 1 @@ -442,6 +446,7 @@ class control_logic(design.design): self.route_dffs() self.route_wlen() if (self.port_type == "rw") or (self.port_type == "w"): + self.route_rbl_delay() self.route_wen() if (self.port_type == "rw") or (self.port_type == "r"): self.route_sen() @@ -469,7 +474,18 @@ class control_logic(design.design): self.delay_inst.place(offset, mirror="MY") def route_delay(self): + + out_pos = self.delay_inst.get_pin("out").bc() + # Connect to the rail level with the vdd rail + # Use pen since it is in every type of control logic + vdd_ypos = self.p_en_bar_nand_inst.get_pin("vdd").by() + in_pos = vector(self.rail_offsets["rbl_bl_delay"].x,vdd_ypos) + mid1 = vector(out_pos.x,in_pos.y) + self.add_wire(("metal1","via1","metal2"),[out_pos, mid1, in_pos]) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=in_pos) + # Input from RBL goes to the delay line for futher delay self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") @@ -481,12 +497,9 @@ class control_logic(design.design): self.connect_inst(["clk","clk_buf","vdd","gnd"]) def place_clk_buf_row(self,row): - """ Place the multistage clock buffer below the control flops """ - x_off = self.control_x_offset - (y_off,mirror)=self.get_offset(row) + x_offset = self.control_x_offset - offset = vector(x_off,y_off) - self.clk_buf_inst.place(offset, mirror) + x_offset = self.place_util(self.clk_buf_inst, x_offset, row) self.row_end_inst.append(self.clk_buf_inst) @@ -523,17 +536,10 @@ class control_logic(design.design): self.connect_inst(["cs","clk_bar","gated_clk_bar","vdd","gnd"]) def place_gated_clk_bar_row(self,row): - """ Place the gated clk logic below the control flops """ - x_off = self.control_x_offset - (y_off,mirror)=self.get_offset(row) + x_offset = self.control_x_offset - offset = vector(x_off,y_off) - self.clk_bar_inst.place(offset, mirror) - - x_off += self.inv.width - - offset = vector(x_off,y_off) - self.gated_clk_bar_inst.place(offset, mirror) + x_offset = self.place_util(self.clk_bar_inst, x_offset, row) + x_offset = self.place_util(self.gated_clk_bar_inst, x_offset, row) self.row_end_inst.append(self.gated_clk_bar_inst) @@ -567,12 +573,9 @@ class control_logic(design.design): self.connect_inst(["clk_buf", "cs","gated_clk_buf","vdd","gnd"]) def place_gated_clk_buf_row(self,row): - """ Place the gated clk logic below the control flops """ - x_off = self.control_x_offset - (y_off,mirror)=self.get_offset(row) - - offset = vector(x_off,y_off) - self.gated_clk_buf_inst.place(offset, mirror) + x_offset = self.control_x_offset + + x_offset = self.place_util(self.gated_clk_buf_inst, x_offset, row) self.row_end_inst.append(self.gated_clk_buf_inst) @@ -594,11 +597,9 @@ class control_logic(design.design): self.connect_inst(["gated_clk_bar", "wl_en", "vdd", "gnd"]) def place_wlen_row(self, row): - x_off = self.control_x_offset - (y_off,mirror)=self.get_offset(row) - - offset = vector(x_off, y_off) - self.wl_en_inst.place(offset, mirror) + x_offset = self.control_x_offset + + x_offset = self.place_util(self.wl_en_inst, x_offset, row) self.row_end_inst.append(self.wl_en_inst) @@ -609,29 +610,32 @@ class control_logic(design.design): self.connect_output(self.wl_en_inst, "Z", "wl_en") def create_pen_row(self): - self.p_en_bar_inst=self.add_inst(name="nand_p_en_bar", - mod=self.nand2) + self.p_en_bar_nand_inst=self.add_inst(name="nand_p_en_bar", + mod=self.nand2) self.connect_inst(["gated_clk_buf", "rbl_bl_delay", "p_en_bar_unbuf", "vdd", "gnd"]) - self.p_en_bar_inst=self.add_inst(name="buf_p_en_bar", - mod=self.p_en_bar_driver) + self.p_en_bar_driver_inst=self.add_inst(name="buf_p_en_bar", + mod=self.p_en_bar_driver) self.connect_inst(["p_en_bar_unbuf", "p_en_bar", "vdd", "gnd"]) - - def place_pen_row(self,row): - x_off = self.control_x_offset - (y_off,mirror)=self.get_offset(row) - offset = vector(x_off,y_off) - self.p_en_bar_inst.place(offset, mirror) + x_offset = self.control_x_offset - self.row_end_inst.append(self.p_en_bar_inst) + x_offset = self.place_util(self.p_en_bar_nand_inst, x_offset, row) + x_offset = self.place_util(self.p_en_bar_driver_inst, x_offset, row) + + self.row_end_inst.append(self.p_en_bar_driver_inst) def route_pen(self): - in_map = zip(["A"], ["gated_clk_buf"]) - self.connect_vertical_bus(in_map, self.p_en_bar_inst, self.rail_offsets) + in_map = zip(["A", "B"], ["gated_clk_buf", "rbl_bl_delay"]) + self.connect_vertical_bus(in_map, self.p_en_bar_nand_inst, self.rail_offsets) + + out_pos = self.p_en_bar_nand_inst.get_pin("Z").rc() + in_pos = self.p_en_bar_driver_inst.get_pin("A").lc() + mid1 = vector(out_pos.x,in_pos.y) + self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) - self.connect_output(self.p_en_bar_inst, "Z", "p_en_bar") + self.connect_output(self.p_en_bar_driver_inst, "Z", "p_en_bar") def create_sen_row(self): """ Create the sense enable buffer. """ @@ -646,15 +650,9 @@ class control_logic(design.design): def place_sen_row(self,row): - """ - The sense enable buffer gets placed to the far right of the - row. - """ - x_off = self.control_x_offset - (y_off,mirror)=self.get_offset(row) + x_offset = self.control_x_offset - offset = vector(x_off, y_off) - self.s_en_gate_inst.place(offset, mirror) + x_offset = self.place_util(self.s_en_gate_inst, x_offset, row) self.row_end_inst.append(self.s_en_gate_inst) @@ -666,23 +664,41 @@ class control_logic(design.design): else: input_name = "cs_bar" - sen_map = zip(["B"], [input_name]) + sen_map = zip(["A", "B"], ["rbl_bl_delay", input_name]) self.connect_vertical_bus(sen_map, self.s_en_gate_inst, self.rail_offsets) - out_pos = self.delay_inst.get_pin("out").bc() - in_pos = self.s_en_gate_inst.get_pin("A").lc() - mid1 = vector(out_pos.x,in_pos.y) - self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) - self.connect_output(self.s_en_gate_inst, "Z", "s_en") - def create_wen_row(self): + def create_rbl_delay_row(self): self.rbl_bl_delay_inv_inst = self.add_inst(name="rbl_bl_delay_inv", mod=self.inv) self.connect_inst(["rbl_bl_delay", "rbl_bl_delay_bar", "vdd", "gnd"]) + + def place_rbl_delay_row(self,row): + x_offset = self.control_x_offset + + x_offset = self.place_util(self.rbl_bl_delay_inv_inst, x_offset, row) + self.row_end_inst.append(self.rbl_bl_delay_inv_inst) + + def route_rbl_delay(self): + # Connect from delay line + # Connect to rail + + rbl_map = zip(["Z"], ["rbl_bl_delay_bar"]) + self.connect_vertical_bus(rbl_map, self.rbl_bl_delay_inv_inst, self.rail_offsets, ("metal3", "via2", "metal2")) + # The pin is on M1, so we need another via as well + self.add_via_center(layers=("metal1","via1","metal2"), + offset=self.rbl_bl_delay_inv_inst.get_pin("Z").center()) + + + rbl_map = zip(["A"], ["rbl_bl_delay"]) + self.connect_vertical_bus(rbl_map, self.rbl_bl_delay_inv_inst, self.rail_offsets) + + def create_wen_row(self): + # input: we (or cs) output: w_en if self.port_type == "rw": input_name = "we" @@ -697,11 +713,9 @@ class control_logic(design.design): def place_wen_row(self,row): - x_off = self.ctrl_dff_inst.width + self.internal_bus_width - (y_off,mirror)=self.get_offset(row) - - offset = vector(x_off, y_off) - self.w_en_gate_inst.place(offset, mirror) + x_offset = self.control_x_offset + + x_offset = self.place_util(self.w_en_gate_inst, x_offset, row) self.row_end_inst.append(self.w_en_gate_inst) @@ -712,7 +726,7 @@ class control_logic(design.design): # No we for write-only reports, so use cs input_name = "cs" - wen_map = zip(["A", "B"], [input_name, "gated_clk_bar"]) + wen_map = zip(["A", "B", "C"], [input_name, "rbl_bl_delay_bar", "gated_clk_bar"]) self.connect_vertical_bus(wen_map, self.w_en_gate_inst, self.rail_offsets) self.connect_output(self.w_en_gate_inst, "Z", "w_en") @@ -791,9 +805,8 @@ class control_logic(design.design): self.add_power_pin("gnd", pin_loc) self.add_path("metal1", [row_loc, pin_loc]) - if (self.port_type == "rw") or (self.port_type == "r"): - self.copy_layout_pin(self.delay_inst,"gnd") - self.copy_layout_pin(self.delay_inst,"vdd") + self.copy_layout_pin(self.delay_inst,"gnd") + self.copy_layout_pin(self.delay_inst,"vdd") self.copy_layout_pin(self.ctrl_dff_inst,"gnd") self.copy_layout_pin(self.ctrl_dff_inst,"vdd") @@ -958,3 +971,11 @@ class control_logic(design.design): self.graph_inst_exclude.add(self.ctrl_dff_inst) if self.port_type=="rw" or self.port_type=="w": self.graph_inst_exclude.add(self.w_en_gate_inst) + + def place_util(self, inst, x_offset, row): + """ Utility to place a row and compute the next offset """ + + (y_offset,mirror)=self.get_offset(row) + offset = vector(x_offset, y_offset) + inst.place(offset, mirror) + return x_offset+inst.width From 34d28a19e66f1a34da7cddaff1688382dbf1f37b Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 10 Aug 2019 12:30:23 -0700 Subject: [PATCH 194/234] Connect wl_en in all ports to bank. --- compiler/modules/bank.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 6b7462de..99137654 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -915,9 +915,8 @@ class bank(design.design): connection = [] connection.append((self.prefix+"p_en_bar{}".format(port), self.port_data_inst[port].get_pin("p_en_bar").lc())) - if port in self.read_ports: - 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).lc())) + 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).lc())) if port in self.write_ports: connection.append((self.prefix+"w_en{}".format(port), self.port_data_inst[port].get_pin("w_en").lc())) From 23676c0f374eeada21d2f55135ddc6bbeb4ea662 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 10 Aug 2019 12:53:07 -0700 Subject: [PATCH 195/234] Route bl in SRAM write ports too --- compiler/sram/sram_1bank.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 355ca769..51cfeada 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -301,7 +301,7 @@ class sram_1bank(sram_base): dest_pin = self.bank_inst.get_pin(signal+"{}".format(port)) self.connect_vbus_m2m3(src_pin, dest_pin) - for port in self.read_ports: + for port in self.all_ports: # Only input (besides pins) is the replica bitline src_pin = self.control_logic_insts[port].get_pin("rbl_bl") dest_pin = self.bank_inst.get_pin("rbl_bl{}".format(port)) From 6cf7366c569c5c100b4fb549942386e1e11f3a23 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 10 Aug 2019 16:30:02 -0700 Subject: [PATCH 196/234] Gate sen during first half period --- compiler/modules/control_logic.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index e1c470b5..06883125 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -131,10 +131,10 @@ class control_logic(design.design): self.add_mod(self.wen_and) # s_en drives every sense amp - self.sen_and2 = factory.create(module_type="pand2", + self.sen_and3 = factory.create(module_type="pand3", size=self.word_size, height=dff_height) - self.add_mod(self.sen_and2) + self.add_mod(self.sen_and3) # used to generate inverted signals with low fanout self.inv = factory.create(module_type="pinv", @@ -645,8 +645,8 @@ class control_logic(design.design): input_name = "cs_bar" # GATE FOR S_EN self.s_en_gate_inst = self.add_inst(name="buf_s_en_and", - mod=self.sen_and2) - self.connect_inst(["rbl_bl_delay", input_name, "s_en", "vdd", "gnd"]) + mod=self.sen_and3) + self.connect_inst(["rbl_bl_delay", "gated_clk_bar", input_name, "s_en", "vdd", "gnd"]) def place_sen_row(self,row): @@ -664,7 +664,7 @@ class control_logic(design.design): else: input_name = "cs_bar" - sen_map = zip(["A", "B"], ["rbl_bl_delay", input_name]) + sen_map = zip(["A", "B", "C"], ["rbl_bl_delay", "gated_clk_bar", input_name]) self.connect_vertical_bus(sen_map, self.s_en_gate_inst, self.rail_offsets) self.connect_output(self.s_en_gate_inst, "Z", "s_en") From c09005dab9ec1b4ed004e0b84be50fe61ce530ba Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 10 Aug 2019 17:32:36 -0700 Subject: [PATCH 197/234] Redo logic for detecting bad bitlines --- compiler/characterizer/delay.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index c4afc8a1..65bc0b78 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -800,6 +800,8 @@ class delay(simulation): debug.info(2,"{}={}".format(meas.name,val)) + dout_success = True + bl_success = False for meas in self.dout_volt_meas: val = meas.retrieve_measure(port=port) debug.info(2,"{}={}".format(meas.name, val)) @@ -813,15 +815,7 @@ class delay(simulation): dout_success = False debug.info(1, "Debug measurement failed. Value {}V was read on read 0 cycle.".format(val)) bl_success = self.check_bitline_meas(br_vals[sram_op.READ_ONE], bl_vals[sram_op.READ_ONE]) - elif meas.meta_str == sram_op.READ_ONE and val > self.vdd_voltage*0.9: - dout_success = True - bl_success = True - elif meas.meta_str == sram_op.READ_ZERO and val < self.vdd_voltage*0.1: - dout_success = True - bl_success = True - else: - dout_success = False - bl_success = False + # If the bitlines have a correct value while the output does not then that is a # sen error. FIXME: there are other checks that can be done to solidfy this conclusion. if not dout_success and bl_success: From d56a972d61794ef2cf2ff9c9c2c83942ce33e275 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sat, 10 Aug 2019 17:59:30 -0700 Subject: [PATCH 198/234] Update ngspice tests due to new version --- compiler/tests/21_ngspice_delay_test.py | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 06a61d55..39f0d5e0 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -54,27 +54,27 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_hl': [0.22609590000000002], - 'delay_lh': [0.22609590000000002], - 'leakage_power': 0.003317743, + golden_data = {'delay_hl': [0.2264205], + 'delay_lh': [0.2264205], + 'leakage_power': 0.0021017429999999997, 'min_period': 0.859, - 'read0_power': [0.3271056], - 'read1_power': [0.3064244], - 'slew_hl': [0.2153979], - 'slew_lh': [0.2153979], - 'write0_power': [0.3532067], - 'write1_power': [0.3381259]} + 'read0_power': [0.3339161], + 'read1_power': [0.31329440000000003], + 'slew_hl': [0.2590786], + 'slew_lh': [0.2590786], + 'write0_power': [0.36360849999999995], + 'write1_power': [0.3486931]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_hl': [1.709791], - 'delay_lh': [1.709791], - 'leakage_power': 0.06803324999999999, + golden_data = {'delay_hl': [1.7083549999999998], + 'delay_lh': [1.7083549999999998], + 'leakage_power': 0.001119657, 'min_period': 7.812, - 'read0_power': [7.9499070000000005], - 'read1_power': [7.619662999999999], - 'slew_hl': [1.390261], - 'slew_lh': [1.390261], - 'write0_power': [8.913003], - 'write1_power': [8.166687000000001]} + 'read0_power': [8.013845], + 'read1_power': [7.6889389999999995], + 'slew_hl': [1.31918], + 'slew_lh': [1.31918], + 'write0_power': [8.791557000000001], + 'write1_power': [8.70443]} else: self.assertTrue(False) # other techs fail From e5618b88af5aa66c585c8b6f2de9d7b9c75c8214 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Sun, 11 Aug 2019 08:46:36 -0700 Subject: [PATCH 199/234] Don't add sense amp to write only port. Fix write_and None define. --- compiler/modules/port_data.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index b4027be9..a1adb7d4 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -156,11 +156,14 @@ class port_data(design.design): bitcell_bl=self.bl_names[self.port], bitcell_br=self.br_names[self.port]) self.add_mod(self.precharge_array) - - self.sense_amp_array = factory.create(module_type="sense_amp_array", - word_size=self.word_size, - words_per_row=self.words_per_row) - self.add_mod(self.sense_amp_array) + + if self.port in self.read_ports: + self.sense_amp_array = factory.create(module_type="sense_amp_array", + word_size=self.word_size, + words_per_row=self.words_per_row) + self.add_mod(self.sense_amp_array) + else: + self.sense_amp_array = None if self.col_addr_size > 0: @@ -187,7 +190,7 @@ class port_data(design.design): write_size=self.write_size) self.add_mod(self.write_mask_and_array) else: - self.write_mask_and_array_inst = None + self.write_mask_and_array = None else: self.write_driver_array = None From d259efbcda48824c0f4e40b2fbb192be114ee400 Mon Sep 17 00:00:00 2001 From: jsowash Date: Sun, 11 Aug 2019 14:33:08 -0700 Subject: [PATCH 200/234] Connected wdriver_sel between write_mask_and_array and write_driver_array. --- compiler/modules/port_data.py | 45 +++++++++++++++++------- compiler/modules/write_mask_and_array.py | 7 ++-- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 64229685..26104593 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -126,6 +126,7 @@ class port_data(design.design): if self.port in self.readwrite_ports: # (write_mask_and ->) write_driver -> sense_amp -> (column_mux ->) precharge -> bitcell_array self.route_write_mask_and(self.port) + self.route_write_mask_and_to_write_driver(self.port) self.route_write_driver_in(self.port) self.route_sense_amp_out(self.port) self.route_write_driver_to_sense_amp(self.port) @@ -139,7 +140,9 @@ class port_data(design.design): else: # (write_mask_and ->) write_driver -> (column_mux ->) precharge -> bitcell_array self.route_write_mask_and(self.port) - self.route_write_driver_in(self.port) + self.route_write_mask_and_to_write_driver(self.port) + self.route_write_driver_in(self.port) + self.route_write_mask_and_to_write_driver(self.port) self.route_write_driver_to_column_mux_or_precharge_array(self.port) self.route_column_mux_to_precharge_array(self.port) @@ -454,11 +457,16 @@ class port_data(design.design): for bit in range(self.num_wmasks): wdriver_sel_pin = self.write_mask_and_array_inst.get_pin("wmask_out_{}".format(bit)) + # self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), + # layer=wdriver_sel_pin.layer, + # offset=wdriver_sel_pin.center(), + # height=wdriver_sel_pin.height(), + # width=wdriver_sel_pin.width()) + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=wdriver_sel_pin.center()) self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), - layer=wdriver_sel_pin.layer, - offset=wdriver_sel_pin.center(), - height=wdriver_sel_pin.height(), - width=wdriver_sel_pin.width()) + layer="metal2", + offset=wdriver_sel_pin.center()) def route_column_mux_to_precharge_array(self, port): @@ -536,13 +544,17 @@ class port_data(design.design): self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size) - # def route_write_mask_and_to_write_driver(self,port): - # """ Routing of wdriver_sel_{} between write mask AND and write driver """ - # inst1 = self.write_mask_and_array_inst - # inst2 = self.write_driver_array_inst - # - # inst1_wdriver_sel_name = "wdriver_sel_{}" - # start_bit=0 + def route_write_mask_and_to_write_driver(self,port): + """ Routing of wdriver_sel_{} between write mask AND array and write driver array """ + inst1 = self.write_mask_and_array_inst + inst2 = self.write_driver_array_inst + + for bit in range(self.num_wmasks): + wdriver_sel_out_pin = inst1.get_pin("wmask_out_{}".format(bit)) + wdriver_sel_in_pin = inst2.get_pin("en_{}".format(bit)) + self.add_path("metal2", [wdriver_sel_out_pin.center(), wdriver_sel_in_pin.center()]) + + def route_bitline_pins(self): """ Add the bitline pins for the given port """ @@ -580,7 +592,14 @@ class port_data(design.design): if self.write_driver_array_inst: if self.write_mask_and_array_inst: for bit in range(self.num_wmasks): - self.copy_layout_pin(self.write_driver_array_inst, "en_{}".format(bit), "wdriver_sel_{}".format(bit)) + wdriver_en_pin = self.write_driver_array_inst.get_pin("en_{}".format(bit)) + + # self.copy_layout_pin(self.write_driver_array_inst, "en_{}".format(bit), "wdriver_sel_{}".format(bit)) + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=wdriver_en_pin.center()) + self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), + layer="metal2", + offset=wdriver_en_pin.center()) else: self.copy_layout_pin(self.write_driver_array_inst, "en", "w_en") if self.write_mask_and_array_inst: diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index e5052c07..753c2dd4 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -51,7 +51,7 @@ class write_mask_and_array(design.design): self.place_and2_array() self.add_layout_pins() - self.route_en() + self.route_enable() self.add_boundary() self.DRC_LVS() @@ -147,14 +147,13 @@ class write_mask_and_array(design.design): offset=pin_pos) - def route_en(self): + def route_enable(self): for i in range(self.num_wmasks-1): en_pin = self.and2_insts[i].get_pin("B") next_en_pin = self.and2_insts[i+1].get_pin("B") offset = en_pin.center() next_offset = next_en_pin.center() - self.add_path("metal3", [offset, - next_offset]) + self.add_path("metal3", [offset, next_offset]) def get_cin(self): """Get the relative capacitance of all the input connections in the bank""" From aa4803f3c4b69b60be7c23c6d9014129eabfb2db Mon Sep 17 00:00:00 2001 From: jsowash Date: Sun, 11 Aug 2019 15:25:05 -0700 Subject: [PATCH 201/234] Increased enable pin's width for larger # of column mux ways. --- compiler/modules/write_driver_array.py | 2 +- compiler/modules/write_mask_and_array.py | 2 +- compiler/tests/18_port_data_wmask_test.py | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 7f7aa00a..ef87bf6d 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -156,7 +156,7 @@ class write_driver_array(design.design): wmask_en_len = (self.write_size * self.driver_spacing) en_gap = self.driver_spacing - en_pin.width() else: - wmask_en_len = 2*(self.write_size * self.driver_spacing) + wmask_en_len = self.words_per_row*(self.write_size * self.driver_spacing) en_gap = self.driver_spacing self.add_layout_pin(text="en_{0}".format(bit), diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 753c2dd4..1ff6cb30 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -98,7 +98,7 @@ class write_mask_and_array(design.design): if self.driver_spacing * self.write_size < self.and2.width: debug.error("Cannot layout write mask AND array. One pand2 is longer than the corresponding write drivers.") else: - wmask_en_len = 2 * (self.write_size * self.driver_spacing) + wmask_en_len = self.words_per_row * (self.write_size * self.driver_spacing) if wmask_en_len < self.and2.width: debug.error("Cannot layout write mask AND array. One pand2 is longer than the corresponding write drivers.") diff --git a/compiler/tests/18_port_data_wmask_test.py b/compiler/tests/18_port_data_wmask_test.py index abc4f5d0..e89ea77d 100644 --- a/compiler/tests/18_port_data_wmask_test.py +++ b/compiler/tests/18_port_data_wmask_test.py @@ -48,7 +48,6 @@ class port_data_test(openram_test): a = factory.create("port_data", sram_config=c, port=0) self.local_check(a) - c.word_size = 2 c.num_words = 128 c.words_per_row = 8 factory.reset() From 0d7170eb95ee092e6609d4f413d0df6daef8349c Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 14 Aug 2019 09:59:40 -0700 Subject: [PATCH 202/234] Created wmask AND array en pin to go through to top layer. --- compiler/modules/port_data.py | 6 ++-- compiler/modules/write_mask_and_array.py | 31 ++++++++++++------- compiler/sram/sram_1bank.py | 8 +++-- compiler/sram/sram_base.py | 2 +- .../tests/10_write_driver_array_wmask_test.py | 28 ++++++++--------- 5 files changed, 43 insertions(+), 32 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 2eed4bb9..7ce099bb 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -545,7 +545,6 @@ class port_data(design.design): self.add_path("metal2", [wdriver_sel_out_pin.center(), wdriver_sel_in_pin.center()]) - def route_bitline_pins(self): """ Add the bitline pins for the given port """ @@ -582,9 +581,9 @@ class port_data(design.design): if self.write_driver_array_inst: if self.write_mask_and_array_inst: for bit in range(self.num_wmasks): - wdriver_en_pin = self.write_driver_array_inst.get_pin("en_{}".format(bit)) + self.copy_layout_pin(self.write_driver_array_inst, "en_{}".format(bit), "wdriver_sel_{}".format(bit)) - # self.copy_layout_pin(self.write_driver_array_inst, "en_{}".format(bit), "wdriver_sel_{}".format(bit)) + wdriver_en_pin = self.write_driver_array_inst.get_pin("en_{}".format(bit)) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=wdriver_en_pin.center()) self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), @@ -594,6 +593,7 @@ class port_data(design.design): self.copy_layout_pin(self.write_driver_array_inst, "en", "w_en") if self.write_mask_and_array_inst: self.copy_layout_pin(self.write_mask_and_array_inst, "en", "w_en") + def channel_route_bitlines(self, inst1, inst2, num_bits, diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 1ff6cb30..878da688 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -51,7 +51,7 @@ class write_mask_and_array(design.design): self.place_and2_array() self.add_layout_pins() - self.route_enable() + # self.route_enable() self.add_boundary() self.DRC_LVS() @@ -121,9 +121,12 @@ class write_mask_and_array(design.design): offset=en_pin.center()) self.add_via_center(layers=("metal2", "via2", "metal3"), offset=en_pin.center()) - self.add_layout_pin_rect_center(text="en", - layer="metal3", - offset=en_pin.center()) + if i < self.num_wmasks-1: + self.add_layout_pin(text="en", + layer="metal3", + offset=en_pin.ll(), + width = self.en_width(i), + height = en_pin.height()) wmask_out_pin = self.and2_insts[i].get_pin("Z") self.add_layout_pin(text="wmask_out_{0}".format(i), @@ -146,14 +149,20 @@ class write_mask_and_array(design.design): layer="metal3", offset=pin_pos) + def en_width(self, pin): + en_pin = self.and2_insts[pin].get_pin("B") + next_en_pin = self.and2_insts[pin+1].get_pin("B") + width = next_en_pin.lr() - en_pin.ll() + return width[0] - def route_enable(self): - for i in range(self.num_wmasks-1): - en_pin = self.and2_insts[i].get_pin("B") - next_en_pin = self.and2_insts[i+1].get_pin("B") - offset = en_pin.center() - next_offset = next_en_pin.center() - self.add_path("metal3", [offset, next_offset]) + + # def route_enable(self): + # for i in range(self.num_wmasks-1): + # en_pin = self.and2_insts[i].get_pin("B") + # next_en_pin = self.and2_insts[i+1].get_pin("B") + # offset = en_pin.center() + # next_offset = next_en_pin.center() + # self.add_path("metal3", [offset, next_offset]) def get_cin(self): """Get the relative capacitance of all the input connections in the bank""" diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 51cfeada..1100f2cb 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -125,11 +125,13 @@ class sram_1bank(sram_base): -max_gap_size - self.data_dff_insts[port].height) self.data_dff_insts[port].place(data_pos[port]) - # Add the write mask flops to the left of the din flops. + # Add the write mask flops below the din flops. if self.write_size is not None: if port in self.write_ports: - wmask_pos[port] = vector(self.bank.bank_array_ll.x - self.control_logic_insts[port].width, - -max_gap_size - self.wmask_dff_insts[port].height) + wmask_pos[port] = vector(self.bank.bank_array_ll.x, + -max_gap_size - self.wmask_dff_insts[port].height) + # wmask_pos[port] = vector(self.bank.bank_array_ll.x - self.control_logic_insts[port].width, + # -max_gap_size - self.wmask_dff_insts[port].height) self.wmask_dff_insts[port].place(wmask_pos[port]) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index f06a56f0..f25e29f3 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -501,7 +501,7 @@ class sram_base(design, verilog, lef): temp.append("clk{}".format(port)) temp.append("rbl_bl{}".format(port)) - # Ouputs + # Outputs if port in self.read_ports: temp.append("s_en{}".format(port)) if port in self.write_ports: diff --git a/compiler/tests/10_write_driver_array_wmask_test.py b/compiler/tests/10_write_driver_array_wmask_test.py index 0a831572..47a3940b 100644 --- a/compiler/tests/10_write_driver_array_wmask_test.py +++ b/compiler/tests/10_write_driver_array_wmask_test.py @@ -20,7 +20,7 @@ import debug class write_driver_test(openram_test): def runTest(self): - globals.init_openram("config_{0}".format(OPTS.tech_name)) + globals.init("config_{0}".format(OPTS.tech_name)) # check write driver array for single port debug.info(2, "Testing write_driver_array for columns=8, word_size=8, write_size=4") @@ -36,19 +36,19 @@ class write_driver_test(openram_test): self.local_check(a) # check write driver array for multi-port - # OPTS.bitcell = "pbitcell" - # OPTS.num_rw_ports = 1 - # OPTS.num_w_ports = 0 - # OPTS.num_r_ports = 0 - # - # factory.reset() - # debug.info(2, "Testing write_driver_array for columns=8, word_size=8, write_size=4 (multi-port case)") - # a = factory.create(module_type="write_driver_array", columns=8, word_size=8, write_size=4) - # self.local_check(a) - # - # debug.info(2, "Testing write_driver_array for columns=16, word_size=8, write_size=4 (multi-port case)") - # a = factory.create(module_type="write_driver_array", columns=16, word_size=8, write_size=4) - # self.local_check(a) + OPTS.bitcell = "pbitcell" + OPTS.num_rw_ports = 1 + OPTS.num_w_ports = 0 + OPTS.num_r_ports = 0 + + factory.reset() + debug.info(2, "Testing write_driver_array for columns=8, word_size=8, write_size=4 (multi-port case)") + a = factory.create(module_type="write_driver_array", columns=8, word_size=8, write_size=4) + self.local_check(a) + + debug.info(2, "Testing write_driver_array for columns=16, word_size=8, write_size=4 (multi-port case)") + a = factory.create(module_type="write_driver_array", columns=16, word_size=8, write_size=4) + self.local_check(a) globals.end_openram() From 858fbb062d44abdf6f8fbe56b4433ca81a427264 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 14 Aug 2019 11:45:22 -0700 Subject: [PATCH 203/234] Placed wmask dff and added connections for wmask pins. --- compiler/modules/bank.py | 24 +++++- compiler/sram/sram_1bank.py | 80 +++++++++++++++---- .../tests/20_sram_1bank_nomux_wmask_test.py | 54 +++++++++++++ 3 files changed, 139 insertions(+), 19 deletions(-) create mode 100644 compiler/tests/20_sram_1bank_nomux_wmask_test.py diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index a5ab4909..445cafc9 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -121,7 +121,7 @@ class bank(design.design): self.route_column_address_lines(port) self.route_control_lines(port) if self.num_banks > 1: - self.route_bank_select(port) + self.route_bank_select(port) self.route_supplies() @@ -700,6 +700,15 @@ class bank(design.design): offset=data_pin.center(), height=data_pin.height(), width=data_pin.width()) + # + # if self.word_size is not None: + # for bit in range(self.num_wmasks): + # wmask_pin = self.port_data_inst[port].get_pin("bank_wmask_{0}".format(bit)) + # self.add_layout_pin_rect_center(text="bank_wmask{0}_{1}".format(port, bit), + # layer=wmask_pin.layer, + # offset=wmask_pin.center(), + # height=wmask_pin.height(), + # width=wmask_pin.width()) def route_port_address_in(self, port): @@ -711,8 +720,9 @@ class bank(design.design): decoder_name = "addr_{}".format(row) addr_name = "addr{0}_{1}".format(port,addr_idx) self.copy_layout_pin(self.port_address_inst[port], decoder_name, addr_name) - - + + + def route_port_data_in(self, port): """ Connecting port data in """ @@ -720,6 +730,14 @@ class bank(design.design): data_name = "din_{}".format(row) din_name = "din{0}_{1}".format(port,row) self.copy_layout_pin(self.port_data_inst[port], data_name, din_name) + + if self.word_size is not None: + for row in range(self.num_wmasks): + wmask_name = "bank_wmask_{}".format(row) + bank_wmask_name = "bank_wmask{0}_{1}".format(port, row) + self.copy_layout_pin(self.port_data_inst[port], wmask_name, bank_wmask_name) + + def channel_route_bitlines(self, inst1, inst2, num_bits, inst1_bl_name="bl_{}", inst1_br_name="br_{}", diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 1100f2cb..b5534226 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -86,9 +86,19 @@ class sram_1bank(sram_base): data_pos[port] = vector(self.bank.bank_array_ll.x, -max_gap_size - self.dff.height) self.data_dff_insts[port].place(data_pos[port]) + else: data_pos[port] = vector(self.bank.bank_array_ll.x,0) + # Add the write mask flops below the din flops. + if self.write_size is not None: + if port in self.write_ports: + wmask_pos[port] = vector(self.bank.bank_array_ll.x, + - 2*max_gap_size - 2*self.dff.height) + self.wmask_dff_insts[port].place(wmask_pos[port]) + else: + wmask_pos[port] = vector(self.bank.bank_array_ll.x, 0) + # Add the col address flops below the bank to the left of the lower-left of bank array if self.col_addr_dff: col_addr_pos[port] = vector(self.bank.bank_array_ll.x - self.col_addr_dff_insts[port].width - self.bank.m2_gap, @@ -125,14 +135,14 @@ class sram_1bank(sram_base): -max_gap_size - self.data_dff_insts[port].height) self.data_dff_insts[port].place(data_pos[port]) - # Add the write mask flops below the din flops. - if self.write_size is not None: - if port in self.write_ports: - wmask_pos[port] = vector(self.bank.bank_array_ll.x, - -max_gap_size - self.wmask_dff_insts[port].height) - # wmask_pos[port] = vector(self.bank.bank_array_ll.x - self.control_logic_insts[port].width, - # -max_gap_size - self.wmask_dff_insts[port].height) - self.wmask_dff_insts[port].place(wmask_pos[port]) + # # Add the write mask flops below the din flops. + # if self.write_size is not None: + # if port in self.write_ports: + # wmask_pos[port] = vector(self.bank.bank_array_ll.x, + # -max_gap_size - self.wmask_dff_insts[port].height) + # # wmask_pos[port] = vector(self.bank.bank_array_ll.x - self.control_logic_insts[port].width, + # # -max_gap_size - self.wmask_dff_insts[port].height) + # self.wmask_dff_insts[port].place(wmask_pos[port]) if len(self.all_ports)>1: @@ -149,6 +159,13 @@ class sram_1bank(sram_base): self.bank.height + max_gap_size + self.dff.height) self.data_dff_insts[port].place(data_pos[port], mirror="MX") + # Add the write mask flops below the din flops. + if self.write_size is not None: + if port in self.write_ports: + wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, + self.bank.height + 2*max_gap_size + 2*self.dff.height) + self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") + # Add the write mask flops to the left of the din flops. if self.write_size is not None: if port in self.write_ports: @@ -191,13 +208,13 @@ class sram_1bank(sram_base): self.bank.height + max_gap_size + self.dff.height) self.data_dff_insts[port].place(data_pos[port], mirror="MX") - # Add the write mask flops to the left of the din flops. - if self.write_size is not None: - if port in self.write_ports: - wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - self.bank.height + max_gap_size + self.data_dff_insts[port].height) - self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") - + # # Add the write mask flops to the left of the din flops. + # if self.write_size is not None: + # if port in self.write_ports: + # wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, + # self.bank.height + max_gap_size + self.data_dff_insts[port].height) + # self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") + # def add_layout_pins(self): """ @@ -222,6 +239,10 @@ class sram_1bank(sram_base): if port in self.write_ports: for bit in range(self.word_size): self.copy_layout_pin(self.data_dff_insts[port], "din_{}".format(bit), "DIN{0}[{1}]".format(port,bit)) + if self.write_size is not None: + for bit in range(self.num_wmasks): + self.copy_layout_pin(self.wmask_dff_insts[port], "din_{}".format(bit), "wmask{0}[{1}]".format(port,bit)) + def route_layout(self): """ Route a single bank SRAM """ @@ -238,6 +259,7 @@ class sram_1bank(sram_base): self.route_col_addr_dff() self.route_data_dff() + self.route_wmask_dff() def route_clk(self): """ Route the clock network """ @@ -290,6 +312,15 @@ class sram_1bank(sram_base): self.add_path("metal2",[mid_pos, clk_steiner_pos], width=max(m2m3.width,m2m3.height)) self.add_wire(("metal3","via2","metal2"),[data_dff_clk_pos, mid_pos, clk_steiner_pos]) + if self.write_size is not None: + wmask_dff_clk_pin = self.wmask_dff_insts[port].get_pin("clk") + wmask_dff_clk_pos = wmask_dff_clk_pin.center() + mid_pos = vector(clk_steiner_pos.x, wmask_dff_clk_pos.y) + # In some designs, the steiner via will be too close to the mid_pos via + # so make the wire as wide as the contacts + self.add_path("metal2", [mid_pos, clk_steiner_pos], width=max(m2m3.width, m2m3.height)) + self.add_wire(("metal3", "via2", "metal2"), [wmask_dff_clk_pos, mid_pos, clk_steiner_pos]) + def route_control_logic(self): """ Route the control logic pins that are not inputs """ @@ -367,7 +398,24 @@ class sram_1bank(sram_base): route_map = list(zip(bank_pins, dff_pins)) self.create_horizontal_channel_route(route_map, offset) - + + def route_wmask_dff(self): + """ Connect the output of the wmask flops to the write mask AND array """ + # This is where the channel will start (y-dimension at least) + for port in self.write_ports: + if port % 2: + offset = self.wmask_dff_insts[port].ll() - vector(0, (self.word_size + 2) * self.m1_pitch) + else: + offset = self.wmask_dff_insts[port].ul() + vector(0, 2 * self.m1_pitch) + + dff_names = ["dout_{}".format(x) for x in range(self.num_wmasks)] + dff_pins = [self.wmask_dff_insts[port].get_pin(x) for x in dff_names] + + bank_names = ["bank_wmask{0}_{1}".format(port, x) for x in range(self.num_wmasks)] + bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] + + route_map = list(zip(bank_pins, dff_pins)) + self.create_horizontal_channel_route(route_map, offset) def add_lvs_correspondence_points(self): diff --git a/compiler/tests/20_sram_1bank_nomux_wmask_test.py b/compiler/tests/20_sram_1bank_nomux_wmask_test.py new file mode 100644 index 00000000..e0292e95 --- /dev/null +++ b/compiler/tests/20_sram_1bank_nomux_wmask_test.py @@ -0,0 +1,54 @@ +#!/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 + + +# @unittest.skip("SKIPPING 20_sram_1bank_nomux_wmask_test") +class sram_1bank_nomux_wmask_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + from sram_config import sram_config + c = sram_config(word_size=8, + write_size=4, + num_words=16, + num_banks=1) + + c.words_per_row = 1 + c.recompute_sizes() + debug.info(1, "Layout test for {}rw,{}r,{}w sram " + "with {} bit words, {} words, {} bit writes, {} words per " + "row, {} banks".format(OPTS.num_rw_ports, + OPTS.num_r_ports, + OPTS.num_w_ports, + c.word_size, + c.num_words, + c.write_size, + c.words_per_row, + c.num_banks)) + a = factory.create(module_type="sram", sram_config=c) + self.local_check(a, final_verification=True) + + 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()) \ No newline at end of file From f0f811bad9d70e4fcd8aadc502aa401e8690f712 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 14 Aug 2019 12:40:14 -0700 Subject: [PATCH 204/234] Added a condiitonal to only route wmask dff when there's a write size. --- compiler/sram/sram_1bank.py | 3 ++- compiler/tests/10_write_driver_array_wmask_test.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index b5534226..b3f6983f 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -259,7 +259,8 @@ class sram_1bank(sram_base): self.route_col_addr_dff() self.route_data_dff() - self.route_wmask_dff() + if self.write_size is not None: + self.route_wmask_dff() def route_clk(self): """ Route the clock network """ diff --git a/compiler/tests/10_write_driver_array_wmask_test.py b/compiler/tests/10_write_driver_array_wmask_test.py index 47a3940b..d09286b5 100644 --- a/compiler/tests/10_write_driver_array_wmask_test.py +++ b/compiler/tests/10_write_driver_array_wmask_test.py @@ -20,7 +20,7 @@ import debug class write_driver_test(openram_test): def runTest(self): - globals.init("config_{0}".format(OPTS.tech_name)) + globals.init_openram("config_{0}".format(OPTS.tech_name)) # check write driver array for single port debug.info(2, "Testing write_driver_array for columns=8, word_size=8, write_size=4") From 92e0671e15b08f00489a95f3f67cf9713b385a56 Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 15 Aug 2019 12:36:17 -0700 Subject: [PATCH 205/234] Removed DRC error with AND array in freepdk45 and moved pin on en_{} pin in port data. --- compiler/modules/port_data.py | 73 +++++++++++------------- compiler/modules/write_mask_and_array.py | 19 ++---- 2 files changed, 40 insertions(+), 52 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 7ce099bb..1052abab 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -124,8 +124,8 @@ class port_data(design.design): if self.port in self.readwrite_ports: # (write_mask_and ->) write_driver -> sense_amp -> (column_mux ->) precharge -> bitcell_array - self.route_write_mask_and(self.port) - self.route_write_mask_and_to_write_driver(self.port) + self.route_write_mask_and_array_in(self.port) + self.route_write_mask_and_array_to_write_driver(self.port) self.route_write_driver_in(self.port) self.route_sense_amp_out(self.port) self.route_write_driver_to_sense_amp(self.port) @@ -138,10 +138,9 @@ class port_data(design.design): self.route_column_mux_to_precharge_array(self.port) else: # (write_mask_and ->) write_driver -> (column_mux ->) precharge -> bitcell_array - self.route_write_mask_and(self.port) - self.route_write_mask_and_to_write_driver(self.port) + self.route_write_mask_and_array_in(self.port) + self.route_write_mask_and_array_to_write_driver(self.port) self.route_write_driver_in(self.port) - self.route_write_mask_and_to_write_driver(self.port) self.route_write_driver_to_column_mux_or_precharge_array(self.port) self.route_column_mux_to_precharge_array(self.port) @@ -432,31 +431,44 @@ class port_data(design.design): self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name) - def route_write_mask_and(self, port): - """ Add pins for the write mask and array output """ - - # for bit in range(self.num_wmasks): - # wmask_out_name = "wmask_out_{}".format(bit) - # wdriver_sel_name = "wdriver_sel_{}".format(bit) - # self.copy_layout_pin(self.write_mask_and_array_inst, wmask_out_name, wdriver_sel_name) + def route_write_mask_and_array_in(self, port): + """ Add pins for the write mask and array input """ for bit in range(self.num_wmasks): wmask_in_name = "wmask_in_{}".format(bit) bank_wmask_name = "bank_wmask_{}".format(bit) self.copy_layout_pin(self.write_mask_and_array_inst, wmask_in_name, bank_wmask_name) + + def route_write_mask_and_array_to_write_driver(self,port): + """ Routing of wdriver_sel_{} between write mask AND array and write driver array. Adds layout pin for write + mask AND array output and via for write driver enable """ + + inst1 = self.write_mask_and_array_inst + inst2 = self.write_driver_array_inst + for bit in range(self.num_wmasks): - wdriver_sel_pin = self.write_mask_and_array_inst.get_pin("wmask_out_{}".format(bit)) - # self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), - # layer=wdriver_sel_pin.layer, - # offset=wdriver_sel_pin.center(), - # height=wdriver_sel_pin.height(), - # width=wdriver_sel_pin.width()) + # Bring write mask AND array output pin to port data level + self.copy_layout_pin(inst1,"wmask_out_{0}".format(bit), "wdriver_sel_{0}".format(bit)) + + # Add via for the write driver enable input in write driver + wmask_out_pin = inst1.get_pin("wmask_out_{0}".format(bit)) + wdriver_en_pin = inst2.get_pin("en_{0}".format(bit)) + center_x = wmask_out_pin.cx() + center_y = wdriver_en_pin.cy() + end_en_pin = vector(wdriver_en_pin.rx(),wmask_out_pin.ly()g) + center_wmask = vector(center_x, center_y) self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=wdriver_sel_pin.center()) + offset=wdriver_en_pin.rc()) self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), layer="metal2", - offset=wdriver_sel_pin.center()) + offset=wdriver_en_pin.rc()) + + # Route between write mask AND array and write driver array + self.add_path("metal1",[ wmask_out_pin.center(), end_en_pin]) + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=end_en_pin) + self.add_path("metal2", [end_en_pin, wdriver_en_pin.rc()]) def route_column_mux_to_precharge_array(self, port): @@ -525,7 +537,7 @@ class port_data(design.design): def route_write_driver_to_sense_amp(self, port): """ Routing of BL and BR between write driver and sense amp """ - + inst1 = self.write_driver_array_inst inst2 = self.sense_amp_array_inst @@ -534,17 +546,6 @@ class port_data(design.design): self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size) - def route_write_mask_and_to_write_driver(self,port): - """ Routing of wdriver_sel_{} between write mask AND array and write driver array """ - inst1 = self.write_mask_and_array_inst - inst2 = self.write_driver_array_inst - - for bit in range(self.num_wmasks): - wdriver_sel_out_pin = inst1.get_pin("wmask_out_{}".format(bit)) - wdriver_sel_in_pin = inst2.get_pin("en_{}".format(bit)) - self.add_path("metal2", [wdriver_sel_out_pin.center(), wdriver_sel_in_pin.center()]) - - def route_bitline_pins(self): """ Add the bitline pins for the given port """ @@ -581,14 +582,8 @@ class port_data(design.design): if self.write_driver_array_inst: if self.write_mask_and_array_inst: for bit in range(self.num_wmasks): + # Add write driver's en_{} pins self.copy_layout_pin(self.write_driver_array_inst, "en_{}".format(bit), "wdriver_sel_{}".format(bit)) - - wdriver_en_pin = self.write_driver_array_inst.get_pin("en_{}".format(bit)) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=wdriver_en_pin.center()) - self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), - layer="metal2", - offset=wdriver_en_pin.center()) else: self.copy_layout_pin(self.write_driver_array_inst, "en", "w_en") if self.write_mask_and_array_inst: diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 878da688..ba78a5a0 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -51,7 +51,6 @@ class write_mask_and_array(design.design): self.place_and2_array() self.add_layout_pins() - # self.route_enable() self.add_boundary() self.DRC_LVS() @@ -121,12 +120,13 @@ class write_mask_and_array(design.design): offset=en_pin.center()) self.add_via_center(layers=("metal2", "via2", "metal3"), offset=en_pin.center()) + if i < self.num_wmasks-1: self.add_layout_pin(text="en", layer="metal3", - offset=en_pin.ll(), - width = self.en_width(i), - height = en_pin.height()) + offset=en_pin.bc(), + width = self.en_width(i), + height = drc('minwidth_metal3')) wmask_out_pin = self.and2_insts[i].get_pin("Z") self.add_layout_pin(text="wmask_out_{0}".format(i), @@ -152,18 +152,11 @@ class write_mask_and_array(design.design): def en_width(self, pin): en_pin = self.and2_insts[pin].get_pin("B") next_en_pin = self.and2_insts[pin+1].get_pin("B") - width = next_en_pin.lr() - en_pin.ll() + width = next_en_pin.center() - en_pin.center() + # Return x coordinates only return width[0] - # def route_enable(self): - # for i in range(self.num_wmasks-1): - # en_pin = self.and2_insts[i].get_pin("B") - # next_en_pin = self.and2_insts[i+1].get_pin("B") - # offset = en_pin.center() - # next_offset = next_en_pin.center() - # self.add_path("metal3", [offset, next_offset]) - def get_cin(self): """Get the relative capacitance of all the input connections in the bank""" # The enable is connected to an and2 for every row. From aaa1e3a61427492dc6d9ba3741824e47db990636 Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 16 Aug 2019 10:23:51 -0700 Subject: [PATCH 206/234] Added change to route wmask en between driver and AND gates. Need to apply it to all cases. --- compiler/modules/port_data.py | 76 ++++++++++++++++++++---- compiler/modules/write_mask_and_array.py | 6 +- 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 1052abab..9325bef5 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -438,6 +438,7 @@ class port_data(design.design): wmask_in_name = "wmask_in_{}".format(bit) bank_wmask_name = "bank_wmask_{}".format(bit) self.copy_layout_pin(self.write_mask_and_array_inst, wmask_in_name, bank_wmask_name) + # self.copy_layout_pin(self.write_mask_and_array_inst,"wmask_out_{0}".format(bit), "wdriver_sel_{0}".format(bit)) def route_write_mask_and_array_to_write_driver(self,port): @@ -447,28 +448,83 @@ class port_data(design.design): inst1 = self.write_mask_and_array_inst inst2 = self.write_driver_array_inst + # get length of a single driver enable + driver = factory.create(module_type="write_driver") + bitcell = factory.create(module_type="bitcell") + if bitcell.width > driver.width: + driver_spacing = bitcell.width + else: + driver_spacing = driver.width + for bit in range(self.num_wmasks): # Bring write mask AND array output pin to port data level - self.copy_layout_pin(inst1,"wmask_out_{0}".format(bit), "wdriver_sel_{0}".format(bit)) + self.copy_layout_pin(inst1, "wmask_out_{0}".format(bit), "wdriver_sel_{0}".format(bit)) - # Add via for the write driver enable input in write driver wmask_out_pin = inst1.get_pin("wmask_out_{0}".format(bit)) wdriver_en_pin = inst2.get_pin("en_{0}".format(bit)) - center_x = wmask_out_pin.cx() - center_y = wdriver_en_pin.cy() - end_en_pin = vector(wdriver_en_pin.rx(),wmask_out_pin.ly()g) - center_wmask = vector(center_x, center_y) + + + bitline_pin = inst2.get_pin("data_{}".format(bit)) + half_width = bitline_pin.width() / 2 + + + width = driver.width + spacing = 2*drc("metal2_to_metal2") + middle_of_driver = driver.width/2 + len_no_drc = middle_of_driver + spacing + half_width + + if self.words_per_row == 1: + length = 3*width + len_no_drc + (bit*driver.width*self.write_size) + else: + length = 3*width + self.words_per_row*driver_spacing + len_no_drc + (bit*self.words_per_row*driver_spacing*driver.width*self.write_size) + # while (wdriver_en_pin.lx() > length): + # length += driver.width + + offset = vector(length, wdriver_en_pin.cy()) + end_en_pin = vector(length,wmask_out_pin.cy()) + + # Add via for the write driver array's enable input self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=wdriver_en_pin.rc()) + offset=offset) self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), layer="metal2", - offset=wdriver_en_pin.rc()) - + offset=offset) # Route between write mask AND array and write driver array self.add_path("metal1",[ wmask_out_pin.center(), end_en_pin]) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=end_en_pin) - self.add_path("metal2", [end_en_pin, wdriver_en_pin.rc()]) + self.add_path("metal2", [end_en_pin, offset]) + + + + # # get length of a single driver enable + # self.driver = factory.create(module_type="write_driver") + # driver_en = self.driver.get_pin("en") + # len = 2*driver_en.width() + bit*driver_en.width() + # + # + # print(len) + # while (wdriver_en_pin.lx() > len): + # len += 2*driver_en.width() + # print("here") + # len += 2*driver_en.width() + # end_en_pin = vector(len,wmask_out_pin.by()) + # + # offset = vector(len, wdriver_en_pin.cy()) + + + # spacing = drc("metal2_to_metal2") + # center_x = wmask_out_pin.cy() + # center_y = wdriver_en_pin.cx() + # end_en_pin = vector(wdriver_en_pin.rx(),wmask_out_pin.by()) + # + # center_wmask = vector(center_x, center_y) + # + # self.add_path("metal2", [wmask_out_pin.center(), wdriver_en_pin.rc()]) + # + # self.add_path("metal2", [wmask_out_pin.center(), wdriver_en_pin.center()]) + + # # def route_column_mux_to_precharge_array(self, port): diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index ba78a5a0..785534be 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -124,9 +124,9 @@ class write_mask_and_array(design.design): if i < self.num_wmasks-1: self.add_layout_pin(text="en", layer="metal3", - offset=en_pin.bc(), - width = self.en_width(i), - height = drc('minwidth_metal3')) + offset=en_pin.bc(), + width = self.en_width(i), + height = drc('minwidth_metal3')) wmask_out_pin = self.and2_insts[i].get_pin("Z") self.add_layout_pin(text="wmask_out_{0}".format(i), From d02ea06ff2d0ff1588d3304b7f19ce9f7e515c3b Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 16 Aug 2019 14:12:41 -0700 Subject: [PATCH 207/234] Added method to route between the output of wmask AND array and en of write driver. --- compiler/modules/port_data.py | 78 ++++++----------------- compiler/tests/18_port_data_wmask_test.py | 6 +- 2 files changed, 21 insertions(+), 63 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 9325bef5..99e1bcba 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -438,7 +438,6 @@ class port_data(design.design): wmask_in_name = "wmask_in_{}".format(bit) bank_wmask_name = "bank_wmask_{}".format(bit) self.copy_layout_pin(self.write_mask_and_array_inst, wmask_in_name, bank_wmask_name) - # self.copy_layout_pin(self.write_mask_and_array_inst,"wmask_out_{0}".format(bit), "wdriver_sel_{0}".format(bit)) def route_write_mask_and_array_to_write_driver(self,port): @@ -448,14 +447,7 @@ class port_data(design.design): inst1 = self.write_mask_and_array_inst inst2 = self.write_driver_array_inst - # get length of a single driver enable - driver = factory.create(module_type="write_driver") - bitcell = factory.create(module_type="bitcell") - if bitcell.width > driver.width: - driver_spacing = bitcell.width - else: - driver_spacing = driver.width - + i = 0 for bit in range(self.num_wmasks): # Bring write mask AND array output pin to port data level self.copy_layout_pin(inst1, "wmask_out_{0}".format(bit), "wdriver_sel_{0}".format(bit)) @@ -463,68 +455,34 @@ class port_data(design.design): wmask_out_pin = inst1.get_pin("wmask_out_{0}".format(bit)) wdriver_en_pin = inst2.get_pin("en_{0}".format(bit)) - - bitline_pin = inst2.get_pin("data_{}".format(bit)) - half_width = bitline_pin.width() / 2 - - - width = driver.width + # The metal2 wdriver_sel_{} wire must hit the en_{} pin after the closest bitline pin that's right of the + # the wdriver_sel_{} pin in the write driver AND array. spacing = 2*drc("metal2_to_metal2") - middle_of_driver = driver.width/2 - len_no_drc = middle_of_driver + spacing + half_width + if bit == 0: + while (wmask_out_pin.lx() > inst2.get_pin("data_{0}".format(i)).rx()): + i += 1 + length = inst2.get_pin("data_{0}".format(i)).rx() + spacing - if self.words_per_row == 1: - length = 3*width + len_no_drc + (bit*driver.width*self.write_size) else: - length = 3*width + self.words_per_row*driver_spacing + len_no_drc + (bit*self.words_per_row*driver_spacing*driver.width*self.write_size) - # while (wdriver_en_pin.lx() > length): - # length += driver.width + i = i + ( bit*self.write_size ) + length = inst2.get_pin("data_{0}".format(i)).rx() + spacing - offset = vector(length, wdriver_en_pin.cy()) - end_en_pin = vector(length,wmask_out_pin.cy()) + beg_pos = wmask_out_pin.center() + middle_pos = vector(length,wmask_out_pin.cy()) + end_pos = vector(length, wdriver_en_pin.cy()) # Add via for the write driver array's enable input self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=offset) + offset=end_pos) self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), layer="metal2", - offset=offset) + offset=end_pos) + # Route between write mask AND array and write driver array - self.add_path("metal1",[ wmask_out_pin.center(), end_en_pin]) + self.add_path("metal1",[beg_pos, middle_pos]) self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=end_en_pin) - self.add_path("metal2", [end_en_pin, offset]) - - - - # # get length of a single driver enable - # self.driver = factory.create(module_type="write_driver") - # driver_en = self.driver.get_pin("en") - # len = 2*driver_en.width() + bit*driver_en.width() - # - # - # print(len) - # while (wdriver_en_pin.lx() > len): - # len += 2*driver_en.width() - # print("here") - # len += 2*driver_en.width() - # end_en_pin = vector(len,wmask_out_pin.by()) - # - # offset = vector(len, wdriver_en_pin.cy()) - - - # spacing = drc("metal2_to_metal2") - # center_x = wmask_out_pin.cy() - # center_y = wdriver_en_pin.cx() - # end_en_pin = vector(wdriver_en_pin.rx(),wmask_out_pin.by()) - # - # center_wmask = vector(center_x, center_y) - # - # self.add_path("metal2", [wmask_out_pin.center(), wdriver_en_pin.rc()]) - # - # self.add_path("metal2", [wmask_out_pin.center(), wdriver_en_pin.center()]) - - # # + offset=middle_pos) + self.add_path("metal2", [middle_pos, end_pos]) def route_column_mux_to_precharge_array(self, port): diff --git a/compiler/tests/18_port_data_wmask_test.py b/compiler/tests/18_port_data_wmask_test.py index e89ea77d..29b0e624 100644 --- a/compiler/tests/18_port_data_wmask_test.py +++ b/compiler/tests/18_port_data_wmask_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +1#!/usr/bin/env python3 # See LICENSE for licensing information. # # Copyright (c) 2016-2019 Regents of the University of California @@ -70,7 +70,7 @@ class port_data_test(openram_test): self.local_check(a) a = factory.create("port_data", sram_config=c, port=1) self.local_check(a) - + # c.num_words = 32 c.words_per_row = 2 factory.reset() @@ -91,7 +91,7 @@ class port_data_test(openram_test): a = factory.create("port_data", sram_config=c, port=1) self.local_check(a) - c.word_size = 2 + c.word_size = 8 c.num_words = 128 c.words_per_row = 8 factory.reset() From a28c9fed8b5c553ce976c6bcb883f5302b71494f Mon Sep 17 00:00:00 2001 From: jsowash Date: Fri, 16 Aug 2019 14:27:44 -0700 Subject: [PATCH 208/234] Fixed bug for more than 2 wmasks and changed test to test 4 wmasks. --- compiler/modules/port_data.py | 12 ++++++------ compiler/tests/18_port_data_wmask_test.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 99e1bcba..bd9b5069 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -447,7 +447,7 @@ class port_data(design.design): inst1 = self.write_mask_and_array_inst inst2 = self.write_driver_array_inst - i = 0 + loc = 0 for bit in range(self.num_wmasks): # Bring write mask AND array output pin to port data level self.copy_layout_pin(inst1, "wmask_out_{0}".format(bit), "wdriver_sel_{0}".format(bit)) @@ -459,13 +459,13 @@ class port_data(design.design): # the wdriver_sel_{} pin in the write driver AND array. spacing = 2*drc("metal2_to_metal2") if bit == 0: - while (wmask_out_pin.lx() > inst2.get_pin("data_{0}".format(i)).rx()): - i += 1 - length = inst2.get_pin("data_{0}".format(i)).rx() + spacing + while (wmask_out_pin.lx() > inst2.get_pin("data_{0}".format(loc)).rx()): + loc += 1 + length = inst2.get_pin("data_{0}".format(loc)).rx() + spacing else: - i = i + ( bit*self.write_size ) - length = inst2.get_pin("data_{0}".format(i)).rx() + spacing + next_loc = loc + ( bit*self.write_size ) + length = inst2.get_pin("data_{0}".format(next_loc)).rx() + spacing beg_pos = wmask_out_pin.center() middle_pos = vector(length,wmask_out_pin.cy()) diff --git a/compiler/tests/18_port_data_wmask_test.py b/compiler/tests/18_port_data_wmask_test.py index 29b0e624..df5f55dc 100644 --- a/compiler/tests/18_port_data_wmask_test.py +++ b/compiler/tests/18_port_data_wmask_test.py @@ -21,7 +21,7 @@ class port_data_test(openram_test): globals.init_openram("config_{0}".format(OPTS.tech_name)) from sram_config import sram_config - c = sram_config(word_size=8, + c = sram_config(word_size=16, write_size=4, num_words=16) From c19bada8df748d631b13b655b2d1afd2ef983d8a Mon Sep 17 00:00:00 2001 From: jsowash Date: Mon, 19 Aug 2019 08:57:05 -0700 Subject: [PATCH 209/234] Performed clean up and added comments. --- compiler/modules/bank.py | 9 --------- compiler/modules/port_data.py | 3 ++- compiler/sram/sram_1bank.py | 37 ++++++++++++++++------------------- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 445cafc9..7d14f601 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -700,15 +700,6 @@ class bank(design.design): offset=data_pin.center(), height=data_pin.height(), width=data_pin.width()) - # - # if self.word_size is not None: - # for bit in range(self.num_wmasks): - # wmask_pin = self.port_data_inst[port].get_pin("bank_wmask_{0}".format(bit)) - # self.add_layout_pin_rect_center(text="bank_wmask{0}_{1}".format(port, bit), - # layer=wmask_pin.layer, - # offset=wmask_pin.center(), - # height=wmask_pin.height(), - # width=wmask_pin.width()) def route_port_address_in(self, port): diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index bd9b5069..3132cc86 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -459,12 +459,13 @@ class port_data(design.design): # the wdriver_sel_{} pin in the write driver AND array. spacing = 2*drc("metal2_to_metal2") if bit == 0: + # When the write mask output pin is right of the bitline, the target is found while (wmask_out_pin.lx() > inst2.get_pin("data_{0}".format(loc)).rx()): loc += 1 length = inst2.get_pin("data_{0}".format(loc)).rx() + spacing else: - next_loc = loc + ( bit*self.write_size ) + next_loc = loc + (bit * self.write_size) length = inst2.get_pin("data_{0}".format(next_loc)).rx() + spacing beg_pos = wmask_out_pin.center() diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index b3f6983f..7725cd3b 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -94,7 +94,7 @@ class sram_1bank(sram_base): if self.write_size is not None: if port in self.write_ports: wmask_pos[port] = vector(self.bank.bank_array_ll.x, - - 2*max_gap_size - 2*self.dff.height) + - 1.5*max_gap_size - 2*self.dff.height) self.wmask_dff_insts[port].place(wmask_pos[port]) else: wmask_pos[port] = vector(self.bank.bank_array_ll.x, 0) @@ -135,15 +135,6 @@ class sram_1bank(sram_base): -max_gap_size - self.data_dff_insts[port].height) self.data_dff_insts[port].place(data_pos[port]) - # # Add the write mask flops below the din flops. - # if self.write_size is not None: - # if port in self.write_ports: - # wmask_pos[port] = vector(self.bank.bank_array_ll.x, - # -max_gap_size - self.wmask_dff_insts[port].height) - # # wmask_pos[port] = vector(self.bank.bank_array_ll.x - self.control_logic_insts[port].width, - # # -max_gap_size - self.wmask_dff_insts[port].height) - # self.wmask_dff_insts[port].place(wmask_pos[port]) - if len(self.all_ports)>1: # Port 1 @@ -163,7 +154,7 @@ class sram_1bank(sram_base): if self.write_size is not None: if port in self.write_ports: wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - self.bank.height + 2*max_gap_size + 2*self.dff.height) + self.bank.height + 1.5*max_gap_size + 2*self.dff.height) self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") # Add the write mask flops to the left of the din flops. @@ -208,14 +199,6 @@ class sram_1bank(sram_base): self.bank.height + max_gap_size + self.dff.height) self.data_dff_insts[port].place(data_pos[port], mirror="MX") - # # Add the write mask flops to the left of the din flops. - # if self.write_size is not None: - # if port in self.write_ports: - # wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - # self.bank.height + max_gap_size + self.data_dff_insts[port].height) - # self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") - # - def add_layout_pins(self): """ Add the top-level pins for a single bank SRAM with control. @@ -412,11 +395,25 @@ class sram_1bank(sram_base): dff_names = ["dout_{}".format(x) for x in range(self.num_wmasks)] dff_pins = [self.wmask_dff_insts[port].get_pin(x) for x in dff_names] + for x in dff_names: + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=self.wmask_dff_insts[port].get_pin(x).center()) + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=self.wmask_dff_insts[port].get_pin(x).center()) + bank_names = ["bank_wmask{0}_{1}".format(port, x) for x in range(self.num_wmasks)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] + for x in bank_names: + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=self.bank_inst.get_pin(x).center()) + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=self.bank_inst.get_pin(x).center()) + route_map = list(zip(bank_pins, dff_pins)) - self.create_horizontal_channel_route(route_map, offset) + self.create_horizontal_channel_route(netlist=route_map, + offset=offset, + layer_stack=("metal3", "via3", "metal4")) def add_lvs_correspondence_points(self): From 316132a33c31b262391edae81f20be769307f394 Mon Sep 17 00:00:00 2001 From: jsowash Date: Mon, 19 Aug 2019 13:31:49 -0700 Subject: [PATCH 210/234] Sized inverter for number of driven write drivers. --- compiler/modules/write_mask_and_array.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 785534be..5fcc39a0 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -64,7 +64,9 @@ class write_mask_and_array(design.design): self.add_pin("gnd","GROUND") def add_modules(self): - self.and2 = factory.create(module_type="pand2") + # Size the AND gate for the number of write drivers it drives, which is equal to the write size. + self.and2 = factory.create(module_type="pand2", + size=self.write_size) self.add_mod(self.and2) From 71af70a6363abff55275c333d5defe4aa1da3172 Mon Sep 17 00:00:00 2001 From: jsowash Date: Tue, 20 Aug 2019 09:14:23 -0700 Subject: [PATCH 211/234] Moved pwr/gnd vias and corrected width boundary. --- compiler/modules/write_mask_and_array.py | 42 ++++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 5fcc39a0..75d39a94 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -44,12 +44,10 @@ class write_mask_and_array(design.design): def create_layout(self): - - self.width = self.num_wmasks * self.and2.width - - self.height = self.and2.height - self.place_and2_array() + spacing = self.wmask_en_len - self.and2.width + self.width = (self.num_wmasks*self.and2.width) + ((self.num_wmasks-1)*spacing) + self.height = self.and2.height self.add_layout_pins() self.add_boundary() self.DRC_LVS() @@ -102,6 +100,7 @@ class write_mask_and_array(design.design): wmask_en_len = self.words_per_row * (self.write_size * self.driver_spacing) if wmask_en_len < self.and2.width: debug.error("Cannot layout write mask AND array. One pand2 is longer than the corresponding write drivers.") + self.wmask_en_len = wmask_en_len for i in range(self.num_wmasks): base = vector(i * wmask_en_len, 0) @@ -109,6 +108,8 @@ class write_mask_and_array(design.design): def add_layout_pins(self): + self.nand2 = factory.create(module_type="pnand2") + supply_pin=self.nand2.get_pin("vdd") for i in range(self.num_wmasks): wmask_in_pin = self.and2_insts[i].get_pin("A") self.add_layout_pin(text="wmask_in_{0}".format(i), @@ -118,8 +119,10 @@ class write_mask_and_array(design.design): height=wmask_in_pin.height()) en_pin = self.and2_insts[i].get_pin("B") + # Add the M1->M2 stack self.add_via_center(layers=("metal1", "via1", "metal2"), offset=en_pin.center()) + # Add the M2->M3 stack self.add_via_center(layers=("metal2", "via2", "metal3"), offset=en_pin.center()) @@ -137,19 +140,22 @@ class write_mask_and_array(design.design): width=wmask_out_pin.width(), height=wmask_out_pin.height()) - for n in ["vdd", "gnd"]: - pin_list = self.and2_insts[i].get_pins(n) - for pin in pin_list: - pin_pos = pin.center() - # Add the M1->M2 stack - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=pin_pos) - # Add the M2->M3 stack - self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=pin_pos) - self.add_layout_pin_rect_center(text=n, - layer="metal3", - offset=pin_pos) + + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=vector(supply_pin.width()+i*self.wmask_en_len,0)) + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=vector(supply_pin.width()+i*self.wmask_en_len,0)) + self.add_layout_pin_rect_center(text="gnd", + layer="metal3", + offset=vector(supply_pin.width()+i*self.wmask_en_len,0)) + + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=vector(supply_pin.width()+i*self.wmask_en_len, self.height)) + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=vector(supply_pin.width()+i*self.wmask_en_len, self.height)) + self.add_layout_pin_rect_center(text="vdd", + layer="metal3", + offset=vector(supply_pin.width()+i*self.wmask_en_len, self.height)) def en_width(self, pin): en_pin = self.and2_insts[pin].get_pin("B") From f2568fec8000b69190cf8a88bc943d179cbd6684 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 08:49:46 -0700 Subject: [PATCH 212/234] Change permissions on tests to +x. Add single bank wmask test. --- .../tests/10_write_driver_array_wmask_test.py | 0 .../tests/10_write_mask_and_array_test.py | 4 +- compiler/tests/18_port_data_wmask_test.py | 4 +- compiler/tests/19_single_bank_wmask_test.py | 68 +++++++++++++++++++ .../tests/20_sram_1bank_nomux_wmask_test.py | 0 5 files changed, 72 insertions(+), 4 deletions(-) mode change 100644 => 100755 compiler/tests/10_write_driver_array_wmask_test.py mode change 100644 => 100755 compiler/tests/10_write_mask_and_array_test.py mode change 100644 => 100755 compiler/tests/18_port_data_wmask_test.py create mode 100755 compiler/tests/19_single_bank_wmask_test.py mode change 100644 => 100755 compiler/tests/20_sram_1bank_nomux_wmask_test.py diff --git a/compiler/tests/10_write_driver_array_wmask_test.py b/compiler/tests/10_write_driver_array_wmask_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/10_write_mask_and_array_test.py b/compiler/tests/10_write_mask_and_array_test.py old mode 100644 new mode 100755 index 830448eb..91155467 --- a/compiler/tests/10_write_mask_and_array_test.py +++ b/compiler/tests/10_write_mask_and_array_test.py @@ -27,7 +27,7 @@ class write_mask_and_array_test(openram_test): a = factory.create(module_type="write_mask_and_array", columns=8, word_size=8, write_size=4) self.local_check(a) - debug.info(2, "Testing write_mask_and_array for columns=8, word_size=8, write_size=4") + debug.info(2, "Testing write_mask_and_array for columns=16, word_size=16, write_size=4") a = factory.create(module_type="write_mask_and_array", columns=16, word_size=16, write_size=4) self.local_check(a) @@ -58,4 +58,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main(testRunner=debugTestRunner()) \ No newline at end of file + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/18_port_data_wmask_test.py b/compiler/tests/18_port_data_wmask_test.py old mode 100644 new mode 100755 index df5f55dc..e9b70337 --- a/compiler/tests/18_port_data_wmask_test.py +++ b/compiler/tests/18_port_data_wmask_test.py @@ -1,4 +1,4 @@ -1#!/usr/bin/env python3 +#!/usr/bin/env python3 # See LICENSE for licensing information. # # Copyright (c) 2016-2019 Regents of the University of California @@ -110,4 +110,4 @@ if __name__ == "__main__": (OPTS, args) = globals.parse_args() del sys.argv[1:] header(__file__, OPTS.tech_name) - unittest.main(testRunner=debugTestRunner()) \ No newline at end of file + unittest.main(testRunner=debugTestRunner()) diff --git a/compiler/tests/19_single_bank_wmask_test.py b/compiler/tests/19_single_bank_wmask_test.py new file mode 100755 index 00000000..439ffeba --- /dev/null +++ b/compiler/tests/19_single_bank_wmask_test.py @@ -0,0 +1,68 @@ +#!/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 single_bank_wmask_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + from sram_config import sram_config + + + c = sram_config(word_size=8, + write_size=4, + num_words=16, + num_banks=1) + + c.words_per_row=1 + factory.reset() + c.recompute_sizes() + debug.info(1, "No column mux") + a = factory.create("bank", sram_config=c) + self.local_check(a) + + c.num_words=32 + c.words_per_row=2 + factory.reset() + c.recompute_sizes() + debug.info(1, "Two way column mux") + a = factory.create("bank", sram_config=c) + self.local_check(a) + + c.num_words=64 + c.words_per_row=4 + factory.reset() + c.recompute_sizes() + debug.info(1, "Four way column mux") + a = factory.create("bank", sram_config=c) + self.local_check(a) + + c.num_words=128 + c.words_per_row=8 + factory.reset() + c.recompute_sizes() + debug.info(1, "Eight way column mux") + a = factory.create("bank", sram_config=c) + 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()) diff --git a/compiler/tests/20_sram_1bank_nomux_wmask_test.py b/compiler/tests/20_sram_1bank_nomux_wmask_test.py old mode 100644 new mode 100755 From 53d0544291ef50b006906135cce4c39ad63a3ab0 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 08:50:12 -0700 Subject: [PATCH 213/234] Minor cleanup and additional assertion checking. --- compiler/modules/port_data.py | 21 ++++++++------------- compiler/modules/write_driver_array.py | 7 +++---- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index 3132cc86..235f370d 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -457,16 +457,17 @@ class port_data(design.design): # The metal2 wdriver_sel_{} wire must hit the en_{} pin after the closest bitline pin that's right of the # the wdriver_sel_{} pin in the write driver AND array. - spacing = 2*drc("metal2_to_metal2") if bit == 0: # When the write mask output pin is right of the bitline, the target is found - while (wmask_out_pin.lx() > inst2.get_pin("data_{0}".format(loc)).rx()): + while (wmask_out_pin.lx() + self.m2_pitch > inst2.get_pin("data_{0}".format(loc)).rx()): loc += 1 - length = inst2.get_pin("data_{0}".format(loc)).rx() + spacing - + length = inst2.get_pin("data_{0}".format(loc)).rx() + self.m2_pitch + debug.check(loc<=self.num_wmasks,"Couldn't route the write mask select.") else: - next_loc = loc + (bit * self.write_size) - length = inst2.get_pin("data_{0}".format(next_loc)).rx() + spacing + # Stride by the write size rather than finding the next pin to the right + loc += self.write_size + length = inst2.get_pin("data_{0}".format(loc)).rx() + self.m2_pitch + beg_pos = wmask_out_pin.center() middle_pos = vector(length,wmask_out_pin.cy()) @@ -475,15 +476,9 @@ class port_data(design.design): # Add via for the write driver array's enable input self.add_via_center(layers=("metal1", "via1", "metal2"), offset=end_pos) - self.add_layout_pin_rect_center(text="wdriver_sel_{0}".format(bit), - layer="metal2", - offset=end_pos) # Route between write mask AND array and write driver array - self.add_path("metal1",[beg_pos, middle_pos]) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=middle_pos) - self.add_path("metal2", [middle_pos, end_pos]) + self.add_wire(("metal1","via1","metal2"), [beg_pos, middle_pos, end_pos]) def route_column_mux_to_precharge_array(self, port): diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index ef87bf6d..b4cb3c77 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -152,11 +152,10 @@ class write_driver_array(design.design): for bit in range(self.num_wmasks): en_pin = self.driver_insts[bit*self.write_size].get_pin("en") # Determine width of wmask modified en_pin with/without col mux + wmask_en_len = self.words_per_row*(self.write_size * self.driver_spacing) if (self.words_per_row == 1): - wmask_en_len = (self.write_size * self.driver_spacing) en_gap = self.driver_spacing - en_pin.width() else: - wmask_en_len = self.words_per_row*(self.write_size * self.driver_spacing) en_gap = self.driver_spacing self.add_layout_pin(text="en_{0}".format(bit), @@ -168,8 +167,8 @@ class write_driver_array(design.design): self.add_layout_pin(text="en", layer="metal1", offset=self.driver_insts[0].get_pin("en").ll().scale(0,1), - width=self.width, - height=drc('minwidth_metal1')) + width=self.width) + From 0cbc4a7acfdfc87adac049e2dc42844e6d4518b8 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 21 Aug 2019 10:07:20 -0700 Subject: [PATCH 214/234] Moved wmask dff above data dff and changed channel route to m3/m4 for data and m1/m2 for wmask. --- compiler/sram/sram_1bank.py | 138 ++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 78 deletions(-) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 7725cd3b..e42970f7 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -43,13 +43,13 @@ class sram_1bank(sram_base): if self.col_addr_dff: self.col_addr_dff_insts = self.create_col_addr_dff() - - self.data_dff_insts = self.create_data_dff() if self.write_size is not None: self.wmask_dff_insts = self.create_wmask_dff() + self.data_dff_insts = self.create_data_dff() + else: + self.data_dff_insts = self.create_data_dff() - def place_instances(self): """ This places the instances for a single bank SRAM with control @@ -67,8 +67,8 @@ class sram_1bank(sram_base): control_pos = [None]*len(self.all_ports) row_addr_pos = [None]*len(self.all_ports) col_addr_pos = [None]*len(self.all_ports) - data_pos = [None]*len(self.all_ports) wmask_pos = [None]*len(self.all_ports) + data_pos = [None]*len(self.all_ports) # This is M2 pitch even though it is on M1 to help stem via spacings on the trunk # The M1 pitch is for supply rail spacings @@ -77,27 +77,34 @@ class sram_1bank(sram_base): # Port 0 port = 0 - # Add the data flops below the bank to the right of the lower-left of bank array - # This relies on the lower-left of the array of the bank - # decoder in upper left, bank in upper right, sensing in lower right. - # These flops go below the sensing and leave a gap to channel route to the - # sense amps. - if port in self.write_ports: - data_pos[port] = vector(self.bank.bank_array_ll.x, - -max_gap_size - self.dff.height) - self.data_dff_insts[port].place(data_pos[port]) - - else: - data_pos[port] = vector(self.bank.bank_array_ll.x,0) - - # Add the write mask flops below the din flops. if self.write_size is not None: if port in self.write_ports: + # Add the write mask flops below the write mask AND array. wmask_pos[port] = vector(self.bank.bank_array_ll.x, - - 1.5*max_gap_size - 2*self.dff.height) + - max_gap_size - self.dff.height) self.wmask_dff_insts[port].place(wmask_pos[port]) + + # Add the data flops below the write mask flops. + data_pos[port] = vector(self.bank.bank_array_ll.x, + -2*max_gap_size - 2*self.dff.height) + self.data_dff_insts[port].place(data_pos[port]) else: - wmask_pos[port] = vector(self.bank.bank_array_ll.x, 0) + wmask_pos[port] = vector(self.bank.bank_array_ll.x, 0) + data_pos[port] = vector(self.bank.bank_array_ll.x,0) + + else: + # Add the data flops below the bank to the right of the lower-left of bank array + # This relies on the lower-left of the array of the bank + # decoder in upper left, bank in upper right, sensing in lower right. + # These flops go below the sensing and leave a gap to channel route to the + # sense amps. + if port in self.write_ports: + data_pos[port] = vector(self.bank.bank_array_ll.x, + -max_gap_size - self.dff.height) + self.data_dff_insts[port].place(data_pos[port]) + + else: + data_pos[port] = vector(self.bank.bank_array_ll.x,0) # Add the col address flops below the bank to the left of the lower-left of bank array if self.col_addr_dff: @@ -125,46 +132,32 @@ class sram_1bank(sram_base): -max_gap_size - self.col_addr_dff_insts[port].height) self.col_addr_dff_insts[port].place(col_addr_pos[port]) - # Add the data flops below the bank to the right of the lower-left of bank array - # This relies on the lower-left of the array of the bank - # decoder in upper left, bank in upper right, sensing in lower right. - # These flops go below the sensing and leave a gap to channel route to the - # sense amps. - if port in self.write_ports: - data_pos[port] = vector(self.bank.bank_array_ll.x, - -max_gap_size - self.data_dff_insts[port].height) - self.data_dff_insts[port].place(data_pos[port]) - if len(self.all_ports)>1: # Port 1 port = 1 - # Add the data flops above the bank to the left of the upper-right of bank array - # This relies on the upper-right of the array of the bank - # decoder in upper left, bank in upper right, sensing in lower right. - # These flops go below the sensing and leave a gap to channel route to the - # sense amps. if port in self.write_ports: - data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - self.bank.height + max_gap_size + self.dff.height) - self.data_dff_insts[port].place(data_pos[port], mirror="MX") - - # Add the write mask flops below the din flops. - if self.write_size is not None: - if port in self.write_ports: + if self.write_size is not None: + # Add the write mask flops below the write mask AND array. wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - self.bank.height + 1.5*max_gap_size + 2*self.dff.height) + self.bank.height + max_gap_size + self.dff.height) self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") - # Add the write mask flops to the left of the din flops. - if self.write_size is not None: - if port in self.write_ports: - wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - self.bank.height + max_gap_size + self.data_dff_insts[port].height) - self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") - else: - data_pos[port] = self.bank_inst.ur() + # Add the data flops below the write mask flops + data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, + self.bank.height + 2*max_gap_size + 2*self.dff.height) + self.data_dff_insts[port].place(data_pos[port], mirror="MX") + + else: + # Add the data flops above the bank to the left of the upper-right of bank array + # This relies on the upper-right of the array of the bank + # decoder in upper left, bank in upper right, sensing in lower right. + # These flops go below the sensing and leave a gap to channel route to the + # sense amps. + data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, + self.bank.height + max_gap_size + self.dff.height) + self.data_dff_insts[port].place(data_pos[port], mirror="MX") # Add the col address flops above the bank to the right of the upper-right of bank array if self.col_addr_dff: @@ -188,16 +181,7 @@ class sram_1bank(sram_base): y_offset = min(self.control_logic_insts[port].by(), self.bank_inst.by() + self.row_addr_dff_insts[port].height) row_addr_pos[port] = vector(x_offset, y_offset) self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="XY") - - # Add the data flops above the bank to the left of the upper-right of bank array - # This relies on the upper-right of the array of the bank - # decoder in upper left, bank in upper right, sensing in lower right. - # These flops go below the sensing and leave a gap to channel route to the - # sense amps. - if port in self.write_ports: - data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - self.bank.height + max_gap_size + self.dff.height) - self.data_dff_insts[port].place(data_pos[port], mirror="MX") + def add_layout_pins(self): """ @@ -376,12 +360,24 @@ class sram_1bank(sram_base): dff_names = ["dout_{}".format(x) for x in range(self.word_size)] dff_pins = [self.data_dff_insts[port].get_pin(x) for x in dff_names] + for x in dff_names: + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=self.data_dff_insts[port].get_pin(x).center()) + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=self.data_dff_insts[port].get_pin(x).center()) bank_names = ["din{0}_{1}".format(port,x) for x in range(self.word_size)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] + for x in bank_names: + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=self.bank_inst.get_pin(x).bc()) + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=self.bank_inst.get_pin(x).bc()) route_map = list(zip(bank_pins, dff_pins)) - self.create_horizontal_channel_route(route_map, offset) + self.create_horizontal_channel_route(netlist=route_map, + offset=offset, + layer_stack=("metal3", "via3", "metal4")) def route_wmask_dff(self): """ Connect the output of the wmask flops to the write mask AND array """ @@ -395,26 +391,12 @@ class sram_1bank(sram_base): dff_names = ["dout_{}".format(x) for x in range(self.num_wmasks)] dff_pins = [self.wmask_dff_insts[port].get_pin(x) for x in dff_names] - for x in dff_names: - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=self.wmask_dff_insts[port].get_pin(x).center()) - self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=self.wmask_dff_insts[port].get_pin(x).center()) - bank_names = ["bank_wmask{0}_{1}".format(port, x) for x in range(self.num_wmasks)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] - for x in bank_names: - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=self.bank_inst.get_pin(x).center()) - self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=self.bank_inst.get_pin(x).center()) - route_map = list(zip(bank_pins, dff_pins)) - self.create_horizontal_channel_route(netlist=route_map, - offset=offset, - layer_stack=("metal3", "via3", "metal4")) - + self.create_horizontal_channel_route(route_map,offset) + def add_lvs_correspondence_points(self): """ From 54ab9440db4f69f634cc40b89e3612c16760b6fa Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 10:18:46 -0700 Subject: [PATCH 215/234] Use pdriver instead of pinv in pand gates. --- compiler/pgates/pand2.py | 5 +++-- compiler/pgates/pand3.py | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index 48f111c7..b241dc55 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -35,8 +35,9 @@ class pand2(pgate.pgate): # Shield the cap, but have at least a stage effort of 4 self.nand = factory.create(module_type="pnand2",height=self.height) self.add_mod(self.nand) - - self.inv = factory.create(module_type="pinv", size=self.size, height=self.height) + + # Assume stage effort of 3 + self.inv = factory.create(module_type="pdriver", neg_polarity=True, fanout=3*self.size, height=self.height) self.add_mod(self.inv) def create_layout(self): diff --git a/compiler/pgates/pand3.py b/compiler/pgates/pand3.py index b221ad84..fcca6672 100644 --- a/compiler/pgates/pand3.py +++ b/compiler/pgates/pand3.py @@ -35,8 +35,9 @@ class pand3(pgate.pgate): # Shield the cap, but have at least a stage effort of 4 self.nand = factory.create(module_type="pnand3",height=self.height) self.add_mod(self.nand) - - self.inv = factory.create(module_type="pinv", size=self.size, height=self.height) + + # Assume stage effort of 3 + self.inv = factory.create(module_type="pdriver", neg_polarity=True, fanout=3*self.size, height=self.height) self.add_mod(self.inv) def create_layout(self): From 43d45fba9807f7ca7ceb193daeff5f65f3e5c816 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 21 Aug 2019 10:44:04 -0700 Subject: [PATCH 216/234] Moved pwr/gnd pins to the right of the rail. --- compiler/modules/write_mask_and_array.py | 28 +++++++++++------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 75d39a94..9f896955 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -140,22 +140,20 @@ class write_mask_and_array(design.design): width=wmask_out_pin.width(), height=wmask_out_pin.height()) + for n in ["vdd", "gnd"]: + pin_list = self.and2_insts[i].get_pins(n) + for pin in pin_list: + pin_pos = pin.lc() + # Add the M1->M2 stack + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=pin_pos) + # Add the M2->M3 stack + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=pin_pos) + self.add_layout_pin_rect_center(text=n, + layer="metal3", + offset=pin_pos) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=vector(supply_pin.width()+i*self.wmask_en_len,0)) - self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=vector(supply_pin.width()+i*self.wmask_en_len,0)) - self.add_layout_pin_rect_center(text="gnd", - layer="metal3", - offset=vector(supply_pin.width()+i*self.wmask_en_len,0)) - - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=vector(supply_pin.width()+i*self.wmask_en_len, self.height)) - self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=vector(supply_pin.width()+i*self.wmask_en_len, self.height)) - self.add_layout_pin_rect_center(text="vdd", - layer="metal3", - offset=vector(supply_pin.width()+i*self.wmask_en_len, self.height)) def en_width(self, pin): en_pin = self.and2_insts[pin].get_pin("B") From 2b7025335cfa62f4f28f5996a4ec018c36a15a96 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 11:20:35 -0700 Subject: [PATCH 217/234] Use pand2 of correct size. Simplify width checking of AND array. --- compiler/modules/write_mask_and_array.py | 17 ++++++----------- compiler/pgates/pand2.py | 1 - compiler/pgates/pdriver.py | 2 +- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 75d39a94..c54d66c2 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -63,8 +63,9 @@ class write_mask_and_array(design.design): def add_modules(self): # Size the AND gate for the number of write drivers it drives, which is equal to the write size. + # Assume stage effort of 3 to compute the size self.and2 = factory.create(module_type="pand2", - size=self.write_size) + size=self.write_size/4.0) self.add_mod(self.and2) @@ -92,18 +93,12 @@ class write_mask_and_array(design.design): else: self.driver_spacing = self.driver.width - if (self.words_per_row == 1): - wmask_en_len = (self.write_size * self.driver_spacing) - if self.driver_spacing * self.write_size < self.and2.width: - debug.error("Cannot layout write mask AND array. One pand2 is longer than the corresponding write drivers.") - else: - wmask_en_len = self.words_per_row * (self.write_size * self.driver_spacing) - if wmask_en_len < self.and2.width: - debug.error("Cannot layout write mask AND array. One pand2 is longer than the corresponding write drivers.") - self.wmask_en_len = wmask_en_len + self.wmask_en_len = self.words_per_row * (self.write_size * self.driver_spacing) + debug.check(self.wmask_en_len >= self.and2.width, + "Write mask AND is wider than the corresponding write drivers {0} vs {1}.".format(self.and2.width,self.wmask_en_len)) for i in range(self.num_wmasks): - base = vector(i * wmask_en_len, 0) + base = vector(i * self.wmask_en_len, 0) self.and2_insts[i].place(base) diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index b241dc55..d71b1e92 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -36,7 +36,6 @@ class pand2(pgate.pgate): self.nand = factory.create(module_type="pnand2",height=self.height) self.add_mod(self.nand) - # Assume stage effort of 3 self.inv = factory.create(module_type="pdriver", neg_polarity=True, fanout=3*self.size, height=self.height) self.add_mod(self.inv) diff --git a/compiler/pgates/pdriver.py b/compiler/pgates/pdriver.py index 36811a5e..ec55f0c7 100644 --- a/compiler/pgates/pdriver.py +++ b/compiler/pgates/pdriver.py @@ -45,7 +45,7 @@ class pdriver(pgate.pgate): self.num_stages = len(self.size_list) else: # Find the optimal number of stages for the given effort - self.num_stages = max(1,int(round(log(self.fanout)/log(self.stage_effort)))) + self.num_stages = max(1,int(round(self.fanout**(1/self.stage_effort)))) # Increase the number of stages if we need to fix polarity if self.neg_polarity and (self.num_stages%2==0): From b94af3e3fdeba5060848736eb2443ac504bcb7ad Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 11:33:43 -0700 Subject: [PATCH 218/234] Add vias for new channel routes --- compiler/sram/sram_1bank.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index e42970f7..083e28fc 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -226,6 +226,7 @@ class sram_1bank(sram_base): self.route_col_addr_dff() self.route_data_dff() + if self.write_size is not None: self.route_wmask_dff() @@ -361,18 +362,24 @@ class sram_1bank(sram_base): dff_names = ["dout_{}".format(x) for x in range(self.word_size)] dff_pins = [self.data_dff_insts[port].get_pin(x) for x in dff_names] for x in dff_names: + offset = self.data_dff_insts[port].get_pin(x).center() self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=self.data_dff_insts[port].get_pin(x).center()) + offset=offset) self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=self.data_dff_insts[port].get_pin(x).center()) + offset=offset) + self.add_via_center(layers=("metal3", "via3", "metal4"), + offset=offset) bank_names = ["din{0}_{1}".format(port,x) for x in range(self.word_size)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] for x in bank_names: + offset = self.bank_inst.get_pin(x).center() self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=self.bank_inst.get_pin(x).bc()) + offset=offset) self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=self.bank_inst.get_pin(x).bc()) + offset=offset) + self.add_via_center(layers=("metal3", "via3", "metal4"), + offset=offset) route_map = list(zip(bank_pins, dff_pins)) self.create_horizontal_channel_route(netlist=route_map, @@ -390,9 +397,18 @@ class sram_1bank(sram_base): dff_names = ["dout_{}".format(x) for x in range(self.num_wmasks)] dff_pins = [self.wmask_dff_insts[port].get_pin(x) for x in dff_names] + for x in dff_names: + offset = self.wmask_dff_insts[port].get_pin(x).center() + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=offset) bank_names = ["bank_wmask{0}_{1}".format(port, x) for x in range(self.num_wmasks)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] + for x in bank_names: + offset = self.bank_inst.get_pin(x).center() + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=offset) + route_map = list(zip(bank_pins, dff_pins)) self.create_horizontal_channel_route(route_map,offset) From b0821a5a0ecc65b07da8757abb17dd5bce5ab04c Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 11:42:56 -0700 Subject: [PATCH 219/234] Re-add simplified power pins on edges --- compiler/modules/write_mask_and_array.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 2456094e..8f30fd2d 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -135,19 +135,9 @@ class write_mask_and_array(design.design): width=wmask_out_pin.width(), height=wmask_out_pin.height()) - for n in ["vdd", "gnd"]: - pin_list = self.and2_insts[i].get_pins(n) - for pin in pin_list: - pin_pos = pin.lc() - # Add the M1->M2 stack - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=pin_pos) - # Add the M2->M3 stack - self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=pin_pos) - self.add_layout_pin_rect_center(text=n, - layer="metal3", - offset=pin_pos) + self.add_power_pin("gnd", vector(supply_pin.width()+i*self.wmask_en_len,0)) + self.add_power_pin("vdd", vector(supply_pin.width()+i*self.wmask_en_len,self.height)) + def en_width(self, pin): From 4813c01d56fff9afb603f2e35280035ed2d7b268 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 21 Aug 2019 11:50:28 -0700 Subject: [PATCH 220/234] Moved dff's up and moved wmask_AND/wdriver pins left/down, respectively. --- compiler/modules/write_mask_and_array.py | 6 +++--- compiler/sram/sram_1bank.py | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 9f896955..68276fab 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -108,8 +108,6 @@ class write_mask_and_array(design.design): def add_layout_pins(self): - self.nand2 = factory.create(module_type="pnand2") - supply_pin=self.nand2.get_pin("vdd") for i in range(self.num_wmasks): wmask_in_pin = self.and2_insts[i].get_pin("A") self.add_layout_pin(text="wmask_in_{0}".format(i), @@ -117,6 +115,8 @@ class write_mask_and_array(design.design): offset=wmask_in_pin.ll(), width=wmask_in_pin.width(), height=wmask_in_pin.height()) + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=wmask_in_pin.center()) en_pin = self.and2_insts[i].get_pin("B") # Add the M1->M2 stack @@ -143,7 +143,7 @@ class write_mask_and_array(design.design): for n in ["vdd", "gnd"]: pin_list = self.and2_insts[i].get_pins(n) for pin in pin_list: - pin_pos = pin.lc() + pin_pos = vector(pin.lx()-0.75*drc('minwidth_metal1'), pin.cy()) # Add the M1->M2 stack self.add_via_center(layers=("metal1", "via1", "metal2"), offset=pin_pos) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index e42970f7..245ec9e9 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -81,12 +81,12 @@ class sram_1bank(sram_base): if port in self.write_ports: # Add the write mask flops below the write mask AND array. wmask_pos[port] = vector(self.bank.bank_array_ll.x, - - max_gap_size - self.dff.height) + -0.5*max_gap_size - self.dff.height) self.wmask_dff_insts[port].place(wmask_pos[port]) # Add the data flops below the write mask flops. data_pos[port] = vector(self.bank.bank_array_ll.x, - -2*max_gap_size - 2*self.dff.height) + -1.5*max_gap_size - 2*self.dff.height) self.data_dff_insts[port].place(data_pos[port]) else: wmask_pos[port] = vector(self.bank.bank_array_ll.x, 0) @@ -355,7 +355,7 @@ class sram_1bank(sram_base): if port%2: offset = self.data_dff_insts[port].ll() - vector(0, (self.word_size+2)*self.m1_pitch) else: - offset = self.data_dff_insts[port].ul() + vector(0, 2*self.m1_pitch) + offset = self.data_dff_insts[port].ul() + vector(0, 2*self.m1_pitch) dff_names = ["dout_{}".format(x) for x in range(self.word_size)] @@ -369,10 +369,12 @@ class sram_1bank(sram_base): bank_names = ["din{0}_{1}".format(port,x) for x in range(self.word_size)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] for x in bank_names: + pin_offset = vector(self.bank_inst.get_pin(x).cx(), + self.bank_inst.get_pin(x).by() - 0.75*drc('minwidth_metal1')) self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=self.bank_inst.get_pin(x).bc()) + offset=pin_offset) self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=self.bank_inst.get_pin(x).bc()) + offset=pin_offset) route_map = list(zip(bank_pins, dff_pins)) self.create_horizontal_channel_route(netlist=route_map, From 4f01eeb3c16425593193772302c5011a73a856a7 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 21 Aug 2019 12:36:53 -0700 Subject: [PATCH 221/234] Combined changes to the pin locations and vias. --- compiler/modules/write_mask_and_array.py | 8 ++++++-- compiler/sram/sram_1bank.py | 25 ++++++++++++------------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index bb10b5b9..a505ae22 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -103,6 +103,8 @@ class write_mask_and_array(design.design): def add_layout_pins(self): + self.nand2 = factory.create(module_type="pnand2") + supply_pin=self.nand2.get_pin("vdd") for i in range(self.num_wmasks): wmask_in_pin = self.and2_insts[i].get_pin("A") self.add_layout_pin(text="wmask_in_{0}".format(i), @@ -135,8 +137,10 @@ class write_mask_and_array(design.design): width=wmask_out_pin.width(), height=wmask_out_pin.height()) - self.add_power_pin("gnd", vector(supply_pin.width()+i*self.wmask_en_len,0)) - self.add_power_pin("vdd", vector(supply_pin.width()+i*self.wmask_en_len,self.height)) + self.add_power_pin("gnd", vector((supply_pin.lx() - 0.75 *drc('minwidth_metal1'))+i*self.wmask_en_len, + 0)) + self.add_power_pin("vdd", vector((supply_pin.lx() - 0.75*drc('minwidth_metal1'))+i*self.wmask_en_len, + self.height)) def en_width(self, pin): diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 634f569c..c4ef0816 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -362,24 +362,25 @@ class sram_1bank(sram_base): dff_names = ["dout_{}".format(x) for x in range(self.word_size)] dff_pins = [self.data_dff_insts[port].get_pin(x) for x in dff_names] for x in dff_names: - offset = self.data_dff_insts[port].get_pin(x).center() + pin_offset = self.data_dff_insts[port].get_pin(x).center() self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=offset) + offset=pin_offset) self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=offset) + offset=pin_offset) self.add_via_center(layers=("metal3", "via3", "metal4"), - offset=offset) + offset=pin_offset) bank_names = ["din{0}_{1}".format(port,x) for x in range(self.word_size)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] for x in bank_names: - offset = self.bank_inst.get_pin(x).center() + pin_offset = vector(self.bank_inst.get_pin(x).cx(), + self.bank_inst.get_pin(x).by() - 0.75 * drc('minwidth_metal1')) self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=offset) + offset=pin_offset) self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=offset) + offset=pin_offset) self.add_via_center(layers=("metal3", "via3", "metal4"), - offset=offset) . + offset=pin_offset) route_map = list(zip(bank_pins, dff_pins)) self.create_horizontal_channel_route(netlist=route_map, @@ -398,16 +399,16 @@ class sram_1bank(sram_base): dff_names = ["dout_{}".format(x) for x in range(self.num_wmasks)] dff_pins = [self.wmask_dff_insts[port].get_pin(x) for x in dff_names] for x in dff_names: - offset = self.wmask_dff_insts[port].get_pin(x).center() + offset_pin = self.wmask_dff_insts[port].get_pin(x).center() self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=offset) + offset=offset_pin) bank_names = ["bank_wmask{0}_{1}".format(port, x) for x in range(self.num_wmasks)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] for x in bank_names: - offset = self.bank_inst.get_pin(x).center() + offset_pin = self.bank_inst.get_pin(x).center() self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=offset) + offset=offset_pin) route_map = list(zip(bank_pins, dff_pins)) From d0f04405a6d164d88890cb74e57300f6b344c723 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 13:45:34 -0700 Subject: [PATCH 222/234] Convert capital names to lower case for consistency --- compiler/base/verilog.py | 42 +++++++++---------- compiler/characterizer/delay.py | 6 +-- compiler/characterizer/functional.py | 6 +-- compiler/characterizer/lib.py | 42 +++++++++---------- compiler/characterizer/simulation.py | 6 +-- compiler/datasheet/datasheet_gen.py | 20 ++++----- compiler/modules/multibank.py | 26 ++++++------ compiler/sram/sram_1bank.py | 8 ++-- compiler/sram/sram_2bank.py | 2 +- compiler/sram/sram_base.py | 24 +++++------ .../tests/golden/sram_2_16_1_freepdk45.lef | 26 ++++++------ .../tests/golden/sram_2_16_1_freepdk45.sp | 42 +++++++++---------- compiler/tests/golden/sram_2_16_1_freepdk45.v | 36 ++++++++-------- ..._16_1_freepdk45_FF_1p0V_25C_analytical.lib | 26 ++++++------ ..._16_1_freepdk45_SS_1p0V_25C_analytical.lib | 26 ++++++------ .../sram_2_16_1_freepdk45_TT_1p0V_25C.lib | 26 ++++++------ ..._16_1_freepdk45_TT_1p0V_25C_analytical.lib | 26 ++++++------ ...am_2_16_1_freepdk45_TT_1p0V_25C_pruned.lib | 26 ++++++------ .../tests/golden/sram_2_16_1_scn4m_subm.lef | 26 ++++++------ .../tests/golden/sram_2_16_1_scn4m_subm.sp | 42 +++++++++---------- .../tests/golden/sram_2_16_1_scn4m_subm.v | 36 ++++++++-------- ...16_1_scn4m_subm_FF_5p0V_25C_analytical.lib | 26 ++++++------ ...16_1_scn4m_subm_SS_5p0V_25C_analytical.lib | 26 ++++++------ .../sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib | 26 ++++++------ ...16_1_scn4m_subm_TT_5p0V_25C_analytical.lib | 26 ++++++------ ...m_2_16_1_scn4m_subm_TT_5p0V_25C_pruned.lib | 26 ++++++------ compiler/tests/sram_1rw_1r_tb.v | 10 ++--- compiler/tests/sram_1rw_tb.v | 6 +-- compiler/tests/sram_1rw_wmask_tb.v | 6 +-- 29 files changed, 336 insertions(+), 336 deletions(-) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index f9043491..d9a812e1 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -39,14 +39,14 @@ class verilog: self.vf.write(" clk{0},csb{0},web{0},".format(port)) if self.write_size is not None: self.vf.write("wmask{},".format(port)) - self.vf.write("ADDR{0},DIN{0},DOUT{0}".format(port)) + self.vf.write("addr{0},din{0},dout{0}".format(port)) elif port in self.write_ports: self.vf.write(" clk{0},csb{0},".format(port)) if self.write_size is not None: self.vf.write("wmask{},".format(port)) - self.vf.write("ADDR{0},DIN{0}".format(port)) + self.vf.write("addr{0},din{0}".format(port)) elif port in self.read_ports: - self.vf.write(" clk{0},csb{0},ADDR{0},DOUT{0}".format(port)) + self.vf.write(" clk{0},csb{0},addr{0},dout{0}".format(port)) # Continue for every port on a new line if port != self.all_ports[-1]: self.vf.write(",\n") @@ -101,11 +101,11 @@ class verilog: if port in self.write_ports: if self.write_size is not None: self.vf.write(" reg [NUM_WMASKS-1:0] wmask{0}_reg;\n".format(port)) - self.vf.write(" reg [ADDR_WIDTH-1:0] ADDR{0}_reg;\n".format(port)) + self.vf.write(" reg [ADDR_WIDTH-1:0] addr{0}_reg;\n".format(port)) if port in self.write_ports: - self.vf.write(" reg [DATA_WIDTH-1:0] DIN{0}_reg;\n".format(port)) + self.vf.write(" reg [DATA_WIDTH-1:0] din{0}_reg;\n".format(port)) if port in self.read_ports: - self.vf.write(" reg [DATA_WIDTH-1:0] DOUT{0};\n".format(port)) + self.vf.write(" reg [DATA_WIDTH-1:0] dout{0};\n".format(port)) def add_flops(self, port): """ @@ -121,29 +121,29 @@ class verilog: if port in self.write_ports: if self.write_size is not None: self.vf.write(" wmask{0}_reg = wmask{0};\n".format(port)) - self.vf.write(" ADDR{0}_reg = ADDR{0};\n".format(port)) + self.vf.write(" addr{0}_reg = addr{0};\n".format(port)) if port in self.write_ports: - self.vf.write(" DIN{0}_reg = DIN{0};\n".format(port)) + self.vf.write(" din{0}_reg = din{0};\n".format(port)) if port in self.read_ports: - self.vf.write(" DOUT{0} = {1}'bx;\n".format(port,self.word_size)) + self.vf.write(" dout{0} = {1}'bx;\n".format(port,self.word_size)) if port in self.readwrite_ports: self.vf.write(" if ( !csb{0}_reg && web{0}_reg ) \n".format(port)) - self.vf.write(" $display($time,\" Reading %m ADDR{0}=%b DOUT{0}=%b\",ADDR{0}_reg,mem[ADDR{0}_reg]);\n".format(port)) + self.vf.write(" $display($time,\" Reading %m addr{0}=%b dout{0}=%b\",addr{0}_reg,mem[addr{0}_reg]);\n".format(port)) elif port in self.read_ports: self.vf.write(" if ( !csb{0}_reg ) \n".format(port)) - self.vf.write(" $display($time,\" Reading %m ADDR{0}=%b DOUT{0}=%b\",ADDR{0}_reg,mem[ADDR{0}_reg]);\n".format(port)) + self.vf.write(" $display($time,\" Reading %m addr{0}=%b dout{0}=%b\",addr{0}_reg,mem[addr{0}_reg]);\n".format(port)) if port in self.readwrite_ports: self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port)) if self.write_size is not None: - self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b wmask{0}=%b\",ADDR{0}_reg,DIN{0}_reg,wmask{0}_reg);\n".format(port)) + self.vf.write(" $display($time,\" Writing %m addr{0}=%b din{0}=%b wmask{0}=%b\",addr{0}_reg,din{0}_reg,wmask{0}_reg);\n".format(port)) else: - self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b\",ADDR{0}_reg,DIN{0}_reg);\n".format(port)) + self.vf.write(" $display($time,\" Writing %m addr{0}=%b din{0}=%b\",addr{0}_reg,din{0}_reg);\n".format(port)) elif port in self.write_ports: self.vf.write(" if ( !csb{0}_reg )\n".format(port)) if self.write_size is not None: - self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b wmask{0}=%b\",ADDR{0}_reg,DIN{0}_reg,wmask{0}_reg);\n".format(port)) + self.vf.write(" $display($time,\" Writing %m addr{0}=%b din{0}=%b wmask{0}=%b\",addr{0}_reg,din{0}_reg,wmask{0}_reg);\n".format(port)) else: - self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b\",ADDR{0}_reg,DIN{0}_reg);\n".format(port)) + self.vf.write(" $display($time,\" Writing %m addr{0}=%b din{0}=%b\",addr{0}_reg,din{0}_reg);\n".format(port)) self.vf.write(" end\n\n") @@ -158,11 +158,11 @@ class verilog: self.vf.write(" input web{0}; // active low write control\n".format(port)) if self.write_size is not None: self.vf.write(" input [NUM_WMASKS-1:0] wmask{0}; // write mask\n".format(port)) - self.vf.write(" input [ADDR_WIDTH-1:0] ADDR{0};\n".format(port)) + self.vf.write(" input [ADDR_WIDTH-1:0] addr{0};\n".format(port)) if port in self.write_ports: - self.vf.write(" input [DATA_WIDTH-1:0] DIN{0};\n".format(port)) + self.vf.write(" input [DATA_WIDTH-1:0] din{0};\n".format(port)) if port in self.read_ports: - self.vf.write(" output [DATA_WIDTH-1:0] DOUT{0};\n".format(port)) + self.vf.write(" output [DATA_WIDTH-1:0] dout{0};\n".format(port)) def add_write_block(self, port): """ @@ -190,10 +190,10 @@ class verilog: lower = mask * self.write_size upper = lower + self.write_size-1 self.vf.write(" if (wmask{0}_reg[{1}])\n".format(port,mask)) - self.vf.write(" mem[ADDR{0}_reg][{1}:{2}] = DIN{0}_reg[{1}:{2}];\n".format(port,upper,lower)) + self.vf.write(" mem[addr{0}_reg][{1}:{2}] = din{0}_reg[{1}:{2}];\n".format(port,upper,lower)) self.vf.write(" end\n") else: - self.vf.write(" mem[ADDR{0}_reg] = DIN{0}_reg;\n".format(port)) + self.vf.write(" mem[addr{0}_reg] = din{0}_reg;\n".format(port)) self.vf.write(" end\n") def add_read_block(self, port): @@ -209,6 +209,6 @@ class verilog: self.vf.write(" if (!csb{0}_reg && web{0}_reg)\n".format(port)) else: self.vf.write(" if (!csb{0}_reg)\n".format(port)) - self.vf.write(" DOUT{0} <= #(DELAY) mem[ADDR{0}_reg];\n".format(port)) + self.vf.write(" dout{0} <= #(DELAY) mem[addr{0}_reg];\n".format(port)) self.vf.write(" end\n") diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 65bc0b78..91be8ae0 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -1191,7 +1191,7 @@ class delay(simulation): self.measure_cycles[write_port][sram_op.WRITE_ZERO] = len(self.cycle_times)-1 # This also ensures we will have a H->L transition on the next read - self.add_read("R data 1 address {} to set DOUT caps".format(inverse_address), + self.add_read("R data 1 address {} to set dout caps".format(inverse_address), inverse_address,data_zeros,wmask_ones,read_port) self.add_read("R data 0 address {} to check W0 worked".format(self.probe_address), @@ -1205,11 +1205,11 @@ class delay(simulation): self.probe_address,data_ones,wmask_ones,write_port) self.measure_cycles[write_port][sram_op.WRITE_ONE] = len(self.cycle_times)-1 - self.add_write("W data 0 address {} to clear DIN caps".format(inverse_address), + self.add_write("W data 0 address {} to clear din caps".format(inverse_address), inverse_address,data_zeros,wmask_ones,write_port) # This also ensures we will have a L->H transition on the next read - self.add_read("R data 0 address {} to clear DOUT caps".format(inverse_address), + self.add_read("R data 0 address {} to clear dout caps".format(inverse_address), inverse_address,data_zeros,wmask_ones,read_port) self.add_read("R data 1 address {} to check W1 worked".format(self.probe_address), diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 6dcb54e0..257c5b8d 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -76,7 +76,7 @@ class functional(simulation): self.write_functional_stimulus() self.stim.run_sim() - # read DOUT values from SPICE simulation. If the values do not fall within the noise margins, return the error. + # read dout values from SPICE simulation. If the values do not fall within the noise margins, return the error. (success, error) = self.read_stim_results() if not success: return (0, error) @@ -189,7 +189,7 @@ class functional(simulation): self.add_noop_all_ports(comment, "0"*self.addr_size, "0"*self.word_size, "0"*self.num_wmasks) def read_stim_results(self): - # Extrat DOUT values from spice timing.lis + # Extrat dout values from spice timing.lis for (word, dout_port, eo_period, check) in self.write_check: sp_read_value = "" for bit in range(self.word_size): @@ -359,7 +359,7 @@ class functional(simulation): t_rise=self.slew, t_fall=self.slew) - # Generate DOUT value measurements + # Generate dout value measurements self.sf.write("\n * Generation of dout measurements\n") for (word, dout_port, eo_period, check) in self.write_check: t_intital = eo_period - 0.01*self.period diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 747e9869..b8a72f77 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -278,10 +278,10 @@ class lib: # self.lib.write(" }\n\n") def write_bus(self): - """ Adds format of DATA and ADDR bus.""" + """ Adds format of data and addr bus.""" self.lib.write("\n\n") - self.lib.write(" type (DATA){\n") + self.lib.write(" type (data){\n") self.lib.write(" base_type : array;\n") self.lib.write(" data_type : bit;\n") self.lib.write(" bit_width : {0};\n".format(self.sram.word_size)) @@ -289,7 +289,7 @@ class lib: self.lib.write(" bit_to : {0};\n".format(self.sram.word_size - 1)) self.lib.write(" }\n\n") - self.lib.write(" type (ADDR){\n") + self.lib.write(" type (addr){\n") self.lib.write(" base_type : array;\n") self.lib.write(" data_type : bit;\n") self.lib.write(" bit_width : {0};\n".format(self.sram.addr_size)) @@ -329,18 +329,18 @@ class lib: def write_data_bus_output(self, read_port): """ Adds data bus timing results.""" - self.lib.write(" bus(DOUT{0}){{\n".format(read_port)) - self.lib.write(" bus_type : DATA; \n") + self.lib.write(" bus(dout{0}){{\n".format(read_port)) + self.lib.write(" bus_type : data; \n") self.lib.write(" direction : output; \n") # This is conservative, but limit to range that we characterized. self.lib.write(" max_capacitance : {0}; \n".format(max(self.loads)/1000)) self.lib.write(" min_capacitance : {0}; \n".format(min(self.loads)/1000)) self.lib.write(" memory_read(){ \n") - self.lib.write(" address : ADDR{0}; \n".format(read_port)) + self.lib.write(" address : addr{0}; \n".format(read_port)) self.lib.write(" }\n") - self.lib.write(" pin(DOUT{0}[{1}:0]){{\n".format(read_port,self.sram.word_size-1)) + self.lib.write(" pin(dout{0}[{1}:0]){{\n".format(read_port,self.sram.word_size-1)) self.lib.write(" timing(){ \n") self.lib.write(" timing_sense : non_unate; \n") self.lib.write(" related_pin : \"clk{0}\"; \n".format(read_port)) @@ -362,18 +362,18 @@ class lib: self.lib.write(" }\n\n") # bus def write_data_bus_input(self, write_port): - """ Adds DIN data bus timing results.""" + """ Adds din data bus timing results.""" - self.lib.write(" bus(DIN{0}){{\n".format(write_port)) - self.lib.write(" bus_type : DATA; \n") + self.lib.write(" bus(din{0}){{\n".format(write_port)) + self.lib.write(" bus_type : data; \n") self.lib.write(" direction : input; \n") # This is conservative, but limit to range that we characterized. self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]/1000)) self.lib.write(" memory_write(){ \n") - self.lib.write(" address : ADDR{0}; \n".format(write_port)) + self.lib.write(" address : addr{0}; \n".format(write_port)) self.lib.write(" clocked_on : clk{0}; \n".format(write_port)) self.lib.write(" }\n") - self.lib.write(" pin(DIN{0}[{1}:0]){{\n".format(write_port,self.sram.word_size-1)) + self.lib.write(" pin(din{0}[{1}:0]){{\n".format(write_port,self.sram.word_size-1)) self.write_FF_setuphold(write_port) self.lib.write(" }\n") # pin self.lib.write(" }\n") #bus @@ -388,12 +388,12 @@ class lib: def write_addr_bus(self, port): """ Adds addr bus timing results.""" - self.lib.write(" bus(ADDR{0}){{\n".format(port)) - self.lib.write(" bus_type : ADDR; \n") + self.lib.write(" bus(addr{0}){{\n".format(port)) + self.lib.write(" bus_type : addr; \n") self.lib.write(" direction : input; \n") self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]/1000)) self.lib.write(" max_transition : {0};\n".format(self.slews[-1])) - self.lib.write(" pin(ADDR{0}[{1}:0])".format(port,self.sram.addr_size-1)) + self.lib.write(" pin(addr{0}[{1}:0])".format(port,self.sram.addr_size-1)) self.lib.write("{\n") self.write_FF_setuphold(port) @@ -577,10 +577,10 @@ class lib: datasheet.write(str(self.sram.width * self.sram.height)+',') # write timing information for all ports for port in self.all_ports: - #DIN timings + #din timings if port in self.write_ports: datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format( - "DIN{1}[{0}:0]".format(self.sram.word_size - 1, port), + "din{1}[{0}:0]".format(self.sram.word_size - 1, port), min(list(map(round_time,self.times["setup_times_LH"]))), max(list(map(round_time,self.times["setup_times_LH"]))), @@ -596,10 +596,10 @@ class lib: )) for port in self.all_ports: - #DOUT timing + #dout timing if port in self.read_ports: datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format( - "DOUT{1}[{0}:0]".format(self.sram.word_size - 1, port), + "dout{1}[{0}:0]".format(self.sram.word_size - 1, port), min(list(map(round_time,self.char_port_results[port]["delay_lh"]))), max(list(map(round_time,self.char_port_results[port]["delay_lh"]))), @@ -634,9 +634,9 @@ class lib: )) for port in self.all_ports: - #ADDR timings + #addr timings datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format( - "ADDR{1}[{0}:0]".format(self.sram.addr_size - 1, port), + "addr{1}[{0}:0]".format(self.sram.addr_size - 1, port), min(list(map(round_time,self.times["setup_times_LH"]))), max(list(map(round_time,self.times["setup_times_LH"]))), diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 657c3609..c889e951 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -53,9 +53,9 @@ class simulation(): self.gnd_voltage = 0 def create_signal_names(self): - self.addr_name = "A" - self.din_name = "DIN" - self.dout_name = "DOUT" + self.addr_name = "a" + self.din_name = "din" + self.dout_name = "dout" self.pins = self.gen_pin_names(port_signal_names=(self.addr_name,self.din_name,self.dout_name), port_info=(len(self.all_ports),self.write_ports,self.read_ports), abits=self.addr_size, diff --git a/compiler/datasheet/datasheet_gen.py b/compiler/datasheet/datasheet_gen.py index 74764789..02ecc5d4 100644 --- a/compiler/datasheet/datasheet_gen.py +++ b/compiler/datasheet/datasheet_gen.py @@ -161,7 +161,7 @@ def parse_characterizer_csv(f, pages): # check current .lib file produces the slowest timing results while(True): col_start = col - if(row[col].startswith('DIN')): + if(row[col].startswith('din')): start = col for item in sheet.timing_table.rows: if item[0].startswith(row[col]): @@ -200,7 +200,7 @@ def parse_characterizer_csv(f, pages): col += 1 - elif(row[col].startswith('DOUT')): + elif(row[col].startswith('dout')): start = col for item in sheet.timing_table.rows: if item[0].startswith(row[col]): @@ -239,7 +239,7 @@ def parse_characterizer_csv(f, pages): col += 1 - elif(row[col].startswith('CSb')): + elif(row[col].startswith('csb')): start = col for item in sheet.timing_table.rows: if item[0].startswith(row[col]): @@ -278,7 +278,7 @@ def parse_characterizer_csv(f, pages): col += 1 - elif(row[col].startswith('WEb')): + elif(row[col].startswith('web')): start = col for item in sheet.timing_table.rows: if item[0].startswith(row[col]): @@ -317,7 +317,7 @@ def parse_characterizer_csv(f, pages): col += 1 - elif(row[col].startswith('ADDR')): + elif(row[col].startswith('addr')): start = col for item in sheet.timing_table.rows: if item[0].startswith(row[col]): @@ -441,7 +441,7 @@ def parse_characterizer_csv(f, pages): # parse initial timing information while(True): col_start = col - if(row[col].startswith('DIN')): + if(row[col].startswith('din')): start = col new_sheet.timing_table.add_row( @@ -465,7 +465,7 @@ def parse_characterizer_csv(f, pages): col += 1 - elif(row[col].startswith('DOUT')): + elif(row[col].startswith('dout')): start = col new_sheet.timing_table.add_row( @@ -489,7 +489,7 @@ def parse_characterizer_csv(f, pages): col += 1 - elif(row[col].startswith('CSb')): + elif(row[col].startswith('csb')): start = col new_sheet.timing_table.add_row( @@ -513,7 +513,7 @@ def parse_characterizer_csv(f, pages): col += 1 - elif(row[col].startswith('WEb')): + elif(row[col].startswith('web')): start = col new_sheet.timing_table.add_row( @@ -537,7 +537,7 @@ def parse_characterizer_csv(f, pages): col += 1 - elif(row[col].startswith('ADDR')): + elif(row[col].startswith('addr')): start = col new_sheet.timing_table.add_row( diff --git a/compiler/modules/multibank.py b/compiler/modules/multibank.py index 28f689f7..4fbacc3f 100644 --- a/compiler/modules/multibank.py +++ b/compiler/modules/multibank.py @@ -65,11 +65,11 @@ class multibank(design.design): def add_pins(self): """ Adding pins for Bank module""" for i in range(self.word_size): - self.add_pin("DOUT_{0}".format(i),"OUT") + self.add_pin("dout_{0}".format(i),"OUT") for i in range(self.word_size): - self.add_pin("BANK_DIN_{0}".format(i),"IN") + self.add_pin("bank_din_{0}".format(i),"IN") for i in range(self.addr_size): - self.add_pin("A_{0}".format(i),"INPUT") + self.add_pin("a_{0}".format(i),"INPUT") # For more than one bank, we have a bank select and name # the signals gated_*. @@ -302,7 +302,7 @@ class multibank(design.design): temp = [] for i in range(self.word_size): - temp.append("BANK_DIN_{0}".format(i)) + temp.append("bank_din_{0}".format(i)) for i in range(self.word_size): if (self.words_per_row == 1): temp.append("bl_{0}".format(i)) @@ -325,7 +325,7 @@ class multibank(design.design): for i in range(self.word_size): temp.append("sa_out_{0}".format(i)) for i in range(self.word_size): - temp.append("DOUT_{0}".format(i)) + temp.append("dout_{0}".format(i)) temp.extend([self.prefix+"tri_en", self.prefix+"tri_en_bar", "vdd", "gnd"]) self.connect_inst(temp) @@ -596,7 +596,7 @@ class multibank(design.design): """ Add pins for the sense amp output """ for i in range(self.word_size): data_pin = self.sense_amp_array_inst.get_pin("data_{}".format(i)) - self.add_layout_pin_rect_center(text="DOUT_{}".format(i), + self.add_layout_pin_rect_center(text="dout_{}".format(i), layer=data_pin.layer, offset=data_pin.center(), height=data_pin.height(), @@ -606,7 +606,7 @@ class multibank(design.design): """ Metal 3 routing of tri_gate output data """ for i in range(self.word_size): data_pin = self.tri_gate_array_inst.get_pin("out_{}".format(i)) - self.add_layout_pin_rect_center(text="DOUT_{}".format(i), + self.add_layout_pin_rect_center(text="dout_{}".format(i), layer=data_pin.layer, offset=data_pin.center(), height=data_pin.height(), @@ -619,8 +619,8 @@ class multibank(design.design): # Create inputs for the row address lines for i in range(self.row_addr_size): addr_idx = i + self.col_addr_size - decoder_name = "A_{}".format(i) - addr_name = "A_{}".format(addr_idx) + decoder_name = "a_{}".format(i) + addr_name = "a_{}".format(addr_idx) self.copy_layout_pin(self.row_decoder_inst, decoder_name, addr_name) @@ -629,7 +629,7 @@ class multibank(design.design): for i in range(self.word_size): data_name = "data_{}".format(i) - din_name = "BANK_DIN_{}".format(i) + din_name = "bank_din_{}".format(i) self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name) @@ -668,7 +668,7 @@ class multibank(design.design): decode_names = ["Zb", "Z"] # The Address LSB - self.copy_layout_pin(self.col_decoder_inst, "A", "A[0]") + self.copy_layout_pin(self.col_decoder_inst, "A", "a[0]") elif self.col_addr_size > 1: decode_names = [] @@ -677,7 +677,7 @@ class multibank(design.design): for i in range(self.col_addr_size): decoder_name = "in_{}".format(i) - addr_name = "A_{}".format(i) + addr_name = "a_{}".format(i) self.copy_layout_pin(self.col_decoder_inst, decoder_name, addr_name) @@ -827,4 +827,4 @@ class multibank(design.design): rotate=90) self.add_via(layers=("metal2","via2","metal3"), offset=in_pin + self.m2m3_via_offset, - rotate=90) \ No newline at end of file + rotate=90) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 51cfeada..8385f289 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -208,18 +208,18 @@ class sram_1bank(sram_base): if port in self.read_ports: for bit in range(self.word_size): - self.copy_layout_pin(self.bank_inst, "dout{0}_{1}".format(port,bit), "DOUT{0}[{1}]".format(port,bit)) + self.copy_layout_pin(self.bank_inst, "dout{0}_{1}".format(port,bit), "dout{0}[{1}]".format(port,bit)) # Lower address bits for bit in range(self.col_addr_size): - self.copy_layout_pin(self.col_addr_dff_insts[port], "din_{}".format(bit),"ADDR{0}[{1}]".format(port,bit)) + self.copy_layout_pin(self.col_addr_dff_insts[port], "din_{}".format(bit),"addr{0}[{1}]".format(port,bit)) # Upper address bits for bit in range(self.row_addr_size): - self.copy_layout_pin(self.row_addr_dff_insts[port], "din_{}".format(bit),"ADDR{0}[{1}]".format(port,bit+self.col_addr_size)) + self.copy_layout_pin(self.row_addr_dff_insts[port], "din_{}".format(bit),"addr{0}[{1}]".format(port,bit+self.col_addr_size)) if port in self.write_ports: for bit in range(self.word_size): - self.copy_layout_pin(self.data_dff_insts[port], "din_{}".format(bit), "DIN{0}[{1}]".format(port,bit)) + self.copy_layout_pin(self.data_dff_insts[port], "din_{}".format(bit), "din{0}[{1}]".format(port,bit)) def route_layout(self): """ Route a single bank SRAM """ diff --git a/compiler/sram/sram_2bank.py b/compiler/sram/sram_2bank.py index 566b0b00..e1224795 100644 --- a/compiler/sram/sram_2bank.py +++ b/compiler/sram/sram_2bank.py @@ -88,7 +88,7 @@ class sram_2bank(sram_base): mod=self.msb_address, offset=self.msb_address_position, rotate=270) - self.msb_bank_sel_addr = "ADDR[{}]".format(self.addr_size-1) + self.msb_bank_sel_addr = "addr[{}]".format(self.addr_size-1) self.connect_inst([self.msb_bank_sel_addr,"bank_sel[1]","bank_sel[0]","clk_buf", "vdd", "gnd"]) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index f06a56f0..ea644f5f 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -48,11 +48,11 @@ class sram_base(design, verilog, lef): for port in self.write_ports: for bit in range(self.word_size): - self.add_pin("DIN{0}[{1}]".format(port,bit),"INPUT") + self.add_pin("din{0}[{1}]".format(port,bit),"INPUT") for port in self.all_ports: for bit in range(self.addr_size): - self.add_pin("ADDR{0}[{1}]".format(port,bit),"INPUT") + self.add_pin("addr{0}[{1}]".format(port,bit),"INPUT") # These are used to create the physical pins self.control_logic_inputs = [] @@ -80,7 +80,7 @@ class sram_base(design, verilog, lef): self.add_pin("wmask{0}[{1}]".format(port,bit),"INPUT") for port in self.read_ports: for bit in range(self.word_size): - self.add_pin("DOUT{0}[{1}]".format(port,bit),"OUTPUT") + self.add_pin("dout{0}[{1}]".format(port,bit),"OUTPUT") self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") @@ -338,15 +338,15 @@ class sram_base(design, verilog, lef): temp = [] for port in self.read_ports: for bit in range(self.word_size): - temp.append("DOUT{0}[{1}]".format(port,bit)) + temp.append("dout{0}[{1}]".format(port,bit)) for port in self.all_ports: temp.append("rbl_bl{0}".format(port)) for port in self.write_ports: for bit in range(self.word_size): - temp.append("BANK_DIN{0}[{1}]".format(port,bit)) + temp.append("bank_din{0}[{1}]".format(port,bit)) for port in self.all_ports: for bit in range(self.bank_addr_size): - temp.append("A{0}[{1}]".format(port,bit)) + temp.append("a{0}[{1}]".format(port,bit)) if(self.num_banks > 1): for port in self.all_ports: temp.append("bank_sel{0}[{1}]".format(port,bank_num)) @@ -408,8 +408,8 @@ class sram_base(design, verilog, lef): inputs = [] outputs = [] for bit in range(self.row_addr_size): - inputs.append("ADDR{}[{}]".format(port,bit+self.col_addr_size)) - outputs.append("A{}[{}]".format(port,bit+self.col_addr_size)) + inputs.append("addr{}[{}]".format(port,bit+self.col_addr_size)) + outputs.append("a{}[{}]".format(port,bit+self.col_addr_size)) self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"]) @@ -427,8 +427,8 @@ class sram_base(design, verilog, lef): inputs = [] outputs = [] for bit in range(self.col_addr_size): - inputs.append("ADDR{}[{}]".format(port,bit)) - outputs.append("A{}[{}]".format(port,bit)) + inputs.append("addr{}[{}]".format(port,bit)) + outputs.append("a{}[{}]".format(port,bit)) self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"]) @@ -450,8 +450,8 @@ class sram_base(design, verilog, lef): inputs = [] outputs = [] for bit in range(self.word_size): - inputs.append("DIN{}[{}]".format(port,bit)) - outputs.append("BANK_DIN{}[{}]".format(port,bit)) + inputs.append("din{}[{}]".format(port,bit)) + outputs.append("bank_din{}[{}]".format(port,bit)) self.connect_inst(inputs + outputs + ["clk_buf{}".format(port), "vdd", "gnd"]) diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45.lef b/compiler/tests/golden/sram_2_16_1_freepdk45.lef index 5a80802d..15ad3a88 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45.lef +++ b/compiler/tests/golden/sram_2_16_1_freepdk45.lef @@ -3,7 +3,7 @@ NAMESCASESENSITIVE ON ; BUSBITCHARS "[]" ; DIVIDERCHAR "/" ; UNITS - DATABASE MICRONS 1000 ; + dataBASE MICRONS 1000 ; END UNITS SITE MacroSite CLASS Core ; @@ -14,48 +14,48 @@ MACRO sram_2_16_1_freepdk45 SIZE 12145.0 BY 43967.5 ; SYMMETRY X Y R90 ; SITE MacroSite ; - PIN DATA[0] + PIN data[0] DIRECTION INOUT ; PORT LAYER metal2 ; RECT 10260.0 67.5 10330.0 207.5 ; END - END DATA[0] - PIN DATA[1] + END data[0] + PIN data[1] DIRECTION INOUT ; PORT LAYER metal2 ; RECT 10965.0 67.5 11035.0 207.5 ; END - END DATA[1] - PIN ADDR[0] + END data[1] + PIN addr[0] DIRECTION INPUT ; PORT LAYER metal3 ; RECT 67.5 8370.0 837.5 8440.0 ; END - END ADDR[0] - PIN ADDR[1] + END addr[0] + PIN addr[1] DIRECTION INPUT ; PORT LAYER metal3 ; RECT 67.5 7665.0 837.5 7735.0 ; END - END ADDR[1] - PIN ADDR[2] + END addr[1] + PIN addr[2] DIRECTION INPUT ; PORT LAYER metal3 ; RECT 67.5 6960.0 837.5 7030.0 ; END - END ADDR[2] - PIN ADDR[3] + END addr[2] + PIN addr[3] DIRECTION INPUT ; PORT LAYER metal3 ; RECT 67.5 6255.0 837.5 6325.0 ; END - END ADDR[3] + END addr[3] PIN CSb DIRECTION INPUT ; PORT diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45.sp b/compiler/tests/golden/sram_2_16_1_freepdk45.sp index 90500f05..c499390e 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45.sp +++ b/compiler/tests/golden/sram_2_16_1_freepdk45.sp @@ -136,10 +136,10 @@ Xpmos1 vdd A net1 vdd nor_2_pmos121 Xpmos2 net1 B Z vdd nor_2_pmos222 .ENDS nor2 -.SUBCKT msf_control DATA[0] DATA[1] DATA[2] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] data_in[2] data_in_bar[2] clk vdd gnd -XXdff0 DATA[0] data_in[0] data_in_bar[0] clk vdd gnd ms_flop -XXdff1 DATA[1] data_in[1] data_in_bar[1] clk vdd gnd ms_flop -XXdff2 DATA[2] data_in[2] data_in_bar[2] clk vdd gnd ms_flop +.SUBCKT msf_control data[0] data[1] data[2] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] data_in[2] data_in_bar[2] clk vdd gnd +XXdff0 data[0] data_in[0] data_in_bar[0] clk vdd gnd ms_flop +XXdff1 data[1] data_in[1] data_in_bar[1] clk vdd gnd ms_flop +XXdff2 data[2] data_in[2] data_in_bar[2] clk vdd gnd ms_flop .ENDS msf_control .SUBCKT replica_cell_6t bl br wl vdd gnd @@ -524,16 +524,16 @@ XINVERTER_[14] Z[14] decode_out[14] vdd gnd INVERTER XINVERTER_[15] Z[15] decode_out[15] vdd gnd INVERTER .ENDS hierarchical_decoder -.SUBCKT msf_address ADDR[0] ADDR[1] ADDR[2] ADDR[3] A[0] A_bar[0] A[1] A_bar[1] A[2] A_bar[2] A[3] A_bar[3] addr_clk vdd gnd -XXdff0 ADDR[0] A[0] A_bar[0] addr_clk vdd gnd ms_flop -XXdff1 ADDR[1] A[1] A_bar[1] addr_clk vdd gnd ms_flop -XXdff2 ADDR[2] A[2] A_bar[2] addr_clk vdd gnd ms_flop -XXdff3 ADDR[3] A[3] A_bar[3] addr_clk vdd gnd ms_flop +.SUBCKT msf_address addr[0] addr[1] addr[2] addr[3] A[0] A_bar[0] A[1] A_bar[1] A[2] A_bar[2] A[3] A_bar[3] addr_clk vdd gnd +XXdff0 addr[0] A[0] A_bar[0] addr_clk vdd gnd ms_flop +XXdff1 addr[1] A[1] A_bar[1] addr_clk vdd gnd ms_flop +XXdff2 addr[2] A[2] A_bar[2] addr_clk vdd gnd ms_flop +XXdff3 addr[3] A[3] A_bar[3] addr_clk vdd gnd ms_flop .ENDS msf_address -.SUBCKT msf_data_in DATA[0] DATA[1] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] clk vdd gnd -XXdff0 DATA[0] data_in[0] data_in_bar[0] clk vdd gnd ms_flop -XXdff1 DATA[1] data_in[1] data_in_bar[1] clk vdd gnd ms_flop +.SUBCKT msf_data_in data[0] data[1] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] clk vdd gnd +XXdff0 data[0] data_in[0] data_in_bar[0] clk vdd gnd ms_flop +XXdff1 data[1] data_in[1] data_in_bar[1] clk vdd gnd ms_flop .ENDS msf_data_in .SUBCKT msf_data_out data_out[0] data_out[1] tri_in[0] tri_in_bar[0] tri_in[1] tri_in_bar[1] sclk vdd gnd @@ -551,9 +551,9 @@ M_6 in_inv in gnd gnd NMOS_VTG W=90.000000n L=50.000000n .ENDS -.SUBCKT tri_gate_array tri_in[0] tri_in[1] DATA[0] DATA[1] en en_bar vdd gnd -XXtri_gate0 tri_in[0] DATA[0] en en_bar vdd gnd tri_gate -XXtri_gate1 tri_in[1] DATA[1] en en_bar vdd gnd tri_gate +.SUBCKT tri_gate_array tri_in[0] tri_in[1] data[0] data[1] en en_bar vdd gnd +XXtri_gate0 tri_in[0] data[0] en en_bar vdd gnd tri_gate +XXtri_gate1 tri_in[1] data[1] en en_bar vdd gnd tri_gate .ENDS tri_gate_array .SUBCKT wordline_driver decode_out[0] decode_out[1] decode_out[2] decode_out[3] decode_out[4] decode_out[5] decode_out[6] decode_out[7] decode_out[8] decode_out[9] decode_out[10] decode_out[11] decode_out[12] decode_out[13] decode_out[14] decode_out[15] wl[0] wl[1] wl[2] wl[3] wl[4] wl[5] wl[6] wl[7] wl[8] wl[9] wl[10] wl[11] wl[12] wl[13] wl[14] wl[15] clk vdd gnd @@ -643,19 +643,19 @@ Xpmos1 vdd A net1 vdd nor_2_pmos185 Xpmos2 net1 B Z vdd nor_2_pmos286 .ENDS NOR2 -.SUBCKT test_bank1 DATA[0] DATA[1] ADDR[0] ADDR[1] ADDR[2] ADDR[3] s_en w_en tri_en_bar tri_en clk_bar clk vdd gnd +.SUBCKT test_bank1 data[0] data[1] addr[0] addr[1] addr[2] addr[3] s_en w_en tri_en_bar tri_en clk_bar clk vdd gnd Xbitcell_array bl[0] br[0] bl[1] br[1] wl[0] wl[1] wl[2] wl[3] wl[4] wl[5] wl[6] wl[7] wl[8] wl[9] wl[10] wl[11] wl[12] wl[13] wl[14] wl[15] vdd gnd bitcell_array Xprecharge_array bl[0] br[0] bl[1] br[1] clk_bar vdd precharge_array Xsense_amp_array bl[0] br[0] bl[1] br[1] data_out[0] data_out[1] s_en vdd gnd sense_amp_array Xwrite_driver_array data_in[0] data_in[1] bl[0] br[0] bl[1] br[1] w_en vdd gnd write_driver_array -Xdata_in_flop_array DATA[0] DATA[1] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] clk_bar vdd gnd msf_data_in -Xtrigate_data_array data_out[0] data_out[1] DATA[0] DATA[1] tri_en tri_en_bar vdd gnd tri_gate_array +Xdata_in_flop_array data[0] data[1] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] clk_bar vdd gnd msf_data_in +Xtrigate_data_array data_out[0] data_out[1] data[0] data[1] tri_en tri_en_bar vdd gnd tri_gate_array Xaddress_decoder A[0] A[1] A[2] A[3] decode_out[0] decode_out[1] decode_out[2] decode_out[3] decode_out[4] decode_out[5] decode_out[6] decode_out[7] decode_out[8] decode_out[9] decode_out[10] decode_out[11] decode_out[12] decode_out[13] decode_out[14] decode_out[15] vdd gnd hierarchical_decoder Xwordline_driver decode_out[0] decode_out[1] decode_out[2] decode_out[3] decode_out[4] decode_out[5] decode_out[6] decode_out[7] decode_out[8] decode_out[9] decode_out[10] decode_out[11] decode_out[12] decode_out[13] decode_out[14] decode_out[15] wl[0] wl[1] wl[2] wl[3] wl[4] wl[5] wl[6] wl[7] wl[8] wl[9] wl[10] wl[11] wl[12] wl[13] wl[14] wl[15] clk vdd gnd wordline_driver -Xaddress_flop_array ADDR[0] ADDR[1] ADDR[2] ADDR[3] A[0] A_bar[0] A[1] A_bar[1] A[2] A_bar[2] A[3] A_bar[3] clk vdd gnd msf_address +Xaddress_flop_array addr[0] addr[1] addr[2] addr[3] A[0] A_bar[0] A[1] A_bar[1] A[2] A_bar[2] A[3] A_bar[3] clk vdd gnd msf_address .ENDS test_bank1 -.SUBCKT testsram DATA[0] DATA[1] ADDR[0] ADDR[1] ADDR[2] ADDR[3] CSb WEb OEb clk vdd gnd -Xbank0 DATA[0] DATA[1] ADDR[0] ADDR[1] ADDR[2] ADDR[3] s_en w_en tri_en_bar tri_en clk_bar clk vdd gnd test_bank1 +.SUBCKT testsram data[0] data[1] addr[0] addr[1] addr[2] addr[3] CSb WEb OEb clk vdd gnd +Xbank0 data[0] data[1] addr[0] addr[1] addr[2] addr[3] s_en w_en tri_en_bar tri_en clk_bar clk vdd gnd test_bank1 Xcontrol CSb WEb OEb s_en w_en tri_en tri_en_bar clk_bar clk vdd gnd control_logic .ENDS testsram diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45.v b/compiler/tests/golden/sram_2_16_1_freepdk45.v index 025350bc..0a71705b 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45.v +++ b/compiler/tests/golden/sram_2_16_1_freepdk45.v @@ -4,50 +4,50 @@ module sram_2_16_1_freepdk45( // Port 0: RW - clk0,csb0,web0,ADDR0,DIN0,DOUT0 + clk0,csb0,web0,addr0,din0,dout0 ); - parameter DATA_WIDTH = 2 ; - parameter ADDR_WIDTH = 4 ; - parameter RAM_DEPTH = 1 << ADDR_WIDTH; + parameter data_WIDTH = 2 ; + parameter addr_WIDTH = 4 ; + parameter RAM_DEPTH = 1 << addr_WIDTH; // FIXME: This delay is arbitrary. parameter DELAY = 3 ; input clk0; // clock input csb0; // active low chip select input web0; // active low write control - input [ADDR_WIDTH-1:0] ADDR0; - input [DATA_WIDTH-1:0] DIN0; - output [DATA_WIDTH-1:0] DOUT0; + input [addr_WIDTH-1:0] addr0; + input [data_WIDTH-1:0] din0; + output [data_WIDTH-1:0] dout0; reg csb0_reg; reg web0_reg; - reg [ADDR_WIDTH-1:0] ADDR0_reg; - reg [DATA_WIDTH-1:0] DIN0_reg; - reg [DATA_WIDTH-1:0] DOUT0; + reg [addr_WIDTH-1:0] addr0_reg; + reg [data_WIDTH-1:0] din0_reg; + reg [data_WIDTH-1:0] dout0; // All inputs are registers always @(posedge clk0) begin csb0_reg = csb0; web0_reg = web0; - ADDR0_reg = ADDR0; - DIN0_reg = DIN0; - DOUT0 = 2'bx; + addr0_reg = addr0; + din0_reg = din0; + dout0 = 2'bx; if ( !csb0_reg && web0_reg ) - $display($time," Reading %m ADDR0=%b DOUT0=%b",ADDR0_reg,mem[ADDR0_reg]); + $display($time," Reading %m addr0=%b dout0=%b",addr0_reg,mem[addr0_reg]); if ( !csb0_reg && !web0_reg ) - $display($time," Writing %m ADDR0=%b DIN0=%b",ADDR0_reg,DIN0_reg); + $display($time," Writing %m addr0=%b din0=%b",addr0_reg,din0_reg); end -reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; +reg [data_WIDTH-1:0] mem [0:RAM_DEPTH-1]; // Memory Write Block Port 0 // Write Operation : When web0 = 0, csb0 = 0 always @ (negedge clk0) begin : MEM_WRITE0 if ( !csb0_reg && !web0_reg ) - mem[ADDR0_reg] = DIN0_reg; + mem[addr0_reg] = din0_reg; end // Memory Read Block Port 0 @@ -55,7 +55,7 @@ reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; always @ (negedge clk0) begin : MEM_READ0 if (!csb0_reg && web0_reg) - DOUT0 <= #(DELAY) mem[ADDR0_reg]; + dout0 <= #(DELAY) mem[addr0_reg]; end endmodule diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib index 48133f90..a1c5a04b 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_FF_1p0V_25C_analytical.lib @@ -52,7 +52,7 @@ library (sram_2_16_1_freepdk45_FF_1p0V_25C_lib){ default_operating_conditions : OC; - type (DATA){ + type (data){ base_type : array; data_type : bit; bit_width : 2; @@ -60,7 +60,7 @@ library (sram_2_16_1_freepdk45_FF_1p0V_25C_lib){ bit_to : 1; } - type (ADDR){ + type (addr){ base_type : array; data_type : bit; bit_width : 4; @@ -85,15 +85,15 @@ cell (sram_2_16_1_freepdk45){ value : 0.000167; } cell_leakage_power : 0; - bus(DIN0){ - bus_type : DATA; + bus(din0){ + bus_type : data; direction : input; capacitance : 0.2091; memory_write(){ - address : ADDR0; + address : addr0; clocked_on : clk0; } - pin(DIN0[1:0]){ + pin(din0[1:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -124,15 +124,15 @@ cell (sram_2_16_1_freepdk45){ } } } - bus(DOUT0){ - bus_type : DATA; + bus(dout0){ + bus_type : data; direction : output; max_capacitance : 1.6728; min_capacitance : 0.052275; memory_read(){ - address : ADDR0; + address : addr0; } - pin(DOUT0[1:0]){ + pin(dout0[1:0]){ timing(){ timing_sense : non_unate; related_pin : "clk0"; @@ -161,12 +161,12 @@ cell (sram_2_16_1_freepdk45){ } } - bus(ADDR0){ - bus_type : ADDR; + bus(addr0){ + bus_type : addr; direction : input; capacitance : 0.2091; max_transition : 0.04; - pin(ADDR0[3:0]){ + pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib index 59b51dfd..865daada 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_SS_1p0V_25C_analytical.lib @@ -52,7 +52,7 @@ library (sram_2_16_1_freepdk45_SS_1p0V_25C_lib){ default_operating_conditions : OC; - type (DATA){ + type (data){ base_type : array; data_type : bit; bit_width : 2; @@ -60,7 +60,7 @@ library (sram_2_16_1_freepdk45_SS_1p0V_25C_lib){ bit_to : 1; } - type (ADDR){ + type (addr){ base_type : array; data_type : bit; bit_width : 4; @@ -85,15 +85,15 @@ cell (sram_2_16_1_freepdk45){ value : 0.000167; } cell_leakage_power : 0; - bus(DIN0){ - bus_type : DATA; + bus(din0){ + bus_type : data; direction : input; capacitance : 0.2091; memory_write(){ - address : ADDR0; + address : addr0; clocked_on : clk0; } - pin(DIN0[1:0]){ + pin(din0[1:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -124,15 +124,15 @@ cell (sram_2_16_1_freepdk45){ } } } - bus(DOUT0){ - bus_type : DATA; + bus(dout0){ + bus_type : data; direction : output; max_capacitance : 1.6728; min_capacitance : 0.052275; memory_read(){ - address : ADDR0; + address : addr0; } - pin(DOUT0[1:0]){ + pin(dout0[1:0]){ timing(){ timing_sense : non_unate; related_pin : "clk0"; @@ -161,12 +161,12 @@ cell (sram_2_16_1_freepdk45){ } } - bus(ADDR0){ - bus_type : ADDR; + bus(addr0){ + bus_type : addr; direction : input; capacitance : 0.2091; max_transition : 0.04; - pin(ADDR0[3:0]){ + pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib index 6b2723a0..72d01a0f 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C.lib @@ -52,7 +52,7 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ default_operating_conditions : OC; - type (DATA){ + type (data){ base_type : array; data_type : bit; bit_width : 2; @@ -60,7 +60,7 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ bit_to : 1; } - type (ADDR){ + type (addr){ base_type : array; data_type : bit; bit_width : 4; @@ -85,15 +85,15 @@ cell (sram_2_16_1_freepdk45){ value : 0.0011164579999999999; } cell_leakage_power : 0; - bus(DIN0){ - bus_type : DATA; + bus(din0){ + bus_type : data; direction : input; capacitance : 0.2091; memory_write(){ - address : ADDR0; + address : addr0; clocked_on : clk0; } - pin(DIN0[1:0]){ + pin(din0[1:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -124,15 +124,15 @@ cell (sram_2_16_1_freepdk45){ } } } - bus(DOUT0){ - bus_type : DATA; + bus(dout0){ + bus_type : data; direction : output; max_capacitance : 1.6728; min_capacitance : 0.052275; memory_read(){ - address : ADDR0; + address : addr0; } - pin(DOUT0[1:0]){ + pin(dout0[1:0]){ timing(){ timing_sense : non_unate; related_pin : "clk0"; @@ -161,12 +161,12 @@ cell (sram_2_16_1_freepdk45){ } } - bus(ADDR0){ - bus_type : ADDR; + bus(addr0){ + bus_type : addr; direction : input; capacitance : 0.2091; max_transition : 0.04; - pin(ADDR0[3:0]){ + pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib index 4708c2ef..33587063 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_analytical.lib @@ -52,7 +52,7 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ default_operating_conditions : OC; - type (DATA){ + type (data){ base_type : array; data_type : bit; bit_width : 2; @@ -60,7 +60,7 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ bit_to : 1; } - type (ADDR){ + type (addr){ base_type : array; data_type : bit; bit_width : 4; @@ -85,15 +85,15 @@ cell (sram_2_16_1_freepdk45){ value : 0.000179; } cell_leakage_power : 0; - bus(DIN0){ - bus_type : DATA; + bus(din0){ + bus_type : data; direction : input; capacitance : 0.2091; memory_write(){ - address : ADDR0; + address : addr0; clocked_on : clk0; } - pin(DIN0[1:0]){ + pin(din0[1:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -124,15 +124,15 @@ cell (sram_2_16_1_freepdk45){ } } } - bus(DOUT0){ - bus_type : DATA; + bus(dout0){ + bus_type : data; direction : output; max_capacitance : 1.6728; min_capacitance : 0.052275; memory_read(){ - address : ADDR0; + address : addr0; } - pin(DOUT0[1:0]){ + pin(dout0[1:0]){ timing(){ timing_sense : non_unate; related_pin : "clk0"; @@ -161,12 +161,12 @@ cell (sram_2_16_1_freepdk45){ } } - bus(ADDR0){ - bus_type : ADDR; + bus(addr0){ + bus_type : addr; direction : input; capacitance : 0.2091; max_transition : 0.04; - pin(ADDR0[3:0]){ + pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_pruned.lib b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_pruned.lib index dbd7e03b..5817211b 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_pruned.lib +++ b/compiler/tests/golden/sram_2_16_1_freepdk45_TT_1p0V_25C_pruned.lib @@ -52,7 +52,7 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ default_operating_conditions : OC; - type (DATA){ + type (data){ base_type : array; data_type : bit; bit_width : 2; @@ -60,7 +60,7 @@ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){ bit_to : 1; } - type (ADDR){ + type (addr){ base_type : array; data_type : bit; bit_width : 4; @@ -85,15 +85,15 @@ cell (sram_2_16_1_freepdk45){ value : 0.0011164579999999999; } cell_leakage_power : 0; - bus(DIN0){ - bus_type : DATA; + bus(din0){ + bus_type : data; direction : input; capacitance : 0.2091; memory_write(){ - address : ADDR0; + address : addr0; clocked_on : clk0; } - pin(DIN0[1:0]){ + pin(din0[1:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -124,15 +124,15 @@ cell (sram_2_16_1_freepdk45){ } } } - bus(DOUT0){ - bus_type : DATA; + bus(dout0){ + bus_type : data; direction : output; max_capacitance : 1.6728; min_capacitance : 0.052275; memory_read(){ - address : ADDR0; + address : addr0; } - pin(DOUT0[1:0]){ + pin(dout0[1:0]){ timing(){ timing_sense : non_unate; related_pin : "clk0"; @@ -161,12 +161,12 @@ cell (sram_2_16_1_freepdk45){ } } - bus(ADDR0){ - bus_type : ADDR; + bus(addr0){ + bus_type : addr; direction : input; capacitance : 0.2091; max_transition : 0.04; - pin(ADDR0[3:0]){ + pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm.lef b/compiler/tests/golden/sram_2_16_1_scn4m_subm.lef index 9d784677..08ebcdb2 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm.lef +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm.lef @@ -3,7 +3,7 @@ NAMESCASESENSITIVE ON ; BUSBITCHARS "[]" ; DIVIDERCHAR "/" ; UNITS - DATABASE MICRONS 1000 ; + dataBASE MICRONS 1000 ; END UNITS SITE MacroSite CLASS Core ; @@ -14,48 +14,48 @@ MACRO sram_2_16_1_scn3me_subm SIZE 148050.0 BY 461850.0 ; SYMMETRY X Y R90 ; SITE MacroSite ; - PIN DATA[0] + PIN data[0] DIRECTION INOUT ; PORT LAYER metal2 ; RECT 120900.0 0.0 121800.0 1800.0 ; END - END DATA[0] - PIN DATA[1] + END data[0] + PIN data[1] DIRECTION INOUT ; PORT LAYER metal2 ; RECT 131100.0 0.0 132000.0 1800.0 ; END - END DATA[1] - PIN ADDR[0] + END data[1] + PIN addr[0] DIRECTION INPUT ; PORT LAYER metal3 ; RECT 0.0 87600.0 10800.0 89100.0 ; END - END ADDR[0] - PIN ADDR[1] + END addr[0] + PIN addr[1] DIRECTION INPUT ; PORT LAYER metal3 ; RECT 0.0 77400.0 10800.0 78900.0 ; END - END ADDR[1] - PIN ADDR[2] + END addr[1] + PIN addr[2] DIRECTION INPUT ; PORT LAYER metal3 ; RECT 0.0 67200.0 10800.0 68700.0 ; END - END ADDR[2] - PIN ADDR[3] + END addr[2] + PIN addr[3] DIRECTION INPUT ; PORT LAYER metal3 ; RECT 0.0 57000.0 10800.0 58500.0 ; END - END ADDR[3] + END addr[3] PIN CSb DIRECTION INPUT ; PORT diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm.sp b/compiler/tests/golden/sram_2_16_1_scn4m_subm.sp index 258b4464..1b8d4e07 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm.sp +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm.sp @@ -136,10 +136,10 @@ Xpmos1 vdd A net1 vdd nor_2_pmos125 Xpmos2 net1 B Z vdd nor_2_pmos226 .ENDS nor2 -.SUBCKT msf_control DATA[0] DATA[1] DATA[2] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] data_in[2] data_in_bar[2] clk vdd gnd -XXdff0 DATA[0] data_in[0] data_in_bar[0] clk vdd gnd ms_flop -XXdff1 DATA[1] data_in[1] data_in_bar[1] clk vdd gnd ms_flop -XXdff2 DATA[2] data_in[2] data_in_bar[2] clk vdd gnd ms_flop +.SUBCKT msf_control data[0] data[1] data[2] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] data_in[2] data_in_bar[2] clk vdd gnd +XXdff0 data[0] data_in[0] data_in_bar[0] clk vdd gnd ms_flop +XXdff1 data[1] data_in[1] data_in_bar[1] clk vdd gnd ms_flop +XXdff2 data[2] data_in[2] data_in_bar[2] clk vdd gnd ms_flop .ENDS msf_control *********************** "cell_6t" ****************************** @@ -541,16 +541,16 @@ XINVERTER_[14] Z[14] decode_out[14] vdd gnd INVERTER XINVERTER_[15] Z[15] decode_out[15] vdd gnd INVERTER .ENDS hierarchical_decoder -.SUBCKT msf_address ADDR[0] ADDR[1] ADDR[2] ADDR[3] A[0] A_bar[0] A[1] A_bar[1] A[2] A_bar[2] A[3] A_bar[3] addr_clk vdd gnd -XXdff0 ADDR[0] A[0] A_bar[0] addr_clk vdd gnd ms_flop -XXdff1 ADDR[1] A[1] A_bar[1] addr_clk vdd gnd ms_flop -XXdff2 ADDR[2] A[2] A_bar[2] addr_clk vdd gnd ms_flop -XXdff3 ADDR[3] A[3] A_bar[3] addr_clk vdd gnd ms_flop +.SUBCKT msf_address addr[0] addr[1] addr[2] addr[3] A[0] A_bar[0] A[1] A_bar[1] A[2] A_bar[2] A[3] A_bar[3] addr_clk vdd gnd +XXdff0 addr[0] A[0] A_bar[0] addr_clk vdd gnd ms_flop +XXdff1 addr[1] A[1] A_bar[1] addr_clk vdd gnd ms_flop +XXdff2 addr[2] A[2] A_bar[2] addr_clk vdd gnd ms_flop +XXdff3 addr[3] A[3] A_bar[3] addr_clk vdd gnd ms_flop .ENDS msf_address -.SUBCKT msf_data_in DATA[0] DATA[1] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] clk vdd gnd -XXdff0 DATA[0] data_in[0] data_in_bar[0] clk vdd gnd ms_flop -XXdff1 DATA[1] data_in[1] data_in_bar[1] clk vdd gnd ms_flop +.SUBCKT msf_data_in data[0] data[1] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] clk vdd gnd +XXdff0 data[0] data_in[0] data_in_bar[0] clk vdd gnd ms_flop +XXdff1 data[1] data_in[1] data_in_bar[1] clk vdd gnd ms_flop .ENDS msf_data_in .SUBCKT msf_data_out data_out[0] data_out[1] tri_in[0] tri_in_bar[0] tri_in[1] tri_in_bar[1] sclk vdd gnd @@ -571,9 +571,9 @@ M_6 in_inv in gnd gnd n W='1.2*1u' L=0.6u .ENDS -.SUBCKT tri_gate_array tri_in[0] tri_in[1] DATA[0] DATA[1] en en_bar vdd gnd -XXtri_gate0 tri_in[0] DATA[0] en en_bar vdd gnd tri_gate -XXtri_gate1 tri_in[1] DATA[1] en en_bar vdd gnd tri_gate +.SUBCKT tri_gate_array tri_in[0] tri_in[1] data[0] data[1] en en_bar vdd gnd +XXtri_gate0 tri_in[0] data[0] en en_bar vdd gnd tri_gate +XXtri_gate1 tri_in[1] data[1] en en_bar vdd gnd tri_gate .ENDS tri_gate_array .SUBCKT wordline_driver decode_out[0] decode_out[1] decode_out[2] decode_out[3] decode_out[4] decode_out[5] decode_out[6] decode_out[7] decode_out[8] decode_out[9] decode_out[10] decode_out[11] decode_out[12] decode_out[13] decode_out[14] decode_out[15] wl[0] wl[1] wl[2] wl[3] wl[4] wl[5] wl[6] wl[7] wl[8] wl[9] wl[10] wl[11] wl[12] wl[13] wl[14] wl[15] clk vdd gnd @@ -663,19 +663,19 @@ Xpmos1 vdd A net1 vdd nor_2_pmos197 Xpmos2 net1 B Z vdd nor_2_pmos298 .ENDS NOR2 -.SUBCKT test_bank1 DATA[0] DATA[1] ADDR[0] ADDR[1] ADDR[2] ADDR[3] s_en w_en tri_en_bar tri_en clk_bar clk vdd gnd +.SUBCKT test_bank1 data[0] data[1] addr[0] addr[1] addr[2] addr[3] s_en w_en tri_en_bar tri_en clk_bar clk vdd gnd Xbitcell_array bl[0] br[0] bl[1] br[1] wl[0] wl[1] wl[2] wl[3] wl[4] wl[5] wl[6] wl[7] wl[8] wl[9] wl[10] wl[11] wl[12] wl[13] wl[14] wl[15] vdd gnd bitcell_array Xprecharge_array bl[0] br[0] bl[1] br[1] clk_bar vdd precharge_array Xsense_amp_array bl[0] br[0] bl[1] br[1] data_out[0] data_out[1] s_en vdd gnd sense_amp_array Xwrite_driver_array data_in[0] data_in[1] bl[0] br[0] bl[1] br[1] w_en vdd gnd write_driver_array -Xdata_in_flop_array DATA[0] DATA[1] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] clk_bar vdd gnd msf_data_in -Xtrigate_data_array data_out[0] data_out[1] DATA[0] DATA[1] tri_en tri_en_bar vdd gnd tri_gate_array +Xdata_in_flop_array data[0] data[1] data_in[0] data_in_bar[0] data_in[1] data_in_bar[1] clk_bar vdd gnd msf_data_in +Xtrigate_data_array data_out[0] data_out[1] data[0] data[1] tri_en tri_en_bar vdd gnd tri_gate_array Xaddress_decoder A[0] A[1] A[2] A[3] decode_out[0] decode_out[1] decode_out[2] decode_out[3] decode_out[4] decode_out[5] decode_out[6] decode_out[7] decode_out[8] decode_out[9] decode_out[10] decode_out[11] decode_out[12] decode_out[13] decode_out[14] decode_out[15] vdd gnd hierarchical_decoder Xwordline_driver decode_out[0] decode_out[1] decode_out[2] decode_out[3] decode_out[4] decode_out[5] decode_out[6] decode_out[7] decode_out[8] decode_out[9] decode_out[10] decode_out[11] decode_out[12] decode_out[13] decode_out[14] decode_out[15] wl[0] wl[1] wl[2] wl[3] wl[4] wl[5] wl[6] wl[7] wl[8] wl[9] wl[10] wl[11] wl[12] wl[13] wl[14] wl[15] clk vdd gnd wordline_driver -Xaddress_flop_array ADDR[0] ADDR[1] ADDR[2] ADDR[3] A[0] A_bar[0] A[1] A_bar[1] A[2] A_bar[2] A[3] A_bar[3] clk vdd gnd msf_address +Xaddress_flop_array addr[0] addr[1] addr[2] addr[3] A[0] A_bar[0] A[1] A_bar[1] A[2] A_bar[2] A[3] A_bar[3] clk vdd gnd msf_address .ENDS test_bank1 -.SUBCKT testsram DATA[0] DATA[1] ADDR[0] ADDR[1] ADDR[2] ADDR[3] CSb WEb OEb clk vdd gnd -Xbank0 DATA[0] DATA[1] ADDR[0] ADDR[1] ADDR[2] ADDR[3] s_en w_en tri_en_bar tri_en clk_bar clk vdd gnd test_bank1 +.SUBCKT testsram data[0] data[1] addr[0] addr[1] addr[2] addr[3] CSb WEb OEb clk vdd gnd +Xbank0 data[0] data[1] addr[0] addr[1] addr[2] addr[3] s_en w_en tri_en_bar tri_en clk_bar clk vdd gnd test_bank1 Xcontrol CSb WEb OEb s_en w_en tri_en tri_en_bar clk_bar clk vdd gnd control_logic .ENDS testsram diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm.v b/compiler/tests/golden/sram_2_16_1_scn4m_subm.v index 7017b8a7..4c39ddb5 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm.v +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm.v @@ -4,50 +4,50 @@ module sram_2_16_1_scn4m_subm( // Port 0: RW - clk0,csb0,web0,ADDR0,DIN0,DOUT0 + clk0,csb0,web0,addr0,din0,dout0 ); - parameter DATA_WIDTH = 2 ; - parameter ADDR_WIDTH = 4 ; - parameter RAM_DEPTH = 1 << ADDR_WIDTH; + parameter data_WIDTH = 2 ; + parameter addr_WIDTH = 4 ; + parameter RAM_DEPTH = 1 << addr_WIDTH; // FIXME: This delay is arbitrary. parameter DELAY = 3 ; input clk0; // clock input csb0; // active low chip select input web0; // active low write control - input [ADDR_WIDTH-1:0] ADDR0; - input [DATA_WIDTH-1:0] DIN0; - output [DATA_WIDTH-1:0] DOUT0; + input [addr_WIDTH-1:0] addr0; + input [data_WIDTH-1:0] din0; + output [data_WIDTH-1:0] dout0; reg csb0_reg; reg web0_reg; - reg [ADDR_WIDTH-1:0] ADDR0_reg; - reg [DATA_WIDTH-1:0] DIN0_reg; - reg [DATA_WIDTH-1:0] DOUT0; + reg [addr_WIDTH-1:0] addr0_reg; + reg [data_WIDTH-1:0] din0_reg; + reg [data_WIDTH-1:0] dout0; // All inputs are registers always @(posedge clk0) begin csb0_reg = csb0; web0_reg = web0; - ADDR0_reg = ADDR0; - DIN0_reg = DIN0; - DOUT0 = 2'bx; + addr0_reg = addr0; + din0_reg = din0; + dout0 = 2'bx; if ( !csb0_reg && web0_reg ) - $display($time," Reading %m ADDR0=%b DOUT0=%b",ADDR0_reg,mem[ADDR0_reg]); + $display($time," Reading %m addr0=%b dout0=%b",addr0_reg,mem[addr0_reg]); if ( !csb0_reg && !web0_reg ) - $display($time," Writing %m ADDR0=%b DIN0=%b",ADDR0_reg,DIN0_reg); + $display($time," Writing %m addr0=%b din0=%b",addr0_reg,din0_reg); end -reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; +reg [data_WIDTH-1:0] mem [0:RAM_DEPTH-1]; // Memory Write Block Port 0 // Write Operation : When web0 = 0, csb0 = 0 always @ (negedge clk0) begin : MEM_WRITE0 if ( !csb0_reg && !web0_reg ) - mem[ADDR0_reg] = DIN0_reg; + mem[addr0_reg] = din0_reg; end // Memory Read Block Port 0 @@ -55,7 +55,7 @@ reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; always @ (negedge clk0) begin : MEM_READ0 if (!csb0_reg && web0_reg) - DOUT0 <= #(DELAY) mem[ADDR0_reg]; + dout0 <= #(DELAY) mem[addr0_reg]; end endmodule diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib index eef7df1b..c370f993 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_FF_5p0V_25C_analytical.lib @@ -52,7 +52,7 @@ library (sram_2_16_1_scn4m_subm_FF_5p0V_25C_lib){ default_operating_conditions : OC; - type (DATA){ + type (data){ base_type : array; data_type : bit; bit_width : 2; @@ -60,7 +60,7 @@ library (sram_2_16_1_scn4m_subm_FF_5p0V_25C_lib){ bit_to : 1; } - type (ADDR){ + type (addr){ base_type : array; data_type : bit; bit_width : 4; @@ -85,15 +85,15 @@ cell (sram_2_16_1_scn4m_subm){ value : 0.000167; } cell_leakage_power : 0; - bus(DIN0){ - bus_type : DATA; + bus(din0){ + bus_type : data; direction : input; capacitance : 9.8242; memory_write(){ - address : ADDR0; + address : addr0; clocked_on : clk0; } - pin(DIN0[1:0]){ + pin(din0[1:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -124,15 +124,15 @@ cell (sram_2_16_1_scn4m_subm){ } } } - bus(DOUT0){ - bus_type : DATA; + bus(dout0){ + bus_type : data; direction : output; max_capacitance : 78.5936; min_capacitance : 2.45605; memory_read(){ - address : ADDR0; + address : addr0; } - pin(DOUT0[1:0]){ + pin(dout0[1:0]){ timing(){ timing_sense : non_unate; related_pin : "clk0"; @@ -161,12 +161,12 @@ cell (sram_2_16_1_scn4m_subm){ } } - bus(ADDR0){ - bus_type : ADDR; + bus(addr0){ + bus_type : addr; direction : input; capacitance : 9.8242; max_transition : 0.4; - pin(ADDR0[3:0]){ + pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib index 2f5c534c..f52de676 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_SS_5p0V_25C_analytical.lib @@ -52,7 +52,7 @@ library (sram_2_16_1_scn4m_subm_SS_5p0V_25C_lib){ default_operating_conditions : OC; - type (DATA){ + type (data){ base_type : array; data_type : bit; bit_width : 2; @@ -60,7 +60,7 @@ library (sram_2_16_1_scn4m_subm_SS_5p0V_25C_lib){ bit_to : 1; } - type (ADDR){ + type (addr){ base_type : array; data_type : bit; bit_width : 4; @@ -85,15 +85,15 @@ cell (sram_2_16_1_scn4m_subm){ value : 0.000167; } cell_leakage_power : 0; - bus(DIN0){ - bus_type : DATA; + bus(din0){ + bus_type : data; direction : input; capacitance : 9.8242; memory_write(){ - address : ADDR0; + address : addr0; clocked_on : clk0; } - pin(DIN0[1:0]){ + pin(din0[1:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -124,15 +124,15 @@ cell (sram_2_16_1_scn4m_subm){ } } } - bus(DOUT0){ - bus_type : DATA; + bus(dout0){ + bus_type : data; direction : output; max_capacitance : 78.5936; min_capacitance : 2.45605; memory_read(){ - address : ADDR0; + address : addr0; } - pin(DOUT0[1:0]){ + pin(dout0[1:0]){ timing(){ timing_sense : non_unate; related_pin : "clk0"; @@ -161,12 +161,12 @@ cell (sram_2_16_1_scn4m_subm){ } } - bus(ADDR0){ - bus_type : ADDR; + bus(addr0){ + bus_type : addr; direction : input; capacitance : 9.8242; max_transition : 0.4; - pin(ADDR0[3:0]){ + pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib index 943f2ecc..7447a1e2 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C.lib @@ -52,7 +52,7 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ default_operating_conditions : OC; - type (DATA){ + type (data){ base_type : array; data_type : bit; bit_width : 2; @@ -60,7 +60,7 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ bit_to : 1; } - type (ADDR){ + type (addr){ base_type : array; data_type : bit; bit_width : 4; @@ -85,15 +85,15 @@ cell (sram_2_16_1_scn4m_subm){ value : 0.0009813788999999999; } cell_leakage_power : 0; - bus(DIN0){ - bus_type : DATA; + bus(din0){ + bus_type : data; direction : input; capacitance : 9.8242; memory_write(){ - address : ADDR0; + address : addr0; clocked_on : clk0; } - pin(DIN0[1:0]){ + pin(din0[1:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -124,15 +124,15 @@ cell (sram_2_16_1_scn4m_subm){ } } } - bus(DOUT0){ - bus_type : DATA; + bus(dout0){ + bus_type : data; direction : output; max_capacitance : 78.5936; min_capacitance : 2.45605; memory_read(){ - address : ADDR0; + address : addr0; } - pin(DOUT0[1:0]){ + pin(dout0[1:0]){ timing(){ timing_sense : non_unate; related_pin : "clk0"; @@ -161,12 +161,12 @@ cell (sram_2_16_1_scn4m_subm){ } } - bus(ADDR0){ - bus_type : ADDR; + bus(addr0){ + bus_type : addr; direction : input; capacitance : 9.8242; max_transition : 0.4; - pin(ADDR0[3:0]){ + pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib index 4f98380c..4248b986 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_analytical.lib @@ -52,7 +52,7 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ default_operating_conditions : OC; - type (DATA){ + type (data){ base_type : array; data_type : bit; bit_width : 2; @@ -60,7 +60,7 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ bit_to : 1; } - type (ADDR){ + type (addr){ base_type : array; data_type : bit; bit_width : 4; @@ -85,15 +85,15 @@ cell (sram_2_16_1_scn4m_subm){ value : 0.000179; } cell_leakage_power : 0; - bus(DIN0){ - bus_type : DATA; + bus(din0){ + bus_type : data; direction : input; capacitance : 9.8242; memory_write(){ - address : ADDR0; + address : addr0; clocked_on : clk0; } - pin(DIN0[1:0]){ + pin(din0[1:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -124,15 +124,15 @@ cell (sram_2_16_1_scn4m_subm){ } } } - bus(DOUT0){ - bus_type : DATA; + bus(dout0){ + bus_type : data; direction : output; max_capacitance : 78.5936; min_capacitance : 2.45605; memory_read(){ - address : ADDR0; + address : addr0; } - pin(DOUT0[1:0]){ + pin(dout0[1:0]){ timing(){ timing_sense : non_unate; related_pin : "clk0"; @@ -161,12 +161,12 @@ cell (sram_2_16_1_scn4m_subm){ } } - bus(ADDR0){ - bus_type : ADDR; + bus(addr0){ + bus_type : addr; direction : input; capacitance : 9.8242; max_transition : 0.4; - pin(ADDR0[3:0]){ + pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_pruned.lib b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_pruned.lib index b601f3b0..7b649d0d 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_pruned.lib +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm_TT_5p0V_25C_pruned.lib @@ -52,7 +52,7 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ default_operating_conditions : OC; - type (DATA){ + type (data){ base_type : array; data_type : bit; bit_width : 2; @@ -60,7 +60,7 @@ library (sram_2_16_1_scn4m_subm_TT_5p0V_25C_lib){ bit_to : 1; } - type (ADDR){ + type (addr){ base_type : array; data_type : bit; bit_width : 4; @@ -85,15 +85,15 @@ cell (sram_2_16_1_scn4m_subm){ value : 0.0009813788999999999; } cell_leakage_power : 0; - bus(DIN0){ - bus_type : DATA; + bus(din0){ + bus_type : data; direction : input; capacitance : 9.8242; memory_write(){ - address : ADDR0; + address : addr0; clocked_on : clk0; } - pin(DIN0[1:0]){ + pin(din0[1:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; @@ -124,15 +124,15 @@ cell (sram_2_16_1_scn4m_subm){ } } } - bus(DOUT0){ - bus_type : DATA; + bus(dout0){ + bus_type : data; direction : output; max_capacitance : 78.5936; min_capacitance : 2.45605; memory_read(){ - address : ADDR0; + address : addr0; } - pin(DOUT0[1:0]){ + pin(dout0[1:0]){ timing(){ timing_sense : non_unate; related_pin : "clk0"; @@ -161,12 +161,12 @@ cell (sram_2_16_1_scn4m_subm){ } } - bus(ADDR0){ - bus_type : ADDR; + bus(addr0){ + bus_type : addr; direction : input; capacitance : 9.8242; max_transition : 0.4; - pin(ADDR0[3:0]){ + pin(addr0[3:0]){ timing(){ timing_type : setup_rising; related_pin : "clk0"; diff --git a/compiler/tests/sram_1rw_1r_tb.v b/compiler/tests/sram_1rw_1r_tb.v index 9c212e0a..3a2194e1 100644 --- a/compiler/tests/sram_1rw_1r_tb.v +++ b/compiler/tests/sram_1rw_1r_tb.v @@ -19,14 +19,14 @@ module sram_1rw_1r_tb; reg csb1; wire [1:0] dout1; - sram_1rw_1r_2_16_scn4m_subm U0 (.DIN0(din0), - .DOUT0(dout0), - .ADDR0(addr0), + sram_1rw_1r_2_16_scn4m_subm U0 (.din0(din0), + .dout0(dout0), + .addr0(addr0), .csb0(csb0), .web0(web0), .clk0(clk), - .DOUT1(dout1), - .ADDR1(addr1), + .dout1(dout1), + .addr1(addr1), .csb1(csb1), .clk1(clk) ); diff --git a/compiler/tests/sram_1rw_tb.v b/compiler/tests/sram_1rw_tb.v index 31f120e8..f4f6cb33 100644 --- a/compiler/tests/sram_1rw_tb.v +++ b/compiler/tests/sram_1rw_tb.v @@ -13,9 +13,9 @@ module sram_1rw_tb; reg web0; wire [1:0] dout0; - sram_2_16_scn4m_subm U0 (.DIN0(din0), - .DOUT0(dout0), - .ADDR0(addr0), + sram_2_16_scn4m_subm U0 (.din0(din0), + .dout0(dout0), + .addr0(addr0), .csb0(csb0), .web0(web0), .clk0(clk) diff --git a/compiler/tests/sram_1rw_wmask_tb.v b/compiler/tests/sram_1rw_wmask_tb.v index 54aada6e..51d03d6b 100644 --- a/compiler/tests/sram_1rw_wmask_tb.v +++ b/compiler/tests/sram_1rw_wmask_tb.v @@ -14,9 +14,9 @@ module sram_1rw_wmask_tb; reg [1:0] wmask0; wire [1:0] dout0; - sram_2b_16_1rw_freepdk45 U0 (.DIN0(din0), - .DOUT0(dout0), - .ADDR0(addr0), + sram_2b_16_1rw_freepdk45 U0 (.din0(din0), + .dout0(dout0), + .addr0(addr0), .csb0(csb0), .web0(web0), .wmask0(wmask0), From 5f3ffdb8ba4b0d0eb188268466a93c3d74ddd820 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 14:00:55 -0700 Subject: [PATCH 223/234] Output name and version in help --- compiler/globals.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/globals.py b/compiler/globals.py index 0b262430..67a306b2 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -19,8 +19,9 @@ import re import copy import importlib -USAGE = "Usage: openram.py [options] \nUse -h for help.\n" -# Anonymous object that will be the options +VERSION = "1.1.0" +NAME = "OpenRAM v{}".format(VERSION) +USAGE = "openram.py [options] \nUse -h for help.\n" OPTS = options.options() CHECKPOINT_OPTS=None @@ -57,9 +58,9 @@ def parse_args(): } parser = optparse.OptionParser(option_list=option_list, - description="Compile and/or characterize an SRAM.", + description=NAME, usage=USAGE, - version="OpenRAM") + version=VERSION) (options, args) = parser.parse_args(values=OPTS) # If we don't specify a tech, assume scmos. @@ -79,8 +80,7 @@ def print_banner(): return debug.print_raw("|==============================================================================|") - name = "OpenRAM Compiler" - debug.print_raw("|=========" + name.center(60) + "=========|") + debug.print_raw("|=========" + NAME.center(60) + "=========|") debug.print_raw("|=========" + " ".center(60) + "=========|") debug.print_raw("|=========" + "VLSI Design and Automation Lab".center(60) + "=========|") debug.print_raw("|=========" + "Computer Science and Engineering Department".center(60) + "=========|") From 980760b7247168ae73f516d687465906fb29b363 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 21 Aug 2019 14:02:57 -0700 Subject: [PATCH 224/234] Add preferred direction to via1, routed between supply lines in wmask AND array, and only uses m3 for channel route with a write mask. --- compiler/modules/write_mask_and_array.py | 8 +++- compiler/sram/sram_1bank.py | 51 +++++++++++++----------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index a505ae22..3b308b60 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -123,6 +123,7 @@ class write_mask_and_array(design.design): self.add_via_center(layers=("metal2", "via2", "metal3"), offset=en_pin.center()) + # Route en pin between AND gates if i < self.num_wmasks-1: self.add_layout_pin(text="en", layer="metal3", @@ -137,10 +138,15 @@ class write_mask_and_array(design.design): width=wmask_out_pin.width(), height=wmask_out_pin.height()) - self.add_power_pin("gnd", vector((supply_pin.lx() - 0.75 *drc('minwidth_metal1'))+i*self.wmask_en_len, + self.add_power_pin("gnd", vector((supply_pin.lx() - 0.75*drc('minwidth_metal1'))+i*self.wmask_en_len, 0)) self.add_power_pin("vdd", vector((supply_pin.lx() - 0.75*drc('minwidth_metal1'))+i*self.wmask_en_len, self.height)) + if i < self.num_wmasks-1: + for n in ["gnd","vdd"]: + pin = self.and2_insts[i].get_pin(n) + next_pin = self.and2_insts[i+1].get_pin(n) + self.add_path("metal1",[pin.center(),next_pin.center()]) def en_width(self, pin): diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index c4ef0816..613fe8f5 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -141,12 +141,12 @@ class sram_1bank(sram_base): if self.write_size is not None: # Add the write mask flops below the write mask AND array. wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - self.bank.height + max_gap_size + self.dff.height) + self.bank.height + 0.5*max_gap_size + self.dff.height) self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") # Add the data flops below the write mask flops data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, - self.bank.height + 2*max_gap_size + 2*self.dff.height) + self.bank.height + 1.5*max_gap_size + 2*self.dff.height) self.data_dff_insts[port].place(data_pos[port], mirror="MX") else: @@ -361,31 +361,36 @@ class sram_1bank(sram_base): dff_names = ["dout_{}".format(x) for x in range(self.word_size)] dff_pins = [self.data_dff_insts[port].get_pin(x) for x in dff_names] - for x in dff_names: - pin_offset = self.data_dff_insts[port].get_pin(x).center() - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=pin_offset) - self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=pin_offset) - self.add_via_center(layers=("metal3", "via3", "metal4"), - offset=pin_offset) + if self.write_size is not None: + for x in dff_names: + pin_offset = self.data_dff_insts[port].get_pin(x).center() + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=pin_offset) + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=pin_offset) + self.add_via_center(layers=("metal3", "via3", "metal4"), + offset=pin_offset) bank_names = ["din{0}_{1}".format(port,x) for x in range(self.word_size)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] - for x in bank_names: - pin_offset = vector(self.bank_inst.get_pin(x).cx(), - self.bank_inst.get_pin(x).by() - 0.75 * drc('minwidth_metal1')) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=pin_offset) - self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=pin_offset) - self.add_via_center(layers=("metal3", "via3", "metal4"), - offset=pin_offset) - + if self.write_size is not None: + for x in bank_names: + pin_offset = self.bank_inst.get_pin(x).bc() + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=pin_offset, + directions=("V","V")) + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=pin_offset) + self.add_via_center(layers=("metal3", "via3", "metal4"), + offset=pin_offset) + route_map = list(zip(bank_pins, dff_pins)) - self.create_horizontal_channel_route(netlist=route_map, - offset=offset, - layer_stack=("metal3", "via3", "metal4")) + if self.write_size is not None: + self.create_horizontal_channel_route(netlist=route_map, + offset=offset, + layer_stack=("metal3", "via3", "metal4")) + else: + self.create_horizontal_channel_route(route_map, offset) def route_wmask_dff(self): """ Connect the output of the wmask flops to the write mask AND array """ From 9f54afbf2cf8dba4e1d8851dbb89761aef01522d Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 14:29:57 -0700 Subject: [PATCH 225/234] Fix capitalization in verilog golden files --- compiler/base/verilog.py | 24 +++++++++---------- compiler/characterizer/delay.py | 2 +- compiler/characterizer/functional.py | 8 +++---- compiler/characterizer/simulation.py | 4 ++-- compiler/modules/bank.py | 2 +- compiler/modules/multibank.py | 2 +- compiler/modules/port_data.py | 8 +++---- compiler/modules/write_driver_array.py | 4 ++-- compiler/sram/sram_1bank.py | 10 ++++---- compiler/sram/sram_base.py | 4 ++-- compiler/tests/golden/sram_2_16_1_freepdk45.v | 20 ++++++++-------- .../tests/golden/sram_2_16_1_scn4m_subm.v | 20 ++++++++-------- 12 files changed, 54 insertions(+), 54 deletions(-) diff --git a/compiler/base/verilog.py b/compiler/base/verilog.py index d9a812e1..ff13c4f4 100644 --- a/compiler/base/verilog.py +++ b/compiler/base/verilog.py @@ -22,7 +22,7 @@ class verilog: self.vf.write("// OpenRAM SRAM model\n") self.vf.write("// Words: {0}\n".format(self.num_words)) self.vf.write("// Word size: {0}\n".format(self.word_size)) - if self.write_size is not None: + if self.write_size: self.vf.write("// Write size: {0}\n\n".format(self.write_size)) else: self.vf.write("\n") @@ -37,12 +37,12 @@ class verilog: self.vf.write("// Port {0}: W\n".format(port)) if port in self.readwrite_ports: self.vf.write(" clk{0},csb{0},web{0},".format(port)) - if self.write_size is not None: + if self.write_size: self.vf.write("wmask{},".format(port)) self.vf.write("addr{0},din{0},dout{0}".format(port)) elif port in self.write_ports: self.vf.write(" clk{0},csb{0},".format(port)) - if self.write_size is not None: + if self.write_size: self.vf.write("wmask{},".format(port)) self.vf.write("addr{0},din{0}".format(port)) elif port in self.read_ports: @@ -52,7 +52,7 @@ class verilog: self.vf.write(",\n") self.vf.write("\n );\n\n") - if self.write_size is not None: + if self.write_size: self.num_wmasks = int(self.word_size/self.write_size) self.vf.write(" parameter NUM_WMASKS = {0} ;\n".format(self.num_wmasks)) self.vf.write(" parameter DATA_WIDTH = {0} ;\n".format(self.word_size)) @@ -99,7 +99,7 @@ class verilog: if port in self.readwrite_ports: self.vf.write(" reg web{0}_reg;\n".format(port)) if port in self.write_ports: - if self.write_size is not None: + if self.write_size: self.vf.write(" reg [NUM_WMASKS-1:0] wmask{0}_reg;\n".format(port)) self.vf.write(" reg [ADDR_WIDTH-1:0] addr{0}_reg;\n".format(port)) if port in self.write_ports: @@ -119,7 +119,7 @@ class verilog: if port in self.readwrite_ports: self.vf.write(" web{0}_reg = web{0};\n".format(port)) if port in self.write_ports: - if self.write_size is not None: + if self.write_size: self.vf.write(" wmask{0}_reg = wmask{0};\n".format(port)) self.vf.write(" addr{0}_reg = addr{0};\n".format(port)) if port in self.write_ports: @@ -134,13 +134,13 @@ class verilog: self.vf.write(" $display($time,\" Reading %m addr{0}=%b dout{0}=%b\",addr{0}_reg,mem[addr{0}_reg]);\n".format(port)) if port in self.readwrite_ports: self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port)) - if self.write_size is not None: + if self.write_size: self.vf.write(" $display($time,\" Writing %m addr{0}=%b din{0}=%b wmask{0}=%b\",addr{0}_reg,din{0}_reg,wmask{0}_reg);\n".format(port)) else: self.vf.write(" $display($time,\" Writing %m addr{0}=%b din{0}=%b\",addr{0}_reg,din{0}_reg);\n".format(port)) elif port in self.write_ports: self.vf.write(" if ( !csb{0}_reg )\n".format(port)) - if self.write_size is not None: + if self.write_size: self.vf.write(" $display($time,\" Writing %m addr{0}=%b din{0}=%b wmask{0}=%b\",addr{0}_reg,din{0}_reg,wmask{0}_reg);\n".format(port)) else: self.vf.write(" $display($time,\" Writing %m addr{0}=%b din{0}=%b\",addr{0}_reg,din{0}_reg);\n".format(port)) @@ -156,7 +156,7 @@ class verilog: self.vf.write(" input csb{0}; // active low chip select\n".format(port)) if port in self.readwrite_ports: self.vf.write(" input web{0}; // active low write control\n".format(port)) - if self.write_size is not None: + if self.write_size: self.vf.write(" input [NUM_WMASKS-1:0] wmask{0}; // write mask\n".format(port)) self.vf.write(" input [ADDR_WIDTH-1:0] addr{0};\n".format(port)) if port in self.write_ports: @@ -175,17 +175,17 @@ class verilog: self.vf.write(" always @ (negedge clk{0})\n".format(port)) self.vf.write(" begin : MEM_WRITE{0}\n".format(port)) if port in self.readwrite_ports: - if self.write_size is not None: + if self.write_size: self.vf.write(" if ( !csb{0}_reg && !web{0}_reg ) begin\n".format(port)) else: self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port)) else: - if self.write_size is not None: + if self.write_size: self.vf.write(" if (!csb{0}_reg) begin\n".format(port)) else: self.vf.write(" if (!csb{0}_reg)\n".format(port)) - if self.write_size is not None: + if self.write_size: for mask in range(0,self.num_wmasks): lower = mask * self.write_size upper = lower + self.write_size-1 diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 91be8ae0..7a905b11 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -46,7 +46,7 @@ class delay(simulation): self.targ_read_ports = [] self.targ_write_ports = [] self.period = 0 - if self.write_size is not None: + if self.write_size: self.num_wmasks = int(self.word_size / self.write_size) else: self.num_wmasks = 0 diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index 257c5b8d..f3bbcf9f 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -34,7 +34,7 @@ class functional(simulation): if OPTS.is_unit_test: random.seed(12345) - if self.write_size is not None: + if self.write_size: self.num_wmasks = int(self.word_size / self.write_size) else: self.num_wmasks = 0 @@ -61,7 +61,7 @@ class functional(simulation): def initialize_wmask(self): self.wmask = "" - if self.write_size is not None: + if self.write_size: # initialize all wmask bits to 1 for bit in range(self.num_wmasks): self.wmask += "1" @@ -85,7 +85,7 @@ class functional(simulation): return self.check_stim_results() def write_random_memory_sequence(self): - if self.write_size is not None: + if self.write_size: rw_ops = ["noop", "write", "partial_write", "read"] w_ops = ["noop", "write", "partial_write"] else: @@ -340,7 +340,7 @@ class functional(simulation): # Generate wmask bits for port in self.write_ports: - if self.write_size is not None: + if self.write_size: self.sf.write("\n* Generation of wmask signals\n") for bit in range(self.num_wmasks): sig_name = "WMASK{0}_{1} ".format(port, bit) diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index c889e951..a44ba154 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -31,7 +31,7 @@ class simulation(): self.readwrite_ports = self.sram.readwrite_ports self.read_ports = self.sram.read_ports self.write_ports = self.sram.write_ports - if self.write_size is not None: + if self.write_size: self.num_wmasks = int(self.word_size/self.write_size) else: self.num_wmasks = 0 @@ -303,7 +303,7 @@ class simulation(): for port in range(total_ports): pin_names.append("{0}{1}".format(tech.spice["clk"], port)) - if self.write_size is not None: + if self.write_size: for port in write_index: for bit in range(self.num_wmasks): pin_names.append("WMASK{0}_{1}".format(port,bit)) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index a5ab4909..cbf7e6c0 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -30,7 +30,7 @@ class bank(design.design): self.sram_config = sram_config sram_config.set_local_config(self) - if self.write_size is not None: + if self.write_size: self.num_wmasks = int(self.word_size/self.write_size) else: self.num_wmasks = 0 diff --git a/compiler/modules/multibank.py b/compiler/modules/multibank.py index 4fbacc3f..2f933a2d 100644 --- a/compiler/modules/multibank.py +++ b/compiler/modules/multibank.py @@ -187,7 +187,7 @@ class multibank(design.design): words_per_row=self.words_per_row) self.add_mod(self.sense_amp_array) - if self.write_size is not None: + if self.write_size: self.write_mask_driver_array = self.mod_write_mask_driver_array(columns=self.num_cols, word_size=self.word_size, write_size=self.write_size) diff --git a/compiler/modules/port_data.py b/compiler/modules/port_data.py index a1adb7d4..dde93b52 100644 --- a/compiler/modules/port_data.py +++ b/compiler/modules/port_data.py @@ -22,7 +22,7 @@ class port_data(design.design): sram_config.set_local_config(self) self.port = port - if self.write_size is not None: + if self.write_size: self.num_wmasks = int(self.word_size/self.write_size) else: self.num_wmasks = 0 @@ -58,7 +58,7 @@ class port_data(design.design): if self.write_driver_array: self.create_write_driver_array() - if self.write_size is not None: + if self.write_size: self.create_write_mask_and_array() else: self.write_mask_and_array_inst = None @@ -183,7 +183,7 @@ class port_data(design.design): word_size=self.word_size, write_size=self.write_size) self.add_mod(self.write_driver_array) - if self.write_size is not None: + if self.write_size: self.write_mask_and_array = factory.create(module_type="write_mask_and_array", columns=self.num_cols, word_size=self.word_size, @@ -316,7 +316,7 @@ class port_data(design.design): temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) - if self.write_size is not None: + if self.write_size: for i in range(self.num_wmasks): temp.append("wdriver_sel_{}".format(i)) else: diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index 1b152e89..6818a196 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -30,7 +30,7 @@ class write_driver_array(design.design): self.write_size = write_size self.words_per_row = int(columns / word_size) - if self.write_size is not None: + if self.write_size: self.num_wmasks = int(self.word_size/self.write_size) self.create_netlist() @@ -89,7 +89,7 @@ class write_driver_array(design.design): self.driver_insts[index]=self.add_inst(name=name, mod=self.driver) - if self.write_size is not None: + if self.write_size: self.connect_inst(["data_{0}".format(index), "bl_{0}".format(index), "br_{0}".format(index), diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 8385f289..dea1251e 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -46,7 +46,7 @@ class sram_1bank(sram_base): self.data_dff_insts = self.create_data_dff() - if self.write_size is not None: + if self.write_size: self.wmask_dff_insts = self.create_wmask_dff() @@ -126,7 +126,7 @@ class sram_1bank(sram_base): self.data_dff_insts[port].place(data_pos[port]) # Add the write mask flops to the left of the din flops. - if self.write_size is not None: + if self.write_size: if port in self.write_ports: wmask_pos[port] = vector(self.bank.bank_array_ll.x - self.control_logic_insts[port].width, -max_gap_size - self.wmask_dff_insts[port].height) @@ -148,7 +148,7 @@ class sram_1bank(sram_base): self.data_dff_insts[port].place(data_pos[port], mirror="MX") # Add the write mask flops to the left of the din flops. - if self.write_size is not None: + if self.write_size: if port in self.write_ports: wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, self.bank.height + max_gap_size + self.data_dff_insts[port].height) @@ -190,7 +190,7 @@ class sram_1bank(sram_base): self.data_dff_insts[port].place(data_pos[port], mirror="MX") # Add the write mask flops to the left of the din flops. - if self.write_size is not None: + if self.write_size: if port in self.write_ports: wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, self.bank.height + max_gap_size + self.data_dff_insts[port].height) @@ -386,7 +386,7 @@ class sram_1bank(sram_base): #Data dffs and wmask dffs are only for writing so are not useful for evaluating read delay. for inst in self.data_dff_insts: self.graph_inst_exclude.add(inst) - if self.write_size is not None: + if self.write_size: for inst in self.wmask_dff_insts: self.graph_inst_exclude.add(inst) diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index ea644f5f..9b0fbf52 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -35,7 +35,7 @@ class sram_base(design, verilog, lef): self.bank_insts = [] - if self.write_size is not None: + if self.write_size: self.num_wmasks = int(self.word_size/self.write_size) else: self.num_wmasks = 0 @@ -284,7 +284,7 @@ class sram_base(design, verilog, lef): self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size) self.add_mod(self.data_dff) - if self.write_size is not None: + if self.write_size: self.wmask_dff = dff_array(name="wmask_dff", rows=1, columns=self.num_wmasks) self.add_mod(self.wmask_dff) diff --git a/compiler/tests/golden/sram_2_16_1_freepdk45.v b/compiler/tests/golden/sram_2_16_1_freepdk45.v index 0a71705b..5edd2fee 100644 --- a/compiler/tests/golden/sram_2_16_1_freepdk45.v +++ b/compiler/tests/golden/sram_2_16_1_freepdk45.v @@ -7,24 +7,24 @@ module sram_2_16_1_freepdk45( clk0,csb0,web0,addr0,din0,dout0 ); - parameter data_WIDTH = 2 ; - parameter addr_WIDTH = 4 ; - parameter RAM_DEPTH = 1 << addr_WIDTH; + parameter DATA_WIDTH = 2 ; + parameter ADDR_WIDTH = 4 ; + parameter RAM_DEPTH = 1 << ADDR_WIDTH; // FIXME: This delay is arbitrary. parameter DELAY = 3 ; input clk0; // clock input csb0; // active low chip select input web0; // active low write control - input [addr_WIDTH-1:0] addr0; - input [data_WIDTH-1:0] din0; - output [data_WIDTH-1:0] dout0; + input [ADDR_WIDTH-1:0] addr0; + input [DATA_WIDTH-1:0] din0; + output [DATA_WIDTH-1:0] dout0; reg csb0_reg; reg web0_reg; - reg [addr_WIDTH-1:0] addr0_reg; - reg [data_WIDTH-1:0] din0_reg; - reg [data_WIDTH-1:0] dout0; + reg [ADDR_WIDTH-1:0] addr0_reg; + reg [DATA_WIDTH-1:0] din0_reg; + reg [DATA_WIDTH-1:0] dout0; // All inputs are registers always @(posedge clk0) @@ -40,7 +40,7 @@ module sram_2_16_1_freepdk45( $display($time," Writing %m addr0=%b din0=%b",addr0_reg,din0_reg); end -reg [data_WIDTH-1:0] mem [0:RAM_DEPTH-1]; +reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; // Memory Write Block Port 0 // Write Operation : When web0 = 0, csb0 = 0 diff --git a/compiler/tests/golden/sram_2_16_1_scn4m_subm.v b/compiler/tests/golden/sram_2_16_1_scn4m_subm.v index 4c39ddb5..cec47c19 100644 --- a/compiler/tests/golden/sram_2_16_1_scn4m_subm.v +++ b/compiler/tests/golden/sram_2_16_1_scn4m_subm.v @@ -7,24 +7,24 @@ module sram_2_16_1_scn4m_subm( clk0,csb0,web0,addr0,din0,dout0 ); - parameter data_WIDTH = 2 ; - parameter addr_WIDTH = 4 ; - parameter RAM_DEPTH = 1 << addr_WIDTH; + parameter DATA_WIDTH = 2 ; + parameter ADDR_WIDTH = 4 ; + parameter RAM_DEPTH = 1 << ADDR_WIDTH; // FIXME: This delay is arbitrary. parameter DELAY = 3 ; input clk0; // clock input csb0; // active low chip select input web0; // active low write control - input [addr_WIDTH-1:0] addr0; - input [data_WIDTH-1:0] din0; - output [data_WIDTH-1:0] dout0; + input [ADDR_WIDTH-1:0] addr0; + input [DATA_WIDTH-1:0] din0; + output [DATA_WIDTH-1:0] dout0; reg csb0_reg; reg web0_reg; - reg [addr_WIDTH-1:0] addr0_reg; - reg [data_WIDTH-1:0] din0_reg; - reg [data_WIDTH-1:0] dout0; + reg [ADDR_WIDTH-1:0] addr0_reg; + reg [DATA_WIDTH-1:0] din0_reg; + reg [DATA_WIDTH-1:0] dout0; // All inputs are registers always @(posedge clk0) @@ -40,7 +40,7 @@ module sram_2_16_1_scn4m_subm( $display($time," Writing %m addr0=%b din0=%b",addr0_reg,din0_reg); end -reg [data_WIDTH-1:0] mem [0:RAM_DEPTH-1]; +reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; // Memory Write Block Port 0 // Write Operation : When web0 = 0, csb0 = 0 From 737e87392304ba76c08f99d7a19e473bda160ddd Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 21 Aug 2019 14:49:54 -0700 Subject: [PATCH 226/234] Changed via direction for via1 in flip flops. --- compiler/modules/write_mask_and_array.py | 7 +++---- compiler/sram/sram_1bank.py | 11 ++++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/modules/write_mask_and_array.py b/compiler/modules/write_mask_and_array.py index 3b308b60..9d29cbea 100644 --- a/compiler/modules/write_mask_and_array.py +++ b/compiler/modules/write_mask_and_array.py @@ -138,10 +138,9 @@ class write_mask_and_array(design.design): width=wmask_out_pin.width(), height=wmask_out_pin.height()) - self.add_power_pin("gnd", vector((supply_pin.lx() - 0.75*drc('minwidth_metal1'))+i*self.wmask_en_len, - 0)) - self.add_power_pin("vdd", vector((supply_pin.lx() - 0.75*drc('minwidth_metal1'))+i*self.wmask_en_len, - self.height)) + self.add_power_pin("gnd", vector(supply_pin.width() + i * self.wmask_en_len, 0)) + self.add_power_pin("vdd", vector(supply_pin.width() + i * self.wmask_en_len, self.height)) + if i < self.num_wmasks-1: for n in ["gnd","vdd"]: pin = self.and2_insts[i].get_pin(n) diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 613fe8f5..b93a9b86 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -365,7 +365,8 @@ class sram_1bank(sram_base): for x in dff_names: pin_offset = self.data_dff_insts[port].get_pin(x).center() self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=pin_offset) + offset=pin_offset, + directions = ("V", "V")) self.add_via_center(layers=("metal2", "via2", "metal3"), offset=pin_offset) self.add_via_center(layers=("metal3", "via3", "metal4"), @@ -377,8 +378,7 @@ class sram_1bank(sram_base): for x in bank_names: pin_offset = self.bank_inst.get_pin(x).bc() self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=pin_offset, - directions=("V","V")) + offset=pin_offset) self.add_via_center(layers=("metal2", "via2", "metal3"), offset=pin_offset) self.add_via_center(layers=("metal3", "via3", "metal4"), @@ -406,7 +406,8 @@ class sram_1bank(sram_base): for x in dff_names: offset_pin = self.wmask_dff_insts[port].get_pin(x).center() self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=offset_pin) + offset=offset_pin, + directions=("V", "V")) bank_names = ["bank_wmask{0}_{1}".format(port, x) for x in range(self.num_wmasks)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] @@ -414,7 +415,7 @@ class sram_1bank(sram_base): offset_pin = self.bank_inst.get_pin(x).center() self.add_via_center(layers=("metal1", "via1", "metal2"), offset=offset_pin) - + route_map = list(zip(bank_pins, dff_pins)) self.create_horizontal_channel_route(route_map,offset) From 9ada9a7dfa9362d1b697b79009d6397ee0f31375 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 15:32:49 -0700 Subject: [PATCH 227/234] Fix pitch in channel router to support M3/M4. --- compiler/base/hierarchy_layout.py | 45 ++++++++++++++++++------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 287be926..f44cc578 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -680,7 +680,19 @@ class layout(): self.add_via_center(layers=layer_stack, offset=bus_pos, rotate=90) - + def get_layer_pitch(self, layer): + """ Return the track pitch on a given layer """ + if layer=="metal1": + return self.m1_pitch + elif layer=="metal2": + return self.m2_pitch + elif layer=="metal3": + return self.m3_pitch + elif layer=="metal4": + return self.m4_pitch + else: + debug.error("Cannot find layer pitch.") + def add_horizontal_trunk_route(self, pins, trunk_offset, @@ -690,7 +702,7 @@ class layout(): Create a trunk route for all pins with the trunk located at the given y offset. """ if not pitch: - pitch = self.m1_pitch + pitch = self.get_layer_pitch(layer_stack[0]) max_x = max([pin.center().x for pin in pins]) min_x = min([pin.center().x for pin in pins]) @@ -728,7 +740,7 @@ class layout(): Create a trunk route for all pins with the trunk located at the given x offset. """ if not pitch: - pitch = self.m2_pitch + pitch = self.get_layer_pitch(layer_stack[2]) max_y = max([pin.center().y for pin in pins]) min_y = min([pin.center().y for pin in pins]) @@ -762,7 +774,6 @@ class layout(): def create_channel_route(self, netlist, offset, layer_stack=("metal1", "via1", "metal2"), - pitch=None, vertical=False): """ The net list is a list of the nets. Each net is a list of pins @@ -786,7 +797,7 @@ class layout(): g[other_pin]=conflicts return g - def vcg_nets_overlap(net1, net2, vertical): + def vcg_nets_overlap(net1, net2, vertical, pitch): """ Check all the pin pairs on two nets and return a pin overlap if any pin overlaps @@ -794,12 +805,12 @@ class layout(): for pin1 in net1: for pin2 in net2: - if vcg_pin_overlap(pin1, pin2, vertical): + if vcg_pin_overlap(pin1, pin2, vertical, pitch): return True return False - def vcg_pin_overlap(pin1, pin2, vertical): + def vcg_pin_overlap(pin1, pin2, vertical, pitch): """ Check for vertical or horizontal overlap of the two pins """ # FIXME: If the pins are not in a row, this may break. # However, a top pin shouldn't overlap another top pin, for example, so the @@ -813,10 +824,10 @@ class layout(): overlaps = (not vertical and x_overlap) or (vertical and y_overlap) return overlaps - - - if not pitch: - pitch = self.m2_pitch + if vertical: + pitch = self.get_layer_pitch(layer_stack[2]) + else: + pitch = self.get_layer_pitch(layer_stack[0]) # FIXME: Must extend this to a horizontal conflict graph too if we want to minimize the @@ -846,7 +857,7 @@ class layout(): # Skip yourself if net_name1 == net_name2: continue - if vcg_nets_overlap(nets[net_name1], nets[net_name2], vertical): + if vcg_nets_overlap(nets[net_name1], nets[net_name2], vertical, pitch): vcg[net_name2].append(net_name1) # list of routes to do @@ -882,20 +893,18 @@ class layout(): def create_vertical_channel_route(self, netlist, offset, - layer_stack=("metal1", "via1", "metal2"), - pitch=None): + layer_stack=("metal1", "via1", "metal2")): """ Wrapper to create a vertical channel route """ - self.create_channel_route(netlist, offset, layer_stack, pitch, vertical=True) + self.create_channel_route(netlist, offset, layer_stack, vertical=True) def create_horizontal_channel_route(self, netlist, offset, - layer_stack=("metal1", "via1", "metal2"), - pitch=None): + layer_stack=("metal1", "via1", "metal2")): """ Wrapper to create a horizontal channel route """ - self.create_channel_route(netlist, offset, layer_stack, pitch, vertical=False) + self.create_channel_route(netlist, offset, layer_stack, vertical=False) def add_boundary(self, offset=vector(0,0)): """ Add boundary for debugging dimensions """ From a8df5528f9ddf2c044735e3cae75df8fb85b6a63 Mon Sep 17 00:00:00 2001 From: jsowash Date: Wed, 21 Aug 2019 16:06:36 -0700 Subject: [PATCH 228/234] Added 2 mux test for wmask. --- .../tests/20_sram_1bank_2mux_wmask_test.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 compiler/tests/20_sram_1bank_2mux_wmask_test.py diff --git a/compiler/tests/20_sram_1bank_2mux_wmask_test.py b/compiler/tests/20_sram_1bank_2mux_wmask_test.py new file mode 100644 index 00000000..65f025a7 --- /dev/null +++ b/compiler/tests/20_sram_1bank_2mux_wmask_test.py @@ -0,0 +1,54 @@ +#!/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 + + +# @unittest.skip("SKIPPING 20_sram_1bank_2mux_wmask_test") +class sram_1bank_2mux_wmask_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + from sram_config import sram_config + c = sram_config(word_size=8, + write_size=4, + num_words=64, + num_banks=1) + + c.words_per_row = 2 + c.recompute_sizes() + debug.info(1, "Layout test for {}rw,{}r,{}w sram " + "with {} bit words, {} words, {} bit writes, {} words per " + "row, {} banks".format(OPTS.num_rw_ports, + OPTS.num_r_ports, + OPTS.num_w_ports, + c.word_size, + c.num_words, + c.write_size, + c.words_per_row, + c.num_banks)) + a = factory.create(module_type="sram", sram_config=c) + self.local_check(a, final_verification=True) + + 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()) \ No newline at end of file From 2ffdfb18a473b2749168ca64f5593d1bcf1971d6 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Aug 2019 17:11:02 -0700 Subject: [PATCH 229/234] Fix trunks less than a pitch in channel route --- compiler/base/hierarchy_layout.py | 62 +++++++++++-------- .../tests/20_sram_1bank_2mux_wmask_test.py | 0 2 files changed, 35 insertions(+), 27 deletions(-) mode change 100644 => 100755 compiler/tests/20_sram_1bank_2mux_wmask_test.py diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index f44cc578..1b0bf054 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -683,34 +683,37 @@ class layout(): def get_layer_pitch(self, layer): """ Return the track pitch on a given layer """ if layer=="metal1": - return self.m1_pitch + return (self.m1_pitch,self.m1_pitch-self.m1_space,self.m1_space) elif layer=="metal2": - return self.m2_pitch + return (self.m2_pitch,self.m2_pitch-self.m2_space,self.m2_space) elif layer=="metal3": - return self.m3_pitch + return (self.m3_pitch,self.m3_pitch-self.m3_space,self.m3_space) elif layer=="metal4": - return self.m4_pitch + from tech import layer as tech_layer + if "metal4" in tech_layer: + return (self.m3_pitch,self.m3_pitch-self.m4_space,self.m4_space) + else: + return (self.m3_pitch,self.m3_pitch-self.m3_space,self.m3_space) else: debug.error("Cannot find layer pitch.") def add_horizontal_trunk_route(self, pins, trunk_offset, - layer_stack=("metal1", "via1", "metal2"), - pitch=None): + layer_stack, + pitch): """ Create a trunk route for all pins with the trunk located at the given y offset. """ - if not pitch: - pitch = self.get_layer_pitch(layer_stack[0]) - max_x = max([pin.center().x for pin in pins]) min_x = min([pin.center().x for pin in pins]) - - half_minwidth = 0.5*drc["minwidth_{}".format(layer_stack[0])] + + # Add the vertical trunk + half_minwidth = 0.5*self.vertical_width # if we are less than a pitch, just create a non-preferred layer jog - if max_x-min_x < pitch: + if max_x-min_x <= pitch: + # Add the horizontal trunk on the vertical layer! self.add_path(layer_stack[2],[vector(min_x-half_minwidth,trunk_offset.y), vector(max_x+half_minwidth,trunk_offset.y)]) @@ -734,22 +737,20 @@ class layout(): def add_vertical_trunk_route(self, pins, trunk_offset, - layer_stack=("metal1", "via1", "metal2"), - pitch=None): + layer_stack, + pitch): """ Create a trunk route for all pins with the trunk located at the given x offset. """ - if not pitch: - pitch = self.get_layer_pitch(layer_stack[2]) - max_y = max([pin.center().y for pin in pins]) min_y = min([pin.center().y for pin in pins]) # Add the vertical trunk - half_minwidth = 0.5*drc["minwidth_{}".format(layer_stack[2])] + half_minwidth = 0.5*self.horizontal_width # if we are less than a pitch, just create a non-preferred layer jog - if max_y-min_y < pitch: + if max_y-min_y <= pitch: + # Add the horizontal trunk on the vertical layer! self.add_path(layer_stack[0],[vector(trunk_offset.x,min_y-half_minwidth), vector(trunk_offset.x,max_y+half_minwidth)]) @@ -824,10 +825,15 @@ class layout(): overlaps = (not vertical and x_overlap) or (vertical and y_overlap) return overlaps - if vertical: - pitch = self.get_layer_pitch(layer_stack[2]) + if self.get_preferred_direction(layer_stack[0])=="V": + self.vertical_layer = layer_stack[0] + self.horizontal_layer = layer_stack[2] else: - pitch = self.get_layer_pitch(layer_stack[0]) + self.vertical_layer = layer_stack[2] + self.horizontal_layer = layer_stack[0] + + (self.vertical_pitch,self.vertical_width,self.vertical_space) = self.get_layer_pitch(self.vertical_layer) + (self.horizontal_pitch,self.horizontal_width,self.horizontal_space) = self.get_layer_pitch(self.horizontal_layer) # FIXME: Must extend this to a horizontal conflict graph too if we want to minimize the @@ -857,7 +863,9 @@ class layout(): # Skip yourself if net_name1 == net_name2: continue - if vcg_nets_overlap(nets[net_name1], nets[net_name2], vertical, pitch): + if vertical and vcg_nets_overlap(nets[net_name1], nets[net_name2], vertical, self.vertical_pitch): + vcg[net_name2].append(net_name1) + elif not vertical and vcg_nets_overlap(nets[net_name1], nets[net_name2], vertical, self.horizontal_pitch): vcg[net_name2].append(net_name1) # list of routes to do @@ -885,11 +893,11 @@ class layout(): # Add the trunk routes from the bottom up for horizontal or the left to right for vertical if vertical: - self.add_vertical_trunk_route(pin_list, offset, layer_stack, pitch) - offset += vector(pitch,0) + self.add_vertical_trunk_route(pin_list, offset, layer_stack, self.vertical_pitch) + offset += vector(self.vertical_pitch,0) else: - self.add_horizontal_trunk_route(pin_list, offset, layer_stack, pitch) - offset += vector(0,pitch) + self.add_horizontal_trunk_route(pin_list, offset, layer_stack, self.horizontal_pitch) + offset += vector(0,self.horizontal_pitch) def create_vertical_channel_route(self, netlist, offset, diff --git a/compiler/tests/20_sram_1bank_2mux_wmask_test.py b/compiler/tests/20_sram_1bank_2mux_wmask_test.py old mode 100644 new mode 100755 From 27ec6173152c784a68ca9cb275f10beccc4d91e6 Mon Sep 17 00:00:00 2001 From: jsowash Date: Thu, 22 Aug 2019 09:34:53 -0700 Subject: [PATCH 230/234] Fixed M1.5 error in 8mux tests which came from pdriver. --- compiler/pgates/pand3.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/pgates/pand3.py b/compiler/pgates/pand3.py index fcca6672..22864e5a 100644 --- a/compiler/pgates/pand3.py +++ b/compiler/pgates/pand3.py @@ -36,8 +36,7 @@ class pand3(pgate.pgate): self.nand = factory.create(module_type="pnand3",height=self.height) self.add_mod(self.nand) - # Assume stage effort of 3 - self.inv = factory.create(module_type="pdriver", neg_polarity=True, fanout=3*self.size, height=self.height) + self.inv = factory.create(module_type="pinv", size=self.size, height=self.height) self.add_mod(self.inv) def create_layout(self): From afaa946f9c28e2e2fc21b8ff147402922685a939 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 22 Aug 2019 12:03:38 -0700 Subject: [PATCH 231/234] Fix width of non-preferred trunk wire --- compiler/base/hierarchy_layout.py | 32 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 1b0bf054..76c74f11 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -708,29 +708,30 @@ class layout(): max_x = max([pin.center().x for pin in pins]) min_x = min([pin.center().x for pin in pins]) - # Add the vertical trunk - half_minwidth = 0.5*self.vertical_width - # if we are less than a pitch, just create a non-preferred layer jog if max_x-min_x <= pitch: + # Recalculate the far left and right of the pins for the trunk + max_x = max([pin.rx() for pin in pins]) + min_x = min([pin.lx() for pin in pins]) + # Add the horizontal trunk on the vertical layer! - self.add_path(layer_stack[2],[vector(min_x-half_minwidth,trunk_offset.y), vector(max_x+half_minwidth,trunk_offset.y)]) + self.add_path(self.vertical_layer,[vector(min_x,trunk_offset.y), vector(max_x,trunk_offset.y)]) # Route each pin to the trunk for pin in pins: # No bend needed here mid = vector(pin.center().x, trunk_offset.y) - self.add_path(layer_stack[2], [pin.center(), mid]) + self.add_path(self.vertical_layer, [pin.center(), mid]) else: # Add the horizontal trunk - self.add_path(layer_stack[0],[vector(min_x,trunk_offset.y), vector(max_x,trunk_offset.y)]) + self.add_path(self.horizontal_layer,[vector(min_x,trunk_offset.y), vector(max_x,trunk_offset.y)]) trunk_mid = vector(0.5*(max_x+min_x),trunk_offset.y) # Route each pin to the trunk for pin in pins: mid = vector(pin.center().x, trunk_offset.y) - self.add_path(layer_stack[2], [pin.center(), mid]) + self.add_path(self.vertical_layer, [pin.center(), mid]) self.add_via_center(layers=layer_stack, offset=mid) @@ -745,29 +746,30 @@ class layout(): max_y = max([pin.center().y for pin in pins]) min_y = min([pin.center().y for pin in pins]) - # Add the vertical trunk - half_minwidth = 0.5*self.horizontal_width - # if we are less than a pitch, just create a non-preferred layer jog if max_y-min_y <= pitch: + + # Recalculate the far left and right of the pins for the trunk + max_y = max([pin.uy() for pin in pins]) + min_y = min([pin.by() for pin in pins]) - # Add the horizontal trunk on the vertical layer! - self.add_path(layer_stack[0],[vector(trunk_offset.x,min_y-half_minwidth), vector(trunk_offset.x,max_y+half_minwidth)]) + # Add the vertical trunk on the horizontal layer! + self.add_path(self.horizontal_layer,[vector(trunk_offset.x,min_y), vector(trunk_offset.x,max_y)]) # Route each pin to the trunk for pin in pins: # No bend needed here mid = vector(trunk_offset.x, pin.center().y) - self.add_path(layer_stack[0], [pin.center(), mid]) + self.add_path(self.horizontal_layer, [pin.center(), mid]) else: # Add the vertical trunk - self.add_path(layer_stack[2],[vector(trunk_offset.x,min_y), vector(trunk_offset.x,max_y)]) + self.add_path(self.vertical_layer,[vector(trunk_offset.x,min_y), vector(trunk_offset.x,max_y)]) trunk_mid = vector(trunk_offset.x,0.5*(max_y+min_y),) # Route each pin to the trunk for pin in pins: mid = vector(trunk_offset.x, pin.center().y) - self.add_path(layer_stack[0], [pin.center(), mid]) + self.add_path(self.horizontal_layer, [pin.center(), mid]) self.add_via_center(layers=layer_stack, offset=mid) From 560d7680101d9e00fbc79b717f3ed3682c18e04f Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 22 Aug 2019 13:46:32 -0700 Subject: [PATCH 232/234] Fix syntax error in router --- compiler/router/pin_group.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/router/pin_group.py b/compiler/router/pin_group.py index 2303d4a7..99986e76 100644 --- a/compiler/router/pin_group.py +++ b/compiler/router/pin_group.py @@ -470,9 +470,9 @@ class pin_group: # Now, make sure each pin touches an enclosure. If not, add another (diagonal) connector. # This could only happen when there was no enclosure in any cardinal direction from a pin if not self.overlap_any_shape(self.pins, self.enclosures): - connector = self.find_smallest_connector(pin_list, self.enclosures) + connector = self.find_smallest_connector(self.pins, self.enclosures) if connector==None: - debug.error("Could not find a connector for {} with {}".format(pin_list, self.enclosures)) + debug.error("Could not find a connector for {} with {}".format(self.pins, self.enclosures)) self.router.write_debug_gds("no_connector.gds") self.enclosures.append(connector) From bdf29c3a26a217b8d262b8a3cac412e053b6f778 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 22 Aug 2019 13:57:14 -0700 Subject: [PATCH 233/234] Fix non-preferred route width again. This time it is likely right. --- compiler/base/hierarchy_layout.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 76c74f11..26436963 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -711,12 +711,10 @@ class layout(): # if we are less than a pitch, just create a non-preferred layer jog if max_x-min_x <= pitch: - # Recalculate the far left and right of the pins for the trunk - max_x = max([pin.rx() for pin in pins]) - min_x = min([pin.lx() for pin in pins]) + half_layer_width = 0.5*drc["minwidth_{0}".format(self.vertical_layer)] # Add the horizontal trunk on the vertical layer! - self.add_path(self.vertical_layer,[vector(min_x,trunk_offset.y), vector(max_x,trunk_offset.y)]) + self.add_path(self.vertical_layer,[vector(min_x-half_layer_width,trunk_offset.y), vector(max_x+half_layer_width,trunk_offset.y)]) # Route each pin to the trunk for pin in pins: @@ -749,12 +747,10 @@ class layout(): # if we are less than a pitch, just create a non-preferred layer jog if max_y-min_y <= pitch: - # Recalculate the far left and right of the pins for the trunk - max_y = max([pin.uy() for pin in pins]) - min_y = min([pin.by() for pin in pins]) + half_layer_width = 0.5*drc["minwidth_{0}".format(self.horizontal_layer)] # Add the vertical trunk on the horizontal layer! - self.add_path(self.horizontal_layer,[vector(trunk_offset.x,min_y), vector(trunk_offset.x,max_y)]) + self.add_path(self.horizontal_layer,[vector(trunk_offset.x,min_y-half_layer_width), vector(trunk_offset.x,max_y+half_layer_width)]) # Route each pin to the trunk for pin in pins: From 64fc771fc44fdb1c82925a17a84ffff5701255e6 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Thu, 22 Aug 2019 15:02:52 -0700 Subject: [PATCH 234/234] Simplify is not None --- compiler/modules/bank.py | 2 +- compiler/modules/write_driver_array.py | 4 ++-- compiler/sram/sram_1bank.py | 16 ++++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 8ac57208..c0c9d1a0 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -722,7 +722,7 @@ class bank(design.design): din_name = "din{0}_{1}".format(port,row) self.copy_layout_pin(self.port_data_inst[port], data_name, din_name) - if self.word_size is not None: + if self.word_size: for row in range(self.num_wmasks): wmask_name = "bank_wmask_{}".format(row) bank_wmask_name = "bank_wmask{0}_{1}".format(port, row) diff --git a/compiler/modules/write_driver_array.py b/compiler/modules/write_driver_array.py index baf7cbd8..100ee3a2 100644 --- a/compiler/modules/write_driver_array.py +++ b/compiler/modules/write_driver_array.py @@ -62,7 +62,7 @@ class write_driver_array(design.design): for i in range(self.word_size): self.add_pin("bl_{0}".format(i), "OUTPUT") self.add_pin("br_{0}".format(i), "OUTPUT") - if self.write_size is not None: + if self.write_size: for i in range(self.num_wmasks): self.add_pin("en_{0}".format(i), "INPUT") else: @@ -148,7 +148,7 @@ class write_driver_array(design.design): self.add_layout_pin_rect_center(text=n, layer="metal3", offset=pin_pos) - if self.write_size is not None: + if self.write_size: for bit in range(self.num_wmasks): en_pin = self.driver_insts[bit*self.write_size].get_pin("en") # Determine width of wmask modified en_pin with/without col mux diff --git a/compiler/sram/sram_1bank.py b/compiler/sram/sram_1bank.py index 4b58085f..0ae294ec 100644 --- a/compiler/sram/sram_1bank.py +++ b/compiler/sram/sram_1bank.py @@ -77,7 +77,7 @@ class sram_1bank(sram_base): # Port 0 port = 0 - if self.write_size is not None: + if self.write_size: if port in self.write_ports: # Add the write mask flops below the write mask AND array. wmask_pos[port] = vector(self.bank.bank_array_ll.x, @@ -138,7 +138,7 @@ class sram_1bank(sram_base): port = 1 if port in self.write_ports: - if self.write_size is not None: + if self.write_size: # Add the write mask flops below the write mask AND array. wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, self.bank.height + 0.5*max_gap_size + self.dff.height) @@ -207,7 +207,7 @@ class sram_1bank(sram_base): for bit in range(self.word_size): self.copy_layout_pin(self.data_dff_insts[port], "din_{}".format(bit), "din{0}[{1}]".format(port,bit)) - if self.write_size is not None: + if self.write_size: for bit in range(self.num_wmasks): self.copy_layout_pin(self.wmask_dff_insts[port], "din_{}".format(bit), "wmask{0}[{1}]".format(port,bit)) @@ -228,7 +228,7 @@ class sram_1bank(sram_base): self.route_data_dff() - if self.write_size is not None: + if self.write_size: self.route_wmask_dff() def route_clk(self): @@ -282,7 +282,7 @@ class sram_1bank(sram_base): self.add_path("metal2",[mid_pos, clk_steiner_pos], width=max(m2m3.width,m2m3.height)) self.add_wire(("metal3","via2","metal2"),[data_dff_clk_pos, mid_pos, clk_steiner_pos]) - if self.write_size is not None: + if self.write_size: wmask_dff_clk_pin = self.wmask_dff_insts[port].get_pin("clk") wmask_dff_clk_pos = wmask_dff_clk_pin.center() mid_pos = vector(clk_steiner_pos.x, wmask_dff_clk_pos.y) @@ -362,7 +362,7 @@ class sram_1bank(sram_base): dff_names = ["dout_{}".format(x) for x in range(self.word_size)] dff_pins = [self.data_dff_insts[port].get_pin(x) for x in dff_names] - if self.write_size is not None: + if self.write_size: for x in dff_names: pin_offset = self.data_dff_insts[port].get_pin(x).center() self.add_via_center(layers=("metal1", "via1", "metal2"), @@ -375,7 +375,7 @@ class sram_1bank(sram_base): bank_names = ["din{0}_{1}".format(port,x) for x in range(self.word_size)] bank_pins = [self.bank_inst.get_pin(x) for x in bank_names] - if self.write_size is not None: + if self.write_size: for x in bank_names: pin_offset = self.bank_inst.get_pin(x).bc() self.add_via_center(layers=("metal1", "via1", "metal2"), @@ -386,7 +386,7 @@ class sram_1bank(sram_base): offset=pin_offset) route_map = list(zip(bank_pins, dff_pins)) - if self.write_size is not None: + if self.write_size: self.create_horizontal_channel_route(netlist=route_map, offset=offset, layer_stack=("metal3", "via3", "metal4"))