HAL
netlist_parser_manager.cpp
Go to the documentation of this file.
2 
9 
10 #include <fstream>
11 
12 namespace hal
13 {
14  namespace netlist_parser_manager
15  {
16  namespace
17  {
18  std::unordered_map<std::string, std::vector<std::string>> m_parser_to_extensions;
19  std::unordered_map<std::string, std::pair<std::string, ParserFactory>> m_extension_to_parser;
20 
21  ParserFactory get_parser_factory_for_file(const std::filesystem::path& file_name)
22  {
23  std::string extension = utils::to_lower(file_name.extension().string());
24  if (!extension.empty() && extension[0] != '.')
25  {
26  extension = "." + extension;
27  }
28 
29  if (auto it = m_extension_to_parser.find(extension); it != m_extension_to_parser.end())
30  {
31  log_info("netlist_parser", "selected parser: {}", it->second.first);
32  return it->second.second;
33  }
34 
35  log_error("netlist_parser", "no netlist parser registered for file type '{}'", extension);
36  return ParserFactory();
37  }
38 
39  std::vector<std::unique_ptr<Netlist>>
40  dispatch_parse(const std::filesystem::path& file_name, std::unique_ptr<NetlistParser> parser, const GateLibrary* gate_library = nullptr, bool break_on_match = true)
41  {
42  auto begin_time = std::chrono::high_resolution_clock::now();
43 
44  log_info("netlist_parser", "parsing '{}'...", file_name.string());
45 
46  if (auto res = parser->parse(file_name); res.is_error())
47  {
48  log_error("netlist_parser", "failed to parse '{}':\n{}", file_name.string(), res.get_error().get());
49  return {};
50  }
51 
52  log_info("netlist_parser",
53  "finished parsing in {:2.2f} seconds.",
54  (double)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - begin_time).count() / 1000);
55 
56  std::vector<std::unique_ptr<Netlist>> netlists;
57 
58  if (gate_library != nullptr)
59  {
60  begin_time = std::chrono::high_resolution_clock::now();
61 
62  log_info("netlist_parser", "instantiating '{}' with gate library '{}'...", file_name.string(), gate_library->get_name());
63 
64  if (auto res = parser->instantiate(gate_library); res.is_error())
65  {
66  log_info("netlist_parser", "failed to instantiate '{}' with gate library '{}':\n{}", file_name.string(), gate_library->get_name(), res.get_error().get());
67  return {};
68  }
69  else
70  {
71  auto netlist = res.get();
72  netlist->set_input_filename(file_name.string());
73 
74  log_info("netlist_parser",
75  "instantiated '{}' in {:2.2f} seconds.",
76  file_name.string(),
77  (double)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - begin_time).count() / 1000);
78 
79  netlists.push_back(std::move(netlist));
80  }
81  }
82  else
83  {
84  log_warning("netlist_parser", "no (valid) gate library specified, trying to auto-detect gate library...");
86 
88  {
89  begin_time = std::chrono::high_resolution_clock::now();
90 
91  log_info("netlist_parser", "instantiating '{}' with gate library '{}'...", file_name.string(), lib_it->get_name());
92 
93  if (auto res = parser->instantiate(lib_it); res.is_error())
94  {
95  log_info("netlist_parser", "failed to instantiate '{}' with gate library '{}':\n{}", file_name.string(), lib_it->get_name(), res.get_error().get());
96  // log_debug("netlist_parser", "error encountered during netlist instantiation:\n{}", res.get_error().get());
97  continue;
98  }
99  else
100  {
101  auto netlist = res.get();
102 
103  netlist->set_input_filename(file_name.string());
104 
105  log_info("netlist_parser",
106  "instantiated '{}' in {:2.2f} seconds.",
107  file_name.string(),
108  (double)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - begin_time).count() / 1000);
109 
110  netlists.push_back(std::move(netlist));
111 
112  if (break_on_match)
113  {
114  break;
115  }
116  }
117  }
118 
119  if (netlists.empty())
120  {
121  log_error("netlist_parser", "could not find suitable gate library.");
122  return {};
123  }
124  }
125 
126  return netlists;
127  }
128  } // namespace
129 
131  {
132  return ProgramOptions();
133  }
134 
135  bool can_parse(const std::filesystem::path& file_name)
136  {
137  std::string extension = utils::to_lower(file_name.extension().string());
138  if (!extension.empty() && extension[0] != '.')
139  {
140  extension = "." + extension;
141  }
142 
143  if (extension == ".hal") return true;
144 
145  return (m_extension_to_parser.find(extension) != m_extension_to_parser.end());
146  }
147 
148  void register_parser(const std::string& name, const ParserFactory& parser_factory, const std::vector<std::string>& supported_file_extensions)
149  {
150  for (auto ext : supported_file_extensions)
151  {
152  ext = utils::trim(utils::to_lower(ext));
153  if (!ext.empty() && ext[0] != '.')
154  {
155  ext = "." + ext;
156  }
157  if (auto it = m_extension_to_parser.find(ext); it != m_extension_to_parser.end())
158  {
159  log_warning("netlist_parser", "file type '{}' already has associated parser '{}', it remains unchanged", ext, it->second.first);
160  continue;
161  }
162  m_extension_to_parser.emplace(ext, std::make_pair(name, parser_factory));
163  m_parser_to_extensions[name].push_back(ext);
164 
165  log_info("netlist_parser", "registered netlist parser '{}' for file type '{}'", name, ext);
166  }
167  }
168 
169  void unregister_parser(const std::string& name)
170  {
171  if (auto it = m_parser_to_extensions.find(name); it != m_parser_to_extensions.end())
172  {
173  for (const auto& ext : it->second)
174  {
175  if (auto rm_it = m_extension_to_parser.find(ext); rm_it != m_extension_to_parser.end())
176  {
177  m_extension_to_parser.erase(rm_it);
178  log_info("netlist_parser", "unregistered netlist parser '{}' which was registered for file type '{}'", name, ext);
179  }
180  }
181  m_parser_to_extensions.erase(it);
182  }
183  }
184 
185  std::unique_ptr<Netlist> parse(const std::filesystem::path& file_name, const ProgramArguments& args)
186  {
187  ParserFactory factory = get_parser_factory_for_file(file_name);
188  if (!factory)
189  {
190  return nullptr;
191  }
192 
193  const GateLibrary* gate_library = nullptr;
194 
195  if (args.is_option_set("--gate-library"))
196  {
197  std::string gate_library_file = args.get_parameter("--gate-library");
198  gate_library = gate_library_manager::get_gate_library(gate_library_file);
199  if (gate_library == nullptr)
200  {
201  log_error("netlist_parser", "invalid gate library '{}' specified by user.", gate_library_file);
202  return nullptr;
203  }
204  }
205 
206  return parse(file_name, gate_library);
207  }
208 
209  std::unique_ptr<Netlist> parse(const std::filesystem::path& file_name, const GateLibrary* gate_library)
210  {
211  ParserFactory factory = get_parser_factory_for_file(file_name);
212  if (!factory)
213  {
214  return nullptr;
215  }
216 
217  std::vector<std::unique_ptr<Netlist>> netlists = dispatch_parse(file_name, factory(), gate_library);
218 
219  if (netlists.empty())
220  {
221  return nullptr;
222  }
223 
224  return std::move(netlists.at(0));
225  }
226 
227  std::vector<std::unique_ptr<Netlist>> parse_all(const std::filesystem::path& file_name)
228  {
229  ParserFactory factory = get_parser_factory_for_file(file_name);
230  if (!factory)
231  {
232  return {};
233  }
234 
235  return dispatch_parse(file_name, factory(), nullptr, false);
236  }
237 
238  std::unordered_map<std::string, std::vector<std::string>> get_parser_to_extensions()
239  {
240  return m_parser_to_extensions;
241  }
242 
243  } // namespace netlist_parser_manager
244 } // namespace hal
#define log_error(channel,...)
Definition: log.h:78
#define log_info(channel,...)
Definition: log.h:70
#define log_warning(channel,...)
Definition: log.h:76
parser
Definition: control.py:13
std::vector< GateLibrary * > get_gate_libraries()
GateLibrary * get_gate_library(const std::string &file_path)
void unregister_parser(const std::string &name)
std::unordered_map< std::string, std::vector< std::string > > get_parser_to_extensions()
std::function< std::unique_ptr< NetlistParser >()> ParserFactory
bool can_parse(const std::filesystem::path &file_name)
void register_parser(const std::string &name, const ParserFactory &parser_factory, const std::vector< std::string > &supported_file_extensions)
std::unique_ptr< Netlist > parse(const std::filesystem::path &file_name, const ProgramArguments &args)
std::vector< std::unique_ptr< Netlist > > parse_all(const std::filesystem::path &file_name)
CORE_API T trim(const T &s, const char *to_remove=" \t\r\n")
Definition: utils.h:358
CORE_API T to_lower(const T &s)
Definition: utils.h:477
std::string name