Skip to content

Commit 92045cd

Browse files
committed
Criando funcao de conexão
1 parent 516eb4f commit 92045cd

29 files changed

+1794
-724
lines changed

config_generator.py

Lines changed: 106 additions & 119 deletions
Large diffs are not rendered by default.

connector/connect_interface.py

Lines changed: 478 additions & 0 deletions
Large diffs are not rendered by default.

connector/defines.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
ahb_adapter = """
2+
// AHB - Instruction bus
3+
logic [31:0] haddr;
4+
logic hwrite;
5+
logic [2:0] hsize;
6+
logic [2:0] hburst;
7+
logic hmastlock;
8+
logic [3:0] hprot;
9+
logic [1:0] htrans;
10+
logic [31:0] hwdata;
11+
logic [31:0] hrdata;
12+
logic hready;
13+
logic hresp;
14+
15+
ahb_to_wishbone #( // bus adapter
16+
.ADDR_WIDTH(32),
17+
.DATA_WIDTH(32)
18+
) ahb2wb_inst (
19+
// Clock & Reset
20+
.HCLK (clk_core),
21+
.HRESETn (~rst_core),
22+
23+
// AHB interface
24+
.HADDR (haddr),
25+
.HTRANS (htrans),
26+
.HWRITE (hwrite),
27+
.HSIZE (hsize),
28+
.HBURST (hburst),
29+
.HPROT (hprot),
30+
.HLOCK (hmastlock),
31+
.HWDATA (hwdata),
32+
.HREADY (hready),
33+
.HRDATA (hrdata),
34+
.HREADYOUT (hready), // normalmente igual a HREADY em designs simples
35+
.HRESP (hresp),
36+
37+
// Wishbone interface
38+
.wb_cyc (core_cyc),
39+
.wb_stb (core_stb),
40+
.wb_we (core_we),
41+
.wb_wstrb (core_sel),
42+
.wb_adr (core_addr),
43+
.wb_dat_w (core_data_out),
44+
.wb_dat_r (core_data_in),
45+
.wb_ack (core_ack)
46+
);
47+
"""
48+
49+
ahb_data_adapter = """
50+
// AHB - Data bus
51+
// AHB - Instruction bus
52+
logic [31:0] data_haddr;
53+
logic data_hwrite;
54+
logic [2:0] data_hsize;
55+
logic [2:0] data_hburst;
56+
logic data_hmastlock;
57+
logic [3:0] data_hprot;
58+
logic [1:0] data_htrans;
59+
logic [31:0] data_hwdata;
60+
logic [31:0] data_hrdata;
61+
logic data_hready;
62+
logic data_hresp;
63+
64+
ahb_to_wishbone #( // bus adapter
65+
.ADDR_WIDTH(32),
66+
.DATA_WIDTH(32)
67+
) ahb2wb_inst (
68+
// Clock & Reset
69+
.HCLK (clk_core),
70+
.HRESETn (~rst_core),
71+
72+
// AHB interface
73+
.HADDR (data_haddr),
74+
.HTRANS (data_htrans),
75+
.HWRITE (data_hwrite),
76+
.HSIZE (data_hsize),
77+
.HBURST (data_hburst),
78+
.HPROT (data_hprot),
79+
.HLOCK (data_hmastlock),
80+
.HWDATA (data_hwdata),
81+
.HREADY (data_hready),
82+
.HRDATA (data_hrdata),
83+
.HREADYOUT (data_hready), // normalmente igual a HREADY em designs simples
84+
.HRESP (data_hresp),
85+
86+
// Wishbone interface
87+
.wb_cyc (data_mem_cyc),
88+
.wb_stb (data_mem_stb),
89+
.wb_we (data_mem_we),
90+
.wb_wstrb (data_mem_sel),
91+
.wb_adr (data_mem_addr),
92+
.wb_dat_w (data_mem_data_out),
93+
.wb_dat_r (data_mem_data_in),
94+
.wb_ack (data_mem_ack)
95+
);
96+
"""
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
import re
2+
from pathlib import Path
3+
import sys
4+
import json
5+
import ast
6+
import argparse
7+
from prompts import find_interface_prompt
8+
9+
# pip install ollama
10+
from ollama import Client
11+
12+
SERVER_URL = "http://enqii.lsc.ic.unicamp.br:11434"
13+
client = Client(host=SERVER_URL)
14+
15+
16+
def send_prompt(prompt: str, model: str = "qwen2.5:32b") -> tuple[bool, str]:
17+
"""
18+
Sends a prompt to the specified server and receives the model's response.
19+
20+
Args:
21+
prompt (str): The prompt to be sent to the model.
22+
model (str, optional): The model to use. Default is 'qwen2.5:32b'.
23+
24+
Returns:
25+
tuple: A tuple containing a boolean value (indicating success)
26+
and the model's response as a string.
27+
"""
28+
response = client.generate(prompt=prompt, model=model)
29+
30+
# print("Full response:", response) # Debug: show the full response
31+
32+
if not response or "response" not in response:
33+
return 0, ""
34+
35+
return 1, response["response"]
36+
37+
38+
def filter_processor_interface_from_response(response: str) -> str:
39+
"""
40+
It is expected a response with the following json format:
41+
{
42+
"bus_type": One of [AHB, AXI, Avalon, Wishbone, Custom],
43+
"memory_interface": Single or Dual,
44+
"confidence": High/Medium/Low (based on number of matches and comments)
45+
}
46+
This function extracts and returns only the JSON part of the response.
47+
"""
48+
# --- 1. Find last {...} block ---
49+
start = response.rfind("{")
50+
end = response.rfind("}")
51+
if start == -1 or end == -1 or end < start:
52+
raise ValueError("No JSON object found in response.")
53+
candidate = response[start : end + 1]
54+
55+
# --- 2. Small fixes for common LLM mistakes ---
56+
candidate = re.sub(r",\s*([}\]])", r"\1", candidate) # remove trailing commas
57+
candidate = candidate.replace("'", '"') # single → double quotes
58+
candidate = re.sub(r"([,{]\s*)(\w+)(\s*):", r'\1"\2"\3:', candidate) # quote keys
59+
candidate = re.sub(
60+
r"//.*$", "", candidate, flags=re.MULTILINE
61+
) # remove JavaScript-style comments
62+
63+
# --- 3. Try parsing ---
64+
try:
65+
parsed = json.loads(candidate)
66+
except json.JSONDecodeError:
67+
try:
68+
# fallback: try Python dict style with ast.literal_eval
69+
parsed = ast.literal_eval(candidate)
70+
except (ValueError, SyntaxError):
71+
raise ValueError(f"Failed to parse JSON from response: {candidate}")
72+
73+
# --- 4. Keep only expected keys ---
74+
allowed_keys = {"bus_type", "memory_interface", "confidence"}
75+
filtered = {k: parsed[k] for k in allowed_keys if k in parsed}
76+
77+
return filtered
78+
79+
80+
def extract_full_module(file_path, context=10):
81+
"""
82+
Extracts full Verilog/SystemVerilog/VHDL module declarations (with ports)
83+
or VHDL entity declarations, plus N lines of context before and after.
84+
"""
85+
lines = Path(file_path).read_text(encoding="utf-8").splitlines()
86+
87+
# Patterns
88+
verilog_module_pattern = re.compile(r"^\s*module\s+\w+")
89+
vhdl_entity_pattern = re.compile(r"^\s*entity\s+\w+")
90+
91+
results = []
92+
i = 0
93+
while i < len(lines):
94+
line = lines[i]
95+
if verilog_module_pattern.match(line):
96+
# start context
97+
start = max(0, i - context)
98+
# capture until the end of module declaration (line with ');')
99+
j = i
100+
while j < len(lines) and not re.search(r"\)\s*;", lines[j]):
101+
j += 1
102+
# include the line with ');
103+
if j < len(lines):
104+
j += 1
105+
end = min(len(lines), j + context)
106+
snippet = "\n".join(lines[start:end])
107+
results.append((i + 1, snippet))
108+
i = j # skip ahead
109+
elif vhdl_entity_pattern.match(line):
110+
# start context
111+
start = max(0, i - context)
112+
# capture until end <entity_name>;
113+
entity_name = re.search(r"entity\s+(\w+)", line).group(1)
114+
j = i
115+
# match both 'end <name>;' and 'end entity <name>;'
116+
while j < len(lines) and not re.search(
117+
rf"end\s+(entity\s+)?{entity_name}\s*;", lines[j], re.IGNORECASE
118+
):
119+
j += 1
120+
if j < len(lines):
121+
j += 1
122+
end = min(len(lines), j + context)
123+
snippet = "\n".join(lines[start:end])
124+
results.append((i + 1, snippet))
125+
i = j
126+
else:
127+
i += 1
128+
return results
129+
130+
131+
def extract_interface_and_memory_ports(core_declaration, model="qwen2.5:32b"):
132+
133+
prompt = find_interface_prompt.format(core_declaration=core_declaration)
134+
success, response = send_prompt(prompt, model=model)
135+
136+
if not success:
137+
print("Error communicating with the server.")
138+
return None
139+
json_info = filter_processor_interface_from_response(response)
140+
return json_info
141+
142+
143+
def main(file_path: str, context: int, model: str, output: str):
144+
matches = extract_full_module(file_path, context)
145+
146+
if not matches:
147+
print("No module/entity declarations found.")
148+
return
149+
else:
150+
for line_no, snippet in matches:
151+
print("=" * 60)
152+
print(f"Declaration match at line {line_no}:")
153+
print("=" * 60)
154+
print(snippet)
155+
print()
156+
157+
# only get first declaration as it's the most probable option
158+
interface_and_ports = extract_interface_and_memory_ports(matches[0][1], model=model)
159+
if not interface_and_ports:
160+
print("No bus interface type or memory port information found.")
161+
return
162+
else:
163+
print("=" * 60)
164+
print("Bus interface type and number of memory ports:")
165+
print("=" * 60)
166+
print(json.dumps(interface_and_ports, indent=2))
167+
168+
if output:
169+
with open(output, "w", encoding="utf-8") as f:
170+
json.dump(interface_and_ports, f, indent=2)
171+
print(f"\nOutput saved to {output}")
172+
173+
174+
if __name__ == "__main__":
175+
parser = argparse.ArgumentParser(
176+
description="Find processor interface in HDL files."
177+
)
178+
parser.add_argument(
179+
"file", help="Path to the HDL file (Verilog/SystemVerilog/VHDL)"
180+
)
181+
parser.add_argument(
182+
"-c",
183+
"--context",
184+
type=int,
185+
default=10,
186+
help="Number of context lines to include",
187+
)
188+
parser.add_argument(
189+
"-m",
190+
"--model",
191+
type=str,
192+
default="qwen2.5:32b",
193+
help="Model to use for the LLM",
194+
)
195+
parser.add_argument(
196+
"-o", "--output", type=str, help="Path to save the output JSON", required=False
197+
)
198+
args = parser.parse_args()
199+
200+
main(args.file, args.context, args.model, args.output)

0 commit comments

Comments
 (0)