HAL  v4.5.0-232-g8053ac4b3
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
netlist_serializer.cpp
Go to the documentation of this file.
2 
7 #include "hal_core/netlist/net.h"
10 #include "hal_core/utilities/log.h"
11 #include "rapidjson/filereadstream.h"
12 #include "rapidjson/stringbuffer.h"
13 
14 #define PRETTY_JSON_OUTPUT false
15 #if PRETTY_JSON_OUTPUT
16 #include "rapidjson/prettywriter.h"
17 #else
18 #include "rapidjson/writer.h"
19 #endif
20 
21 #include <chrono>
22 #include <fstream>
23 #include <queue>
24 #include <sstream>
25 
26 #ifndef DURATION
27 #define DURATION(begin_time) ((double)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - begin_time).count() / 1000)
28 #endif
29 
30 namespace hal
31 {
32  namespace netlist_serializer
33  {
34  // serializing functions
35  namespace
36  {
37  const int SERIALIZATION_FORMAT_VERSION = 14;
38  int encoded_format_version;
39 
40  // Ver 12 : location of gates
41 #define JSON_STR_HELPER(x) rapidjson::Value{}.SetString(x.c_str(), x.length(), allocator)
42 
43 #define assert_availablility(MEMBER) \
44  if (!root.HasMember(MEMBER)) \
45  { \
46  log_critical("netlist_persistent", "'netlist' node does not include a '{}' node", MEMBER); \
47  return nullptr; \
48  }
49 
50  namespace
51  {
52  struct PinGroupInformation
53  {
54  struct PinInformation
55  {
56  i32 id = -1;
57  Net* net;
58  std::string name;
60  };
61 
62  i32 id = -1;
63  std::string name;
66  std::vector<PinInformation> pins;
67  bool ascending = false;
69  bool ordered = false;
70  };
71 
72  } // namespace
73 
74  // serialize container data
75  rapidjson::Value serialize(const std::map<std::tuple<std::string, std::string>, std::tuple<std::string, std::string>>& data, rapidjson::Document::AllocatorType& allocator)
76  {
77  rapidjson::Value val(rapidjson::kArrayType);
78  for (const auto& it : data)
79  {
80  rapidjson::Value entry(rapidjson::kArrayType);
81  entry.PushBack(JSON_STR_HELPER(std::get<0>(it.first)), allocator);
82  entry.PushBack(JSON_STR_HELPER(std::get<1>(it.first)), allocator);
83  entry.PushBack(JSON_STR_HELPER(std::get<0>(it.second)), allocator);
84  entry.PushBack(JSON_STR_HELPER(std::get<1>(it.second)), allocator);
85  val.PushBack(entry, allocator);
86  }
87  return val;
88  }
89 
90  void deserialize_data(DataContainer* c, const rapidjson::Value& val)
91  {
92  for (const auto& entry : val.GetArray())
93  {
94  c->set_data(entry[0].GetString(), entry[1].GetString(), entry[2].GetString(), entry[3].GetString());
95  }
96  }
97 
98  // serialize parameters
99  rapidjson::Value serialize_parameters(const std::unordered_map<std::string, std::pair<Parameter, std::string>>& params, rapidjson::Document::AllocatorType& allocator)
100  {
101  rapidjson::Value out(rapidjson::kObjectType);
102  for (const auto& [pname, decl_and_value] : params)
103  {
104  const auto& [decl, pvalue] = decl_and_value;
105  rapidjson::Value entry(rapidjson::kObjectType);
106  const std::string type_str = enum_to_string<Parameter::Type>(decl.get_type());
107  entry.AddMember("type", JSON_STR_HELPER(type_str), allocator);
108  entry.AddMember("size", static_cast<u32>(decl.get_size()), allocator);
109  entry.AddMember("default", JSON_STR_HELPER(decl.get_default_value()), allocator);
110  if (decl.get_type() == Parameter::Type::Enum)
111  {
112  rapidjson::Value enum_values(rapidjson::kArrayType);
113  for (const auto& v : decl.get_enum_values())
114  {
115  enum_values.PushBack(JSON_STR_HELPER(v), allocator);
116  }
117  entry.AddMember("enum_values", enum_values, allocator);
118  }
119  entry.AddMember("value", JSON_STR_HELPER(pvalue), allocator);
120  out.AddMember(JSON_STR_HELPER(pname), entry, allocator);
121  }
122  return out;
123  }
124 
125  // Reconstruct a Parameter declaration from a serialized JSON entry.
126  // Returns OK with the declaration on success, an error describing what was wrong otherwise.
127  Result<Parameter> deserialize_parameter_decl(const std::string& name, const rapidjson::Value& entry)
128  {
129  if (!entry.HasMember("type") || !entry.HasMember("value"))
130  {
131  return ERR("parameter '" + name + "' is missing 'type' or 'value'");
132  }
133  const std::string type_str = entry["type"].GetString();
134  if (!is_valid_enum<Parameter::Type>(type_str))
135  {
136  return ERR("parameter '" + name + "' has unknown type '" + type_str + "'");
137  }
138  const Parameter::Type ptype = enum_from_string<Parameter::Type>(type_str);
139  const std::string default_value = (entry.HasMember("default") && entry["default"].IsString()) ? entry["default"].GetString() : std::string{};
140  switch (ptype)
141  {
143  return Parameter::Boolean(name, default_value);
144  }
146  const u16 size = (entry.HasMember("size") && entry["size"].IsUint()) ? static_cast<u16>(entry["size"].GetUint()) : 0;
147  return Parameter::BitVector(name, size, default_value);
148  }
150  const u16 size = (entry.HasMember("size") && entry["size"].IsUint()) ? static_cast<u16>(entry["size"].GetUint()) : 0;
151  return Parameter::LogicVector(name, size, default_value);
152  }
154  return Parameter::Integer(name, default_value);
155  }
157  return Parameter::String(name, default_value);
158  }
159  case Parameter::Type::Float: {
160  return Parameter::Float(name, default_value);
161  }
162  case Parameter::Type::Time: {
163  return Parameter::Time(name, default_value);
164  }
165  case Parameter::Type::Enum: {
166  std::vector<std::string> values;
167  if (entry.HasMember("enum_values") && entry["enum_values"].IsArray())
168  {
169  for (const auto& v : entry["enum_values"].GetArray())
170  {
171  if (!v.IsString())
172  {
173  return ERR("parameter '" + name + "' has non-string entry in 'enum_values'");
174  }
175  values.emplace_back(v.GetString());
176  }
177  }
178  return Parameter::Enum(name, values, default_value);
179  }
180  }
181  return ERR("parameter '" + name + "' has unhandled type");
182  }
183 
184  // Deserialize the contents of a "parameters" JSON object into a DataContainer.
185  // For each entry, reconstructs the declaration and stores the value via set_parameter.
186  Result<std::monostate> deserialize_parameters(DataContainer* c, const rapidjson::Value& val)
187  {
188  for (auto p_it = val.MemberBegin(); p_it != val.MemberEnd(); ++p_it)
189  {
190  const std::string pname = p_it->name.GetString();
191  auto decl_res = deserialize_parameter_decl(pname, p_it->value);
192  if (decl_res.is_error())
193  {
194  return ERR(decl_res.get_error().get());
195  }
196  if (auto res = c->set_parameter(decl_res.get(), p_it->value["value"].GetString()); res.is_error())
197  {
198  return ERR("failed to set parameter '" + pname + "': " + res.get_error().get());
199  }
200  }
201  return OK({});
202  }
203 
204  // serialize endpoint
205  rapidjson::Value serialize(const Endpoint* ep, rapidjson::Document::AllocatorType& allocator)
206  {
207  rapidjson::Value val(rapidjson::kObjectType);
208  val.AddMember("gate_id", ep->get_gate()->get_id(), allocator);
209  val.AddMember("pin_id", ep->get_pin()->get_id(), allocator);
210  return val;
211  }
212 
213  bool deserialize_destination(Netlist* nl, Net* net, const rapidjson::Value& val)
214  {
215  Gate* gate = nl->get_gate_by_id(val["gate_id"].GetUint());
216  GatePin* pin;
217 
218  if (val.HasMember("pin_id"))
219  {
220  const u32 pin_id = val["pin_id"].GetUint();
221  pin = gate->get_type()->get_pin_by_id(pin_id);
222  if (pin == nullptr)
223  {
224  log_error("netlist_persistent",
225  "could not deserialize destination of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": failed to get pin with ID "
226  + std::to_string(pin_id));
227  return false;
228  }
229 
230  if (encoded_format_version <= 12)
231  {
232  // swap pins because of legacy pin group bug
233  if (const auto [group, index] = pin->get_group(); group->size() > 1)
234  {
235  bool ascending = group->is_ascending();
236  u32 len = group->size();
237  i32 start_index = group->get_start_index();
238  i32 end_index = ascending ? (start_index + (i32)len - 1) : (start_index - (i32)len + 1);
239  i32 target_index = ascending ? (end_index - (index - start_index)) : (end_index + (start_index - index));
240 
241  if (const auto pin_res = group->get_pin_at_index(target_index); pin_res.is_error())
242  {
243  log_error("netlist_persistent",
244  "could not deserialize destination of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": failed to swap pin with ID "
245  + std::to_string(pin_id) + ":\n{}",
246  pin_res.get_error().get());
247  return false;
248  }
249  else
250  {
251  pin = pin_res.get();
252  }
253  }
254  }
255  }
256  else
257  {
258  // legacy code for backward compatibility
259  const std::string pin_name = val["pin_type"].GetString();
260  pin = gate->get_type()->get_pin_by_name(pin_name);
261  if (pin == nullptr)
262  {
263  log_error("netlist_persistent",
264  "could not deserialize destination of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": failed to get pin with name '" + pin_name + "'");
265  return false;
266  }
267  }
268 
269  if (!net->add_destination(gate, pin))
270  {
271  log_error("netlist_persistent",
272  "could not deserialize destination of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": failed to add pin '" + pin->get_name()
273  + "' as destination to net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()));
274  return false;
275  }
276  return true;
277  }
278 
279  bool deserialize_source(Netlist* nl, Net* net, const rapidjson::Value& val)
280  {
281  Gate* gate = nl->get_gate_by_id(val["gate_id"].GetUint());
282  GatePin* pin;
283 
284  if (val.HasMember("pin_id"))
285  {
286  const u32 pin_id = val["pin_id"].GetUint();
287  pin = gate->get_type()->get_pin_by_id(pin_id);
288  if (pin == nullptr)
289  {
290  log_error("netlist_persistent",
291  "could not deserialize source of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": failed to get pin with ID " + std::to_string(pin_id));
292  return false;
293  }
294 
295  if (encoded_format_version <= 12)
296  {
297  // swap pins because of legacy pin group bug
298  if (const auto [group, index] = pin->get_group(); group->size() > 1)
299  {
300  bool ascending = group->is_ascending();
301  u32 len = group->size();
302  i32 start_index = group->get_start_index();
303  i32 end_index = ascending ? (start_index + (i32)len - 1) : (start_index - (i32)len + 1);
304  i32 target_index = ascending ? (end_index - (index - start_index)) : (end_index + (start_index - index));
305 
306  if (const auto pin_res = group->get_pin_at_index(target_index); pin_res.is_error())
307  {
308  log_error("netlist_persistent",
309  "could not deserialize source of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": failed to swap pin with ID "
310  + std::to_string(pin_id) + ":\n{}",
311  pin_res.get_error().get());
312  return false;
313  }
314  else
315  {
316  pin = pin_res.get();
317  }
318  }
319  }
320  }
321  else
322  {
323  // legacy code for backward compatibility
324  const std::string pin_name = val["pin_type"].GetString();
325  pin = gate->get_type()->get_pin_by_name(pin_name);
326  if (pin == nullptr)
327  {
328  log_error("netlist_persistent",
329  "could not deserialize source of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": failed to get pin with name '" + pin_name + "'");
330  return false;
331  }
332  }
333 
334  if (net->add_source(gate, pin) == nullptr)
335  {
336  log_error("netlist_persistent",
337  "could not deserialize source of net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()) + ": failed to add pin '" + pin->get_name()
338  + "' as source to net '" + net->get_name() + "' with ID " + std::to_string(net->get_id()));
339  return false;
340  }
341  return true;
342  }
343 
344  // serialize gate
345  rapidjson::Value serialize(const Gate* gate, rapidjson::Document::AllocatorType& allocator)
346  {
347  rapidjson::Value val(rapidjson::kObjectType);
348  val.AddMember("id", gate->get_id(), allocator);
349  val.AddMember("name", gate->get_name(), allocator);
350  val.AddMember("type", gate->get_type()->get_name(), allocator);
351  if (gate->has_location())
352  {
353  val.AddMember("location_x", gate->get_location_x(), allocator);
354  val.AddMember("location_y", gate->get_location_y(), allocator);
355  }
356  auto data = serialize(gate->get_data_map(), allocator);
357  if (!data.Empty())
358  {
359  val.AddMember("data", data, allocator);
360  }
361  if (const auto& params = gate->get_parameters(); !params.empty())
362  {
363  val.AddMember("parameters", serialize_parameters(params, allocator), allocator);
364  }
365  {
366  rapidjson::Value functions(rapidjson::kObjectType);
367  for (const auto& [name, function] : gate->get_boolean_functions(true))
368  {
369  const std::string function_str = function.to_string();
370  functions.AddMember(JSON_STR_HELPER(name), JSON_STR_HELPER(function_str), allocator);
371  }
372  if (functions.MemberCount() > 0)
373  {
374  val.AddMember("custom_functions", functions, allocator);
375  }
376  }
377  return val;
378  }
379 
380  // Migrate "generic" data entries (old .hal format) to typed parameters.
381  // Old parsers stored values as: "bit_vector" → unprefixed uppercase hex ("CAFE"),
382  // "bit_value"/"std_logic" → single state char ("X", "0"). New format uses prefixes.
383  void migrate_generic_data_to_parameters(DataContainer* c, const GateType* gate_type = nullptr)
384  {
385  std::vector<std::pair<std::string, std::string>> to_delete;
386 
387  for (const auto& [key_tuple, value_tuple] : c->get_data_map())
388  {
389  if (std::get<0>(key_tuple) != "generic")
390  continue;
391 
392  const std::string& name = std::get<1>(key_tuple);
393  const std::string& type_str = std::get<0>(value_tuple);
394  const std::string& raw_value = std::get<1>(value_tuple);
395 
396  std::string migrated_value = raw_value;
397  Result<Parameter> inferred_decl = ERR("unrecognized data type '" + type_str + "'");
398  bool skip = false;
399 
400  if (type_str == "boolean")
401  {
402  inferred_decl = Parameter::Boolean(name, "");
403  }
404  else if (type_str == "integer")
405  {
406  inferred_decl = Parameter::Integer(name, "");
407  }
408  else if (type_str == "floating_point")
409  {
410  inferred_decl = Parameter::Float(name, "");
411  }
412  else if (type_str == "time")
413  {
414  inferred_decl = Parameter::Time(name, "");
415  }
416  else if (type_str == "string")
417  {
418  inferred_decl = Parameter::String(name, "");
419  }
420  else if (type_str == "bit_value" || type_str == "std_logic")
421  {
422  // Old format: single char ('0', '1', 'X', ...); new: "0b0", "0bX"
423  const bool already_prefixed = raw_value.size() >= 3 && raw_value[0] == '0'
424  && (raw_value[1] == 'b' || raw_value[1] == 'B');
425  const char bit_char = already_prefixed ? raw_value[2]
426  : (raw_value.empty() ? '\0' : raw_value[0]);
427  if (bit_char == '\0')
428  {
429  log_warning("netlist_persistent", "skipping migration of generic data entry '{}': empty value", name);
430  skip = true;
431  }
432  else
433  {
434  migrated_value = std::string("0b") + bit_char;
435  inferred_decl = (bit_char == '0' || bit_char == '1')
436  ? Parameter::BitVector(name, 1, "")
437  : Parameter::LogicVector(name, 1, "");
438  }
439  }
440  else if (type_str == "bit_vector" || type_str == "std_logic_vector")
441  {
442  const bool has_prefix = raw_value.size() >= 3 && raw_value[0] == '0'
443  && (raw_value[1] == 'b' || raw_value[1] == 'B'
444  || raw_value[1] == 'o' || raw_value[1] == 'O'
445  || raw_value[1] == 'x' || raw_value[1] == 'X');
446  if (raw_value.empty())
447  {
448  log_warning("netlist_persistent", "skipping migration of generic data entry '{}': empty vector value", name);
449  skip = true;
450  }
451  else if (has_prefix)
452  {
453  const char pfx = static_cast<char>(std::tolower(static_cast<unsigned char>(raw_value[1])));
454  const auto n = static_cast<u16>(raw_value.size() - 2);
455  const u16 size = (pfx == 'b') ? n
456  : (pfx == 'o') ? static_cast<u16>(n * 3)
457  : static_cast<u16>(n * 4);
458  if (size == 0)
459  {
460  log_warning("netlist_persistent", "skipping migration of generic data entry '{}': zero-size vector", name);
461  skip = true;
462  }
463  else
464  {
465  inferred_decl = (type_str == "std_logic_vector")
468  }
469  }
470  else
471  {
472  // Old format: unprefixed uppercase hex (e.g. "CAFE")
473  const u16 size = static_cast<u16>(raw_value.size() * 4);
474  migrated_value = "0x" + raw_value;
475  inferred_decl = (type_str == "std_logic_vector")
478  }
479  }
480 
481  if (skip)
482  continue;
483 
484  if (inferred_decl.is_error())
485  {
486  log_warning("netlist_persistent", "skipping migration of generic data entry '{}' (type '{}'): {}", name, type_str, inferred_decl.get_error().get());
487  continue;
488  }
489 
490  // Gate-type declaration takes precedence if available
491  Result<Parameter> final_decl = inferred_decl;
492  if (gate_type != nullptr)
493  {
494  if (auto gt_res = gate_type->get_parameter(name); gt_res.is_ok())
495  final_decl = gt_res;
496  }
497 
498  if (auto res = c->set_parameter(final_decl.get(), migrated_value); res.is_error())
499  {
500  log_warning("netlist_persistent", "skipping migration of generic data entry '{}': {}", name, res.get_error().get());
501  continue;
502  }
503 
504  to_delete.emplace_back(std::get<0>(key_tuple), name);
505  }
506 
507  for (const auto& [cat, key] : to_delete)
508  c->delete_data(cat, key);
509  }
510 
511  bool deserialize_gate(Netlist* nl, const rapidjson::Value& val, const std::unordered_map<std::string, hal::GateType*>& gate_types)
512  {
513  const u32 gate_id = val["id"].GetUint();
514  const std::string gate_name = val["name"].GetString();
515  const std::string gate_type = val["type"].GetString();
516  i32 lx = -1;
517  i32 ly = -1;
518  if (val.HasMember("location_x") && val.HasMember("location_y"))
519  {
520  lx = val["location_x"].GetInt();
521  ly = val["location_y"].GetInt();
522  }
523  if (auto it = gate_types.find(gate_type); it != gate_types.end())
524  {
525  auto gate = nl->create_gate(gate_id, it->second, gate_name, lx, ly);
526  if (gate == nullptr)
527  {
528  log_error("netlist_persistent", "could not deserialize gate '" + gate_name + "' with ID " + std::to_string(gate_id) + ": failed to create gate");
529  return false;
530  }
531 
532  if (val.HasMember("data"))
533  {
534  deserialize_data(gate, val["data"]);
535  }
536 
537  if (val.HasMember("parameters"))
538  {
539  if (auto res = deserialize_parameters(gate, val["parameters"]); res.is_error())
540  {
541  log_error("netlist_persistent", "could not deserialize gate '" + gate_name + "' with ID " + std::to_string(gate_id) + ": {}", res.get_error().get());
542  return false;
543  }
544  }
545  else
546  {
547  migrate_generic_data_to_parameters(gate, it->second);
548  }
549 
550  if (val.HasMember("custom_functions"))
551  {
552  auto functions = val["custom_functions"].GetObject();
553  for (auto f_it = functions.MemberBegin(); f_it != functions.MemberEnd(); ++f_it)
554  {
555  auto func = BooleanFunction::from_string(f_it->value.GetString());
556  if (func.is_error())
557  {
558  log_error("netlist_persistent",
559  "could not deserialize gate '" + gate_name + "' with ID " + std::to_string(gate_id) + ": failed to parse Boolean function from string\n{}",
560  func.get_error().get());
561  return false;
562  }
563  gate->add_boolean_function(f_it->name.GetString(), func.get());
564  }
565  }
566 
567  return true;
568  }
569 
570  log_error("netlist_persistent",
571  "could not deserialize gate '" + gate_name + "' with ID " + std::to_string(gate_id) + ": failed to find gate '" + gate_type + "' in gate library '"
572  + nl->get_gate_library()->get_name() + "'");
573  return false;
574  }
575 
576  // serialize net
577  rapidjson::Value serialize(const Net* net, rapidjson::Document::AllocatorType& allocator)
578  {
579  rapidjson::Value val(rapidjson::kObjectType);
580  val.AddMember("id", net->get_id(), allocator);
581  val.AddMember("name", net->get_name(), allocator);
582 
583  {
584  rapidjson::Value srcs(rapidjson::kArrayType);
585  std::vector<Endpoint*> sorted = net->get_sources();
586  std::sort(sorted.begin(), sorted.end(), [](Endpoint* lhs, Endpoint* rhs) { return lhs->get_gate()->get_id() < rhs->get_gate()->get_id(); });
587  for (const Endpoint* src : sorted)
588  {
589  srcs.PushBack(serialize(src, allocator), allocator);
590  }
591  if (!srcs.Empty())
592  {
593  val.AddMember("srcs", srcs, allocator);
594  }
595  }
596 
597  {
598  rapidjson::Value dsts(rapidjson::kArrayType);
599  std::vector<Endpoint*> sorted = net->get_destinations();
600  std::sort(sorted.begin(), sorted.end(), [](Endpoint* lhs, Endpoint* rhs) { return lhs->get_gate()->get_id() < rhs->get_gate()->get_id(); });
601  for (const Endpoint* dst : sorted)
602  {
603  dsts.PushBack(serialize(dst, allocator), allocator);
604  }
605  if (!dsts.Empty())
606  {
607  val.AddMember("dsts", dsts, allocator);
608  }
609  }
610 
611  auto data = serialize(net->get_data_map(), allocator);
612  if (!data.Empty())
613  {
614  val.AddMember("data", data, allocator);
615  }
616  if (const auto& params = net->get_parameters(); !params.empty())
617  {
618  val.AddMember("parameters", serialize_parameters(params, allocator), allocator);
619  }
620  return val;
621  }
622 
623  bool deserialize_net(Netlist* nl, const rapidjson::Value& val)
624  {
625  const u32 net_id = val["id"].GetUint();
626  const std::string net_name = val["name"].GetString();
627  auto net = nl->create_net(net_id, net_name);
628  if (net == nullptr)
629  {
630  log_error("netlist_persistent", "could not deserialize net '" + net_name + "' with ID " + std::to_string(net_id) + ": failed to create net");
631  return false;
632  }
633 
634  if (val.HasMember("srcs"))
635  {
636  for (const auto& src_node : val["srcs"].GetArray())
637  {
638  if (!deserialize_source(nl, net, src_node))
639  {
640  log_error("netlist_persistent", "could not deserialize net '" + net_name + "' with ID " + std::to_string(net_id) + ": failed to deserialize source");
641  return false;
642  }
643  }
644  }
645 
646  if (val.HasMember("dsts"))
647  {
648  for (const auto& dst_node : val["dsts"].GetArray())
649  {
650  if (!deserialize_destination(nl, net, dst_node))
651  {
652  log_error("netlist_persistent", "could not deserialize net '" + net_name + "' with ID " + std::to_string(net_id) + ": failed to deserialize destination");
653  return false;
654  }
655  }
656  }
657 
658  if (val.HasMember("data"))
659  {
660  deserialize_data(net, val["data"]);
661  }
662 
663  if (val.HasMember("parameters"))
664  {
665  if (auto res = deserialize_parameters(net, val["parameters"]); res.is_error())
666  {
667  log_error("netlist_persistent", "could not deserialize net '" + net_name + "' with ID " + std::to_string(net_id) + ": {}", res.get_error().get());
668  return false;
669  }
670  }
671 
672  return true;
673  }
674 
675  // serialize module
676  rapidjson::Value serialize(const Module* module, rapidjson::Document::AllocatorType& allocator)
677  {
678  rapidjson::Value val(rapidjson::kObjectType);
679  val.AddMember("id", module->get_id(), allocator);
680  val.AddMember("type", module->get_type(), allocator);
681  val.AddMember("name", module->get_name(), allocator);
682  Module* parent = module->get_parent_module();
683  if (parent == nullptr)
684  {
685  val.AddMember("parent", 0, allocator);
686  }
687  else
688  {
689  val.AddMember("parent", parent->get_id(), allocator);
690  }
691  {
692  rapidjson::Value gates(rapidjson::kArrayType);
693  std::vector<Gate*> sorted = module->get_gates(nullptr, false);
694  std::sort(sorted.begin(), sorted.end(), [](Gate* lhs, Gate* rhs) { return lhs->get_id() < rhs->get_id(); });
695  for (const Gate* g : sorted)
696  {
697  gates.PushBack(g->get_id(), allocator);
698  }
699  if (!gates.Empty())
700  {
701  val.AddMember("gates", gates, allocator);
702  }
703  }
704  {
705  rapidjson::Value json_pin_groups(rapidjson::kArrayType);
706  for (const PinGroup<ModulePin>* pin_group : module->get_pin_groups())
707  {
708  rapidjson::Value json_pin_group(rapidjson::kObjectType);
709  json_pin_group.AddMember("id", pin_group->get_id(), allocator);
710  json_pin_group.AddMember("name", pin_group->get_name(), allocator);
711  json_pin_group.AddMember("direction", enum_to_string(pin_group->get_direction()), allocator);
712  json_pin_group.AddMember("type", enum_to_string(pin_group->get_type()), allocator);
713  json_pin_group.AddMember("ascending", pin_group->is_ascending(), allocator);
714  json_pin_group.AddMember("ordered", pin_group->is_ordered(), allocator);
715  json_pin_group.AddMember("start_index", pin_group->get_start_index(), allocator);
716  rapidjson::Value json_pins(rapidjson::kArrayType);
717  for (const ModulePin* pin : pin_group->get_pins())
718  {
719  rapidjson::Value json_pin(rapidjson::kObjectType);
720  json_pin.AddMember("id", pin->get_id(), allocator);
721  json_pin.AddMember("name", pin->get_name(), allocator);
722  json_pin.AddMember("type", enum_to_string(pin->get_type()), allocator);
723  json_pin.AddMember("net_id", pin->get_net()->get_id(), allocator);
724  json_pins.PushBack(json_pin, allocator);
725  }
726  json_pin_group.AddMember("pins", json_pins, allocator);
727  json_pin_groups.PushBack(json_pin_group, allocator);
728  }
729  if (!json_pin_groups.Empty())
730  {
731  val.AddMember("pin_groups", json_pin_groups, allocator);
732  }
733  }
734 
735  auto data = serialize(module->get_data_map(), allocator);
736  if (!data.Empty())
737  {
738  val.AddMember("data", data, allocator);
739  }
740  if (const auto& params = module->get_parameters(); !params.empty())
741  {
742  val.AddMember("parameters", serialize_parameters(params, allocator), allocator);
743  }
744  return val;
745  }
746 
747  bool deserialize_module(Netlist* nl, const rapidjson::Value& val, std::unordered_map<Module*, std::vector<PinGroupInformation>>& pin_group_cache)
748  {
749  const u32 module_id = val["id"].GetUint();
750  const std::string module_name = val["name"].GetString();
751  const u32 parent_id = val["parent"].GetUint();
752  Module* sm = nl->get_top_module();
753 
754  if (parent_id == 0)
755  {
756  // top_module must not be created but might be renamed
757  const std::string top_module_name = val["name"].GetString();
758  if (top_module_name != sm->get_name())
759  {
760  sm->set_name(top_module_name);
761  }
762  }
763  else
764  {
765  sm = nl->create_module(module_id, module_name, nl->get_module_by_id(parent_id));
766  if (sm == nullptr)
767  {
768  log_error("netlist_persistent", "could not deserialize module '" + module_name + "' with ID " + std::to_string(module_id) + ": failed to create module");
769  return false;
770  }
771  }
772 
773  if (val.HasMember("type"))
774  {
775  sm->set_type(val["type"].GetString());
776  }
777 
778  if (val.HasMember("gates"))
779  {
780  std::vector<Gate*> gates;
781  for (auto& gate_node : val["gates"].GetArray())
782  {
783  if (!sm->is_top_module())
784  {
785  gates.push_back(nl->get_gate_by_id(gate_node.GetUint()));
786  }
787  }
788  sm->assign_gates(gates);
789  }
790 
791  if (val.HasMember("data"))
792  {
793  deserialize_data(sm, val["data"]);
794  }
795 
796  if (val.HasMember("parameters"))
797  {
798  if (auto res = deserialize_parameters(sm, val["parameters"]); res.is_error())
799  {
800  log_error("netlist_persistent", "could not deserialize module '" + module_name + "' with ID " + std::to_string(module_id) + ": {}", res.get_error().get());
801  return false;
802  }
803  }
804  else
805  {
806  migrate_generic_data_to_parameters(sm);
807  }
808 
809  if (val.HasMember("pin_groups"))
810  {
811  // pins need to be cached until all modules have been instantiated
812  for (const auto& json_pin_group : val["pin_groups"].GetArray())
813  {
814  PinGroupInformation pin_group;
815  pin_group.id = json_pin_group["id"].GetUint();
816  pin_group.name = json_pin_group["name"].GetString();
817  if (json_pin_group.HasMember("direction"))
818  {
819  pin_group.direction = enum_from_string<PinDirection>(json_pin_group["direction"].GetString());
820  }
821  else
822  {
823  pin_group.direction = PinDirection::none;
824  }
825  if (json_pin_group.HasMember("type"))
826  {
827  pin_group.type = enum_from_string<PinType>(json_pin_group["type"].GetString());
828  }
829  else
830  {
831  pin_group.type = PinType::none;
832  }
833  if (json_pin_group.HasMember("ordered"))
834  {
835  pin_group.ordered = json_pin_group["ordered"].GetBool();
836  }
837  else
838  {
839  pin_group.type = PinType::none;
840  }
841  pin_group.ascending = json_pin_group["ascending"].GetBool();
842  pin_group.start_index = json_pin_group["start_index"].GetUint();
843 
844  for (const auto& pin_node : json_pin_group["pins"].GetArray())
845  {
846  PinGroupInformation::PinInformation pin;
847  pin.id = pin_node["id"].GetUint();
848  pin.name = pin_node["name"].GetString();
849  pin.net = nl->get_net_by_id(pin_node["net_id"].GetUint());
850  pin.type = enum_from_string<PinType>(pin_node["type"].GetString());
851  pin_group.pins.push_back(pin);
852  }
853  pin_group_cache[sm].push_back(pin_group);
854  }
855  }
856 
857  // legacy code below
858  if (val.HasMember("input_ports"))
859  {
860  for (const auto& json_pin_legacy : val["input_ports"].GetArray())
861  {
862  PinGroupInformation pin_group;
863  pin_group.name = json_pin_legacy["port_name"].GetString();
864  PinGroupInformation::PinInformation pin;
865  pin.name = json_pin_legacy["port_name"].GetString();
866  pin.net = nl->get_net_by_id(json_pin_legacy["net_id"].GetUint());
867  pin_group.pins.push_back(pin);
868  pin_group_cache[sm].push_back(pin_group);
869  }
870  }
871 
872  if (val.HasMember("output_ports"))
873  {
874  for (const auto& json_pin_legacy : val["output_ports"].GetArray())
875  {
876  PinGroupInformation pin_group;
877  pin_group.name = json_pin_legacy["port_name"].GetString();
878  PinGroupInformation::PinInformation pin;
879  pin.name = json_pin_legacy["port_name"].GetString();
880  pin.net = nl->get_net_by_id(json_pin_legacy["net_id"].GetUint());
881  pin_group.pins.push_back(pin);
882  pin_group_cache[sm].push_back(pin_group);
883  }
884  }
885  // legacy code above
886 
887  return true;
888  }
889 
890  bool deserialize_module_pins(const std::unordered_map<Module*, std::vector<PinGroupInformation>>& pin_group_cache)
891  {
892  for (const auto& [sm, pin_groups] : pin_group_cache)
893  {
894  for (const PinGroupInformation& pg : pin_groups)
895  {
896  std::vector<ModulePin*> pins;
897  for (const PinGroupInformation::PinInformation& p : pg.pins)
898  {
899  u32 pid = (p.id > 0) ? (u32)p.id : sm->get_unique_pin_id();
900  if (auto res = sm->create_pin(pid, p.name, p.net, p.type, false); res.is_error())
901  {
902  log_error("netlist_persistent",
903  "could not deserialize pin '" + p.name + "' of module '" + sm->get_name() + "' with ID " + std::to_string(sm->get_id()) + ": failed to create pin\n{}",
904  res.get_error().get());
905  return false;
906  }
907  else
908  {
909  pins.push_back(res.get());
910  }
911  }
912  u32 pgid = (pg.id > 0) ? (u32)pg.id : sm->get_unique_pin_group_id();
913  if (auto res = sm->create_pin_group(pgid, pg.name, pins, pg.direction, pg.type, pg.ascending, pg.start_index, pg.ordered); res.is_error())
914  {
915  log_error("netlist_persistent",
916  "could not deserialize pin group '" + pg.name + "' of module '" + sm->get_name() + "' with ID " + std::to_string(sm->get_id())
917  + ": failed to create pin group\n{}",
918  res.get_error().get());
919  return false;
920  }
921  }
922  }
923  return true;
924  }
925 
926  // serialize netlist
927  void serialize(const Netlist* nl, rapidjson::Document& document)
928  {
929  rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
930  rapidjson::Value root(rapidjson::kObjectType);
931 
932  root.AddMember("gate_library", nl->get_gate_library()->get_path().string(), allocator);
933  root.AddMember("id", nl->get_id(), allocator);
934  root.AddMember("input_file", nl->get_input_filename().string(), allocator);
935  root.AddMember("design_name", nl->get_design_name(), allocator);
936  root.AddMember("device_name", nl->get_device_name(), allocator);
937 
938  {
939  rapidjson::Value gates(rapidjson::kArrayType);
940  rapidjson::Value global_vccs(rapidjson::kArrayType);
941  rapidjson::Value global_gnds(rapidjson::kArrayType);
942  std::vector<Gate*> sorted = nl->get_gates();
943  std::sort(sorted.begin(), sorted.end(), [](Gate* lhs, Gate* rhs) { return lhs->get_id() < rhs->get_id(); });
944  for (const Gate* gate : sorted)
945  {
946  gates.PushBack(serialize(gate, allocator), allocator);
947 
948  if (nl->is_gnd_gate(gate))
949  {
950  global_gnds.PushBack(gate->get_id(), allocator);
951  }
952 
953  if (nl->is_vcc_gate(gate))
954  {
955  global_vccs.PushBack(gate->get_id(), allocator);
956  }
957  }
958  root.AddMember("gates", gates, allocator);
959  root.AddMember("global_vcc", global_vccs, allocator);
960  root.AddMember("global_gnd", global_gnds, allocator);
961  }
962  {
963  rapidjson::Value nets(rapidjson::kArrayType);
964  rapidjson::Value global_in(rapidjson::kArrayType);
965  rapidjson::Value global_out(rapidjson::kArrayType);
966  std::vector<Net*> sorted = nl->get_nets();
967  std::sort(sorted.begin(), sorted.end(), [](Net* lhs, Net* rhs) { return lhs->get_id() < rhs->get_id(); });
968  for (const Net* net : sorted)
969  {
970  nets.PushBack(serialize(net, allocator), allocator);
971 
972  if (nl->is_global_input_net(net))
973  {
974  global_in.PushBack(net->get_id(), allocator);
975  }
976 
977  if (nl->is_global_output_net(net))
978  {
979  global_out.PushBack(net->get_id(), allocator);
980  }
981  }
982  root.AddMember("nets", nets, allocator);
983  root.AddMember("global_in", global_in, allocator);
984  root.AddMember("global_out", global_out, allocator);
985  }
986  {
987  rapidjson::Value modules(rapidjson::kArrayType);
988 
989  // module ids are not sorted to preserve hierarchy
990  std::queue<const Module*> q;
991  q.push(nl->get_top_module());
992  while (!q.empty())
993  {
994  const Module* module = q.front();
995  q.pop();
996 
997  modules.PushBack(serialize(module, allocator), allocator);
998 
999  for (const Module* sm : module->get_submodules())
1000  {
1001  q.push(sm);
1002  }
1003  }
1004  root.AddMember("modules", modules, allocator);
1005  }
1006 
1007  document.AddMember("netlist", root, document.GetAllocator());
1008  }
1009 
1010  std::unique_ptr<Netlist> deserialize(const rapidjson::Document& document, GateLibrary* gatelib)
1011  {
1012  if (!document.HasMember("netlist"))
1013  {
1014  log_error("netlist_persistent", "could not deserialize netlist: file has no 'netlist' node");
1015  return nullptr;
1016  }
1017  auto root = document["netlist"].GetObject();
1018 
1019  if (!gatelib)
1020  {
1021  // no preferred gate library explicitly given
1022  if (!root.HasMember("gate_library"))
1023  {
1024  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'gate_library'");
1025  return nullptr;
1026  }
1027 
1028  std::filesystem::path glib_path(root["gate_library"].GetString());
1029 
1030  if (glib_path.is_relative())
1031  {
1032  ProjectManager* pm = ProjectManager::instance();
1033  if (pm)
1034  {
1035  glib_path = pm->get_project_directory() / glib_path;
1036  }
1037  }
1038  gatelib = gate_library_manager::get_gate_library(glib_path.string());
1039 
1040  if (gatelib == nullptr)
1041  {
1042  // not found : try the other possible gate library extension
1043  if (glib_path.extension() == ".hgl")
1044  {
1045  glib_path.replace_extension(".lib");
1046  }
1047  else
1048  {
1049  glib_path.replace_extension(".hgl");
1050  }
1051 
1052  gatelib = gate_library_manager::get_gate_library(glib_path.string());
1053  if (gatelib == nullptr)
1054  {
1055  log_critical("netlist_persistent", "could not deserialize netlist: failed to load gate library '" + std::string(root["gate_library"].GetString()) + "'");
1056  return nullptr;
1057  }
1058  else
1059  {
1060  log_info("netlist_persistent", "gate library '{}' required but using '{}' instead.", root["gate_library"].GetString(), glib_path.string());
1061  }
1062  }
1063  }
1064 
1065  auto nl = std::make_unique<Netlist>(gatelib);
1066 
1067  // disable automatically checking module nets
1068  nl->enable_automatic_net_checks(false);
1069 
1070  if (!root.HasMember("id"))
1071  {
1072  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'id'");
1073  return nullptr;
1074  }
1075  nl->set_id(root["id"].GetUint());
1076 
1077  if (!root.HasMember("input_file"))
1078  {
1079  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'input_file'");
1080  return nullptr;
1081  }
1082  nl->set_input_filename(root["input_file"].GetString());
1083 
1084  if (!root.HasMember("design_name"))
1085  {
1086  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'design_name'");
1087  return nullptr;
1088  }
1089  nl->set_design_name(root["design_name"].GetString());
1090 
1091  if (!root.HasMember("device_name"))
1092  {
1093  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'device_name'");
1094  return nullptr;
1095  }
1096  nl->set_device_name(root["device_name"].GetString());
1097 
1098  if (!root.HasMember("gates"))
1099  {
1100  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'gates'");
1101  return nullptr;
1102  }
1103  auto gate_types = nl->get_gate_library()->get_gate_types();
1104  for (auto& gate_node : root["gates"].GetArray())
1105  {
1106  if (!deserialize_gate(nl.get(), gate_node, gate_types))
1107  {
1108  log_error("netlist_persistent", "could not deserialize netlist: failed to deserialize gate");
1109  return nullptr;
1110  }
1111  }
1112 
1113  if (!root.HasMember("global_vcc"))
1114  {
1115  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'global_vcc'");
1116  return nullptr;
1117  }
1118  for (auto& gate_node : root["global_vcc"].GetArray())
1119  {
1120  if (!nl->mark_vcc_gate(nl->get_gate_by_id(gate_node.GetUint())))
1121  {
1122  log_error("netlist_persistent", "could not deserialize netlist: failed to mark VCC gate");
1123  return nullptr;
1124  }
1125  }
1126 
1127  if (!root.HasMember("global_gnd"))
1128  {
1129  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'global_gnd'");
1130  return nullptr;
1131  }
1132  for (auto& gate_node : root["global_gnd"].GetArray())
1133  {
1134  if (!nl->mark_gnd_gate(nl->get_gate_by_id(gate_node.GetUint())))
1135  {
1136  log_error("netlist_persistent", "could not deserialize netlist: failed to mark GND gate");
1137  return nullptr;
1138  }
1139  }
1140 
1141  if (!root.HasMember("nets"))
1142  {
1143  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'nets'");
1144  return nullptr;
1145  }
1146  for (auto& net_node : root["nets"].GetArray())
1147  {
1148  if (!deserialize_net(nl.get(), net_node))
1149  {
1150  log_error("netlist_persistent", "could not deserialize netlist: failed to deserialize net");
1151  return nullptr;
1152  }
1153  }
1154 
1155  if (!root.HasMember("global_in"))
1156  {
1157  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'global_in'");
1158  return nullptr;
1159  }
1160  for (auto& net_node : root["global_in"].GetArray())
1161  {
1162  if (!nl->mark_global_input_net(nl->get_net_by_id(net_node.GetUint())))
1163  {
1164  log_error("netlist_persistent", "could not deserialize netlist: failed to mark global input net");
1165  return nullptr;
1166  }
1167  }
1168 
1169  if (!root.HasMember("global_out"))
1170  {
1171  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'global_out'");
1172  return nullptr;
1173  }
1174  for (auto& net_node : root["global_out"].GetArray())
1175  {
1176  if (!nl->mark_global_output_net(nl->get_net_by_id(net_node.GetUint())))
1177  {
1178  log_error("netlist_persistent", "could not deserialize netlist: failed to mark global output net");
1179  return nullptr;
1180  }
1181  }
1182 
1183  if (!root.HasMember("modules"))
1184  {
1185  log_error("netlist_persistent", "could not deserialize netlist: node 'netlist' has no node 'modules'");
1186  return nullptr;
1187  }
1188  std::unordered_map<Module*, std::vector<PinGroupInformation>> pin_group_cache;
1189  for (auto& module_node : root["modules"].GetArray())
1190  {
1191  if (!deserialize_module(nl.get(), module_node, pin_group_cache))
1192  {
1193  log_error("netlist_persistent", "could not deserialize netlist: failed to deserialize module");
1194  return nullptr;
1195  }
1196  }
1197 
1198  // update module nets, internal nets, input nets, and output nets
1199  for (Module* mod : nl->get_modules())
1200  {
1201  mod->update_nets();
1202  }
1203 
1204  // load module pins (nets must have been updated beforehand)
1205  if (!deserialize_module_pins(pin_group_cache))
1206  {
1207  log_error("netlist_persistent", "could not deserialize netlist: failed to deserialize module pins");
1208  return nullptr;
1209  }
1210 
1211  // re-enable automatically checking module nets
1212  nl->enable_automatic_net_checks(true);
1213 
1214  return nl;
1215  }
1216 
1217  std::unique_ptr<Netlist>
1218  deserialize_document(rapidjson::Document& document, GateLibrary* gatelib, std::string source, std::chrono::time_point<std::chrono::high_resolution_clock>& begin_time)
1219  {
1220  if (document.HasParseError())
1221  {
1222  log_error("netlist_persistent", "invalid json string for deserialization");
1223  return nullptr;
1224  }
1225 
1226  if (document.HasMember("serialization_format_version"))
1227  {
1228  encoded_format_version = document["serialization_format_version"].GetUint();
1229  if (encoded_format_version < SERIALIZATION_FORMAT_VERSION)
1230  {
1231  log_warning("netlist_persistent", "the netlist was serialized with an older version of the serializer, deserialization may contain errors.");
1232  }
1233  else if (encoded_format_version > SERIALIZATION_FORMAT_VERSION)
1234  {
1235  log_warning("netlist_persistent", "the netlist was serialized with a newer version of the serializer, deserialization may contain errors.");
1236  }
1237  }
1238  else
1239  {
1240  log_warning("netlist_persistent", "the netlist was serialized with an older version of the serializer, deserialization may contain errors.");
1241  }
1242 
1243  auto netlist = deserialize(document, gatelib);
1244 
1245  if (netlist)
1246  {
1247  log_info("netlist_persistent", "deserialized '{}' in {:2.2f} seconds", source, DURATION(begin_time));
1248  }
1249 
1250  // event_controls::enable_all(true);
1251  return netlist;
1252  }
1253 
1254  } // namespace
1255 
1256  bool serialize_to_file(const Netlist* nl, const std::filesystem::path& hal_file)
1257  {
1258  if (nl == nullptr)
1259  {
1260  return false;
1261  }
1262 
1263  auto begin_time = std::chrono::high_resolution_clock::now();
1264 
1265  std::filesystem::path serialize_to_dir = hal_file.parent_path();
1266  if (serialize_to_dir.empty())
1267  {
1268  return false;
1269  }
1270 
1271  if (serialize_to_dir.is_relative())
1272  {
1273  serialize_to_dir = ProjectManager::instance()->get_project_directory() / serialize_to_dir;
1274  }
1275 
1276  // create directory if it got erased in the meantime
1277  if (!std::filesystem::exists(serialize_to_dir))
1278  {
1279  std::error_code err;
1280  if (!std::filesystem::create_directories(serialize_to_dir, err))
1281  {
1282  log_error("netlist_persistent", "Could not create directory '{}', error was '{}'.", serialize_to_dir.string(), err.message());
1283  return false;
1284  }
1285  }
1286 
1287  std::ofstream hal_file_stream;
1288  hal_file_stream.open(hal_file.string());
1289  if (hal_file_stream.fail())
1290  {
1291  log_error("netlist_persistent", "could not open or create file {}: please verify that the file and the containing directory is writable", hal_file.string());
1292  return false;
1293  }
1294 
1295  rapidjson::Document document;
1296  document.SetObject();
1297 
1298  document.AddMember("serialization_format_version", SERIALIZATION_FORMAT_VERSION, document.GetAllocator());
1299 
1300  serialize(nl, document);
1301 
1302  rapidjson::StringBuffer strbuf;
1303 #if PRETTY_JSON_OUTPUT == 1
1304  rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(strbuf);
1305 #else
1306  rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
1307 #endif
1308  document.Accept(writer);
1309 
1310  hal_file_stream << strbuf.GetString();
1311 
1312  hal_file_stream.close();
1313 
1314  log_info("netlist_persistent", "serialized netlist in {:2.2f} seconds", DURATION(begin_time));
1315 
1316  return true;
1317  }
1318 
1319  std::unique_ptr<Netlist> deserialize_from_file(const std::filesystem::path& hal_file, GateLibrary* gatelib)
1320  {
1321  auto begin_time = std::chrono::high_resolution_clock::now();
1322 
1323  // event_controls::enable_all(false);
1324 
1325  FILE* pFile = fopen(hal_file.string().c_str(), "rb");
1326  if (pFile == NULL)
1327  {
1328  log_error("netlist_persistent", "unable to open '{}'.", hal_file.string());
1329  return nullptr;
1330  }
1331 
1332  char buffer[65536];
1333  rapidjson::FileReadStream is(pFile, buffer, sizeof(buffer));
1334  rapidjson::Document document;
1335  document.ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(is);
1336  fclose(pFile);
1337 
1338  return deserialize_document(document, gatelib, hal_file.string(), begin_time);
1339  }
1340 
1341  std::unique_ptr<Netlist> deserialize_from_string(const std::string& hal_string, GateLibrary* gatelib)
1342  {
1343  auto begin_time = std::chrono::high_resolution_clock::now();
1344 
1345  // event_controls::enable_all(false);
1346 
1347  rapidjson::Document document;
1348  document.Parse<0, rapidjson::UTF8<>>(hal_string.c_str());
1349 
1350  return deserialize_document(document, gatelib, "source string", begin_time);
1351  }
1352  } // namespace netlist_serializer
1353 } // namespace hal
1354 
1355 #undef DURATION
u32 size
static Result< BooleanFunction > from_string(const std::string &expression)
const std::map< std::tuple< std::string, std::string >, std::tuple< std::string, std::string > > & get_data_map() const
const std::unordered_map< std::string, std::pair< Parameter, std::string > > & get_parameters() const
Module * get_parent_module() const
Definition: module.cpp:126
const std::vector< Gate * > & get_gates() const
Definition: module.cpp:400
std::string get_name() const
Definition: module.cpp:88
std::vector< PinGroup< ModulePin > * > get_pin_groups(const std::function< bool(PinGroup< ModulePin > *)> &filter=nullptr) const
Definition: module.cpp:971
std::vector< Module * > get_submodules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=false) const
Definition: module.cpp:268
std::string get_type() const
Definition: module.cpp:107
u32 get_id() const
Definition: module.cpp:83
static ProjectManager * instance()
const ProjectDirectory & get_project_directory() const
uint16_t u16
Definition: defines.h:40
uint32_t u32
Definition: defines.h:41
int32_t i32
Definition: defines.h:36
#define log_error(channel,...)
Definition: log.h:78
#define log_info(channel,...)
Definition: log.h:70
#define log_critical(channel,...)
Definition: log.h:80
#define log_warning(channel,...)
Definition: log.h:76
#define ERR(message)
Definition: result.h:60
#define OK(...)
Definition: result.h:56
const Module * module(const Gate *g, const NodeBoxes &boxes)
GateLibrary * get_gate_library(const std::string &file_path)
std::unique_ptr< Netlist > deserialize_from_string(const std::string &hal_string, GateLibrary *gate_lib=nullptr)
bool serialize_to_file(const Netlist *netlist, const std::filesystem::path &hal_file)
std::unique_ptr< Netlist > deserialize_from_file(const std::filesystem::path &hal_file, GateLibrary *gate_lib=nullptr)
Definition: defines.h:45
PinDirection
Definition: pin_direction.h:36
std::error_code error_code
Definition: defines.h:46
PinType
Definition: pin_type.h:36
std::string enum_to_string(T e)
Definition: enums.h:53
PinType type
std::vector< PinInformation > pins
#define DURATION(begin_time)
bool ordered
Net * net
u32 start_index
bool ascending
PinDirection direction
std::string name
#define JSON_STR_HELPER(x)
const int SERIALIZATION_FORMAT_VERSION
static Result< Parameter > Boolean(const std::string &name, const std::string &default_value)
Definition: parameter.cpp:319
static Result< Parameter > BitVector(const std::string &name, u16 size, const std::string &default_value)
Definition: parameter.cpp:340
static Result< Parameter > Integer(const std::string &name, const std::string &default_value)
Definition: parameter.cpp:390
static Result< Parameter > String(const std::string &name, const std::string &default_value)
Definition: parameter.cpp:411
static Result< Parameter > LogicVector(const std::string &name, u16 size, const std::string &default_value)
Definition: parameter.cpp:365
static Result< Parameter > Time(const std::string &name, const std::string &default_value)
Definition: parameter.cpp:448
static Result< Parameter > Enum(const std::string &name, const std::vector< std::string > &values, const std::string &default_value)
Definition: parameter.cpp:469
static Result< Parameter > Float(const std::string &name, const std::string &default_value)
Definition: parameter.cpp:427