Skip to content

Commit

Permalink
initial functionality for HTML generation
Browse files Browse the repository at this point in the history
  • Loading branch information
gadfort committed Aug 5, 2023
1 parent 83a58a4 commit 7a67aa8
Show file tree
Hide file tree
Showing 7 changed files with 385 additions and 5 deletions.
7 changes: 5 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ requires-python = ">=3.6"
license = {file = "LICENSE"}
dependencies = [
"siliconcompiler>=0.13.0",
"GitPython>=3.1.0"
"GitPython>=3.1.0",
"Jinja2>=2.11.3"
]
dynamic = ["version"]

Expand All @@ -34,4 +35,6 @@ dev = [
"Bug Tracker" = "https://github.com/siliconcompiler/scgallery/issues"

[tool.poetry]
include = ["scgallery/designs/*", "scgallery/libraries/*"]
include = ["scgallery/designs/*",
"scgallery/libraries/*",
"scgallery/templates/*"]
5 changes: 4 additions & 1 deletion scgallery/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
__version__ = None

from .gallery import Gallery
import os
root = os.path.dirname(__file__)

__all__ = [
"Gallery"
"Gallery",
"root"
]
6 changes: 4 additions & 2 deletions scgallery/gallery.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,13 @@ def argparse(self):
)

parser.add_argument('-design',
action='append',
choices=sorted(self.__designs.keys()),
metavar='<design>',
help='Name of design to run')

parser.add_argument('-target',
action='append',
choices=sorted(self.__targets.keys()),
metavar='<target>',
help='Name of target to run')
Expand Down Expand Up @@ -129,12 +131,12 @@ def argparse(self):
self.set_remote(args.remote)

if args.target:
self.set_run_targets({args.target: self.__targets[args.target]})
self.set_run_targets({target: self.__targets[target] for target in args.target})
else:
self.set_run_targets(self.__targets)

if args.design:
self.set_run_designs({args.design: self.__designs[args.design]})
self.set_run_designs({design: self.__designs[design] for design in args.design})
else:
self.set_run_designs(self.__designs)

Expand Down
116 changes: 116 additions & 0 deletions scgallery/report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from jinja2 import Environment, FileSystemLoader
from scgallery import root
import os
import glob
import base64
import siliconcompiler

jinja2_env = Environment(loader=FileSystemLoader(os.path.join(root, 'templates')))
encoding = 'utf-8'


def __load_image(path):
if os.path.isfile(path):
with open(path, 'rb') as img_file:
return base64.b64encode(img_file.read()).decode(encoding)
return None


def __get_favicon():
return __load_image(os.path.join(os.path.dirname(siliconcompiler.__file__), 'data', 'logo.png'))


def generate_overview(images_data):
platforms = set()
designs = set()
data = {}
for image in images_data:
platforms.add(image['platform'])
designs.add(image['design'])

data.setdefault(image['platform'], {})[image['design']] = image
image['data'] = __load_image(image['path'])

with open('overview.html', 'w', encoding=encoding) as wf:
wf.write(jinja2_env.get_template('overview.html').render(
sc_version=siliconcompiler.__version__,
favicon=__get_favicon(),
platforms=sorted(list(platforms)),
designs=sorted(list(designs)),
images=data
))


def __generate_design_detail(chips):
views = {
"optimizer": {
"step": "export",
"index": "1",
"path": "reports/images/*.optimizer.png"
},
"routing": {
"step": "export",
"index": "1",
"path": "reports/images/*.routing.png"
},
"placement": {
"step": "export",
"index": "1",
"path": "reports/images/*.placement.png"
},
"clocks": {
"step": "export",
"index": "1",
"path": "reports/images/*.clocks.png"
}
}
platforms = set()

design = None

images_data = {}

for chip in chips:
design = chip.design
platform = chip.get('asic', 'logiclib')[0]
platforms.add(platform)

images_data[platform] = {}
for view, specs in views.items():
paths = glob.glob(os.path.join(chip._getworkdir(step=specs['step'],
index=specs['index']),
specs['path']))
if paths:
images_data[platform][view] = __load_image(paths[0])
else:
images_data[platform][view] = None

return jinja2_env.get_template('design_detailed.html').render(
sc_version=siliconcompiler.__version__,
favicon=__get_favicon(),
design=design,
platforms=sorted(list(platforms)),
views=list(views.keys()),
images=images_data)


def generate_details(chips):
designs = {}
for design_chips in chips:
for chip in design_chips:
designs.setdefault(chip.design, []).append(chip)

pages = {}
for design, design_chips in designs.items():
page_data = __generate_design_detail(design_chips)
pages[design] = base64.b64encode(bytes(page_data, encoding)).decode(encoding)
# pages[design] = "".join(page_data.splitlines())

design_set = sorted(list(designs.keys()))
with open('details.html', 'w', encoding=encoding) as wf:
wf.write(jinja2_env.get_template('details.html').render(
sc_version=siliconcompiler.__version__,
favicon=__get_favicon(),
initial_design=design_set[0],
designs=design_set,
pages=pages))
44 changes: 44 additions & 0 deletions scgallery/templates/design_detailed.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">

<head>
<title>SiliconCompiler Image Gallery {{ sc_version }} - {{ design }}</title>
{% if favicon %}
<link rel="icon" href="data:image/jpeg;base64,{{ favicon }}" type="image/x-icon">
{% endif %}
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
.rd-rotate {
writing-mode: vertical-rl;
text-orientation: upright;
}
</style>
</head>

<body>
<h1>{{ design }} gallery</h1>
<table class="image-table">
<tr align="center">
<th />
{% for platform in platforms %}
<th>{{ platform }}</th>
{% endfor %}
</tr>
{% for view in views %}
<tr valign="top">
<td class="rd-rotate">{{ view }}</td>
{% for platform in platforms %}
<td>
{% if view in images[platform] and images[platform][view] %}
<img src="data:image/jpeg;base64,{{ images[platform][view] }}"
alt="{{ platform }} - {{ view }}"
width="100%">
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</body>

</html>
167 changes: 167 additions & 0 deletions scgallery/templates/details.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<!DOCTYPE html>
<html lang="en">

<head>
<title>SiliconCompiler Image Gallery {{ sc_version }} - details</title>
{% if favicon %}
<link rel="icon" href="data:image/jpeg;base64,{{ favicon }}" type="image/x-icon">
{% endif %}
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- CSS Tabs is licensed under Creative Commons Attribution 3.0 - http://creativecommons.org/licenses/by/3.0/ -->
<style type="text/css">
body {
font: 100% verdana, arial, sans-serif;
background-color: #fff;
}

/* begin css tabs */

ul#tabnav {
/* general settings */
text-align: left;
/* set to left, right or center */
margin: 8px 0 0 0;
/* set margins as desired */
font: bold 11px verdana, arial, sans-serif;
/* set font as desired */
border-bottom: 1px solid #6c6;
/* set border COLOR as desired */
list-style-type: none;
padding: 3px 10px 0px 10px;
}

ul#tabnav li {
/* do not change */
display: inline-block;
}

ul#tabnav li.selected {
/* settings for selected tab */
border-bottom: 1px solid #fff;
/* set border color to page background color */
background-color: #fff;
/* set background color to match above border color */
}


ul#tabnav li {
/* settings for all tab links */
padding: 3px 4px;
border: 1px solid #6c6;
/* set border COLOR as desired; usually matches border color specified in #tabnav */
border-bottom: 1px solid #cfc;
background-color: #cfc;
/* set unselected tab background color as desired */
color: #666;
/* set unselected tab link color as desired */
margin-right: 0px;
/* set additional spacing between tabs as desired */
text-decoration: none;
cursor: pointer;
}

ul#tabnav li:hover {
/* settings for hover effect */
background: #afa;
/* set desired hover color */
}

/* end css tabs */

/* FF 100% height iframe */
html,
body,
div,
iframe {
margin: 0;
padding: 0;
}

iframe {
display: block;
width: 100%;
border: none;
}

h1 {
display: inline;
float: left;
font-size: small;
margin: 0;
padding: 0 10px;
}

h2 {
display: inline;
float: right;
font-size: small;
margin: 0;
padding: 0 10px;
}
</style>

<script type="text/javascript">
function updateBody(tabId, page) {
console.log(tabId)
document.getElementById(selectedTab).setAttribute("class", "unselected");
tab = document.getElementById(tabId)
tab.setAttribute("class", "selected");
selectedTab = tabId;
iframe = document.getElementById("design_frame");
iframe.srcdoc = atob(tabData[tabId]);
}
function init(tabId) {
selectedTab = tabId
updateBody(tabId);
updateViewport();

window.onresize = updateViewport;
}

function updateViewport() {
var viewportheight;

// the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight

if (typeof window.innerWidth != 'undefined') {
viewportheight = window.innerHeight
}

// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)

else if (typeof document.documentElement != 'undefined'
&& typeof document.documentElement.clientWidth !=
'undefined' && document.documentElement.clientWidth != 0) {
viewportheight = document.documentElement.clientHeight
}
// older versions of IE
else {
viewportheight = document.getElementsByTagName('body')[0].clientHeight
}

iframe = document.getElementById("design_frame");
iframe.style.height = (viewportheight - 30) + 'px';
}
var selectedTab = ""
var tabData = {
{% for design in designs %}
tab_{{ design }}: "{{ pages[design] }}",
{% endfor %}
}
</script>

</head>

<body onload="init('tab_{{ initial_design }}');">
<p align="center">SiliconCompiler Image Gallery {{ sc_version }}</p>
<ul id="tabnav">
{% for design in designs %}
<li id="tab_{{ design }}" class="unselected" onclick="updateBody('tab_{{ design }}')">{{ design }}</li>
{% endfor %}
</ul>
<div>
<iframe id="design_frame" height="100%" width="100%" frameborder="0"></iframe>
</div>
</body>

</html>
Loading

0 comments on commit 7a67aa8

Please sign in to comment.