mirror of https://github.com/VLSIDA/OpenRAM.git
Add custom cell custom port order code. Update setup/hold to use it.
This commit is contained in:
parent
80333ffacb
commit
baae28194b
|
|
@ -22,8 +22,12 @@ class _cell:
|
||||||
self._port_map = {x: x for x in port_order}
|
self._port_map = {x: x for x in port_order}
|
||||||
|
|
||||||
# Update mapping of names
|
# Update mapping of names
|
||||||
|
self._original_port_order = port_order
|
||||||
self._port_order = port_order
|
self._port_order = port_order
|
||||||
|
|
||||||
|
# Create an index array
|
||||||
|
self._port_indices = [self._port_order.index(x) for x in self._original_port_order]
|
||||||
|
|
||||||
# Update ordered name list
|
# Update ordered name list
|
||||||
self._port_names = [self._port_map[x] for x in self._port_order]
|
self._port_names = [self._port_map[x] for x in self._port_order]
|
||||||
|
|
||||||
|
|
@ -49,6 +53,12 @@ class _cell:
|
||||||
self._port_names = [self._port_map[x] for x in self._port_order]
|
self._port_names = [self._port_map[x] for x in self._port_order]
|
||||||
# Update ordered type list in the new order
|
# Update ordered type list in the new order
|
||||||
self._port_types = [self._port_types_map[x] for x in self._port_order]
|
self._port_types = [self._port_types_map[x] for x in self._port_order]
|
||||||
|
# Update the index array
|
||||||
|
self._port_indices = [self._port_order.index(x) for x in self._original_port_order]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port_indices(self):
|
||||||
|
return self._port_indices
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def port_map(self):
|
def port_map(self):
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ class design(hierarchy_design):
|
||||||
# that they matched here
|
# that they matched here
|
||||||
debug.check(prop.port_names == self.pins,
|
debug.check(prop.port_names == self.pins,
|
||||||
"Custom cell pin names do not match spice file:\n{0} vs {1}".format(prop.port_names, self.pins))
|
"Custom cell pin names do not match spice file:\n{0} vs {1}".format(prop.port_names, self.pins))
|
||||||
|
self.add_pin_indices(prop.port_indices)
|
||||||
self.add_pin_names(prop.port_map)
|
self.add_pin_names(prop.port_map)
|
||||||
self.add_pin_types(prop.port_types)
|
self.add_pin_types(prop.port_types)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,13 +63,6 @@ class layout():
|
||||||
except ImportError:
|
except ImportError:
|
||||||
self.pwr_grid_layer = "m3"
|
self.pwr_grid_layer = "m3"
|
||||||
|
|
||||||
def add_pin_names(self, pin_dict):
|
|
||||||
"""
|
|
||||||
Create a mapping from internal pin names to external pin names.
|
|
||||||
"""
|
|
||||||
self.pin_names = pin_dict
|
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# GDS layout
|
# GDS layout
|
||||||
############################################################
|
############################################################
|
||||||
|
|
@ -325,10 +318,7 @@ class layout():
|
||||||
"""
|
"""
|
||||||
Return the pin or list of pins
|
Return the pin or list of pins
|
||||||
"""
|
"""
|
||||||
if text in self.pin_names:
|
name = self.get_pin_name(text)
|
||||||
name = self.pin_names[text]
|
|
||||||
else:
|
|
||||||
name = text
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if len(self.pin_map[name]) > 1:
|
if len(self.pin_map[name]) > 1:
|
||||||
|
|
@ -345,16 +335,42 @@ class layout():
|
||||||
"""
|
"""
|
||||||
Return a pin list (instead of a single pin)
|
Return a pin list (instead of a single pin)
|
||||||
"""
|
"""
|
||||||
if text in self.pin_names:
|
name = self.get_pin_name(text)
|
||||||
name = self.pin_names[text]
|
|
||||||
else:
|
|
||||||
name = text
|
|
||||||
|
|
||||||
if name in self.pin_map.keys():
|
if name in self.pin_map.keys():
|
||||||
return self.pin_map[name]
|
return self.pin_map[name]
|
||||||
else:
|
else:
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
|
def add_pin_names(self, pin_dict):
|
||||||
|
"""
|
||||||
|
Create a mapping from internal pin names to external pin names.
|
||||||
|
"""
|
||||||
|
self.pin_names = pin_dict
|
||||||
|
|
||||||
|
self.original_pin_names = {y: x for (x, y) in self.pin_names.items()}
|
||||||
|
|
||||||
|
def get_pin_name(self, text):
|
||||||
|
""" Return the custom cell pin name """
|
||||||
|
|
||||||
|
if text in self.pin_names:
|
||||||
|
return self.pin_names[text]
|
||||||
|
else:
|
||||||
|
return text
|
||||||
|
|
||||||
|
def get_original_pin_names(self):
|
||||||
|
""" Return the internal cell pin name """
|
||||||
|
|
||||||
|
# This uses the hierarchy_spice pins (in order)
|
||||||
|
return [self.get_original_pin_name(x) for x in self.pins]
|
||||||
|
|
||||||
|
def get_original_pin_name(self, text):
|
||||||
|
""" Return the internal cell pin names in custom port order """
|
||||||
|
if text in self.original_pin_names:
|
||||||
|
return self.original_pin_names[text]
|
||||||
|
else:
|
||||||
|
return text
|
||||||
|
|
||||||
def get_pin_names(self):
|
def get_pin_names(self):
|
||||||
"""
|
"""
|
||||||
Return a pin list of all pins
|
Return a pin list of all pins
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,13 @@ class spice():
|
||||||
self.valid_signal_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"]
|
self.valid_signal_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"]
|
||||||
# Holds subckts/mods for this module
|
# Holds subckts/mods for this module
|
||||||
self.mods = []
|
self.mods = []
|
||||||
# Holds the pins for this module
|
# Holds the pins for this module (in order)
|
||||||
self.pins = []
|
self.pins = []
|
||||||
# The type map of each pin: INPUT, OUTPUT, INOUT, POWER, GROUND
|
# The type map of each pin: INPUT, OUTPUT, INOUT, POWER, GROUND
|
||||||
# for each instance, this is the set of nets/nodes that map to the pins for this instance
|
# for each instance, this is the set of nets/nodes that map to the pins for this instance
|
||||||
self.pin_type = {}
|
self.pin_type = {}
|
||||||
|
# An (optional) list of indices to reorder the pins to match the spice.
|
||||||
|
self.pin_indices = []
|
||||||
# THE CONNECTIONS MUST MATCH THE ORDER OF THE PINS (restriction imposed by the
|
# THE CONNECTIONS MUST MATCH THE ORDER OF THE PINS (restriction imposed by the
|
||||||
# Spice format)
|
# Spice format)
|
||||||
self.conns = []
|
self.conns = []
|
||||||
|
|
@ -95,10 +97,25 @@ class spice():
|
||||||
else:
|
else:
|
||||||
debug.error("Mismatch in type and pin list lengths.", -1)
|
debug.error("Mismatch in type and pin list lengths.", -1)
|
||||||
|
|
||||||
|
def add_pin_indices(self, index_list):
|
||||||
|
"""
|
||||||
|
Add pin indices for all the cell's pins.
|
||||||
|
"""
|
||||||
|
self.pin_indices = index_list
|
||||||
|
|
||||||
|
def get_ordered_inputs(self, input_list):
|
||||||
|
"""
|
||||||
|
Return the inputs reordered to match the pins.
|
||||||
|
"""
|
||||||
|
if not self.pin_indices:
|
||||||
|
return input_list
|
||||||
|
|
||||||
|
new_list = [input_list[x] for x in self.pin_indices]
|
||||||
|
return new_list
|
||||||
|
|
||||||
def add_pin_types(self, type_list):
|
def add_pin_types(self, type_list):
|
||||||
"""
|
"""
|
||||||
Add pin types for all the cell's pins.
|
Add pin types for all the cell's pins.
|
||||||
Typically, should only be used for handmade cells.
|
|
||||||
"""
|
"""
|
||||||
# This only works if self.pins == bitcell.pin_names
|
# This only works if self.pins == bitcell.pin_names
|
||||||
if len(type_list) != len(self.pins):
|
if len(type_list) != len(self.pins):
|
||||||
|
|
@ -159,19 +176,26 @@ class spice():
|
||||||
self.mods.append(mod)
|
self.mods.append(mod)
|
||||||
|
|
||||||
def connect_inst(self, args, check=True):
|
def connect_inst(self, args, check=True):
|
||||||
"""Connects the pins of the last instance added
|
"""
|
||||||
|
Connects the pins of the last instance added
|
||||||
It is preferred to use the function with the check to find if
|
It is preferred to use the function with the check to find if
|
||||||
there is a problem. The check option can be set to false
|
there is a problem. The check option can be set to false
|
||||||
where we dynamically generate groups of connections after a
|
where we dynamically generate groups of connections after a
|
||||||
group of modules are generated."""
|
group of modules are generated.
|
||||||
|
"""
|
||||||
|
|
||||||
num_pins = len(self.insts[-1].mod.pins)
|
num_pins = len(self.insts[-1].mod.pins)
|
||||||
num_args = len(args)
|
num_args = len(args)
|
||||||
|
|
||||||
|
# Order the arguments if the hard cell has a custom port order
|
||||||
|
ordered_args = self.get_ordered_inputs(args)
|
||||||
|
|
||||||
if (check and num_pins != num_args):
|
if (check and num_pins != num_args):
|
||||||
if num_pins < num_args:
|
if num_pins < num_args:
|
||||||
mod_pins = self.insts[-1].mod.pins + [""] * (num_args - num_pins)
|
mod_pins = self.insts[-1].mod.pins + [""] * (num_args - num_pins)
|
||||||
arg_pins = args
|
arg_pins = ordered_args
|
||||||
else:
|
else:
|
||||||
arg_pins = args + [""] * (num_pins - num_args)
|
arg_pins = ordered_args + [""] * (num_pins - num_args)
|
||||||
mod_pins = self.insts[-1].mod.pins
|
mod_pins = self.insts[-1].mod.pins
|
||||||
|
|
||||||
modpins_string = "\n".join(["{0} -> {1}".format(arg, mod) for (arg, mod) in zip(arg_pins, mod_pins)])
|
modpins_string = "\n".join(["{0} -> {1}".format(arg, mod) for (arg, mod) in zip(arg_pins, mod_pins)])
|
||||||
|
|
@ -180,8 +204,9 @@ class spice():
|
||||||
modpins_string),
|
modpins_string),
|
||||||
1)
|
1)
|
||||||
|
|
||||||
self.conns.append(args)
|
self.conns.append(ordered_args)
|
||||||
|
|
||||||
|
# This checks if we don't have enough instance port connections for the number of insts
|
||||||
if check and (len(self.insts)!=len(self.conns)):
|
if check and (len(self.insts)!=len(self.conns)):
|
||||||
insts_string=pformat(self.insts)
|
insts_string=pformat(self.insts)
|
||||||
conns_string=pformat(self.conns)
|
conns_string=pformat(self.conns)
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
import debug
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
|
||||||
class verilog:
|
class verilog:
|
||||||
"""
|
"""
|
||||||
Create a behavioral Verilog file for simulation.
|
Create a behavioral Verilog file for simulation.
|
||||||
|
|
@ -16,7 +16,7 @@ class verilog:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def verilog_write(self,verilog_name):
|
def verilog_write(self, verilog_name):
|
||||||
""" Write a behavioral Verilog model. """
|
""" Write a behavioral Verilog model. """
|
||||||
self.vf = open(verilog_name, "w")
|
self.vf = open(verilog_name, "w")
|
||||||
|
|
||||||
|
|
@ -220,6 +220,9 @@ class verilog:
|
||||||
self.vf.write(" dout{0} <= #(DELAY) mem[addr{0}_reg];\n".format(port))
|
self.vf.write(" dout{0} <= #(DELAY) mem[addr{0}_reg];\n".format(port))
|
||||||
self.vf.write(" end\n")
|
self.vf.write(" end\n")
|
||||||
|
|
||||||
|
self.vf.write(" always @(csb{0})\n".format(port))
|
||||||
|
self.vf.write(" dout{0} = 0)\n".format(port))
|
||||||
|
|
||||||
def add_address_check(self, wport, rport):
|
def add_address_check(self, wport, rport):
|
||||||
""" Output a warning if the two addresses match """
|
""" Output a warning if the two addresses match """
|
||||||
# If the rport is actually reading... and addresses match.
|
# If the rport is actually reading... and addresses match.
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ class setup_hold():
|
||||||
|
|
||||||
# instantiate the master-slave d-flip-flop
|
# instantiate the master-slave d-flip-flop
|
||||||
self.sf.write("\n* Instantiation of the Master-Slave D-flip-flop\n")
|
self.sf.write("\n* Instantiation of the Master-Slave D-flip-flop\n")
|
||||||
self.stim.inst_model(pins=self.dff.get_ordered_inputs(self.dff.pins),
|
self.stim.inst_model(pins=self.dff.get_original_pin_names(),
|
||||||
model_name=self.dff.cell_name)
|
model_name=self.dff.cell_name)
|
||||||
|
|
||||||
self.write_data(mode=mode,
|
self.write_data(mode=mode,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue