From d4cd8aff1531248ffc248227d32a31028bf0aa48 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 14 May 2018 16:36:58 -0700 Subject: [PATCH 01/25] Change permissions of tests --- compiler/tests/00_code_format_check_test.py | 0 compiler/tests/01_library_drc_test.py | 0 compiler/tests/02_library_lvs_test.py | 0 compiler/tests/03_contact_test.py | 0 compiler/tests/03_path_test.py | 0 compiler/tests/03_ptx_1finger_nmos_test.py | 0 compiler/tests/03_ptx_1finger_pmos_test.py | 0 compiler/tests/03_ptx_3finger_nmos_test.py | 0 compiler/tests/03_ptx_3finger_pmos_test.py | 0 compiler/tests/03_ptx_4finger_nmos_test.py | 0 compiler/tests/03_ptx_4finger_pmos_test.py | 0 compiler/tests/03_wire_test.py | 0 compiler/tests/04_pinv_10x_test.py | 0 compiler/tests/04_pinv_1x_beta_test.py | 0 compiler/tests/04_pinv_1x_test.py | 0 compiler/tests/04_pinv_2x_test.py | 0 compiler/tests/04_pinvbuf_test.py | 0 compiler/tests/04_pnand2_test.py | 0 compiler/tests/04_pnand3_test.py | 0 compiler/tests/04_pnor2_test.py | 0 compiler/tests/04_precharge_test.py | 0 compiler/tests/04_single_level_column_mux_test.py | 0 compiler/tests/05_bitcell_array_test.py | 0 compiler/tests/06_hierarchical_decoder_test.py | 0 compiler/tests/06_hierarchical_predecode2x4_test.py | 0 compiler/tests/06_hierarchical_predecode3x8_test.py | 0 compiler/tests/07_single_level_column_mux_array_test.py | 0 compiler/tests/08_precharge_array_test.py | 0 compiler/tests/08_wordline_driver_test.py | 0 compiler/tests/09_sense_amp_array_test.py | 0 compiler/tests/10_write_driver_array_test.py | 0 compiler/tests/11_dff_array_test.py | 0 compiler/tests/11_dff_buf_array_test.py | 0 compiler/tests/11_dff_buf_test.py | 0 compiler/tests/11_dff_inv_array_test.py | 0 compiler/tests/11_dff_inv_test.py | 0 compiler/tests/11_ms_flop_array_test.py | 0 compiler/tests/12_tri_gate_array_test.py | 0 compiler/tests/13_delay_chain_test.py | 0 compiler/tests/14_replica_bitline_test.py | 0 compiler/tests/16_control_logic_test.py | 0 compiler/tests/19_bank_select_test.py | 0 compiler/tests/19_multi_bank_test.py | 0 compiler/tests/19_single_bank_test.py | 0 compiler/tests/20_sram_1bank_test.py | 0 compiler/tests/20_sram_2bank_test.py | 0 compiler/tests/20_sram_4bank_test.py | 0 compiler/tests/21_hspice_delay_test.py | 0 compiler/tests/21_hspice_setuphold_test.py | 0 compiler/tests/21_ngspice_delay_test.py | 0 compiler/tests/21_ngspice_setuphold_test.py | 0 compiler/tests/22_sram_func_test.py | 0 compiler/tests/23_lib_sram_model_test.py | 0 compiler/tests/23_lib_sram_prune_test.py | 0 compiler/tests/23_lib_sram_test.py | 0 compiler/tests/24_lef_sram_test.py | 0 compiler/tests/25_verilog_sram_test.py | 0 compiler/tests/30_openram_test.py | 0 compiler/tests/regress.py | 0 59 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 compiler/tests/00_code_format_check_test.py mode change 100644 => 100755 compiler/tests/01_library_drc_test.py mode change 100644 => 100755 compiler/tests/02_library_lvs_test.py mode change 100644 => 100755 compiler/tests/03_contact_test.py mode change 100644 => 100755 compiler/tests/03_path_test.py mode change 100644 => 100755 compiler/tests/03_ptx_1finger_nmos_test.py mode change 100644 => 100755 compiler/tests/03_ptx_1finger_pmos_test.py mode change 100644 => 100755 compiler/tests/03_ptx_3finger_nmos_test.py mode change 100644 => 100755 compiler/tests/03_ptx_3finger_pmos_test.py mode change 100644 => 100755 compiler/tests/03_ptx_4finger_nmos_test.py mode change 100644 => 100755 compiler/tests/03_ptx_4finger_pmos_test.py mode change 100644 => 100755 compiler/tests/03_wire_test.py mode change 100644 => 100755 compiler/tests/04_pinv_10x_test.py mode change 100644 => 100755 compiler/tests/04_pinv_1x_beta_test.py mode change 100644 => 100755 compiler/tests/04_pinv_1x_test.py mode change 100644 => 100755 compiler/tests/04_pinv_2x_test.py mode change 100644 => 100755 compiler/tests/04_pinvbuf_test.py mode change 100644 => 100755 compiler/tests/04_pnand2_test.py mode change 100644 => 100755 compiler/tests/04_pnand3_test.py mode change 100644 => 100755 compiler/tests/04_pnor2_test.py mode change 100644 => 100755 compiler/tests/04_precharge_test.py mode change 100644 => 100755 compiler/tests/04_single_level_column_mux_test.py mode change 100644 => 100755 compiler/tests/05_bitcell_array_test.py mode change 100644 => 100755 compiler/tests/06_hierarchical_decoder_test.py mode change 100644 => 100755 compiler/tests/06_hierarchical_predecode2x4_test.py mode change 100644 => 100755 compiler/tests/06_hierarchical_predecode3x8_test.py mode change 100644 => 100755 compiler/tests/07_single_level_column_mux_array_test.py mode change 100644 => 100755 compiler/tests/08_precharge_array_test.py mode change 100644 => 100755 compiler/tests/08_wordline_driver_test.py mode change 100644 => 100755 compiler/tests/09_sense_amp_array_test.py mode change 100644 => 100755 compiler/tests/10_write_driver_array_test.py mode change 100644 => 100755 compiler/tests/11_dff_array_test.py mode change 100644 => 100755 compiler/tests/11_dff_buf_array_test.py mode change 100644 => 100755 compiler/tests/11_dff_buf_test.py mode change 100644 => 100755 compiler/tests/11_dff_inv_array_test.py mode change 100644 => 100755 compiler/tests/11_dff_inv_test.py mode change 100644 => 100755 compiler/tests/11_ms_flop_array_test.py mode change 100644 => 100755 compiler/tests/12_tri_gate_array_test.py mode change 100644 => 100755 compiler/tests/13_delay_chain_test.py mode change 100644 => 100755 compiler/tests/14_replica_bitline_test.py mode change 100644 => 100755 compiler/tests/16_control_logic_test.py mode change 100644 => 100755 compiler/tests/19_bank_select_test.py mode change 100644 => 100755 compiler/tests/19_multi_bank_test.py mode change 100644 => 100755 compiler/tests/19_single_bank_test.py mode change 100644 => 100755 compiler/tests/20_sram_1bank_test.py mode change 100644 => 100755 compiler/tests/20_sram_2bank_test.py mode change 100644 => 100755 compiler/tests/20_sram_4bank_test.py mode change 100644 => 100755 compiler/tests/21_hspice_delay_test.py mode change 100644 => 100755 compiler/tests/21_hspice_setuphold_test.py mode change 100644 => 100755 compiler/tests/21_ngspice_delay_test.py mode change 100644 => 100755 compiler/tests/21_ngspice_setuphold_test.py mode change 100644 => 100755 compiler/tests/22_sram_func_test.py mode change 100644 => 100755 compiler/tests/23_lib_sram_model_test.py mode change 100644 => 100755 compiler/tests/23_lib_sram_prune_test.py mode change 100644 => 100755 compiler/tests/23_lib_sram_test.py mode change 100644 => 100755 compiler/tests/24_lef_sram_test.py mode change 100644 => 100755 compiler/tests/25_verilog_sram_test.py mode change 100644 => 100755 compiler/tests/30_openram_test.py mode change 100644 => 100755 compiler/tests/regress.py diff --git a/compiler/tests/00_code_format_check_test.py b/compiler/tests/00_code_format_check_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/01_library_drc_test.py b/compiler/tests/01_library_drc_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/02_library_lvs_test.py b/compiler/tests/02_library_lvs_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/03_contact_test.py b/compiler/tests/03_contact_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/03_path_test.py b/compiler/tests/03_path_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/03_ptx_1finger_nmos_test.py b/compiler/tests/03_ptx_1finger_nmos_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/03_ptx_1finger_pmos_test.py b/compiler/tests/03_ptx_1finger_pmos_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/03_ptx_3finger_nmos_test.py b/compiler/tests/03_ptx_3finger_nmos_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/03_ptx_3finger_pmos_test.py b/compiler/tests/03_ptx_3finger_pmos_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/03_ptx_4finger_nmos_test.py b/compiler/tests/03_ptx_4finger_nmos_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/03_ptx_4finger_pmos_test.py b/compiler/tests/03_ptx_4finger_pmos_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/03_wire_test.py b/compiler/tests/03_wire_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/04_pinv_10x_test.py b/compiler/tests/04_pinv_10x_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/04_pinv_1x_beta_test.py b/compiler/tests/04_pinv_1x_beta_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/04_pinv_1x_test.py b/compiler/tests/04_pinv_1x_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/04_pinv_2x_test.py b/compiler/tests/04_pinv_2x_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/04_pinvbuf_test.py b/compiler/tests/04_pinvbuf_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/04_pnand2_test.py b/compiler/tests/04_pnand2_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/04_pnand3_test.py b/compiler/tests/04_pnand3_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/04_pnor2_test.py b/compiler/tests/04_pnor2_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/04_precharge_test.py b/compiler/tests/04_precharge_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/04_single_level_column_mux_test.py b/compiler/tests/04_single_level_column_mux_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/05_bitcell_array_test.py b/compiler/tests/05_bitcell_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/06_hierarchical_decoder_test.py b/compiler/tests/06_hierarchical_decoder_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/06_hierarchical_predecode2x4_test.py b/compiler/tests/06_hierarchical_predecode2x4_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/06_hierarchical_predecode3x8_test.py b/compiler/tests/06_hierarchical_predecode3x8_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/07_single_level_column_mux_array_test.py b/compiler/tests/07_single_level_column_mux_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/08_precharge_array_test.py b/compiler/tests/08_precharge_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/08_wordline_driver_test.py b/compiler/tests/08_wordline_driver_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/09_sense_amp_array_test.py b/compiler/tests/09_sense_amp_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/10_write_driver_array_test.py b/compiler/tests/10_write_driver_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/11_dff_array_test.py b/compiler/tests/11_dff_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/11_dff_buf_array_test.py b/compiler/tests/11_dff_buf_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/11_dff_buf_test.py b/compiler/tests/11_dff_buf_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/11_dff_inv_array_test.py b/compiler/tests/11_dff_inv_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/11_dff_inv_test.py b/compiler/tests/11_dff_inv_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/11_ms_flop_array_test.py b/compiler/tests/11_ms_flop_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/12_tri_gate_array_test.py b/compiler/tests/12_tri_gate_array_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/13_delay_chain_test.py b/compiler/tests/13_delay_chain_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/14_replica_bitline_test.py b/compiler/tests/14_replica_bitline_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/19_bank_select_test.py b/compiler/tests/19_bank_select_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/19_multi_bank_test.py b/compiler/tests/19_multi_bank_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/19_single_bank_test.py b/compiler/tests/19_single_bank_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/20_sram_1bank_test.py b/compiler/tests/20_sram_1bank_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/20_sram_2bank_test.py b/compiler/tests/20_sram_2bank_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/20_sram_4bank_test.py b/compiler/tests/20_sram_4bank_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/21_hspice_setuphold_test.py b/compiler/tests/21_hspice_setuphold_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/21_ngspice_setuphold_test.py b/compiler/tests/21_ngspice_setuphold_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/22_sram_func_test.py b/compiler/tests/22_sram_func_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/23_lib_sram_model_test.py b/compiler/tests/23_lib_sram_model_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/23_lib_sram_prune_test.py b/compiler/tests/23_lib_sram_prune_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/23_lib_sram_test.py b/compiler/tests/23_lib_sram_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/24_lef_sram_test.py b/compiler/tests/24_lef_sram_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/25_verilog_sram_test.py b/compiler/tests/25_verilog_sram_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/30_openram_test.py b/compiler/tests/30_openram_test.py old mode 100644 new mode 100755 diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py old mode 100644 new mode 100755 From b3dc6560f58a7e1adaca12b9b81b3a8fe6ce7d96 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 09:10:12 -0700 Subject: [PATCH 02/25] Remove regress.sh script --- compiler/regress.sh | 3 --- 1 file changed, 3 deletions(-) delete mode 100755 compiler/regress.sh diff --git a/compiler/regress.sh b/compiler/regress.sh deleted file mode 100755 index 904ef9d8..00000000 --- a/compiler/regress.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -python tests/regress.py -t freepdk45 -python tests/regress.py -t scn3me_subm From a9a95ebf7c4e914acc625e16a51b9d5fd0d51e85 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 09:11:14 -0700 Subject: [PATCH 03/25] Fix pex test permissions --- compiler/tests/22_pex_test.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 compiler/tests/22_pex_test.py diff --git a/compiler/tests/22_pex_test.py b/compiler/tests/22_pex_test.py old mode 100644 new mode 100755 From af84742c1933060116e6e738783d9d1067eac8f5 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 09:57:57 -0700 Subject: [PATCH 04/25] Simplify m2 pitch calculation --- compiler/modules/hierarchical_decoder.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 179cc936..68712e36 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -60,7 +60,6 @@ class hierarchical_decoder(design.design): def add_decoders(self): """ Create the decoders based on the number of pre-decodes """ - # FIXME: Only add these if needed? self.pre2_4 = pre2x4() self.add_mod(self.pre2_4) @@ -68,8 +67,8 @@ class hierarchical_decoder(design.design): self.add_mod(self.pre3_8) def determine_predecodes(self,num_inputs): - """Determines the number of 2:4 pre-decoder and 3:8 pre-decoder - needed based on the number of inputs""" + """ Determines the number of 2:4 pre-decoder and 3:8 pre-decoder + needed based on the number of inputs """ if (num_inputs == 2): return (1,0) elif (num_inputs == 3): @@ -90,11 +89,7 @@ class hierarchical_decoder(design.design): debug.error("Invalid number of inputs for hierarchical decoder",-1) def setup_layout_constants(self): - # Vertical metal rail gap definition - self.metal2_extend_contact = (contact.m1m2.second_layer_height - contact.m1m2.contact_width) / 2 - self.metal2_spacing = self.metal2_extend_contact + self.m2_space - self.metal2_pitch = self.metal2_spacing + self.m2_width - self.via_shift = (contact.m1m2.second_layer_width - contact.m1m2.first_layer_width) / 2 + self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space) self.predec_groups = [] # This array is a 2D array. @@ -143,10 +138,11 @@ class hierarchical_decoder(design.design): debug.error("Not enough rows for a hierarchical decoder. Non-hierarchical not supported yet.",-1) # Calculates height and width of pre-decoder, - if(self.no_of_pre3x8 > 0): + if self.no_of_pre3x8 > 0: self.predecoder_width = self.pre3_8.width else: self.predecoder_width = self.pre2_4.width + self.predecoder_height = self.pre2_4.height*self.no_of_pre2x4 + self.pre3_8.height*self.no_of_pre3x8 # Calculates height and width of row-decoder @@ -154,7 +150,7 @@ class hierarchical_decoder(design.design): nand_width = self.nand2.width else: nand_width = self.nand3.width - self.routing_width = self.metal2_pitch*self.total_number_of_predecoder_outputs + self.routing_width = self.m2_pitch*self.total_number_of_predecoder_outputs self.row_decoder_height = self.inv.height * self.rows # Calculates height and width of hierarchical decoder @@ -171,7 +167,7 @@ class hierarchical_decoder(design.design): self.add_pre3x8(i) def add_pre2x4(self,num): - """ Add a 2x4 predecoder """ + """ Add a 2x4 predecoder to the left of the origin """ if (self.num_inputs == 2): base = vector(-self.pre2_4.width,0) @@ -195,7 +191,6 @@ class hierarchical_decoder(design.design): self.add_pre2x4_pins(num) - def add_pre2x4_pins(self,num): """ Add the input pins to the 2x4 predecoder """ @@ -213,7 +208,7 @@ class hierarchical_decoder(design.design): def add_pre3x8(self,num): - """ Add 3x8 numbered predecoder """ + """ Add 3x8 predecoder to the left of the origin and above any 2x4 decoders """ if (self.num_inputs == 3): offset = vector(-self.pre_3_8.width,0) mirror ="R0" @@ -388,7 +383,7 @@ class hierarchical_decoder(design.design): for i in range(self.total_number_of_predecoder_outputs): # The offsets go into the negative x direction # assuming the predecodes are placed at (self.routing_width,0) - x_offset = self.metal2_pitch * i + x_offset = self.m2_pitch * i self.rail_x_offsets.append(x_offset+0.5*self.m2_width) self.add_rect(layer="metal2", offset=vector(x_offset,0), From e60d1573104326e25b2963220b3b2a498e8d5e53 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 13:16:38 -0700 Subject: [PATCH 05/25] Add input pin rails to hierarchical decoder for easier connections at SRAM level. --- compiler/modules/hierarchical_decoder.py | 125 +++++++++++++++-------- 1 file changed, 83 insertions(+), 42 deletions(-) diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 68712e36..557e4af6 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -45,7 +45,8 @@ class hierarchical_decoder(design.design): self.add_pins() self.create_pre_decoder() self.create_row_decoder() - self.create_vertical_rail() + self.create_input_rail() + self.create_predecode_rail() self.route_vdd_gnd() def add_modules(self): @@ -89,6 +90,7 @@ class hierarchical_decoder(design.design): debug.error("Invalid number of inputs for hierarchical decoder",-1) def setup_layout_constants(self): + self.m1_pitch = contact.m1m2.height + max(self.m1_space,self.m2_space) self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space) self.predec_groups = [] # This array is a 2D array. @@ -115,7 +117,77 @@ class hierarchical_decoder(design.design): self.calculate_dimensions() + def create_input_rail(self): + """ Create input rails for the predecoders """ + # input bus width plus a spacing track + input_width = (self.num_inputs+1) * self.m2_pitch + # inputs should be as high as the decoders + input_height = self.no_of_pre2x4*self.pre2_4.height + self.no_of_pre2x4*self.pre3_8.height + + # Find the left-most predecoder + min_x = 0 + if self.no_of_pre2x4 > 0: + min_x = min(min_x, -self.pre2_4.width) + if self.no_of_pre3x8 > 0: + min_x = min(min_x, -self.pre3_8.width) + for i in range(self.num_inputs): + x_offset = min_x - input_width + i*self.m2_pitch + pin_offset = vector(x_offset,0) + self.add_layout_pin(text="A[{0}]".format(i), + layer="metal2", + offset=vector(x_offset,0), + height=input_height) + + self.connect_input_to_predecodes() + + + def connect_input_to_predecodes(self): + """ Connect the vertical input rail to the predecoders """ + for pre_num in range(self.no_of_pre2x4): + for i in range(2): + index = pre_num * 2 + i + + input_pin = self.get_pin("A[{}]".format(index)) + + in_name = "in[{}]".format(i) + decoder_pin = self.pre2x4_inst[pre_num].get_pin(in_name) + + # Offset each decoder pin up so they don't conflit + decoder_offset = decoder_pin.center() + vector(0,i*self.m2_pitch) + input_offset = input_pin.center().scale(1,0) + decoder_offset.scale(0,1) + + self.connect_input_rail(decoder_offset, input_offset) + + + for pre_num in range(self.no_of_pre3x8): + for i in range(3): + index = pre_num * 3 + i + self.no_of_pre2x4 * 2 + + input_pin = self.get_pin("A[{}]".format(index)) + + in_name = "in[{}]".format(i) + decoder_pin = self.pre3x8_inst[pre_num].get_pin(in_name) + + # Offset each decoder pin up so they don't conflit + decoder_offset = decoder_pin.center() + vector(0,i*self.m2_pitch) + input_offset = input_pin.center().scale(1,0) + decoder_offset.scale(0,1) + + self.connect_input_rail(decoder_offset, input_offset) + + + def connect_input_rail(self, input_offset, output_offset): + """ Connect a vertical M2 coordinate to another vertical M2 coordinate to the predecode inputs """ + + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=input_offset, + rotate=90) + self.add_via_center(layers=("metal2", "via2", "metal3"), + offset=output_offset, + rotate=90) + self.add_path(("metal3"), [input_offset, output_offset]) + + def add_pins(self): """ Add the module pins """ @@ -189,23 +261,6 @@ class hierarchical_decoder(design.design): offset=base)) self.connect_inst(pins) - self.add_pre2x4_pins(num) - - - def add_pre2x4_pins(self,num): - """ Add the input pins to the 2x4 predecoder """ - - for i in range(2): - pin = self.pre2x4_inst[num].get_pin("in[{}]".format(i)) - pin_offset = pin.ll() - - pin = self.pre2_4.get_pin("in[{}]".format(i)) - self.add_layout_pin(text="A[{0}]".format(i + 2*num ), - layer="metal2", - offset=pin_offset, - width=pin.width(), - height=pin.height()) - def add_pre3x8(self,num): """ Add 3x8 predecoder to the left of the origin and above any 2x4 decoders """ @@ -233,20 +288,6 @@ class hierarchical_decoder(design.design): offset=offset)) self.connect_inst(pins) - # The 3x8 predecoders will be stacked, so use yoffset - self.add_pre3x8_pins(num,offset) - - def add_pre3x8_pins(self,num,offset): - """ Add the input pins to the 3x8 predecoder at the given offset """ - - for i in range(3): - pin = self.pre3x8_inst[num].get_pin("in[{}]".format(i)) - pin_offset = pin.ll() - self.add_layout_pin(text="A[{0}]".format(i + 3*num + 2*self.no_of_pre2x4), - layer="metal2", - offset=pin_offset, - width=pin.width(), - height=pin.height()) @@ -372,7 +413,7 @@ class hierarchical_decoder(design.design): - def create_vertical_rail(self): + def create_predecode_rail(self): """ Creates vertical metal 2 rails to connect predecoder and decoder stages.""" # This is not needed for inputs <4 since they have no pre/decode stages. @@ -401,7 +442,7 @@ class hierarchical_decoder(design.design): index = pre_num * 4 + i out_name = "out[{}]".format(i) pin = self.pre2x4_inst[pre_num].get_pin(out_name) - self.connect_rail_m3(index, pin) + self.connect_predecode_rail_m3(index, pin) for pre_num in range(self.no_of_pre3x8): @@ -409,7 +450,7 @@ class hierarchical_decoder(design.design): index = pre_num * 8 + i + self.no_of_pre2x4 * 4 out_name = "out[{}]".format(i) pin = self.pre3x8_inst[pre_num].get_pin(out_name) - self.connect_rail_m3(index, pin) + self.connect_predecode_rail_m3(index, pin) @@ -425,17 +466,17 @@ class hierarchical_decoder(design.design): if (self.num_inputs == 4 or self.num_inputs == 5): for index_A in self.predec_groups[0]: for index_B in self.predec_groups[1]: - self.connect_rail(index_A, self.nand_inst[row_index].get_pin("A")) - self.connect_rail(index_B, self.nand_inst[row_index].get_pin("B")) + self.connect_predecode_rail(index_A, self.nand_inst[row_index].get_pin("A")) + self.connect_predecode_rail(index_B, self.nand_inst[row_index].get_pin("B")) row_index = row_index + 1 elif (self.num_inputs > 5): for index_A in self.predec_groups[0]: for index_B in self.predec_groups[1]: for index_C in self.predec_groups[2]: - self.connect_rail(index_A, self.nand_inst[row_index].get_pin("A")) - self.connect_rail(index_B, self.nand_inst[row_index].get_pin("B")) - self.connect_rail(index_C, self.nand_inst[row_index].get_pin("C")) + self.connect_predecode_rail(index_A, self.nand_inst[row_index].get_pin("A")) + self.connect_predecode_rail(index_B, self.nand_inst[row_index].get_pin("B")) + self.connect_predecode_rail(index_C, self.nand_inst[row_index].get_pin("C")) row_index = row_index + 1 def route_vdd_gnd(self): @@ -471,7 +512,7 @@ class hierarchical_decoder(design.design): self.copy_layout_pin(pre, "gnd") - def connect_rail(self, rail_index, pin): + def connect_predecode_rail(self, rail_index, pin): """ Connect the routing rail to the given metal1 pin """ rail_pos = vector(self.rail_x_offsets[rail_index],pin.lc().y) self.add_path("metal1", [rail_pos, pin.lc()]) @@ -480,7 +521,7 @@ class hierarchical_decoder(design.design): rotate=90) - def connect_rail_m3(self, rail_index, pin): + def connect_predecode_rail_m3(self, rail_index, pin): """ Connect the routing rail to the given metal1 pin """ mid_point = vector(pin.cx(), pin.cy()+self.inv.height/2) rail_pos = vector(self.rail_x_offsets[rail_index],mid_point.y) From 2e5d60ae87c02dd5ae9cfa671fb8f9220dcd4e41 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 14:45:27 -0700 Subject: [PATCH 06/25] Fix input height error for input rail pins --- compiler/modules/hierarchical_decoder.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 557e4af6..0398b9a6 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -122,7 +122,7 @@ class hierarchical_decoder(design.design): # input bus width plus a spacing track input_width = (self.num_inputs+1) * self.m2_pitch # inputs should be as high as the decoders - input_height = self.no_of_pre2x4*self.pre2_4.height + self.no_of_pre2x4*self.pre3_8.height + input_height = self.no_of_pre2x4*self.pre2_4.height + self.no_of_pre3x8*self.pre3_8.height # Find the left-most predecoder min_x = 0 @@ -137,6 +137,7 @@ class hierarchical_decoder(design.design): self.add_layout_pin(text="A[{0}]".format(i), layer="metal2", offset=vector(x_offset,0), + width=self.m2_width, height=input_height) self.connect_input_to_predecodes() From 94db2052dd2376da1f26a2f36d00e7721c788e22 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 15:42:46 -0700 Subject: [PATCH 07/25] Consolidate metal pitch rules to new design class --- compiler/base/contact.py | 7 ++-- .../base/{design.py => hierarchy_design.py} | 34 ++----------------- compiler/modules/bank.py | 4 --- compiler/modules/bank_select.py | 4 --- compiler/modules/control_logic.py | 4 --- compiler/modules/hierarchical_decoder.py | 3 -- compiler/modules/hierarchical_predecode.py | 4 --- compiler/modules/replica_bitline.py | 5 --- .../modules/single_level_column_mux_array.py | 1 - compiler/sram.py | 6 ---- 10 files changed, 7 insertions(+), 65 deletions(-) rename compiler/base/{design.py => hierarchy_design.py} (70%) diff --git a/compiler/base/contact.py b/compiler/base/contact.py index c3fa810d..2aa3ada5 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -1,11 +1,11 @@ -import design +import hierarchy_design import debug import utils from tech import drc from vector import vector -class contact(design.design): +class contact(hierarchy_design.hierarchy_design): """ Object for a contact shape with its conductor enclosures. Creates a contact array minimum active or poly enclosure and metal1 enclosure. @@ -31,7 +31,7 @@ class contact(design.design): dimensions[0], dimensions[1]) - design.design.__init__(self, name) + hierarchy_design.hierarchy_design.__init__(self, name) debug.info(4, "create contact object {0}".format(name)) self.layer_stack = layer_stack @@ -167,4 +167,5 @@ active = contact(layer_stack=("active", "contact", "poly")) poly = contact(layer_stack=("poly", "contact", "metal1")) m1m2 = contact(layer_stack=("metal1", "via1", "metal2")) m2m3 = contact(layer_stack=("metal2", "via2", "metal3")) +#m3m4 = contact(layer_stack=("metal3", "via3", "metal4")) diff --git a/compiler/base/design.py b/compiler/base/hierarchy_design.py similarity index 70% rename from compiler/base/design.py rename to compiler/base/hierarchy_design.py index 794bb79a..2af96f7d 100644 --- a/compiler/base/design.py +++ b/compiler/base/hierarchy_design.py @@ -7,7 +7,7 @@ import os from globals import OPTS -class design(hierarchy_spice.spice, hierarchy_layout.layout): +class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): """ Design Class for all modules to inherit the base features. Class consisting of a set of modules and instances of these modules @@ -23,7 +23,6 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout): hierarchy_layout.layout.__init__(self, name) hierarchy_spice.spice.__init__(self, name) - self.setup_drc_constants() # Check if the name already exists, if so, give an error # because each reference must be a unique name. @@ -38,8 +37,8 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout): 'sram', 'hierarchical_predecode2x4', 'hierarchical_predecode3x8'] - if name not in design.name_map: - design.name_map.append(name) + if name not in hierarchy_design.name_map: + hierarchy_design.name_map.append(name) else: for ok_names in ok_list: if ok_names in self.__class__.__name__: @@ -47,27 +46,6 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout): else: debug.error("Duplicate layout reference name {0} of class {1}. GDS2 requires names be unique.".format(name,self.__class__),-1) - def setup_drc_constants(self): - """ These are some DRC constants used in many places in the compiler.""" - from tech import drc - self.well_width = drc["minwidth_well"] - self.poly_width = drc["minwidth_poly"] - self.poly_space = drc["poly_to_poly"] - self.m1_width = drc["minwidth_metal1"] - self.m1_space = drc["metal1_to_metal1"] - self.m2_width = drc["minwidth_metal2"] - self.m2_space = drc["metal2_to_metal2"] - self.m3_width = drc["minwidth_metal3"] - self.m3_space = drc["metal3_to_metal3"] - self.active_width = drc["minwidth_active"] - self.contact_width = drc["minwidth_contact"] - - self.poly_to_active = drc["poly_to_active"] - self.poly_extend_active = drc["poly_extend_active"] - self.contact_to_gate = drc["contact_to_gate"] - self.well_enclose_active = drc["well_enclosure_active"] - self.implant_enclose_active = drc["implant_enclosure_active"] - self.implant_space = drc["implant_to_implant"] def get_layout_pins(self,inst): """ Return a map of pin locations of the instance offset """ @@ -125,9 +103,3 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout): 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 diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 3ed6c222..db58441a 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -161,10 +161,6 @@ class bank(design.design): else: self.num_col_addr_lines = 0 - # M1/M2 routing pitch is based on contacted pitch - self.m1_pitch = contact.m1m2.height + max(self.m1_space,self.m2_space) - self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space) - # The width of this bus is needed to place other modules (e.g. decoder) # A width on each side too self.central_bus_width = self.m2_pitch * self.num_control_lines + 2*self.m2_width diff --git a/compiler/modules/bank_select.py b/compiler/modules/bank_select.py index d0b3070a..2abfb3c6 100644 --- a/compiler/modules/bank_select.py +++ b/compiler/modules/bank_select.py @@ -56,10 +56,6 @@ class bank_select(design.design): def calculate_module_offsets(self): - # M1/M2 routing pitch is based on contacted pitch - self.m1_pitch = contact.m1m2.height + max(self.m1_space,self.m2_space) - self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space) - self.xoffset_nand = self.inv4x.width + 2*self.m2_pitch + drc["pwell_to_nwell"] self.xoffset_nor = self.inv4x.width + 2*self.m2_pitch + drc["pwell_to_nwell"] self.xoffset_inv = max(self.xoffset_nand + self.nand2.width, self.xoffset_nor + self.nor2.width) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 33501158..8526cb43 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -86,10 +86,6 @@ class control_logic(design.design): # These aren't for instantiating, but we use them to get the dimensions #self.poly_contact_offset = vector(0.5*contact.poly.width,0.5*contact.poly.height) - # M1/M2 routing pitch is based on contacted pitch - self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(drc["metal1_to_metal1"],drc["metal2_to_metal2"]) - self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(drc["metal2_to_metal2"],drc["metal3_to_metal3"]) - # Have the cell gap leave enough room to route an M2 wire. # Some cells may have pwell/nwell spacing problems too when the wells are different heights. #self.cell_gap = max(self.m2_pitch,drc["pwell_to_nwell"]) diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 0398b9a6..375201eb 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -90,9 +90,6 @@ class hierarchical_decoder(design.design): debug.error("Invalid number of inputs for hierarchical decoder",-1) def setup_layout_constants(self): - self.m1_pitch = contact.m1m2.height + max(self.m1_space,self.m2_space) - self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space) - self.predec_groups = [] # This array is a 2D array. # Distributing vertical rails to different groups. One group belongs to one pre-decoder. diff --git a/compiler/modules/hierarchical_predecode.py b/compiler/modules/hierarchical_predecode.py index e0d05d92..d111b02b 100644 --- a/compiler/modules/hierarchical_predecode.py +++ b/compiler/modules/hierarchical_predecode.py @@ -50,10 +50,6 @@ class hierarchical_predecode(design.design): debug.error("Invalid number of predecode inputs.",-1) def setup_constraints(self): - # use a conservative douple spacing just to get rid of annoying via DRCs - self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space, self.m2_space) - self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space,self.m3_space) - # The rail offsets are indexed by the label self.rails = {} diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index 8d1d6242..f4c8995f 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -53,11 +53,6 @@ class replica_bitline(design.design): # These aren't for instantiating, but we use them to get the dimensions self.poly_contact_offset = vector(0.5*contact.poly.width,0.5*contact.poly.height) - # M1/M2 routing pitch is based on contacted pitch - self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space,self.m2_space) - self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space,self.m3_space) - - # Quadrant 1: Replica bitline and such are not rotated, but they must be placed far enough # away from the delay chain/inverter with space for three M2 tracks self.bitcell_offset = vector(0,self.replica_bitcell.height) diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index 31614ae1..777958a5 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -57,7 +57,6 @@ class single_level_column_mux_array(design.design): def setup_layout_constants(self): self.column_addr_size = num_of_inputs = int(self.words_per_row / 2) self.width = self.columns * self.mux.width - self.m1_pitch = contact.m1m2.width + max(drc["metal1_to_metal1"],drc["metal2_to_metal2"]) # one set of metal1 routes for select signals and a pair to interconnect the mux outputs bl/br # one extra route pitch is to space from the sense amp self.route_height = (self.words_per_row + 3)*self.m1_pitch diff --git a/compiler/sram.py b/compiler/sram.py index 0c144fb7..a8689742 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -48,12 +48,6 @@ class sram(design.design): design.design.__init__(self, name) - # M1/M2 routing pitch is based on contacted pitch of the biggest layer - self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space,self.m2_space) - self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space,self.m3_space) - self.m3_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space,self.m3_space) - - self.control_size = 6 self.bank_to_bus_distance = 5*self.m3_width From 9d5e5086a148289b18a4cf13df635a8ffccb709b Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 15:43:26 -0700 Subject: [PATCH 08/25] Add new extra design class with additional hierarchy for shared design rules --- compiler/base/design.py | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 compiler/base/design.py diff --git a/compiler/base/design.py b/compiler/base/design.py new file mode 100644 index 00000000..750eebd1 --- /dev/null +++ b/compiler/base/design.py @@ -0,0 +1,55 @@ +import hierarchy_design +import contact +import globals +import verify +import debug +import os +from globals import OPTS + + +class design(hierarchy_design.hierarchy_design): + """ + This is the same as the hierarchy_design class except it contains + some DRC constants and analytical models for other modules to reuse. + + """ + + def __init__(self, name): + hierarchy_design.hierarchy_design.__init__(self,name) + + self.setup_drc_constants() + + self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(self.m1_space, self.m2_space) + self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(self.m2_space, self.m3_space) + # SCMOS doesn't have m4... + #self.m3_pitch = max(contact.m3m4.width,contact.m3m4.height) + max(self.m3_space, self.m4_space) + self.m3_pitch = self.m2_pitch + + def setup_drc_constants(self): + """ These are some DRC constants used in many places in the compiler.""" + from tech import drc + self.well_width = drc["minwidth_well"] + self.poly_width = drc["minwidth_poly"] + self.poly_space = drc["poly_to_poly"] + self.m1_width = drc["minwidth_metal1"] + self.m1_space = drc["metal1_to_metal1"] + self.m2_width = drc["minwidth_metal2"] + self.m2_space = drc["metal2_to_metal2"] + self.m3_width = drc["minwidth_metal3"] + self.m3_space = drc["metal3_to_metal3"] + self.active_width = drc["minwidth_active"] + self.contact_width = drc["minwidth_contact"] + + self.poly_to_active = drc["poly_to_active"] + self.poly_extend_active = drc["poly_extend_active"] + self.contact_to_gate = drc["contact_to_gate"] + self.well_enclose_active = drc["well_enclosure_active"] + self.implant_enclose_active = drc["implant_enclosure_active"] + self.implant_space = drc["implant_to_implant"] + + 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 From 7bf271fd631fab3dd4c9e3802db3d86dbc94d9ce Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 15:52:07 -0700 Subject: [PATCH 09/25] Skip pex and functional tests which are not working. --- compiler/tests/22_pex_test.py | 2 +- compiler/tests/22_sram_func_test.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/tests/22_pex_test.py b/compiler/tests/22_pex_test.py index fbde5145..3e146ba8 100755 --- a/compiler/tests/22_pex_test.py +++ b/compiler/tests/22_pex_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 22_sram_func_test") +@unittest.skip("SKIPPING 22_sram_pex_test") class sram_func_test(openram_test): def runTest(self): diff --git a/compiler/tests/22_sram_func_test.py b/compiler/tests/22_sram_func_test.py index 63b8bdd2..eedb0805 100755 --- a/compiler/tests/22_sram_func_test.py +++ b/compiler/tests/22_sram_func_test.py @@ -11,6 +11,7 @@ import globals from globals import OPTS import debug +@unittest.skip("SKIPPING 22_sram_func_test") class sram_func_test(openram_test): def runTest(self): From bbc98097ac2b5a8ad6e585aa2cba047b5bf8ba1c Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 15:53:37 -0700 Subject: [PATCH 10/25] Add getpass include to unit test 30 --- compiler/tests/30_openram_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/tests/30_openram_test.py b/compiler/tests/30_openram_test.py index 02fa4759..df480fdc 100755 --- a/compiler/tests/30_openram_test.py +++ b/compiler/tests/30_openram_test.py @@ -12,6 +12,7 @@ sys.path.append(os.path.join(sys.path[0],"..")) import globals from globals import OPTS import debug +import getpass class openram_test(openram_test): From f234e43241efe51e65c1d20e0303e6c123bbb44f Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 16:07:30 -0700 Subject: [PATCH 11/25] Reset new hierarchy_design instead of design for duplicate GDS name checker --- compiler/tests/testutils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index caef7211..4219d4e5 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -55,8 +55,8 @@ class openram_test(unittest.TestCase): def reset(self): """ Reset the static duplicate name checker for unit tests """ - import design - design.design.name_map=[] + import hierarchy_design + hierarchy_design.hierarchy_design.name_map=[] def isclose(self, value1,value2,error_tolerance=1e-2): """ This is used to compare relative values. """ From 019512bc25e2153859529ffc7c5bad6be45dd652 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 9 Jul 2018 16:07:53 -0700 Subject: [PATCH 12/25] Fix python3 module reference in functional test --- compiler/tests/22_sram_func_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/22_sram_func_test.py b/compiler/tests/22_sram_func_test.py index eedb0805..f9045f1a 100755 --- a/compiler/tests/22_sram_func_test.py +++ b/compiler/tests/22_sram_func_test.py @@ -46,7 +46,7 @@ class sram_func_test(openram_test): debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data)) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) - d = delay.delay(s,tempspice,corner) + d = delay(s,tempspice,corner) d.set_probe(probe_address,probe_data) # This will exit if it doesn't find a feasible period From 98f1914e9ff3bb8d360058a8ffb1b499e5db555e Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 10 Jul 2018 09:31:41 -0700 Subject: [PATCH 13/25] Fix width of decoder with new input bus. Bank tests work again. --- compiler/modules/hierarchical_decoder.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 375201eb..1705c192 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -116,8 +116,6 @@ class hierarchical_decoder(design.design): def create_input_rail(self): """ Create input rails for the predecoders """ - # input bus width plus a spacing track - input_width = (self.num_inputs+1) * self.m2_pitch # inputs should be as high as the decoders input_height = self.no_of_pre2x4*self.pre2_4.height + self.no_of_pre3x8*self.pre3_8.height @@ -129,7 +127,7 @@ class hierarchical_decoder(design.design): min_x = min(min_x, -self.pre3_8.width) for i in range(self.num_inputs): - x_offset = min_x - input_width + i*self.m2_pitch + x_offset = min_x - self.input_routing_width + i*self.m2_pitch pin_offset = vector(x_offset,0) self.add_layout_pin(text="A[{0}]".format(i), layer="metal2", @@ -220,12 +218,14 @@ class hierarchical_decoder(design.design): nand_width = self.nand2.width else: nand_width = self.nand3.width - self.routing_width = self.m2_pitch*self.total_number_of_predecoder_outputs + self.internal_routing_width = self.m2_pitch*self.total_number_of_predecoder_outputs self.row_decoder_height = self.inv.height * self.rows + self.input_routing_width = (self.num_inputs+1) * self.m2_pitch # Calculates height and width of hierarchical decoder self.height = self.row_decoder_height - self.width = self.predecoder_width + self.routing_width + nand_width + self.inv.width + self.width = self.input_routing_width + self.predecoder_width \ + + self.internal_routing_width + nand_width + self.inv.width def create_pre_decoder(self): """ Creates pre-decoder and places labels input address [A] """ @@ -347,7 +347,7 @@ class hierarchical_decoder(design.design): self.nand_inst.append(self.add_inst(name=name, mod=nand_mod, - offset=[self.routing_width, y_off], + offset=[self.internal_routing_width, y_off], mirror=mirror)) @@ -359,9 +359,9 @@ class hierarchical_decoder(design.design): z_pin = self.inv.get_pin("Z") if (self.num_inputs == 4 or self.num_inputs == 5): - x_off = self.routing_width + self.nand2.width + x_off = self.internal_routing_width + self.nand2.width else: - x_off = self.routing_width + self.nand3.width + x_off = self.internal_routing_width + self.nand3.width self.inv_inst = [] for row in range(self.rows): @@ -421,7 +421,7 @@ class hierarchical_decoder(design.design): self.rail_x_offsets = [] for i in range(self.total_number_of_predecoder_outputs): # The offsets go into the negative x direction - # assuming the predecodes are placed at (self.routing_width,0) + # assuming the predecodes are placed at (self.internal_routing_width,0) x_offset = self.m2_pitch * i self.rail_x_offsets.append(x_offset+0.5*self.m2_width) self.add_rect(layer="metal2", From 25cf57ede50c5f6f4442d907cc1d94e43cb80d1b Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 10 Jul 2018 10:06:59 -0700 Subject: [PATCH 14/25] Push create bus functions down into layout class. --- compiler/base/hierarchy_layout.py | 56 +++++++++ compiler/modules/hierarchical_decoder.py | 17 ++- compiler/sram.py | 140 ++++++++--------------- 3 files changed, 114 insertions(+), 99 deletions(-) diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index 010680d6..58a3d1fe 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -524,6 +524,62 @@ class layout(lef.lef): return blockages + def create_horizontal_pin_bus(self, layer, pitch, offset, names, length): + """ Create a horizontal bus of pins. """ + self.create_bus(layer,pitch,offset,names,length,vertical=False,make_pins=True) + + def create_vertical_pin_bus(self, layer, pitch, offset, names, length): + """ Create a horizontal bus of pins. """ + self.create_bus(layer,pitch,offset,names,length,vertical=True,make_pins=True) + + def create_vertical_bus(self, layer, pitch, offset, names, length): + """ Create a horizontal bus. """ + self.create_bus(layer,pitch,offset,names,length,vertical=True,make_pins=False) + + def create_horiontal_bus(self, layer, pitch, offset, names, length): + """ Create a horizontal bus. """ + self.create_bus(layer,pitch,offset,names,length,vertical=False,make_pins=False) + + + def create_bus(self, layer, pitch, offset, names, length, vertical, make_pins): + """ + Create a horizontal or vertical bus. It can be either just rectangles, or actual + layout pins. It returns an map of line center line positions indexed by name. + """ + + # half minwidth so we can return the center line offsets + half_minwidth = 0.5*drc["minwidth_{}".format(layer)] + + line_positions = {} + if vertical: + for i in range(len(names)): + line_offset = offset + vector(i*pitch,0) + if make_pins: + self.add_layout_pin(text=names[i], + layer=layer, + offset=line_offset, + height=length) + else: + self.add_rect(layer=layer, + offset=line_offset, + height=length) + line_positions[names[i]]=line_offset+vector(half_minwidth,0) + else: + for i in range(len(names)): + line_offset = offset + vector(0,i*pitch + half_minwidth) + if make_pins: + self.add_layout_pin(text=names[i], + layer=layer, + offset=line_offset, + width=length) + else: + self.add_rect(layer=layer, + offset=line_offset, + width=length) + line_positions[names[i]]=line_offset+vector(0,half_minwidth) + + return line_positions + def add_enclosure(self, insts, layer="nwell"): """ Add a layer that surrounds the given instances. Useful for creating wells, for example. Doesn't check for minimum widths or diff --git a/compiler/modules/hierarchical_decoder.py b/compiler/modules/hierarchical_decoder.py index 1705c192..5742cc6c 100644 --- a/compiler/modules/hierarchical_decoder.py +++ b/compiler/modules/hierarchical_decoder.py @@ -125,16 +125,15 @@ class hierarchical_decoder(design.design): min_x = min(min_x, -self.pre2_4.width) if self.no_of_pre3x8 > 0: min_x = min(min_x, -self.pre3_8.width) - - for i in range(self.num_inputs): - x_offset = min_x - self.input_routing_width + i*self.m2_pitch - pin_offset = vector(x_offset,0) - self.add_layout_pin(text="A[{0}]".format(i), - layer="metal2", - offset=vector(x_offset,0), - width=self.m2_width, - height=input_height) + input_offset=vector(min_x - self.input_routing_width,0) + input_bus_names = ["A[{0}]".format(i) for i in range(self.num_inputs)] + self.create_vertical_pin_bus(layer="metal2", + pitch=self.m2_pitch, + offset=input_offset, + names=input_bus_names, + length=input_height) + self.connect_input_to_predecodes() diff --git a/compiler/sram.py b/compiler/sram.py index a8689742..e2ffa1fc 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -103,8 +103,10 @@ class sram(design.design): debug.info(1,"Words per row: {}".format(self.words_per_row)) def estimate_words_per_row(self,tentative_num_cols, word_size): - """This provides a heuristic rounded estimate for the number of words - per row.""" + """ + This provides a heuristic rounded estimate for the number of words + per row. + """ if tentative_num_cols < 1.5*word_size: return 1 @@ -114,7 +116,8 @@ class sram(design.design): return 2 def amend_words_per_row(self,tentative_num_rows, words_per_row): - """This picks the number of words per row more accurately by limiting + """ + This picks the number of words per row more accurately by limiting it to a minimum and maximum. """ # Recompute the words per row given a hard max @@ -319,7 +322,8 @@ class sram(design.design): self.supply_bus_width = self.data_bus_width # Sanity check to ensure we can fit the control logic above a single bank (0.9 is a hack really) - debug.check(self.bank.width + self.vertical_bus_width > 0.9*self.control_logic.width, "Bank is too small compared to control logic.") + debug.check(self.bank.width + self.vertical_bus_width > 0.9*self.control_logic.width, + "Bank is too small compared to control logic.") def compute_four_bank_offsets(self): @@ -336,7 +340,8 @@ class sram(design.design): self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 0) self.data_bus_offset = vector(0, self.bank.height + self.bank_to_bus_distance) - self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height + self.bank.height + 2*self.bank_to_bus_distance) + self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height \ + + self.bank.height + 2*self.bank_to_bus_distance) self.control_bus_offset = vector(0, self.supply_bus_offset.y + self.supply_bus_height) self.bank_sel_bus_offset = self.vertical_bus_offset + vector(self.m2_pitch*self.control_size,0) self.addr_bus_offset = self.bank_sel_bus_offset.scale(1,0) + vector(self.m2_pitch*self.num_banks,0) @@ -347,7 +352,8 @@ class sram(design.design): # Bank select flops get put to the right of control logic above bank1 and the buses # Leave a pitch to get the vdd rails up to M2 self.msb_address_position = vector(self.bank_inst[1].lx() + 3*self.supply_rail_pitch, - self.supply_bus_offset.y + self.supply_bus_height + 2*self.m1_pitch + self.msb_address.width) + self.supply_bus_offset.y + self.supply_bus_height \ + + 2*self.m1_pitch + self.msb_address.width) # Decoder goes above the MSB address flops, and is flipped in Y # separate the two by a bank to bus distance for nwell rules, just in case @@ -375,73 +381,65 @@ class sram(design.design): # Bank select flops get put to the right of control logic above bank1 and the buses # Leave a pitch to get the vdd rails up to M2 self.msb_address_position = vector(self.bank_inst[1].lx() + 3*self.supply_rail_pitch, - self.supply_bus_offset.y+self.supply_bus_height + 2*self.m1_pitch + self.msb_address.width) + self.supply_bus_offset.y + self.supply_bus_height \ + + 2*self.m1_pitch + self.msb_address.width) def add_busses(self): """ Add the horizontal and vertical busses """ # Vertical bus # The order of the control signals on the control bus: self.control_bus_names = ["clk_buf", "tri_en_bar", "tri_en", "clk_buf_bar", "w_en", "s_en"] - self.vert_control_bus_positions = self.create_bus(layer="metal2", - pitch=self.m2_pitch, - offset=self.vertical_bus_offset, - names=self.control_bus_names, - length=self.vertical_bus_height, - vertical=True) + self.vert_control_bus_positions = self.create_vertical_bus(layer="metal2", + pitch=self.m2_pitch, + offset=self.vertical_bus_offset, + names=self.control_bus_names, + length=self.vertical_bus_height)) self.addr_bus_names=["A[{}]".format(i) for i in range(self.addr_size)] - self.vert_control_bus_positions.update(self.create_bus(layer="metal2", - pitch=self.m2_pitch, - offset=self.addr_bus_offset, - names=self.addr_bus_names, - length=self.addr_bus_height, - vertical=True, - make_pins=True)) + self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="metal2", + pitch=self.m2_pitch, + offset=self.addr_bus_offset, + names=self.addr_bus_names, + length=self.addr_bus_height)) self.bank_sel_bus_names = ["bank_sel[{}]".format(i) for i in range(self.num_banks)] - self.vert_control_bus_positions.update(self.create_bus(layer="metal2", - pitch=self.m2_pitch, - offset=self.bank_sel_bus_offset, - names=self.bank_sel_bus_names, - length=self.vertical_bus_height, - vertical=True, - make_pins=True)) + self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="metal2", + pitch=self.m2_pitch, + offset=self.bank_sel_bus_offset, + names=self.bank_sel_bus_names, + length=self.vertical_bus_height)) # Horizontal data bus self.data_bus_names = ["DATA[{}]".format(i) for i in range(self.word_size)] - self.data_bus_positions = self.create_bus(layer="metal3", - pitch=self.m3_pitch, - offset=self.data_bus_offset, - names=self.data_bus_names, - length=self.data_bus_width, - vertical=False, - make_pins=True) + self.data_bus_positions = self.create_horizontal_pin_bus(layer="metal3", + pitch=self.m3_pitch, + offset=self.data_bus_offset, + names=self.data_bus_names, + length=self.data_bus_width) # Horizontal control logic bus # vdd/gnd in bus go along whole SRAM # FIXME: Fatten these wires? - self.horz_control_bus_positions = self.create_bus(layer="metal1", - pitch=self.m1_pitch, - offset=self.supply_bus_offset, - names=["vdd"], - length=self.supply_bus_width, - vertical=False) + self.horz_control_bus_positions = self.create_horizontal_bus(layer="metal1", + pitch=self.m1_pitch, + offset=self.supply_bus_offset, + names=["vdd"], + length=self.supply_bus_width) # The gnd rail must not be the entire width since we protrude the right-most vdd rail up for # the decoder in 4-bank SRAMs - self.horz_control_bus_positions.update(self.create_bus(layer="metal1", - pitch=self.m1_pitch, - offset=self.supply_bus_offset+vector(0,self.m1_pitch), - names=["gnd"], - length=self.supply_bus_width, - vertical=False)) - self.horz_control_bus_positions.update(self.create_bus(layer="metal1", - pitch=self.m1_pitch, - offset=self.control_bus_offset, - names=self.control_bus_names, - length=self.control_bus_width, - vertical=False)) + self.horz_control_bus_positions.update(self.create_horizontal_bus(layer="metal1", + pitch=self.m1_pitch, + offset=self.supply_bus_offset+vector(0,self.m1_pitch), + names=["gnd"], + length=self.supply_bus_width)) + self.horz_control_bus_positions.update(self.create_horizontal_bus(layer="metal1", + pitch=self.m1_pitch, + offset=self.control_bus_offset, + names=self.control_bus_names, + length=self.control_bus_width)) + def add_two_bank_logic(self): """ Add the control and MSB logic """ @@ -848,44 +846,6 @@ class sram(design.design): return bank_inst - # FIXME: This should be in geometry.py or it's own class since it is - # reusable - def create_bus(self, layer, pitch, offset, names, length, vertical=False, make_pins=False): - """ Create a horizontal or vertical bus. It can be either just rectangles, or actual - layout pins. It returns an map of line center line positions indexed by name. """ - - # half minwidth so we can return the center line offsets - half_minwidth = 0.5*drc["minwidth_{}".format(layer)] - - line_positions = {} - if vertical: - for i in range(len(names)): - line_offset = offset + vector(i*pitch,0) - if make_pins: - self.add_layout_pin(text=names[i], - layer=layer, - offset=line_offset, - height=length) - else: - self.add_rect(layer=layer, - offset=line_offset, - height=length) - line_positions[names[i]]=line_offset+vector(half_minwidth,0) - else: - for i in range(len(names)): - line_offset = offset + vector(0,i*pitch + half_minwidth) - if make_pins: - self.add_layout_pin(text=names[i], - layer=layer, - offset=line_offset, - width=length) - else: - self.add_rect(layer=layer, - offset=line_offset, - width=length) - line_positions[names[i]]=line_offset+vector(0,half_minwidth) - - return line_positions def add_addr_dff(self, position): From f5855ee68a231b1fbfff84b6e63a8658440b135f Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 10 Jul 2018 10:17:23 -0700 Subject: [PATCH 15/25] Fix analytical power of contact with new hierarchy_design level introduced. --- compiler/base/contact.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/base/contact.py b/compiler/base/contact.py index 2aa3ada5..5c300033 100644 --- a/compiler/base/contact.py +++ b/compiler/base/contact.py @@ -158,6 +158,9 @@ class contact(hierarchy_design.hierarchy_design): width=well_width, height=well_height) + def analytical_power(self, proc, vdd, temp, load): + """ Get total power of a module """ + return self.return_power() # This is not instantiated and used for calculations only. From 707f303eb7071fb51711fc8d6ce9c0c4ae7e477b Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 10 Jul 2018 10:34:54 -0700 Subject: [PATCH 16/25] Fix syntax error in sram.py --- compiler/sram.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/sram.py b/compiler/sram.py index e2ffa1fc..90dfe8dc 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -135,7 +135,7 @@ class sram(design.design): """ Add pins for entire SRAM. """ for i in range(self.word_size): - self.add_pin("DATA[{0}]".format(i),"INOUT") + self.add_pin("DIN[{0}]".format(i),"INPUT") for i in range(self.addr_size): self.add_pin("ADDR[{0}]".format(i),"INPUT") @@ -144,6 +144,10 @@ class sram(design.design): self.control_logic_outputs=self.control_logic.get_outputs() self.add_pin_list(self.control_logic_inputs,"INPUT") + + for i in range(self.word_size): + self.add_pin("DOUT[{0}]".format(i),"OUTPUT") + self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") @@ -151,9 +155,7 @@ class sram(design.design): """ Layout creation """ if self.num_banks == 1: - self.add_single_bank_modules() - self.add_single_bank_pins() - self.route_single_bank() + sram_1bank.sram_1bank.__init__() elif self.num_banks == 2: self.add_two_bank_modules() self.route_two_banks() @@ -393,7 +395,7 @@ class sram(design.design): pitch=self.m2_pitch, offset=self.vertical_bus_offset, names=self.control_bus_names, - length=self.vertical_bus_height)) + length=self.vertical_bus_height) self.addr_bus_names=["A[{}]".format(i) for i in range(self.addr_size)] self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="metal2", From 19c53cd50cfd031f003650e871114380f0b36705 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 10 Jul 2018 14:16:18 -0700 Subject: [PATCH 17/25] Do not fail assertion in exception code. --- compiler/tests/testutils.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index 4219d4e5..1aedcc0b 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -28,18 +28,13 @@ class openram_test(unittest.TestCase): import verify result=verify.run_drc(a.name, tempgds) self.reset() - try: - self.assertTrue(result==0) - except: + if result != 0: self.fail("DRC failed: {}".format(a.name)) result=verify.run_lvs(a.name, tempgds, tempspice, final_verification) self.reset() - try: - self.assertTrue(result==0) - except: - self.reset() + if result != 0: self.fail("LVS mismatch: {}".format(a.name)) if OPTS.purge_temp: From d95a1925d41198f8da97903de48385372ad48683 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 10 Jul 2018 14:17:09 -0700 Subject: [PATCH 18/25] Refactor banked SRAM into multiple files and dynamically load in SRAM --- compiler/base/design.py | 6 +- compiler/sram.py | 620 ++-------------------------------------- compiler/sram_1bank.py | 101 +++++++ compiler/sram_2bank.py | 216 ++++++++++++++ compiler/sram_4bank.py | 314 ++++++++++++++++++++ 5 files changed, 662 insertions(+), 595 deletions(-) create mode 100644 compiler/sram_1bank.py create mode 100644 compiler/sram_2bank.py create mode 100644 compiler/sram_4bank.py diff --git a/compiler/base/design.py b/compiler/base/design.py index 750eebd1..09522f35 100644 --- a/compiler/base/design.py +++ b/compiler/base/design.py @@ -1,4 +1,4 @@ -import hierarchy_design +from hierarchy_design import hierarchy_design import contact import globals import verify @@ -7,7 +7,7 @@ import os from globals import OPTS -class design(hierarchy_design.hierarchy_design): +class design(hierarchy_design): """ This is the same as the hierarchy_design class except it contains some DRC constants and analytical models for other modules to reuse. @@ -15,7 +15,7 @@ class design(hierarchy_design.hierarchy_design): """ def __init__(self, name): - hierarchy_design.hierarchy_design.__init__(self,name) + hierarchy_design.__init__(self,name) self.setup_drc_constants() diff --git a/compiler/sram.py b/compiler/sram.py index 90dfe8dc..0296ad02 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -1,19 +1,17 @@ import sys -from tech import drc, spice -import debug -import design -from math import log,sqrt,ceil -import contact -from bank import bank -from dff_buf_array import dff_buf_array -from dff_array import dff_array import datetime import getpass +import debug +import design +from sram_1bank import sram_1bank +from sram_2bank import sram_2bank +from sram_4bank import sram_4bank +from math import log,sqrt,ceil from vector import vector from globals import OPTS, print_time -class sram(design.design): +class sram(sram_1bank,sram_2bank,sram_4bank): """ Dynamically generated SRAM by connecting banks to control logic. The number of banks should be 1 , 2 or 4 @@ -35,8 +33,8 @@ class sram(design.design): # reset the static duplicate name checker for unit tests # in case we create more than one SRAM - import design - design.design.name_map=[] + from design import design + design.name_map=[] self.word_size = word_size self.num_words = num_words @@ -46,12 +44,20 @@ class sram(design.design): self.num_words)) start_time = datetime.datetime.now() - design.design.__init__(self, name) + self.compute_sizes() + + if self.num_banks == 1: + sram_1bank.__init__(self,name) + elif self.num_banks == 2: + sram_2bank.__init__(self,name) + elif self.num_banks == 4: + sram_4bank.__init__(self,name) + else: + debug.error("Invalid number of banks.",-1) self.control_size = 6 self.bank_to_bus_distance = 5*self.m3_width - - self.compute_sizes() + self.create_modules() self.add_pins() self.create_layout() @@ -151,157 +157,11 @@ class sram(design.design): self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") + def create_layout(self): - """ Layout creation """ - - if self.num_banks == 1: - sram_1bank.sram_1bank.__init__() - elif self.num_banks == 2: - self.add_two_bank_modules() - self.route_two_banks() - elif self.num_banks == 4: - self.add_four_bank_modules() - self.route_four_banks() - else: - debug.error("Invalid number of banks.",-1) - - - def add_four_bank_modules(self): - """ Adds the modules and the buses to the top level """ - - self.compute_bus_sizes() - - self.add_four_banks() - - self.compute_four_bank_offsets() - - self.add_busses() - - self.add_four_bank_logic() - - self.width = self.bank_inst[1].ur().x - self.height = max(self.control_logic_inst.uy(),self.msb_decoder_inst.uy()) - - - def add_two_bank_modules(self): - """ Adds the modules and the buses to the top level """ - - self.compute_bus_sizes() - - self.add_two_banks() - - self.compute_two_bank_offsets() - - self.add_busses() - - self.add_two_bank_logic() - - self.width = self.bank_inst[1].ur().x - self.height = self.control_logic_inst.uy() - - - def add_single_bank_modules(self): - """ - This adds the moduels for a single bank SRAM with control - logic. - """ - - # No orientation or offset - self.bank_inst = self.add_bank(0, [0, 0], 1, 1) - - # 3/5/18 MRG: Cannot reference positions inside submodules because boundaries - # are not recomputed using instance placement. So, place the control logic such that it aligns - # with the top of the SRAM. - control_pos = vector(-self.control_logic.width - self.m3_pitch, - 3*self.supply_rail_width) - self.add_control_logic(position=control_pos) - - # Leave room for the control routes to the left of the flops - addr_pos = vector(self.control_logic_inst.lx() + 4*self.m2_pitch, - control_pos.y + self.control_logic.height + self.m1_pitch) - self.add_addr_dff(addr_pos) - - # two supply rails are already included in the bank, so just 2 here. - self.width = self.bank.width + self.control_logic.width + 2*self.supply_rail_pitch - self.height = self.bank.height - - - def route_shared_banks(self): - """ Route the shared signals for two and four bank configurations. """ - - # create the input control pins - for n in self.control_logic_inputs + ["clk"]: - self.copy_layout_pin(self.control_logic_inst, n) - - # connect the control logic to the control bus - for n in self.control_logic_outputs + ["vdd", "gnd"]: - pins = self.control_logic_inst.get_pins(n) - for pin in pins: - if pin.layer=="metal2": - pin_pos = pin.bc() - break - rail_pos = vector(pin_pos.x,self.horz_control_bus_positions[n].y) - self.add_path("metal2",[pin_pos,rail_pos]) - self.add_via_center(("metal1","via1","metal2"),rail_pos) - - # connect the control logic cross bar - for n in self.control_logic_outputs: - cross_pos = vector(self.vert_control_bus_positions[n].x,self.horz_control_bus_positions[n].y) - self.add_via_center(("metal1","via1","metal2"),cross_pos) - - # connect the bank select signals to the vertical bus - for i in range(self.num_banks): - pin = self.bank_inst[i].get_pin("bank_sel") - pin_pos = pin.rc() if i==0 else pin.lc() - rail_pos = vector(self.vert_control_bus_positions["bank_sel[{}]".format(i)].x,pin_pos.y) - self.add_path("metal3",[pin_pos,rail_pos]) - self.add_via_center(("metal2","via2","metal3"),rail_pos) - - - def route_four_banks(self): - """ Route all of the signals for the four bank SRAM. """ - - self.route_shared_banks() - - # connect the data output to the data bus - for n in self.data_bus_names: - for i in [0,1]: - pin_pos = self.bank_inst[i].get_pin(n).bc() - rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y) - self.add_path("metal2",[pin_pos,rail_pos]) - self.add_via_center(("metal2","via2","metal3"),rail_pos) - - for i in [2,3]: - pin_pos = self.bank_inst[i].get_pin(n).uc() - rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y) - self.add_path("metal2",[pin_pos,rail_pos]) - self.add_via_center(("metal2","via2","metal3"),rail_pos) - - # route msb address bits - # route 2:4 decoder - self.route_double_msb_address() - - # connect the banks to the vertical address bus - # connect the banks to the vertical control bus - for n in self.addr_bus_names + self.control_bus_names: - # Skip these from the horizontal bus - if n in ["vdd", "gnd"]: continue - # This will be the bank select, so skip it - if n in self.msb_bank_sel_addr: continue - - for bank_id in [0,2]: - pin0_pos = self.bank_inst[bank_id].get_pin(n).rc() - pin1_pos = self.bank_inst[bank_id+1].get_pin(n).lc() - rail_pos = vector(self.vert_control_bus_positions[n].x,pin0_pos.y) - self.add_path("metal3",[pin0_pos,pin1_pos]) - self.add_via_center(("metal2","via2","metal3"),rail_pos) - - - self.route_bank_supply_rails(left_banks=[0,2], bottom_banks=[2,3]) - - - - + """ Layout creation """ + self.add_modules() + self.route() def compute_bus_sizes(self): """ Compute the independent bus widths shared between two and four bank SRAMs """ @@ -328,63 +188,6 @@ class sram(design.design): "Bank is too small compared to control logic.") - def compute_four_bank_offsets(self): - """ Compute the overall offsets for a four bank SRAM """ - - # The main difference is that the four bank SRAM has the data bus in the middle of the four banks - # as opposed to the top of the banks. - - # In 4 bank SRAM, the height is determined by the bank decoder and address flop - self.vertical_bus_height = 2*self.bank.height + 4*self.bank_to_bus_distance + self.data_bus_height \ - + self.supply_bus_height + self.msb_decoder.height + self.msb_address.width - # The address bus extends down through the power rails, but control and bank_sel bus don't - self.addr_bus_height = self.vertical_bus_height - - self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 0) - self.data_bus_offset = vector(0, self.bank.height + self.bank_to_bus_distance) - self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height \ - + self.bank.height + 2*self.bank_to_bus_distance) - self.control_bus_offset = vector(0, self.supply_bus_offset.y + self.supply_bus_height) - self.bank_sel_bus_offset = self.vertical_bus_offset + vector(self.m2_pitch*self.control_size,0) - self.addr_bus_offset = self.bank_sel_bus_offset.scale(1,0) + vector(self.m2_pitch*self.num_banks,0) - - # Control is placed at the top above the control bus and everything - self.control_logic_position = vector(0, self.control_bus_offset.y + self.control_bus_height + self.m1_pitch) - - # Bank select flops get put to the right of control logic above bank1 and the buses - # Leave a pitch to get the vdd rails up to M2 - self.msb_address_position = vector(self.bank_inst[1].lx() + 3*self.supply_rail_pitch, - self.supply_bus_offset.y + self.supply_bus_height \ - + 2*self.m1_pitch + self.msb_address.width) - - # Decoder goes above the MSB address flops, and is flipped in Y - # separate the two by a bank to bus distance for nwell rules, just in case - self.msb_decoder_position = self.msb_address_position + vector(self.msb_decoder.width, self.bank_to_bus_distance) - - - def compute_two_bank_offsets(self): - """ Compute the overall offsets for a two bank SRAM """ - - # In 2 bank SRAM, the height is determined by the control bus which is higher than the msb address - self.vertical_bus_height = self.bank.height + 2*self.bank_to_bus_distance + self.data_bus_height + self.control_bus_height - # The address bus extends down through the power rails, but control and bank_sel bus don't - self.addr_bus_height = self.vertical_bus_height - - self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 0) - self.data_bus_offset = vector(0, self.bank.height + self.bank_to_bus_distance) - self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height) - self.control_bus_offset = vector(0, self.supply_bus_offset.y + self.supply_bus_height) - self.bank_sel_bus_offset = self.vertical_bus_offset + vector(self.m2_pitch*self.control_size,0) - self.addr_bus_offset = self.bank_sel_bus_offset.scale(1,0) + vector(self.m2_pitch*self.num_banks,0) - - # Control is placed at the top above the control bus and everything - self.control_logic_position = vector(0, self.control_bus_offset.y + self.control_bus_height + self.m1_pitch) - - # Bank select flops get put to the right of control logic above bank1 and the buses - # Leave a pitch to get the vdd rails up to M2 - self.msb_address_position = vector(self.bank_inst[1].lx() + 3*self.supply_rail_pitch, - self.supply_bus_offset.y + self.supply_bus_height \ - + 2*self.m1_pitch + self.msb_address.width) def add_busses(self): """ Add the horizontal and vertical busses """ @@ -443,293 +246,8 @@ class sram(design.design): length=self.control_bus_width)) - def add_two_bank_logic(self): - """ Add the control and MSB logic """ - - self.add_control_logic(position=self.control_logic_position) - - self.msb_address_inst = self.add_inst(name="msb_address", - mod=self.msb_address, - offset=self.msb_address_position, - rotate=270) - self.msb_bank_sel_addr = "ADDR[{}]".format(self.addr_size-1) - self.connect_inst([self.msb_bank_sel_addr,"bank_sel[1]","bank_sel[0]","clk_buf", "vdd", "gnd"]) - - def add_four_bank_logic(self): - """ Add the control and MSB decode/bank select logic for four banks """ - - - self.add_control_logic(position=self.control_logic_position) - - self.msb_address_inst = self.add_inst(name="msb_address", - mod=self.msb_address, - offset=self.msb_address_position, - rotate=270) - - self.msb_bank_sel_addr = ["ADDR[{}]".format(i) for i in range(self.addr_size-2,self.addr_size,1)] - temp = list(self.msb_bank_sel_addr) - temp.extend(["msb{0}[{1}]".format(j,i) for i in range(2) for j in ["","_bar"]]) - temp.extend(["clk_buf", "vdd", "gnd"]) - self.connect_inst(temp) - - self.msb_decoder_inst = self.add_inst(name="msb_decoder", - mod=self.msb_decoder, - offset=self.msb_decoder_position, - mirror="MY") - temp = ["msb[{}]".format(i) for i in range(2)] - temp.extend(["bank_sel[{}]".format(i) for i in range(4)]) - temp.extend(["vdd", "gnd"]) - self.connect_inst(temp) - - - def route_two_banks(self): - """ Route all of the signals for the two bank SRAM. """ - - self.route_shared_banks() - - # connect the horizontal control bus to the vertical bus - # connect the data output to the data bus - for n in self.data_bus_names: - for i in [0,1]: - pin_pos = self.bank_inst[i].get_pin(n).uc() - rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y) - self.add_path("metal2",[pin_pos,rail_pos]) - self.add_via_center(("metal2","via2","metal3"),rail_pos) - - self.route_single_msb_address() - - # connect the banks to the vertical address bus - # connect the banks to the vertical control bus - for n in self.addr_bus_names + self.control_bus_names: - # Skip these from the horizontal bus - if n in ["vdd", "gnd"]: continue - # This will be the bank select, so skip it - if n == self.msb_bank_sel_addr: continue - pin0_pos = self.bank_inst[0].get_pin(n).rc() - pin1_pos = self.bank_inst[1].get_pin(n).lc() - rail_pos = vector(self.vert_control_bus_positions[n].x,pin0_pos.y) - self.add_path("metal3",[pin0_pos,pin1_pos]) - self.add_via_center(("metal2","via2","metal3"),rail_pos) - - def route_double_msb_address(self): - """ Route two MSB address bits and the bank decoder for 4-bank SRAM """ - - # connect the MSB flops to the address input bus - for i in [0,1]: - msb_pins = self.msb_address_inst.get_pins("din[{}]".format(i)) - for msb_pin in msb_pins: - if msb_pin.layer == "metal3": - msb_pin_pos = msb_pin.lc() - break - rail_pos = vector(self.vert_control_bus_positions[self.msb_bank_sel_addr[i]].x,msb_pin_pos.y) - self.add_path("metal3",[msb_pin_pos,rail_pos]) - self.add_via_center(("metal2","via2","metal3"),rail_pos) - - # Connect clk - clk_pin = self.msb_address_inst.get_pin("clk") - clk_pos = clk_pin.bc() - rail_pos = self.horz_control_bus_positions["clk_buf"] - bend_pos = vector(clk_pos.x,self.horz_control_bus_positions["clk_buf"].y) - self.add_path("metal1",[clk_pos,bend_pos,rail_pos]) - - # Connect bank decoder outputs to the bank select vertical bus wires - for i in range(self.num_banks): - msb_pin = self.msb_decoder_inst.get_pin("out[{}]".format(i)) - msb_pin_pos = msb_pin.lc() - rail_pos = vector(self.vert_control_bus_positions["bank_sel[{}]".format(i)].x,msb_pin_pos.y) - self.add_path("metal1",[msb_pin_pos,rail_pos]) - self.add_via_center(("metal1","via1","metal2"),rail_pos) - - # connect MSB flop outputs to the bank decoder inputs - msb_pin = self.msb_address_inst.get_pin("dout[0]") - msb_pin_pos = msb_pin.rc() - in_pin = self.msb_decoder_inst.get_pin("in[0]") - in_pos = in_pin.bc() + vector(0,1*self.m2_pitch,) # pin is up from bottom - out_pos = msb_pin_pos + vector(1*self.m2_pitch,0) # route out to the right - up_pos = vector(out_pos.x,in_pos.y) # and route up to the decoer - self.add_wire(("metal1","via1","metal2"),[msb_pin_pos,out_pos,up_pos,in_pos]) - self.add_via_center(("metal1","via1","metal2"),in_pos) - self.add_via_center(("metal1","via1","metal2"),msb_pin_pos,rotate=90) - - msb_pin = self.msb_address_inst.get_pin("dout[1]") - msb_pin_pos = msb_pin.rc() - in_pin = self.msb_decoder_inst.get_pin("in[1]") - in_pos = in_pin.bc() + vector(0,self.bitcell.height+self.m2_pitch) # route the next row up - out_pos = msb_pin_pos + vector(2*self.m2_pitch,0) # route out to the right - up_pos = vector(out_pos.x,in_pos.y) # and route up to the decoer - self.add_wire(("metal1","via1","metal2"),[msb_pin_pos,out_pos,up_pos,in_pos]) - self.add_via_center(("metal1","via1","metal2"),in_pos) - self.add_via_center(("metal1","via1","metal2"),msb_pin_pos,rotate=90) - - self.route_double_msb_address_supplies() - - def route_double_msb_address_supplies(self): - """ Route the vdd/gnd bits of the 2-bit bank decoder. """ - - # Route the right-most vdd/gnd of the right upper bank to the top of the decoder - vdd_pins = self.bank_inst[1].get_pins("vdd") - left_bank_vdd_pin = None - right_bank_vdd_pin = None - for vdd_pin in vdd_pins: - if vdd_pin.layer != "metal2": - continue - if left_bank_vdd_pin == None or vdd_pin.lx()right_bank_vdd_pin.lx(): - right_bank_vdd_pin = vdd_pin - # Route to top - self.add_rect(layer="metal2", - offset=vdd_pin.ul(), - height=self.height-vdd_pin.uy(), - width=vdd_pin.width()) - - gnd_pins = self.bank_inst[1].get_pins("gnd") - left_bank_gnd_pin = None - right_bank_gnd_pin = None - for gnd_pin in gnd_pins: - if gnd_pin.layer != "metal2": - continue - if left_bank_gnd_pin == None or gnd_pin.lx()right_bank_gnd_pin.lx(): - right_bank_gnd_pin = gnd_pin - # Route to top - self.add_rect(layer="metal2", - offset=gnd_pin.ul(), - height=self.height-gnd_pin.uy(), - width=gnd_pin.width()) - - # Connect bank decoder vdd/gnd supplies using the previous bank pins - vdd_pins = self.msb_decoder_inst.get_pins("vdd") - for vdd_pin in vdd_pins: - if vdd_pin.layer != "metal1": - continue - rail1_pos = vector(left_bank_vdd_pin.cx(),vdd_pin.cy()) - rail2_pos = vector(right_bank_vdd_pin.cx(),vdd_pin.cy()) - self.add_path("metal1",[rail1_pos,rail2_pos]) - self.add_via_center(layers=("metal1","via1","metal2"), - offset=rail1_pos, - rotate=90, - size=[1,3]) - self.add_via_center(layers=("metal1","via1","metal2"), - offset=rail2_pos, - rotate=90, - size=[1,3]) - gnd_pins = self.msb_decoder_inst.get_pins("gnd") - for gnd_pin in gnd_pins: - if gnd_pin.layer != "metal1": - continue - rail1_pos = vector(left_bank_gnd_pin.cx(),gnd_pin.cy()) - rail2_pos = vector(right_bank_gnd_pin.cx(),gnd_pin.cy()) - self.add_path("metal1",[rail1_pos,rail2_pos]) - self.add_via_center(layers=("metal1","via1","metal2"), - offset=rail1_pos, - rotate=90, - size=[1,3]) - self.add_via_center(layers=("metal1","via1","metal2"), - offset=rail2_pos, - rotate=90, - size=[1,3]) - - # connect the bank MSB flop supplies - vdd_pins = self.msb_address_inst.get_pins("vdd") - # vdd pins go down to the rail - for vdd_pin in vdd_pins: - if vdd_pin.layer != "metal1": - continue - vdd_pos = vdd_pin.bc() - down_pos = vdd_pos - vector(0,self.m1_pitch) - rail_pos = vector(vdd_pos.x,self.horz_control_bus_positions["vdd"].y) - self.add_path("metal1",[vdd_pos,down_pos]) - self.add_via_center(layers=("metal1","via1","metal2"), - offset=down_pos, - rotate=90) - self.add_path("metal2",[down_pos,rail_pos]) - self.add_via_center(layers=("metal1","via1","metal2"), - offset=rail_pos) - # gnd pins go right to the rail - gnd_pins = self.msb_address_inst.get_pins("gnd") - for gnd_pin in gnd_pins: - if gnd_pin.layer != "metal2": - continue - rail1_pos = vector(left_bank_gnd_pin.cx(),gnd_pin.cy()) - self.add_path("metal1",[rail1_pos,gnd_pin.lc()]) - self.add_via_center(layers=("metal1","via1","metal2"), - offset=gnd_pin.lc(), - rotate=90) - self.add_via_center(layers=("metal1","via1","metal2"), - offset=rail1_pos, - rotate=90, - size=[1,3]) - - def route_single_msb_address(self): - """ Route one MSB address bit for 2-bank SRAM """ - - # connect the bank MSB flop supplies - vdd_pins = self.msb_address_inst.get_pins("vdd") - for vdd_pin in vdd_pins: - if vdd_pin.layer != "metal1": continue - vdd_pos = vdd_pin.bc() - down_pos = vdd_pos - vector(0,self.m1_pitch) - rail_pos = vector(vdd_pos.x,self.horz_control_bus_positions["vdd"].y) - self.add_path("metal1",[vdd_pos,down_pos]) - self.add_via_center(("metal1","via1","metal2"),down_pos,rotate=90) - self.add_path("metal2",[down_pos,rail_pos]) - self.add_via_center(("metal1","via1","metal2"),rail_pos) - - gnd_pins = self.msb_address_inst.get_pins("gnd") - # Only add the ground connection to the lowest metal2 rail in the flop array - # FIXME: SCMOS doesn't have a vertical rail in the cell, or we could use those - lowest_y = None - for gnd_pin in gnd_pins: - if gnd_pin.layer != "metal2": continue - if lowest_y==None or gnd_pin.by()right_bank_vdd_pin.lx(): + right_bank_vdd_pin = vdd_pin + # Route to top + self.add_rect(layer="metal2", + offset=vdd_pin.ul(), + height=self.height-vdd_pin.uy(), + width=vdd_pin.width()) + + gnd_pins = self.bank_inst[1].get_pins("gnd") + left_bank_gnd_pin = None + right_bank_gnd_pin = None + for gnd_pin in gnd_pins: + if gnd_pin.layer != "metal2": + continue + if left_bank_gnd_pin == None or gnd_pin.lx()right_bank_gnd_pin.lx(): + right_bank_gnd_pin = gnd_pin + # Route to top + self.add_rect(layer="metal2", + offset=gnd_pin.ul(), + height=self.height-gnd_pin.uy(), + width=gnd_pin.width()) + + # Connect bank decoder vdd/gnd supplies using the previous bank pins + vdd_pins = self.msb_decoder_inst.get_pins("vdd") + for vdd_pin in vdd_pins: + if vdd_pin.layer != "metal1": + continue + rail1_pos = vector(left_bank_vdd_pin.cx(),vdd_pin.cy()) + rail2_pos = vector(right_bank_vdd_pin.cx(),vdd_pin.cy()) + self.add_path("metal1",[rail1_pos,rail2_pos]) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=rail1_pos, + rotate=90, + size=[1,3]) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=rail2_pos, + rotate=90, + size=[1,3]) + gnd_pins = self.msb_decoder_inst.get_pins("gnd") + for gnd_pin in gnd_pins: + if gnd_pin.layer != "metal1": + continue + rail1_pos = vector(left_bank_gnd_pin.cx(),gnd_pin.cy()) + rail2_pos = vector(right_bank_gnd_pin.cx(),gnd_pin.cy()) + self.add_path("metal1",[rail1_pos,rail2_pos]) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=rail1_pos, + rotate=90, + size=[1,3]) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=rail2_pos, + rotate=90, + size=[1,3]) + + # connect the bank MSB flop supplies + vdd_pins = self.msb_address_inst.get_pins("vdd") + # vdd pins go down to the rail + for vdd_pin in vdd_pins: + if vdd_pin.layer != "metal1": + continue + vdd_pos = vdd_pin.bc() + down_pos = vdd_pos - vector(0,self.m1_pitch) + rail_pos = vector(vdd_pos.x,self.horz_control_bus_positions["vdd"].y) + self.add_path("metal1",[vdd_pos,down_pos]) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=down_pos, + rotate=90) + self.add_path("metal2",[down_pos,rail_pos]) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=rail_pos) + # gnd pins go right to the rail + gnd_pins = self.msb_address_inst.get_pins("gnd") + for gnd_pin in gnd_pins: + if gnd_pin.layer != "metal2": + continue + rail1_pos = vector(left_bank_gnd_pin.cx(),gnd_pin.cy()) + self.add_path("metal1",[rail1_pos,gnd_pin.lc()]) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=gnd_pin.lc(), + rotate=90) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=rail1_pos, + rotate=90, + size=[1,3]) + + + def route(self): + """ Route all of the signals for the four bank SRAM. """ + + self.route_shared_banks() + + # connect the data output to the data bus + for n in self.data_bus_names: + for i in [0,1]: + pin_pos = self.bank_inst[i].get_pin(n).bc() + rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y) + self.add_path("metal2",[pin_pos,rail_pos]) + self.add_via_center(("metal2","via2","metal3"),rail_pos) + + for i in [2,3]: + pin_pos = self.bank_inst[i].get_pin(n).uc() + rail_pos = vector(pin_pos.x,self.data_bus_positions[n].y) + self.add_path("metal2",[pin_pos,rail_pos]) + self.add_via_center(("metal2","via2","metal3"),rail_pos) + + # route msb address bits + # route 2:4 decoder + self.route_double_msb_address() + + # connect the banks to the vertical address bus + # connect the banks to the vertical control bus + for n in self.addr_bus_names + self.control_bus_names: + # Skip these from the horizontal bus + if n in ["vdd", "gnd"]: continue + # This will be the bank select, so skip it + if n in self.msb_bank_sel_addr: continue + + for bank_id in [0,2]: + pin0_pos = self.bank_inst[bank_id].get_pin(n).rc() + pin1_pos = self.bank_inst[bank_id+1].get_pin(n).lc() + rail_pos = vector(self.vert_control_bus_positions[n].x,pin0_pos.y) + self.add_path("metal3",[pin0_pos,pin1_pos]) + self.add_via_center(("metal2","via2","metal3"),rail_pos) + + + self.route_bank_supply_rails(left_banks=[0,2], bottom_banks=[2,3]) + + From c6503dd77199ad8114b4bf5a5c925ff6342dcd54 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 10 Jul 2018 16:39:32 -0700 Subject: [PATCH 19/25] Modify unit tests to reset options during init_openram so that they don't use old parameters after a failure. --- compiler/base/hierarchy_design.py | 12 +++++-- compiler/globals.py | 32 +++++++++++++++---- compiler/tests/01_library_drc_test.py | 3 +- compiler/tests/02_library_lvs_test.py | 3 +- compiler/tests/03_contact_test.py | 2 -- compiler/tests/03_path_test.py | 5 +-- compiler/tests/03_ptx_1finger_nmos_test.py | 2 -- compiler/tests/03_ptx_1finger_pmos_test.py | 2 -- compiler/tests/03_ptx_3finger_nmos_test.py | 2 -- compiler/tests/03_ptx_3finger_pmos_test.py | 2 -- compiler/tests/03_ptx_4finger_nmos_test.py | 2 -- compiler/tests/03_ptx_4finger_pmos_test.py | 2 -- compiler/tests/03_wire_test.py | 3 -- compiler/tests/04_pbitcell_test.py | 4 +-- compiler/tests/04_pinv_10x_test.py | 2 -- compiler/tests/04_pinv_1x_beta_test.py | 2 -- compiler/tests/04_pinv_1x_test.py | 2 -- compiler/tests/04_pinv_2x_test.py | 2 -- compiler/tests/04_pinvbuf_test.py | 2 -- compiler/tests/04_pnand2_test.py | 2 -- compiler/tests/04_pnand3_test.py | 2 -- compiler/tests/04_pnor2_test.py | 2 -- compiler/tests/04_precharge_test.py | 2 -- .../tests/04_single_level_column_mux_test.py | 2 -- compiler/tests/05_bitcell_array_test.py | 2 -- compiler/tests/05_pbitcell_array_test.py | 18 ++++------- .../tests/06_hierarchical_decoder_test.py | 2 -- .../06_hierarchical_predecode2x4_test.py | 2 -- .../06_hierarchical_predecode3x8_test.py | 2 -- .../07_single_level_column_mux_array_test.py | 2 -- compiler/tests/08_precharge_array_test.py | 2 -- compiler/tests/08_wordline_driver_test.py | 2 -- compiler/tests/09_sense_amp_array_test.py | 2 -- compiler/tests/10_write_driver_array_test.py | 2 -- compiler/tests/11_dff_array_test.py | 2 -- compiler/tests/11_dff_buf_array_test.py | 2 -- compiler/tests/11_dff_buf_test.py | 2 -- compiler/tests/11_dff_inv_array_test.py | 2 -- compiler/tests/11_dff_inv_test.py | 2 -- compiler/tests/11_ms_flop_array_test.py | 2 -- compiler/tests/12_tri_gate_array_test.py | 2 -- compiler/tests/13_delay_chain_test.py | 2 -- compiler/tests/14_replica_bitline_test.py | 2 -- compiler/tests/16_control_logic_test.py | 2 -- compiler/tests/19_bank_select_test.py | 2 -- compiler/tests/19_multi_bank_test.py | 2 -- compiler/tests/19_single_bank_test.py | 2 -- compiler/tests/20_sram_1bank_test.py | 2 -- compiler/tests/20_sram_2bank_test.py | 2 -- compiler/tests/20_sram_4bank_test.py | 2 -- compiler/tests/21_hspice_delay_test.py | 7 ---- compiler/tests/21_hspice_setuphold_test.py | 3 -- compiler/tests/21_ngspice_delay_test.py | 6 ---- compiler/tests/21_ngspice_setuphold_test.py | 6 ---- compiler/tests/22_pex_test.py | 6 ++-- compiler/tests/22_sram_func_test.py | 6 +--- compiler/tests/23_lib_sram_model_test.py | 4 +-- compiler/tests/23_lib_sram_prune_test.py | 4 --- compiler/tests/23_lib_sram_test.py | 5 --- compiler/tests/24_lef_sram_test.py | 4 --- compiler/tests/25_verilog_sram_test.py | 4 --- compiler/tests/regress.py | 1 + compiler/tests/testutils.py | 25 ++++++++++----- 63 files changed, 68 insertions(+), 177 deletions(-) diff --git a/compiler/base/hierarchy_design.py b/compiler/base/hierarchy_design.py index 2af96f7d..87659bd7 100644 --- a/compiler/base/hierarchy_design.py +++ b/compiler/base/hierarchy_design.py @@ -61,7 +61,9 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): def DRC_LVS(self, final_verification=False): """Checks both DRC and LVS for a module""" - if OPTS.check_lvsdrc: + # Unit tests will check themselves. + # Do not run if disabled in options. + if not OPTS.is_unit_test and OPTS.check_lvsdrc: tempspice = OPTS.openram_temp + "/temp.sp" tempgds = OPTS.openram_temp + "/temp.gds" self.sp_write(tempspice) @@ -73,7 +75,9 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): def DRC(self): """Checks DRC for a module""" - if OPTS.check_lvsdrc: + # Unit tests will check themselves. + # Do not run if disabled in options. + if not OPTS.is_unit_test and OPTS.check_lvsdrc: tempgds = OPTS.openram_temp + "/temp.gds" self.gds_write(tempgds) debug.check(verify.run_drc(self.name, tempgds) == 0,"DRC failed for {0}".format(self.name)) @@ -81,7 +85,9 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): def LVS(self, final_verification=False): """Checks LVS for a module""" - if OPTS.check_lvsdrc: + # Unit tests will check themselves. + # Do not run if disabled in options. + if not OPTS.is_unit_test and OPTS.check_lvsdrc: tempspice = OPTS.openram_temp + "/temp.sp" tempgds = OPTS.openram_temp + "/temp.gds" self.sp_write(tempspice) diff --git a/compiler/globals.py b/compiler/globals.py index 86d091b1..8c305664 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -9,12 +9,14 @@ import optparse import options import sys import re +import copy import importlib USAGE = "Usage: openram.py [options] \nUse -h for help.\n" # Anonymous object that will be the options OPTS = options.options() +CHECKPOINT_OPTS=None def parse_args(): """ Parse the optional arguments for OpenRAM """ @@ -102,6 +104,7 @@ def check_versions(): def init_openram(config_file, is_unit_test=True): """Initialize the technology, paths, simulators, etc.""" + check_versions() debug.info(1,"Initializing OpenRAM...") @@ -112,6 +115,10 @@ def init_openram(config_file, is_unit_test=True): import_tech() + # Reset the static duplicate name checker for unit tests. + import hierarchy_design + hierarchy_design.hierarchy_design.name_map=[] + def get_tool(tool_type, preferences): @@ -132,15 +139,25 @@ def get_tool(tool_type, preferences): return(None,"") - def read_config(config_file, is_unit_test=True): """ Read the configuration file that defines a few parameters. The config file is just a Python file that defines some config - options. + options. This will only actually get read the first time. Subsequent + reads will just restore the previous copy (ask mrg) """ global OPTS - + global CHECKPOINT_OPTS + + # This is a hack. If we are running a unit test and have checkpointed + # the options, load them rather than reading the config file. + # This way, the configuration is reloaded at the start of every unit test. + # If a unit test fails, we don't have to worry about restoring the old config values + # that may have been tested. + if is_unit_test and CHECKPOINT_OPTS: + OPTS = copy.deepcopy(CHECKPOINT_OPTS) + return + # Create a full path relative to current dir unless it is already an abs path if not os.path.isabs(config_file): config_file = os.getcwd() + "/" + config_file @@ -164,6 +181,7 @@ def read_config(config_file, is_unit_test=True): # The command line will over-ride the config file # except in the case of the tech name! This is because the tech name # is sometimes used to specify the config file itself (e.g. unit tests) + # Note that if we re-read a config file, nothing will get read again! if not k in OPTS.__dict__ or k=="tech_name": OPTS.__dict__[k]=v @@ -192,7 +210,10 @@ def read_config(config_file, is_unit_test=True): os.chmod(OPTS.output_path, 0o750) except: debug.error("Unable to make output directory.",-1) - + + # Make a checkpoint of the options so we can restore + # after each unit test + CHECKPOINT_OPTS = copy.deepcopy(OPTS) def end_openram(): @@ -275,9 +296,6 @@ def import_tech(): debug.info(2,"Importing technology: " + OPTS.tech_name) - # Set the tech to the config file we read in instead of the command line value. - OPTS.tech_name = OPTS.tech_name - # environment variable should point to the technology dir try: OPENRAM_TECH = os.path.abspath(os.environ.get("OPENRAM_TECH")) diff --git a/compiler/tests/01_library_drc_test.py b/compiler/tests/01_library_drc_test.py index e1f9506a..a3c07d47 100755 --- a/compiler/tests/01_library_drc_test.py +++ b/compiler/tests/01_library_drc_test.py @@ -15,7 +15,8 @@ class library_drc_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - + OPTS.check_lvsdrc=True + (gds_dir, gds_files) = setup_files() drc_errors = 0 debug.info(1, "\nPerforming DRC on: " + ", ".join(gds_files)) diff --git a/compiler/tests/02_library_lvs_test.py b/compiler/tests/02_library_lvs_test.py index 22f2d3d7..d85f284e 100755 --- a/compiler/tests/02_library_lvs_test.py +++ b/compiler/tests/02_library_lvs_test.py @@ -14,6 +14,7 @@ class library_lvs_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) import verify + OPTS.check_lvsdrc=True (gds_dir, sp_dir, allnames) = setup_files() lvs_errors = 0 debug.info(1, "Performing LVS on: " + ", ".join(allnames)) @@ -28,7 +29,7 @@ class library_lvs_test(openram_test): lvs_errors += 1 debug.error("Missing SPICE file {}".format(gds_name)) lvs_errors += verify.run_lvs(f, gds_name, sp_name) - self.assertEqual(lvs_errors, 0) + # fail if the error count is not zero self.assertEqual(lvs_errors, 0) globals.end_openram() diff --git a/compiler/tests/03_contact_test.py b/compiler/tests/03_contact_test.py index cf1d5f8c..b5938cec 100755 --- a/compiler/tests/03_contact_test.py +++ b/compiler/tests/03_contact_test.py @@ -15,7 +15,6 @@ class contact_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import contact @@ -43,7 +42,6 @@ class contact_test(openram_test): c = contact.contact(layer_stack, (3, 3)) self.local_drc_check(c) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/03_path_test.py b/compiler/tests/03_path_test.py index 7f8af2d9..88a195c4 100755 --- a/compiler/tests/03_path_test.py +++ b/compiler/tests/03_path_test.py @@ -15,8 +15,7 @@ class path_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False - + import path import tech import design @@ -84,8 +83,6 @@ class path_test(openram_test): path.path(w, layer_stack, position_list) self.local_drc_check(w) - # return it back to it's normal state - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/03_ptx_1finger_nmos_test.py b/compiler/tests/03_ptx_1finger_nmos_test.py index af87aa1f..02ef0f2b 100755 --- a/compiler/tests/03_ptx_1finger_nmos_test.py +++ b/compiler/tests/03_ptx_1finger_nmos_test.py @@ -15,7 +15,6 @@ class ptx_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import ptx import tech @@ -26,7 +25,6 @@ class ptx_test(openram_test): tx_type="nmos") self.local_drc_check(fet) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/03_ptx_1finger_pmos_test.py b/compiler/tests/03_ptx_1finger_pmos_test.py index 6b13b5c4..c00ccb72 100755 --- a/compiler/tests/03_ptx_1finger_pmos_test.py +++ b/compiler/tests/03_ptx_1finger_pmos_test.py @@ -15,7 +15,6 @@ class ptx_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import ptx import tech @@ -26,7 +25,6 @@ class ptx_test(openram_test): tx_type="pmos") self.local_drc_check(fet) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/03_ptx_3finger_nmos_test.py b/compiler/tests/03_ptx_3finger_nmos_test.py index 1a68bbcf..60293266 100755 --- a/compiler/tests/03_ptx_3finger_nmos_test.py +++ b/compiler/tests/03_ptx_3finger_nmos_test.py @@ -15,7 +15,6 @@ class ptx_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import ptx import tech @@ -28,7 +27,6 @@ class ptx_test(openram_test): connect_poly=True) self.local_drc_check(fet) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/03_ptx_3finger_pmos_test.py b/compiler/tests/03_ptx_3finger_pmos_test.py index e3570f1a..792de25f 100755 --- a/compiler/tests/03_ptx_3finger_pmos_test.py +++ b/compiler/tests/03_ptx_3finger_pmos_test.py @@ -15,7 +15,6 @@ class ptx_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import ptx import tech @@ -28,7 +27,6 @@ class ptx_test(openram_test): connect_poly=True) self.local_drc_check(fet) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/03_ptx_4finger_nmos_test.py b/compiler/tests/03_ptx_4finger_nmos_test.py index 45722501..d4cc0da5 100755 --- a/compiler/tests/03_ptx_4finger_nmos_test.py +++ b/compiler/tests/03_ptx_4finger_nmos_test.py @@ -15,7 +15,6 @@ class ptx_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import ptx import tech @@ -28,7 +27,6 @@ class ptx_test(openram_test): connect_poly=True) self.local_drc_check(fet) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/03_ptx_4finger_pmos_test.py b/compiler/tests/03_ptx_4finger_pmos_test.py index fb7dfd6c..c35390c9 100755 --- a/compiler/tests/03_ptx_4finger_pmos_test.py +++ b/compiler/tests/03_ptx_4finger_pmos_test.py @@ -15,7 +15,6 @@ class ptx_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import ptx import tech @@ -28,7 +27,6 @@ class ptx_test(openram_test): connect_poly=True) self.local_drc_check(fet) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/03_wire_test.py b/compiler/tests/03_wire_test.py index 17abe160..cf50dc10 100755 --- a/compiler/tests/03_wire_test.py +++ b/compiler/tests/03_wire_test.py @@ -15,7 +15,6 @@ class wire_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import wire import tech @@ -122,8 +121,6 @@ class wire_test(openram_test): wire.wire(w, layer_stack, position_list) self.local_drc_check(w) - # return it back to it's normal state - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/04_pbitcell_test.py b/compiler/tests/04_pbitcell_test.py index 8a684839..b2eb7fb5 100755 --- a/compiler/tests/04_pbitcell_test.py +++ b/compiler/tests/04_pbitcell_test.py @@ -22,7 +22,6 @@ class pbitcell_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import pbitcell import tech @@ -67,9 +66,8 @@ class pbitcell_test(openram_test): tx = pbitcell.pbitcell(num_readwrite=2,num_write=0,num_read=0) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() - OPTS.bitcell = "bitcell" + # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/04_pinv_10x_test.py b/compiler/tests/04_pinv_10x_test.py index 4e396b83..09eef9c3 100755 --- a/compiler/tests/04_pinv_10x_test.py +++ b/compiler/tests/04_pinv_10x_test.py @@ -17,7 +17,6 @@ class pinv_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import pinv import tech @@ -26,7 +25,6 @@ class pinv_test(openram_test): tx = pinv.pinv(size=8) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/04_pinv_1x_beta_test.py b/compiler/tests/04_pinv_1x_beta_test.py index d8c98ea6..17829e14 100755 --- a/compiler/tests/04_pinv_1x_beta_test.py +++ b/compiler/tests/04_pinv_1x_beta_test.py @@ -17,7 +17,6 @@ class pinv_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import pinv import tech @@ -26,7 +25,6 @@ class pinv_test(openram_test): tx = pinv.pinv(size=1, beta=3) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/04_pinv_1x_test.py b/compiler/tests/04_pinv_1x_test.py index fa36a280..a0db1100 100755 --- a/compiler/tests/04_pinv_1x_test.py +++ b/compiler/tests/04_pinv_1x_test.py @@ -16,7 +16,6 @@ class pinv_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import pinv @@ -26,7 +25,6 @@ class pinv_test(openram_test): tx = pinv.pinv(size=1) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/04_pinv_2x_test.py b/compiler/tests/04_pinv_2x_test.py index bedb259f..66ea15da 100755 --- a/compiler/tests/04_pinv_2x_test.py +++ b/compiler/tests/04_pinv_2x_test.py @@ -17,7 +17,6 @@ class pinv_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import pinv import tech @@ -26,7 +25,6 @@ class pinv_test(openram_test): tx = pinv.pinv(size=2) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/04_pinvbuf_test.py b/compiler/tests/04_pinvbuf_test.py index 3fc5e3c3..ffe6fa33 100755 --- a/compiler/tests/04_pinvbuf_test.py +++ b/compiler/tests/04_pinvbuf_test.py @@ -17,7 +17,6 @@ class pinvbuf_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import pinvbuf @@ -25,7 +24,6 @@ class pinvbuf_test(openram_test): a = pinvbuf.pinvbuf(4,8) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/04_pnand2_test.py b/compiler/tests/04_pnand2_test.py index adf3a4e8..af35bae8 100755 --- a/compiler/tests/04_pnand2_test.py +++ b/compiler/tests/04_pnand2_test.py @@ -19,7 +19,6 @@ class pnand2_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import pnand2 import tech @@ -28,7 +27,6 @@ class pnand2_test(openram_test): tx = pnand2.pnand2(size=1) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/04_pnand3_test.py b/compiler/tests/04_pnand3_test.py index 594be7ff..6984a0e0 100755 --- a/compiler/tests/04_pnand3_test.py +++ b/compiler/tests/04_pnand3_test.py @@ -19,7 +19,6 @@ class pnand3_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import pnand3 import tech @@ -28,7 +27,6 @@ class pnand3_test(openram_test): tx = pnand3.pnand3(size=1) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/04_pnor2_test.py b/compiler/tests/04_pnor2_test.py index fe18bd4c..a15f6907 100755 --- a/compiler/tests/04_pnor2_test.py +++ b/compiler/tests/04_pnor2_test.py @@ -19,7 +19,6 @@ class pnor2_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import pnor2 import tech @@ -28,7 +27,6 @@ class pnor2_test(openram_test): tx = pnor2.pnor2(size=1) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/04_precharge_test.py b/compiler/tests/04_precharge_test.py index 018f6ef7..55460289 100755 --- a/compiler/tests/04_precharge_test.py +++ b/compiler/tests/04_precharge_test.py @@ -17,7 +17,6 @@ class precharge_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import precharge import tech @@ -26,7 +25,6 @@ class precharge_test(openram_test): tx = precharge.precharge(name="precharge_driver", size=1) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/04_single_level_column_mux_test.py b/compiler/tests/04_single_level_column_mux_test.py index 494fcd84..d282a11a 100755 --- a/compiler/tests/04_single_level_column_mux_test.py +++ b/compiler/tests/04_single_level_column_mux_test.py @@ -19,7 +19,6 @@ class single_level_column_mux_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import single_level_column_mux import tech @@ -28,7 +27,6 @@ class single_level_column_mux_test(openram_test): tx = single_level_column_mux.single_level_column_mux(tx_size=8) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/05_bitcell_array_test.py b/compiler/tests/05_bitcell_array_test.py index 849e6666..37649ad5 100755 --- a/compiler/tests/05_bitcell_array_test.py +++ b/compiler/tests/05_bitcell_array_test.py @@ -19,7 +19,6 @@ class array_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import bitcell_array @@ -27,7 +26,6 @@ class array_test(openram_test): a = bitcell_array.bitcell_array(name="bitcell_array", cols=4, rows=4) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/05_pbitcell_array_test.py b/compiler/tests/05_pbitcell_array_test.py index 2dfed383..aa623f56 100755 --- a/compiler/tests/05_pbitcell_array_test.py +++ b/compiler/tests/05_pbitcell_array_test.py @@ -11,38 +11,32 @@ import globals from globals import OPTS import debug -#@unittest.skip("SKIPPING 05_array_multiport_test") - -class array_multiport_test(openram_test): +#@unittest.skip("SKIPPING 05_pbitcell_array_test") +class pbitcell_array_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import bitcell_array + debug.info(2, "Testing 4x4 array for multiport bitcell, with read ports at the edge of the bit cell") OPTS.bitcell = "pbitcell" OPTS.rw_ports = 2 OPTS.r_ports = 2 OPTS.w_ports = 2 - - debug.info(2, "Testing 4x4 array for multiport bitcell, with read ports at the edge of the bit cell") a = bitcell_array.bitcell_array(name="pbitcell_array", cols=4, rows=4) self.local_check(a) - + + debug.info(2, "Testing 4x4 array for multiport bitcell, with read/write ports at the edge of the bit cell") + OPTS.bitcell = "pbitcell" OPTS.rw_ports = 2 OPTS.r_ports = 0 OPTS.w_ports = 2 - - debug.info(2, "Testing 4x4 array for multiport bitcell, with read/write ports at the edge of the bit cell") a = bitcell_array.bitcell_array(name="pbitcell_array", cols=4, rows=4) self.local_check(a) - - OPTS.bitcell = "bitcell" - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/06_hierarchical_decoder_test.py b/compiler/tests/06_hierarchical_decoder_test.py index 48cae531..eb0b105a 100755 --- a/compiler/tests/06_hierarchical_decoder_test.py +++ b/compiler/tests/06_hierarchical_decoder_test.py @@ -17,7 +17,6 @@ class hierarchical_decoder_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import hierarchical_decoder import tech @@ -48,7 +47,6 @@ class hierarchical_decoder_test(openram_test): a = hierarchical_decoder.hierarchical_decoder(rows=512) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/06_hierarchical_predecode2x4_test.py b/compiler/tests/06_hierarchical_predecode2x4_test.py index 021f53b6..79db3665 100755 --- a/compiler/tests/06_hierarchical_predecode2x4_test.py +++ b/compiler/tests/06_hierarchical_predecode2x4_test.py @@ -17,7 +17,6 @@ class hierarchical_predecode2x4_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import hierarchical_predecode2x4 as pre import tech @@ -26,7 +25,6 @@ class hierarchical_predecode2x4_test(openram_test): a = pre.hierarchical_predecode2x4() self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/06_hierarchical_predecode3x8_test.py b/compiler/tests/06_hierarchical_predecode3x8_test.py index e6bcda2d..b6609829 100755 --- a/compiler/tests/06_hierarchical_predecode3x8_test.py +++ b/compiler/tests/06_hierarchical_predecode3x8_test.py @@ -17,7 +17,6 @@ class hierarchical_predecode3x8_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import hierarchical_predecode3x8 as pre import tech @@ -26,7 +25,6 @@ class hierarchical_predecode3x8_test(openram_test): a = pre.hierarchical_predecode3x8() self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/07_single_level_column_mux_array_test.py b/compiler/tests/07_single_level_column_mux_array_test.py index 120f1093..1becd179 100755 --- a/compiler/tests/07_single_level_column_mux_array_test.py +++ b/compiler/tests/07_single_level_column_mux_array_test.py @@ -16,7 +16,6 @@ class single_level_column_mux_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import single_level_column_mux_array @@ -32,7 +31,6 @@ class single_level_column_mux_test(openram_test): a = single_level_column_mux_array.single_level_column_mux_array(columns=32, word_size=4) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/08_precharge_array_test.py b/compiler/tests/08_precharge_array_test.py index 84eaf6ea..d4a3190f 100755 --- a/compiler/tests/08_precharge_array_test.py +++ b/compiler/tests/08_precharge_array_test.py @@ -17,7 +17,6 @@ class precharge_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import precharge_array import tech @@ -26,7 +25,6 @@ class precharge_test(openram_test): pc = precharge_array.precharge_array(columns=3) self.local_check(pc) - OPTS.check_lvsdrc = True globals.end_openram() diff --git a/compiler/tests/08_wordline_driver_test.py b/compiler/tests/08_wordline_driver_test.py index 1688bb5b..af97f018 100755 --- a/compiler/tests/08_wordline_driver_test.py +++ b/compiler/tests/08_wordline_driver_test.py @@ -19,7 +19,6 @@ class wordline_driver_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import wordline_driver import tech @@ -28,7 +27,6 @@ class wordline_driver_test(openram_test): tx = wordline_driver.wordline_driver(rows=8) self.local_check(tx) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/09_sense_amp_array_test.py b/compiler/tests/09_sense_amp_array_test.py index db1adf75..ba483218 100755 --- a/compiler/tests/09_sense_amp_array_test.py +++ b/compiler/tests/09_sense_amp_array_test.py @@ -17,7 +17,6 @@ class sense_amp_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import sense_amp_array @@ -30,7 +29,6 @@ class sense_amp_test(openram_test): a = sense_amp_array.sense_amp_array(word_size=4, words_per_row=4) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/10_write_driver_array_test.py b/compiler/tests/10_write_driver_array_test.py index bc47d3ab..d7f1f7ec 100755 --- a/compiler/tests/10_write_driver_array_test.py +++ b/compiler/tests/10_write_driver_array_test.py @@ -17,7 +17,6 @@ class write_driver_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import write_driver_array @@ -29,7 +28,6 @@ class write_driver_test(openram_test): a = write_driver_array.write_driver_array(columns=16, word_size=8) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/11_dff_array_test.py b/compiler/tests/11_dff_array_test.py index a194ddad..e85056e9 100755 --- a/compiler/tests/11_dff_array_test.py +++ b/compiler/tests/11_dff_array_test.py @@ -17,7 +17,6 @@ class dff_array_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import dff_array @@ -33,7 +32,6 @@ class dff_array_test(openram_test): a = dff_array.dff_array(rows=3, columns=1) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/11_dff_buf_array_test.py b/compiler/tests/11_dff_buf_array_test.py index dc1af1e7..6c40e447 100755 --- a/compiler/tests/11_dff_buf_array_test.py +++ b/compiler/tests/11_dff_buf_array_test.py @@ -17,7 +17,6 @@ class dff_buf_array_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import dff_buf_array @@ -33,7 +32,6 @@ class dff_buf_array_test(openram_test): a = dff_buf_array.dff_buf_array(rows=3, columns=1) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/11_dff_buf_test.py b/compiler/tests/11_dff_buf_test.py index 22d0e3cb..44aca54c 100755 --- a/compiler/tests/11_dff_buf_test.py +++ b/compiler/tests/11_dff_buf_test.py @@ -17,7 +17,6 @@ class dff_buf_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import dff_buf @@ -25,7 +24,6 @@ class dff_buf_test(openram_test): a = dff_buf.dff_buf(4, 8) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/11_dff_inv_array_test.py b/compiler/tests/11_dff_inv_array_test.py index 4781d199..3d2b8cac 100755 --- a/compiler/tests/11_dff_inv_array_test.py +++ b/compiler/tests/11_dff_inv_array_test.py @@ -17,7 +17,6 @@ class dff_inv_array_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import dff_inv_array @@ -33,7 +32,6 @@ class dff_inv_array_test(openram_test): a = dff_inv_array.dff_inv_array(rows=3, columns=1) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/11_dff_inv_test.py b/compiler/tests/11_dff_inv_test.py index a20f2df5..b09a6591 100755 --- a/compiler/tests/11_dff_inv_test.py +++ b/compiler/tests/11_dff_inv_test.py @@ -17,7 +17,6 @@ class dff_inv_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import dff_inv @@ -25,7 +24,6 @@ class dff_inv_test(openram_test): a = dff_inv.dff_inv(4) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/11_ms_flop_array_test.py b/compiler/tests/11_ms_flop_array_test.py index 050afd71..97ef6ece 100755 --- a/compiler/tests/11_ms_flop_array_test.py +++ b/compiler/tests/11_ms_flop_array_test.py @@ -17,7 +17,6 @@ class dff_array_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import ms_flop_array @@ -29,7 +28,6 @@ class dff_array_test(openram_test): a = ms_flop_array.ms_flop_array(columns=16, word_size=8) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/12_tri_gate_array_test.py b/compiler/tests/12_tri_gate_array_test.py index 9f61a5b6..08d1596d 100755 --- a/compiler/tests/12_tri_gate_array_test.py +++ b/compiler/tests/12_tri_gate_array_test.py @@ -17,7 +17,6 @@ class tri_gate_array_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import tri_gate_array @@ -29,7 +28,6 @@ class tri_gate_array_test(openram_test): a = tri_gate_array.tri_gate_array(columns=16, word_size=8) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/13_delay_chain_test.py b/compiler/tests/13_delay_chain_test.py index ef2d1a85..d8a2d67c 100755 --- a/compiler/tests/13_delay_chain_test.py +++ b/compiler/tests/13_delay_chain_test.py @@ -17,7 +17,6 @@ class delay_chain_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import delay_chain @@ -25,7 +24,6 @@ class delay_chain_test(openram_test): a = delay_chain.delay_chain(fanout_list=[4, 4, 4, 4]) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/14_replica_bitline_test.py b/compiler/tests/14_replica_bitline_test.py index 97598693..b393c136 100755 --- a/compiler/tests/14_replica_bitline_test.py +++ b/compiler/tests/14_replica_bitline_test.py @@ -17,7 +17,6 @@ class replica_bitline_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import replica_bitline @@ -34,7 +33,6 @@ class replica_bitline_test(openram_test): a = replica_bitline.replica_bitline(stages,fanout,rows) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index 231e2440..7aeb54c1 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -17,7 +17,6 @@ class control_logic_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import control_logic import tech @@ -26,7 +25,6 @@ class control_logic_test(openram_test): a = control_logic.control_logic(num_rows=128) self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/19_bank_select_test.py b/compiler/tests/19_bank_select_test.py index 025e4cc4..955c7b4e 100755 --- a/compiler/tests/19_bank_select_test.py +++ b/compiler/tests/19_bank_select_test.py @@ -17,7 +17,6 @@ class bank_select_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import bank_select @@ -25,7 +24,6 @@ class bank_select_test(openram_test): a = bank_select.bank_select() self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/19_multi_bank_test.py b/compiler/tests/19_multi_bank_test.py index 088b810b..1a900f4c 100755 --- a/compiler/tests/19_multi_bank_test.py +++ b/compiler/tests/19_multi_bank_test.py @@ -17,7 +17,6 @@ class multi_bank_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import bank @@ -37,7 +36,6 @@ class multi_bank_test(openram_test): a = bank.bank(word_size=2, num_words=128, words_per_row=8, num_banks=2, name="bank4_multi") self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/19_single_bank_test.py b/compiler/tests/19_single_bank_test.py index 4b4ba7df..5bbc60ad 100755 --- a/compiler/tests/19_single_bank_test.py +++ b/compiler/tests/19_single_bank_test.py @@ -17,7 +17,6 @@ class single_bank_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import bank @@ -38,7 +37,6 @@ class single_bank_test(openram_test): a = bank.bank(word_size=2, num_words=128, words_per_row=8, num_banks=1, name="bank4_single") self.local_check(a) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/20_sram_1bank_test.py b/compiler/tests/20_sram_1bank_test.py index 8289191b..6bc738dd 100755 --- a/compiler/tests/20_sram_1bank_test.py +++ b/compiler/tests/20_sram_1bank_test.py @@ -17,7 +17,6 @@ class sram_1bank_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import sram @@ -37,7 +36,6 @@ class sram_1bank_test(openram_test): # a = sram.sram(word_size=2, num_words=128, num_banks=1, name="sram4") # self.local_check(a, final_verification=True) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/20_sram_2bank_test.py b/compiler/tests/20_sram_2bank_test.py index 9334040a..7ae6bf13 100755 --- a/compiler/tests/20_sram_2bank_test.py +++ b/compiler/tests/20_sram_2bank_test.py @@ -18,7 +18,6 @@ class sram_2bank_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import sram @@ -38,7 +37,6 @@ class sram_2bank_test(openram_test): # a = sram.sram(word_size=2, num_words=256 num_banks=2, name="sram4") # self.local_check(a, final_verification=True) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/20_sram_4bank_test.py b/compiler/tests/20_sram_4bank_test.py index 2e8bfefc..3fb69dc9 100755 --- a/compiler/tests/20_sram_4bank_test.py +++ b/compiler/tests/20_sram_4bank_test.py @@ -18,7 +18,6 @@ class sram_4bank_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) global verify import verify - OPTS.check_lvsdrc = False import sram @@ -38,7 +37,6 @@ class sram_4bank_test(openram_test): # a = sram.sram(word_size=2, num_words=256, num_banks=4, name="sram4") # self.local_check(a, final_verification=True) - OPTS.check_lvsdrc = True globals.end_openram() # instantiate a copy of the class to actually run the test diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 9ac3db2e..b170b072 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -15,7 +15,6 @@ class timing_sram_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = False OPTS.spice_name="hspice" OPTS.analytical_delay = False @@ -35,7 +34,6 @@ class timing_sram_test(openram_test): num_banks=OPTS.num_banks, name="sram1") - OPTS.check_lvsdrc = True tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) @@ -85,12 +83,7 @@ class timing_sram_test(openram_test): else: self.isclose(data[k],golden_data[k],0.15) - - # reset these options - OPTS.check_lvsdrc = True - OPTS.analytical_delay = True reload(characterizer) - globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/21_hspice_setuphold_test.py b/compiler/tests/21_hspice_setuphold_test.py index 78403a56..5c4f72a6 100755 --- a/compiler/tests/21_hspice_setuphold_test.py +++ b/compiler/tests/21_hspice_setuphold_test.py @@ -15,7 +15,6 @@ class timing_setup_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = False OPTS.spice_name="hspice" OPTS.analytical_delay = False @@ -59,8 +58,6 @@ class timing_setup_test(openram_test): else: self.isclose(data[k],golden_data[k],0.15) - OPTS.check_lvsdrc = True - OPTS.analytical_delay = True reload(characterizer) globals.end_openram() diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 7f7bfd39..36e0c0d0 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -15,7 +15,6 @@ class timing_sram_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = False OPTS.spice_name="ngspice" OPTS.analytical_delay = False @@ -84,12 +83,7 @@ class timing_sram_test(openram_test): else: self.isclose(data[k],golden_data[k],0.15) - # reset these options - OPTS.check_lvsdrc = True - OPTS.spice_name="hspice" - OPTS.analytical_delay = True reload(characterizer) - globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/21_ngspice_setuphold_test.py b/compiler/tests/21_ngspice_setuphold_test.py index 9a8ff67c..24c69aa7 100755 --- a/compiler/tests/21_ngspice_setuphold_test.py +++ b/compiler/tests/21_ngspice_setuphold_test.py @@ -15,7 +15,6 @@ class timing_setup_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = False OPTS.spice_name="ngspice" OPTS.analytical_delay = False @@ -58,12 +57,7 @@ class timing_setup_test(openram_test): else: self.isclose(data[k],golden_data[k],0.15) - # reset these options - OPTS.check_lvsdrc = True - OPTS.spice_name="hspice" - OPTS.analytical_delay = True reload(characterizer) - globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/22_pex_test.py b/compiler/tests/22_pex_test.py index 3e146ba8..1ccf6cfe 100755 --- a/compiler/tests/22_pex_test.py +++ b/compiler/tests/22_pex_test.py @@ -31,14 +31,12 @@ class sram_func_test(openram_test): import tech debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") - OPTS.check_lvsdrc = False + global OPTS OPTS.use_pex = True s = sram.sram(word_size=OPTS.word_size, num_words=OPTS.num_words, num_banks=OPTS.num_banks, name="test_sram1") - OPTS.check_lvsdrc = True - OPTS.use_pex = False tempspice = OPTS.openram_temp + "temp.sp" tempgds = OPTS.openram_temp + "temp.gds" @@ -90,7 +88,7 @@ class sram_func_test(openram_test): self.assertTrue(round(value1) > 0.5 * tech.spice["supply_voltage"]) self.assertTrue(round(value2) < 0.5 * tech.spice["supply_voltage"]) - OPTS.check_lvsdrc = True + def convert_voltage_unit(self, string): newstring = "" diff --git a/compiler/tests/22_sram_func_test.py b/compiler/tests/22_sram_func_test.py index f9045f1a..22443c5a 100755 --- a/compiler/tests/22_sram_func_test.py +++ b/compiler/tests/22_sram_func_test.py @@ -16,8 +16,6 @@ class sram_func_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = False - OPTS.spice_name="" # Unset to use any simulator OPTS.analytical_delay = False # This is a hack to reload the characterizer __init__ with the spice version @@ -36,8 +34,6 @@ class sram_func_test(openram_test): num_banks=1, name="sram_func_test") - OPTS.check_lvsdrc = True - tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) @@ -56,7 +52,7 @@ class sram_func_test(openram_test): feasible_period = d.find_feasible_period() os.remove(tempspice) - OPTS.analytical_delay = True + reload(characterizer) globals.end_openram() diff --git a/compiler/tests/23_lib_sram_model_test.py b/compiler/tests/23_lib_sram_model_test.py index 9eb8ac5b..2691de48 100755 --- a/compiler/tests/23_lib_sram_model_test.py +++ b/compiler/tests/23_lib_sram_model_test.py @@ -15,7 +15,6 @@ class lib_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = False import sram from characterizer import lib @@ -25,8 +24,7 @@ class lib_test(openram_test): num_words=16, num_banks=1, name="sram_2_16_1_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = True - + tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) diff --git a/compiler/tests/23_lib_sram_prune_test.py b/compiler/tests/23_lib_sram_prune_test.py index 4227bc44..b2f45d8a 100755 --- a/compiler/tests/23_lib_sram_prune_test.py +++ b/compiler/tests/23_lib_sram_prune_test.py @@ -15,8 +15,6 @@ class lib_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = False - OPTS.spice_name="" # Unset to use any simulator OPTS.analytical_delay = False OPTS.trim_netlist = True @@ -35,7 +33,6 @@ class lib_test(openram_test): num_words=16, num_banks=1, name="sram_2_16_1_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = True tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) @@ -54,7 +51,6 @@ class lib_test(openram_test): golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),newname) self.isapproxdiff(libname,golden,0.40) - OPTS.analytical_delay = True reload(characterizer) globals.end_openram() diff --git a/compiler/tests/23_lib_sram_test.py b/compiler/tests/23_lib_sram_test.py index 46750250..80f34064 100755 --- a/compiler/tests/23_lib_sram_test.py +++ b/compiler/tests/23_lib_sram_test.py @@ -15,8 +15,6 @@ class lib_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = False - OPTS.spice_name="" # Unset to use any simulator OPTS.analytical_delay = False OPTS.trim_netlist = False @@ -35,7 +33,6 @@ class lib_test(openram_test): num_words=16, num_banks=1, name="sram_2_16_1_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = True tempspice = OPTS.openram_temp + "temp.sp" s.sp_write(tempspice) @@ -53,8 +50,6 @@ class lib_test(openram_test): golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename) self.isapproxdiff(libname,golden,0.40) - OPTS.analytical_delay = True - OPTS.trim_netlist = True reload(characterizer) globals.end_openram() diff --git a/compiler/tests/24_lef_sram_test.py b/compiler/tests/24_lef_sram_test.py index 4cd654ae..fbd16034 100755 --- a/compiler/tests/24_lef_sram_test.py +++ b/compiler/tests/24_lef_sram_test.py @@ -15,8 +15,6 @@ class lef_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - # we will manually run lvs/drc - OPTS.check_lvsdrc = False import sram @@ -26,8 +24,6 @@ class lef_test(openram_test): num_banks=OPTS.num_banks, name="sram_2_16_1_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = True - gdsfile = s.name + ".gds" leffile = s.name + ".lef" gdsname = OPTS.openram_temp + gdsfile diff --git a/compiler/tests/25_verilog_sram_test.py b/compiler/tests/25_verilog_sram_test.py index 8ceb093b..fe0be3d9 100755 --- a/compiler/tests/25_verilog_sram_test.py +++ b/compiler/tests/25_verilog_sram_test.py @@ -15,8 +15,6 @@ class verilog_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - # we will manually run lvs/drc - OPTS.check_lvsdrc = False import sram @@ -26,8 +24,6 @@ class verilog_test(openram_test): num_banks=OPTS.num_banks, name="sram_2_16_1_{0}".format(OPTS.tech_name)) - OPTS.check_lvsdrc = True - vfile = s.name + ".v" vname = OPTS.openram_temp + vfile s.verilog_write(vname) diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py index daf9f3b6..73ec0d7f 100755 --- a/compiler/tests/regress.py +++ b/compiler/tests/regress.py @@ -27,5 +27,6 @@ modules = map(__import__, moduleNames) suite = unittest.TestSuite() load = unittest.defaultTestLoader.loadTestsFromModule suite.addTests(map(load, modules)) + ret = not unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful() sys.exit(ret) diff --git a/compiler/tests/testutils.py b/compiler/tests/testutils.py index 1aedcc0b..7949e113 100644 --- a/compiler/tests/testutils.py +++ b/compiler/tests/testutils.py @@ -1,5 +1,5 @@ import unittest,warnings -import sys,os,glob +import sys,os,glob,copy sys.path.append(os.path.join(sys.path[0],"..")) from globals import OPTS import debug @@ -8,17 +8,23 @@ class openram_test(unittest.TestCase): """ Base unit test that we have some shared classes in. """ def local_drc_check(self, w): + + self.reset() + tempgds = OPTS.openram_temp + "temp.gds" w.gds_write(tempgds) import verify - self.assertFalse(verify.run_drc(w.name, tempgds)) - files = glob.glob(OPTS.openram_temp + '*') - for f in files: - os.remove(f) + result=verify.run_drc(w.name, tempgds) + if result != 0: + self.fail("DRC failed: {}".format(a.name)) + + self.cleanup() def local_check(self, a, final_verification=False): + self.reset() + tempspice = OPTS.openram_temp + "temp.sp" tempgds = OPTS.openram_temp + "temp.gds" @@ -27,13 +33,11 @@ class openram_test(unittest.TestCase): import verify result=verify.run_drc(a.name, tempgds) - self.reset() if result != 0: self.fail("DRC failed: {}".format(a.name)) result=verify.run_lvs(a.name, tempgds, tempspice, final_verification) - self.reset() if result != 0: self.fail("LVS mismatch: {}".format(a.name)) @@ -49,9 +53,14 @@ class openram_test(unittest.TestCase): os.remove(f) def reset(self): - """ Reset the static duplicate name checker for unit tests """ + """ + Reset everything after each test. + """ + # Reset the static duplicate name checker for unit tests. import hierarchy_design hierarchy_design.hierarchy_design.name_map=[] + + def isclose(self, value1,value2,error_tolerance=1e-2): """ This is used to compare relative values. """ From b3732f4fcf7c8c0bf39e93f28fdfe781fa80a792 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 11 Jul 2018 09:51:28 -0700 Subject: [PATCH 20/25] Output debug warnings and errors to stderr. Clean up regress script a bit. --- compiler/debug.py | 6 +++--- compiler/tests/regress.py | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/debug.py b/compiler/debug.py index 7001373e..1bf46db0 100644 --- a/compiler/debug.py +++ b/compiler/debug.py @@ -13,19 +13,19 @@ def check(check,str): (frame, filename, line_number, function_name, lines, index) = inspect.getouterframes(inspect.currentframe())[1] if not check: - print("ERROR: file {0}: line {1}: {2}".format(os.path.basename(filename),line_number,str)) + sys.stderr.write("ERROR: file {0}: line {1}: {2}\n".format(os.path.basename(filename),line_number,str)) assert 0 def error(str,return_value=0): (frame, filename, line_number, function_name, lines, index) = inspect.getouterframes(inspect.currentframe())[1] - print("ERROR: file {0}: line {1}: {2}".format(os.path.basename(filename),line_number,str)) + sys.stderr.write("ERROR: file {0}: line {1}: {2}\n".format(os.path.basename(filename),line_number,str)) assert return_value==0 def warning(str): (frame, filename, line_number, function_name, lines, index) = inspect.getouterframes(inspect.currentframe())[1] - print("WARNING: file {0}: line {1}: {2}".format(os.path.basename(filename),line_number,str)) + sys.stderr.write("WARNING: file {0}: line {1}: {2}\n".format(os.path.basename(filename),line_number,str)) def info(lev, str): diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py index 73ec0d7f..93989248 100755 --- a/compiler/tests/regress.py +++ b/compiler/tests/regress.py @@ -28,5 +28,6 @@ suite = unittest.TestSuite() load = unittest.defaultTestLoader.loadTestsFromModule suite.addTests(map(load, modules)) -ret = not unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful() -sys.exit(ret) +test_runner = unittest.TextTestRunner(verbosity=2,stream=sys.stderr) +test_result = test_runner.run(suite) +sys.exit(not test_result.wasSuccessful()) From f894ef47afffdd84ee4ebd340e25cc3853d58970 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 11 Jul 2018 11:58:22 -0700 Subject: [PATCH 21/25] Fix missing list conversion to run drc library tests. --- compiler/tests/01_library_drc_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/tests/01_library_drc_test.py b/compiler/tests/01_library_drc_test.py index a3c07d47..b4d35a5f 100755 --- a/compiler/tests/01_library_drc_test.py +++ b/compiler/tests/01_library_drc_test.py @@ -13,14 +13,12 @@ class library_drc_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) - global verify import verify - OPTS.check_lvsdrc=True - + (gds_dir, gds_files) = setup_files() drc_errors = 0 debug.info(1, "\nPerforming DRC on: " + ", ".join(gds_files)) - for f in gds_files: + for f in list(gds_files): name = re.sub('\.gds$', '', f) gds_name = "{0}/{1}".format(gds_dir, f) if not os.path.isfile(gds_name): @@ -32,11 +30,12 @@ class library_drc_test(openram_test): self.assertEqual(drc_errors, 0) globals.end_openram() + def setup_files(): gds_dir = OPTS.openram_tech + "/gds_lib" files = os.listdir(gds_dir) nametest = re.compile("\.gds$", re.IGNORECASE) - gds_files = filter(nametest.search, files) + gds_files = list(filter(nametest.search, files)) return (gds_dir, gds_files) @@ -46,3 +45,4 @@ if __name__ == "__main__": del sys.argv[1:] header(__file__, OPTS.tech_name) unittest.main() + From 58646ab8e6007eacc057b8d450b8b9afde6014c3 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 11 Jul 2018 11:59:24 -0700 Subject: [PATCH 22/25] Add DRC/LVS/PEX statistics in verbose=1 mode --- compiler/tests/regress.py | 6 ++++++ compiler/verify/__init__.py | 19 ++++++++++--------- compiler/verify/assura.py | 22 ++++++++++++++++++++++ compiler/verify/calibre.py | 23 ++++++++++++++++++++++- compiler/verify/magic.py | 20 ++++++++++++++++++++ 5 files changed, 80 insertions(+), 10 deletions(-) diff --git a/compiler/tests/regress.py b/compiler/tests/regress.py index 93989248..d97def2b 100755 --- a/compiler/tests/regress.py +++ b/compiler/tests/regress.py @@ -30,4 +30,10 @@ suite.addTests(map(load, modules)) test_runner = unittest.TextTestRunner(verbosity=2,stream=sys.stderr) test_result = test_runner.run(suite) + +import verify +verify.print_drc_stats() +verify.print_lvs_stats() +verify.print_pex_stats() + sys.exit(not test_result.wasSuccessful()) diff --git a/compiler/verify/__init__.py b/compiler/verify/__init__.py index a83629b0..2199e765 100644 --- a/compiler/verify/__init__.py +++ b/compiler/verify/__init__.py @@ -13,7 +13,7 @@ import debug from globals import OPTS,find_exe,get_tool import sys -debug.info(2,"Initializing verify...") +debug.info(1,"Initializing verify...") if not OPTS.check_lvsdrc: debug.info(1,"LVS/DRC/PEX disabled.") @@ -21,6 +21,7 @@ if not OPTS.check_lvsdrc: OPTS.lvs_exe = None OPTS.pex_exe = None else: + debug.info(1, "Finding DRC/LVS/PEX tools.") OPTS.drc_exe = get_tool("DRC",["calibre","assura","magic"]) OPTS.lvs_exe = get_tool("LVS",["calibre","assura","netgen"]) OPTS.pex_exe = get_tool("PEX",["calibre","magic"]) @@ -31,22 +32,22 @@ if OPTS.check_lvsdrc and OPTS.tech_name == "freepdk45": if OPTS.drc_exe == None: pass elif "calibre"==OPTS.drc_exe[0]: - from .calibre import run_drc + from .calibre import run_drc,print_drc_stats elif "assura"==OPTS.drc_exe[0]: - from .assura import run_drc + from .assura import run_drc,print_drc_stats elif "magic"==OPTS.drc_exe[0]: - from .magic import run_drc + from .magic import run_drc,print_drc_stats else: debug.warning("Did not find a supported DRC tool.") if OPTS.lvs_exe == None: pass elif "calibre"==OPTS.lvs_exe[0]: - from .calibre import run_lvs + from .calibre import run_lvs,print_lvs_stats elif "assura"==OPTS.lvs_exe[0]: - from .assura import run_lvs + from .assura import run_lvs,print_lvs_stats elif "netgen"==OPTS.lvs_exe[0]: - from .magic import run_lvs + from .magic import run_lvs,print_lvs_stats else: debug.warning("Did not find a supported LVS tool.") @@ -54,9 +55,9 @@ else: if OPTS.pex_exe == None: pass elif "calibre"==OPTS.pex_exe[0]: - from .calibre import run_pex + from .calibre import run_pex,print_pex_stats elif "magic"==OPTS.pex_exe[0]: - from .magic import run_pex + from .magic import run_pex,print_pex_stats else: debug.warning("Did not find a supported PEX tool.") diff --git a/compiler/verify/assura.py b/compiler/verify/assura.py index 27949721..d3c605f3 100644 --- a/compiler/verify/assura.py +++ b/compiler/verify/assura.py @@ -25,10 +25,18 @@ import time import debug from globals import OPTS +# Keep track of statistics +num_drc_runs = 0 +num_lvs_runs = 0 +num_pex_runs = 0 + def run_drc(name, gds_name): """Run DRC check on a given top-level name which is implemented in gds_name.""" + global num_drc_runs + num_drc_runs += 1 + from tech import drc drc_rules = drc["drc_rules"] drc_runset = OPTS.openram_temp + name + ".rsf" @@ -88,6 +96,10 @@ def run_drc(name, gds_name): def run_lvs(name, gds_name, sp_name): """Run LVS check on a given top-level name which is implemented in gds_name and sp_name. """ + + global num_lvs_runs + num_lvs_runs += 1 + from tech import drc lvs_rules = drc["lvs_rules"] lvs_runset = OPTS.openram_temp + name + ".rsf" @@ -170,3 +182,13 @@ def run_pex(name, gds_name, sp_name, output=None): """Run pex on a given top-level name which is implemented in gds_name and sp_name. """ debug.error("PEX extraction not implemented with Assura.",-1) + + global num_pex_runs + num_pex_runs += 1 + +def print_drc_stats(): + debug.info(1,"DRC runs: {0}".format(num_drc_runs)) +def print_lvs_stats(): + debug.info(1,"LVS runs: {0}".format(num_lvs_runs)) +def print_pex_stats(): + debug.info(1,"PEX runs: {0}".format(num_pex_runs)) diff --git a/compiler/verify/calibre.py b/compiler/verify/calibre.py index 38e92a2c..a7cd9290 100644 --- a/compiler/verify/calibre.py +++ b/compiler/verify/calibre.py @@ -65,10 +65,17 @@ import debug from globals import OPTS import subprocess +# Keep track of statistics +num_drc_runs = 0 +num_lvs_runs = 0 +num_pex_runs = 0 def run_drc(cell_name, gds_name): """Run DRC check on a given top-level name which is implemented in gds_name.""" + + global num_drc_runs + num_drc_runs += 1 # the runset file contains all the options to run calibre from tech import drc @@ -141,7 +148,10 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): """Run LVS check on a given top-level name which is implemented in gds_name and sp_name. Final verification will ensure that there are no remaining virtual conections. """ - + + global num_lvs_runs + num_lvs_runs += 1 + from tech import drc lvs_rules = drc["lvs_rules"] lvs_runset = { @@ -258,6 +268,10 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): def run_pex(cell_name, gds_name, sp_name, output=None): """Run pex on a given top-level name which is implemented in gds_name and sp_name. """ + + global num_pex_runs + num_pex_runs += 1 + from tech import drc if output == None: output = name + ".pex.netlist" @@ -354,3 +368,10 @@ def correct_port(name, output_file_name, ref_file_name): output_file.write(circuit_title) output_file.write(part2) output_file.close() + +def print_drc_stats(): + debug.info(1,"DRC runs: {0}".format(num_drc_runs)) +def print_lvs_stats(): + debug.info(1,"LVS runs: {0}".format(num_lvs_runs)) +def print_pex_stats(): + debug.info(1,"PEX runs: {0}".format(num_pex_runs)) diff --git a/compiler/verify/magic.py b/compiler/verify/magic.py index f438bad8..319d159a 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -64,6 +64,11 @@ import debug from globals import OPTS import subprocess +# Keep track of statistics +num_drc_runs = 0 +num_lvs_runs = 0 +num_pex_runs = 0 + def write_magic_script(cell_name, gds_name, extract=False): """ Write a magic script to perform DRC and optionally extraction. """ @@ -148,6 +153,9 @@ def write_netgen_script(cell_name, sp_name): def run_drc(cell_name, gds_name, extract=False): """Run DRC check on a cell which is implemented in gds_name.""" + global num_drc_runs + num_drc_runs += 1 + write_magic_script(cell_name, gds_name, extract) # run drc @@ -198,6 +206,9 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False): implemented in gds_name and sp_name. Final verification will ensure that there are no remaining virtual conections. """ + global num_lvs_runs + num_lvs_runs += 1 + run_drc(cell_name, gds_name, extract=True) write_netgen_script(cell_name, sp_name) @@ -270,6 +281,9 @@ def run_pex(name, gds_name, sp_name, output=None): """Run pex on a given top-level name which is implemented in gds_name and sp_name. """ + global num_pex_runs + num_pex_runs += 1 + debug.warning("PEX using magic not implemented.") return 1 @@ -337,3 +351,9 @@ def run_pex(name, gds_name, sp_name, output=None): return out_errors +def print_drc_stats(): + debug.info(1,"DRC runs: {0}".format(num_drc_runs)) +def print_lvs_stats(): + debug.info(1,"LVS runs: {0}".format(num_lvs_runs)) +def print_pex_stats(): + debug.info(1,"PEX runs: {0}".format(num_pex_runs)) From 265b5d977a0acd6ec8703f465e3c695944518776 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 11 Jul 2018 12:00:15 -0700 Subject: [PATCH 23/25] Fix option reload problems and checkpointing so that it works properly. --- compiler/characterizer/__init__.py | 9 ++++++--- compiler/globals.py | 14 +++++++++++--- compiler/tests/02_library_lvs_test.py | 2 +- compiler/tests/21_hspice_delay_test.py | 2 +- compiler/tests/21_hspice_setuphold_test.py | 2 -- compiler/tests/21_ngspice_delay_test.py | 1 - compiler/tests/22_pex_test.py | 13 +++++++++++-- compiler/tests/30_openram_test.py | 3 --- 8 files changed, 30 insertions(+), 16 deletions(-) diff --git a/compiler/characterizer/__init__.py b/compiler/characterizer/__init__.py index 6930a112..dc9398d0 100644 --- a/compiler/characterizer/__init__.py +++ b/compiler/characterizer/__init__.py @@ -1,16 +1,18 @@ import os import debug +import globals from globals import OPTS,find_exe,get_tool from .lib import * from .delay import * from .setup_hold import * -debug.info(2,"Initializing characterizer...") - +debug.info(1,"Initializing characterizer...") OPTS.spice_exe = "" if not OPTS.analytical_delay: + debug.info(1, "Finding spice simulator.") + if OPTS.spice_name != "": OPTS.spice_exe=find_exe(OPTS.spice_name) if OPTS.spice_exe=="": @@ -24,6 +26,7 @@ if not OPTS.analytical_delay: if OPTS.spice_exe == "": debug.error("No recognizable spice version found. Unable to perform characterization.",1) - +else: + debug.info(1,"Analytical model enabled.") diff --git a/compiler/globals.py b/compiler/globals.py index 8c305664..90f85f70 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -155,7 +155,7 @@ def read_config(config_file, is_unit_test=True): # If a unit test fails, we don't have to worry about restoring the old config values # that may have been tested. if is_unit_test and CHECKPOINT_OPTS: - OPTS = copy.deepcopy(CHECKPOINT_OPTS) + OPTS.__dict__ = CHECKPOINT_OPTS.__dict__.copy() return # Create a full path relative to current dir unless it is already an abs path @@ -213,12 +213,17 @@ def read_config(config_file, is_unit_test=True): # Make a checkpoint of the options so we can restore # after each unit test - CHECKPOINT_OPTS = copy.deepcopy(OPTS) - + if not CHECKPOINT_OPTS: + CHECKPOINT_OPTS = copy.copy(OPTS) def end_openram(): """ Clean up openram for a proper exit """ cleanup_paths() + + import verify + verify.print_drc_stats() + verify.print_lvs_stats() + verify.print_pex_stats() @@ -227,6 +232,7 @@ def cleanup_paths(): """ We should clean up the temp directory after execution. """ + global OPTS if not OPTS.purge_temp: debug.info(0,"Preserving temp directory: {}".format(OPTS.openram_temp)) return @@ -341,6 +347,8 @@ def print_time(name, now_time, last_time=None): def report_status(): """ Check for valid arguments and report the info about the SRAM being generated """ + global OPTS + # Check if all arguments are integers for bits, size, banks if type(OPTS.word_size)!=int: debug.error("{0} is not an integer in config file.".format(OPTS.word_size)) diff --git a/compiler/tests/02_library_lvs_test.py b/compiler/tests/02_library_lvs_test.py index d85f284e..0b35f159 100755 --- a/compiler/tests/02_library_lvs_test.py +++ b/compiler/tests/02_library_lvs_test.py @@ -14,7 +14,7 @@ class library_lvs_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) import verify - OPTS.check_lvsdrc=True + (gds_dir, sp_dir, allnames) = setup_files() lvs_errors = 0 debug.info(1, "Performing LVS on: " + ", ".join(allnames)) diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index b170b072..289f3934 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -17,6 +17,7 @@ class timing_sram_test(openram_test): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) OPTS.spice_name="hspice" OPTS.analytical_delay = False + # This is a hack to reload the characterizer __init__ with the spice version from importlib import reload @@ -83,7 +84,6 @@ class timing_sram_test(openram_test): else: self.isclose(data[k],golden_data[k],0.15) - reload(characterizer) globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/21_hspice_setuphold_test.py b/compiler/tests/21_hspice_setuphold_test.py index 5c4f72a6..f9d8a01c 100755 --- a/compiler/tests/21_hspice_setuphold_test.py +++ b/compiler/tests/21_hspice_setuphold_test.py @@ -26,7 +26,6 @@ class timing_setup_test(openram_test): if not OPTS.spice_exe: debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1) - import sram import tech slews = [tech.spice["rise_time"]*2] @@ -58,7 +57,6 @@ class timing_setup_test(openram_test): else: self.isclose(data[k],golden_data[k],0.15) - reload(characterizer) globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 36e0c0d0..739d63ea 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -83,7 +83,6 @@ class timing_sram_test(openram_test): else: self.isclose(data[k],golden_data[k],0.15) - reload(characterizer) globals.end_openram() # instantiate a copdsay of the class to actually run the test diff --git a/compiler/tests/22_pex_test.py b/compiler/tests/22_pex_test.py index 1ccf6cfe..24cb7733 100755 --- a/compiler/tests/22_pex_test.py +++ b/compiler/tests/22_pex_test.py @@ -16,6 +16,17 @@ class sram_func_test(openram_test): def runTest(self): globals.init_openram("config_20_{0}".format(OPTS.tech_name)) + + OPTS.use_pex = True + + # This is a hack to reload the characterizer __init__ with the spice version + from importlib import reload + import characterizer + reload(characterizer) + from characterizer import setup_hold + if not OPTS.spice_exe: + debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1) + global verify import verify @@ -31,8 +42,6 @@ class sram_func_test(openram_test): import tech debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") - global OPTS - OPTS.use_pex = True s = sram.sram(word_size=OPTS.word_size, num_words=OPTS.num_words, num_banks=OPTS.num_banks, diff --git a/compiler/tests/30_openram_test.py b/compiler/tests/30_openram_test.py index df480fdc..51546ae3 100755 --- a/compiler/tests/30_openram_test.py +++ b/compiler/tests/30_openram_test.py @@ -73,10 +73,7 @@ class openram_test(openram_test): shutil.rmtree(out_path, ignore_errors=True) self.assertEqual(os.path.exists(out_path),False) - # The default was on, so disable it. - OPTS.check_lvsdrc=False globals.end_openram() - OPTS.check_lvsdrc=True # instantiate a copy of the class to actually run the test if __name__ == "__main__": From 8a530da2ccb71164d28d34adbd0fbd248b5fc3a0 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 11 Jul 2018 12:07:37 -0700 Subject: [PATCH 24/25] Remove extra conversion to list --- compiler/tests/01_library_drc_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/tests/01_library_drc_test.py b/compiler/tests/01_library_drc_test.py index b4d35a5f..b809c14d 100755 --- a/compiler/tests/01_library_drc_test.py +++ b/compiler/tests/01_library_drc_test.py @@ -18,7 +18,7 @@ class library_drc_test(openram_test): (gds_dir, gds_files) = setup_files() drc_errors = 0 debug.info(1, "\nPerforming DRC on: " + ", ".join(gds_files)) - for f in list(gds_files): + for f in gds_files: name = re.sub('\.gds$', '', f) gds_name = "{0}/{1}".format(gds_dir, f) if not os.path.isfile(gds_name): From 7d8352a04d4f1f1e33609ac72ea93420fa16804f Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 11 Jul 2018 12:12:03 -0700 Subject: [PATCH 25/25] Fix order of checkpointing so that it is done after characterizer and verify have found their executables. --- compiler/globals.py | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/compiler/globals.py b/compiler/globals.py index 90f85f70..34cfbe08 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -105,6 +105,7 @@ def check_versions(): def init_openram(config_file, is_unit_test=True): """Initialize the technology, paths, simulators, etc.""" + check_versions() debug.info(1,"Initializing OpenRAM...") @@ -119,6 +120,26 @@ def init_openram(config_file, is_unit_test=True): import hierarchy_design hierarchy_design.hierarchy_design.name_map=[] + global OPTS + global CHECKPOINT_OPTS + + # This is a hack. If we are running a unit test and have checkpointed + # the options, load them rather than reading the config file. + # This way, the configuration is reloaded at the start of every unit test. + # If a unit test fails, we don't have to worry about restoring the old config values + # that may have been tested. + if is_unit_test and CHECKPOINT_OPTS: + OPTS.__dict__ = CHECKPOINT_OPTS.__dict__.copy() + return + + # Import these to find the executables for checkpointing + import characterizer + import verify + # Make a checkpoint of the options so we can restore + # after each unit test + if not CHECKPOINT_OPTS: + CHECKPOINT_OPTS = copy.copy(OPTS) + def get_tool(tool_type, preferences): @@ -147,16 +168,6 @@ def read_config(config_file, is_unit_test=True): reads will just restore the previous copy (ask mrg) """ global OPTS - global CHECKPOINT_OPTS - - # This is a hack. If we are running a unit test and have checkpointed - # the options, load them rather than reading the config file. - # This way, the configuration is reloaded at the start of every unit test. - # If a unit test fails, we don't have to worry about restoring the old config values - # that may have been tested. - if is_unit_test and CHECKPOINT_OPTS: - OPTS.__dict__ = CHECKPOINT_OPTS.__dict__.copy() - return # Create a full path relative to current dir unless it is already an abs path if not os.path.isabs(config_file): @@ -211,10 +222,6 @@ def read_config(config_file, is_unit_test=True): except: debug.error("Unable to make output directory.",-1) - # Make a checkpoint of the options so we can restore - # after each unit test - if not CHECKPOINT_OPTS: - CHECKPOINT_OPTS = copy.copy(OPTS) def end_openram(): """ Clean up openram for a proper exit """