HAL
hgl_parser.cpp
Go to the documentation of this file.
2 
10 #include "hal_core/utilities/log.h"
12 #include "rapidjson/filereadstream.h"
13 #include "rapidjson/stringbuffer.h"
14 
15 namespace hal
16 {
17  Result<std::unique_ptr<GateLibrary>> HGLParser::parse(const std::filesystem::path& file_path)
18  {
19  m_path = file_path;
20 
21  FILE* fp = fopen(file_path.string().c_str(), "r");
22  if (fp == NULL)
23  {
24  return ERR("could not parse HGL file '" + m_path.string() + "' : unable to open file");
25  }
26 
27  char buffer[65536];
28  rapidjson::FileReadStream is(fp, buffer, sizeof(buffer));
29  rapidjson::Document document;
30  document.ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(is);
31  fclose(fp);
32 
33  if (document.HasParseError())
34  {
35  return ERR("could not parse HGL file '" + m_path.string() + "': failed parsing JSON format");
36  }
37 
38  if (auto res = parse_gate_library(document); res.is_error())
39  {
40  return ERR_APPEND(res.get_error(), "could not parse HGL file '" + m_path.string() + "': failed to parse gate library");
41  }
42 
43  return OK(std::move(m_gate_lib));
44  }
45 
46  Result<std::monostate> HGLParser::parse_gate_library(const rapidjson::Document& document)
47  {
48  if (!document.HasMember("version") || !document["version"].IsUint() || document["version"].GetUint() < HGL_FORMAT_VERSION)
49  {
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.");
51  }
52 
53  if (document.HasMember("version") && document["version"].IsUint())
54  {
55  file_version = document["version"].GetUint();
56  }
57 
58  if (!document.HasMember("library"))
59  {
60  return ERR("could not parse gate library: missing 'library' node");
61  }
62 
63  const std::string gate_lib_name = document["library"].GetString();
64  m_gate_lib = std::make_unique<GateLibrary>(m_path, gate_lib_name);
65 
66  if (document.HasMember("gate_locations") && document["gate_locations"].IsObject())
67  {
68  auto gate_locs = document["gate_locations"].GetObject();
69 
70  if (!gate_locs.HasMember("data_category") || !gate_locs["data_category"].IsString())
71  {
72  return ERR("could not parse gate library '" + gate_lib_name + "': missing 'data_category' entry for gate locations");
73  }
74 
75  if (!gate_locs.HasMember("data_x_identifier") || !gate_locs["data_x_identifier"].IsString())
76  {
77  return ERR("could not parse gate library '" + gate_lib_name + "': missing 'data_x_identifier' entry for gate locations");
78  }
79 
80  if (!gate_locs.HasMember("data_y_identifier") || !gate_locs["data_y_identifier"].IsString())
81  {
82  return ERR("could not parse gate library '" + gate_lib_name + "': missing 'data_y_identifier' entry for gate locations");
83  }
84 
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());
87  }
88 
89  if (!document.HasMember("cells"))
90  {
91  return ERR("could not parse gate library '" + gate_lib_name + "': missing 'cells' node");
92  }
93 
94  for (const auto& gate_type : document["cells"].GetArray())
95  {
96  if (auto res = parse_gate_type(gate_type); res.is_error())
97  {
98  return ERR_APPEND(res.get_error(), "could not parse gate library '" + gate_lib_name + "': failed parsing gate type");
99  }
100  }
101 
102  return OK({});
103  }
104 
105  Result<std::monostate> HGLParser::parse_gate_type(const rapidjson::Value& gate_type)
106  {
107  if (!gate_type.HasMember("name") || !gate_type["name"].IsString())
108  {
109  return ERR("could not parse gate type: missing or invalid name");
110  }
111 
112  const std::string name = gate_type["name"].GetString();
113  std::set<GateTypeProperty> properties;
114  if (gate_type.HasMember("types") && gate_type["types"].IsArray())
115  {
116  for (const auto& base_type : gate_type["types"].GetArray())
117  {
118  const std::string property_str = base_type.GetString();
119 
120  try
121  {
122  GateTypeProperty property = enum_from_string<GateTypeProperty>(property_str);
123  properties.insert(property);
124  }
125  catch (const std::runtime_error&)
126  {
127  // legacy support
128  if (property_str == "buffer")
129  {
130  properties.insert(GateTypeProperty::c_buffer);
131  }
132  else if (property_str == "carry")
133  {
134  properties.insert(GateTypeProperty::c_carry);
135  }
136  else if (property_str == "mux")
137  {
138  properties.insert(GateTypeProperty::c_mux);
139  }
140  else if (property_str == "lut")
141  {
142  properties.insert(GateTypeProperty::c_lut);
143  }
144  else
145  {
146  return ERR("could not parse gate type '" + name + "': invalid property '" + base_type.GetString() + "'");
147  }
148  }
149  }
150  }
151  else
152  {
153  properties = {GateTypeProperty::combinational};
154  }
155 
156  std::unique_ptr<GateTypeComponent> parent_component = nullptr;
157  if (gate_type.HasMember("lut_config") && gate_type["lut_config"].IsObject())
158  {
159  if (auto res = parse_lut_config(gate_type["lut_config"]); res.is_error())
160  {
161  return ERR_APPEND(res.get_error(), "could not parse gate type '" + name + "': failed parsing LUT configuration");
162  }
163  else
164  {
165  parent_component = res.get();
166  }
167  }
168  else if (gate_type.HasMember("ff_config") && gate_type["ff_config"].IsObject())
169  {
170  if (auto res = parse_ff_config(gate_type["ff_config"]); res.is_error())
171  {
172  return ERR_APPEND(res.get_error(), "could not parse gate type '" + name + "': failed parsing FF configuration");
173  }
174  else
175  {
176  parent_component = res.get();
177  }
178  }
179  else if (gate_type.HasMember("latch_config") && gate_type["latch_config"].IsObject())
180  {
181  if (auto res = parse_latch_config(gate_type["latch_config"]); res.is_error())
182  {
183  return ERR_APPEND(res.get_error(), "could not parse gate type '" + name + "': failed parsing latch configuration");
184  }
185  else
186  {
187  parent_component = res.get();
188  }
189  }
190  else if (gate_type.HasMember("ram_config") && gate_type["ram_config"].IsObject())
191  {
192  if (auto res = parse_ram_config(gate_type["ram_config"]); res.is_error())
193  {
194  return ERR_APPEND(res.get_error(), "could not parse gate type '" + name + "': failed parsing RAM configuration");
195  }
196  else
197  {
198  parent_component = res.get();
199  }
200  }
201 
202  GateType* gt = m_gate_lib->create_gate_type(name, properties, std::move(parent_component));
203  if (gt == nullptr)
204  {
205  return ERR("could not parse gate type '" + name + "': failed to create gate type");
206  }
207 
208  if (file_version >= 2)
209  {
210  if (gate_type.HasMember("pin_groups") && gate_type["pin_groups"].IsArray())
211  {
212  for (const auto& pg_val : gate_type["pin_groups"].GetArray())
213  {
214  if (!pg_val.HasMember("name") || !pg_val["name"].IsString())
215  {
216  return ERR("could not parse pin group: missing or invalid name");
217  }
218  std::string pg_name = pg_val["name"].GetString();
219 
220  if (!pg_val.HasMember("direction") || !pg_val["direction"].IsString())
221  {
222  return ERR("could not parse pin group '" + pg_name + "': missing or invalid pin direction");
223  }
224  PinDirection pg_direction;
225  std::string pg_direction_str = pg_val["direction"].GetString();
226  try
227  {
228  pg_direction = enum_from_string<PinDirection>(pg_direction_str);
229  }
230  catch (const std::runtime_error&)
231  {
232  return ERR("could not parse pin '" + pg_name + "': invalid pin direction '" + pg_direction_str + "'");
233  }
234 
235  if (!pg_val.HasMember("type") || !pg_val["type"].IsString())
236  {
237  return ERR("could not parse pin group '" + pg_name + "': missing or invalid pin type");
238  }
239  PinType pg_type;
240  std::string pg_type_str = pg_val["type"].GetString();
241  try
242  {
243  pg_type = enum_from_string<PinType>(pg_type_str);
244  }
245  catch (const std::runtime_error&)
246  {
247  return ERR("could not parse pin group '" + pg_name + "': invalid pin type '" + pg_type_str + "'");
248  }
249 
250  if (!pg_val.HasMember("ascending") || !pg_val["ascending"].IsBool())
251  {
252  return ERR("could not parse pin group '" + pg_name + "': missing or ascending property");
253  }
254  bool ascending = pg_val["ascending"].GetBool();
255 
256  bool ordered = false;
257  if (pg_val.HasMember("ordered") && pg_val["ordered"].IsBool())
258  {
259  ordered = pg_val["ordered"].GetBool();
260  }
261 
262  if (!pg_val.HasMember("start_index") || !pg_val["start_index"].IsUint())
263  {
264  return ERR("could not parse pin group '" + pg_name + "': missing or start index");
265  }
266  u32 start_index = pg_val["start_index"].GetUint();
267 
268  if (pg_val.HasMember("pins") && pg_val["pins"].IsArray())
269  {
270  std::vector<GatePin*> pins;
271 
272  for (const auto& p_val : pg_val["pins"].GetArray())
273  {
274  if (!p_val.HasMember("name") || !p_val["name"].IsString())
275  {
276  return ERR("could not parse pin: missing or invalid name");
277  }
278  std::string p_name = p_val["name"].GetString();
279 
280  if (!p_val.HasMember("direction") || !p_val["direction"].IsString())
281  {
282  return ERR("could not parse pin '" + p_name + "': missing or invalid pin direction");
283  }
284  PinDirection p_direction;
285  std::string p_direction_str = p_val["direction"].GetString();
286  try
287  {
288  p_direction = enum_from_string<PinDirection>(p_direction_str);
289  }
290  catch (const std::runtime_error&)
291  {
292  return ERR("could not parse pin '" + p_name + "': invalid pin direction '" + p_direction_str + "'");
293  }
294 
295  PinType p_type;
296  if (p_val.HasMember("type") && p_val["type"].IsString())
297  {
298  std::string p_type_str = p_val["type"].GetString();
299  try
300  {
301  p_type = enum_from_string<PinType>(p_type_str);
302  }
303  catch (const std::runtime_error&)
304  {
305  return ERR("could not parse pin '" + p_name + "': invalid pin type '" + p_type_str + "'");
306  }
307  }
308  else
309  {
310  p_type = PinType::none;
311  }
312 
313  auto p_res = gt->create_pin(p_name, p_direction, p_type, false);
314  if (p_res.is_error())
315  {
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 + "'");
317  }
318  pins.push_back(p_res.get());
319 
320  if (p_val.HasMember("function") && p_val["function"].IsString())
321  {
322  if (auto res = BooleanFunction::from_string(p_val["function"].GetString()); res.is_error())
323  {
324  return ERR_APPEND(res.get_error(),
325  "could not parse gate type '" + name + "' with ID " + std::to_string(gt->get_id()) + ": failed parsing Boolean function with name '" + p_name
326  + "' from string");
327  }
328  else
329  {
330  gt->add_boolean_function(p_name, res.get());
331  }
332  }
333 
334  if (p_val.HasMember("x_function") && p_val["x_function"].IsString())
335  {
336  if (auto res = BooleanFunction::from_string(p_val["x_function"].GetString()); res.is_error())
337  {
338  return ERR_APPEND(res.get_error(),
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");
341  }
342  else
343  {
344  gt->add_boolean_function(p_name + "_undefined", res.get());
345  }
346  }
347 
348  if (p_val.HasMember("z_function") && p_val["z_function"].IsString())
349  {
350  if (auto res = BooleanFunction::from_string(p_val["z_function"].GetString()); res.is_error())
351  {
352  return ERR_APPEND(res.get_error(),
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");
355  }
356  else
357  {
358  gt->add_boolean_function(p_name + "_tristate", res.get());
359  }
360  }
361  }
362 
363  auto pg_res = gt->create_pin_group(pg_name, pins, pg_direction, pg_type, ascending, start_index, ordered);
364  if (pg_res.is_error())
365  {
366  return ERR_APPEND(pg_res.get_error(),
367  "could not parse gate type '" + name + "' with ID " + std::to_string(gt->get_id()) + ": failed to create pin group '" + pg_name + "'");
368  }
369  }
370  else
371  {
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 + "'");
373  }
374  }
375  }
376  }
377  else if (file_version < 2)
378  {
379  std::map<std::string, std::string> pins_to_groups;
380  std::map<std::string, GroupCtx> groups_to_pins;
381 
382  if (gate_type.HasMember("groups") && gate_type["groups"].IsArray())
383  {
384  for (const auto& group_val : gate_type["groups"].GetArray())
385  {
386  // read name
387  std::string pg_name;
388  if (!group_val.HasMember("name") || !group_val["name"].IsString())
389  {
390  return ERR("could not parse gate type '" + name + "' with ID " + std::to_string(gt->get_id()) + ": missing or invalid pin group name");
391  }
392 
393  pg_name = group_val["name"].GetString();
394  if (!group_val.HasMember("pins") || !group_val["pins"].IsArray())
395  {
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 + "'");
397  }
398 
399  // TODO will need changes to HGL format to be fancy
400  i32 start = -1;
401  i32 direction = 0;
402  std::vector<std::string> pins;
403  GroupCtx pin_group_info;
404  for (const auto& pin_obj : group_val["pins"].GetArray())
405  {
406  if (!pin_obj.IsObject())
407  {
408  return ERR("could not parse pin group '" + name + "' with ID " + std::to_string(gt->get_id()) + ": invalid pin group assignment");
409  }
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;
415 
416  // if (auto res = gt->get_pin_by_name(pin_name); res == nullptr)
417  // {
418  // return ERR("could not parse pin group '" + name + "': failed to get pin by name '" + pin_name + "'");
419  // }
420  // else
421  // {
422  // pins.push_back(res);
423  // }
424 
425  if (start == -1)
426  {
427  start = pin_index;
428  }
429  else
430  {
431  direction = (start < (i32)pin_index) ? 1 : -1;
432  }
433  }
434 
435  pin_group_info.ascending = (direction == 1) ? true : false;
436  pin_group_info.start_index = start;
437 
438  // if (auto res = gt->create_pin_group(name, pins, pins.at(0)->get_direction(), pins.at(0)->get_type(), , start); res.is_error())
439  // {
440  // return ERR_APPEND(res.get_error(), "could not parse pin group '" + name + "': failed to create pin group");
441  // }
442  groups_to_pins[pg_name] = pin_group_info;
443  }
444  }
445 
446  PinCtx pin_ctx;
447  if (gate_type.HasMember("pins") && gate_type["pins"].IsArray())
448  {
449  for (const auto& pin : gate_type["pins"].GetArray())
450  {
451  if (auto res = parse_pin(pin_ctx, pin); res.is_error())
452  {
453  return ERR_APPEND(res.get_error(), "could not parse gate type '" + name + "' with ID " + std::to_string(gt->get_id()) + ": failed parsing pin");
454  }
455  }
456  }
457 
458  for (const auto& pin_name : pin_ctx.pins)
459  {
460  if (const auto it = pins_to_groups.find(pin_name); it == pins_to_groups.end())
461  {
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())
463  {
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);
465  }
466  }
467  else
468  {
469  if (gt->get_pin_group_by_name(it->second) != nullptr)
470  {
471  continue;
472  }
473 
474  std::vector<GatePin*> pins;
475  auto pg_info = groups_to_pins.at(it->second);
476  for (const auto& p_name : pg_info.pins)
477  {
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())
479  {
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);
481  }
482  else
483  {
484  pins.push_back(res.get());
485  }
486  }
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())
488  {
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);
490  }
491  }
492  }
493 
494  for (const auto& [f_name, func] : pin_ctx.boolean_functions)
495  {
496  if (auto res = BooleanFunction::from_string(func); res.is_error())
497  {
498  return ERR_APPEND(res.get_error(),
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");
500  }
501  else
502  {
503  gt->add_boolean_function(f_name, res.get());
504  }
505  }
506  }
507 
508  return OK({});
509  }
510 
511  Result<std::monostate> HGLParser::parse_pin(PinCtx& pin_ctx, const rapidjson::Value& pin)
512  {
513  if (!pin.HasMember("name") || !pin["name"].IsString())
514  {
515  return ERR("could not parse pin: missing or invalid name");
516  }
517 
518  std::string name = pin["name"].GetString();
519  if (!pin.HasMember("direction") || !pin["direction"].IsString())
520  {
521  return ERR("could not parse pin '" + name + "': missing or invalid pin direction");
522  }
523 
524  std::string direction = pin["direction"].GetString();
525  try
526  {
527  pin_ctx.pin_to_direction[name] = enum_from_string<PinDirection>(direction);
528  pin_ctx.pins.push_back(name);
529  }
530  catch (const std::runtime_error&)
531  {
532  return ERR("could not parse pin '" + name + "': invalid pin direction '" + direction + "'");
533  }
534 
535  if (pin.HasMember("function") && pin["function"].IsString())
536  {
537  pin_ctx.boolean_functions[name] = pin["function"].GetString();
538  }
539 
540  if (pin.HasMember("x_function") && pin["x_function"].IsString())
541  {
542  pin_ctx.boolean_functions[name + "_undefined"] = pin["x_function"].GetString();
543  }
544 
545  if (pin.HasMember("z_function") && pin["z_function"].IsString())
546  {
547  pin_ctx.boolean_functions[name + "_tristate"] = pin["z_function"].GetString();
548  }
549 
550  if (pin.HasMember("type") && pin["type"].IsString())
551  {
552  std::string type_str = pin["type"].GetString();
553  try
554  {
555  pin_ctx.pin_to_type[name] = enum_from_string<PinType>(type_str);
556  }
557  catch (const std::runtime_error&)
558  {
559  return ERR("could not parse pin '" + name + "': invalid pin type '" + type_str + "'");
560  }
561  }
562  else
563  {
564  pin_ctx.pin_to_type[name] = PinType::none;
565  }
566 
567  return OK({});
568  }
569 
570  Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_lut_config(const rapidjson::Value& lut_config)
571  {
572  if (!lut_config.HasMember("bit_order") || !lut_config["bit_order"].IsString())
573  {
574  return ERR("could not parse LUT configuration: missing or invalid bit order");
575  }
576 
577  if (!lut_config.HasMember("data_category") || !lut_config["data_category"].IsString())
578  {
579  return ERR("could not parse LUT configuration: missing or invalid data category for LUT initialization");
580  }
581 
582  if (!lut_config.HasMember("data_identifier") || !lut_config["data_identifier"].IsString())
583  {
584  return ERR("could not parse LUT configuration: missing or invalid data identifier for LUT initialization");
585  }
586 
587  std::unique_ptr<GateTypeComponent> init_component = GateTypeComponent::create_init_component(lut_config["data_category"].GetString(), {lut_config["data_identifier"].GetString()});
588  return OK(GateTypeComponent::create_lut_component(std::move(init_component), std::string(lut_config["bit_order"].GetString()) == "ascending"));
589  }
590 
591  Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_ff_config(const rapidjson::Value& ff_config)
592  {
593  if (!ff_config.HasMember("state") || !ff_config["state"].IsString())
594  {
595  return ERR("could not parse flip-flop configuration: missing or invalid state identifier");
596  }
597  if (!ff_config.HasMember("neg_state") || !ff_config["neg_state"].IsString())
598  {
599  return ERR("could not parse flip-flop configuration: missing or invalid negated state identifier");
600  }
601  if (!ff_config.HasMember("next_state") || !ff_config["next_state"].IsString())
602  {
603  return ERR("could not parse flip-flop configuration: missing or invalid next state function");
604  }
605  if (!ff_config.HasMember("clocked_on") || !ff_config["clocked_on"].IsString())
606  {
607  return ERR("could not parse flip-flop configuration: missing or invalid clock function");
608  }
609 
610  std::unique_ptr<GateTypeComponent> init_component = nullptr;
611  if (ff_config.HasMember("data_category") && ff_config["data_category"].IsString())
612  {
613  std::vector<std::string> init_identifiers;
614  if (ff_config.HasMember("data_identifier") && ff_config["data_identifier"].IsString())
615  { // backward compatability
616  init_identifiers.push_back(ff_config["data_identifier"].GetString());
617  }
618  else
619  {
620  return ERR("could not parse flip-flop configuration: missing or invalid data identifier for flip-flop initialization");
621  }
622  init_component = GateTypeComponent::create_init_component(ff_config["data_category"].GetString(), init_identifiers);
623  }
624  else if (ff_config.HasMember("data_identifier") && ff_config["data_identifier"].IsString())
625  {
626  return ERR("could not parse flip-flop configuration: missing or invalid data category for flip-flop initialization");
627  }
628 
629  std::string state_identifier = ff_config["state"].GetString();
630  std::string neg_state_identifier = ff_config["neg_state"].GetString();
631  std::unique_ptr<GateTypeComponent> state_component = GateTypeComponent::create_state_component(std::move(init_component), state_identifier, neg_state_identifier);
632  assert(state_component != nullptr);
633 
634  BooleanFunction next_state_function;
635  if (auto res = BooleanFunction::from_string(ff_config["next_state"].GetString()); res.is_error())
636  {
637  return ERR("could not parse flip-flop configuration: failed parsing next state function from string");
638  }
639  else
640  {
641  next_state_function = res.get();
642  }
643  BooleanFunction clocked_on_function;
644  if (auto res = BooleanFunction::from_string(ff_config["clocked_on"].GetString()); res.is_error())
645  {
646  return ERR("could not parse flip-flop configuration: failed parsing clock function from string");
647  }
648  else
649  {
650  clocked_on_function = res.get();
651  }
652 
653  std::unique_ptr<GateTypeComponent> component = GateTypeComponent::create_ff_component(std::move(state_component), next_state_function, clocked_on_function);
654 
655  FFComponent* ff_component = component->convert_to<FFComponent>();
656  assert(ff_component != nullptr);
657 
658  if (ff_config.HasMember("clear_on") && ff_config["clear_on"].IsString())
659  {
660  if (auto res = BooleanFunction::from_string(ff_config["clear_on"].GetString()); res.is_error())
661  {
662  return ERR("could not parse flip-flop configuration: failed parsing asynchronous reset function from string");
663  }
664  else
665  {
666  ff_component->set_async_reset_function(res.get());
667  }
668  }
669 
670  if (ff_config.HasMember("preset_on") && ff_config["preset_on"].IsString())
671  {
672  if (auto res = BooleanFunction::from_string(ff_config["preset_on"].GetString()); res.is_error())
673  {
674  return ERR("could not parse flip-flop configuration: failed parsing asynchronous set function from string");
675  }
676  else
677  {
678  ff_component->set_async_set_function(res.get());
679  }
680  }
681 
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();
684 
685  if (has_state && has_neg_state)
686  {
687  AsyncSetResetBehavior cp1, cp2;
688 
689  if (const auto behav = enum_from_string<AsyncSetResetBehavior>(ff_config["state_clear_preset"].GetString(), AsyncSetResetBehavior::undef); behav != AsyncSetResetBehavior::undef)
690  {
691  cp1 = behav;
692  }
693  else
694  {
695  return ERR("could not parse flip-flop configuration: failed parsing state on concurrent asynchronous set and reset from string");
696  }
697 
698  if (const auto behav = enum_from_string<AsyncSetResetBehavior>(ff_config["neg_state_clear_preset"].GetString(), AsyncSetResetBehavior::undef); behav != AsyncSetResetBehavior::undef)
699  {
700  cp2 = behav;
701  }
702  else
703  {
704  return ERR("could not parse flip-flop configuration: failed parsing negated state on concurrent asynchronous set and reset from string");
705  }
706 
707  ff_component->set_async_set_reset_behavior(cp1, cp2);
708  }
709  else if ((has_state && !has_neg_state) || (!has_state && has_neg_state))
710  {
711  return ERR("could not parse flip-flop configuration: missing state or negated state on concurrent asynchronous set and reset");
712  }
713 
714  return OK(std::move(component));
715  }
716 
717  Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_latch_config(const rapidjson::Value& latch_config)
718  {
719  if (!latch_config.HasMember("state") || !latch_config["state"].IsString())
720  {
721  return ERR("could not parse latch configuration: missing or invalid state identifier");
722  }
723  if (!latch_config.HasMember("neg_state") || !latch_config["neg_state"].IsString())
724  {
725  return ERR("could not parse latch configuration: missing or invalid negated state identifier");
726  }
727 
728  std::string state_identifier = latch_config["state"].GetString();
729  std::string neg_state_identifier = latch_config["neg_state"].GetString();
730  std::unique_ptr<GateTypeComponent> state_component = GateTypeComponent::create_state_component(nullptr, state_identifier, neg_state_identifier);
731  assert(state_component != nullptr);
732 
733  std::unique_ptr<GateTypeComponent> component = GateTypeComponent::create_latch_component(std::move(state_component));
734  LatchComponent* latch_component = component->convert_to<LatchComponent>();
735  assert(latch_component != nullptr);
736 
737  if (latch_config.HasMember("data_in") && latch_config["data_in"].IsString() && latch_config.HasMember("enable_on") && latch_config["enable_on"].IsString())
738  {
739  if (auto res = BooleanFunction::from_string(latch_config["data_in"].GetString()); res.is_error())
740  {
741  return ERR("could not parse latch configuration: failed parsing data in function from string");
742  }
743  else
744  {
745  latch_component->set_data_in_function(res.get());
746  }
747 
748  if (auto res = BooleanFunction::from_string(latch_config["enable_on"].GetString()); res.is_error())
749  {
750  return ERR("could not parse latch configuration: failed parsing enable function from string");
751  }
752  else
753  {
754  latch_component->set_enable_function(res.get());
755  }
756  }
757  else if (latch_config.HasMember("data_in") && latch_config["data_in"].IsString())
758  {
759  return ERR("could not parse latch configuration: missing or invalid enable function");
760  }
761  else if (latch_config.HasMember("enable_on") && latch_config["enable_on"].IsString())
762  {
763  return ERR("could not parse latch configuration: missing or invalid data in function");
764  }
765 
766  if (latch_config.HasMember("clear_on") && latch_config["clear_on"].IsString())
767  {
768  if (auto res = BooleanFunction::from_string(latch_config["clear_on"].GetString()); res.is_error())
769  {
770  return ERR("could not parse latch configuration: failed parsing asynchronous reset function from string");
771  }
772  else
773  {
774  latch_component->set_async_reset_function(res.get());
775  }
776  }
777 
778  if (latch_config.HasMember("preset_on") && latch_config["preset_on"].IsString())
779  {
780  if (auto res = BooleanFunction::from_string(latch_config["preset_on"].GetString()); res.is_error())
781  {
782  return ERR("could not parse latch configuration: failed parsing asynchronous set function from string");
783  }
784  else
785  {
786  latch_component->set_async_set_function(res.get());
787  }
788  }
789 
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();
792 
793  if (has_state && has_neg_state)
794  {
795  AsyncSetResetBehavior cp1, cp2;
796 
797  if (const auto behav = enum_from_string<AsyncSetResetBehavior>(latch_config["state_clear_preset"].GetString(), AsyncSetResetBehavior::undef); behav != AsyncSetResetBehavior::undef)
798  {
799  cp1 = behav;
800  }
801  else
802  {
803  return ERR("could not parse latch configuration: failed parsing state on concurrent asynchronous set and reset from string");
804  }
805 
806  if (const auto behav = enum_from_string<AsyncSetResetBehavior>(latch_config["neg_state_clear_preset"].GetString(), AsyncSetResetBehavior::undef); behav != AsyncSetResetBehavior::undef)
807  {
808  cp2 = behav;
809  }
810  else
811  {
812  return ERR("could not parse latch configuration: failed parsing negated state on concurrent asynchronous set and reset from string");
813  }
814 
815  latch_component->set_async_set_reset_behavior(cp1, cp2);
816  }
817  else if ((has_state && !has_neg_state) || (!has_state && has_neg_state))
818  {
819  return ERR("could not parse latch configuration: missing state or negated state on concurrent asynchronous set and reset");
820  }
821 
822  return OK(std::move(component));
823  }
824 
825  Result<std::unique_ptr<GateTypeComponent>> HGLParser::parse_ram_config(const rapidjson::Value& ram_config)
826  {
827  std::unique_ptr<GateTypeComponent> sub_component = nullptr;
828  if (ram_config.HasMember("data_category") && ram_config["data_category"].IsString())
829  {
830  std::vector<std::string> init_identifiers;
831  if (ram_config.HasMember("data_identifiers") && ram_config["data_identifiers"].IsArray())
832  { // now allows for multiple identifiers (required for BRAM)
833 
834  for (const auto& identifier : ram_config["data_identifiers"].GetArray())
835  {
836  init_identifiers.push_back(identifier.GetString());
837  }
838  }
839  else
840  {
841  return ERR("could not parse RAM configuration: missing or invalid data identifier for RAM initialization");
842  }
843  sub_component = GateTypeComponent::create_init_component(ram_config["data_category"].GetString(), init_identifiers);
844  }
845  else if (ram_config.HasMember("data_identifiers") && ram_config["data_identifiers"].IsArray())
846  {
847  return ERR("could not parse RAM configuration: missing or invalid data category for RAM initialization");
848  }
849 
850  if (!ram_config.HasMember("bit_size") || !ram_config["bit_size"].IsUint())
851  {
852  return ERR("could not parse RAM configuration: missing or invalid bit size");
853  }
854 
855  if (!ram_config.HasMember("ram_ports") || !ram_config["ram_ports"].IsArray())
856  {
857  return ERR("could not parse RAM configuration: missing or invalid RAM ports");
858  }
859 
860  for (const auto& ram_port : ram_config["ram_ports"].GetArray())
861  {
862  if (!ram_port.HasMember("data_group") || !ram_port["data_group"].IsString())
863  {
864  return ERR("could not parse RAM configuration: missing or invalid data pin groups for RAM port");
865  }
866 
867  if (!ram_port.HasMember("address_group") || !ram_port["address_group"].IsString())
868  {
869  return ERR("could not parse RAM configuration: missing or invalid address pin groups for RAM port");
870  }
871 
872  if (!ram_port.HasMember("clocked_on") || !ram_port["clocked_on"].IsString())
873  {
874  return ERR("could not parse RAM configuration: missing or invalid clock function for RAM port");
875  }
876 
877  if (!ram_port.HasMember("enabled_on") || !ram_port["enabled_on"].IsString())
878  {
879  return ERR("could not parse RAM configuration: missing or invalid enable function for RAM port");
880  }
881 
882  if (!ram_port.HasMember("is_write") || !ram_port["is_write"].IsBool())
883  {
884  return ERR("could not parse RAM configuration: missing or invalid write flag for RAM port");
885  }
886 
887  BooleanFunction clocked_on_function;
888  if (auto res = BooleanFunction::from_string(ram_port["clocked_on"].GetString()); res.is_error())
889  {
890  return ERR("could not parse RAM configuration: failed parsing clock function from string");
891  }
892  else
893  {
894  clocked_on_function = res.get();
895  }
896 
897  BooleanFunction enabled_on_function;
898  if (auto res = BooleanFunction::from_string(ram_port["enabled_on"].GetString()); res.is_error())
899  {
900  return ERR("could not parse RAM configuration: failed parsing clock function from string");
901  }
902  else
903  {
904  enabled_on_function = res.get();
905  }
906 
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());
909  }
910 
911  std::unique_ptr<GateTypeComponent> component = GateTypeComponent::create_ram_component(std::move(sub_component), ram_config["bit_size"].GetUint());
912 
913  return OK(std::move(component));
914  }
915 } // namespace hal
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
Definition: hgl_parser.cpp:17
int32_t i32
Definition: defines.h:36
#define log_warning(channel,...)
Definition: log.h:76
#define ERR(message)
Definition: result.h:53
#define OK(...)
Definition: result.h:49
#define ERR_APPEND(prev_error, message)
Definition: result.h:57
PinDirection
Definition: pin_direction.h:36
PinType
Definition: pin_type.h:36
quint32 u32
std::vector< PinInformation > pins
bool ordered
u32 start_index
bool ascending
PinDirection direction
std::string name