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,7 +22,11 @@ class _cell:
|
|||
self._port_map = {x: x for x in port_order}
|
||||
|
||||
# Update mapping of names
|
||||
self._original_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
|
||||
self._port_names = [self._port_map[x] for x in self._port_order]
|
||||
|
|
@ -49,7 +53,13 @@ class _cell:
|
|||
self._port_names = [self._port_map[x] for x in self._port_order]
|
||||
# Update ordered type list in the new 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
|
||||
def port_map(self):
|
||||
return self._port_map
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ class design(hierarchy_design):
|
|||
# that they matched here
|
||||
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))
|
||||
self.add_pin_indices(prop.port_indices)
|
||||
self.add_pin_names(prop.port_map)
|
||||
self.add_pin_types(prop.port_types)
|
||||
|
||||
|
|
|
|||
|
|
@ -62,14 +62,7 @@ class layout():
|
|||
self.pwr_grid_layer = power_grid[0]
|
||||
except ImportError:
|
||||
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
|
||||
############################################################
|
||||
|
|
@ -325,11 +318,8 @@ class layout():
|
|||
"""
|
||||
Return the pin or list of pins
|
||||
"""
|
||||
if text in self.pin_names:
|
||||
name = self.pin_names[text]
|
||||
else:
|
||||
name = text
|
||||
|
||||
name = self.get_pin_name(text)
|
||||
|
||||
try:
|
||||
if len(self.pin_map[name]) > 1:
|
||||
debug.error("Should use a pin iterator since more than one pin {}".format(text), -1)
|
||||
|
|
@ -345,16 +335,42 @@ class layout():
|
|||
"""
|
||||
Return a pin list (instead of a single pin)
|
||||
"""
|
||||
if text in self.pin_names:
|
||||
name = self.pin_names[text]
|
||||
else:
|
||||
name = text
|
||||
name = self.get_pin_name(text)
|
||||
|
||||
if name in self.pin_map.keys():
|
||||
return self.pin_map[name]
|
||||
else:
|
||||
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):
|
||||
"""
|
||||
Return a pin list of all pins
|
||||
|
|
|
|||
|
|
@ -35,11 +35,13 @@ class spice():
|
|||
self.valid_signal_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"]
|
||||
# Holds subckts/mods for this module
|
||||
self.mods = []
|
||||
# Holds the pins for this module
|
||||
# Holds the pins for this module (in order)
|
||||
self.pins = []
|
||||
# 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
|
||||
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
|
||||
# Spice format)
|
||||
self.conns = []
|
||||
|
|
@ -95,10 +97,25 @@ class spice():
|
|||
else:
|
||||
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):
|
||||
"""
|
||||
Add pin types for all the cell's pins.
|
||||
Typically, should only be used for handmade cells.
|
||||
"""
|
||||
# This only works if self.pins == bitcell.pin_names
|
||||
if len(type_list) != len(self.pins):
|
||||
|
|
@ -107,7 +124,7 @@ class spice():
|
|||
\n Module names={}\
|
||||
".format(self.name, self.pins, type_list), 1)
|
||||
self.pin_type = {pin: type for pin, type in zip(self.pins, type_list)}
|
||||
|
||||
|
||||
def get_pin_type(self, name):
|
||||
""" Returns the type of the signal pin. """
|
||||
pin_type = self.pin_type[name]
|
||||
|
|
@ -159,19 +176,26 @@ class spice():
|
|||
self.mods.append(mod)
|
||||
|
||||
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
|
||||
there is a problem. The check option can be set to false
|
||||
where we dynamically generate groups of connections after a
|
||||
group of modules are generated."""
|
||||
group of modules are generated.
|
||||
"""
|
||||
|
||||
num_pins = len(self.insts[-1].mod.pins)
|
||||
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 num_pins < num_args:
|
||||
mod_pins = self.insts[-1].mod.pins + [""] * (num_args - num_pins)
|
||||
arg_pins = args
|
||||
arg_pins = ordered_args
|
||||
else:
|
||||
arg_pins = args + [""] * (num_pins - num_args)
|
||||
arg_pins = ordered_args + [""] * (num_pins - num_args)
|
||||
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)])
|
||||
|
|
@ -180,8 +204,9 @@ class spice():
|
|||
modpins_string),
|
||||
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)):
|
||||
insts_string=pformat(self.insts)
|
||||
conns_string=pformat(self.conns)
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import debug
|
||||
import math
|
||||
|
||||
|
||||
class verilog:
|
||||
"""
|
||||
Create a behavioral Verilog file for simulation.
|
||||
|
|
@ -16,7 +16,7 @@ class verilog:
|
|||
def __init__(self):
|
||||
pass
|
||||
|
||||
def verilog_write(self,verilog_name):
|
||||
def verilog_write(self, verilog_name):
|
||||
""" Write a behavioral Verilog model. """
|
||||
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(" 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):
|
||||
""" Output a warning if the two 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
|
||||
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)
|
||||
|
||||
self.write_data(mode=mode,
|
||||
|
|
|
|||
Loading…
Reference in New Issue