├── .gitignore
├── Application
├── Generator
│ ├── HDL_Database
│ │ ├── verilog_database.xml
│ │ └── vhdl_database.xml
│ ├── TB_Database
│ │ ├── verilog_tb_database.xml
│ │ └── vhdl_tb_database.xml
│ ├── TCL_Database
│ │ └── tcl_database.xml
│ ├── WCFG_Database
│ │ └── wcfg_database.xml
│ └── generator.py
├── HDLDesigner
│ ├── Architecture
│ │ ├── arch_help.md
│ │ ├── arch_help.py
│ │ ├── architecture.py
│ │ ├── chipEnabled.py
│ │ ├── concurrentstmt_dialog.py
│ │ ├── instance_dialog.py
│ │ ├── note_dialog.py
│ │ └── process_dialog.py
│ ├── ChatGPT
│ │ ├── VHDLModel.py
│ │ ├── VerilogModel.py
│ │ ├── chatgpt.py
│ │ ├── chatgpt_help.md
│ │ └── chatgpt_help.py
│ ├── Generate
│ │ └── generation.py
│ ├── IOPorts
│ │ ├── io_port_dialog.py
│ │ ├── io_ports.py
│ │ ├── port_help.md
│ │ ├── port_help.py
│ │ └── sequential_dialog.py
│ ├── InternalSignal
│ │ ├── int_sig_dialog.py
│ │ ├── internal_help.md
│ │ ├── internal_help.py
│ │ ├── internal_signal.py
│ │ └── stateNamesDialog.py
│ ├── Package
│ │ ├── package.py
│ │ ├── package_dialog.py
│ │ ├── package_help.md
│ │ └── package_help.py
│ ├── Subcomponents
│ │ ├── component_dialog.py
│ │ ├── subcomp_help.md
│ │ ├── subcomp_help.py
│ │ └── subcomponents.py
│ ├── comp
│ │ ├── comp_details.py
│ │ ├── comp_help.md
│ │ └── comp_help.py
│ ├── hdl_designer.py
│ └── testPlan
│ │ ├── testplan.py
│ │ ├── testplan_help.md
│ │ └── testplan_help.py
├── Help
│ ├── help.md
│ └── help.py
├── Home
│ └── home.py
├── ProjectManager
│ ├── eda_help.md
│ ├── eda_help.py
│ ├── language_help.md
│ ├── language_help.py
│ ├── projectLink.py
│ ├── project_manager.py
│ ├── settings_help.md
│ └── settings_help.py
├── Resources
│ ├── blue_logo.png
│ ├── hdlgen_title_blue.png
│ ├── hdlgen_title_red.png
│ ├── main_menu_0.png
│ ├── main_menu_1.png
│ ├── processdiagram.png
│ └── red_logo.png
├── Settings
│ ├── VHDLModelDefault.py
│ ├── VHDLTestbenchDefault.py
│ ├── VerilogModelDefault.py
│ ├── VerilogTestbenchDefault.py
│ └── settings.py
├── main.py
├── prompts.yml
└── requirements.txt
├── LICENSE.md
├── README.md
├── Sample_Projects
└── Sample_Projects_Downloads.pdf
└── User_Projects
└── User_Projects_Downloads.pdf
/.gitignore:
--------------------------------------------------------------------------------
1 | # Python cache files and compiled python files/classes
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # Application specific files generated at runtime
7 | # Override with "git add -f User_Projects/*" to update example User Projects
8 | **/config.ini
9 | User_Projects/
10 |
11 | # Ignore PyCharm, VSCode and Vivado files
12 | **/.idea/
13 | .idea/
14 | **/.vscode/
15 | .vscode
16 | **/*.log
17 | *.log
18 | **/*.jou
19 | *.jou
--------------------------------------------------------------------------------
/Application/Generator/HDL_Database/verilog_database.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 | module $comp_name(
$signals
);
$portDef
$arch
endmodule
16 |
17 | $sig_name
18 | $modeput $size $name;
19 | reg $int_sig_type $int_sig_name;
20 | $int_sig_declaration
$arch_elements
21 | parameter $stateName = $bits;
22 | -- Package
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package arrayPackage is
$arrays
$Component
end arrayPackage;
package body arrayPackage is
end arrayPackage;
23 | type $arrayName is array($arraySize downto 0) of $signalType($arrayLength downto 0);
24 | always @($input_signals)
begin : $process_label$default_assignments
end
25 |
if ( $assignment == 1'b$lvl )
begin$default_assignments
end
$else
26 | else
begin$default_assignments
end
27 | elsif $edge(clk) then
$default_assignments
28 | if (clk) then
$default_assignments end if;
29 | case ( $stateType )
30 | case ( $stateType )$whenCase
default :
begin
end
endcase
31 | $output_signal = $value;
32 | $output_signal = $value;
33 | .$output_signal ($value)
34 | assign $statement
35 | $instance $instance_label
(
$portAssign
);
36 | component $model is
port(
$ports
);
end component $model;
37 | /// $notes
38 | /// assign $output_signal = $notes;
39 |
40 |
--------------------------------------------------------------------------------
/Application/Generator/HDL_Database/vhdl_database.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
16 | library ieee;
17 | use ieee.std_logic_1164.all;
18 | use ieee.numeric_std.all;
19 |
20 |
21 | entity $comp_name is
Port(
$signals
);
end entity $comp_name;
22 |
23 | $sig_name : $mode $type;
24 |
25 | architecture $arch_name of $comp_name is
$int_sig_declaration
begin
$arch_elements
end $arch_name;
26 |
27 | signal $int_sig_name : $int_sig_type;
28 |
29 | type stateType is ($stateNamesList);
30 | -- Package
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package MainPackage is
$arrays
$Component
end MainPackage;
package body MainPackage is
end MainPackage;
31 | type $arrayName is array($arraySize downto 0) of $signalType($arrayLength downto 0);
32 | $process_label: process($input_signals)
begin
$default_assignments
end process;
33 | if $edge(clk) then
$default_assignments end if;
34 | if $assignment = '$value' then
$default_assignments$else end if;
35 | else
$default_assignments
36 | elsif $edge(clk) then
$default_assignments
37 | case $stateType is
38 | case $stateType is$whenCase
when others =>
null;
end case;
39 | $output_signal <= $value;
40 | $output_signal => $value
41 | $concurrentstmt_label: $statement
42 | $instance_label: $instance
port map(
$portAssign
);
43 | component $model is
port(
$ports
);
end component $model;
44 | --- $notes
45 | --- $concurrentstmt_label: $output_signal <= $notes;
46 |
47 |
--------------------------------------------------------------------------------
/Application/Generator/TB_Database/verilog_tb_database.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
16 | module $comp_name_TB();
17 |
18 | $sig_name : $mode $type;
19 |
20 | $regOrwire $size $sig_name;
21 |
22 | $tbSignalDeclaration
$arch_elements
end
endmodule
23 |
24 | signal $int_sig_name : $int_sig_type;
25 |
26 | .$sig_name ($sig_name),
27 |
28 | $output_signal <= $value;
29 |
30 |
--------------------------------------------------------------------------------
/Application/Generator/TB_Database/vhdl_tb_database.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
16 | library ieee;
17 | use ieee.std_logic_1164.all;
18 | use ieee.numeric_std.all;
19 |
20 |
21 | entity $comp_name_TB is end entity $comp_name_TB;
22 |
23 | $sig_name : $mode $type;
24 |
25 | signal $sig_name : $type;
26 |
27 | architecture behave of $comp_name_TB is
$component_declarations
component $comp_name is
Port(
$port
);
end component;
$tbSignalDeclaration
begin
$arch_elements
end process;
end behave;
28 |
29 | signal $int_sig_name : $int_sig_type;
30 |
31 | $sig_name => $sig_name,
32 |
33 | $output_signal <= $value;
34 |
35 | $concurrentstmt_label: $statement
36 |
--------------------------------------------------------------------------------
/Application/Generator/TCL_Database/tcl_database.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 | # AMD-Xilinx Vivado project start and tcl script: Create project, xc7z020clg400-1 technology, %lang model
16 | # To execute,
17 | # open cmd window
18 | # cd to project folder
19 | # start Vivado (with tcl file parameter)
20 | # e.g, for project name $proj_name
21 | # cmd
22 | # cd $proj_dir
23 | # $vivado_bat_path -source $tcl_path
24 |
25 | # Vivado tcl file $proj_name.tcl, created in AMDprj folder
26 | cd $proj_dir
27 | # Close_project Not required. Will advise that Vivado sessions should be closed.
28 | start_gui
29 | create_project $proj_name ./$lang/AMDprj -part xc7z020clg400-1 -force
30 | set_property target_language $lang [current_project]
31 | add_files -norecurse ./$lang/model/$comp_name.$ext
$arrayPackage
$files
32 | update_compile_order -fileset sources_1
33 | set_property SOURCE_SET sources_1 [get_filesets sim_1]
34 | add_files -fileset sim_1 -norecurse ./$lang/testbench/$tb_name.$ext
35 | update_compile_order -fileset sim_1
36 | # Remove IOBs from snthesised schematics
37 | current_run [get_runs synth_1]
38 | set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value -no_iobuf -objects [get_runs synth_1]
39 |
40 | # Save created wcfg in project
41 | set_property SOURCE_SET sources_1 [get_filesets sim_1]
42 | add_files -fileset sim_1 -norecurse ./$lang/AMDprj/$tb_name_behav.wcfg
43 | # save_wave_config {./$lang/AMDprj/$tb_name_behav.wcfg}
44 |
45 |
46 | # Assume that the quartus executable pointer has been setup in the HDLGen settings
47 | # e.g, Quartus installation folder is
48 | # C:\intelFPGA_lite\22.1std\quartus\bin64\
49 | # Quartus executable quartus.exe
50 |
51 | # If click HDLGen 'Generate / Open Quartus
52 | # Execute this tcl file using
53 | # C:\intelFPGA_lite\22.1std\quartus\bin64\quartus_map $comp_name.tcl
54 |
55 | # Assume
56 | # Quartus project $comp_name.qpf
57 | # Folder $proj_dirC:\2023\vicilogic\HDLGenTop\HDLGen\User_Projects\sequential\counters\$comp_name\$lang\Intelprj
58 |
59 | # To synthesise the HDL model, after executing this tcl file, open the project in Quartus, run the following
60 | # C:\intelFPGA_lite\22.1std\quartus\bin64\quartus.exe CB4CLED.qpf
61 | # The user can then synthesise the design using menu Project > Start compilation (or shortcut ctrl/L)
62 | # or use GUI Tools > Green arrow function "Start Analysis and Synthesis" or shortcut (ctrl/K)
63 |
64 | # Copyright (C) 2023 Intel Corporation. All rights reserved.
65 | # Your use of Intel Corporation's design tools, logic functions
66 | # and other software and tools, and any partner logic
67 | # functions, and any output files from any of the foregoing
68 | # (including device programming or simulation files), and any
69 | # associated documentation or information are expressly subject
70 | # to the terms and conditions of the Intel Program License
71 | # Subscription Agreement, the Intel Quartus Prime License Agreement,
72 | # the Intel FPGA IP License Agreement, or other applicable license
73 | # agreement, including, without limitation, that your use is for
74 | # the sole purpose of programming logic devices manufactured by
75 | # Intel and sold by Intel or its authorized distributors. Please
76 | # refer to the applicable agreement for further details, at
77 | # https://fpgasoftware.intel.com/eula.
78 |
79 | # Quartus Prime: Generate Tcl File for Project
80 |
81 | # Load Quartus Prime Tcl Project package
82 | package require ::quartus::project0
83 | set need_to_close_project 0
84 |
85 | project create $comp_name
86 | project open $comp_name
87 |
88 | set make_assignments 1
89 |
90 | # Make assignments
91 | if {$make_assignments} {
92 | set_global_assignment -name FAMILY "Cyclone V"
93 | set_global_assignment -name DEVICE 5CSEBA6U23I7
94 | set_global_assignment -name ORIGINAL_QUARTUS_VERSION 22.1STD.1
95 | set_global_assignment -name PROJECT_CREATION_TIME_DATE "08:49:38 MAY 02, 2023"
96 | set_global_assignment -name LAST_QUARTUS_VERSION "22.1std.1 Lite Edition"
97 | set_global_assignment -name $lang_FILE ../model/$comp_name.$ext
98 | set_global_assignment -name $lang_FILE ../../../../../../Package/MainPackage.vhd
99 | set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
100 | set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40"
101 | set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100
102 | set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256
103 | set_global_assignment -name EDA_SIMULATION_TOOL "Questa Intel FPGA ($lang)"
104 | set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation
105 | set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation
106 | set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_timing
107 | set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_symbol
108 | set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_signal_integrity
109 | set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_boundary_scan
110 | }
111 |
112 | # Commit assignments
113 | export_assignments
114 |
115 |
--------------------------------------------------------------------------------
/Application/Generator/WCFG_Database/wcfg_database.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | testNo
28 | testNo
29 |
30 |
31 |
32 | endOfSim
33 | endOfSim
34 |
35 |
36 |
37 |
38 | UUT
39 | label
40 |
41 | entity
42 | label
43 |
44 |
45 |
46 |
47 | [signal][size]
48 | [signal][size]
49 |
50 |
51 |
52 |
53 |
54 | internal
55 | label
56 |
57 |
58 |
59 |
60 | [signal][size]
61 | [signal][size]
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/Architecture/arch_help.md:
--------------------------------------------------------------------------------
1 | # Architecture
2 |
3 | This menu enables the creation and editing of processes, concurrent statements and component instantiations
4 |
5 | - New process
6 | - Process name
7 | - suffix (_p default)
8 | - Add non-default logic
9 | - Examples
10 | if RWr = 1
11 | if rd > 0
12 | NSArray(rd) = WBDat
13 | end if
14 | end if
15 |
16 | Use nested, indented if-elsif-else-end if and case-end case stateements
17 |
18 | - sensitivity list: tick all signals which apply
19 | synchronous (clocked): clk and/or rst are automatically validated as the sensitivity list
20 | - Select
21 | - output signal
22 | - select signal
23 | - default values
24 | - select
25 | signal name or
26 | 'zero'
27 | custom value
28 | - enter custom default value
29 | - Click OK to complete
30 |
31 |
32 | - New concurrent statement
33 | - concurrent statement name
34 | - default suffix is _c
35 | - assign signal
36 | - select signal to be assigned or
37 | - 'zero'
38 | - click 'custom value' to enter custom value, e.g, equation in the custom value field
39 | - Click OK to complete
40 |
41 | - New (component) instance
42 | - instance name
43 | - suffix (_i defaul)
44 | - component list (accesses the components listed in the sub-components menu
45 | - assign input or internal signal name to the component port signals
46 | - Click OK to complete
47 |
48 | - The existing processes, concurrent statements and component instances are listed and can be edited or deleted
49 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/Architecture/arch_help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | COMP_HELP_DOC_FILE_PATH = "./HDLDesigner/Architecture/arch_help.md"
6 |
7 |
8 | class ArchHelpDialog(QDialog):
9 |
10 | def __init__(self):
11 | super().__init__()
12 | self.setWindowTitle("HDLGen Help")
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 |
17 | self.mainLayout = QVBoxLayout()
18 | self.setFixedSize(800, 800)
19 | self.setup_ui()
20 |
21 | def setup_ui(self):
22 |
23 | # Writing xml file
24 | with open(COMP_HELP_DOC_FILE_PATH, "r") as f:
25 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/Architecture/chipEnabled.py:
--------------------------------------------------------------------------------
1 | #Dialog called inside process_dialog. Allows user to selct what signal to use as the hcip enabled signal.
2 | from xml.dom import minidom
3 | from PySide2.QtWidgets import *
4 | from PySide2.QtGui import *
5 | import sys
6 | sys.path.append("..")
7 | from ProjectManager.project_manager import ProjectManager
8 |
9 | BLACK_COLOR = "color: black"
10 | WHITE_COLOR = "color: white"
11 |
12 | class ChipEnabledDialog(QDialog):
13 |
14 | def __init__(self, add_or_edit, ce_data = None):
15 | super().__init__()
16 |
17 | if add_or_edit == "add":
18 | self.setWindowTitle("Set Chip Enabled Signal")
19 | elif add_or_edit == "edit":
20 | self.setWindowTitle("Edit Chip Enabled Signal")
21 | title_font = QFont()
22 | title_font.setPointSize(10)
23 | title_font.setBold(True)
24 | bold_font = QFont()
25 | bold_font.setBold(True)
26 | input_font = QFont()
27 | input_font.setPointSize(10)
28 | self.internal_signals = []
29 | self.input_signals = []
30 | self.output_signals = []
31 |
32 | self.input_layout = QGridLayout()
33 |
34 | self.mainLayout = QVBoxLayout()
35 |
36 | self.chipEnabled_name_label = QLabel("Chip Enabled Signal")
37 | self.chipEnabled_name_label.setFont(input_font)
38 | self.chipEnabled_name_label.setStyleSheet(WHITE_COLOR)
39 |
40 | self.chipEnabled_signals_combo = QComboBox()
41 | self.chipEnabled_signals_combo.setFont(input_font)
42 | self.chipEnabled_signals_combo.setStyleSheet("QComboBox {padding: 2px;}")
43 |
44 | self.cancel_btn = QPushButton("Cancel")
45 | self.cancel_btn.setFont(input_font)
46 | self.cancel_btn.setStyleSheet(
47 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
48 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
49 |
50 |
51 | self.ok_btn = QPushButton("Ok")
52 | self.ok_btn.setEnabled(False)
53 | self.ok_btn.setFont(input_font)
54 | self.ok_btn.setStyleSheet(
55 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
56 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
57 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
58 |
59 | self.input_frame = QFrame()
60 |
61 | self.cancelled = True
62 |
63 | self.setup_ui()
64 |
65 | self.populate_signals(ProjectManager.get_xml_data_path())
66 |
67 | if add_or_edit == "edit" and ce_data != None:
68 | self.load_ce_data(ce_data)
69 |
70 | def setup_ui(self):
71 |
72 | self.input_layout.addWidget(self.chipEnabled_name_label, 0, 0, 1, 2)
73 | self.input_layout.addWidget(self.chipEnabled_signals_combo, 1, 0, 1, 2)
74 | self.input_layout.addItem(QSpacerItem(0, 10), 2, 0, 1, 2)
75 | self.input_layout.addWidget(self.cancel_btn, 3, 0, 2, 1, alignment=Qt.AlignRight)
76 | self.input_layout.addWidget(self.ok_btn, 3, 1, 2, 1, alignment=Qt.AlignRight)
77 |
78 | self.chipEnabled_signals_combo.currentTextChanged.connect(self.enable_ok_btn);
79 | self.input_frame.setFrameShape(QFrame.StyledPanel)
80 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
81 | self.input_frame.setContentsMargins(10, 10, 10, 10)
82 | self.input_frame.setFixedSize(400, 175)
83 | self.input_frame.setLayout(self.input_layout)
84 | self.ok_btn.clicked.connect(self.get_data)
85 | self.cancel_btn.clicked.connect(self.cancel_selected)
86 |
87 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
88 |
89 | self.setLayout(self.mainLayout)
90 |
91 | def populate_signals(self, proj_dir):
92 | if (proj_dir != None):
93 | root = minidom.parse(proj_dir)
94 | HDLGen = root.documentElement
95 | hdlDesign = HDLGen.getElementsByTagName("hdlDesign")
96 |
97 | io_ports = hdlDesign[0].getElementsByTagName('entityIOPorts')
98 | signal_nodes = io_ports[0].getElementsByTagName('signal')
99 |
100 | intSignals = hdlDesign[0].getElementsByTagName('internalSignals')
101 | intSignal_nodes = intSignals[0].getElementsByTagName('signal')
102 |
103 | if len(signal_nodes) != 0 or len(intSignal_nodes) != 0:
104 |
105 | for i in range(0, len(signal_nodes)):
106 | name = signal_nodes[i].getElementsByTagName('name')[0].firstChild.data
107 | mode = signal_nodes[i].getElementsByTagName('mode')[0].firstChild.data
108 |
109 | if mode != "out":
110 | if name != "clk" and name != "rst":
111 | self.input_signals.append(name)
112 |
113 | for i in range(0, len(intSignal_nodes)):
114 | internal_signal = intSignal_nodes[i].getElementsByTagName('name')[0].firstChild.data
115 | self.internal_signals.append(internal_signal)
116 |
117 | if len(self.input_signals) != 0 or len(self.internal_signals) != 0:
118 | self.chipEnabled_signals_combo.addItem("Please select")
119 | self.chipEnabled_signals_combo.addItems(self.input_signals + self.internal_signals)
120 |
121 |
122 | def load_ce_data(self, ce_data):
123 | if ce_data in self.internal_signals or ce_data in self.input_signals:
124 | self.chipEnabled_signals_combo.setCurrentText(ce_data)
125 | else:
126 | self.chipEnabled_signals_combo.setCurrentText("Please select")
127 | def get_data(self):
128 | data = self.chipEnabled_signals_combo.currentText()
129 | self.cancelled = False
130 | self.close()
131 | return data
132 |
133 | def cancel_selected(self):
134 | self.cancelled = True
135 | self.close()
136 | def enable_ok_btn(self):
137 | if self.chipEnabled_signals_combo.currentText() != "Please select":
138 | self.ok_btn.setEnabled(True)
139 | else:
140 | self.ok_btn.setEnabled(False)
141 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/Architecture/concurrentstmt_dialog.py:
--------------------------------------------------------------------------------
1 | #Dialog box for concurrent statement called by the architecture.py when adding or editing concurrent statement
2 | from xml.dom import minidom
3 | from PySide2.QtWidgets import *
4 | from PySide2.QtGui import *
5 | import sys
6 | import re
7 | sys.path.append("..")
8 | from ProjectManager.project_manager import ProjectManager
9 | from HDLDesigner.Architecture.note_dialog import note_Dialog
10 |
11 | BLACK_COLOR = "color: black"
12 | WHITE_COLOR = "color: white"
13 |
14 | class ConcurrentStmtDialog(QDialog):
15 |
16 | def __init__(self, add_or_edit, concNames ,conc_data = None):
17 | super().__init__()
18 |
19 | if add_or_edit == "add":
20 | self.setWindowTitle("New Concurrent Statement")
21 | elif add_or_edit == "edit":
22 | self.setWindowTitle("Edit Concurrent Statement")
23 | self.conc_names = concNames
24 | self.conc_name = ""
25 | if conc_data != None:
26 | self.conc_name = conc_data[1]
27 | title_font = QFont()
28 | title_font.setPointSize(10)
29 | title_font.setBold(True)
30 | bold_font = QFont()
31 | bold_font.setBold(True)
32 | input_font = QFont()
33 | input_font.setPointSize(10)
34 |
35 | self.internal_signals = []
36 | self.input_signals = []
37 | self.output_signals = []
38 | self.conc_notes = "None"
39 | self.input_layout = QGridLayout()
40 |
41 | self.mainLayout = QVBoxLayout()
42 |
43 | self.conc_name_label = QLabel("Concurrent Statement Name*")
44 | self.conc_name_label.setStyleSheet(WHITE_COLOR)
45 | self.conc_name_label.setFont(input_font)
46 | self.conc_name_input = QLineEdit()
47 | self.conc_name_input.setFont(input_font)
48 | self.noteBox = QCheckBox("Custom Value")
49 | self.noteBox.setStyleSheet(WHITE_COLOR)
50 | self.noteBox.setFont(input_font)
51 | self.note_label = QLabel("Custom Value")
52 | self.note_label.setStyleSheet(WHITE_COLOR)
53 | self.note_label.setFont(input_font)
54 | self.note_label.setVisible(False)
55 | self.note_input = QLineEdit()
56 | self.note_input.setVisible(False)
57 | self.note_input.setFont(input_font)
58 | self.add_note_btn = QPushButton("Add Custom Value")
59 | self.add_note_btn.setFont(input_font)
60 | self.add_note_btn.setStyleSheet(
61 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
62 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
63 | self.add_note_btn.setVisible(False)
64 |
65 | self.out_sig_header_layout = QHBoxLayout()
66 | self.out_sig_label = QLabel("Assign Signal")
67 | self.out_sig_label.setFont(input_font)
68 | self.out_sig_label.setStyleSheet(WHITE_COLOR)
69 | self.options_sig_label = QLabel("Default Value")
70 | self.options_sig_label.setFont(input_font)
71 | self.options_sig_label.setStyleSheet(WHITE_COLOR)
72 | self.val_label = QLabel("Binary Value")
73 | self.val_label.setFont(input_font)
74 | self.val_label.setStyleSheet(WHITE_COLOR)
75 | self.out_sig_empty_info = QLabel("No Output Signals found!\nPlease add signal in the IO Ports")
76 | self.out_sig_empty_info.setFont(input_font)
77 | self.out_sig_empty_info.setFixedSize(400, 300)
78 |
79 | self.out_signals_combo = QComboBox()
80 | self.out_signals_combo.setFont(input_font)
81 | self.out_signals_combo.setStyleSheet("QComboBox {padding: 2px;}")
82 | self.options_signals_combo = QComboBox()
83 | self.options_signals_combo.setFont(input_font)
84 | self.options_signals_combo.setStyleSheet("QComboBox {padding: 2px;}")
85 | self.out_val_input = QLineEdit()
86 | self.out_val_input.setFont(input_font)
87 | validator = QIntValidator()
88 | self.out_val_input.setValidator(validator)
89 |
90 | self.out_sig_layout = QHBoxLayout()
91 |
92 | self.suffix_label = QLabel("Suffix")
93 | self.suffix_label.setStyleSheet(WHITE_COLOR)
94 | self.suffix_label.setFont(input_font)
95 | self.suffix_input = QLineEdit()
96 | self.suffix_input.setFont(input_font)
97 | self.suffix_input.setEnabled(False)
98 | self.suffix_input.setText("_c")
99 |
100 | self.cancel_btn = QPushButton("Cancel")
101 | self.cancel_btn.setFont(input_font)
102 | self.cancel_btn.setStyleSheet(
103 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
104 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
105 |
106 |
107 | self.ok_btn = QPushButton("Ok")
108 | self.ok_btn.setEnabled(False)
109 | self.ok_btn.setFont(input_font)
110 | self.ok_btn.setStyleSheet(
111 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
112 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
113 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
114 |
115 | self.input_frame = QFrame()
116 |
117 | self.cancelled = True
118 |
119 | self.setup_ui()
120 |
121 | self.populate_signals(ProjectManager.get_xml_data_path())
122 |
123 | if add_or_edit == "edit" and conc_data != None:
124 | self.load_conc_data(conc_data)
125 |
126 | def setup_ui(self):
127 |
128 | self.input_layout.addWidget(self.conc_name_label, 0, 0, 1, 1)
129 | self.input_layout.addWidget(self.conc_name_input, 1, 0, 1, 1)
130 | self.input_layout.addWidget(self.suffix_label, 0, 1, 1, 1)
131 | self.input_layout.addWidget(self.suffix_input, 1, 1, 1, 1)
132 | self.input_layout.addWidget(self.noteBox, 1, 2, 1, 1)
133 | self.input_layout.addWidget(self.out_sig_label, 3, 0, 1, 1)
134 | self.input_layout.addWidget(self.out_signals_combo, 4, 0, 1, 1)
135 | self.input_layout.addWidget(self.add_note_btn, 4, 1, 1, 1)
136 | self.input_layout.addWidget(self.options_sig_label,3,1,1,1)
137 | self.input_layout.addWidget(self.options_signals_combo, 4, 1, 1, 1)
138 | self.input_layout.addItem(QSpacerItem(0, 10), 5, 0, 1, 3)
139 | self.input_layout.addWidget(self.cancel_btn, 6, 1, 1, 1, alignment=Qt.AlignRight)
140 | self.input_layout.addWidget(self.ok_btn, 6, 2, 1, 1, alignment=Qt.AlignRight)
141 |
142 | self.conc_name_input.textChanged.connect(self.enable_ok_btn);
143 | self.input_frame.setFrameShape(QFrame.StyledPanel)
144 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
145 | self.input_frame.setContentsMargins(10, 10, 10, 10)
146 | self.input_frame.setFixedSize(600, 300)
147 | self.input_frame.setLayout(self.input_layout)
148 | self.add_note_btn.clicked.connect(self.add_conc_note)
149 | self.ok_btn.clicked.connect(self.get_data)
150 | self.cancel_btn.clicked.connect(self.cancel_selected)
151 | self.noteBox.clicked.connect(self.note_checked)
152 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
153 |
154 | self.setLayout(self.mainLayout)
155 |
156 | def populate_signals(self, proj_dir):
157 |
158 | if (proj_dir != None):
159 | root = minidom.parse(proj_dir)
160 | HDLGen = root.documentElement
161 | hdlDesign = HDLGen.getElementsByTagName("hdlDesign")
162 |
163 | io_ports = hdlDesign[0].getElementsByTagName('entityIOPorts')
164 | signal_nodes = io_ports[0].getElementsByTagName('signal')
165 |
166 | intSignals = hdlDesign[0].getElementsByTagName('internalSignals')
167 | intSignal_nodes = intSignals[0].getElementsByTagName('signal')
168 |
169 | if len(signal_nodes) != 0 or len(intSignal_nodes) != 0:
170 |
171 | for i in range(0, len(signal_nodes)):
172 | name = signal_nodes[i].getElementsByTagName('name')[0].firstChild.data
173 | mode = signal_nodes[i].getElementsByTagName('mode')[0].firstChild.data
174 |
175 | if mode == "out":
176 | self.output_signals.append(name)
177 | else:
178 | if name != "clk" and name != "rst":
179 | self.input_signals.append(name)
180 |
181 | for i in range(0, len(intSignal_nodes)):
182 | internal_signal = intSignal_nodes[i].getElementsByTagName('name')[0].firstChild.data
183 | self.internal_signals.append(internal_signal)
184 |
185 | if len(self.output_signals) != 0 or len(self.internal_signals) != 0:
186 |
187 | self.output_signals.insert(0, "Select signal")
188 | self.out_signals_combo.addItems(self.output_signals + self.internal_signals )
189 | self.output_signals.pop(0)
190 | self.options_signals_combo.addItem("zero")
191 | self.options_signals_combo.addItems(self.internal_signals + self.input_signals)
192 |
193 | else:
194 | self.out_sig_layout.addWidget(self.out_sig_empty_info, alignment=Qt.AlignTop)
195 | return
196 |
197 | self.out_sig_layout.addWidget(self.out_sig_empty_info, alignment=Qt.AlignTop)
198 |
199 | def load_conc_data(self, conc_data):
200 |
201 | self.conc_name_input.setText(conc_data[1])
202 | self.conc_notes = conc_data[3]
203 | if self.conc_notes != "None":
204 | self.noteBox.setChecked(True)
205 | self.add_note_btn.setVisible(True)
206 | self.options_sig_label.setVisible(False)
207 | self.options_signals_combo.setVisible(False)
208 | self.add_note_btn.setText("Edit Custom Value")
209 | if len(conc_data[2]) != 0:
210 | temp = conc_data[2][0].split(",")
211 | out_sig = temp[0]
212 | out_val = temp[1]
213 | self.out_signals_combo.setCurrentText(out_sig)
214 | self.options_signals_combo.setCurrentText(out_val)
215 | self.out_val_input.setEnabled(False)
216 |
217 |
218 | def get_data(self):
219 | data = []
220 | out_sig = []
221 | concurrentName = self.conc_name_input.text().strip().replace(" ", "")
222 | if concurrentName[-2:] != "_c":
223 | concurrentName=concurrentName+"_c"
224 | data.append(concurrentName)
225 | output = self.out_signals_combo.currentText()
226 | if self.noteBox.isChecked():
227 | out_sig.append(output+",zero")
228 | else:
229 | self.conc_notes = "None"
230 | value = self.options_signals_combo.currentText()
231 | out_sig.append(output + "," + value)
232 | data.append(out_sig)
233 | data.append(self.conc_notes)
234 |
235 | self.cancelled = False
236 | self.close()
237 | return data
238 |
239 | def cancel_selected(self):
240 | self.cancelled = True
241 | self.close()
242 | def enable_ok_btn(self):
243 | if self.conc_name_input.text() != ""and (self.conc_name_input.text()+"_c" not in self.conc_names or self.conc_name_input.text() == self.conc_name[:-2] ) and (self.conc_name_input.text() not in self.conc_names or self.conc_name_input.text() == self.conc_name):
244 | self.ok_btn.setEnabled(True)
245 | else:
246 | self.ok_btn.setEnabled(False)
247 |
248 | def add_conc_note(self):
249 | button = self.sender()
250 | if button:
251 | if button.text() == "Edit Custom Value":
252 | add_note = note_Dialog("edit", "Concurrent Statement Custom Value",self.conc_notes)
253 | else:
254 | add_note = note_Dialog("add", "Concurrent Statement Custom Value",self.conc_notes)
255 | add_note.exec_()
256 |
257 | if not add_note.cancelled:
258 | note_data = add_note.get_data()
259 | note_data = re.sub(r'\s+', ' ', note_data)
260 | if note_data == "None":
261 | self.add_note_btn.setText("Add Custom Value")
262 | else:
263 | self.add_note_btn.setText("Edit Custom Value")
264 | self.conc_notes = note_data
265 |
266 | def note_checked(self):
267 | if self.noteBox.isChecked():
268 | self.add_note_btn.setVisible(True)
269 | self.options_sig_label.setVisible(False)
270 | self.options_signals_combo.setVisible(False)
271 | else:
272 | self.add_note_btn.setVisible(False)
273 | self.options_sig_label.setVisible(True)
274 | self.options_signals_combo.setVisible(True)
275 | def disable_Binary_input(self):
276 | combo = self.sender()
277 | if combo:
278 | if combo.currentText() == "Binary":
279 | self.out_val_input.setEnabled(True)
280 | self.out_val_input.setPlaceholderText("Eg. 1")
281 | else:
282 | self.out_val_input.clear()
283 | self.out_val_input.setPlaceholderText("")
284 | self.out_val_input.setEnabled(False)
285 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/Architecture/note_dialog.py:
--------------------------------------------------------------------------------
1 | #Dialog box for note called by concurrenentstmt_dialog.py or process_dialog.py
2 | from PySide2.QtWidgets import *
3 | from PySide2.QtGui import *
4 | import sys
5 |
6 | sys.path.append("..")
7 |
8 | BLACK_COLOR = "color: black"
9 | WHITE_COLOR = "color: white"
10 |
11 |
12 | class note_Dialog(QDialog):
13 |
14 | def __init__(self, add_or_edit, noteType, note_data=None):
15 | super().__init__()
16 |
17 | self.input_layout = QGridLayout()
18 | self.setWindowTitle(noteType)
19 | self.noteType = noteType
20 | title_font = QFont()
21 | title_font.setPointSize(10)
22 | title_font.setBold(True)
23 | bold_font = QFont()
24 | bold_font.setBold(True)
25 | input_font = QFont()
26 | input_font.setPointSize(10)
27 | self.mainLayout = QVBoxLayout()
28 |
29 | self.note_label = QLabel(noteType)
30 | self.note_label.setFont(input_font)
31 | self.note_label.setStyleSheet(WHITE_COLOR)
32 | self.note_input = QPlainTextEdit()
33 | self.note_input.setLineWrapMode(QPlainTextEdit.NoWrap)
34 | self.note_input.setFont(input_font)
35 |
36 | self.cancel_btn = QPushButton("Cancel")
37 | self.cancel_btn.setFont(input_font)
38 | self.cancel_btn.setStyleSheet(
39 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
40 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
41 |
42 | self.ok_btn = QPushButton("Ok")
43 | self.ok_btn.setFont(input_font)
44 | self.ok_btn.setStyleSheet(
45 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
46 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
47 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
48 |
49 | self.input_frame = QFrame()
50 |
51 | self.cancelled = True
52 |
53 | self.setup_ui()
54 | if add_or_edit == "edit" and note_data is not None:
55 | self.load_sig_data(note_data)
56 |
57 | def setup_ui(self):
58 |
59 | self.input_layout.addWidget(self.note_label, 0, 0, 1, 1)
60 | self.input_layout.addWidget(self.note_input, 1, 0, 4, 3)
61 | self.input_layout.addWidget(self.cancel_btn, 6, 1, 1, 1, alignment=Qt.AlignRight)
62 | self.input_layout.addWidget(self.ok_btn, 6, 2, 1, 1, alignment=Qt.AlignRight)
63 |
64 | self.input_frame.setFrameShape(QFrame.StyledPanel)
65 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
66 | self.input_frame.setContentsMargins(10, 10, 10, 10)
67 | self.input_frame.setLayout(self.input_layout)
68 | if self.noteType == "Concurrent Statement Custom Value":
69 | self.input_frame.setFixedSize(700, 350)
70 | else:
71 | self.input_frame.setFixedSize(700, 700)
72 |
73 | self.ok_btn.clicked.connect(self.get_data)
74 | self.cancel_btn.clicked.connect(self.cancel_selected)
75 |
76 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
77 |
78 | self.setLayout(self.mainLayout)
79 |
80 |
81 | def load_sig_data(self, note_data):
82 | if note_data == "None":
83 | note_data=""
84 | note_data = note_data.replace("
", "\n")
85 | note_data = note_data.replace("&","&")
86 | note_data = note_data.replace("&", "&")
87 | note_data = note_data.replace(""","\"")
88 | note_data = note_data.replace("'","\'")
89 | note_data = note_data.replace("<","<")
90 | note_data = note_data.replace(" ","\t")
91 | note_data = note_data.replace(">",">")
92 | note_data = note_data.replace(",",",")
93 | self.note_input.setPlainText(note_data)
94 |
95 | def get_data(self):
96 | data = self.note_input.toPlainText().strip()
97 | cursor = self.note_input.textCursor()
98 | doc = self.note_input.document()
99 | lines = ""
100 | line = ""
101 | for i in range(doc.blockCount()):
102 | block = doc.findBlockByNumber(i)
103 | if block.isVisible():
104 | for j in range(block.layout().lineCount()):
105 | lineStart = block.position() + block.layout().lineAt(j).textStart()
106 | lineEnd = lineStart + block.layout().lineAt(j).textLength()
107 | cursor.setPosition(lineStart)
108 | cursor.setPosition(lineEnd, QTextCursor.KeepAnchor)
109 | line += cursor.selectedText()
110 | if lineEnd == cursor.position():
111 | lines += line + "\n"
112 | line = ""
113 | lines = lines.strip()
114 | data = lines
115 | data=data.replace("&","&")
116 | data=data.replace("\n", "
")
117 | data = data.replace("\"", """)
118 | data = data.replace("\'", "'")
119 | data = data.replace("\n", "
")
120 | data = data.replace("<", "<")
121 | data = data.replace("\t", " ")
122 | data = data.replace(">", ">")
123 | data=data.replace(",",",")
124 | if data == "":
125 | data = "None"
126 | self.cancelled = False
127 | self.close()
128 | return data
129 |
130 | def cancel_selected(self):
131 | self.cancelled = True
132 | self.close()
133 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/ChatGPT/VHDLModel.py:
--------------------------------------------------------------------------------
1 | #Called in generation.py used for editing the ChatGPT Prompt header
2 | from PySide2.QtWidgets import *
3 | from PySide2.QtGui import *
4 | import yaml
5 |
6 | BLACK_COLOR = "color: black"
7 | WHITE_COLOR = "color: white"
8 |
9 | class VHDLModelDialog(QDialog):
10 |
11 | def __init__(self, add_or_edit, data=None):
12 | super().__init__()
13 |
14 | self.setWindowTitle("ChatGPT VHDL Model Command")
15 | title_font = QFont()
16 | title_font.setPointSize(10)
17 | title_font.setBold(True)
18 | bold_font = QFont()
19 | bold_font.setBold(True)
20 | input_font = QFont()
21 | input_font.setPointSize(10)
22 | self.input_layout = QGridLayout()
23 | self.mainLayout = QVBoxLayout()
24 |
25 | self.ChatGPT_model_label = QLabel("ChatGPT Model Commands")
26 | self.ChatGPT_model_label.setStyleSheet(WHITE_COLOR)
27 | self.ChatGPT_model_label.setFont(input_font)
28 | self.ChatGPT_model_input = QPlainTextEdit()
29 | self.ChatGPT_model_input.setLineWrapMode(QPlainTextEdit.WidgetWidth)
30 | self.ChatGPT_model_input.setFont(input_font)
31 |
32 |
33 | self.reset_btn = QPushButton("Reset")
34 | self.reset_btn.setFont(input_font)
35 | self.reset_btn.setStyleSheet(
36 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
37 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
38 |
39 | self.cancel_btn = QPushButton("Cancel")
40 | self.cancel_btn.setFont(input_font)
41 | self.cancel_btn.setStyleSheet(
42 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
43 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
44 |
45 | self.ok_btn = QPushButton("Ok")
46 | self.ok_btn.setFont(input_font)
47 | self.ok_btn.setStyleSheet(
48 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
49 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
50 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
51 | self.input_frame = QFrame()
52 |
53 | self.cancelled = True
54 |
55 | self.setup_ui()
56 |
57 | self.load_data()
58 |
59 | def setup_ui(self):
60 | self.input_layout.addWidget(self.ChatGPT_model_label, 0, 0, 1, 4)
61 | self.input_layout.addWidget(self.ChatGPT_model_input, 1, 0, 4, 4)
62 | self.input_layout.addWidget(self.reset_btn, 5, 1, 1, 1, alignment=Qt.AlignRight)
63 | self.input_layout.addWidget(self.cancel_btn, 5, 2, 1, 1, alignment=Qt.AlignRight)
64 | self.input_layout.addWidget(self.ok_btn, 5, 3, 1, 1, alignment=Qt.AlignRight)
65 | self.input_frame.setFrameShape(QFrame.StyledPanel)
66 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
67 | self.input_frame.setContentsMargins(10, 10, 10, 10)
68 | self.input_frame.setFixedSize(900, 800)
69 | self.input_frame.setLayout(self.input_layout)
70 | self.cancel_btn.clicked.connect(self.cancel_selected)
71 |
72 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
73 |
74 | self.setLayout(self.mainLayout)
75 | self.ok_btn.clicked.connect(self.get_data)
76 | self.reset_btn.clicked.connect(self.reset)
77 |
78 | def cancel_selected(self):
79 | self.cancelled = True
80 | self.close()
81 |
82 | def load_data(self):
83 | with open('prompts.yml', 'r') as prompts:
84 | self.config = yaml.safe_load(prompts)
85 |
86 | data = self.config["vhdlchatgptmodel"]
87 |
88 | self.ChatGPT_model_input.setPlainText(data)
89 |
90 | def get_data(self):
91 | data = self.ChatGPT_model_input.toPlainText().strip()
92 | self.cancelled = False
93 | self.close()
94 | return data
95 |
96 | def reset(self):
97 | with open('prompts.yml', 'r') as prompts:
98 | self.config = yaml.safe_load(prompts)
99 |
100 | data = self.config["vhdlchatgptmodelreset"]
101 |
102 | self.ChatGPT_model_input.setPlainText(data)
--------------------------------------------------------------------------------
/Application/HDLDesigner/ChatGPT/VerilogModel.py:
--------------------------------------------------------------------------------
1 | #Called in generation.py used for editing the ChatGPT Prompt header
2 | from PySide2.QtWidgets import *
3 | from PySide2.QtGui import *
4 | import yaml
5 |
6 | BLACK_COLOR = "color: black"
7 | WHITE_COLOR = "color: white"
8 |
9 | class VerilogModelDialog(QDialog):
10 |
11 | def __init__(self, add_or_edit, data=None):
12 | super().__init__()
13 |
14 | self.setWindowTitle("ChatGPT Verilog Model Command")
15 | title_font = QFont()
16 | title_font.setPointSize(10)
17 | title_font.setBold(True)
18 | bold_font = QFont()
19 | bold_font.setBold(True)
20 | input_font = QFont()
21 | input_font.setPointSize(10)
22 | self.input_layout = QGridLayout()
23 | self.mainLayout = QVBoxLayout()
24 |
25 | self.ChatGPT_model_label = QLabel("ChatGPT Model Commands")
26 | self.ChatGPT_model_label.setStyleSheet(WHITE_COLOR)
27 | self.ChatGPT_model_label.setFont(input_font)
28 | self.ChatGPT_model_input = QPlainTextEdit()
29 | self.ChatGPT_model_input.setLineWrapMode(QPlainTextEdit.WidgetWidth)
30 | self.ChatGPT_model_input.setFont(input_font)
31 |
32 |
33 | self.reset_btn = QPushButton("Reset")
34 | self.reset_btn.setFont(input_font)
35 | self.reset_btn.setStyleSheet(
36 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
37 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
38 |
39 | self.cancel_btn = QPushButton("Cancel")
40 | self.cancel_btn.setFont(input_font)
41 | self.cancel_btn.setStyleSheet(
42 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
43 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
44 |
45 | self.ok_btn = QPushButton("Ok")
46 | self.ok_btn.setFont(input_font)
47 | self.ok_btn.setStyleSheet(
48 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
49 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
50 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
51 | self.input_frame = QFrame()
52 |
53 | self.cancelled = True
54 |
55 | self.setup_ui()
56 |
57 | self.load_data()
58 |
59 | def setup_ui(self):
60 | self.input_layout.addWidget(self.ChatGPT_model_label, 0, 0, 1, 4)
61 | self.input_layout.addWidget(self.ChatGPT_model_input, 1, 0, 4, 4)
62 | self.input_layout.addWidget(self.reset_btn, 5, 1, 1, 1, alignment=Qt.AlignRight)
63 | self.input_layout.addWidget(self.cancel_btn, 5, 2, 1, 1, alignment=Qt.AlignRight)
64 | self.input_layout.addWidget(self.ok_btn, 5, 3, 1, 1, alignment=Qt.AlignRight)
65 | self.input_frame.setFrameShape(QFrame.StyledPanel)
66 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
67 | self.input_frame.setContentsMargins(10, 10, 10, 10)
68 | self.input_frame.setFixedSize(900, 800)
69 | self.input_frame.setLayout(self.input_layout)
70 | self.cancel_btn.clicked.connect(self.cancel_selected)
71 |
72 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
73 |
74 | self.setLayout(self.mainLayout)
75 | self.ok_btn.clicked.connect(self.get_data)
76 | self.reset_btn.clicked.connect(self.reset)
77 |
78 | def cancel_selected(self):
79 | self.cancelled = True
80 | self.close()
81 |
82 | def load_data(self):
83 | with open('prompts.yml', 'r') as prompts:
84 | self.config = yaml.safe_load(prompts)
85 |
86 | data = self.config["verilogchatgptmodel"]
87 |
88 | self.ChatGPT_model_input.setPlainText(data)
89 |
90 | def get_data(self):
91 | data = self.ChatGPT_model_input.toPlainText().strip()
92 | self.cancelled = False
93 | self.close()
94 | return data
95 |
96 | def reset(self):
97 | with open('prompts.yml', 'r') as prompts:
98 | self.config = yaml.safe_load(prompts)
99 |
100 | data = self.config["verilogchatgptmodelreset"]
101 |
102 | self.ChatGPT_model_input.setPlainText(data)
--------------------------------------------------------------------------------
/Application/HDLDesigner/ChatGPT/chatgpt_help.md:
--------------------------------------------------------------------------------
1 | # ChatGPT
2 |
3 | - Selection of VHDL or Verilog generation is performed in the HDL Designer menu
4 |
5 | - This menu
6 |
7 | - loads and previews the default ChatGPT prompt headers
8 | - Model
9 | - enables editing of the ChatGPT prompt headers
10 |
11 | - Generates and previews HDL templates (and backups the previous version) for
12 | - HDL model
13 | - HDL testbench
14 |
15 | - Assembles, previews, copies the ChatGPT prompt, for (and backups the previous prompt)
16 | - completion of HDL model
17 | - ChatGPT prompt header elements
18 | - ChatGPT prompt header for HDL model template completion
19 | - HDLGen-ChatGPT-generated HDL model tempalte
20 | - generation of HDL testbench stim_p stimulus and signal checking
21 | - ChatGPT prompt header elements
22 | - ChatGPT prompt header for HDL testbench stim_p generation
23 | - testbench signal declarations
24 | - test plan (fromatted)
25 |
26 | - Accesses
27 | - folder
28 | - AMD simulator log files
29 | - backups and clears backup files)
30 |
31 |
32 | HDLGen-ChatGPT allows users to modify and test the ChatGPT prompt headers.
33 | This facilitates handling of any issue uncovered during HDL generation for a particular design,
34 | or accommodating any future changes which may occur in ChatGPT functionality, affecting generated HDL code output.
35 |
36 | The Edit ChatGPT Prompt Header menu opens an editor, displaying and facilitating editing of the selected
37 | ChatGPT prompt and descriptive comment (with ~ comment prefix).
38 | ChatGPT prompts in the HDL Designer > Generate menu, are used for HDL model and HDL testbench HDL generation.
39 | The user selects VHDL or Verilog in the Project Manager TAB.
40 |
41 | An issue can be detected in a generated HDL process or concurrent statement, on review of ChatGPT code or
42 | by a warning or error flagged in the EDA tool. The ChatGPT prompt header can include comments using (~) prefix,
43 | with a ChatGPT prompt instruction to ignore these comments.
44 |
45 | Prompt header comments can be used for description of the reason for the prompt, though also to filter
46 | a ChatGPT prompt to output an individual HDL section, e.g, process or concurrent statement.
47 | The user can subsequently submit focused ChatGPT prompts to query the generated code segment, and request
48 | alternative ChatGPT output. The refined HDL output segment can be pasted into the EDA tool, for further checking
49 | and processing. This incremental HDL generation approach can be very effective. Backups of all ChatGPT prompts
50 | are automatically generated and can be accessed through the HDLGen-ChatGPT generate menu. Note that the incremental
51 | approach diverges from the use of a single crafted ChatGPT prompt and requires the recording of subsequent prompts
52 | by the user, since re-running the original ChatGPT prompt over-writes the latest generated HDL.
53 |
54 | An issue can be detected in a generated HDL process or concurrent statement, on review of ChatGPT code
55 | or by a warning or error flagged in the EDA tool. The ChatGPT prompt header can include comments using (~) prefix,
56 | with a ChatGPT prompt instruction to ignore these comments. Prompt header comments can be used for description of
57 | the reason for the prompt, though also to filter a ChatGPT prompt to output an individual HDL section, e.g, process
58 | or concurrent statement. The user can subsequently submit focused ChatGPT prompts to query the generated code segment,
59 | and request alternative ChatGPT output. The refined HDL output segment can be pasted into the EDA tool, for further
60 | checking and processing. This incremental HDL generation approach can be very effective. Backups of all ChatGPT
61 | prompts are automatically generated and can be accessed through the HDLGen-ChatGPT generate menu. Note that the
62 | incremental approach diverges from the use of a single crafted ChatGPT prompt and requires the recording of subsequent
63 | prompts by the user, since re-running the original ChatGPT prompt over-writes the latest generated HDL.
64 |
65 |
66 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/ChatGPT/chatgpt_help.py:
--------------------------------------------------------------------------------
1 | import markdown as md
2 | from PySide2.QtWidgets import *
3 |
4 | COMP_HELP_DOC_FILE_PATH = "./HDLDesigner/ChatGPT/chatgpt_help.md"
5 |
6 |
7 | class ChatGPTHelpDialog(QDialog):
8 |
9 | def __init__(self):
10 | super().__init__()
11 | self.setWindowTitle("HDLGen Help")
12 |
13 | self.markdown_view = QTextBrowser(readOnly=True)
14 | self.markdown_view.setOpenExternalLinks(True)
15 |
16 | self.mainLayout = QVBoxLayout()
17 | self.setFixedSize(800, 800)
18 | self.setup_ui()
19 |
20 | def setup_ui(self):
21 |
22 | # Writing xml file
23 | with open(COMP_HELP_DOC_FILE_PATH, "r") as f:
24 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
25 | self.markdown_view.setHtml(doc)
26 | self.mainLayout.addWidget(self.markdown_view)
27 | self.setLayout(self.mainLayout)
28 |
29 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/IOPorts/io_port_dialog.py:
--------------------------------------------------------------------------------
1 | #Dialog box for adding/editing port signals called in the io_ports.py class.
2 | from xml.dom import minidom
3 |
4 | from PySide2 import QtWidgets
5 | from PySide2.QtCore import QSizeF
6 | from PySide2.QtWidgets import *
7 | from PySide2.QtGui import *
8 |
9 | BLACK_COLOR = "color: black"
10 | WHITE_COLOR = "color: white"
11 | from ProjectManager.project_manager import ProjectManager
12 | class IOPortDialog(QDialog):
13 |
14 | def __init__(self, add_or_edit, signals_names, signal_data = None):
15 | super().__init__()
16 | input_font = QFont()
17 | input_font.setPointSize(10)
18 | self.input_layout = QGridLayout()
19 |
20 | if add_or_edit == "add":
21 | self.setWindowTitle("New IO Port")
22 | elif add_or_edit == "edit":
23 | self.setWindowTitle("Edit IO Port")
24 | self.signalNames = signals_names
25 | self.signalName=""
26 | if signal_data != None:
27 | self.signalName = signal_data[0]
28 | self.mainLayout = QVBoxLayout()
29 |
30 | self.sig_name_label = QLabel("Signal Name *")
31 | self.sig_name_label.setStyleSheet(WHITE_COLOR)
32 | self.sig_name_label.setFont(input_font)
33 | self.sig_name_input = QLineEdit()
34 | self.sig_name_input.setFont(input_font)
35 |
36 |
37 | self.sig_mode_label = QLabel("Mode")
38 | self.sig_mode_label.setStyleSheet(WHITE_COLOR)
39 | self.sig_mode_label.setFont(input_font)
40 | self.sig_mode_input = QComboBox()
41 | self.sig_mode_input.setFont(input_font)
42 | self.sig_mode_input.setStyleSheet("QComboBox {padding: 2px;}")
43 | pal = self.sig_mode_input.palette()
44 | pal.setColor(QPalette.Button, QColor(255, 255, 255))
45 | self.sig_mode_input.setPalette(pal)
46 | self.sig_mode_input.addItem("Input")
47 | self.sig_mode_input.addItem("Output")
48 |
49 | self.sig_type_label = QLabel("Type")
50 | self.sig_type_label.setStyleSheet(WHITE_COLOR)
51 | self.sig_type_label.setFont(input_font)
52 | self.sig_type_input = QComboBox()
53 | self.sig_type_input.setFont(input_font)
54 | self.sig_type_input.setStyleSheet("QComboBox {padding: 2px;}")
55 | pal = self.sig_type_input.palette()
56 | pal.setColor(QPalette.Button, QColor(255, 255, 255))
57 | self.sig_type_input.setPalette(pal)
58 | self.sig_type_input.addItem("single bit")
59 | self.sig_type_input.addItem("bus")
60 | self.sig_type_input.addItem(("array"))
61 |
62 | self.sig_size_label = QLabel("Size (eg. 32) * ")
63 | self.sig_size_label.setStyleSheet(WHITE_COLOR)
64 | self.sig_size_label.setFont(input_font)
65 | self.sig_size_input = QLineEdit()
66 | self.sig_size_input.setFont(input_font)
67 | self.sig_size_input.setText("1")
68 | self.sig_size_input.setEnabled(False)
69 | self.sig_size_input.setFont(input_font)
70 |
71 | self.arrayName_label = QLabel("Arrays")
72 | self.arrayName_label.setStyleSheet(WHITE_COLOR)
73 | self.arrayName_label.setFont(input_font)
74 | self.arrayName_input = QComboBox()
75 | self.arrayName_input.setFont(input_font)
76 | self.arrayName_input.setStyleSheet("QComboBox {padding: 2px;}")
77 | pal = self.arrayName_input.palette()
78 | pal.setColor(QPalette.Button, QColor(255, 255, 255))
79 | self.arrayName_input.setPalette(pal)
80 | self.arrayName_label.setVisible(False)
81 | self.arrayName_input.setVisible(False)
82 | self.arrayName_input.setCurrentText("Create in packages")
83 |
84 | self.onlyInt = QIntValidator()
85 | self.sig_size_input.setValidator(self.onlyInt)
86 |
87 | self.sig_description_label = QLabel("Signal Description")
88 | self.sig_description_label.setStyleSheet(WHITE_COLOR)
89 | self.sig_description_label.setFont(input_font)
90 | self.sig_description_input = QPlainTextEdit()#MyPlainTextEdit()#QPlainTextEdit()#QLineEdit()
91 | self.sig_description_input.setLineWrapMode(QPlainTextEdit.WidgetWidth)
92 | self.sig_description_input.setFont(input_font)
93 |
94 | self.cancel_btn = QPushButton("Cancel")
95 | self.cancel_btn.setFont(input_font)
96 | self.cancel_btn.setStyleSheet(
97 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
98 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
99 |
100 | self.ok_btn = QPushButton("Ok")
101 | self.ok_btn.setEnabled(False)
102 | self.ok_btn.setFont(input_font)
103 | self.ok_btn.setStyleSheet(
104 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
105 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
106 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
107 |
108 | self.input_frame = QFrame()
109 |
110 | self.cancelled = True
111 | self.arrays=[]
112 | self.setup_ui()
113 | mainPackageDir = ProjectManager.get_package_hdlgen()
114 | root = minidom.parse(mainPackageDir)
115 | HDLGen = root.documentElement
116 | hdlDesign = HDLGen.getElementsByTagName("hdlDesign")
117 | mainPackage = hdlDesign[0].getElementsByTagName("mainPackage")
118 | array_nodes = mainPackage[0].getElementsByTagName('array')
119 |
120 |
121 | if len(array_nodes) != 0:
122 | for i in range(0, len(array_nodes)):
123 | array_name = array_nodes[i].getElementsByTagName('name')[0].firstChild.data
124 | self.arrays.append(array_name)
125 | self.arrayName_input.addItems(self.arrays)
126 |
127 | if add_or_edit == "edit" and signal_data != None:
128 | self.load_signal_data(signal_data)
129 |
130 | def setup_ui(self):
131 | self.input_layout.addWidget(self.sig_name_label, 0, 0, 1, 1)
132 | self.input_layout.addWidget(self.sig_name_input, 1, 0, 1, 1)
133 | self.input_layout.addWidget(self.sig_mode_label, 0, 1, 1, 1)
134 | self.input_layout.addWidget(self.sig_mode_input, 1, 1, 1, 1)
135 | self.input_layout.addWidget(self.sig_type_label, 2, 0, 1, 1)
136 | self.input_layout.addWidget(self.sig_type_input, 3, 0, 1, 1)
137 | self.input_layout.addWidget(self.sig_size_label, 2, 1, 1, 1)
138 | self.input_layout.addWidget(self.sig_size_input, 3, 1, 1, 1)
139 | self.input_layout.addWidget(self.arrayName_label, 2, 1, 1, 1)
140 | self.input_layout.addWidget(self.arrayName_input, 3, 1, 1, 1)
141 | self.input_layout.addWidget(self.sig_description_label, 4, 0, 1, 2)
142 | self.input_layout.addWidget(self.sig_description_input, 5, 0, 1, 2)
143 | self.input_layout.addItem(QSpacerItem(0, 20), 6, 0, 1, 2)
144 | self.input_layout.addWidget(self.cancel_btn, 7, 0, 1, 1, alignment=Qt.AlignRight)
145 | self.input_layout.addWidget(self.ok_btn, 7, 1, 1, 1, alignment=Qt.AlignRight)
146 |
147 | self.input_frame.setFrameShape(QFrame.StyledPanel)
148 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
149 | self.input_frame.setContentsMargins(10, 10, 10, 10)
150 | self.input_frame.setFixedSize(600, 600)
151 | self.input_frame.setLayout(self.input_layout)
152 |
153 | self.sig_name_input.textChanged.connect(self.enable_ok_btn);
154 | self.sig_size_input.textChanged.connect(self.enable_ok_btn);
155 | self.sig_type_input.currentTextChanged.connect(self.enable_size_option)
156 | self.sig_type_input.currentTextChanged.connect(self.sig_type_options)
157 | self.ok_btn.clicked.connect(self.get_signals)
158 | self.cancel_btn.clicked.connect(self.cancel_selected)
159 |
160 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
161 |
162 | self.setLayout(self.mainLayout)
163 |
164 | def get_signals(self):
165 | cursor = self.sig_description_input.textCursor()
166 | doc = self.sig_description_input.document()
167 | lines = ""
168 | line = ""
169 | for i in range(doc.blockCount()):
170 | block = doc.findBlockByNumber(i)
171 | if block.isVisible():
172 | for j in range(block.layout().lineCount()):
173 | lineStart = block.position() + block.layout().lineAt(j).textStart()
174 | lineEnd = lineStart + block.layout().lineAt(j).textLength()
175 | cursor.setPosition(lineStart)
176 | cursor.setPosition(lineEnd, QTextCursor.KeepAnchor)
177 | line += cursor.selectedText()
178 | if lineEnd == cursor.position():
179 | lines += line+"\n"
180 | line = ""
181 | lines=lines.strip()
182 | signalDescription=lines
183 | signalDescription = signalDescription.replace("&", "&")
184 | signalDescription = signalDescription.replace("\n", "
")
185 | signalDescription = signalDescription.replace("\"", """)
186 | signalDescription = signalDescription.replace("\'", "'")
187 | signalDescription = signalDescription.replace("\n", "
")
188 | signalDescription = signalDescription.replace("<", "<")
189 | signalDescription = signalDescription.replace("\t", " ")
190 | signalDescription = signalDescription.replace(">", ">")
191 | signalDescription = signalDescription.replace(",", ",")
192 |
193 | if signalDescription == "":
194 | signalDescription = "to be completed"
195 | if self.sig_type_input.currentText() == "array":
196 | typeValue= "array,"+self.arrayName_input.currentText()
197 | else:
198 | typeValue= self.sig_type_input.currentText()
199 | sig_details = [self.sig_name_input.text().strip().replace(" ", ""),
200 | self.sig_mode_input.currentText(),
201 | typeValue,
202 | self.sig_size_input.text(),
203 | signalDescription
204 | ]
205 | self.cancelled = False
206 | self.close()
207 | return sig_details
208 |
209 | def load_signal_data(self, signal_data):
210 | self.sig_name_input.setText(signal_data[0])
211 | self.sig_mode_input.setCurrentText(signal_data[1])
212 | sig_type=signal_data[2]
213 | if sig_type != "bus" and signal_data[2] != "single bit":
214 | sig_type = "array"
215 | arrayname = signal_data[2].split(",")
216 | self.arrayName_input.setCurrentText(arrayname[1])
217 | self.sig_type_input.setCurrentText(sig_type)
218 | self.sig_size_input.setText(signal_data[3])
219 | signal_data[4] = signal_data[4].replace("
", "\n")
220 | signal_data[4] = signal_data[4].replace("&", "&")
221 | signal_data[4] = signal_data[4].replace("&", "&")
222 | signal_data[4] = signal_data[4].replace(""", "\"")
223 | signal_data[4] = signal_data[4].replace("'", "\'")
224 | signal_data[4] = signal_data[4].replace("<", "<")
225 | signal_data[4] = signal_data[4].replace(" ", "\t")
226 | signal_data[4] = signal_data[4].replace(">", ">")
227 | signal_data[4] = signal_data[4].replace(",", ",")
228 |
229 | self.sig_description_input.setPlainText(signal_data[4])
230 |
231 | def cancel_selected(self):
232 | self.cancelled = True
233 | self.close()
234 |
235 | def enable_ok_btn(self):
236 | if self.sig_name_input.text() != "" and self.sig_size_input.text() != "" and (self.sig_name_input.text() not in self.signalNames or (self.sig_name_input.text() == self.signalName and self.sig_name_input.text() != "")):
237 | self.ok_btn.setEnabled(True)
238 | else:
239 | if self.sig_name_input.text() != "" and self.sig_type_input.currentText() == "array" and self.arrayName_input.currentText() != "":
240 | self.ok_btn.setEnabled(True)
241 | else:
242 | self.ok_btn.setEnabled(False)
243 |
244 | def enable_size_option(self):
245 | if self.sig_type_input.currentText() == "bus":
246 | self.sig_size_input.setEnabled(True)
247 | self.sig_size_input.clear()
248 | else:
249 | self.sig_size_input.setEnabled(False)
250 | self.sig_size_input.setText("1")
251 | def sig_type_options(self):
252 | if self.sig_type_input.currentText() == "array":
253 | self.arrayName_label.setVisible(True)
254 | self.arrayName_input.setVisible(True)
255 | self.sig_size_input.setVisible(False)
256 | self.sig_size_label.setVisible(False)
257 |
258 | else:
259 | self.sig_size_input.setVisible(True)
260 | self.sig_size_label.setVisible(True)
261 | self.arrayName_label.setVisible(False)
262 | self.arrayName_input.setVisible(False)
263 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/IOPorts/port_help.md:
--------------------------------------------------------------------------------
1 | # Port
2 |
3 | - This menu enables the creation and editing of component port signals, with
4 | - port direction: input or output
5 | - port signal type
6 |
7 | - The menu display name, mode, type and size for added port signals
8 |
9 | - If select 'combinational'
10 | - add signal
11 | - signal name
12 | - mode: input or output
13 | - type: single bit, bus, array
14 | - size (width): enter value in the field
15 | - signal description: capture the signal dictionary information fromt the design specification
16 | - Click OK to complete
17 |
18 | - If select 'RTL'
19 | - Setup clk/rst menu appears. Click to open menu.
20 | - L-H low to high active clk edge
21 | - H-L high to low active clk edge
22 | - rst
23 | - No if component does not include a rst input
24 | - Yes
25 | - rst type
26 | - Asynch: asynchronous rst
27 | - Synch: synchronous rst
28 | - active rst level
29 | - 0, asserted low
30 | - 1, asserted high
31 | - Click OK to complete
32 |
33 | - The existing port signals are listed and can be edited or deleted.
--------------------------------------------------------------------------------
/Application/HDLDesigner/IOPorts/port_help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | COMP_HELP_DOC_FILE_PATH = "./HDLDesigner/IOPorts/port_help.md"
6 |
7 |
8 | class IoHelpDialog(QDialog):
9 |
10 | def __init__(self):
11 | super().__init__()
12 | self.setWindowTitle("HDLGen Help")
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 |
17 | self.mainLayout = QVBoxLayout()
18 | self.setFixedSize(800, 800)
19 | self.setup_ui()
20 |
21 | def setup_ui(self):
22 |
23 | # Writing xml file
24 | with open(COMP_HELP_DOC_FILE_PATH, "r") as f:
25 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/IOPorts/sequential_dialog.py:
--------------------------------------------------------------------------------
1 | #Dialog box for adding/editing rtl logic called in the io_ports.py class.
2 | import sys
3 | from xml.dom import minidom
4 | from PySide2.QtWidgets import *
5 | from PySide2.QtGui import *
6 |
7 |
8 |
9 | sys.path.append("..")
10 |
11 | BLACK_COLOR = "color: black"
12 | WHITE_COLOR = "color: white"
13 |
14 | class seqDialog(QDialog):
15 |
16 | def __init__(self, proj_dir):
17 | super().__init__()
18 | input_font = QFont()
19 | input_font.setPointSize(10)
20 | self.input_layout = QGridLayout()
21 | self.setWindowTitle("Set up clk/rst")
22 |
23 | self.mainLayout = QVBoxLayout()
24 |
25 |
26 | self.activeClkEdge_label = QLabel("Active Clk Edge")
27 | self.activeClkEdge_label.setFont(input_font)
28 | self.activeClkEdge_label.setStyleSheet(WHITE_COLOR)
29 | self.activeClkEdge_input = QComboBox()
30 | self.activeClkEdge_input.setFont(input_font)
31 | self.activeClkEdge_input.setStyleSheet("QComboBox {padding: 2px;}")
32 | pal = self.activeClkEdge_input.palette()
33 | pal.setColor(QPalette.Button, QColor(255, 255, 255))
34 | self.activeClkEdge_input.setPalette(pal)
35 | self.activeClkEdge_input.addItem("L-H")
36 | self.activeClkEdge_input.addItem("H-L")
37 |
38 | self.rst_label = QLabel("rst")
39 | self.rst_label.setFont(input_font)
40 | self.rst_label.setStyleSheet(WHITE_COLOR)
41 | self.rst_input = QComboBox()
42 | self.rst_input.setFont(input_font)
43 | self.rst_input.setStyleSheet("QComboBox {padding: 2px;}")
44 | pal = self.rst_input.palette()
45 | pal.setColor(QPalette.Button, QColor(255, 255, 255))
46 | self.rst_input.setPalette(pal)
47 | self.rst_input.addItem("No")
48 | self.rst_input.addItem("Yes")
49 |
50 | self.rstType_label = QLabel("rst type")
51 | self.rstType_label.setFont(input_font)
52 | self.rstType_label.setStyleSheet(WHITE_COLOR)
53 | self.rstType_label.setVisible(False)
54 | self.rstType_input = QComboBox()
55 | self.rstType_input.setFont(input_font)
56 | self.rstType_input.setStyleSheet("QComboBox {padding: 2px;}")
57 | pal = self.rstType_input.palette()
58 | pal.setColor(QPalette.Button, QColor(255, 255, 255))
59 | self.rstType_input.setPalette(pal)
60 | self.rstType_input.addItem("asynch")
61 | self.rstType_input.addItem("synch")
62 | self.rstType_input.setVisible(False)
63 |
64 | self.activeRstLvlEq1_label = QLabel("Active rst lvl")
65 | self.activeRstLvlEq1_label.setStyleSheet(WHITE_COLOR)
66 | self.activeRstLvlEq1_label.setVisible(False)
67 | self.activeRstLvlEq1_label.setFont(input_font)
68 | self.activeRstLvlEq1_input = QComboBox()
69 | pal = self.activeRstLvlEq1_input.palette()
70 | self.activeRstLvlEq1_input.setFont(input_font)
71 | self.activeRstLvlEq1_input.setStyleSheet("QComboBox {padding: 2px;}")
72 | pal.setColor(QPalette.Button, QColor(255, 255, 255))
73 | self.activeRstLvlEq1_input.setPalette(pal)
74 | self.activeRstLvlEq1_input.addItem("1")
75 | self.activeRstLvlEq1_input.addItem("0")
76 | self.activeRstLvlEq1_input.setVisible(False)
77 |
78 | self.cancel_btn = QPushButton("Cancel")
79 | self.cancel_btn.setFont(input_font)
80 | self.cancel_btn.setStyleSheet(
81 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
82 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
83 |
84 | self.ok_btn = QPushButton("Ok")
85 | self.ok_btn.setFont(input_font)
86 | self.ok_btn.setStyleSheet(
87 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
88 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
89 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
90 |
91 | self.input_frame = QFrame()
92 |
93 | self.cancelled = True
94 |
95 | self.setup_ui()
96 |
97 | if proj_dir != None:
98 | self.load_data(proj_dir)
99 | def setup_ui(self):
100 | self.input_layout.addWidget(self.activeClkEdge_label, 0, 0, 1, 1, alignment=Qt.AlignTop)
101 | self.input_layout.addWidget(self.activeClkEdge_input, 1, 0, 1, 1, alignment=Qt.AlignTop)
102 | self.input_layout.addWidget(self.rst_label, 0, 1, 1, 1, alignment=Qt.AlignTop)
103 | self.input_layout.addWidget(self.rst_input, 1, 1, 1, 1, alignment=Qt.AlignTop)
104 | self.input_layout.addItem(QSpacerItem(0, 100), 2, 0)
105 | self.input_layout.addWidget(self.rstType_label, 2, 0, 1, 1, alignment=Qt.AlignBottom)
106 | self.input_layout.addWidget(self.rstType_input, 3, 0, 1, 1, alignment=Qt.AlignTop)
107 | self.input_layout.addWidget(self.activeRstLvlEq1_label, 2, 1, 1, 1, alignment=Qt.AlignBottom)
108 | self.input_layout.addWidget(self.activeRstLvlEq1_input, 3, 1, 1, 1, alignment=Qt.AlignTop)
109 | self.input_layout.addItem(QSpacerItem(0, 100), 4, 0)
110 | self.input_layout.addWidget(self.cancel_btn, 5, 0, alignment=Qt.AlignRight)
111 | self.input_layout.addWidget(self.ok_btn, 5, 1, alignment=Qt.AlignRight)
112 |
113 | self.input_frame.setFrameShape(QFrame.StyledPanel)
114 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
115 | self.input_frame.setContentsMargins(10, 10, 10, 10)
116 | self.input_frame.setFixedSize(400, 400)
117 | self.input_frame.setLayout(self.input_layout)
118 |
119 | self.ok_btn.clicked.connect(self.get_clkAndRst)
120 | self.cancel_btn.clicked.connect(self.cancel_selected)
121 | self.rst_input.currentTextChanged.connect(self.rst_options)
122 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
123 |
124 | self.setLayout(self.mainLayout)
125 |
126 | def get_clkAndRst(self):
127 | if self.rst_input.currentText() == "Yes":
128 | clkAndRst_details = [self.activeClkEdge_input.currentText(),
129 | self.rst_input.currentText(),
130 | self.rstType_input.currentText(),
131 | self.activeRstLvlEq1_input.currentText()
132 | ]
133 | else:
134 | clkAndRst_details = [self.activeClkEdge_input.currentText(),
135 | self.rst_input.currentText()
136 | ]
137 | self.cancelled = False
138 | self.close()
139 | return clkAndRst_details
140 | def cancel_selected(self):
141 | self.cancelled = True
142 | self.close()
143 |
144 |
145 |
146 | def rst_options(self):
147 | if self.rst_input.currentText() == "Yes":
148 | self.rstType_label.setVisible(True)
149 | self.rstType_input.setVisible(True)
150 | self.activeRstLvlEq1_label.setVisible(True)
151 | self.activeRstLvlEq1_input.setVisible(True)
152 | else:
153 | self.rstType_label.setVisible(False)
154 | self.rstType_input.setVisible(False)
155 | self.activeRstLvlEq1_label.setVisible(False)
156 | self.activeRstLvlEq1_input.setVisible(False)
157 |
158 | def enable_size_option(self):
159 | if self.sig_type_input.currentText() == "Yes":
160 | self.sig_size_input.setEnabled(True)
161 | self.sig_size_input.clear()
162 | else:
163 | self.sig_size_input.setEnabled(False)
164 | self.sig_size_input.setText("1")
165 |
166 | def load_data(self, proj_dir):
167 |
168 | root = minidom.parse(str(proj_dir))
169 | HDLGen = root.documentElement
170 | hdlDesign = HDLGen.getElementsByTagName("hdlDesign")
171 |
172 | clkAndRst = hdlDesign[0].getElementsByTagName('clkAndRst')
173 | if clkAndRst[0].firstChild is not None:
174 | for i in range(0, len(clkAndRst)):
175 | clkEdgeValue = clkAndRst[i].getElementsByTagName('activeClkEdge')[0].firstChild.data
176 | rstValue = clkAndRst[i].getElementsByTagName('rst')[0].firstChild.data
177 | self.activeClkEdge_input.setCurrentText(clkEdgeValue)
178 | self.rst_input.setCurrentText(rstValue)
179 | if rstValue == "Yes":
180 | rstTypeValue = clkAndRst[i].getElementsByTagName('RstType')[0].firstChild.data
181 | rstLvlValue = clkAndRst[i].getElementsByTagName('ActiveRstLvl')[0].firstChild.data
182 | self.rstType_input.setCurrentText(rstTypeValue)
183 | self.activeRstLvlEq1_input.setCurrentText(rstLvlValue)
184 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/InternalSignal/internal_help.md:
--------------------------------------------------------------------------------
1 | # Internal Signal
2 |
3 | - This menu enables the creation and editing of internal signals
4 |
5 | - The menu display name, mode, type and size for added port signals
6 |
7 | - If select add signal
8 | - internal signal name
9 |
10 | - signal type
11 |
12 | - standard
13 | - single bit
14 | - bus
15 | - signed
16 | - unsigned
17 | - integer
18 | - signal description
19 |
20 | - state signal pair (NS/CS)
21 | - CS name
22 | - NS name
23 | - suffix
24 | - bus
25 | - size
26 | - signal description
27 | - enumerated type
28 | - add state
29 | - signal description
30 | - integer
31 | - no of values
32 | - signal description
33 | - size
34 | - signal description
35 |
36 | - array
37 | - select array name from list (created sub-components menu)
38 | - signal description
39 |
40 | - Click OK to complete
41 |
42 | - The existing internal signals are listed and can be edited or deleted
43 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/InternalSignal/internal_help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | COMP_HELP_DOC_FILE_PATH = "./HDLDesigner/InternalSignal/internal_help.md"
6 |
7 |
8 | class IntHelpDialog(QDialog):
9 |
10 | def __init__(self):
11 | super().__init__()
12 | self.setWindowTitle("HDLGen Help")
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 |
17 | self.mainLayout = QVBoxLayout()
18 | self.setFixedSize(800, 800)
19 | self.setup_ui()
20 |
21 | def setup_ui(self):
22 |
23 | # Writing xml file
24 | with open(COMP_HELP_DOC_FILE_PATH, "r") as f:
25 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/InternalSignal/stateNamesDialog.py:
--------------------------------------------------------------------------------
1 | #state names dialog called in int_sig_dialog.py if state name is added
2 | from PySide2.QtWidgets import *
3 | from PySide2.QtGui import *
4 |
5 | import sys
6 |
7 | sys.path.append("..")
8 | from ProjectManager.project_manager import ProjectManager
9 |
10 | BLACK_COLOR = "color: black"
11 | WHITE_COLOR = "color: white"
12 |
13 |
14 | class state_Name_Dialog(QDialog):
15 |
16 | def __init__(self, add_or_edit, stateName_data=None):
17 | super().__init__()
18 |
19 | self.input_layout = QGridLayout()
20 | self.setWindowTitle("New State Name")
21 |
22 | title_font = QFont()
23 | title_font.setPointSize(10)
24 | title_font.setBold(True)
25 | bold_font = QFont()
26 | bold_font.setBold(True)
27 | input_font = QFont()
28 | input_font.setPointSize(10)
29 | self.mainLayout = QVBoxLayout()
30 |
31 | self.state_name_label = QLabel("State Name")
32 | self.state_name_label.setFont(input_font)
33 | self.state_name_label.setStyleSheet(WHITE_COLOR)
34 | self.state_name_input = QLineEdit()
35 | self.state_name_input.setFont(input_font)
36 |
37 | self.cancel_btn = QPushButton("Cancel")
38 | self.cancel_btn.setFont(input_font)
39 | self.cancel_btn.setStyleSheet(
40 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
41 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
42 |
43 | self.ok_btn = QPushButton("Ok")
44 | self.ok_btn.setEnabled(False)
45 | self.ok_btn.setFont(input_font)
46 | self.ok_btn.setStyleSheet(
47 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
48 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
49 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
50 |
51 | self.input_frame = QFrame()
52 |
53 | self.cancelled = True
54 |
55 | self.setup_ui()
56 | if add_or_edit == "edit" and stateName_data != None:
57 | self.load_sig_data(stateName_data)
58 |
59 | def setup_ui(self):
60 |
61 | self.input_layout.addWidget(self.state_name_label, 0, 0, 1, 1)
62 | self.input_layout.addWidget(self.state_name_input, 1, 0, 1, 3)
63 |
64 |
65 | self.input_layout.addItem(QSpacerItem(0, 20), 2, 0, 1, 3)
66 | self.input_layout.addWidget(self.cancel_btn, 3, 1, 1, 1, alignment=Qt.AlignRight)
67 | self.input_layout.addWidget(self.ok_btn, 3, 2, 1, 1, alignment=Qt.AlignRight)
68 |
69 | self.input_frame.setFrameShape(QFrame.StyledPanel)
70 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
71 | self.input_frame.setContentsMargins(10, 10, 10, 10)
72 | self.input_frame.setLayout(self.input_layout)
73 |
74 | self.state_name_input.textChanged.connect(self.enable_ok_btn);
75 |
76 | self.ok_btn.clicked.connect(self.get_data)
77 | self.cancel_btn.clicked.connect(self.cancel_selected)
78 |
79 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
80 |
81 | self.setLayout(self.mainLayout)
82 |
83 |
84 | def load_sig_data(self, stateName_data):
85 | self.state_name_input.setText(stateName_data)
86 |
87 | def get_data(self):
88 | state_name = self.state_name_input.text().strip().replace(" ", "")
89 | data = state_name
90 | self.cancelled = False
91 | self.close()
92 | return data
93 |
94 | def cancel_selected(self):
95 | self.cancelled = True
96 | self.close()
97 |
98 | def enable_ok_btn(self):
99 | if self.state_name_input.text() != "" :
100 | self.ok_btn.setEnabled(True)
101 | else:
102 | self.ok_btn.setEnabled(False)
103 |
104 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/Package/package_dialog.py:
--------------------------------------------------------------------------------
1 | #Dialog box for adding/editing type called in the package.py class.
2 | from PySide2.QtWidgets import *
3 | from PySide2.QtGui import *
4 | import sys
5 |
6 | sys.path.append("..")
7 |
8 | BLACK_COLOR = "color: black"
9 | WHITE_COLOR = "color: white"
10 |
11 |
12 | class PackageDialog(QDialog):
13 |
14 | def __init__(self, add_or_edit, array_data=None):
15 | super().__init__()
16 | self.input_layout = QGridLayout()
17 | if add_or_edit == "add":
18 | self.setWindowTitle("New Package Signal")
19 | elif add_or_edit == "edit":
20 | self.setWindowTitle("Edit Package Signal")
21 |
22 | input_font = QFont()
23 | input_font.setPointSize(10)
24 | bold_font = QFont()
25 | bold_font.setBold(True)
26 |
27 | self.mainLayout = QVBoxLayout()
28 | self.sig_types = [ "bus", "signed", "unsigned"]
29 | self.array_name_label = QLabel("Array Name*")
30 | self.array_name_label.setStyleSheet(WHITE_COLOR)
31 | self.array_name_label.setFont(input_font)
32 | self.array_name_input = QLineEdit()
33 | self.array_name_input.setFont(input_font)
34 |
35 | self.arraySize_label = QLabel("Array Depth")
36 | self.arraySize_label.setFont(input_font)
37 | self.arraySize_label.setStyleSheet(WHITE_COLOR)
38 | self.arraySize_input = QLineEdit()
39 | self.arraySize_input.setFont(input_font)
40 |
41 | self.arrayLength_label = QLabel("Array Width")
42 | self.arrayLength_label.setStyleSheet(WHITE_COLOR)
43 | self.arrayLength_label.setFont(input_font)
44 | self.arrayLength_input = QLineEdit()
45 | self.arrayLength_input.setFont(input_font)
46 |
47 | self.sig_type_label = QLabel("Signal Type")
48 | self.sig_type_label.setFont(input_font)
49 | self.sig_type_label.setStyleSheet(WHITE_COLOR)
50 | self.sig_type_combo = QComboBox()
51 | self.sig_type_combo.setFont(input_font)
52 | self.sig_type_combo.setStyleSheet("QComboBox {padding: 2px;}")
53 | pal = self.sig_type_combo.palette()
54 | pal.setColor(QPalette.Button, QColor(255, 255, 255))
55 | self.sig_type_combo.setPalette(pal)
56 | self.sig_type_combo.addItems(self.sig_types)
57 |
58 | self.onlyInt = QIntValidator()
59 | self.arraySize_input.setValidator(self.onlyInt)
60 | self.arrayLength_input.setValidator(self.onlyInt)
61 |
62 | self.sig_desc_label = QLabel("Signal Description")
63 | self.sig_desc_label.setFont(input_font)
64 | self.sig_desc_label.setStyleSheet(WHITE_COLOR)
65 | self.sig_desc_input = QLineEdit()
66 | self.sig_desc_input.setFont(input_font)
67 |
68 | self.cancel_btn = QPushButton("Cancel")
69 | self.cancel_btn.setFont(input_font)
70 | self.cancel_btn.setStyleSheet(
71 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
72 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
73 |
74 | self.ok_btn = QPushButton("Ok")
75 | self.ok_btn.setFont(input_font)
76 | self.ok_btn.setEnabled(False)
77 | self.ok_btn.setStyleSheet(
78 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
79 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
80 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
81 |
82 | self.input_frame = QFrame()
83 |
84 | self.cancelled = True
85 |
86 | self.setup_ui()
87 |
88 | if add_or_edit == "edit" and array_data != None:
89 | self.load_sig_data(array_data)
90 |
91 | def setup_ui(self):
92 |
93 | self.input_layout.addWidget(self.array_name_label, 0, 0) # , 1, 3)
94 | self.input_layout.addWidget(self.array_name_input, 1, 0) # , 1, 3)
95 |
96 | self.input_layout.addWidget(self.sig_type_label, 0, 1)
97 | self.input_layout.addWidget(self.sig_type_combo, 1, 1)
98 |
99 | self.input_layout.addWidget(self.arraySize_label, 2, 0, 1, 1)
100 | self.input_layout.addWidget(self.arraySize_input, 3, 0, 1, 1)
101 |
102 | self.input_layout.addWidget(self.arrayLength_label, 2, 1, 1, 1)
103 | self.input_layout.addWidget(self.arrayLength_input, 3, 1, 1, 1)
104 |
105 | self.input_layout.addItem(QSpacerItem(0, 20), 4, 0, 1, 2)
106 | self.input_layout.addWidget(self.cancel_btn, 5, 0, 1, 1, alignment=Qt.AlignRight)
107 | self.input_layout.addWidget(self.ok_btn, 5, 1, 1, 1, alignment=Qt.AlignRight)
108 |
109 | self.input_frame.setFrameShape(QFrame.StyledPanel)
110 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
111 | self.input_frame.setContentsMargins(10, 10, 10, 10)
112 | #self.input_frame.setFixedSize(600, 600)
113 | self.input_frame.setLayout(self.input_layout)
114 |
115 | self.ok_btn.clicked.connect(self.get_data)
116 | self.cancel_btn.clicked.connect(self.cancel_selected)
117 |
118 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
119 | self.arraySize_input.textChanged.connect(self.enable_ok_btn)
120 | self.arrayLength_input.textChanged.connect(self.enable_ok_btn)
121 | self.setLayout(self.mainLayout)
122 |
123 | def load_sig_data(self, array_data):
124 | self.array_name_input.setText(array_data[0])
125 | self.arraySize_input.setText(array_data[1])
126 | self.arrayLength_input.setText(array_data[2])
127 | sig_type = array_data[3]
128 | if sig_type == "std_logic_vector":
129 | sig_type = "bus"
130 | self.sig_type_combo.setCurrentText(sig_type)
131 |
132 | def get_data(self):
133 | sig_type = self.sig_type_combo.currentText()
134 | if sig_type == "bus":
135 | sig_type = "std_logic_vector"
136 | data = [self.array_name_input.text().strip(), self.arraySize_input.text().strip(), self.arrayLength_input.text().strip(), sig_type]
137 |
138 | self.cancelled = False
139 | self.close()
140 |
141 | return data
142 |
143 | def cancel_selected(self):
144 | self.cancelled = True
145 | self.close()
146 |
147 | def enable_ok_btn(self):
148 | if self.array_name_input.text() != "" and self.arraySize_input.text() != "" and self.arrayLength_input.text() != "":
149 | self.ok_btn.setEnabled(True)
150 | else:
151 | self.ok_btn.setEnabled(False)
152 | def delete_clicked(self):
153 | button = self.sender()
154 | if button:
155 | print("deleting row")
156 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/Package/package_help.md:
--------------------------------------------------------------------------------
1 | # Type
2 |
3 | - This menu enables the creation of bus, signed or unsigned 2-D array types
4 |
5 | - Click on 'Add type'
6 |
7 | - Menu options
8 | - Array Name
9 | - Select any name, not already used
10 | - Signal Type
11 | - Select bus, signed or unsigned type
12 | - Array Depth
13 | - Select the number of array elements, e.g, in an 8 x 32-bit array the value would be 8
14 | - Array Width
15 | - Select the array data width, e.g, in an 8 x 32-bit array the value would be 32
16 |
17 | - The existing array types are listed and can be edited or deleted.
--------------------------------------------------------------------------------
/Application/HDLDesigner/Package/package_help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | COMP_HELP_DOC_FILE_PATH = "./HDLDesigner/Package/package_help.md"
6 |
7 |
8 | class PackHelpDialog(QDialog):
9 |
10 | def __init__(self):
11 | super().__init__()
12 | self.setWindowTitle("HDLGen Help")
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 |
17 | self.mainLayout = QVBoxLayout()
18 | self.setFixedSize(800, 800)
19 | self.setup_ui()
20 |
21 | def setup_ui(self):
22 |
23 | # Writing xml file
24 | with open(COMP_HELP_DOC_FILE_PATH, "r") as f:
25 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/Subcomponents/component_dialog.py:
--------------------------------------------------------------------------------
1 | #Dialog box for adding/editing sub-component called in the subcomponents.py class.
2 | import re
3 | import os
4 | from PySide2.QtWidgets import *
5 | from PySide2.QtGui import *
6 | from pathlib import Path
7 | import sys
8 |
9 | sys.path.append("..")
10 | import configparser
11 | from ProjectManager.project_manager import ProjectManager
12 | from Generator.generator import Generator
13 |
14 | WHITE_COLOR = "color: white"
15 |
16 | class ComponentDialog(QDialog):
17 | def __init__(self, add_or_edit, component_data = None):
18 | super().__init__()
19 |
20 | if add_or_edit == "add":
21 | self.setWindowTitle("New component")
22 | elif add_or_edit == "edit":
23 | self.setWindowTitle("Edit component")
24 |
25 | input_font = QFont()
26 | input_font.setPointSize(10)
27 | bold_font = QFont()
28 | bold_font.setBold(True)
29 |
30 | self.internal_signals = []
31 | self.input_signals = []
32 | self.output_signals = []
33 |
34 | self.input_layout = QGridLayout()
35 |
36 | self.mainLayout = QVBoxLayout()
37 |
38 | self.component_name_label = QLabel("Component Name")
39 | self.component_name_label.setStyleSheet(WHITE_COLOR)
40 | self.component_name_label.setFont(input_font)
41 | self.component_name_input = QLabel("Browse to select VHDL Model")
42 | self.component_name_input.setStyleSheet(WHITE_COLOR)
43 | self.component_name_input.setEnabled(False)
44 | self.component_name_input.setFont(input_font)
45 |
46 | self.signal_empty_info = QLabel("No Top level Signals found!\nPlease add input and output signals in Ports")
47 | self.signal_empty_info.setFont(input_font)
48 | self.signal_empty_info.setFixedSize(400, 300)
49 | self.signal_table = QTableWidget()
50 |
51 | self.signal_layout = QVBoxLayout()
52 | self.signal_frame = QFrame()
53 |
54 | self.file_path_label = QLabel("Component model file path")
55 | self.file_path_label.setFont(input_font)
56 | self.file_path_label.setStyleSheet(WHITE_COLOR)
57 | self.file_path_input = QLineEdit()
58 | self.file_path_input.setFont(input_font)
59 |
60 | self.browse_btn = QPushButton("Browse")
61 | self.browse_btn.setFont(input_font)
62 | self.browse_btn.setStyleSheet(
63 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
64 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
65 |
66 | self.cancel_btn = QPushButton("Cancel")
67 | self.cancel_btn.setFont(input_font)
68 | self.cancel_btn.setStyleSheet(
69 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
70 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
71 |
72 | self.ok_btn = QPushButton("Ok")
73 | self.ok_btn.setFont(input_font)
74 | self.ok_btn.setStyleSheet(
75 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
76 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
77 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
78 |
79 | self.input_frame = QFrame()
80 |
81 | self.cancelled = True
82 | self.generator = Generator()
83 | self.config = configparser.ConfigParser()
84 | self.setup_ui()
85 |
86 |
87 | if add_or_edit == "edit" and component_data != None:
88 | self.load_component_data(component_data)
89 |
90 | def setup_ui(self):
91 | bold_font = QFont()
92 | bold_font.setBold(True)
93 |
94 | self.signal_table.setFrameStyle(QFrame.NoFrame)
95 | self.signal_table.setColumnCount(3)
96 | self.signal_table.setShowGrid(False)
97 | self.signal_table.setHorizontalHeaderLabels(['Name', 'Mode', ' Type'])
98 | header = self.signal_table.horizontalHeader()
99 | header.setSectionsClickable(False)
100 | header.setSectionsMovable(False)
101 | self.signal_table.horizontalHeader().setFont(bold_font)
102 | self.signal_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
103 | self.signal_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
104 | self.signal_table.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
105 |
106 | self.signal_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
107 | vert = self.signal_table.verticalHeader()
108 | vert.hide()
109 | self.signal_layout.addWidget(self.signal_table)
110 | self.signal_frame.setFrameStyle(QFrame.NoFrame)
111 | self.signal_frame.setStyleSheet(".QFrame{background-color: white; border-radius: 5px;}")
112 | self.signal_frame.setLayout(self.signal_layout)
113 | self.signal_frame.setFixedSize(600, 600)
114 |
115 | self.input_layout.addWidget(self.component_name_label, 0, 0, 1, 1)
116 | self.input_layout.addWidget(self.component_name_input, 1, 0, 1, 1)
117 | self.input_layout.addWidget(self.file_path_label, 2, 0, 1, 2)
118 | self.input_layout.addWidget(self.file_path_input,3, 0, 1, 1)
119 | self.input_layout.addWidget(self.browse_btn, 3, 1, 1, 1)
120 | self.input_layout.addWidget(self.signal_frame, 4, 0, 4, 2)
121 |
122 |
123 | self.input_layout.addItem(QSpacerItem(0, 50), 6, 0, 1, 3)
124 | self.input_layout.addWidget(self.cancel_btn, 8, 0, 1, 1, alignment=Qt.AlignRight)
125 | self.input_layout.addWidget(self.ok_btn, 8, 1, 1, 1, alignment=Qt.AlignRight)
126 |
127 | self.input_frame.setFrameShape(QFrame.StyledPanel)
128 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
129 | self.input_frame.setContentsMargins(10, 10, 10, 10)
130 | self.input_frame.setLayout(self.input_layout)
131 | self.ok_btn.clicked.connect(self.get_data)
132 | self.cancel_btn.clicked.connect(self.cancel_selected)
133 | self.browse_btn.clicked.connect(self.set_comp_path)
134 |
135 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
136 |
137 | self.setLayout(self.mainLayout)
138 |
139 | def populate_signals(self, comp_dir):
140 | abs_component_path = os.path.join(ProjectManager.get_proj_environment(), comp_dir)
141 | rows = self.signal_table.rowCount()
142 |
143 | # Remove all existing rows if repopulating the signals table
144 | for i in range(rows):
145 | self.signal_table.removeRow(0)
146 |
147 | self.comp_signals, self.model, self.comp_mode = self.loadComponent(abs_component_path)
148 |
149 | for i, signal in enumerate(self.comp_signals):
150 | temp = self.comp_mode[i].split(' ')
151 | row_position = self.signal_table.rowCount()
152 | self.signal_table.insertRow(row_position)
153 | self.signal_table.setRowHeight(row_position, 5)
154 |
155 | self.signal_table.setItem(row_position, 0, QTableWidgetItem(signal))
156 | if temp[1] == "std_logic":
157 | temp[1] = "single bit"
158 | elif temp[1][0:16] == "std_logic_vector":
159 | temp[1] = "bus "+ "["+temp[1][17:]+":0]"
160 | self.signal_table.setItem(row_position, 1, QTableWidgetItem(temp[0]))
161 | self.signal_table.setItem(row_position, 2, QTableWidgetItem(temp[1]))
162 |
163 | @staticmethod
164 | def is_subdirectory(directory, parent):
165 | # Get the common prefix of the two paths
166 | common_prefix = os.path.commonprefix([directory, parent])
167 |
168 | # Check if the common prefix is the same as the potential parent
169 | return os.path.normpath(common_prefix) == os.path.normpath(parent)
170 |
171 | def set_comp_path(self):
172 | environment = ProjectManager.get_proj_environment()
173 |
174 | comp_path = QFileDialog.getOpenFileName(self, "Select model .vhd file", dir=str(environment), filter="VHDL files (*.vhd)")
175 |
176 | comp_path = Path(comp_path[0])
177 |
178 | if comp_path != "" and ComponentDialog.is_subdirectory(comp_path, environment):
179 | comp_rel_path = os.path.relpath(comp_path, environment)
180 | self.file_path_input.setText(str(comp_path))
181 | self.populate_signals(comp_rel_path)
182 | print("The directory is within the potential parent directory.")
183 | else:
184 | print("The directory is not within the potential parent directory.")
185 | msgBox = QMessageBox()
186 | msgBox.setWindowTitle("Alert")
187 | msgBox.setText("Component cannot be added!\nThe component is not part of the project environment.")
188 | msgBox.exec_()
189 |
190 | def load_component_data(self, component_data):
191 | self.component_name_input.setText(component_data[0])
192 | self.file_path_input.setText(
193 | str(os.path.join(ProjectManager.get_proj_environment(), component_data[1]))
194 | )
195 | signals = []
196 | mode = []
197 | type = []
198 | rows = self.signal_table.rowCount()
199 | for i in range(rows):
200 | self.signal_table.removeRow(0)
201 | for signal in component_data[2]:
202 | temp = signal.split(',')
203 | signals.append(temp[0])
204 | mode.append(temp[1])
205 | type.append(temp[2])
206 | i = 0
207 | for sig in signals:
208 | row_position = self.signal_table.rowCount()
209 | self.signal_table.insertRow(row_position)
210 | self.signal_table.setRowHeight(row_position, 5)
211 | self.signal_table.setItem(row_position, 0, QTableWidgetItem(sig))
212 | self.signal_table.setItem(row_position, 1, QTableWidgetItem(mode[i]))
213 | if type[i] == "std_logic":
214 | type[i] = "single bit"
215 | elif type[i][0:16] == "std_logic_vector":
216 | type[i] = "bus "+ "["+type[i][17:]
217 | type[i] = type[i].replace(" downto ",":")
218 | type[i] = type[i].replace(")","]")
219 | self.signal_table.setItem(row_position, 2, QTableWidgetItem(type[i]))
220 | i = i+1
221 | self.signal_layout.addWidget(self.signal_table)
222 |
223 | def cancel_selected(self):
224 | self.cancelled = True
225 | self.close()
226 |
227 | def enable_ok_btn(self):
228 | if self.component_name_input.text() != "":
229 | self.ok_btn.setEnabled(True)
230 | else:
231 | self.ok_btn.setEnabled(False)
232 |
233 | def get_data(self):
234 | data = []
235 | signals = []
236 |
237 | for i in range(self.signal_table.rowCount()):
238 | signal = self.signal_table.item(i, 0).text()
239 | mode = self.signal_table.item(i, 1).text()
240 | type = self.signal_table.item(i, 2).text()
241 |
242 | if type == "single bit":
243 | type = "std_logic"
244 |
245 | elif type[0:3] == "bus":
246 | type = "std_logic_vector(" + type[5:] + " downto 0)"
247 | type = type.replace(":0]","")
248 |
249 | signals.append(signal + "," + mode + "," + type)
250 |
251 | data.append(self.component_name_input.text())
252 | # When saving the component path to disk, save it as a relative path, relative to the project environment.
253 | # This keeps file paths intact if the project is moved from one disk to another.
254 | comp_path = self.file_path_input.text()
255 | environment = ProjectManager.get_proj_environment()
256 | comp_rel_path = os.path.relpath(comp_path, environment)
257 |
258 | data.append(comp_rel_path)
259 | data.append(signals)
260 | self.cancelled = False
261 | self.close()
262 | return data
263 |
264 | def loadComponent(self, comp_dir):
265 | # Open the VHDL file and read its contents
266 | with open(comp_dir, 'r') as file:
267 | vhdl_code = file.read()
268 | # Use a regular expression to match the port declarations
269 | model = os.path.splitext(os.path.basename(comp_dir))[0]
270 | start_port_pattern = re.compile(r'entity\s*' + model + '\s*is\s*Port\s*\(', re.IGNORECASE | re.DOTALL)
271 | matchStart = start_port_pattern.search(vhdl_code)
272 | startEnd = matchStart.end()
273 | startStart = matchStart.start()
274 | end_port_pattern = re.compile(r'\);\s*end\s*Entity\s*' + model, re.IGNORECASE | re.DOTALL)
275 | matchEnd = end_port_pattern.search(vhdl_code)
276 | endStart = matchEnd.start()
277 | endEnd = matchEnd.end()
278 |
279 | asign = vhdl_code[startEnd:endStart]
280 | asign = "\n".join([line for line in asign.splitlines() if line.strip()])
281 | signal_names = [line.split(":")[0].strip() for line in asign.splitlines()]
282 | signal_mode = [line.split(":")[1].strip().replace(";","") for line in asign.splitlines()]
283 | self.component_name_input.setText(model)
284 | return signal_names, model, signal_mode
285 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/Subcomponents/subcomp_help.md:
--------------------------------------------------------------------------------
1 | # Sub-component
2 |
3 | - This menue enables the creation of a component for use in hierarchical designs
4 |
5 | - Click on 'Add component'
6 |
7 | - Use the browser to find and select the component model in the folder structure
8 | - Browse to the VHDL or Verilog 'model' folder and the .vhd or .v fiel respectively
9 | - The component signal ports will appear, with signal name, mode and type
10 | - Click OK to complete
11 |
12 | - The existing components are listed and can be edited or deleted.
--------------------------------------------------------------------------------
/Application/HDLDesigner/Subcomponents/subcomp_help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | COMP_HELP_DOC_FILE_PATH = "./HDLDesigner/Subcomponents/subcomp_help.md"
6 |
7 |
8 | class SubcompHelpDialog(QDialog):
9 |
10 | def __init__(self):
11 | super().__init__()
12 | self.setWindowTitle("HDLGen Help")
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 |
17 | self.mainLayout = QVBoxLayout()
18 | self.setFixedSize(800, 800)
19 | self.setup_ui()
20 |
21 | def setup_ui(self):
22 |
23 | # Writing xml file
24 | with open(COMP_HELP_DOC_FILE_PATH, "r") as f:
25 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/Subcomponents/subcomponents.py:
--------------------------------------------------------------------------------
1 | #Sub-components section in HDL Designer. This class will call component_dialog.py when adding/editing a component and subcomp_help.md if help button is clicked
2 | #This class will save all entered data to the mainPackage.hdlgen. The save happens when there is a change.
3 | import os
4 | import sys
5 | from xml.dom import minidom
6 | from PySide2.QtWidgets import *
7 | from PySide2.QtGui import *
8 | import qtawesome as qta
9 |
10 | sys.path.append("../..")
11 | from ProjectManager.project_manager import ProjectManager
12 | from HDLDesigner.Subcomponents.component_dialog import ComponentDialog
13 | from Generator.generator import Generator
14 | from HDLDesigner.Subcomponents.subcomp_help import SubcompHelpDialog
15 |
16 | BLACK_COLOR = "color: black"
17 | WHITE_COLOR = "color: white"
18 | ICONS_DIR = "../../Resources/icons/"
19 | class Subcomponents(QWidget):
20 |
21 | def __init__(self):
22 | super().__init__()
23 | small_text_font = QFont()
24 | small_text_font.setPointSize(10)
25 | title_font = QFont()
26 | title_font.setPointSize(12)
27 | title_font.setBold(True)
28 | bold_font = QFont()
29 | bold_font.setBold(True)
30 | input_font = QFont()
31 | input_font.setPointSize(10)
32 |
33 | self.all_signals = []
34 | self.all_signals_names = []
35 | self.arrays = []
36 | self.arrays_names = []
37 | self.comps = []
38 | self.comps_names = []
39 |
40 | self.package_heading_layout = QHBoxLayout()
41 | self.package_action_layout = QVBoxLayout()
42 | self.component_list_layout = QVBoxLayout()
43 | self.mainLayout = QVBoxLayout()
44 |
45 | self.package_label = QLabel("Sub-components")
46 | self.package_label.setFont(title_font)
47 | self.package_label.setStyleSheet(WHITE_COLOR)
48 |
49 | self.add_component_btn = QPushButton("Add component")
50 | self.add_component_btn.setFont(input_font)
51 | self.add_component_btn.setStyleSheet(
52 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain; padding: 10px;}"
53 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
54 |
55 | self.subcomp_info_btn = QPushButton()
56 | self.subcomp_info_btn.setIcon(qta.icon("mdi.help"))
57 | self.subcomp_info_btn.setFixedSize(25, 25)
58 | self.subcomp_info_btn.clicked.connect(self.subcomp_help_window)
59 | self.list_div = QFrame()
60 | self.list_div.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129);}')
61 | self.list_div.setFixedHeight(1)
62 |
63 | self.component_table = QTableWidget()
64 |
65 | self.package_list_frame = QFrame()
66 | self.component_list_frame = QFrame()
67 | self.package_action_frame = QFrame()
68 | self.generator = Generator()
69 | self.setup_ui()
70 | self.load_data()
71 |
72 | def setup_ui(self):
73 | bold_font = QFont()
74 | bold_font.setBold(True)
75 |
76 | self.package_heading_layout.addWidget(self.package_label)#, 0, 0, 1, 1)
77 | self.package_heading_layout.addWidget(self.add_component_btn, alignment=Qt.AlignRight)#, 0, 1, 1, 1)
78 | self.package_heading_layout.addWidget(self.subcomp_info_btn)#, 0, 2, 1, 1)
79 | #self.port_heading_layout.addWidget(self.add_btn, alignment=Qt.AlignRight)
80 | self.add_component_btn.clicked.connect(self.add_component)
81 |
82 | self.component_list_layout.setAlignment(Qt.AlignTop)
83 |
84 | self.component_table.setColumnCount(3)
85 | self.component_table.setShowGrid(False)
86 | self.component_table.setHorizontalHeaderLabels(['Component Name', '', ''])
87 | header = self.component_table.horizontalHeader()
88 | header.setSectionsClickable(False)
89 | header.setSectionsMovable(False)
90 | self.component_table.horizontalHeader().setFont(bold_font)
91 | self.component_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
92 | self.component_table.setColumnWidth(1, 10)
93 | self.component_table.setColumnWidth(2, 10)
94 | self.component_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
95 | vert = self.component_table.verticalHeader()
96 | vert.hide()
97 | self.component_table.setFrameStyle(QFrame.NoFrame)
98 | self.component_list_layout.addWidget(self.component_table)
99 |
100 | self.component_list_frame.setFrameShape(QFrame.StyledPanel)
101 | self.component_list_frame.setStyleSheet('.QFrame{background-color: white; border-radius: 5px;}')
102 | self.component_list_frame.setLayout(self.component_list_layout)
103 |
104 | self.package_action_layout.addLayout(self.package_heading_layout)
105 | self.package_action_layout.addSpacerItem(QSpacerItem(0, 5))
106 | self.package_action_layout.addWidget(self.component_list_frame)
107 | self.package_action_layout.addSpacerItem(QSpacerItem(0, 5))
108 | self.package_action_frame.setFrameShape(QFrame.StyledPanel)
109 | self.package_action_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
110 | self.package_action_frame.setLayout(self.package_action_layout)
111 |
112 | self.mainLayout.addWidget(self.package_action_frame)
113 |
114 | self.setLayout(self.mainLayout)
115 |
116 | def add_component(self):
117 | add_comp = ComponentDialog("add")
118 | add_comp.exec_()
119 | if not add_comp.cancelled:
120 | comp_data = add_comp.get_data()
121 | self.comps.append(comp_data)
122 | self.comps_names.append((comp_data[0]))
123 | delete_btn = QPushButton()
124 | delete_btn.setIcon(qta.icon("mdi.delete"))
125 | delete_btn.setFixedSize(35, 22)
126 | delete_btn.clicked.connect(self.delete_component)
127 |
128 | edit_btn = QPushButton()
129 | edit_btn.setIcon(qta.icon("mdi.pencil"))
130 | edit_btn.setFixedSize(35, 22)
131 | edit_btn.clicked.connect(self.edit_component)
132 |
133 | row_position = self.component_table.rowCount()
134 | self.component_table.insertRow(row_position)
135 | self.component_table.setRowHeight(row_position, 5)
136 | self.component_table.setItem(row_position, 0, QTableWidgetItem(comp_data[0]))
137 | self.component_table.setCellWidget(row_position, 1, edit_btn)
138 | self.component_table.setCellWidget(row_position, 2, delete_btn)
139 | self.save_data()
140 |
141 | def edit_component(self):
142 | button = self.sender()
143 | if button:
144 | row = self.component_table.indexAt(button.pos()).row()
145 | add_comp = ComponentDialog("edit", self.comps[row])
146 | add_comp.exec_()
147 |
148 | if not add_comp.cancelled:
149 | comp_data = add_comp.get_data()
150 | self.component_table.removeRow(row)
151 | self.comps.pop(row)
152 | self.comps_names.pop(row)
153 |
154 | delete_btn = QPushButton()
155 | delete_btn.setIcon(qta.icon("mdi.delete"))
156 | delete_btn.setFixedSize(35, 22)
157 | delete_btn.clicked.connect(self.delete_component)
158 |
159 | edit_btn = QPushButton()
160 | edit_btn.setIcon(qta.icon("mdi.pencil"))
161 | edit_btn.setFixedSize(35, 22)
162 | edit_btn.clicked.connect(self.edit_component)
163 |
164 | self.comps.insert(row, comp_data)
165 | self.comps_names.insert(row, comp_data[0])
166 | self.component_table.insertRow(row)
167 | self.component_table.setRowHeight(row, 5)
168 | self.component_table.setItem(row, 0, QTableWidgetItem(comp_data[0]))
169 | self.component_table.setCellWidget(row, 1, edit_btn)
170 | self.component_table.setCellWidget(row, 2, delete_btn)
171 | self.save_data()
172 |
173 | def subcomp_help_window(self):
174 | subcomp_help_dialog = SubcompHelpDialog()
175 | subcomp_help_dialog.exec_()
176 |
177 | def delete_component(self):
178 | button = self.sender()
179 | if button:
180 | row = self.component_table.indexAt(button.pos()).row()
181 | self.component_table.removeRow(row)
182 | self.comps.pop(row)
183 | self.comps_names.pop(row)
184 | self.save_data()
185 |
186 | def save_data(self):
187 | mainPackageDir = ProjectManager.get_package_hdlgen()
188 |
189 | root = minidom.parse(mainPackageDir)
190 | HDLGen = root.documentElement
191 | hdlDesign = HDLGen.getElementsByTagName("hdlDesign")
192 | new_comp_node = root.createElement("components")
193 |
194 | for component in self.comps:
195 | comp_node = root.createElement("component")
196 | package_model_node = root.createElement("model")
197 | package_model_node.appendChild(root.createTextNode(component[0]))
198 | comp_node.appendChild(package_model_node)
199 | package_dir_node = root.createElement("dir")
200 | package_dir_node.appendChild(root.createTextNode(component[1]))
201 | comp_node.appendChild(package_dir_node)
202 |
203 | for output_signal in component[2]:
204 | port_node = root.createElement("port")
205 | temp = output_signal.split(",")
206 | ports = temp[0] + "," + temp[1] + "," + temp[2]
207 | port_node.appendChild(root.createTextNode(ports))
208 | comp_node.appendChild(port_node)
209 | new_comp_node.appendChild(comp_node)
210 | hdlDesign[0].replaceChild(new_comp_node, hdlDesign[0].getElementsByTagName("components")[0])
211 | # converting the doc into a string in xml format
212 | xml_str = root.toprettyxml()
213 | xml_str = '\n'.join([line for line in xml_str.splitlines() if line.strip()])
214 | # Writing xml file
215 | with open(mainPackageDir, "w", encoding='UTF-8', newline='\n') as f:
216 | f.write(xml_str)
217 | self.generator.generate_mainPackage()
218 | print("Saved sub component")
219 |
220 | def load_data(self):
221 | if self.comps:
222 | for row in range(0, self.component_table.rowCount()):
223 | self.component_table.removeRow(0)
224 | self.comps.pop(0)
225 | self.comps_names.pop(0)
226 |
227 | mainPackageDir = ProjectManager.get_package_hdlgen()
228 |
229 | try:
230 | # Fetch component information from mainPackage.hdlgen for the project
231 | root = minidom.parse(mainPackageDir)
232 | HDLGen = root.documentElement
233 | hdlDesign = HDLGen.getElementsByTagName("hdlDesign")
234 | compPackage = hdlDesign[0].getElementsByTagName("components")
235 | comp_nodes = compPackage[0].getElementsByTagName("component")
236 |
237 | # Iterate over all component instances in the package file
238 | for idx, node in enumerate(comp_nodes):
239 | # Get the model name and model .vhd path from the package file
240 | model_name = node.getElementsByTagName('model')[0].firstChild.data
241 | directory = node.getElementsByTagName('dir')[0].firstChild.data
242 |
243 | # Get port data for each in the
244 | signals = list(signal.firstChild.data for signal in node.getElementsByTagName("port"))
245 | component_data = [model_name, directory, signals]
246 |
247 | self.comps_names.append(model_name)
248 | self.comps.append(component_data)
249 |
250 | # Create Component Edit Button
251 | edit_btn = QPushButton()
252 | edit_btn.setIcon(qta.icon("mdi.pencil"))
253 | edit_btn.setFixedSize(35, 22)
254 | edit_btn.clicked.connect(self.edit_component)
255 |
256 | # Create Component Delete Button
257 | delete_btn = QPushButton()
258 | delete_btn.setIcon(qta.icon("mdi.delete"))
259 | delete_btn.setFixedSize(35, 22)
260 | delete_btn.clicked.connect(self.delete_component)
261 |
262 | # Add Component name, Edit button, Delete button to sub-components table
263 | self.component_table.insertRow(idx)
264 | self.component_table.setRowHeight(idx, 5)
265 | self.component_table.setItem(idx, 0, QTableWidgetItem(model_name))
266 | self.component_table.setCellWidget(idx, 1, edit_btn)
267 | self.component_table.setCellWidget(idx, 2, delete_btn)
268 |
269 | except Exception as e:
270 | print(repr(e))
--------------------------------------------------------------------------------
/Application/HDLDesigner/comp/comp_details.py:
--------------------------------------------------------------------------------
1 | #Component section in HDL Designer. This class will only call comp_help.md if help button is clicked
2 | #This class will save all entered data to the .hdlgen. The save happens when there is a change.
3 | import os
4 | from xml.dom import minidom
5 | from PySide2.QtWidgets import *
6 | from PySide2.QtCore import *
7 | from PySide2.QtGui import *
8 | import sys
9 | import configparser
10 | import qtawesome as qta
11 | sys.path.append("..")
12 | from ProjectManager.project_manager import ProjectManager
13 | from HDLDesigner.comp.comp_help import CompHelpDialog
14 |
15 |
16 | WHITE_COLOR = "color: white"
17 |
18 | class CompDetails(QWidget):
19 | save_signal = Signal(bool)
20 | def __init__(self, proj_dir):
21 | super().__init__()
22 | small_text_font = QFont()
23 | small_text_font.setPointSize(10)
24 | title_font = QFont()
25 | title_font.setPointSize(12)
26 | title_font.setBold(True)
27 | self.proj_dir = proj_dir
28 |
29 | self.mainLayout = QVBoxLayout()
30 |
31 | self.input_layout = QGridLayout()
32 | self.comp_label = QLabel("Component")
33 | self.comp_label.setFont(title_font)
34 | self.comp_label.setStyleSheet(WHITE_COLOR)
35 |
36 | self.comp_name_label = QLabel("Component Name*")
37 | self.comp_name_label.setStyleSheet(WHITE_COLOR)
38 | self.comp_name_label.setFont(small_text_font)
39 | self.comp_name_input = QLineEdit()
40 | self.comp_name_input.setFont(small_text_font)
41 |
42 | self.comp_info_btn = QPushButton()
43 | self.comp_info_btn.setIcon(qta.icon("mdi.help"))
44 | self.comp_info_btn.setFixedSize(25, 25)
45 | self.comp_info_btn.clicked.connect(self.comp_help_window)
46 |
47 | self.comp_title_label = QLabel("Single Line Title")
48 | self.comp_title_label.setStyleSheet(WHITE_COLOR)
49 | self.comp_title_label.setFont(small_text_font)
50 | self.comp_title_input = QLineEdit()
51 | self.comp_title_input.setFont(small_text_font)
52 |
53 | self.comp_description_label = QLabel("Component Description")
54 | self.comp_description_label.setStyleSheet(WHITE_COLOR)
55 | self.comp_description_label.setFont(small_text_font)
56 | self.comp_description_input = QPlainTextEdit()
57 | self.comp_description_input.setLineWrapMode(QPlainTextEdit.WidgetWidth)
58 | self.comp_description_input.setFont(small_text_font)
59 |
60 | self.comp_author_label = QLabel("Authors")
61 | self.comp_author_label.setStyleSheet(WHITE_COLOR)
62 | self.comp_author_label.setFont(small_text_font)
63 | self.comp_author_input = QLineEdit()
64 | self.comp_author_input.setFont(small_text_font)
65 |
66 | self.comp_company_label = QLabel("Company")
67 | self.comp_company_label.setStyleSheet(WHITE_COLOR)
68 | self.comp_company_label.setFont(small_text_font)
69 | self.comp_company_input = QLineEdit()
70 | self.comp_company_input.setFont(small_text_font)
71 |
72 | self.comp_email_label = QLabel("Email")
73 | self.comp_email_label.setStyleSheet(WHITE_COLOR)
74 | self.comp_email_label.setFont(small_text_font)
75 | self.comp_email_input = QLineEdit()
76 | self.comp_email_input.setFont(small_text_font)
77 |
78 | self.comp_date_label = QLabel("Date")
79 | self.comp_date_label.setStyleSheet(WHITE_COLOR)
80 | self.comp_date_label.setFont(small_text_font)
81 |
82 | self.reset_btn = QPushButton("Reset")
83 | self.reset_btn.setFixedSize(60, 30)
84 | self.reset_btn.setStyleSheet(
85 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain; }"
86 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;}")
87 |
88 | self.btn_layout = QHBoxLayout()
89 |
90 | self.vspacer = QSpacerItem(30, 40)
91 |
92 | self.comp_date_picker = QDateEdit(calendarPopup=True)
93 | self.comp_date_picker.setDate(QDate.currentDate())
94 | self.comp_date_picker.setFont(small_text_font)
95 | self.comp_date_picker.setDisplayFormat("dd/MM/yyyy")
96 |
97 | self.input_frame = QFrame()
98 | self.setup_ui()
99 | if proj_dir != None:
100 | self.load_data(proj_dir)
101 |
102 | def setup_ui(self):
103 | config = configparser.ConfigParser()
104 | config.read('config.ini')
105 | author = config.get('user', 'author').strip()
106 | email = config.get('user', 'email').strip()
107 | company = config.get('user', 'company').strip()
108 | self.comp_author_input.setText(author)
109 |
110 | self.comp_email_input.setText(email)
111 | self.comp_company_input.setText(company)
112 | self.input_layout.addWidget(self.comp_label, 0, 0,1,1)
113 | self.input_layout.addWidget(self.comp_info_btn,0,1,alignment=Qt.AlignRight)
114 | self.input_layout.addWidget(self.comp_name_label, 1, 0)
115 | self.input_layout.addWidget(self.comp_name_input, 2, 0, 1, 2)
116 | self.comp_name_input.setText(ProjectManager.get_proj_name())
117 | self.comp_title_input.setText("To be Completed")
118 | self.input_layout.addWidget(self.comp_title_label, 3, 0)
119 | self.input_layout.addWidget(self.comp_title_input, 4, 0, 1, 2)
120 | self.comp_description_input.setPlainText("To be Completed")
121 | self.input_layout.addWidget(self.comp_description_label, 5, 0)
122 | self.input_layout.addWidget(self.comp_description_input, 6, 0, 4, 2)
123 |
124 | self.input_layout.addWidget(self.comp_author_label, 10, 0)
125 | self.input_layout.addWidget(self.comp_author_input, 11, 0, 1, 1)
126 |
127 | self.input_layout.addWidget(self.comp_company_label, 10, 1)
128 | self.input_layout.addWidget(self.comp_company_input, 11, 1, 1, 1)
129 |
130 | self.input_layout.addWidget(self.comp_email_label, 12, 0)
131 | self.input_layout.addWidget(self.comp_email_input, 13, 0, 1, 1)
132 |
133 | self.input_layout.addWidget(self.comp_date_label, 12, 1)
134 | self.input_layout.addWidget(self.comp_date_picker, 13, 1, 1, 1)
135 |
136 | self.comp_description_input.textChanged.connect(self.save_data)
137 | self.comp_author_input.textChanged.connect(self.save_data)
138 | self.comp_name_input.textChanged.connect(self.save_data)
139 | self.comp_email_input.textChanged.connect(self.save_data)
140 | self.comp_title_input.textChanged.connect(self.save_data)
141 | self.comp_company_input.textChanged.connect(self.save_data)
142 | self.comp_date_picker.dateChanged.connect(self.save_data)
143 |
144 | self.input_layout.addItem(self.vspacer, 14, 0, 1, 2)
145 | self.input_layout.addLayout(self.btn_layout, 15, 1)
146 |
147 | self.input_frame.setFrameShape(QFrame.StyledPanel)
148 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
149 | self.input_frame.setContentsMargins(30, 30, 30, 25)
150 | self.input_frame.setLayout(self.input_layout)
151 |
152 | self.mainLayout.addWidget(self.input_frame)
153 |
154 | self.setLayout(self.mainLayout)
155 |
156 | def update_comp_name(self):
157 | self.comp_name_input.setText(ProjectManager.get_proj_name())
158 |
159 | def save_data(self):
160 |
161 | xml_data_path = ProjectManager.get_xml_data_path()
162 |
163 | root = minidom.parse(xml_data_path)
164 | HDLGen = root.documentElement
165 | hdlDesign = HDLGen.getElementsByTagName("hdlDesign")
166 |
167 | comp_name = self.comp_name_input.text()
168 | if comp_name == "":
169 | comp_name = "To be completed"
170 | comp_title = self.comp_title_input.text()
171 | if comp_title == "":
172 | comp_title = "To be completed"
173 | cursor = self.comp_description_input.textCursor()
174 | doc = self.comp_description_input.document()
175 | lines = ""
176 | line = ""
177 | for i in range(doc.blockCount()):
178 | block = doc.findBlockByNumber(i)
179 | if block.isVisible():
180 | for j in range(block.layout().lineCount()):
181 | lineStart = block.position() + block.layout().lineAt(j).textStart()
182 | lineEnd = lineStart + block.layout().lineAt(j).textLength()
183 | cursor.setPosition(lineStart)
184 | cursor.setPosition(lineEnd, QTextCursor.KeepAnchor)
185 | line += cursor.selectedText()
186 | if lineEnd == cursor.position():
187 | lines += line + "\n"
188 | line = ""
189 | lines = lines.strip()
190 | comp_description = lines
191 | comp_authors = self.comp_author_input.text().strip()
192 | if comp_authors == "":
193 | comp_authors = "To be completed"
194 | comp_company = self.comp_company_input.text().strip()
195 | if comp_company == "":
196 | comp_company = "To be completed"
197 | comp_email = self.comp_email_input.text().strip()
198 | if comp_email == "":
199 | comp_email = "To be completed"
200 | comp_date = self.comp_date_picker.text()
201 |
202 | header = hdlDesign[0].getElementsByTagName('header')
203 |
204 | header[0].getElementsByTagName('compName')[0].firstChild.data = comp_name
205 | header[0].getElementsByTagName('title')[0].firstChild.data = comp_title
206 |
207 | if comp_description.count('\n') == 0:
208 | comp_description=self.comp_description_input.toPlainText()
209 | comp_description = comp_description.replace("&", "&")
210 | comp_description = comp_description.replace("\n", "
")
211 | comp_description = comp_description.replace("\"", """)
212 | comp_description = comp_description.replace("\'", "'")
213 | comp_description = comp_description.replace("\n", "
")
214 | comp_description = comp_description.replace("<", "<")
215 | comp_description = comp_description.replace("\t", " ")
216 | comp_description = comp_description.replace(">", ">")
217 | comp_description = comp_description.replace(",", ",")
218 |
219 | if comp_description == "":
220 | comp_description = "To be completed"
221 | header[0].getElementsByTagName('description')[0].firstChild.data = comp_description
222 | header[0].getElementsByTagName('authors')[0].firstChild.data = comp_authors
223 | header[0].getElementsByTagName('company')[0].firstChild.data = comp_company
224 | header[0].getElementsByTagName('email')[0].firstChild.data = comp_email
225 | header[0].getElementsByTagName('date')[0].firstChild.data = comp_date
226 |
227 | # converting the doc into a string in xml format
228 | xml_str = root.toprettyxml()
229 | xml_str = '\n'.join([line for line in xml_str.splitlines() if line.strip()])
230 |
231 | # Writing xml file
232 | with open(xml_data_path, "w", encoding='UTF-8', newline='\n') as f:
233 | f.write(xml_str)
234 | hdl = False
235 | self.save_signal.emit(hdl)
236 | print("Saved Component details")
237 |
238 | def comp_help_window(self):
239 | comp_help_dialog = CompHelpDialog()
240 | comp_help_dialog.exec_()
241 |
242 | def reset_comp_details(self):
243 |
244 | self.comp_name_input.clear()
245 | self.comp_title_input.clear()
246 | self.comp_description_input.clear()
247 | self.comp_author_input.clear()
248 | self.comp_company_input.clear()
249 | self.comp_email_input.clear()
250 | self.comp_date_picker.setDate(QDate.currentDate())
251 |
252 | def load_data(self, proj_dir):
253 | root = minidom.parse(str(proj_dir))
254 | HDLGen = root.documentElement
255 | hdlDesign = HDLGen.getElementsByTagName("hdlDesign")
256 |
257 | header = hdlDesign[0].getElementsByTagName('header')
258 |
259 | comp_name = header[0].getElementsByTagName('compName')[0].firstChild.data
260 | comp_title = header[0].getElementsByTagName('title')[0].firstChild.data
261 | comp_description = header[0].getElementsByTagName('description')[0].firstChild.data
262 |
263 | comp_authors = header[0].getElementsByTagName('authors')[0].firstChild.data
264 | comp_company = header[0].getElementsByTagName('company')[0].firstChild.data
265 | comp_email = header[0].getElementsByTagName('email')[0].firstChild.data
266 | comp_date = header[0].getElementsByTagName('date')[0].firstChild.data
267 |
268 | if comp_description != "null":
269 | comp_description = comp_description.replace("
", "\n")
270 | comp_description = comp_description.replace("&", "&")
271 | comp_description = comp_description.replace("&", "&")
272 | comp_description = comp_description.replace(""", "\"")
273 | comp_description = comp_description.replace("'", "\'")
274 | comp_description = comp_description.replace("<", "<")
275 | comp_description = comp_description.replace(" ", "\t")
276 | comp_description = comp_description.replace(">", ">")
277 | comp_description = comp_description.replace(",", ",")
278 | self.comp_description_input.setPlainText(comp_description)
279 |
280 | if comp_name != "null":
281 | self.comp_name_input.setText(comp_name)
282 |
283 | if comp_title != "null":
284 | self.comp_title_input.setText(comp_title)
285 |
286 | if comp_authors != "null":
287 | self.comp_author_input.setText(comp_authors)
288 |
289 | if comp_company != "null":
290 | self.comp_company_input.setText(comp_company)
291 |
292 | if comp_email != "null":
293 | self.comp_email_input.setText(comp_email)
294 |
295 | if comp_date != "null":
296 | self.comp_date_picker.setDate(QDate.fromString(comp_date))
--------------------------------------------------------------------------------
/Application/HDLDesigner/comp/comp_help.md:
--------------------------------------------------------------------------------
1 | # Component
2 |
3 | - Complete the following fields, using the information in the design specification
4 | - Component name
5 | - Single line title
6 | - Component description
7 | PRovide a complete description, considering psuedo code as an efficient method of description.
8 |
9 | - Creator details can be entered on an individual project bases, though you are advised to use the project settings menu to define these values for all projects.
10 | - Close the current project
11 | - Click settings
12 | - Complete the following fields
13 | - Authors
14 | - Company
15 | - Email
16 | - These fields will be used in all subsequently created project
17 |
18 | - The date field is automatically generated
19 |
20 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/comp/comp_help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | COMP_HELP_DOC_FILE_PATH = "./HDLDesigner/comp/comp_help.md"
6 |
7 |
8 | class CompHelpDialog(QDialog):
9 |
10 | def __init__(self):
11 | super().__init__()
12 | self.setWindowTitle("HDLGen Help")
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 |
17 | self.mainLayout = QVBoxLayout()
18 | self.setFixedSize(800, 800)
19 | self.setup_ui()
20 |
21 | def setup_ui(self):
22 |
23 | # Writing xml file
24 | with open(COMP_HELP_DOC_FILE_PATH, "r") as f:
25 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
--------------------------------------------------------------------------------
/Application/HDLDesigner/hdl_designer.py:
--------------------------------------------------------------------------------
1 | #This class is a tab in the home.py class of the GUI. it contains the 8 classes comp_details.py, architecture.py, io_ports.py, testplan.py, internal_signal.py,
2 | #package.py, subcomponents.py, generation.py, generator.py will also call project_manager.py to get information
3 | import os
4 | from xml.dom import minidom
5 | from PySide2.QtWidgets import *
6 | from PySide2.QtCore import *
7 | import sys
8 | sys.path.append("..")
9 | from HDLDesigner.comp.comp_details import CompDetails
10 | from HDLDesigner.IOPorts.io_ports import IOPorts
11 | from HDLDesigner.Architecture.architecture import Architecture
12 | from HDLDesigner.testPlan.testplan import TestPlan
13 | from HDLDesigner.InternalSignal.internal_signal import InternalSignal
14 | from HDLDesigner.Package.package import Package
15 | from HDLDesigner.Subcomponents.subcomponents import Subcomponents
16 | from HDLDesigner.Generate.generation import Gen
17 | from Generator.generator import Generator
18 | from ProjectManager.project_manager import ProjectManager
19 |
20 |
21 | class HDLDesigner(QWidget):
22 |
23 | def __init__(self, proj_dir, load_data):
24 | super().__init__()
25 |
26 | self.proj_dir = proj_dir
27 | self.code = "No Model Code"
28 | self.chatgpt_header = "No Header Command Entered"
29 | self.chatgpt_model = "No Model Command Entered"
30 | self.chatgpt_tb = "No Testbench"
31 | self.tb_code = "No Testbench"
32 | self.ModelCmd = "No Command Entered"
33 | self.HeaderCmd = "No Command Entered"
34 | self.hdl = "VHDL"
35 | self.mainLayout = QHBoxLayout()
36 | self.preview_pane_layout = QVBoxLayout()
37 |
38 | self.preview_label = QLabel("Preview")
39 | self.preview_window = QTextEdit()
40 |
41 | self.tabs = VerticalTabWidget()
42 | self.tabs.other_class = self
43 | # Creating a container
44 | self.container = QWidget()
45 | self.project_manager = ProjectManager(self.proj_dir, self)
46 | self.setup_ui()
47 | self.hdl = "VHDL"
48 | if load_data:
49 | if self.project_manager.vhdl_check.isChecked():
50 | self.hdl = "VHDL"
51 | self.update_preview("VHDL")
52 | else:
53 | self.hdl = "Verilog"
54 | self.update_preview("Verilog")
55 | else:
56 | self.hdl = "VHDL"
57 |
58 | def setup_ui(self):
59 | self.compDetails = CompDetails(self.proj_dir)
60 | self.ioPorts = IOPorts(self.proj_dir)
61 | self.architecture = Architecture(self.proj_dir)
62 | self.testplan = TestPlan(self.proj_dir)
63 | self.generate = Gen(self.proj_dir)
64 | self.internalSignal = InternalSignal(self.proj_dir)
65 | self.package = Package()
66 | self.subcomponents = Subcomponents()
67 |
68 | self.preview_window.setReadOnly(True)
69 | self.preview_pane_layout.addWidget(self.preview_label)
70 | self.preview_pane_layout.addWidget(self.preview_window)
71 |
72 | self.tabs.addTab(self.compDetails, "Component")
73 | self.tabs.addTab(self.package, "Types")
74 | self.tabs.addTab(self.subcomponents, "Sub-components")
75 | self.tabs.addTab(self.ioPorts, "Ports")
76 | self.tabs.addTab(self.internalSignal, "Internal Signals")
77 | self.tabs.addTab(self.architecture, "Architecture")
78 | self.tabs.addTab(self.testplan, "Test Plan")
79 | self.tabs.addTab(self.generate, "Generate")
80 | font = self.tabs.font()
81 | font.setPointSize(12)
82 | self.tabs.setFont(font)
83 | self.mainLayout.addWidget(self.tabs)
84 | self.mainLayout.addLayout(self.preview_pane_layout)
85 | self.setLayout(self.mainLayout)
86 |
87 | self.compDetails.save_signal.connect(self.update_preview)
88 | self.ioPorts.save_signal.connect(self.update_preview)
89 | self.ioPorts.save_signal.connect(self.update_arch)
90 | self.internalSignal.save_signal.connect(self.update_preview)
91 | self.architecture.save_signal.connect(self.update_preview)
92 | self.generate.save_signal.connect(self.update_preview)
93 | self.generate.header_title_check.clicked.connect(self.update_preview)
94 | self.generate.msg_title_check.clicked.connect(self.update_preview)
95 | self.generate.header_model_check.clicked.connect(self.update_preview)
96 | self.generate.model_check.clicked.connect(self.update_preview)
97 | self.generate.msg_model_check.clicked.connect(self.update_preview)
98 | self.generate.header_testbench_check.clicked.connect(self.update_preview)
99 | self.generate.testbench_check.clicked.connect(self.update_preview)
100 | self.generate.msg_testbench_check.clicked.connect(self.update_preview)
101 | self.generate.tab_widget.currentChanged.connect(self.update_preview)
102 |
103 | def update_preview(self, hdl):
104 | root = minidom.parse(ProjectManager.get_proj_hdlgen())
105 | HDLGen = root.documentElement
106 | hdlDesign = HDLGen.getElementsByTagName("hdlDesign")
107 | testbench_node = hdlDesign[0].getElementsByTagName('testbench')
108 | if len(testbench_node) != 0 and testbench_node[0].firstChild is not None:
109 | tb_node = testbench_node[0].getElementsByTagName('TBNote')[0]
110 | self.tbnote = tb_node.firstChild.nodeValue
111 | self.tbnote = self.tbnote.replace("
", "\n")
112 | self.tbnote = self.tbnote.replace("&", "&")
113 | self.tbnote = self.tbnote.replace(""", "\"")
114 | self.tbnote = self.tbnote.replace("'", "\'")
115 | self.tbnote = self.tbnote.replace("<", "<")
116 | self.tbnote = self.tbnote.replace(" ", "\t")
117 | self.tbnote = self.tbnote.replace(">", ">")
118 | self.tbnote = self.tbnote.replace(",", ",")
119 | if self.tbnote == "None":
120 | self.tbnote = "No Test Plan Created"
121 | else:
122 | self.tbnote = "No Test Plan Created"
123 |
124 | if hdl != False and hdl != True and not isinstance(hdl, (int, float)):
125 | self.hdl = hdl
126 | if self.hdl == "VHDL":
127 | entity_name, self.code, instances, self.chatgpt_header, self.chatgpt_model = Generator.generate_vhdl(self)
128 | entity_name, self.tb_code, wcfg, self.chatgpt_tb = Generator.create_vhdl_testbench_code(self)
129 | chatgpt = hdlDesign[0].getElementsByTagName('chatgpt')[0]
130 | if chatgpt.hasChildNodes():
131 | commands_node = chatgpt.getElementsByTagName('commands')[0]
132 | VHDLModel = commands_node.getElementsByTagName('VHDLModel')[0].firstChild.data
133 | VHDLModel = VHDLModel.replace("
", "\n")
134 | VHDLModel = VHDLModel.replace("&", "&")
135 | VHDLModel = VHDLModel.replace(""", "\"")
136 | VHDLModel = VHDLModel.replace("'", "\'")
137 | VHDLModel = VHDLModel.replace("<", "<")
138 | VHDLModel = VHDLModel.replace(" ", "\t")
139 | VHDLModel = VHDLModel.replace(">", ">")
140 | VHDLModel = VHDLModel.replace(",", ",")
141 | lines = VHDLModel.split('\n')
142 | filtered_lines = [line for line in lines if not line.startswith('~')]
143 | VHDLModel = '\n'.join(filtered_lines)
144 | self.ModelCmd = VHDLModel
145 | elif self.hdl == "Verilog":
146 | entity_name,self.code, instances, self.chatgpt_header, self.chatgpt_model = Generator.generate_verilog(self)
147 | entity_name, self.tb_code, wcfg, self.chatgpt_tb = Generator.create_verilog_testbench_code(self)
148 | chatgpt = hdlDesign[0].getElementsByTagName('chatgpt')[0]
149 | if chatgpt.hasChildNodes():
150 | commands_node = chatgpt.getElementsByTagName('commands')[0]
151 | VerilogModel = commands_node.getElementsByTagName('VerilogModel')[0].firstChild.data
152 | VerilogModel = VerilogModel.replace("
", "\n")
153 | VerilogModel = VerilogModel.replace("&", "&")
154 | VerilogModel = VerilogModel.replace(""", "\"")
155 | VerilogModel = VerilogModel.replace("'", "\'")
156 | VerilogModel = VerilogModel.replace("<", "<")
157 | VerilogModel = VerilogModel.replace(" ", "\t")
158 | VerilogModel = VerilogModel.replace(">", ">")
159 | VerilogModel = VerilogModel.replace(",", ",")
160 | lines = VerilogModel.split('\n')
161 | filtered_lines = [line for line in lines if not line.startswith('~')]
162 | VerilogModel = '\n'.join(filtered_lines)
163 | self.ModelCmd=VerilogModel
164 | if self.tabs.currentIndex() == 6:
165 | self.preview_window.setText(self.tb_code)
166 | self.preview_label.setText("HDL Testbench Preview")
167 | elif self.tabs.currentIndex() == 7:
168 | if self.generate.tab_widget.currentIndex() == 0:
169 | if self.generate.model_check.isChecked():
170 | self.preview_label.setText("HDL Model Preview")
171 | self.preview_window.setText(self.code)
172 | elif self.generate.header_model_check.isChecked():
173 | self.preview_label.setText("ChatGPT Prompt Header Preview")
174 | self.preview_window.setText(self.ModelCmd)
175 | elif self.generate.msg_model_check.isChecked():
176 | self.preview_label.setText("ChatGPT Prompt, to generate final HDL model")
177 | self.preview_window.setText(self.ModelCmd + "\n\n" +self.code)
178 | elif self.generate.tab_widget.currentIndex() == 1:
179 | if self.generate.header_testbench_check.isChecked():
180 | self.preview_label.setText("ChatGPT Prompt Header Preview")
181 | elif self.generate.testbench_check.isChecked():
182 | self.preview_window.setText(self.tb_code)
183 | self.preview_label.setText("HDL Testbench Preview")
184 | elif self.generate.tab_widget.currentIndex() == 2:
185 | if self.generate.header_title_check.isChecked():
186 | self.preview_label.setText("ChatGPT Prompt Header Preview")
187 | self.preview_window.setText(self.HeaderCmd)
188 | elif self.generate.msg_title_check.isChecked():
189 | self.preview_label.setText("ChatGPT Prompt, to generate final HDL title")
190 | self.preview_window.setText(self.HeaderCmd+ "\n\n" +self.chatgpt_header)
191 | else:
192 | self.preview_window.setText(self.code)
193 | self.preview_label.setText("HDL Model Preview")
194 |
195 | def update_arch(self):
196 | xml_data_path = ProjectManager.get_proj_hdlgen()
197 | self.architecture.updateProcessName(xml_data_path)
198 |
199 | def get_hdl(self):
200 | return self.hdl
201 |
202 | class TabBar(QTabBar):
203 |
204 | def tabSizeHint(self, index):
205 | s = QTabBar.tabSizeHint(self, index)
206 | s.transpose()
207 | return s
208 |
209 | def paintEvent(self, event):
210 | painter = QStylePainter(self)
211 | opt = QStyleOptionTab()
212 | for i in range(self.count()):
213 | self.initStyleOption(opt, i)
214 | painter.drawControl(QStyle.CE_TabBarTabShape, opt)
215 | painter.save()
216 |
217 | s = opt.rect.size() * 100
218 | s.transpose()
219 | r = QRect(QPoint(), s)
220 | r.moveCenter(opt.rect.center())
221 | opt.rect = r
222 |
223 | c = self.tabRect(i).center()
224 | painter.translate(c)
225 | painter.rotate(90)
226 | painter.translate(-c)
227 | painter.drawControl(QStyle.CE_TabBarTabLabel, opt)
228 | painter.restore()
229 |
230 | class VerticalTabWidget(QTabWidget):
231 | def __init__(self, other_class=None, *args, **kwargs):
232 | QTabWidget.__init__(self, *args, **kwargs)
233 | self.setTabBar(TabBar())
234 | self.setTabPosition(QTabWidget.West)
235 | self.currentChanged.connect(self.tab_changed)
236 | self.previous_index = self.currentIndex()
237 | self.other_class = other_class
238 | def tab_changed(self, index):
239 | # save state of previous tab
240 | prev_tab = self.widget(self.previous_index)
241 | if index == 6 or index == 7:
242 | if self.other_class:
243 | lang = self.other_class.get_hdl()
244 | self.other_class.update_preview(lang)
245 | if self.previous_index == 6 or self.previous_index == 7:
246 | if self.other_class:
247 | lang = self.other_class.get_hdl()
248 | self.other_class.update_preview(lang)
249 | self.previous_index = index
--------------------------------------------------------------------------------
/Application/HDLDesigner/testPlan/testplan_help.md:
--------------------------------------------------------------------------------
1 | ## How to use the Test Table
2 |
3 | ### Signal Radix Format
4 | `1'b` is a 1-bit binary number (i.e. 0 or 1).
5 | Similarly, `16'b` is a 16-bit binary number.
6 | You can also specify a hexadecimal number: `16'h` represents a 16-bit hex number (e.g. `BEEF`).
7 | Decimal numbers can be specified explicitly with `d`, e.g. `16'd`, but simply writing `16` will work fine.
8 |
9 | ### Notes column
10 | The notes column can be used to describe the scenario being tested.
11 | When specified, it will appear as a comment in the generated testbench code.
12 | It is not a required field.
13 |
14 | ### Sequential Logic Components
15 | ##### The Clock Signal
16 | The testbench HDL includes a clock (Signal: `CLK`), with a default period of 20ns (50 Mhz).
17 | ##### The Reset Signal
18 | The reset signal (Signal: `RST`) is initially asserted, deasserting after `0.2 * period` after the first active clock edge.
19 |
20 | ### Delay Values
21 | The delay value is the number of periods to wait for, following the application of the test input signals, before asserting the validity of the output signals. Integer values can be specified, which will cause an N period delay, ending 0.2 periods after the active clock edge. This is due to the initial assertion of the reset signal for 0.2 periods, causing an offset. Real numbers can also be entered, e.g. 0.2, which will result in the delay ending 0.4 periods after the active clock edge (0.2 for `RST` and 0.2 for the delay).
22 |
23 | ### Editing the test table template
24 | The test table template generated by HDLGen-ChatGPT can be copied and pasted into Excel (or any other spreadsheet editor). When copied into a spreadsheet editor, you may have to set the cells to "Text" mode to prevent leading zeros from being truncated by Excel.
25 |
26 | Once the test table template has been completed, it can be copied from the spreadsheet editor and pasted back into the textbox which appears after entering "Edit Testplan".
27 |
28 | The template is generated by HDLGen-ChatGPT when the "Test Plan" tab is entered for the first time. To prevent overwriting any completed test plan work, the test plan template must be reset manually any time a signal is added or removed (Alternatively, signal columns can be added or removed from the testplan by hand, provided the testplan format is followed).
29 |
30 | The test table is a tab-separated table with each table row terminated by a newline character.
--------------------------------------------------------------------------------
/Application/HDLDesigner/testPlan/testplan_help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | COMP_HELP_DOC_FILE_PATH = "./HDLDesigner/testPlan/testplan_help.md"
6 |
7 |
8 | class TestPlanHelpDialog(QDialog):
9 |
10 | def __init__(self):
11 | super().__init__()
12 | self.setWindowTitle("HDLGen Help")
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 |
17 | self.mainLayout = QVBoxLayout()
18 | self.setFixedSize(800, 800)
19 | self.setup_ui()
20 |
21 | def setup_ui(self):
22 |
23 | # Writing xml file
24 | with open(COMP_HELP_DOC_FILE_PATH, "r") as f:
25 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
--------------------------------------------------------------------------------
/Application/Help/help.md:
--------------------------------------------------------------------------------
1 | # HDLGen-ChatGPT application
2 | - HDLGen-ChatGPT is an open-source client application, developed in the University of Galway
3 | ([Fearghal Morgan](mailto:fearghal.morgan1@gmail.com?subject=HDLGen-ChatGPT), John Patrick Byrne, Abishek Bupathi).
4 | Contact us with comments or suggestions.
5 |
6 | - Project website, with lots of links [HDLGen-ChatGPT github repository](https://github.com/HDLGen-ChatGPT/HDLGen-ChatGPT)
7 |
8 | - Our other work:
9 | [Vicilogic](https://www.vicilogic.com): online learning, assessment, remote FPGA prototying and coure builder platform
10 |
11 |
12 | - Why use HDLGen-ChatGPT and what can it do?
13 | - Many students find it difficult to develop mastery of
14 | - hardware description language (HDL) languages VHDL and Verilog
15 | modelling and testbenching for HDL simulation
16 | - complex Electronic Design Automation (EDA) tools, used for HDL
17 | simulation, synthesis, and FPGA prototyping.
18 | - HDLGen-ChatGPT and ChatGPT tools enable fast, automated
19 | - capture of digital systems design and test specification
20 | information
21 | - generation of VHDL and Verilog model templates
22 | - low level logic pseudo code
23 | - generation of VHDL and Verilog testbench templates
24 | - generation of EDA tool suite projects and folder
25 | (AMD Vivado and Intel Quartus)
26 | - ChatGPT prompts for completion of
27 | - HDL models
28 | - HDL template stimulus process and signal checking
29 |
30 | - HDLGen-ChatGPT currently supports
31 | - VHDL and Verilog hardware desciption language (HDLs)
32 | - AMD Xilinx Vivado V2019.1 FPGA EDA tool suite. [Video on V2019.1 installation instructions (same as for V2018.2)](https://vicicourse.s3.eu-west-1.amazonaws.com/AMD+Vivado/vivado2018.2Install.mp4)
33 | - Intel Quartus V21.1.1.850 FPGA EDA tool suite [3]
34 | - ChatGPT-3.5 or later
35 |
--------------------------------------------------------------------------------
/Application/Help/help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | HELP_DOC_FILE_PATH = "./Help/help.md"
6 | OLD_HELP_DOC_FILE_PATH = "./Help/help(old).md"
7 | HELP_DOC_FILE_DIR = "./Help/"
8 |
9 | class Help(QWidget):
10 |
11 | def __init__(self):
12 | super().__init__()
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 | self.mainLayout = QVBoxLayout()
17 |
18 | self.setup_ui()
19 |
20 | def setup_ui(self):
21 |
22 | # Writing xml file
23 | with open(HELP_DOC_FILE_PATH, "r") as f:
24 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
25 |
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
31 |
32 | class HelpDialog(QDialog):
33 |
34 | def __init__(self):
35 | super().__init__()
36 | self.setWindowTitle("HDLGen Help")
37 |
38 | self.markdown_view = QTextBrowser(readOnly=True)
39 | self.markdown_view.setOpenExternalLinks(True)
40 |
41 | self.mainLayout = QVBoxLayout()
42 | self.setFixedSize(700, 500)
43 | self.setup_ui()
44 |
45 | def setup_ui(self):
46 |
47 | # Writing xml file
48 | with open(HELP_DOC_FILE_PATH, "r") as f:
49 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
50 |
51 | self.markdown_view.setHtml(doc)
52 | self.mainLayout.addWidget(self.markdown_view)
53 | self.setLayout(self.mainLayout)
54 |
55 |
56 | """
57 | class WebEnginePage(QWebEnginePage):
58 | def acceptNavigationRequest(self, url, _type, isMainFrame):
59 | if _type == QWebEnginePage.NavigationTypeLinkClicked:
60 | QDesktopServices.openUrl(url);
61 | return False
62 | return True
63 |
64 | class HtmlView(QWebEngineView):
65 | def __init__(self, *args, **kwargs):
66 | QWebEngineView.__init__(self, *args, **kwargs)
67 | self.setPage(WebEnginePage(self))
68 | """
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Application/ProjectManager/eda_help.md:
--------------------------------------------------------------------------------
1 | # Selecting and linking to Electronic Design Automation (EDA) tool suites
2 |
3 | - For each project, setup pointers to the EDA tools path(s)
4 | - Select if using AMD Vivado EDA tool suite (use V 2019.1) or Intel Quartus, if the EDA tool suites are installed on your computer
5 | - Vivado 2019.1: browse to select the vivado.bat file in the Vivado installation folder. This is typically C:\Xilinx\Vivado\2019.1\bin\vivado.bat.
6 |
7 | - To configure pointers permanently for all projects,
8 | - Close the project (opens the splash page)
9 | - Click settings
10 | - Setup the paths to the EDA tool(s)
11 | - Click OK
12 |
13 | - If the EDA tools are not installed, you leave the fields blank. Much of ChatGPT can operate without using the EDA tools.
14 |
15 | - Video: Install AMD Vivado Vivado V2019.1 FPGA EDA tool suite. [V2019.1 installation instructions (same as for V2018.2)](https://vicicourse.s3.eu-west-1.amazonaws.com/AMD+Vivado/vivado2018.2Install.mp4)#### [Video tutorials](https://www.vicilogic.com/vicilearn/run_step/?c_id=56)
--------------------------------------------------------------------------------
/Application/ProjectManager/eda_help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | EDA_HELP_DOC_FILE_PATH = "./ProjectManager/eda_help.md"
6 |
7 |
8 | class EDAHelpDialog(QDialog):
9 |
10 | def __init__(self):
11 | super().__init__()
12 | self.setWindowTitle("HDLGen Help")
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 |
17 | self.mainLayout = QVBoxLayout()
18 | self.setFixedSize(800, 800)
19 | self.setup_ui()
20 |
21 | def setup_ui(self):
22 |
23 | # Writing xml file
24 | with open(EDA_HELP_DOC_FILE_PATH, "r") as f:
25 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
--------------------------------------------------------------------------------
/Application/ProjectManager/language_help.md:
--------------------------------------------------------------------------------
1 | # Supported Hardware Description Language
2 |
3 | - Select VHDL or Verilog HDL generation. This seletion is applied in all HDLGen-ChatGPT menus, until changed here.
4 | - The 'HDL Designer' 'Generate' menu header indicates if VHDL or Verilog language is veing generated. Return to the 'Project Manager' 'Generate' menu if you wish to modify the selected HDL language.
5 | - SystemVerilog and Chisel are not currently supported.
--------------------------------------------------------------------------------
/Application/ProjectManager/language_help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | VIVADO_HELP_DOC_FILE_PATH = "./ProjectManager/language_help.md"
6 |
7 |
8 | class LanguageHelpDialog(QDialog):
9 |
10 | def __init__(self):
11 | super().__init__()
12 | self.setWindowTitle("HDLGen Help")
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 |
17 | self.mainLayout = QVBoxLayout()
18 | self.setFixedSize(800, 800)
19 | self.setup_ui()
20 |
21 | def setup_ui(self):
22 |
23 | # Writing xml file
24 | with open(VIVADO_HELP_DOC_FILE_PATH, "r") as f:
25 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
--------------------------------------------------------------------------------
/Application/ProjectManager/projectLink.py:
--------------------------------------------------------------------------------
1 | from PySide2.QtWidgets import *
2 | from PySide2.QtGui import *
3 | import configparser
4 |
5 | BLACK_COLOR = "color: black"
6 | WHITE_COLOR = "color: white"
7 |
8 | class LinkDialog(QDialog):
9 |
10 | def __init__(self, add_or_edit, data=None):
11 | super().__init__()
12 |
13 | self.setWindowTitle("Project Information Link")
14 | title_font = QFont()
15 | title_font.setPointSize(10)
16 | title_font.setBold(True)
17 | bold_font = QFont()
18 | bold_font.setBold(True)
19 | input_font = QFont()
20 | input_font.setPointSize(10)
21 |
22 | self.input_layout = QGridLayout()
23 | self.mainLayout = QVBoxLayout()
24 |
25 | self.link_label = QLabel("Project Information Link")
26 | self.link_label.setFont(input_font)
27 | self.link_label.setStyleSheet(WHITE_COLOR)
28 | self.link_input = QLineEdit()
29 | self.link_input.setFont(input_font)
30 |
31 |
32 | self.cancel_btn = QPushButton("Cancel")
33 | self.cancel_btn.setFont(input_font)
34 | self.cancel_btn.setStyleSheet(
35 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
36 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
37 |
38 |
39 | self.ok_btn = QPushButton("Ok")
40 | self.ok_btn.setFont(input_font)
41 | self.ok_btn.setStyleSheet(
42 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
43 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
44 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
45 | self.input_frame = QFrame()
46 |
47 | self.cancelled = True
48 | self.config = configparser.ConfigParser()
49 |
50 | self.setup_ui()
51 | if add_or_edit == "edit" and data != None:
52 | self.load_data(data)
53 | def setup_ui(self):
54 |
55 | self.input_layout.addWidget(self.link_label, 0, 0, 1, 4)
56 | self.input_layout.addWidget(self.link_input, 1, 0, 1, 4)
57 |
58 | self.input_layout.addWidget(self.cancel_btn, 2, 2, 1, 1, alignment=Qt.AlignRight)
59 | self.input_layout.addWidget(self.ok_btn, 2, 3, 1, 1, alignment=Qt.AlignRight)
60 | self.input_frame.setFrameShape(QFrame.StyledPanel)
61 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
62 | self.input_frame.setContentsMargins(10, 10, 10, 10)
63 | self.input_frame.setFixedSize(500, 200)
64 | self.input_frame.setLayout(self.input_layout)
65 | self.cancel_btn.clicked.connect(self.cancel_selected)
66 |
67 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
68 |
69 | self.setLayout(self.mainLayout)
70 | self.ok_btn.clicked.connect(self.get_data)
71 |
72 | def cancel_selected(self):
73 | self.cancelled = True
74 | self.close()
75 |
76 | def load_data(self, data):
77 | if data == "None":
78 | data=""
79 | data = data.replace("
", "\n")
80 | data = data.replace("&","&")
81 | data = data.replace("&", "&")
82 | data = data.replace(""","\"")
83 | data = data.replace("'","\'")
84 | data = data.replace("<","<")
85 | data = data.replace(" ","\t")
86 | data = data.replace(">",">")
87 | self.link_input.setText(data)
88 | def get_data(self):
89 | data = self.link_input.text().strip()
90 | data = data.replace("&", "&")
91 | data = data.replace("\n", "
")
92 | data = data.replace("\"", """)
93 | data = data.replace("\'", "'")
94 | data = data.replace("\n", "
")
95 | data = data.replace("<", "<")
96 | data = data.replace("\t", " ")
97 | data = data.replace(">", ">")
98 | data = data.replace(",", " ")
99 | if data == "":
100 | data = "None"
101 | self.cancelled = False
102 | self.close()
103 | return data
--------------------------------------------------------------------------------
/Application/ProjectManager/settings_help.md:
--------------------------------------------------------------------------------
1 | # Project Settings
2 |
3 | - The fields provide details on the current project
4 | - 'Project Name' defines the HDLGen-Chat top level project folder, which may contain multiple 'Project Folders'
5 | - 'Project Folder' defines the name of the specific project folder, inside the 'Project Name' folder
6 | - 'Project Environment' defines the fodler which contains the folder 'Package', which includes VHDL package file 'MainPackage.vhd' (used in VHDL models)
7 |
8 | - HDLGen-ChatGPT will remember the previously opened project
9 |
10 | - Changing fields, and using the browser
11 | - Change the 'Project Name' field and click the 'HDL Designer' TAB, to copy the entire project to a new area, with the defined 'Project Name'.
12 | - Change the 'Project Folder' and click the 'HDL Designer' TAB, to copy the entire project to a new area, with the defined 'Project Name', and within folder 'Project Folder'.
13 | - Change the 'Project Environment' and click the 'HDL Designer' TAB to save the 'Project Folder' and 'Project Name' within the environment folder. A new 'MainPackage.vhd' file may be created (and used), within folder 'Package'. It may be necessary to use the 'HDL Designer' TAB 'Sub-Components' menu to add componentents is your design isa hierarchical.
14 |
15 | - Click the 'Close Project' button to close the project and return to the HDLGen-ChatGPT splash page
--------------------------------------------------------------------------------
/Application/ProjectManager/settings_help.py:
--------------------------------------------------------------------------------
1 | #Displays the assoicated help markdown file
2 | import markdown as md
3 | from PySide2.QtWidgets import *
4 |
5 | VIVADO_HELP_DOC_FILE_PATH = "./ProjectManager/settings_help.md"
6 |
7 |
8 | class SettingsHelpDialog(QDialog):
9 |
10 | def __init__(self):
11 | super().__init__()
12 | self.setWindowTitle("HDLGen Help")
13 |
14 | self.markdown_view = QTextBrowser(readOnly=True)
15 | self.markdown_view.setOpenExternalLinks(True)
16 |
17 | self.mainLayout = QVBoxLayout()
18 | self.setFixedSize(800, 800)
19 | self.setup_ui()
20 |
21 | def setup_ui(self):
22 |
23 | # Writing xml file
24 | with open(VIVADO_HELP_DOC_FILE_PATH, "r") as f:
25 | doc = md.markdown(f.read(), extensions=['fenced_code', 'codehilite', 'tables', 'attr_list'])
26 | self.markdown_view.setHtml(doc)
27 | self.mainLayout.addWidget(self.markdown_view)
28 | self.setLayout(self.mainLayout)
29 |
30 |
--------------------------------------------------------------------------------
/Application/Resources/blue_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Logicademy/HDLGen-ChatGPT/b9ea68a40cbe3dc57e04223fdd5bfdc68f64adce/Application/Resources/blue_logo.png
--------------------------------------------------------------------------------
/Application/Resources/hdlgen_title_blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Logicademy/HDLGen-ChatGPT/b9ea68a40cbe3dc57e04223fdd5bfdc68f64adce/Application/Resources/hdlgen_title_blue.png
--------------------------------------------------------------------------------
/Application/Resources/hdlgen_title_red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Logicademy/HDLGen-ChatGPT/b9ea68a40cbe3dc57e04223fdd5bfdc68f64adce/Application/Resources/hdlgen_title_red.png
--------------------------------------------------------------------------------
/Application/Resources/main_menu_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Logicademy/HDLGen-ChatGPT/b9ea68a40cbe3dc57e04223fdd5bfdc68f64adce/Application/Resources/main_menu_0.png
--------------------------------------------------------------------------------
/Application/Resources/main_menu_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Logicademy/HDLGen-ChatGPT/b9ea68a40cbe3dc57e04223fdd5bfdc68f64adce/Application/Resources/main_menu_1.png
--------------------------------------------------------------------------------
/Application/Resources/processdiagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Logicademy/HDLGen-ChatGPT/b9ea68a40cbe3dc57e04223fdd5bfdc68f64adce/Application/Resources/processdiagram.png
--------------------------------------------------------------------------------
/Application/Resources/red_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Logicademy/HDLGen-ChatGPT/b9ea68a40cbe3dc57e04223fdd5bfdc68f64adce/Application/Resources/red_logo.png
--------------------------------------------------------------------------------
/Application/Settings/VHDLModelDefault.py:
--------------------------------------------------------------------------------
1 | #Dialog box for the ChatGPT prompt from prompts.yml file. This is called from setting.py and data is exchanged. User can edit the prompts.yml file using this for the specific prompt
2 | from PySide2.QtWidgets import *
3 | from PySide2.QtGui import *
4 | import configparser
5 |
6 | BLACK_COLOR = "color: black"
7 | WHITE_COLOR = "color: white"
8 |
9 | class VHDLModelDefaultDialog(QDialog):
10 |
11 | def __init__(self, add_or_edit, data=None, resetData=None):
12 | super().__init__()
13 |
14 | self.setWindowTitle("ChatGPT VHDL Model Default Prompt")
15 | bold_font = QFont()
16 | bold_font.setBold(True)
17 | input_font = QFont()
18 | input_font.setPointSize(10)
19 |
20 | self.input_layout = QGridLayout()
21 | self.mainLayout = QVBoxLayout()
22 |
23 | self.ChatGPT_default_label = QLabel("ChatGPT Default Prompt")
24 | self.ChatGPT_default_label.setStyleSheet(WHITE_COLOR)
25 | self.ChatGPT_default_label.setFont(input_font)
26 | self.ChatGPT_default_input = QPlainTextEdit()
27 | self.ChatGPT_default_input.setLineWrapMode(QPlainTextEdit.WidgetWidth)
28 | self.ChatGPT_default_input.setFont(input_font)
29 |
30 |
31 | self.reset_btn = QPushButton("Reset")
32 | self.reset_btn.setFont(input_font)
33 | self.reset_btn.setStyleSheet(
34 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
35 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
36 |
37 | self.cancel_btn = QPushButton("Cancel")
38 | self.cancel_btn.setFont(input_font)
39 | self.cancel_btn.setStyleSheet(
40 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
41 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
42 |
43 |
44 | self.ok_btn = QPushButton("Ok")
45 | self.ok_btn.setFont(input_font)
46 | self.ok_btn.setStyleSheet(
47 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
48 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
49 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
50 |
51 | self.input_frame = QFrame()
52 |
53 | self.cancelled = True
54 | self.config = configparser.ConfigParser()
55 |
56 | self.setup_ui()
57 | if add_or_edit == "edit" and data != None and resetData != None:
58 | self.resetData = resetData
59 | self.ChatGPT_default_input.setPlainText(data)
60 |
61 | def setup_ui(self):
62 | self.input_layout.addWidget(self.ChatGPT_default_label, 0, 0, 1, 4)
63 | self.input_layout.addWidget(self.ChatGPT_default_input, 1, 0, 4, 4)
64 |
65 | self.input_layout.addWidget(self.reset_btn, 6, 1, 1, 1, alignment=Qt.AlignRight)
66 | self.input_layout.addWidget(self.cancel_btn, 6, 2, 1, 1, alignment=Qt.AlignRight)
67 | self.input_layout.addWidget(self.ok_btn, 6, 3, 1, 1, alignment=Qt.AlignRight)
68 | self.input_frame.setFrameShape(QFrame.StyledPanel)
69 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
70 | self.input_frame.setContentsMargins(10, 10, 10, 10)
71 | self.input_frame.setFixedSize(900, 800)
72 | self.input_frame.setLayout(self.input_layout)
73 | self.cancel_btn.clicked.connect(self.cancel_selected)
74 |
75 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
76 |
77 | self.setLayout(self.mainLayout)
78 | self.reset_btn.clicked.connect(self.reset)
79 | self.ok_btn.clicked.connect(self.get_data)
80 |
81 | def cancel_selected(self):
82 | self.cancelled = True
83 | self.close()
84 |
85 | def get_data(self):
86 | data = self.ChatGPT_default_input.toPlainText().strip()
87 | if data == "":
88 | data = "None"
89 | self.cancelled = False
90 | self.close()
91 | return data
92 |
93 | def reset(self):
94 | self.ChatGPT_default_input.setPlainText(self.resetData)
--------------------------------------------------------------------------------
/Application/Settings/VHDLTestbenchDefault.py:
--------------------------------------------------------------------------------
1 | #Dialog box for the ChatGPT prompt from prompts.yml file. This is called from setting.py and data is exchanged. User can edit the prompts.yml file using this for the specific prompt
2 | from PySide2.QtWidgets import *
3 | from PySide2.QtGui import *
4 | import configparser
5 |
6 | BLACK_COLOR = "color: black"
7 | WHITE_COLOR = "color: white"
8 |
9 | class VHDLTestbenchDefaultDialog(QDialog):
10 |
11 | def __init__(self, add_or_edit, data=None, resetData=None):
12 | super().__init__()
13 |
14 | self.setWindowTitle("ChatGPT VHDL Testbench Default Prompt")
15 |
16 | bold_font = QFont()
17 | bold_font.setBold(True)
18 | input_font = QFont()
19 | input_font.setPointSize(10)
20 |
21 | self.input_layout = QGridLayout()
22 | self.mainLayout = QVBoxLayout()
23 |
24 | self.ChatGPT_default_label = QLabel("ChatGPT Default Prompt")
25 | self.ChatGPT_default_label.setStyleSheet(WHITE_COLOR)
26 | self.ChatGPT_default_label.setFont(input_font)
27 | self.ChatGPT_default_input = QPlainTextEdit()
28 | self.ChatGPT_default_input.setLineWrapMode(QPlainTextEdit.WidgetWidth)
29 | self.ChatGPT_default_input.setFont(input_font)
30 |
31 | self.reset_btn = QPushButton("Reset")
32 | self.reset_btn.setFont(input_font)
33 | self.reset_btn.setStyleSheet(
34 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
35 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
36 |
37 | self.cancel_btn = QPushButton("Cancel")
38 | self.cancel_btn.setFont(input_font)
39 | self.cancel_btn.setStyleSheet(
40 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
41 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
42 |
43 | self.ok_btn = QPushButton("Ok")
44 | self.ok_btn.setFont(input_font)
45 | self.ok_btn.setStyleSheet(
46 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
47 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
48 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
49 | self.input_frame = QFrame()
50 |
51 | self.cancelled = True
52 | self.config = configparser.ConfigParser()
53 |
54 | self.setup_ui()
55 | if add_or_edit == "edit" and data != None and resetData != None:
56 | self.resetData = resetData
57 | self.ChatGPT_default_input.setPlainText(data)
58 |
59 | def setup_ui(self):
60 | self.input_layout.addWidget(self.ChatGPT_default_label, 0, 0, 1, 4)
61 | self.input_layout.addWidget(self.ChatGPT_default_input, 1, 0, 4, 4)
62 | self.input_layout.addWidget(self.reset_btn, 6, 1, 1, 1, alignment=Qt.AlignRight)
63 | self.input_layout.addWidget(self.cancel_btn, 6, 2, 1, 1, alignment=Qt.AlignRight)
64 | self.input_layout.addWidget(self.ok_btn, 6, 3, 1, 1, alignment=Qt.AlignRight)
65 | self.input_frame.setFrameShape(QFrame.StyledPanel)
66 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
67 | self.input_frame.setContentsMargins(10, 10, 10, 10)
68 | self.input_frame.setFixedSize(900, 800)
69 | self.input_frame.setLayout(self.input_layout)
70 | self.cancel_btn.clicked.connect(self.cancel_selected)
71 |
72 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
73 |
74 | self.setLayout(self.mainLayout)
75 | self.reset_btn.clicked.connect(self.reset)
76 | self.ok_btn.clicked.connect(self.get_data)
77 |
78 | def cancel_selected(self):
79 | self.cancelled = True
80 | self.close()
81 |
82 | def get_data(self):
83 | data = self.ChatGPT_default_input.toPlainText().strip()
84 | if data == "":
85 | data = "None"
86 | self.cancelled = False
87 | self.close()
88 | return data
89 |
90 | def reset(self):
91 | self.ChatGPT_default_input.setPlainText(self.resetData)
--------------------------------------------------------------------------------
/Application/Settings/VerilogModelDefault.py:
--------------------------------------------------------------------------------
1 | #Dialog box for the ChatGPT prompt from prompts.yml file. This is called from setting.py and data is exchanged. User can edit the prompts.yml file using this for the specific prompt
2 | from PySide2.QtWidgets import *
3 | from PySide2.QtGui import *
4 | import configparser
5 |
6 | BLACK_COLOR = "color: black"
7 | WHITE_COLOR = "color: white"
8 |
9 | class VerilogModelDefaultDialog(QDialog):
10 |
11 | def __init__(self, add_or_edit, data=None, resetData=None):
12 | super().__init__()
13 |
14 | self.setWindowTitle("ChatGPT Verilog Model Default Prompt")
15 | input_font = QFont()
16 | input_font.setPointSize(10)
17 | bold_font = QFont()
18 | bold_font.setBold(True)
19 |
20 | self.input_layout = QGridLayout()
21 | self.mainLayout = QVBoxLayout()
22 |
23 | self.ChatGPT_default_label = QLabel("ChatGPT Default Prompt")
24 | self.ChatGPT_default_label.setStyleSheet(WHITE_COLOR)
25 | self.ChatGPT_default_label.setFont(input_font)
26 | self.ChatGPT_default_input = QPlainTextEdit()
27 | self.ChatGPT_default_input.setLineWrapMode(QPlainTextEdit.WidgetWidth)
28 | self.ChatGPT_default_input.setFont(input_font)
29 |
30 | self.reset_btn = QPushButton("Reset")
31 | self.reset_btn.setFont(input_font)
32 | self.reset_btn.setStyleSheet(
33 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
34 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
35 |
36 | self.cancel_btn = QPushButton("Cancel")
37 | self.cancel_btn.setFont(input_font)
38 | self.cancel_btn.setStyleSheet(
39 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
40 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
41 |
42 | self.ok_btn = QPushButton("Ok")
43 | self.ok_btn.setFont(input_font)
44 | self.ok_btn.setStyleSheet(
45 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
46 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
47 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
48 | self.input_frame = QFrame()
49 |
50 | self.cancelled = True
51 | self.config = configparser.ConfigParser()
52 |
53 | self.setup_ui()
54 | if add_or_edit == "edit" and data != None and resetData != None:
55 | self.resetData = resetData
56 | self.ChatGPT_default_input.setPlainText(data)
57 |
58 | def setup_ui(self):
59 | self.input_layout.addWidget(self.ChatGPT_default_label, 0, 0, 1, 4)
60 | self.input_layout.addWidget(self.ChatGPT_default_input, 1, 0, 4, 4)
61 | self.input_layout.addWidget(self.reset_btn, 6, 1, 1, 1, alignment=Qt.AlignRight)
62 | self.input_layout.addWidget(self.cancel_btn, 6, 2, 1, 1, alignment=Qt.AlignRight)
63 | self.input_layout.addWidget(self.ok_btn, 6, 3, 1, 1, alignment=Qt.AlignRight)
64 | self.input_frame.setFrameShape(QFrame.StyledPanel)
65 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
66 | self.input_frame.setContentsMargins(10, 10, 10, 10)
67 | self.input_frame.setFixedSize(900, 800)
68 | self.input_frame.setLayout(self.input_layout)
69 | self.cancel_btn.clicked.connect(self.cancel_selected)
70 |
71 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
72 |
73 | self.setLayout(self.mainLayout)
74 | self.ok_btn.clicked.connect(self.get_data)
75 | self.reset_btn.clicked.connect(self.reset)
76 |
77 | def cancel_selected(self):
78 | self.cancelled = True
79 | self.close()
80 |
81 | def get_data(self):
82 | data = self.ChatGPT_default_input.toPlainText().strip()
83 | if data == "":
84 | data = "None"
85 | self.cancelled = False
86 | self.close()
87 | return data
88 |
89 | def reset(self):
90 | self.ChatGPT_default_input.setPlainText(self.resetData)
--------------------------------------------------------------------------------
/Application/Settings/VerilogTestbenchDefault.py:
--------------------------------------------------------------------------------
1 | #Dialog box for the ChatGPT prompt from prompts.yml file. This is called from setting.py and data is exchanged. User can edit the prompts.yml file using this for the specific prompt
2 | from PySide2.QtWidgets import *
3 | from PySide2.QtGui import *
4 | import configparser
5 |
6 | BLACK_COLOR = "color: black"
7 | WHITE_COLOR = "color: white"
8 |
9 | class VerilogTestbenchDefaultDialog(QDialog):
10 |
11 | def __init__(self, add_or_edit, data=None, resetData=None):
12 | super().__init__()
13 |
14 | self.setWindowTitle("ChatGPT Verilog Testbench Default Prompt")
15 | input_font = QFont()
16 | input_font.setPointSize(10)
17 | bold_font = QFont()
18 | bold_font.setBold(True)
19 |
20 | self.input_layout = QGridLayout()
21 | self.mainLayout = QVBoxLayout()
22 |
23 | self.ChatGPT_default_label = QLabel("ChatGPT Default Prompt")
24 | self.ChatGPT_default_label.setStyleSheet(WHITE_COLOR)
25 | self.ChatGPT_default_label.setFont(input_font)
26 | self.ChatGPT_default_input = QPlainTextEdit()
27 | self.ChatGPT_default_input.setLineWrapMode(QPlainTextEdit.WidgetWidth)
28 | self.ChatGPT_default_input.setFont(input_font)
29 |
30 | self.reset_btn = QPushButton("Reset")
31 | self.reset_btn.setFont(input_font)
32 | self.reset_btn.setStyleSheet(
33 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
34 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
35 |
36 | self.cancel_btn = QPushButton("Cancel")
37 | self.cancel_btn.setFont(input_font)
38 | self.cancel_btn.setStyleSheet(
39 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
40 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
41 |
42 | self.ok_btn = QPushButton("Ok")
43 | self.ok_btn.setFont(input_font)
44 | self.ok_btn.setStyleSheet(
45 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
46 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
47 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
48 | self.input_frame = QFrame()
49 |
50 | self.cancelled = True
51 | self.config = configparser.ConfigParser()
52 |
53 | self.setup_ui()
54 | if add_or_edit == "edit" and data != None and resetData != None:
55 | self.resetData = resetData
56 | self.ChatGPT_default_input.setPlainText(data)
57 |
58 | def setup_ui(self):
59 | self.input_layout.addWidget(self.ChatGPT_default_label, 0, 0, 1, 4)
60 | self.input_layout.addWidget(self.ChatGPT_default_input, 1, 0, 4, 4)
61 | self.input_layout.addWidget(self.reset_btn, 6, 1, 1, 1, alignment=Qt.AlignRight)
62 | self.input_layout.addWidget(self.cancel_btn, 6, 2, 1, 1, alignment=Qt.AlignRight)
63 | self.input_layout.addWidget(self.ok_btn, 6, 3, 1, 1, alignment=Qt.AlignRight)
64 | self.input_frame.setFrameShape(QFrame.StyledPanel)
65 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
66 | self.input_frame.setContentsMargins(10, 10, 10, 10)
67 | self.input_frame.setFixedSize(900, 800)
68 | self.input_frame.setLayout(self.input_layout)
69 | self.cancel_btn.clicked.connect(self.cancel_selected)
70 |
71 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
72 |
73 | self.setLayout(self.mainLayout)
74 | self.ok_btn.clicked.connect(self.get_data)
75 | self.reset_btn.clicked.connect(self.reset)
76 |
77 | def cancel_selected(self):
78 | self.cancelled = True
79 | self.close()
80 |
81 | def get_data(self):
82 | data = self.ChatGPT_default_input.toPlainText().strip()
83 | if data == "":
84 | data = "None"
85 | self.cancelled = False
86 | self.close()
87 | return data
88 |
89 | def reset(self):
90 | self.ChatGPT_default_input.setPlainText(self.resetData)
91 |
--------------------------------------------------------------------------------
/Application/Settings/settings.py:
--------------------------------------------------------------------------------
1 | #settings dialog box when settings is clicked in main.py. Reads/writes from config.ini file default and reusable information
2 | from PySide2.QtWidgets import *
3 | from PySide2.QtGui import *
4 | import sys, yaml, configparser
5 | # make sure to add to requirements.txt
6 | from Settings.VHDLModelDefault import VHDLModelDefaultDialog
7 | from Settings.VerilogModelDefault import VerilogModelDefaultDialog
8 | sys.path.append("..")
9 |
10 | BLACK_COLOR = "color: black"
11 | WHITE_COLOR = "color: white"
12 |
13 | class settingsDialog(QDialog):
14 |
15 | def __init__(self):
16 | super().__init__()
17 | self.commands = ["None", "None", "None", "None", "None", "None","None", "None", "None", "None"]
18 | self.setWindowTitle("Settings")
19 | title_font = QFont()
20 | title_font.setPointSize(12)
21 | title_font.setBold(True)
22 | bold_font = QFont()
23 | bold_font.setBold(True)
24 | input_font = QFont()
25 | input_font.setPointSize(10)
26 |
27 | self.input_layout = QGridLayout()
28 | self.mainLayout = QVBoxLayout()
29 |
30 | self.author_label = QLabel("Author")
31 | self.author_label.setStyleSheet(WHITE_COLOR)
32 | self.author_label.setFont(title_font)
33 | self.author_input = QLineEdit()
34 | self.author_input.setFont(input_font)
35 |
36 | self.email_label = QLabel("Email")
37 | self.email_label.setStyleSheet(WHITE_COLOR)
38 | self.email_input = QLineEdit()
39 |
40 | self.company_label = QLabel("Company")
41 | self.company_label.setStyleSheet(WHITE_COLOR)
42 | self.company_input = QLineEdit()
43 |
44 | self.vivado_label = QLabel("Vivado.bat path")
45 | self.vivado_label.setStyleSheet(WHITE_COLOR)
46 | self.vivado_input = QLineEdit()
47 |
48 | self.quartus_label = QLabel("Quartus path")
49 | self.quartus_label.setStyleSheet(WHITE_COLOR)
50 | self.quartus_input = QLineEdit()
51 |
52 | self.header_VHDL = QPushButton("VHDL Title Section Command")
53 | #self.header_VHDL.setFixedSize(200, 25)
54 | self.header_VHDL.setStyleSheet(
55 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }"
56 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
57 | self.model_VHDL = QPushButton("VHDL Model Command")
58 | #self.model_VHDL.setFixedSize(250, 25)
59 | self.model_VHDL.setStyleSheet(
60 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }"
61 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
62 | self.header_Verilog = QPushButton("Verilog Title Section Command")
63 | #self.header_Verilog.setFixedSize(200, 25)
64 | self.header_Verilog.setStyleSheet(
65 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }"
66 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
67 | self.model_Verilog = QPushButton("Verilog Model Command")
68 | # self.model_Verilog.setFixedSize(250, 25)
69 | self.model_Verilog.setStyleSheet(
70 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }"
71 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
72 | self.browse_btn = QPushButton("Browse")
73 | #self.browse_btn.setFixedSize(80, 25)
74 | self.browse_btn.setStyleSheet(
75 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }"
76 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
77 | self.quartus_browse_btn = QPushButton("Browse")
78 | #self.quartus_browse_btn.setFixedSize(80, 25)
79 | self.quartus_browse_btn.setStyleSheet(
80 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }"
81 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
82 |
83 | self.cancel_btn = QPushButton("Cancel")
84 | # self.cancel_btn.setFixedSize(60, 25)
85 | self.cancel_btn.setStyleSheet(
86 | "QPushButton {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
87 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}")
88 |
89 |
90 | self.ok_btn = QPushButton("Ok")
91 | #self.ok_btn.setFixedSize(60, 25)
92 | self.ok_btn.setStyleSheet(
93 | "QPushButton {background-color: rgb(169,169,169); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
94 | " QPushButton:pressed { background-color: rgb(250, 250, 250); color: black; border-radius: 8px; border-style: plain;padding: 10px;}"
95 | "QPushButton:enabled {background-color: white; color: black; border-radius: 8px; border-style: plain;padding: 10px; }")
96 | self.input_frame = QFrame()
97 |
98 | self.cancelled = True
99 | self.config = configparser.ConfigParser()
100 | self.vivado_label.setFont(title_font)
101 | self.email_label.setFont(title_font)
102 | self.company_label.setFont(title_font)
103 | self.quartus_label.setFont(title_font)
104 | self.vivado_input.setFont(input_font)
105 | self.email_input.setFont(input_font)
106 | self.company_input.setFont(input_font)
107 | self.quartus_input.setFont(input_font)
108 | self.browse_btn.setFont(input_font)
109 | self.quartus_browse_btn.setFont(input_font)
110 | self.model_VHDL.setFont(input_font)
111 | self.model_Verilog.setFont(input_font)
112 | self.ok_btn.setFont(input_font)
113 | self.cancel_btn.setFont(input_font)
114 | self.setup_ui()
115 |
116 | def setup_ui(self):
117 | self.config.read('config.ini')
118 |
119 | with open('prompts.yml', 'r') as prompts:
120 | self.prompts = yaml.safe_load(prompts)
121 |
122 | vivadoPath= self.config.get('user', 'vivado.bat')
123 | quartusPath = self.config.get('user','quartus')
124 | author = self.config.get('user', 'author')
125 | email = self.config.get('user', 'email')
126 | company = self.config.get('user', 'company')
127 |
128 | self.commands[0] = self.prompts["vhdlchatgptmodel"]
129 | self.commands[1] = self.prompts["verilogchatgptmodel"]
130 | self.commands[2] = self.prompts["vhdlchatgptmodelreset"]
131 | self.commands[3] = self.prompts["verilogchatgptmodelreset"]
132 |
133 | self.vivado_input.setText(vivadoPath.strip())
134 | self.quartus_input.setText(quartusPath.strip())
135 | self.author_input.setText(author.strip())
136 | self.email_input.setText(email.strip())
137 | self.company_input.setText(company.strip())
138 | self.input_layout.addWidget(self.author_label, 0, 0, 1, 1)
139 | self.input_layout.addWidget(self.author_input, 1, 0, 1, 1)
140 | self.input_layout.addWidget(self.email_label, 0, 1, 1, 1)
141 | self.input_layout.addWidget(self.email_input, 1, 1, 1, 1)
142 | self.input_layout.addWidget(self.company_label, 0, 2, 1, 2)
143 | self.input_layout.addWidget(self.company_input, 1, 2, 1, 2)
144 | self.input_layout.addWidget(self.vivado_label, 2, 0, 1, 3)
145 | self.input_layout.addWidget(self.vivado_input, 3, 0, 1, 3)
146 | self.input_layout.addWidget(self.browse_btn, 3, 3, 1, 1)
147 | self.input_layout.addWidget(self.quartus_label, 4, 0, 1, 3)
148 | self.input_layout.addWidget(self.quartus_input, 5, 0, 1, 3)
149 | self.input_layout.addWidget(self.quartus_browse_btn, 5, 3, 1, 1)
150 | self.input_layout.addWidget(self.model_VHDL, 6, 0)
151 | self.input_layout.addWidget(self.model_Verilog, 6, 1)
152 | #self.header_VHDL.clicked.connect(self.vhdl_header_command)
153 | #self.header_Verilog.clicked.connect(self.verilog_header_command)
154 | self.model_VHDL.clicked.connect(self.vhdl_model_command)
155 | self.model_Verilog.clicked.connect(self.verilog_model_command)
156 |
157 | self.input_layout.addWidget(self.cancel_btn, 9, 2, 1, 1, alignment=Qt.AlignRight)
158 | self.input_layout.addWidget(self.ok_btn, 9, 3, 1, 1, alignment=Qt.AlignRight)
159 | self.input_frame.setFrameShape(QFrame.StyledPanel)
160 | self.input_frame.setStyleSheet('.QFrame{background-color: rgb(97, 107, 129); border-radius: 5px;}')
161 | self.input_frame.setContentsMargins(10, 10, 10, 10)
162 | self.input_frame.setFixedSize(1000, 500)
163 | self.input_frame.setLayout(self.input_layout)
164 | self.cancel_btn.clicked.connect(self.cancel)
165 |
166 | self.mainLayout.addWidget(self.input_frame, alignment=Qt.AlignCenter)
167 |
168 | self.setLayout(self.mainLayout)
169 | self.browse_btn.clicked.connect(self.set_vivado_bat_path)
170 | self.quartus_browse_btn.clicked.connect(self.set_quartus_exe_path)
171 | self.ok_btn.clicked.connect(self.save)
172 |
173 | def set_vivado_bat_path(self):
174 | vivado_bat_path = QFileDialog.getOpenFileName(self,"Select Xilinx Vivado Batch file (vivado.bat)","C:/", filter="Batch (*.bat)")
175 | vivado_bat_path = vivado_bat_path[0]
176 | self.vivado_input.setText(vivado_bat_path)
177 |
178 | def set_quartus_exe_path(self):
179 | quartus_exe_path = QFileDialog.getOpenFileName(self,"Select Quartus Exe file (quartus_map.exe)","C:/", filter="Batch (*.exe)")
180 | quartus_exe_path = quartus_exe_path[0]
181 | self.quartus_input.setText(quartus_exe_path)
182 |
183 | def cancel(self):
184 | self.cancelled = True
185 | self.close()
186 |
187 | def enable_ok_btn(self):
188 | if self.vivado_input.text() != "" and self.vivado_input.text() != "To be completed":
189 | self.ok_btn.setEnabled(True)
190 | else:
191 | self.ok_btn.setEnabled(False)
192 |
193 | def save(self):
194 | if self.vivado_input.text().strip() == "":
195 | self.vivado_input.setText("To be completed")
196 | if self.quartus_input.text().strip() == "":
197 | self.quartus_input.setText("To be completed")
198 | if self.author_input.text().strip() == "":
199 | self.author_input.setText("To be completed")
200 | if self.email_input.text().strip() == "":
201 | self.email_input.setText("To be completed")
202 | if self.company_input.text().strip() == "":
203 | self.company_input.setText("To be completed")
204 |
205 | self.config.set("user", "author", self.author_input.text())
206 | self.config.set("user", "email", self.email_input.text())
207 | self.config.set("user", "company", self.company_input.text())
208 | self.config.set("user", "vivado.bat", self.vivado_input.text())
209 | self.config.set("user", "quartus", self.quartus_input.text())
210 |
211 | with open('config.ini', 'w') as configfile:
212 | self.config.write(configfile)
213 |
214 | with open('prompts.yml', 'r') as prompts:
215 | self.prompts = yaml.safe_load(prompts)
216 |
217 | self.prompts["vhdlchatgptmodel"] = self.commands[0]
218 | self.prompts["verilogchatgptmodel"] = self.commands[1]
219 |
220 | with open('prompts.yml', 'w') as prompts:
221 | yaml.dump(self.prompts, prompts)
222 |
223 | self.cancelled = False
224 | self.close()
225 |
226 | def vhdl_model_command(self):
227 | vhdl_model = VHDLModelDefaultDialog("edit", self.commands[0], self.commands[2])
228 | vhdl_model.exec_()
229 |
230 | if not vhdl_model.cancelled:
231 | vhdl_model = vhdl_model.get_data()
232 | self.commands[0] = vhdl_model
233 |
234 | def verilog_model_command(self):
235 | verilog_model = VerilogModelDefaultDialog("edit", self.commands[1], self.commands[3])
236 | verilog_model.exec_()
237 |
238 | if not verilog_model.cancelled:
239 | verilog_model = verilog_model.get_data()
240 | self.commands[1] = verilog_model
--------------------------------------------------------------------------------
/Application/main.py:
--------------------------------------------------------------------------------
1 | #main.py is the file that is called when HDLGen-ChatGPT is started. From here the home.py, settings.py and help.py are called. This displays the splash page on start up
2 | import os
3 | from PySide2.QtGui import *
4 | from PySide2.QtWidgets import *
5 | from PySide2.QtCore import *
6 | from pathlib import Path
7 | import sys
8 | sys.path.append(".")
9 | from Home.home import Home
10 | from Help.help import HelpDialog
11 | from Settings.settings import settingsDialog
12 | import configparser
13 |
14 |
15 | APP_AUTHORS = "Created by Fearghal Morgan, Abishek Bupathi & JP Byrne"
16 |
17 | VICI_DESCRIPTION = "Online learning and assessment, Remote FPGA\nprototyping and course builder"
18 |
19 | APP_DESCRIPTION = "- Open source application and tutorials found on GitHub
" \
20 | "- Fast digital systems design capture from design and test specifications
" \
21 | "- Generate HDL model templates and low-level logic pseudo code
" \
22 | "- Generate HDL testbench templates (stimulus and signal checking)
" \
23 | "- Assemble ChatGPT prompt
- " \
24 | "
- Execute ChatGPT prompts to complete HDL model and testbench stimulus / signal checking
" \
25 | "- Create EDA project, simulate HDL, synthesis HDL, prototype FPGA hardware
"
26 |
27 | APP_DESCRIPTION1 = "- Fast capture and generation of HDL model and testbench templates
" \
28 | "- Generation of ChatGPT messages, including header and HDL templates
" \
29 | "- ChatGPT-directed HDL model and testbench generation
" \
30 | "- EDA project creation and launch
" \
31 | "- Supports VHDL and Verilog / AMD Xilinx Vivado
" \
32 | "- Open source application
"
33 |
34 | class HDLGen(QMainWindow):
35 | def __init__(self):
36 | super().__init__()
37 | self.setWindowTitle("HDLGen-ChatGPT Version 1.0.0")
38 | self.setWindowFlags(self.windowFlags() & ~Qt.WindowMaximizeButtonHint)
39 |
40 | title_font = QFont()
41 | title_font.setPointSize(20)
42 | title_font.setBold(True)
43 |
44 | title_1_font = QFont()
45 | title_1_font.setPointSize(12)
46 |
47 | bold_font = QFont()
48 | bold_font.setPointSize(10)
49 | bold_font.setBold(True)
50 |
51 | text_font = QFont()
52 | text_font.setPointSize(10)
53 |
54 | # Initializing UI Elements
55 | self.mainLayout = QHBoxLayout()
56 | self.button_layout = QGridLayout()
57 | self.info_layout = QVBoxLayout()
58 | self.Settings_top_layout = QGridLayout()
59 |
60 | self.open_btn = QPushButton("Open Existing Project")
61 | self.open_btn.setFont(text_font)
62 | self.new_btn = QPushButton("Create New Project")
63 | self.new_btn.setFont(text_font)
64 | self.help_btn = QPushButton("Help")
65 | self.help_btn.setFont(text_font)
66 | self.help_btn.setStyleSheet(
67 | "QPushButton {background-color: white; border-radius: 10px; border-style: plain;padding: 10px; }"
68 | " QPushButton:pressed {background-color: white; border-radius: 10px; border-style: plain;padding: 10px;}")
69 | self.settings_btn = QPushButton("Settings")
70 | self.settings_btn.setFont(text_font)
71 | self.settings_btn.setStyleSheet(
72 | "QPushButton {background-color: white; border-radius: 10px; border-style: plain;padding: 10px; }"
73 | " QPushButton:pressed {background-color: white; border-radius: 10px; border-style: plain;padding: 10px;}")
74 | self.open_btn.setStyleSheet(
75 | "QPushButton {background-color: rgb(97, 107, 129); color: white; border-radius: 10px; border-style: plain;padding: 10px; }"
76 | " QPushButton:pressed { background-color: rgb(72, 80, 98); color: white; border-radius: 10px; border-style: plain;padding: 10px;}")
77 | self.open_btn.clicked.connect(self.open_project)
78 | self.new_btn.setStyleSheet(
79 | "QPushButton {background-color: rgb(97, 107, 129); color: white; border-radius: 10px; border-style: plain;padding: 10px; }"
80 | " QPushButton:pressed { background-color: rgb(72, 80, 98); color: white; border-radius: 10px; border-style: plain;padding: 10px;}")
81 | self.new_btn.clicked.connect(self.new_project)
82 | self.help_btn.clicked.connect(self.help_window)
83 |
84 | self.settings_btn.clicked.connect(self.settings_window)
85 |
86 | self.help_btn_spacer = QLabel("")
87 | self.settings_btn_spacer = QLabel("")
88 | self.settings_btn_spacer.setFixedSize(60, 25)
89 | self.help_btn_spacer.setFixedSize(35, 25)
90 |
91 | self.hdlgen_logo = QLabel("HDLGen-ChatGPT")
92 | self.hdlgen_logo.setFont(title_font)
93 | self.hdlgen_logo.setAlignment(Qt.AlignCenter)
94 | self.hdlgen_logo_1 = QLabel("HDLGen-ChatGPT / ChatGPT / EDA Tool Suite Process Flow")
95 | self.hdlgen_logo_1.setFont(title_1_font)
96 | self.hdlgen_logo_1.setAlignment(Qt.AlignCenter)
97 | self.app_description = QLabel(APP_DESCRIPTION)
98 | self.app_description.setFont(text_font)
99 | self.app_description.linkActivated.connect(self.link)
100 | self.processphoto = QLabel()
101 | curr_direct = os.getcwd()
102 | photo_direct = curr_direct + "/Resources/processdiagram.png"
103 | pixmap = QPixmap(photo_direct)
104 |
105 | self.processphoto.setPixmap(pixmap)
106 | self.tutorial_link = QLabel(
107 | 'Tutorials Tutorial videos on HDLGen/ChatGPT, for a range of design examples')
108 | self.tutorial_link.setFont(text_font)
109 | self.tutorial_link.linkActivated.connect(self.link)
110 | self.github_link = QLabel('GitHub\nIf you use HDLGen-ChatGPT, please include the Github reference to our work')
111 | self.github_link.setFont(text_font)
112 | self.app_authors = QLabel(APP_AUTHORS)
113 | self.app_authors.setFont(bold_font)
114 | self.github_link.linkActivated.connect(self.link)
115 | self.vici_link = QLabel('VICILOGIC online courses: digital systems design and RISC-V architecture and applications')
116 | self.vici_link.setFont(text_font)
117 | self.vici_link.linkActivated.connect(self.link)
118 | self.chatgpt_link = QLabel('ChatGPT Online large language model-based chatbot developed by OpenAI')
119 | self.chatgpt_link.setFont(text_font)
120 | self.chatgpt_link.linkActivated.connect(self.link)
121 | # Creating a container
122 | self.container = QWidget()
123 | self.config = configparser.ConfigParser()
124 |
125 | if not self.config.read('config.ini'):
126 | HDLGen.create_config_file()
127 | self.config.read('config.ini')
128 |
129 | self.setup_ui()
130 |
131 | def setup_ui(self):
132 | print("Setting up UI")
133 | self.button_layout.addWidget(self.hdlgen_logo,0,0,1,3)
134 | self.button_layout.addWidget(self.new_btn, 0, 5, 1,1)
135 | self.button_layout.addWidget(self.open_btn, 0, 4,1,1)
136 | self.button_layout.addWidget(self.settings_btn, 0, 6,1,1)
137 | self.button_layout.addWidget(self.help_btn, 0, 7,1,1)
138 |
139 | self.info_layout.addSpacerItem(QSpacerItem(1, 25))
140 | self.info_layout.addSpacerItem(QSpacerItem(1, 25))
141 | self.info_layout.addLayout(self.button_layout)
142 | self.info_layout.addSpacerItem(QSpacerItem(1, 25))
143 | self.info_layout.addWidget(self.hdlgen_logo_1, alignment=Qt.AlignCenter)
144 | self.info_layout.addSpacerItem(QSpacerItem(1, 5))
145 | self.info_layout.addWidget(self.processphoto, alignment=Qt.AlignCenter)
146 | self.info_layout.addSpacerItem(QSpacerItem(1, 5))
147 | self.info_layout.addWidget(self.github_link, alignment=Qt.AlignCenter)
148 | self.info_layout.addSpacerItem(QSpacerItem(1, 10))
149 |
150 | self.mainLayout.addLayout(self.info_layout)
151 | self.container.setLayout(self.mainLayout)
152 |
153 | self.setLayout(self.mainLayout)
154 | self.setCentralWidget(self.container)
155 |
156 | def help_window(self):
157 | help_dialog = HelpDialog()
158 | help_dialog.exec_()
159 |
160 | def new_project(self):
161 | self.window = Home()
162 | self.window.showMaximized()
163 | self.close()
164 |
165 | def open_project(self):
166 | lastDir = self.config.get('user', 'recentEnviro')
167 |
168 | if not os.path.exists(lastDir):
169 | lastDir = Path("../User_Projects/")
170 |
171 | selected_proj_dir = QFileDialog.getOpenFileName(self, "Select the Project HDLGen File", str(lastDir), filter="HDLGen (*.hdlgen)")
172 | load_proj_dir = Path(selected_proj_dir[0])
173 |
174 | if load_proj_dir.exists():
175 | self.window = Home(load_proj_dir)
176 | self.window.showMaximized()
177 | self.close()
178 |
179 | def link(self, url_str):
180 | QDesktopServices.openUrl(QUrl(url_str))
181 |
182 | def settings_window(self):
183 | settings_dialog = settingsDialog()
184 | settings_dialog.exec_()
185 |
186 | @staticmethod
187 | def create_config_file():
188 | config_file = os.path.join(os.getcwd(), 'config.ini')
189 |
190 | default_config = configparser.ConfigParser()
191 |
192 | default_environment = Path(os.getcwd()).parent.absolute() / 'User_Projects'
193 |
194 | default_config['user'] = {
195 | 'author': 'To be completed',
196 | 'email': 'To be completed',
197 | 'company': 'To be completed',
198 | 'vivado.bat': 'To be completed',
199 | 'recentenviro': default_environment,
200 | 'quartus': 'To be completed'
201 | }
202 |
203 | with open(config_file, 'w', encoding='UTF-8') as f:
204 | default_config.write(f)
205 | f.flush()
206 |
207 | def main():
208 | if hasattr(Qt, 'AA_EnableHighDpiScaling'):
209 | QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
210 |
211 | if hasattr(Qt, 'AA_UseHighDpiPixmaps'):
212 | QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
213 |
214 | app = QApplication(sys.argv)
215 |
216 | window = HDLGen()
217 | window.setWindowFlags(window.windowFlags() | Qt.WindowMaximizeButtonHint)
218 | window.move(0, 0)
219 | window.show()
220 |
221 | app.setStyle('windowsvista')
222 | app.exec_()
223 |
224 | if __name__ == '__main__':
225 | main()
226 |
--------------------------------------------------------------------------------
/Application/requirements.txt:
--------------------------------------------------------------------------------
1 | Markdown==3.3.6
2 | PySide2==5.15.2.1
3 | QtAwesome==1.1.1
4 | pyperclip==1.8.2
5 | pyyaml
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ##
6 | ### HDLGen-ChatGPT and ChatGPT:
7 | ### Digital Systems Design and Test Plan Capture Wizard, VHDL/Verilog Model and Testbench Generator, EDA Project Generator/Launcher
8 | * [Download installable app](https://github.com/fearghal1/HDLGen-ChatGPT/releases/tag/v1.0.0)
9 | ##
10 | * [Setup Git environment](https://vicicourse.s3.eu-west-1.amazonaws.com/HDLGen/Setup+Python+and+Git+Environment.pdf)
11 | * [Setup HDLGen-ChatGPT Python app](https://vicicourse.s3.eu-west-1.amazonaws.com/HDLGen/HDLGen-ChatGPT+application+setup+in+Python+and+Git+environment.pdf)
12 | ##
13 | * [RSP2023 Workshop Presentation, 21st Sept 2023 "HDLGen-ChatGPT Case Study: RISC-V Processor VHDL and Verilog Model, Testbench and EDA Project Generation", 34th International Workshop on Rapid System Prototyping (RSP), Sept 2023](https://vicicourse.s3.eu-west-1.amazonaws.com/HDLGen/RSP2023/RSP2023_presentation_RSP2023+HDLGen-ChatGPT+Case+Study+-+RISC-V+Processor+VHDL+and+Verilog+Model%2C+Testbench+and+EDA+Project+Generation.pdf)
14 | * [Tutorials and project downloads](https://vicicourse.s3.eu-west-1.amazonaws.com/HDLGen/videos/HDLGen-ChatGPT+demos.pdf)
15 | * [User experiences](https://vicicourse.s3.eu-west-1.amazonaws.com/HDLGen/RSP2023/Early+user+feedback+(16+users)+To+John+Patrick.pdf)
16 | ##
17 | * [Kanban project management](https://github.com/orgs/HDLGen-ChatGPT/projects/3/views/1)
18 | * HDLGen-ChatGPT / ChatGPT / EDA toolsuite process diagram:
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | * License: GNU Affero General Public License 3.0 - [https://opensource.org/license/agpl-v3](https://opensource.org/license/agpl-v3)
33 |
--------------------------------------------------------------------------------
/Sample_Projects/Sample_Projects_Downloads.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Logicademy/HDLGen-ChatGPT/b9ea68a40cbe3dc57e04223fdd5bfdc68f64adce/Sample_Projects/Sample_Projects_Downloads.pdf
--------------------------------------------------------------------------------
/User_Projects/User_Projects_Downloads.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Logicademy/HDLGen-ChatGPT/b9ea68a40cbe3dc57e04223fdd5bfdc68f64adce/User_Projects/User_Projects_Downloads.pdf
--------------------------------------------------------------------------------