diff --git a/compiler/characterizer/lib.py b/compiler/characterizer/lib.py index 03d9961e..436ee301 100644 --- a/compiler/characterizer/lib.py +++ b/compiler/characterizer/lib.py @@ -526,15 +526,15 @@ class lib: for (corner, lib_name) in zip(self.corners, self.lib_files): - ports = "" - if OPTS.num_rw_ports>0: - ports += "{}_".format(OPTS.num_rw_ports) - if OPTS.num_w_ports>0: - ports += "{}_".format(OPTS.num_w_ports) - if OPTS.num_r_ports>0: - ports += "{}_".format(OPTS.num_r_ports) +# ports = "" +# if OPTS.num_rw_ports>0: +# ports += "{}_".format(OPTS.num_rw_ports) +# if OPTS.num_w_ports>0: +# ports += "{}_".format(OPTS.num_w_ports) +# if OPTS.num_r_ports>0: +# ports += "{}_".format(OPTS.num_r_ports) - datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12}".format("sram_{0}_{1}_{2}{3}".format(OPTS.word_size, OPTS.num_words, ports, OPTS.tech_name), + datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13}".format("sram_{0}_{1}_{2}".format(OPTS.word_size, OPTS.num_words, OPTS.tech_name), OPTS.num_words, OPTS.num_banks, OPTS.num_rw_ports, @@ -546,7 +546,8 @@ class lib: self.corner[0], round_time(self.char_sram_results["min_period"]), self.out_dir, - lib_name)) + lib_name, + OPTS.word_size)) datasheet.close() diff --git a/compiler/datasheet/assets/vlsi_logo.png b/compiler/datasheet/assets/vlsi_logo.png new file mode 100644 index 00000000..3f02a45e Binary files /dev/null and b/compiler/datasheet/assets/vlsi_logo.png differ diff --git a/compiler/datasheet/datasheet.py b/compiler/datasheet/datasheet.py index 396215a8..543c75fa 100644 --- a/compiler/datasheet/datasheet.py +++ b/compiler/datasheet/datasheet.py @@ -3,16 +3,21 @@ from operating_conditions import * from characterization_corners import * from deliverables import * from timing_and_current_data import * +from in_out import * +import os +from globals import OPTS class datasheet(): def __init__(self,identifier): + self.io = [] self.corners = [] self.timing = [] self.operating = [] self.dlv = [] self.name = identifier self.html = "" + def generate_html(self): self.html = """""" - self.html +='

{0}

' - self.html +='

{0}

' - self.html +='

{0}

' + self.html +='

'+ self.name + '.html' + '

' +# self.html +='

{0}

' +# self.html +='

{0}

' + + self.html +='

Ports and Configuration (DEBUG)

' + self.html += in_out(self.io,table_id='data').__html__().replace('<','<').replace('"','"').replace('>',">") + self.html +='

Operating Conditions

' self.html += operating_conditions(self.operating,table_id='data').__html__() + self.html += '

Timing and Current Data

' self.html += timing_and_current_data(self.timing,table_id='data').__html__() + self.html += '

Characterization Corners

' self.html += characterization_corners(self.corners,table_id='data').__html__() + self.html +='

Deliverables

' self.html += deliverables(self.dlv,table_id='data').__html__().replace('<','<').replace('"','"').replace('>',">") - + self.html +='

*Feature only supported with characterizer

' + + self.html +='VLSIDA' diff --git a/compiler/datasheet/datasheet_gen.py b/compiler/datasheet/datasheet_gen.py index 6bfb165f..e68e94df 100644 --- a/compiler/datasheet/datasheet_gen.py +++ b/compiler/datasheet/datasheet_gen.py @@ -8,17 +8,24 @@ Locate all timing elements in .lib Diagram generation Improve css """ - -import os, math -import optparse -from flask_table import * -import csv +import debug from globals import OPTS -from deliverables import * -from operating_conditions import * -from timing_and_current_data import * -from characterization_corners import * -from datasheet import * + +if OPTS.datasheet_gen: + import flask_table + import os, math + import optparse + import csv + from deliverables import * + from operating_conditions import * + from timing_and_current_data import * + from characterization_corners import * + from datasheet import * + from in_out import * +else: + debug.warning("Python library flask_table not found. Skipping html datasheet generation. This can be installed with pip install flask-table.") + + def process_name(corner): if corner == "TT": @@ -43,12 +50,13 @@ def parse_file(f,pages): NUM_W_PORTS = row[4] NUM_R_PORTS = row[5] TECH_NAME = row[6] - TEMP = row[7] - VOLT = row[8] + TEMP = row[8] + VOLT = row[7] PROC = row[9] MIN_PERIOD = row[10] OUT_DIR = row[11] LIB_NAME = row[12] + WORD_SIZE = row[13] for sheet in pages: @@ -95,39 +103,55 @@ def parse_file(f,pages): new_sheet.operating.append(operating_conditions_item('Power supply (VDD) range',VOLT,VOLT,VOLT,'Volts')) new_sheet.operating.append(operating_conditions_item('Operating Temperature',TEMP,TEMP,TEMP,'Celsius')) try: - new_sheet.operating.append(operating_conditions_item('Operating Frequency (F)','','',str(math.floor(1000/float(MIN_PERIOD))),'MHz')) + new_sheet.operating.append(operating_conditions_item('Operating Frequency (F)*','','',str(math.floor(1000/float(MIN_PERIOD))),'MHz')) except Exception: - new_sheet.operating.append(operating_conditions_item('Operating Frequency (F)','','',"unknown",'MHz')) #analytical model fails to provide MIN_PERIOD + new_sheet.operating.append(operating_conditions_item('Operating Frequency (F)*','','',"unknown",'MHz')) #analytical model fails to provide MIN_PERIOD - + new_sheet.timing.append(timing_and_current_data_item('Cycle time','2','3','4')) + new_sheet.timing.append(timing_and_current_data_item('Access time','2','3','4')) + new_sheet.timing.append(timing_and_current_data_item('Positive clk setup','2','3','4')) + new_sheet.timing.append(timing_and_current_data_item('Positive clk hold','2','3','4')) + new_sheet.timing.append(timing_and_current_data_item('RW setup','2','3','4')) + new_sheet.timing.append(timing_and_current_data_item('RW hold','2','3','4')) + new_sheet.timing.append(timing_and_current_data_item('AC current','2','3','4')) + new_sheet.timing.append(timing_and_current_data_item('Standby current','2','3','4')) + new_sheet.timing.append(timing_and_current_data_item('Area','2','3','4')) - new_sheet.timing.append(timing_and_current_data_item('1','2','3','4')) - new_sheet.dlv.append(deliverables_item('.sp','SPICE netlists','{1}.{2}'.format(OUT_DIR,NAME,'sp'))) new_sheet.dlv.append(deliverables_item('.v','Verilog simulation models','{1}.{2}'.format(OUT_DIR,NAME,'v'))) new_sheet.dlv.append(deliverables_item('.gds','GDSII layout views','{1}.{2}'.format(OUT_DIR,NAME,'gds'))) new_sheet.dlv.append(deliverables_item('.lef','LEF files','{1}.{2}'.format(OUT_DIR,NAME,'lef'))) new_sheet.dlv.append(deliverables_item('.lib','Synthesis models','{1}'.format(LIB_NAME,LIB_NAME.replace(OUT_DIR,'')))) + + new_sheet.io.append(in_out_item('WORD_SIZE',WORD_SIZE)) + new_sheet.io.append(in_out_item('NUM_WORDS',NUM_WORDS)) + new_sheet.io.append(in_out_item('NUM_BANKS',NUM_BANKS)) + new_sheet.io.append(in_out_item('NUM_RW_PORTS',NUM_RW_PORTS)) + new_sheet.io.append(in_out_item('NUM_R_PORTS',NUM_R_PORTS)) + new_sheet.io.append(in_out_item('NUM_W_PORTS',NUM_W_PORTS)) + + class datasheet_gen(): def datasheet_write(name): - - in_dir = OPTS.openram_temp - if not (os.path.isdir(in_dir)): - os.mkdir(in_dir) + if OPTS.datasheet_gen: + in_dir = OPTS.openram_temp + + if not (os.path.isdir(in_dir)): + os.mkdir(in_dir) - #if not (os.path.isdir(out_dir)): - # os.mkdir(out_dir) + #if not (os.path.isdir(out_dir)): + # os.mkdir(out_dir) - datasheets = [] - parse_file(in_dir + "/datasheet.info", datasheets) + datasheets = [] + parse_file(in_dir + "/datasheet.info", datasheets) - for sheets in datasheets: - with open(name, 'w+') as f: - sheets.generate_html() - f.write(sheets.html) + for sheets in datasheets: + with open(name, 'w+') as f: + sheets.generate_html() + f.write(sheets.html) diff --git a/compiler/datasheet/in_out.py b/compiler/datasheet/in_out.py new file mode 100644 index 00000000..f656dba6 --- /dev/null +++ b/compiler/datasheet/in_out.py @@ -0,0 +1,11 @@ +from flask_table import * + +class in_out(Table): + typ = Col('Type') + description = Col('Description') + + +class in_out_item(object): + def __init__(self, typ, description): + self.typ = typ + self.description = description diff --git a/compiler/globals.py b/compiler/globals.py index f19559e2..11606bf2 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -100,9 +100,17 @@ def check_versions(): minor_required = 5 if not (major_python_version == major_required and minor_python_version >= minor_required): debug.error("Python {0}.{1} or greater is required.".format(major_required,minor_required),-1) - + # FIXME: Check versions of other tools here?? # or, this could be done in each module (e.g. verify, characterizer, etc.) + global OPTS + + try: + import flask_table + OPTS.datasheet_gen = 1 + except: + OPTS.datasheet_gen = 0 + def init_openram(config_file, is_unit_test=True): """Initialize the technology, paths, simulators, etc.""" diff --git a/compiler/openram.py b/compiler/openram.py index 6fc6ec71..2163ae5c 100755 --- a/compiler/openram.py +++ b/compiler/openram.py @@ -40,7 +40,9 @@ import verify from sram import sram from sram_config import sram_config #from parser import * -output_extensions = ["sp","v","lib","html"] +output_extensions = ["sp","v","lib"] +if OPTS.datasheet_gen: + output_extensions.append("html") if not OPTS.netlist_only: output_extensions.extend(["gds","lef"]) output_files = ["{0}.{1}".format(OPTS.output_name,x) for x in output_extensions]