15 #include "rapidjson/filereadstream.h"
16 #include "rapidjson/stringbuffer.h"
24 FILE* fp = fopen(file_path.string().c_str(),
"r");
27 return ERR(
"could not parse HGL file '" + m_path.string() +
"' : unable to open file");
31 rapidjson::FileReadStream is(fp, buffer,
sizeof(buffer));
32 rapidjson::Document document;
33 document.ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(is);
36 if (document.HasParseError())
38 return ERR(
"could not parse HGL file '" + m_path.string() +
"': failed parsing JSON format");
41 if (
auto res = upgrade_outdated_file(document); res.is_error())
43 return ERR_APPEND(res.get_error(),
"could not parse HGL file '" + m_path.string() +
"': failed to upgrade outdated file format");
46 if (
auto res = parse_gate_library(document); res.is_error())
48 return ERR_APPEND(res.get_error(),
"could not parse HGL file '" + m_path.string() +
"': failed to parse gate library");
53 return OK(std::move(m_gate_lib));
58 if (!document.IsObject() || !document.HasMember(
"version") || !document[
"version"].IsUint() || document[
"version"].GetUint() >= HGL_FORMAT_VERSION)
64 const u32 version = document[
"version"].GetUint();
70 return ERR(res.get_error());
72 for (
const std::string& warning : res.get())
74 log_warning(
"gate_library_parser",
"'{}' cannot be upgraded to HGL format version {} completely: {}", m_path.string(), HGL_FORMAT_VERSION, warning);
81 return ERR(
"HGL file format version " + std::to_string(version) +
" is outdated (requires version " + std::to_string(HGL_FORMAT_VERSION) +
"), the file needs to be upgraded");
85 if (res_replace.is_error())
87 return ERR(res_replace.get_error());
90 log_info(
"gate_library_parser",
"upgraded gate library '{}' from HGL format version {} to {}, the original file was kept as '{}'.", m_path.string(), version, HGL_FORMAT_VERSION, res_replace.get().string());
94 Result<std::monostate> HGLParser::parse_gate_library(
const rapidjson::Document& document)
96 if (!document.HasMember(
"version") || !document[
"version"].IsUint() || document[
"version"].GetUint() < HGL_FORMAT_VERSION)
98 return ERR(
"could not parse gate library: HGL file format version is outdated (requires version " + std::to_string(HGL_FORMAT_VERSION) +
")");
101 if (!document.HasMember(
"library"))
103 return ERR(
"could not parse gate library: missing 'library' node");
106 const std::string gate_lib_name = document[
"library"].GetString();
107 m_gate_lib = std::make_unique<GateLibrary>(m_path, gate_lib_name);
109 if (document.HasMember(
"gate_locations") && document[
"gate_locations"].IsObject())
111 auto gate_locs = document[
"gate_locations"].GetObject();
113 if (!gate_locs.HasMember(
"data_category") || !gate_locs[
"data_category"].IsString())
115 return ERR(
"could not parse gate library '" + gate_lib_name +
"': missing 'data_category' entry for gate locations");
118 if (!gate_locs.HasMember(
"data_x_identifier") || !gate_locs[
"data_x_identifier"].IsString())
120 return ERR(
"could not parse gate library '" + gate_lib_name +
"': missing 'data_x_identifier' entry for gate locations");
123 if (!gate_locs.HasMember(
"data_y_identifier") || !gate_locs[
"data_y_identifier"].IsString())
125 return ERR(
"could not parse gate library '" + gate_lib_name +
"': missing 'data_y_identifier' entry for gate locations");
128 m_gate_lib->set_gate_location_data_category(gate_locs[
"data_category"].GetString());
129 m_gate_lib->set_gate_location_data_identifiers(gate_locs[
"data_x_identifier"].GetString(), gate_locs[
"data_y_identifier"].GetString());
132 if (!document.HasMember(
"cells"))
134 return ERR(
"could not parse gate library '" + gate_lib_name +
"': missing 'cells' node");
137 for (
const auto& gate_type : document[
"cells"].GetArray())
139 if (
auto res = parse_gate_type(gate_type); res.is_error())
141 return ERR_APPEND(res.get_error(),
"could not parse gate library '" + gate_lib_name +
"': failed parsing gate type");
148 Result<std::monostate> HGLParser::parse_gate_type(
const rapidjson::Value& gate_type)
150 if (!gate_type.HasMember(
"name") || !gate_type[
"name"].IsString())
152 return ERR(
"could not parse gate type: missing or invalid name");
155 const std::string
name = gate_type[
"name"].GetString();
156 std::set<GateTypeProperty> properties;
157 if (gate_type.HasMember(
"types") && gate_type[
"types"].IsArray())
159 for (
const auto& base_type : gate_type[
"types"].GetArray())
161 const std::string property_str = base_type.GetString();
165 GateTypeProperty property = enum_from_string<GateTypeProperty>(property_str);
166 properties.insert(property);
168 catch (
const std::runtime_error&)
170 return ERR(
"could not parse gate type '" +
name +
"': invalid property '" + base_type.GetString() +
"'");
179 std::unique_ptr<GateTypeComponent> parent_component =
nullptr;
180 if (gate_type.HasMember(
"lut_config") && gate_type[
"lut_config"].IsObject())
182 const auto& lut_cfg = gate_type[
"lut_config"];
183 if (
auto res = parse_lut_config(lut_cfg); res.is_error())
185 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"': failed parsing LUT configuration");
189 parent_component = res.get();
192 else if (gate_type.HasMember(
"ff_config") && gate_type[
"ff_config"].IsObject())
194 if (
auto res = parse_ff_config(gate_type[
"ff_config"]); res.is_error())
196 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"': failed parsing FF configuration");
200 parent_component = res.get();
203 else if (gate_type.HasMember(
"latch_config") && gate_type[
"latch_config"].IsObject())
205 if (
auto res = parse_latch_config(gate_type[
"latch_config"]); res.is_error())
207 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"': failed parsing latch configuration");
211 parent_component = res.get();
214 else if (gate_type.HasMember(
"ram_config") && gate_type[
"ram_config"].IsObject())
216 if (
auto res = parse_ram_config(gate_type[
"ram_config"]); res.is_error())
218 return ERR_APPEND(res.get_error(),
"could not parse gate type '" +
name +
"': failed parsing RAM configuration");
222 parent_component = res.get();
226 GateType* gt = m_gate_lib->create_gate_type(
name, properties, std::move(parent_component));
229 return ERR(
"could not parse gate type '" +
name +
"': failed to create gate type");
234 std::map<std::string, u16> var_sizes;
235 if (gate_type.HasMember(
"parameters") && gate_type[
"parameters"].IsArray())
237 for (
const auto& param_val : gate_type[
"parameters"].GetArray())
239 if (!param_val.HasMember(
"name") || !param_val[
"name"].IsString())
241 return ERR(
"could not parse parameter for gate type '" +
name +
"': missing or invalid name");
243 if (!param_val.HasMember(
"type") || !param_val[
"type"].IsString())
245 return ERR(
"could not parse parameter for gate type '" +
name +
"': missing or invalid type");
247 if (!param_val.HasMember(
"default") || !param_val[
"default"].IsString())
249 return ERR(
"could not parse parameter for gate type '" +
name +
"': missing or invalid default value");
252 const std::string pname = param_val[
"name"].GetString();
253 const std::string pdefault = param_val[
"default"].GetString();
254 const std::string ptype = param_val[
"type"].GetString();
258 if (ptype ==
"boolean")
261 if (param_res.is_error())
263 return ERR(param_res.get_error());
265 param = param_res.get();
267 else if (ptype ==
"bit_vector")
269 if (!param_val.HasMember(
"size") || !param_val[
"size"].IsUint())
271 return ERR(
"could not parse parameter '" + pname +
"' for gate type '" +
name +
"': bit-vector parameter requires a 'size' field");
273 const u32 sz = param_val[
"size"].GetUint();
276 if (param_res.is_error())
278 return ERR(param_res.get_error());
280 param = param_res.get();
282 else if (ptype ==
"logic_vector")
284 if (!param_val.HasMember(
"size") || !param_val[
"size"].IsUint())
286 return ERR(
"could not parse parameter '" + pname +
"' for gate type '" +
name +
"': logic-vector parameter requires a 'size' field");
288 const u32 sz = param_val[
"size"].GetUint();
291 if (param_res.is_error())
293 return ERR(param_res.get_error());
295 param = param_res.get();
297 else if (ptype ==
"integer")
300 if (param_res.is_error())
302 return ERR(param_res.get_error());
304 param = param_res.get();
306 else if (ptype ==
"string")
309 if (param_res.is_error())
311 return ERR(param_res.get_error());
313 param = param_res.get();
315 else if (ptype ==
"float")
318 if (param_res.is_error())
320 return ERR(param_res.get_error());
322 param = param_res.get();
324 else if (ptype ==
"time")
327 if (param_res.is_error())
329 return ERR(param_res.get_error());
331 param = param_res.get();
333 else if (ptype ==
"enum")
335 if (!param_val.HasMember(
"values") || !param_val[
"values"].IsArray())
337 return ERR(
"could not parse parameter '" + pname +
"' for gate type '" +
name +
"': enum parameter requires a 'values' array");
339 std::vector<std::string> values;
340 for (
const auto& v : param_val[
"values"].GetArray())
344 return ERR(
"could not parse parameter '" + pname +
"' for gate type '" +
name +
"': enum 'values' must be strings");
346 values.emplace_back(v.GetString());
350 if (param_res.is_error())
352 return ERR(param_res.get_error());
354 param = param_res.get();
358 return ERR(
"could not parse parameter '" + pname +
"' for gate type '" +
name +
"': unknown type '" + ptype +
"'");
361 if (
auto res = gt->add_parameter(param); res.is_error())
363 return ERR_APPEND(res.get_error(),
"could not parse parameters for gate type '" +
name +
"'");
366 var_sizes[param.get_name()] = param.get_size();
370 if (gate_type.HasMember(
"pin_groups") && gate_type[
"pin_groups"].IsArray())
372 for (
const auto& pg_val : gate_type[
"pin_groups"].GetArray())
374 if (!pg_val.HasMember(
"name") || !pg_val[
"name"].IsString())
376 return ERR(
"could not parse pin group: missing or invalid name");
378 std::string pg_name = pg_val[
"name"].GetString();
380 if (!pg_val.HasMember(
"direction") || !pg_val[
"direction"].IsString())
382 return ERR(
"could not parse pin group '" + pg_name +
"': missing or invalid pin direction");
385 std::string pg_direction_str = pg_val[
"direction"].GetString();
388 pg_direction = enum_from_string<PinDirection>(pg_direction_str);
390 catch (
const std::runtime_error&)
392 return ERR(
"could not parse pin '" + pg_name +
"': invalid pin direction '" + pg_direction_str +
"'");
395 if (!pg_val.HasMember(
"type") || !pg_val[
"type"].IsString())
397 return ERR(
"could not parse pin group '" + pg_name +
"': missing or invalid pin type");
400 std::string pg_type_str = pg_val[
"type"].GetString();
403 pg_type = enum_from_string<PinType>(pg_type_str);
405 catch (
const std::runtime_error&)
407 return ERR(
"could not parse pin group '" + pg_name +
"': invalid pin type '" + pg_type_str +
"'");
410 if (!pg_val.HasMember(
"ascending") || !pg_val[
"ascending"].IsBool())
412 return ERR(
"could not parse pin group '" + pg_name +
"': missing or ascending property");
414 bool ascending = pg_val[
"ascending"].GetBool();
417 if (pg_val.HasMember(
"ordered") && pg_val[
"ordered"].IsBool())
419 ordered = pg_val[
"ordered"].GetBool();
422 if (!pg_val.HasMember(
"start_index") || !pg_val[
"start_index"].IsUint())
424 return ERR(
"could not parse pin group '" + pg_name +
"': missing or start index");
428 if (pg_val.HasMember(
"pins") && pg_val[
"pins"].IsArray())
430 std::vector<GatePin*>
pins;
432 for (
const auto& p_val : pg_val[
"pins"].GetArray())
434 if (!p_val.HasMember(
"name") || !p_val[
"name"].IsString())
436 return ERR(
"could not parse pin: missing or invalid name");
438 std::string p_name = p_val[
"name"].GetString();
440 if (!p_val.HasMember(
"direction") || !p_val[
"direction"].IsString())
442 return ERR(
"could not parse pin '" + p_name +
"': missing or invalid pin direction");
445 std::string p_direction_str = p_val[
"direction"].GetString();
448 p_direction = enum_from_string<PinDirection>(p_direction_str);
450 catch (
const std::runtime_error&)
452 return ERR(
"could not parse pin '" + p_name +
"': invalid pin direction '" + p_direction_str +
"'");
456 if (p_val.HasMember(
"type") && p_val[
"type"].IsString())
458 std::string p_type_str = p_val[
"type"].GetString();
461 p_type = enum_from_string<PinType>(p_type_str);
463 catch (
const std::runtime_error&)
465 return ERR(
"could not parse pin '" + p_name +
"': invalid pin type '" + p_type_str +
"'");
473 auto p_res = gt->create_pin(p_name, p_direction, p_type,
false);
474 if (p_res.is_error())
476 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 +
"'");
478 pins.push_back(p_res.get());
480 if (p_val.HasMember(
"function") && p_val[
"function"].IsString())
485 "could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed parsing Boolean function with name '" + p_name
490 gt->add_boolean_function(p_name, res.get());
494 if (p_val.HasMember(
"x_function") && p_val[
"x_function"].IsString())
499 "could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed parsing Boolean function with name '" + p_name
500 +
"_undefined' from string");
504 gt->add_boolean_function(p_name +
"_undefined", res.get());
508 if (p_val.HasMember(
"z_function") && p_val[
"z_function"].IsString())
513 "could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed parsing Boolean function with name '" + p_name
514 +
"_tristate' from string");
518 gt->add_boolean_function(p_name +
"_tristate", res.get());
524 if (pg_res.is_error())
526 return ERR_APPEND(pg_res.get_error(),
"could not parse gate type '" +
name +
"' with ID " + std::to_string(gt->get_id()) +
": failed to create pin group '" + pg_name +
"'");
531 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 +
"'");
539 Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_lut_config(
const rapidjson::Value& lut_config)
542 if (lut_config.HasMember(
"output_pins") && lut_config[
"output_pins"].IsArray())
546 std::string pin_name;
551 std::vector<std::string> input_pins;
553 std::vector<PinCfg> pin_cfgs;
555 for (
const auto& entry : lut_config[
"output_pins"].GetArray())
557 if (!entry.HasMember(
"pin") || !entry[
"pin"].IsString())
559 return ERR(
"could not parse LUT configuration: missing or invalid pin name in output_pins entry");
561 const std::string pin_name = entry[
"pin"].GetString();
563 if (!entry.HasMember(
"data_identifier") || !entry[
"data_identifier"].IsString())
565 return ERR(
"could not parse LUT configuration: missing or invalid data_identifier for pin '" + pin_name +
"'");
567 const std::string
identifier = entry[
"data_identifier"].GetString();
569 if (!entry.HasMember(
"bit_offset") || !entry[
"bit_offset"].IsUint())
571 return ERR(
"could not parse LUT configuration: missing or invalid bit_offset for pin '" + pin_name +
"'");
573 const u32 bit_offset = entry[
"bit_offset"].GetUint();
575 if (!entry.HasMember(
"bit_count") || !entry[
"bit_count"].IsUint())
577 return ERR(
"could not parse LUT configuration: missing or invalid bit_count for pin '" + pin_name +
"'");
579 const u32 bit_count = entry[
"bit_count"].GetUint();
582 if (!entry.HasMember(
"is_ascending") || !entry[
"is_ascending"].IsBool())
584 return ERR(
"could not parse LUT configuration: missing or invalid is_ascending for pin '" + pin_name +
"'");
586 bool pin_ascending = entry[
"is_ascending"].GetBool();
588 if (!entry.HasMember(
"input_pins") || !entry[
"input_pins"].IsArray())
590 return ERR(
"could not parse LUT configuration: missing or invalid input_pins for pin '" + pin_name +
"'");
592 std::vector<std::string> input_pins;
593 for (
const auto& pv : entry[
"input_pins"].GetArray())
597 return ERR(
"could not parse LUT configuration: non-string entry in input_pins for pin '" + pin_name +
"'");
599 input_pins.emplace_back(pv.GetString());
601 if (input_pins.empty())
603 return ERR(
"could not parse LUT configuration: input_pins must be non-empty for pin '" + pin_name +
"'");
606 pin_cfgs.push_back({pin_name,
identifier, bit_offset, bit_count, pin_ascending, std::move(input_pins)});
609 std::unordered_map<std::string, LUTComponent::LUTOutputConfig> cfg_map;
610 for (
const auto& pc : pin_cfgs)
612 cfg_map.emplace(pc.pin_name, LUTComponent::LUTOutputConfig(pc.identifier, pc.bit_offset, pc.bit_count, pc.is_ascending, pc.input_pins));
621 Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_ff_config(
const rapidjson::Value& ff_config)
623 if (!ff_config.HasMember(
"state") || !ff_config[
"state"].IsString())
625 return ERR(
"could not parse flip-flop configuration: missing or invalid state identifier");
627 if (!ff_config.HasMember(
"neg_state") || !ff_config[
"neg_state"].IsString())
629 return ERR(
"could not parse flip-flop configuration: missing or invalid negated state identifier");
631 if (!ff_config.HasMember(
"next_state") || !ff_config[
"next_state"].IsString())
633 return ERR(
"could not parse flip-flop configuration: missing or invalid next state function");
635 if (!ff_config.HasMember(
"clocked_on") || !ff_config[
"clocked_on"].IsString())
637 return ERR(
"could not parse flip-flop configuration: missing or invalid clock function");
640 std::unique_ptr<GateTypeComponent> init_component =
nullptr;
641 if (ff_config.HasMember(
"data_category") && ff_config[
"data_category"].IsString())
643 std::vector<std::string> init_identifiers;
644 if (ff_config.HasMember(
"data_identifier") && ff_config[
"data_identifier"].IsString())
646 init_identifiers.push_back(ff_config[
"data_identifier"].GetString());
650 return ERR(
"could not parse flip-flop configuration: missing or invalid data identifier for flip-flop initialization");
654 else if (ff_config.HasMember(
"data_identifier") && ff_config[
"data_identifier"].IsString())
656 return ERR(
"could not parse flip-flop configuration: missing or invalid data category for flip-flop initialization");
659 std::string state_identifier = ff_config[
"state"].GetString();
660 std::string neg_state_identifier = ff_config[
"neg_state"].GetString();
661 std::unique_ptr<GateTypeComponent> state_component =
StateComponent::create(std::move(init_component), state_identifier, neg_state_identifier);
662 assert(state_component !=
nullptr);
664 BooleanFunction next_state_function;
667 return ERR(
"could not parse flip-flop configuration: failed parsing next state function from string");
671 next_state_function = res.get();
673 BooleanFunction clocked_on_function;
676 return ERR(
"could not parse flip-flop configuration: failed parsing clock function from string");
680 clocked_on_function = res.get();
683 std::unique_ptr<GateTypeComponent> component =
FFComponent::create(std::move(state_component), next_state_function, clocked_on_function);
685 FFComponent* ff_component = component->convert_to<FFComponent>();
686 assert(ff_component !=
nullptr);
688 if (ff_config.HasMember(
"clear_on") && ff_config[
"clear_on"].IsString())
692 return ERR(
"could not parse flip-flop configuration: failed parsing asynchronous reset function from string");
696 ff_component->set_async_reset_function(res.get());
700 if (ff_config.HasMember(
"preset_on") && ff_config[
"preset_on"].IsString())
704 return ERR(
"could not parse flip-flop configuration: failed parsing asynchronous set function from string");
708 ff_component->set_async_set_function(res.get());
712 bool has_state = ff_config.HasMember(
"state_clear_preset") && ff_config[
"state_clear_preset"].IsString();
713 bool has_neg_state = ff_config.HasMember(
"neg_state_clear_preset") && ff_config[
"neg_state_clear_preset"].IsString();
715 if (has_state && has_neg_state)
725 return ERR(
"could not parse flip-flop configuration: failed parsing state on concurrent asynchronous set and reset from string");
734 return ERR(
"could not parse flip-flop configuration: failed parsing negated state on concurrent asynchronous set and reset from string");
737 ff_component->set_async_set_reset_behavior(cp1, cp2);
739 else if ((has_state && !has_neg_state) || (!has_state && has_neg_state))
741 return ERR(
"could not parse flip-flop configuration: missing state or negated state on concurrent asynchronous set and reset");
744 return OK(std::move(component));
747 Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_latch_config(
const rapidjson::Value& latch_config)
749 if (!latch_config.HasMember(
"state") || !latch_config[
"state"].IsString())
751 return ERR(
"could not parse latch configuration: missing or invalid state identifier");
753 if (!latch_config.HasMember(
"neg_state") || !latch_config[
"neg_state"].IsString())
755 return ERR(
"could not parse latch configuration: missing or invalid negated state identifier");
758 std::string state_identifier = latch_config[
"state"].GetString();
759 std::string neg_state_identifier = latch_config[
"neg_state"].GetString();
760 std::unique_ptr<GateTypeComponent> state_component =
StateComponent::create(
nullptr, state_identifier, neg_state_identifier);
761 assert(state_component !=
nullptr);
764 LatchComponent* latch_component = component->convert_to<LatchComponent>();
765 assert(latch_component !=
nullptr);
767 if (latch_config.HasMember(
"data_in") && latch_config[
"data_in"].IsString() && latch_config.HasMember(
"enable_on") && latch_config[
"enable_on"].IsString())
771 return ERR(
"could not parse latch configuration: failed parsing data in function from string");
775 latch_component->set_data_in_function(res.get());
780 return ERR(
"could not parse latch configuration: failed parsing enable function from string");
784 latch_component->set_enable_function(res.get());
787 else if (latch_config.HasMember(
"data_in") && latch_config[
"data_in"].IsString())
789 return ERR(
"could not parse latch configuration: missing or invalid enable function");
791 else if (latch_config.HasMember(
"enable_on") && latch_config[
"enable_on"].IsString())
793 return ERR(
"could not parse latch configuration: missing or invalid data in function");
796 if (latch_config.HasMember(
"clear_on") && latch_config[
"clear_on"].IsString())
800 return ERR(
"could not parse latch configuration: failed parsing asynchronous reset function from string");
804 latch_component->set_async_reset_function(res.get());
808 if (latch_config.HasMember(
"preset_on") && latch_config[
"preset_on"].IsString())
812 return ERR(
"could not parse latch configuration: failed parsing asynchronous set function from string");
816 latch_component->set_async_set_function(res.get());
820 bool has_state = latch_config.HasMember(
"state_clear_preset") && latch_config[
"state_clear_preset"].IsString();
821 bool has_neg_state = latch_config.HasMember(
"neg_state_clear_preset") && latch_config[
"neg_state_clear_preset"].IsString();
823 if (has_state && has_neg_state)
833 return ERR(
"could not parse latch configuration: failed parsing state on concurrent asynchronous set and reset from string");
842 return ERR(
"could not parse latch configuration: failed parsing negated state on concurrent asynchronous set and reset from string");
845 latch_component->set_async_set_reset_behavior(cp1, cp2);
847 else if ((has_state && !has_neg_state) || (!has_state && has_neg_state))
849 return ERR(
"could not parse latch configuration: missing state or negated state on concurrent asynchronous set and reset");
852 return OK(std::move(component));
855 Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_ram_config(
const rapidjson::Value& ram_config)
857 if (!ram_config.HasMember(
"data_identifiers") || !ram_config[
"data_identifiers"].IsArray())
859 return ERR(
"could not parse RAM configuration: missing or invalid data_identifiers");
862 std::vector<std::string> init_identifiers;
863 for (
const auto&
identifier : ram_config[
"data_identifiers"].GetArray())
865 init_identifiers.push_back(
identifier.GetString());
868 std::unique_ptr<GateTypeComponent> sub_component =
nullptr;
870 if (!ram_config.HasMember(
"bit_size") || !ram_config[
"bit_size"].IsUint())
872 return ERR(
"could not parse RAM configuration: missing or invalid bit size");
875 if (!ram_config.HasMember(
"ram_ports") || !ram_config[
"ram_ports"].IsArray())
877 return ERR(
"could not parse RAM configuration: missing or invalid RAM ports");
880 for (
const auto& ram_port : ram_config[
"ram_ports"].GetArray())
882 if (!ram_port.HasMember(
"data_group") || !ram_port[
"data_group"].IsString())
884 return ERR(
"could not parse RAM configuration: missing or invalid data pin groups for RAM port");
887 if (!ram_port.HasMember(
"address_group") || !ram_port[
"address_group"].IsString())
889 return ERR(
"could not parse RAM configuration: missing or invalid address pin groups for RAM port");
892 if (!ram_port.HasMember(
"clocked_on") || !ram_port[
"clocked_on"].IsString())
894 return ERR(
"could not parse RAM configuration: missing or invalid clock function for RAM port");
897 if (!ram_port.HasMember(
"enabled_on") || !ram_port[
"enabled_on"].IsString())
899 return ERR(
"could not parse RAM configuration: missing or invalid enable function for RAM port");
902 if (!ram_port.HasMember(
"is_write") || !ram_port[
"is_write"].IsBool())
904 return ERR(
"could not parse RAM configuration: missing or invalid write flag for RAM port");
907 BooleanFunction clocked_on_function;
910 return ERR(
"could not parse RAM configuration: failed parsing clock function from string");
914 clocked_on_function = res.get();
917 BooleanFunction enabled_on_function;
920 return ERR(
"could not parse RAM configuration: failed parsing clock function from string");
924 enabled_on_function = res.get();
928 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());
931 std::unique_ptr<GateTypeComponent> component =
RAMComponent::create(std::move(sub_component), ram_config[
"bit_size"].GetUint(), init_identifiers);
933 return OK(std::move(component));
static Result< BooleanFunction > from_string(const std::string &expression)
static std::unique_ptr< FFComponent > create(std::unique_ptr< GateTypeComponent > component, const BooleanFunction &next_state_bf, const BooleanFunction &clock_bf)
static bool is_upgrade_requested()
static void set_parse_status(ParseStatus status)
@ NoError
The gate library was parsed successfully.
@ NeedsUpgrade
The file format is outdated, it gets upgraded by parsing it again after request_upgrade.
Result< std::unique_ptr< GateLibrary > > parse(const std::filesystem::path &file_path) override
static std::unique_ptr< InitComponent > create(const std::string &init_category, const std::vector< std::string > &init_identifiers)
static std::unique_ptr< LUTComponent > create(std::unordered_map< std::string, LUTOutputConfig > configs={})
static std::unique_ptr< LatchComponent > create(std::unique_ptr< GateTypeComponent > component)
static std::unique_ptr< RAMComponent > create(std::unique_ptr< GateTypeComponent > component, const u32 bit_size, const std::vector< std::string > &init_identifiers={})
static std::unique_ptr< RAMPortComponent > create(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)
static std::unique_ptr< StateComponent > create(std::unique_ptr< GateTypeComponent > component, const std::string &state_identifier, const std::string &neg_state_identifier)
#define log_info(channel,...)
#define log_warning(channel,...)
#define ERR_APPEND(prev_error, message)
Result< std::vector< std::string > > upgrade_document(rapidjson::Document &document)
Result< std::filesystem::path > replace_file(const rapidjson::Document &document, const std::filesystem::path &file_path)
std::vector< PinInformation > pins
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)