From 3bb8aa7e559d508121db7b8b0ab348117fd7b0f0 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Fri, 26 Oct 2018 17:37:25 -0700 Subject: [PATCH 1/7] Fixed import errors with mux analytical delay model. --- compiler/modules/sense_amp.py | 1 + compiler/modules/single_level_column_mux_array.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index 6187b37a..3a857efd 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -25,6 +25,7 @@ class sense_amp(design.design): def input_load(self): #Input load for the bitlines which are connected to the source/drain of a TX. Not the selects. + from tech import spice, parameter bitline_pmos_size = 8 #FIXME: This should be set somewhere and referenced. Probably in tech file. return spice["min_tx_drain_c"]*(bitline_pmos_size/parameter["min_tx_size"])#ff diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index a74f8514..d78e0fdc 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -218,7 +218,7 @@ class single_level_column_mux_array(design.design): rotate=90) def analytical_delay(self, vdd, slew, load=0.0): - from tech import spice + from tech import spice, parameter r = spice["min_tx_r"]/(self.mux.ptx_width/parameter["min_tx_size"]) #Drains of mux transistors make up capacitance. c_para = spice["min_tx_drain_c"]*(self.mux.ptx_width/parameter["min_tx_size"])*self.words_per_row#ff From e5dcf5d5b1340b43376ef93b339015f33df5b785 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Tue, 30 Oct 2018 22:19:26 -0700 Subject: [PATCH 2/7] Altered bitline with heuristic to have a larger delay chain for larger column muxes. Also have to alter the feasible period for functional tests to pass. --- compiler/characterizer/functional.py | 10 ++++++++- compiler/characterizer/simulation.py | 4 ++-- compiler/modules/control_logic.py | 22 ++++++++++++++----- compiler/sram_base.py | 6 ++--- .../tests/22_psram_1bank_4mux_func_test.py | 2 +- .../tests/22_psram_1bank_8mux_func_test.py | 5 +++-- .../tests/22_sram_1bank_4mux_func_test.py | 2 +- .../tests/22_sram_1bank_8mux_func_test.py | 5 +++-- technology/scn4m_subm/tech/tech.py | 2 +- 9 files changed, 40 insertions(+), 18 deletions(-) diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index d6579ab5..4bd9cf71 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -31,7 +31,15 @@ class functional(simulation): self.stored_words = {} self.write_check = [] self.read_check = [] - + + def set_spice_constants(self): + """Spice constants for functional test""" + simulation.set_spice_constants(self) + #Heuristic increase for functional period. Base feasible period typically does not pass the functional test + #for column mux of this size. Increase the feasible period by 20% for this case. + if self.sram.words_per_row >= 4: + self.period = self.period*1.2 + def run(self): # Generate a random sequence of reads and writes self.write_random_memory_sequence() diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index 3d156d2d..235939d8 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -209,14 +209,14 @@ class simulation(): t_current, t_current+self.period) elif op == "write": - comment = "\tWriting {0} to address {1} (from port {2}) during cylce {3} ({4}ns - {5}ns)".format(word, + comment = "\tWriting {0} to address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, addr, port, int(t_current/self.period), t_current, t_current+self.period) else: - comment = "\tReading {0} from address {1} (from port {2}) during cylce {3} ({4}ns - {5}ns)".format(word, + comment = "\tReading {0} from address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word, addr, port, int(t_current/self.period), diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index e6662617..4ac32967 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -18,13 +18,14 @@ class control_logic(design.design): Dynamically generated Control logic for the total SRAM circuit. """ - def __init__(self, num_rows, port_type="rw"): + def __init__(self, num_rows, words_per_row, port_type="rw"): """ Constructor """ name = "control_logic_" + port_type design.design.__init__(self, name) debug.info(1, "Creating {}".format(name)) self.num_rows = num_rows + self.words_per_row = words_per_row self.port_type = port_type if self.port_type == "rw": @@ -92,14 +93,25 @@ class control_logic(design.design): from importlib import reload c = reload(__import__(OPTS.replica_bitline)) replica_bitline = getattr(c, OPTS.replica_bitline) - # FIXME: These should be tuned according to the size! - delay_stages = 4 # Must be non-inverting - delay_fanout = 3 # This can be anything >=2 + + delay_stages, delay_fanout = self.get_delay_chain_size() bitcell_loads = int(math.ceil(self.num_rows / 2.0)) self.replica_bitline = replica_bitline(delay_stages, delay_fanout, bitcell_loads, name="replica_bitline_"+self.port_type) self.add_mod(self.replica_bitline) - + def get_delay_chain_size(self): + """Determine the size of the delay chain used for the Sense Amp Enable """ + # FIXME: These should be tuned according to the additional size parameters + delay_fanout = 3 # This can be anything >=2 + # Delay stages Must be non-inverting + if self.words_per_row >= 8: + delay_stages = 8 + elif self.words_per_row == 4: + delay_stages = 6 + else: + delay_stages = 4 + return (delay_stages, delay_fanout) + def setup_signal_busses(self): """ Setup bus names, determine the size of the busses etc """ diff --git a/compiler/sram_base.py b/compiler/sram_base.py index cc8247ed..a1be1f30 100644 --- a/compiler/sram_base.py +++ b/compiler/sram_base.py @@ -223,13 +223,13 @@ class sram_base(design): from control_logic import control_logic # Create the control logic module for each port type if OPTS.num_rw_ports>0: - self.control_logic = self.control_logic_rw = control_logic(num_rows=self.num_rows, port_type="rw") + self.control_logic = self.control_logic_rw = control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, port_type="rw") self.add_mod(self.control_logic_rw) if OPTS.num_w_ports>0: - self.control_logic_w = control_logic(num_rows=self.num_rows, port_type="w") + self.control_logic_w = control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, port_type="w") self.add_mod(self.control_logic_w) if OPTS.num_r_ports>0: - self.control_logic_r = control_logic(num_rows=self.num_rows, port_type="r") + self.control_logic_r = control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, port_type="r") self.add_mod(self.control_logic_r) # Create the address and control flops (but not the clk) diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index 1ae684d9..e04493fd 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 22_psram_1bank_4mux_func_test") +#@unittest.skip("SKIPPING 22_psram_1bank_4mux_func_test") class psram_1bank_4mux_func_test(openram_test): def runTest(self): diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index d81e76f9..d4ff94a8 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 22_psram_1bank_8mux_func_test") +#@unittest.skip("SKIPPING 22_psram_1bank_8mux_func_test") class psram_1bank_8mux_func_test(openram_test): def runTest(self): @@ -29,7 +29,7 @@ class psram_1bank_8mux_func_test(openram_test): from sram import sram from sram_config import sram_config c = sram_config(word_size=4, - num_words=512, + num_words=256, num_banks=1) c.words_per_row=8 debug.info(1, "Functional test for psram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, @@ -37,6 +37,7 @@ class psram_1bank_8mux_func_test(openram_test): c.words_per_row, c.num_banks)) s = sram(c, name="sram") + tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) diff --git a/compiler/tests/22_sram_1bank_4mux_func_test.py b/compiler/tests/22_sram_1bank_4mux_func_test.py index c16b86fe..18836664 100755 --- a/compiler/tests/22_sram_1bank_4mux_func_test.py +++ b/compiler/tests/22_sram_1bank_4mux_func_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 22_sram_1bank_4mux_func_test") +#@unittest.skip("SKIPPING 22_sram_1bank_4mux_func_test") class sram_1bank_4mux_func_test(openram_test): def runTest(self): diff --git a/compiler/tests/22_sram_1bank_8mux_func_test.py b/compiler/tests/22_sram_1bank_8mux_func_test.py index be8e538f..c66a26bd 100755 --- a/compiler/tests/22_sram_1bank_8mux_func_test.py +++ b/compiler/tests/22_sram_1bank_8mux_func_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 22_sram_1bank_8mux_func_test") +#@unittest.skip("SKIPPING 22_sram_1bank_8mux_func_test") class sram_1bank_8mux_func_test(openram_test): def runTest(self): @@ -30,7 +30,7 @@ class sram_1bank_8mux_func_test(openram_test): from sram import sram from sram_config import sram_config c = sram_config(word_size=4, - num_words=512, + num_words=256, num_banks=1) c.words_per_row=8 debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, @@ -38,6 +38,7 @@ class sram_1bank_8mux_func_test(openram_test): c.words_per_row, c.num_banks)) s = sram(c, name="sram") + tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 0e81953a..25afd844 100755 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -240,7 +240,7 @@ spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+" #spice stimulus related variables -spice["feasible_period"] = 5 # estimated feasible period in ns +spice["feasible_period"] = 5 # estimated feasible period in ns spice["supply_voltages"] = [4.5, 5.0, 5.5] # Supply voltage corners in [Volts] spice["nom_supply_voltage"] = 5.0 # Nominal supply voltage in [Volts] spice["rise_time"] = 0.05 # rise time in [Nano-seconds] From 9321f0461b97d1e57307a7f0aec6569a7afac4e4 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Wed, 31 Oct 2018 00:06:34 -0700 Subject: [PATCH 3/7] Fixed error in control logic test. Added gds/sp for replica cell 1rw+1r. --- compiler/tests/16_control_logic_test.py | 10 +- .../freepdk45/gds_lib/replica_cell_1rw_1r.gds | Bin 0 -> 16384 bytes .../freepdk45/sp_lib/replica_cell_1rw_1r.sp | 14 ++ .../gds_lib/replica_cell_1rw_1r.gds | Bin 0 -> 6154 bytes .../mag_lib/replica_cell_1rw_1r.mag | 149 ++++++++++++++++++ .../scn4m_subm/sp_lib/replica_cell_1rw_1r.sp | 14 ++ 6 files changed, 182 insertions(+), 5 deletions(-) create mode 100644 technology/freepdk45/gds_lib/replica_cell_1rw_1r.gds create mode 100644 technology/freepdk45/sp_lib/replica_cell_1rw_1r.sp create mode 100644 technology/scn4m_subm/gds_lib/replica_cell_1rw_1r.gds create mode 100644 technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag create mode 100644 technology/scn4m_subm/sp_lib/replica_cell_1rw_1r.sp diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index 7a4ff768..897c51c2 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -20,7 +20,7 @@ class control_logic_test(openram_test): # check control logic for single port debug.info(1, "Testing sample for control_logic") - a = control_logic.control_logic(num_rows=128) + a = control_logic.control_logic(num_rows=128, words_per_row=1) self.local_check(a) # check control logic for multi-port @@ -31,7 +31,7 @@ class control_logic_test(openram_test): OPTS.num_r_ports = 0 debug.info(1, "Testing sample for control_logic for multiport") - a = control_logic.control_logic(num_rows=128) + a = control_logic.control_logic(num_rows=128, words_per_row=1) self.local_check(a) # Check port specific control logic @@ -40,15 +40,15 @@ class control_logic_test(openram_test): OPTS.num_r_ports = 1 debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - a = control_logic.control_logic(num_rows=128, port_type="rw") + a = control_logic.control_logic(num_rows=128, words_per_row=1, port_type="rw") self.local_check(a) debug.info(1, "Testing sample for control_logic for multiport, only write control logic") - a = control_logic.control_logic(num_rows=128, port_type="w") + a = control_logic.control_logic(num_rows=128, words_per_row=1, port_type="w") self.local_check(a) debug.info(1, "Testing sample for control_logic for multiport, only read control logic") - a = control_logic.control_logic(num_rows=128, port_type="r") + a = control_logic.control_logic(num_rows=128, words_per_row=1, port_type="r") self.local_check(a) globals.end_openram() diff --git a/technology/freepdk45/gds_lib/replica_cell_1rw_1r.gds b/technology/freepdk45/gds_lib/replica_cell_1rw_1r.gds new file mode 100644 index 0000000000000000000000000000000000000000..c42bffb4021f8044bd7ebbb09e8d3331f5f24b51 GIT binary patch literal 16384 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 literal 0 HcmV?d00001 diff --git a/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag new file mode 100644 index 00000000..1568d599 --- /dev/null +++ b/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag @@ -0,0 +1,149 @@ +magic +tech scmos +timestamp 1540969238 +<< nwell >> +rect 0 50 54 79 +<< pwell >> +rect 0 0 54 50 +<< ntransistor >> +rect 14 35 16 41 +rect 22 29 24 41 +rect 30 29 32 41 +rect 38 35 40 41 +rect 14 17 16 25 +rect 22 17 24 25 +rect 30 17 32 25 +rect 38 17 40 25 +<< ptransistor >> +rect 22 58 24 62 +rect 30 58 32 62 +<< ndiffusion >> +rect 9 39 14 41 +rect 13 35 14 39 +rect 16 35 17 41 +rect 21 33 22 41 +rect 17 29 22 33 +rect 24 29 25 41 +rect 29 29 30 41 +rect 32 33 33 41 +rect 37 35 38 41 +rect 40 39 45 41 +rect 40 35 41 39 +rect 32 29 37 33 +rect 9 23 14 25 +rect 13 19 14 23 +rect 9 17 14 19 +rect 16 17 22 25 +rect 24 17 25 25 +rect 29 17 30 25 +rect 32 17 38 25 +rect 40 23 45 25 +rect 40 19 41 23 +rect 40 17 45 19 +<< pdiffusion >> +rect 21 58 22 62 +rect 24 58 25 62 +rect 29 58 30 62 +rect 32 58 33 62 +<< ndcontact >> +rect 9 35 13 39 +rect 17 33 21 41 +rect 25 29 29 41 +rect 33 33 37 41 +rect 41 35 45 39 +rect 9 19 13 23 +rect 25 17 29 25 +rect 41 19 45 23 +<< pdcontact >> +rect 17 58 21 62 +rect 25 58 29 62 +rect 33 58 37 62 +<< psubstratepcontact >> +rect 25 9 29 13 +<< nsubstratencontact >> +rect 25 72 29 76 +<< polysilicon >> +rect 22 62 24 64 +rect 30 62 32 64 +rect 22 48 24 58 +rect 30 55 32 58 +rect 31 51 32 55 +rect 14 41 16 46 +rect 22 44 23 48 +rect 22 41 24 44 +rect 30 41 32 51 +rect 38 41 40 46 +rect 14 33 16 35 +rect 38 33 40 35 +rect 14 25 16 26 +rect 22 25 24 29 +rect 30 25 32 29 +rect 38 25 40 26 +rect 14 15 16 17 +rect 22 15 24 17 +rect 30 15 32 17 +rect 38 15 40 17 +<< polycontact >> +rect 27 51 31 55 +rect 10 42 14 46 +rect 23 44 27 48 +rect 40 42 44 46 +rect 12 26 16 30 +rect 38 26 42 30 +<< metal1 >> +rect 0 72 25 76 +rect 29 72 54 76 +rect 0 65 54 69 +rect 10 46 14 65 +rect 29 58 33 62 +rect 17 55 20 58 +rect 17 51 27 55 +rect 17 41 20 51 +rect 34 48 37 58 +rect 27 44 37 48 +rect 34 41 37 44 +rect 40 46 44 65 +rect 6 35 9 39 +rect 45 35 48 39 +rect 25 25 29 29 +rect 25 13 29 17 +rect 0 9 25 13 +rect 29 9 54 13 +rect 0 2 16 6 +rect 20 2 34 6 +rect 38 2 54 6 +<< m2contact >> +rect 25 72 29 76 +rect 25 58 29 62 +rect 2 35 6 39 +rect 16 26 20 30 +rect 48 35 52 39 +rect 34 26 38 30 +rect 9 19 13 23 +rect 41 19 45 23 +rect 16 2 20 6 +rect 34 2 38 6 +<< metal2 >> +rect 2 39 6 76 +rect 2 0 6 35 +rect 9 23 13 76 +rect 25 62 29 72 +rect 9 0 13 19 +rect 16 6 20 26 +rect 34 6 38 26 +rect 41 23 45 76 +rect 41 0 45 19 +rect 48 39 52 76 +rect 48 0 52 35 +<< bb >> +rect 0 0 54 74 +<< labels >> +rlabel metal1 27 4 27 4 1 wl1 +rlabel psubstratepcontact 27 11 27 11 1 gnd +rlabel m2contact 27 74 27 74 5 vdd +rlabel metal1 19 67 19 67 1 wl0 +rlabel metal2 4 7 4 7 2 bl0 +rlabel metal2 11 7 11 7 1 bl1 +rlabel metal2 43 7 43 7 1 br1 +rlabel metal2 50 7 50 7 8 br0 +<< end >> diff --git a/technology/scn4m_subm/sp_lib/replica_cell_1rw_1r.sp b/technology/scn4m_subm/sp_lib/replica_cell_1rw_1r.sp new file mode 100644 index 00000000..0a235af8 --- /dev/null +++ b/technology/scn4m_subm/sp_lib/replica_cell_1rw_1r.sp @@ -0,0 +1,14 @@ + +.SUBCKT replica_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd +MM9 RA_to_R_right wl1 br1 gnd n w=1.6u l=0.4u +MM8 RA_to_R_right Q gnd gnd n w=1.6u l=0.4u +MM7 RA_to_R_left vdd gnd gnd n w=1.6u l=0.4u +MM6 RA_to_R_left wl1 bl1 gnd n w=1.6u l=0.4u +MM5 Q wl0 bl0 gnd n w=1.2u l=0.4u +MM4 vdd wl0 br0 gnd n w=1.2u l=0.4u +MM1 Q vdd gnd gnd n w=2.4u l=0.4u +MM0 vdd Q gnd gnd n w=2.4u l=0.4u +MM3 Q vdd vdd vdd p w=0.8u l=0.4u +MM2 vdd Q vdd vdd p w=0.8u l=0.4u +.ENDS + From b00fc040a39d126db73eb34ee1b8fa54908a8a2f Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Thu, 1 Nov 2018 12:29:49 -0700 Subject: [PATCH 4/7] 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 From 642dc8517c5809ad2b46ec371f7e63899d50e22b Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Thu, 1 Nov 2018 14:05:55 -0700 Subject: [PATCH 5/7] Added no mux functional test for 1rw+1r. Delay characterization also works for the custom cell as well. --- compiler/example_config_freepdk45.py | 14 +++-- compiler/example_config_scn4m_subm.py | 18 ++++-- .../22_sram_1rw_1r_1bank_nomux_func_test.py | 60 +++++++++++++++++++ 3 files changed, 82 insertions(+), 10 deletions(-) create mode 100755 compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py diff --git a/compiler/example_config_freepdk45.py b/compiler/example_config_freepdk45.py index 5e7a689f..c6f36c29 100644 --- a/compiler/example_config_freepdk45.py +++ b/compiler/example_config_freepdk45.py @@ -11,8 +11,14 @@ output_name = "sram_{0}_{1}_{2}".format(word_size,num_words,tech_name) #Setting for multiport # netlist_only = True -# bitcell = "pbitcell" -# replica_bitcell="replica_pbitcell" # num_rw_ports = 1 -# num_r_ports = 0 -# num_w_ports = 1 +# num_r_ports = 1 +# num_w_ports = 0 + +#Pbitcell modules for multiport +#bitcell = "pbitcell" +#replica_bitcell="replica_pbitcell" + +#Custom 1rw+1r multiport cell. Set the above port numbers to rw = 1, r = 1, w = 0 +# bitcell = "bitcell_1rw_1r" +# replica_bitcell = "replica_bitcell_1rw_1r" diff --git a/compiler/example_config_scn4m_subm.py b/compiler/example_config_scn4m_subm.py index 436d0ffd..e53d64a8 100644 --- a/compiler/example_config_scn4m_subm.py +++ b/compiler/example_config_scn4m_subm.py @@ -10,9 +10,15 @@ output_path = "temp" output_name = "sram_{0}_{1}_{2}".format(word_size,num_words,tech_name) #Setting for multiport -netlist_only = True -bitcell = "pbitcell" -replica_bitcell="replica_pbitcell" -num_rw_ports = 1 -num_r_ports = 1 -num_w_ports = 1 \ No newline at end of file +# netlist_only = True +# num_rw_ports = 1 +# num_r_ports = 1 +# num_w_ports = 0 + +#Pbitcell modules for multiport +#bitcell = "pbitcell" +#replica_bitcell="replica_pbitcell" + +#Custom 1rw+1r multiport cell. Set the above port numbers to rw = 1, r = 1, w = 0 +# bitcell = "bitcell_1rw_1r" +# replica_bitcell = "replica_bitcell_1rw_1r" \ No newline at end of file diff --git a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py new file mode 100755 index 00000000..aa80656d --- /dev/null +++ b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +""" +Run a functioal test on 1 bank SRAM +""" + +import unittest +from testutils import header,openram_test +import sys,os +sys.path.append(os.path.join(sys.path[0],"..")) +import globals +from globals import OPTS +import debug + +#@unittest.skip("SKIPPING 22_sram_1rw_1r_1bank_nomux_func_test") +class psram_1bank_nomux_func_test(openram_test): + + def runTest(self): + globals.init_openram("config_20_{0}".format(OPTS.tech_name)) + OPTS.analytical_delay = False + OPTS.netlist_only = True + 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 + + # This is a hack to reload the characterizer __init__ with the spice version + from importlib import reload + import characterizer + reload(characterizer) + from characterizer import functional + from sram import sram + from sram_config import sram_config + c = sram_config(word_size=4, + num_words=32, + num_banks=1) + c.words_per_row=1 + debug.info(1, "Functional test for sram 1rw,1r with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, + c.num_words, + c.words_per_row, + c.num_banks)) + s = sram(c, name="sram") + tempspice = OPTS.openram_temp + "temp.sp" + s.sp_write(tempspice) + + corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) + + f = functional(s.s, tempspice, corner) + f.num_cycles = 10 + (fail, error) = f.run() + self.assertTrue(fail,error) + + globals.end_openram() + +# instantiate a copy of the class to actually run the test +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main() From f05865b307319f9c7c5bdacf5442d9cbdac50cce Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Fri, 2 Nov 2018 17:16:41 -0700 Subject: [PATCH 6/7] Fixed drc issues with replica bitline test. --- compiler/modules/replica_bitline.py | 53 +++++++++++------- technology/scn4m_subm/gds_lib/cell_1rw_1r.gds | Bin 6202 -> 6202 bytes .../gds_lib/replica_cell_1rw_1r.gds | Bin 6154 -> 6154 bytes technology/scn4m_subm/mag_lib/cell_1rw_1r.mag | 4 +- .../mag_lib/replica_cell_1rw_1r.mag | 4 +- 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index 99c0e188..84aaa63d 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -84,7 +84,6 @@ 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() @@ -190,26 +189,17 @@ class replica_bitline(design.design): if pin.layer != "metal1": continue - self.add_path("metal1", [pin_right, pin_extension]) + pin_width_ydir = pin.uy()-pin.by() + #Width is set to pin y width to avoid DRC issues with m1 gaps + self.add_path("metal1", [pin_right, pin_extension], pin_width_ydir) self.add_power_pin("gnd", pin_extension) # 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]) + self.short_wordlines(pin, pin_last, "right", False, row, vector(self.m3_pitch,0)) - def short_wordlines(self, wl_pin_a, wl_pin_b, pin_side, is_replica_cell): + def short_wordlines(self, wl_pin_a, wl_pin_b, pin_side, is_replica_cell, cell_row=0, offset_x_vec=None): """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. @@ -221,12 +211,21 @@ class replica_bitline(design.design): #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 offset_x_vec != None: + correct_x = offset_x_vec + else: + 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.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 offset_x_vec != None: + correct_x = offset_x_vec + else: + 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: @@ -235,11 +234,20 @@ class replica_bitline(design.design): debug.error("Could not connect wordlines on specified input side={}".format(pin_side),1) #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): + for port in range(self.total_ports): + if is_replica_cell: wl = self.wl_list[port] pin = self.rbc_inst.get_pin(wl) + else: + wl = self.wl_list[port]+"_{}".format(cell_row) + pin = self.rbl_inst.get_pin(wl) + + if pin_side == "left": self.add_path("metal1", [pin.lc()-correct_x, pin.lc()]) + elif pin_side == "right": + self.add_path("metal1", [pin.rc()+correct_x, pin.rc()]) + + def route_supplies(self): """ Propagate all vdd/gnd pins up to this level for all modules """ @@ -259,8 +267,13 @@ class replica_bitline(design.design): # Replica bitcell needs to be routed up to M3 pin=self.rbc_inst.get_pin("vdd") - # Don't rotate this via to vit in FreePDK45 - self.add_power_pin("vdd", pin.center(), rotate=0) + # Don't rotate this via to vit in FreePDK45. In the custom cell, the pin cannot be placed + # directly on vdd or there will be a drc error with a wordline. Place the pin slightly farther + # away then route to it. A better solution would be to rotate the m1 in the via or move the pin + # a m1_pitch below the entire cell. + pin_extension = pin.center() - vector(0,self.m1_pitch) + self.add_power_pin("vdd", pin_extension, rotate=0) + self.add_path("metal1", [pin.center(), pin_extension]) for pin in self.rbc_inst.get_pins("gnd"): self.add_power_pin("gnd", pin.center()) diff --git a/technology/scn4m_subm/gds_lib/cell_1rw_1r.gds b/technology/scn4m_subm/gds_lib/cell_1rw_1r.gds index 0b13d628845584a367f83602fefb4c3f8b3b7134..4254ba26d107b9392f1889275302e2b261d967b4 100644 GIT binary patch delta 107 zcmdmGu**P+fsKKQftf*uk%^&-?Y delta 96 zcmdmGu**P+fsKKQftf*uk%^&C3&cMLJ!T=bdWhp5P3@m~`%nrmX3;^gy51Ie~ delta 96 zcmeA&=rT}ZU}IonU}lhEWMU{|;9`(x00A{Pn~8y8qLQ&FR*8*S8^tDPi}Uh`N-!{3 XUSQymWGhRV%p-n*jh%skg@pkC_Vo+& diff --git a/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag index e6420e89..85323b17 100644 --- a/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag +++ b/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag @@ -1,6 +1,6 @@ magic tech scmos -timestamp 1540504134 +timestamp 1541193956 << nwell >> rect 0 50 54 79 << pwell >> @@ -139,10 +139,10 @@ rect 0 0 54 74 << labels >> rlabel metal1 27 4 27 4 1 wl1 rlabel psubstratepcontact 27 11 27 11 1 gnd -rlabel m2contact 27 74 27 74 5 vdd rlabel metal1 19 67 19 67 1 wl0 rlabel metal2 4 7 4 7 2 bl0 rlabel metal2 11 7 11 7 1 bl1 rlabel metal2 43 7 43 7 1 br1 rlabel metal2 50 7 50 7 8 br0 +rlabel metal1 19 74 19 74 5 vdd << end >> diff --git a/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag index 1568d599..38edce07 100644 --- a/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag +++ b/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag @@ -1,6 +1,6 @@ magic tech scmos -timestamp 1540969238 +timestamp 1541194096 << nwell >> rect 0 50 54 79 << pwell >> @@ -140,10 +140,10 @@ rect 0 0 54 74 << labels >> rlabel metal1 27 4 27 4 1 wl1 rlabel psubstratepcontact 27 11 27 11 1 gnd -rlabel m2contact 27 74 27 74 5 vdd rlabel metal1 19 67 19 67 1 wl0 rlabel metal2 4 7 4 7 2 bl0 rlabel metal2 11 7 11 7 1 bl1 rlabel metal2 43 7 43 7 1 br1 rlabel metal2 50 7 50 7 8 br0 +rlabel metal1 19 74 19 74 5 vdd << end >> From 4c26dede23cefbd9f2a187731e16d0d6c663998f Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Mon, 5 Nov 2018 14:56:22 -0800 Subject: [PATCH 7/7] Unskipped functional tests and increases the number of ports on pbitcell functional tests. --- compiler/tests/22_psram_1bank_2mux_func_test.py | 3 +++ compiler/tests/22_psram_1bank_4mux_func_test.py | 5 ++++- compiler/tests/22_psram_1bank_8mux_func_test.py | 3 +++ compiler/tests/22_psram_1bank_nomux_func_test.py | 3 +++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index 1e1367ed..f2679c03 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -20,6 +20,9 @@ class psram_1bank_2mux_func_test(openram_test): OPTS.netlist_only = True OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 1 # This is a hack to reload the characterizer __init__ with the spice version from importlib import reload diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index de2e01d4..a8d6dab2 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 22_psram_1bank_4mux_func_test") +#@unittest.skip("SKIPPING 22_psram_1bank_4mux_func_test") class psram_1bank_4mux_func_test(openram_test): def runTest(self): @@ -20,6 +20,9 @@ class psram_1bank_4mux_func_test(openram_test): OPTS.netlist_only = True OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 1 # This is a hack to reload the characterizer __init__ with the spice version from importlib import reload diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index efbb68c3..1a0a1ec5 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -20,6 +20,9 @@ class psram_1bank_8mux_func_test(openram_test): OPTS.netlist_only = True OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 1 # This is a hack to reload the characterizer __init__ with the spice version from importlib import reload diff --git a/compiler/tests/22_psram_1bank_nomux_func_test.py b/compiler/tests/22_psram_1bank_nomux_func_test.py index ce852dff..7817b055 100755 --- a/compiler/tests/22_psram_1bank_nomux_func_test.py +++ b/compiler/tests/22_psram_1bank_nomux_func_test.py @@ -20,6 +20,9 @@ class psram_1bank_nomux_func_test(openram_test): OPTS.netlist_only = True OPTS.bitcell = "pbitcell" OPTS.replica_bitcell="replica_pbitcell" + OPTS.num_rw_ports = 1 + OPTS.num_r_ports = 1 + OPTS.num_w_ports = 1 # This is a hack to reload the characterizer __init__ with the spice version from importlib import reload