12 #include "rapidjson/filereadstream.h"
13 #include "rapidjson/stringbuffer.h"
21 FILE* fp = fopen(file_path.string().c_str(),
"r");
24 return ERR(
"could not parse HGL file '" + m_path.string() +
"' : unable to open file");
28 rapidjson::FileReadStream is(fp, buffer,
sizeof(buffer));
29 rapidjson::Document document;
30 document.ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(is);
33 if (document.HasParseError())
35 return ERR(
"could not parse HGL file '" + m_path.string() +
"': failed parsing JSON format");
38 if (
auto res = parse_gate_library(document); res.is_error())
40 return ERR_APPEND(res.get_error(),
"could not parse HGL file '" + m_path.string() +
"': failed to parse gate library");
43 return OK(std::move(m_gate_lib));
48 if (!document.HasMember(
"version") || !document[
"version"].IsUint() || document[
"version"].GetUint() < HGL_FORMAT_VERSION)
50 log_warning(
"hgl_parser",
"you are using an outdated HGL file format that might not support all features, please make sure to re-write the HGL file using the HAL HGL writer.");
53 if (document.HasMember(
"version") && document[
"version"].IsUint())
55 file_version = document[
"version"].GetUint();
58 if (!document.HasMember(
"library"))
60 return ERR(
"could not parse gate library: missing 'library' node");
63 const std::string gate_lib_name = document[
"library"].GetString();
64 m_gate_lib = std::make_unique<GateLibrary>(m_path, gate_lib_name);
66 if (document.HasMember(
"gate_locations") && document[
"gate_locations"].IsObject())
68 auto gate_locs = document[
"gate_locations"].GetObject();
70 if (!gate_locs.HasMember(
"data_category") || !gate_locs[
"data_category"].IsString())
72 return ERR(
"could not parse gate library '" + gate_lib_name +
"': missing 'data_category' entry for gate locations");
75 if (!gate_locs.HasMember(
"data_x_identifier") || !gate_locs[
"data_x_identifier"].IsString())
77 return ERR(
"could not parse gate library '" + gate_lib_name +
"': missing 'data_x_identifier' entry for gate locations");
80 if (!gate_locs.HasMember(
"data_y_identifier") || !gate_locs[
"data_y_identifier"].IsString())
82 return ERR(
"could not parse gate library '" + gate_lib_name +
"': missing 'data_y_identifier' entry for gate locations");
85 m_gate_lib->set_gate_location_data_category(gate_locs[
"data_category"].GetString());
86 m_gate_lib->set_gate_location_data_identifiers(gate_locs[
"data_x_identifier"].GetString(), gate_locs[
"data_y_identifier"].GetString());
89 if (!document.HasMember(
"cells"))
91 return ERR(
"could not parse gate library '" + gate_lib_name +
"': missing 'cells' node");
94 for (
const auto& gate_type : document[
"cells"].GetArray())
96 if (
auto res = parse_gate_type(gate_type); res.is_error())
98 return ERR_APPEND(res.get_error(),
"could not parse gate library '" + gate_lib_name +
"': failed parsing gate type");
105 Result<std::monostate> HGLParser::parse_gate_type(
const rapidjson::Value& gate_type)
107 if (!gate_type.HasMember(
"name") || !gate_type[
"name"].IsString())
109 return ERR(
"could not parse gate type: missing or invalid name");
112 const std::string
name = gate_type[
"name"].GetString();
113 std::set<GateTypeProperty> properties;
114 if (gate_type.HasMember(
"types") && gate_type[
"types"].IsArray())
116 for (
const auto& base_type : gate_type[
"types"].GetArray())
118 const std::string property_str = base_type.GetString();
122 GateTypeProperty property = enum_from_string<GateTypeProperty>(property_str);
123 properties.insert(property);
125 catch (
const std::runtime_error&)
128 if (property_str ==
"buffer")
132 else if (property_str ==
"carry")
136 else if (property_str ==
"mux")
140 else if (property_str ==
"lut")
146 return ERR(
"could not parse gate type '" +
name +
"': invalid property '" + base_type.GetString() +
"'");
156 std::unique_ptr<GateTypeComponent> parent_component =
nullptr;
157 if (gate_type.HasMember(
"lut_config") && gate_type[
"lut_config"].IsObject())
159 if (
auto res = parse_lut_config(gate_type[
"lut_config"]); res.is_error())
161 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"': failed parsing LUT configuration");
165 parent_component = res.get();
168 else if (gate_type.HasMember(
"ff_config") && gate_type[
"ff_config"].IsObject())
170 if (
auto res = parse_ff_config(gate_type[
"ff_config"]); res.is_error())
172 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"': failed parsing FF configuration");
176 parent_component = res.get();
179 else if (gate_type.HasMember(
"latch_config") && gate_type[
"latch_config"].IsObject())
181 if (
auto res = parse_latch_config(gate_type[
"latch_config"]); res.is_error())
183 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"': failed parsing latch configuration");
187 parent_component = res.get();
190 else if (gate_type.HasMember(
"ram_config") && gate_type[
"ram_config"].IsObject())
192 if (
auto res = parse_ram_config(gate_type[
"ram_config"]); res.is_error())
194 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"': failed parsing RAM configuration");
198 parent_component = res.get();
202 GateType* gt = m_gate_lib->create_gate_type(
name, properties, std::move(parent_component));
205 return ERR(
"could not parse gate type '" +
name +
"': failed to create gate type");
208 if (file_version >= 2)
210 if (gate_type.HasMember(
"pin_groups") && gate_type[
"pin_groups"].IsArray())
212 for (
const auto& pg_val : gate_type[
"pin_groups"].GetArray())
214 if (!pg_val.HasMember(
"name") || !pg_val[
"name"].IsString())
216 return ERR(
"could not parse pin group: missing or invalid name");
218 std::string pg_name = pg_val[
"name"].GetString();
220 if (!pg_val.HasMember(
"direction") || !pg_val[
"direction"].IsString())
222 return ERR(
"could not parse pin group '" + pg_name +
"': missing or invalid pin direction");
225 std::string pg_direction_str = pg_val[
"direction"].GetString();
228 pg_direction = enum_from_string<PinDirection>(pg_direction_str);
230 catch (
const std::runtime_error&)
232 return ERR(
"could not parse pin '" + pg_name +
"': invalid pin direction '" + pg_direction_str +
"'");
235 if (!pg_val.HasMember(
"type") || !pg_val[
"type"].IsString())
237 return ERR(
"could not parse pin group '" + pg_name +
"': missing or invalid pin type");
240 std::string pg_type_str = pg_val[
"type"].GetString();
243 pg_type = enum_from_string<PinType>(pg_type_str);
245 catch (
const std::runtime_error&)
247 return ERR(
"could not parse pin group '" + pg_name +
"': invalid pin type '" + pg_type_str +
"'");
250 if (!pg_val.HasMember(
"ascending") || !pg_val[
"ascending"].IsBool())
252 return ERR(
"could not parse pin group '" + pg_name +
"': missing or ascending property");
254 bool ascending = pg_val[
"ascending"].GetBool();
257 if (pg_val.HasMember(
"ordered") && pg_val[
"ordered"].IsBool())
259 ordered = pg_val[
"ordered"].GetBool();
262 if (!pg_val.HasMember(
"start_index") || !pg_val[
"start_index"].IsUint())
264 return ERR(
"could not parse pin group '" + pg_name +
"': missing or start index");
268 if (pg_val.HasMember(
"pins") && pg_val[
"pins"].IsArray())
270 std::vector<GatePin*>
pins;
272 for (
const auto& p_val : pg_val[
"pins"].GetArray())
274 if (!p_val.HasMember(
"name") || !p_val[
"name"].IsString())
276 return ERR(
"could not parse pin: missing or invalid name");
278 std::string p_name = p_val[
"name"].GetString();
280 if (!p_val.HasMember(
"direction") || !p_val[
"direction"].IsString())
282 return ERR(
"could not parse pin '" + p_name +
"': missing or invalid pin direction");
285 std::string p_direction_str = p_val[
"direction"].GetString();
288 p_direction = enum_from_string<PinDirection>(p_direction_str);
290 catch (
const std::runtime_error&)
292 return ERR(
"could not parse pin '" + p_name +
"': invalid pin direction '" + p_direction_str +
"'");
296 if (p_val.HasMember(
"type") && p_val[
"type"].IsString())
298 std::string p_type_str = p_val[
"type"].GetString();
301 p_type = enum_from_string<PinType>(p_type_str);
303 catch (
const std::runtime_error&)
305 return ERR(
"could not parse pin '" + p_name +
"': invalid pin type '" + p_type_str +
"'");
313 auto p_res = gt->create_pin(p_name, p_direction, p_type,
false);
314 if (p_res.is_error())
316 return ERR_APPEND(p_res.get_error(),
"could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed to create pin '" + p_name +
"'");
318 pins.push_back(p_res.get());
320 if (p_val.HasMember(
"function") && p_val[
"function"].IsString())
325 "could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed parsing Boolean function with name '" + p_name
330 gt->add_boolean_function(p_name, res.get());
334 if (p_val.HasMember(
"x_function") && p_val[
"x_function"].IsString())
339 "could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed parsing Boolean function with name '" + p_name
340 +
"_undefined' from string");
344 gt->add_boolean_function(p_name +
"_undefined", res.get());
348 if (p_val.HasMember(
"z_function") && p_val[
"z_function"].IsString())
353 "could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed parsing Boolean function with name '" + p_name
354 +
"_tristate' from string");
358 gt->add_boolean_function(p_name +
"_tristate", res.get());
364 if (pg_res.is_error())
367 "could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed to create pin group '" + pg_name +
"'");
372 return ERR(
"could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": no pins given for pin group with name '" + pg_name +
"'");
377 else if (file_version < 2)
379 std::map<std::string, std::string> pins_to_groups;
380 std::map<std::string, GroupCtx> groups_to_pins;
382 if (gate_type.HasMember(
"groups") && gate_type[
"groups"].IsArray())
384 for (
const auto& group_val : gate_type[
"groups"].GetArray())
388 if (!group_val.HasMember(
"name") || !group_val[
"name"].IsString())
390 return ERR(
"could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": missing or invalid pin group name");
393 pg_name = group_val[
"name"].GetString();
394 if (!group_val.HasMember(
"pins") || !group_val[
"pins"].IsArray())
396 return ERR(
"could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": missing or invalid pins for pin group '" + pg_name +
"'");
402 std::vector<std::string>
pins;
403 GroupCtx pin_group_info;
404 for (
const auto& pin_obj : group_val[
"pins"].GetArray())
406 if (!pin_obj.IsObject())
408 return ERR(
"could not parse pin group '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": invalid pin group assignment");
410 const auto pin_val = pin_obj.GetObject().MemberBegin();
411 u32 pin_index = std::stoul(pin_val->name.GetString());
412 std::string pin_name = pin_val->value.GetString();
413 pin_group_info.pins.push_back(pin_name);
414 pins_to_groups[pin_name] = pg_name;
435 pin_group_info.ascending = (
direction == 1) ?
true :
false;
436 pin_group_info.start_index = start;
442 groups_to_pins[pg_name] = pin_group_info;
447 if (gate_type.HasMember(
"pins") && gate_type[
"pins"].IsArray())
449 for (
const auto& pin : gate_type[
"pins"].GetArray())
451 if (
auto res = parse_pin(pin_ctx, pin); res.is_error())
453 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed parsing pin");
458 for (
const auto& pin_name : pin_ctx.pins)
460 if (
const auto it = pins_to_groups.find(pin_name); it == pins_to_groups.end())
462 if (
auto res = gt->create_pin(pin_name, pin_ctx.pin_to_direction.at(pin_name), pin_ctx.pin_to_type.at(pin_name),
true); res.is_error())
464 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed to create pin '" + pin_name);
469 if (gt->get_pin_group_by_name(it->second) !=
nullptr)
474 std::vector<GatePin*>
pins;
475 auto pg_info = groups_to_pins.at(it->second);
476 for (
const auto& p_name : pg_info.pins)
478 if (
auto res = gt->create_pin(p_name, pin_ctx.pin_to_direction.at(p_name), pin_ctx.pin_to_type.at(p_name),
false); res.is_error())
480 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed to create pin '" + p_name);
484 pins.push_back(res.get());
487 if (
auto res = gt->create_pin_group(it->second,
pins,
pins.front()->get_direction(),
pins.front()->get_type(), pg_info.ascending, pg_info.start_index); res.is_error())
489 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed to create pin group '" + it->second);
494 for (
const auto& [f_name, func] : pin_ctx.boolean_functions)
499 "could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed parsing Boolean function with name '" + f_name +
"' from string");
503 gt->add_boolean_function(f_name, res.get());
511 Result<std::monostate> HGLParser::parse_pin(PinCtx& pin_ctx,
const rapidjson::Value& pin)
513 if (!pin.HasMember(
"name") || !pin[
"name"].IsString())
515 return ERR(
"could not parse pin: missing or invalid name");
518 std::string
name = pin[
"name"].GetString();
519 if (!pin.HasMember(
"direction") || !pin[
"direction"].IsString())
521 return ERR(
"could not parse pin '" +
name +
"': missing or invalid pin direction");
524 std::string
direction = pin[
"direction"].GetString();
527 pin_ctx.pin_to_direction[
name] = enum_from_string<PinDirection>(
direction);
528 pin_ctx.pins.push_back(
name);
530 catch (
const std::runtime_error&)
532 return ERR(
"could not parse pin '" +
name +
"': invalid pin direction '" +
direction +
"'");
535 if (pin.HasMember(
"function") && pin[
"function"].IsString())
537 pin_ctx.boolean_functions[
name] = pin[
"function"].GetString();
540 if (pin.HasMember(
"x_function") && pin[
"x_function"].IsString())
542 pin_ctx.boolean_functions[
name +
"_undefined"] = pin[
"x_function"].GetString();
545 if (pin.HasMember(
"z_function") && pin[
"z_function"].IsString())
547 pin_ctx.boolean_functions[
name +
"_tristate"] = pin[
"z_function"].GetString();
550 if (pin.HasMember(
"type") && pin[
"type"].IsString())
552 std::string type_str = pin[
"type"].GetString();
555 pin_ctx.pin_to_type[
name] = enum_from_string<PinType>(type_str);
557 catch (
const std::runtime_error&)
559 return ERR(
"could not parse pin '" +
name +
"': invalid pin type '" + type_str +
"'");
570 Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_lut_config(
const rapidjson::Value& lut_config)
572 if (!lut_config.HasMember(
"bit_order") || !lut_config[
"bit_order"].IsString())
574 return ERR(
"could not parse LUT configuration: missing or invalid bit order");
577 if (!lut_config.HasMember(
"data_category") || !lut_config[
"data_category"].IsString())
579 return ERR(
"could not parse LUT configuration: missing or invalid data category for LUT initialization");
582 if (!lut_config.HasMember(
"data_identifier") || !lut_config[
"data_identifier"].IsString())
584 return ERR(
"could not parse LUT configuration: missing or invalid data identifier for LUT initialization");
591 Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_ff_config(
const rapidjson::Value& ff_config)
593 if (!ff_config.HasMember(
"state") || !ff_config[
"state"].IsString())
595 return ERR(
"could not parse flip-flop configuration: missing or invalid state identifier");
597 if (!ff_config.HasMember(
"neg_state") || !ff_config[
"neg_state"].IsString())
599 return ERR(
"could not parse flip-flop configuration: missing or invalid negated state identifier");
601 if (!ff_config.HasMember(
"next_state") || !ff_config[
"next_state"].IsString())
603 return ERR(
"could not parse flip-flop configuration: missing or invalid next state function");
605 if (!ff_config.HasMember(
"clocked_on") || !ff_config[
"clocked_on"].IsString())
607 return ERR(
"could not parse flip-flop configuration: missing or invalid clock function");
610 std::unique_ptr<GateTypeComponent> init_component =
nullptr;
611 if (ff_config.HasMember(
"data_category") && ff_config[
"data_category"].IsString())
613 std::vector<std::string> init_identifiers;
614 if (ff_config.HasMember(
"data_identifier") && ff_config[
"data_identifier"].IsString())
616 init_identifiers.push_back(ff_config[
"data_identifier"].GetString());
620 return ERR(
"could not parse flip-flop configuration: missing or invalid data identifier for flip-flop initialization");
624 else if (ff_config.HasMember(
"data_identifier") && ff_config[
"data_identifier"].IsString())
626 return ERR(
"could not parse flip-flop configuration: missing or invalid data category for flip-flop initialization");
629 std::string state_identifier = ff_config[
"state"].GetString();
630 std::string neg_state_identifier = ff_config[
"neg_state"].GetString();
632 assert(state_component !=
nullptr);
634 BooleanFunction next_state_function;
637 return ERR(
"could not parse flip-flop configuration: failed parsing next state function from string");
641 next_state_function = res.get();
643 BooleanFunction clocked_on_function;
646 return ERR(
"could not parse flip-flop configuration: failed parsing clock function from string");
650 clocked_on_function = res.get();
655 FFComponent* ff_component = component->convert_to<FFComponent>();
656 assert(ff_component !=
nullptr);
658 if (ff_config.HasMember(
"clear_on") && ff_config[
"clear_on"].IsString())
662 return ERR(
"could not parse flip-flop configuration: failed parsing asynchronous reset function from string");
666 ff_component->set_async_reset_function(res.get());
670 if (ff_config.HasMember(
"preset_on") && ff_config[
"preset_on"].IsString())
674 return ERR(
"could not parse flip-flop configuration: failed parsing asynchronous set function from string");
678 ff_component->set_async_set_function(res.get());
682 bool has_state = ff_config.HasMember(
"state_clear_preset") && ff_config[
"state_clear_preset"].IsString();
683 bool has_neg_state = ff_config.HasMember(
"neg_state_clear_preset") && ff_config[
"neg_state_clear_preset"].IsString();
685 if (has_state && has_neg_state)
695 return ERR(
"could not parse flip-flop configuration: failed parsing state on concurrent asynchronous set and reset from string");
704 return ERR(
"could not parse flip-flop configuration: failed parsing negated state on concurrent asynchronous set and reset from string");
707 ff_component->set_async_set_reset_behavior(cp1, cp2);
709 else if ((has_state && !has_neg_state) || (!has_state && has_neg_state))
711 return ERR(
"could not parse flip-flop configuration: missing state or negated state on concurrent asynchronous set and reset");
714 return OK(std::move(component));
717 Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_latch_config(
const rapidjson::Value& latch_config)
719 if (!latch_config.HasMember(
"state") || !latch_config[
"state"].IsString())
721 return ERR(
"could not parse latch configuration: missing or invalid state identifier");
723 if (!latch_config.HasMember(
"neg_state") || !latch_config[
"neg_state"].IsString())
725 return ERR(
"could not parse latch configuration: missing or invalid negated state identifier");
728 std::string state_identifier = latch_config[
"state"].GetString();
729 std::string neg_state_identifier = latch_config[
"neg_state"].GetString();
731 assert(state_component !=
nullptr);
734 LatchComponent* latch_component = component->convert_to<LatchComponent>();
735 assert(latch_component !=
nullptr);
737 if (latch_config.HasMember(
"data_in") && latch_config[
"data_in"].IsString() && latch_config.HasMember(
"enable_on") && latch_config[
"enable_on"].IsString())
741 return ERR(
"could not parse latch configuration: failed parsing data in function from string");
745 latch_component->set_data_in_function(res.get());
750 return ERR(
"could not parse latch configuration: failed parsing enable function from string");
754 latch_component->set_enable_function(res.get());
757 else if (latch_config.HasMember(
"data_in") && latch_config[
"data_in"].IsString())
759 return ERR(
"could not parse latch configuration: missing or invalid enable function");
761 else if (latch_config.HasMember(
"enable_on") && latch_config[
"enable_on"].IsString())
763 return ERR(
"could not parse latch configuration: missing or invalid data in function");
766 if (latch_config.HasMember(
"clear_on") && latch_config[
"clear_on"].IsString())
770 return ERR(
"could not parse latch configuration: failed parsing asynchronous reset function from string");
774 latch_component->set_async_reset_function(res.get());
778 if (latch_config.HasMember(
"preset_on") && latch_config[
"preset_on"].IsString())
782 return ERR(
"could not parse latch configuration: failed parsing asynchronous set function from string");
786 latch_component->set_async_set_function(res.get());
790 bool has_state = latch_config.HasMember(
"state_clear_preset") && latch_config[
"state_clear_preset"].IsString();
791 bool has_neg_state = latch_config.HasMember(
"neg_state_clear_preset") && latch_config[
"neg_state_clear_preset"].IsString();
793 if (has_state && has_neg_state)
803 return ERR(
"could not parse latch configuration: failed parsing state on concurrent asynchronous set and reset from string");
812 return ERR(
"could not parse latch configuration: failed parsing negated state on concurrent asynchronous set and reset from string");
815 latch_component->set_async_set_reset_behavior(cp1, cp2);
817 else if ((has_state && !has_neg_state) || (!has_state && has_neg_state))
819 return ERR(
"could not parse latch configuration: missing state or negated state on concurrent asynchronous set and reset");
822 return OK(std::move(component));
825 Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_ram_config(
const rapidjson::Value& ram_config)
827 std::unique_ptr<GateTypeComponent> sub_component =
nullptr;
828 if (ram_config.HasMember(
"data_category") && ram_config[
"data_category"].IsString())
830 std::vector<std::string> init_identifiers;
831 if (ram_config.HasMember(
"data_identifiers") && ram_config[
"data_identifiers"].IsArray())
834 for (
const auto& identifier : ram_config[
"data_identifiers"].GetArray())
836 init_identifiers.push_back(identifier.GetString());
841 return ERR(
"could not parse RAM configuration: missing or invalid data identifier for RAM initialization");
845 else if (ram_config.HasMember(
"data_identifiers") && ram_config[
"data_identifiers"].IsArray())
847 return ERR(
"could not parse RAM configuration: missing or invalid data category for RAM initialization");
850 if (!ram_config.HasMember(
"bit_size") || !ram_config[
"bit_size"].IsUint())
852 return ERR(
"could not parse RAM configuration: missing or invalid bit size");
855 if (!ram_config.HasMember(
"ram_ports") || !ram_config[
"ram_ports"].IsArray())
857 return ERR(
"could not parse RAM configuration: missing or invalid RAM ports");
860 for (
const auto& ram_port : ram_config[
"ram_ports"].GetArray())
862 if (!ram_port.HasMember(
"data_group") || !ram_port[
"data_group"].IsString())
864 return ERR(
"could not parse RAM configuration: missing or invalid data pin groups for RAM port");
867 if (!ram_port.HasMember(
"address_group") || !ram_port[
"address_group"].IsString())
869 return ERR(
"could not parse RAM configuration: missing or invalid address pin groups for RAM port");
872 if (!ram_port.HasMember(
"clocked_on") || !ram_port[
"clocked_on"].IsString())
874 return ERR(
"could not parse RAM configuration: missing or invalid clock function for RAM port");
877 if (!ram_port.HasMember(
"enabled_on") || !ram_port[
"enabled_on"].IsString())
879 return ERR(
"could not parse RAM configuration: missing or invalid enable function for RAM port");
882 if (!ram_port.HasMember(
"is_write") || !ram_port[
"is_write"].IsBool())
884 return ERR(
"could not parse RAM configuration: missing or invalid write flag for RAM port");
887 BooleanFunction clocked_on_function;
890 return ERR(
"could not parse RAM configuration: failed parsing clock function from string");
894 clocked_on_function = res.get();
897 BooleanFunction enabled_on_function;
900 return ERR(
"could not parse RAM configuration: failed parsing clock function from string");
904 enabled_on_function = res.get();
908 std::move(sub_component), ram_port[
"data_group"].GetString(), ram_port[
"address_group"].GetString(), clocked_on_function, enabled_on_function, ram_port[
"is_write"].GetBool());
913 return OK(std::move(component));
static Result< BooleanFunction > from_string(const std::string &expression)
static std::unique_ptr< GateTypeComponent > create_state_component(std::unique_ptr< GateTypeComponent > component, const std::string &state_identifier, const std::string &neg_state_identifier)
static std::unique_ptr< GateTypeComponent > create_lut_component(std::unique_ptr< GateTypeComponent > component, bool init_ascending)
static std::unique_ptr< GateTypeComponent > create_init_component(const std::string &init_category, const std::vector< std::string > &init_identifiers)
static std::unique_ptr< GateTypeComponent > create_latch_component(std::unique_ptr< GateTypeComponent > component)
static std::unique_ptr< GateTypeComponent > create_ram_component(std::unique_ptr< GateTypeComponent > component, const u32 bit_size)
static std::unique_ptr< GateTypeComponent > create_ff_component(std::unique_ptr< GateTypeComponent > component, const BooleanFunction &next_state_bf, const BooleanFunction &clock_bf)
static std::unique_ptr< GateTypeComponent > create_ram_port_component(std::unique_ptr< GateTypeComponent > component, const std::string &data_group, const std::string &addr_group, const BooleanFunction &clock_bf, const BooleanFunction &enable_bf, bool is_write)
Result< std::unique_ptr< GateLibrary > > parse(const std::filesystem::path &file_path) override
#define log_warning(channel,...)
#define ERR_APPEND(prev_error, message)
std::vector< PinInformation > pins