11 #include "rapidjson/filereadstream.h"
12 #include "rapidjson/stringbuffer.h"
14 #define PRETTY_JSON_OUTPUT false
15 #if PRETTY_JSON_OUTPUT
16 #include "rapidjson/prettywriter.h"
18 #include "rapidjson/writer.h"
27 #define DURATION(begin_time) ((double)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - begin_time).count() / 1000)
38 int encoded_format_version;
41 #define JSON_STR_HELPER(x) rapidjson::Value{}.SetString(x.c_str(), x.length(), allocator)
43 #define assert_availablility(MEMBER) \
44 if (!root.HasMember(MEMBER)) \
46 log_critical("netlist_persistent", "'netlist' node does not include a '{}' node", MEMBER); \
52 struct PinGroupInformation
66 std::vector<PinInformation>
pins;
75 rapidjson::Value serialize(
const std::map<std::tuple<std::string, std::string>, std::tuple<std::string, std::string>>& data, rapidjson::Document::AllocatorType& allocator)
77 rapidjson::Value val(rapidjson::kArrayType);
78 for (
const auto& it :
data)
80 rapidjson::Value entry(rapidjson::kArrayType);
85 val.PushBack(entry, allocator);
90 void deserialize_data(DataContainer* c,
const rapidjson::Value& val)
92 for (
const auto& entry : val.GetArray())
94 c->set_data(entry[0].GetString(), entry[1].GetString(), entry[2].GetString(), entry[3].GetString());
99 rapidjson::Value serialize(
const Endpoint* ep, rapidjson::Document::AllocatorType& allocator)
101 rapidjson::Value val(rapidjson::kObjectType);
102 val.AddMember(
"gate_id", ep->get_gate()->get_id(), allocator);
103 val.AddMember(
"pin_id", ep->get_pin()->get_id(), allocator);
107 bool deserialize_destination(Netlist* nl, Net*
net,
const rapidjson::Value& val)
109 Gate* gate = nl->get_gate_by_id(val[
"gate_id"].GetUint());
112 if (val.HasMember(
"pin_id"))
114 const u32 pin_id = val[
"pin_id"].GetUint();
115 pin = gate->get_type()->get_pin_by_id(pin_id);
119 "could not deserialize destination of net '" +
net->get_name() +
"' with ID " + std::to_string(
net->get_id()) +
": failed to get pin with ID "
120 + std::to_string(pin_id));
124 if (encoded_format_version <= 12)
127 if (
const auto [group,
index] = pin->get_group(); group->size() > 1)
130 u32 len = group->size();
135 if (
const auto pin_res = group->get_pin_at_index(target_index); pin_res.is_error())
138 "could not deserialize destination of net '" +
net->get_name() +
"' with ID " + std::to_string(
net->get_id()) +
": failed to swap pin with ID "
139 + std::to_string(pin_id) +
":\n{}",
140 pin_res.get_error().get());
153 const std::string pin_name = val[
"pin_type"].GetString();
154 pin = gate->get_type()->get_pin_by_name(pin_name);
158 "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 +
"'");
163 if (!
net->add_destination(gate, pin))
166 "could not deserialize destination of net '" +
net->get_name() +
"' with ID " + std::to_string(
net->get_id()) +
": failed to add pin '" + pin->get_name()
167 +
"' as destination to net '" +
net->get_name() +
"' with ID " + std::to_string(
net->get_id()));
173 bool deserialize_source(Netlist* nl, Net*
net,
const rapidjson::Value& val)
175 Gate* gate = nl->get_gate_by_id(val[
"gate_id"].GetUint());
178 if (val.HasMember(
"pin_id"))
180 const u32 pin_id = val[
"pin_id"].GetUint();
181 pin = gate->get_type()->get_pin_by_id(pin_id);
185 "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));
189 if (encoded_format_version <= 12)
192 if (
const auto [group,
index] = pin->get_group(); group->size() > 1)
195 u32 len = group->size();
200 if (
const auto pin_res = group->get_pin_at_index(target_index); pin_res.is_error())
203 "could not deserialize source of net '" +
net->get_name() +
"' with ID " + std::to_string(
net->get_id()) +
": failed to swap pin with ID "
204 + std::to_string(pin_id) +
":\n{}",
205 pin_res.get_error().get());
218 const std::string pin_name = val[
"pin_type"].GetString();
219 pin = gate->get_type()->get_pin_by_name(pin_name);
223 "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 +
"'");
228 if (
net->add_source(gate, pin) ==
nullptr)
231 "could not deserialize source of net '" +
net->get_name() +
"' with ID " + std::to_string(
net->get_id()) +
": failed to add pin '" + pin->get_name()
232 +
"' as source to net '" +
net->get_name() +
"' with ID " + std::to_string(
net->get_id()));
239 rapidjson::Value serialize(
const Gate* gate, rapidjson::Document::AllocatorType& allocator)
241 rapidjson::Value val(rapidjson::kObjectType);
242 val.AddMember(
"id", gate->get_id(), allocator);
243 val.AddMember(
"name", gate->get_name(), allocator);
244 val.AddMember(
"type", gate->get_type()->get_name(), allocator);
245 if (gate->has_location())
247 val.AddMember(
"location_x", gate->get_location_x(), allocator);
248 val.AddMember(
"location_y", gate->get_location_y(), allocator);
250 auto data = serialize(gate->get_data_map(), allocator);
253 val.AddMember(
"data", data, allocator);
256 rapidjson::Value functions(rapidjson::kObjectType);
257 for (
const auto& [
name,
function] : gate->get_boolean_functions(
true))
259 const std::string function_str =
function.to_string();
262 if (functions.MemberCount() > 0)
264 val.AddMember(
"custom_functions", functions, allocator);
270 bool deserialize_gate(Netlist* nl,
const rapidjson::Value& val,
const std::unordered_map<std::string, hal::GateType*>& gate_types)
272 const u32 gate_id = val[
"id"].GetUint();
273 const std::string gate_name = val[
"name"].GetString();
274 const std::string gate_type = val[
"type"].GetString();
277 if (val.HasMember(
"location_x") && val.HasMember(
"location_y"))
279 lx = val[
"location_x"].GetInt();
280 ly = val[
"location_y"].GetInt();
282 if (
auto it = gate_types.find(gate_type); it != gate_types.end())
284 auto gate = nl->create_gate(gate_id, it->second, gate_name, lx, ly);
287 log_error(
"netlist_persistent",
"could not deserialize gate '" + gate_name +
"' with ID " + std::to_string(gate_id) +
": failed to create gate");
291 if (val.HasMember(
"data"))
293 deserialize_data(gate, val[
"data"]);
296 if (val.HasMember(
"custom_functions"))
298 auto functions = val[
"custom_functions"].GetObject();
299 for (
auto f_it = functions.MemberBegin(); f_it != functions.MemberEnd(); ++f_it)
305 "could not deserialize gate '" + gate_name +
"' with ID " + std::to_string(gate_id) +
": failed to parse Boolean function from string\n{}",
306 func.get_error().get());
309 gate->add_boolean_function(f_it->name.GetString(), func.get());
317 "could not deserialize gate '" + gate_name +
"' with ID " + std::to_string(gate_id) +
": failed to find gate '" + gate_type +
"' in gate library '"
318 + nl->get_gate_library()->get_name() +
"'");
323 rapidjson::Value serialize(
const Net*
net, rapidjson::Document::AllocatorType& allocator)
325 rapidjson::Value val(rapidjson::kObjectType);
326 val.AddMember(
"id",
net->get_id(), allocator);
327 val.AddMember(
"name",
net->get_name(), allocator);
330 rapidjson::Value srcs(rapidjson::kArrayType);
331 std::vector<Endpoint*> sorted =
net->get_sources();
332 std::sort(sorted.begin(), sorted.end(), [](Endpoint* lhs, Endpoint* rhs) { return lhs->get_gate()->get_id() < rhs->get_gate()->get_id(); });
333 for (
const Endpoint* src : sorted)
335 srcs.PushBack(serialize(src, allocator), allocator);
339 val.AddMember(
"srcs", srcs, allocator);
344 rapidjson::Value dsts(rapidjson::kArrayType);
345 std::vector<Endpoint*> sorted =
net->get_destinations();
346 std::sort(sorted.begin(), sorted.end(), [](Endpoint* lhs, Endpoint* rhs) { return lhs->get_gate()->get_id() < rhs->get_gate()->get_id(); });
347 for (
const Endpoint* dst : sorted)
349 dsts.PushBack(serialize(dst, allocator), allocator);
353 val.AddMember(
"dsts", dsts, allocator);
357 auto data = serialize(
net->get_data_map(), allocator);
360 val.AddMember(
"data", data, allocator);
365 bool deserialize_net(Netlist* nl,
const rapidjson::Value& val)
367 const u32 net_id = val[
"id"].GetUint();
368 const std::string net_name = val[
"name"].GetString();
369 auto net = nl->create_net(net_id, net_name);
372 log_error(
"netlist_persistent",
"could not deserialize net '" + net_name +
"' with ID " + std::to_string(net_id) +
": failed to create net");
376 if (val.HasMember(
"srcs"))
378 for (
const auto& src_node : val[
"srcs"].GetArray())
380 if (!deserialize_source(nl,
net, src_node))
382 log_error(
"netlist_persistent",
"could not deserialize net '" + net_name +
"' with ID " + std::to_string(net_id) +
": failed to deserialize source");
388 if (val.HasMember(
"dsts"))
390 for (
const auto& dst_node : val[
"dsts"].GetArray())
392 if (!deserialize_destination(nl,
net, dst_node))
394 log_error(
"netlist_persistent",
"could not deserialize net '" + net_name +
"' with ID " + std::to_string(net_id) +
": failed to deserialize destination");
400 if (val.HasMember(
"data"))
402 deserialize_data(
net, val[
"data"]);
409 rapidjson::Value serialize(
const Module*
module, rapidjson::Document::AllocatorType& allocator)
411 rapidjson::Value val(rapidjson::kObjectType);
416 if (parent ==
nullptr)
418 val.AddMember(
"parent", 0, allocator);
422 val.AddMember(
"parent", parent->get_id(), allocator);
425 rapidjson::Value gates(rapidjson::kArrayType);
427 std::sort(sorted.begin(), sorted.end(), [](Gate* lhs, Gate* rhs) { return lhs->get_id() < rhs->get_id(); });
428 for (
const Gate* g : sorted)
430 gates.PushBack(g->get_id(), allocator);
434 val.AddMember(
"gates", gates, allocator);
438 rapidjson::Value json_pin_groups(rapidjson::kArrayType);
441 rapidjson::Value json_pin_group(rapidjson::kObjectType);
442 json_pin_group.AddMember(
"id", pin_group->get_id(), allocator);
443 json_pin_group.AddMember(
"name", pin_group->get_name(), allocator);
444 json_pin_group.AddMember(
"direction",
enum_to_string(pin_group->get_direction()), allocator);
445 json_pin_group.AddMember(
"type",
enum_to_string(pin_group->get_type()), allocator);
446 json_pin_group.AddMember(
"ascending", pin_group->is_ascending(), allocator);
447 json_pin_group.AddMember(
"ordered", pin_group->is_ordered(), allocator);
448 json_pin_group.AddMember(
"start_index", pin_group->get_start_index(), allocator);
449 rapidjson::Value json_pins(rapidjson::kArrayType);
450 for (
const ModulePin* pin : pin_group->get_pins())
452 rapidjson::Value json_pin(rapidjson::kObjectType);
453 json_pin.AddMember(
"id", pin->get_id(), allocator);
454 json_pin.AddMember(
"name", pin->get_name(), allocator);
455 json_pin.AddMember(
"type",
enum_to_string(pin->get_type()), allocator);
456 json_pin.AddMember(
"net_id", pin->get_net()->get_id(), allocator);
457 json_pins.PushBack(json_pin, allocator);
459 json_pin_group.AddMember(
"pins", json_pins, allocator);
460 json_pin_groups.PushBack(json_pin_group, allocator);
462 if (!json_pin_groups.Empty())
464 val.AddMember(
"pin_groups", json_pin_groups, allocator);
471 val.AddMember(
"data", data, allocator);
476 bool deserialize_module(Netlist* nl,
const rapidjson::Value& val, std::unordered_map<Module*, std::vector<PinGroupInformation>>& pin_group_cache)
478 const u32 module_id = val[
"id"].GetUint();
479 const std::string module_name = val[
"name"].GetString();
480 const u32 parent_id = val[
"parent"].GetUint();
481 Module* sm = nl->get_top_module();
486 const std::string top_module_name = val[
"name"].GetString();
487 if (top_module_name != sm->get_name())
489 sm->set_name(top_module_name);
494 sm = nl->create_module(module_id, module_name, nl->get_module_by_id(parent_id));
497 log_error(
"netlist_persistent",
"could not deserialize module '" + module_name +
"' with ID " + std::to_string(module_id) +
": failed to create module");
502 if (val.HasMember(
"type"))
504 sm->set_type(val[
"type"].GetString());
507 if (val.HasMember(
"gates"))
509 std::vector<Gate*> gates;
510 for (
auto& gate_node : val[
"gates"].GetArray())
512 if (!sm->is_top_module())
514 gates.push_back(nl->get_gate_by_id(gate_node.GetUint()));
517 sm->assign_gates(gates);
520 if (val.HasMember(
"data"))
522 deserialize_data(sm, val[
"data"]);
525 if (val.HasMember(
"pin_groups"))
528 for (
const auto& json_pin_group : val[
"pin_groups"].GetArray())
530 PinGroupInformation pin_group;
531 pin_group.id = json_pin_group[
"id"].GetUint();
532 pin_group.name = json_pin_group[
"name"].GetString();
533 if (json_pin_group.HasMember(
"direction"))
535 pin_group.direction = enum_from_string<PinDirection>(json_pin_group[
"direction"].GetString());
541 if (json_pin_group.HasMember(
"type"))
543 pin_group.type = enum_from_string<PinType>(json_pin_group[
"type"].GetString());
549 if (json_pin_group.HasMember(
"ordered"))
551 pin_group.ordered = json_pin_group[
"ordered"].GetBool();
557 pin_group.ascending = json_pin_group[
"ascending"].GetBool();
558 pin_group.start_index = json_pin_group[
"start_index"].GetUint();
560 for (
const auto& pin_node : json_pin_group[
"pins"].GetArray())
562 PinGroupInformation::PinInformation pin;
563 pin.id = pin_node[
"id"].GetUint();
564 pin.name = pin_node[
"name"].GetString();
565 pin.net = nl->get_net_by_id(pin_node[
"net_id"].GetUint());
566 pin.type = enum_from_string<PinType>(pin_node[
"type"].GetString());
567 pin_group.pins.push_back(pin);
569 pin_group_cache[sm].push_back(pin_group);
574 if (val.HasMember(
"input_ports"))
576 for (
const auto& json_pin_legacy : val[
"input_ports"].GetArray())
578 PinGroupInformation pin_group;
579 pin_group.name = json_pin_legacy[
"port_name"].GetString();
580 PinGroupInformation::PinInformation pin;
581 pin.name = json_pin_legacy[
"port_name"].GetString();
582 pin.net = nl->get_net_by_id(json_pin_legacy[
"net_id"].GetUint());
583 pin_group.pins.push_back(pin);
584 pin_group_cache[sm].push_back(pin_group);
588 if (val.HasMember(
"output_ports"))
590 for (
const auto& json_pin_legacy : val[
"output_ports"].GetArray())
592 PinGroupInformation pin_group;
593 pin_group.name = json_pin_legacy[
"port_name"].GetString();
594 PinGroupInformation::PinInformation pin;
595 pin.name = json_pin_legacy[
"port_name"].GetString();
596 pin.net = nl->get_net_by_id(json_pin_legacy[
"net_id"].GetUint());
597 pin_group.pins.push_back(pin);
598 pin_group_cache[sm].push_back(pin_group);
606 bool deserialize_module_pins(
const std::unordered_map<Module*, std::vector<PinGroupInformation>>& pin_group_cache)
608 for (
const auto& [sm, pin_groups] : pin_group_cache)
610 for (
const PinGroupInformation& pg : pin_groups)
612 std::vector<ModulePin*>
pins;
613 for (
const PinGroupInformation::PinInformation& p : pg.pins)
615 u32 pid = (p.id > 0) ? (
u32)p.id : sm->get_unique_pin_id();
616 if (
auto res = sm->create_pin(pid, p.name, p.net, p.type,
false); res.is_error())
619 "could not deserialize pin '" + p.name +
"' of module '" + sm->get_name() +
"' with ID " + std::to_string(sm->get_id()) +
": failed to create pin\n{}",
620 res.get_error().get());
625 pins.push_back(res.get());
628 u32 pgid = (pg.id > 0) ? (
u32)pg.id : sm->get_unique_pin_group_id();
629 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())
632 "could not deserialize pin group '" + pg.name +
"' of module '" + sm->get_name() +
"' with ID " + std::to_string(sm->get_id())
633 +
": failed to create pin group\n{}",
634 res.get_error().get());
643 void serialize(
const Netlist* nl, rapidjson::Document& document)
645 rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
646 rapidjson::Value root(rapidjson::kObjectType);
648 root.AddMember(
"gate_library", nl->get_gate_library()->get_path().string(), allocator);
649 root.AddMember(
"id", nl->get_id(), allocator);
650 root.AddMember(
"input_file", nl->get_input_filename().string(), allocator);
651 root.AddMember(
"design_name", nl->get_design_name(), allocator);
652 root.AddMember(
"device_name", nl->get_device_name(), allocator);
655 rapidjson::Value gates(rapidjson::kArrayType);
656 rapidjson::Value global_vccs(rapidjson::kArrayType);
657 rapidjson::Value global_gnds(rapidjson::kArrayType);
658 std::vector<Gate*> sorted = nl->get_gates();
659 std::sort(sorted.begin(), sorted.end(), [](Gate* lhs, Gate* rhs) { return lhs->get_id() < rhs->get_id(); });
660 for (
const Gate* gate : sorted)
662 gates.PushBack(serialize(gate, allocator), allocator);
664 if (nl->is_gnd_gate(gate))
666 global_gnds.PushBack(gate->get_id(), allocator);
669 if (nl->is_vcc_gate(gate))
671 global_vccs.PushBack(gate->get_id(), allocator);
674 root.AddMember(
"gates", gates, allocator);
675 root.AddMember(
"global_vcc", global_vccs, allocator);
676 root.AddMember(
"global_gnd", global_gnds, allocator);
679 rapidjson::Value nets(rapidjson::kArrayType);
680 rapidjson::Value global_in(rapidjson::kArrayType);
681 rapidjson::Value global_out(rapidjson::kArrayType);
682 std::vector<Net*> sorted = nl->get_nets();
683 std::sort(sorted.begin(), sorted.end(), [](Net* lhs, Net* rhs) { return lhs->get_id() < rhs->get_id(); });
684 for (
const Net*
net : sorted)
686 nets.PushBack(serialize(
net, allocator), allocator);
688 if (nl->is_global_input_net(
net))
690 global_in.PushBack(
net->get_id(), allocator);
693 if (nl->is_global_output_net(
net))
695 global_out.PushBack(
net->get_id(), allocator);
698 root.AddMember(
"nets", nets, allocator);
699 root.AddMember(
"global_in", global_in, allocator);
700 root.AddMember(
"global_out", global_out, allocator);
703 rapidjson::Value modules(rapidjson::kArrayType);
706 std::queue<const Module*> q;
707 q.push(nl->get_top_module());
713 modules.PushBack(serialize(
module, allocator), allocator);
720 root.AddMember(
"modules", modules, allocator);
723 document.AddMember(
"netlist", root, document.GetAllocator());
726 std::unique_ptr<Netlist> deserialize(
const rapidjson::Document& document, GateLibrary* gatelib)
728 if (!document.HasMember(
"netlist"))
730 log_error(
"netlist_persistent",
"could not deserialize netlist: file has no 'netlist' node");
733 auto root = document[
"netlist"].GetObject();
738 if (!root.HasMember(
"gate_library"))
740 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'gate_library'");
744 std::filesystem::path glib_path(root[
"gate_library"].GetString());
746 if (glib_path.is_relative())
750 glib_path = pm->get_project_directory() / glib_path;
754 if (gatelib ==
nullptr)
757 if (glib_path.extension() ==
".hgl")
759 glib_path.replace_extension(
".lib");
763 glib_path.replace_extension(
".hgl");
767 if (gatelib ==
nullptr)
769 log_critical(
"netlist_persistent",
"could not deserialize netlist: failed to load gate library '" + std::string(root[
"gate_library"].GetString()) +
"'");
774 log_info(
"netlist_persistent",
"gate library '{}' required but using '{}' instead.", root[
"gate_library"].GetString(), glib_path.string());
779 auto nl = std::make_unique<Netlist>(gatelib);
782 nl->enable_automatic_net_checks(
false);
784 if (!root.HasMember(
"id"))
786 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'id'");
789 nl->set_id(root[
"id"].GetUint());
791 if (!root.HasMember(
"input_file"))
793 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'input_file'");
796 nl->set_input_filename(root[
"input_file"].GetString());
798 if (!root.HasMember(
"design_name"))
800 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'design_name'");
803 nl->set_design_name(root[
"design_name"].GetString());
805 if (!root.HasMember(
"device_name"))
807 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'device_name'");
810 nl->set_device_name(root[
"device_name"].GetString());
812 if (!root.HasMember(
"gates"))
814 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'gates'");
817 auto gate_types = nl->get_gate_library()->get_gate_types();
818 for (
auto& gate_node : root[
"gates"].GetArray())
820 if (!deserialize_gate(nl.get(), gate_node, gate_types))
822 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to deserialize gate");
827 if (!root.HasMember(
"global_vcc"))
829 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'global_vcc'");
832 for (
auto& gate_node : root[
"global_vcc"].GetArray())
834 if (!nl->mark_vcc_gate(nl->get_gate_by_id(gate_node.GetUint())))
836 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to mark VCC gate");
841 if (!root.HasMember(
"global_gnd"))
843 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'global_gnd'");
846 for (
auto& gate_node : root[
"global_gnd"].GetArray())
848 if (!nl->mark_gnd_gate(nl->get_gate_by_id(gate_node.GetUint())))
850 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to mark GND gate");
855 if (!root.HasMember(
"nets"))
857 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'nets'");
860 for (
auto& net_node : root[
"nets"].GetArray())
862 if (!deserialize_net(nl.get(), net_node))
864 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to deserialize net");
869 if (!root.HasMember(
"global_in"))
871 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'global_in'");
874 for (
auto& net_node : root[
"global_in"].GetArray())
876 if (!nl->mark_global_input_net(nl->get_net_by_id(net_node.GetUint())))
878 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to mark global input net");
883 if (!root.HasMember(
"global_out"))
885 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'global_out'");
888 for (
auto& net_node : root[
"global_out"].GetArray())
890 if (!nl->mark_global_output_net(nl->get_net_by_id(net_node.GetUint())))
892 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to mark global output net");
897 if (!root.HasMember(
"modules"))
899 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'modules'");
902 std::unordered_map<Module*, std::vector<PinGroupInformation>> pin_group_cache;
903 for (
auto& module_node : root[
"modules"].GetArray())
905 if (!deserialize_module(nl.get(), module_node, pin_group_cache))
907 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to deserialize module");
913 for (Module* mod : nl->get_modules())
919 if (!deserialize_module_pins(pin_group_cache))
921 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to deserialize module pins");
926 nl->enable_automatic_net_checks(
true);
931 std::unique_ptr<Netlist> deserialize_document(rapidjson::Document& document, GateLibrary* gatelib, std::string source,
932 std::chrono::time_point<std::chrono::high_resolution_clock>& begin_time)
934 if (document.HasParseError())
936 log_error(
"netlist_persistent",
"invalid json string for deserialization");
940 if (document.HasMember(
"serialization_format_version"))
942 encoded_format_version = document[
"serialization_format_version"].GetUint();
945 log_warning(
"netlist_persistent",
"the netlist was serialized with an older version of the serializer, deserialization may contain errors.");
949 log_warning(
"netlist_persistent",
"the netlist was serialized with a newer version of the serializer, deserialization may contain errors.");
954 log_warning(
"netlist_persistent",
"the netlist was serialized with an older version of the serializer, deserialization may contain errors.");
957 auto netlist = deserialize(document, gatelib);
961 log_info(
"netlist_persistent",
"deserialized '{}' in {:2.2f} seconds", source,
DURATION(begin_time));
977 auto begin_time = std::chrono::high_resolution_clock::now();
979 std::filesystem::path serialize_to_dir = hal_file.parent_path();
980 if (serialize_to_dir.empty())
983 if (serialize_to_dir.is_relative())
987 if (!std::filesystem::exists(serialize_to_dir))
990 if (!std::filesystem::create_directories(serialize_to_dir, err))
992 log_error(
"netlist_persistent",
"Could not create directory '{}', error was '{}'.", serialize_to_dir.string(), err.message());
997 std::ofstream hal_file_stream;
998 hal_file_stream.open(hal_file.string());
999 if (hal_file_stream.fail())
1001 log_error(
"netlist_persistent",
"could not open or create file {}: please verify that the file and the containing directory is writable", hal_file.string());
1005 rapidjson::Document document;
1006 document.SetObject();
1010 serialize(nl, document);
1012 rapidjson::StringBuffer strbuf;
1013 #if PRETTY_JSON_OUTPUT == 1
1014 rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(strbuf);
1016 rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
1018 document.Accept(writer);
1020 hal_file_stream << strbuf.GetString();
1022 hal_file_stream.close();
1024 log_info(
"netlist_persistent",
"serialized netlist in {:2.2f} seconds",
DURATION(begin_time));
1031 auto begin_time = std::chrono::high_resolution_clock::now();
1035 FILE* pFile = fopen(hal_file.string().c_str(),
"rb");
1038 log_error(
"netlist_persistent",
"unable to open '{}'.", hal_file.string());
1043 rapidjson::FileReadStream is(pFile, buffer,
sizeof(buffer));
1044 rapidjson::Document document;
1045 document.ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(is);
1048 return deserialize_document(document, gatelib, hal_file.string(), begin_time);
1053 auto begin_time = std::chrono::high_resolution_clock::now();
1057 rapidjson::Document document;
1058 document.Parse<0, rapidjson::UTF8<> >(hal_string.c_str());
1060 return deserialize_document(document, gatelib,
"source string", begin_time);
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
Module * get_parent_module() const
const std::vector< Gate * > & get_gates() const
std::string get_name() const
std::vector< PinGroup< ModulePin > * > get_pin_groups(const std::function< bool(PinGroup< ModulePin > *)> &filter=nullptr) const
std::vector< Module * > get_submodules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=false) const
std::string get_type() const
static ProjectManager * instance()
const ProjectDirectory & get_project_directory() const
#define log_error(channel,...)
#define log_info(channel,...)
#define log_critical(channel,...)
#define log_warning(channel,...)
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)
std::error_code error_code
std::string enum_to_string(T e)
std::vector< PinInformation > pins
#define DURATION(begin_time)
#define JSON_STR_HELPER(x)
const int SERIALIZATION_FORMAT_VERSION