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.
This commit is contained in:
Matt Guthaus 2018-10-10 15:15:58 -07:00
parent a2b1d025ab
commit 6bbf66d55b
29 changed files with 334 additions and 1176 deletions

View File

@ -83,26 +83,27 @@ class pin_layout:
max_y = min(ll.y, oll.y) max_y = min(ll.y, oll.y)
return [vector(min_x,min_y),vector(max_x,max_y)] return [vector(min_x,min_y),vector(max_x,max_y)]
def overlaps(self, other): def xoverlaps(self, other):
""" Check if a shape overlaps with a rectangle """ """ Check if shape has x overlap """
(ll,ur) = self.rect (ll,ur) = self.rect
(oll,our) = other.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 x_overlaps = False
y_overlaps = False
# check if self is within other x range # 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): if (ll.x >= oll.x and ll.x <= our.x) or (ur.x >= oll.x and ur.x <= our.x):
x_overlaps = True x_overlaps = True
# check if other is within self x range # 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): if (oll.x >= ll.x and oll.x <= ur.x) or (our.x >= ll.x and our.x <= ur.x):
x_overlaps = True 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 # 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): if (ll.y >= oll.y and ll.y <= our.y) or (ur.y >= oll.y and ur.y <= our.y):
y_overlaps = True 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): if (oll.y >= ll.y and oll.y <= ur.y) or (our.y >= ll.y and our.y <= ur.y):
y_overlaps = True 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 return x_overlaps and y_overlaps
def area(self):
""" Return the area. """
return self.height()*self.width()
def height(self): def height(self):
""" Return height. Abs is for pre-normalized value.""" """ Return height. Abs is for pre-normalized value."""

View File

@ -107,8 +107,7 @@ class bank(design.design):
if self.num_banks > 1: if self.num_banks > 1:
self.route_bank_select() self.route_bank_select()
self.route_vdd_gnd() self.route_supplies()
def create_modules(self): def create_modules(self):
""" Add modules. The order should not matter! """ """ 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) 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 """ """ Propagate all vdd/gnd pins up to this level for all modules """
for inst in self.insts: for inst in self.insts:
self.copy_power_pins(inst,"vdd") self.copy_power_pins(inst,"vdd")

View File

@ -282,15 +282,7 @@ class hierarchical_predecode(design.design):
# Add pins in two locations # Add pins in two locations
for xoffset in [in_xoffset, out_xoffset]: for xoffset in [in_xoffset, out_xoffset]:
pin_pos = vector(xoffset, nand_pin.cy()) pin_pos = vector(xoffset, nand_pin.cy())
self.add_via_center(layers=("metal1", "via1", "metal2"), self.add_power_pin(n, pin_pos)
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)

View File

@ -63,6 +63,18 @@ class grid_path:
def __len__(self): def __len__(self):
return len(self.pathlist) 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): def append(self,item):
""" """
Append the list of items to the cells Append the list of items to the cells

View File

@ -44,19 +44,20 @@ class router:
self.pins = {} self.pins = {}
# This is a set of all pins so that we don't create blockages for these shapes. # This is a set of all pins so that we don't create blockages for these shapes.
self.all_pins = set() 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 = {} self.pin_groups = {}
# The corresponding sets (components) of grids for each pin # These are the corresponding pin grids for each pin group.
self.pin_components = {} 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 ### 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=[] self.blockages=[]
# A set of blocked grids # The corresponding set of blocked grids for above pin shapes
self.blocked_grids = set() 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 ### The routed data structures
# A list of paths that have been "routed" # A list of paths that have been "routed"
@ -79,7 +80,7 @@ class router:
self.all_pins = set() self.all_pins = set()
self.pin_groups = {} self.pin_groups = {}
self.pin_grids = {} self.pin_grids = {}
self.pin_paritals = {} self.pin_blockages = {}
# DO NOT clear the blockages as these don't change # DO NOT clear the blockages as these don't change
self.rg.reinit() self.rg.reinit()
@ -159,7 +160,7 @@ class router:
self.all_pins.update(pin_set) self.all_pins.update(pin_set)
for pin in self.pins[pin_name]: 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]: for layer in [self.vert_layer_number,self.horiz_layer_number]:
self.retrieve_blockages(layer) self.retrieve_blockages(layer)
self.convert_blockages()
# # def reinit(self): # # def reinit(self):
# # """ # # """
@ -207,6 +207,9 @@ class router:
# This will get all shapes as blockages and convert to grid units # This will get all shapes as blockages and convert to grid units
# This ignores shapes that were pins # This ignores shapes that were pins
self.find_blockages() self.find_blockages()
# Convert the blockages to grid units
self.convert_blockages()
# This will convert the pins to grid units # This will convert the pins to grid units
# It must be done after blockages to ensure no DRCs between expanded pins and blocked grids # 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 # Enclose the continguous grid units in a metal rectangle to fix some DRCs
self.enclose_pins() self.enclose_pins()
def prepare_blockages(self): def prepare_blockages(self, pin_name):
""" """
Reset and add all of the blockages in the design. Reset and add all of the blockages in the design.
Names is a list of pins to add as a blockage. 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. # Start fresh. Not the best for run-time, but simpler.
self.clear_blockages() self.clear_blockages()
@ -233,13 +236,15 @@ class router:
self.set_supply_rail_blocked(True) self.set_supply_rail_blocked(True)
# Block all of the pin components (some will be unblocked if they're a source/target) # Block all of the pin components (some will be unblocked if they're a source/target)
for name in self.pin_components.keys(): for name in self.pin_grids.keys():
self.set_blockages(self.pin_components[name],True) self.set_blockages(self.pin_grids[name],True)
# Block all of the pin component partial blockages
for name in self.pin_component_blockages.keys(): # Don't mark the other components as targets since we want to route
self.set_blockages(self.pin_component_blockages[name],True) # 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. # These are the paths that have already been routed.
self.set_path_blockages() self.set_path_blockages()
@ -304,7 +309,7 @@ class router:
""" """
Clear all blockages on the grid. Clear all blockages on the grid.
""" """
debug.info(2,"Clearing all blockages") debug.info(3,"Clearing all blockages")
self.rg.clear_blockages() self.rg.clear_blockages()
def set_blockages(self, blockages, value=True): def set_blockages(self, blockages, value=True):
@ -730,18 +735,13 @@ class router:
def convert_pins(self, pin_name): 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: try:
self.pin_components[pin_name] self.pin_grids[pin_name]
except: 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 found_pin = False
for pg in self.pin_groups[pin_name]: for pg in self.pin_groups[pin_name]:
#print("PG ",pg) #print("PG ",pg)
@ -757,27 +757,37 @@ class router:
blockage_in_tracks = self.convert_blockage(pin) blockage_in_tracks = self.convert_blockage(pin)
blockage_set.update(blockage_in_tracks) 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," pins {}".format(pin_set))
debug.info(2," blocks {}".format(blockage_set)) debug.info(2," blocks {}".format(blockage_set))
# At least one of the groups must have some valid tracks # 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() 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 # 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 # Add all of the partial blocked grids to the set for the design
# if they are not blocked by other metal # if they are not blocked by other metal
partial_set = blockage_set - pin_set - self.blocked_grids #partial_set = blockage_set - pin_set
self.pin_component_blockages[pin_name].append(partial_set) #self.pin_blockages[pin_name].append(partial_set)
# We should not have added the pins to the blockages, # We should not have added the pins to the blockages,
# but remove them just in case # but remove them just in case
# Partial set may still be in the blockages if there were # Partial set may still be in the blockages if there were
# other shapes disconnected from the pins that were also overlapping # 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): def enclose_pin_grids(self, grids, seed):
@ -789,7 +799,7 @@ class router:
# We may have started with an empty set # We may have started with an empty set
if not grids: if not grids:
return return None
# Start with the seed # Start with the seed
ll = seed ll = seed
@ -800,7 +810,7 @@ class router:
while True: while True:
right = row[-1] + vector3d(1,0,0) right = row[-1] + vector3d(1,0,0)
# Can't move if not in the pin shape # 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) row.append(right)
else: else:
break break
@ -809,7 +819,7 @@ class router:
next_row = [x+vector3d(0,1,0) for x in row] next_row = [x+vector3d(0,1,0) for x in row]
for cell in next_row: for cell in next_row:
# Can't move if any cell is not in the pin shape # 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 break
else: else:
row = next_row row = next_row
@ -820,8 +830,66 @@ class router:
# Add a shape from ll to ur # Add a shape from ll to ur
ur = row[-1] 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()<smallest.area():
smallest = new_enclosure
return smallest
def enclose_pins(self): def enclose_pins(self):
""" """
@ -829,26 +897,84 @@ class router:
put a rectangle over it. It does not enclose grid squares that are blocked put a rectangle over it. It does not enclose grid squares that are blocked
by other shapes. by other shapes.
""" """
# FIXME: This could be optimized, but we just do a simple greedy biggest shape for pin_name in self.pin_grids.keys():
# for now. debug.info(1,"Enclosing pins for {}".format(pin_name))
for pin_name in self.pin_components.keys(): debug.check(len(self.pin_groups[pin_name])==len(self.pin_grids[pin_name]),"Unequal pin_group and pin_grid")
for pin_set,partial_set in zip(self.pin_components[pin_name],self.pin_component_blockages[pin_name]): for pin_group,pin_set in zip(self.pin_groups[pin_name],self.pin_grids[pin_name]):
total_pin_grids = pin_set | partial_set
# Starting with each pin, add the max enclosure
# This will result in redundant overlaps, but it is easy.
for seed in total_pin_grids:
self.enclose_pin_grids(total_pin_grids, seed)
# Compute the enclosure pin_layout list of the set of tracks
enclosure_list = self.compute_enclosures(pin_set)
for pin in enclosure_list:
debug.info(2,"Adding enclosure {0} {1}".format(pin_name, pin))
self.cell.add_rect(layer=pin.layer,
offset=pin.ll(),
width=pin.width(),
height=pin.height())
# Check if a pin shape overlaps any enclosure.
# If so, we are done.
# FIXME: Check if by more than a DRC width
if self.overlap_any_shape(pin_group, enclosure_list):
debug.info(2,"Pin overlaps enclosure {0}".format(pin_name))
else:
new_enclosure = self.find_smallest_connector(pin_group, enclosure_list)
debug.info(2,"Adding connector enclosure {0} {1}".format(pin_name, new_enclosure))
self.cell.add_rect(layer=new_enclosure.layer,
offset=new_enclosure.ll(),
width=new_enclosure.width(),
height=new_enclosure.height())
#self.write_debug_gds("pin_debug.gds", True) #self.write_debug_gds("pin_debug.gds", True)
def compute_enclosure(self, pin, enclosure):
"""
Compute an enclosure to connect the pin to the enclosure shape.
This assumes the shape will be the dimension of the pin.
"""
if pin.xoverlaps(enclosure):
# Is it vertical overlap, extend pin shape to enclosure
plc = pin.lc()
prc = pin.rc()
elc = enclosure.lc()
erc = enclosure.rc()
ymin = min(plc.y,elc.y)
ymax = max(plc.y,elc.y)
ll = vector(plc.x, ymin)
ur = vector(prc.x, ymax)
p = pin_layout(pin.name, [ll, ur], pin.layer)
elif pin.yoverlaps(enclosure):
# Is it horizontal overlap, extend pin shape to enclosure
pbc = pin.bc()
puc = pin.uc()
ebc = enclosure.bc()
euc = enclosure.uc()
xmin = min(pbc.x,ebc.x)
xmax = max(pbc.x,ebc.x)
ll = vector(xmin, pbc.y)
ur = vetor(xmax, puc.y)
p = pin_layout(pin.name, [ll, ur], pin.layer)
else:
# Neither, so we must do a corner-to corner
pc = pin.center()
ec = enclosure.center()
xmin = min(pc.x, ec.x)
xmax = max(pc.x, ec.x)
ymin = min(pc.y, ec.y)
ymax = max(pc.y, ec.y)
ll = vector(xmin, ymin)
ur = vector(xmax, ymax)
p = pin_layout(pin.name, [ll, ur], pin.layer)
return p
def add_source(self, pin_name): def add_source(self, pin_name):
""" """
This will mark the grids for all pin components as a source. This will mark the grids for all pin components as a source.
Marking as source or target also clears blockage status. Marking as source or target also clears blockage status.
""" """
for i in range(self.num_pin_components(pin_name)): for i in range(self.num_pin_grids(pin_name)):
self.add_pin_component_source(pin_name, i) self.add_pin_component_source(pin_name, i)
def add_target(self, pin_name): def add_target(self, pin_name):
@ -856,14 +982,14 @@ class router:
This will mark the grids for all pin components as a target. This will mark the grids for all pin components as a target.
Marking as source or target also clears blockage status. Marking as source or target also clears blockage status.
""" """
for i in range(self.num_pin_components(pin_name)): for i in range(self.num_pin_grids(pin_name)):
self.add_pin_component_target(pin_name, i) self.add_pin_component_target(pin_name, i)
def num_pin_components(self, pin_name): def num_pin_components(self, pin_name):
""" """
This returns how many disconnected pin components there are. This returns how many disconnected pin components there are.
""" """
return len(self.pin_components[pin_name]) return len(self.pin_grids[pin_name])
def add_pin_component_source(self, pin_name, index): def add_pin_component_source(self, pin_name, index):
""" """
@ -872,7 +998,7 @@ class router:
""" """
debug.check(index<self.num_pin_components(pin_name),"Pin component index too large.") debug.check(index<self.num_pin_components(pin_name),"Pin component index too large.")
pin_in_tracks = self.pin_components[pin_name][index] pin_in_tracks = self.pin_grids[pin_name][index]
debug.info(1,"Set source: " + str(pin_name) + " " + str(pin_in_tracks)) debug.info(1,"Set source: " + str(pin_name) + " " + str(pin_in_tracks))
self.rg.add_source(pin_in_tracks) self.rg.add_source(pin_in_tracks)
@ -889,9 +1015,9 @@ class router:
This will mark only the pin tracks from the indexed pin component as a target. This will mark only the pin tracks from the indexed pin component as a target.
It also unsets it as a blockage. It also unsets it as a blockage.
""" """
debug.check(index<self.num_pin_components(pin_name),"Pin component index too large.") debug.check(index<self.num_pin_grids(pin_name),"Pin component index too large.")
pin_in_tracks = self.pin_components[pin_name][index] pin_in_tracks = self.pin_grids[pin_name][index]
debug.info(1,"Set target: " + str(pin_name) + " " + str(pin_in_tracks)) debug.info(1,"Set target: " + str(pin_name) + " " + str(pin_in_tracks))
self.rg.add_target(pin_in_tracks) self.rg.add_target(pin_in_tracks)
@ -914,7 +1040,7 @@ class router:
""" """
Add the supply rails of given name as a routing target. Add the supply rails of given name as a routing target.
""" """
debug.info(2,"Blocking supply rail") debug.info(3,"Blocking supply rail")
for rail in self.supply_rails: for rail in self.supply_rails:
for wave_index in range(len(rail)): for wave_index in range(len(rail)):
pin_in_tracks = rail[wave_index] pin_in_tracks = rail[wave_index]
@ -926,7 +1052,7 @@ class router:
Block all of the pin components. Block all of the pin components.
""" """
debug.info(2,"Setting blockages {0} {1}".format(pin_name,value)) debug.info(2,"Setting blockages {0} {1}".format(pin_name,value))
for component in self.pin_components[pin_name]: for component in self.pin_grids[pin_name]:
self.set_blockages(component, value) self.set_blockages(component, value)
@ -1009,6 +1135,11 @@ class router:
z = ll.z z = ll.z
pin = self.add_enclosure(ll, ur, z, name) pin = self.add_enclosure(ll, ur, z, name)
self.cell.add_layout_pin(text=name,
layer=pin.layer,
offset=pin.ll(),
width=pin.width(),
height=pin.height())
return pin return pin
@ -1027,18 +1158,9 @@ class router:
(unused,abs_ur) = self.convert_track_to_pin(ur) (unused,abs_ur) = self.convert_track_to_pin(ur)
#print("enclose ll={0} ur={1}".format(ll,ur)) #print("enclose ll={0} ur={1}".format(ll,ur))
#print("enclose ll={0} ur={1}".format(abs_ll,abs_ur)) #print("enclose ll={0} ur={1}".format(abs_ll,abs_ur))
pin = pin_layout(name, [abs_ll, abs_ur], layer)
if name:
pin = self.cell.add_layout_pin(name,
layer=layer,
offset=abs_ll,
width=abs_ur.x-abs_ll.x,
height=abs_ur.y-abs_ll.y)
else:
pin = self.cell.add_rect(layer=layer,
offset=abs_ll,
width=abs_ur.x-abs_ll.x,
height=abs_ur.y-abs_ll.y)
return pin return pin
@ -1093,14 +1215,14 @@ class router:
# returns the path in tracks # returns the path in tracks
(path,cost) = self.rg.route(detour_scale) (path,cost) = self.rg.route(detour_scale)
if path: if path:
debug.info(1,"Found path: cost={0} ".format(cost)) debug.info(2,"Found path: cost={0} ".format(cost))
debug.info(2,str(path)) debug.info(3,str(path))
self.paths.append(path) self.paths.append(path)
self.add_route(path) self.add_route(path)
else: else:
self.write_debug_gds() self.write_debug_gds("failed_route.gds")
# clean up so we can try a reroute # clean up so we can try a reroute
self.reinit() self.rg.reinit()
return False return False
return True return True
@ -1131,10 +1253,6 @@ class router:
""" """
Write out a GDS file with the routing grid and search information annotated on it. Write out a GDS file with the routing grid and search information annotated on it.
""" """
# Only add the debug info to the gds file if we have any debugging on.
# This is because we may reroute a wire with detours and don't want the debug information.
if OPTS.debug_level==0: return
self.add_router_info() self.add_router_info()
self.cell.gds_write(gds_name) self.cell.gds_write(gds_name)
@ -1150,7 +1268,7 @@ class router:
""" """
debug.info(0,"Adding router info") debug.info(0,"Adding router info")
if OPTS.debug_level==0: if OPTS.debug_level>0:
# Display the inflated blockage # Display the inflated blockage
for blockage in self.blockages: for blockage in self.blockages:
debug.info(1,"Adding {}".format(blockage)) debug.info(1,"Adding {}".format(blockage))
@ -1160,7 +1278,7 @@ class router:
width=ur.x-ll.x, width=ur.x-ll.x,
height=ur.y-ll.y) height=ur.y-ll.y)
if OPTS.debug_level>1: 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() grid_keys=self.rg.map.keys()
partial_track=vector(0,self.track_width/6.0) partial_track=vector(0,self.track_width/6.0)
for g in grid_keys: for g in grid_keys:

View File

@ -42,14 +42,14 @@ class signal_grid(grid):
We will use an A* search, so this cost must be pessimistic. We will use an A* search, so this cost must be pessimistic.
Cost so far will be the length of the path. 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 # Counter is used to not require data comparison in Python 3.x
# Items will be returned in order they are added during cost ties # Items will be returned in order they are added during cost ties
self.counter = 0 self.counter = 0
for s in self.source: for s in self.source:
cost = self.cost_to_target(s) 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)]))) heappush(self.q,(cost,self.counter,grid_path([vector3d(s)])))
self.counter+=1 self.counter+=1
@ -83,12 +83,12 @@ class signal_grid(grid):
while len(self.q)>0: while len(self.q)>0:
# should we keep the path in the queue as well or just the final node? # should we keep the path in the queue as well or just the final node?
(cost,count,curpath) = heappop(self.q) (cost,count,curpath) = heappop(self.q)
debug.info(2,"Queue size: size=" + str(len(self.q)) + " " + str(cost)) debug.info(3,"Queue size: size=" + str(len(self.q)) + " " + str(cost))
debug.info(3,"Expanding: cost=" + str(cost) + " " + str(curpath)) debug.info(4,"Expanding: cost=" + str(cost) + " " + str(curpath))
# expand the last element # expand the last element
neighbors = self.expand_dirs(curpath) neighbors = self.expand_dirs(curpath)
debug.info(3,"Neighbors: " + str(neighbors)) debug.info(4,"Neighbors: " + str(neighbors))
for n in neighbors: for n in neighbors:
# make a new copy of the path to not update the old ones # 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.map[n[0]].min_cost): if (self.map[n[0]].min_cost==-1 or predicted_cost<self.map[n[0]].min_cost):
self.map[n[0]].min_path = newpath self.map[n[0]].min_path = newpath
self.map[n[0]].min_cost = predicted_cost self.map[n[0]].min_cost = predicted_cost
debug.info(3,"Enqueuing: cost=" + str(current_cost) + "+" + str(target_cost) + " " + str(newpath)) debug.info(4,"Enqueuing: cost=" + str(current_cost) + "+" + str(target_cost) + " " + str(newpath))
# add the cost to get to this point if we haven't reached it yet # add the cost to get to this point if we haven't reached it yet
heappush(self.q,(predicted_cost,self.counter,newpath)) heappush(self.q,(predicted_cost,self.counter,newpath))
self.counter += 1 self.counter += 1

View File

@ -60,69 +60,66 @@ class supply_router(router):
# Add the supply rails in a mesh network and connect H/V with vias # Add the supply rails in a mesh network and connect H/V with vias
# Block everything # Block everything
self.prepare_blockages() self.prepare_blockages(self.gnd_name)
# Clear the rail we're routing
self.set_blockages(self.pin_components[self.gnd_name],False)
# Determine the rail locations # Determine the rail locations
self.route_supply_rails(self.gnd_name,0) self.route_supply_rails(self.gnd_name,0)
# Block everything # Block everything
self.prepare_blockages() self.prepare_blockages(self.vdd_name)
# Clear the rail we're routing
self.set_blockages(self.pin_components[self.vdd_name],False)
# Determine the rail locations # Determine the rail locations
self.route_supply_rails(self.vdd_name,1) self.route_supply_rails(self.vdd_name,1)
#self.write_debug_gds("pre_pin_debug.gds",stop_program=True)
# Route the supply pins to the supply rails # Route the supply pins to the supply rails
self.route_pins_to_rails(gnd_name) self.route_pins_to_rails(gnd_name)
self.route_pins_to_rails(vdd_name) self.route_pins_to_rails(vdd_name)
#self.write_debug_gds(stop_program=False) #self.write_debug_gds("post_pin_debug.gds",stop_program=False)
return True return True
def connect_supply_rails(self, name): def connect_supply_rails(self, name):
""" """
Determine which supply rails overlap and can accomodate a via. Determine which supply rails overlap and can accomodate a via.
Remove any paths that do not have a via since they are disconnected. Remove any supply rails that do not have a via since they are disconnected.
NOTE: It is still possible though unlikely that there are disconnected groups of rails.
""" """
# Split into horizontal and vertical # Split into horizontal and vertical paths
vertical_paths = [(i,x) for i,x in enumerate(self.supply_rails) if x[0][0].z==1 and x.name==name] vertical_rails = [x for x in self.supply_rails if x[0][0].z==1 and x.name==name]
horizontal_paths = [(i,x) for i,x in enumerate(self.supply_rails) if x[0][0].z==0 and x.name==name] horizontal_rails = [x for x in self.supply_rails if x[0][0].z==0 and x.name==name]
# Flag to see if the paths have a via # Flag to see if each supply rail has at least one via (i.e. it is "connected")
via_flag = [False] * len(self.supply_rails) vertical_flags = [False] * len(vertical_rails)
# Ignore the other nets that we aren't considering horizontal_flags = [False] * len(horizontal_rails)
for i,p in enumerate(self.supply_rails):
if p.name != name:
via_flag[i]=True
# Compute a list of "shared areas" that are bigger than a via # Compute a list of "shared areas" that are bigger than a via
via_areas = [] via_areas = []
for vindex,v in vertical_paths: for vindex,v in enumerate(vertical_rails):
for hindex,h in horizontal_paths: for hindex,h in enumerate(horizontal_rails):
# Compute the overlap of the two paths, None if no overlap # Compute the overlap of the two paths, None if no overlap
overlap = v.overlap(h) overlap = v.overlap(h)
if overlap: if overlap:
(ll,ur) = overlap (ll,ur) = overlap
# We can add a via only if it is a full track width in each dimension # We can add a via only if it is a full track width in each dimension
if ur.x-ll.x >= self.rail_track_width-1 and ur.y-ll.y >= self.rail_track_width-1: if ur.x-ll.x >= self.rail_track_width-1 and ur.y-ll.y >= self.rail_track_width-1:
via_flag[vindex]=True vertical_flags[vindex]=True
via_flag[hindex]=True horizontal_flags[hindex]=True
via_areas.append(overlap) via_areas.append(overlap)
# Go through and add the vias at the center of the intersection # Go through and add the vias at the center of the intersection
for (ll,ur) in via_areas: for (ll,ur) in via_areas:
center = (ll + ur).scale(0.5,0.5,0) center = (ll + ur).scale(0.5,0.5,0)
self.add_via(center,self.rail_track_width) self.add_via(center,self.rail_track_width)
# Remove the paths that have not been connected by any via # Retrieve the original indices into supply_rails for removal
remove_indices = [i for i,x in enumerate(via_flag) if not x] remove_hrails = [rail for flag,rail in zip(horizontal_flags,horizontal_rails) if not flag]
for index in remove_indices: remove_vrails = [rail for flag,rail in zip(vertical_flags,vertical_rails) if not flag]
debug.info(1,"Removing disconnected supply rail {}".format(self.supply_rails[index])) for rail in remove_hrails + remove_vrails:
del self.supply_rails[index] debug.info(1,"Removing disconnected supply rail {}".format(rail))
self.supply_rails.remove(rail)
def add_supply_rails(self, name): def add_supply_rails(self, name):
""" """
@ -139,8 +136,8 @@ class supply_router(router):
def route_supply_rails(self, name, supply_number): def route_supply_rails(self, name, supply_number):
""" """
Route the horizontal and vertical supply rails across the entire design. 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 start_offset = supply_number*self.rail_track_width
max_yoffset = self.rg.ur.y max_yoffset = self.rg.ur.y
max_xoffset = self.rg.ur.x max_xoffset = self.rg.ur.x
@ -166,6 +163,7 @@ class supply_router(router):
# Add the supply rail vias (and prune disconnected rails) # Add the supply rail vias (and prune disconnected rails)
self.connect_supply_rails(name) self.connect_supply_rails(name)
# Add the rails themselves # Add the rails themselves
self.add_supply_rails(name) self.add_supply_rails(name)
@ -187,7 +185,17 @@ class supply_router(router):
if not wave_path: if not wave_path:
return None 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 wave_path.name = name
self.supply_rails.append(wave_path) self.supply_rails.append(wave_path)
@ -216,13 +224,7 @@ class supply_router(router):
self.rg.reinit() self.rg.reinit()
self.prepare_blockages() self.prepare_blockages(pin_name)
# 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)
# Add the single component of the pin as the source # Add the single component of the pin as the source
# which unmarks it as a blockage too # which unmarks it as a blockage too

View File

@ -82,9 +82,9 @@ class sram_base(design):
self.offset_all_coordinates() self.offset_all_coordinates()
# FIXME: Only works in positive directions # Must be done after offsetting lower-left
self.supply_route() self.route_supplies()
highest_coord = self.find_highest_coords() highest_coord = self.find_highest_coords()
self.width = highest_coord[0] self.width = highest_coord[0]
self.height = highest_coord[1] self.height = highest_coord[1]
@ -92,23 +92,8 @@ class sram_base(design):
self.DRC_LVS(final_verification=True) 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 route_supplies(self):
def supply_route(self):
""" Route the supply grid and connect the pins to them. """ """ Route the supply grid and connect the pins to them. """
for inst in self.insts: for inst in self.insts:
@ -211,31 +196,6 @@ class sram_base(design):
length=self.control_bus_width)) 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): def add_multi_bank_modules(self):
""" Create the multibank address flops and bank decoder """ """ Create the multibank address flops and bank decoder """

0
compiler/tests/04_replica_pbitcell_test.py Normal file → Executable file
View File

0
compiler/tests/06_hierarchical_decoder_test.py Normal file → Executable file
View File

0
compiler/tests/06_hierarchical_predecode2x4_test.py Normal file → Executable file
View File

0
compiler/tests/06_hierarchical_predecode3x8_test.py Normal file → Executable file
View File

0
compiler/tests/14_replica_bitline_test.py Normal file → Executable file
View File

0
compiler/tests/16_control_logic_test.py Normal file → Executable file
View File

0
compiler/tests/19_bank_select_test.py Normal file → Executable file
View File

0
compiler/tests/19_pmulti_bank_test.py Normal file → Executable file
View File

View File

@ -20,30 +20,38 @@ class sram_1bank_test(openram_test):
c = sram_config(word_size=4, c = sram_config(word_size=4,
num_words=16, num_words=16,
num_banks=1) 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 if True:
c.words_per_row=2 c.word_size=4
debug.info(1, "Single bank two way column mux with control logic") c.num_words=16
a = sram(c, "sram2") c.words_per_row=1
self.local_check(a, final_verification=True) 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 if True:
c.words_per_row=4 c.word_size=4
debug.info(1, "Single bank, four way column mux with control logic") c.num_words=32
a = sram(c, "sram3") c.words_per_row=2
self.local_check(a, final_verification=True) 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 if True:
c.num_words=128 c.word_size=4
c.words_per_row=8 c.num_words=64
debug.info(1, "Single bank, eight way column mux with control logic") c.words_per_row=4
a = sram(c, "sram4") debug.info(1, "Single bank, four way column mux with control logic")
self.local_check(a, final_verification=True) 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() globals.end_openram()

0
compiler/tests/22_hspice_psram_func_test.py Normal file → Executable file
View File

0
compiler/tests/22_hspice_sram_func_test.py Normal file → Executable file
View File

0
compiler/tests/22_ngspice_psram_func_test.py Normal file → Executable file
View File

0
compiler/tests/22_ngspice_sram_func_test.py Normal file → Executable file
View File

0
compiler/tests/config_20_freepdk45.py Normal file → Executable file
View File

0
compiler/tests/config_20_scn3me_subm.py Normal file → Executable file
View File

0
compiler/tests/config_20_scn4m_subm.py Normal file → Executable file
View File

Binary file not shown.

View File

@ -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

View File

@ -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

View File

@ -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");
}
}
}
}
}

0
compiler/tests/testutils.py Normal file → Executable file
View File