From 3802c537e51164c15895752eda4b8de426c6d678 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Wed, 27 Feb 2019 22:19:03 -0800 Subject: [PATCH 1/6] added add_db.py to add .db files to datasheets --- compiler/datasheet/add_db.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 compiler/datasheet/add_db.py diff --git a/compiler/datasheet/add_db.py b/compiler/datasheet/add_db.py new file mode 100644 index 00000000..1df3cf7b --- /dev/null +++ b/compiler/datasheet/add_db.py @@ -0,0 +1,34 @@ +from pathlib import Path +import glob +import os + +# This is the path to the directory you would like to search +# This directory is searched recursively for .html files + +path_to_files = '../temp/' + + +def get_file_tree(path): + return list(Path(path).rglob("*.html")) + + +def parse_html(file, db): + start_tag = 'Deliverables

' + with open(file, 'r+') as f: + + file_string = f.read() + start_byte = file_string.find(start_tag) + len(start_tag) + row = '' + file_string = "%s%s%s" % ( + file_string[:start_byte], row, file_string[start_byte:]) + f.seek(0) + f.write(file_string) + + +datasheet_list = get_file_tree(path_to_files) +for datasheet in datasheet_list: + if glob.glob(os.path.dirname(datasheet)+'/*.db'): + db_files = list(Path(os.path.dirname(datasheet)).rglob("*.db")) + for db_file in db_files: + parse_html(datasheet, db_file) From fac9ff9be632ccd9118d771b825aa89a114ef0d3 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Wed, 6 Mar 2019 20:59:52 -0800 Subject: [PATCH 2/6] changed add_db.py to uncommenting method --- compiler/datasheet/add_db.py | 47 ++++++++++++++++++++--------- compiler/datasheet/datasheet.py | 15 +++++---- compiler/datasheet/datasheet_gen.py | 5 +++ compiler/datasheet/table_gen.py | 25 ++++++++++----- 4 files changed, 63 insertions(+), 29 deletions(-) diff --git a/compiler/datasheet/add_db.py b/compiler/datasheet/add_db.py index 1df3cf7b..f0f69fc7 100644 --- a/compiler/datasheet/add_db.py +++ b/compiler/datasheet/add_db.py @@ -12,23 +12,40 @@ def get_file_tree(path): return list(Path(path).rglob("*.html")) -def parse_html(file, db): - start_tag = 'Deliverables

TypeDescriptionLink
.dbCompiled .lib file'+str(os.path.basename(db))+'
' - with open(file, 'r+') as f: +def parse_html(file, comment): + start_tag = '' + with open(file, 'r+') as f: file_string = f.read() - start_byte = file_string.find(start_tag) + len(start_tag) - row = '' - file_string = "%s%s%s" % ( - file_string[:start_byte], row, file_string[start_byte:]) - f.seek(0) - f.write(file_string) + start_byte = file_string.find(start_tag) + while(start_byte != -1): + f.seek(0) + file_string = f.read() + start_byte = file_string.find(start_tag) + end_byte = file_string.find(end_tag) + start_byte + len(end_tag) + + f.seek(start_byte) + found = f.read(end_byte - start_byte) + + file_string = "%s%s%s" % ( + file_string[:start_byte], found[len(start_tag):len(found)-len(end_tag)] , file_string[end_byte:]) + + f.seek(0) + f.write(file_string) + start_byte = file_string.find(start_tag) + end_byte = file_string.find(end_tag) + start_byte + len(end_tag) + +def uncomment(comments): + for datasheet in datasheet_list: + for comment in comments: + if glob.glob(os.path.dirname(datasheet)+'/*' + comment): + comment_files = list(Path(os.path.dirname(datasheet)).rglob('*'+comment)) + for comment_file in comment_files: + parse_html(datasheet, comment) datasheet_list = get_file_tree(path_to_files) -for datasheet in datasheet_list: - if glob.glob(os.path.dirname(datasheet)+'/*.db'): - db_files = list(Path(os.path.dirname(datasheet)).rglob("*.db")) - for db_file in db_files: - parse_html(datasheet, db_file) +comments = ['.db'] +uncomment(comments) + diff --git a/compiler/datasheet/datasheet.py b/compiler/datasheet/datasheet.py index a7700349..a21d3dae 100644 --- a/compiler/datasheet/datasheet.py +++ b/compiler/datasheet/datasheet.py @@ -38,6 +38,9 @@ class datasheet(): with open(os.path.abspath(os.environ.get("OPENRAM_HOME")) + '/datasheet/assets/OpenRAM_logo.png', "rb") as image_file: openram_logo = base64.b64encode(image_file.read()) + #comment table rows which we may want to enable after compile time + comments = ['.db'] + self.html += 'VLSIDAOpenRAM'.format(str(vlsi_logo)[2:-1], str(openram_logo)[2:-1]) self.html += '

' + \ @@ -51,11 +54,11 @@ class datasheet(): 'Git commit id: ' + str(self.git_id) + '

' # print port table self.html += '

Ports and Configuration

' - self.html += self.io_table.to_html() + self.html += self.io_table.to_html(comments) # print operating condidition information self.html += '

Operating Conditions

' - self.html += self.operating_table.to_html() + self.html += self.operating_table.to_html(comments) # check if analytical model is being used self.html += '

Timing Data

' @@ -66,13 +69,13 @@ class datasheet(): model = "spice characterizer" # display timing data self.html += '

Using '+model+'

' - self.html += self.timing_table.to_html() + self.html += self.timing_table.to_html(comments) # display power data self.html += '

Power Data

' - self.html += self.power_table.to_html() + self.html += self.power_table.to_html(comments) # display corner information self.html += '

Characterization Corners

' - self.html += self.corners_table.to_html() + self.html += self.corners_table.to_html(comments) # display deliverables table self.html += '

Deliverables

' - self.html += self.dlv_table.to_html() + self.html += self.dlv_table.to_html(comments) diff --git a/compiler/datasheet/datasheet_gen.py b/compiler/datasheet/datasheet_gen.py index 3b4fe2ac..e6c728f0 100644 --- a/compiler/datasheet/datasheet_gen.py +++ b/compiler/datasheet/datasheet_gen.py @@ -386,6 +386,9 @@ def parse_characterizer_csv(f, pages): [PROC, VOLT, TEMP, LIB_NAME.replace(OUT_DIR, '').replace(NAME, '')]) new_sheet.dlv_table.add_row( ['.lib', 'Synthesis models', '{1}'.format(LIB_NAME, LIB_NAME.replace(OUT_DIR, ''))]) + new_sheet.dlv_table.add_row( + ['.db', 'Compiled .lib', '{1}'.format(LIB_NAME[:-3] + 'db', LIB_NAME.replace(OUT_DIR, '')[:-3] + 'db')]) + if found == 0: @@ -603,6 +606,8 @@ def parse_characterizer_csv(f, pages): ['.html', 'This datasheet', '{0}.{1}'.format(OPTS.output_name, 'html')]) new_sheet.dlv_table.add_row( ['.lib', 'Synthesis models', '{1}'.format(LIB_NAME, LIB_NAME.replace(OUT_DIR, ''))]) + new_sheet.dlv_table.add_row( + ['.db', 'Compiled .lib', '{1}'.format(LIB_NAME[:-3] + 'db', LIB_NAME.replace(OUT_DIR, '')[:-3] + 'db')]) new_sheet.dlv_table.add_row( ['.py', 'OpenRAM configuration file', '{0}.{1}'.format(OPTS.output_name, 'py')]) new_sheet.dlv_table.add_row( diff --git a/compiler/datasheet/table_gen.py b/compiler/datasheet/table_gen.py index 8f94e896..a03fea8c 100644 --- a/compiler/datasheet/table_gen.py +++ b/compiler/datasheet/table_gen.py @@ -22,27 +22,36 @@ class table_gen: html += '' return html - def gen_table_body(self): + def gen_table_body(self,comments): """generate html body (used after gen_table_head)""" html = '' html += '' html += '' for row in self.rows[1:]: - html += '' - for col in row: - html += '' - html += '' + + if row[0] not in comments: + html += '' + for col in row: + html += '' + html += '' + + else: + html += '' + html += '' html += '' return html - def to_html(self): + def to_html(self,comments): """writes table_gen object to inline html""" html = '' html += '
TypeDescriptionLink
.dbCompiled .lib file'+str(os.path.basename(db))+'
' + str(col) + '
' + str(col) + '
' html += self.gen_table_head() - html += self.gen_table_body() - html += '
' + html += self.gen_table_body(comments) + html += '\n' return html From 83e810f8b89fde9144c916954a980aa70f3ca89c Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Wed, 6 Mar 2019 21:12:21 -0800 Subject: [PATCH 3/6] added sorting to deliverables output --- compiler/datasheet/datasheet.py | 1 + compiler/datasheet/table_gen.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/compiler/datasheet/datasheet.py b/compiler/datasheet/datasheet.py index a21d3dae..b48d217d 100644 --- a/compiler/datasheet/datasheet.py +++ b/compiler/datasheet/datasheet.py @@ -78,4 +78,5 @@ class datasheet(): self.html += self.corners_table.to_html(comments) # display deliverables table self.html += '

Deliverables

' + self.dlv_table.sort() self.html += self.dlv_table.to_html(comments) diff --git a/compiler/datasheet/table_gen.py b/compiler/datasheet/table_gen.py index a03fea8c..82cb3393 100644 --- a/compiler/datasheet/table_gen.py +++ b/compiler/datasheet/table_gen.py @@ -45,6 +45,8 @@ class table_gen: html += '' html += '' return html + def sort(self): + self.rows[1:] = sorted(self.rows[1:], key=lambda x : x[0]) def to_html(self,comments): """writes table_gen object to inline html""" From c1770036aca72ef91515df4736127567fce80eaf Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Wed, 6 Mar 2019 22:20:07 -0800 Subject: [PATCH 4/6] made the add_db code much simpler --- compiler/datasheet/add_db.py | 33 +++++++++++---------------------- compiler/datasheet/table_gen.py | 2 +- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/compiler/datasheet/add_db.py b/compiler/datasheet/add_db.py index f0f69fc7..d708985f 100644 --- a/compiler/datasheet/add_db.py +++ b/compiler/datasheet/add_db.py @@ -14,36 +14,25 @@ def get_file_tree(path): def parse_html(file, comment): start_tag = '' + end_tag = comment+'-->' - with open(file, 'r+') as f: + with open(file, 'r') as f: + file_string = f.read() - start_byte = file_string.find(start_tag) - while(start_byte != -1): - f.seek(0) - file_string = f.read() - start_byte = file_string.find(start_tag) - end_byte = file_string.find(end_tag) + start_byte + len(end_tag) - - f.seek(start_byte) - found = f.read(end_byte - start_byte) - - file_string = "%s%s%s" % ( - file_string[:start_byte], found[len(start_tag):len(found)-len(end_tag)] , file_string[end_byte:]) - - f.seek(0) - f.write(file_string) - start_byte = file_string.find(start_tag) - end_byte = file_string.find(end_tag) + start_byte + len(end_tag) + with open(file, 'w') as f: + file_string = file_string.replace(start_tag,"") + file_string = file_string.replace(end_tag,"") + + f.write(file_string) + def uncomment(comments): + comment_files = [] for datasheet in datasheet_list: for comment in comments: if glob.glob(os.path.dirname(datasheet)+'/*' + comment): - comment_files = list(Path(os.path.dirname(datasheet)).rglob('*'+comment)) - for comment_file in comment_files: - parse_html(datasheet, comment) + parse_html(datasheet, comment) datasheet_list = get_file_tree(path_to_files) comments = ['.db'] diff --git a/compiler/datasheet/table_gen.py b/compiler/datasheet/table_gen.py index 82cb3393..227bb5c4 100644 --- a/compiler/datasheet/table_gen.py +++ b/compiler/datasheet/table_gen.py @@ -40,7 +40,7 @@ class table_gen: html += '' + html += ''+row[0]+'-->' html += '' html += '' From 4754e6851d20db5454e00c6620fa9908e34da266 Mon Sep 17 00:00:00 2001 From: Jesse Cirimelli-Low Date: Wed, 6 Mar 2019 22:21:05 -0800 Subject: [PATCH 5/6] add_db takes commline line argv for path --- compiler/datasheet/add_db.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/datasheet/add_db.py b/compiler/datasheet/add_db.py index d708985f..862c1d8a 100644 --- a/compiler/datasheet/add_db.py +++ b/compiler/datasheet/add_db.py @@ -1,11 +1,12 @@ from pathlib import Path import glob import os +import sys # This is the path to the directory you would like to search # This directory is searched recursively for .html files -path_to_files = '../temp/' +path_to_files = sys.argv[1] def get_file_tree(path): From 910878ed30ed65aec2ec8ef787a8cba3b8c70bd7 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Thu, 7 Mar 2019 12:30:27 -0800 Subject: [PATCH 6/6] Removed bitline measures until hardcoded signal names are made dynamic --- compiler/characterizer/delay.py | 18 +++++++++--------- compiler/tests/21_hspice_delay_test.py | 12 ++---------- compiler/tests/21_ngspice_delay_test.py | 12 ++---------- 3 files changed, 13 insertions(+), 29 deletions(-) diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 29b12ae9..9c15cd2a 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -42,8 +42,8 @@ class delay(simulation): #Altering the names will crash the characterizer. TODO: object orientated approach to the measurements. self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"] self.power_meas_names = ["read0_power", "read1_power", "write0_power", "write1_power"] - self.voltage_when_names = ["volt_bl", "volt_br"] - self.bitline_delay_names = ["delay_bl", "delay_br"] + #self.voltage_when_names = ["volt_bl", "volt_br"] + #self.bitline_delay_names = ["delay_bl", "delay_br"] def create_measurement_objects(self): """Create the measurements used for read and write ports""" @@ -84,8 +84,8 @@ class delay(simulation): bl_name = "Xsram.Xbank0.bl{}_{}".format(port_format, self.bitline_column) br_name = "Xsram.Xbank0.br{}_{}".format(port_format, self.bitline_column) - self.read_meas_objs.append(voltage_when_measure(self.voltage_when_names[0], trig_name, bl_name, "RISE", .5)) - self.read_meas_objs.append(voltage_when_measure(self.voltage_when_names[1], trig_name, br_name, "RISE", .5)) + # self.read_meas_objs.append(voltage_when_measure(self.voltage_when_names[0], trig_name, bl_name, "RISE", .5)) + # self.read_meas_objs.append(voltage_when_measure(self.voltage_when_names[1], trig_name, br_name, "RISE", .5)) #These are read values but need to be separated for unique error checking. self.create_bitline_delay_measurement_objects() @@ -105,10 +105,10 @@ class delay(simulation): targ_val = (self.vdd_voltage - tech.spice["v_threshold_typical"])/self.vdd_voltage #Calculate as a percentage of vdd targ_name = "{0}{1}_{2}".format(self.dout_name,"{}",self.probe_data) #Empty values are the port and probe data bit - self.bitline_delay_objs.append(delay_measure(self.bitline_delay_names[0], trig_name, bl_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9)) - self.bitline_delay_objs[-1].meta_str = "read0" - self.bitline_delay_objs.append(delay_measure(self.bitline_delay_names[1], trig_name, br_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9)) - self.bitline_delay_objs[-1].meta_str = "read1" + # self.bitline_delay_objs.append(delay_measure(self.bitline_delay_names[0], trig_name, bl_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9)) + # self.bitline_delay_objs[-1].meta_str = "read0" + # self.bitline_delay_objs.append(delay_measure(self.bitline_delay_names[1], trig_name, br_name, "FALL", "FALL", targ_vdd=targ_val, measure_scale=1e9)) + # self.bitline_delay_objs[-1].meta_str = "read1" #Enforces the time delay on the bitline measurements for read0 or read1 for obj in self.bitline_delay_objs: obj.meta_add_delay = True @@ -966,7 +966,7 @@ class delay(simulation): def get_empty_measure_data_dict(self): """Make a dict of lists for each type of delay and power measurement to append results to""" - measure_names = self.delay_meas_names + self.power_meas_names + self.voltage_when_names + self.bitline_delay_names + measure_names = self.delay_meas_names + self.power_meas_names #Create list of dicts. List lengths is # of ports. Each dict maps the measurement names to lists. measure_data = [{mname:[] for mname in measure_names} for i in self.all_ports] return measure_data diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index fa7fc35f..8808b868 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -51,9 +51,7 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_bl': [0.1980959], - 'delay_br': [0.1946091], - 'delay_hl': [0.2121267], + golden_data = {'delay_hl': [0.2121267], 'delay_lh': [0.2121267], 'leakage_power': 0.0023761999999999998, 'min_period': 0.43, @@ -61,14 +59,10 @@ class timing_sram_test(openram_test): 'read1_power': [0.48940979999999995], 'slew_hl': [0.0516745], 'slew_lh': [0.0516745], - 'volt_bl': [0.5374525], - 'volt_br': [1.1058], 'write0_power': [0.46267169999999996], 'write1_power': [0.4670826]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_bl': [1.1029], - 'delay_br': [0.9656455999999999], - 'delay_hl': [1.288], + golden_data = {'delay_hl': [1.288], 'delay_lh': [1.288], 'leakage_power': 0.0273896, 'min_period': 2.578, @@ -76,8 +70,6 @@ class timing_sram_test(openram_test): 'read1_power': [16.2616], 'slew_hl': [0.47891700000000004], 'slew_lh': [0.47891700000000004], - 'volt_bl': [4.2155], - 'volt_br': [5.8142], 'write0_power': [16.0656], 'write1_power': [16.2616]} diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index 5af44e69..4548f836 100755 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -51,9 +51,7 @@ class timing_sram_test(openram_test): data.update(port_data[0]) if OPTS.tech_name == "freepdk45": - golden_data = {'delay_bl': [0.2003652], - 'delay_br': [0.198698], - 'delay_hl': [0.2108836], + golden_data = {'delay_hl': [0.2108836], 'delay_lh': [0.2108836], 'leakage_power': 0.001564799, 'min_period': 0.508, @@ -61,14 +59,10 @@ class timing_sram_test(openram_test): 'read1_power': [0.4198608], 'slew_hl': [0.0455126], 'slew_lh': [0.0455126], - 'volt_bl': [0.6472883], - 'volt_br': [1.114024], 'write0_power': [0.40681890000000004], 'write1_power': [0.4198608]} elif OPTS.tech_name == "scn4m_subm": - golden_data = {'delay_bl': [1.3937359999999999], - 'delay_br': [1.2596429999999998], - 'delay_hl': [1.5747600000000002], + golden_data = {'delay_hl': [1.5747600000000002], 'delay_lh': [1.5747600000000002], 'leakage_power': 0.00195795, 'min_period': 3.281, @@ -76,8 +70,6 @@ class timing_sram_test(openram_test): 'read1_power': [14.369810000000001], 'slew_hl': [0.49631959999999997], 'slew_lh': [0.49631959999999997], - 'volt_bl': [4.132618], - 'volt_br': [5.573099], 'write0_power': [13.79953], 'write1_power': [14.369810000000001]}