mirror of https://github.com/YosysHQ/nextpnr.git
Improve file open error messages (#1700)
Define open_(o|i)fstream_and_log_error in log.h to: - quote 'filename' - add error cause to easier troubleshoot - use existing consistent string style - easily allows OS specific message Introduce it when file are opened and add it where error message was missing.
This commit is contained in:
parent
28fefe6172
commit
33e1c9033b
|
|
@ -609,13 +609,13 @@ int CommandHandler::executeMain(std::unique_ptr<Context> ctx)
|
|||
try {
|
||||
if (vm.count("json")) {
|
||||
std::string filename = vm["json"].as<std::string>();
|
||||
std::ifstream f(filename);
|
||||
auto f = open_ifstream_and_log_error(filename, "JSON file");
|
||||
if (!parse_json(f, filename, w.getContext()))
|
||||
log_error("Loading design failed.\n");
|
||||
|
||||
if (vm.count("sdc")) {
|
||||
std::string sdc_filename = vm["sdc"].as<std::string>();
|
||||
std::ifstream sdc_stream(sdc_filename);
|
||||
auto sdc_stream = open_ifstream_and_log_error(sdc_filename, "SDC file");
|
||||
w.getContext()->read_sdc(sdc_stream);
|
||||
}
|
||||
|
||||
|
|
@ -635,13 +635,14 @@ int CommandHandler::executeMain(std::unique_ptr<Context> ctx)
|
|||
#endif
|
||||
if (vm.count("json")) {
|
||||
std::string filename = vm["json"].as<std::string>();
|
||||
std::ifstream f(filename);
|
||||
auto f = open_ifstream_and_log_error(filename, "'--json' file");
|
||||
|
||||
if (!parse_json(f, filename, ctx.get()))
|
||||
log_error("Loading design failed.\n");
|
||||
|
||||
if (vm.count("sdc")) {
|
||||
std::string sdc_filename = vm["sdc"].as<std::string>();
|
||||
std::ifstream sdc_stream(sdc_filename);
|
||||
auto sdc_stream = open_ifstream_and_log_error(sdc_filename, "SDC file");
|
||||
ctx->read_sdc(sdc_stream);
|
||||
}
|
||||
|
||||
|
|
@ -703,24 +704,20 @@ int CommandHandler::executeMain(std::unique_ptr<Context> ctx)
|
|||
|
||||
if (vm.count("write")) {
|
||||
std::string filename = vm["write"].as<std::string>();
|
||||
std::ofstream f(filename);
|
||||
auto f = open_ofstream_and_log_error(filename, "JSON '--write' file");
|
||||
if (!write_json_file(f, filename, ctx.get()))
|
||||
log_error("Saving design failed.\n");
|
||||
}
|
||||
|
||||
if (vm.count("sdf")) {
|
||||
std::string filename = vm["sdf"].as<std::string>();
|
||||
std::ofstream f(filename);
|
||||
if (!f)
|
||||
log_error("Failed to open SDF file '%s' for writing.\n", filename.c_str());
|
||||
auto f = open_ofstream_and_log_error(filename, "SDF file");
|
||||
ctx->writeSDF(f, vm.count("sdf-cvc"));
|
||||
}
|
||||
|
||||
if (vm.count("report")) {
|
||||
std::string filename = vm["report"].as<std::string>();
|
||||
std::ofstream f(filename);
|
||||
if (!f)
|
||||
log_error("Failed to open report file '%s' for writing.\n", filename.c_str());
|
||||
auto f = open_ofstream_and_log_error(filename, "report file");
|
||||
ctx->writeJsonReport(f);
|
||||
}
|
||||
|
||||
|
|
@ -778,7 +775,7 @@ void CommandHandler::load_json(Context *ctx, std::string filename)
|
|||
setupContext(ctx);
|
||||
setupArchContext(ctx);
|
||||
{
|
||||
std::ifstream f(filename);
|
||||
auto f = open_ifstream_and_log_error(filename, "JSON file");
|
||||
if (!parse_json(f, filename, ctx))
|
||||
log_error("Loading design failed.\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <cerrno>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
@ -187,6 +188,28 @@ void log_error(const char *format, ...)
|
|||
logv_error(format, ap);
|
||||
}
|
||||
|
||||
std::ifstream open_ifstream_and_log_error(std::string filename, const char *file_description)
|
||||
{
|
||||
std::ifstream file(filename);
|
||||
if (!file.is_open()) {
|
||||
log_error("Failed to open %s '%s': %s.\n", file_description, filename.c_str(),
|
||||
std::error_code(errno, std::generic_category()).message().c_str());
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
std::ofstream open_ofstream_and_log_error(std::string filename, const char *file_description)
|
||||
{
|
||||
std::ofstream file(filename);
|
||||
if (!file.is_open()) {
|
||||
log_error("Failed to open %s '%s' for writing: %s.\n", file_description, filename.c_str(),
|
||||
std::error_code(errno, std::generic_category()).message().c_str());
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
void log_break()
|
||||
{
|
||||
if (log_newline_count < 2)
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -30,6 +30,8 @@
|
|||
#include "hashlib.h"
|
||||
#include "nextpnr_namespaces.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
typedef std::function<void(std::string)> log_write_type;
|
||||
|
|
@ -88,6 +90,12 @@ static inline void log_assert_worker(bool cond, const char *expr, const char *fi
|
|||
|
||||
#define log_abort() log_error("Abort in %s:%d.\n", __FILE__, __LINE__)
|
||||
|
||||
/// open `filename`, if error log "Failed to open {file_description} '{filename}'" with cause
|
||||
std::ifstream open_ifstream_and_log_error(std::string filename, const char *file_description);
|
||||
|
||||
/// open `filename`, if error log "Failed to open {file_description} '{filename}' for writing" with cause
|
||||
std::ofstream open_ofstream_and_log_error(std::string filename, const char *file_description);
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,9 +50,7 @@ bool operator==(const PortRef &a, const PortRef &b) { return (a.cell == b.cell)
|
|||
// Load a JSON file into a design
|
||||
void parse_json_shim(std::string filename, Context &d)
|
||||
{
|
||||
std::ifstream inf(filename);
|
||||
if (!inf)
|
||||
throw std::runtime_error("failed to open file " + filename);
|
||||
auto inf = open_ifstream_and_log_error(filename, "JSON file");
|
||||
parse_json(inf, filename, &d);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ struct SVGWriter
|
|||
|
||||
void Context::writeSVG(const std::string &filename, const std::string &flags) const
|
||||
{
|
||||
std::ofstream out(filename);
|
||||
auto out = open_ofstream_and_log_error(filename, "SVG file");
|
||||
SVGWriter(this, out)(flags);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#define STATIC_UTIL_H
|
||||
|
||||
#include <fstream>
|
||||
#include "log.h"
|
||||
#include "nextpnr_assertions.h"
|
||||
#include "nextpnr_namespaces.h"
|
||||
|
||||
|
|
@ -105,6 +106,10 @@ struct FFTArray
|
|||
void write_csv(const std::string &filename) const
|
||||
{
|
||||
std::ofstream out(filename);
|
||||
if (!out.is_open()) {
|
||||
log_error("Failed to open CSV file for writing '%s': %s.\n", filename.c_str(),
|
||||
std::error_code(errno, std::generic_category()).message().c_str());
|
||||
}
|
||||
NPNR_ASSERT(out);
|
||||
for (int y = 0; y < m_height; y++) {
|
||||
for (int x = 0; x < m_width; x++) {
|
||||
|
|
|
|||
|
|
@ -1718,26 +1718,19 @@ struct Router2
|
|||
if (!cfg.heatmap.empty()) {
|
||||
{
|
||||
std::string filename(cfg.heatmap + "_congestion_by_wiretype_" + std::to_string(iter) + ".csv");
|
||||
std::ofstream cong_map(filename);
|
||||
if (!cong_map)
|
||||
log_error("Failed to open congestion-by-wiretype heatmap %s for writing.\n", filename.c_str());
|
||||
auto cong_map = open_ofstream_and_log_error(filename, "congestion-by-wiretype heatmap");
|
||||
write_congestion_by_wiretype_heatmap(cong_map);
|
||||
log_info(" wrote congestion-by-wiretype heatmap to %s.\n", filename.c_str());
|
||||
}
|
||||
{
|
||||
std::string filename(cfg.heatmap + "_utilisation_by_wiretype_" + std::to_string(iter) + ".csv");
|
||||
std::ofstream cong_map(filename);
|
||||
if (!cong_map)
|
||||
log_error("Failed to open utilisation-by-wiretype heatmap %s for writing.\n", filename.c_str());
|
||||
auto cong_map = open_ofstream_and_log_error(filename, "utilisation-by-wiretype heatmap");
|
||||
write_utilisation_by_wiretype_heatmap(cong_map);
|
||||
log_info(" wrote utilisation-by-wiretype heatmap to %s.\n", filename.c_str());
|
||||
}
|
||||
{
|
||||
std::string filename(cfg.heatmap + "_congestion_by_coordinate_" + std::to_string(iter) + ".csv");
|
||||
std::ofstream cong_map(filename);
|
||||
if (!cong_map)
|
||||
log_error("Failed to open congestion-by-coordinate heatmap %s for writing.\n",
|
||||
filename.c_str());
|
||||
auto cong_map = open_ofstream_and_log_error(filename, "congestion-by-coordinate heatmap");
|
||||
write_congestion_by_coordinate_heatmap(cong_map);
|
||||
log_info(" wrote congestion-by-coordinate heatmap to %s.\n", filename.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1364,10 +1364,7 @@ struct ECP5Bitgen
|
|||
void run(const std::string &base_config_file)
|
||||
{
|
||||
if (!base_config_file.empty()) {
|
||||
std::ifstream config_file(base_config_file);
|
||||
if (!config_file) {
|
||||
log_error("failed to open base config file '%s'\n", base_config_file.c_str());
|
||||
}
|
||||
auto config_file = open_ifstream_and_log_error(base_config_file, "base config file");
|
||||
config_file >> cc;
|
||||
} else {
|
||||
switch (ctx->args.type) {
|
||||
|
|
@ -1599,7 +1596,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
|||
|
||||
// Configure chip
|
||||
if (!text_config_file.empty()) {
|
||||
std::ofstream out_config(text_config_file);
|
||||
auto out_config = open_ofstream_and_log_error(text_config_file, "text config file");
|
||||
out_config << bitgen.cc;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,11 +266,9 @@ void ECP5CommandHandler::customAfterLoad(Context *ctx)
|
|||
if (vm.count("lpf")) {
|
||||
std::vector<std::string> files = vm["lpf"].as<std::vector<std::string>>();
|
||||
for (const auto &filename : files) {
|
||||
std::ifstream in(filename);
|
||||
if (!in)
|
||||
log_error("failed to open LPF file '%s'\n", filename.c_str());
|
||||
auto in = open_ifstream_and_log_error(filename, "LPF file");
|
||||
if (!ctx->apply_lpf(filename, in))
|
||||
log_error("failed to parse LPF file '%s'\n", filename.c_str());
|
||||
log_error("Failed to parse LPF file '%s'\n", filename.c_str());
|
||||
}
|
||||
|
||||
for (auto &cell : ctx->cells) {
|
||||
|
|
|
|||
|
|
@ -213,10 +213,7 @@ struct FabulousImpl : ViaductAPI
|
|||
std::ifstream open_data_rel(const std::string &postfix)
|
||||
{
|
||||
const std::string filename(fab_root + postfix);
|
||||
std::ifstream in(filename);
|
||||
if (!in)
|
||||
log_error("failed to open data file '%s' (is FAB_ROOT set correctly?)\n", filename.c_str());
|
||||
return in;
|
||||
return open_ifstream_and_log_error(filename, "data file (is FAB_ROOT set correctly?)");
|
||||
}
|
||||
|
||||
std::string fab_root;
|
||||
|
|
|
|||
|
|
@ -537,10 +537,7 @@ struct FABulousDesignConstraints
|
|||
|
||||
void apply_constraints()
|
||||
{
|
||||
std::ifstream in(filename);
|
||||
if (!in) {
|
||||
log_error("failed to open constraint file\n");
|
||||
}
|
||||
auto in = open_ifstream_and_log_error(filename, "constraint file");
|
||||
|
||||
std::string line;
|
||||
std::string accumulated_line;
|
||||
|
|
|
|||
|
|
@ -519,9 +519,7 @@ struct BitstreamBackend
|
|||
|
||||
void GateMateImpl::write_bitstream(const std::string &device, const std::string &filename)
|
||||
{
|
||||
std::ofstream out(filename);
|
||||
if (!out)
|
||||
log_error("Failed to open file '%s' for writing (%s).\n", filename.c_str(), strerror(errno));
|
||||
auto out = open_ofstream_and_log_error(filename, "bitstream file");
|
||||
|
||||
BitstreamBackend be(ctx, this, device, out);
|
||||
be.write_bitstream();
|
||||
|
|
|
|||
|
|
@ -411,9 +411,7 @@ struct GateMateCCFReader
|
|||
|
||||
void GateMateImpl::parse_ccf(const std::string &filename)
|
||||
{
|
||||
std::ifstream in(filename);
|
||||
if (!in)
|
||||
log_error("Failed to open CCF file '%s'.\n", filename.c_str());
|
||||
auto in = open_ifstream_and_log_error(filename, "CCF file");
|
||||
GateMateCCFReader reader(ctx, this, in);
|
||||
reader.run();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,10 +267,8 @@ void GowinImpl::pack()
|
|||
{
|
||||
if (ctx->settings.count(ctx->id("cst.filename"))) {
|
||||
std::string filename = ctx->settings[ctx->id("cst.filename")].as_string();
|
||||
std::ifstream in(filename);
|
||||
if (!in) {
|
||||
log_error("failed to open CST file '%s'\n", filename.c_str());
|
||||
}
|
||||
auto in = open_ifstream_and_log_error(filename, "CST file");
|
||||
|
||||
if (!gowin_apply_constraints(ctx, in)) {
|
||||
log_error("failed to parse CST file '%s'\n", filename.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -694,9 +694,7 @@ struct BitstreamJsonBackend
|
|||
|
||||
void NgUltraImpl::write_bitstream_json(const std::string &filename)
|
||||
{
|
||||
std::ofstream out(filename);
|
||||
if (!out)
|
||||
log_error("failed to open file %s for writing (%s)\n", filename.c_str(), strerror(errno));
|
||||
auto out = open_ofstream_and_log_error(filename, "bitstream json file");
|
||||
|
||||
BitstreamJsonBackend be(ctx, this, out);
|
||||
be.write_json();
|
||||
|
|
|
|||
|
|
@ -37,9 +37,7 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||
|
||||
void NgUltraImpl::parse_csv(const std::string &filename)
|
||||
{
|
||||
std::ifstream in(filename);
|
||||
if (!in)
|
||||
log_error("failed to open CSV file '%s'\n", filename.c_str());
|
||||
auto in = open_ifstream_and_log_error(filename, "CSV file");
|
||||
log_info("Parsing CSV file..\n");
|
||||
std::string line;
|
||||
std::string linebuf;
|
||||
|
|
|
|||
|
|
@ -264,8 +264,7 @@ struct FasmBackend
|
|||
boost::erase_all(loc, "_T1");
|
||||
boost::replace_all(loc, "IOI_OLOGIC", "OLOGIC_Y");
|
||||
// the replacements transformed it into : LIOI3_X0Y73.OLOGIC_Y1
|
||||
out << loc << "."
|
||||
<< "ZINV_T1" << std::endl;
|
||||
out << loc << "." << "ZINV_T1" << std::endl;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
@ -1822,9 +1821,7 @@ struct FasmBackend
|
|||
|
||||
void XilinxImpl::write_fasm(const std::string &filename)
|
||||
{
|
||||
std::ofstream out(filename);
|
||||
if (!out)
|
||||
log_error("failed to open file %s for writing (%s)\n", filename.c_str(), strerror(errno));
|
||||
auto out = open_ofstream_and_log_error(filename, "FASM file");
|
||||
|
||||
FasmBackend be(this->ctx, this, out);
|
||||
be.write_fasm();
|
||||
|
|
|
|||
|
|
@ -36,9 +36,7 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||
|
||||
void XilinxImpl::parse_xdc(const std::string &filename)
|
||||
{
|
||||
std::ifstream in(filename);
|
||||
if (!in)
|
||||
log_error("failed to open XDC file '%s'\n", filename.c_str());
|
||||
auto in = open_ifstream_and_log_error(filename, "XDC file");
|
||||
log_info("Parsing XDC file...\n");
|
||||
std::string line;
|
||||
std::string linebuf;
|
||||
|
|
|
|||
|
|
@ -32,9 +32,8 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||
|
||||
static void write_bitstream(const Context *ctx, std::string asc_file)
|
||||
{
|
||||
std::ofstream out(asc_file);
|
||||
if (!out)
|
||||
log_error("Failed to open output file %s\n", asc_file.c_str());
|
||||
auto out = open_ofstream_and_log_error(asc_file, "output file");
|
||||
|
||||
write_asc(ctx, out);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ void Ice40CommandHandler::customAfterLoad(Context *ctx)
|
|||
{
|
||||
if (vm.count("pcf")) {
|
||||
std::string filename = vm["pcf"].as<std::string>();
|
||||
std::ifstream pcf(filename);
|
||||
auto pcf = open_ifstream_and_log_error(filename, "PCF file");
|
||||
if (!apply_pcf(ctx, filename, pcf))
|
||||
log_error("Loading PCF failed.\n");
|
||||
} else {
|
||||
|
|
@ -109,7 +109,7 @@ void Ice40CommandHandler::customBitstream(Context *ctx)
|
|||
{
|
||||
if (vm.count("asc")) {
|
||||
std::string filename = vm["asc"].as<std::string>();
|
||||
std::ofstream f(filename);
|
||||
auto f = open_ofstream_and_log_error(filename, "ASC file");
|
||||
write_asc(ctx, f);
|
||||
}
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ void Ice40CommandHandler::setupArchContext(Context *ctx)
|
|||
|
||||
if (vm.count("read")) {
|
||||
std::string filename = vm["read"].as<std::string>();
|
||||
std::ifstream f(filename);
|
||||
auto f = open_ifstream_and_log_error(filename, "ASC file");
|
||||
if (!read_asc(ctx, f))
|
||||
log_error("Loading ASC failed.\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -797,7 +797,7 @@ void write_bitstream(Context *ctx, std::string text_config_file)
|
|||
|
||||
// Configure chip
|
||||
if (!text_config_file.empty()) {
|
||||
std::ofstream out_config(text_config_file);
|
||||
auto out_config = open_ofstream_and_log_error(text_config_file, "text config file");
|
||||
out_config << bitgen.cc;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,9 +89,7 @@ void MachXO2CommandHandler::customAfterLoad(Context *ctx)
|
|||
if (vm.count("lpf")) {
|
||||
std::vector<std::string> files = vm["lpf"].as<std::vector<std::string>>();
|
||||
for (const auto &filename : files) {
|
||||
std::ifstream in(filename);
|
||||
if (!in)
|
||||
log_error("failed to open LPF file '%s'\n", filename.c_str());
|
||||
auto in = open_ifstream_and_log_error(filename, "LPF file");
|
||||
if (!ctx->apply_lpf(filename, in))
|
||||
log_error("failed to parse LPF file '%s'\n", filename.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <cerrno>
|
||||
#include <fstream>
|
||||
#include "command.h"
|
||||
#include "design_utils.h"
|
||||
|
|
@ -62,8 +63,10 @@ void MistralCommandHandler::customBitstream(Context *ctx)
|
|||
ctx->cyclonev->rbf_save(data);
|
||||
|
||||
std::ofstream out(filename, std::ios::binary);
|
||||
if (!out)
|
||||
log_error("Failed to open output RBF file %s.\n", filename.c_str());
|
||||
if (!out.is_open()) {
|
||||
log_error("Failed to open RBF file '%s' for writing: %s.\n", filename.c_str(),
|
||||
std::error_code(errno, std::generic_category()).message().c_str());
|
||||
}
|
||||
out.write(reinterpret_cast<const char *>(data.data()), data.size());
|
||||
}
|
||||
}
|
||||
|
|
@ -85,9 +88,7 @@ void MistralCommandHandler::customAfterLoad(Context *ctx)
|
|||
{
|
||||
if (vm.count("qsf")) {
|
||||
std::string filename = vm["qsf"].as<std::string>();
|
||||
std::ifstream in(filename);
|
||||
if (!in)
|
||||
log_error("Failed to open input QSF file %s.\n", filename.c_str());
|
||||
auto in = open_ifstream_and_log_error(filename, "input QSF file");
|
||||
ctx->read_qsf(in);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,9 +62,7 @@ void NexusCommandHandler::customBitstream(Context *ctx)
|
|||
{
|
||||
if (vm.count("fasm")) {
|
||||
std::string filename = vm["fasm"].as<std::string>();
|
||||
std::ofstream out(filename);
|
||||
if (!out)
|
||||
log_error("Failed to open output FASM file %s.\n", filename.c_str());
|
||||
auto out = open_ofstream_and_log_error(filename, "output FASM file");
|
||||
ctx->write_fasm(out);
|
||||
}
|
||||
}
|
||||
|
|
@ -101,9 +99,7 @@ void NexusCommandHandler::customAfterLoad(Context *ctx)
|
|||
{
|
||||
if (vm.count("pdc")) {
|
||||
std::string filename = vm["pdc"].as<std::string>();
|
||||
std::ifstream in(filename);
|
||||
if (!in)
|
||||
log_error("Failed to open input PDC file %s.\n", filename.c_str());
|
||||
auto in = open_ifstream_and_log_error(filename, "input PDC file");
|
||||
ctx->read_pdc(in);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue