mirror of https://github.com/VLSIDA/OpenRAM.git
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:
parent
a2b1d025ab
commit
6bbf66d55b
|
|
@ -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."""
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()<smallest.area():
|
||||
smallest = new_enclosure
|
||||
|
||||
return smallest
|
||||
|
||||
def enclose_pins(self):
|
||||
"""
|
||||
|
|
@ -829,26 +897,84 @@ class router:
|
|||
put a rectangle over it. It does not enclose grid squares that are blocked
|
||||
by other shapes.
|
||||
"""
|
||||
# FIXME: This could be optimized, but we just do a simple greedy biggest shape
|
||||
# for now.
|
||||
for pin_name in self.pin_components.keys():
|
||||
for pin_set,partial_set in zip(self.pin_components[pin_name],self.pin_component_blockages[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)
|
||||
for pin_name in self.pin_grids.keys():
|
||||
debug.info(1,"Enclosing pins for {}".format(pin_name))
|
||||
debug.check(len(self.pin_groups[pin_name])==len(self.pin_grids[pin_name]),"Unequal pin_group and pin_grid")
|
||||
for pin_group,pin_set in zip(self.pin_groups[pin_name],self.pin_grids[pin_name]):
|
||||
|
||||
# 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)
|
||||
|
||||
|
||||
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):
|
||||
"""
|
||||
This will mark the grids for all pin components as a source.
|
||||
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)
|
||||
|
||||
def add_target(self, pin_name):
|
||||
|
|
@ -856,14 +982,14 @@ class router:
|
|||
This will mark the grids for all pin components as a target.
|
||||
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)
|
||||
|
||||
def num_pin_components(self, pin_name):
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
|
|
@ -872,7 +998,7 @@ class router:
|
|||
"""
|
||||
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))
|
||||
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.
|
||||
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))
|
||||
self.rg.add_target(pin_in_tracks)
|
||||
|
||||
|
|
@ -914,7 +1040,7 @@ class router:
|
|||
"""
|
||||
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 wave_index in range(len(rail)):
|
||||
pin_in_tracks = rail[wave_index]
|
||||
|
|
@ -926,7 +1052,7 @@ class router:
|
|||
Block all of the pin components.
|
||||
"""
|
||||
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)
|
||||
|
||||
|
||||
|
|
@ -1009,6 +1135,11 @@ class router:
|
|||
z = ll.z
|
||||
|
||||
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
|
||||
|
||||
|
|
@ -1027,18 +1158,9 @@ class router:
|
|||
(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(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
|
||||
|
||||
|
||||
|
|
@ -1093,14 +1215,14 @@ class router:
|
|||
# returns the path in tracks
|
||||
(path,cost) = self.rg.route(detour_scale)
|
||||
if path:
|
||||
debug.info(1,"Found path: cost={0} ".format(cost))
|
||||
debug.info(2,str(path))
|
||||
debug.info(2,"Found path: cost={0} ".format(cost))
|
||||
debug.info(3,str(path))
|
||||
self.paths.append(path)
|
||||
self.add_route(path)
|
||||
else:
|
||||
self.write_debug_gds()
|
||||
self.write_debug_gds("failed_route.gds")
|
||||
# clean up so we can try a reroute
|
||||
self.reinit()
|
||||
self.rg.reinit()
|
||||
return False
|
||||
return True
|
||||
|
||||
|
|
@ -1131,10 +1253,6 @@ class router:
|
|||
"""
|
||||
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.cell.gds_write(gds_name)
|
||||
|
||||
|
|
@ -1150,7 +1268,7 @@ class router:
|
|||
"""
|
||||
debug.info(0,"Adding router info")
|
||||
|
||||
if OPTS.debug_level==0:
|
||||
if OPTS.debug_level>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:
|
||||
|
|
|
|||
|
|
@ -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.map[n[0]].min_cost):
|
||||
self.map[n[0]].min_path = newpath
|
||||
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
|
||||
heappush(self.q,(predicted_cost,self.counter,newpath))
|
||||
self.counter += 1
|
||||
|
|
|
|||
|
|
@ -60,69 +60,66 @@ class supply_router(router):
|
|||
|
||||
# Add the supply rails in a mesh network and connect H/V with vias
|
||||
# Block everything
|
||||
self.prepare_blockages()
|
||||
# Clear the rail we're routing
|
||||
self.set_blockages(self.pin_components[self.gnd_name],False)
|
||||
self.prepare_blockages(self.gnd_name)
|
||||
# Determine the rail locations
|
||||
self.route_supply_rails(self.gnd_name,0)
|
||||
|
||||
# Block everything
|
||||
self.prepare_blockages()
|
||||
# Clear the rail we're routing
|
||||
self.set_blockages(self.pin_components[self.vdd_name],False)
|
||||
self.prepare_blockages(self.vdd_name)
|
||||
# Determine the rail locations
|
||||
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
|
||||
self.route_pins_to_rails(gnd_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
|
||||
|
||||
|
||||
def connect_supply_rails(self, name):
|
||||
"""
|
||||
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
|
||||
vertical_paths = [(i,x) for i,x in enumerate(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]
|
||||
# Split into horizontal and vertical paths
|
||||
vertical_rails = [x for x in self.supply_rails if x[0][0].z==1 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
|
||||
via_flag = [False] * len(self.supply_rails)
|
||||
# Ignore the other nets that we aren't considering
|
||||
for i,p in enumerate(self.supply_rails):
|
||||
if p.name != name:
|
||||
via_flag[i]=True
|
||||
# Flag to see if each supply rail has at least one via (i.e. it is "connected")
|
||||
vertical_flags = [False] * len(vertical_rails)
|
||||
horizontal_flags = [False] * len(horizontal_rails)
|
||||
|
||||
# Compute a list of "shared areas" that are bigger than a via
|
||||
via_areas = []
|
||||
for vindex,v in vertical_paths:
|
||||
for hindex,h in horizontal_paths:
|
||||
for vindex,v in enumerate(vertical_rails):
|
||||
for hindex,h in enumerate(horizontal_rails):
|
||||
# Compute the overlap of the two paths, None if no overlap
|
||||
overlap = v.overlap(h)
|
||||
if overlap:
|
||||
(ll,ur) = overlap
|
||||
# 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:
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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 """
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue