HAL  v4.5.0-124-g47ab54673
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
gate_library_manager.cpp
Go to the documentation of this file.
2 
8 
9 #include <iostream>
10 
11 namespace hal
12 {
13  namespace gate_library_manager
14  {
15  namespace
16  {
17  std::map<std::filesystem::path, std::shared_ptr<GateLibrary>> m_gate_libraries;
18 
19  Result<std::monostate> prepare_library(const std::shared_ptr<GateLibrary>& lib)
20  {
21  auto gate_types = lib->get_gate_types();
22 
23  for (const auto& [gt_name, gt] : gate_types)
24  {
25  if (gt->has_property(GateTypeProperty::power))
26  {
27  lib->mark_vcc_gate_type(gt);
28  }
29  if (gt->has_property(GateTypeProperty::ground))
30  {
31  lib->mark_gnd_gate_type(gt);
32  }
33  }
34 
35  if (lib->get_gnd_gate_types().empty())
36  {
37  std::string name = "HAL_GND";
38  if (gate_types.find(name) != gate_types.end())
39  {
40  return ERR("could not prepare gate library '" + lib->get_name() + "': no GND gate type found within gate library, but gate type 'HAL_GND' already exists");
41  }
42 
43  GateType* gt = lib->create_gate_type(name, {GateTypeProperty::combinational, GateTypeProperty::ground});
44  if (auto res = gt->create_pin("O", PinDirection::output, PinType::ground); res.is_error())
45  {
46  return ERR_APPEND(res.get_error(), "could not prepare gate library '" + lib->get_name() + "': failed to create output pin 'O' for gate type 'HAL_GND'");
47  }
48  gt->add_boolean_function("O", BooleanFunction::Const(BooleanFunction::Value::ZERO));
49  lib->mark_gnd_gate_type(gt);
50  log_info("gate_library_manager", "gate library did not contain a GND gate, auto-generated type '{}'.", name);
51  }
52 
53  if (lib->get_vcc_gate_types().empty())
54  {
55  std::string name = "HAL_VDD";
56  if (gate_types.find(name) != gate_types.end())
57  {
58  return ERR("could not prepare gate library '" + lib->get_name() + "': no VDD gate type found within gate library, but gate type 'HAL_VDD' already exists");
59  }
60 
61  GateType* gt = lib->create_gate_type(name, {GateTypeProperty::combinational, GateTypeProperty::power});
62  if (auto res = gt->create_pin("O", PinDirection::output, PinType::power); res.is_error())
63  {
64  return ERR_APPEND(res.get_error(), "could not prepare gate library '" + lib->get_name() + "': failed to create output pin 'O' for gate type 'HAL_VDD'");
65  }
66  gt->add_boolean_function("O", BooleanFunction::Const(BooleanFunction::Value::ONE));
67  lib->mark_vcc_gate_type(gt);
68  log_info("gate_library_manager", "gate library did not contain a VDD gate, auto-generated type '{}'.", name);
69  }
70 
71  return OK({});
72  }
73  } // namespace
74 
75  GateLibrary* load(std::filesystem::path file_path, bool reload)
76  {
77  if (!std::filesystem::exists(file_path))
78  {
79  log_error("gate_library_manager", "gate library file '{}' does not exist.", file_path.string());
80  return nullptr;
81  }
82 
83  if (!file_path.is_absolute())
84  {
85  file_path = std::filesystem::absolute(file_path);
86  }
87 
88  if (!reload)
89  {
90  if (auto it = m_gate_libraries.find(file_path); it != m_gate_libraries.end())
91  {
92  log_info("gate_library_parser", "the gate library file '{}' is already loaded.", file_path.string());
93  return it->second.get();
94  }
95  }
96 
97  std::shared_ptr<GateLibrary> gate_lib = gate_library_parser_manager::parse(file_path);
98  if (gate_lib == nullptr)
99  {
100  return nullptr;
101  }
102 
103  if (auto res = prepare_library(gate_lib); res.is_error())
104  {
105  log_error("gate_library_parser", "error encountered while loading gate library:\n{}", res.get_error().get());
106  return nullptr;
107  }
108 
109  GateLibrary* res = gate_lib.get();
110  m_gate_libraries[file_path.string()] = std::move(gate_lib);
111  return res;
112  }
113 
114  void load_all(bool reload)
115  {
116  std::vector<std::filesystem::path> lib_dirs = utils::get_gate_library_directories();
117 
118  for (const auto& lib_dir : lib_dirs)
119  {
120  if (!std::filesystem::exists(lib_dir))
121  {
122  continue;
123  }
124 
125  log_info("gate_library_manager", "loading all gate library files from {}.", lib_dir.string());
126 
127  for (const auto& lib_path : utils::RecursiveDirectoryRange(lib_dir))
128  {
129  load(lib_path.path(), reload);
130  }
131  }
132  }
133 
134  std::vector<std::filesystem::path> get_all_path()
135  {
136  std::vector<std::filesystem::path> retval;
137  for (const auto& lib_dir : utils::get_gate_library_directories())
138  {
139  if (!std::filesystem::exists(lib_dir))
140  continue;
141  for (const auto& lib_path : utils::RecursiveDirectoryRange(lib_dir))
142  retval.push_back(lib_path.path());
143  }
144  return retval;
145  }
146 
147  bool save(std::filesystem::path file_path, GateLibrary* gate_lib, bool overwrite)
148  {
149  if (std::filesystem::exists(file_path))
150  {
151  if (overwrite)
152  {
153  log_info("gate_library_manager", "gate library file '{}' already exists and will be overwritten.", file_path.string());
154  }
155  else
156  {
157  log_error("gate_library_manager", "gate library file '{}' already exists, aborting.", file_path.string());
158  return false;
159  }
160  }
161 
162  if (!file_path.is_absolute())
163  {
164  file_path = std::filesystem::absolute(file_path);
165  }
166 
167  return gate_library_writer_manager::write(gate_lib, file_path);
168  }
169 
170  std::shared_ptr<GateLibrary> get_owning(const GateLibrary* gate_lib)
171  {
172  // A reload replaces the entry of a library in the map, which destroys the library that was
173  // there before. Anything still using it - a loaded netlist above all - has to keep it alive,
174  // so hand out the owning pointer rather than the raw one.
175  for (const auto& [path, lib] : m_gate_libraries)
176  {
177  UNUSED(path);
178  if (lib.get() == gate_lib)
179  {
180  return lib;
181  }
182  }
183 
184  // not managed here, for instance a library a test built itself: refer to it without owning it
185  return std::shared_ptr<GateLibrary>(const_cast<GateLibrary*>(gate_lib), [](GateLibrary*) {});
186  }
187 
188  void remove(std::filesystem::path file_path)
189  {
190  m_gate_libraries.erase(file_path);
191  }
192 
193  GateLibrary* get_gate_library(const std::string& file_path)
194  {
195  std::filesystem::path absolute_path;
196 
197  if (std::filesystem::exists(file_path))
198  {
199  // if an existing file is queried, load it by its absolute path
200  absolute_path = std::filesystem::absolute(file_path);
201  }
202  else
203  {
204  // if a non existing file is queried, search for it in the standard directories
205  auto stripped_name = std::filesystem::path(file_path).filename();
206  log_info("gate_library_manager", "file '{}' does not exist, searching for '{}' in the default gate library directories...", file_path, stripped_name.string());
207 
208  auto lib_path = utils::get_file(stripped_name, utils::get_gate_library_directories());
209  if (lib_path.empty())
210  {
211  log_info("gate_library_manager", "could not find gate library file '{}'.", stripped_name.string());
212  return nullptr;
213  }
214  absolute_path = std::filesystem::absolute(lib_path);
215  }
216 
217  // absolute path to file is known, check if it is already loaded
218  if (auto it = m_gate_libraries.find(absolute_path.string()); it != m_gate_libraries.end())
219  {
220  return it->second.get();
221  }
222 
223  // not loaded yet -> load
224  return load(absolute_path);
225  }
226 
227  GateLibrary* get_gate_library_by_name(const std::string& lib_name)
228  {
229  for (const auto& it : m_gate_libraries)
230  {
231  if (it.second->get_name() == lib_name)
232  {
233  return it.second.get();
234  }
235  }
236  return nullptr;
237  }
238 
239  std::vector<GateLibrary*> get_gate_libraries()
240  {
241  std::vector<GateLibrary*> res;
242  res.reserve(m_gate_libraries.size());
243  for (const auto& it : m_gate_libraries)
244  {
245  res.push_back(it.second.get());
246  }
247  return res;
248  }
249  } // namespace gate_library_manager
250 } // namespace hal
static BooleanFunction Const(const BooleanFunction::Value &value)
#define UNUSED(expr)
Definition: defines.h:49
#define log_error(channel,...)
Definition: log.h:78
#define log_info(channel,...)
Definition: log.h:70
#define ERR(message)
Definition: result.h:60
#define OK(...)
Definition: result.h:56
#define ERR_APPEND(prev_error, message)
Definition: result.h:64
GateLibrary * load(std::filesystem::path file_path, bool reload=false)
std::shared_ptr< GateLibrary > get_owning(const GateLibrary *gate_lib)
std::vector< GateLibrary * > get_gate_libraries()
std::vector< std::filesystem::path > get_all_path()
void remove(std::filesystem::path file_path)
GateLibrary * get_gate_library_by_name(const std::string &lib_name)
void load_all(bool reload=false)
bool save(std::filesystem::path file_path, GateLibrary *gate_lib, bool overwrite=false)
GateLibrary * get_gate_library(const std::string &file_path)
std::unique_ptr< GateLibrary > parse(std::filesystem::path file_path)
bool write(const GateLibrary *gate_lib, const std::filesystem::path &file_path)
std::filesystem::path get_file(std::string file_name, std::vector< std::filesystem::path > path_hints)
Definition: utils.cpp:220
std::vector< std::filesystem::path > get_gate_library_directories()
Definition: utils.cpp:186
Definition: defines.h:45
std::string name