mirror of https://github.com/VLSIDA/OpenRAM.git
implement pin_spice object
This commit is contained in:
parent
4e649aad6b
commit
146efc5070
|
|
@ -45,7 +45,7 @@ class design(hierarchy_design):
|
|||
"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)
|
||||
self.update_pin_types(prop.port_types)
|
||||
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ from .delay_data import delay_data
|
|||
from .wire_spice_model import wire_spice_model
|
||||
from .power_data import power_data
|
||||
from .logical_effort import convert_relative_c_to_farad, convert_farad_to_relative_c
|
||||
from .pin_spice import pin_spice
|
||||
|
||||
|
||||
class spice():
|
||||
|
|
@ -49,14 +50,10 @@ class spice():
|
|||
if not os.path.exists(self.lvs_file):
|
||||
self.lvs_file = self.sp_file
|
||||
|
||||
self.valid_signal_types = ["INOUT", "INPUT", "OUTPUT", "BIAS", "POWER", "GROUND"]
|
||||
# Holds subckts/mods for this module
|
||||
self.mods = set()
|
||||
# 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
|
||||
|
|
@ -90,106 +87,97 @@ class spice():
|
|||
|
||||
def add_pin(self, name, pin_type="INOUT"):
|
||||
""" Adds a pin to the pins list. Default type is INOUT signal. """
|
||||
self.pins.append(name)
|
||||
self.pin_type[name]=pin_type
|
||||
debug.check(pin_type in self.valid_signal_types,
|
||||
"Invalid signaltype for {0}: {1}".format(name,
|
||||
pin_type))
|
||||
new_pin = pin_spice(name, pin_type)
|
||||
debug.check(new_pin not in self.pins, "cannot add duplicate spice pin")
|
||||
self.pins.append(new_pin)
|
||||
|
||||
def add_pin_list(self, pin_list, pin_type="INOUT"):
|
||||
""" Adds a pin_list to the pins list """
|
||||
# The type list can be a single type for all pins
|
||||
# The pin type list can be a single type for all pins
|
||||
# or a list that is the same length as the pin list.
|
||||
if type(pin_type)==str:
|
||||
if type(pin_type) == str:
|
||||
for pin in pin_list:
|
||||
debug.check(pin_type in self.valid_signal_types,
|
||||
"Invalid signaltype for {0}: {1}".format(pin,
|
||||
pin_type))
|
||||
self.add_pin(pin, pin_type)
|
||||
|
||||
elif len(pin_type)==len(pin_list):
|
||||
for (pin, ptype) in zip(pin_list, pin_type):
|
||||
debug.check(ptype in self.valid_signal_types,
|
||||
"Invalid signaltype for {0}: {1}".format(pin,
|
||||
ptype))
|
||||
self.add_pin(pin, ptype)
|
||||
for (pin, type) in zip(pin_list, pin_type):
|
||||
self.add_pin(pin, type)
|
||||
else:
|
||||
debug.error("Mismatch in type and pin list lengths.", -1)
|
||||
debug.error("Pin type must be a string or list of strings the same length as pin_list", -1)
|
||||
|
||||
def add_pin_indices(self, index_list):
|
||||
"""
|
||||
Add pin indices for all the cell's pins.
|
||||
"""
|
||||
""" 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.
|
||||
"""
|
||||
""" 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.
|
||||
"""
|
||||
# This only works if self.pins == bitcell.pin_names
|
||||
def update_pin_types(self, type_list):
|
||||
""" Change pin types for all the cell's pins. """
|
||||
if len(type_list) != len(self.pins):
|
||||
debug.error("{} spice subcircuit number of port types does not match number of pins\
|
||||
\n SPICE names={}\
|
||||
\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)}
|
||||
for pin, type in zip(self.pins, type_list):
|
||||
pin.set_pin_type(type)
|
||||
|
||||
def get_pin_type(self, name):
|
||||
""" Returns the type of the signal pin. """
|
||||
pin_type = self.pin_type[name]
|
||||
debug.check(pin_type in self.valid_signal_types,
|
||||
"Invalid signaltype for {0}: {1}".format(name, pin_type))
|
||||
return pin_type
|
||||
for pin in self.pins:
|
||||
if pin.name == name:
|
||||
return pin.type
|
||||
debug.error("Spice pin {} not found".format(name))
|
||||
|
||||
def get_pin_dir(self, name):
|
||||
""" Returns the direction of the pin. (Supply/ground are INOUT). """
|
||||
if self.pin_type[name] in ["POWER", "GROUND"]:
|
||||
pin_type = self.get_pin_type(name)
|
||||
if pin_type in ["POWER", "GROUND"]:
|
||||
return "INOUT"
|
||||
else:
|
||||
return self.pin_type[name]
|
||||
return pin_type
|
||||
|
||||
def get_inputs(self):
|
||||
""" These use pin types to determine pin lists. These
|
||||
may be over-ridden by submodules that didn't use pin directions yet."""
|
||||
"""
|
||||
These use pin types to determine pin lists.
|
||||
Returns names only to maintain historical interface.
|
||||
"""
|
||||
input_list = []
|
||||
for pin in self.pins:
|
||||
if self.pin_type[pin]=="INPUT":
|
||||
input_list.append(pin)
|
||||
if pin.type == "INPUT":
|
||||
input_list.append(pin.name)
|
||||
return input_list
|
||||
|
||||
def get_outputs(self):
|
||||
""" These use pin types to determine pin lists. These
|
||||
may be over-ridden by submodules that didn't use pin directions yet."""
|
||||
"""
|
||||
These use pin types to determine pin lists.
|
||||
Returns names only to maintain historical interface.
|
||||
"""
|
||||
output_list = []
|
||||
for pin in self.pins:
|
||||
if self.pin_type[pin]=="OUTPUT":
|
||||
output_list.append(pin)
|
||||
if pin.type == "OUTPUT":
|
||||
output_list.append(pin.name)
|
||||
return output_list
|
||||
|
||||
def copy_pins(self, other_module, suffix=""):
|
||||
""" This will copy all of the pins from the other module and add an optional suffix."""
|
||||
for pin in other_module.pins:
|
||||
self.add_pin(pin + suffix, other_module.get_pin_type(pin))
|
||||
|
||||
def get_inouts(self):
|
||||
""" These use pin types to determine pin lists. These
|
||||
may be over-ridden by submodules that didn't use pin directions yet."""
|
||||
inout_list = []
|
||||
for pin in self.pins:
|
||||
if self.pin_type[pin]=="INOUT":
|
||||
inout_list.append(pin)
|
||||
if pin.type == "INOUT":
|
||||
inout_list.append(pin.name)
|
||||
return inout_list
|
||||
|
||||
def copy_pins(self, other_module, suffix=""):
|
||||
""" This will copy all of the pins from the other module and add an optional suffix."""
|
||||
for pin in other_module.pins:
|
||||
self.add_pin(pin.name + suffix, pin.type)
|
||||
|
||||
def connect_inst(self, args, check=True):
|
||||
"""
|
||||
Connects the pins of the last instance added
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class lef:
|
|||
"""
|
||||
SRAM LEF Class open GDS file, read pins information, obstruction
|
||||
and write them to LEF file.
|
||||
This is inherited by the sram_base class.
|
||||
This is inherited by the sram_1bank class.
|
||||
"""
|
||||
def __init__(self, layers):
|
||||
# LEF db units per micron
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
from openram import debug
|
||||
|
||||
|
||||
class pin_spice:
|
||||
"""
|
||||
A class to represent a spice netlist pin.
|
||||
"""
|
||||
|
||||
valid_pin_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"]
|
||||
|
||||
def __init__(self, name, type):
|
||||
self.name = name
|
||||
self.set_type(type)
|
||||
|
||||
self._hash = hash(self.name)
|
||||
|
||||
def set_type(self, type):
|
||||
debug.check(type in pin_spice.valid_pin_types,
|
||||
"Invalid pin type for {0}: {1}".format(self.name, type))
|
||||
self.type = type
|
||||
|
||||
def __str__(self):
|
||||
""" override print function output """
|
||||
return "(pin_name={} type={})".format(self.name, self.type)
|
||||
|
||||
def __repr__(self):
|
||||
""" override repr function output """
|
||||
return self.name
|
||||
|
||||
def __hash__(self):
|
||||
"""
|
||||
Implement the hash function for sets etc.
|
||||
Only hash name since spice does not allow two pins to share a name.
|
||||
Provides a speedup if pin_spice is used as a key for dicts.
|
||||
"""
|
||||
return self._hash
|
||||
Loading…
Reference in New Issue