From b00fc040a39d126db73eb34ee1b8fa54908a8a2f Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Thu, 1 Nov 2018 12:29:49 -0700 Subject: [PATCH] Added replica 1rw+1r cell python modules. Also added drc/lvs checks in replica bitline, but test is failing due to pin error in freepdk45 and metal spacing error in scmos. --- compiler/bitcells/replica_bitcell_1rw_1r.py | 23 ++++++++ compiler/modules/replica_bitline.py | 55 ++++++++++++++++-- compiler/tests/14_replica_bitline_test.py | 24 +++++++- .../freepdk45/gds_lib/replica_cell_1rw_1r.gds | Bin 16384 -> 16384 bytes 4 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 compiler/bitcells/replica_bitcell_1rw_1r.py diff --git a/compiler/bitcells/replica_bitcell_1rw_1r.py b/compiler/bitcells/replica_bitcell_1rw_1r.py new file mode 100644 index 00000000..790a6251 --- /dev/null +++ b/compiler/bitcells/replica_bitcell_1rw_1r.py @@ -0,0 +1,23 @@ +import design +import debug +import utils +from tech import GDS,layer + +class replica_bitcell_1rw_1r(design.design): + """ + A single bit cell which is forced to store a 0. + This module implements the single memory cell used in the design. It + is a hand-made cell, so the layout and netlist should be available in + the technology library. """ + + pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"] + (width,height) = utils.get_libcell_size("replica_cell_1rw_1r", GDS["unit"], layer["boundary"]) + pin_map = utils.get_libcell_pins(pin_names, "replica_cell_1rw_1r", GDS["unit"], layer["boundary"]) + + def __init__(self): + design.design.__init__(self, "replica_cell_1rw_1r") + debug.info(2, "Create replica bitcell 1rw+1r object") + + self.width = replica_bitcell_1rw_1r.width + self.height = replica_bitcell_1rw_1r.height + self.pin_map = replica_bitcell_1rw_1r.pin_map diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index 8095d049..99c0e188 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -84,6 +84,7 @@ class replica_bitline(design.design): #self.mod_delay_chain = getattr(g, OPTS.delay_chain) g = reload(__import__(OPTS.replica_bitcell)) + print(OPTS.replica_bitcell) self.mod_replica_bitcell = getattr(g, OPTS.replica_bitcell) self.bitcell = self.replica_bitcell = self.mod_replica_bitcell() @@ -192,13 +193,54 @@ class replica_bitline(design.design): self.add_path("metal1", [pin_right, pin_extension]) self.add_power_pin("gnd", pin_extension) - # for multiport, need to short wordlines to each other so they all connect to gnd + # for multiport, need to short wordlines to each other so they all connect to gnd. wl_last = self.wl_list[self.total_ports-1]+"_{}".format(row) pin_last = self.rbl_inst.get_pin(wl_last) + self.short_wordlines(pin, pin_last, "right", False) + # if self.total_ports > 1: + # wl_last = self.wl_list[self.total_ports-1]+"_{}".format(row) + # pin_last = self.rbl_inst.get_pin(wl_last) + + # #m1 needs to be extended in the y directions, direction needs to be determined as every other cell is flipped + # correct_x = vector(0.5*drc("minwidth_metal1"), 0) + # correct_y = vector(0, 0.5*drc("minwidth_metal1")) + # if pin.uy() > pin_last.uy(): + # self.add_path("metal1", [pin.rc()+correct_x+correct_y, pin_last.rc()+correct_x-correct_y]) + # else: + # self.add_path("metal1", [pin.rc()+correct_x-correct_y, pin_last.rc()+correct_x+correct_y]) + + def short_wordlines(self, wl_pin_a, wl_pin_b, pin_side, is_replica_cell): + """Connects the word lines together for a single bitcell. Also requires which side of the bitcell to short the pins.""" + #Assumes input pins are wordlines. Also assumes the word lines are horizontal in metal1. Also assumes pins have same x coord. + #This is my (Hunter) first time editing layout in openram so this function is likely not optimal. + if self.total_ports > 1: + #1. Create vertical metal for all the bitlines to connect to + #m1 needs to be extended in the y directions, direction needs to be determined as every other cell is flipped + correct_y = vector(0, 0.5*drc("minwidth_metal1")) + #x spacing depends on the side being drawn. Unknown to me (Hunter) why the size of the space differs by the side. + #I assume this is related to how a wire is draw, but I have not investigated the issue. + if pin_side == "right": + correct_x = vector(0.5*drc("minwidth_metal1"), 0) + if wl_pin_a.uy() > wl_pin_b.uy(): + self.add_path("metal1", [wl_pin_a.rc()+correct_x+correct_y, wl_pin_b.rc()+correct_x-correct_y]) + else: + self.add_path("metal1", [wl_pin_a.rc()+correct_x-correct_y, wl_pin_b.rc()+correct_x+correct_y]) + elif pin_side == "left": + correct_x = vector(1.5*drc("minwidth_metal1"), 0) + if wl_pin_a.uy() > wl_pin_b.uy(): + self.add_path("metal1", [wl_pin_a.lc()-correct_x+correct_y, wl_pin_b.lc()-correct_x-correct_y]) + else: + self.add_path("metal1", [wl_pin_a.lc()-correct_x-correct_y, wl_pin_b.lc()-correct_x+correct_y]) + else: + debug.error("Could not connect wordlines on specified input side={}".format(pin_side),1) - correct = vector(0.5*drc("minwidth_metal1"), 0) - self.add_path("metal1", [pin.rc()-correct, pin_last.rc()-correct]) - + #2. Connect word lines horizontally. Only replica cell needs. Bitline loads currently already do this. + if is_replica_cell: + for port in range(self.total_ports): + wl = self.wl_list[port] + pin = self.rbc_inst.get_pin(wl) + self.add_path("metal1", [pin.lc()-correct_x, pin.lc()]) + def route_supplies(self): """ Propagate all vdd/gnd pins up to this level for all modules """ @@ -267,9 +309,10 @@ class replica_bitline(design.design): wl_last = self.wl_list[self.total_ports-1] pin = self.rbc_inst.get_pin(wl) pin_last = self.rbc_inst.get_pin(wl_last) + x_offset = self.short_wordlines(pin, pin_last, "left", True) - correct = vector(0.5*drc("minwidth_metal1"), 0) - self.add_path("metal1", [pin.lc()+correct, pin_last.lc()+correct]) + #correct = vector(0.5*drc("minwidth_metal1"), 0) + #self.add_path("metal1", [pin.lc()+correct, pin_last.lc()+correct]) # DRAIN ROUTE # Route the drain to the vdd rail diff --git a/compiler/tests/14_replica_bitline_test.py b/compiler/tests/14_replica_bitline_test.py index 6797bc65..d73499fc 100755 --- a/compiler/tests/14_replica_bitline_test.py +++ b/compiler/tests/14_replica_bitline_test.py @@ -24,6 +24,26 @@ class replica_bitline_test(openram_test): debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows)) a = replica_bitline.replica_bitline(stages,fanout,rows) self.local_check(a) + #debug.error("Exiting...", 1) + + stages=8 + rows=100 + debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows)) + a = replica_bitline.replica_bitline(stages,fanout,rows) + self.local_check(a) + + #check replica bitline in handmade multi-port 1rw+1r cell + OPTS.bitcell = "bitcell_1rw_1r" + OPTS.replica_bitcell = "replica_bitcell_1rw_1r" + OPTS.num_rw_ports = 1 + OPTS.num_w_ports = 0 + OPTS.num_r_ports = 1 + stages=4 + fanout=4 + rows=13 + debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows)) + a = replica_bitline.replica_bitline(stages,fanout,rows) + self.local_check(a) stages=8 rows=100 @@ -31,7 +51,7 @@ class replica_bitline_test(openram_test): a = replica_bitline.replica_bitline(stages,fanout,rows) self.local_check(a) - # check replica bitline in multi-port + # check replica bitline in pbitcell multi-port OPTS.bitcell = "pbitcell" OPTS.replica_bitcell = "replica_pbitcell" OPTS.num_rw_ports = 1 @@ -61,7 +81,7 @@ class replica_bitline_test(openram_test): debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows)) a = replica_bitline.replica_bitline(stages,fanout,rows) self.local_check(a) - + stages=8 rows=100 debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows)) diff --git a/technology/freepdk45/gds_lib/replica_cell_1rw_1r.gds b/technology/freepdk45/gds_lib/replica_cell_1rw_1r.gds index c42bffb4021f8044bd7ebbb09e8d3331f5f24b51..8bc45cbbfdbb2663c7c2d5062f0b625dfdaf5ecd 100644 GIT binary patch delta 1344 zcmZ`&ON-M`6h2AY)V8UOZE<30n@*wDc6_AGqX~jDg9<8ApDU5+4-j=g(dC3eH*SXZ zfNM8y6m)Ujxfx*)Tom2=_yI0N9Nfu_$vkpTI-1SRIp_P%`Oe3^o+o&oPzMP_NI+Q- z;Q?eo02yMC4*%m&8`e9i?LrXT)G{62b@g7iYw3WVaDMo4nb+}#P)>yawj^8>Nby3V zoDPd!pRBTc%%F&Vyu#^tKR%AKd5zso$ij(G7o7ElYoI{zl_aTueg5*`^qKy(fn|mh ztw1i`%4J8%-=yzGvch-j1UspCY9Awr#d?kF*3nbite;vJxtftu#05D;DKeq>tBO;Y zttN3UH-odq{kWnQ@Vjyw-)aT+D0?r`s>%DJu2iB;d5tY8)ff-|A%UtkaqfVIm4j_I zTYMsto{{bC?d|hZ>jV+m-uF;x<|mAuTkG8{h`C$T@KcY3HG7>gP4q~jn>Yr7^K;+#%rl@1t2{JkRI|g^BExS z=XcNa82|Wp_S@051UDXEc3UL+8i{fSt<4*)e0Up8kd+vKID@Z@8foy{XmLv|JnpLa z)2Q=QZ!2Y*b;22#bj;8^!Y{P{NP`w%%xQv`EQ(*XN_f?x^&s;Ebx?Oy zT(GMI@Yp^~qBnMv!wr1rci*(DT%!?aY~rP!5``VY<(@W~THBkFoIR*>jz$D5I`mOJ ci$tFsDs|Io5Z*Dj$H!Y+dv4e=8@YF+za+~ZXaE2J delta 1326 zcmZuwOKTHh6umP^Cgx?PNibtbGVMr=Nqr=lM*;!=N!K2^@Lte&_DtaLXa0k zcnnb}LKbG=toNOUd|#_a#sjywt;T9C%W7J-VbuV8!sY&_bw0;iLO$XF*qX2+kl~e3 zKI#n{4q0KTfKCzZV1d)|QE=#I^BH>(iVJ5vU9b#sP(cRw$w^ZC=F+v!g^TSQ9nS#MtlBTdA}H5FG+Y zclbN@1t943_utVW{&jBX_mkTp9yY#iR7myBS0!~iThc2j@9r58mjeLeJigIq$%2=9 zg~w>(>6U`Obd9%~qn2T4gwrwTF@56%zrM~d>8|){%n`g~Qv9Zw!|NuUyPfA#opXdA zv}`V@jx}4sRjWtNs50E4$2><{9