-
Notifications
You must be signed in to change notification settings - Fork 51
/
Copy pathCC_TOOLS.py
176 lines (158 loc) · 5.85 KB
/
CC_TOOLS.py
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import os
import shutil
import sys
import C_TO_LOGIC
import SYN
import VHDL
from utilities import GET_TOOL_PATH
# Tool path constants
TOOL_EXE = "p_r"
# Default to env if there
ENV_TOOL_PATH = GET_TOOL_PATH(TOOL_EXE)
if ENV_TOOL_PATH:
CC_TOOLS_PR_PATH = ENV_TOOL_PATH
CC_TOOLS_PATH = os.path.abspath(os.path.dirname(CC_TOOLS_PR_PATH) + "../../")
else:
CC_TOOLS_PATH = "/media/1TB/Programs/Linux/cc-toolchain-linux_testing_12.09.24"
class ParsedTimingReport:
def __init__(self, syn_output):
path_report = PathReport(syn_output)
self.path_reports = dict()
self.path_reports[path_report.path_group] = path_report
if len(self.path_reports) == 0:
raise Exception(f"Bad synthesis log?:\n{syn_output}")
class PathReport:
def __init__(self, path_report_text):
self.path_delay_ns = None # nanoseconds
# Fake clock info since no clock constrainted existed?
self.path_group = "clk"
self.slack_ns = None
self.source_ns_per_clock = None # From latch edge time
self.path_group = None # Clock name?
self.netlist_resources = set() # Set of strings
self.start_reg_name = None
self.end_reg_name = None
for line in path_report_text.split("\n"):
tok = "Maximum Clock Frequency"
if tok in line:
#print(line)
fmax_mhz = float(line.split(":")[1].strip().split(" ")[0])
#print("fmax_mhz",fmax_mhz)
self.path_delay_ns = 1000.0 / fmax_mhz
# Returns parsed timing report
def SYN_AND_REPORT_TIMING(
inst_name,
Logic,
parser_state,
TimingParamsLookupTable,
total_latency=None,
hash_ext=None,
use_existing_log_file=True,
):
multimain_timing_params = SYN.MultiMainTimingParams()
multimain_timing_params.TimingParamsLookupTable = TimingParamsLookupTable
return SYN_AND_REPORT_TIMING_NEW(
parser_state,
multimain_timing_params,
inst_name,
total_latency,
hash_ext,
use_existing_log_file,
)
# Returns parsed timing report
def SYN_AND_REPORT_TIMING_MULTIMAIN(parser_state, multimain_timing_params):
return SYN_AND_REPORT_TIMING_NEW(parser_state, multimain_timing_params)
# MULTIMAIN OR SINGLE INSTANCE
# Returns parsed timing report
def SYN_AND_REPORT_TIMING_NEW(
parser_state,
multimain_timing_params,
inst_name=None,
total_latency=None,
hash_ext=None,
use_existing_log_file=True,
):
# Which vhdl files?
vhdl_files_texts, top_entity_name = SYN.GET_VHDL_FILES_TCL_TEXT_AND_TOP(
multimain_timing_params, parser_state, inst_name
)
log_file_name = top_entity_name + ".log"
# Single inst
if inst_name:
Logic = parser_state.LogicInstLookupTable[inst_name]
# First create syn/imp directory for this logic
output_directory = SYN.GET_OUTPUT_DIRECTORY(Logic)
else:
# Multimain
# First create directory for this logic
output_directory = SYN.SYN_OUTPUT_DIRECTORY + "/" + SYN.TOP_LEVEL_MODULE
if not os.path.exists(output_directory):
os.makedirs(output_directory)
log_path = output_directory + "/" + log_file_name
syn_log_path = output_directory + "/syn_" + log_file_name # Need separate logs?
# Use same configs based on to speed up run time?
log_to_read = log_path
# If log file exists dont run syn
if os.path.exists(log_to_read) and use_existing_log_file:
# print "SKIPPED:", syn_imp_bash_cmd
print("Reading log", log_to_read)
f = open(log_path, "r")
log_text = f.read()
f.close()
return ParsedTimingReport(log_text)
# Not from log:
# Write top level vhdl for this module/multimain
if inst_name:
VHDL.WRITE_LOGIC_ENTITY(
inst_name,
Logic,
output_directory,
parser_state,
multimain_timing_params.TimingParamsLookupTable,
)
VHDL.WRITE_LOGIC_TOP(
inst_name,
Logic,
output_directory,
parser_state,
multimain_timing_params.TimingParamsLookupTable,
)
else:
VHDL.WRITE_MULTIMAIN_TOP(parser_state, multimain_timing_params)
# Generate files for this SYN
# Write clock constraint and include it
constraints_filepath = SYN.WRITE_CLK_CONSTRAINTS_FILE(parser_state, inst_name)
clk_to_mhz, constraints_filepath = SYN.GET_CLK_TO_MHZ_AND_CONSTRAINTS_PATH(
parser_state, inst_name
)
# Generate build scripts
# TODO dont base on cc-toolchain directory?
CC_TOOLS_YOSYS = CC_TOOLS_PATH + "/bin/yosys/yosys"
CC_TOOLS_PR = CC_TOOLS_PATH + "/bin/p_r/p_r"
CC_TOOLS_PR_FLAGS = f"-ccf {constraints_filepath}" #-cCP?
temp_local_out_dir = CC_TOOLS_PATH + "/workspace/pipelinec_temp_"+top_entity_name
shutil.rmtree(temp_local_out_dir, ignore_errors=True)
os.makedirs(temp_local_out_dir)
os.makedirs(f"{output_directory}/net", exist_ok=True)
sh_text = ""
sh_text += f"""
#!/bin/bash
{CC_TOOLS_YOSYS} -ql {syn_log_path} -p 'ghdl --std=08 --warn-no-binding -C --ieee=synopsys {vhdl_files_texts} -e {top_entity_name}; synth_gatemate -top {top_entity_name} -nomx8 -vlog {output_directory}/net/{top_entity_name}_synth.v' &> /dev/null
{CC_TOOLS_PR} -i {output_directory}/net/{top_entity_name}_synth.v -o {top_entity_name} {CC_TOOLS_PR_FLAGS} &> {log_path}
"""
sh_file = top_entity_name + ".sh"
sh_path = output_directory + "/" + sh_file
f = open(sh_path, "w")
f.write(sh_text)
f.close()
# Run the build script
print("Running CC_TOOLS:", sh_path, flush=True)
syn_imp_bash_cmd = (
"bash " + sh_path
)
C_TO_LOGIC.GET_SHELL_CMD_OUTPUT(syn_imp_bash_cmd, cwd=temp_local_out_dir)
f = open(log_path, "r")
log_text = f.read()
f.close()
shutil.rmtree(temp_local_out_dir, ignore_errors=True)
return ParsedTimingReport(log_text)