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
| Type | Description | Link |
|---|
|
'
+ with open(file, 'r+') as f:
+
+ file_string = f.read()
+ start_byte = file_string.find(start_tag) + len(start_tag)
+ row = '
| .db | Compiled .lib file | '+str(os.path.basename(db))+' |
'
+ 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| Type | Description | Link |
|---|
|
'
- 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 = '
| .db | Compiled .lib file | '+str(os.path.basename(db))+' |
'
- 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 += '
'.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 += '| ' + str(col) + ' | '
- html += '
'
+
+ if row[0] not in comments:
+ html += ''
+ for col in row:
+ html += '| ' + str(col) + ' | '
+ 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 += ''
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]}