From e6a84f574f7ed7fbb1f6d810e1369e849ae407a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 Aug 2025 19:50:40 +0000 Subject: [PATCH 1/2] Initial plan From e55b915579c036f0ae69d1ae24e30e16a4f433b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 Aug 2025 19:55:31 +0000 Subject: [PATCH 2/2] Generate PPTX file from poster.html with complete content Co-authored-by: FCHXWH823 <176723341+FCHXWH823@users.noreply.github.com> --- html_to_pptx_converter.py | 241 ++++++++++++++++++++++++++++++++++++++ poster-pptx-README.md | 54 +++++++++ poster.pptx | Bin 0 -> 29514 bytes verify_pptx.py | 105 +++++++++++++++++ 4 files changed, 400 insertions(+) create mode 100644 html_to_pptx_converter.py create mode 100644 poster-pptx-README.md create mode 100644 poster.pptx create mode 100644 verify_pptx.py diff --git a/html_to_pptx_converter.py b/html_to_pptx_converter.py new file mode 100644 index 0000000..5fdf002 --- /dev/null +++ b/html_to_pptx_converter.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python3 +""" +HTML to PPTX Converter for LLM4Hardware Poster +Converts poster.html to an equivalent PPTX presentation with one slide +""" + +import os +from bs4 import BeautifulSoup +from pptx import Presentation +from pptx.util import Inches, Pt +from pptx.dml.color import RGBColor +from pptx.enum.text import PP_ALIGN, MSO_ANCHOR +from pptx.enum.shapes import MSO_SHAPE + +def hex_to_rgb(hex_color): + """Convert hex color to RGB tuple""" + hex_color = hex_color.lstrip('#') + return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) + +def create_poster_pptx(): + """Create a PPTX file from the poster.html content""" + + # Read the HTML file + with open('poster.html', 'r', encoding='utf-8') as f: + html_content = f.read() + + # Parse HTML with BeautifulSoup + soup = BeautifulSoup(html_content, 'html.parser') + + # Create new presentation + prs = Presentation() + + # Use blank slide layout + blank_slide_layout = prs.slide_layouts[6] # Blank layout + slide = prs.slides.add_slide(blank_slide_layout) + + # Set slide dimensions (16:9 aspect ratio) + prs.slide_width = Inches(13.33) + prs.slide_height = Inches(7.5) + + # Add background gradient (approximating the CSS gradient) + # Create a rectangle covering the entire slide + background = slide.shapes.add_shape( + MSO_SHAPE.RECTANGLE, + Inches(0), Inches(0), + prs.slide_width, prs.slide_height + ) + background.fill.solid() + background.fill.fore_color.rgb = RGBColor(102, 126, 234) # #667eea + background.line.fill.background() + + # Add a white content area (simulating the poster white background) + content_bg = slide.shapes.add_shape( + MSO_SHAPE.RECTANGLE, + Inches(0.5), Inches(0.3), + Inches(12.33), Inches(6.9) + ) + content_bg.fill.solid() + content_bg.fill.fore_color.rgb = RGBColor(255, 255, 255) + content_bg.line.color.rgb = RGBColor(200, 200, 200) + content_bg.shadow.inherit = False + + # Header section with gradient background + header_bg = slide.shapes.add_shape( + MSO_SHAPE.RECTANGLE, + Inches(0.5), Inches(0.3), + Inches(12.33), Inches(1.5) + ) + header_bg.fill.solid() + header_bg.fill.fore_color.rgb = RGBColor(102, 126, 234) # #667eea + header_bg.line.fill.background() + + header_box = slide.shapes.add_textbox( + Inches(1), Inches(0.4), Inches(11.33), Inches(1.3) + ) + header_frame = header_box.text_frame + header_frame.clear() + + # Title + title_p = header_frame.paragraphs[0] + title_p.text = "šŸš€ LLM4Hardware" + title_p.font.size = Pt(40) + title_p.font.bold = True + title_p.font.color.rgb = RGBColor(255, 255, 255) + title_p.alignment = PP_ALIGN.CENTER + + # Subtitle + subtitle_p = header_frame.add_paragraph() + subtitle_p.text = "Generative AI for Chip Design" + subtitle_p.font.size = Pt(20) + subtitle_p.font.color.rgb = RGBColor(255, 255, 255) + subtitle_p.alignment = PP_ALIGN.CENTER + + # GitHub info section + github_box = slide.shapes.add_textbox( + Inches(1), Inches(2.2), Inches(11.33), Inches(0.8) + ) + github_frame = github_box.text_frame + github_frame.clear() + + github_p = github_frame.paragraphs[0] + github_p.text = "šŸ“¦ Repository: github.com/FCHXWH823/LLM4Hardware" + github_p.font.size = Pt(16) + github_p.font.bold = True + github_p.font.color.rgb = RGBColor(51, 51, 51) + github_p.alignment = PP_ALIGN.CENTER + + # Featured projects section + featured_box = slide.shapes.add_textbox( + Inches(0.5), Inches(3.2), Inches(12.33), Inches(1.8) + ) + featured_frame = featured_box.text_frame + featured_frame.clear() + + # Featured title + featured_title = featured_frame.paragraphs[0] + featured_title.text = "🌟 Featured Submodules" + featured_title.font.size = Pt(20) + featured_title.font.bold = True + featured_title.font.color.rgb = RGBColor(229, 81, 0) # #e65100 + featured_title.alignment = PP_ALIGN.CENTER + + # AutoChip project + autochip_p = featured_frame.add_paragraph() + autochip_p.text = "šŸ”§ AutoChip: Generate functional Verilog modules from design prompts using LLMs with iterative error feedback" + autochip_p.font.size = Pt(12) + autochip_p.font.color.rgb = RGBColor(51, 51, 51) + + # Security project + security_p = featured_frame.add_paragraph() + security_p.text = "šŸ›”ļø Security Assertions: LLM-generated SystemVerilog assertions for hardware security verification" + security_p.font.size = Pt(12) + security_p.font.color.rgb = RGBColor(51, 51, 51) + + # C2HLSC project + c2hlsc_p = featured_frame.add_paragraph() + c2hlsc_p.text = "⚔ C2HLSC: Bridge software-to-hardware design gap using LLMs to refactor C code for HLS" + c2hlsc_p.font.size = Pt(12) + c2hlsc_p.font.color.rgb = RGBColor(51, 51, 51) + + # Main topics section (left column - Verilog) + verilog_box = slide.shapes.add_textbox( + Inches(0.5), Inches(5.2), Inches(3.8), Inches(1.8) + ) + verilog_frame = verilog_box.text_frame + verilog_frame.clear() + + verilog_title = verilog_frame.paragraphs[0] + verilog_title.text = "šŸ”§ LLM4Verilog Generation" + verilog_title.font.size = Pt(14) + verilog_title.font.bold = True + verilog_title.font.color.rgb = RGBColor(76, 175, 80) # #4CAF50 + + verilog_projects = [ + "• AutoChip: Functional Verilog generation with LLM feedback", + "• VeriThoughts: Reasoning-based Verilog code generation", + "• ROME: Hierarchical prompting for complex chip design", + "• PrefixLLM: LLM-aided prefix circuit design", + "• Veritas: Deterministic Verilog synthesis from CNF" + ] + + for project in verilog_projects: + p = verilog_frame.add_paragraph() + p.text = project + p.font.size = Pt(10) + p.font.color.rgb = RGBColor(51, 51, 51) + + # Security section (middle column) + security_box = slide.shapes.add_textbox( + Inches(4.7), Inches(5.2), Inches(3.8), Inches(1.8) + ) + security_frame = security_box.text_frame + security_frame.clear() + + security_title = security_frame.paragraphs[0] + security_title.text = "šŸ›”ļø LLM4Security" + security_title.font.size = Pt(14) + security_title.font.bold = True + security_title.font.color.rgb = RGBColor(255, 87, 34) # #FF5722 + + security_projects = [ + "• Security Assertions: Hardware assertion generation for security", + "• Hybrid-NL2SVA: Natural Language to SystemVerilog Assertion", + "• OpenTitan RAG SVA: RAG system for OpenTitan SVA generation", + "• LLMPirate: LLMs for black-box hardware IP piracy", + "• FSM Testbench Gen: Testbench generation and bug detection" + ] + + for project in security_projects: + p = security_frame.add_paragraph() + p.text = project + p.font.size = Pt(10) + p.font.color.rgb = RGBColor(51, 51, 51) + + # C2HLS section (right column) + c2hls_box = slide.shapes.add_textbox( + Inches(8.9), Inches(5.2), Inches(3.8), Inches(1.8) + ) + c2hls_frame = c2hls_box.text_frame + c2hls_frame.clear() + + c2hls_title = c2hls_frame.paragraphs[0] + c2hls_title.text = "⚔ LLM4C2HLS" + c2hls_title.font.size = Pt(14) + c2hls_title.font.bold = True + c2hls_title.font.color.rgb = RGBColor(33, 150, 243) # #2196F3 + + c2hls_projects = [ + "• C2HLSC: Bridge software-to-hardware design gap", + "• HLS Optimization: Automated C-to-HLS code transformation", + "• Masala-CHAI: Large-scale SPICE netlist dataset" + ] + + for project in c2hls_projects: + p = c2hls_frame.add_paragraph() + p.text = project + p.font.size = Pt(10) + p.font.color.rgb = RGBColor(51, 51, 51) + + # Statistics section + stats_box = slide.shapes.add_textbox( + Inches(1), Inches(7.1), Inches(11.33), Inches(0.3) + ) + stats_frame = stats_box.text_frame + stats_frame.clear() + + stats_p = stats_frame.paragraphs[0] + stats_p.text = "šŸ“Š 12+ Research Projects • 7 Git Submodules • 10+ Published Papers • 3 Main Focus Areas" + stats_p.font.size = Pt(12) + stats_p.font.bold = True + stats_p.font.color.rgb = RGBColor(255, 255, 255) + stats_p.alignment = PP_ALIGN.CENTER + + # Save the presentation + output_filename = 'poster.pptx' + prs.save(output_filename) + print(f"PPTX file saved as: {output_filename}") + return output_filename + +if __name__ == "__main__": + create_poster_pptx() \ No newline at end of file diff --git a/poster-pptx-README.md b/poster-pptx-README.md new file mode 100644 index 0000000..dca3534 --- /dev/null +++ b/poster-pptx-README.md @@ -0,0 +1,54 @@ +# Poster PPTX Generation + +This directory contains tools to convert the HTML poster (`poster.html`) to PowerPoint format (`poster.pptx`). + +## Generated Files + +- `poster.pptx` - PowerPoint presentation containing a single slide with the same content as poster.html +- `html_to_pptx_converter.py` - Python script that converts HTML to PPTX +- `verify_pptx.py` - Verification script to check PPTX content + +## Features + +The generated PPTX file contains: + +- **Single slide layout** matching the HTML poster design +- **All text content** from the original HTML poster +- **Color-coded sections** matching the HTML design: + - Green for LLM4Verilog Generation (#4CAF50) + - Red for LLM4Security (#FF5722) + - Blue for LLM4C2HLS (#2196F3) +- **Proper formatting** with emojis, bullet points, and hierarchy +- **Background design** approximating the HTML gradient and layout + +## Content Included + +1. **Header**: Title and subtitle with blue gradient background +2. **Repository Info**: GitHub repository link +3. **Featured Submodules**: AutoChip, Security Assertions, C2HLSC +4. **Three Main Sections**: + - šŸ”§ LLM4Verilog Generation (5 projects) + - šŸ›”ļø LLM4Security (5 projects) + - ⚔ LLM4C2HLS (3 projects) +5. **Statistics**: Project counts and key metrics + +## Usage + +To regenerate the PPTX file: + +```bash +python3 html_to_pptx_converter.py +``` + +To verify the content: + +```bash +python3 verify_pptx.py +``` + +## Dependencies + +- python-pptx +- beautifulsoup4 + +The generated `poster.pptx` file can be opened in Microsoft PowerPoint, Google Slides, or any compatible presentation software. \ No newline at end of file diff --git a/poster.pptx b/poster.pptx new file mode 100644 index 0000000000000000000000000000000000000000..929ccb4dfd4a7a1e68f8416de43ef68e7f723f34 GIT binary patch literal 29514 zcmdqIQsxIRdpj3XI~RQw zPX|+HT?P+Zn~9VW`93D3uuERCL>Yt<#}!PrKiy77rC_`PQbmbY zpdmVuQdp|nr|X$G@;v?S;P=uf?JSZDLX%^`l?*rfb0)oX8d=Kxg^o7atF`aEc*i$Z}KAS2`|nxC`o>cmO?<70HJVl z0WP%%(vRc&N81w9G`u00tR-eI`jA7gypQ{%PLS{alH_Z6jx(UIB=3L#0l|JHS>MUj z#+i}fuWM!elsqUg(vM4i@DHYgC_1o}2@OJy8C(OQW#wKU@ΝO>&5Q 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

P)$WWwbI?{*e>*k(=)&j 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 literal 0 HcmV?d00001 diff --git a/verify_pptx.py b/verify_pptx.py new file mode 100644 index 0000000..14aedd4 --- /dev/null +++ b/verify_pptx.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +""" +PPTX Verification Script +Verifies that the generated PPTX contains the expected content from poster.html +""" + +from pptx import Presentation +import os + +def verify_pptx_content(): + """Verify the content of the generated PPTX file""" + + pptx_file = 'poster.pptx' + + if not os.path.exists(pptx_file): + print(f"āŒ Error: {pptx_file} not found!") + return False + + print(f"āœ… Found PPTX file: {pptx_file}") + + try: + # Load the presentation + prs = Presentation(pptx_file) + + print(f"šŸ“Š Presentation info:") + print(f" - Number of slides: {len(prs.slides)}") + print(f" - Slide width: {prs.slide_width}") + print(f" - Slide height: {prs.slide_height}") + + if len(prs.slides) == 0: + print("āŒ No slides found in presentation!") + return False + + # Check the first (and only) slide + slide = prs.slides[0] + print(f"\nšŸ“„ Slide 1 content:") + print(f" - Number of shapes: {len(slide.shapes)}") + + # Extract all text content + all_text = [] + for shape in slide.shapes: + if hasattr(shape, 'text_frame'): + for paragraph in shape.text_frame.paragraphs: + if paragraph.text.strip(): + all_text.append(paragraph.text.strip()) + + print(f" - Text elements found: {len(all_text)}") + + # Check for key content elements + key_elements = [ + "LLM4Hardware", + "Generative AI for Chip Design", + "github.com/FCHXWH823/LLM4Hardware", + "Featured Submodules", + "AutoChip", + "Security Assertions", + "C2HLSC", + "LLM4Verilog Generation", + "LLM4Security", + "LLM4C2HLS", + "Research Projects" + ] + + found_elements = [] + missing_elements = [] + + for element in key_elements: + found = False + for text in all_text: + if element in text: + found = True + found_elements.append(element) + break + if not found: + missing_elements.append(element) + + print(f"\nāœ… Content verification:") + print(f" - Found elements: {len(found_elements)}/{len(key_elements)}") + + for element in found_elements: + print(f" āœ“ {element}") + + if missing_elements: + print(f"\nāŒ Missing elements:") + for element in missing_elements: + print(f" āœ— {element}") + + print(f"\nšŸ“ All text content:") + for i, text in enumerate(all_text, 1): + print(f" {i}. {text}") + + success = len(missing_elements) == 0 + if success: + print(f"\nāœ… Verification successful! PPTX contains all expected content.") + else: + print(f"\nāš ļø Verification partially successful. Some content may be missing.") + + return success + + except Exception as e: + print(f"āŒ Error reading PPTX file: {e}") + return False + +if __name__ == "__main__": + verify_pptx_content() \ No newline at end of file