mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-08-30 09:58:33 +02:00
merging changes in bitcell.py
This commit is contained in:
@@ -120,3 +120,10 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
|
||||
for i in self.insts:
|
||||
text+=str(i)+",\n"
|
||||
return text
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
""" Get total power of a module """
|
||||
total_module_power = self.return_power()
|
||||
for inst in self.insts:
|
||||
total_module_power += inst.mod.analytical_power(proc, vdd, temp, load)
|
||||
return total_module_power
|
||||
|
||||
@@ -121,7 +121,8 @@ class layout(lef.lef):
|
||||
def add_inst(self, name, mod, offset=[0,0], mirror="R0",rotate=0):
|
||||
"""Adds an instance of a mod to this module"""
|
||||
self.insts.append(geometry.instance(name, mod, offset, mirror, rotate))
|
||||
debug.info(4, "adding instance" + ",".join(x.name for x in self.insts))
|
||||
debug.info(3, "adding instance {}".format(self.insts[-1]))
|
||||
debug.info(4, "instance list: " + ",".join(x.name for x in self.insts))
|
||||
return self.insts[-1]
|
||||
|
||||
def get_inst(self, name):
|
||||
@@ -453,6 +454,7 @@ class layout(lef.lef):
|
||||
|
||||
def gds_write_file(self, newLayout):
|
||||
"""Recursive GDS write function"""
|
||||
# Visited means that we already prepared self.gds for this subtree
|
||||
if self.visited:
|
||||
return
|
||||
for i in self.insts:
|
||||
@@ -468,10 +470,11 @@ class layout(lef.lef):
|
||||
"""Write the entire gds of the object to the file."""
|
||||
debug.info(3, "Writing to {0}".format(gds_name))
|
||||
|
||||
#self.gds = gdsMill.VlsiLayout(name=self.name,units=GDS["unit"])
|
||||
writer = gdsMill.Gds2writer(self.gds)
|
||||
# clear the visited flag for the traversal
|
||||
self.clear_visited()
|
||||
# MRG: 3/2/18 We don't want to clear the visited flag since
|
||||
# this would result in duplicates of all instances being placed in self.gds
|
||||
# which may have been previously processed!
|
||||
#self.clear_visited()
|
||||
# recursively create all the remaining objects
|
||||
self.gds_write_file(self.gds)
|
||||
# populates the xyTree data structure for gds
|
||||
|
||||
@@ -97,8 +97,8 @@ class spice(verilog.verilog):
|
||||
for i in range(len(self.spice)):
|
||||
self.spice[i] = self.spice[i].rstrip(" \n")
|
||||
|
||||
# find first subckt line in the file
|
||||
subckt = re.compile("^.subckt", re.IGNORECASE)
|
||||
# find the correct subckt line in the file
|
||||
subckt = re.compile("^.subckt {}".format(self.name), re.IGNORECASE)
|
||||
subckt_line = filter(subckt.search, self.spice)[0]
|
||||
# parses line into ports and remove subckt
|
||||
self.pins = subckt_line.split(" ")[2:]
|
||||
@@ -214,6 +214,9 @@ class spice(verilog.verilog):
|
||||
|
||||
def generate_rc_net(self,lump_num, wire_length, wire_width):
|
||||
return wire_spice_model(lump_num, wire_length, wire_width)
|
||||
|
||||
def return_power(self, dynamic=0.0, leakage=0.0):
|
||||
return power_data(dynamic, leakage)
|
||||
|
||||
class delay_data:
|
||||
"""
|
||||
@@ -246,6 +249,37 @@ class delay_data:
|
||||
assert isinstance(other,delay_data)
|
||||
return delay_data(other.delay + self.delay,
|
||||
self.slew)
|
||||
|
||||
class power_data:
|
||||
"""
|
||||
This is the power class to represent the power information
|
||||
Dynamic and leakage power are stored as a single object with this class.
|
||||
"""
|
||||
def __init__(self, dynamic=0.0, leakage=0.0):
|
||||
""" init function support two init method"""
|
||||
# will take single input as a coordinate
|
||||
self.dynamic = dynamic
|
||||
self.leakage = leakage
|
||||
|
||||
def __str__(self):
|
||||
""" override print function output """
|
||||
return "Power Data: Dynamic "+str(self.dynamic)+", Leakage "+str(self.leakage)+" in nW"
|
||||
|
||||
def __add__(self, other):
|
||||
"""
|
||||
Override - function (left), for power_data: a+b != b+a
|
||||
"""
|
||||
assert isinstance(other,power_data)
|
||||
return power_data(other.dynamic + self.dynamic,
|
||||
other.leakage + self.leakage)
|
||||
|
||||
def __radd__(self, other):
|
||||
"""
|
||||
Override - function (left), for power_data: a+b != b+a
|
||||
"""
|
||||
assert isinstance(other,power_data)
|
||||
return power_data(other.dynamic + self.dynamic,
|
||||
other.leakage + self.leakage)
|
||||
|
||||
|
||||
class wire_spice_model:
|
||||
|
||||
@@ -721,17 +721,24 @@ class delay():
|
||||
delay_hl.append(bank_delay.delay/1e3)
|
||||
slew_lh.append(bank_delay.slew/1e3)
|
||||
slew_hl.append(bank_delay.slew/1e3)
|
||||
|
||||
|
||||
power = sram.analytical_power(self.process, self.vdd_voltage, self.temperature, load)
|
||||
#convert from nW to mW
|
||||
power.dynamic /= 1e6
|
||||
power.leakage /= 1e6
|
||||
debug.info(1,"Dynamic Power: {0} mW".format(power.dynamic))
|
||||
debug.info(1,"Leakage Power: {0} mW".format(power.leakage))
|
||||
|
||||
data = {"min_period": 0,
|
||||
"delay_lh": delay_lh,
|
||||
"delay_hl": delay_hl,
|
||||
"slew_lh": slew_lh,
|
||||
"slew_hl": slew_hl,
|
||||
"read0_power": 0,
|
||||
"read1_power": 0,
|
||||
"write0_power": 0,
|
||||
"write1_power": 0,
|
||||
"leakage_power": 0
|
||||
"read0_power": power.dynamic,
|
||||
"read1_power": power.dynamic,
|
||||
"write0_power": power.dynamic,
|
||||
"write1_power": power.dynamic,
|
||||
"leakage_power": power.leakage
|
||||
}
|
||||
return data
|
||||
|
||||
|
||||
@@ -1228,3 +1228,4 @@ class bank(design.design):
|
||||
result = msf_addr_delay + decoder_delay + word_driver_delay \
|
||||
+ bitcell_array_delay + bl_t_data_out_delay + data_t_DATA_delay
|
||||
return result
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ class bitcell(design.design):
|
||||
c_para = spice["min_tx_drain_c"]
|
||||
result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = swing)
|
||||
return result
|
||||
|
||||
|
||||
|
||||
def list_bitcell_pins(self, col, row):
|
||||
# Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array
|
||||
bitcell_pins = ["bl[{0}]".format(col),
|
||||
@@ -56,4 +57,12 @@ class bitcell(design.design):
|
||||
column_pins = ["BL", "BR"]
|
||||
return column_pins
|
||||
|
||||
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
"""Bitcell power in nW. Only characterizes leakage."""
|
||||
from tech import spice
|
||||
leakage = spice["bitcell_leakage"]
|
||||
dynamic = 0 #temporary
|
||||
total_power = self.return_power(dynamic, leakage)
|
||||
return total_power
|
||||
|
||||
|
||||
@@ -179,6 +179,25 @@ class bitcell_array(design.design):
|
||||
#we do not consider the delay over the wire for now
|
||||
return self.return_delay(cell_delay.delay+wl_to_cell_delay.delay,
|
||||
wl_to_cell_delay.slew)
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
"""Power of Bitcell array and bitline in nW."""
|
||||
from tech import drc
|
||||
|
||||
# Dynamic Power from Bitline
|
||||
bl_wire = self.gen_bl_wire()
|
||||
cell_load = 2 * bl_wire.return_input_cap()
|
||||
bl_swing = 0.1 #This should probably be defined in the tech file or input
|
||||
freq = spice["default_event_rate"]
|
||||
bitline_dynamic = bl_swing*cell_load*vdd*vdd*freq #not sure if calculation is correct
|
||||
|
||||
#Calculate the bitcell power which currently only includes leakage
|
||||
cell_power = self.cell.analytical_power(proc, vdd, temp, load)
|
||||
|
||||
#Leakage power grows with entire array and bitlines.
|
||||
total_power = self.return_power(cell_power.dynamic + bitline_dynamic * self.column_size,
|
||||
cell_power.leakage * self.column_size * self.row_size)
|
||||
return total_power
|
||||
|
||||
def gen_wl_wire(self):
|
||||
wl_wire = self.generate_rc_net(int(self.column_size), self.width, drc["minwidth_metal1"])
|
||||
|
||||
@@ -98,7 +98,7 @@ class control_logic(design.design):
|
||||
|
||||
# GAP between main control and replica bitline
|
||||
self.replica_bitline_gap = 2*self.m2_pitch
|
||||
|
||||
|
||||
|
||||
|
||||
def add_modules(self):
|
||||
@@ -688,4 +688,4 @@ class control_logic(design.design):
|
||||
height=pin.height(),
|
||||
width=pin.width())
|
||||
|
||||
|
||||
|
||||
@@ -494,6 +494,7 @@ class hierarchical_decoder(design.design):
|
||||
result = result + z_t_decodeout_delay
|
||||
return result
|
||||
|
||||
|
||||
def input_load(self):
|
||||
if self.determine_predecodes(self.num_inputs)[1]==0:
|
||||
pre = self.pre2_4
|
||||
|
||||
@@ -55,5 +55,6 @@ class hierarchical_predecode2x4(hierarchical_predecode):
|
||||
|
||||
return a_t_b_delay + b_t_z_delay + a_t_out_delay
|
||||
|
||||
|
||||
def input_load(self):
|
||||
return self.nand.input_load()
|
||||
|
||||
@@ -64,6 +64,5 @@ class hierarchical_predecode3x8(hierarchical_predecode):
|
||||
return a_t_b_delay + b_t_z_delay + a_t_out_delay
|
||||
|
||||
|
||||
|
||||
def input_load(self):
|
||||
return self.nand.input_load()
|
||||
|
||||
@@ -26,4 +26,25 @@ class ms_flop(design.design):
|
||||
from tech import spice
|
||||
result = self.return_delay(spice["msflop_delay"], spice["msflop_slew"])
|
||||
return result
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
from tech import spice
|
||||
c_eff = self.calculate_effective_capacitance(load)
|
||||
f = spice["default_event_rate"]
|
||||
power_dyn = c_eff*vdd*vdd*f
|
||||
power_leak = spice["msflop_leakage"]
|
||||
|
||||
total_power = self.return_power(power_dyn, power_leak)
|
||||
return total_power
|
||||
|
||||
def calculate_effective_capacitance(self, load):
|
||||
"""Computes effective capacitance. Results in fF"""
|
||||
from tech import spice, parameter
|
||||
c_load = load
|
||||
c_para = spice["flop_para_cap"]#ff
|
||||
transistion_prob = spice["flop_transisition_prob"]
|
||||
return transistion_prob*(c_load + c_para)
|
||||
|
||||
|
||||
|
||||
@@ -134,3 +134,4 @@ class ms_flop_array(design.design):
|
||||
|
||||
def analytical_delay(self, slew, load=0.0):
|
||||
return self.ms.analytical_delay(slew=slew, load=load)
|
||||
|
||||
|
||||
@@ -30,3 +30,8 @@ class sense_amp(design.design):
|
||||
result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
|
||||
return self.return_delay(result.delay, result.slew)
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
#Power in this module currently not defined. Returns 0 nW (leakage and dynamic).
|
||||
total_power = self.return_power()
|
||||
return total_power
|
||||
|
||||
@@ -117,3 +117,4 @@ class sense_amp_array(design.design):
|
||||
|
||||
def analytical_delay(self, slew, load=0.0):
|
||||
return self.amp.analytical_delay(slew=slew, load=load)
|
||||
|
||||
|
||||
@@ -32,7 +32,12 @@ class tri_gate(design.design):
|
||||
r = spice["min_tx_r"]
|
||||
c_para = spice["min_tx_drain_c"]
|
||||
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
|
||||
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
#Power in this module currently not defined. Returns 0 nW (leakage and dynamic).
|
||||
total_power = self.return_power()
|
||||
return total_power
|
||||
|
||||
def input_load(self):
|
||||
return 9*spice["min_tx_gate_c"]
|
||||
|
||||
@@ -111,3 +111,4 @@ class tri_gate_array(design.design):
|
||||
|
||||
def analytical_delay(self, slew, load=0.0):
|
||||
return self.tri.analytical_delay(slew = slew, load = load)
|
||||
|
||||
|
||||
@@ -205,6 +205,7 @@ class wordline_driver(design.design):
|
||||
net_t_wl = self.inv.analytical_delay(decode_t_net.slew, load)
|
||||
|
||||
return decode_t_net + net_t_wl
|
||||
|
||||
|
||||
|
||||
def input_load(self):
|
||||
return self.nand2.input_load()
|
||||
|
||||
@@ -241,3 +241,20 @@ class pinv(pgate.pgate):
|
||||
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
|
||||
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
c_eff = self.calculate_effective_capacitance(load)
|
||||
freq = spice["default_event_rate"]
|
||||
power_dyn = c_eff*vdd*vdd*freq
|
||||
power_leak = spice["inv_leakage"]
|
||||
|
||||
total_power = self.return_power(power_dyn, power_leak)
|
||||
return total_power
|
||||
|
||||
def calculate_effective_capacitance(self, load):
|
||||
"""Computes effective capacitance. Results in fF"""
|
||||
c_load = load
|
||||
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
transistion_prob = spice["inv_transisition_prob"]
|
||||
return transistion_prob*(c_load + c_para)
|
||||
@@ -213,3 +213,20 @@ class pnand2(pgate.pgate):
|
||||
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
|
||||
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
c_eff = self.calculate_effective_capacitance(load)
|
||||
freq = spice["default_event_rate"]
|
||||
power_dyn = c_eff*vdd*vdd*freq
|
||||
power_leak = spice["nand2_leakage"]
|
||||
|
||||
total_power = self.return_power(power_dyn, power_leak)
|
||||
return total_power
|
||||
|
||||
def calculate_effective_capacitance(self, load):
|
||||
"""Computes effective capacitance. Results in fF"""
|
||||
c_load = load
|
||||
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
transistion_prob = spice["nand2_transisition_prob"]
|
||||
return transistion_prob*(c_load + c_para)
|
||||
|
||||
@@ -233,3 +233,20 @@ class pnand3(pgate.pgate):
|
||||
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
|
||||
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
c_eff = self.calculate_effective_capacitance(load)
|
||||
freq = spice["default_event_rate"]
|
||||
power_dyn = c_eff*vdd*vdd*freq
|
||||
power_leak = spice["nand3_leakage"]
|
||||
|
||||
total_power = self.return_power(power_dyn, power_leak)
|
||||
return total_power
|
||||
|
||||
def calculate_effective_capacitance(self, load):
|
||||
"""Computes effective capacitance. Results in fF"""
|
||||
c_load = load
|
||||
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
transistion_prob = spice["nand3_transisition_prob"]
|
||||
return transistion_prob*(c_load + c_para)
|
||||
|
||||
@@ -223,3 +223,21 @@ class pnor2(pgate.pgate):
|
||||
r = spice["min_tx_r"]/(self.nmos_size/parameter["min_tx_size"])
|
||||
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
return self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew)
|
||||
|
||||
def analytical_power(self, proc, vdd, temp, load):
|
||||
"""Returns dynamic and leakage power. Results in nW"""
|
||||
c_eff = self.calculate_effective_capacitance(load)
|
||||
freq = spice["default_event_rate"]
|
||||
power_dyn = c_eff*vdd*vdd*freq
|
||||
power_leak = spice["nor2_leakage"]
|
||||
|
||||
total_power = self.return_power(power_dyn, power_leak)
|
||||
return total_power
|
||||
|
||||
def calculate_effective_capacitance(self, load):
|
||||
"""Computes effective capacitance. Results in fF"""
|
||||
c_load = load
|
||||
c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff
|
||||
transistion_prob = spice["nor2_transisition_prob"]
|
||||
return transistion_prob*(c_load + c_para)
|
||||
|
||||
@@ -1015,7 +1015,6 @@ class sram(design.design):
|
||||
""" LH and HL are the same in analytical model. """
|
||||
return self.bank.analytical_delay(slew,load)
|
||||
|
||||
|
||||
def save_output(self):
|
||||
""" Save all the output files while reporting time to do it as well. """
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ cell (sram_2_16_1_freepdk45){
|
||||
|
||||
leakage_power () {
|
||||
when : "CSb";
|
||||
value : 0;
|
||||
value : 0.000173;
|
||||
}
|
||||
cell_leakage_power : 0;
|
||||
bus(DATA){
|
||||
@@ -298,19 +298,19 @@ cell (sram_2_16_1_freepdk45){
|
||||
internal_power(){
|
||||
when : "!CSb & clk & !WEb";
|
||||
rise_power(scalar){
|
||||
values("0.0");
|
||||
values("0.065526962224");
|
||||
}
|
||||
fall_power(scalar){
|
||||
values("0.0");
|
||||
values("0.065526962224");
|
||||
}
|
||||
}
|
||||
internal_power(){
|
||||
when : "!CSb & !clk & WEb";
|
||||
rise_power(scalar){
|
||||
values("0.0");
|
||||
values("0.065526962224");
|
||||
}
|
||||
fall_power(scalar){
|
||||
values("0.0");
|
||||
values("0.065526962224");
|
||||
}
|
||||
}
|
||||
internal_power(){
|
||||
|
||||
@@ -82,7 +82,7 @@ cell (sram_2_16_1_scn3me_subm){
|
||||
|
||||
leakage_power () {
|
||||
when : "CSb";
|
||||
value : 0;
|
||||
value : 0.000173;
|
||||
}
|
||||
cell_leakage_power : 0;
|
||||
bus(DATA){
|
||||
@@ -298,19 +298,19 @@ cell (sram_2_16_1_scn3me_subm){
|
||||
internal_power(){
|
||||
when : "!CSb & clk & !WEb";
|
||||
rise_power(scalar){
|
||||
values("0.0");
|
||||
values("10.9314668117");
|
||||
}
|
||||
fall_power(scalar){
|
||||
values("0.0");
|
||||
values("10.9314668117");
|
||||
}
|
||||
}
|
||||
internal_power(){
|
||||
when : "!CSb & !clk & WEb";
|
||||
rise_power(scalar){
|
||||
values("0.0");
|
||||
values("10.9314668117");
|
||||
}
|
||||
fall_power(scalar){
|
||||
values("0.0");
|
||||
values("10.9314668117");
|
||||
}
|
||||
}
|
||||
internal_power(){
|
||||
|
||||
+20
-13
@@ -113,19 +113,8 @@ def write_netgen_script(cell_name, sp_name):
|
||||
f = open(run_file, "w")
|
||||
f.write("#!/bin/sh\n")
|
||||
f.write("{} -noconsole << EOF\n".format(OPTS.lvs_exe[1]))
|
||||
f.write("readnet spice {}.spice\n".format(cell_name))
|
||||
f.write("readnet spice {}\n".format(sp_name))
|
||||
f.write("ignore class c\n")
|
||||
f.write("permute transistors\n")
|
||||
f.write("equate class {{{0}.spice nfet}} {{{1} n}}\n".format(cell_name, sp_name))
|
||||
f.write("equate class {{{0}.spice pfet}} {{{1} p}}\n".format(cell_name, sp_name))
|
||||
# This circuit has symmetries and needs to be flattened to resolve them or the banks won't pass
|
||||
# Is there a more elegant way to add this when needed?
|
||||
f.write("flatten class {{{0}.spice precharge_array}}\n".format(cell_name))
|
||||
f.write("property {{{0}.spice nfet}} remove as ad ps pd\n".format(cell_name))
|
||||
f.write("property {{{0}.spice pfet}} remove as ad ps pd\n".format(cell_name))
|
||||
f.write("property {{{0} n}} remove as ad ps pd\n".format(sp_name))
|
||||
f.write("property {{{0} p}} remove as ad ps pd\n".format(sp_name))
|
||||
f.write("readnet spice {0}.spice\n".format(cell_name))
|
||||
f.write("readnet spice {0}\n".format(sp_name))
|
||||
# Allow some flexibility in W size because magic will snap to a lambda grid
|
||||
# This can also cause disconnects unfortunately!
|
||||
# f.write("property {{{0}{1}.spice nfet}} tolerance {{w 0.1}}\n".format(OPTS.openram_temp,
|
||||
@@ -137,6 +126,24 @@ def write_netgen_script(cell_name, sp_name):
|
||||
f.write("EOF\n")
|
||||
f.close()
|
||||
os.system("chmod u+x {}".format(run_file))
|
||||
|
||||
setup_file = OPTS.openram_temp + "setup.tcl"
|
||||
f = open(setup_file, "w")
|
||||
f.write("ignore class c\n")
|
||||
f.write("equate class {{nfet {0}.spice}} {{n {1}}}\n".format(cell_name, sp_name))
|
||||
f.write("equate class {{pfet {0}.spice}} {{p {1}}}\n".format(cell_name, sp_name))
|
||||
# This circuit has symmetries and needs to be flattened to resolve them or the banks won't pass
|
||||
# Is there a more elegant way to add this when needed?
|
||||
f.write("flatten class {{{0}.spice precharge_array}}\n".format(cell_name))
|
||||
f.write("property {{nfet {0}.spice}} remove as ad ps pd\n".format(cell_name))
|
||||
f.write("property {{pfet {0}.spice}} remove as ad ps pd\n".format(cell_name))
|
||||
f.write("property {{n {0}}} remove as ad ps pd\n".format(sp_name))
|
||||
f.write("property {{p {0}}} remove as ad ps pd\n".format(sp_name))
|
||||
f.write("permute transistors\n")
|
||||
f.write("permute pins n source drain\n")
|
||||
f.write("permute pins p source drain\n")
|
||||
f.close()
|
||||
|
||||
|
||||
def run_drc(cell_name, gds_name, extract=False):
|
||||
"""Run DRC check on a cell which is implemented in gds_name."""
|
||||
|
||||
Reference in New Issue
Block a user