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_parameters(
const std::unordered_map<std::string, std::pair<Parameter, std::string>>& params, rapidjson::Document::AllocatorType& allocator)
101 rapidjson::Value out(rapidjson::kObjectType);
102 for (
const auto& [pname, decl_and_value] : params)
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());
108 entry.AddMember(
"size",
static_cast<u32>(decl.get_size()), allocator);
109 entry.AddMember(
"default",
JSON_STR_HELPER(decl.get_default_value()), allocator);
112 rapidjson::Value enum_values(rapidjson::kArrayType);
113 for (
const auto& v : decl.get_enum_values())
117 entry.AddMember(
"enum_values", enum_values, allocator);
127 Result<Parameter> deserialize_parameter_decl(
const std::string&
name,
const rapidjson::Value& entry)
129 if (!entry.HasMember(
"type") || !entry.HasMember(
"value"))
131 return ERR(
"parameter '" +
name +
"' is missing 'type' or 'value'");
133 const std::string type_str = entry[
"type"].GetString();
134 if (!is_valid_enum<Parameter::Type>(type_str))
136 return ERR(
"parameter '" +
name +
"' has unknown type '" + type_str +
"'");
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{};
146 const u16 size = (entry.HasMember(
"size") && entry[
"size"].IsUint()) ?
static_cast<u16>(entry[
"size"].GetUint()) : 0;
150 const u16 size = (entry.HasMember(
"size") && entry[
"size"].IsUint()) ?
static_cast<u16>(entry[
"size"].GetUint()) : 0;
166 std::vector<std::string> values;
167 if (entry.HasMember(
"enum_values") && entry[
"enum_values"].IsArray())
169 for (
const auto& v : entry[
"enum_values"].GetArray())
173 return ERR(
"parameter '" +
name +
"' has non-string entry in 'enum_values'");
175 values.emplace_back(v.GetString());
181 return ERR(
"parameter '" +
name +
"' has unhandled type");
186 Result<std::monostate> deserialize_parameters(DataContainer* c,
const rapidjson::Value& val)
188 for (
auto p_it = val.MemberBegin(); p_it != val.MemberEnd(); ++p_it)
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())
194 return ERR(decl_res.get_error().get());
196 if (
auto res = c->set_parameter(decl_res.get(), p_it->value[
"value"].GetString()); res.is_error())
198 return ERR(
"failed to set parameter '" + pname +
"': " + res.get_error().get());
205 rapidjson::Value serialize(
const Endpoint* ep, rapidjson::Document::AllocatorType& allocator)
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);
213 bool deserialize_destination(Netlist* nl, Net*
net,
const rapidjson::Value& val)
215 Gate* gate = nl->get_gate_by_id(val[
"gate_id"].GetUint());
218 if (val.HasMember(
"pin_id"))
220 const u32 pin_id = val[
"pin_id"].GetUint();
221 pin = gate->get_type()->get_pin_by_id(pin_id);
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));
230 if (encoded_format_version <= 12)
233 if (
const auto [group,
index] = pin->get_group(); group->size() > 1)
236 u32 len = group->size();
241 if (
const auto pin_res = group->get_pin_at_index(target_index); pin_res.is_error())
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());
259 const std::string pin_name = val[
"pin_type"].GetString();
260 pin = gate->get_type()->get_pin_by_name(pin_name);
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 +
"'");
269 if (!
net->add_destination(gate, pin))
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()));
279 bool deserialize_source(Netlist* nl, Net*
net,
const rapidjson::Value& val)
281 Gate* gate = nl->get_gate_by_id(val[
"gate_id"].GetUint());
284 if (val.HasMember(
"pin_id"))
286 const u32 pin_id = val[
"pin_id"].GetUint();
287 pin = gate->get_type()->get_pin_by_id(pin_id);
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));
295 if (encoded_format_version <= 12)
298 if (
const auto [group,
index] = pin->get_group(); group->size() > 1)
301 u32 len = group->size();
306 if (
const auto pin_res = group->get_pin_at_index(target_index); pin_res.is_error())
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());
324 const std::string pin_name = val[
"pin_type"].GetString();
325 pin = gate->get_type()->get_pin_by_name(pin_name);
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 +
"'");
334 if (
net->add_source(gate, pin) ==
nullptr)
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()));
345 rapidjson::Value serialize(
const Gate* gate, rapidjson::Document::AllocatorType& allocator)
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())
353 val.AddMember(
"location_x", gate->get_location_x(), allocator);
354 val.AddMember(
"location_y", gate->get_location_y(), allocator);
356 auto data = serialize(gate->get_data_map(), allocator);
359 val.AddMember(
"data", data, allocator);
361 if (
const auto& params = gate->get_parameters(); !params.empty())
363 val.AddMember(
"parameters", serialize_parameters(params, allocator), allocator);
366 rapidjson::Value functions(rapidjson::kObjectType);
367 for (
const auto& [
name,
function] : gate->get_boolean_functions(
true))
369 const std::string function_str =
function.to_string();
372 if (functions.MemberCount() > 0)
374 val.AddMember(
"custom_functions", functions, allocator);
383 void migrate_generic_data_to_parameters(DataContainer* c,
const GateType* gate_type =
nullptr)
385 std::vector<std::pair<std::string, std::string>> to_delete;
387 for (
const auto& [key_tuple, value_tuple] : c->get_data_map())
389 if (std::get<0>(key_tuple) !=
"generic")
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);
396 std::string migrated_value = raw_value;
397 Result<Parameter> inferred_decl =
ERR(
"unrecognized data type '" + type_str +
"'");
400 if (type_str ==
"boolean")
404 else if (type_str ==
"integer")
408 else if (type_str ==
"floating_point")
412 else if (type_str ==
"time")
416 else if (type_str ==
"string")
420 else if (type_str ==
"bit_value" || type_str ==
"std_logic")
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')
429 log_warning(
"netlist_persistent",
"skipping migration of generic data entry '{}': empty value",
name);
434 migrated_value = std::string(
"0b") + bit_char;
435 inferred_decl = (bit_char ==
'0' || bit_char ==
'1')
440 else if (type_str ==
"bit_vector" || type_str ==
"std_logic_vector")
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())
448 log_warning(
"netlist_persistent",
"skipping migration of generic data entry '{}': empty vector value",
name);
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);
460 log_warning(
"netlist_persistent",
"skipping migration of generic data entry '{}': zero-size vector",
name);
465 inferred_decl = (type_str ==
"std_logic_vector")
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")
484 if (inferred_decl.is_error())
486 log_warning(
"netlist_persistent",
"skipping migration of generic data entry '{}' (type '{}'): {}",
name, type_str, inferred_decl.get_error().get());
491 Result<Parameter> final_decl = inferred_decl;
492 if (gate_type !=
nullptr)
494 if (
auto gt_res = gate_type->get_parameter(
name); gt_res.is_ok())
498 if (
auto res = c->set_parameter(final_decl.get(), migrated_value); res.is_error())
500 log_warning(
"netlist_persistent",
"skipping migration of generic data entry '{}': {}",
name, res.get_error().get());
504 to_delete.emplace_back(std::get<0>(key_tuple),
name);
507 for (
const auto& [cat, key] : to_delete)
508 c->delete_data(cat, key);
511 bool deserialize_gate(Netlist* nl,
const rapidjson::Value& val,
const std::unordered_map<std::string, hal::GateType*>& gate_types)
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();
518 if (val.HasMember(
"location_x") && val.HasMember(
"location_y"))
520 lx = val[
"location_x"].GetInt();
521 ly = val[
"location_y"].GetInt();
523 if (
auto it = gate_types.find(gate_type); it != gate_types.end())
525 auto gate = nl->create_gate(gate_id, it->second, gate_name, lx, ly);
528 log_error(
"netlist_persistent",
"could not deserialize gate '" + gate_name +
"' with ID " + std::to_string(gate_id) +
": failed to create gate");
532 if (val.HasMember(
"data"))
534 deserialize_data(gate, val[
"data"]);
537 if (val.HasMember(
"parameters"))
539 if (
auto res = deserialize_parameters(gate, val[
"parameters"]); res.is_error())
541 log_error(
"netlist_persistent",
"could not deserialize gate '" + gate_name +
"' with ID " + std::to_string(gate_id) +
": {}", res.get_error().get());
547 migrate_generic_data_to_parameters(gate, it->second);
550 if (val.HasMember(
"custom_functions"))
552 auto functions = val[
"custom_functions"].GetObject();
553 for (
auto f_it = functions.MemberBegin(); f_it != functions.MemberEnd(); ++f_it)
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());
563 gate->add_boolean_function(f_it->name.GetString(), func.get());
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() +
"'");
577 rapidjson::Value serialize(
const Net*
net, rapidjson::Document::AllocatorType& allocator)
579 rapidjson::Value val(rapidjson::kObjectType);
580 val.AddMember(
"id",
net->get_id(), allocator);
581 val.AddMember(
"name",
net->get_name(), allocator);
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)
589 srcs.PushBack(serialize(src, allocator), allocator);
593 val.AddMember(
"srcs", srcs, allocator);
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)
603 dsts.PushBack(serialize(dst, allocator), allocator);
607 val.AddMember(
"dsts", dsts, allocator);
611 auto data = serialize(
net->get_data_map(), allocator);
614 val.AddMember(
"data", data, allocator);
616 if (
const auto& params =
net->get_parameters(); !params.empty())
618 val.AddMember(
"parameters", serialize_parameters(params, allocator), allocator);
623 bool deserialize_net(Netlist* nl,
const rapidjson::Value& val)
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);
630 log_error(
"netlist_persistent",
"could not deserialize net '" + net_name +
"' with ID " + std::to_string(net_id) +
": failed to create net");
634 if (val.HasMember(
"srcs"))
636 for (
const auto& src_node : val[
"srcs"].GetArray())
638 if (!deserialize_source(nl,
net, src_node))
640 log_error(
"netlist_persistent",
"could not deserialize net '" + net_name +
"' with ID " + std::to_string(net_id) +
": failed to deserialize source");
646 if (val.HasMember(
"dsts"))
648 for (
const auto& dst_node : val[
"dsts"].GetArray())
650 if (!deserialize_destination(nl,
net, dst_node))
652 log_error(
"netlist_persistent",
"could not deserialize net '" + net_name +
"' with ID " + std::to_string(net_id) +
": failed to deserialize destination");
658 if (val.HasMember(
"data"))
660 deserialize_data(
net, val[
"data"]);
663 if (val.HasMember(
"parameters"))
665 if (
auto res = deserialize_parameters(
net, val[
"parameters"]); res.is_error())
667 log_error(
"netlist_persistent",
"could not deserialize net '" + net_name +
"' with ID " + std::to_string(net_id) +
": {}", res.get_error().get());
676 rapidjson::Value serialize(
const Module*
module, rapidjson::Document::AllocatorType& allocator)
678 rapidjson::Value val(rapidjson::kObjectType);
683 if (parent ==
nullptr)
685 val.AddMember(
"parent", 0, allocator);
689 val.AddMember(
"parent", parent->get_id(), allocator);
692 rapidjson::Value gates(rapidjson::kArrayType);
694 std::sort(sorted.begin(), sorted.end(), [](Gate* lhs, Gate* rhs) { return lhs->get_id() < rhs->get_id(); });
695 for (
const Gate* g : sorted)
697 gates.PushBack(g->get_id(), allocator);
701 val.AddMember(
"gates", gates, allocator);
705 rapidjson::Value json_pin_groups(rapidjson::kArrayType);
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())
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);
726 json_pin_group.AddMember(
"pins", json_pins, allocator);
727 json_pin_groups.PushBack(json_pin_group, allocator);
729 if (!json_pin_groups.Empty())
731 val.AddMember(
"pin_groups", json_pin_groups, allocator);
738 val.AddMember(
"data", data, allocator);
742 val.AddMember(
"parameters", serialize_parameters(params, allocator), allocator);
747 bool deserialize_module(Netlist* nl,
const rapidjson::Value& val, std::unordered_map<Module*, std::vector<PinGroupInformation>>& pin_group_cache)
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();
757 const std::string top_module_name = val[
"name"].GetString();
758 if (top_module_name != sm->get_name())
760 sm->set_name(top_module_name);
765 sm = nl->create_module(module_id, module_name, nl->get_module_by_id(parent_id));
768 log_error(
"netlist_persistent",
"could not deserialize module '" + module_name +
"' with ID " + std::to_string(module_id) +
": failed to create module");
773 if (val.HasMember(
"type"))
775 sm->set_type(val[
"type"].GetString());
778 if (val.HasMember(
"gates"))
780 std::vector<Gate*> gates;
781 for (
auto& gate_node : val[
"gates"].GetArray())
783 if (!sm->is_top_module())
785 gates.push_back(nl->get_gate_by_id(gate_node.GetUint()));
788 sm->assign_gates(gates);
791 if (val.HasMember(
"data"))
793 deserialize_data(sm, val[
"data"]);
796 if (val.HasMember(
"parameters"))
798 if (
auto res = deserialize_parameters(sm, val[
"parameters"]); res.is_error())
800 log_error(
"netlist_persistent",
"could not deserialize module '" + module_name +
"' with ID " + std::to_string(module_id) +
": {}", res.get_error().get());
806 migrate_generic_data_to_parameters(sm);
809 if (val.HasMember(
"pin_groups"))
812 for (
const auto& json_pin_group : val[
"pin_groups"].GetArray())
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"))
819 pin_group.direction = enum_from_string<PinDirection>(json_pin_group[
"direction"].GetString());
825 if (json_pin_group.HasMember(
"type"))
827 pin_group.type = enum_from_string<PinType>(json_pin_group[
"type"].GetString());
833 if (json_pin_group.HasMember(
"ordered"))
835 pin_group.ordered = json_pin_group[
"ordered"].GetBool();
841 pin_group.ascending = json_pin_group[
"ascending"].GetBool();
842 pin_group.start_index = json_pin_group[
"start_index"].GetUint();
844 for (
const auto& pin_node : json_pin_group[
"pins"].GetArray())
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);
853 pin_group_cache[sm].push_back(pin_group);
858 if (val.HasMember(
"input_ports"))
860 for (
const auto& json_pin_legacy : val[
"input_ports"].GetArray())
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);
872 if (val.HasMember(
"output_ports"))
874 for (
const auto& json_pin_legacy : val[
"output_ports"].GetArray())
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);
890 bool deserialize_module_pins(
const std::unordered_map<Module*, std::vector<PinGroupInformation>>& pin_group_cache)
892 for (
const auto& [sm, pin_groups] : pin_group_cache)
894 for (
const PinGroupInformation& pg : pin_groups)
896 std::vector<ModulePin*>
pins;
897 for (
const PinGroupInformation::PinInformation& p : pg.pins)
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())
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());
909 pins.push_back(res.get());
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())
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());
927 void serialize(
const Netlist* nl, rapidjson::Document& document)
929 rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
930 rapidjson::Value root(rapidjson::kObjectType);
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);
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)
946 gates.PushBack(serialize(gate, allocator), allocator);
948 if (nl->is_gnd_gate(gate))
950 global_gnds.PushBack(gate->get_id(), allocator);
953 if (nl->is_vcc_gate(gate))
955 global_vccs.PushBack(gate->get_id(), allocator);
958 root.AddMember(
"gates", gates, allocator);
959 root.AddMember(
"global_vcc", global_vccs, allocator);
960 root.AddMember(
"global_gnd", global_gnds, allocator);
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)
970 nets.PushBack(serialize(
net, allocator), allocator);
972 if (nl->is_global_input_net(
net))
974 global_in.PushBack(
net->get_id(), allocator);
977 if (nl->is_global_output_net(
net))
979 global_out.PushBack(
net->get_id(), allocator);
982 root.AddMember(
"nets", nets, allocator);
983 root.AddMember(
"global_in", global_in, allocator);
984 root.AddMember(
"global_out", global_out, allocator);
987 rapidjson::Value modules(rapidjson::kArrayType);
990 std::queue<const Module*> q;
991 q.push(nl->get_top_module());
997 modules.PushBack(serialize(
module, allocator), allocator);
1004 root.AddMember(
"modules", modules, allocator);
1007 document.AddMember(
"netlist", root, document.GetAllocator());
1010 std::unique_ptr<Netlist> deserialize(
const rapidjson::Document& document, GateLibrary* gatelib)
1012 if (!document.HasMember(
"netlist"))
1014 log_error(
"netlist_persistent",
"could not deserialize netlist: file has no 'netlist' node");
1017 auto root = document[
"netlist"].GetObject();
1022 if (!root.HasMember(
"gate_library"))
1024 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'gate_library'");
1028 std::filesystem::path glib_path(root[
"gate_library"].GetString());
1030 if (glib_path.is_relative())
1035 glib_path = pm->get_project_directory() / glib_path;
1040 if (gatelib ==
nullptr)
1043 if (glib_path.extension() ==
".hgl")
1045 glib_path.replace_extension(
".lib");
1049 glib_path.replace_extension(
".hgl");
1053 if (gatelib ==
nullptr)
1055 log_critical(
"netlist_persistent",
"could not deserialize netlist: failed to load gate library '" + std::string(root[
"gate_library"].GetString()) +
"'");
1060 log_info(
"netlist_persistent",
"gate library '{}' required but using '{}' instead.", root[
"gate_library"].GetString(), glib_path.string());
1065 auto nl = std::make_unique<Netlist>(gatelib);
1068 nl->enable_automatic_net_checks(
false);
1070 if (!root.HasMember(
"id"))
1072 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'id'");
1075 nl->set_id(root[
"id"].GetUint());
1077 if (!root.HasMember(
"input_file"))
1079 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'input_file'");
1082 nl->set_input_filename(root[
"input_file"].GetString());
1084 if (!root.HasMember(
"design_name"))
1086 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'design_name'");
1089 nl->set_design_name(root[
"design_name"].GetString());
1091 if (!root.HasMember(
"device_name"))
1093 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'device_name'");
1096 nl->set_device_name(root[
"device_name"].GetString());
1098 if (!root.HasMember(
"gates"))
1100 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'gates'");
1103 auto gate_types = nl->get_gate_library()->get_gate_types();
1104 for (
auto& gate_node : root[
"gates"].GetArray())
1106 if (!deserialize_gate(nl.get(), gate_node, gate_types))
1108 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to deserialize gate");
1113 if (!root.HasMember(
"global_vcc"))
1115 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'global_vcc'");
1118 for (
auto& gate_node : root[
"global_vcc"].GetArray())
1120 if (!nl->mark_vcc_gate(nl->get_gate_by_id(gate_node.GetUint())))
1122 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to mark VCC gate");
1127 if (!root.HasMember(
"global_gnd"))
1129 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'global_gnd'");
1132 for (
auto& gate_node : root[
"global_gnd"].GetArray())
1134 if (!nl->mark_gnd_gate(nl->get_gate_by_id(gate_node.GetUint())))
1136 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to mark GND gate");
1141 if (!root.HasMember(
"nets"))
1143 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'nets'");
1146 for (
auto& net_node : root[
"nets"].GetArray())
1148 if (!deserialize_net(nl.get(), net_node))
1150 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to deserialize net");
1155 if (!root.HasMember(
"global_in"))
1157 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'global_in'");
1160 for (
auto& net_node : root[
"global_in"].GetArray())
1162 if (!nl->mark_global_input_net(nl->get_net_by_id(net_node.GetUint())))
1164 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to mark global input net");
1169 if (!root.HasMember(
"global_out"))
1171 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'global_out'");
1174 for (
auto& net_node : root[
"global_out"].GetArray())
1176 if (!nl->mark_global_output_net(nl->get_net_by_id(net_node.GetUint())))
1178 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to mark global output net");
1183 if (!root.HasMember(
"modules"))
1185 log_error(
"netlist_persistent",
"could not deserialize netlist: node 'netlist' has no node 'modules'");
1188 std::unordered_map<Module*, std::vector<PinGroupInformation>> pin_group_cache;
1189 for (
auto& module_node : root[
"modules"].GetArray())
1191 if (!deserialize_module(nl.get(), module_node, pin_group_cache))
1193 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to deserialize module");
1199 for (Module* mod : nl->get_modules())
1205 if (!deserialize_module_pins(pin_group_cache))
1207 log_error(
"netlist_persistent",
"could not deserialize netlist: failed to deserialize module pins");
1212 nl->enable_automatic_net_checks(
true);
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)
1220 if (document.HasParseError())
1222 log_error(
"netlist_persistent",
"invalid json string for deserialization");
1226 if (document.HasMember(
"serialization_format_version"))
1228 encoded_format_version = document[
"serialization_format_version"].GetUint();
1231 log_warning(
"netlist_persistent",
"the netlist was serialized with an older version of the serializer, deserialization may contain errors.");
1235 log_warning(
"netlist_persistent",
"the netlist was serialized with a newer version of the serializer, deserialization may contain errors.");
1240 log_warning(
"netlist_persistent",
"the netlist was serialized with an older version of the serializer, deserialization may contain errors.");
1243 auto netlist = deserialize(document, gatelib);
1247 log_info(
"netlist_persistent",
"deserialized '{}' in {:2.2f} seconds", source,
DURATION(begin_time));
1263 auto begin_time = std::chrono::high_resolution_clock::now();
1265 std::filesystem::path serialize_to_dir = hal_file.parent_path();
1266 if (serialize_to_dir.empty())
1271 if (serialize_to_dir.is_relative())
1277 if (!std::filesystem::exists(serialize_to_dir))
1280 if (!std::filesystem::create_directories(serialize_to_dir, err))
1282 log_error(
"netlist_persistent",
"Could not create directory '{}', error was '{}'.", serialize_to_dir.string(), err.message());
1287 std::ofstream hal_file_stream;
1288 hal_file_stream.open(hal_file.string());
1289 if (hal_file_stream.fail())
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());
1295 rapidjson::Document document;
1296 document.SetObject();
1300 serialize(nl, document);
1302 rapidjson::StringBuffer strbuf;
1303 #if PRETTY_JSON_OUTPUT == 1
1304 rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(strbuf);
1306 rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
1308 document.Accept(writer);
1310 hal_file_stream << strbuf.GetString();
1312 hal_file_stream.close();
1314 log_info(
"netlist_persistent",
"serialized netlist in {:2.2f} seconds",
DURATION(begin_time));
1321 auto begin_time = std::chrono::high_resolution_clock::now();
1325 FILE* pFile = fopen(hal_file.string().c_str(),
"rb");
1328 log_error(
"netlist_persistent",
"unable to open '{}'.", hal_file.string());
1333 rapidjson::FileReadStream is(pFile, buffer,
sizeof(buffer));
1334 rapidjson::Document document;
1335 document.ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(is);
1338 return deserialize_document(document, gatelib, hal_file.string(), begin_time);
1343 auto begin_time = std::chrono::high_resolution_clock::now();
1347 rapidjson::Document document;
1348 document.Parse<0, rapidjson::UTF8<>>(hal_string.c_str());
1350 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
const std::unordered_map< std::string, std::pair< Parameter, std::string > > & get_parameters() 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
static Result< Parameter > Boolean(const std::string &name, const std::string &default_value)
static Result< Parameter > BitVector(const std::string &name, u16 size, const std::string &default_value)
static Result< Parameter > Integer(const std::string &name, const std::string &default_value)
static Result< Parameter > String(const std::string &name, const std::string &default_value)
static Result< Parameter > LogicVector(const std::string &name, u16 size, const std::string &default_value)
static Result< Parameter > Time(const std::string &name, const std::string &default_value)
static Result< Parameter > Enum(const std::string &name, const std::vector< std::string > &values, const std::string &default_value)
static Result< Parameter > Float(const std::string &name, const std::string &default_value)