yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
driver.cc
Go to the documentation of this file.
1 /*
2  * yosys -- Yosys Open SYnthesis Suite
3  *
4  * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  */
19 
20 #include "kernel/yosys.h"
21 #include "libs/sha1/sha1.h"
22 
23 #ifdef YOSYS_ENABLE_READLINE
24 # include <readline/readline.h>
25 # include <readline/history.h>
26 #endif
27 
28 #include <stdio.h>
29 #include <string.h>
30 #include <limits.h>
31 #include <errno.h>
32 
33 #if !defined(_WIN32) || defined(__MINGW32__)
34 # include <unistd.h>
35 #else
36 char *optarg;
37 int optind = 1, optcur = 1;
38 int getopt(int argc, char **argv, const char *optstring)
39 {
40  if (optind >= argc || argv[optind][0] != '-')
41  return -1;
42 
43  bool takes_arg = false;
44  int opt = argv[optind][optcur];
45  for (int i = 0; optstring[i]; i++)
46  if (opt == optstring[i] && optstring[i + 1] == ':')
47  takes_arg = true;
48 
49  if (!takes_arg) {
50  if (argv[optind][++optcur] == 0)
51  optind++, optcur = 1;
52  return opt;
53  }
54 
55  if (argv[optind][++optcur]) {
56  optarg = argv[optind++] + optcur;
57  optcur = 1;
58  return opt;
59  }
60 
61  optarg = argv[++optind];
62  optind++, optcur = 1;
63  return opt;
64 }
65 #endif
66 
67 
69 
70 int main(int argc, char **argv)
71 {
72  std::string frontend_command = "auto";
73  std::string backend_command = "auto";
74  std::vector<std::string> passes_commands;
75  std::vector<std::string> plugin_filenames;
76  std::string output_filename = "";
77  std::string scriptfile = "";
78  bool scriptfile_tcl = false;
79  bool got_output_filename = false;
80  bool print_banner = true;
81  bool print_stats = true;
82  bool call_abort = false;
83 
84 #ifdef YOSYS_ENABLE_READLINE
85  int history_offset = 0;
86  std::string history_file;
87  if (getenv("HOME") != NULL) {
88  history_file = stringf("%s/.yosys_history", getenv("HOME"));
89  read_history(history_file.c_str());
90  history_offset = where_history();
91  }
92 #endif
93 
94  int opt;
95  while ((opt = getopt(argc, argv, "AQTVSm:f:Hh:b:o:p:l:qv:ts:c:")) != -1)
96  {
97  switch (opt)
98  {
99  case 'A':
100  call_abort = true;
101  break;
102  case 'Q':
103  print_banner = false;
104  break;
105  case 'T':
106  print_stats = false;
107  break;
108  case 'V':
109  printf("%s\n", yosys_version_str);
110  exit(0);
111  case 'S':
112  passes_commands.push_back("synth");
113  break;
114  case 'm':
115  plugin_filenames.push_back(optarg);
116  break;
117  case 'f':
118  frontend_command = optarg;
119  break;
120  case 'H':
121  passes_commands.push_back("help");
122  break;
123  case 'h':
124  passes_commands.push_back(stringf("help %s", optarg));
125  break;
126  case 'b':
127  backend_command = optarg;
128  break;
129  case 'p':
130  passes_commands.push_back(optarg);
131  break;
132  case 'o':
133  output_filename = optarg;
134  got_output_filename = true;
135  break;
136  case 'l':
137  log_files.push_back(fopen(optarg, "wt"));
138  if (log_files.back() == NULL) {
139  fprintf(stderr, "Can't open log file `%s' for writing!\n", optarg);
140  exit(1);
141  }
142  break;
143  case 'q':
144  if (log_errfile == stderr)
145  log_quiet_warnings = true;
146  log_errfile = stderr;
147  break;
148  case 'v':
149  log_errfile = stderr;
150  log_verbose_level = atoi(optarg);
151  break;
152  case 't':
153  log_time = true;
154  break;
155  case 's':
156  scriptfile = optarg;
157  scriptfile_tcl = false;
158  break;
159  case 'c':
160  scriptfile = optarg;
161  scriptfile_tcl = true;
162  break;
163  default:
164  fprintf(stderr, "\n");
165  fprintf(stderr, "Usage: %s [-V -S -Q -T -q] [-v <level>[-t] [-l <logfile>] [-o <outfile>] [-f <frontend>] [-h cmd] \\\n", argv[0]);
166  fprintf(stderr, " %*s[{-s|-c} <scriptfile>] [-p <pass> [-p ..]] [-b <backend>] [-m <module_file>] [<infile> [..]]\n", int(strlen(argv[0])+1), "");
167  fprintf(stderr, "\n");
168  fprintf(stderr, " -Q\n");
169  fprintf(stderr, " suppress printing of banner (copyright, disclaimer, version)\n");
170  fprintf(stderr, "\n");
171  fprintf(stderr, " -T\n");
172  fprintf(stderr, " suppress printing of footer (log hash, version, timing statistics)\n");
173  fprintf(stderr, "\n");
174  fprintf(stderr, " -q\n");
175  fprintf(stderr, " quiet operation. only write warnings and error messages to console\n");
176  fprintf(stderr, " use this option twice to also quiet warning messages\n");
177  fprintf(stderr, "\n");
178  fprintf(stderr, " -v <level>\n");
179  fprintf(stderr, " print log headers up to level <level> to the console. (implies -q)\n");
180  fprintf(stderr, "\n");
181  fprintf(stderr, " -t\n");
182  fprintf(stderr, " annotate all log messages with a time stamp\n");
183  fprintf(stderr, "\n");
184  fprintf(stderr, " -l logfile\n");
185  fprintf(stderr, " write log messages to the specified file\n");
186  fprintf(stderr, "\n");
187  fprintf(stderr, " -o outfile\n");
188  fprintf(stderr, " write the design to the specified file on exit\n");
189  fprintf(stderr, "\n");
190  fprintf(stderr, " -b backend\n");
191  fprintf(stderr, " use this backend for the output file specified on the command line\n");
192  fprintf(stderr, "\n");
193  fprintf(stderr, " -f backend\n");
194  fprintf(stderr, " use the specified front for the input files on the command line\n");
195  fprintf(stderr, "\n");
196  fprintf(stderr, " -H\n");
197  fprintf(stderr, " print the command list\n");
198  fprintf(stderr, "\n");
199  fprintf(stderr, " -h command\n");
200  fprintf(stderr, " print the help message for the specified command\n");
201  fprintf(stderr, "\n");
202  fprintf(stderr, " -s scriptfile\n");
203  fprintf(stderr, " execute the commands in the script file\n");
204  fprintf(stderr, "\n");
205  fprintf(stderr, " -c tcl_scriptfile\n");
206  fprintf(stderr, " execute the commands in the tcl script file (see 'help tcl' for details)\n");
207  fprintf(stderr, "\n");
208  fprintf(stderr, " -p command\n");
209  fprintf(stderr, " execute the commands\n");
210  fprintf(stderr, "\n");
211  fprintf(stderr, " -m module_file\n");
212  fprintf(stderr, " load the specified module (aka plugin)\n");
213  fprintf(stderr, "\n");
214  fprintf(stderr, " -A\n");
215  fprintf(stderr, " will call abort() at the end of the script. useful for debugging\n");
216  fprintf(stderr, "\n");
217  fprintf(stderr, " -V\n");
218  fprintf(stderr, " print version information and exit\n");
219  fprintf(stderr, "\n");
220  fprintf(stderr, "The option -S is an shortcut for calling the \"synth\" command, a default\n");
221  fprintf(stderr, "script for transforming the verilog input to a gate-level netlist. For example:\n");
222  fprintf(stderr, "\n");
223  fprintf(stderr, " yosys -o output.blif -S input.v\n");
224  fprintf(stderr, "\n");
225  fprintf(stderr, "For more complex synthesis jobs it is recommended to use the read_* and write_*\n");
226  fprintf(stderr, "commands in a script file instead of specifying input and output files on the\n");
227  fprintf(stderr, "command line.\n");
228  fprintf(stderr, "\n");
229  fprintf(stderr, "When no commands, script files or input files are specified on the command\n");
230  fprintf(stderr, "line, yosys automatically enters the interactive command mode. Use the 'help'\n");
231  fprintf(stderr, "command to get information on the individual commands.\n");
232  fprintf(stderr, "\n");
233  exit(1);
234  }
235  }
236 
237  if (log_errfile == NULL)
238  log_files.push_back(stderr);
239 
240  if (print_banner) {
241  log("\n");
242  log(" /----------------------------------------------------------------------------\\\n");
243  log(" | |\n");
244  log(" | yosys -- Yosys Open SYnthesis Suite |\n");
245  log(" | |\n");
246  log(" | Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> |\n");
247  log(" | |\n");
248  log(" | Permission to use, copy, modify, and/or distribute this software for any |\n");
249  log(" | purpose with or without fee is hereby granted, provided that the above |\n");
250  log(" | copyright notice and this permission notice appear in all copies. |\n");
251  log(" | |\n");
252  log(" | THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |\n");
253  log(" | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |\n");
254  log(" | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |\n");
255  log(" | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |\n");
256  log(" | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |\n");
257  log(" | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |\n");
258  log(" | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |\n");
259  log(" | |\n");
260  log(" \\----------------------------------------------------------------------------/\n");
261  log("\n");
262  log(" %s\n", yosys_version_str);
263  log("\n");
264  }
265 
266  if (print_stats)
267  log_hasher = new SHA1;
268 
269  yosys_setup();
270 
271  for (auto &fn : plugin_filenames)
272  load_plugin(fn, {});
273 
274  if (optind == argc && passes_commands.size() == 0 && scriptfile.empty()) {
275  if (!got_output_filename)
276  backend_command = "";
278  }
279 
280  while (optind < argc)
281  run_frontend(argv[optind++], frontend_command, yosys_design, output_filename == "-" ? &backend_command : NULL, NULL);
282 
283  if (!scriptfile.empty()) {
284  if (scriptfile_tcl) {
285 #ifdef YOSYS_ENABLE_TCL
286  if (Tcl_EvalFile(yosys_get_tcl_interp(), scriptfile.c_str()) != TCL_OK)
287  log_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(yosys_get_tcl_interp()));
288 #else
289  log_error("Can't exectue TCL script: this version of yosys is not built with TCL support enabled.\n");
290 #endif
291  } else
292  run_frontend(scriptfile, "script", yosys_design, output_filename == "-" ? &backend_command : NULL, NULL);
293  }
294 
295  for (auto it = passes_commands.begin(); it != passes_commands.end(); it++)
296  run_pass(*it, yosys_design);
297 
298  if (!backend_command.empty())
299  run_backend(output_filename, backend_command, yosys_design);
300 
301  if (print_stats)
302  {
303  std::string hash = log_hasher->final().substr(0, 10);
304  delete log_hasher;
305  log_hasher = nullptr;
306 
307  log_spacer();
308 #ifdef _WIN32
309  log("End of script. Logfile hash: %s\n", hash.c_str());
310 #else
311  struct rusage ru_buffer;
312  getrusage(RUSAGE_SELF, &ru_buffer);
313  log("End of script. Logfile hash: %s, CPU: user %.2fs system %.2fs\n", hash.c_str(),
314  ru_buffer.ru_utime.tv_sec + 1e-6 * ru_buffer.ru_utime.tv_usec,
315  ru_buffer.ru_stime.tv_sec + 1e-6 * ru_buffer.ru_stime.tv_usec);
316 #endif
317  log("%s\n", yosys_version_str);
318 
319  int64_t total_ns = 0;
320  std::set<std::tuple<int64_t, int, std::string>> timedat;
321 
322  for (auto &it : pass_register)
323  if (it.second->call_counter) {
324  total_ns += it.second->runtime_ns + 1;
325  timedat.insert(make_tuple(it.second->runtime_ns + 1, it.second->call_counter, it.first));
326  }
327 
328  int out_count = 0;
329  log("Time spent:");
330  for (auto it = timedat.rbegin(); it != timedat.rend() && out_count < 4; it++, out_count++) {
331  if (out_count >= 2 && (std::get<0>(*it) < 1000000000 || int(100*std::get<0>(*it) / total_ns) < 20)) {
332  log(", ...");
333  break;
334  }
335  log("%s %d%% %dx %s (%d sec)", out_count ? "," : "", int(100*std::get<0>(*it) / total_ns),
336  std::get<1>(*it), std::get<2>(*it).c_str(), int(std::get<0>(*it) / 1000000000));
337  }
338  log("%s\n", out_count ? "" : " no commands executed");
339  }
340 
341 #ifdef YOSYS_ENABLE_COVER
342  if (getenv("YOSYS_COVER_DIR") || getenv("YOSYS_COVER_FILE"))
343  {
344  char filename_buffer[4096];
345  FILE *f;
346 
347  if (getenv("YOSYS_COVER_DIR")) {
348  snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", getenv("YOSYS_COVER_DIR"), getpid());
349  f = fdopen(mkstemps(filename_buffer, 4), "w");
350  } else {
351  snprintf(filename_buffer, 4096, "%s", getenv("YOSYS_COVER_FILE"));
352  f = fopen(filename_buffer, "a+");
353  }
354 
355  if (f == NULL)
356  log_error("Can't create coverage file `%s'.\n", filename_buffer);
357 
358  log("<writing coverage file \"%s\">\n", filename_buffer);
359 
360  for (auto &it : get_coverage_data())
361  fprintf(f, "%-60s %10d %s\n", it.second.first.c_str(), it.second.second, it.first.c_str());
362 
363  fclose(f);
364  }
365 #endif
366 
367  if (call_abort)
368  abort();
369 
370 #ifdef YOSYS_ENABLE_READLINE
371  if (!history_file.empty()) {
372  if (history_offset > 0) {
373  history_truncate_file(history_file.c_str(), 100);
374  append_history(where_history() - history_offset, history_file.c_str());
375  } else
376  write_history(history_file.c_str());
377  }
378 
379  clear_history();
380  HIST_ENTRY **hist_list = history_list();
381  if (hist_list != NULL)
382  free(hist_list);
383 #endif
384 
385  yosys_shutdown();
386 
387  return 0;
388 }
389 
const char * yosys_version_str
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
void free(void *)
RTLIL::Design * yosys_design
Definition: yosys.cc:52
void yosys_setup()
Definition: yosys.cc:339
FILE * log_errfile
Definition: log.cc:39
bool log_time
Definition: log.cc:42
void log_error(const char *format,...)
Definition: log.cc:204
SHA1 * log_hasher
Definition: log.cc:40
YOSYS_NAMESPACE_BEGIN std::vector< FILE * > log_files
Definition: log.cc:37
Definition: sha1.h:28
int log_verbose_level
Definition: log.cc:45
static uint32_t hash(uint32_t x)
Definition: Map.h:38
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
USING_YOSYS_NAMESPACE int main(int argc, char **argv)
Definition: driver.cc:70
#define NULL
void load_plugin(std::string filename, std::vector< std::string > aliases)
Definition: plugin.cc:49
void shell(RTLIL::Design *design)
Definition: yosys.cc:812
void log(const char *format,...)
Definition: log.cc:180
void run_backend(std::string filename, std::string command, RTLIL::Design *design)
Definition: yosys.cc:703
std::map< std::string, Pass * > pass_register
Definition: register.cc:35
void yosys_shutdown()
Definition: yosys.cc:346
std::string final()
Definition: sha1.cpp:69
void run_pass(std::string command, RTLIL::Design *design)
Definition: yosys.cc:696
bool log_quiet_warnings
Definition: log.cc:44
void run_frontend(std::string filename, std::string command, RTLIL::Design *design, std::string *backend_command, std::string *from_to_label)
Definition: yosys.cc:603
void log_spacer()
Definition: log.cc:226