From 6bbf66d55b28dd5e88fedf01947b8ca937547c0f Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 10 Oct 2018 15:15:58 -0700 Subject: [PATCH] Rewrote pin enclosure code to better address off grid pins. Include only maximal pin enclosure shapes. Add smallest area connector for off grid pins. Fix decoder to use add_power_pin code. Change permissions. --- compiler/base/pin_layout.py | 57 +- compiler/modules/bank.py | 5 +- compiler/modules/hierarchical_predecode.py | 10 +- compiler/router/grid_path.py | 12 + compiler/router/router.py | 272 +++++--- compiler/router/signal_grid.py | 12 +- compiler/router/supply_router.py | 76 +-- compiler/sram_base.py | 48 +- compiler/tests/04_replica_pbitcell_test.py | 0 .../tests/06_hierarchical_decoder_test.py | 0 .../06_hierarchical_predecode2x4_test.py | 0 .../06_hierarchical_predecode3x8_test.py | 0 compiler/tests/14_replica_bitline_test.py | 0 compiler/tests/16_control_logic_test.py | 0 compiler/tests/19_bank_select_test.py | 0 compiler/tests/19_pmulti_bank_test.py | 0 compiler/tests/20_sram_1bank_test.py | 50 +- compiler/tests/22_hspice_psram_func_test.py | 0 compiler/tests/22_hspice_sram_func_test.py | 0 compiler/tests/22_ngspice_psram_func_test.py | 0 compiler/tests/22_ngspice_sram_func_test.py | 0 compiler/tests/config_20_freepdk45.py | 0 compiler/tests/config_20_scn3me_subm.py | 0 compiler/tests/config_20_scn4m_subm.py | 0 compiler/tests/sram1.gds | Bin 304042 -> 0 bytes compiler/tests/sram1.lef | 19 - compiler/tests/sram1.sp | 602 ------------------ compiler/tests/sram1_TT_5p0V_25C.lib | 347 ---------- compiler/tests/testutils.py | 0 29 files changed, 334 insertions(+), 1176 deletions(-) mode change 100644 => 100755 compiler/tests/04_replica_pbitcell_test.py mode change 100644 => 100755 compiler/tests/06_hierarchical_decoder_test.py mode change 100644 => 100755 compiler/tests/06_hierarchical_predecode2x4_test.py mode change 100644 => 100755 compiler/tests/06_hierarchical_predecode3x8_test.py mode change 100644 => 100755 compiler/tests/14_replica_bitline_test.py mode change 100644 => 100755 compiler/tests/16_control_logic_test.py mode change 100644 => 100755 compiler/tests/19_bank_select_test.py mode change 100644 => 100755 compiler/tests/19_pmulti_bank_test.py mode change 100644 => 100755 compiler/tests/22_hspice_psram_func_test.py mode change 100644 => 100755 compiler/tests/22_hspice_sram_func_test.py mode change 100644 => 100755 compiler/tests/22_ngspice_psram_func_test.py mode change 100644 => 100755 compiler/tests/22_ngspice_sram_func_test.py mode change 100644 => 100755 compiler/tests/config_20_freepdk45.py mode change 100644 => 100755 compiler/tests/config_20_scn3me_subm.py mode change 100644 => 100755 compiler/tests/config_20_scn4m_subm.py delete mode 100644 compiler/tests/sram1.gds delete mode 100644 compiler/tests/sram1.lef delete mode 100644 compiler/tests/sram1.sp delete mode 100644 compiler/tests/sram1_TT_5p0V_25C.lib mode change 100644 => 100755 compiler/tests/testutils.py diff --git a/compiler/base/pin_layout.py b/compiler/base/pin_layout.py index 041c63bf..95a060f1 100644 --- a/compiler/base/pin_layout.py +++ b/compiler/base/pin_layout.py @@ -83,26 +83,27 @@ class pin_layout: max_y = min(ll.y, oll.y) return [vector(min_x,min_y),vector(max_x,max_y)] - - def overlaps(self, other): - """ Check if a shape overlaps with a rectangle """ + + def xoverlaps(self, other): + """ Check if shape has x overlap """ (ll,ur) = self.rect (oll,our) = other.rect - - # Can only overlap on the same layer - if self.layer != other.layer: - return False - - # Start assuming no overlaps x_overlaps = False - y_overlaps = False # check if self is within other x range if (ll.x >= oll.x and ll.x <= our.x) or (ur.x >= oll.x and ur.x <= our.x): x_overlaps = True # check if other is within self x range if (oll.x >= ll.x and oll.x <= ur.x) or (our.x >= ll.x and our.x <= ur.x): x_overlaps = True - + + return x_overlaps + + def yoverlaps(self, other): + """ Check if shape has x overlap """ + (ll,ur) = self.rect + (oll,our) = other.rect + y_overlaps = False + # check if self is within other y range if (ll.y >= oll.y and ll.y <= our.y) or (ur.y >= oll.y and ur.y <= our.y): y_overlaps = True @@ -110,7 +111,41 @@ class pin_layout: if (oll.y >= ll.y and oll.y <= ur.y) or (our.y >= ll.y and our.y <= ur.y): y_overlaps = True + return y_overlaps + + def contains(self, other): + """ Check if a shape contains another rectangle """ + # Can only overlap on the same layer + if self.layer != other.layer: + return False + + (ll,ur) = self.rect + (oll,our) = other.rect + + + if not (oll.y >= ll.y and oll.y <= ur.y): + return False + + if not (oll.x >= ll.x and oll.x <= ur.x): + return False + + return True + + + def overlaps(self, other): + """ Check if a shape overlaps with a rectangle """ + # Can only overlap on the same layer + if self.layer != other.layer: + return False + + x_overlaps = self.xoverlaps(other) + y_overlaps = self.yoverlaps(other) + return x_overlaps and y_overlaps + + def area(self): + """ Return the area. """ + return self.height()*self.width() def height(self): """ Return height. Abs is for pre-normalized value.""" diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index a3c42f9a..cfb26e30 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -107,8 +107,7 @@ class bank(design.design): if self.num_banks > 1: self.route_bank_select() - self.route_vdd_gnd() - + self.route_supplies() def create_modules(self): """ Add modules. The order should not matter! """ @@ -573,7 +572,7 @@ class bank(design.design): self.bank_select_inst[port].place(self.bank_select_pos) - def route_vdd_gnd(self): + 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") diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index cec3a925..5d8fde54 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -282,15 +282,7 @@ class hierarchical_predecode(design.design): # Add pins in two locations for xoffset in [in_xoffset, out_xoffset]: pin_pos = vector(xoffset, nand_pin.cy()) - self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=pin_pos, - rotate=90) - self.add_via_center(layers=("metal2", "via2", "metal3"), - offset=pin_pos, - rotate=90) - self.add_layout_pin_rect_center(text=n, - layer="metal3", - offset=pin_pos) + self.add_power_pin(n, pin_pos) diff --git a/compiler/router/grid_path.py b/compiler/router/grid_path.py index e828ad0e..9f196b94 100644 --- a/compiler/router/grid_path.py +++ b/compiler/router/grid_path.py @@ -63,6 +63,18 @@ class grid_path: def __len__(self): return len(self.pathlist) + def trim_last(self): + """ + Drop the last item + """ + self.pathlist.pop() + + def trim_first(self): + """ + Drop the first item + """ + self.pathlist.pop(0) + def append(self,item): """ Append the list of items to the cells diff --git a/compiler/router/router.py b/compiler/router/router.py index 84728811..e41f51d8 100644 --- a/compiler/router/router.py +++ b/compiler/router/router.py @@ -44,19 +44,20 @@ class router: self.pins = {} # This is a set of all pins so that we don't create blockages for these shapes. self.all_pins = set() - # A set of connected pin groups + + # This is a set of pin groups. Each group consists of overlapping pin shapes on the same layer. self.pin_groups = {} - # The corresponding sets (components) of grids for each pin - self.pin_components = {} + # These are the corresponding pin grids for each pin group. + self.pin_grids = {} + # The corresponding set of partially blocked grids for each pin group. + # These are blockages for other nets but unblocked for this component. + self.pin_blockages = {} ### The blockage data structures - # A list of pin layout shapes that are blockages + # A list of metal shapes (using the same pin_layout structure) that are not pins but blockages. self.blockages=[] - # A set of blocked grids + # The corresponding set of blocked grids for above pin shapes self.blocked_grids = set() - # The corresponding set of partially blocked grids for each component. - # These are blockages for other nets but unblocked for this component. - self.pin_component_blockages = {} ### The routed data structures # A list of paths that have been "routed" @@ -79,7 +80,7 @@ class router: self.all_pins = set() self.pin_groups = {} self.pin_grids = {} - self.pin_paritals = {} + self.pin_blockages = {} # DO NOT clear the blockages as these don't change self.rg.reinit() @@ -159,7 +160,7 @@ class router: self.all_pins.update(pin_set) for pin in self.pins[pin_name]: - debug.info(2,"Found pin {}".format(str(pin))) + debug.info(2,"Retrieved pin {}".format(str(pin))) @@ -181,7 +182,6 @@ class router: for layer in [self.vert_layer_number,self.horiz_layer_number]: self.retrieve_blockages(layer) - self.convert_blockages() # # def reinit(self): # # """ @@ -207,6 +207,9 @@ class router: # This will get all shapes as blockages and convert to grid units # This ignores shapes that were pins self.find_blockages() + + # Convert the blockages to grid units + self.convert_blockages() # This will convert the pins to grid units # It must be done after blockages to ensure no DRCs between expanded pins and blocked grids @@ -216,12 +219,12 @@ class router: # Enclose the continguous grid units in a metal rectangle to fix some DRCs self.enclose_pins() - def prepare_blockages(self): + 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(1,"Preparing blockages.") + debug.info(3,"Preparing blockages.") # Start fresh. Not the best for run-time, but simpler. self.clear_blockages() @@ -233,13 +236,15 @@ class router: self.set_supply_rail_blocked(True) # Block all of the pin components (some will be unblocked if they're a source/target) - for name in self.pin_components.keys(): - self.set_blockages(self.pin_components[name],True) + for name in self.pin_grids.keys(): + self.set_blockages(self.pin_grids[name],True) - # Block all of the pin component partial blockages - for name in self.pin_component_blockages.keys(): - self.set_blockages(self.pin_component_blockages[name],True) - + + # 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 + self.set_blockages(self.pin_grids[pin_name],False) + # These are the paths that have already been routed. self.set_path_blockages() @@ -304,7 +309,7 @@ class router: """ Clear all blockages on the grid. """ - debug.info(2,"Clearing all blockages") + debug.info(3,"Clearing all blockages") self.rg.clear_blockages() def set_blockages(self, blockages, value=True): @@ -730,18 +735,13 @@ class router: def convert_pins(self, pin_name): """ - Convert the pin groups into pin tracks and blockage tracks + Convert the pin groups into pin tracks and blockage tracks. """ try: - self.pin_components[pin_name] + self.pin_grids[pin_name] except: - self.pin_components[pin_name] = [] + self.pin_grids[pin_name] = [] - try: - self.pin_component_blockages[pin_name] - except: - self.pin_component_blockages[pin_name] = [] - found_pin = False for pg in self.pin_groups[pin_name]: #print("PG ",pg) @@ -757,27 +757,37 @@ class router: blockage_in_tracks = self.convert_blockage(pin) blockage_set.update(blockage_in_tracks) + # If we have a blockage, we must remove the grids + # Remember, this excludes the pin blockages already + shared_set = pin_set & self.blocked_grids + if shared_set: + debug.info(2,"Removing pins {}".format(shared_set)) + shared_set = blockage_set & self.blocked_grids + if shared_set: + debug.info(2,"Removing blocks {}".format(shared_set)) + pin_set.difference_update(self.blocked_grids) + blockage_set.difference_update(self.blocked_grids) debug.info(2," pins {}".format(pin_set)) debug.info(2," blocks {}".format(blockage_set)) # At least one of the groups must have some valid tracks - if (len(pin_set) == 0): + if (len(pin_set)==0 and len(blockage_set)==0): self.write_debug_gds() - debug.error("Unable to find pin on grid.",-1) + debug.error("Unable to find unblocked pin on grid.") # We need to route each of the components, so don't combine the groups - self.pin_components[pin_name].append(pin_set) + self.pin_grids[pin_name].append(pin_set | blockage_set) # Add all of the partial blocked grids to the set for the design # if they are not blocked by other metal - partial_set = blockage_set - pin_set - self.blocked_grids - self.pin_component_blockages[pin_name].append(partial_set) + #partial_set = blockage_set - pin_set + #self.pin_blockages[pin_name].append(partial_set) # We should not have added the pins to the blockages, # but remove them just in case # Partial set may still be in the blockages if there were # other shapes disconnected from the pins that were also overlapping - self.blocked_grids.difference_update(pin_set) + #self.blocked_grids.difference_update(pin_set) def enclose_pin_grids(self, grids, seed): @@ -789,7 +799,7 @@ class router: # We may have started with an empty set if not grids: - return + return None # Start with the seed ll = seed @@ -800,7 +810,7 @@ class router: while True: right = row[-1] + vector3d(1,0,0) # Can't move if not in the pin shape - if right in grids: + if right in grids and right not in self.blocked_grids: row.append(right) else: break @@ -809,7 +819,7 @@ class router: next_row = [x+vector3d(0,1,0) for x in row] for cell in next_row: # Can't move if any cell is not in the pin shape - if cell not in grids: + if cell not in grids or cell in self.blocked_grids: break else: row = next_row @@ -820,8 +830,66 @@ class router: # Add a shape from ll to ur ur = row[-1] - self.add_enclosure(ll, ur, ll.z) + return self.add_enclosure(ll, ur, ll.z) + + def compute_enclosures(self, tracks): + """ + Find the minimum rectangle enclosures of the given tracks. + """ + pin_list = [] + for seed in tracks: + pin_list.append(self.enclose_pin_grids(tracks, seed)) + + # Prune any enclosre that is contained in another + new_pin_list = pin_list + for pin1 in pin_list: + for pin2 in pin_list: + if pin1 == pin2: + continue + if pin2.contains(pin1): + try: + new_pin_list.remove(pin1) + except ValueError: + pass + + return new_pin_list + + def overlap_any_shape(self, pin_list, shape_list): + """ + Does the given pin overlap any of the shapes in the pin list. + """ + for pin in pin_list: + for other in shape_list: + if pin.overlaps(other): + return True + + return False + + def max_pin_layout(self, pin_list): + """ + Return the max area pin_layout + """ + biggest = pin_list[0] + for pin in pin_list: + if pin.area() > biggest.area(): + biggest = pin + + return pin + + def find_smallest_connector(self, pin_list, enclosure_list): + """ + Compute all of the connectors between non-overlapping pins and enclosures. + Return the smallest. + """ + smallest = None + for pin in pin_list: + for enclosure in enclosure_list: + new_enclosure = self.compute_enclosure(pin, enclosure) + if smallest == None or new_enclosure.area()0: # Display the inflated blockage for blockage in self.blockages: debug.info(1,"Adding {}".format(blockage)) @@ -1160,7 +1278,7 @@ class router: width=ur.x-ll.x, height=ur.y-ll.y) if OPTS.debug_level>1: - #self.set_blockages(self.blocked_grids,True) + self.set_blockages(self.blocked_grids,True) grid_keys=self.rg.map.keys() partial_track=vector(0,self.track_width/6.0) for g in grid_keys: diff --git a/compiler/router/signal_grid.py b/compiler/router/signal_grid.py index 5c88d74d..0f8d6315 100644 --- a/compiler/router/signal_grid.py +++ b/compiler/router/signal_grid.py @@ -42,14 +42,14 @@ class signal_grid(grid): We will use an A* search, so this cost must be pessimistic. Cost so far will be the length of the path. """ - debug.info(1,"Initializing queue.") + #debug.info(3,"Initializing queue.") # Counter is used to not require data comparison in Python 3.x # Items will be returned in order they are added during cost ties self.counter = 0 for s in self.source: cost = self.cost_to_target(s) - debug.info(2,"Init: cost=" + str(cost) + " " + str([s])) + debug.info(3,"Init: cost=" + str(cost) + " " + str([s])) heappush(self.q,(cost,self.counter,grid_path([vector3d(s)]))) self.counter+=1 @@ -83,12 +83,12 @@ class signal_grid(grid): while len(self.q)>0: # should we keep the path in the queue as well or just the final node? (cost,count,curpath) = heappop(self.q) - debug.info(2,"Queue size: size=" + str(len(self.q)) + " " + str(cost)) - debug.info(3,"Expanding: cost=" + str(cost) + " " + str(curpath)) + debug.info(3,"Queue size: size=" + str(len(self.q)) + " " + str(cost)) + debug.info(4,"Expanding: cost=" + str(cost) + " " + str(curpath)) # expand the last element neighbors = self.expand_dirs(curpath) - debug.info(3,"Neighbors: " + str(neighbors)) + debug.info(4,"Neighbors: " + str(neighbors)) for n in neighbors: # make a new copy of the path to not update the old ones @@ -108,7 +108,7 @@ class signal_grid(grid): if (self.map[n[0]].min_cost==-1 or predicted_cost= self.rail_track_width-1 and ur.y-ll.y >= self.rail_track_width-1: - via_flag[vindex]=True - via_flag[hindex]=True + vertical_flags[vindex]=True + horizontal_flags[hindex]=True via_areas.append(overlap) - # Go through and add the vias at the center of the intersection for (ll,ur) in via_areas: center = (ll + ur).scale(0.5,0.5,0) self.add_via(center,self.rail_track_width) - # Remove the paths that have not been connected by any via - remove_indices = [i for i,x in enumerate(via_flag) if not x] - for index in remove_indices: - debug.info(1,"Removing disconnected supply rail {}".format(self.supply_rails[index])) - del self.supply_rails[index] + # Retrieve the original indices into supply_rails for removal + remove_hrails = [rail for flag,rail in zip(horizontal_flags,horizontal_rails) if not flag] + remove_vrails = [rail for flag,rail in zip(vertical_flags,vertical_rails) if not flag] + for rail in remove_hrails + remove_vrails: + debug.info(1,"Removing disconnected supply rail {}".format(rail)) + self.supply_rails.remove(rail) def add_supply_rails(self, name): """ @@ -139,8 +136,8 @@ class supply_router(router): def route_supply_rails(self, name, supply_number): """ Route the horizontal and vertical supply rails across the entire design. + Must be done with lower left at 0,0 """ - start_offset = supply_number*self.rail_track_width max_yoffset = self.rg.ur.y max_xoffset = self.rg.ur.x @@ -166,6 +163,7 @@ class supply_router(router): # Add the supply rail vias (and prune disconnected rails) self.connect_supply_rails(name) + # Add the rails themselves self.add_supply_rails(name) @@ -187,7 +185,17 @@ class supply_router(router): if not wave_path: return None - if len(wave_path)>=2*self.rail_track_width: + # We must have at least 2 tracks to drop plus 2 tracks for a via + if len(wave_path)>=4*self.rail_track_width: + # drop the first and last steps to leave escape routing room + # around the blockage that stopped the probe + # except, don't drop the first if it is the first in a row/column + if (direct==direction.NORTH and seed_wave[0].y>0): + wave_path.trim_first() + elif (direct == direction.EAST and seed_wave[0].x>0): + wave_path.trim_first() + + wave_path.trim_last() wave_path.name = name self.supply_rails.append(wave_path) @@ -216,13 +224,7 @@ class supply_router(router): self.rg.reinit() - self.prepare_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 - self.set_blockages(self.pin_components[pin_name],False) - self.set_blockages(self.pin_component_blockages[pin_name],False) + self.prepare_blockages(pin_name) # Add the single component of the pin as the source # which unmarks it as a blockage too diff --git a/compiler/sram_base.py b/compiler/sram_base.py index 7b616a9c..df39a062 100644 --- a/compiler/sram_base.py +++ b/compiler/sram_base.py @@ -82,9 +82,9 @@ class sram_base(design): self.offset_all_coordinates() - # FIXME: Only works in positive directions - self.supply_route() - + # Must be done after offsetting lower-left + self.route_supplies() + highest_coord = self.find_highest_coords() self.width = highest_coord[0] self.height = highest_coord[1] @@ -92,23 +92,8 @@ class sram_base(design): self.DRC_LVS(final_verification=True) - def route_vdd_gnd_pins(self): - """ Propagate all vdd/gnd pins up to this level for all modules """ - - #These are the instances that every bank has - top_instances = [self.bank_inst, - self.row_addr_dff_inst, - self.data_dff_inst, - self.control_logic_inst[0]] - if self.col_addr_dff: - top_instances.append(self.col_addr_dff_inst) - - for inst in top_instances: - self.copy_layout_pin(inst, "vdd") - self.copy_layout_pin(inst, "gnd") - - def supply_route(self): + def route_supplies(self): """ Route the supply grid and connect the pins to them. """ for inst in self.insts: @@ -211,31 +196,6 @@ class sram_base(design): length=self.control_bus_width)) - def route_vdd_gnd(self): - """ Propagate all vdd/gnd pins up to this level for all modules """ - - # These are the instances that every bank has - top_instances = [self.bitcell_array_inst, - self.precharge_array_inst, - self.sense_amp_array_inst, - self.write_driver_array_inst, - self.tri_gate_array_inst, - self.row_decoder_inst, - self.wordline_driver_inst] - - # Add these if we use the part... - if self.col_addr_size > 0: - top_instances.append(self.col_decoder_inst) - top_instances.append(self.col_mux_array_inst) - - if self.num_banks > 1: - top_instances.append(self.bank_select_inst) - - - for inst in top_instances: - self.copy_layout_pin(inst, "vdd") - self.copy_layout_pin(inst, "gnd") - def add_multi_bank_modules(self): """ Create the multibank address flops and bank decoder """ diff --git a/compiler/tests/04_replica_pbitcell_test.py b/compiler/tests/04_replica_pbitcell_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/06_hierarchical_decoder_test.py b/compiler/tests/06_hierarchical_decoder_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/06_hierarchical_predecode2x4_test.py b/compiler/tests/06_hierarchical_predecode2x4_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/06_hierarchical_predecode3x8_test.py b/compiler/tests/06_hierarchical_predecode3x8_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/14_replica_bitline_test.py b/compiler/tests/14_replica_bitline_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/19_bank_select_test.py b/compiler/tests/19_bank_select_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/19_pmulti_bank_test.py b/compiler/tests/19_pmulti_bank_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/20_sram_1bank_test.py b/compiler/tests/20_sram_1bank_test.py index ce482b6d..5a3ca148 100755 --- a/compiler/tests/20_sram_1bank_test.py +++ b/compiler/tests/20_sram_1bank_test.py @@ -20,30 +20,38 @@ class sram_1bank_test(openram_test): c = sram_config(word_size=4, num_words=16, num_banks=1) - - c.words_per_row=1 - debug.info(1, "Single bank, no column mux with control logic") - a = sram(c, "sram1") - self.local_check(a, final_verification=True) - c.num_words=32 - c.words_per_row=2 - debug.info(1, "Single bank two way column mux with control logic") - a = sram(c, "sram2") - self.local_check(a, final_verification=True) + if True: + c.word_size=4 + c.num_words=16 + c.words_per_row=1 + debug.info(1, "Single bank, no column mux with control logic") + a = sram(c, "sram1") + self.local_check(a, final_verification=True) - c.num_words=64 - c.words_per_row=4 - debug.info(1, "Single bank, four way column mux with control logic") - a = sram(c, "sram3") - self.local_check(a, final_verification=True) + if True: + c.word_size=4 + c.num_words=32 + c.words_per_row=2 + debug.info(1, "Single bank two way column mux with control logic") + a = sram(c, "sram2") + self.local_check(a, final_verification=True) - c.word_size=2 - c.num_words=128 - c.words_per_row=8 - debug.info(1, "Single bank, eight way column mux with control logic") - a = sram(c, "sram4") - self.local_check(a, final_verification=True) + if True: + c.word_size=4 + c.num_words=64 + c.words_per_row=4 + debug.info(1, "Single bank, four way column mux with control logic") + a = sram(c, "sram3") + self.local_check(a, final_verification=True) + + if True: + c.word_size=2 + c.num_words=128 + c.words_per_row=8 + debug.info(1, "Single bank, eight way column mux with control logic") + a = sram(c, "sram4") + self.local_check(a, final_verification=True) globals.end_openram() diff --git a/compiler/tests/22_hspice_psram_func_test.py b/compiler/tests/22_hspice_psram_func_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/22_hspice_sram_func_test.py b/compiler/tests/22_hspice_sram_func_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/22_ngspice_psram_func_test.py b/compiler/tests/22_ngspice_psram_func_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/22_ngspice_sram_func_test.py b/compiler/tests/22_ngspice_sram_func_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/config_20_freepdk45.py b/compiler/tests/config_20_freepdk45.py old mode 100644 new mode 100755 diff --git a/compiler/tests/config_20_scn3me_subm.py b/compiler/tests/config_20_scn3me_subm.py old mode 100644 new mode 100755 diff --git a/compiler/tests/config_20_scn4m_subm.py b/compiler/tests/config_20_scn4m_subm.py old mode 100644 new mode 100755 diff --git a/compiler/tests/sram1.gds b/compiler/tests/sram1.gds deleted file mode 100644 index d6ed28eb6391318f026a98274c50b90601202712..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 304042 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 SUFciqRxbEw86)q=Nbi5xVB-z| diff --git a/compiler/tests/sram1.lef b/compiler/tests/sram1.lef deleted file mode 100644 index c0563063..00000000 --- a/compiler/tests/sram1.lef +++ /dev/null @@ -1,19 +0,0 @@ -VERSION 5.4 ; -NAMESCASESENSITIVE ON ; -BUSBITCHARS "[]" ; -DIVIDERCHAR "/" ; -UNITS - DATABASE MICRONS 1000 ; -END UNITS -SITE MacroSite - CLASS Core ; - SIZE 324000.0 by 421500.0 ; -END MacroSite -MACRO sram1 - CLASS BLOCK ; - SIZE 324000.0 BY 421500.0 ; - SYMMETRY X Y R90 ; - SITE MacroSite ; - PIN DIN[0] - DIRECTION INPUT ; - PORT diff --git a/compiler/tests/sram1.sp b/compiler/tests/sram1.sp deleted file mode 100644 index 622af672..00000000 --- a/compiler/tests/sram1.sp +++ /dev/null @@ -1,602 +0,0 @@ -************************************************** -* OpenRAM generated memory. -* Words: 16 -* Data bits: 4 -* Banks: 1 -* Column mux: 1:1 -************************************************** -* Positive edge-triggered FF -.subckt dff D Q clk vdd gnd -M0 vdd clk a_2_6# vdd p w=12u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M1 a_17_74# D vdd vdd p w=6u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M2 a_22_6# clk a_17_74# vdd p w=6u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M3 a_31_74# a_2_6# a_22_6# vdd p w=6u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M4 vdd a_34_4# a_31_74# vdd p w=6u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M5 a_34_4# a_22_6# vdd vdd p w=6u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M6 a_61_74# a_34_4# vdd vdd p w=6u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M7 a_66_6# a_2_6# a_61_74# vdd p w=6u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M8 a_76_84# clk a_66_6# vdd p w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M9 vdd Q a_76_84# vdd p w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M10 gnd clk a_2_6# gnd n w=6u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M11 Q a_66_6# vdd vdd p w=12u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M12 a_17_6# D gnd gnd n w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M13 a_22_6# a_2_6# a_17_6# gnd n w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M14 a_31_6# clk a_22_6# gnd n w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M15 gnd a_34_4# a_31_6# gnd n w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M16 a_34_4# a_22_6# gnd gnd n w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M17 a_61_6# a_34_4# gnd gnd n w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M18 a_66_6# clk a_61_6# gnd n w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M19 a_76_6# a_2_6# a_66_6# gnd n w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M20 gnd Q a_76_6# gnd n w=3u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -M21 Q a_66_6# gnd gnd n w=6u l=0.6u -+ ad=0p pd=0u as=0p ps=0u -.ends dff - -* ptx M{0} {1} n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p - -* ptx M{0} {1} p m=1 w=4.8u l=0.6u pd=10.799999999999999u ps=10.799999999999999u as=7.199999999999999p ad=7.199999999999999p - -.SUBCKT pinv_2 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=4.8u l=0.6u pd=10.799999999999999u ps=10.799999999999999u as=7.199999999999999p ad=7.199999999999999p -Mpinv_nmos Z A gnd gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -.ENDS pinv_2 - -.SUBCKT dff_inv_2 D Q Qb clk vdd gnd -Xdff_inv_dff D Q clk vdd gnd dff -Xdff_inv_inv1 Q Qb vdd gnd pinv_2 -.ENDS dff_inv_2 - -.SUBCKT dff_array_3x1 din[0] din[1] din[2] dout[0] dout_bar[0] dout[1] dout_bar[1] dout[2] dout_bar[2] clk vdd gnd -XXdff_r0_c0 din[0] dout[0] dout_bar[0] clk vdd gnd dff_inv_2 -XXdff_r1_c0 din[1] dout[1] dout_bar[1] clk vdd gnd dff_inv_2 -XXdff_r2_c0 din[2] dout[2] dout_bar[2] clk vdd gnd dff_inv_2 -.ENDS dff_array_3x1 - -* ptx M{0} {1} p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p - -.SUBCKT pnand2_1 A B Z vdd gnd -Mpnand2_pmos1 vdd A Z vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_pmos2 Z B vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_nmos1 Z B net1 gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_nmos2 net1 A gnd gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -.ENDS pnand2_1 - -.SUBCKT pnand3_1 A B C Z vdd gnd -Mpnand3_pmos1 vdd A Z vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_pmos2 Z B vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_pmos3 Z C vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_nmos1 Z C net1 gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_nmos2 net1 B net2 gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_nmos3 net2 A gnd gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -.ENDS pnand3_1 - -* ptx M{0} {1} n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p - -.SUBCKT pinv_3 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpinv_nmos Z A gnd gnd n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -.ENDS pinv_3 - -* ptx M{0} {1} n m=1 w=4.8u l=0.6u pd=10.799999999999999u ps=10.799999999999999u as=7.199999999999999p ad=7.199999999999999p - -* ptx M{0} {1} p m=1 w=9.6u l=0.6u pd=20.4u ps=20.4u as=14.399999999999999p ad=14.399999999999999p - -.SUBCKT pinv_4 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=9.6u l=0.6u pd=20.4u ps=20.4u as=14.399999999999999p ad=14.399999999999999p -Mpinv_nmos Z A gnd gnd n m=1 w=4.8u l=0.6u pd=10.799999999999999u ps=10.799999999999999u as=7.199999999999999p ad=7.199999999999999p -.ENDS pinv_4 - -* ptx M{0} {1} n m=4 w=4.8u l=0.6u pd=10.799999999999999u ps=10.799999999999999u as=7.199999999999999p ad=7.199999999999999p - -* ptx M{0} {1} p m=4 w=9.6u l=0.6u pd=20.4u ps=20.4u as=14.399999999999999p ad=14.399999999999999p - -.SUBCKT pinv_5 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=4 w=9.6u l=0.6u pd=20.4u ps=20.4u as=14.399999999999999p ad=14.399999999999999p -Mpinv_nmos Z A gnd gnd n m=4 w=4.8u l=0.6u pd=10.799999999999999u ps=10.799999999999999u as=7.199999999999999p ad=7.199999999999999p -.ENDS pinv_5 - -.SUBCKT pinvbuf_4_16 A Zb Z vdd gnd -Xbuf_inv1 A zb_int vdd gnd pinv_3 -Xbuf_inv2 zb_int z_int vdd gnd pinv_4 -Xbuf_inv3 z_int Zb vdd gnd pinv_5 -Xbuf_inv4 zb_int Z vdd gnd pinv_5 -.ENDS pinvbuf_4_16 - -.SUBCKT pinv_6 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpinv_nmos Z A gnd gnd n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -.ENDS pinv_6 - -.SUBCKT pinv_7 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=9.6u l=0.6u pd=20.4u ps=20.4u as=14.399999999999999p ad=14.399999999999999p -Mpinv_nmos Z A gnd gnd n m=1 w=4.8u l=0.6u pd=10.799999999999999u ps=10.799999999999999u as=7.199999999999999p ad=7.199999999999999p -.ENDS pinv_7 - -.SUBCKT pinv_8 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=4 w=9.6u l=0.6u pd=20.4u ps=20.4u as=14.399999999999999p ad=14.399999999999999p -Mpinv_nmos Z A gnd gnd n m=4 w=4.8u l=0.6u pd=10.799999999999999u ps=10.799999999999999u as=7.199999999999999p ad=7.199999999999999p -.ENDS pinv_8 - -*********************** "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 - -*********************** "cell_6t" ****************************** -.SUBCKT cell_6t bl br wl vdd gnd -M_1 net_1 net_2 vdd vdd p W='0.9u' L=1.2u -M_2 net_2 net_1 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 net_1 gnd n W='1.2u' L=0.6u -M_5 net_2 net_1 gnd gnd n W='2.4u' L=0.6u -M_6 net_1 net_2 gnd gnd n W='2.4u' L=0.6u -.ENDS $ cell_6t - -.SUBCKT bitline_load bl[0] br[0] wl[0] wl[1] wl[2] wl[3] vdd gnd -Xbit_r0_c0 bl[0] br[0] wl[0] vdd gnd cell_6t -Xbit_r1_c0 bl[0] br[0] wl[1] vdd gnd cell_6t -Xbit_r2_c0 bl[0] br[0] wl[2] vdd gnd cell_6t -Xbit_r3_c0 bl[0] br[0] wl[3] vdd gnd cell_6t -.ENDS bitline_load - -.SUBCKT pinv_9 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpinv_nmos Z A gnd gnd n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -.ENDS pinv_9 - -.SUBCKT delay_chain in out vdd gnd -Xdinv0 in dout_1 vdd gnd pinv_9 -Xdload_0_0 dout_1 n_0_0 vdd gnd pinv_9 -Xdload_0_1 dout_1 n_0_1 vdd gnd pinv_9 -Xdload_0_2 dout_1 n_0_2 vdd gnd pinv_9 -Xdinv1 dout_1 dout_2 vdd gnd pinv_9 -Xdload_1_0 dout_2 n_1_0 vdd gnd pinv_9 -Xdload_1_1 dout_2 n_1_1 vdd gnd pinv_9 -Xdload_1_2 dout_2 n_1_2 vdd gnd pinv_9 -Xdinv2 dout_2 out vdd gnd pinv_9 -Xdload_2_0 out n_2_0 vdd gnd pinv_9 -Xdload_2_1 out n_2_1 vdd gnd pinv_9 -Xdload_2_2 out n_2_2 vdd gnd pinv_9 -.ENDS delay_chain - -.SUBCKT pinv_10 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpinv_nmos Z A gnd gnd n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -.ENDS pinv_10 - -* ptx M{0} {1} p m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p - -.SUBCKT replica_bitline en out vdd gnd -Xrbl_inv bl[0] out vdd gnd pinv_10 -Mrbl_access_tx vdd delayed_en bl[0] vdd p m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -Xdelay_chain en delayed_en vdd gnd delay_chain -Xbitcell bl[0] br[0] delayed_en vdd gnd replica_cell_6t -Xload bl[0] br[0] gnd gnd gnd gnd vdd gnd bitline_load -.ENDS replica_bitline - -.SUBCKT control_logic csb web oeb clk s_en w_en tri_en tri_en_bar clk_buf_bar clk_buf vdd gnd -Xctrl_dffs csb web oeb cs_bar cs we_bar we oe_bar oe clk_buf vdd gnd dff_array_3x1 -Xclkbuf clk clk_buf_bar clk_buf vdd gnd pinvbuf_4_16 -Xnand3_w_en_bar clk_buf_bar cs we w_en_bar vdd gnd pnand3_1 -Xinv_pre_w_en w_en_bar pre_w_en vdd gnd pinv_6 -Xinv_pre_w_en_bar pre_w_en pre_w_en_bar vdd gnd pinv_7 -Xinv_w_en2 pre_w_en_bar w_en vdd gnd pinv_8 -Xinv_tri_en1 pre_tri_en_bar pre_tri_en1 vdd gnd pinv_7 -Xtri_en_buf1 pre_tri_en1 pre_tri_en_bar1 vdd gnd pinv_7 -Xtri_en_buf2 pre_tri_en_bar1 tri_en vdd gnd pinv_8 -Xnand2_tri_en clk_buf_bar oe pre_tri_en_bar vdd gnd pnand2_1 -Xtri_en_bar_buf1 pre_tri_en_bar pre_tri_en2 vdd gnd pinv_7 -Xtri_en_bar_buf2 pre_tri_en2 tri_en_bar vdd gnd pinv_8 -Xnand3_rblk_bar clk_buf_bar oe cs rblk_bar vdd gnd pnand3_1 -Xinv_rblk rblk_bar rblk vdd gnd pinv_6 -Xinv_s_en pre_s_en_bar s_en vdd gnd pinv_8 -Xinv_pre_s_en_bar pre_s_en pre_s_en_bar vdd gnd pinv_7 -Xreplica_bitline rblk pre_s_en vdd gnd replica_bitline -.ENDS control_logic - -.SUBCKT dff_array din[0] din[1] din[2] din[3] dout[0] dout[1] dout[2] dout[3] clk vdd gnd -XXdff_r0_c0 din[0] dout[0] clk vdd gnd dff -XXdff_r1_c0 din[1] dout[1] clk vdd gnd dff -XXdff_r2_c0 din[2] dout[2] clk vdd gnd dff -XXdff_r3_c0 din[3] dout[3] clk vdd gnd dff -.ENDS dff_array - -.SUBCKT bitcell_array bl[0] br[0] bl[1] br[1] bl[2] br[2] bl[3] br[3] 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 -Xbit_r0_c0 bl[0] br[0] wl[0] vdd gnd cell_6t -Xbit_r1_c0 bl[0] br[0] wl[1] vdd gnd cell_6t -Xbit_r2_c0 bl[0] br[0] wl[2] vdd gnd cell_6t -Xbit_r3_c0 bl[0] br[0] wl[3] vdd gnd cell_6t -Xbit_r4_c0 bl[0] br[0] wl[4] vdd gnd cell_6t -Xbit_r5_c0 bl[0] br[0] wl[5] vdd gnd cell_6t -Xbit_r6_c0 bl[0] br[0] wl[6] vdd gnd cell_6t -Xbit_r7_c0 bl[0] br[0] wl[7] vdd gnd cell_6t -Xbit_r8_c0 bl[0] br[0] wl[8] vdd gnd cell_6t -Xbit_r9_c0 bl[0] br[0] wl[9] vdd gnd cell_6t -Xbit_r10_c0 bl[0] br[0] wl[10] vdd gnd cell_6t -Xbit_r11_c0 bl[0] br[0] wl[11] vdd gnd cell_6t -Xbit_r12_c0 bl[0] br[0] wl[12] vdd gnd cell_6t -Xbit_r13_c0 bl[0] br[0] wl[13] vdd gnd cell_6t -Xbit_r14_c0 bl[0] br[0] wl[14] vdd gnd cell_6t -Xbit_r15_c0 bl[0] br[0] wl[15] vdd gnd cell_6t -Xbit_r0_c1 bl[1] br[1] wl[0] vdd gnd cell_6t -Xbit_r1_c1 bl[1] br[1] wl[1] vdd gnd cell_6t -Xbit_r2_c1 bl[1] br[1] wl[2] vdd gnd cell_6t -Xbit_r3_c1 bl[1] br[1] wl[3] vdd gnd cell_6t -Xbit_r4_c1 bl[1] br[1] wl[4] vdd gnd cell_6t -Xbit_r5_c1 bl[1] br[1] wl[5] vdd gnd cell_6t -Xbit_r6_c1 bl[1] br[1] wl[6] vdd gnd cell_6t -Xbit_r7_c1 bl[1] br[1] wl[7] vdd gnd cell_6t -Xbit_r8_c1 bl[1] br[1] wl[8] vdd gnd cell_6t -Xbit_r9_c1 bl[1] br[1] wl[9] vdd gnd cell_6t -Xbit_r10_c1 bl[1] br[1] wl[10] vdd gnd cell_6t -Xbit_r11_c1 bl[1] br[1] wl[11] vdd gnd cell_6t -Xbit_r12_c1 bl[1] br[1] wl[12] vdd gnd cell_6t -Xbit_r13_c1 bl[1] br[1] wl[13] vdd gnd cell_6t -Xbit_r14_c1 bl[1] br[1] wl[14] vdd gnd cell_6t -Xbit_r15_c1 bl[1] br[1] wl[15] vdd gnd cell_6t -Xbit_r0_c2 bl[2] br[2] wl[0] vdd gnd cell_6t -Xbit_r1_c2 bl[2] br[2] wl[1] vdd gnd cell_6t -Xbit_r2_c2 bl[2] br[2] wl[2] vdd gnd cell_6t -Xbit_r3_c2 bl[2] br[2] wl[3] vdd gnd cell_6t -Xbit_r4_c2 bl[2] br[2] wl[4] vdd gnd cell_6t -Xbit_r5_c2 bl[2] br[2] wl[5] vdd gnd cell_6t -Xbit_r6_c2 bl[2] br[2] wl[6] vdd gnd cell_6t -Xbit_r7_c2 bl[2] br[2] wl[7] vdd gnd cell_6t -Xbit_r8_c2 bl[2] br[2] wl[8] vdd gnd cell_6t -Xbit_r9_c2 bl[2] br[2] wl[9] vdd gnd cell_6t -Xbit_r10_c2 bl[2] br[2] wl[10] vdd gnd cell_6t -Xbit_r11_c2 bl[2] br[2] wl[11] vdd gnd cell_6t -Xbit_r12_c2 bl[2] br[2] wl[12] vdd gnd cell_6t -Xbit_r13_c2 bl[2] br[2] wl[13] vdd gnd cell_6t -Xbit_r14_c2 bl[2] br[2] wl[14] vdd gnd cell_6t -Xbit_r15_c2 bl[2] br[2] wl[15] vdd gnd cell_6t -Xbit_r0_c3 bl[3] br[3] wl[0] vdd gnd cell_6t -Xbit_r1_c3 bl[3] br[3] wl[1] vdd gnd cell_6t -Xbit_r2_c3 bl[3] br[3] wl[2] vdd gnd cell_6t -Xbit_r3_c3 bl[3] br[3] wl[3] vdd gnd cell_6t -Xbit_r4_c3 bl[3] br[3] wl[4] vdd gnd cell_6t -Xbit_r5_c3 bl[3] br[3] wl[5] vdd gnd cell_6t -Xbit_r6_c3 bl[3] br[3] wl[6] vdd gnd cell_6t -Xbit_r7_c3 bl[3] br[3] wl[7] vdd gnd cell_6t -Xbit_r8_c3 bl[3] br[3] wl[8] vdd gnd cell_6t -Xbit_r9_c3 bl[3] br[3] wl[9] vdd gnd cell_6t -Xbit_r10_c3 bl[3] br[3] wl[10] vdd gnd cell_6t -Xbit_r11_c3 bl[3] br[3] wl[11] vdd gnd cell_6t -Xbit_r12_c3 bl[3] br[3] wl[12] vdd gnd cell_6t -Xbit_r13_c3 bl[3] br[3] wl[13] vdd gnd cell_6t -Xbit_r14_c3 bl[3] br[3] wl[14] vdd gnd cell_6t -Xbit_r15_c3 bl[3] br[3] wl[15] vdd gnd cell_6t -.ENDS bitcell_array - -* ptx M{0} {1} p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p - -.SUBCKT precharge bl br en vdd -Mlower_pmos bl en br vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mupper_pmos1 bl en vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mupper_pmos2 br en vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -.ENDS precharge - -.SUBCKT precharge_array bl[0] br[0] bl[1] br[1] bl[2] br[2] bl[3] br[3] en vdd -Xpre_column_0 bl[0] br[0] en vdd precharge -Xpre_column_1 bl[1] br[1] en vdd precharge -Xpre_column_2 bl[2] br[2] en vdd precharge -Xpre_column_3 bl[3] br[3] en vdd precharge -.ENDS precharge_array -*********************** "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 - - -.SUBCKT sense_amp_array data[0] bl[0] br[0] data[1] bl[1] br[1] data[2] bl[2] br[2] data[3] bl[3] br[3] en vdd gnd -Xsa_d0 bl[0] br[0] data[0] en vdd gnd sense_amp -Xsa_d1 bl[1] br[1] data[1] en vdd gnd sense_amp -Xsa_d2 bl[2] br[2] data[2] en vdd gnd sense_amp -Xsa_d3 bl[3] br[3] data[3] en vdd gnd sense_amp -.ENDS sense_amp_array -*********************** Write_Driver ****************************** -.SUBCKT write_driver din bl br en vdd gnd - -**** Inverter to conver Data_in to data_in_bar ****** -M_1 net_3 din gnd gnd n W='1.2*1u' L=0.6u -M_2 net_3 din vdd vdd p W='2.1*1u' L=0.6u - -**** 2input nand gate follwed by inverter to drive BL ****** -M_3 net_2 en net_7 gnd n W='2.1*1u' L=0.6u -M_4 net_7 din gnd gnd n W='2.1*1u' L=0.6u -M_5 net_2 en vdd vdd p W='2.1*1u' L=0.6u -M_6 net_2 din vdd vdd p W='2.1*1u' L=0.6u - - -M_7 net_1 net_2 vdd vdd p W='2.1*1u' L=0.6u -M_8 net_1 net_2 gnd gnd n W='1.2*1u' L=0.6u - -**** 2input nand gate follwed by inverter to drive BR****** - -M_9 net_4 en vdd vdd p W='2.1*1u' L=0.6u -M_10 net_4 en net_8 gnd n W='2.1*1u' L=0.6u -M_11 net_8 net_3 gnd gnd n W='2.1*1u' L=0.6u -M_12 net_4 net_3 vdd vdd p W='2.1*1u' L=0.6u - -M_13 net_6 net_4 vdd vdd p W='2.1*1u' L=0.6u -M_14 net_6 net_4 gnd gnd n W='1.2*1u' L=0.6u - -************************************************ - -M_15 bl net_6 net_5 gnd n W='3.6*1u' L=0.6u -M_16 br net_1 net_5 gnd n W='3.6*1u' L=0.6u -M_17 net_5 en gnd gnd n W='3.6*1u' L=0.6u - - - -.ENDS $ write_driver - - -.SUBCKT write_driver_array data[0] data[1] data[2] data[3] bl[0] br[0] bl[1] br[1] bl[2] br[2] bl[3] br[3] en vdd gnd -XXwrite_driver0 data[0] bl[0] br[0] en vdd gnd write_driver -XXwrite_driver1 data[1] bl[1] br[1] en vdd gnd write_driver -XXwrite_driver2 data[2] bl[2] br[2] en vdd gnd write_driver -XXwrite_driver3 data[3] bl[3] br[3] en vdd gnd write_driver -.ENDS write_driver_array - -.SUBCKT pinv_11 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpinv_nmos Z A gnd gnd n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -.ENDS pinv_11 - -.SUBCKT pnand2_2 A B Z vdd gnd -Mpnand2_pmos1 vdd A Z vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_pmos2 Z B vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_nmos1 Z B net1 gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_nmos2 net1 A gnd gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -.ENDS pnand2_2 - -.SUBCKT pnand3_2 A B C Z vdd gnd -Mpnand3_pmos1 vdd A Z vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_pmos2 Z B vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_pmos3 Z C vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_nmos1 Z C net1 gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_nmos2 net1 B net2 gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_nmos3 net2 A gnd gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -.ENDS pnand3_2 - -.SUBCKT pinv_12 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpinv_nmos Z A gnd gnd n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -.ENDS pinv_12 - -.SUBCKT pnand2_3 A B Z vdd gnd -Mpnand2_pmos1 vdd A Z vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_pmos2 Z B vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_nmos1 Z B net1 gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_nmos2 net1 A gnd gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -.ENDS pnand2_3 - -.SUBCKT pre2x4 in[0] in[1] out[0] out[1] out[2] out[3] vdd gnd -XXpre_inv[0] in[0] inbar[0] vdd gnd pinv_12 -XXpre_inv[1] in[1] inbar[1] vdd gnd pinv_12 -XXpre_nand_inv[0] Z[0] out[0] vdd gnd pinv_12 -XXpre_nand_inv[1] Z[1] out[1] vdd gnd pinv_12 -XXpre_nand_inv[2] Z[2] out[2] vdd gnd pinv_12 -XXpre_nand_inv[3] Z[3] out[3] vdd gnd pinv_12 -XXpre2x4_nand[0] inbar[0] inbar[1] Z[0] vdd gnd pnand2_3 -XXpre2x4_nand[1] in[0] inbar[1] Z[1] vdd gnd pnand2_3 -XXpre2x4_nand[2] inbar[0] in[1] Z[2] vdd gnd pnand2_3 -XXpre2x4_nand[3] in[0] in[1] Z[3] vdd gnd pnand2_3 -.ENDS pre2x4 - -.SUBCKT pinv_13 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpinv_nmos Z A gnd gnd n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -.ENDS pinv_13 - -.SUBCKT pnand3_3 A B C Z vdd gnd -Mpnand3_pmos1 vdd A Z vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_pmos2 Z B vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_pmos3 Z C vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_nmos1 Z C net1 gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_nmos2 net1 B net2 gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand3_nmos3 net2 A gnd gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -.ENDS pnand3_3 - -.SUBCKT pre3x8 in[0] in[1] in[2] out[0] out[1] out[2] out[3] out[4] out[5] out[6] out[7] vdd gnd -XXpre_inv[0] in[0] inbar[0] vdd gnd pinv_13 -XXpre_inv[1] in[1] inbar[1] vdd gnd pinv_13 -XXpre_inv[2] in[2] inbar[2] vdd gnd pinv_13 -XXpre_nand_inv[0] Z[0] out[0] vdd gnd pinv_13 -XXpre_nand_inv[1] Z[1] out[1] vdd gnd pinv_13 -XXpre_nand_inv[2] Z[2] out[2] vdd gnd pinv_13 -XXpre_nand_inv[3] Z[3] out[3] vdd gnd pinv_13 -XXpre_nand_inv[4] Z[4] out[4] vdd gnd pinv_13 -XXpre_nand_inv[5] Z[5] out[5] vdd gnd pinv_13 -XXpre_nand_inv[6] Z[6] out[6] vdd gnd pinv_13 -XXpre_nand_inv[7] Z[7] out[7] vdd gnd pinv_13 -XXpre3x8_nand[0] inbar[0] inbar[1] inbar[2] Z[0] vdd gnd pnand3_3 -XXpre3x8_nand[1] in[0] inbar[1] inbar[2] Z[1] vdd gnd pnand3_3 -XXpre3x8_nand[2] inbar[0] in[1] inbar[2] Z[2] vdd gnd pnand3_3 -XXpre3x8_nand[3] in[0] in[1] inbar[2] Z[3] vdd gnd pnand3_3 -XXpre3x8_nand[4] inbar[0] inbar[1] in[2] Z[4] vdd gnd pnand3_3 -XXpre3x8_nand[5] in[0] inbar[1] in[2] Z[5] vdd gnd pnand3_3 -XXpre3x8_nand[6] inbar[0] in[1] in[2] Z[6] vdd gnd pnand3_3 -XXpre3x8_nand[7] in[0] in[1] in[2] Z[7] vdd gnd pnand3_3 -.ENDS pre3x8 - -.SUBCKT hierarchical_decoder_16rows A[0] A[1] A[2] A[3] decode[0] decode[1] decode[2] decode[3] decode[4] decode[5] decode[6] decode[7] decode[8] decode[9] decode[10] decode[11] decode[12] decode[13] decode[14] decode[15] vdd gnd -Xpre[0] A[0] A[1] out[0] out[1] out[2] out[3] vdd gnd pre2x4 -Xpre[1] A[2] A[3] out[4] out[5] out[6] out[7] vdd gnd pre2x4 -XDEC_NAND[0] out[0] out[4] Z[0] vdd gnd pnand2_2 -XDEC_NAND[1] out[0] out[5] Z[1] vdd gnd pnand2_2 -XDEC_NAND[2] out[0] out[6] Z[2] vdd gnd pnand2_2 -XDEC_NAND[3] out[0] out[7] Z[3] vdd gnd pnand2_2 -XDEC_NAND[4] out[1] out[4] Z[4] vdd gnd pnand2_2 -XDEC_NAND[5] out[1] out[5] Z[5] vdd gnd pnand2_2 -XDEC_NAND[6] out[1] out[6] Z[6] vdd gnd pnand2_2 -XDEC_NAND[7] out[1] out[7] Z[7] vdd gnd pnand2_2 -XDEC_NAND[8] out[2] out[4] Z[8] vdd gnd pnand2_2 -XDEC_NAND[9] out[2] out[5] Z[9] vdd gnd pnand2_2 -XDEC_NAND[10] out[2] out[6] Z[10] vdd gnd pnand2_2 -XDEC_NAND[11] out[2] out[7] Z[11] vdd gnd pnand2_2 -XDEC_NAND[12] out[3] out[4] Z[12] vdd gnd pnand2_2 -XDEC_NAND[13] out[3] out[5] Z[13] vdd gnd pnand2_2 -XDEC_NAND[14] out[3] out[6] Z[14] vdd gnd pnand2_2 -XDEC_NAND[15] out[3] out[7] Z[15] vdd gnd pnand2_2 -XDEC_INV_[0] Z[0] decode[0] vdd gnd pinv_11 -XDEC_INV_[1] Z[1] decode[1] vdd gnd pinv_11 -XDEC_INV_[2] Z[2] decode[2] vdd gnd pinv_11 -XDEC_INV_[3] Z[3] decode[3] vdd gnd pinv_11 -XDEC_INV_[4] Z[4] decode[4] vdd gnd pinv_11 -XDEC_INV_[5] Z[5] decode[5] vdd gnd pinv_11 -XDEC_INV_[6] Z[6] decode[6] vdd gnd pinv_11 -XDEC_INV_[7] Z[7] decode[7] vdd gnd pinv_11 -XDEC_INV_[8] Z[8] decode[8] vdd gnd pinv_11 -XDEC_INV_[9] Z[9] decode[9] vdd gnd pinv_11 -XDEC_INV_[10] Z[10] decode[10] vdd gnd pinv_11 -XDEC_INV_[11] Z[11] decode[11] vdd gnd pinv_11 -XDEC_INV_[12] Z[12] decode[12] vdd gnd pinv_11 -XDEC_INV_[13] Z[13] decode[13] vdd gnd pinv_11 -XDEC_INV_[14] Z[14] decode[14] vdd gnd pinv_11 -XDEC_INV_[15] Z[15] decode[15] vdd gnd pinv_11 -.ENDS hierarchical_decoder_16rows -*********************** 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 - -.SUBCKT tri_gate_array in[0] in[1] in[2] in[3] out[0] out[1] out[2] out[3] en en_bar vdd gnd -XXtri_gate0 in[0] out[0] en en_bar vdd gnd tri_gate -XXtri_gate1 in[1] out[1] en en_bar vdd gnd tri_gate -XXtri_gate2 in[2] out[2] en en_bar vdd gnd tri_gate -XXtri_gate3 in[3] out[3] en en_bar vdd gnd tri_gate -.ENDS tri_gate_array - -.SUBCKT pinv_14 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpinv_nmos Z A gnd gnd n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -.ENDS pinv_14 - -.SUBCKT pinv_15 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpinv_nmos Z A gnd gnd n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -.ENDS pinv_15 - -.SUBCKT pnand2_4 A B Z vdd gnd -Mpnand2_pmos1 vdd A Z vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_pmos2 Z B vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_nmos1 Z B net1 gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpnand2_nmos2 net1 A gnd gnd n m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -.ENDS pnand2_4 - -.SUBCKT wordline_driver in[0] in[1] in[2] in[3] in[4] in[5] in[6] in[7] in[8] in[9] in[10] in[11] in[12] in[13] in[14] in[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] en vdd gnd -Xwl_driver_inv_en0 en en_bar[0] vdd gnd pinv_15 -Xwl_driver_nand0 en_bar[0] in[0] net[0] vdd gnd pnand2_4 -Xwl_driver_inv0 net[0] wl[0] vdd gnd pinv_14 -Xwl_driver_inv_en1 en en_bar[1] vdd gnd pinv_15 -Xwl_driver_nand1 en_bar[1] in[1] net[1] vdd gnd pnand2_4 -Xwl_driver_inv1 net[1] wl[1] vdd gnd pinv_14 -Xwl_driver_inv_en2 en en_bar[2] vdd gnd pinv_15 -Xwl_driver_nand2 en_bar[2] in[2] net[2] vdd gnd pnand2_4 -Xwl_driver_inv2 net[2] wl[2] vdd gnd pinv_14 -Xwl_driver_inv_en3 en en_bar[3] vdd gnd pinv_15 -Xwl_driver_nand3 en_bar[3] in[3] net[3] vdd gnd pnand2_4 -Xwl_driver_inv3 net[3] wl[3] vdd gnd pinv_14 -Xwl_driver_inv_en4 en en_bar[4] vdd gnd pinv_15 -Xwl_driver_nand4 en_bar[4] in[4] net[4] vdd gnd pnand2_4 -Xwl_driver_inv4 net[4] wl[4] vdd gnd pinv_14 -Xwl_driver_inv_en5 en en_bar[5] vdd gnd pinv_15 -Xwl_driver_nand5 en_bar[5] in[5] net[5] vdd gnd pnand2_4 -Xwl_driver_inv5 net[5] wl[5] vdd gnd pinv_14 -Xwl_driver_inv_en6 en en_bar[6] vdd gnd pinv_15 -Xwl_driver_nand6 en_bar[6] in[6] net[6] vdd gnd pnand2_4 -Xwl_driver_inv6 net[6] wl[6] vdd gnd pinv_14 -Xwl_driver_inv_en7 en en_bar[7] vdd gnd pinv_15 -Xwl_driver_nand7 en_bar[7] in[7] net[7] vdd gnd pnand2_4 -Xwl_driver_inv7 net[7] wl[7] vdd gnd pinv_14 -Xwl_driver_inv_en8 en en_bar[8] vdd gnd pinv_15 -Xwl_driver_nand8 en_bar[8] in[8] net[8] vdd gnd pnand2_4 -Xwl_driver_inv8 net[8] wl[8] vdd gnd pinv_14 -Xwl_driver_inv_en9 en en_bar[9] vdd gnd pinv_15 -Xwl_driver_nand9 en_bar[9] in[9] net[9] vdd gnd pnand2_4 -Xwl_driver_inv9 net[9] wl[9] vdd gnd pinv_14 -Xwl_driver_inv_en10 en en_bar[10] vdd gnd pinv_15 -Xwl_driver_nand10 en_bar[10] in[10] net[10] vdd gnd pnand2_4 -Xwl_driver_inv10 net[10] wl[10] vdd gnd pinv_14 -Xwl_driver_inv_en11 en en_bar[11] vdd gnd pinv_15 -Xwl_driver_nand11 en_bar[11] in[11] net[11] vdd gnd pnand2_4 -Xwl_driver_inv11 net[11] wl[11] vdd gnd pinv_14 -Xwl_driver_inv_en12 en en_bar[12] vdd gnd pinv_15 -Xwl_driver_nand12 en_bar[12] in[12] net[12] vdd gnd pnand2_4 -Xwl_driver_inv12 net[12] wl[12] vdd gnd pinv_14 -Xwl_driver_inv_en13 en en_bar[13] vdd gnd pinv_15 -Xwl_driver_nand13 en_bar[13] in[13] net[13] vdd gnd pnand2_4 -Xwl_driver_inv13 net[13] wl[13] vdd gnd pinv_14 -Xwl_driver_inv_en14 en en_bar[14] vdd gnd pinv_15 -Xwl_driver_nand14 en_bar[14] in[14] net[14] vdd gnd pnand2_4 -Xwl_driver_inv14 net[14] wl[14] vdd gnd pinv_14 -Xwl_driver_inv_en15 en en_bar[15] vdd gnd pinv_15 -Xwl_driver_nand15 en_bar[15] in[15] net[15] vdd gnd pnand2_4 -Xwl_driver_inv15 net[15] wl[15] vdd gnd pinv_14 -.ENDS wordline_driver - -.SUBCKT pinv_16 A Z vdd gnd -Mpinv_pmos Z A vdd vdd p m=1 w=2.4u l=0.6u pd=6.0u ps=6.0u as=3.5999999999999996p ad=3.5999999999999996p -Mpinv_nmos Z A gnd gnd n m=1 w=1.2u l=0.6u pd=3.5999999999999996u ps=3.5999999999999996u as=1.7999999999999998p ad=1.7999999999999998p -.ENDS pinv_16 - -.SUBCKT bank DOUT[0] DOUT[1] DOUT[2] DOUT[3] DIN[0] DIN[1] DIN[2] DIN[3] A[0] A[1] A[2] A[3] s_en w_en tri_en_bar tri_en clk_buf_bar clk_buf vdd gnd -Xbitcell_array bl[0] br[0] bl[1] br[1] bl[2] br[2] bl[3] br[3] 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] bl[2] br[2] bl[3] br[3] clk_buf_bar vdd precharge_array -Xsense_amp_array sa_out[0] bl[0] br[0] sa_out[1] bl[1] br[1] sa_out[2] bl[2] br[2] sa_out[3] bl[3] br[3] s_en vdd gnd sense_amp_array -Xwrite_driver_array DIN[0] DIN[1] DIN[2] DIN[3] bl[0] br[0] bl[1] br[1] bl[2] br[2] bl[3] br[3] w_en vdd gnd write_driver_array -Xtri_gate_array sa_out[0] sa_out[1] sa_out[2] sa_out[3] DOUT[0] DOUT[1] DOUT[2] DOUT[3] tri_en tri_en_bar vdd gnd tri_gate_array -Xrow_decoder A[0] A[1] A[2] A[3] dec_out[0] dec_out[1] dec_out[2] dec_out[3] dec_out[4] dec_out[5] dec_out[6] dec_out[7] dec_out[8] dec_out[9] dec_out[10] dec_out[11] dec_out[12] dec_out[13] dec_out[14] dec_out[15] vdd gnd hierarchical_decoder_16rows -Xwordline_driver dec_out[0] dec_out[1] dec_out[2] dec_out[3] dec_out[4] dec_out[5] dec_out[6] dec_out[7] dec_out[8] dec_out[9] dec_out[10] dec_out[11] dec_out[12] dec_out[13] dec_out[14] dec_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_buf vdd gnd wordline_driver -.ENDS bank - -.SUBCKT sram1 DIN[0] DIN[1] DIN[2] DIN[3] ADDR[0] ADDR[1] ADDR[2] ADDR[3] csb web oeb clk DOUT[0] DOUT[1] DOUT[2] DOUT[3] vdd gnd -Xbank0 DOUT[0] DOUT[1] DOUT[2] DOUT[3] DIN[0] DIN[1] DIN[2] DIN[3] A[0] A[1] A[2] A[3] s_en w_en tri_en_bar tri_en clk_buf_bar clk_buf vdd gnd bank -Xcontrol csb_s web_s oeb_s clk s_en w_en tri_en tri_en_bar clk_buf_bar clk_buf vdd gnd control_logic -Xaddress ADDR[0] ADDR[1] ADDR[2] ADDR[3] A[0] A[1] A[2] A[3] clk_buf vdd gnd dff_array -Xaddress ADDR[0] ADDR[1] ADDR[2] ADDR[3] A[0] A[1] A[2] A[3] clk_buf vdd gnd dff_array -.ENDS sram1 diff --git a/compiler/tests/sram1_TT_5p0V_25C.lib b/compiler/tests/sram1_TT_5p0V_25C.lib deleted file mode 100644 index ddf17785..00000000 --- a/compiler/tests/sram1_TT_5p0V_25C.lib +++ /dev/null @@ -1,347 +0,0 @@ -library (sram1_TT_5p0V_25C_lib){ - delay_model : "table_lookup"; - time_unit : "1ns" ; - voltage_unit : "1v" ; - current_unit : "1mA" ; - resistance_unit : "1kohm" ; - capacitive_load_unit(1 ,fF) ; - leakage_power_unit : "1mW" ; - pulling_resistance_unit :"1kohm" ; - operating_conditions(OC){ - process : 1.0 ; - voltage : 5.0 ; - temperature : 25; - } - - input_threshold_pct_fall : 50.0 ; - output_threshold_pct_fall : 50.0 ; - input_threshold_pct_rise : 50.0 ; - output_threshold_pct_rise : 50.0 ; - slew_lower_threshold_pct_fall : 10.0 ; - slew_upper_threshold_pct_fall : 90.0 ; - slew_lower_threshold_pct_rise : 10.0 ; - slew_upper_threshold_pct_rise : 90.0 ; - - nom_voltage : 5.0; - nom_temperature : 25; - nom_process : 1.0; - default_cell_leakage_power : 0.0 ; - default_leakage_power_density : 0.0 ; - default_input_pin_cap : 1.0 ; - default_inout_pin_cap : 1.0 ; - default_output_pin_cap : 0.0 ; - default_max_transition : 0.5 ; - default_fanout_load : 1.0 ; - default_max_fanout : 4.0 ; - default_connection_class : universal ; - - lu_table_template(CELL_TABLE){ - variable_1 : input_net_transition; - variable_2 : total_output_net_capacitance; - index_1("0.0125, 0.05, 0.4"); - index_2("2.45605, 9.8242, 78.5936"); - } - - lu_table_template(CONSTRAINT_TABLE){ - variable_1 : related_pin_transition; - variable_2 : constrained_pin_transition; - index_1("0.0125, 0.05, 0.4"); - index_2("0.0125, 0.05, 0.4"); - } - - default_operating_conditions : OC; - - - type (DATA){ - base_type : array; - data_type : bit; - bit_width : 4; - bit_from : 0; - bit_to : 3; - } - - type (ADDR){ - base_type : array; - data_type : bit; - bit_width : 4; - bit_from : 0; - bit_to : 3; - } - -cell (sram1){ - memory(){ - type : ram; - address_width : 4; - word_width : 4; - } - interface_timing : true; - dont_use : true; - map_only : true; - dont_touch : true; - area : 136566.0; - - leakage_power () { - when : "CSb"; - value : 0.000202; - } - cell_leakage_power : 0; - bus(DATA){ - bus_type : DATA; - direction : inout; - max_capacitance : 78.5936; - min_capacitance : 2.45605; - three_state : "!OEb & !clk"; - memory_write(){ - address : ADDR; - clocked_on : clk; - } - memory_read(){ - address : ADDR; - } - pin(DATA[3:0]){ - timing(){ - timing_type : setup_rising; - related_pin : "clk"; - rise_constraint(CONSTRAINT_TABLE) { - values("0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009"); - } - fall_constraint(CONSTRAINT_TABLE) { - values("0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009"); - } - } - timing(){ - timing_type : hold_rising; - related_pin : "clk"; - rise_constraint(CONSTRAINT_TABLE) { - values("0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001"); - } - fall_constraint(CONSTRAINT_TABLE) { - values("0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001"); - } - } - timing(){ - timing_sense : non_unate; - related_pin : "clk"; - timing_type : falling_edge; - cell_rise(CELL_TABLE) { - values("0.612, 0.66, 1.1",\ - "0.612, 0.66, 1.1",\ - "0.612, 0.66, 1.1"); - } - cell_fall(CELL_TABLE) { - values("0.612, 0.66, 1.1",\ - "0.612, 0.66, 1.1",\ - "0.612, 0.66, 1.1"); - } - rise_transition(CELL_TABLE) { - values("0.024, 0.081, 0.61",\ - "0.024, 0.081, 0.61",\ - "0.024, 0.081, 0.61"); - } - fall_transition(CELL_TABLE) { - values("0.024, 0.081, 0.61",\ - "0.024, 0.081, 0.61",\ - "0.024, 0.081, 0.61"); - } - } - } - } - - bus(ADDR){ - bus_type : ADDR; - direction : input; - capacitance : 9.8242; - max_transition : 0.4; - pin(ADDR[3:0]){ - timing(){ - timing_type : setup_rising; - related_pin : "clk"; - rise_constraint(CONSTRAINT_TABLE) { - values("0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009"); - } - fall_constraint(CONSTRAINT_TABLE) { - values("0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009"); - } - } - timing(){ - timing_type : hold_rising; - related_pin : "clk"; - rise_constraint(CONSTRAINT_TABLE) { - values("0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001"); - } - fall_constraint(CONSTRAINT_TABLE) { - values("0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001"); - } - } - } - } - - pin(CSb){ - direction : input; - capacitance : 9.8242; - timing(){ - timing_type : setup_rising; - related_pin : "clk"; - rise_constraint(CONSTRAINT_TABLE) { - values("0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009"); - } - fall_constraint(CONSTRAINT_TABLE) { - values("0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009"); - } - } - timing(){ - timing_type : hold_rising; - related_pin : "clk"; - rise_constraint(CONSTRAINT_TABLE) { - values("0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001"); - } - fall_constraint(CONSTRAINT_TABLE) { - values("0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001"); - } - } - } - - pin(OEb){ - direction : input; - capacitance : 9.8242; - timing(){ - timing_type : setup_rising; - related_pin : "clk"; - rise_constraint(CONSTRAINT_TABLE) { - values("0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009"); - } - fall_constraint(CONSTRAINT_TABLE) { - values("0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009"); - } - } - timing(){ - timing_type : hold_rising; - related_pin : "clk"; - rise_constraint(CONSTRAINT_TABLE) { - values("0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001"); - } - fall_constraint(CONSTRAINT_TABLE) { - values("0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001"); - } - } - } - - pin(WEb){ - direction : input; - capacitance : 9.8242; - timing(){ - timing_type : setup_rising; - related_pin : "clk"; - rise_constraint(CONSTRAINT_TABLE) { - values("0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009"); - } - fall_constraint(CONSTRAINT_TABLE) { - values("0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009",\ - "0.009, 0.009, 0.009"); - } - } - timing(){ - timing_type : hold_rising; - related_pin : "clk"; - rise_constraint(CONSTRAINT_TABLE) { - values("0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001"); - } - fall_constraint(CONSTRAINT_TABLE) { - values("0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001",\ - "0.001, 0.001, 0.001"); - } - } - } - - pin(clk){ - clock : true; - direction : input; - capacitance : 9.8242; - internal_power(){ - when : "!CSb & clk & !WEb"; - rise_power(scalar){ - values("10.812808757533329"); - } - fall_power(scalar){ - values("10.812808757533329"); - } - } - internal_power(){ - when : "!CSb & !clk & WEb"; - rise_power(scalar){ - values("10.812808757533329"); - } - fall_power(scalar){ - values("10.812808757533329"); - } - } - internal_power(){ - when : "CSb"; - rise_power(scalar){ - values("0"); - } - fall_power(scalar){ - values("0"); - } - } - timing(){ - timing_type :"min_pulse_width"; - related_pin : clk; - rise_constraint(scalar) { - values("0.0"); - } - fall_constraint(scalar) { - values("0.0"); - } - } - timing(){ - timing_type :"minimum_period"; - related_pin : clk; - rise_constraint(scalar) { - values("0"); - } - fall_constraint(scalar) { - values("0"); - } - } - } - } -} diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py old mode 100644 new mode 100755